You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
refactor(docs-audit): a route SOURCE of two kinds — admit spec contract declarations behind a runtime-registration guard (#15274)
* refactor(docs-audit): a route SOURCE of two kinds, and admit contract declarations
Rename the "registrar" concept in affected-docs.mjs to a route SOURCE with two
kinds -- a registration call site (the existing filename convention) and a spec
contract declaration (admitted by evidence) -- and implement the evidence route
behind a runtime-registration guard.
The guard is the HTTP method the declaration answers on, read beside the path,
rather than a hand-kept exclusion list: it keeps out the whole class of data
payloads that merely carry a `path:` key, of which the connector-action input in
packages/spec/src/conversions/registry.ts is today's only instance.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
* test(docs-audit): pin the two route-source kinds and the guard between them
Adds the #11857 self-test battery (21 cases): the guard admits a contract
declaring its verb beside its path, declines a connector-action input, and the
counterfactual proves the parser reads that payload's tail so the guard is what
declines it. Live pins for the real registry.ts, the five admitted declarations,
and the measured no-op of excluding route ledgers from kind (a).
Roster 28 -> 29 batteries, floor raised with the cases.
Renames the concept in scripts/docs-audit/README.md to match the script.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
* test(docs-audit): floor the contract-kind population so a shape pin cannot pass vacuously
Ablation B (evidence route disabled) left the battery green: `every()` over an
empty list is true, so the pin that says WHAT kind (b) admits said nothing about
WHETHER it admits. Adds the size floor and names the declaration the storage
ledger's closure rests on.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
* docs(docs-audit): finish the rename in the anchor provenance string
The `route` anchor's own `from` note still read "its registrar handler names
it" -- the one place the old word reached a user-visible string rather than a
comment. Found by running the tool in normal mode on a real diff.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
---------
Co-authored-by: Claude <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: scripts/docs-audit/README.md
+79-17Lines changed: 79 additions & 17 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -49,12 +49,12 @@ Three anchor kinds, each exact:
49
49
| anchor | what it is | how it is derived |
50
50
|:--|:--|:--|
51
51
|`symbol`| a documentable declaration the diff touched | the top-level declaration, or a member of a top-level **container** (class / interface / type / enum / schema object), enclosing each changed line — on **both** sides of the diff, so a removed export still anchors the pages naming it. A member that is a **data property** is additionally qualified by its declaring container against the authorable surface (see below) |
52
-
|`route`| a wire path the change touched | a path literal on a changed line, plus every route whose **registrar handler** references a changed symbol |
52
+
|`route`| a wire path the change touched | a path literal on a changed line, plus every route whose **route-source handler** references a changed symbol |
53
53
|`sdk`| the client method bound to an anchor route | the declared `route` ⟷ `client` rows in the repo's route ledgers |
54
54
55
55
The `route` and `sdk` hops are what carry the derivation across the surface boundary the
|registrar files| 12 | 12 | two ADR-0049 ledger entries were admitted in between and are excluded again here; they produced **0 tails and 0 reachable rows**, so they never moved the figures below |
213
+
|route sources| 12 | 12 | two ADR-0049 ledger entries were admitted in between and are excluded again here; they produced **0 tails and 0 reachable rows**, so they never moved the figures below |
214
214
| route tails | 43 | 44 |`rest-server.ts` unrolled `for (const publishedPath of […])` into a literal `path:` — a variable path yields no tail, a literal one does |
215
215
| client-bound rows | 222 | 219 | three `:type/:section/:name` rows deleted from `rest-route-ledger.ts`, all three already unreachable |
216
216
|**reachable**|**45**|**47**| the one new tail `/:type/:name/published` selects `meta.getPublished` on the rest ledger *and* on the runtime ledger |
217
217
218
218
⭐ 45 → 47 is the bridge reaching **more** of its population, not losing track of it, so
219
219
the figure stands at 47. ⛔ Do not "restore" 45: the only recognizer spelling that
220
220
reproduces it drops ten of the fourteen matched files, including a tail-producing
221
-
registrar — the control appears to recover exactly when the recognizer stops working.
221
+
call site — the control appears to recover exactly when the recognizer stops working.
222
222
223
223
That number now travels with the answer. `bridgeCoverage` is emitted on every run whose
224
224
change carried a bridgeable symbol (`{ measured: false, reason }` when it did not — never a
@@ -246,34 +246,96 @@ among them), so the silence is not an empty region.
246
246
247
247
`56 of 56` and `46 of 87` used to print in the same words, and they are not the same
248
248
finding. Every unreachable row is now attributed against a **ceiling** — every `path:` any
249
-
`packages/**` file declares, with `REGISTRAR_FILE_RE` ignored entirely, built by
250
-
`maximalTailsFrom` from the same `parseRegistrarSource` over the same walk. Measured on
249
+
`packages/**` file declares, with `CALL_SITE_FILE_RE` ignored entirely, built by
250
+
`maximalTailsFrom` from the same `parseRouteSource` over the same walk. Measured on
251
251
`589758d22`, the 177 unreachable rows partition as:
252
252
253
253
| cause | rows | what it means |
254
254
| --- | --- | --- |
255
255
|`discovery-gap`| 14 | an in-repo file declares this exact path; the filename convention did not scan that file. The JSON **names the witness**. |
256
-
|`no-in-repo-registrar`| 56 | on a ledger where **not one** row is declared in-repo — declared upstream and catch-all-mounted. No discovery change reaches it. |
257
-
|`undecided`| 107 | no in-repo declaration for the row, on a ledger that *has* in-repo registrars. Absence and an unreadable spelling are not distinguishable here, so neither is claimed. |
256
+
|`no-in-repo-declaration`| 56 | on a ledger where **not one** row is declared in-repo — declared upstream and catch-all-mounted. No discovery change reaches it. |
257
+
|`undecided`| 107 | no in-repo declaration for the row, on a ledger that *has* in-repo route sources. Absence and an unreadable spelling are not distinguishable here, so neither is claimed. |
258
258
259
-
Exactly **one** of the seven ledgers is `no-in-repo-registrar` today: `auth-route-ledger.ts`,
259
+
Exactly **one** of the seven ledgers is `no-in-repo-declaration` today: `auth-route-ledger.ts`,
260
260
whose own header has said so since #3656 — better-auth declares those routes inside
261
261
`node_modules` and the plugin mounts them with a single ``rawApp.all(`${basePath}/*`)``,
262
262
which `routeTailOf` cannot and should not turn into a tail. That is why widening
263
-
`REGISTRAR_FILE_RE` to admit `auth-plugin.ts` was measured to move `registrar files
263
+
`CALL_SITE_FILE_RE` to admit `auth-plugin.ts` was measured to move `route sources
264
264
scanned` 12 → 13 and **nothing else**.
265
265
266
-
⛔ **This changes no discovery and moves no reach.**`REGISTRAR_FILE_RE` is byte-identical,
267
-
the bridge still rides on `registrarByTail` alone, and `reachable` is 45 before and after —
266
+
⛔ **This changes no discovery and moves no reach.**`CALL_SITE_FILE_RE` is byte-identical,
267
+
the bridge still rides on `routeSourceByTail` alone, and `reachable` is 45 before and after —
268
268
pinned in `--self-test`. The ceiling only explains the number; it never participates in it,
269
269
and because it is a superset by construction a ceiling that misses a *reachable* row is a
270
270
`brokenScan` verdict rather than a quieter result.
271
271
272
272
The classification is **derived, never listed**. Control on `589758d22`: adding one
273
273
in-repo file that declares one auth route — under a filename the convention does not match
274
-
— moves the auth ledger out of `no-in-repo-registrar` on its own (structural 56 → 0,
274
+
— moves the auth ledger out of `no-in-repo-declaration` on its own (structural 56 → 0,
275
275
`reachable` still 45), and removing it restores 56.
276
276
277
+
### A route SOURCE is two kinds, and one of them is admitted by evidence (#11857)
278
+
279
+
Maintainer ruling A, 2026-09-04 decision batch #31. Until this card the recognizer's name,
280
+
docblock and `--self-test` all meant *the file that registers the route* — while the
281
+
measured widening that motivated the card admits five `packages/spec`**Zod contract
282
+
declarations**, which register nothing. The ruling made the **rename** a condition of
283
+
admitting them: nothing here is called a "registrar" any more, because the word would
284
+
otherwise denote two constructs.
285
+
286
+
A **route source** is a file whose source declares a route. Two kinds:
0 commit comments