Skip to content

Commit cabd7cc

Browse files
claude[bot]claude
andauthored
docs(scripts): the swallow-family census reads the #12981 handover as landed (#15459, #15473) (#15502)
The census `scripts/measure-durability-swallow-family.mjs` is the #12981 programme's instrument of record. PR #15458 performed the handover it had reserved for the programme's last step (`tryInsert`/`tryUpdate` into the gate's `DURABILITY_CRITICAL_CALLEES`) and PR #15472 closed the programme; four statements in this file still described both as pending. - The header's "The handover" section is past tense and names PR #15458/#15472. - "an 18-entry vocabulary" is 20, the count the gate now declares. - `tryInsert`/`tryUpdate` move from `origin: 'seed-wrapper'` to `'gate-vocabulary'` in `WRITE_SHAPED_CALLEES`: after #15458 they ARE declared in the gate, and the OVERLAP reading has to say what the tree says. `tryDelete` was not part of the handover and stays `seed-wrapper`. - The `DETERMINED` row for `keys.ts::handleKeysRequest` no longer says the site is waiting for a declaration the #12981 ruling (Q1 = A) refused. Its `anchor`, `verdict`, `scope` and key are byte-identical. - The `SELF_TEST_MODES` gated-subset note stops calling the handover reserved. The by-value copy of the gate's vocabulary stays a copy — the header says why — but a by-value copy's failure mode is silence, which is what let this file go stale under a green farm. `readGateVocabulary()` parses the gate's own declaration (never imports it) and the `--self-test` cross-checks the copy against it in BOTH modes, with a negative leg proving the comparison can fire. It announces drift; it never absorbs it. Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk Co-authored-by: Claude <noreply@anthropic.com>
1 parent 6f94458 commit cabd7cc

1 file changed

Lines changed: 169 additions & 18 deletions

File tree

scripts/measure-durability-swallow-family.mjs

Lines changed: 169 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,9 @@
5353
// > swallow-shaped file means NOT MEASURED for that site, never
5454
// > "level approved."
5555
//
56-
// The gate matches callee NAMES from an 18-entry `DURABILITY_CRITICAL_CALLEES`
57-
// vocabulary. A seeder that reaches storage through `ql.insert(...)` is not in
56+
// The gate matches callee NAMES from a 20-entry `DURABILITY_CRITICAL_CALLEES`
57+
// vocabulary -- 18 until PR #15458 added the seeder wrappers `tryInsert` and
58+
// `tryUpdate`. A seeder that reaches storage through `ql.insert(...)` is not in
5859
// that vocabulary and never was, so the gate walks the file, finds no seam it
5960
// understands, and scores it clean. #12923 measured the cost: the RBAC catalog
6061
// seeders swallowed refused writes in `catch { return null; }`, and a boot
@@ -191,13 +192,26 @@
191192
// Picking a regex that happens to return 15 would have been the other option.
192193
// It would also have been a false green about false greens.
193194
//
194-
// ## The handover (the ruling's LAST step, not this one)
195+
// ## The handover (the ruling's LAST step) -- LANDED in PR #15458
195196
//
196-
// The programme ends by adding the seeder-helper names (`tryInsert`/`tryUpdate`)
197+
// The programme ended by adding the seeder-helper names (`tryInsert`/`tryUpdate`)
197198
// to the gate's `DURABILITY_CRITICAL_CALLEES` **with zero reds**, which is what
198199
// keeps `scripts/durability-degradation.baseline.json` at its designed empty
199-
// steady state. That step is gated on `outstanding == 0` for those wrappers in
200-
// this census. Until then:
200+
// steady state. PR #15458 performed that step and measured it: the gate's
201+
// verdict line was unchanged, the baseline stayed empty, and THIS census's
202+
// reading was byte-identical across it -- the vocabulary below is copied by
203+
// VALUE, so the gate's map growing moved nothing here. #12981 then closed with
204+
// PR #15472.
205+
//
206+
// Those two names are therefore labelled `gate-vocabulary` below (#15459): after
207+
// that PR they ARE declared in the gate, and the census's OVERLAP reading has to
208+
// say what the tree says. `tryDelete` is not in the gate and stays
209+
// `seed-wrapper`. The copy stays a copy, and is now cross-checked against the
210+
// gate's own declaration on every `--self-test` -- see `readGateVocabulary`.
211+
//
212+
// The prohibitions this step was held behind did NOT expire with it. Two of them
213+
// were re-affirmed by the ruling that closed the programme (#12981 comment
214+
// 5543738972, Q1 = A), and they are standing:
201215
//
202216
// - ⛔ do NOT add an entry to `durability-degradation.baseline.json` (option B,
203217
// refused by the ruling: filling the empty ledger teaches every seat that
@@ -229,6 +243,10 @@ import { parseSourceFile } from './ts-parse.mjs';
229243
const ROOT = fileURLToPath(new URL('..', import.meta.url));
230244
const SCAN_ROOT = join(ROOT, 'packages');
231245

246+
/** The sibling GATE, READ (never imported) so the copy below can be cross-checked. */
247+
const GATE_SCRIPT = 'scripts/check-durability-degradation-log-level.mjs';
248+
const GATE_VOCABULARY_IDENT = 'DURABILITY_CRITICAL_CALLEES';
249+
232250
/**
233251
* Callees whose failure means "the bytes did not land".
234252
*
@@ -240,14 +258,23 @@ const SCAN_ROOT = join(ROOT, 'packages');
240258
* - `objectql` -- the ObjectQL-level write surface the seeders use.
241259
* - `seed-wrapper` -- the `catch { return null; }` helpers this family IS
242260
* (`permission-set-projection.ts` and its per-file
243-
* copies). These are the names the ruling's last step
244-
* hands to the gate.
261+
* copies) that the gate does NOT declare. `tryInsert`
262+
* and `tryUpdate` sat here until the ruling's last step
263+
* handed them over (PR #15458); they are
264+
* `gate-vocabulary` now, because that is what the tree
265+
* says. `tryDelete` was not part of that handover and
266+
* is still this census's alone.
245267
* - `gate-vocabulary` -- already declared in
246268
* `check-durability-degradation-log-level.mjs`.
247269
* Carried here so the census can report the OVERLAP:
248270
* how many members the gate can already see. Copied by
249271
* value on purpose -- importing the gate's map would
250272
* couple a non-gate instrument to a merge-blocking one.
273+
* A by-value copy's failure mode is SILENCE, so this
274+
* subset is cross-checked against the gate's own
275+
* declaration on every `--self-test` and reddens on
276+
* drift -- see `readGateVocabulary`. It announces;
277+
* it never absorbs.
251278
*/
252279
const WRITE_SHAPED_CALLEES = new Map([
253280
['insert', 'objectql'],
@@ -261,9 +288,9 @@ const WRITE_SHAPED_CALLEES = new Map([
261288
['updateMany', 'driver-contract'],
262289
['deleteMany', 'driver-contract'],
263290
['dropTable', 'driver-contract'],
264-
['tryInsert', 'seed-wrapper'],
265-
['tryUpdate', 'seed-wrapper'],
266291
['tryDelete', 'seed-wrapper'],
292+
['tryInsert', 'gate-vocabulary'],
293+
['tryUpdate', 'gate-vocabulary'],
267294
['syncSchema', 'gate-vocabulary'],
268295
['syncSchemasBatch', 'gate-vocabulary'],
269296
['syncRegisteredSchemas', 'gate-vocabulary'],
@@ -670,10 +697,13 @@ const DETERMINED = new Map([
670697
+ 'several rounds and was listed under "the repair worklist" on every run, so batch 7 had to '
671698
+ 'open the file to discover it was already settled. Nothing claims to have persisted and the '
672699
+ 'request does not look normal from the outside — AGENTS.md\'s third legal ending. Its '
673-
+ 'delivery is pinned in `http-dispatcher.keys.test.ts`. ⛔ The declaration this site is '
674-
+ 'waiting for belongs to the programme\'s LAST step, the one that widens '
675-
+ '`DURABILITY_CRITICAL_CALLEES`; this row does not bring that step forward and must not be '
676-
+ 're-keyed by it.',
700+
+ 'delivery is pinned in `http-dispatcher.keys.test.ts`. ⛔ This site is waiting for '
701+
+ 'nothing: the #12981 ruling (comment 5543738972, Q1 = A) settled that no gate declaration is '
702+
+ 'owed here, ever. The widening that landed (PR #15458) added `tryInsert`/`tryUpdate`, and '
703+
+ 'neither matches a seam in this function; the only name that would is bare `insert`, which '
704+
+ 'this census refuses by design. An entry keyed here would be STALE on arrival, so THIS ROW '
705+
+ 'is the record -- which is what the ruling relies on. PR #15472 rewrote the in-file note to '
706+
+ 'say so and kept the anchor sentence byte-identical.',
677707
},
678708
],
679709
[
@@ -856,10 +886,10 @@ function staleLines(stale) {
856886
* asserts membership at a declared TIER lives in `all`, and `all` is what a
857887
* human or an agent touching this instrument runs.
858888
*
859-
* ⛔ This subset is also not, and must not be used to bring forward, the
860-
* ruling's reserved handover step (`tryInsert`/`tryUpdate` into the real gate's
861-
* `DURABILITY_CRITICAL_CALLEES`, still gated on `outstanding == 0`) -- see "The
862-
* handover" above.
889+
* ⛔ This subset was also not, and must never be used as, a route to the
890+
* ruling's handover step (`tryInsert`/`tryUpdate` into the real gate's
891+
* `DURABILITY_CRITICAL_CALLEES`). That step landed on its own terms in PR
892+
* #15458 -- see "The handover" above.
863893
*
864894
* ## The FIFTH family (#13886) is in BOTH modes, and that is the point
865895
*
@@ -878,6 +908,17 @@ function staleLines(stale) {
878908
* (`FAILURE_PROPAGATION_SITES`), demanding a one-line deletion that lands with
879909
* the repair. That is categorically unlike `POSITIVE_CONTROLS`, where the
880910
* cheapest way to green is to WEAKEN the control.
911+
*
912+
* ## The COPIED gate vocabulary (#15459) is in both modes, for the same reason
913+
*
914+
* `WRITE_SHAPED_CALLEES` carries the gate's vocabulary BY VALUE, and the
915+
* `--self-test` compares that copy against the gate's own declaration
916+
* (`readGateVocabulary`). It passes the same test: a successful repair cannot
917+
* destroy it, because it compares two DECLARATIONS and never touches membership.
918+
* It is in `gated` because drift is exactly the failure a farm has to catch --
919+
* PR #15458 grew the gate's map from 18 names to 20 and this file went stale in
920+
* four places the same afternoon (#15459, #15473), under a green farm the whole
921+
* time, which is the cost of an uncross-checked copy stated as a measurement.
881922
*/
882923
const SELF_TEST_MODES = new Set(['all', 'gated']);
883924

@@ -1689,6 +1730,76 @@ function checkResolutionControl(control) {
16891730
return { matched, wrong };
16901731
}
16911732

1733+
/**
1734+
* The gate's `DURABILITY_CRITICAL_CALLEES` names, read out of its SOURCE.
1735+
*
1736+
* `WRITE_SHAPED_CALLEES` copies that vocabulary by value on purpose (its header
1737+
* says why), and a by-value copy's failure mode is SILENCE: the gate grows a
1738+
* name, the copy does not, and this census keeps printing an OVERLAP reading
1739+
* that is simply wrong with nothing anywhere to say so. That is the lie-carrier
1740+
* shape the `DETERMINED` register closes one layer down, and it is not
1741+
* hypothetical here -- see the section above.
1742+
*
1743+
* So the copy is CROSS-CHECKED, not replaced. The gate is still never imported:
1744+
* a non-gate instrument that imports a merge-blocking one inherits its blocking,
1745+
* and the map is not exported in any case. It is PARSED, the way every other
1746+
* fact in this file is read -- through `parseSourceFile`, which refuses an
1747+
* unparseable source instead of scoring it empty.
1748+
*
1749+
* ⛔ Announce, never absorb. The census does not adopt the gate's names on the
1750+
* fly; drift reddens the self-test and a person decides which side moved.
1751+
*
1752+
* @returns the declared names in source order, or `null` when the declaration
1753+
* cannot be read in the shape this cross-check understands -- which the
1754+
* caller reports as a FAILURE, never as "no names".
1755+
*/
1756+
function readGateVocabulary() {
1757+
const file = join(ROOT, GATE_SCRIPT);
1758+
const sf = parseSourceFile(file, readFileSync(file, 'utf8'), scriptKindFor(file));
1759+
let names = null;
1760+
walkAll(sf, (node) => {
1761+
if (names !== null || !ts.isVariableDeclaration(node)) return;
1762+
if (!ts.isIdentifier(node.name) || node.name.text !== GATE_VOCABULARY_IDENT) return;
1763+
const init = node.initializer;
1764+
if (!init || !ts.isNewExpression(init) || init.arguments?.length !== 1) return;
1765+
const [entries] = init.arguments;
1766+
if (!ts.isArrayLiteralExpression(entries)) return;
1767+
const collected = [];
1768+
for (const entry of entries.elements) {
1769+
// A shape this reader does not understand must not degrade to a shorter
1770+
// list: that would green the comparison against a vocabulary nobody read.
1771+
if (!ts.isArrayLiteralExpression(entry) || entry.elements.length === 0) return;
1772+
const [key] = entry.elements;
1773+
if (!ts.isStringLiteralLike(key)) return;
1774+
collected.push(key.text);
1775+
}
1776+
names = collected;
1777+
});
1778+
return names;
1779+
}
1780+
1781+
/** The census's copy of that vocabulary: the `gate-vocabulary` origin subset. */
1782+
function copiedGateVocabulary() {
1783+
return [...WRITE_SHAPED_CALLEES]
1784+
.filter(([, origin]) => origin === 'gate-vocabulary')
1785+
.map(([name]) => name);
1786+
}
1787+
1788+
/**
1789+
* @returns `{ missing, extra }` -- names the gate declares that the copy lacks,
1790+
* and names labelled `gate-vocabulary` here that the gate does not
1791+
* declare. Both directions matter: the first is a member the census
1792+
* under-reports as overlap, the second is overlap it invents.
1793+
*/
1794+
function compareGateVocabulary(copied, declared) {
1795+
const copiedSet = new Set(copied);
1796+
const declaredSet = new Set(declared);
1797+
return {
1798+
missing: declared.filter((name) => !copiedSet.has(name)),
1799+
extra: copied.filter((name) => !declaredSet.has(name)),
1800+
};
1801+
}
1802+
16921803
function selfTest(mode = 'all') {
16931804
const gated = mode === 'gated';
16941805
const problems = [];
@@ -1801,6 +1912,44 @@ function selfTest(mode = 'all') {
18011912
}
18021913
}
18031914

1915+
// ── The COPIED gate vocabulary (#15459), asserted in BOTH modes ───────────
1916+
//
1917+
// See SELF_TEST_MODES for why this leg is gated. Two legs: the copy must equal
1918+
// the gate's own declaration, and the comparison must be able to say it does
1919+
// not.
1920+
const declaredGateNames = readGateVocabulary();
1921+
const copiedGateNames = copiedGateVocabulary();
1922+
if (declaredGateNames === null) {
1923+
problems.push(`the gate's \`${GATE_VOCABULARY_IDENT}\` could not be read out of ${GATE_SCRIPT} in the `
1924+
+ 'shape this cross-check understands. Reported as a FAILURE and never as "no names": an '
1925+
+ 'unreadable declaration compared silently would green this leg forever, which is the exact '
1926+
+ 'defect the cross-check exists to close. Re-point `readGateVocabulary` at its new shape.');
1927+
} else {
1928+
const drift = compareGateVocabulary(copiedGateNames, declaredGateNames);
1929+
if (drift.missing.length > 0 || drift.extra.length > 0) {
1930+
problems.push('the `gate-vocabulary` copy in `WRITE_SHAPED_CALLEES` has DRIFTED from the gate\'s own '
1931+
+ `\`${GATE_VOCABULARY_IDENT}\` (${copiedGateNames.length} copied, ${declaredGateNames.length} declared)`
1932+
+ (drift.missing.length > 0
1933+
? `\n declared by the gate, missing from the copy: ${drift.missing.join(', ')}` : '')
1934+
+ (drift.extra.length > 0
1935+
? `\n labelled \`gate-vocabulary\` here, NOT declared by the gate: ${drift.extra.join(', ')}` : '')
1936+
+ '\n The copy is deliberate and is NOT adopted automatically (see `WRITE_SHAPED_CALLEES`):'
1937+
+ ' decide which side moved. A name the gate gained belongs in the copy; a name this census'
1938+
+ ' wants that the gate does not declare belongs under a different `origin`.');
1939+
}
1940+
// NEGATIVE leg — the comparison must actually fire. A cross-check that
1941+
// cannot report drift is the by-value copy's own failure mode wearing a
1942+
// green tick, so perturb the copy in BOTH directions and require both back.
1943+
const probeAbsent = copiedGateNames[0];
1944+
const probeInvented = 'aNameNoGateWillEverDeclare';
1945+
const probe = compareGateVocabulary([...copiedGateNames.slice(1), probeInvented], declaredGateNames);
1946+
if (!probe.missing.includes(probeAbsent) || !probe.extra.includes(probeInvented)) {
1947+
problems.push('the gate-vocabulary cross-check did not fire: a copy with one declared name dropped '
1948+
+ `and one undeclared name added was compared as ${probe.missing.length} missing / `
1949+
+ `${probe.extra.length} extra. Without this leg the comparison can pass VACUOUSLY.`);
1950+
}
1951+
}
1952+
18041953
// The durability filter must actually filter: the raw shape is ~3.5x this.
18051954
if (members.length === 0) {
18061955
problems.push('census found ZERO members — on this tree that is a broken matcher, not a clean repo.');
@@ -1818,6 +1967,7 @@ function selfTest(mode = 'all') {
18181967
+ `${REGRESSION_CONTROLS.length} regression control(s) stay clear, `
18191968
+ `${RESOLUTION_CONTROLS.length} resolution control(s) resolve as declared, `
18201969
+ `${DETERMINED.size} DETERMINED register row(s) cross-check clean, `
1970+
+ `${copiedGateNames.length} copied gate-vocabulary name(s) match the gate's own declaration, `
18211971
+ `${members.length} member site(s) total\n`
18221972
+ ` ${POSITIVE_CONTROLS.length} positive control(s) are NOT asserted here, permanently: they pin `
18231973
+ 'members of the #12981 worklist, which\n that programme exists to remove — a control the repair '
@@ -1832,6 +1982,7 @@ function selfTest(mode = 'all') {
18321982
+ `${REGRESSION_CONTROLS.length} regression control(s) stay clear, `
18331983
+ `${RESOLUTION_CONTROLS.length} resolution control(s) resolve as declared, `
18341984
+ `${DETERMINED.size} DETERMINED register row(s) cross-check clean, `
1985+
+ `${copiedGateNames.length} copied gate-vocabulary name(s) match the gate's own declaration, `
18351986
+ `${members.length} member site(s) total\n`,
18361987
);
18371988
return 0;

0 commit comments

Comments
 (0)