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
{{ message }}
Repository navigation
refactor(daemon): stop importing the commands barrel through src/runtime.ts #2540
The value closure of src/runtime.ts is 122 files, 48 of them under src/commands/. The daemon's total value closure is 717 files and carries 121 src/commands/** files — roughly the entire commands zone (140 files, 21k LOC) — plus 17 root flat files. The daemon loads a command surface it does not dispatch through, and every change in commands is potentially a daemon-restart-cost event.
Umbrella: #2545. Chosen first because it is the only child that changes what the daemon actually loads, and because #2469 (eager-closure budget tolerance) is unblocked by cutting closure, not by adding budget.
Required behavior
src/runtime.ts keeps its public shape: AgentDevice, createAgentDevice, createMemorySessionStore, localCommandPolicy, restrictedCommandPolicy, and the re-exported command types. No consumer-side API change is part of this issue.
Daemon consumers of src/runtime.ts take the specific declarations they use through their owning module or contract, not through the runtime facade. Determine the used symbol set per importer before choosing the seam; do not invent an interface wider than the symbols in use.
The barrel src/commands/index.ts either stops being the value entry for runtime binding, or the binding moves to the composition root that needs it. One construction path, no second registry.
Completion conditions
Value-only transitive closure from src/daemon/** contains zero files under src/commands/. Measured with a probe over scripts/layering/model.ts as described in the parent, and reported in the PR.
src/runtime.ts has no value edge into src/commands/**, or is no longer reachable from src/daemon/** at all.
No new eager work: the eager-import-closure budgets for the daemon entry surfaces do not rise.
R4 stays 0, R5 stays 0, R6 does not grow past the ratchet.
Out of scope
Repackaging src/commands as a workspace package. That decision needs the cli-schema orientation settled first (sibling child).
Any change to the command descriptor registry or the command-registry package.
Closure measurement: the runtime.ts cut alone does not reach the completion condition
Probe over scripts/layering/model.ts (value edges only, static, from src/daemon/**) at e6f288012b:
cut
daemon closure
src/commands/** files
none (today)
719
121
src/runtime.ts → commands/index.ts only
662
75
that + the daemon's two cli-schema/command-schema.ts imports
584
0
The second path is src/daemon → src/cli-schema/command-schema.ts → src/commands/command-metadata.ts → src/commands/family/registry.ts → every command family. Two daemon files hold it, one symbol each:
src/daemon/request-execution-scope.ts takes applyCommandDefaults. It resolves the full per-command schema, which is authored inside the command facets. Exactly one command declares defaults today (app, appsFilter), and src/cli/parser/args.ts already applies the same defaults on the CLI side.
src/daemon/session-action-recorder.ts takes recordedFlagKeys. That function lives in src/commands/cli-grammar/flag-registry.ts and its closure is only the four flag-definitions-*.ts files plus flag-types.ts.
So "zero src/commands/** files" needs these two edges cut as well. Either this issue owns them (import recordedFlagKeys from the flag registry directly and take the daemon-side defaults application through something that does not resolve the whole facet table), or the condition is relaxed here and #2543 owns it. I have posted the same data on #2545 and #2543 so the sequencing is decided in one place.
The issue's probe of 75 assumed nothing replaces the barrel. It cannot: the daemon calls capture.snapshot/diffSnapshot/screenshot, selectors.find/get/is/wait and interactions.gesture/click/press/fill/hover/settleObservation, so the 33-34 files implementing those three families return the moment a scoped binder replaces createAgentDevice. That residue is the daemon's own dispatch surface, not accidental coupling.
Two consequences:
"Zero src/commands/** in the daemon closure" is only reachable if the daemon stops executing commands in-process. Proposed replacement condition: the daemon reaches only the command families it dispatches through (capture, selectors, interactions), imports no all-family barrel, and holds 0 src/commands files outside those families plus whatever refactor(cli-schema): orient the schema layer below commands #2543 resolves.
recordedFlagKeys cannot be imported from commands/cli-grammar/flag-registry.ts by the daemon. That is a direct daemon → commands value edge and R2 commands-floor rejects it (scripts/layering/zone-policy.ts:47). The symbol has to move down to packages/command-registry, which is refactor(cli-schema): orient the schema layer below commands #2543's "flag grammar goes down" step — so this issue should not own that edge.
Suggest: #2548 merges as the runtime split, the condition above replaces the zero, and the remaining 74-file path is #2543's.
Closing on the decision above: the completion condition is the dispatched-families invariant, not zero. #2548 delivered the runtime split, #2562 cut the second path through cli-schema/command-schema.ts. At 775163bb35 the daemon reaches src/commands only through src/runtime-command-surface.ts, and the closure holds 34 files (30 under */runtime/**, 4 shared runtime helpers), no facet, reader, formatter, or barrel. src/runtime.ts keeps its public shape. Umbrella body updated with the same wording.
Activity
thymikee commentedon Sep 13, 2026
Closure measurement: the runtime.ts cut alone does not reach the completion condition
Probe over
scripts/layering/model.ts(value edges only, static, fromsrc/daemon/**) ate6f288012b:src/commands/**filessrc/runtime.ts → commands/index.tsonlycli-schema/command-schema.tsimportsThe second path is
src/daemon → src/cli-schema/command-schema.ts → src/commands/command-metadata.ts → src/commands/family/registry.ts → every command family. Two daemon files hold it, one symbol each:src/daemon/request-execution-scope.tstakesapplyCommandDefaults. It resolves the full per-command schema, which is authored inside the command facets. Exactly one command declaresdefaultstoday (app,appsFilter), andsrc/cli/parser/args.tsalready applies the same defaults on the CLI side.src/daemon/session-action-recorder.tstakesrecordedFlagKeys. That function lives insrc/commands/cli-grammar/flag-registry.tsand its closure is only the fourflag-definitions-*.tsfiles plusflag-types.ts.So "zero
src/commands/**files" needs these two edges cut as well. Either this issue owns them (importrecordedFlagKeysfrom the flag registry directly and take the daemon-side defaults application through something that does not resolve the whole facet table), or the condition is relaxed here and #2543 owns it. I have posted the same data on #2545 and #2543 so the sequencing is decided in one place.thymikee commentedon Sep 13, 2026
Completion contract: the achievable floor is 34, not 0 — needs a decision before #2548 can close this
PR #2548 ships the
src/runtime.tscut. Measured value-only closure fromsrc/daemon/**, with the change in place:src/commands/**9aa6465768)command-schema.tsedgesThe issue's probe of 75 assumed nothing replaces the barrel. It cannot: the daemon calls
capture.snapshot/diffSnapshot/screenshot,selectors.find/get/is/waitandinteractions.gesture/click/press/fill/hover/settleObservation, so the 33-34 files implementing those three families return the moment a scoped binder replacescreateAgentDevice. That residue is the daemon's own dispatch surface, not accidental coupling.Two consequences:
src/commands/**in the daemon closure" is only reachable if the daemon stops executing commands in-process. Proposed replacement condition: the daemon reaches only the command families it dispatches through (capture,selectors,interactions), imports no all-family barrel, and holds 0src/commandsfiles outside those families plus whatever refactor(cli-schema): orient the schema layer below commands #2543 resolves.recordedFlagKeyscannot be imported fromcommands/cli-grammar/flag-registry.tsby the daemon. That is a directdaemon → commandsvalue edge and R2commands-floorrejects it (scripts/layering/zone-policy.ts:47). The symbol has to move down topackages/command-registry, which is refactor(cli-schema): orient the schema layer below commands #2543's "flag grammar goes down" step — so this issue should not own that edge.Suggest: #2548 merges as the runtime split, the condition above replaces the zero, and the remaining 74-file path is #2543's.
refactor(daemon): bind only the command families the daemon dispatche…
thymikee commentedon Sep 14, 2026
Closing on the decision above: the completion condition is the dispatched-families invariant, not zero. #2548 delivered the runtime split, #2562 cut the second path through
cli-schema/command-schema.ts. At775163bb35the daemon reachessrc/commandsonly throughsrc/runtime-command-surface.ts, and the closure holds 34 files (30 under*/runtime/**, 4 shared runtime helpers), no facet, reader, formatter, or barrel.src/runtime.tskeeps its public shape. Umbrella body updated with the same wording.