Skip to content

refactor: extract @agent-device/command-output - #4120

Merged
thymikee merged 8 commits into
mainfrom
refactor/command-output-package
Nov 1, 2026
Merged

thymikee merged 8 commits into
mainfrom
refactor/command-output-package

Conversation

@thymikee

@thymikee thymikee commented Oct 31, 2026 •

Copy link
Copy Markdown
Member

Summary

Extracts the shared CLI/MCP presentation (family formatters, warning routing, color, human error lines, serialization) into private @agent-device/command-output. Sources moved with git mv. command-surface gains no presentation import; MCP stays root. 82 files, +663/−277 rename-aware.

  • Purity: the package reads no process member (R86, including named imports). printHumanError, printJson and the stderr progress sink stay root; stdout/stderrIsTTY arrive as input.
  • Entry: exactly ".", explicit names, including FormatCliOutputParams. formatCliOutput and the diff renderers load the formatter tables on first call.
  • Deep callers render through production formatCliOutput.
  • Review fixes kept: bounded warning-collapse regex (CodeQL), -i conformance samples, named-import guard.
  • Rebase: onto ff8c2285c8 (refactor: extract client workspace package #4121 client extraction). Conflicts were manifests, entry pins, cli-runner.ts and render-fixtures.ts; both packages stay registered. Lockfile regenerated with pnpm (only the new importer). range-diff: the last four commits are unchanged; one added commit merges a duplicate import.

Eager closure at the old base: cli.ts 256→256, SDK 241→241, MCP server 254→230, entry 19 (ceiling 20); the budget gate passed on the rebased head.

Validation

Full gate at bc1c0dece1: pnpm check --head bc1c0dece1 passed, exactCommit: true (tooling, fallow, unit); merge-tree against current main is clean. CI then failed AgentGuidance (docs/agents 40,007 bytes > 40,000); f4795dfaa7 shortens one sentence in code-ownership.md, no cap raised. Docs-only delta to f4795dfaa7: check:affected --base bc1c0dece1 --head f4795dfaa7 selected agent-guidance, passed, exactCommit: true; not a new full gate. Earlier CI passes apply to older heads. Not device-facing. CI-only lanes pending.

🤖 Generated with Claude Code

@vercel

vercel Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
agent-device-website Ready Ready Preview Oct 31, 2026 4:17pm UTC

Request Review

@github-actions

github-actions Bot commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

Size Report

Metric Base Current Diff
Installed (including dependencies) 5.63 MB 5.64 MB +558 B
Package (unpacked) 5.63 MB 5.63 MB +558 B
Package (download) 1.72 MB 1.72 MB +386 B

Startup median (7 runs, lower is better):

Scenario Base Current Diff
CLI --version 41.8 ms 42.4 ms +0.6 ms
CLI --help 83.8 ms 84.1 ms +0.2 ms

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 81 files

Reply with feedback, questions, or to request a fix.

View guided diff | Turn on auto-fix | Re-trigger cubic

Comment thread scripts/layering/model.ts Resolved
@apex-sentinel-staging

apex-sentinel-staging Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

Apex Sentinel

Verdict: approve

Since the last review: 3 new · 0 still open · 3 no longer raised

3 finding(s): 2 minor, 1 nit. Verdict: approve. reached max rounds (1).

🟡 Minor (2)

Where Finding
scripts/help-conformance-sample-outputs.mjs:50 🆕 Pinned help-conformance sample was reordered to match the new dispatcher path; placement of the hidden-content hint should be verified against the renderer
packages/command-output/src/output/color.ts:4 🆕 supportsColor dropped its process.stdout default: one-argument calls now silently disable color
🔵 Nit (1)
Where Finding
scripts/help-conformance-sample-outputs.mjs:53 🆕 OFFSCREEN_TARGET_SNAPSHOT_SAMPLE was regenerated into the wrong presentation mode and its comment still claims it is visible-first
Not in the reviewers' prompt (1 file)
  • pnpm-lock.yaml: generated or a lockfile, so its lines were left out

Reply under an inline comment with @apex-sentinel-staging note ... or @apex-sentinel-staging pivot ... to re-check that finding.
Comment @apex-sentinel-staging review on this conversation to run a full review.

@apex-sentinel-staging apex-sentinel-staging Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apex Sentinel: 4 new findings on 23907a4. The verdict and the full list are in the summary comment.

Comment thread packages/command-output/src/index.ts Resolved
@thymikee

Copy link
Copy Markdown
Member Author

I reviewed 23907a4 and found no code problems that need a change before merge. The extraction reads as formatting-only.

Not blocking, and you can take or leave these: colorize in color.ts calls styleText with no options, so Node re-reads process.stdout and the env and ignores the injected supportsColor result (passing {validateStream:false} fixes it and lets diff.test.ts stop mutating process.env); formatToolErrorText in src/mcp/tool-error.ts still rebuilds the lines that formatHumanErrorLines now owns; responseWarningRoute(findCommandMetadata(name)) is repeated at five sites, so it could take the command name and look up inside the package; and src/mcp/command-tools.ts passes stderrIsTTY: Boolean(process.stderr.isTTY) although MCP text never reaches stderr, so MCP should pass false.

The open threads on the R86 named-import gap (#4120 (comment)), the settle command list that is not pinned to the trait (#4120 (comment)), and the ADR 0008 line 14 contradiction (#4120 (comment)) still apply. Three lower-priority threads also still apply: the sample-outputs comment, the duplicated params type, and the unexported ColorStream. These do not apply and can be resolved: the two interactiveOnly threads (#4120 (comment), #4120 (comment)) because the base values had no effect; the facade test threads (#4120 (comment), #4120 (comment)) because the entry path is covered by other callers; the layering comment (#4120 (comment)) because it is illustrative; and the parseableOutput type thread (#4120 (comment)) because the field is declared true.

CI is not settled. Smoke Tests is still running, and CodeQL failed with no excerpt I could read. The PR moves about 40 formatter files, so a CodeQL alert in a moved file may be an old one that now shows as new. Please check the alert and dismiss it if it is old, let Smoke Tests finish, then fix the threads that still apply.

@apex-sentinel-staging apex-sentinel-staging Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apex Sentinel: 3 new findings on 0e344e5. The verdict and the full list are in the summary comment.

Comment thread packages/command-output/src/index.ts Resolved
@thymikee

Copy link
Copy Markdown
Member Author

The code at fd9a924 looks good. The earlier findings from #4120 (comment) are fixed, and nothing new came up in this pass.

CI is green at fd9a924 (24 checks, none failing). I did not rerun check:affected or the vitest suites, so the delta-gate claim rests on the author's comment and CI.

The PR now has merge conflicts with main (ff8c228). #4121 changed package.json, pnpm-lock.yaml, examples/sdk/tsconfig.json, scripts/layering/package-entry-surface.ts and src/commands/cli-runner.ts. Two of these need a manual merge, not a side pick: package-entry-surface.ts, where both PRs add a package entry pin, and cli-runner.ts, where both change imports. I did not try the merge myself. After the rebase, the R86 PROCESS_ENTRIES list and the layering ranks must also include @agent-device/client. Then rerun check:affected.

No inline thread from other reviewers still applies at fd9a924. These are fixed in the code and already resolved: #4120 (comment) (process imports in the pure package), #4120 (comment) (settle command assertion), #4120 (comment) (ADR 0008 formatter ownership), #4120 (comment) and #4120 (comment) (interactiveOnly on -i snapshots), #4120 (comment) and #4120 (comment) (tests call formatCliOutput from the index), #4120 (comment) (layering rank), #4120 (comment) (conformance comment), #4120 (comment) (parseableOutput param type), #4120 (comment) (FormatCliOutputParams type), #4120 (comment) (ColorStream export), #4120 (comment) (FormatCliOutputParams export). Two are harmless and need no change: #4120 (comment) (doctorCliOutput uses the same stderrIsTTY boolean as the other formatters, so it only differs in signature style) and #4120 (comment) (PURE_PRESENTATION_ROOTS already covers the only presentation package, and a global stream ban would widen R86 beyond this extraction).

thymikee and others added 7 commits October 31, 2026 17:05
Move the shared CLI and MCP command presentation (family output formatters, warning routing,
color, human error lines, device and result serialization) out of src/commands into a private
workspace package with one explicit entry. The command surface keeps declaration and projection
and gains no presentation import.

The package performs no process I/O. The purity split lands with the move:
- formatHumanErrorLines returns the stderr lines; printHumanError stays a root writer in
  src/commands/output/human-error.ts, and printJson stays root.
- supportsColor, the diff renderers and the doctor formatter take the terminal fact (stdout stream,
  stderrIsTTY) as input; the CLI and MCP root boundaries pass it from their process.
- CommandProgressState belongs to the formatter owner; the stderr progress sink stays root.
- responseWarningRoute derives the warning route from descriptor metadata, so the light entry
  needs no command-surface value import.

The entry names its exports and loads the formatter tables (formatCliOutput), and the snapshot and
screenshot diff renderers, on first call, so color, serialization and CLI startup users do not
evaluate the formatter closure. MCP no longer evaluates it at startup either.

Deep callers in scripts and tests render through the production formatCliOutput.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ages off process state

Rank the command-output zone above the command surface, pin its single named entry, extend R86 so
packages/command-output/src reads no process member (streams and TTY facts arrive as input), assert
the entry evaluates no formatter table, snapshot or diff renderer, and keep the SDK and command
surface entries free of the package. The provider import ban covers the new package root.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

# Conflicts:
#	scripts/layering/package-entry-surface.ts
… metadata generics

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…e client extraction

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@thymikee
thymikee force-pushed the refactor/command-output-package branch from fd9a924 to bc1c0de Compare October 31, 2026 16:12

@apex-sentinel-staging apex-sentinel-staging Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apex Sentinel: 3 new findings on bc1c0de. The verdict and the full list are in the summary comment.

@thymikee

Copy link
Copy Markdown
Member Author

The code looks good at f4795df. The conflict from the earlier review (#4120 (comment)) is fixed, and the rebase keeps both entry pins and the client process-entry and rank. CI is green on all 24 checks, and there are no conflicts. I checked the conflict resolution through the diff against the new merge-base ff8c228 and the range-diff. I did not run check:affected, layering, or the vitest suites locally, so the gate results rest on CI.

Not blocking, take or leave: formatToolErrorText in src/mcp/tool-error.ts rebuilds the Error/Cause/Hint/Warning/candidate-view/divergence lines that formatHumanErrorLines in @agent-device/command-output already returns, while the package description says it owns CLI and MCP command presentation. A follow-up could build the MCP text from formatHumanErrorLines (adding supportedOn or an option for the diagnostic lines), or narrow the description to CLI presentation.

No open thread still applies. These three do not apply and are already resolved: the one-argument supportsColor thread, because stream is a required parameter in packages/command-output/src/output/color.ts so a one-argument call fails typecheck and every caller passes a stream (#4120 (comment)); the snapshot sample route thread, because the sample now renders through formatCliOutput('snapshot', ..., {interactiveOnly:true}) as production does (#4120 (comment)); and the sample mode thread, because real snapshot -i flattens on main and at head and the hidden-content summary stays (#4120 (comment)).

@thymikee thymikee added the ready-for-human Valid work that needs human implementation, judgment, or maintainer merge label Oct 31, 2026
@thymikee
thymikee merged commit 4b3a764 into main Nov 1, 2026
24 checks passed
@thymikee
thymikee deleted the refactor/command-output-package branch November 1, 2026 06:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-human Valid work that needs human implementation, judgment, or maintainer merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant