fix(qa-checklist): re-point nine bad-citation anchors and drain their residual rows - #19181
Merged
os-try-charles merged 1 commit intoSep 19, 2026
Merged
Conversation
…ng route-ledger anchors First slice of the SHARED_RESOLVER_RESIDUAL drain. Nine `bad-citation` rows across three area files are repaired at the citation, not at the resolver: each anchor named a client-method name, a route path parameter or an imported class, none of which is a declaration site in the cited file. Every one is re-pointed at the declaration the item actually means -- the route table the file exports, or the host plugin list -- following the convention this corpus already uses for `auth-route-ledger.ts#AUTH_ROUTE_LEDGER`. No `#symbol` is dropped, so the floor population is byte-identical: the anchor census prints the same per-file counts before and after, with ten occurrences moving from `residual` to `resolved` (577/633 -> 587/633). The ledger's ceiling comes down with the rows, 55 -> 46, and the shape and verdict tallies in its header are re-counted in the same edit. Claude-Session: https://claude.ai/code/session_017ef78bLdybu3AffehKkhfk Co-authored-by: Claude <noreply@anthropic.com>
os-try-charles
marked this pull request as ready for review
September 19, 2026 09:09
os-try-charles
deleted the
claude/issue-18104-drain-bad-citation-residual
branch
September 19, 2026 09:54
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #18104
Clause-②: no
The slice, and why these three
SHARED_RESOLVER_RESIDUALcarries 47bad-citationrows across 12 area files. The cardallows landing per area file, so this is the first slice:
areas/access-security.json,areas/api-backend.jsonandareas/automation.json— 9 rows, 10 anchor occurrences.They were picked because they are one reading, not three: 8 of the 9 cite a route
ledger —
packages/rest/src/rest-route-ledger.ts,packages/runtime/src/route-ledger.tsand
packages/triggers/trigger-api/src/trigger-api-route-ledger.ts— and every one of themnamed something a route TABLE carries as data (a client-method name, a route path
parameter) rather than something the file declares. Repairing them is one judgement applied
nine times, which keeps the PR reviewable; the remaining 38 rows are untouched and stay on
the ledger.
Per row: which kind it was (acceptance item 2)
All nine are genuinely wrong citations, re-pointed. None of them is an
accept-setcase,so none of them belongs to #18101. Each old symbol was checked against
scripts/symbol-anchors.mjs#symbolResolutionClassdirectly and returnsnull; each new onereturns
declaration.rest-route-ledger.ts#saveItemclient:string value#REST_ROUTE_LEDGERrest-route-ledger.ts#shareId#REST_ROUTE_LEDGERrest-route-ledger.ts#REST(2 occurrences, 1 row)#REST_ROUTE_LEDGERruntime/route-ledger.ts#getLegalNextStates#ROUTE_LEDGERtrigger-api-route-ledger.ts#flowName#TRIGGER_API_ROUTE_LEDGERruntime/route-ledger.ts#getScreen#ROUTE_LEDGERruntime/route-ledger.ts#runId#ROUTE_LEDGERruntime/route-ledger.ts#getRuntimeStatus#ROUTE_LEDGERobjectstack.config.ts#ConnectorRestPlugin#pluginsThe eight ledger rows are not renames. Each citation's prose already named the routes or the
families it means; what it was missing was a symbol the cited file declares, and in a route
ledger that is the exported table. This is the corpus's own established spelling — the
line two entries above one of the repaired ones already reads
packages/plugins/plugin-auth/src/auth-route-ledger.ts#AUTH_ROUTE_LEDGER.The ninth is a different reading.
objectstack.config.tsimports the three connector pluginclasses and constructs them; the declaration the item is about — "this host wires these
connectors" — is the host's own
pluginslist, which is an object-literal key at the startof a line and resolves as a
declaration. The original parenthetical naming all threeplugin classes is kept intact.
No
#symbolwas dropped, and no floor moved--anchor-censusis byte-identical before and after, all 17 family files:That is the mechanical statement of it: the floor population is
resolved + residual, so arepair moves an occurrence from one side to the other and leaves every per-file count where
it was. Ten occurrences moved: 577/633 resolved -> 587/633, residual 56 -> 46.
scripts/checklist-symbol-anchor-baseline.jsonis untouched.Rows left by repair, and the ceiling came down with them
SHARED_RESOLVER_RESIDUAL55 rows -> 46.SHARED_RESOLVER_RESIDUAL_CEILING55 -> 46, inthe same edit. The header's shape tallies are re-counted with the rows
(
string-substring29 -> 21,import-only9 -> 8,bad-citation47 -> 38);accept-setstays 8 and is untouched.
The binding measurement in that header ("56 of 633, at #16898") is left standing as the
dated reading it is, with a note saying so and pointing a reader at
SHARED_RESOLVER_RESIDUAL.lengthand the console line for the live count.Positive control (acceptance item 3)
Two legs, each mutating the committed tree, proving the mutation landed on disk before
reading any verdict, then restoring with
git checkout HEAD --the mutated path and proving therestore by blob hash against HEAD plus an empty
git diff HEAD— never by an exit code.Control run first: bare gate exit 0, zero
ABSENT SYMBOLlines.Leg A — a repaired anchor is still being judged, and it resolves. One repaired citation
in
api-backend.jsonwas re-pointed toREST_ROUTE_LEDGER_ABLATION_NOT_DECLARED(on-diskproof: target text before=1, injected marker after=1). Gate exit 1:
Restored (blob
64486cd5...== HEAD,git diff HEADempty), gate back to exit 0. Sothe green on these citations is the shared resolver answering
declaration, not the gatehaving gone quiet on them.
Leg B — an unrelated row still reds. The un-repaired
areas/studio-authoring.json/rest-route-ledger.ts#getHistoryrow was deleted from theledger without repairing its citation (on-disk proof: row before=1, after=0). Gate
exit 1 with
ABSENT SYMBOLnaming that anchor; restored (blobb52b00f3...== HEAD),back to exit 0. So the nine rows left this ledger by repair — the population is still
firing for everything that was not repaired.
Gates
node scripts/pm/dispatch-gates.mjs --commandsre-derived against the real changed set(4 paths, committed) yields 31 families, matching the dispatch's derivation.
All 31 were run and all 31 exited 0 — reconciled with
dispatch-gates --ran RECORDFILE --repo objectstack-ai/objectstack:31 derived, 31 run, 0 NOT-MEASURED, 0 UNRUN, with an exit code recorded per command sothat zero is derived rather than claimed.
scripts/check-platform-checklist.mjsis itself a gate, so both halves were runseparately, not just the aggregate: bare invocation exit 0 (
OK - 15 areas, 264 items ... 587/633 resolved ... 46 on the named #16898 residual, 17 file floors held) and--self-testexit 0 (221 assertions).pnpm check:platform-checklist, which chainschecklist-select --self-testin front of both, also exits 0.One family first reported exit 3 — PREREQUISITE NOT MET, not a finding:
@objectstack/lint run check:doc-formula-expressionswants@objectstack/formulaand@objectstack/lintbuilt. Built them (under the shared verify lock) and re-ran: exit 0.No import relationship changed and no TypeScript program's view moved — the diff is one
ESM gate script's data plus three JSON documents — so no per-package
typecheckis owedbeyond what the derivation already places.
"All 31 derived families green" is not "CI green". The derivation itself names what sits
outside those 31: 53 artifact-roster families, 11 declared-wide-population families, 14
families that apply once a changeset exists, and 1 path-scheduled CI job. CI is the
authority on those.
Changeset
No changeset: nothing published moves. Measured rather than assumed — the root package is
private, and no package manifest in the tree declares afiles[]entry escaping its owndirectory, while this diff touches only repo-root
scripts/anddocs/qa/, neither ofwhich is inside any package.
skip-changesetapplies.Acceptance notes
$commentis now inaccurate, and this PR deliberately does not fixit. It reads "Each entry is the count of anchors that RESOLVED in that family file";
since [finding] the platform-checklist corpus resolves symbol anchors with its OWN rule, not the shared resolver — a permissive token match where the ruling says there is to be exactly one implementation #16898 an entry is resolved + residual, which the gate's own
--anchor-censusfooter states outright.
scripts/checklist-symbol-anchor-baseline.jsonline 3 declaresitself
⛔ MAINTAINER-ONLY, and reading that authority narrowly — as scoping only tolowering a floor — is the move the line exists to stop. Reported, not touched. It is a
one-sentence maintainer edit.
detector-artifactrow is not in this slice, and the card's repair instruction forit does not survive contact with the tree at
eeaa88245. The card says "repairing itmeans fixing the detector, not the citation". But platform-checklist reuses the shared resolver's RULE but is still not a registered corpus — the anchor grammar stays forked, and the two copies have already drifted (23 extensions vs 8) #18107 moved this corpus's detector into
the shared core:
scripts/check-platform-checklist.mjsimportsextractAnchors,sweepCorpusandANCHORABLE_EXTENSIONSfromscripts/symbol-anchors.mjsand carries noanchor grammar of its own — its own
--self-testasserts exactly that. The phantom#accessis produced bySYMBOLin the shared module, whose character class admits nohyphen. So "fix the detector" is now a change to
scripts/symbol-anchors.mjs, which allthree cards in this split forbid by name. Whoever takes
areas/identity-auth.jsonneedseither a maintainer ruling on that widening or a citation-side repair — and the
citation-side repair on the current bytes is not obvious either, because the anchor there
is written
...access-security.json#accessfollowed by a space, with the item-idaccess-security.scope-depth-asymmetryin the parenthetical after it. Noted for triage,not filed as a separate card from here.
Generated by Claude Code