From 52a5a14e72cff8036fbc3d8980c8b4bd7ab2b16c Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 6 Sep 2026 11:48:44 +0000 Subject: [PATCH 1/2] chore(typecheck): sibling test programs + script wiring for seven ledgered packages WIP: the tsconfig.test.json files and the package.json wiring. Ledgers, the TEST_DEBT graduations and the config headers follow in the next commits. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01Vbw3RPgdtqesx4azk9SbW8 --- packages/connectors/connector-mcp/package.json | 4 +++- packages/connectors/connector-mcp/tsconfig.test.json | 11 +++++++++++ packages/connectors/connector-openapi/package.json | 4 +++- .../connectors/connector-openapi/tsconfig.test.json | 11 +++++++++++ packages/connectors/connector-rest/package.json | 4 +++- packages/connectors/connector-rest/tsconfig.test.json | 11 +++++++++++ packages/formula/package.json | 4 +++- packages/formula/tsconfig.test.json | 11 +++++++++++ packages/mcp/package.json | 4 +++- packages/mcp/tsconfig.test.json | 9 +++++++++ packages/platform-objects/package.json | 4 +++- packages/platform-objects/tsconfig.test.json | 11 +++++++++++ packages/services/service-sms/package.json | 4 +++- packages/services/service-sms/tsconfig.test.json | 11 +++++++++++ 14 files changed, 96 insertions(+), 7 deletions(-) create mode 100644 packages/connectors/connector-mcp/tsconfig.test.json create mode 100644 packages/connectors/connector-openapi/tsconfig.test.json create mode 100644 packages/connectors/connector-rest/tsconfig.test.json create mode 100644 packages/formula/tsconfig.test.json create mode 100644 packages/mcp/tsconfig.test.json create mode 100644 packages/platform-objects/tsconfig.test.json create mode 100644 packages/services/service-sms/tsconfig.test.json diff --git a/packages/connectors/connector-mcp/package.json b/packages/connectors/connector-mcp/package.json index 0aa6fada47..cf1034ce8b 100644 --- a/packages/connectors/connector-mcp/package.json +++ b/packages/connectors/connector-mcp/package.json @@ -14,8 +14,10 @@ }, "scripts": { "build": "tsup --config ../../../tsup.config.ts && node ../../../scripts/check-dts-emitted.mjs", + "check:test-typecheck": "tsx ../../../scripts/check-test-typecheck.mts --self-test && tsx ../../../scripts/check-test-typecheck.mts --package packages/connectors/connector-mcp --project tsconfig.test.json", + "gen:test-typecheck-debt": "tsx ../../../scripts/check-test-typecheck.mts --update --package packages/connectors/connector-mcp --project tsconfig.test.json", "test": "vitest run --passWithNoTests", - "typecheck": "tsc --noEmit" + "typecheck": "tsc --noEmit && pnpm check:test-typecheck" }, "dependencies": { "@modelcontextprotocol/sdk": "^1.30.0", diff --git a/packages/connectors/connector-mcp/tsconfig.test.json b/packages/connectors/connector-mcp/tsconfig.test.json new file mode 100644 index 0000000000..bb2d41027b --- /dev/null +++ b/packages/connectors/connector-mcp/tsconfig.test.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "noEmit": true, + "module": "esnext", + "moduleResolution": "bundler", + "lib": ["ES2022"] + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/packages/connectors/connector-openapi/package.json b/packages/connectors/connector-openapi/package.json index 2fb927e1a7..7b55de9912 100644 --- a/packages/connectors/connector-openapi/package.json +++ b/packages/connectors/connector-openapi/package.json @@ -14,8 +14,10 @@ }, "scripts": { "build": "tsup --config ../../../tsup.config.ts && node ../../../scripts/check-dts-emitted.mjs", + "check:test-typecheck": "tsx ../../../scripts/check-test-typecheck.mts --self-test && tsx ../../../scripts/check-test-typecheck.mts --package packages/connectors/connector-openapi --project tsconfig.test.json", + "gen:test-typecheck-debt": "tsx ../../../scripts/check-test-typecheck.mts --update --package packages/connectors/connector-openapi --project tsconfig.test.json", "test": "vitest run --passWithNoTests", - "typecheck": "tsc --noEmit" + "typecheck": "tsc --noEmit && pnpm check:test-typecheck" }, "dependencies": { "@objectstack/core": "workspace:*", diff --git a/packages/connectors/connector-openapi/tsconfig.test.json b/packages/connectors/connector-openapi/tsconfig.test.json new file mode 100644 index 0000000000..bb2d41027b --- /dev/null +++ b/packages/connectors/connector-openapi/tsconfig.test.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "noEmit": true, + "module": "esnext", + "moduleResolution": "bundler", + "lib": ["ES2022"] + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/packages/connectors/connector-rest/package.json b/packages/connectors/connector-rest/package.json index 579e448dfc..bb9f311ca1 100644 --- a/packages/connectors/connector-rest/package.json +++ b/packages/connectors/connector-rest/package.json @@ -14,8 +14,10 @@ }, "scripts": { "build": "tsup --config ../../../tsup.config.ts && node ../../../scripts/check-dts-emitted.mjs", + "check:test-typecheck": "tsx ../../../scripts/check-test-typecheck.mts --self-test && tsx ../../../scripts/check-test-typecheck.mts --package packages/connectors/connector-rest --project tsconfig.test.json", + "gen:test-typecheck-debt": "tsx ../../../scripts/check-test-typecheck.mts --update --package packages/connectors/connector-rest --project tsconfig.test.json", "test": "vitest run --passWithNoTests", - "typecheck": "tsc --noEmit" + "typecheck": "tsc --noEmit && pnpm check:test-typecheck" }, "dependencies": { "@objectstack/core": "workspace:*", diff --git a/packages/connectors/connector-rest/tsconfig.test.json b/packages/connectors/connector-rest/tsconfig.test.json new file mode 100644 index 0000000000..bb2d41027b --- /dev/null +++ b/packages/connectors/connector-rest/tsconfig.test.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "noEmit": true, + "module": "esnext", + "moduleResolution": "bundler", + "lib": ["ES2022"] + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/packages/formula/package.json b/packages/formula/package.json index b51f0efeb9..245d12721f 100644 --- a/packages/formula/package.json +++ b/packages/formula/package.json @@ -14,8 +14,10 @@ }, "scripts": { "build": "tsup --config ../../tsup.config.ts && node ../../scripts/check-dts-emitted.mjs", + "check:test-typecheck": "tsx ../../scripts/check-test-typecheck.mts --self-test && tsx ../../scripts/check-test-typecheck.mts --package packages/formula --project tsconfig.test.json", + "gen:test-typecheck-debt": "tsx ../../scripts/check-test-typecheck.mts --update --package packages/formula --project tsconfig.test.json", "test": "vitest run", - "typecheck": "tsc --noEmit" + "typecheck": "tsc --noEmit && pnpm check:test-typecheck" }, "dependencies": { "@marcbachmann/cel-js": "^8.0.0", diff --git a/packages/formula/tsconfig.test.json b/packages/formula/tsconfig.test.json new file mode 100644 index 0000000000..bb2d41027b --- /dev/null +++ b/packages/formula/tsconfig.test.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "noEmit": true, + "module": "esnext", + "moduleResolution": "bundler", + "lib": ["ES2022"] + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/packages/mcp/package.json b/packages/mcp/package.json index e0823a503d..467ba21acf 100644 --- a/packages/mcp/package.json +++ b/packages/mcp/package.json @@ -20,8 +20,10 @@ }, "scripts": { "build": "tsup --config ../../tsup.config.ts && node ../../scripts/check-dts-emitted.mjs", + "check:test-typecheck": "tsx ../../scripts/check-test-typecheck.mts --self-test && tsx ../../scripts/check-test-typecheck.mts --package packages/mcp --project tsconfig.test.json", + "gen:test-typecheck-debt": "tsx ../../scripts/check-test-typecheck.mts --update --package packages/mcp --project tsconfig.test.json", "test": "vitest run", - "typecheck": "tsc --noEmit" + "typecheck": "tsc --noEmit && pnpm check:test-typecheck" }, "dependencies": { "@modelcontextprotocol/sdk": "^1.30.0", diff --git a/packages/mcp/tsconfig.test.json b/packages/mcp/tsconfig.test.json new file mode 100644 index 0000000000..4b7d8fae90 --- /dev/null +++ b/packages/mcp/tsconfig.test.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "noEmit": true, + "lib": ["ES2022"] + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/packages/platform-objects/package.json b/packages/platform-objects/package.json index 57442849b7..4f6830c1eb 100644 --- a/packages/platform-objects/package.json +++ b/packages/platform-objects/package.json @@ -64,8 +64,10 @@ }, "scripts": { "build": "tsup && node ../../scripts/check-dts-emitted.mjs", + "check:test-typecheck": "tsx ../../scripts/check-test-typecheck.mts --self-test && tsx ../../scripts/check-test-typecheck.mts --package packages/platform-objects --project tsconfig.test.json", + "gen:test-typecheck-debt": "tsx ../../scripts/check-test-typecheck.mts --update --package packages/platform-objects --project tsconfig.test.json", "test": "vitest run --passWithNoTests", - "typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.scripts.json" + "typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.scripts.json && pnpm check:test-typecheck" }, "dependencies": { "@objectstack/metadata-core": "workspace:*", diff --git a/packages/platform-objects/tsconfig.test.json b/packages/platform-objects/tsconfig.test.json new file mode 100644 index 0000000000..bb2d41027b --- /dev/null +++ b/packages/platform-objects/tsconfig.test.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "noEmit": true, + "module": "esnext", + "moduleResolution": "bundler", + "lib": ["ES2022"] + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/packages/services/service-sms/package.json b/packages/services/service-sms/package.json index afaea4ba6d..981f2faf4e 100644 --- a/packages/services/service-sms/package.json +++ b/packages/services/service-sms/package.json @@ -14,8 +14,10 @@ }, "scripts": { "build": "tsup --config ../../../tsup.config.ts && node ../../../scripts/check-dts-emitted.mjs", + "check:test-typecheck": "tsx ../../../scripts/check-test-typecheck.mts --self-test && tsx ../../../scripts/check-test-typecheck.mts --package packages/services/service-sms --project tsconfig.test.json", + "gen:test-typecheck-debt": "tsx ../../../scripts/check-test-typecheck.mts --update --package packages/services/service-sms --project tsconfig.test.json", "test": "vitest run --passWithNoTests", - "typecheck": "tsc --noEmit" + "typecheck": "tsc --noEmit && pnpm check:test-typecheck" }, "dependencies": { "@objectstack/core": "workspace:*", diff --git a/packages/services/service-sms/tsconfig.test.json b/packages/services/service-sms/tsconfig.test.json new file mode 100644 index 0000000000..bb2d41027b --- /dev/null +++ b/packages/services/service-sms/tsconfig.test.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "noEmit": true, + "module": "esnext", + "moduleResolution": "bundler", + "lib": ["ES2022"] + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} From e46c29ffca40986097deef3ad464f95601cf0304 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 6 Sep 2026 11:55:30 +0000 Subject: [PATCH 2/2] chore(typecheck): ledgers, TEST_DEBT graduations, merge dispositions and config headers Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01Vbw3RPgdtqesx4azk9SbW8 --- .../connector-mcp/test-typecheck-debt.json | 8 + .../connector-mcp/tsconfig.test.json | 93 ++++++++++++ .../test-typecheck-debt.json | 8 + .../connector-openapi/tsconfig.test.json | 92 ++++++++++++ .../connector-rest/test-typecheck-debt.json | 8 + .../connector-rest/tsconfig.test.json | 93 ++++++++++++ packages/formula/test-typecheck-debt.json | 27 ++++ packages/formula/tsconfig.test.json | 79 ++++++++++ packages/mcp/test-typecheck-debt.json | 25 ++++ packages/mcp/tsconfig.test.json | 93 ++++++++++++ .../platform-objects/test-typecheck-debt.json | 9 ++ packages/platform-objects/tsconfig.test.json | 84 +++++++++++ .../service-sms/test-typecheck-debt.json | 8 + .../services/service-sms/tsconfig.test.json | 92 ++++++++++++ scripts/check-type-check-coverage.mjs | 138 ++++++++++++------ scripts/check-type-source-resolution.mjs | 51 ++++++- scripts/regen-artifacts.mjs | 104 +++++++++++++ 17 files changed, 959 insertions(+), 53 deletions(-) create mode 100644 packages/connectors/connector-mcp/test-typecheck-debt.json create mode 100644 packages/connectors/connector-openapi/test-typecheck-debt.json create mode 100644 packages/connectors/connector-rest/test-typecheck-debt.json create mode 100644 packages/formula/test-typecheck-debt.json create mode 100644 packages/mcp/test-typecheck-debt.json create mode 100644 packages/platform-objects/test-typecheck-debt.json create mode 100644 packages/services/service-sms/test-typecheck-debt.json diff --git a/packages/connectors/connector-mcp/test-typecheck-debt.json b/packages/connectors/connector-mcp/test-typecheck-debt.json new file mode 100644 index 0000000000..8cbe9f6ca5 --- /dev/null +++ b/packages/connectors/connector-mcp/test-typecheck-debt.json @@ -0,0 +1,8 @@ +{ + "_comment": "Per-file tsc error debt of the @objectstack/connector-mcp TEST layer (#5286). `tsconfig.test.json` compiles `src/**/*.test.ts` — which `tsconfig.json` excludes and therefore no gate ever read — and every file below still carries errors from before that gate existed. THIS FIELD IS GENERATED: every regeneration rewrites it from scripts/check-test-typecheck.mts, and the EXACT ratchet below requires a regeneration on every repair — so an edit made here is gone by the next one. Anything true of THIS package goes in the sibling `_note` field, which is authored, is preserved verbatim, and is never written by the generator (#12624). This comment states NO cause for the errors, deliberately: the classes differ per package and per file, they move as the debt is paid down, and a cause written here is rewritten verbatim into every ledger by every regeneration — so it outlives its own repair and cannot be corrected in the file where it is read. Measure instead, before repairing anything: `tsc --noEmit --pretty false -p tsconfig.test.json` in the package prints the real classes with their TS codes. Each entry maps a file to its per-SIGNATURE error counts, never to a bare total (#13470): a signature is the TS code plus the diagnostic message with structural type blobs collapsed, and it carries NO line or column — so the pin survives edits that move code around, and only stops matching when the error itself becomes a different error. EXACT ratchet, judged by re-running tsc: a file that gains errors is red, a file that loses them is red until its number is re-recorded, a file that reaches zero is red until its entry is deleted, a signature that ARRIVES or VANISHES is red even when the file total is unchanged, and a file NOT listed here may have no errors at all. Regenerate with: pnpm --filter @objectstack/connector-mcp gen:test-typecheck-debt", + "entries": { + "src/mcp-provider.test.ts": { + "TS2339: Property 'then' does not exist on type '…'.": 5 + } + } +} diff --git a/packages/connectors/connector-mcp/tsconfig.test.json b/packages/connectors/connector-mcp/tsconfig.test.json index bb2d41027b..69eb391776 100644 --- a/packages/connectors/connector-mcp/tsconfig.test.json +++ b/packages/connectors/connector-mcp/tsconfig.test.json @@ -1,3 +1,96 @@ +// The TEST-layer type-check program (#12511), adopting the mechanism #5286 set +// for `packages/spec` and #5449 generalised. `tsconfig.json` beside this file +// stays exactly as it is: it is the BUILD config, and its `**/*.test.ts` +// exclusion has a reason — ci.yml gates that no test file reaches the published +// artifact. This sibling puts the excluded layer back in front of tsc, and +// `package.json`'s `typecheck` script NAMES it (via `check:test-typecheck +// --project`), because a config no script invokes is exactly the phantom this +// whole mechanism is about. +// +// BEFORE THIS FILE, NO tsc PROGRAM COMPILED A SINGLE TEST FILE HERE, measured +// rather than read off the config. At 6a1e38244 with the workspace closure +// built first, `tsc --noEmit --listFiles -p tsconfig.json` — the only config +// this package's `typecheck` named — puts 349 files in the program, 4 of +// them this package's own `src/**`, and **0** of its 3 `src/**/*.test.ts`. +// So the zero is the `exclude` line and not a probe that sees nothing. Positive +// controls in the SAME run, same binary, same worktree: `packages/rest`'s test +// program 186 test files, `packages/metadata-core`'s 15, +// `packages/drivers/driver-memory`'s build config 44 — without them every zero +// above is unfalsifiable. Under this file the count is **3 of 3** +// (418 files in the program). +// +// What differs from the build config, and what deliberately does NOT: +// - MODULE SEMANTICS. This package is NOT `"type": "module"`, so the +// inherited NodeNext compiles as CommonJS the files vitest executes as ESM. +// Matching vitest is fidelity, not laxity. ⚠️ Measured subtraction on +// today's tree: **zero** — no test file here reaches for `import.meta` or +// writes an extension-less relative import, so on THIS tree the mismatch +// costs nothing. Of the seven packages onboarded by this card only +// `packages/formula` measured a subtraction (TS1470 x2), which is exactly +// why eight mechanical copies of one config would not have been eight +// correct configs. The override is declared anyway, because the alternative +// is that the first test file to use either construct gets a config-tier +// diagnostic ledgered as though it were a defect. ⚠️ `bundler` resolution +// also stops requiring `.js` on this package's own `src` relative imports IN +// THIS PROGRAM; nothing is lost by that, because leg 1 of `typecheck` still +// compiles `src` under the build config's NodeNext and is where that rule is +// enforced. +// - `lib: ["ES2022"]`, for the reason `packages/rest` and `packages/lint` +// state: the root config's `lib` is ES2020 while vitest runs these files on +// a Node with ES2022 builtins, so the gap is reported as TS2550 about the +// CHECK rather than about the code. ⚠️ Measured effect today: **zero** — +// this layer carries no TS2550 either way. Fidelity to the runtime, not +// error reduction, and it is stated that way rather than claimed as a +// subtraction. It is also the exact trap the card that ordered this file was +// filed about: `Object.hasOwn` in a new test is TS2550 against a pre-ES2022 +// lib, and the package's advertised `typecheck` said nothing about it. No +// `DOM`: nothing in this layer touches a browser global. +// - ⛔ STRICTNESS IS UNTOUCHED. `strict`, `noUnusedLocals`, +// `noUnusedParameters`, `noImplicitReturns`, `noFallthroughCasesInSwitch`, +// `types: ["node"]` and `rootDir` are inherited from `tsconfig.json` and +// through it the root config, and none of them is re-declared here. +// `rootDir` (`./src`) needs no widening: every test file here lives under +// `src` and none reaches outside the package, so the TS6059 pile +// `packages/cli`'s sibling had to widen `rootDir` to clear does not arise — +// measured, the raw program carries no TS6059. ⚠️ A child that declared its +// own `paths` would REPLACE the parent map rather than merge into it, +// silently sending a source-resolved specifier back to `dist/`, so this file +// declares none. Nothing here may loosen a type rule; if a test does not +// compile, that is the finding. +// +// MEASURED at 6a1e38244 with the dependency closure built (an error count taken +// against an unbuilt closure is not a reading — unresolved-import cascades +// inflate it): this layer reports **5 errors across 1 file**, which is the same 5 that +// `scripts/check-type-check-coverage.mjs` recorded for this package in its +// per-PACKAGE `TEST_DEBT` ledger, reproduced class for class (TS2339 x5) and +// file for file. That entry GRADUATES in this change rather than being paid +// down: the identical population is now held one level finer, per file and per +// signature, in `test-typecheck-debt.json` beside this config. There is no +// config-tier subtraction here and nothing was exposed behind one, so the +// attribution has no remainder in either direction. +// +// // All 5 sit in `src/mcp-provider.test.ts` and carry ONE signature — +// `Property 'then' does not exist on type 'ConnectorMaterialization | +// Promise'` — so this package and +// `packages/connectors/connector-openapi` measure the identical population +// against the same connector contract. One narrowing at the call site is the +// whole ledger. +// +// Every one of the 5 is PRE-EXISTING: this change edits no test file, and each +// would have been reported on `origin/main` had this program always existed. +// They are ledgered EXACT and shrink-only — a file that gains an error is red, +// one that loses one is red until re-recorded, one that reaches zero is red +// until its entry is deleted, a signature that ARRIVES or VANISHES is red even +// at an unchanged file total, and a file NOT listed there may have no errors at +// all. ⛔ The 5 are NOT repaired here: seeding the ledger is the deliverable, +// and turning an onboarding into a cleanup is how it stops landing at all. +// +// ⚠️ 2 of the 3 files carry NO ledger entry, and that is load-bearing +// rather than incidental: any error any one of them ever gains is red on +// arrival. That is the half of this gate that starts working today. This layer +// also holds ZERO `@ts-expect-error` directives (grepped with a positive control +// — the same grep hits `packages/spec/src`), so no pin here was silently dead; +// what the gap cost was the other half. { "extends": "./tsconfig.json", "compilerOptions": { diff --git a/packages/connectors/connector-openapi/test-typecheck-debt.json b/packages/connectors/connector-openapi/test-typecheck-debt.json new file mode 100644 index 0000000000..78b2aa53d6 --- /dev/null +++ b/packages/connectors/connector-openapi/test-typecheck-debt.json @@ -0,0 +1,8 @@ +{ + "_comment": "Per-file tsc error debt of the @objectstack/connector-openapi TEST layer (#5286). `tsconfig.test.json` compiles `src/**/*.test.ts` — which `tsconfig.json` excludes and therefore no gate ever read — and every file below still carries errors from before that gate existed. THIS FIELD IS GENERATED: every regeneration rewrites it from scripts/check-test-typecheck.mts, and the EXACT ratchet below requires a regeneration on every repair — so an edit made here is gone by the next one. Anything true of THIS package goes in the sibling `_note` field, which is authored, is preserved verbatim, and is never written by the generator (#12624). This comment states NO cause for the errors, deliberately: the classes differ per package and per file, they move as the debt is paid down, and a cause written here is rewritten verbatim into every ledger by every regeneration — so it outlives its own repair and cannot be corrected in the file where it is read. Measure instead, before repairing anything: `tsc --noEmit --pretty false -p tsconfig.test.json` in the package prints the real classes with their TS codes. Each entry maps a file to its per-SIGNATURE error counts, never to a bare total (#13470): a signature is the TS code plus the diagnostic message with structural type blobs collapsed, and it carries NO line or column — so the pin survives edits that move code around, and only stops matching when the error itself becomes a different error. EXACT ratchet, judged by re-running tsc: a file that gains errors is red, a file that loses them is red until its number is re-recorded, a file that reaches zero is red until its entry is deleted, a signature that ARRIVES or VANISHES is red even when the file total is unchanged, and a file NOT listed here may have no errors at all. Regenerate with: pnpm --filter @objectstack/connector-openapi gen:test-typecheck-debt", + "entries": { + "src/openapi-provider.test.ts": { + "TS2339: Property 'then' does not exist on type '…'.": 5 + } + } +} diff --git a/packages/connectors/connector-openapi/tsconfig.test.json b/packages/connectors/connector-openapi/tsconfig.test.json index bb2d41027b..3c57891f81 100644 --- a/packages/connectors/connector-openapi/tsconfig.test.json +++ b/packages/connectors/connector-openapi/tsconfig.test.json @@ -1,3 +1,95 @@ +// The TEST-layer type-check program (#12511), adopting the mechanism #5286 set +// for `packages/spec` and #5449 generalised. `tsconfig.json` beside this file +// stays exactly as it is: it is the BUILD config, and its `**/*.test.ts` +// exclusion has a reason — ci.yml gates that no test file reaches the published +// artifact. This sibling puts the excluded layer back in front of tsc, and +// `package.json`'s `typecheck` script NAMES it (via `check:test-typecheck +// --project`), because a config no script invokes is exactly the phantom this +// whole mechanism is about. +// +// BEFORE THIS FILE, NO tsc PROGRAM COMPILED A SINGLE TEST FILE HERE, measured +// rather than read off the config. At 6a1e38244 with the workspace closure +// built first, `tsc --noEmit --listFiles -p tsconfig.json` — the only config +// this package's `typecheck` named — puts 332 files in the program, 4 of +// them this package's own `src/**`, and **0** of its 4 `src/**/*.test.ts`. +// So the zero is the `exclude` line and not a probe that sees nothing. Positive +// controls in the SAME run, same binary, same worktree: `packages/rest`'s test +// program 186 test files, `packages/metadata-core`'s 15, +// `packages/drivers/driver-memory`'s build config 44 — without them every zero +// above is unfalsifiable. Under this file the count is **4 of 4** +// (402 files in the program). +// +// What differs from the build config, and what deliberately does NOT: +// - MODULE SEMANTICS. This package is NOT `"type": "module"`, so the +// inherited NodeNext compiles as CommonJS the files vitest executes as ESM. +// Matching vitest is fidelity, not laxity. ⚠️ Measured subtraction on +// today's tree: **zero** — no test file here reaches for `import.meta` or +// writes an extension-less relative import, so on THIS tree the mismatch +// costs nothing. Of the seven packages onboarded by this card only +// `packages/formula` measured a subtraction (TS1470 x2), which is exactly +// why eight mechanical copies of one config would not have been eight +// correct configs. The override is declared anyway, because the alternative +// is that the first test file to use either construct gets a config-tier +// diagnostic ledgered as though it were a defect. ⚠️ `bundler` resolution +// also stops requiring `.js` on this package's own `src` relative imports IN +// THIS PROGRAM; nothing is lost by that, because leg 1 of `typecheck` still +// compiles `src` under the build config's NodeNext and is where that rule is +// enforced. +// - `lib: ["ES2022"]`, for the reason `packages/rest` and `packages/lint` +// state: the root config's `lib` is ES2020 while vitest runs these files on +// a Node with ES2022 builtins, so the gap is reported as TS2550 about the +// CHECK rather than about the code. ⚠️ Measured effect today: **zero** — +// this layer carries no TS2550 either way. Fidelity to the runtime, not +// error reduction, and it is stated that way rather than claimed as a +// subtraction. It is also the exact trap the card that ordered this file was +// filed about: `Object.hasOwn` in a new test is TS2550 against a pre-ES2022 +// lib, and the package's advertised `typecheck` said nothing about it. No +// `DOM`: nothing in this layer touches a browser global. +// - ⛔ STRICTNESS IS UNTOUCHED. `strict`, `noUnusedLocals`, +// `noUnusedParameters`, `noImplicitReturns`, `noFallthroughCasesInSwitch`, +// `types: ["node"]` and `rootDir` are inherited from `tsconfig.json` and +// through it the root config, and none of them is re-declared here. +// `rootDir` (`./src`) needs no widening: every test file here lives under +// `src` and none reaches outside the package, so the TS6059 pile +// `packages/cli`'s sibling had to widen `rootDir` to clear does not arise — +// measured, the raw program carries no TS6059. ⚠️ A child that declared its +// own `paths` would REPLACE the parent map rather than merge into it, +// silently sending a source-resolved specifier back to `dist/`, so this file +// declares none. Nothing here may loosen a type rule; if a test does not +// compile, that is the finding. +// +// MEASURED at 6a1e38244 with the dependency closure built (an error count taken +// against an unbuilt closure is not a reading — unresolved-import cascades +// inflate it): this layer reports **5 errors across 1 file**, which is the same 5 that +// `scripts/check-type-check-coverage.mjs` recorded for this package in its +// per-PACKAGE `TEST_DEBT` ledger, reproduced class for class (TS2339 x5) and +// file for file. That entry GRADUATES in this change rather than being paid +// down: the identical population is now held one level finer, per file and per +// signature, in `test-typecheck-debt.json` beside this config. There is no +// config-tier subtraction here and nothing was exposed behind one, so the +// attribution has no remainder in either direction. +// +// // All 5 sit in `src/openapi-provider.test.ts` and carry ONE signature — +// `Property 'then' does not exist on type 'ConnectorMaterialization | +// Promise'` — the identical population +// `packages/connectors/connector-mcp` measures against the same connector +// contract. One narrowing at the call site is the whole ledger. +// +// Every one of the 5 is PRE-EXISTING: this change edits no test file, and each +// would have been reported on `origin/main` had this program always existed. +// They are ledgered EXACT and shrink-only — a file that gains an error is red, +// one that loses one is red until re-recorded, one that reaches zero is red +// until its entry is deleted, a signature that ARRIVES or VANISHES is red even +// at an unchanged file total, and a file NOT listed there may have no errors at +// all. ⛔ The 5 are NOT repaired here: seeding the ledger is the deliverable, +// and turning an onboarding into a cleanup is how it stops landing at all. +// +// ⚠️ 3 of the 4 files carry NO ledger entry, and that is load-bearing +// rather than incidental: any error any one of them ever gains is red on +// arrival. That is the half of this gate that starts working today. This layer +// also holds ZERO `@ts-expect-error` directives (grepped with a positive control +// — the same grep hits `packages/spec/src`), so no pin here was silently dead; +// what the gap cost was the other half. { "extends": "./tsconfig.json", "compilerOptions": { diff --git a/packages/connectors/connector-rest/test-typecheck-debt.json b/packages/connectors/connector-rest/test-typecheck-debt.json new file mode 100644 index 0000000000..ca6ac14cca --- /dev/null +++ b/packages/connectors/connector-rest/test-typecheck-debt.json @@ -0,0 +1,8 @@ +{ + "_comment": "Per-file tsc error debt of the @objectstack/connector-rest TEST layer (#5286). `tsconfig.test.json` compiles `src/**/*.test.ts` — which `tsconfig.json` excludes and therefore no gate ever read — and every file below still carries errors from before that gate existed. THIS FIELD IS GENERATED: every regeneration rewrites it from scripts/check-test-typecheck.mts, and the EXACT ratchet below requires a regeneration on every repair — so an edit made here is gone by the next one. Anything true of THIS package goes in the sibling `_note` field, which is authored, is preserved verbatim, and is never written by the generator (#12624). This comment states NO cause for the errors, deliberately: the classes differ per package and per file, they move as the debt is paid down, and a cause written here is rewritten verbatim into every ledger by every regeneration — so it outlives its own repair and cannot be corrected in the file where it is read. Measure instead, before repairing anything: `tsc --noEmit --pretty false -p tsconfig.test.json` in the package prints the real classes with their TS codes. Each entry maps a file to its per-SIGNATURE error counts, never to a bare total (#13470): a signature is the TS code plus the diagnostic message with structural type blobs collapsed, and it carries NO line or column — so the pin survives edits that move code around, and only stops matching when the error itself becomes a different error. EXACT ratchet, judged by re-running tsc: a file that gains errors is red, a file that loses them is red until its number is re-recorded, a file that reaches zero is red until its entry is deleted, a signature that ARRIVES or VANISHES is red even when the file total is unchanged, and a file NOT listed here may have no errors at all. Regenerate with: pnpm --filter @objectstack/connector-rest gen:test-typecheck-debt", + "entries": { + "src/rest-connector.test.ts": { + "TS6133: 'vi' is declared but its value is never read.": 1 + } + } +} diff --git a/packages/connectors/connector-rest/tsconfig.test.json b/packages/connectors/connector-rest/tsconfig.test.json index bb2d41027b..10df97b88b 100644 --- a/packages/connectors/connector-rest/tsconfig.test.json +++ b/packages/connectors/connector-rest/tsconfig.test.json @@ -1,3 +1,96 @@ +// The TEST-layer type-check program (#12511), adopting the mechanism #5286 set +// for `packages/spec` and #5449 generalised. `tsconfig.json` beside this file +// stays exactly as it is: it is the BUILD config, and its `**/*.test.ts` +// exclusion has a reason — ci.yml gates that no test file reaches the published +// artifact. This sibling puts the excluded layer back in front of tsc, and +// `package.json`'s `typecheck` script NAMES it (via `check:test-typecheck +// --project`), because a config no script invokes is exactly the phantom this +// whole mechanism is about. +// +// BEFORE THIS FILE, NO tsc PROGRAM COMPILED A SINGLE TEST FILE HERE, measured +// rather than read off the config. At 6a1e38244 with the workspace closure +// built first, `tsc --noEmit --listFiles -p tsconfig.json` — the only config +// this package's `typecheck` named — puts 340 files in the program, 4 of +// them this package's own `src/**`, and **0** of its 4 `src/**/*.test.ts`. +// So the zero is the `exclude` line and not a probe that sees nothing. Positive +// controls in the SAME run, same binary, same worktree: `packages/rest`'s test +// program 186 test files, `packages/metadata-core`'s 15, +// `packages/drivers/driver-memory`'s build config 44 — without them every zero +// above is unfalsifiable. Under this file the count is **4 of 4** +// (405 files in the program). +// +// What differs from the build config, and what deliberately does NOT: +// - MODULE SEMANTICS. This package is NOT `"type": "module"`, so the +// inherited NodeNext compiles as CommonJS the files vitest executes as ESM. +// Matching vitest is fidelity, not laxity. ⚠️ Measured subtraction on +// today's tree: **zero** — no test file here reaches for `import.meta` or +// writes an extension-less relative import, so on THIS tree the mismatch +// costs nothing. Of the seven packages onboarded by this card only +// `packages/formula` measured a subtraction (TS1470 x2), which is exactly +// why eight mechanical copies of one config would not have been eight +// correct configs. The override is declared anyway, because the alternative +// is that the first test file to use either construct gets a config-tier +// diagnostic ledgered as though it were a defect. ⚠️ `bundler` resolution +// also stops requiring `.js` on this package's own `src` relative imports IN +// THIS PROGRAM; nothing is lost by that, because leg 1 of `typecheck` still +// compiles `src` under the build config's NodeNext and is where that rule is +// enforced. +// - `lib: ["ES2022"]`, for the reason `packages/rest` and `packages/lint` +// state: the root config's `lib` is ES2020 while vitest runs these files on +// a Node with ES2022 builtins, so the gap is reported as TS2550 about the +// CHECK rather than about the code. ⚠️ Measured effect today: **zero** — +// this layer carries no TS2550 either way. Fidelity to the runtime, not +// error reduction, and it is stated that way rather than claimed as a +// subtraction. It is also the exact trap the card that ordered this file was +// filed about: `Object.hasOwn` in a new test is TS2550 against a pre-ES2022 +// lib, and the package's advertised `typecheck` said nothing about it. No +// `DOM`: nothing in this layer touches a browser global. +// - ⛔ STRICTNESS IS UNTOUCHED. `strict`, `noUnusedLocals`, +// `noUnusedParameters`, `noImplicitReturns`, `noFallthroughCasesInSwitch`, +// `types: ["node"]` and `rootDir` are inherited from `tsconfig.json` and +// through it the root config, and none of them is re-declared here. +// `rootDir` (`./src`) needs no widening: every test file here lives under +// `src` and none reaches outside the package, so the TS6059 pile +// `packages/cli`'s sibling had to widen `rootDir` to clear does not arise — +// measured, the raw program carries no TS6059. ⚠️ A child that declared its +// own `paths` would REPLACE the parent map rather than merge into it, +// silently sending a source-resolved specifier back to `dist/`, so this file +// declares none. Nothing here may loosen a type rule; if a test does not +// compile, that is the finding. +// +// MEASURED at 6a1e38244 with the dependency closure built (an error count taken +// against an unbuilt closure is not a reading — unresolved-import cascades +// inflate it): this layer reports **1 error across 1 file**, which is the same 1 that +// `scripts/check-type-check-coverage.mjs` recorded for this package in its +// per-PACKAGE `TEST_DEBT` ledger, reproduced class for class (TS6133 x1) and +// file for file. That entry GRADUATES in this change rather than being paid +// down: the identical population is now held one level finer, per file and per +// signature, in `test-typecheck-debt.json` beside this config. There is no +// config-tier subtraction here and nothing was exposed behind one, so the +// attribution has no remainder in either direction. +// +// // The single error is `'vi' is declared but its value is never read` in +// `src/rest-connector.test.ts`. ⚠️ A one-entry ledger is the MOST exposed to a +// bad regeneration, not the least: a recomputation that writes zero deletes the +// whole record, and an empty ledger reads as a package that graduated. That is +// why this file has a merge disposition of its own in +// `scripts/regen-artifacts.mjs` rather than sharing one. +// +// Every one of the 1 is PRE-EXISTING: this change edits no test file, and each +// would have been reported on `origin/main` had this program always existed. +// They are ledgered EXACT and shrink-only — a file that gains an error is red, +// one that loses one is red until re-recorded, one that reaches zero is red +// until its entry is deleted, a signature that ARRIVES or VANISHES is red even +// at an unchanged file total, and a file NOT listed there may have no errors at +// all. ⛔ The 1 are NOT repaired here: seeding the ledger is the deliverable, +// and turning an onboarding into a cleanup is how it stops landing at all. +// +// ⚠️ 3 of the 4 files carry NO ledger entry, and that is load-bearing +// rather than incidental: any error any one of them ever gains is red on +// arrival. That is the half of this gate that starts working today. This layer +// also holds ZERO `@ts-expect-error` directives (grepped with a positive control +// — the same grep hits `packages/spec/src`), so no pin here was silently dead; +// what the gap cost was the other half. { "extends": "./tsconfig.json", "compilerOptions": { diff --git a/packages/formula/test-typecheck-debt.json b/packages/formula/test-typecheck-debt.json new file mode 100644 index 0000000000..4ae4c5e935 --- /dev/null +++ b/packages/formula/test-typecheck-debt.json @@ -0,0 +1,27 @@ +{ + "_comment": "Per-file tsc error debt of the @objectstack/formula TEST layer (#5286). `tsconfig.test.json` compiles `src/**/*.test.ts` — which `tsconfig.json` excludes and therefore no gate ever read — and every file below still carries errors from before that gate existed. THIS FIELD IS GENERATED: every regeneration rewrites it from scripts/check-test-typecheck.mts, and the EXACT ratchet below requires a regeneration on every repair — so an edit made here is gone by the next one. Anything true of THIS package goes in the sibling `_note` field, which is authored, is preserved verbatim, and is never written by the generator (#12624). This comment states NO cause for the errors, deliberately: the classes differ per package and per file, they move as the debt is paid down, and a cause written here is rewritten verbatim into every ledger by every regeneration — so it outlives its own repair and cannot be corrected in the file where it is read. Measure instead, before repairing anything: `tsc --noEmit --pretty false -p tsconfig.test.json` in the package prints the real classes with their TS codes. Each entry maps a file to its per-SIGNATURE error counts, never to a bare total (#13470): a signature is the TS code plus the diagnostic message with structural type blobs collapsed, and it carries NO line or column — so the pin survives edits that move code around, and only stops matching when the error itself becomes a different error. EXACT ratchet, judged by re-running tsc: a file that gains errors is red, a file that loses them is red until its number is re-recorded, a file that reaches zero is red until its entry is deleted, a signature that ARRIVES or VANISHES is red even when the file total is unchanged, and a file NOT listed here may have no errors at all. Regenerate with: pnpm --filter @objectstack/formula gen:test-typecheck-debt", + "entries": { + "src/cel-to-filter.test.ts": { + "TS2739: Type '…' is missing the following properties from type '…': id, organization_id, team_member_ids, department": 1 + }, + "src/matches-filter-temporal-conformance.test.ts": { + "TS2345: Argument of type 'TemporalRow' is not assignable to parameter of type '…'.": 2, + "TS2345: Argument of type 'TemporalTimeRow' is not assignable to parameter of type '…'.": 1 + }, + "src/normalize.test.ts": { + "TS2352: Conversion of type '…' to type '…' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.": 3 + }, + "src/rls-predicate.test.ts": { + "TS2339: Property 'url' does not exist on type 'ImportMeta'.": 1, + "TS2591: Cannot find name 'node:fs'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node` and then add 'node' to the types field in your tsconfig.": 1, + "TS2591: Cannot find name 'node:path'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node` and then add 'node' to the types field in your tsconfig.": 1, + "TS2591: Cannot find name 'node:url'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node` and then add 'node' to the types field in your tsconfig.": 1 + }, + "src/skill-catalog-sync.test.ts": { + "TS2339: Property 'url' does not exist on type 'ImportMeta'.": 1, + "TS2591: Cannot find name 'node:fs'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node` and then add 'node' to the types field in your tsconfig.": 1, + "TS2591: Cannot find name 'node:path'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node` and then add 'node' to the types field in your tsconfig.": 1, + "TS2591: Cannot find name 'node:url'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node` and then add 'node' to the types field in your tsconfig.": 1 + } + } +} diff --git a/packages/formula/tsconfig.test.json b/packages/formula/tsconfig.test.json index bb2d41027b..55dcec61a1 100644 --- a/packages/formula/tsconfig.test.json +++ b/packages/formula/tsconfig.test.json @@ -1,3 +1,82 @@ +// The TEST-layer type-check program (#12511), adopting the mechanism #5286 set +// for `packages/spec` and #5449 generalised. `tsconfig.json` beside this file +// stays exactly as it is: it is the BUILD config, and its `**/*.test.ts` +// exclusion has a reason — ci.yml gates that no test file reaches the published +// artifact. This sibling puts the excluded layer back in front of tsc, and +// `package.json`'s `typecheck` script NAMES it (via `check:test-typecheck +// --project`), because a config no script invokes is exactly the phantom this +// whole mechanism is about. +// +// BEFORE THIS FILE, NO tsc PROGRAM COMPILED A SINGLE TEST FILE HERE, measured +// rather than read off the config. At 6a1e38244 with the workspace closure +// built first, `tsc --noEmit --listFiles -p tsconfig.json` — the only config +// this package's `typecheck` named — puts 181 files in the program, 15 of them +// this package's own `src/**`, and **0** of its 29 `src/**/*.test.ts`. Positive +// controls in the SAME run: `packages/rest`'s test program 186 test files, +// `packages/metadata-core`'s 15, `packages/drivers/driver-memory`'s build +// config 44. Under this file the count is **29 of 29** (271 files in program). +// +// What differs from the build config, and what deliberately does NOT: +// - MODULE SEMANTICS, and this is the ONE package of the seven onboarded with +// this card where the change subtracts a measured error pile. This package +// is NOT `"type": "module"`, so the inherited NodeNext compiles as CommonJS +// the files vitest executes as ESM, and two of them use `import.meta.url` to +// locate fixtures. Measured cost of that mismatch: TS1470 x2 ("the +// `import.meta` meta-property is not allowed in files which will build into +// CommonJS output", `src/rls-predicate.test.ts` and +// `src/skill-catalog-sync.test.ts`). Those 2 are about the CHECK, never +// about the code, and they are the whole of the 17 -> 15 step below. +// Matching vitest is fidelity, not laxity. +// ⚠️ `bundler` resolution also stops requiring `.js` on this package's own +// `src` relative imports IN THIS PROGRAM — nothing is lost by that, because +// leg 1 of `typecheck` still compiles `src` under the build config's +// NodeNext and is where that rule is enforced. +// - `lib: ["ES2022"]`, for the reason `packages/rest` and `packages/lint` +// state: the root config's `lib` is ES2020 while vitest runs on a Node with +// ES2022 builtins, so the gap is reported as TS2550 about the CHECK. +// ⚠️ Measured effect on today's tree: **zero** — this layer carries no +// TS2550 either way. Fidelity to the runtime, not error reduction, and it is +// stated that way rather than claimed as a subtraction. No `DOM`: nothing in +// this layer touches a browser global. +// - ⛔ STRICTNESS IS UNTOUCHED. `strict`, `noUnusedLocals`, +// `noUnusedParameters`, `noImplicitReturns`, `noFallthroughCasesInSwitch` +// and `rootDir` are inherited from `tsconfig.json` and through it the root +// config. `rootDir` needs no widening: every test file here lives under +// `src` and none reaches outside the package. ⚠️ A child declaring its own +// `paths` would REPLACE the parent map rather than merge into it, so this +// file declares none. Nothing here may loosen a type rule; if a test does +// not compile, that is the finding. +// +// MEASURED at 6a1e38244 with the dependency closure built: the raw program +// (build semantics, test glob dropped) reports **17**, reproducing the 17 that +// `scripts/check-type-check-coverage.mjs` recorded in its per-PACKAGE +// `TEST_DEBT` ledger; under this config it reports **15 errors across 5 files**. +// The -2 is the TS1470 pair above, and NOTHING was exposed behind it — there was +// no unresolved-import cascade to collapse, so the attribution has no remainder +// in either direction. +// +// ⚠️ A COMPOSITION CORRECTION the deleted ledger entry earned: it attributed its +// TS2591 x6 to «`process`». Measured here, all six are node builtins named as +// bare module specifiers — `node:fs` x2, `node:path` x2, `node:url` x2, in those +// same two files — and the TS2339 x2 beside them read `Property 'url' does not +// exist on type 'ImportMeta'`. Both classes SURVIVE this move, and both have one +// cause: this package declares no `@types/node` and its tsconfig names no +// `types`, so the node typings never reach its program. That is real debt with a +// real repair. ⛔ It is deliberately NOT repaired here — seeding the ledger is +// the deliverable, and turning an onboarding into a cleanup is how it stops +// landing at all. +// +// Every one of the 15 is PRE-EXISTING: this change edits no test file, and each +// would have been reported on `origin/main` had this program always existed. +// They are ledgered per file and per signature in `test-typecheck-debt.json` +// beside this config, EXACT and shrink-only — a file that gains an error is red, +// one that loses one is red until re-recorded, one that reaches zero is red +// until its entry is deleted, a signature that ARRIVES or VANISHES is red even +// at an unchanged file total, and a file NOT listed there may have no errors at +// all. 24 of the 29 files carry no entry, so any error any of them gains is red +// on arrival. This layer holds ZERO `@ts-expect-error` directives (grepped with +// a positive control — the same grep hits `packages/spec/src`), so no pin here +// was silently dead. { "extends": "./tsconfig.json", "compilerOptions": { diff --git a/packages/mcp/test-typecheck-debt.json b/packages/mcp/test-typecheck-debt.json new file mode 100644 index 0000000000..bdd2da260d --- /dev/null +++ b/packages/mcp/test-typecheck-debt.json @@ -0,0 +1,25 @@ +{ + "_comment": "Per-file tsc error debt of the @objectstack/mcp TEST layer (#5286). `tsconfig.test.json` compiles `src/**/*.test.ts` — which `tsconfig.json` excludes and therefore no gate ever read — and every file below still carries errors from before that gate existed. THIS FIELD IS GENERATED: every regeneration rewrites it from scripts/check-test-typecheck.mts, and the EXACT ratchet below requires a regeneration on every repair — so an edit made here is gone by the next one. Anything true of THIS package goes in the sibling `_note` field, which is authored, is preserved verbatim, and is never written by the generator (#12624). This comment states NO cause for the errors, deliberately: the classes differ per package and per file, they move as the debt is paid down, and a cause written here is rewritten verbatim into every ledger by every regeneration — so it outlives its own repair and cannot be corrected in the file where it is read. Measure instead, before repairing anything: `tsc --noEmit --pretty false -p tsconfig.test.json` in the package prints the real classes with their TS codes. Each entry maps a file to its per-SIGNATURE error counts, never to a bare total (#13470): a signature is the TS code plus the diagnostic message with structural type blobs collapsed, and it carries NO line or column — so the pin survives edits that move code around, and only stops matching when the error itself becomes a different error. EXACT ratchet, judged by re-running tsc: a file that gains errors is red, a file that loses them is red until its number is re-recorded, a file that reaches zero is red until its entry is deleted, a signature that ARRIVES or VANISHES is red even when the file total is unchanged, and a file NOT listed here may have no errors at all. Regenerate with: pnpm --filter @objectstack/mcp gen:test-typecheck-debt", + "entries": { + "src/__tests__/mcp-server-runtime.test.ts": { + "TS6133: 'MCPServerRuntimeConfig' is declared but its value is never read.": 1 + }, + "src/mcp-action-tools.test.ts": { + "TS18046: 'json' is of type 'unknown'.": 14 + }, + "src/mcp-http-tools.scopes.test.ts": { + "TS18046: 'json' is of type 'unknown'.": 8 + }, + "src/mcp-server-runtime.http.test.ts": { + "TS18046: 'json' is of type 'unknown'.": 21, + "TS18046: 'withAgg.json' is of type 'unknown'.": 1, + "TS18046: 'without.json' is of type 'unknown'.": 1 + }, + "src/mcp-validate-expression.test.ts": { + "TS18046: 'json' is of type 'unknown'.": 6 + }, + "src/skill-prompts.test.ts": { + "TS2352: Conversion of type 'SkillPrompt | null' to type '…' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.": 1 + } + } +} diff --git a/packages/mcp/tsconfig.test.json b/packages/mcp/tsconfig.test.json index 4b7d8fae90..d4f332be68 100644 --- a/packages/mcp/tsconfig.test.json +++ b/packages/mcp/tsconfig.test.json @@ -1,3 +1,96 @@ +// The TEST-layer type-check program (#12511), adopting the mechanism #5286 set +// for `packages/spec` and #5449 generalised, and which 31 sibling configs now +// use. `tsconfig.json` beside this file stays exactly as it is: it is the BUILD +// config, and its `**/*.test.ts` exclusion has a reason — ci.yml gates that no +// test file reaches the published artifact. This sibling puts the excluded +// layer back in front of tsc, and `package.json`'s `typecheck` script NAMES it +// (via `check:test-typecheck --project`), because a config no script invokes is +// exactly the phantom this whole mechanism is about. +// +// BEFORE THIS FILE, NO tsc PROGRAM COMPILED A SINGLE TEST FILE HERE, and that +// is measured rather than read off the config. At 6a1e38244 with the workspace +// closure built first, `tsc --noEmit --listFiles -p tsconfig.json` — the ONLY +// config this package's `typecheck` named — puts 412 files in the program, 11 +// of them this package's own `src/**`, and **0** of its 26 `src/**/*.test.ts`. +// So the zero is the `exclude` line and not a probe that sees nothing. Positive +// controls in the SAME run, same binary, same worktree: `packages/rest`'s test +// program 186 test files, `packages/metadata-core`'s 15, +// `packages/drivers/driver-memory`'s build config 44 — without them every zero +// above is unfalsifiable. Under this file the count is **26 of 26** (553 files +// in the program). +// +// ⚠️ MODULE SEMANTICS ARE UNTOUCHED HERE, unlike `packages/rest`'s sibling and +// most of the family — and that is this package's own judgement, not an +// omission. `@objectstack/mcp` IS `"type": "module"`, so the build config's +// inherited NodeNext already reads these files as ESM; it is also the STRICTER +// of the two readings, since it holds the `.js` import extensions this package +// must ship, which `bundler` resolution would let a missing extension compile +// past and fail at run time under Node. Measured rather than assumed: this +// layer writes **zero** extension-less relative imports, and switching to +// `esnext`/`bundler` subtracts nothing from the 53 below. `metadata-core`'s +// sibling is the precedent for this shape; `rest`'s is not. +// +// - `lib: ["ES2022"]` IS declared, and it is the one departure. The root +// config's `lib` is ES2020 while vitest runs these files on a Node with +// ES2022 builtins, so the gap is reported as TS2550 about the CHECK rather +// than about the code. ⚠️ Measured effect on today's tree: **zero** — this +// layer carries no TS2550 either way. It is fidelity to the runtime, not +// error reduction, and it is stated that way on purpose. It is also the +// exact trap the card that ordered this file was filed about: a dev wrote +// `Object.hasOwn` in a new test, which against a pre-ES2022 lib is TS2550, +// and the package's advertised `typecheck` said nothing while a full-closure +// build was the only thing that could see it. +// - `rootDir` is INHERITED (`./src`) and needs no widening, which is worth +// recording because `packages/cli`'s sibling had to widen its own. This +// package's tests all live under `src`. The one import that escapes the +// package —`src/canonical-expression-envelopes.test.ts` reaching +// `../../../scripts/js-comment-mask.mjs` — lands on a checked-in +// `js-comment-mask.d.mts`, so it resolves as a declaration file and reports +// no TS6059. Measured, not reasoned: the raw program carries no TS6059. +// - ⛔ STRICTNESS IS UNTOUCHED. `strict`, `noUnusedLocals`, +// `noUnusedParameters`, `noImplicitReturns`, `noFallthroughCasesInSwitch` +// and `types: ["node"]` are inherited from `tsconfig.json` and through it +// the root config, and none is re-declared here. ⚠️ A child declaring its +// own `paths` would REPLACE the parent map rather than merge into it, so +// this file declares none. Nothing here may loosen a type rule; if a test +// does not compile, that is the finding. +// +// MEASURED at 6a1e38244 with the dependency closure built (an error count taken +// against an unbuilt closure is not a reading — unresolved-import cascades +// inflate it): this layer reports **53 errors across 6 files**, which is the +// same 53 `scripts/check-type-check-coverage.mjs` recorded for this package in +// its per-PACKAGE `TEST_DEBT` ledger, reproduced class for class (TS18046 x51, +// TS2352 x1, TS6133 x1) and file for file. That entry GRADUATES in this change +// rather than being paid down: the identical population is now held one level +// finer, per file and per signature, in `test-typecheck-debt.json` beside this +// config. 51 of the 53 are one idiom — `await res.json()` bound without a +// narrowing — across four suites, so one helper there is very nearly the whole +// ledger. +// +// Every one of the 53 is PRE-EXISTING: this change edits no test file, and each +// would have been reported on `origin/main` had this program always existed. +// They are ledgered EXACT and shrink-only — a file that gains an error is red, +// one that loses one is red until re-recorded, one that reaches zero is red +// until its entry is deleted, a signature that ARRIVES or VANISHES is red even +// at an unchanged file total, and a file NOT listed there may have no errors at +// all. ⛔ The 53 are NOT repaired here: seeding the ledger is the deliverable, +// and turning an onboarding into a cleanup is how it stops landing at all. +// +// ⚠️ 20 of the 26 files carry NO ledger entry, and that is load-bearing rather +// than incidental: any error any one of them ever gains is red on arrival. That +// is the half of this gate that starts working today. This layer also holds +// ZERO `@ts-expect-error` directives (grepped with a positive control — the +// same grep hits `packages/spec/src`), so no pin here was silently dead; what +// the gap cost was the other half. +// +// ⚠️ ONE DISAGREEMENT THIS FILE DOES NOT CLOSE, declared so it is not read as an +// oversight: `vitest.config.ts` aliases `@objectstack/metadata-core` and +// `@objectstack/lint` to those packages' SOURCE, while this program resolves +// their TYPES through `dist/`. `paths` is the obvious repair and is measured to +// be the wrong one for an ONBOARDING program (PR #12570 billed other packages' +// source diagnostics into the onboarding package's ledger), so the exposure is +// declared in `scripts/check-type-source-resolution.mjs`'s shrink-only registry +// instead, where it stays visible. That file's #12511 doc-block has the numbers. { "extends": "./tsconfig.json", "compilerOptions": { diff --git a/packages/platform-objects/test-typecheck-debt.json b/packages/platform-objects/test-typecheck-debt.json new file mode 100644 index 0000000000..55b8b5525a --- /dev/null +++ b/packages/platform-objects/test-typecheck-debt.json @@ -0,0 +1,9 @@ +{ + "_comment": "Per-file tsc error debt of the @objectstack/platform-objects TEST layer (#5286). `tsconfig.test.json` compiles `src/**/*.test.ts` — which `tsconfig.json` excludes and therefore no gate ever read — and every file below still carries errors from before that gate existed. THIS FIELD IS GENERATED: every regeneration rewrites it from scripts/check-test-typecheck.mts, and the EXACT ratchet below requires a regeneration on every repair — so an edit made here is gone by the next one. Anything true of THIS package goes in the sibling `_note` field, which is authored, is preserved verbatim, and is never written by the generator (#12624). This comment states NO cause for the errors, deliberately: the classes differ per package and per file, they move as the debt is paid down, and a cause written here is rewritten verbatim into every ledger by every regeneration — so it outlives its own repair and cannot be corrected in the file where it is read. Measure instead, before repairing anything: `tsc --noEmit --pretty false -p tsconfig.test.json` in the package prints the real classes with their TS codes. Each entry maps a file to its per-SIGNATURE error counts, never to a bare total (#13470): a signature is the TS code plus the diagnostic message with structural type blobs collapsed, and it carries NO line or column — so the pin survives edits that move code around, and only stops matching when the error itself becomes a different error. EXACT ratchet, judged by re-running tsc: a file that gains errors is red, a file that loses them is red until its number is re-recorded, a file that reaches zero is red until its entry is deleted, a signature that ARRIVES or VANISHES is red even when the file total is unchanged, and a file NOT listed here may have no errors at all. Regenerate with: pnpm --filter @objectstack/platform-objects gen:test-typecheck-debt", + "entries": { + "src/feature-gate-guard.test.ts": { + "TS2339: Property 'gatedInputs' does not exist on type '…'.": 2, + "TS7006: Parameter 'path' implicitly has an 'any' type.": 1 + } + } +} diff --git a/packages/platform-objects/tsconfig.test.json b/packages/platform-objects/tsconfig.test.json index bb2d41027b..fef104cdd1 100644 --- a/packages/platform-objects/tsconfig.test.json +++ b/packages/platform-objects/tsconfig.test.json @@ -1,3 +1,87 @@ +// The TEST-layer type-check program (#12511), adopting the mechanism #5286 set +// for `packages/spec` and #5449 generalised. `tsconfig.json` beside this file +// stays exactly as it is: it is the BUILD config, and its `**/*.test.ts` +// exclusion has a reason — ci.yml gates that no test file reaches the published +// artifact. This sibling puts the excluded layer back in front of tsc, and +// `package.json`'s `typecheck` script NAMES it (via `check:test-typecheck +// --project`), as a THIRD leg beside the existing `tsconfig.scripts.json` one, +// because a config no script invokes is exactly the phantom this mechanism is +// about. +// +// ⚠️ THIS PACKAGE IS THE CARD'S OWN LIVE EXEMPLAR, and its two-config shape is +// the reason: `typecheck` already ran TWO programs (`tsconfig.json` and +// `tsconfig.scripts.json`), and a reader who checked only whether a sibling +// `tsconfig.*.json` existed would have scored the package repaired. It was not. +// Measured at 6a1e38244 with the workspace closure built first, both named +// programs put **0** of this package's 35 `src/**/*.test.ts` files in the +// program — `tsconfig.json` 419 files / 91 own `src` / 0 tests, +// `tsconfig.scripts.json` 371 / 72 / 0 (its `include` is `scripts/**/*`). +// Positive controls in the SAME run, same binary, same worktree: +// `packages/rest`'s test program 186 test files, `packages/metadata-core`'s 15, +// `packages/drivers/driver-memory`'s build config 44 — without them every zero +// above is unfalsifiable. Under this file the count is **35 of 35** (579 files +// in the program). +// +// What differs from the build config, and what deliberately does NOT: +// - MODULE SEMANTICS. This package is NOT `"type": "module"`, so the +// inherited NodeNext compiles as CommonJS what vitest executes as ESM. +// Matching vitest is fidelity, not laxity. ⚠️ Measured subtraction on +// today's tree: **zero** — unlike `packages/formula`, no test file here +// reaches for `import.meta` or writes an extension-less relative import, so +// the mismatch costs nothing TODAY. It is declared anyway because the +// alternative is that the first test file to use either gets a config-tier +// diagnostic ledgered as if it were a defect, which is the exact confusion +// this mechanism's header spends its length on. ⚠️ `bundler` resolution also +// stops requiring `.js` on this package's own `src` relative imports in this +// program; nothing is lost, because leg 1 still compiles `src` under +// NodeNext and is where that rule is enforced. +// - `lib: ["ES2022"]`: the root config's `lib` is ES2020 while vitest runs on +// a Node with ES2022 builtins, so the gap reports as TS2550 about the CHECK. +// Measured effect today: **zero**. Fidelity, not error reduction. +// - ⛔ STRICTNESS IS UNTOUCHED. `strict`, `noUnusedLocals`, +// `noUnusedParameters`, `noImplicitReturns`, `noFallthroughCasesInSwitch`, +// `types: ["node"]` and `rootDir` are inherited and none is re-declared. +// `rootDir` (`./src`) needs no widening even though +// `src/pages/canonical-expression-envelopes.test.ts` imports +// `../../../../scripts/js-comment-mask.mjs`: that path lands on a checked-in +// `js-comment-mask.d.mts`, so it resolves as a declaration file and the raw +// program carries no TS6059. Measured, not reasoned. ⚠️ A child declaring +// its own `paths` would REPLACE the parent map rather than merge into it, so +// this file declares none. +// +// MEASURED at 6a1e38244 with the dependency closure built (an error count taken +// against an unbuilt closure is not a reading): this layer reports **3 errors +// across 1 file** (`src/feature-gate-guard.test.ts` — TS2339 x2, TS7006 x1), +// which is the same 3 `scripts/check-type-check-coverage.mjs` recorded in its +// per-PACKAGE `TEST_DEBT` ledger, class for class and file for file. That entry +// GRADUATES in this change rather than being paid down. +// +// ⭐ THE READING THAT PUT THIS PACKAGE ON THE CARD is not in the 3. PR #15874 +// hit a real TS2339 on `Intl.supportedValuesOf` here and had to build a scratch +// tsconfig to see it, because the effective `lib` was `lib.es2020.d.ts` and no +// program this package's `typecheck` invoked read the file at all. Both halves +// of that are closed above: the tests are in a program, and the program's `lib` +// is the one vitest actually provides. +// +// Every one of the 3 is PRE-EXISTING: this change edits no test file, and each +// would have been reported on `origin/main` had this program always existed. +// They are ledgered per file and per signature in `test-typecheck-debt.json` +// beside this config, EXACT and shrink-only — a file that gains an error is red, +// one that loses one is red until re-recorded, one that reaches zero is red +// until its entry is deleted, a signature that ARRIVES or VANISHES is red even +// at an unchanged file total, and a file NOT listed there may have no errors at +// all. ⛔ The 3 are NOT repaired here. 34 of the 35 files carry no entry, so any +// error any of them gains is red on arrival — that is the half of this gate that +// starts working today. This layer holds ZERO `@ts-expect-error` directives +// (grepped with a positive control — the same grep hits `packages/spec/src`). +// +// ⚠️ ONE DISAGREEMENT THIS FILE DOES NOT CLOSE, declared so it is not read as an +// oversight: `vitest.config.ts` aliases `@objectstack/lint` to that package's +// SOURCE, while this program resolves its TYPES through `dist/`. `paths` is +// measured to be the wrong repair for an ONBOARDING program (PR #12570 billed +// other packages' source diagnostics into the onboarding package's ledger), so +// the exposure is declared in `scripts/check-type-source-resolution.mjs`'s +// shrink-only registry instead. That file's #12511 doc-block has the numbers. { "extends": "./tsconfig.json", "compilerOptions": { diff --git a/packages/services/service-sms/test-typecheck-debt.json b/packages/services/service-sms/test-typecheck-debt.json new file mode 100644 index 0000000000..c3776cbf5a --- /dev/null +++ b/packages/services/service-sms/test-typecheck-debt.json @@ -0,0 +1,8 @@ +{ + "_comment": "Per-file tsc error debt of the @objectstack/service-sms TEST layer (#5286). `tsconfig.test.json` compiles `src/**/*.test.ts` — which `tsconfig.json` excludes and therefore no gate ever read — and every file below still carries errors from before that gate existed. THIS FIELD IS GENERATED: every regeneration rewrites it from scripts/check-test-typecheck.mts, and the EXACT ratchet below requires a regeneration on every repair — so an edit made here is gone by the next one. Anything true of THIS package goes in the sibling `_note` field, which is authored, is preserved verbatim, and is never written by the generator (#12624). This comment states NO cause for the errors, deliberately: the classes differ per package and per file, they move as the debt is paid down, and a cause written here is rewritten verbatim into every ledger by every regeneration — so it outlives its own repair and cannot be corrected in the file where it is read. Measure instead, before repairing anything: `tsc --noEmit --pretty false -p tsconfig.test.json` in the package prints the real classes with their TS codes. Each entry maps a file to its per-SIGNATURE error counts, never to a bare total (#13470): a signature is the TS code plus the diagnostic message with structural type blobs collapsed, and it carries NO line or column — so the pin survives edits that move code around, and only stops matching when the error itself becomes a different error. EXACT ratchet, judged by re-running tsc: a file that gains errors is red, a file that loses them is red until its number is re-recorded, a file that reaches zero is red until its entry is deleted, a signature that ARRIVES or VANISHES is red even when the file total is unchanged, and a file NOT listed here may have no errors at all. Regenerate with: pnpm --filter @objectstack/service-sms gen:test-typecheck-debt", + "entries": { + "src/transports/transports.test.ts": { + "TS2493: Tuple type '…' of length '0' has no element at index '0'.": 1 + } + } +} diff --git a/packages/services/service-sms/tsconfig.test.json b/packages/services/service-sms/tsconfig.test.json index bb2d41027b..ad86c01385 100644 --- a/packages/services/service-sms/tsconfig.test.json +++ b/packages/services/service-sms/tsconfig.test.json @@ -1,3 +1,95 @@ +// The TEST-layer type-check program (#12511), adopting the mechanism #5286 set +// for `packages/spec` and #5449 generalised. `tsconfig.json` beside this file +// stays exactly as it is: it is the BUILD config, and its `**/*.test.ts` +// exclusion has a reason — ci.yml gates that no test file reaches the published +// artifact. This sibling puts the excluded layer back in front of tsc, and +// `package.json`'s `typecheck` script NAMES it (via `check:test-typecheck +// --project`), because a config no script invokes is exactly the phantom this +// whole mechanism is about. +// +// BEFORE THIS FILE, NO tsc PROGRAM COMPILED A SINGLE TEST FILE HERE, measured +// rather than read off the config. At 6a1e38244 with the workspace closure +// built first, `tsc --noEmit --listFiles -p tsconfig.json` — the only config +// this package's `typecheck` named — puts 751 files in the program, 7 of +// them this package's own `src/**`, and **0** of its 5 `src/**/*.test.ts`. +// So the zero is the `exclude` line and not a probe that sees nothing. Positive +// controls in the SAME run, same binary, same worktree: `packages/rest`'s test +// program 186 test files, `packages/metadata-core`'s 15, +// `packages/drivers/driver-memory`'s build config 44 — without them every zero +// above is unfalsifiable. Under this file the count is **5 of 5** +// (792 files in the program). +// +// What differs from the build config, and what deliberately does NOT: +// - MODULE SEMANTICS. This package is NOT `"type": "module"`, so the +// inherited NodeNext compiles as CommonJS the files vitest executes as ESM. +// Matching vitest is fidelity, not laxity. ⚠️ Measured subtraction on +// today's tree: **zero** — no test file here reaches for `import.meta` or +// writes an extension-less relative import, so on THIS tree the mismatch +// costs nothing. Of the seven packages onboarded by this card only +// `packages/formula` measured a subtraction (TS1470 x2), which is exactly +// why eight mechanical copies of one config would not have been eight +// correct configs. The override is declared anyway, because the alternative +// is that the first test file to use either construct gets a config-tier +// diagnostic ledgered as though it were a defect. ⚠️ `bundler` resolution +// also stops requiring `.js` on this package's own `src` relative imports IN +// THIS PROGRAM; nothing is lost by that, because leg 1 of `typecheck` still +// compiles `src` under the build config's NodeNext and is where that rule is +// enforced. +// - `lib: ["ES2022"]`, for the reason `packages/rest` and `packages/lint` +// state: the root config's `lib` is ES2020 while vitest runs these files on +// a Node with ES2022 builtins, so the gap is reported as TS2550 about the +// CHECK rather than about the code. ⚠️ Measured effect today: **zero** — +// this layer carries no TS2550 either way. Fidelity to the runtime, not +// error reduction, and it is stated that way rather than claimed as a +// subtraction. It is also the exact trap the card that ordered this file was +// filed about: `Object.hasOwn` in a new test is TS2550 against a pre-ES2022 +// lib, and the package's advertised `typecheck` said nothing about it. No +// `DOM`: nothing in this layer touches a browser global. +// - ⛔ STRICTNESS IS UNTOUCHED. `strict`, `noUnusedLocals`, +// `noUnusedParameters`, `noImplicitReturns`, `noFallthroughCasesInSwitch`, +// `types: ["node"]` and `rootDir` are inherited from `tsconfig.json` and +// through it the root config, and none of them is re-declared here. +// `rootDir` (`./src`) needs no widening: every test file here lives under +// `src` and none reaches outside the package, so the TS6059 pile +// `packages/cli`'s sibling had to widen `rootDir` to clear does not arise — +// measured, the raw program carries no TS6059. ⚠️ A child that declared its +// own `paths` would REPLACE the parent map rather than merge into it, +// silently sending a source-resolved specifier back to `dist/`, so this file +// declares none. Nothing here may loosen a type rule; if a test does not +// compile, that is the finding. +// +// MEASURED at 6a1e38244 with the dependency closure built (an error count taken +// against an unbuilt closure is not a reading — unresolved-import cascades +// inflate it): this layer reports **1 error across 1 file**, which is the same 1 that +// `scripts/check-type-check-coverage.mjs` recorded for this package in its +// per-PACKAGE `TEST_DEBT` ledger, reproduced class for class (TS2493 x1) and +// file for file. That entry GRADUATES in this change rather than being paid +// down: the identical population is now held one level finer, per file and per +// signature, in `test-typecheck-debt.json` beside this config. There is no +// config-tier subtraction here and nothing was exposed behind one, so the +// attribution has no remainder in either direction. +// +// // The single error is `Tuple type '[]' of length '0' has no element at index '0'` +// in `src/transports/transports.test.ts` — the same one the deleted `TEST_DEBT` +// entry named, and it has survived two arrivals of new hidden test files without +// moving. ⚠️ A one-entry ledger is the MOST exposed to a bad regeneration, not +// the least: a recomputation that writes zero deletes the whole record. +// +// Every one of the 1 is PRE-EXISTING: this change edits no test file, and each +// would have been reported on `origin/main` had this program always existed. +// They are ledgered EXACT and shrink-only — a file that gains an error is red, +// one that loses one is red until re-recorded, one that reaches zero is red +// until its entry is deleted, a signature that ARRIVES or VANISHES is red even +// at an unchanged file total, and a file NOT listed there may have no errors at +// all. ⛔ The 1 are NOT repaired here: seeding the ledger is the deliverable, +// and turning an onboarding into a cleanup is how it stops landing at all. +// +// ⚠️ 4 of the 5 files carry NO ledger entry, and that is load-bearing +// rather than incidental: any error any one of them ever gains is red on +// arrival. That is the half of this gate that starts working today. This layer +// also holds ZERO `@ts-expect-error` directives (grepped with a positive control +// — the same grep hits `packages/spec/src`), so no pin here was silently dead; +// what the gap cost was the other half. { "extends": "./tsconfig.json", "compilerOptions": { diff --git a/scripts/check-type-check-coverage.mjs b/scripts/check-type-check-coverage.mjs index 4666caf866..2883da31d9 100644 --- a/scripts/check-type-check-coverage.mjs +++ b/scripts/check-type-check-coverage.mjs @@ -1165,50 +1165,97 @@ const TEST_DEBT = { // still does not: measured on the way out, its test layer holds ZERO // `@ts-expect-error` directives, so that half had no subject here either. - '@objectstack/mcp': { - errors: 53, - note: 'TS18046 x51 -- `json` is of type unknown, one `await res.json()` idiom repeated across four ' - + 'files (23 in mcp-server-runtime.http.test.ts, 14 in mcp-action-tools.test.ts, 8 in ' - + 'mcp-http-tools.scopes.test.ts, 6 in mcp-validate-expression.test.ts); TS6133 x1; TS2352 x1. ' - + 'RE-TALLIED from tsc at the 53 below (62b2655d8) and unchanged class for class, which is why the ' - + 'composition above is kept rather than rewritten: the 51 TS18046 sit in exactly those four files ' - + 'in exactly those counts. The two singletons the old tally named by class without saying where ' - + 'are src/skill-prompts.test.ts(185,23) for the TS2352 and ' - + 'src/__tests__/mcp-server-runtime.test.ts(7,1) for the TS6133 (`MCPServerRuntimeConfig` declared, ' - + 'never read). ' - + 'Measured 52 at 5ab08428 -> 53 at 34558c2cc. This entry WAS the fifth bootstrap margin and the ' - + 'one the ratchet found on its OWN introducing PR: #5278 reached the merge queue and was kicked ' - + 'at 03:25:18Z on this single +1, which is not #6077\'s doing (that PR\'s own queue generation ' - + 'was green) but a pre-existing drift no gate in this repo could see until the ledger was ' - + 're-measured against a moving base. The +1 is fully attributed: ' - + 'src/skill-prompts.test.ts(185,23), a TS2352 casting `SkillPrompt | null` to `Record< string, ' - + 'unknown >` -- the file #3905 / PR #6077 added when it projected skill `instructions` as MCP ' - + 'prompt primitives, which is also why this package\'s hidden test-file count moved up by one ' - + '(the count itself is derived by this gate, not recorded here -- #5826). The old note\'s composition ' - + 'was misleading in the way the top of this ledger warns about: it read "`error` is of type ' - + 'unknown, one catch-block idiom", while all 51 are the response-body `json` binding, not a ' - + 'catch block. packages/mcp took a feature landing the same day, so it is an actively-moving ' - + 'package and an exact number here would very likely lose the same race that killed option D ' - + 'five times over. THE MARGIN IS GONE, and has been since #7888 / PR #8225 lowered 63 -> 53 onto ' - + 'the exact measurement; RECORDED 63 was that margin (+10 over 53 measured at 34558c2cc) and this ' - + 'sentence is its history, not this entry\'s present state. RECORDED now equals what tsc reports, ' - + 're-confirmed at 53 at 62b2655d8, so the next new error in this package goes red on arrival -- ' - + 're-establishing a margin deliberately remains a maintainer call (#5278 option A).', - }, - '@objectstack/formula': { - errors: 17, - note: 'TS2591 x6 (`process`), TS2345 x3, TS2352 x3, TS1470 x2, TS2339 x2, TS2739 x1. Re-measured 17 ' - + 'at 5ab08428, up from 12; the TS2591 half doubled, which is the missing `types:["node"]` again ' - + 'rather than five new defects. The TS2739 was inside that 17 from the start and simply went ' - + 'UNLISTED, so this tally read 16 over a field of 17 until #13631 re-measured 17 at cc837dbfec ' - + 'and restored it -- COMPOSITION reads tier itemisations and does not sum per-code tallies, so ' - + 'nothing mechanical read the gap. It is the only one of the 17 in `src/cel-to-filter.test.ts` ' - + '(173,52), where the local `ok()` helper pins its second argument to the exact shape of the ' - + 'module-level `VARS` and a partial context cannot satisfy it; the same file already carries a ' - + 'hand-widened copy of that helper (`filterOf`) written for exactly that reason.', - }, - '@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.' }, +// ── #12511: SEVEN packages GRADUATED at once, and not one of them was paid down +// +// `mcp` (53), `formula` (17), `platform-objects` (3), `connector-mcp` (5), +// `connector-openapi` (5), `connector-rest` (1) and `service-sms` (1) left this +// ledger on 2026-09-06, by the same route as `runtime`, `cli`, `lint`, +// `driver-mongodb`, `verify` and the three plugins: each now has a +// `tsconfig.test.json` its own `typecheck` script NAMES, so `hidesTests` is +// false for it and this gate's per-PACKAGE approximation has nothing left to +// approximate. ⛔ Read that first — a deleted TEST_DEBT entry normally means the +// errors are gone, and here it does not. This change repairs no test file and +// edits none. +// +// ⚠️ SEVEN IN ONE CHANGE IS NOT A BLANKET EDIT, and that distinction is the +// whole reason the card ordering this refused one. Each sibling config was +// written against its OWN measured hole and states its own reading in its own +// header; the judgement genuinely diverged on both axes that matter here: +// +// - MODULE SEMANTICS. `mcp` is `"type": "module"`, so NodeNext already reads +// its tests as ESM and is the STRICTER of the two readings — its sibling +// therefore changes module semantics NOT AT ALL, which is +// `packages/metadata-core`'s precedent rather than `packages/rest`'s. The +// other six are not `"type": "module"`, so NodeNext compiles as CJS what +// vitest executes as ESM, and their siblings carry `module: esnext` / +// `moduleResolution: bundler` for fidelity to the runtime. +// - THE MEASURED SUBTRACTION, which is ZERO for six of the seven. The +// remedy that "obviously" dissolves a config-tier pile dissolved one only +// where the pile was actually there, and 8 mechanical copies of any one of +// these configs would have been 8 configs nobody measured. +// +// The attribution has no remainder in either direction. RAW is re-measured on +// the way out through this gate's own `remeasureProject` shape (extends the +// package's `tsconfig.json`, drops ONLY the test glob) at 6a1e38244 with the +// dependency closure built; LEDGER is what `tsconfig.test.json` reports at +// 52a5a14e7 on that same closure. An error count taken against an unbuilt +// closure is not a reading — unresolved-import cascades inflate it. +// +// package RECORDED RAW dissolve exposed LEDGER +// mcp 53 53 0 0 53 +// formula 17 17 -2 0 15 +// platform-objects 3 3 0 0 3 +// connector-mcp 5 5 0 0 5 +// connector-openapi 5 5 0 0 5 +// connector-rest 1 1 0 0 1 +// service-sms 1 1 0 0 1 +// +// RECORDED equalled RAW for all seven, class for class and file for file, so +// every number this ledger held was exact and stayed exact to the end. The +// identical populations are now held one level finer, per FILE and per +// SIGNATURE, in each package's own `test-typecheck-debt.json`. +// +// The single dissolution is `formula`'s TS1470 x2 ("`import.meta` is not +// allowed in files which will build into CommonJS output", +// `src/rls-predicate.test.ts` and `src/skill-catalog-sync.test.ts`), which goes +// away under `module: esnext` because it was the CHECK being misconfigured and +// never the tests. NOTHING was exposed behind it: there was no unresolved-import +// cascade to collapse in any of the seven, so there is no `+n` term anywhere in +// the table. +// +// ⚠️ ONE COMPOSITION CORRECTION, recorded because the next reader would +// otherwise go looking for the wrong thing: `formula`'s deleted note attributed +// its TS2591 x6 to «`process`». Measured here, all six are the bare module +// specifiers of node builtins — `node:fs` x2, `node:path` x2, `node:url` x2, in +// those same two files — and the TS2339 x2 beside them are `Property 'url' does +// not exist on type 'ImportMeta'`. Both classes SURVIVE the move and are +// ledgered: this package declares no `@types/node` and its tsconfig names no +// `types`, so the node typings never reach its program. That is real debt with a +// real repair, and ⛔ it is deliberately NOT repaired here — seeding the ledger +// is the deliverable, and turning an onboarding into a cleanup is how it stops +// landing at all. +// +// ⚠️ PINS_CHECKED reported nothing for any of the seven in either direction and +// still does not: their test layers hold ZERO `@ts-expect-error` directives +// (grepped with a positive control — the same grep hits `packages/spec/src`), so +// that half had no subject here. What the gap cost was the other half: 83 +// diagnostics that no gate this repo runs had ever reported. +// +// ⛔ WHAT DID NOT GRADUATE, and why it is still below: `@objectstack/http-conformance`. +// Its 2 recorded errors reproduce exactly (TS2307 x1, TS2304 x1) and its own +// note already says what they are — both inside `node_modules` `.d.ts` files, so +// the entry moves with the lockfile rather than with this package's code. The +// reason it cannot take the sibling route unchanged is one this file did not +// record before: `packages/qa/http-conformance/tsconfig.json` is one of the six +// package configs that do NOT extend the repo root config, and it is the only +// one of those that also declares no `skipLibCheck` — which is the sole reason +// those two third-party declarations are checked at all. Ledgering them per FILE +// would key a shrink-only ratchet on `.pnpm` content-hash paths that move on any +// unrelated dependency bump, and turning `skipLibCheck` on in a test program has +// no precedent among the 31 sibling configs (none declares it). That is a +// judgement about this repo's config policy rather than about this package, so +// it is left to the card. + '@objectstack/http-conformance': { errors: 2, note: 'TS2307 x1, TS2304 x1, and BOTH are reported inside node_modules `.d.ts` files ' @@ -1228,9 +1275,6 @@ const TEST_DEBT = { + 'gate refreshes and refuses on -- the number dropped because the program became well-defined, ' + 'not because anything was suppressed.', }, - '@objectstack/platform-objects': { errors: 3, note: 'TS2339 x2, TS7006 x1. Re-measured 3 at 5ab08428, exact.' }, - '@objectstack/service-sms': { errors: 1, note: 'TS2493 x1, in transports.test.ts. Re-measured 1 at 5ab08428 and still 1 at e8db1a230, after two more hidden test files: #5773 added sms-manifest-providers.contract.test.ts and #2814 / PR #6042 added sms-daily-quota.test.ts. The file count moved twice while the error count did not -- both new files are type-clean with the exclusion lifted.' }, - '@objectstack/connector-rest': { errors: 1, note: 'TS6133 x1. Re-measured 1 at 5ab08428, exact.' }, }; // Repo-relative path -> why this test file's `@ts-expect-error` directives are diff --git a/scripts/check-type-source-resolution.mjs b/scripts/check-type-source-resolution.mjs index 0a9be2e8ea..082f6df6c6 100644 --- a/scripts/check-type-source-resolution.mjs +++ b/scripts/check-type-source-resolution.mjs @@ -276,6 +276,38 @@ const REPO_ROOT = resolve(HERE, '..'); * re-baseline), and `@objectstack/rest` (#12542 / PR #12570 at `3f41a215`, the * first package to take the #5286 sibling route for this reason). * + * ## The #12511 re-baseline — six packages onboarding one program each + * + * Seven packages took the #5286 sibling route in one change; six of them move + * this registry. Every admitted dep is annotated `via tsconfig.test.json` by + * this gate's own provenance output, i.e. reached ONLY through the program the + * change onboarded — condition 1 above, read off the instrument rather than + * asserted. `@objectstack/formula` onboarded a program and admitted NOTHING, + * which is the control that says the other six are reporting a real widening + * rather than an artifact of the population growing. + * + * before 125 programs / 78 packages, 61 entries, 310 package-dep pairs + * after 132 programs / 78 packages, 61 entries, 319 package-dep pairs + * + * so +7 programs, +0 entries (all six already had one) and +9 pairs: `mcp` +2 + * (`lint`, `metadata-core`), `platform-objects` +3 (`core`, `formula`, `lint`), + * `connector-mcp` / `connector-openapi` / `connector-rest` +1 each + * (`service-automation`), `service-sms` +1 (`service-settings`). The ratchet is + * shrink-only from the new number. + * + * ⚠️ TWO OF THE NINE ARE A DISAGREEMENT WORTH NAMING, because a later reader + * will otherwise find it and think it was missed. `packages/mcp` and + * `packages/platform-objects` both alias `@objectstack/lint` (and mcp also + * `@objectstack/metadata-core`) to that package's SOURCE in their vitest + * configs, precisely so the suite runs against the checkout rather than a build + * artifact — while the test program admitted above still resolves those same + * specifiers' TYPES through `dist/`. So for those specifiers the RUN and the + * TYPE VERDICT read different artifacts. `paths` is the obvious repair and is + * measured to be the wrong one here: the refusal directly above is explicit + * that for the ONBOARDING case it billed other packages' source diagnostics + * into the onboarding package's ledger (PR #12570, 37 -> 42). Declared here + * instead, where the shrink-only ratchet keeps it visible. + * * ⛔ Still NOT open: `paths` remains the fix for a dep exposed through an * EXISTING program, and no widening may silence one. For the onboarding case * `paths` is additionally the WRONG tool, measured on PR #12570 rather than @@ -294,9 +326,9 @@ const KNOWN_DIST_RESOLVED_TYPE_IMPORTS = { '@objectstack/plugin-hono-server', '@objectstack/runtime', '@objectstack/spec', ], '@objectstack/client-react': ['@objectstack/client', '@objectstack/spec'], - '@objectstack/connector-mcp': ['@objectstack/core', '@objectstack/spec'], - '@objectstack/connector-openapi': ['@objectstack/core', '@objectstack/spec'], - '@objectstack/connector-rest': ['@objectstack/core', '@objectstack/spec'], + '@objectstack/connector-mcp': ['@objectstack/core', '@objectstack/service-automation', '@objectstack/spec'], + '@objectstack/connector-openapi': ['@objectstack/core', '@objectstack/service-automation', '@objectstack/spec'], + '@objectstack/connector-rest': ['@objectstack/core', '@objectstack/service-automation', '@objectstack/spec'], '@objectstack/connector-slack': [ '@objectstack/core', '@objectstack/service-automation', '@objectstack/spec', ], @@ -383,7 +415,8 @@ const KNOWN_DIST_RESOLVED_TYPE_IMPORTS = { '@objectstack/knowledge-ragflow': ['@objectstack/core', '@objectstack/spec'], '@objectstack/lint': ['@objectstack/formula', '@objectstack/sdui-parser', '@objectstack/spec'], '@objectstack/mcp': [ - '@objectstack/core', '@objectstack/formula', '@objectstack/spec', '@objectstack/types', + '@objectstack/core', '@objectstack/formula', '@objectstack/lint', + '@objectstack/metadata-core', '@objectstack/spec', '@objectstack/types', ], '@objectstack/metadata': [ '@objectstack/core', '@objectstack/driver-sqlite-wasm', '@objectstack/metadata-core', @@ -399,7 +432,10 @@ const KNOWN_DIST_RESOLVED_TYPE_IMPORTS = { '@objectstack/core', '@objectstack/formula', '@objectstack/metadata', '@objectstack/metadata-core', '@objectstack/metadata-protocol', '@objectstack/spec', '@objectstack/types', ], - '@objectstack/platform-objects': ['@objectstack/metadata-core', '@objectstack/spec'], + '@objectstack/platform-objects': [ + '@objectstack/core', '@objectstack/formula', '@objectstack/lint', + '@objectstack/metadata-core', '@objectstack/spec', + ], // ── #14062 re-baseline, on the onboarding limb above ───────────────────── // // The director ruling of 2026-09-01 on #14062 (maintainer verbatim: 「同意」) @@ -820,7 +856,10 @@ const KNOWN_DIST_RESOLVED_TYPE_IMPORTS = { // #11490 re-baseline: NEW entries — reached only through `tsconfig.scripts.json`. '@objectstack/service-messaging': ['@objectstack/spec'], '@objectstack/service-realtime': ['@objectstack/spec'], - '@objectstack/service-sms': ['@objectstack/core', '@objectstack/plugin-auth', '@objectstack/spec'], + '@objectstack/service-sms': [ + '@objectstack/core', '@objectstack/plugin-auth', '@objectstack/service-settings', + '@objectstack/spec', + ], // #15050 re-baseline (the onboarding limb above): a NEW entry, reached ONLY // through `tsconfig.test.json` (all 7 deps) and `tsconfig.scripts.json` // (`@objectstack/spec` again, no new pairs). Same shape as `service-cluster` diff --git a/scripts/regen-artifacts.mjs b/scripts/regen-artifacts.mjs index 987db802ea..8d27f52c2c 100644 --- a/scripts/regen-artifacts.mjs +++ b/scripts/regen-artifacts.mjs @@ -646,6 +646,110 @@ export const NOT_DRIVER_MANAGED = Object.freeze([ + 'the runtime row above: a recomputed value here reads as a clean, plausible REPAIR rather ' + 'than as noise, and a dropped entry is indistinguishable from a file somebody fixed.', }, + // ── #12511: the seven ledgered packages that graduated together ─────────── + // + // Seven rows and not one, for the reason the `packages/client` row above + // states: `reconcileGenerators` keys on (owner, script), three manifests + // defined `gen:test-typecheck-debt` when that row was written and eleven do + // now, so one entry standing for the family would be a disposition nobody + // actually made for any of these files. Each package's `TEST_DEBT` entry in + // `scripts/check-type-check-coverage.mjs` graduated in the same change, so + // each file below is now the ONLY record of its population anywhere in the + // tree. ⛔ `@objectstack/http-conformance` is deliberately absent: it did not + // graduate, keeps its per-package entry, and defines no generator. + { + path: 'packages/mcp/test-typecheck-debt.json', + gen: 'gen:test-typecheck-debt', + owner: '@objectstack/mcp', + why: + 'a SHRINK-ONLY ratchet — see `packages/plugins/plugin-approvals/test-typecheck-debt.json` ' + + 'above; same generator, same per-package ledger, same reason a merge must never recompute ' + + 'it: the half-merged tree is not the tree whose type errors this file records, so a file ' + + 'that GAINED errors would enter the ledger as merge noise instead of as red. ' + + 'This is the biggest of the seven (53 errors over 6 files) and 51 of them are ONE idiom — `await ' + + 'res.json()` bound without a narrowing — repeated across four suites. That uniformity is exactly ' + + 'what makes a mid-merge recompute unreadable here: a number that moved from 53 to 49 because the ' + + 'half-merged tree resolved one import differently looks like four repairs somebody landed, and ' + + 'the per-signature keys underneath would be silently rewritten with it.', + }, + { + path: 'packages/formula/test-typecheck-debt.json', + gen: 'gen:test-typecheck-debt', + owner: '@objectstack/formula', + why: + 'a SHRINK-ONLY ratchet — see `packages/plugins/plugin-approvals/test-typecheck-debt.json` ' + + 'above; same generator, same per-package ledger, same reason a merge must never recompute ' + + 'it: the half-merged tree is not the tree whose type errors this file records, so a file ' + + 'that GAINED errors would enter the ledger as merge noise instead of as red. ' + + 'The only one of the seven whose ledger is NOT its recorded per-package number (15, from a ' + + 'recorded 17): the TS1470 x2 dissolved under the sibling config\'s `module: esnext` while ' + + 'everything else survived. A recomputation mid-merge cannot tell a dissolution from a repair, ' + + 'and this file is the only record that the -2 was the former.', + }, + { + path: 'packages/platform-objects/test-typecheck-debt.json', + gen: 'gen:test-typecheck-debt', + owner: '@objectstack/platform-objects', + why: + 'a SHRINK-ONLY ratchet — see `packages/plugins/plugin-approvals/test-typecheck-debt.json` ' + + 'above; same generator, same per-package ledger, same reason a merge must never recompute ' + + 'it: the half-merged tree is not the tree whose type errors this file records, so a file ' + + 'that GAINED errors would enter the ledger as merge noise instead of as red. ' + + 'Three errors over one file, all in `src/feature-gate-guard.test.ts`. At that size a recomputed ' + + 'value reads as a clean REPAIR rather than as noise, and a dropped entry is indistinguishable ' + + 'from a file somebody fixed — the `packages/cli` row above states that direction of the trade at ' + + 'length.', + }, + { + path: 'packages/connectors/connector-mcp/test-typecheck-debt.json', + gen: 'gen:test-typecheck-debt', + owner: '@objectstack/connector-mcp', + why: + 'a SHRINK-ONLY ratchet — see `packages/plugins/plugin-approvals/test-typecheck-debt.json` ' + + 'above; same generator, same per-package ledger, same reason a merge must never recompute ' + + 'it: the half-merged tree is not the tree whose type errors this file records, so a file ' + + 'that GAINED errors would enter the ledger as merge noise instead of as red. ' + + 'Five errors carrying ONE signature in one file, which is the shape this row protects least ' + + 'visibly: a recompute that keeps the count and swaps the signature is exactly the substitution ' + + 'the per-signature ledger exists to catch, and doing it as merge noise defeats it silently.', + }, + { + path: 'packages/connectors/connector-openapi/test-typecheck-debt.json', + gen: 'gen:test-typecheck-debt', + owner: '@objectstack/connector-openapi', + why: + 'a SHRINK-ONLY ratchet — see `packages/plugins/plugin-approvals/test-typecheck-debt.json` ' + + 'above; same generator, same per-package ledger, same reason a merge must never recompute ' + + 'it: the half-merged tree is not the tree whose type errors this file records, so a file ' + + 'that GAINED errors would enter the ledger as merge noise instead of as red. ' + + 'Five errors carrying one signature in one file — see the `connector-mcp` row directly above; ' + + 'the two packages measure the identical population against the same connector contract.', + }, + { + path: 'packages/connectors/connector-rest/test-typecheck-debt.json', + gen: 'gen:test-typecheck-debt', + owner: '@objectstack/connector-rest', + why: + 'a SHRINK-ONLY ratchet — see `packages/plugins/plugin-approvals/test-typecheck-debt.json` ' + + 'above; same generator, same per-package ledger, same reason a merge must never recompute ' + + 'it: the half-merged tree is not the tree whose type errors this file records, so a file ' + + 'that GAINED errors would enter the ledger as merge noise instead of as red. ' + + 'The smallest ledger in the repo at ONE error, and smallness is the hazard rather than the ' + + 'reassurance: a mid-merge recompute that writes zero here deletes the whole record, and an empty ' + + 'ledger reads as a package that graduated.', + }, + { + path: 'packages/services/service-sms/test-typecheck-debt.json', + gen: 'gen:test-typecheck-debt', + owner: '@objectstack/service-sms', + why: + 'a SHRINK-ONLY ratchet — see `packages/plugins/plugin-approvals/test-typecheck-debt.json` ' + + 'above; same generator, same per-package ledger, same reason a merge must never recompute ' + + 'it: the half-merged tree is not the tree whose type errors this file records, so a file ' + + 'that GAINED errors would enter the ledger as merge noise instead of as red. ' + + 'One error, in `src/transports/transports.test.ts` — see the `connector-rest` row directly above ' + + 'for why a one-entry ledger is the most exposed to a mid-merge recompute, not the least.', + }, { path: 'packages/sdui-parser/objectui-lockstep.json', gen: 'gen:sdui-lockstep',