Surfaced by the contract review of PR #15708 (verdict comment 5550099353 on #15064, boundary flags: 「Pre-existing CLI convention gap, out of scope」). Filed unassigned by the patch-round seat for first-touch grading; #15064 is not addressed here and nothing in PR #15708 changes this.
Measured (at 1914df81f)
packages/cli/src/utils/format.ts:246 — errorCodeFields(error) forwards code and httpStatus only; its TSDoc says the SDK sets error.httpStatus = res.status on every wire failure.
- Engine-thrown refusals carry
status, not httpStatus: packages/objectql/src/engine.ts (INVALID_SORT / INVALID_FIELD producers stamp err.status = 400) and packages/objectql/src/summary-backfill.ts resolveRecomputeScope (err.code = 'INVALID_FIELD'; err.status = 400).
- Consequence:
os migrate summary-nulls --json --recompute-undefined-on-empty customer.nope emits { error, code: 'INVALID_FIELD' } with no status field, while the same class of failure arriving over the wire would carry httpStatus: 400. The pin packages/cli/src/commands/migrate/summary-nulls.test.ts 「a refused scope entry (INVALID_FIELD) reaches the --json error envelope with its code」 can only assert code for this reason.
- Every command that spreads
errorCodeFields(error) into a --json envelope over a locally thrown engine error has the same shape (grep -rn "errorCodeFields(" packages/cli/src/commands).
Prior art (searched before filing — MCP search_issues, control query hit #15064)
#8570 (closed) fixed the mirror case in REST batch rows (httpStatus read only .status); #13347 (closed) introduced errorCodeFields for the 48 sites that emitted only error.message; #15549 (open) is a sibling where one os lint --eval --json site spreads no envelope at all. None covers this reader/producer spelling mismatch.
Not a ruling — two shapes, for the owning lane
(a) errorCodeFields also reads a numeric status (the ADR-0112 engine spelling) into httpStatus, declared in its TSDoc — one reader, two producer spellings honoured. (b) Engine producers also stamp httpStatus — touches every producer. Contract-first says the spelling is decided once; which side owns it is the decision.
Re-check
packages/cli/src/utils/format.ts — errorCodeFields
packages/objectql/src/summary-backfill.ts — resolveRecomputeScope
packages/cli/src/commands/migrate/summary-nulls.ts — the two emitJson({ error, ...errorCodeFields(error) }) sites
Generated by Claude Code
Surfaced by the contract review of PR #15708 (verdict comment
5550099353on #15064, boundary flags: 「Pre-existing CLI convention gap, out of scope」). Filed unassigned by the patch-round seat for first-touch grading; #15064 is not addressed here and nothing in PR #15708 changes this.Measured (at
1914df81f)packages/cli/src/utils/format.ts:246—errorCodeFields(error)forwardscodeandhttpStatusonly; its TSDoc says the SDK setserror.httpStatus = res.statuson every wire failure.status, nothttpStatus:packages/objectql/src/engine.ts(INVALID_SORT/INVALID_FIELDproducers stamperr.status = 400) andpackages/objectql/src/summary-backfill.tsresolveRecomputeScope(err.code = 'INVALID_FIELD'; err.status = 400).os migrate summary-nulls --json --recompute-undefined-on-empty customer.nopeemits{ error, code: 'INVALID_FIELD' }with no status field, while the same class of failure arriving over the wire would carryhttpStatus: 400. The pinpackages/cli/src/commands/migrate/summary-nulls.test.ts「a refused scope entry (INVALID_FIELD) reaches the --json error envelope with its code」 can only assertcodefor this reason.errorCodeFields(error)into a--jsonenvelope over a locally thrown engine error has the same shape (grep -rn "errorCodeFields(" packages/cli/src/commands).Prior art (searched before filing — MCP
search_issues, control query hit #15064)#8570 (closed) fixed the mirror case in REST batch rows (
httpStatusread only.status); #13347 (closed) introducederrorCodeFieldsfor the 48 sites that emitted onlyerror.message; #15549 (open) is a sibling where oneos lint --eval --jsonsite spreads no envelope at all. None covers this reader/producer spelling mismatch.Not a ruling — two shapes, for the owning lane
(a)
errorCodeFieldsalso reads a numericstatus(the ADR-0112 engine spelling) intohttpStatus, declared in its TSDoc — one reader, two producer spellings honoured. (b) Engine producers also stamphttpStatus— touches every producer. Contract-first says the spelling is decided once; which side owns it is the decision.Re-check
Generated by Claude Code