You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
postActionObservation in the command-descriptor registry is already the right enumerator for "which commands support --settle". The problem is coverage: only four of ten caller-facing surfaces derive from it, and the gate covers two. The other six are hand-spread per command and silently no-op when forgotten — a reader that drops settleInputFromFlags doesn't fail, it just ignores --settle.
This is the same failure mode commonInputFromFlags already documents for --no-record ("a drop at any one of them silently disables the flag"), and the same problem interaction-guarantees.ts already solved for dispatch paths by making completeness a compile error.
The drift is already in the tree
Cross-checking every surface against the trait (probe over commandDescriptors):
find advertises a settle payload in its MCP output schema while carrying no trait, no CLI flag, and no MCP input field. It forwards req.flags to its internal press/click, so a hand-built daemon request can produce the payload — but no public surface can ask for it.
scroll declares nothing, purely because it isn't in the typed-result spine (CommandResultMap), not because it returns anything different from back. That one shipped in feat: support --settle on scroll and back (#1638) #1650 despite a gate and a careful review.
Hoist the reader spread to the framework seam.readInputFromCli(command, positionals, flags) already knows the command name, so one line there deletes six hand-spreads and makes forgetting structurally impossible:
Derive the remaining three runtime surfaces — session-event safe-flag specs, MCP output schema, CLI output formatter. withSettleObservation (added in feat: support --settle on scroll and back (#1638) #1650 for back) already generalizes from "name one command" to "wrap every settle-capable command's schema".
Extend the descriptor gate to all ten surfaces, in post-action-observation.test.ts. This is the item that actually matters: it converts six silent-drift surfaces into one failing test, and it would have caught both rows above. The type-level surfaces (contracts option types) can follow interaction-guarantees.ts and become a compile error rather than a runtime assertion.
Resolve find — either give it the trait (it already forwards flags to its internal dispatch) or drop settle from its output schema. Needs a call on intent.
Explicitly out of scope
The two daemon orchestrations (interaction route vs generic route) look like the obvious duplication and are the wrong target. The interaction route settles inside the runtime command because it needs the resolution's pre-action baseline and composes with --verify; the generic route settles after dispatch against the stored session snapshot. Unifying them would mean inventing a fake resolution for scroll/back. The parts that genuinely are shared — the settle engine and issueSettleRefs — already are, as of #1650.
Sizing
Roughly −30 LOC. The line count is not the point: the reason to do this is that six surfaces currently fail silently, and the seventh settle-capable command will hit the same trap. Evidence that it is a real trap rather than a theoretical one: #1650 added two commands, touched seven surfaces by hand, had a gate, and still shipped the scroll output-schema asymmetry.
postActionObservationin the command-descriptor registry is already the right enumerator for "which commands support--settle". The problem is coverage: only four of ten caller-facing surfaces derive from it, and the gate covers two. The other six are hand-spread per command and silently no-op when forgotten — a reader that dropssettleInputFromFlagsdoesn't fail, it just ignores--settle.This is the same failure mode
commonInputFromFlagsalready documents for--no-record("a drop at any one of them silently disables the flag"), and the same probleminteraction-guarantees.tsalready solved for dispatch paths by making completeness a compile error.The drift is already in the tree
Cross-checking every surface against the trait (probe over
commandDescriptors):findadvertises asettlepayload in its MCP output schema while carrying no trait, no CLI flag, and no MCP input field. It forwardsreq.flagsto its internal press/click, so a hand-built daemon request can produce the payload — but no public surface can ask for it.scrolldeclares nothing, purely because it isn't in the typed-result spine (CommandResultMap), not because it returns anything different fromback. That one shipped in feat: support --settle on scroll and back (#1638) #1650 despite a gate and a careful review.Surface coverage
settleInputFromFlags)toSettleOptions)& SettleCommandOptions)Proposed work, in order
readInputFromCli(command, positionals, flags)already knows the command name, so one line there deletes six hand-spreads and makes forgetting structurally impossible:withSettleObservation(added in feat: support --settle on scroll and back (#1638) #1650 forback) already generalizes from "name one command" to "wrap every settle-capable command's schema".post-action-observation.test.ts. This is the item that actually matters: it converts six silent-drift surfaces into one failing test, and it would have caught both rows above. The type-level surfaces (contracts option types) can followinteraction-guarantees.tsand become a compile error rather than a runtime assertion.find— either give it the trait (it already forwards flags to its internal dispatch) or dropsettlefrom its output schema. Needs a call on intent.Explicitly out of scope
The two daemon orchestrations (interaction route vs generic route) look like the obvious duplication and are the wrong target. The interaction route settles inside the runtime command because it needs the resolution's pre-action baseline and composes with
--verify; the generic route settles after dispatch against the stored session snapshot. Unifying them would mean inventing a fake resolution for scroll/back. The parts that genuinely are shared — the settle engine andissueSettleRefs— already are, as of #1650.Sizing
Roughly −30 LOC. The line count is not the point: the reason to do this is that six surfaces currently fail silently, and the seventh settle-capable command will hit the same trap. Evidence that it is a real trap rather than a theoretical one: #1650 added two commands, touched seven surfaces by hand, had a gate, and still shipped the
scrolloutput-schema asymmetry.Follow-up to #1638 / #1650.