refactor(commands): move commands-side rendering out of src/daemon and retire the doctor progress flag - #2349
Conversation
…their callers `formatDoctorCheckSummaryLine`, `formatDoctorCheckDetailLines`, and `formatCliStatusMarker` are shared by the daemon doctor handlers, the CLI replay-test reporter, and the doctor CLI output formatter. Owning them in `src/daemon/handlers/` forced `src/commands` to reach up into `src/daemon` through a dynamic import; `src/core` sits below every caller. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Eddu5VC45qAXUkXNZJyruZ
The `serialize*` helpers render command results for the CLI and MCP surfaces, not for the daemon; only the two deployment target resolvers were shared with daemon handlers. The serializers move to `src/commands/output/` beside the formatters that call them, and the resolvers move to `src/core` below both owners, so `src/commands` and `src/mcp` no longer reach into `src/daemon` for them. The MCP edge becomes a static import; the `src/commands` edges stay function-scoped because `src/cli.ts` eagerly evaluates both output modules. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Eddu5VC45qAXUkXNZJyruZ
…ng the doctor progress flag Streamed `command` progress was rendered to stderr by the daemon client, which recorded "doctor progress was rendered" in a process-global flag that `doctorCliOutput` then consumed to suppress its final summary. The rendering was commands-side, so it moves there: the CLI installs `createStderrCommandProgressSink` as the request's `RequestProgressSink` for every non-`test`, non-`--json` command, and hands its `CommandProgressState` to the output formatters with the result. The transport now only forwards events to the sink the caller installed. Behavior is unchanged in the three modes the tests pin: progress streamed to stderr suppresses doctor's check lines, no progress prints them, and a caller that installs its own sink (SDK, MCP) writes nothing to this process's stderr and is not suppressed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Eddu5VC45qAXUkXNZJyruZ
Completion evidenceZero edges from
|
Size Report
Startup median (7 runs, lower is better):
|
The end-to-end doctor progress cases landed in `cli-network.test.ts`, which is already past the 1,000-line tripwire, so the test-file-size ratchet rejected the growth. They are doctor-output cases rather than network ones: they move to `cli-doctor-progress.test.ts`, and `cli-network.test.ts` returns to its merge-base size. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Eddu5VC45qAXUkXNZJyruZ
|
Clean review at 29f3527. The shared helpers and serializers have clear owners, and the doctor progress state is local to each CLI run. Streamed output avoids duplicates; custom sinks still get the full result. The tests cover both streamed and unstreamed CLI output, and the old global flag is gone. Ready for human review. Remaining CI is still running, so this is not yet a merge-ready claim. |
|
Takes #2347's move of the daemon code-signature walker into `@agent-device/host-kit` together with its workspace-specifier resolution, and drops this branch's own copy of that fix: one resolver, the one on main. The claim this branch owed keeps its own test beside the walker — the daemon source graph stamps `packages/command-registry/src/registry.ts`, `catalog.ts` and the manifest, measured at 1,461 modules, and touching the registry changes the signature. `src/cli/commands/router-types.ts`: #2349's `CommandProgressState` import alongside this branch's catalog specifier. A fixture string in the relocated CLI-route test also goes back to the specifier it illustrates; the move rewrote it as if it were a real import. Three review points, recorded here because their commits are pushed: - Dropping `registry.ts` and `platform-execution-entry.ts` from `HUB_ENTRY_FILES` is not only bookkeeping: the package manifest now publishes them, so the gate discovers them as domain facades and `denyPlatformImplementations` flips false to true. Both now carry the ADR-0019 assertion that they evaluate no concrete platform implementation, and both pass it. That strengthening is intended. - The 150 this branch reports against the issue's 154 is a filter difference, not a discrepancy: `pnpm depgraph` collapses to one edge per file pair, and 150 counts value edges only. Counting type-only and dynamic edges on the same graph gives 174 into 67 root files, which is the shape the issue's own per-file breakdown uses; both readings drop by exactly the 36 the issue predicts. - The six tests that stay in root do so for one root symbol each: parity needs STRUCTURED_BATCH_COMMAND_NAMES, DAEMON_COMMAND_DESCRIPTORS, canRunReplayScopedAction and DaemonRequest; ref-frame-effect needs DAEMON_COMMAND_DESCRIPTORS, resolveRefFrameEffect and DaemonRequest; timeout-policy needs DEFAULT_STABLE_TIMEOUT_MS; platform-execution-cli-route needs CLI_INJECTED_DAEMON_DISPATCHES and CliInjectedRoute; post-action-observation needs AgentDeviceClient, getCliCommandSchema, readInputFromCli, findCommandMetadata, the two command-family registry listers, SettleCapableClientOptionCommands, buildActionDetails and COMMAND_OUTPUT_SCHEMAS; shutdown-runtime-execution imports nothing but reads the daemon and root host sources whose text it pins. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016DkNZCMWtm1KUbseKANADi
Summary
Closes #2337.
src/commandsandsrc/mcpreached intosrc/daemonfor rendering they own — 11import()sites, 5 file edges. Each moves to its owner:daemon/result-serialization.ts→commands/output/result-serialization.ts; the two deployment target resolvers its daemon handlers needed →core/deploy-result-target.ts.daemon/handlers/doctor-output.tsandhandlers/status-markers.ts→src/core/, below the daemon handlers, the replay-test reporter and the doctor formatter.daemon/client/doctor-progress.ts(a process-global flag) is deleted, not deprecated. The CLI installscreateStderrCommandProgressSinkas the request'sRequestProgressSinkand hands itsCommandProgressStateto the output formatters; the daemon client only forwards events to the caller's sink.The MCP edge becomes static. The
src/commandsedges stay function-scoped: static would takesrc/cli.tsfrom 380 to 384 eager modules, which the no-growth budget rejects. No budget raised, no compatibility re-export, no gate or baseline edit needed.Validation
Tested at
e4bc1ea:pnpm install --frozen-lockfile && pnpm build,pnpm typecheck,pnpm lint,pnpm check:affected --run— all runnable checks passed (270 files / 2025 tests, plus daemon-wire-compat).Graph query over
pnpm depgraphoutput (non-type edges,src/commands|src/mcp → src/daemon): 5 at27a97ee, 0 at head — query, both outputs and the rename-only stat in the first comment.pnpm check:layering: OK, 0 R5 back-edges, R2 clean. Eager-closure budgets: 442 pass; all 225 entries unchanged,src/cli.ts380 → 380.Doctor CLI output is byte-identical in all three modes (progress streamed, none, custom sink); captures diffed empty. The new CLI-level test was verified failing without the fix.
🤖 Generated with Claude Code
https://claude.ai/code/session_01Eddu5VC45qAXUkXNZJyruZ
Generated by Claude Code