Skip to content

Commit 8cf806f

Browse files
claude[bot]claude
andauthored
chore(typecheck): seven ledgered packages type-check their own tests through a sibling test program (#12511) (#16295)
* 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 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Vbw3RPgdtqesx4azk9SbW8 * chore(typecheck): ledgers, TEST_DEBT graduations, merge dispositions and config headers Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Vbw3RPgdtqesx4azk9SbW8 --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 92b5d7f commit 8cf806f

24 files changed

Lines changed: 1055 additions & 60 deletions

packages/connectors/connector-mcp/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
1414
},
1515
"scripts": {
1616
"build": "tsup --config ../../../tsup.config.ts && node ../../../scripts/check-dts-emitted.mjs",
17+
"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",
18+
"gen:test-typecheck-debt": "tsx ../../../scripts/check-test-typecheck.mts --update --package packages/connectors/connector-mcp --project tsconfig.test.json",
1719
"test": "vitest run --passWithNoTests",
18-
"typecheck": "tsc --noEmit"
20+
"typecheck": "tsc --noEmit && pnpm check:test-typecheck"
1921
},
2022
"dependencies": {
2123
"@modelcontextprotocol/sdk": "^1.30.0",
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"_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",
3+
"entries": {
4+
"src/mcp-provider.test.ts": {
5+
"TS2339: Property 'then' does not exist on type '…'.": 5
6+
}
7+
}
8+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
// The TEST-layer type-check program (#12511), adopting the mechanism #5286 set
2+
// for `packages/spec` and #5449 generalised. `tsconfig.json` beside this file
3+
// stays exactly as it is: it is the BUILD config, and its `**/*.test.ts`
4+
// exclusion has a reason — ci.yml gates that no test file reaches the published
5+
// artifact. This sibling puts the excluded layer back in front of tsc, and
6+
// `package.json`'s `typecheck` script NAMES it (via `check:test-typecheck
7+
// --project`), because a config no script invokes is exactly the phantom this
8+
// whole mechanism is about.
9+
//
10+
// BEFORE THIS FILE, NO tsc PROGRAM COMPILED A SINGLE TEST FILE HERE, measured
11+
// rather than read off the config. At 6a1e38244 with the workspace closure
12+
// built first, `tsc --noEmit --listFiles -p tsconfig.json` — the only config
13+
// this package's `typecheck` named — puts 349 files in the program, 4 of
14+
// them this package's own `src/**`, and **0** of its 3 `src/**/*.test.ts`.
15+
// So the zero is the `exclude` line and not a probe that sees nothing. Positive
16+
// controls in the SAME run, same binary, same worktree: `packages/rest`'s test
17+
// program 186 test files, `packages/metadata-core`'s 15,
18+
// `packages/drivers/driver-memory`'s build config 44 — without them every zero
19+
// above is unfalsifiable. Under this file the count is **3 of 3**
20+
// (418 files in the program).
21+
//
22+
// What differs from the build config, and what deliberately does NOT:
23+
// - MODULE SEMANTICS. This package is NOT `"type": "module"`, so the
24+
// inherited NodeNext compiles as CommonJS the files vitest executes as ESM.
25+
// Matching vitest is fidelity, not laxity. ⚠️ Measured subtraction on
26+
// today's tree: **zero** — no test file here reaches for `import.meta` or
27+
// writes an extension-less relative import, so on THIS tree the mismatch
28+
// costs nothing. Of the seven packages onboarded by this card only
29+
// `packages/formula` measured a subtraction (TS1470 x2), which is exactly
30+
// why eight mechanical copies of one config would not have been eight
31+
// correct configs. The override is declared anyway, because the alternative
32+
// is that the first test file to use either construct gets a config-tier
33+
// diagnostic ledgered as though it were a defect. ⚠️ `bundler` resolution
34+
// also stops requiring `.js` on this package's own `src` relative imports IN
35+
// THIS PROGRAM; nothing is lost by that, because leg 1 of `typecheck` still
36+
// compiles `src` under the build config's NodeNext and is where that rule is
37+
// enforced.
38+
// - `lib: ["ES2022"]`, for the reason `packages/rest` and `packages/lint`
39+
// state: the root config's `lib` is ES2020 while vitest runs these files on
40+
// a Node with ES2022 builtins, so the gap is reported as TS2550 about the
41+
// CHECK rather than about the code. ⚠️ Measured effect today: **zero** —
42+
// this layer carries no TS2550 either way. Fidelity to the runtime, not
43+
// error reduction, and it is stated that way rather than claimed as a
44+
// subtraction. It is also the exact trap the card that ordered this file was
45+
// filed about: `Object.hasOwn` in a new test is TS2550 against a pre-ES2022
46+
// lib, and the package's advertised `typecheck` said nothing about it. No
47+
// `DOM`: nothing in this layer touches a browser global.
48+
// - ⛔ STRICTNESS IS UNTOUCHED. `strict`, `noUnusedLocals`,
49+
// `noUnusedParameters`, `noImplicitReturns`, `noFallthroughCasesInSwitch`,
50+
// `types: ["node"]` and `rootDir` are inherited from `tsconfig.json` and
51+
// through it the root config, and none of them is re-declared here.
52+
// `rootDir` (`./src`) needs no widening: every test file here lives under
53+
// `src` and none reaches outside the package, so the TS6059 pile
54+
// `packages/cli`'s sibling had to widen `rootDir` to clear does not arise —
55+
// measured, the raw program carries no TS6059. ⚠️ A child that declared its
56+
// own `paths` would REPLACE the parent map rather than merge into it,
57+
// silently sending a source-resolved specifier back to `dist/`, so this file
58+
// declares none. Nothing here may loosen a type rule; if a test does not
59+
// compile, that is the finding.
60+
//
61+
// MEASURED at 6a1e38244 with the dependency closure built (an error count taken
62+
// against an unbuilt closure is not a reading — unresolved-import cascades
63+
// inflate it): this layer reports **5 errors across 1 file**, which is the same 5 that
64+
// `scripts/check-type-check-coverage.mjs` recorded for this package in its
65+
// per-PACKAGE `TEST_DEBT` ledger, reproduced class for class (TS2339 x5) and
66+
// file for file. That entry GRADUATES in this change rather than being paid
67+
// down: the identical population is now held one level finer, per file and per
68+
// signature, in `test-typecheck-debt.json` beside this config. There is no
69+
// config-tier subtraction here and nothing was exposed behind one, so the
70+
// attribution has no remainder in either direction.
71+
//
72+
// // All 5 sit in `src/mcp-provider.test.ts` and carry ONE signature —
73+
// `Property 'then' does not exist on type 'ConnectorMaterialization |
74+
// Promise<ConnectorMaterialization>'` — so this package and
75+
// `packages/connectors/connector-openapi` measure the identical population
76+
// against the same connector contract. One narrowing at the call site is the
77+
// whole ledger.
78+
//
79+
// Every one of the 5 is PRE-EXISTING: this change edits no test file, and each
80+
// would have been reported on `origin/main` had this program always existed.
81+
// They are ledgered EXACT and shrink-only — a file that gains an error is red,
82+
// one that loses one is red until re-recorded, one that reaches zero is red
83+
// until its entry is deleted, a signature that ARRIVES or VANISHES is red even
84+
// at an unchanged file total, and a file NOT listed there may have no errors at
85+
// all. ⛔ The 5 are NOT repaired here: seeding the ledger is the deliverable,
86+
// and turning an onboarding into a cleanup is how it stops landing at all.
87+
//
88+
// ⚠️ 2 of the 3 files carry NO ledger entry, and that is load-bearing
89+
// rather than incidental: any error any one of them ever gains is red on
90+
// arrival. That is the half of this gate that starts working today. This layer
91+
// also holds ZERO `@ts-expect-error` directives (grepped with a positive control
92+
// — the same grep hits `packages/spec/src`), so no pin here was silently dead;
93+
// what the gap cost was the other half.
94+
{
95+
"extends": "./tsconfig.json",
96+
"compilerOptions": {
97+
"noEmit": true,
98+
"module": "esnext",
99+
"moduleResolution": "bundler",
100+
"lib": ["ES2022"]
101+
},
102+
"include": ["src/**/*"],
103+
"exclude": ["node_modules", "dist"]
104+
}

packages/connectors/connector-openapi/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
1414
},
1515
"scripts": {
1616
"build": "tsup --config ../../../tsup.config.ts && node ../../../scripts/check-dts-emitted.mjs",
17+
"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",
18+
"gen:test-typecheck-debt": "tsx ../../../scripts/check-test-typecheck.mts --update --package packages/connectors/connector-openapi --project tsconfig.test.json",
1719
"test": "vitest run --passWithNoTests",
18-
"typecheck": "tsc --noEmit"
20+
"typecheck": "tsc --noEmit && pnpm check:test-typecheck"
1921
},
2022
"dependencies": {
2123
"@objectstack/core": "workspace:*",
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"_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",
3+
"entries": {
4+
"src/openapi-provider.test.ts": {
5+
"TS2339: Property 'then' does not exist on type '…'.": 5
6+
}
7+
}
8+
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
// The TEST-layer type-check program (#12511), adopting the mechanism #5286 set
2+
// for `packages/spec` and #5449 generalised. `tsconfig.json` beside this file
3+
// stays exactly as it is: it is the BUILD config, and its `**/*.test.ts`
4+
// exclusion has a reason — ci.yml gates that no test file reaches the published
5+
// artifact. This sibling puts the excluded layer back in front of tsc, and
6+
// `package.json`'s `typecheck` script NAMES it (via `check:test-typecheck
7+
// --project`), because a config no script invokes is exactly the phantom this
8+
// whole mechanism is about.
9+
//
10+
// BEFORE THIS FILE, NO tsc PROGRAM COMPILED A SINGLE TEST FILE HERE, measured
11+
// rather than read off the config. At 6a1e38244 with the workspace closure
12+
// built first, `tsc --noEmit --listFiles -p tsconfig.json` — the only config
13+
// this package's `typecheck` named — puts 332 files in the program, 4 of
14+
// them this package's own `src/**`, and **0** of its 4 `src/**/*.test.ts`.
15+
// So the zero is the `exclude` line and not a probe that sees nothing. Positive
16+
// controls in the SAME run, same binary, same worktree: `packages/rest`'s test
17+
// program 186 test files, `packages/metadata-core`'s 15,
18+
// `packages/drivers/driver-memory`'s build config 44 — without them every zero
19+
// above is unfalsifiable. Under this file the count is **4 of 4**
20+
// (402 files in the program).
21+
//
22+
// What differs from the build config, and what deliberately does NOT:
23+
// - MODULE SEMANTICS. This package is NOT `"type": "module"`, so the
24+
// inherited NodeNext compiles as CommonJS the files vitest executes as ESM.
25+
// Matching vitest is fidelity, not laxity. ⚠️ Measured subtraction on
26+
// today's tree: **zero** — no test file here reaches for `import.meta` or
27+
// writes an extension-less relative import, so on THIS tree the mismatch
28+
// costs nothing. Of the seven packages onboarded by this card only
29+
// `packages/formula` measured a subtraction (TS1470 x2), which is exactly
30+
// why eight mechanical copies of one config would not have been eight
31+
// correct configs. The override is declared anyway, because the alternative
32+
// is that the first test file to use either construct gets a config-tier
33+
// diagnostic ledgered as though it were a defect. ⚠️ `bundler` resolution
34+
// also stops requiring `.js` on this package's own `src` relative imports IN
35+
// THIS PROGRAM; nothing is lost by that, because leg 1 of `typecheck` still
36+
// compiles `src` under the build config's NodeNext and is where that rule is
37+
// enforced.
38+
// - `lib: ["ES2022"]`, for the reason `packages/rest` and `packages/lint`
39+
// state: the root config's `lib` is ES2020 while vitest runs these files on
40+
// a Node with ES2022 builtins, so the gap is reported as TS2550 about the
41+
// CHECK rather than about the code. ⚠️ Measured effect today: **zero** —
42+
// this layer carries no TS2550 either way. Fidelity to the runtime, not
43+
// error reduction, and it is stated that way rather than claimed as a
44+
// subtraction. It is also the exact trap the card that ordered this file was
45+
// filed about: `Object.hasOwn` in a new test is TS2550 against a pre-ES2022
46+
// lib, and the package's advertised `typecheck` said nothing about it. No
47+
// `DOM`: nothing in this layer touches a browser global.
48+
// - ⛔ STRICTNESS IS UNTOUCHED. `strict`, `noUnusedLocals`,
49+
// `noUnusedParameters`, `noImplicitReturns`, `noFallthroughCasesInSwitch`,
50+
// `types: ["node"]` and `rootDir` are inherited from `tsconfig.json` and
51+
// through it the root config, and none of them is re-declared here.
52+
// `rootDir` (`./src`) needs no widening: every test file here lives under
53+
// `src` and none reaches outside the package, so the TS6059 pile
54+
// `packages/cli`'s sibling had to widen `rootDir` to clear does not arise —
55+
// measured, the raw program carries no TS6059. ⚠️ A child that declared its
56+
// own `paths` would REPLACE the parent map rather than merge into it,
57+
// silently sending a source-resolved specifier back to `dist/`, so this file
58+
// declares none. Nothing here may loosen a type rule; if a test does not
59+
// compile, that is the finding.
60+
//
61+
// MEASURED at 6a1e38244 with the dependency closure built (an error count taken
62+
// against an unbuilt closure is not a reading — unresolved-import cascades
63+
// inflate it): this layer reports **5 errors across 1 file**, which is the same 5 that
64+
// `scripts/check-type-check-coverage.mjs` recorded for this package in its
65+
// per-PACKAGE `TEST_DEBT` ledger, reproduced class for class (TS2339 x5) and
66+
// file for file. That entry GRADUATES in this change rather than being paid
67+
// down: the identical population is now held one level finer, per file and per
68+
// signature, in `test-typecheck-debt.json` beside this config. There is no
69+
// config-tier subtraction here and nothing was exposed behind one, so the
70+
// attribution has no remainder in either direction.
71+
//
72+
// // All 5 sit in `src/openapi-provider.test.ts` and carry ONE signature —
73+
// `Property 'then' does not exist on type 'ConnectorMaterialization |
74+
// Promise<ConnectorMaterialization>'` — the identical population
75+
// `packages/connectors/connector-mcp` measures against the same connector
76+
// contract. One narrowing at the call site is the whole ledger.
77+
//
78+
// Every one of the 5 is PRE-EXISTING: this change edits no test file, and each
79+
// would have been reported on `origin/main` had this program always existed.
80+
// They are ledgered EXACT and shrink-only — a file that gains an error is red,
81+
// one that loses one is red until re-recorded, one that reaches zero is red
82+
// until its entry is deleted, a signature that ARRIVES or VANISHES is red even
83+
// at an unchanged file total, and a file NOT listed there may have no errors at
84+
// all. ⛔ The 5 are NOT repaired here: seeding the ledger is the deliverable,
85+
// and turning an onboarding into a cleanup is how it stops landing at all.
86+
//
87+
// ⚠️ 3 of the 4 files carry NO ledger entry, and that is load-bearing
88+
// rather than incidental: any error any one of them ever gains is red on
89+
// arrival. That is the half of this gate that starts working today. This layer
90+
// also holds ZERO `@ts-expect-error` directives (grepped with a positive control
91+
// — the same grep hits `packages/spec/src`), so no pin here was silently dead;
92+
// what the gap cost was the other half.
93+
{
94+
"extends": "./tsconfig.json",
95+
"compilerOptions": {
96+
"noEmit": true,
97+
"module": "esnext",
98+
"moduleResolution": "bundler",
99+
"lib": ["ES2022"]
100+
},
101+
"include": ["src/**/*"],
102+
"exclude": ["node_modules", "dist"]
103+
}

packages/connectors/connector-rest/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
1414
},
1515
"scripts": {
1616
"build": "tsup --config ../../../tsup.config.ts && node ../../../scripts/check-dts-emitted.mjs",
17+
"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",
18+
"gen:test-typecheck-debt": "tsx ../../../scripts/check-test-typecheck.mts --update --package packages/connectors/connector-rest --project tsconfig.test.json",
1719
"test": "vitest run --passWithNoTests",
18-
"typecheck": "tsc --noEmit"
20+
"typecheck": "tsc --noEmit && pnpm check:test-typecheck"
1921
},
2022
"dependencies": {
2123
"@objectstack/core": "workspace:*",

0 commit comments

Comments
 (0)