Skip to content

Commit 75ddfd7

Browse files
committed
fix(qa): derive the authz matrix docblock's ledger figures instead of hand-typing them
`authz-conformance.matrix.ts` stated the REST route ledger holds "94 rows / 19 families" in the present tense and undated. Measured today the table holds 91 rows / 19 families: the families count was right, the row count was not. The cause was NOT the route-guarding move (`cc837dbfec`) whose own stale figures sat seven lines below it in the same docblock — guarding a route never changes its ledger disposition. It moved when #14503 took the three REST package read/delete rows out of the ledger (94 -> 91, `sdk` 84 -> 81; families unmoved at 19 because all three departing rows carried `family: packages`, which survives on the publish row). Two stale figures in one docblock with two entirely different causes; attributing this one to the neighbour teaches the wrong lesson, so the docblock now records the attribution. Correcting the constant alone would leave the mechanism intact, so all four figures in that sentence — both ledgers' rows and their families/domains — are now DERIVED and pinned in the companion test against a scoped read of the ledger each one names. The pin reads the PROSE rather than an exported constant: the defect is a sentence that went false, and lifting the number into a symbol would leave the sentence free to rot while the symbol stayed green. No symbol is exported from `packages/rest` or `packages/runtime` for it — both ledgers are only read, through the scoping rule `probeSource` already used, now extracted as `scopedSource` so there is one rule rather than two. The pin folds `//` continuations before matching, which is load-bearing rather than tidying: every figure in that docblock wraps mid-phrase, so a line-at-a-time literal search for the row/family phrase reads ZERO against the very file that carries it. A control case pins that failure, because a zero from an instrument blind to the shape is not a reading of absence. Five more cases prove the pin bites — stale rows, stale groups, a deleted figure, a second unpinned copy, and that the anchor is the ledger PATH so the dated "94 -> 91" attribution is not mistaken for a present-tense claim — each doctored from the measured value so no case hand-types a count of its own. The runtime ledger's "82 rows / 21 domains" in the same sentence measured CORRECT today and is pinned unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TSf4DV7ziu4V5j73e46b7c
1 parent 7173d7d commit 75ddfd7

2 files changed

Lines changed: 302 additions & 4 deletions

File tree

packages/qa/dogfood/test/authz-conformance.matrix.ts

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,40 @@
2424
// hand-curated regex table reaching 1 of 17 REST registrars and 4 of 17
2525
// dispatcher domain files.
2626
//
27-
// The population comes from `packages/rest/src/rest-route-ledger.ts` (94 rows
27+
// The population comes from `packages/rest/src/rest-route-ledger.ts` (91 rows
2828
// / 19 families) and `packages/runtime/src/route-ledger.ts` (82 rows / 21
2929
// domains) because those two are enumerated from a RUNNING server and guarded
3030
// in both directions by their own conformance tests — so a new family or
3131
// domain cannot be silently absent from them, and therefore cannot be silently
32-
// absent from here. Widening a regex instead was refused: it rots on the next
32+
// absent from here.
33+
//
34+
// [#17111] Those four figures are DERIVED, not hand-typed. The companion test
35+
// parses THIS sentence and asserts each number against a scoped read of the
36+
// ledger the sentence names, so a row, family or domain arriving or leaving
37+
// reds CI here instead of rotting into a false present tense. That pin is the
38+
// only reason the present tense above is safe to write at all; an undated
39+
// hand-typed count in this position is what #17111 was filed about, and what
40+
// #16307/#16954 were filed about before it.
41+
//
42+
// ⚠️ The pin folds the `//` continuations before it reads, because every
43+
// figure in this docblock WRAPS mid-phrase — the row/family phrase above is
44+
// split across two comment lines. A one-line literal search for it therefore
45+
// matches NOTHING in this file, and a zero from one is not a reading, it is
46+
// the instrument missing. ⛔ Do not re-flow these figures into a shape the
47+
// parser cannot anchor: it keys on the backticked ledger path immediately
48+
// followed by the parenthesised pair, and requires EXACTLY ONE of each, so a
49+
// second unpinned copy of either figure is red rather than a fresh carrier.
50+
//
51+
// ⚠️ The REST row count read 94 here until #17111 corrected it, and the
52+
// cause was NOT the route-guarding move (`cc837dbfec`) whose own stale figures
53+
// sat seven lines below it: guarding a route never changes its ledger
54+
// disposition, and reading this drift as the gate move's sends the next reader
55+
// to the wrong change. It moved when #14503 took the three REST package
56+
// read/delete rows out of the ledger — 94 rows → 91, `sdk` 84 → 81, with
57+
// families unmoved at 19 because all three departing rows carried
58+
// `family: packages`, which survives on the publish row. Two stale figures in
59+
// one docblock with two entirely different causes is the failure mode the pin
60+
// above ends. Widening a regex instead was refused: it rots on the next
3361
// added file, which is the mechanism this replaces. Deriving "gated" from
3462
// source syntax was refused too, on a measurement — 22 of 29 apparently
3563
// ungated `register(` sites in `rest-server.ts` are false, a 76% false-ungated

packages/qa/dogfood/test/authz-conformance.test.ts

Lines changed: 272 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -461,8 +461,21 @@ const PROBES: readonly Probe[] = [
461461
*/
462462
function probeSource(probe: Probe): string {
463463
const src = readFileSync(join(REPO_ROOT, probe.file), 'utf8');
464-
if (!probe.within) return src;
465-
const from = src.indexOf(`export const ${probe.within}`);
464+
return probe.within ? scopedSource(src, probe.within) : src;
465+
}
466+
467+
/**
468+
* The body of ONE exported array literal in `src` — `export const <within>`
469+
* up to the closing `\n];` — or the EMPTY string when that export is not
470+
* there, per the rule above.
471+
*
472+
* Extracted so the probe reader and the #17111 docblock-figure pin read the
473+
* ledger tables through ONE scoping rule: two copies would let a rename widen
474+
* one of them while the other stayed correct, and the wider one would still
475+
* mint plausible numbers.
476+
*/
477+
function scopedSource(src: string, within: string): string {
478+
const from = src.indexOf(`export const ${within}`);
466479
if (from < 0) return '';
467480
const to = src.indexOf('\n];', from);
468481
return to < 0 ? '' : src.slice(from, to);
@@ -1458,3 +1471,260 @@ describe('#7976 — row ↔ proof attribution is mutual', () => {
14581471
).toBe(true);
14591472
});
14601473
});
1474+
1475+
// ── #17111 — the docblock's ledger figures are DERIVED, not hand-typed ──────
1476+
//
1477+
// The matrix docblock states the size of BOTH route ledgers in the present
1478+
// tense. It read "94 rows / 19 families" for the nine days after #14503 took
1479+
// three REST package read/delete rows out of the ledger, and it was UNDATED —
1480+
// so nothing in the sentence told a reader it described a past state, and
1481+
// nothing in CI could tell either. It was the sixth hand-typed count to go
1482+
// stale in one triage round, which is why the deliverable here is the
1483+
// derivation and not the corrected constant.
1484+
//
1485+
// ⛔ This pin reads the PROSE, deliberately — not an exported constant. The
1486+
// defect is a sentence that went false; lifting the number out of the sentence
1487+
// into a symbol would leave the sentence free to rot again while the symbol
1488+
// stayed green, which is the same trade that produced the card.
1489+
//
1490+
// ⚠️ It folds the `//` continuations before matching, and that fold is
1491+
// load-bearing rather than tidying: every figure in that docblock WRAPS
1492+
// mid-phrase, so a line-at-a-time literal search for the row/family phrase
1493+
// reads ZERO against the very file that carries it. The control leg below
1494+
// pins that failure, because a zero from an instrument that cannot see the
1495+
// shape is not a reading of absence.
1496+
1497+
const MATRIX_FILE = 'authz-conformance.matrix.ts';
1498+
1499+
/** One figure pair the matrix docblock states, and how its ledger spells a row. */
1500+
interface DocblockLedgerClaim {
1501+
/** Repo-relative ledger path, exactly as the docblock backticks it. */
1502+
file: string;
1503+
/** The exported table inside it — the read is SCOPED, never the whole file. */
1504+
within: string;
1505+
/** The noun the docblock groups by. */
1506+
groupNoun: 'families' | 'domains';
1507+
/** The grouping field — one occurrence per row, counted DISTINCT. */
1508+
groupRe: RegExp;
1509+
}
1510+
1511+
const DOCBLOCK_LEDGER_CLAIMS: readonly DocblockLedgerClaim[] = [
1512+
{
1513+
file: 'packages/rest/src/rest-route-ledger.ts',
1514+
within: 'REST_ROUTE_LEDGER',
1515+
groupNoun: 'families',
1516+
groupRe: /family: '([^']+)'/g,
1517+
},
1518+
{
1519+
file: 'packages/runtime/src/route-ledger.ts',
1520+
within: 'ROUTE_LEDGER',
1521+
groupNoun: 'domains',
1522+
groupRe: /domain: '([^']+)'/g,
1523+
},
1524+
];
1525+
1526+
/** Both ledgers open every row with `route:`, so counting it counts rows. */
1527+
const LEDGER_ROW_RE = /route: '([^']+)'/g;
1528+
1529+
function allMatches(body: string, re: RegExp): string[] {
1530+
re.lastIndex = 0; // Fresh lastIndex per read (module-level, `g`-flagged).
1531+
const out: string[] = [];
1532+
let m: RegExpExecArray | null;
1533+
while ((m = re.exec(body)) !== null) out.push(m[1]!);
1534+
return out;
1535+
}
1536+
1537+
/**
1538+
* What one ledger table holds TODAY.
1539+
*
1540+
* `groupOccurrences` is returned alongside `rows` on purpose: both fields are
1541+
* one-per-row, so the two counts disagreeing means the scope has swallowed
1542+
* something that is not a row (a doc-comment spelling `route:`, a type
1543+
* declaration) and NEITHER number is trustworthy. The check refuses that
1544+
* instead of reporting the plausible one.
1545+
*/
1546+
function measureLedgerTable(claim: DocblockLedgerClaim): {
1547+
rows: number;
1548+
groups: number;
1549+
groupOccurrences: number;
1550+
} {
1551+
const body = scopedSource(readFileSync(join(REPO_ROOT, claim.file), 'utf8'), claim.within);
1552+
const groupValues = allMatches(body, claim.groupRe);
1553+
return {
1554+
rows: allMatches(body, LEDGER_ROW_RE).length,
1555+
groups: new Set(groupValues).size,
1556+
groupOccurrences: groupValues.length,
1557+
};
1558+
}
1559+
1560+
/** `//` continuations folded away, so a phrase split across two comment lines reads as one. */
1561+
function flattenLineComments(src: string): string {
1562+
return src.replace(/\n[ \t]*\/\/ ?/g, ' ').replace(/[ \t]+/g, ' ');
1563+
}
1564+
1565+
/**
1566+
* Every figure the (already-folded) docblock states for one ledger.
1567+
*
1568+
* Anchored on the backticked ledger PATH immediately followed by the
1569+
* parenthesised pair — not on the bare numbers, which also appear in the dated
1570+
* drift note one paragraph down and must not be pinned as present-tense
1571+
* claims. Every match is returned so the caller can refuse a SECOND copy: an
1572+
* unpinned duplicate is exactly how a third carrier of a stale figure appears.
1573+
*/
1574+
function claimedFigures(flat: string, claim: DocblockLedgerClaim): { rows: number; groups: number }[] {
1575+
const path = claim.file.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
1576+
const re = new RegExp('`' + path + '` \\((\\d+) rows / (\\d+) ' + claim.groupNoun + '\\)', 'g');
1577+
return allMatchPairs(flat, re);
1578+
}
1579+
1580+
function allMatchPairs(flat: string, re: RegExp): { rows: number; groups: number }[] {
1581+
const out: { rows: number; groups: number }[] = [];
1582+
let m: RegExpExecArray | null;
1583+
while ((m = re.exec(flat)) !== null) out.push({ rows: Number(m[1]), groups: Number(m[2]) });
1584+
return out;
1585+
}
1586+
1587+
/** Disagreements between the docblock's stated figures and the ledgers, on folded text. */
1588+
function checkFoldedDocblockFigures(flat: string): string[] {
1589+
const problems: string[] = [];
1590+
for (const claim of DOCBLOCK_LEDGER_CLAIMS) {
1591+
const claimed = claimedFigures(flat, claim);
1592+
if (claimed.length === 0) {
1593+
problems.push(
1594+
`${claim.file}: the docblock states no (N rows / M ${claim.groupNoun}) figure for it — the pin has lost its subject`,
1595+
);
1596+
continue;
1597+
}
1598+
if (claimed.length > 1) {
1599+
problems.push(
1600+
`${claim.file}: ${claimed.length} present-tense figures state its size; exactly ONE pinned copy is allowed`,
1601+
);
1602+
}
1603+
const actual = measureLedgerTable(claim);
1604+
if (actual.rows !== actual.groupOccurrences) {
1605+
problems.push(
1606+
`${claim.file}: the scoped table yields ${actual.rows} \`route:\` but ${actual.groupOccurrences} \`${claim.groupNoun.slice(0, -3)}\`-field occurrences — the scope is reading non-rows, so neither count is a reading`,
1607+
);
1608+
continue;
1609+
}
1610+
for (const c of claimed) {
1611+
if (c.rows !== actual.rows) {
1612+
problems.push(`${claim.file}: docblock says ${c.rows} rows, the table holds ${actual.rows}`);
1613+
}
1614+
if (c.groups !== actual.groups) {
1615+
problems.push(
1616+
`${claim.file}: docblock says ${c.groups} ${claim.groupNoun}, the table holds ${actual.groups}`,
1617+
);
1618+
}
1619+
}
1620+
}
1621+
return problems;
1622+
}
1623+
1624+
/** Disagreements, from the raw file text. */
1625+
function checkDocblockFigures(text: string): string[] {
1626+
return checkFoldedDocblockFigures(flattenLineComments(text));
1627+
}
1628+
1629+
describe("#17111 — the matrix docblock's ledger figures are pinned to the ledgers", () => {
1630+
const matrixText = (): string => readFileSync(join(HERE, MATRIX_FILE), 'utf8');
1631+
const REST = DOCBLOCK_LEDGER_CLAIMS[0]!;
1632+
1633+
it('CONTROL — both ledger tables are readable and non-trivial (the counts below are readings)', () => {
1634+
// Without this, every assertion here would be satisfied just as well by
1635+
// two claims pointed at files that no longer carry the table.
1636+
for (const claim of DOCBLOCK_LEDGER_CLAIMS) {
1637+
const { rows, groups, groupOccurrences } = measureLedgerTable(claim);
1638+
expect(rows, `${claim.file} rows`).toBeGreaterThan(10);
1639+
expect(groups, `${claim.file} ${claim.groupNoun}`).toBeGreaterThan(1);
1640+
// One grouping field per row, so these must agree exactly.
1641+
expect(groupOccurrences, `${claim.file} group-field occurrences`).toBe(rows);
1642+
expect(groups).toBeLessThanOrEqual(rows);
1643+
}
1644+
// …and the scope is what makes those readings OF the table: a renamed
1645+
// export reads EMPTY rather than falling back to the whole file.
1646+
const src = readFileSync(join(REPO_ROOT, REST.file), 'utf8');
1647+
expect(scopedSource(src, 'NO_SUCH_EXPORT')).toBe('');
1648+
expect(scopedSource(src, REST.within).length).toBeGreaterThan(0);
1649+
});
1650+
1651+
it('CONTROL — the figures WRAP, so folding is the instrument, not decoration', () => {
1652+
// The card's own instrument failure, pinned: read line-at-a-time, the
1653+
// claim is not in the file at all. Any future reader reaching for
1654+
// `git grep -F` on these phrases gets a zero that means nothing.
1655+
const raw = matrixText();
1656+
for (const claim of DOCBLOCK_LEDGER_CLAIMS) {
1657+
expect(claimedFigures(raw, claim), `${claim.file} unfolded`).toEqual([]);
1658+
expect(claimedFigures(flattenLineComments(raw), claim).length, `${claim.file} folded`).toBe(1);
1659+
}
1660+
});
1661+
1662+
it('every figure the docblock states equals what its ledger holds TODAY', () => {
1663+
expect(checkDocblockFigures(matrixText())).toEqual([]);
1664+
});
1665+
1666+
it('a stale ROW count is RED — the #14503 drift, replayed', () => {
1667+
// Doctored from the MEASURED value, so this case hand-types no count of
1668+
// its own — the thing the card was filed about.
1669+
const { rows, groups } = measureLedgerTable(REST);
1670+
const flat = flattenLineComments(matrixText());
1671+
const doctored = flat.replace(
1672+
`(${rows} rows / ${groups} families)`,
1673+
`(${rows + 3} rows / ${groups} families)`,
1674+
);
1675+
expect(doctored, 'the doctoring must land, or this case proves nothing').not.toBe(flat);
1676+
expect(
1677+
checkFoldedDocblockFigures(doctored).some((p) =>
1678+
p.includes(`docblock says ${rows + 3} rows, the table holds ${rows}`),
1679+
),
1680+
).toBe(true);
1681+
});
1682+
1683+
it('a stale GROUP count is RED too — both halves of the pair are pinned', () => {
1684+
const { rows, groups } = measureLedgerTable(REST);
1685+
const flat = flattenLineComments(matrixText());
1686+
const doctored = flat.replace(
1687+
`(${rows} rows / ${groups} families)`,
1688+
`(${rows} rows / ${groups + 1} families)`,
1689+
);
1690+
expect(doctored).not.toBe(flat);
1691+
expect(
1692+
checkFoldedDocblockFigures(doctored).some((p) =>
1693+
p.includes(`docblock says ${groups + 1} families, the table holds ${groups}`),
1694+
),
1695+
).toBe(true);
1696+
});
1697+
1698+
it('DELETING the figure is RED — the pin cannot be silenced by dropping its subject', () => {
1699+
// Otherwise the cheapest way to green this gate would be to remove the
1700+
// sentence, which is the claim, not the defect.
1701+
const { rows, groups } = measureLedgerTable(REST);
1702+
const flat = flattenLineComments(matrixText());
1703+
const doctored = flat.replace(`\`${REST.file}\` (${rows} rows / ${groups} families)`, `\`${REST.file}\``);
1704+
expect(doctored).not.toBe(flat);
1705+
expect(
1706+
checkFoldedDocblockFigures(doctored).some((p) => p.includes('the pin has lost its subject')),
1707+
).toBe(true);
1708+
});
1709+
1710+
it('a SECOND present-tense copy of a figure is RED — a new carrier cannot arrive unpinned', () => {
1711+
const { rows, groups } = measureLedgerTable(REST);
1712+
const one = `\`${REST.file}\` (${rows} rows / ${groups} families)`;
1713+
const flat = flattenLineComments(matrixText());
1714+
const doctored = flat.replace(one, `${one} and again ${one}`);
1715+
expect(doctored).not.toBe(flat);
1716+
expect(
1717+
checkFoldedDocblockFigures(doctored).some((p) => /present-tense figures state its size/.test(p)),
1718+
).toBe(true);
1719+
});
1720+
1721+
it('the anchor is the PATH, so the dated drift note is NOT pinned as a present-tense claim', () => {
1722+
// The docblock records "94 rows → 91" as the #14503 transition. That is a
1723+
// dated attribution, not a claim about today, and a pin keyed on bare
1724+
// numbers would have to treat it as one.
1725+
const flat = flattenLineComments(matrixText());
1726+
expect(flat).toContain('#14503');
1727+
expect(claimedFigures(flat, REST).length).toBe(1);
1728+
expect(checkFoldedDocblockFigures(flat)).toEqual([]);
1729+
});
1730+
});

0 commit comments

Comments
 (0)