Found while running the lower-case-LOCAL census on #13478 (PR #13789). Not fixed there, deliberately: that card's scope was a census of a different spelling, and this one is a third position with its own reading.
The gap
check-dispatcher-error-vocabulary.mjs reaches a code: in an object literal when the value is a quoted literal (objlit), a SCREAMING_SNAKE constant (objlitconst), a template (objlittemplate), or a helper parameter (objlithelper). It does not reach an inline literal expression — a ternary or a ||/?? chain of literals written at the stamp itself:
return{status: isProvisioning ? 503 : isFailed ? 502 : 404,body: {error: raw,code: isProvisioning
? 'PROJECT_PROVISIONING'
: isFailed
? 'PROJECT_PROVISIONING_FAILED'
: 'PROJECT_NOT_FOUND',},};objlit needs the quote immediately after the colon; here the condition comes first.objlitconst needs a SCREAMING_SNAKE identifier after the colon.objlittemplate needs backticks.objlithelper's candidate regex captures the condition's identifier (isProvisioning), which is not a parameter, so it declines.check:error-code-casing needs a quoted lowercase literal beside the token code; these are upper-case, so they are not its business either.
So: no site and no unresolved — the same "no verdict, no report, and nothing says so" shape objlithelper and the assignconst local were each opened to close, in a third position.
This is distinct from #13478's class. That one is a lower-case LOCAL holding the ternary; resolveConstant is the machinery for it. This one is the ternary written at the stamp, where no resolution is needed at all — every branch is a literal already, and literalCodeValues reduces it directly.
The census
Measured on the tree at 597020aa5, with the gate's own primitives (enclosingOpeners, sliceBalanced, splitTopLevel, literalCodeValues) and a positive control that a ternary is caught while a bare literal, a runtime call and a type annotation are each correctly excluded:
| |
|---|
| positions reached by no shape | 2 |
| distinct values behind them | 5 |
| unregistered wire codes hiding | 0 |
Both positions come back clean, for different reasons, and both were checked rather than assumed:
packages/rest/src/error-response.ts:1250 — PROJECT_PROVISIONING, PROJECT_PROVISIONING_FAILED, PROJECT_NOT_FOUND. All three are in ERROR_CODE_LEDGER. Worth noting anyway: this is the REST door file, and these are stamped straight into an HTTP error envelope's body.code. Registered today, invisible to the gate tomorrow.packages/runtime/src/domains/automation.ts:1125 — body.name === undefined ? 'required' : 'invalid_type', inside { field: 'name', code: ... }. A D6 field-addressed validation catalog, legitimately not a wire error code, and correctly outside both gates.
⇒ preventive, not a live defect — the same disposition the census gave #13478, on the same evidence standard.
What a round on this would owe
The discipline the two sibling widenings were held to: census first, then decide. The reconciliation runs in both directions, so any newly admitted value needs a declaration row in packages/runtime/src/dispatcher-error-vocabulary.ts and the row cannot land before the widening. The figures above are the census; what is not measured is what a widening would cost in precision — the objlithelper position already reaches 65 type annotations for every value stamp, and an inline-expression shape would need its own guard against that.
One cheap observation for whoever takes it: unlike the other two, this position needs no resolver at all. literalCodeValues already reduces the expression, so the shape is close to a reduction of the value text between code: and the property's terminating comma.
Family
Generated by Claude Code
Found while running the lower-case-LOCAL census on #13478 (PR #13789). Not fixed there, deliberately: that card's scope was a census of a different spelling, and this one is a third position with its own reading.
The gap
check-dispatcher-error-vocabulary.mjsreaches acode:in an object literal when the value is a quoted literal (objlit), a SCREAMING_SNAKE constant (objlitconst), a template (objlittemplate), or a helper parameter (objlithelper). It does not reach an inline literal expression — a ternary or a||/??chain of literals written at the stamp itself:objlitneeds the quote immediately after the colon; here the condition comes first.objlitconstneeds a SCREAMING_SNAKE identifier after the colon.objlittemplateneeds backticks.objlithelper's candidate regex captures the condition's identifier (isProvisioning), which is not a parameter, so it declines.check:error-code-casingneeds a quoted lowercase literal beside the tokencode; these are upper-case, so they are not its business either.So: no site and no unresolved — the same "no verdict, no report, and nothing says so" shape
objlithelperand theassignconstlocal were each opened to close, in a third position.This is distinct from #13478's class. That one is a lower-case LOCAL holding the ternary;
resolveConstantis the machinery for it. This one is the ternary written at the stamp, where no resolution is needed at all — every branch is a literal already, andliteralCodeValuesreduces it directly.The census
Measured on the tree at
597020aa5, with the gate's own primitives (enclosingOpeners,sliceBalanced,splitTopLevel,literalCodeValues) and a positive control that a ternary is caught while a bare literal, a runtime call and a type annotation are each correctly excluded:Both positions come back clean, for different reasons, and both were checked rather than assumed:
packages/rest/src/error-response.ts:1250—PROJECT_PROVISIONING,PROJECT_PROVISIONING_FAILED,PROJECT_NOT_FOUND. All three are inERROR_CODE_LEDGER. Worth noting anyway: this is the REST door file, and these are stamped straight into an HTTP error envelope'sbody.code. Registered today, invisible to the gate tomorrow.packages/runtime/src/domains/automation.ts:1125—body.name === undefined ? 'required' : 'invalid_type', inside{ field: 'name', code: ... }. A D6 field-addressed validation catalog, legitimately not a wire error code, and correctly outside both gates.⇒ preventive, not a live defect — the same disposition the census gave #13478, on the same evidence standard.
What a round on this would owe
The discipline the two sibling widenings were held to: census first, then decide. The reconciliation runs in both directions, so any newly admitted value needs a declaration row in
packages/runtime/src/dispatcher-error-vocabulary.tsand the row cannot land before the widening. The figures above are the census; what is not measured is what a widening would cost in precision — theobjlithelperposition already reaches 65 type annotations for every value stamp, and an inline-expression shape would need its own guard against that.One cheap observation for whoever takes it: unlike the other two, this position needs no resolver at all.
literalCodeValuesalready reduces the expression, so the shape is close to a reduction of the value text betweencode:and the property's terminating comma.Family
code:fed by a lower-case LOCAL in an object literal is reached by no vocabulary shape — the object-literal twin of the repaired assign-position gap #13478 — the lower-case LOCAL feeding an object-literalcode:. Censused at zero; still open as a declared blind spot.enclosingDeclarationhas no header form for a class PROPERTY holding an arrow — a code helper spelled that way is dropped in silence #13430 —enclosingDeclarationhas no header form for a class PROPERTY holding an arrow. Ended not planned at zero live instances.Generated by Claude Code