From 1a383fa387debd0357f06023e9d0dfcf93297480 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 23 Aug 2026 23:02:33 +0000 Subject: [PATCH] build(trigger-record-change): graduate the package out of the TEST_DEBT ledger MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `check:type-check-debt --re-measure` reported TEST_DEBT 9 against a measured 0 for `@objectstack/trigger-record-change`. The 0 re-derived on current main (7f30b6be) and holds, so this is a graduation rather than a ceiling lowering. The gate's graduation message offers two remedies as interchangeable. Neither description fitted this package, and both halves were measured before choosing: * "add a `typecheck` script" — it already had one (`tsc --noEmit`). The hole was TESTS_COVERED (src checks, tests hidden by `**/*.test.ts` in the build tsconfig), not COVERED. * "drop the test exclusion" — resolves exactly the 10-file program the ledger scored at 0 (`tsc --showConfig`) and leaves `dist/` byte-identical, but the 7 re-admitted tests import @objectstack/driver-sql, /formula, /objectql and /service-automation, which the build config's program never held: `check:type-source-resolution` goes exit 0 -> exit 1 naming all four, against a shrink-only registry whose own message rules that widening the entry is not the fix. So it takes the sibling-config route the repo already uses for `packages/spec`, `client`, `metadata-core` and `metadata-fs`: a `tsconfig.test.json` named by the `typecheck` script, putting the same 10 files in front of tsc while the build config — the only one that gate reads — is untouched. The ledger entry is deleted in the same commit, as the gate's structural half requires. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_015ahemw8RcTgqtxrj15PEZx --- .../trigger-record-change/package.json | 2 +- .../trigger-record-change/tsconfig.test.json | 74 +++++++++++++++++++ scripts/check-type-check-coverage.mjs | 23 +++++- 3 files changed, 97 insertions(+), 2 deletions(-) create mode 100644 packages/triggers/trigger-record-change/tsconfig.test.json diff --git a/packages/triggers/trigger-record-change/package.json b/packages/triggers/trigger-record-change/package.json index 322c07e48b..be43c02531 100644 --- a/packages/triggers/trigger-record-change/package.json +++ b/packages/triggers/trigger-record-change/package.json @@ -15,7 +15,7 @@ "scripts": { "build": "tsup --config ../../../tsup.config.ts", "test": "vitest run --passWithNoTests", - "typecheck": "tsc --noEmit" + "typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.test.json" }, "dependencies": { "@objectstack/core": "workspace:*", diff --git a/packages/triggers/trigger-record-change/tsconfig.test.json b/packages/triggers/trigger-record-change/tsconfig.test.json new file mode 100644 index 0000000000..30978f284e --- /dev/null +++ b/packages/triggers/trigger-record-change/tsconfig.test.json @@ -0,0 +1,74 @@ +// The TEST-layer type-check program (the #5286 mechanism `packages/spec` set and +// PR #5546 / PR #5478 carried to `packages/client`, `packages/metadata-core` and +// `packages/metadata-fs`). `tsconfig.json` beside this one stays exactly as it +// is: it is the BUILD config, and `package.json`'s `typecheck` script NAMES this +// sibling (`tsc --noEmit -p tsconfig.test.json`), because a config no script +// invokes reads as coverage and delivers none. +// +// WHY THE SIBLING AND NOT THE ONE-LINE REMEDY. The type-check-debt gate offers +// two remedies for a hidden test layer -- add a `typecheck` script, or drop the +// `**/*.test.ts` exclusion from `tsconfig.json` -- and presents them as +// interchangeable. For this package NEITHER description fits and the second one +// is a red `main`, both measured before this file was written: +// +// - The `typecheck` script was ALREADY here (`tsc --noEmit`) and always had +// been. This package was never in the "src does not check" hole; it was in +// the "src checks, tests are hidden" one, which is the other ledger. +// - Dropping the exclusion resolves a 10-file program (3 src + 7 tests, `tsc +// --showConfig`) that is byte-for-byte the file set the ledger's re-measure +// scored at 0, and the tsup build is unaffected (entry is `src/index.ts` +// alone, so `dist/` comes out identical and no test file reaches it). It +// still fails: those 7 tests import `@objectstack/driver-sql`, +// `@objectstack/formula`, `@objectstack/objectql` and +// `@objectstack/service-automation`, none of which the BUILD config's +// program has ever contained, so `pnpm check:type-source-resolution` goes +// from exit 0 to exit 1 -- "NEW dist-resolved type import(s) since this +// entry was measured" -- against a registry that is SHRINK-ONLY and whose +// own message rules that widening the entry is not the fix. That gate reads +// each package's `tsconfig.json` and only that one, so the excluded region +// put back HERE leaves its population unchanged. +// +// The remediation it actually asks for -- `paths` rules pointing those four +// dependencies at their source -- is a separate card by that gate's own ruling +// ("Remediation is per-package and lands as its own card, because the switch is +// not free"), and this file does not pre-empt it. +// +// What differs from the build config, and what deliberately does NOT: +// - `exclude` drops `**/*.test.ts` and nothing else. That single subtraction +// IS the hole; `include` already names `src/**/*` and all 7 test files live +// under it, so there is nothing to widen and no glob that could bill this +// layer for a non-test file. +// - `noEmit` is asserted rather than left to the CLI flag, so an editor's TS +// server reading this config cannot emit into `dist/`. +// - MODULE SEMANTICS ARE UNTOUCHED, unlike the `packages/spec` and +// `packages/client` siblings. Those switched to `esnext`/`bundler` because +// the inherited NodeNext compiled their ESM tests as CJS and reported +// errors about the CHECK (TS2835, TS1470, TS2550). Nothing to fix here: +// these tests use no `import.meta` and no extensionless cross-package +// relative imports, and the whole layer compiles at 0 under the inherited +// settings. Matching the program the ledger's 0 was measured over is the +// point -- a different `module` would be a different measurement. +// - `rootDir` IS UNTOUCHED, also unlike those siblings. It stays `./src` +// because every test file is already under it: the re-measure reported +// TS6059 x0, so there is no misconfiguration diagnostic to neutralise and +// widening would only loosen which files may enter the program. +// - STRICTNESS IS UNTOUCHED. `strict`, `noUnusedLocals`, `noUnusedParameters`, +// `noImplicitReturns` and the rest are inherited from the root config. +// Nothing here may loosen a type rule; if a test does not compile, that is +// the finding. +// +// There is NO `test-typecheck-debt.json` beside this config, on purpose -- the +// same call `packages/metadata-core` and `packages/metadata-fs` made. The whole +// test layer compiles at ZERO errors, so a per-file shrink-only ledger would +// hold nothing while costing this package a `tsx` dependency and two more +// scripts. A bare `tsc --noEmit -p tsconfig.test.json` is the strictly stronger +// gate at zero residue: ANY error here is red immediately, with no ledger to be +// added to. +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "noEmit": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/scripts/check-type-check-coverage.mjs b/scripts/check-type-check-coverage.mjs index 7a7b505737..c1ef843d5e 100644 --- a/scripts/check-type-check-coverage.mjs +++ b/scripts/check-type-check-coverage.mjs @@ -706,6 +706,28 @@ const EXEMPT = { // `@objectstack/cli` (146 raw across 65 files, after #8612 repaired the first // two of its 59 missing import extensions) is deliberately NOT part of that // graduation -- it is a programme rather than a sitting, and its entry stands. +// +// `@objectstack/trigger-record-change` GRADUATED from this ledger (entry: 9 raw +// TS2353, re-measured 0). It is worth a line here because BOTH remedies the +// graduation message above offers were wrong for it, and that message is what +// the next taker will read: +// - "add a `typecheck` script" -- it already had one, and always had. The +// package was never in DEBT's hole ("src does not check"); it was in this +// ledger's ("src checks, tests are hidden"), which is why the message's +// first branch has nothing to do. +// - "drop the test exclusion" -- MEASURED as a red `main`. It resolves +// exactly the 10-file program this ledger's re-measure scored at 0 and +// leaves `dist/` byte-identical (tsup builds `src/index.ts` alone), but the +// 7 tests it re-admits import four workspace packages the BUILD config's +// program never contained, and `check:type-source-resolution` goes 0 -> 1 +// naming them, against a registry that is shrink-only and whose own message +// rules that widening the entry is not the fix. +// So it took the #5286 sibling route (`tsconfig.test.json` named by the +// `typecheck` script), which puts the same 10 files in front of tsc while +// leaving `tsconfig.json` -- the only config that gate reads -- untouched. The +// general lesson, which is this ledger's to carry: the two remedies are +// interchangeable only where the excluded tests import nothing the src layer +// does not, and that is a property to MEASURE per package, never to assume. const TEST_DEBT = { '@objectstack/plugin-approvals': { errors: 348, @@ -952,7 +974,6 @@ const TEST_DEBT = { }, '@objectstack/plugin-security': { errors: 11, note: 'TS2739 x8, TS2740 x5, TS2345/TS2322/TS2741 x2 each -- incomplete literals. Re-measured 21 at 5ab08428, up from 20, and still 21 at e8db1a230 after the package gained a test file -- the file count moved, the error count did not (which is why the file count is derived here rather than written down, #5826).' }, '@objectstack/formula': { errors: 17, note: 'TS2591 x6 (`process`), TS2345 x3, TS2352 x3, TS1470 x2, TS2339 x2. Re-measured 17 at 5ab08428, up from 12; the TS2591 half doubled, which is the missing `types:["node"]` again rather than five new defects.' }, - '@objectstack/trigger-record-change': { errors: 9, note: 'TS2353 x9 -- still the one unknown-property shape repeated, now in four files. Re-measured 9 at 5ab08428, up from 8.' }, '@objectstack/verify': { errors: 8, note: 'TS2835 x4, TS7006 x4. Re-measured 8 at 5ab08428, up from 6; both classes are the NodeNext pair from the top-of-ledger note.' }, '@objectstack/connector-mcp': { errors: 5, note: 'TS2339 x5. Re-measured 5 at 5ab08428, exact.' }, '@objectstack/connector-openapi': { errors: 5, note: 'TS2339 x5. Re-measured 5 at 5ab08428, exact.' },