From 820cfabaa40fd3107e6758712f6e619383337f9e Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 24 Aug 2026 14:23:09 +0000 Subject: [PATCH] fix(docs-audit): retire the lead-anchor widening family for a key-position allowlist MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `declLead` anchored the ledger `route:`/`client:` key with a word boundary, which fails only against a preceding WORD character. Four cards each shrank one more character class out of the false-positive set and named the next residue, which is the wrong discipline for a bounded defect: the anchor admitted 12225 of the code points in 0..0x2FFF and the family was arguing about a handful at the edge of that set. The anchor is inverted. It no longer enumerates what may not precede the key; it names the positions where an object-literal property key may begin — start of input, whitespace, `{`, `,` — and rejects everything else. That closes `$`, `.`, `-` and Unicode identifier characters in one move, needs no `u` flag, and keeps the anchor spelled once in `declLead` with the `\s*:\s*` run untouched. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_015ahemw8RcTgqtxrj15PEZx --- scripts/docs-audit/affected-docs.mjs | 187 ++++++++++++++++++++++----- 1 file changed, 156 insertions(+), 31 deletions(-) diff --git a/scripts/docs-audit/affected-docs.mjs b/scripts/docs-audit/affected-docs.mjs index dd3f379bbb..4b938f36e8 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 `(? declLead(k)).join(' | ')); + // ⛔ AND IT ONLY EVER REMOVES (#11717) — swept over code points, not argued. The allowlist + // is a strict SUBSET of the `\b` it replaced, which is what makes "retire the family" a + // tightening rather than a re-shuffle. A future card that widens the allowlist — adding `(` + // to admit a call-position key, say — fails HERE the moment it admits one character `\b` + // rejected, instead of reading as one more honest shrink. + const sweepOld = String.raw`\b(route|client)\s*:\s*`; + const sweepNew = declLead('(route|client)'); + const admitsAfter = (src, ch) => { + for (const m of (ch + "route: 'x'").matchAll(new RegExp(src, 'g'))) if (m.index === ch.length) return true; + return false; + }; + let sweptOld = 0, sweptNew = 0, sweptNewNotOld = 0; + for (let cp = 0; cp <= 0x2fff; cp++) { + const ch = String.fromCodePoint(cp); + const o = admitsAfter(sweepOld, ch); + const n = admitsAfter(sweepNew, ch); + if (o) sweptOld++; + if (n) sweptNew++; + if (n && !o) sweptNewNotOld++; + } + check('declLead', 'the anchor only ever REMOVES — it admits nothing the `\\b` it replaced rejected', + 'sweep 0..0x2FFF', 0, sweptNewNotOld); + check('declLead', 'and the allowlist is the far SMALLER set, by the margin the sweep measures', + 'sweep 0..0x2FFF', '12225 → 25', `${sweptOld} → ${sweptNew}`); + if (failed) { console.error(`\n✗ affected-docs self-test failed (${failed} case(s)).`);