Found while implementing #11772, which closes exactly this defect one command over (os build / compile.ts). Out of that card's scope: the maintainer ruling on #11772 is worded for compile.ts specifically, and extending the same widening to a second command's public --json payload is its own machine-contract decision (Clause ②), not a mechanical port. Recorded rather than fixed.
Measured
Read from source at origin/mainc804f0ca5, packages/cli/src/commands/validate.ts. Computation sites vs. emitJson exits, by line:
86 const unknownKeyWarnings = […] <- computed FIRST, pre-parse
94 emitJson parse failure errors (no warnings)
126 const { advisories: ruleAdvisories }
133 emitJson rule errors errors, warnings: ruleAdvisories
169 const capProviderWarnings = […]
175 emitJson capability errors errors (no warnings)
203 const docWarnings = […]
206 emitJson doc errors errors, warnings: ruleAdvisories
238 const structuralWarnings = []
306 emitJson success warnings: all five lists
391 emitJson catch-all error (no warnings)
So on every one of the five failure exits the payload carries strictly less than the run had already computed:
| exit | computed by then | carried | dropped |
|---|
| parse failure (94) | unknownKey | — | 1 |
| rule errors (133) | unknownKey, rule | rule | 1 |
| capability errors (175) | unknownKey, rule, capProvider | — | 3 |
| doc errors (206) | unknownKey, rule, capProvider, doc | rule | 3 |
| catch-all (391) | whatever the run reached | — | all |
Note the parse-failure exit in particular: validate.ts computes unknownKeyWarnings at line 86, before the parse, precisely so the finding survives an unrelated schema error — and then the parse-failure payload drops it anyway. That is a stronger instance than the one #11772 fixes, where nothing is computed that early.
Why it matters
Same shape as #11643 / #11391 / #11772: the text face prints these advisory blocks with — re-run with --json for the full list, and the --json re-run of a tree that fails a later gate returns a payload without the list in it. The remedy the notice names is unreachable until an unrelated failure is fixed.
Not proposed here
The obvious route is the one the maintainer ruled for os build on 2026-08-25 (option 1: every failure exit carries the lists the run has already computed, so warnings means the same thing on every exit). Whether os validate --json's contract should widen the same way — and whether its structuralWarnings member changes the answer — is a decision for triage, not this filing. #11772 is not addressed by this issue; it is already closed out on the build side.
Filed unassigned, no labels — severity and route are triage's call.
Generated by Claude Code
Found while implementing #11772, which closes exactly this defect one command over (
os build/compile.ts). Out of that card's scope: the maintainer ruling on #11772 is worded forcompile.tsspecifically, and extending the same widening to a second command's public--jsonpayload is its own machine-contract decision (Clause ②), not a mechanical port. Recorded rather than fixed.Measured
Read from source at
origin/mainc804f0ca5,packages/cli/src/commands/validate.ts. Computation sites vs.emitJsonexits, by line:So on every one of the five failure exits the payload carries strictly less than the run had already computed:
Note the parse-failure exit in particular:
validate.tscomputesunknownKeyWarningsat line 86, before the parse, precisely so the finding survives an unrelated schema error — and then the parse-failure payload drops it anyway. That is a stronger instance than the one #11772 fixes, where nothing is computed that early.Why it matters
Same shape as #11643 / #11391 / #11772: the text face prints these advisory blocks with
— re-run with --json for the full list, and the--jsonre-run of a tree that fails a later gate returns a payload without the list in it. The remedy the notice names is unreachable until an unrelated failure is fixed.Not proposed here
The obvious route is the one the maintainer ruled for
os buildon 2026-08-25 (option 1: every failure exit carries the lists the run has already computed, sowarningsmeans the same thing on every exit). Whetheros validate --json's contract should widen the same way — and whether itsstructuralWarningsmember changes the answer — is a decision for triage, not this filing. #11772 is not addressed by this issue; it is already closed out on thebuildside.Filed unassigned, no labels — severity and route are triage's call.
Generated by Claude Code