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
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';
229243const ROOT = fileURLToPath ( new URL ( '..' , import . meta. url ) ) ;
230244const 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 */
252279const 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 */
882923const 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+
16921803function 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