What happened?
src/resolver/action-resolver.ts:131-158 (resolveConfirm) attempts to fall back from confirm to suggest when ctx.replacement is set. But the engine never sets a replacement for confirm actions.
In src/engine/engine.ts:124-125, the engine reads:
const replacement =
'replacement' in rule.defaultAction ? rule.defaultAction.replacement : undefined
A confirm action has no replacement field (see src/core/types.ts:19), so replacement is always undefined when the engine calls resolveAction. The check if (capabilities.suggest && ctx.replacement) at action-resolver.ts:146 is always false for confirm rules coming from the engine.
The unit test in src/resolver/action-resolver.test.ts:165-186 passes only because it constructs a custom ResolveContext with replacement: 'safe-cmd' — that branch is never reached in production.
Result: a confirm action with no fallback always ends up at fallbackBlock in real engine flow, never at suggest.
What did you expect to happen?
Either the engine should pass a meaningful replacement for confirm actions, or the unreachable confirm → suggest branch in the resolver should be removed to avoid misleading future maintainers.
Steps to reproduce
- Define a rule with
action: { type: 'confirm' } and no fallback
- Call
engine.evaluate({ ... }) with capabilities.confirm: true
- Observe the resolver enters
resolveConfirm, the suggest branch is skipped, and the action becomes fallbackBlock
What happened?
src/resolver/action-resolver.ts:131-158(resolveConfirm) attempts to fall back fromconfirmtosuggestwhenctx.replacementis set. But the engine never sets a replacement forconfirmactions.In
src/engine/engine.ts:124-125, the engine reads:A
confirmaction has noreplacementfield (seesrc/core/types.ts:19), soreplacementis alwaysundefinedwhen the engine callsresolveAction. The checkif (capabilities.suggest && ctx.replacement)ataction-resolver.ts:146is always false for confirm rules coming from the engine.The unit test in
src/resolver/action-resolver.test.ts:165-186passes only because it constructs a customResolveContextwithreplacement: 'safe-cmd'— that branch is never reached in production.Result: a
confirmaction with nofallbackalways ends up atfallbackBlockin real engine flow, never atsuggest.What did you expect to happen?
Either the engine should pass a meaningful replacement for confirm actions, or the unreachable
confirm → suggestbranch in the resolver should be removed to avoid misleading future maintainers.Steps to reproduce
action: { type: 'confirm' }and nofallbackengine.evaluate({ ... })withcapabilities.confirm: trueresolveConfirm, thesuggestbranch is skipped, and the action becomesfallbackBlock