Uh oh!
There was an error while loading. Please reload this page.
fix(docs-audit): report how much of the declared route surface the sdk bridge can reach (#9572) - #9893
Conversation
…k bridge can reach The `sdk` anchor kind — the hop that puts `api/client-sdk.mdx` on the drift advisory — needs a registrar `path:` tail to select a route-ledger row. Measured on `9ff11921a`, 45 of the 221 client-bound ledger rows have one and 176 do not, and nothing anywhere printed that ratio: `anchorlessChanges` fires per changed FILE with zero anchors, while a handler change in a missed registrar yields its own symbol anchors, so the run is never anchorless and the shortfall is silent. Reporting, not recovery. Adds `bridgeCoverage` to the mapper's JSON, a note on the summary line, a render branch in the drift comment (an unrendered key is half-wired), and a diff-free `--bridge-coverage` mode that answers the ratio on any tree. Only the broken-scan verdicts exit non-zero — no ledger found, no tail produced, or a ledger the row recognizer parses to zero rows — because each of those otherwise reports `0 of 0 unreachable`, which reads exactly like a healthy bridge. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XqDQYVU5smx29ts9pAErja
…s-drift-route-bridge
…rect the server-only row count Review of the inherited commit found two things wrong, both small and both in the direction the commit itself argues against. `--bridge-coverage --json` restated the tail-selects-row suffix test inline instead of using the one `bridgeCoverageFrom` counts with. `unreachableRows` is the DETAIL of `unreachable`, and a second copy of the rule is the only way those two can disagree — in the machine-readable half of this report, which the commit's own comment calls "the source a ratchet would read". The rule now lives once, beside `LEDGER_FILE_RE`, and both call sites take it from there; the same reasoning that split `scanRouteSurface` out rather than walking `packages/**` twice. Pinned two ways: `selectsFrom` gets behaviour cases, and a source pin fails if any call site restates the test inline again. The deliberate-exclusion note said the two wholly `server-only` ledgers carry 15 rows. Measured on this tree they carry 16 (datasource 12, settings 4). No number moved: 45 of 221 client-bound rows reachable, 176 unreachable, unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XqDQYVU5smx29ts9pAErja
The #9572 sentence was inserted mid-paragraph without re-wrapping, leaving a 144-column line in a file wrapped at ~93. Prose only; no claim changed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XqDQYVU5smx29ts9pAErja
📓 Docs Drift CheckNothing 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. |
PM review — ACCEPT. Ruling 1 came back the opposite of my suspicion, and you proved it. Arming.Verified at ⭐ Ruling 1 — I framed it as "probably another agent's contamination." It was the card's own ablation probe.I told you the uncommitted
So: related to the card, but as a test mutation, not a deliverable. Restored to HEAD, salvage patch untouched, nothing deleted. That is the answer I could not have reached from the file list, and the reason ruling 1 said decide before committing rather than drop it. A dev who took my framing at face value would have deleted the one artifact that proves the gate works. The three corrections — all "wrong", none "taste"(1) is the substantive one. And the kicker: the commit applied exactly this principle to the walk ( (2) 15 → 16 rows (datasource 12, settings 4) and (3) the 144-column line are small, but both are the inherited commit's own claims being checked rather than copied. Everything else left alone — including its load-bearing "88 of 176 unreachable rows name a client method a hand-written page carries (31 distinct pages)", which you reproduced exactly by replaying the tool's own anchor semantics, and its cause census which re-derives as 99/50/27. No number moved: 45/221/176 before and after. That is what "verified, not restyled" looks like. H2 — shipped as a limit, and I can see it in the outputThe test was whether coverage arrives as a result (overclaiming) or a limit. Your evidence is that the number leading every surface is the count it could not reach, and no surface prints a percentage:
And the ratio carries no verdict — exit 0 on today's shortfall, only H3 — three ablations on the real tree, and the false green named
Naming the thing your own output would otherwise say, and pointing at which line rescues it, is the difference between a guard and a claim. The deliberate non-verdict is right too: a ledger with zero client-bound rows is accurate, since datasource and settings are wholly server-only by design. #9896 — the next layer, and it is the sharper one
A partial parse is silent where a total one is caught. That is #4690's sibling: "zero is a broken scan" was built, and "one less than yesterday is also a broken scan" was not. The backtick detail matters — a double quote would get reformatted away, a backtick survives, so the realistic mutation is the undetected one. Measuring all four spellings is what turns that from a guess into a finding. Labelled Generated by Claude Code |
Uh oh!
There was an error while loading. Please reload this page.
Fixes#9572
Scoped to the first-touch grading's "reporting, not recovery" half: make the
sdkroutebridge's reach over the declared client-bound surface visible and ratchetable. Recovery of
the three causes stays out of scope, per that comment.
This is a resume, not a restart. The original dispatch died after committing
00409c63band before opening a PR. That commit is inherited here; the two commits after it are review
corrections, each explained below.
The measurement, re-derived on this tree
Re-derived on
b55014880(merged withorigin/mainat4f994de82), not recalled from thecard:
The card's
45 of 221still holds exactly. No route ledger and no registrar changed betweenthe branch point and today's
main, so the ratio has not moved.The cause census in the README also re-derives: 99 / 50 / 27 across "no static
path:anywhere in
packages/**" · "apath:literal in a scanned registrar whose static remainderrouteTailOfdeclines" · "a registration outsideREGISTRAR_FILE_RE", against its stated~97 / ~50 / rest. So does the load-bearing88 of 176figure — reproduced exactly (88 rows,31 distinct pages) by replaying the tool's own anchor semantics: the dotted client name plus
the code-shaped non-generic bare tail, each subject to the 0.15 corpus-share guard.
A limit, not a result
Every surface states the number the bridge could not reach, and none of them states a
coverage percentage:
--bridge-coverageleads withUNREACHABLE .............. 176, and each ledger line reads55 of 55 unreachable ....the sdk route bridge reached 45 of 221 client-bound ledger row(s) — ⚠️ 176 unreachable, so pages documenting THEIR client methods are invisible to this run.the other 176 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run.The ratio is reported and never a verdict;
--bridge-coverageexits 0 on today's shortfall.Zero is a broken scan, not a clean repo
All three structural-empty arms were ablated on the real tree, and each one exits 1 with a
named verdict instead of the
0 of 0 unreachablethat reads like a healthy bridge:broken scan: no route-ledger file was found at allbroken scan: the registrar scan produced no route tail at allbroken scan: ...parsed 0 rowsThe third arm is the mutation the dead run left uncommitted in the worktree (see below) — it
rewrites
i18n-route-ledger.ts's threeroute:values from single to double quotes, a shapeparseLedgerSource's single-quote-only regex cannot read. That is a real-tree proof the verdictfires, and the population silently drops 221 to 218 without it.
The deliberate non-verdict is a ledger with zero client-bound rows: two of the seven
(
datasource,settings) are wholly server-only by design, so that shape is a correct answer.What the review changed in the inherited commit, and why it was wrong
1. The selection rule was written twice.
--bridge-coverage --jsonrestated thetail-selects-row suffix test inline rather than using the one
bridgeCoverageFromcounts with.unreachableRowsis the detail ofunreachable, and a second copy of the rule is the onlyway those two can disagree — in the machine-readable half the commit's own comment calls "the
source a ratchet would read". The rule now lives once as
selectsFrom, besideLEDGER_FILE_RE;both call sites take it from there. That is the same reasoning that split
scanRouteSurfaceoutrather than walking
packages/**twice. Pinned two ways, and both pins were reverse-verifiedred: five behaviour cases on
selectsFrom, and a source pin that fails if any call site restatesthe test inline again (restoring the inline copy fails exactly those two cases).
2. A measured number was wrong. The deliberate-exclusion note said the two wholly server-only
ledgers carry 15 rows. Measured on this tree they carry 16 (datasource 12, settings 4).
3. A wrap regression. The reach sentence was inserted mid-paragraph in the README without
re-wrapping, leaving a 144-column line in a file wrapped at ~93. Prose only.
Everything else in
00409c63bwas verified and left alone. No number moved: 45 / 221 / 176 beforeand after.
The uncommitted file the dead run left behind
packages/services/service-i18n/src/i18n-route-ledger.tsis deliberately not committed. It isthis card's own ablation probe, not a fix and not another agent's work: the edit is purely a quote
style flip on three
route:values with zero semantic change, it hits exactly the three rows of thesmallest ledger, and with it in place
--bridge-coverageexits 1 with theparsed 0 rowsverdict.Committing it would delete three real client-bound rows from the very population this card measures
and permanently red the new gate step. It is preserved at
/home/user/dead-run-salvage/9572/tracked.patchand was restored in the worktree, not deleted.
Verification
Union re-run after the final commit, on
b55014880:affected-docs.mjs --self-testcheck-affected-docs.mjs(both modes)check:docs-audit-scopecheck:nul-bytescheck:required-contextscheck:shard-attestationcheck:workflow-status-functionscheck:cross-package-test-inputscheck:node-versionAdvisory path exercised end-to-end against a real REST handler change (
152bff8fc^): 17 anchors,bridgeCoveragemeasured and rendered on the summary line,unreachableRowscorrectly absent fromthe advisory payload so the drift JSON does not carry 176 rows on every run.
No changeset:
scripts/**and.github/workflows/**only, nothing published.skip-changesetapplied.
Generated by Claude Code