Skip to content

[finding] check-error-code-casing's ||/?? fallback recognizer anchors on the STAMP SITE only, so our authored default in a const code = … initializer is still seen by no gate #10897

Description

@os-zhuang

Found while executing #10762 (documenting the delegation map after the #10658 / PR #10760 widening). Filed rather than absorbed: it is a different gate, a behaviour question rather than a comment one, and #10762 is comment-only by construction.

The shape

PR #10760 added a fifth recognizer to scripts/check-error-code-casing.mjs for the OUR-DEFAULT slot of a ||/?? chain. Its anchor is the position token:

re: /(?:\bcode\s*\??\s*:|\.code\s*=(?!=))\s*(?['"`])[\w$.?!()[\]|&\s]{0,80}?(?:\|\||\?\?)\s*'([a-z][a-z0-9_]*)'/g

So it reaches the chain when the chain sits at the stamp site{ code: parsed?.code || 'lit' }, err.code = e?.code ?? 'lit'. It does not reach the identical chain one indirection earlier, in a local's initializer:

const code = parsed?.code || 'lower_thing';   // ← our authored default, same as above
const err = new Error(msg);
err.code = code;
throw err;

const code = is neither code:/code?: nor .code =, so no pattern matches. A typed local does not help either: const code: string = … puts an = in the gap class, which the class refuses.

Measured, with a live positive control on both sides

Driving both gates' own exported entry points (findViolations, deriveSites) on origin/main at 9faa9bc51d:

shape check:dispatcher-error-vocabulary check:error-code-casing
stamp-site { code: p?.code || 'stamp_lower_failed' } no site 1 (fallback)
stamp-site err.code = p?.code || 'stamp_lower_failed' no site 1 (fallback)
local-init const code = p?.code || 'local_lower_failed' no site, no unresolved 0
local-init const code = p?.code || 'LOCAL_UPPER_FAILED' no site, no unresolved 0 (out of its value space)
control: local-init const code = flag ? 'TERN_A' : 'TERN_B' 2 sites (assignconst) n/a

The last row is the control that makes the zeros readable: the dispatcher gate does reduce and report a local initializer when every limb is a literal (#9568), so its silence on row 3 is the deliberate ALL-OR-NOTHING bound, not a broken probe. The casing-gate rows 1–2 are the matching control on the other side.

Row 3 is therefore reported by neither gate — the same "two gates, each assuming the other" configuration that check-dispatcher-error-vocabulary's own header records for owd_widening_forbidden.

Why it is arguably the casing gate's, not the dispatcher gate's

The dispatcher gate's silence is correct and should not change: under #9568 a chain with one runtime limb reduces to nothing, because harvesting the literal half would report a code the program may never stamp while staying silent about the limb it cannot see.

But that is exactly the epistemic position PR #10760 already ruled on for the stamp site, and ruled the other way, in its own words: the pattern "still only ever captures a STRING LITERAL, and a literal in our source is by construction ours … it reaches only the default WE author, which is exactly the operand ADR-0112 D1 governs." const code = parsed?.code || 'lower_thing' is our authored default by that same reasoning. The asymmetry between the two positions is an artifact of where the recognizer anchors, not a decision anyone took.

Extent today: 0

Swept 1885 non-test .ts/.tsx files under packages/ (comments masked with the gates' own maskComments) for a code-named local whose initializer is a runtime-limbed ||/?? chain with a lowercase literal default: 0 hits. Like #10762, the drift understates coverage and has no live victim today — recorded so the next reader does not have to re-derive it.

Refs

#10762 (the delegation map, where this boundary is now written down) · #10658 / PR #10760 (the widening) · #9568 (the ALL-OR-NOTHING reduction) · ADR-0112 D1

Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions