Skip to content

fix(docs-audit): exclude ADR-0049 migration ledger entries from registrar discovery - #13058

Merged
os-elon merged 1 commit into
mainfrom
claude/issue-12966-registrar-file-re-anchoring
Aug 29, 2026
Merged

fix(docs-audit): exclude ADR-0049 migration ledger entries from registrar discovery#13058
os-elon merged 1 commit into
mainfrom
claude/issue-12966-registrar-file-re-anchoring

Conversation

@os-elon

Copy link
Copy Markdown
Collaborator

Fixes#12966

REGISTRAR_FILE_RE substring-matches route in a basename, which admitted two ADR-0049
enforce-or-remove ledger entries as route registrars — files whose entire job is to record
that manifest.contributes.routes was retired. A "route registrar" probe was counting
the files that record routes being deleted.

Verified at d60a9810be.

The broken control, reproduced first

#11857's recipe requires reproducing 12 registrar files / 43 tails before any delta
means anything. It does reproduce — at the ref it was written for:

--bridge-coveragetree a6eca9223tree 8f10a79f7a
registrar files1214
route tails4344
client-bound rows222219
reachable4547

Today's tool run against the a6eca9223 tree returns 12 / 43 / 45 / 222identical to
that tree's own tool
, so there is zero tool-version drift and every move below is a tree
effect.

The two files moved the registrar count and nothing else

Per-file ablation of all 14 matched files (each removed, tool re-run, tree restored and
proved byte-identical to HEAD by git hash-object):

ablatedtailsreachable
rest-server.ts44 → 247 → 2
external-datasource-routes.ts44 → 4247 → 45
either ADR-0049 entry44 → 4447 → 47

The first two rows are the dual: the instrument returns non-zero on both columns, so the
two zeros are readings and not a dead probe. Neither entry declares a path: line at all —
the one path byte in the pair sits in the prose phrase "every spec-validating path".

So the card's open question resolves as "neither". The +1 tail and +2 reachable do
not split between the two files; they have a different cause entirely:

  • tails 43 → 44rest-server.ts unrolled for (const publishedPath of [...]) into a
    literal path: `${metaPath}/:type/:name/published`. A variable path yields no tail, a
    literal one does, so exactly one new tail was minted.
  • reachable 45 → 47 — that single tail selects two rows no tail could select before:
    meta.getPublished on rest-route-ledger.ts and meta.getPublished on
    runtime/route-ledger.ts.
  • client-bound 222 → 219 — three :type/:section/:name rows were deleted from
    rest-route-ledger.ts. All three were already unreachable, so reachable moves by zero.

Arithmetic closes: unreachable 177 − 3 deleted − 2 newly reachable = 172.

45 → 47 is the bridge reaching more of its population, not drifting. The figure stays
at 47 and this PR deliberately does not restore 45.

⚠️ Whole-word anchoring does not fix this, at any spelling

Both anchorings were implemented against this tree and measured, then reverted:

recognizerregistrar filestailsreachableentries excluded
today1444470
token route or routes1344470
token route alone442452

The premise is wrong about these two files: routesalready is a whole
dot/dash-delimited token in both, split identically to every genuine registrar —
[18] [kernel__Manifest__contributes] [routes] against [hmr] [routes].

The remedy shipped is therefore the directory class only. It is also the durable half:
the entry population grows every time a route-named key is retired.

Result

registrarFiles 14 → 12. tails, reachable, unreachable, clientRows, the 79-tail
ceiling and the 14/56/102 cause split are all unmoved, and router.zod.ts is preserved.

Contamination re-derived at d60a9810be: 2 of 275.ts files under
packages/spec/src/migrations/entries/ (the positive control is the 275; triage read 273
yesterday, the tree grew by two). There is no third contaminant, and it is the only
directory in the tree with this shape.

Also in this diff

The 45 quotes in this file and in scripts/docs-audit/README.md are ref-pinned to
9ff11921a and remain true of it, so they are not rewritten. What was missing is a current
figure with a cause, and that is added beside them. One live claim did expire and is
corrected: a note asserting nothing bridges to /:type/:name/published "today", which the
publishedPath literalisation has since made false — the hermetic fixture it sits beside is
kept verbatim.

skip-changeset: this PR edits a CI-internal script and releases nothing, which is the case
lint.yml names verbatim as the textbook one for the label.

Verification

  • --self-test 474 → 487 cases, all green.
  • Non-vacuity, measured: reverting only the call site to the pre-fix line turns exactly
    7 cases red — the two walk equalities plus five per-fixture rows — while the six
    predicate pins and the over-reach control (migrations/runner-route.ts must stay a
    registrar) stay green, which is the prediction made before running. Live coverage returns
    to 14/44/47 while ablated. Tool restored byte-identical to HEAD afterwards.
  • Gate family derived from the real diff via scripts/pm/dispatch-gates.mjs --repo, exit
    codes captured before any pipe. 19 families, all exit=0, including
    docs-audit/check-affected-docs and docs-audit/check-drift-comment, and the two
    convention-triggered ones this diff incurs by editing a gate script
    (pm/bare-root-worklist.mjs --self-test, check:pm-dispatch-gates).

Records quoting the stale figure

#10534 and #9572 both quote 45. Neither is edited here; both are flagged in a comment on
#12966 with the cause of the move. #11857 remains open and untouched — remedy 3 (require a
runtime registration signal) belongs to its half A and is not implemented here.

Generated by Claude Code


Generated by Claude Code

…trar discovery
REGISTRAR_FILE_RE substring-matches `route` in a basename, which admitted two
ADR-0049 enforce-or-remove ledger entries -- files that record `contributes.routes`
being RETIRED -- as route registrars. Excluded as a directory class instead, and
the current bridge figures are recorded with the cause of every move.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CPrUz21stTFhJRUirdc4yw
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

Nothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs.

What this run could not see
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.

Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json e4902d2b95f1a941fcb7d6dc71ead8f5adef5e6fpackageMentionDocs.

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

Labels

documentationImprovements or additions to documentationsize/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@os-elon@claude