Observation
scripts/check-required-contexts.mjs conflates two facts under one registry: "this context is required" and "this job's name: literal is contract". For a required context the two coincide, so the conflation was free. It stops being free the moment a row is dropped for the first reason while the second still holds.
That happened on #9533 (2026-08-18): the Build Docs (ci.yml:build-docs) and Console Pin Gate (ci.yml:console-pin) rows were dropped because the live ruleset never carried those contexts. Correct, and the intended outcome. The side effect is that both name: literals are now asserted by nothing, while these places still refer to the jobs by exact name:
| site | what it says |
|---|
docs/releases-maintenance.md:204 | "It is not the Console Pin Gate" — disambiguates it from check-objectui-pin-fresh |
packages/console/README.md:38 | "Opening the PR runs CI's Console Pin Gate" |
scripts/check-objectui-pin-fresh.mjs (3 sites, incl. a self-test assertion) | the same disambiguation, asserted on its own report text |
.github/workflows/objectui-pin-freshness.yml:5-8 | "NOT ci.yml's Console Pin Gate — the names are close" |
.github/workflows/lint.yml:1548 | "Deliberately lives in this job, not in ci.yml's Build Docs" |
Renaming either job is now a one-line edit that silently falsifies all of the above. That is the #6865 defect shape exactly — a load-bearing string with nothing saying so — minus the merge-queue consequence, which is the half that made it urgent enough to build a gate for.
Why it was not fixed in #9533
A pin for "contract job names that are not required contexts" is a new mechanism, and #9533's card was ledger hygiene under a maintainer ruling that said drop the rows. Building the mechanism there would have been scope creep in a PR whose whole point was that the registry should not claim more than it can attest.
Also worth weighing before building anything: RETIRED_CONTEXT_NAMES is explicitly the wrong home (measured on #9533 — a row there reds docs/releases-maintenance.md's correct current prose with a diagnostic that is false, because neither name is dead).
Options, if this is worth closing at all
- A. Do nothing. The cost of a silent rename here is stale prose, not a gate outage. Cheapest, and the honest baseline.
- B. A second list in the same file —
CONTRACT_JOB_NAMES, asserting only assertions 1-3 (file parses, job id exists, name: matches) with a why field naming the prose that depends on it. Small, reuses judge, no new file. - C. Push it onto the referring sites — have
check-objectui-pin-fresh.mjs assert ci.yml's job name, since it already self-tests its own disambiguation text. Distributes the assertion to whoever depends on it, at the cost of each site growing a workflow read.
No recommendation attached; this is filed as an observation, not a queued card. finding, unassigned.
Generated by Claude Code
Observation
scripts/check-required-contexts.mjsconflates two facts under one registry: "this context is required" and "this job'sname:literal is contract". For a required context the two coincide, so the conflation was free. It stops being free the moment a row is dropped for the first reason while the second still holds.That happened on #9533 (2026-08-18): the
Build Docs(ci.yml:build-docs) andConsole Pin Gate(ci.yml:console-pin) rows were dropped because the live ruleset never carried those contexts. Correct, and the intended outcome. The side effect is that bothname:literals are now asserted by nothing, while these places still refer to the jobs by exact name:docs/releases-maintenance.md:204check-objectui-pin-freshpackages/console/README.md:38scripts/check-objectui-pin-fresh.mjs(3 sites, incl. a self-test assertion).github/workflows/objectui-pin-freshness.yml:5-8.github/workflows/lint.yml:1548Renaming either job is now a one-line edit that silently falsifies all of the above. That is the #6865 defect shape exactly — a load-bearing string with nothing saying so — minus the merge-queue consequence, which is the half that made it urgent enough to build a gate for.
Why it was not fixed in #9533
A pin for "contract job names that are not required contexts" is a new mechanism, and #9533's card was ledger hygiene under a maintainer ruling that said drop the rows. Building the mechanism there would have been scope creep in a PR whose whole point was that the registry should not claim more than it can attest.
Also worth weighing before building anything:
RETIRED_CONTEXT_NAMESis explicitly the wrong home (measured on #9533 — a row there redsdocs/releases-maintenance.md's correct current prose with a diagnostic that is false, because neither name is dead).Options, if this is worth closing at all
CONTRACT_JOB_NAMES, asserting only assertions 1-3 (file parses, job id exists,name:matches) with awhyfield naming the prose that depends on it. Small, reusesjudge, no new file.check-objectui-pin-fresh.mjsassert ci.yml's job name, since it already self-tests its own disambiguation text. Distributes the assertion to whoever depends on it, at the cost of each site growing a workflow read.No recommendation attached; this is filed as an observation, not a queued card.
finding, unassigned.Generated by Claude Code