Skip to content

[finding] the dispatcher gate's resolver anchors on const, so a let-held error code is reduced by nobody even when every branch is a literal #10918

Description

@claude

Found while closing #10897 (teaching check-error-code-casing to read the
our-default slot in a code local's initializer). Filed rather than absorbed:
it is the OTHER gate's resolver, it is a behaviour change to a deliberate bound,
and #10897 was explicitly scoped to the recognizer.

The shape

declaredInitializers in scripts/check-dispatcher-error-vocabulary.mjs
anchors its head regex on const alone:

consthead=newRegExp(`\\b${exported ? 'export\\s+' : '(?:export\\s+)?'}const\\s+${name}\\s*(?::[^=;\\n]+)?=\\s*`,'g',);

So a code held in a let reduces to nothing. resolveConstant answers null,
the codehelper branch reads that as "unreducible" and takes the documented
runtime-value bound — no site and no unresolved — even when the value is a
plain string literal sitting right there in the source.

That is not the bound #9568 wrote. Its words: "a value a source scan cannot
evaluate is out of reach; a value spelled out in every branch is not, whichever
shape it arrives through."
A let initialized to a literal is spelled out. It
is out of reach only because of how the anchor is spelled.

Measured, with a positive control on each side

Driving deriveSites and findViolations on origin/main at 58563be069,
one fixture per row, each a complete export function that stamps err.code = code and throws:

shapecheck:dispatcher-error-vocabularycheck:error-code-casing
let code = 'REASSIGN_FALLBACK'; if (x) code = 'REASSIGN_OTHER';no site, no unresolved0
let code = 'REASSIGN_FALLBACK'; if (x) code = p?.code || 'reassigned_lower_failed';no site, no unresolved0
control: const code = 'local_direct_failed'1 site (assignconst)0
control: const code = flag ? 'tern_lower_a' : 'tern_lower_b'2 sites (assignconst)0
control: const code = p?.code || 'reassigned_lower_failed'no site1 (local-fallback, after #10897)

Rows 3 and 4 are the control that makes rows 1 and 2 readable rather than a
broken probe: the identical shape spelled const does reduce, lowercase
included, and does produce sites. Row 5 is the casing-gate control on the other
side. Row 1 is the sharpest one — both of its values are literals, both
unregistered, and no gate says a word.

Two separable halves

  1. let / var declarations. The cheap half, and the one that matches
    [finding] check:dispatcher-error-vocabulary still cannot see a code held in a local ternary — sys-metadata-repository's live 403 NOT_CREATABLE / NOT_OVERRIDABLE #9568's stated intent: widen the declaredInitializers anchor. The reason to
    be careful rather than quick is that a let can be reassigned, so the set
    of values a let holds is not simply its initializer — reducing it to the
    initializer alone would report a value the program may not stamp, which is
    the same wrongness the ALL-OR-NOTHING rule ([finding] check:dispatcher-error-vocabulary still cannot see a code held in a local ternary — sys-metadata-repository's live 403 NOT_CREATABLE / NOT_OVERRIDABLE #9568) exists to refuse. The
    honest widening probably reduces a let only when the file contains no
    reassignment of it, and reports it as unresolved when it does — never
    silently, which is the bound this gate holds itself to everywhere else.

  2. Bare reassignment (code = p?.code || 'lit', no declarator) — row 2.
    Harder: no declaration to anchor on, and a textual scan has no scopes. Worth
    recording, not necessarily worth closing. Note [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's new local-fallback
    recognizer deliberately requires a declarator, so the casing gate does not
    reach this one either.

Extent today: not swept

I did not sweep the tree for live victims — that measurement belongs with
whoever takes this, since the right population depends on which half is being
closed. What is known: 47 code-named local declarations exist under
packages/** (measured for #10897's blast radius), and at least one of them is
a let (packages/metadata-protocol/src/protocol.ts:6551,
let code: unknown | null =). Whether any holds an unregistered literal is the
open question.

Search note

The issue-search endpoint is unavailable from an agent seat here ("sessions are
bound to their configured repositories"), so the duplicate check behind this
card is a title grep over the 100 most recently created open issues, not a full
search. Worth a second look before anyone starts.

Refs

#10897 / PR #10914 (where this was found) - #9568 (the ALL-OR-NOTHING reduction
and the bound this contradicts) - #9460 (the local-variable bound it refines) -
ADR-0112 D1

Generated by Claude Code


Generated by Claude Code

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions