From b1789af5fe3793fbce1c20a8fe683b2878e7d43b Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 18 Aug 2026 16:10:52 +0000 Subject: [PATCH 1/2] feat(gate): enumerate check:engine-double-contract's pinned population so a lost pin names itself MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The gate pinned 319 engine doubles and reported that count as a printed integer nobody compared. Deleting a pinned double's whole `delete()` member took it to 318 with the gate green (exit 0), because discovery requires the member to exist: a double that stops declaring one simply leaves the population. DISCOVERED fires at zero, never at one-fewer-than-yesterday. Adds a fifth invariant, RETAINED, over a generated ledger of the pinned (file, verb, count) rows. The four existing checks are untouched. A lost pin is classified into four worlds — file deleted, verb gone, members deleted, double unguarded — so a legitimate decrease and the defect get different messages and different remedies. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01XqDQYVU5smx29ts9pAErja --- scripts/check-engine-double-contract.mjs | 502 ++++++- scripts/engine-double-contract.pinned.json | 1545 ++++++++++++++++++++ 2 files changed, 2043 insertions(+), 4 deletions(-) create mode 100644 scripts/engine-double-contract.pinned.json diff --git a/scripts/check-engine-double-contract.mjs b/scripts/check-engine-double-contract.mjs index 04e121026c..b518bb5345 100644 --- a/scripts/check-engine-double-contract.mjs +++ b/scripts/check-engine-double-contract.mjs @@ -136,6 +136,81 @@ // scans. Without it a typo'd or retired verb makes an entry // unreachable -- it would reconcile against nothing, forever, // and read as a live exemption. +// RETAINED a double that WAS pinned still is. The pinned population is +// enumerated in `engine-double-contract.pinned.json`, so a pin +// that leaves names itself instead of decrementing a printed +// integer nobody compares (#9680). See the block below. +// +// ## RETAINED, and why the pinned set is enumerated rather than counted (#9680) +// +// The four invariants above ratchet the LEDGERED population in both directions +// -- measured on this branch, deleting a DEBT-ledgered double's member reddens +// (`RECONCILED: baseline entry for … declares no engine double with a delete +// any more`), and so does dropping one of the five doubles behind the EXEMPT +// entry (`down to 4 … from the baseline's 5`). The PINNED population had no +// such ratchet, and that asymmetry is the whole of #9680: DISCOVERED fires at +// zero, never at one-fewer-than-yesterday, and PINNED iterates the discovered +// set, so a pinned double that stops declaring the member simply LEAVES. +// +// Discovery requires the member to exist, so absence is invisible by +// construction. Measured, two directions, on `packages/core/src/utils/ +// migration-journal.test.ts`: +// +// delete the whole `async delete(…)` member OK -- 318 pinned (was 319), exit 0 +// delete only the `assertEngineDeleteDispatch` call x PINNED …, exit 1 +// +// The control going red is what makes the first line a blind spot rather than a +// broken harness: the gate pins the dispatch behaviour of a member that EXISTS. +// +// ## Why an identity ledger and not a count, priced rather than assumed +// +// A count-delta ("319, shrink-fails") is the cheaper artifact and was rejected +// on two measurements, not on taste: +// +// - It cannot see a SWAP. One double loses `delete` while another gains one +// and the total is unchanged, so the instrument reads clean while coverage +// moved. An enumeration compares membership, so the swap is two rows. +// - Its remedy carries no information. A legitimate removal and this card's +// defect produce the SAME one-character diff (`319` -> `318`), so review +// cannot tell them apart and the only available habit is "bump the number" +// -- the failure mode a ratchet exists to prevent, re-created by the +// ratchet itself. +// +// The maintenance objection to an enumeration is real but was measured and is +// small. Over the 269 commits on `main` in the month to 2026-08-18, membership +// of the pinned set changed in 7 commits (2.6%): 8 files entered per verb, and +// **zero left**. So the nuisance case an identity ledger is accused of -- a +// correct change reddened by a legitimate decrease -- fired 0 times in a month, +// while the additions it does redden on are already in conversation with this +// gate (they are new fakes that had to write `assert…Dispatch` because PINNED +// demanded it). 308 entries today against the 135 the DEBT ledger already +// carries: same file format, same order of magnitude, same reconciliation shape. +// +// ## How a LEGITIMATE decrease is expressed (the anti-nuisance half) +// +// `node scripts/check-engine-double-contract.mjs --write`, then commit. That is +// the whole remedy, it is the repo's existing ratchet idiom (see +// check-slot-lookup-ratchet.mjs's `--update`), and it is mechanical -- there is +// no number to choose, so there is no number to fudge. +// +// What keeps that from degenerating into "regenerate on red" is that the gate +// CLASSIFIES the loss before asking for anything, and says which of three +// worlds it is in: +// +// file gone from disk a deleted test. Legitimate; regenerate. +// file present, verb gone THE #9680 DEFECT. The member was dropped while +// the fake and its file live on. Loud, and named. +// fewer doubles than pinned the same defect at a finer grain: the file pins +// several and one member was deleted. Nothing else +// in this gate reacts, because a fake is still there. +// all doubles present, the double went UNGUARDED -- already an error +// fewer pinned under PINNED above, and cross-named here so one +// output explains the whole picture. +// +// A count can reach none of those three, because by the time it has been +// decremented the identity is gone. And `--write` prints every loss it is about +// to record, so the author reads what left at the moment they regenerate rather +// than discovering it in review. // // ## Why "routes through the shared predicate" and not "mirrors the guard" // @@ -163,13 +238,14 @@ // while degrading. What it can do is make the rejection surface impossible to // drift, which is the half that shipped #4434. -import { readFileSync, readdirSync, existsSync } from 'node:fs'; +import { readFileSync, readdirSync, existsSync, writeFileSync } from 'node:fs'; import { join, dirname, relative, sep } from 'node:path'; import { fileURLToPath } from 'node:url'; import ts from 'typescript'; const ROOT = join(dirname(fileURLToPath(import.meta.url)), '..'); const BASELINE_PATH = join(ROOT, 'scripts', 'engine-double-contract.baseline.json'); +const PINNED_LEDGER_PATH = join(ROOT, 'scripts', 'engine-double-contract.pinned.json'); const SCAN_ROOTS = ['packages', 'examples']; /** @@ -1190,6 +1266,226 @@ function readBaseline() { return JSON.parse(readFileSync(BASELINE_PATH, 'utf8')); } +/** + * The RETAINED ledger (#9680) — the enumerated pinned population. + * + * Deliberately a SEPARATE artifact from `engine-double-contract.baseline.json` + * rather than more rows in it. The baseline is 135 hand-written MEASURED + * justifications whose readability this file's header calls the gate's whole + * value ("shrink-only, hand reviewed"); folding 308 generated rows in would + * bury the reasons under the census and blur which rows a human must agree to. + * These two ledgers also answer to opposite polarities — the baseline records + * debt and may only SHRINK, this one records coverage and may only GROW — so a + * reader who conflates them reads every ratchet in this file backwards. + * + * A missing file reads as an empty ledger so a fresh checkout bootstraps + * through `--write` rather than crashing, exactly as `readBaseline` does. + */ +function readPinnedLedger() { + if (!existsSync(PINNED_LEDGER_PATH)) return { entries: [] }; + return JSON.parse(readFileSync(PINNED_LEDGER_PATH, 'utf8')); +} + +/** + * The pinned population as (file, verb, pinned-count) rows, sorted for a stable + * diff. + * + * Counted per FILE and not merely as membership, because a file may hold more + * than one pinned double for a verb — measured on this branch: 319 pinned + * doubles across 308 (file, verb) pairs, so 11 pairs carry more than one. A + * membership-only ledger would let a file that pins two deletes drop to one in + * silence, which is this card's defect at a finer grain. + */ +function censusPinned(slices) { + const rows = []; + for (const { slice, found } of slices) { + for (const { file, doubles } of found) { + const pinned = doubles.filter((d) => d.pinned).length; + if (pinned > 0) rows.push({ file, verb: slice.verb, pinned }); + } + } + rows.sort((a, b) => (a.file === b.file ? a.verb.localeCompare(b.verb) : a.file.localeCompare(b.file))); + return rows; +} + +/** + * The (file, verb) key for every map in this section. + * + * `JSON.stringify` of the pair rather than a joined string: a separator has to + * be a character neither half can contain, and the obvious candidates are worse + * than they look -- a space can appear in a path, and the NUL that would be + * unambiguous is a raw control byte this repo bans outright + * (`scripts/check-nul-bytes.mjs`), which is not a rule to route around inside a + * gate. Stringifying the pair has no separator to collide on at all. + */ +const pairKey = (file, verb) => JSON.stringify([file, verb]); + +/** + * How many doubles the scan still DECLARES per (file, verb), pinned or not. + * + * Distinct from `censusPinned`, and the distinction carries the whole + * classification below. A double that went UNGUARDED leaves the census (which + * counts pinned doubles) but stays here (which counts declared ones), while a + * double whose member was DELETED leaves both. Reading the census alone would + * report every newly-unguarded double as "the member was dropped" -- the wrong + * remedy attached to the wrong story. + * + * Counted rather than a membership Set, because a file may pin several doubles + * for one verb (measured: 10 of 308 rows do). Membership alone cannot separate + * "the file pinned two deletes and now pins one because a MEMBER WAS DELETED" + * from "...because a member stopped calling the predicate", and those two want + * opposite remedies: restore the member vs re-pin it. + */ +function declaredCounts(slices) { + const counts = new Map(); + for (const { slice, found } of slices) { + for (const { file, doubles } of found) counts.set(pairKey(file, slice.verb), doubles.length); + } + return counts; +} + +/** + * Which of the four worlds a lost pin is in -- see the RETAINED block in the + * header. A pure function so the self-test can drive all four without a + * filesystem full of fixtures. + * + * Order matters: a file that is gone cannot also have "lost a member", so disk + * is asked first; then whether the verb is declared at all; then whether FEWER + * doubles are declared than the ledger pinned, which is the only evidence that + * separates a deleted member from a member that merely stopped being pinned. + */ +function classifyPinLoss({ onDisk, declared, wasPinned }) { + if (!onDisk) return 'file-removed'; + if (declared === 0) return 'double-removed'; + if (declared < wasPinned) return 'members-removed'; + return 'unpinned'; +} + +const REGEN = 'node scripts/check-engine-double-contract.mjs --write'; + +/** + * RETAINED's errors, as a pure function of two censuses and the ledger. + * + * `onDisk` is injected so the self-test can drive all three loss worlds without + * creating and deleting real files. + */ +function retainedErrors(census, ledger, ledgerExists, declared, onDisk) { + const errors = []; + + // Bootstrap. Without this a missing artifact reports 308 separate "not in the + // ledger" errors, which reads as a catastrophe and buries the one-line fix. + if (!ledgerExists) { + return [ + `RETAINED: ${relative(ROOT, PINNED_LEDGER_PATH)} is missing. That file IS the pinned ` + + 'population; without it this gate is back to printing an integer nobody compares ' + + `(#9680). Bootstrap it with \`${REGEN}\` and commit it.`, + ]; + } + + const found = new Map(census.map((r) => [pairKey(r.file, r.verb), r.pinned])); + const recorded = new Map(); + + for (const entry of ledger.entries) { + // Same reasoning as DECLARED: an entry naming a verb no slice scans + // reconciles against nothing forever, so it would read as permanent + // coverage while protecting nothing. + if (!SCANNED_VERBS.has(entry.verb)) { + errors.push( + `RETAINED: pinned-ledger entry for ${entry.file} names verb ${JSON.stringify(entry.verb)}, ` + + `which no slice scans (known: ${[...SCANNED_VERBS].join(', ')}). An entry no slice ` + + 'reaches can never lose its pin, so it records coverage that cannot be checked — fix ' + + 'the verb or delete the entry.', + ); + continue; + } + recorded.set(pairKey(entry.file, entry.verb), entry.pinned); + } + + // ── The loss direction: a pin the ledger records that the scan no longer sees. + for (const entry of ledger.entries) { + if (!SCANNED_VERBS.has(entry.verb)) continue; + const now = found.get(pairKey(entry.file, entry.verb)) ?? 0; + if (now >= entry.pinned) continue; + + const world = classifyPinLoss({ + onDisk: onDisk(entry.file), + declared: declared.get(pairKey(entry.file, entry.verb)) ?? 0, + wasPinned: entry.pinned, + }); + const slice = SLICES.find((s) => s.verb === entry.verb); + const head = `RETAINED [${entry.verb}]: ${entry.file}`; + + if (world === 'file-removed') { + errors.push( + `${head} is gone from disk, and the pinned ledger still records ${entry.pinned} pinned ` + + `${entry.verb} double(s) there. A deleted test is a LEGITIMATE decrease: run ` + + `\`${REGEN}\` and commit the ledger. There is no number to choose and no judgement to ` + + 'make — the diff records which pin left, which is the review signal a bare count ' + + 'could never carry.', + ); + } else if (world === 'double-removed') { + errors.push( + `${head} is still on disk but declares NO engine double with a ${entry.verb} any more, ` + + `while the pinned ledger records ${entry.pinned}. This is the #9680 shape exactly: the ` + + 'member was DROPPED rather than the test deleted, and discovery needs the member to ' + + 'exist, so the double left the population and every other invariant in this gate ' + + `passed over it in silence (measured: 319 pinned -> 318, exit 0). Restore the ` + + `${entry.verb}() member and its \`${slice.pinCall}\` call. ONLY if the double is ` + + `genuinely and intentionally gone — the fake no longer stands in for the engine at ` + + `all — run \`${REGEN}\` and commit, so the ledger diff records which pin left.`, + ); + } else if (world === 'members-removed') { + const declaredNow = declared.get(pairKey(entry.file, entry.verb)) ?? 0; + errors.push( + `${head} declares ${declaredNow} engine double(s) with a ${entry.verb}, down from the ` + + `${entry.pinned} the pinned ledger records as pinned. This is the #9680 shape at a ` + + 'finer grain: the file still holds a fake, so nothing else in this gate reacts, but ' + + `${entry.pinned - declaredNow} ${entry.verb}() member(s) were DELETED and the coverage ` + + 'they carried left with them. Restore the member(s) and their ' + + `\`${slice.pinCall}\` call. ONLY if the double(s) are genuinely and intentionally gone ` + + `— that fake no longer stands in for the engine — run \`${REGEN}\` and commit, so the ` + + 'ledger diff records which pin left.', + ); + } else { + errors.push( + `${head} still declares every ${entry.verb} double the ledger counted, but only ${now} of ` + + `${entry.pinned} route through ${[...slice.symbols][0]} any more. The double went ` + + 'UNGUARDED rather than absent, so the PINNED error naming this same file is the one to ' + + 'act on — this line exists so one output explains the whole picture. Re-pin it; do ' + + `NOT reach for \`${REGEN}\`, which would record the loss as intended.`, + ); + } + } + + // ── The growth direction: coverage the ledger does not yet know about. + // + // An error rather than a silent accept, and the reason is decay: measured over + // the month to 2026-08-18, 8 files ENTERED the pinned set per verb and none + // left, so a ledger that only had to be touched on removals would never be + // touched at all and every new double would sit outside the ratchet forever — + // this card's blind spot, re-opened on the newest code. The remedy is the same + // one command, and the author is already in conversation with this gate. + for (const row of census) { + const was = recorded.get(pairKey(row.file, row.verb)); + if (was === undefined) { + errors.push( + `RETAINED [${row.verb}]: ${row.file} pins ${row.pinned} engine double(s) that the pinned ` + + 'ledger does not record. New pinned coverage is GOOD and nothing is wrong with your ' + + `change — the ledger just has to learn about it, or it never protects this file. Run ` + + `\`${REGEN}\` and commit.`, + ); + } else if (row.pinned > was) { + errors.push( + `RETAINED [${row.verb}]: ${row.file} now pins ${row.pinned} engine double(s), ledger ` + + `records ${was}. Coverage grew, which is the direction this ledger wants — run ` + + `\`${REGEN}\` and commit so the new double is ratcheted too.`, + ); + } + } + + return errors; +} + // ── The ratchet-remedy authority convention (#8435) ────────────────────────── // // Four independent PRs, four authors, four brand-new test files, one shift -- @@ -1374,6 +1670,22 @@ function audit() { } } + // ── RETAINED (#9680) — the pinned population is enumerated, not counted ─── + // + // Runs AFTER the per-slice loop because it reads the same `slices` the loop + // built. It adds no criterion to the four above and changes no verdict any of + // them reaches: every error below concerns a (file, verb) pair the ledger + // names, or one the census found and the ledger does not. + const census = censusPinned(slices); + const pinnedLedger = readPinnedLedger(); + errors.push(...retainedErrors( + census, + pinnedLedger, + existsSync(PINNED_LEDGER_PATH), + declaredCounts(slices), + (file) => existsSync(join(ROOT, file)), + )); + // ── The consumer seams (#8194) ──────────────────────────────────────────── const seamFiles = scanAllSeams(); const seamCount = seamFiles.reduce((n, f) => n + f.seams.length, 0); @@ -1415,11 +1727,64 @@ function audit() { } } - return { slices, baseline, errors, seamFiles, seamCount }; + return { slices, baseline, errors, seamFiles, seamCount, census, pinnedLedger }; +} + +const PINNED_LEDGER_COMMENT = + 'GENERATED — the RETAINED ledger of check-engine-double-contract.mjs (#9680). Regenerate with ' + + '`node scripts/check-engine-double-contract.mjs --write`; never hand-edit. Each row is one ' + + '(file, verb) whose engine double routes through the producer\'s dispatch predicate. This is ' + + 'the OPPOSITE polarity to engine-double-contract.baseline.json: that ledger records DEBT and ' + + 'may only shrink, this one records COVERAGE and may only grow. A row that disappears is a ' + + 'pinned double that left the population — the blind spot #9680 measured, where deleting a ' + + 'double\'s delete() member took 319 pinned to 318 with the gate green. Read a removal in this ' + + 'file\'s diff as a coverage loss and check it was intended.'; + +/** + * Regenerate the RETAINED ledger (#9680). + * + * Prints every LOSS it is about to record before writing. That is the half that + * keeps `--write` from becoming the "bump the number" reflex ruling this gate + * out was meant to prevent: the author reads which pin left at the moment they + * regenerate, rather than meeting it in review — or not at all. + */ +function writeLedger() { + const { slices } = audit(); + const census = censusPinned(slices); + const before = readPinnedLedger(); + const was = new Map((before.entries ?? []).map((e) => [pairKey(e.file, e.verb), e.pinned])); + const now = new Map(census.map((r) => [pairKey(r.file, r.verb), r.pinned])); + + const losses = []; + for (const [k, n] of was) { + const after = now.get(k) ?? 0; + const [file, verb] = JSON.parse(k); + if (after < n) losses.push(`[${verb}] ${file}: ${n} pinned -> ${after}`); + } + const gains = [...now].filter(([k, n]) => n > (was.get(k) ?? 0)).length; + + writeFileSync( + PINNED_LEDGER_PATH, + `${JSON.stringify({ $comment: PINNED_LEDGER_COMMENT, entries: census }, null, 2)}\n`, + ); + + console.log(''); + if (losses.length) { + console.log(` ⛔ RECORDING ${losses.length} PIN LOSS(ES) — read these before you commit:`); + for (const l of losses) console.log(` - ${l}`); + console.log(' Each line is coverage this gate will no longer hold. If any of them is a'); + console.log(' dropped member rather than a deleted test, restore it instead of committing.'); + } else { + console.log(' No pin losses — this regeneration only records new or grown coverage.'); + } + console.log( + `\ncheck-engine-double-contract --write: ${census.length} (file, verb) row(s), ` + + `${gains} added or grown, ${losses.length} lost.\n`, + ); } function report() { - const { slices, baseline, errors, seamFiles, seamCount } = audit(); + const { slices, baseline, errors, seamFiles, seamCount, census } = audit(); console.log(''); let totalPinned = 0; @@ -1477,7 +1842,15 @@ function report() { const debt = baseline.entries.filter((e) => e.kind !== 'EXEMPT').length; console.log( `check-engine-double-contract: OK — ${totalPinned} pinned, ${debt} in the DEBT ledger, ` - + `${exempt.length} exempt.\n`, + + `${exempt.length} exempt.`, + ); + // Say that the pinned number is now RATCHETED, not merely printed. Before + // #9680 this line ended at "319 pinned" and that integer was the only trace a + // vanished double left; a reader had no way to tell a checked count from a + // reported one, which is what let 319 -> 318 read as success. + console.log( + `check-engine-double-contract: ${census.length} (file, verb) row(s) held by the RETAINED ` + + `ledger — a pin that leaves names itself.\n`, ); } @@ -2224,6 +2597,126 @@ class Svc { + 'predicate discriminates rather than approving everything)', !ratchetRemedyCarriesAuthority(unmarkedOffer)); + + // ── RETAINED (#9680): the pinned population is enumerated, not counted ───── + // + // Driven through the two pure functions the invariant is built from, so all + // four loss worlds are exercised without creating and deleting real files. + // `onDisk` and the two censuses are injected for exactly that reason. + const LEDGER_OK = true; + const noDisk = () => false; + const onDisk = () => true; + const dcount = (pairs) => new Map(pairs.map(([f, v, n]) => [pairKey(f, v), n])); + const anyOf = (errs, needle) => errs.some((e) => e.includes(needle)); + + // The census reads PINNED doubles, the declared census reads ALL of them. + // Both directions, because conflating them is what made the first draft of + // this invariant tell a file whose member was deleted to "re-pin" it. + const mixedSlices = [{ + slice: SLICES[0], + found: [{ file: 'a.test.ts', doubles: [{ pinned: true }, { pinned: false }] }], + }]; + expect('censusPinned counts only the PINNED doubles', + censusPinned(mixedSlices).length === 1 && censusPinned(mixedSlices)[0].pinned === 1); + expect('declaredCounts counts pinned AND unpinned doubles', + declaredCounts(mixedSlices).get(pairKey('a.test.ts', 'delete')) === 2); + expect('censusPinned omits a file whose doubles are all unpinned', + censusPinned([{ slice: SLICES[0], found: [{ file: 'b.test.ts', doubles: [{ pinned: false }] }] }]) + .length === 0); + + // ── The four loss worlds, each separated from its neighbours. + expect('a file gone from disk classifies as file-removed', + classifyPinLoss({ onDisk: false, declared: 0, wasPinned: 1 }) === 'file-removed'); + expect('a file on disk declaring no double classifies as double-removed', + classifyPinLoss({ onDisk: true, declared: 0, wasPinned: 1 }) === 'double-removed'); + expect('fewer doubles declared than pinned classifies as members-removed', + classifyPinLoss({ onDisk: true, declared: 1, wasPinned: 2 }) === 'members-removed'); + expect('every double still declared classifies as unpinned', + classifyPinLoss({ onDisk: true, declared: 2, wasPinned: 2 }) === 'unpinned'); + + // ── The clean direction: a ledger that matches the census reports nothing. + // Without this every assertion below could pass on a function that always + // errors, which is the guard-that-cannot-pass twin of #4118. + const cleanLedger = { entries: [{ file: 'a.test.ts', verb: 'delete', pinned: 1 }] }; + const cleanCensus = [{ file: 'a.test.ts', verb: 'delete', pinned: 1 }]; + expect('a ledger matching the census is silent', + retainedErrors(cleanCensus, cleanLedger, LEDGER_OK, + dcount([['a.test.ts', 'delete', 1]]), onDisk).length === 0); + + // ── Each loss world reaches its OWN message, and never a neighbour's. + const lostFile = retainedErrors([], cleanLedger, LEDGER_OK, dcount([]), noDisk); + expect('a deleted test file is reported as a legitimate decrease', + lostFile.length === 1 && anyOf(lostFile, 'gone from disk') + && anyOf(lostFile, 'LEGITIMATE decrease')); + + const lostDouble = retainedErrors([], cleanLedger, LEDGER_OK, dcount([]), onDisk); + expect('a dropped member on a live file is reported as the #9680 defect', + lostDouble.length === 1 && anyOf(lostDouble, 'declares NO engine double') + && anyOf(lostDouble, '#9680')); + expect('the dropped-member message does NOT read as a legitimate decrease', + !anyOf(lostDouble, 'gone from disk')); + + const twoPinned = { entries: [{ file: 'a.test.ts', verb: 'delete', pinned: 2 }] }; + const lostOne = retainedErrors([{ file: 'a.test.ts', verb: 'delete', pinned: 1 }], twoPinned, + LEDGER_OK, dcount([['a.test.ts', 'delete', 1]]), onDisk); + expect('one member deleted out of two pinned is reported as members-removed', + lostOne.length === 1 && anyOf(lostOne, 'down from the 2')); + expect('the members-removed message does not tell the author to re-pin', + !anyOf(lostOne, 'Re-pin it')); + + const wentLoose = retainedErrors([], cleanLedger, LEDGER_OK, + dcount([['a.test.ts', 'delete', 1]]), onDisk); + expect('a double that went unguarded is reported as unpinned, not as absent', + wentLoose.length === 1 && anyOf(wentLoose, 'went UNGUARDED') + && !anyOf(wentLoose, 'declares NO engine double')); + expect('the unpinned message refuses the regeneration remedy', + anyOf(wentLoose, 'do NOT reach for')); + + // ── The growth direction. Both spellings, because a new FILE and a new double + // in a known file arrive by different routes and only one was in the first draft. + const grewNew = retainedErrors([{ file: 'new.test.ts', verb: 'delete', pinned: 1 }], + { entries: [] }, LEDGER_OK, dcount([['new.test.ts', 'delete', 1]]), onDisk); + expect('a newly pinned file the ledger does not record is reported', + grewNew.length === 1 && anyOf(grewNew, 'does not record')); + expect('new coverage is not reported as anyone’s mistake', + anyOf(grewNew, 'nothing is wrong with your change')); + + const grewMore = retainedErrors([{ file: 'a.test.ts', verb: 'delete', pinned: 2 }], cleanLedger, + LEDGER_OK, dcount([['a.test.ts', 'delete', 2]]), onDisk); + expect('a file that pins MORE than the ledger records is reported', + grewMore.length === 1 && anyOf(grewMore, 'Coverage grew')); + + // ── Bootstrap: a missing ledger is ONE error, not one per row. The failure + // this guards is a fresh checkout reporting 308 problems for one missing file. + const missing = retainedErrors( + [{ file: 'a.test.ts', verb: 'delete', pinned: 1 }, { file: 'b.test.ts', verb: 'update', pinned: 1 }], + { entries: [] }, false, dcount([]), onDisk); + expect('a missing pinned ledger reports exactly one bootstrap error', + missing.length === 1 && anyOf(missing, 'is missing')); + + // ── DECLARED's twin for this ledger: an entry naming a verb no slice scans + // can never lose its pin, so it would record coverage nothing checks. + const badVerb = retainedErrors([], { entries: [{ file: 'a.test.ts', verb: 'destroy', pinned: 1 }] }, + LEDGER_OK, dcount([]), onDisk); + expect('a pinned-ledger entry naming an unscanned verb is rejected', + badVerb.length === 1 && anyOf(badVerb, 'no slice scans')); + expect('an unscanned-verb entry is not ALSO reported as a lost pin', + !anyOf(badVerb, 'gone from disk') && !anyOf(badVerb, 'declares NO engine double')); + + // ── The reason this invariant exists, stated as an assertion: the pinned + // population must be enumerated. A ledger holding only a COUNT cannot express + // the swap that motivated #9680 -- one file loses a pin, another gains one -- + // so the census rows carry identity, and this fails if they ever stop. + expect('census rows carry file identity, not just a total', + censusPinned(mixedSlices)[0].file === 'a.test.ts' + && typeof censusPinned(mixedSlices)[0].verb === 'string'); + const swapBefore = { entries: [{ file: 'x.test.ts', verb: 'delete', pinned: 1 }] }; + const swapAfter = [{ file: 'y.test.ts', verb: 'delete', pinned: 1 }]; + const swap = retainedErrors(swapAfter, swapBefore, LEDGER_OK, + dcount([['y.test.ts', 'delete', 1]]), onDisk); + expect('a SWAP (one pin lost, one gained, total unchanged) is reported both ways', + swap.length === 2 && anyOf(swap, 'x.test.ts') && anyOf(swap, 'y.test.ts')); + if (failures.length) { for (const f of failures) console.error(` x self-test: ${f}`); console.error(`\ncheck-engine-double-contract --self-test: ${failures.length} failure(s).\n`); @@ -2249,4 +2742,5 @@ class Svc { } if (process.argv.includes('--self-test')) selfTest(); +else if (process.argv.includes('--write')) writeLedger(); else report(); diff --git a/scripts/engine-double-contract.pinned.json b/scripts/engine-double-contract.pinned.json new file mode 100644 index 0000000000..8536b2888f --- /dev/null +++ b/scripts/engine-double-contract.pinned.json @@ -0,0 +1,1545 @@ +{ + "$comment": "GENERATED — the RETAINED ledger of check-engine-double-contract.mjs (#9680). Regenerate with `node scripts/check-engine-double-contract.mjs --write`; never hand-edit. Each row is one (file, verb) whose engine double routes through the producer's dispatch predicate. This is the OPPOSITE polarity to engine-double-contract.baseline.json: that ledger records DEBT and may only shrink, this one records COVERAGE and may only grow. A row that disappears is a pinned double that left the population — the blind spot #9680 measured, where deleting a double's delete() member took 319 pinned to 318 with the gate green. Read a removal in this file's diff as a coverage loss and check it was intended.", + "entries": [ + { + "file": "packages/core/src/utils/migration-journal.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/core/src/utils/migration-journal.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/mcp/src/mcp-stdio-tools.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/mcp/src/mcp-stdio-tools.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/mcp/src/mcp-write-response-internal-fields.tripwire.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/mcp/src/mcp-write-response-internal-fields.tripwire.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/mcp/src/plugin.record-resource-exposure.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/mcp/src/plugin.record-resource-exposure.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/migrations/recorded-by-sentinel.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/migrations/recorded-by-sentinel.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol-publish-drafts-advisories.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol-publish-drafts-advisories.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol-publish-drafts-endpoint-gate.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol-publish-drafts-endpoint-gate.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol-publish-drafts-org-scope.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol-publish-drafts-org-scope.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol-publish-drafts-package-scope.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol-publish-drafts-package-scope.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.adr0005-org-override-rollback.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.adr0005-org-override-rollback.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.audit-field-governance.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.audit-field-governance.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.batch-row-conformance.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.batch-row-conformance.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.batch-row-driver-text.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.batch-row-driver-text.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.batch-row-http-status.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.batch-row-http-status.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.batch-verb-driver-code.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.batch-verb-driver-code.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.batch-verb-driver-text.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.batch-verb-driver-text.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.capability-write-door.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.capability-write-door.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.code-only-types.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.code-only-types.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.container-issue-descent.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.container-issue-descent.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.dashboard-dataset-publish-gate.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.dashboard-dataset-publish-gate.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.delete-object-registry-unregister.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.delete-object-registry-unregister.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.delete-receipt-wording.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.delete-receipt-wording.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.delete-rewrap-envelope.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.delete-rewrap-envelope.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.diff-canonical-type-and-history-outage.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.diff-canonical-type-and-history-outage.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.diff-credential-redaction.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.diff-credential-redaction.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.diff-dead-history-read.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.diff-dead-history-read.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.driver-text-disclosure.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.driver-text-disclosure.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.dropped-fields.test.ts", + "verb": "update", + "pinned": 3 + }, + { + "file": "packages/metadata-protocol/src/protocol.flow-org-override-closed.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.flow-org-override-closed.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.graft-folded-form-sections.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.graft-folded-form-sections.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.injected-system-columns.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.injected-system-columns.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.legacy-overlay-delete.test.ts", + "verb": "delete", + "pinned": 2 + }, + { + "file": "packages/metadata-protocol/src/protocol.legacy-overlay-delete.test.ts", + "verb": "update", + "pinned": 2 + }, + { + "file": "packages/metadata-protocol/src/protocol.lifecycle-audit-rows.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.lifecycle-audit-rows.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.lock-gate-fail-closed.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.lock-gate-fail-closed.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.meta-types-mint-door-agreement.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.meta-types-mint-door-agreement.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.metadata-redaction.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.metadata-redaction.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.migrate-stored-noncanonical-type.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.migrate-stored-noncanonical-type.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.object-registry-write-through-spelling.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.object-registry-write-through-spelling.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.org-scoped-cold-boot-audit-live-registry.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.org-scoped-cold-boot-audit-live-registry.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.org-scoped-cold-boot-audit.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.org-scoped-cold-boot-audit.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.org-scoped-write-refused.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.org-scoped-write-refused.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.package-publish-audit-rows.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.package-publish-audit-rows.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.platform-schedule-org-gate.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.platform-schedule-org-gate.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.publish-commit-capture-read-failure.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.publish-commit-capture-read-failure.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.publish-side-effects-canonical-type.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.publish-side-effects-canonical-type.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.publish-stored-type-canonical.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.publish-stored-type-canonical.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.read-decorations.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.read-decorations.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.record-package-commit-durability.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.record-package-commit-durability.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.revert-stored-type-canonical.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.revert-stored-type-canonical.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.runtime-authoring-gate.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.runtime-authoring-gate.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.save-flow-canonicalization.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.save-flow-canonicalization.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.save-receipt-wording.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.save-receipt-wording.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.save-union-issues.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.save-union-issues.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.stored-conversions.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.stored-conversions.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.stored-migration.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.stored-migration.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.stored-residue-resave.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.stored-residue-resave.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.unrecognised-meta-type.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.unrecognised-meta-type.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.validate-data.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.validate-data.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.write-response-internal-fields.tripwire.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/protocol.write-response-internal-fields.tripwire.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/seed-loader-composite-external-id.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/seed-loader-composite-external-id.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/seed-loader-deferred-dropped.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/seed-loader-deferred-dropped.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/seed-loader-deferred-failure.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/seed-loader-deferred-failure.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/seed-loader-driver-text.test.ts", + "verb": "delete", + "pinned": 2 + }, + { + "file": "packages/metadata-protocol/src/seed-loader-driver-text.test.ts", + "verb": "update", + "pinned": 2 + }, + { + "file": "packages/metadata-protocol/src/seed-loader-engine-schema-fallback.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/seed-loader-engine-schema-fallback.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/seed-loader-env-scope.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/seed-loader-env-scope.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/seed-loader-existing-records-read-failure.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/seed-loader-existing-records-read-failure.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/seed-loader-multi-value-reference.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/seed-loader-multi-value-reference.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/seed-loader-name-probe.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/seed-loader-name-probe.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/seed-loader-replay.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/seed-loader-replay.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/seed-loader-retry.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/seed-loader-retry.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/seed-loader-state-machine-exempt.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/seed-loader-state-machine-exempt.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/seed-loader-summary-stale.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/seed-loader-summary-stale.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/seed-loader-unresolved-drop.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/seed-loader-unresolved-drop.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/sys-metadata-repository.draft-drain.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/sys-metadata-repository.draft-drain.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/sys-metadata-repository.history-counters.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/sys-metadata-repository.history-counters.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/sys-metadata-repository.package-writability.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/sys-metadata-repository.package-writability.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/sys-metadata-repository.recorded-by.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/sys-metadata-repository.recorded-by.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/view-container-runtime-expansion.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata-protocol/src/view-container-runtime-expansion.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/metadata/src/migrations/migrate-sys-notification-to-event.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/metadata/src/migrations/migrate-sys-notification-to-event.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/objectql/src/layered-overlay-integration.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/objectql/src/layered-overlay-integration.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/objectql/src/package-disable-enforcement.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/objectql/src/package-disable-enforcement.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/objectql/src/protocol-boot-hydration-scoped.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/objectql/src/protocol-boot-object-package-binding.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/objectql/src/protocol-boot-object-package-binding.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/objectql/src/protocol-commit-history.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/objectql/src/protocol-commit-history.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/objectql/src/protocol-delete-object-registry-heal.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/objectql/src/protocol-delete-object-registry-heal.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/objectql/src/protocol-meta-effective-schema.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/objectql/src/protocol-meta-effective-schema.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/objectql/src/protocol-meta-type-canonicalization.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/objectql/src/protocol-meta-type-canonicalization.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/objectql/src/protocol-object-overlay-layer.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/objectql/src/protocol-object-overlay-layer.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/objectql/src/protocol-org-overlay-registry-gate.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/objectql/src/protocol-org-overlay-registry-gate.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/objectql/src/protocol-packaged-object-base.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/objectql/src/protocol-packaged-object-base.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/objectql/src/protocol-publish-package-drafts.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/objectql/src/protocol-publish-rollback.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/objectql/src/protocol-publish-rollback.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/objectql/src/protocol-registry-shadow.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/objectql/src/protocol-save-meta-repo-path.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/objectql/src/protocol-save-meta-repo-path.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/objectql/src/protocol-view-identity-overlay.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/objectql/src/protocol-view-identity-overlay.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/objectql/src/protocol-writepath-object-ownership.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/objectql/src/protocol-writepath-object-ownership.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/objectql/src/registry-tenant-index-author-declared-column.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/objectql/src/registry-tenant-index-author-declared-column.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/objectql/src/registry-tenant-index-declaration.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/objectql/src/registry-tenant-index-declaration.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/objectql/src/registry-tenant-index-follows-wall.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/objectql/src/registry-tenant-index-follows-wall.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/objectql/src/seed-loader-org-fallback.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/objectql/src/seed-loader-org-stamp.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/objectql/src/sys-metadata-repository.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/objectql/src/sys-metadata-repository.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/platform-objects/src/plugin.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/platform-objects/src/system/migration-flag.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-approvals/src/admin-exemption-retired.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-approvals/src/record-reader-visibility.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-approvals/src/record-reader-visibility.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-auth/src/accept-invitation-adopt-membership.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-auth/src/accept-invitation-adopt-membership.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-auth/src/auth-manager.jwt-eddsa-fallback.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-auth/src/auth-manager.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-auth/src/auth-manager.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-auth/src/auth-where-operator-coverage.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-auth/src/change-email-delete-user-wiring.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-auth/src/change-email-delete-user-wiring.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-auth/src/impersonation-bearer-rotation.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-auth/src/impersonation-bearer-rotation.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-auth/src/org-create-posture-gate.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-auth/src/remove-member-permission-guard.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-auth/src/remove-member-permission-guard.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-auth/src/remove-user-atomicity.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-auth/src/remove-user-atomicity.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-auth/src/session-of-record.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-auth/src/session-tombstone.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-auth/src/session-tombstone.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-email/src/attachment-reclaim.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-email/src/email-plugin.attachment-storage.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-email/src/email-plugin.outbox-sweep.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-email/src/email-plugin.queue-delivery.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-email/src/email-plugin.template-runtime-write.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-security/src/authored-row-write-verdict.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-security/src/authored-row-write-verdict.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-security/src/check-only-write-scope.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-security/src/check-only-write-scope.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-security/src/claim-seed-ownership.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-security/src/permission-denied-user-copy.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-security/src/permission-denied-user-copy.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-security/src/row-write-widener-composition.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-security/src/row-write-widener-composition.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-security/src/security-denial-user-copy.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-security/src/security-denial-user-copy.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-security/src/select-only-write-visibility.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-security/src/select-only-write-visibility.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-security/src/share-link-tenant-wall.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-security/src/share-link-tenant-wall.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-security/src/suggested-audience-bindings-install-path.test.ts", + "verb": "delete", + "pinned": 2 + }, + { + "file": "packages/plugins/plugin-security/src/suggested-audience-bindings-install-path.test.ts", + "verb": "update", + "pinned": 2 + }, + { + "file": "packages/plugins/plugin-security/src/vama-write-path-convergence.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-security/src/vama-write-path-convergence.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-sharing/src/authored-row-write-deferral.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-sharing/src/authored-row-write-deferral.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-sharing/src/boot-backfill.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-sharing/src/bu-tree-recompute.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-sharing/src/bu-tree-recompute.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-sharing/src/bulk-recompute.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-sharing/src/federated-phantom-owner-scoping.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-sharing/src/federated-phantom-owner-scoping.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-sharing/src/recipient-width.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-sharing/src/recipient-width.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-sharing/src/record-share-cascade.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-sharing/src/share-link-eligibility.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-sharing/src/share-link-enforcement-context.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-sharing/src/share-link-enforcement-context.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-sharing/src/sharing-rule-provenance.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-sharing/src/sharing-rule.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-sharing/src/sharing-service.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-sharing/src/system-caller-inert-grant.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-sharing/src/system-caller-inert-grant.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-sharing/src/system-write-skip-notice.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-sharing/src/system-write-skip-notice.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-webhooks/src/webhook-drop-durable-record.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-webhooks/src/webhook-drop-durable-record.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-webhooks/src/webhook-signing-secret.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/plugins/plugin-webhooks/src/webhook-signing-secret.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/rest/src/meta-published-overlay.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/rest/src/meta-published-overlay.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/rest/src/public-form-lookup-picker.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/rest/src/public-form-lookup-picker.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/rest/src/public-form-routes.stored-row.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/rest/src/public-form-routes.stored-row.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/runtime/src/action-execution-calldata-not-found.test.ts", + "verb": "delete", + "pinned": 2 + }, + { + "file": "packages/runtime/src/domains/meta-published-runtime-publish.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/runtime/src/domains/meta-published-runtime-publish.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/runtime/src/domains/share-links-enforcement-context.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/runtime/src/domains/share-links-enforcement-context.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/runtime/src/http-dispatcher.keys.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/runtime/src/http-dispatcher.keys.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/runtime/src/meta-compound-arity-mint-door.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/runtime/src/meta-compound-arity-mint-door.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/runtime/src/meta-field-overlay-lock.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/runtime/src/meta-field-overlay-lock.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/runtime/src/meta-overlay-read-your-writes.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/runtime/src/meta-overlay-read-your-writes.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/runtime/src/meta-write-org-scope.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/runtime/src/meta-write-org-scope.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/runtime/src/seed-loader.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/runtime/src/seed-loader.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/services/service-automation/src/builtin/crud-bulk-intent.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/services/service-automation/src/builtin/wait-node-degraded-run.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/services/service-automation/src/run-summary.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/services/service-job/src/db-job-adapter.degraded-outcome.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/services/service-job/src/db-job-adapter.timeout.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/services/service-knowledge/src/__tests__/reap-guard.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/services/service-messaging/src/delivery-headers-at-rest.integration.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/services/service-messaging/src/notification-schema-conformance.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/services/service-queue/src/db-queue-adapter.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/services/service-queue/src/job-queue-retention.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/services/service-settings/src/settings-secret-rotation.test.ts", + "verb": "update", + "pinned": 2 + }, + { + "file": "packages/services/service-settings/src/sys-secret-orphan-report.test.ts", + "verb": "update", + "pinned": 1 + }, + { + "file": "packages/services/service-storage/src/lax-deviation-reclamation-gate.test.ts", + "verb": "update", + "pinned": 2 + }, + { + "file": "packages/services/service-storage/src/metadata-store.test.ts", + "verb": "delete", + "pinned": 1 + }, + { + "file": "packages/services/service-storage/src/storage-routes.metadata-outage.test.ts", + "verb": "delete", + "pinned": 1 + } + ] +} From 0c98edf9c596145a3f1ffc83fee467dd995f1eae Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 19 Aug 2026 07:30:45 +0000 Subject: [PATCH 2/2] docs(gate): re-measure the pinned-set churn over the full commit population MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The shipped comment justified this ratchet with "the 269 commits on `main` in the month to 2026-08-18 ... changed in 7 commits (2.6%) ... zero left". 269 was the depth of the shallow clone the measuring agent ran in, not the month's traffic (#9878). A denominator swap would not have been honest: the numerator was computed over the same 269 visible commits, so `7/3,110` would have replaced one unverified number with another inside the comment whose whole job is to justify a merge-blocking gate. Re-measured instead, over the full population. Method (stated in the comment so it can be redone): membership is proxied by `assertEngine…Dispatch(` call sites in test files under the scan roots, calibrated against this gate's own ledger at HEAD — 0 false negatives on the file sets, 309 of 310 (file, verb) rows agreeing on the exact count. Over 3,103 first-parent commits (2026-07-18..2026-08-18): delete changed in 111 commits (3.6%) 162 entered 1 left update changed in 103 commits (3.3%) 160 entered 1 left The rate is HIGHER than the sample reported, which is the direction swapping only the denominator would have hidden. The single departure per verb is one commit, f16e54e1d, that DELETED a test file and added a replacement carrying both pins in the same commit — repo-wide coverage never dropped. Zero instances of the shape this ratchet catches (file present, verb gone), and zero per-file counts that shrank without reaching zero. Also corrects "308 entries today" to 310 in the same paragraph, which the merge's ledger regeneration moved. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01XqDQYVU5smx29ts9pAErja --- scripts/check-engine-double-contract.mjs | 45 +++++++++++++++++++----- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/scripts/check-engine-double-contract.mjs b/scripts/check-engine-double-contract.mjs index fee679d5a9..e3d573e777 100644 --- a/scripts/check-engine-double-contract.mjs +++ b/scripts/check-engine-double-contract.mjs @@ -177,14 +177,43 @@ // ratchet itself. // // The maintenance objection to an enumeration is real but was measured and is -// small. Over the 269 commits on `main` in the month to 2026-08-18, membership -// of the pinned set changed in 7 commits (2.6%): 8 files entered per verb, and -// **zero left**. So the nuisance case an identity ledger is accused of -- a -// correct change reddened by a legitimate decrease -- fired 0 times in a month, -// while the additions it does redden on are already in conversation with this -// gate (they are new fakes that had to write `assert…Dispatch` because PINNED -// demanded it). 308 entries today against the 135 the DEBT ledger already -// carries: same file format, same order of magnitude, same reconciliation shape. +// small. Measured over the FULL population: 3,103 first-parent commits on +// `main` in the month to 2026-08-18 (`git log --first-parent +// --since=2026-07-18 --until=2026-08-18 origin/main`). Membership of the pinned +// set changed in 111 of them for `delete` (3.6%) and 103 for `update` (3.3%); +// 162 and 160 files ENTERED, and exactly ONE left per verb. +// +// ⛔ An earlier revision of this comment read "the 269 commits ... changed in 7 +// commits (2.6%) ... zero left". 269 was the depth of the shallow clone the +// measuring agent ran in, not the month's traffic, and the 7 and the "zero" +// were themselves computed over only those 269 commits -- so every number in +// the sentence, numerator included, described a ~9% sample. It is re-measured +// here rather than rescaled: the true rate is HIGHER than the sample reported, +// which is the direction that swapping only the denominator would have hidden. +// +// The single departure per verb is the case worth stating precisely, because it +// is the nuisance an identity ledger is accused of and it did not behave like +// one: f16e54e1d deleted `protocol-delete-object-package-binding-guard.test.ts` +// and added a replacement carrying both pins in the SAME commit, so repo-wide +// coverage never dropped. It lands in the "file gone from disk" world below, +// whose remedy is mechanical and carries no judgement call. Across the whole +// month there were ZERO instances of the shape this ratchet exists to catch -- +// file present, verb gone -- and zero per-file counts that shrank without +// reaching zero. +// +// Method, stated so this can be redone rather than trusted: membership is +// proxied by `assertEngine…Dispatch(` call sites in test files under the scan +// roots, calibrated against this gate's own ledger at HEAD -- 0 false negatives +// on the file sets, and 309 of 310 (file, verb) rows agreeing on the exact +// count. Anyone re-running it must first prove their clone actually covers the +// window; a shallow one silently answers for its own depth, which is the whole +// reason this paragraph had to be rewritten. +// +// So the additions the ratchet does redden on are already in conversation with +// this gate (they are new fakes that had to write `assert…Dispatch` because +// PINNED demanded it). 310 entries today against the 135 the DEBT ledger +// already carries: same file format, same order of magnitude, same +// reconciliation shape. // // ## How a LEGITIMATE decrease is expressed (the anti-nuisance half) //