From 6de837d3020f4d6303096a3557538555e3369d61 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 24 Aug 2026 13:36:25 +0000 Subject: [PATCH] fix(docs-audit): widen the ledger key anchor from \b to a negative lookbehind MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `declLead` anchored the `route:`/`client:` key with `\b`, which fails only against a preceding WORD character. `$` is not one, and `$route` is a legal JS identifier, so `$route:` was read as a declaration by all eight lead scans — agreed, and agreed by being wrong together. The anchor is now `symbolRe`'s set rather than `dottedRe`'s, because `declLead`'s key is a BARE token: a preceding `$` continues an identifier, and a preceding `.` makes the token a member access whose colon belongs to a ternary. Both minted phantom rows; the character class closes the class instead of enumerating escapees. `-` is deliberately left out — `a-route` is two tokens, so that `route` is the whole token and is not a declaration for a different reason, one it shares with the bare `cond ? route : x` no lookbehind can reach. Unlike the previous move, this one also moves `declarationsIn` — the eighth scan, left byte-identical on purpose last time — so it is priced with its own before/after, at row identity rather than counter equality. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_015ahemw8RcTgqtxrj15PEZx --- scripts/docs-audit/affected-docs.mjs | 283 ++++++++++++++++++++++++--- 1 file changed, 251 insertions(+), 32 deletions(-) diff --git a/scripts/docs-audit/affected-docs.mjs b/scripts/docs-audit/affected-docs.mjs index dd3f379bbb..15da4f14a5 100644 --- a/scripts/docs-audit/affected-docs.mjs +++ b/scripts/docs-audit/affected-docs.mjs @@ -1391,24 +1391,65 @@ function typeDeclRegions(code) { * explicitly for their own population moves, and it is made explicitly here for the same * reason: the alternative is moving a reported number quietly. * - * ⛔ THE RESIDUE THIS DOES NOT CLOSE, named rather than left to be discovered. `\b` fails only - * against a preceding WORD character, so `$route:` — a legal JS identifier — is still read as - * a declaration. It is no longer a DIVERGENCE (all eight now agree on it), which is what this - * card was about, but it is still a phantom, and tightening to `(? `${r.route} → ${r.client}`).join(' | ')}`); + + // (D3) THE IN-WINDOW `client:` MATCH (`windowClientRe`). `window.match()` takes the FIRST + // hit, so a `$client:` ahead of the real `client:` BECAME the binding, and the real one fell + // through to #10636's unclaimed sweep and was named as a value no row read. + const dollarClient = parseLedgerSource([ + 'export const L = [', + " { route: 'GET /api/v1/meta', family: 'metadata', disposition: 'sdk',", + " $client: 'wrong.binding', client: 'meta.getTypes' },", + '];', + ].join('\n')); + check('parseLedgerSource', 'a `$client:` does not become the row BINDING (#11630)', 'binding', + 'meta.getTypes', dollarClient.rows[0]?.client); + check('parseLedgerSource', 'and the real `client:` is bound, not swept up as unclaimed', 'declared', + '1 client / 0 declined', + `${dollarClient.clientsDeclared} client / ${dollarClient.declined.length} declined`); + + // (D4) THE DECLINED SWEEP (`declinedIn`), the LOUD direction: a double-quoted `$route:` was + // billed as a `route:` value the parse FAILED to read — entering the denominator, named with + // its line, and firing a PARTIAL-read verdict with exit 1 on a wholly accurate ledger. + const dollarDeclined = parseLedgerSource([ + 'export const L = [', + ' { $route: "GET /api/v1/gone", family: \'metadata\', disposition: \'sdk\' },', + " { route: 'GET /api/v1/meta', family: 'metadata', disposition: 'sdk', client: 'meta.getTypes' },", + '];', + ].join('\n')); + check('parseLedgerSource', 'a double-quoted `$route:` is not billed as a DECLINED row (#11630)', + 'declared', '1 row / 1 route / 0 declined', + `${dollarDeclined.rows.length} row / ${dollarDeclined.routesDeclared} route / ${dollarDeclined.declined.length} declined`); + check('bridgeCoverageFrom', 'so no PARTIAL-read verdict fires on an accurate ledger', 'brokenScan', + 0, bridgeCoverageFrom([{ file: 'q-route-ledger.ts', ...dollarDeclined }], ['/api/v1/meta']).brokenScan.length); + + // (D5) THE RAW SWEEP behind `outsideCode` — a `$route:` in a COMMENT was printed to the + // reader on every `--bridge-coverage` run as a lead sitting where the mask says code is not. + const dollarProse = parseLedgerSource([ + "// The retired row read $route: 'GET /api/v1/gone' before #1234.", + 'export const L = [', + " { route: 'GET /api/v1/meta', family: 'metadata', disposition: 'sdk', client: 'meta.getTypes' },", + '];', + ].join('\n')); + check('parseLedgerSource', 'a `$route:` in PROSE is not reported as a prose-quoted lead (#11630)', + 'outsideCode', 0, dollarProse.outsideCode.length); + + // (D6) ⛔ THE EIGHTH SCAN — `declarationsIn`, via `unreadableIn`. THIS is what makes #11630 a + // SECOND population move rather than a re-run of #11542's: #11542 left this scan + // byte-identical on purpose and priced its before/after that way. A `$route:` whose value is + // not a string literal at all was billed here as a declaration the recognizer could not + // read — `1 row / 2 route / 1 declined` with a PARTIAL-read verdict, on an accurate ledger. + // Compare `--self-test`'s `subroute:` twin above, which reads `1 row / 1 route / 0 declined` + // on BOTH trees because the anchored scan always agreed about the word-prefixed class. + const dollarUnreadable = parseLedgerSource([ + 'export const L = [', + " { $route: ROUTES.gone, family: 'metadata', disposition: 'sdk' },", + " { route: 'GET /api/v1/meta', family: 'metadata', disposition: 'sdk', client: 'meta.getTypes' },", + '];', + ].join('\n')); + check('parseLedgerSource', 'a non-literal `$route:` is billed to nothing — the EIGHTH scan moved too (#11630)', + 'declared', '1 row / 1 route / 0 declined', + `${dollarUnreadable.rows.length} row / ${dollarUnreadable.routesDeclared} route / ${dollarUnreadable.declined.length} declined`); + check('bridgeCoverageFrom', 'and `declarationsIn` moving fires no PARTIAL-read verdict either', + 'brokenScan', 0, + bridgeCoverageFrom([{ file: 'r-route-ledger.ts', ...dollarUnreadable }], ['/api/v1/meta']).brokenScan.length); + + // (D7) ⛔ THE SECOND CLASS THE CHARACTER CLASS CLOSES, found by MEASUREMENT rather than + // assumed from the card, which named only `$`. A `.` before the key makes the token a MEMBER + // ACCESS, and the colon then belongs to a TERNARY and never to a key — `cond ? obj.route : + // 'GET /api/v1/gone'` minted a phantom row on a path nobody declares. This is why the set is + // `symbolRe`'s `[\w$.]` and not `dottedRe`'s `[\w$]`: `declLead`'s key is a BARE token. + const dottedKey = parseLedgerSource([ + 'export const L = [', + " { route: 'GET /api/v1/meta', family: 'metadata', disposition: 'sdk', client: 'meta.getTypes' },", + '];', + "const fallback = cond ? defaults.route : 'GET /api/v1/gone';", + ].join('\n')); + check('parseLedgerSource', 'a member-access `.route :` in a TERNARY mints NO row (#11630)', + 'row count', 1, dottedKey.rows.length); + check('parseLedgerSource', 'and the real row keeps its binding across it', 'row', + 'GET /api/v1/meta → meta.getTypes', + `${dottedKey.rows[0]?.route} → ${dottedKey.rows[0]?.client}`); + check('parseLedgerSource', 'and it leaves the denominator alone as well', 'declared', + '1 route / 1 client / 0 declined', + `${dottedKey.routesDeclared} route / ${dottedKey.clientsDeclared} client / ${dottedKey.declined.length} declined`); + + // ⛔ THE BOUNDARY THIS CARD DOES NOT CROSS, in its turn — both halves pinned so the next + // card of this shape MOVES a pin rather than finding none, exactly as this one did. + // + // (a) `-` is NOT in the set. `a-route` is two tokens, so that `route` IS the whole token — + // not a declaration for a DIFFERENT reason (expression position), one it shares with the + // bare `cond ? route : x` no lookbehind can reach. Excluding `-` would close one spelling of + // that class and leave its plainest spelling open. + const minusKey = parseLedgerSource([ + 'export const L = [', + " { route: 'GET /api/v1/meta', family: 'metadata', disposition: 'sdk', client: 'meta.getTypes' },", + '];', + "const n = cond ? a-route : 'GET /api/v1/gone';", + ].join('\n')); + check('parseLedgerSource', 'a `-`-prefixed lead still mints a row — deliberately outside the set (#11630)', + 'row count', 2, minusKey.rows.length); + // (b) `\w` is ASCII-only, so a UNICODE identifier character still passes — `éroute:` is + // admitted by the lookbehind exactly as it was by `\b`. Closing it means a `\p{L}` class + // under the `u` flag, which changes escape semantics for every source these leads are + // COMPOSED with at the eight call sites. 0 occurrences across the seven live ledgers. + const unicodeKey = parseLedgerSource([ + 'export const L = [', + " { éroute: 'GET /api/v1/gone', family: 'metadata', disposition: 'sdk' },", + " { route: 'GET /api/v1/meta', family: 'metadata', disposition: 'sdk', client: 'meta.getTypes' },", + '];', + ].join('\n')); + check('parseLedgerSource', 'a UNICODE-prefixed lead still mints a phantom row — residue, deliberately unmoved', + 'row count', 2, unicodeKey.rows.length); // ⛔ REPORTED, NEVER A VERDICT. A comment explaining a retired row by quoting its old path // is legitimate prose; reddening CI over it is the false red the #9747 family declines. @@ -3568,24 +3754,57 @@ function selfTest() { // copy is the same hole re-opening, and only a source pin can see it: every behavioural // fixture above would keep passing while the new scan drifted on its own. check('declLead', 'the run between a `route:`/`client:` colon and its value is spelled ONCE', 'affected-docs.mjs', - 1, (ownSource.match(/String\.raw`\\b\$\{keys\}\\s\*:\\s\*`/g) || []).length); + 1, (ownSource.match(/String\.raw`\(\? declLead(k)).join(' | ')); + // …and BEHAVIOURALLY the anchor is a strict TIGHTENING of the `\b` it replaced, which is the + // invariant the population pricing rests on: the key alternation always opens with a word + // character, so `\b` there fails exactly when the previous character is a word character, + // making `(? declLead(k))`). ⛔ That pin reads this file as TEXT, so even + // naming the compiled spelling in a comment here would count — it is described, not + // quoted, for the same reason. + const leadSource = declLead('(route|client)'); + const lead = new RegExp(leadSource); + let admitsMore = 0; + let moved = 0; + for (let c = 0; c < 0x3000; c++) { + const s = String.fromCodePoint(c) + "route: 'x'"; + const b = bAnchor.test(s); + const l = lead.test(s); + if (l && !b) admitsMore++; + if (b && !l) moved++; + } + check('declLead', 'the anchor only ever REMOVES — it admits nothing `\\b` did not', 'code points 0..0x2FFF', + 0, admitsMore); + check('declLead', 'and the characters it moves are exactly `$` and `.`', 'code points 0..0x2FFF', + 2, moved); + } if (failed) {