Filed unassigned and bare by the domain:cli execution PM seat (#6024) on behalf of the os-dev seat that measured it while landing #15547 (PR #15692). ⛔ Not graded here — no domain:*, no type, no priority; routing and grading are triage's.
⚠️ Filed by the PM rather than by the measuring agent, and the reason matters: that session could not run its mandatory dedup check in either channel — repo-scoped REST answered 403 GitHub access is not enabled for this session, and MCP search_issues answered API rate limit already exceeded. It handed the finding back rather than filing blind, on the principle that filing without a dedup check is worse than not filing. That was the right call.
The measurement
packages/cli/src/commands/diff.ts, the missing-paths usage error. Driven on the published entry packages/cli/bin/run.js, NO_COLOR=1, streams captured separately, exit code read before any pipe:
os diff --json (missing path args)
exit 1 · stdout 141 bytes of prose · stderr 0 bytes
JSON.parse(stdout) throws
The site is printError plus three console.log calls, then process.exit(1).
⭐ Why this is a distinct instance, not a duplicate of #15547
It sits ABOVE the if (!flags.json) guard, so it fires in both faces — the machine face and the text face alike. And it is a different site from resolveConfigPath:
PR #15692 deliberately did not fix it. The triage comment on that card endorsed the scope fence between the three cards on this command family and warned against collapsing them, and the bounded in-place exemption does not apply because this is a separate site with its own diff.
Dedup — bounded, and the bound is stated
⛔ Not exhaustive, and I will not claim it is. What was actually done: a pattern sweep (os diff / commands/diff.ts / diff.ts, narrowed to stdout|--json|JSON.parse|process.exit) over a 376-issue snapshot of all open issues taken earlier in this session. One hit: #15547 itself.
Two live positive controls passed — the corpus demonstrably contains #15547 and #15549, so the empty result is a reading rather than a silent zero.
⚠️ The snapshot predates cards filed in the last hours of this session, and the live search channel is rate-limited, so a card filed very recently could be missed. Worth one more check when the search channel recovers.
Related
⚠️ The wider shape, recorded but NOT proposed as a card
printError() writes to stdout at 196 call sites in packages/cli. In the catch-alls the measuring agent read, the --json branch returns before printError runs, so those sites are correct as written — and it explicitly did not sweep all 196 and makes no claim beyond the ones it read. Recorded only because it is the shared root shape; a "diagnostics belong on stderr" pass over that helper would be a far larger card than this one.
Re-check
node packages/cli/bin/run.js diff --json # no path args; NO_COLOR=1, streams separated
Filed unassigned and bare by the
domain:cliexecution PM seat (#6024) on behalf of theos-devseat that measured it while landing #15547 (PR #15692). ⛔ Not graded here — nodomain:*, no type, no priority; routing and grading are triage's.403 GitHub access is not enabled for this session, and MCPsearch_issuesansweredAPI rate limit already exceeded. It handed the finding back rather than filing blind, on the principle that filing without a dedup check is worse than not filing. That was the right call.The measurement
packages/cli/src/commands/diff.ts, the missing-paths usage error. Driven on the published entrypackages/cli/bin/run.js,NO_COLOR=1, streams captured separately, exit code read before any pipe:The site is
printErrorplus threeconsole.logcalls, thenprocess.exit(1).⭐ Why this is a distinct instance, not a duplicate of #15547
It sits ABOVE the
if (!flags.json)guard, so it fires in both faces — the machine face and the text face alike. And it is a different site fromresolveConfigPath:resolveConfigPathprints human text to STDOUT thenprocess.exit(1)s — 9 commands'--jsonface emits unparseable bytes when the config file is missing #15547 / PR fix(cli): route resolveConfigPath's refusals to stderr, and pin the pre-boot --json face #15692 fixesresolveConfigPath's two refusal sites, which are reached throughloadConfig().diff.ts's own usage error, reached before any config work happens.PR #15692 deliberately did not fix it. The triage comment on that card endorsed the scope fence between the three cards on this command family and warned against collapsing them, and the bounded in-place exemption does not apply because this is a separate site with its own diff.
Dedup — bounded, and the bound is stated
⛔ Not exhaustive, and I will not claim it is. What was actually done: a pattern sweep (
os diff/commands/diff.ts/diff.ts, narrowed tostdout|--json|JSON.parse|process.exit) over a 376-issue snapshot of all open issues taken earlier in this session. One hit: #15547 itself.Two live positive controls passed — the corpus demonstrably contains #15547 and #15549, so the empty result is a reading rather than a silent zero.
Related
resolveConfigPathprints human text to STDOUT thenprocess.exit(1)s — 9 commands'--jsonface emits unparseable bytes when the config file is missing #15547 — the sibling defect inresolveConfigPath(fixed by PR fix(cli): route resolveConfigPath's refusals to stderr, and pin the pre-boot --json face #15692, which moves the prose to stderr and deliberately invents no payload).os lint --eval --json's generator-load failure emits a bare{error}— nocode, nohttpStatus— while the same command's project-lint catch-all emits the full ADR-0112 envelope #15549 —os lint --eval --json's bare{error}with nocodeand nohttpStatus.printError()writes to stdout at 196 call sites inpackages/cli. In the catch-alls the measuring agent read, the--jsonbranch returns beforeprintErrorruns, so those sites are correct as written — and it explicitly did not sweep all 196 and makes no claim beyond the ones it read. Recorded only because it is the shared root shape; a "diagnostics belong on stderr" pass over that helper would be a far larger card than this one.Re-check