@@ -937,9 +937,12 @@ const EXEMPT = {
937937// So it took the #5286 sibling route (`tsconfig.test.json` named by the
938938// `typecheck` script), which puts the same 10 files in front of tsc while
939939// leaving `tsconfig.json` -- the only config that gate reads -- untouched. The
940- // general lesson, which is this ledger's to carry: the two remedies are
940+ // general lesson, which is this ledger's to carry: the two edits were
941941// interchangeable only where the excluded tests import nothing the src layer
942- // does not, and that is a property to MEASURE per package, never to assume.
942+ // does not, and that was a property to MEASURE per package, never to assume.
943+ // ⛔ Nobody has to weigh them any more -- the exclusion edit is no longer an
944+ // offered route (#18953); the sibling config is the whole prescription, and
945+ // this paragraph is the record of why, not a second option.
943946//
944947// `@objectstack/rest` GRADUATED from this ledger (#12542; entry: 155 raw,
945948// re-measured 37 raw across 13 files under the sibling program). It is worth a
@@ -987,10 +990,13 @@ const EXEMPT = {
987990// an exclusion go red the way trigger-record-change did, 4 stay green
988991// (`objectql`, `lint`, `formula`, `verify`), and the 19th (`cli`) has no
989992// exclusion to drop at all -- its tests are hidden by an `include` that never
990- // reaches them. So that package was the majority case, not the exception, and
991- // the graduation message no longer offers the exclusion route without its
992- // precondition. Re-measure before relying on the split: it moves with every
993- // import a test file gains.
993+ // reaches them. So that package was the majority case, not the exception --
994+ // and that is the measurement the graduation message was withdrawn on: it no
995+ // longer offers the exclusion route AT ALL (maintainer ruling of 2026-09-18 on
996+ // #18953), once the gate that decided the precondition had itself been retired
997+ // (#18373). ⛔ The 14/4 split above is kept here as a READING, never as a route
998+ // to pick from: it was taken at e47d5ef61, it moves with every import a test
999+ // file gains, and nothing measures it any more.
9941000//
9951001// ── #14062: three plugin entries GRADUATED, and what replaced them ───────────
9961002//
@@ -1094,14 +1100,16 @@ const EXEMPT = {
10941100// what WOULD happen, not about an existing dead pin, exactly as `cli`'s
10951101// graduation recorded for its own 115 files.
10961102//
1097- // ⚠️ ROUTE (b) WAS AVAILABLE HERE and was still not taken. The #11491 note
1098- // above names `verify` as one of the 4 entries whose exclusion could be dropped
1099- // with `check:type-source-resolution` staying green, and that split was
1100- // re-measured on 2026-09-04 under a trap-restored mutation and still holds for
1101- // this package (exit 0; 124 programs across 78 packages). It was declined on
1102- // module semantics: `tsconfig.json` inherits NodeNext from the repo root and
1103- // would hold the test layer to a resolver vitest never runs it under. Onboard
1104- // by WIRING, not by widening the build config.
1103+ // ⚠️ DROPPING THE EXCLUSION WAS AVAILABLE HERE and was still not taken. The
1104+ // #11491 note above names `verify` as one of the 4 entries whose exclusion
1105+ // could be dropped with `check:type-source-resolution` staying green, and that
1106+ // split was re-measured on 2026-09-04 under a trap-restored mutation and still
1107+ // held for this package (exit 0; 124 programs across 78 packages). It was
1108+ // declined on module semantics: `tsconfig.json` inherits NodeNext from the repo
1109+ // root and would hold the test layer to a resolver vitest never runs it under.
1110+ // Onboard by WIRING, not by widening the build config -- which is now the only
1111+ // route the graduation message prescribes at all (#18953), so this record is
1112+ // history and ⛔ not a second option anybody still has to weigh.
11051113const TEST_DEBT = {
11061114// ── #14710: `@objectstack/cli` GRADUATED, and it was not paid down ─────────
11071115//
@@ -4482,11 +4490,32 @@ function ratchetRemedyCarriesAuthority(message) {
44824490//
44834491// So the fix is not more words. It is the branch: `m.ledger` is already on
44844492// every measurement, and each ledger's remedy prints only where it is the
4485- // remedy. Neither is dropped -- both are still offered, in the branch that
4486- // owns them. Within TEST_DEBT there IS a real choice of route, so that one
4487- // keeps both and names the PRECONDITION plus the command that decides it: a
4488- // message the reader has to open a gate's source to act on has not fixed
4489- // anything.
4493+ // remedy. Neither LEDGER is dropped -- each still gets the remedy that is its
4494+ // own, in the branch that owns it.
4495+ //
4496+ // ── Within TEST_DEBT the exclusion route came OUT (#18953) ──────────────────
4497+ //
4498+ // TEST_DEBT used to print a SECOND route beside the sibling config: drop the
4499+ // `**/*.test.ts` entry from `exclude` (or widen `include` to reach the test
4500+ // tree). Whether that route was available for a given package was decided by
4501+ // `check:type-source-resolution` -- and that gate was RETIRED under the
4502+ // maintainer ruling of 2026-09-18 on #18373, leaving an official route whose
4503+ // precondition nothing measured any more. What it had measured is the second
4504+ // bullet above: RED for 14 of the 18 entries that had an exclusion to drop. A
4505+ // remedy that is wrong 14 times out of 18, with nothing left to say so, is not
4506+ // a remedy, so the maintainer ruling of 2026-09-18 on #18953 (decision batch
4507+ // #159 item 4, letter ②, maintainer verbatim 「同意」) withdrew it: the printed
4508+ // prescription names (a) alone, and the docs that restated the route drop it
4509+ // with the same edit.
4510+ //
4511+ // ⛔ The other way out was REJECTED in that same ruling, so the way back in is
4512+ // closed from both sides: having THIS gate measure the precondition itself
4513+ // rebuilds half of a gate the maintainer had just retired. An author who
4514+ // widens `include` to the test tree anyway does so on their own judgement --
4515+ // ⛔ not on this gate's advice, which now says nothing about that edit in
4516+ // either direction. The self-test pins the withdrawal as ANTI-content, the way
4517+ // every other branch here is pinned, because the state a well-meaning re-merge
4518+ // returns to is the one that printed both.
44904519//
44914520// ⛔ This changes no verdict and no number. Graduation candidates were, and
44924521// remain, a NOTE -- never a failure.
@@ -4511,16 +4540,9 @@ function graduationRemedy({ ledger, isRoot = false }) {
45114540 `Onboard it: put the hidden test files in front of tsc, and delete the TEST_DEBT entry in the same ` +
45124541 `PR. ⛔ Adding a \`typecheck\` script is NOT the remedy here -- this ledger is "src checks, tests ` +
45134542 `are hidden", so the package already has one.\n` +
4514- ` (a) The #5286 sibling route: add a \`tsconfig.test.json\` that reaches the ` +
4515- `tests and NAME it in the \`typecheck\` script. Always available -- it leaves \`tsconfig.json\` alone.\n` +
4516- ` (b) Drop the \`**/*.test.ts\` entry from \`exclude\` in \`tsconfig.json\` (or widen \`include\` to ` +
4517- `reach the test tree). ⛔ The gate that DECIDED whether this route was available, ` +
4518- `\`check:type-source-resolution\`, was RETIRED under the maintainer ruling of 2026-09-18 on #18373 ` +
4519- `-- so nothing measures it for you any more, and ⛔ its silence is not a clearance. What it measured ` +
4520- `has not changed: the re-admitted tests import workspace packages this package's src program never ` +
4521- `held, its registry was ⛔ SHRINK-ONLY so registering the new ones was never the way out, and it read ` +
4522- `red on 14 of the 18 entries that have an exclusion to drop. Treat (b) as the worse route and prefer ` +
4523- `(a), which leaves \`tsconfig.json\` alone; nothing in this gate's own verdict will tell you.`
4543+ ` (a) The #5286 sibling route, and the ONLY route this gate prescribes: add a ` +
4544+ `\`tsconfig.test.json\` that reaches the tests and NAME it in the \`typecheck\` script. Always ` +
4545+ `available -- it leaves \`tsconfig.json\` alone.`
45244546 ) ;
45254547 }
45264548 if ( ledger === 'DEBT' ) {
@@ -6405,15 +6427,17 @@ function selfTest() {
64056427 + 'that remedy is a no-op on every one of them -- the misfire #11491 was filed on.' ,
64066428 } ,
64076429 {
6408- label : 'TEST_DEBT graduation still carries what the retired gate measured about the exclusion route' ,
6430+ label : 'TEST_DEBT graduation prescribes the sibling config ALONE -- the exclusion route is withdrawn ' ,
64096431 message : testDebtGrad ,
6410- present : [ 'check:type-source-resolution' , 'SHRINK-ONLY' , 'tsconfig.test.json' ] ,
6411- absent : [ ] ,
6412- why : 'the exclusion route read red on 14 of the 18 entries that have an exclusion, and this gate '
6413- + 'never ran it. A message the author has to read a second gate\'s SOURCE to act on is the half '
6414- + 'of #11491 that a correct-but-terse rewrite would leave unfixed -- and once that gate was '
6415- + 'retired (2026-09-18, #18373) the measurement is the ONLY thing left warning the author, so '
6416- + 'these needles stay exactly as they were.' ,
6432+ present : [ 'tsconfig.test.json' , 'the ONLY route this gate prescribes' ] ,
6433+ absent : [ 'exclude' , 'widen' , 'check:type-source-resolution' , 'SHRINK-ONLY' ] ,
6434+ why : 'the exclusion route read red on 14 of the 18 entries that had an exclusion, and the gate that '
6435+ + 'decided the precondition per package was retired (2026-09-18, #18373), so nothing measured it. '
6436+ + 'The maintainer ruling of 2026-09-18 on #18953 withdrew the route rather than leave an official '
6437+ + 'path that is wrong 14 times out of 18: the remedy names (a) alone. These are ANTI-content '
6438+ + 'needles on purpose -- a presence-only assertion would sit green through exactly the '
6439+ + 're-merge that hands the route back, and the retired gate\'s NAME is only one of the spellings '
6440+ + 'it could come back under, which is why `exclude` and `widen` are named beside it.' ,
64176441 } ,
64186442 {
64196443 label : 'the workspace root graduates through `typecheck:root`, never through `typecheck`' ,
@@ -6428,9 +6452,12 @@ function selfTest() {
64286452 label : 'an unrecognised ledger inherits NEITHER remedy' ,
64296453 message : gradNote ( { ledger : 'FUTURE_DEBT' } ) ,
64306454 present : [ 'FUTURE_DEBT' ] ,
6431- absent : [ ADD_SCRIPT , 'drop the test exclusion' , 'check:type-source-resolution ' ] ,
6455+ absent : [ ADD_SCRIPT , 'drop the test exclusion' , 'tsconfig.test.json ' ] ,
64326456 why : 'a third ledger silently receiving DEBT\'s advice is how this message was wrong for TEST_DEBT '
6433- + 'for its whole life. Saying less is the only safe default.' ,
6457+ + 'for its whole life. Saying less is the only safe default. ⚠️ The TEST_DEBT needle here is '
6458+ + '`tsconfig.test.json` and NOT the retired gate\'s name: that name left the message when #18953 '
6459+ + 'withdrew the exclusion route, and an anti-content needle naming a string no branch can emit '
6460+ + 'proves nothing about inheritance.' ,
64346461 } ,
64356462 ] ;
64366463 for ( const c of gradCases ) {
0 commit comments