Part of #3069.
Purpose
Nothing in production sets retryOnNoChange: true (grep of src and packages, non-test). The flag is still read in src/daemon/interaction-outcome-policy.ts, and it keeps pendingInteractionOutcome alive in src/daemon/session-state.ts and src/daemon/deferred-interaction-outcome.ts. The path re-sends an interaction when the tree looks unchanged, which is the same class of blind resend that error.details.dispatched exists to prevent: a tap that landed on a screen that had not re-rendered yet runs twice. The e2e consumer review (tester-army) traced it as a double-tap source.
Required behavior
- Remove
retryOnNoChange from packages/contracts/src/command-flags.ts and every surface that carries it. Retiring a flag touches the CLI grammar, structured input, MCP schema, help, the wire ledger, and the docs; each must refuse or drop the key, not silently accept it.
- Remove
pendingInteractionOutcome from SessionState, its owner entry in the state-field table, and bump the state-file version.
- Delete
deferred-interaction-outcome.ts and the branch of interaction-outcome-policy.ts that reads the flag. Freshness retires only on a trustworthy capture.
Completion conditions
grep -rn "retryOnNoChange\|pendingInteractionOutcome" src packages returns nothing outside git log.
pnpm check:affected --run passes; the wire-compat ledger records the removal as a breaking change to a flag no released client sets.
- No interaction is re-sent by the daemon without the producer proving
dispatched: "no".
Dependencies
After #3071 merges (it names this path as the remaining blind resend on the daemon side).
Part of #3069.
Purpose
Nothing in production sets
retryOnNoChange: true(grep ofsrcandpackages, non-test). The flag is still read insrc/daemon/interaction-outcome-policy.ts, and it keepspendingInteractionOutcomealive insrc/daemon/session-state.tsandsrc/daemon/deferred-interaction-outcome.ts. The path re-sends an interaction when the tree looks unchanged, which is the same class of blind resend thaterror.details.dispatchedexists to prevent: a tap that landed on a screen that had not re-rendered yet runs twice. The e2e consumer review (tester-army) traced it as a double-tap source.Required behavior
retryOnNoChangefrompackages/contracts/src/command-flags.tsand every surface that carries it. Retiring a flag touches the CLI grammar, structured input, MCP schema, help, the wire ledger, and the docs; each must refuse or drop the key, not silently accept it.pendingInteractionOutcomefromSessionState, its owner entry in the state-field table, and bump the state-file version.deferred-interaction-outcome.tsand the branch ofinteraction-outcome-policy.tsthat reads the flag. Freshness retires only on a trustworthy capture.Completion conditions
grep -rn "retryOnNoChange\|pendingInteractionOutcome" src packagesreturns nothing outsidegit log.pnpm check:affected --runpasses; the wire-compat ledger records the removal as a breaking change to a flag no released client sets.dispatched: "no".Dependencies
After #3071 merges (it names this path as the remaining blind resend on the daemon side).