diff --git a/.changeset/runtime-test-typecheck-wiring.md b/.changeset/runtime-test-typecheck-wiring.md new file mode 100644 index 0000000000..e3e4926816 --- /dev/null +++ b/.changeset/runtime-test-typecheck-wiring.md @@ -0,0 +1,41 @@ +--- +"@objectstack/runtime": patch +--- + +fix(runtime): wire `packages/runtime`'s test layer into `check:test-typecheck`, so its 214 test files are type-checked at all (#14504) + +`packages/runtime/tsconfig.json` excluded `**/*.test.ts` and `**/*.spec.ts`, and +the package's `typecheck` script was a bare `tsc --noEmit` against that very +config — so no gate anywhere read a runtime test file with a type checker. +Measured at `224f8ea4a0` with the workspace closure built first, rather than +read off the config: `tsc --noEmit --listFiles -p tsconfig.json` puts 899 files +in the program and **0** of the package's 214 `src/**/*.test.ts` among them, +while 79 of its non-test `src/**` files ARE there — so the zero is the +`exclude` line, not a probe that sees nothing. The directional control is +`packages/drivers/driver-memory`, whose tsconfig carries no test exclusion: the +same probe puts 40 of its 40 test files in the program. Under the new +`tsconfig.test.json` the count is **214 of 214**. + +Onboarded by *wiring* to the shared mechanism (`scripts/check-test-typecheck.mts`) +the way `objectql`, `rest`, `lint` and the fourteen `packages/plugins/**` are +wired, never by copying it: a sibling `tsconfig.test.json` matching vitest's +real module semantics (`module: esnext`, `moduleResolution: bundler`, +`lib: ["ES2022"]`), named by `typecheck` via `check:test-typecheck --project`. +Strictness and `rootDir` are untouched and inherited; not one `any` and not one +`@ts-expect-error` was added to any test file to open the gate. + +**Seeded, not repaired, per this card's triage ruling.** The layer reports 191 +errors across 27 files and they are recorded EXACT and shrink-only in the new +`test-typecheck-debt.json`. Every one is pre-existing: no test file is edited +here. The other 187 files carry no entry, so any error they gain is red on +arrival. + +This is a CONVERSION rather than a new debt-opening decision. The same program +under the build config's inherited NodeNext reports 206 — exactly the number +`scripts/check-type-check-coverage.mjs` already held for this package in its +per-PACKAGE `TEST_DEBT` ledger — and that entry graduates here, as the pairing +forces. The 206 → 191 step is attributed in both directions with no remainder: +−19 config-tier diagnostics that dissolve under vitest's module semantics +(TS2835 ×13, the TS7006 ×4 cascading above them, TS2550 ×2) and +4 that +collapsing the cascade exposed (TS2322 ×4 in `src/seed-loader.test.ts`, +previously masked by an `any` from the unresolved import). diff --git a/packages/runtime/package.json b/packages/runtime/package.json index a4b289544a..1066d95f6e 100644 --- a/packages/runtime/package.json +++ b/packages/runtime/package.json @@ -21,7 +21,9 @@ "scripts": { "build": "tsup --config tsup.config.ts && node ../../scripts/check-dts-emitted.mjs", "dev": "tsc -w", - "typecheck": "tsc --noEmit", + "typecheck": "tsc --noEmit && pnpm check:test-typecheck", + "check:test-typecheck": "tsx ../../scripts/check-test-typecheck.mts --self-test && tsx ../../scripts/check-test-typecheck.mts --package packages/runtime --project tsconfig.test.json", + "gen:test-typecheck-debt": "tsx ../../scripts/check-test-typecheck.mts --update --package packages/runtime --project tsconfig.test.json", "test": "vitest run" }, "dependencies": { diff --git a/packages/runtime/test-typecheck-debt.json b/packages/runtime/test-typecheck-debt.json new file mode 100644 index 0000000000..396db924e9 --- /dev/null +++ b/packages/runtime/test-typecheck-debt.json @@ -0,0 +1,129 @@ +{ + "_comment": "Per-file tsc error debt of the @objectstack/runtime 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/runtime gen:test-typecheck-debt", + "_note": "SEEDED, NOT REPAIRED, and that was the card's own triage ruling rather than this author's convenience: 191 errors across 27 of this package's 214 test files, measured at 224f8ea4a0 with the workspace closure built first, on the PR that first put those files in front of tsc. Repairing them in the same change would have buried the gate under a 191-error cleanup, which is how an onboarding stops landing; the ratchet only has to shrink from here. WHERE THE 191 CAME FROM, both directions attributed: the same program under the build config's inherited NodeNext semantics reports 206, and 206 is exactly what `scripts/check-type-check-coverage.mjs` had recorded for this package in its per-PACKAGE `TEST_DEBT` ledger — so this file does not add debt, it holds the SAME population one level finer, per file and per signature, and that `TEST_DEBT` entry graduated in the same change. 19 of the 206 dissolve under this program's vitest-matching module semantics (TS2835 x13 extension-less relative imports, the TS7006 x4 above them, TS2550 x2 `Array.prototype.at`) and were about the CHECK rather than the code; collapsing that cascade EXPOSED 4 more (TS2322 x4 in src/seed-loader.test.ts, previously hidden behind an `any` from the unresolved import). 206 - 19 + 4 = 191, with no unexplained remainder. WHAT IS ALREADY GATED, and it is most of the package: 187 of the 214 test files carry no entry here at all, so any error any one of them gains is red on arrival. ⚠️ This layer holds ZERO `@ts-expect-error` directives — measured, not assumed — so unlike packages/spec and packages/client no pin was silently dead here and none reports TS2578 under this program. The cost of the gap was the 191 unreported errors and the fact that a type-level pin could not be written in this package at all; the second half is what this file makes possible. THE PILE IS CONCENTRATED, which is the useful thing for whoever pays it down: src/http-dispatcher.actions-type-dispatch.test.ts x30, src/http-dispatcher.test.ts x18, src/notifications.hono.integration.test.ts x16, src/http-dispatcher.actions-identity-addressing.test.ts x14 and src/action-body-identity.test.ts x14 are 92 of the 191, and TS18048 x91 (reads of a possibly-undefined optional) is very nearly half of the whole ledger on its own — the shape src/http-dispatcher.keys.test.ts already solved with a `responseOf()` narrowing helper. RECORDED EXACTLY, no bootstrap margin: this layer has never been gated, so the first new error in it should go red rather than be absorbed.", + "entries": { + "src/action-body-identity.test.ts": { + "TS18048: 'actionCtx' is possibly 'undefined'.": 8, + "TS2339: Property 'executionContext' does not exist on type 'never'.": 1, + "TS2493: Tuple type '…' of length '0' has no element at index '2'.": 5 + }, + "src/action-execution-calldata-query.test.ts": { + "TS2322: Type '…' is not assignable to type '…'.": 1 + }, + "src/auth-unknown-subpath.hono.integration.test.ts": { + "TS2353: Object literal may only specify known properties, and 'requireAuth' does not exist in type 'DispatcherPluginConfig'.": 1, + "TS2571: Object is of type 'unknown'.": 1 + }, + "src/dispatcher-plugin.anonymous-gate.integration.test.ts": { + "TS2339: Property 'data' does not exist on type '…'.": 1, + "TS2493: Tuple type '…' of length '0' has no element at index '1'.": 1 + }, + "src/dispatcher-plugin.ready.integration.test.ts": { + "TS18046: 'body' is of type 'unknown'.": 8 + }, + "src/domains/automation-descriptor-query-validation.test.ts": { + "TS2339: Property 'field' does not exist on type '…'.": 1 + }, + "src/domains/automation-write-capability-gate.test.ts": { + "TS2348: Value of type '…' is not callable. Did you mean to include 'new'?": 1 + }, + "src/domains/meta-item-envelope.test.ts": { + "TS18048: 'res.response' is possibly 'undefined'.": 9 + }, + "src/domains/meta-migrate-stored.test.ts": { + "TS18048: 'res.response' is possibly 'undefined'.": 6 + }, + "src/domains/meta-object-fls.test.ts": { + "TS18048: 'res.response' is possibly 'undefined'.": 4 + }, + "src/error-envelope.conformance.test.ts": { + "TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 6 + }, + "src/http-dispatcher.actions-identity-addressing.test.ts": { + "TS18048: 'res.response' is possibly 'undefined'.": 14 + }, + "src/http-dispatcher.actions-type-dispatch.test.ts": { + "TS18048: 'res.response' is possibly 'undefined'.": 24, + "TS2493: Tuple type '…' of length '0' has no element at index '1'.": 6 + }, + "src/http-dispatcher.kernel-resolver.test.ts": { + "TS2352: Conversion of type 'undefined' to type 'HttpProtocolContext' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.": 1, + "TS2493: Tuple type '…' of length '0' has no element at index '0'.": 1, + "TS2493: Tuple type '…' of length '1' has no element at index '1'.": 1 + }, + "src/http-dispatcher.keys.test.ts": { + "TS18048: 'res.response' is possibly 'undefined'.": 9 + }, + "src/http-dispatcher.mcp.test.ts": { + "TS18048: 'res.response' is possibly 'undefined'.": 11 + }, + "src/http-dispatcher.test.ts": { + "TS18048: 'mint.response' is possibly 'undefined'.": 1, + "TS18048: 'res.response' is possibly 'undefined'.": 5, + "TS2339: Property 'chat' does not exist on type '…'.": 1, + "TS2339: Property 'execute' does not exist on type '…'.": 1, + "TS2339: Property 'getLocales' does not exist on type '…'.": 2, + "TS2339: Property 'listFlows' does not exist on type '…'.": 1, + "TS2339: Property 'listInbox' does not exist on type '…'.": 1, + "TS2339: Property 'provider' does not exist on type '…'.": 1, + "TS2339: Property 'registerFlow' does not exist on type '…'.": 1, + "TS2339: Property 'route' does not exist on type '…'.": 1, + "TS2339: Property 'trigger' does not exist on type '…'.": 1, + "TS2339: Property 'user' does not exist on type 'never'.": 1, + "TS2493: Tuple type '…' of length '0' has no element at index '2'.": 1 + }, + "src/notification-schema-conformance.integration.test.ts": { + "TS18046: 'body' is of type 'unknown'.": 1, + "TS2353: Object literal may only specify known properties, and 'requireAuth' does not exist in type 'DispatcherPluginConfig'.": 1 + }, + "src/notification-schema-conformance.test.ts": { + "TS18046: 'f' is of type 'unknown'.": 1 + }, + "src/notifications.hono.integration.test.ts": { + "TS18046: 'after' is of type 'unknown'.": 2, + "TS18046: 'afterOne' is of type 'unknown'.": 1, + "TS18046: 'before' is of type 'unknown'.": 2, + "TS18046: 'body' is of type 'unknown'.": 1, + "TS18046: 'cleared' is of type 'unknown'.": 2, + "TS18046: 'list' is of type 'unknown'.": 4, + "TS18046: 'readAll' is of type 'unknown'.": 1, + "TS2353: Object literal may only specify known properties, and 'requireAuth' does not exist in type 'DispatcherPluginConfig'.": 1, + "TS2571: Object is of type 'unknown'.": 2 + }, + "src/observability/error-reporter.test.ts": { + "TS2554: Expected 0 arguments, but got 2.": 1 + }, + "src/observability/metrics.test.ts": { + "TS2554: Expected 0 arguments, but got 1.": 1, + "TS2554: Expected 0 arguments, but got 2.": 2 + }, + "src/route-parity.integration.test.ts": { + "TS18046: 'disc' is of type 'unknown'.": 4, + "TS2339: Property 'data' does not exist on type '…'.": 1, + "TS2353: Object literal may only specify known properties, and 'requireAuth' does not exist in type 'DispatcherPluginConfig'.": 1 + }, + "src/runtime.test.ts": { + "TS6133: 'PluginContext' is declared but its value is never read.": 1, + "TS6133: 'beforeEach' is declared but its value is never read.": 1 + }, + "src/sandbox/quickjs-runner.test.ts": { + "TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 4, + "TS6133: 'n' is declared but its value is never read.": 1 + }, + "src/security/resolve-execution-context.test.ts": { + "TS2322: Type '…' is not assignable to type 'never'.": 1, + "TS2339: Property '$in' does not exist on type 'object'.": 2, + "TS7006: Parameter 'object' implicitly has an 'any' type.": 1, + "TS7006: Parameter 'opts' implicitly has an 'any' type.": 1, + "TS7006: Parameter 'ql' implicitly has an 'any' type.": 1, + "TS7006: Parameter 'row' implicitly has an 'any' type.": 1, + "TS7053: Element implicitly has an 'any' type because expression of type 'any' can't be used to index type '{ sys_api_key: { id: string; key: string; revoked: boolean; user_id: string; active_organization_id: string; expires_at: string; }[]; sys_member: { user_id: string; organization_id: string; role: string; }[]; ... 4 more ...; sys_user_position: never[]; }'.": 1 + }, + "src/seed-loader.test.ts": { + "TS2322: Type '…' is not assignable to type '…'.": 4, + "TS6133: 'result' is declared but its value is never read.": 2, + "TS6133: 'type' is declared but its value is never read.": 1, + "TS6196: 'SeedLoaderRequest' is declared but never used.": 1 + } + } +} diff --git a/packages/runtime/tsconfig.test.json b/packages/runtime/tsconfig.test.json new file mode 100644 index 0000000000..808e3a73cd --- /dev/null +++ b/packages/runtime/tsconfig.test.json @@ -0,0 +1,109 @@ +// The TEST-layer type-check program (#14504), 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` / +// `**/*.spec.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 change 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 224f8ea4a0 with the workspace +// closure built first, `tsc --noEmit --listFiles -p tsconfig.json` puts 899 +// files in the program and **0** of this package's 214 `src/**/*.test.ts` among +// them — while 79 of its non-test `src/**` files ARE there, so the zero is the +// `exclude` line and not a probe that sees nothing. The directional control is +// `packages/drivers/driver-memory`, whose tsconfig carries no test exclusion: +// the same probe puts **40 of its 40** test files in the program. Under this +// file the count is **214 of 214** (1148 files total). +// `pnpm --filter @objectstack/runtime typecheck` exiting 0 was a true sentence +// carrying no information about any test file in this package. +// +// ⚠️ ONE THING THE FILING OVERSTATED, recorded so the next reader does not go +// looking for it: the card's sharpest line — "a `@ts-expect-error` written in +// any `packages/runtime` test today is a phantom check" — is a statement about +// what WOULD happen, not about an existing pin. Measured here: this layer holds +// **zero** `@ts-expect-error` directives across all 214 files, so no pin was +// silently dead and none reports TS2578 under this program. What the gap really +// cost is the other half: 191 real type errors in the test layer that no gate +// has ever reported, and no way to write a type-level pin here at all. The +// first half is now ledgered; the second is now possible. +// +// What differs from the build config, and what deliberately does NOT: +// - module semantics ONLY, plus `lib`. The tests are written and executed as +// ESM by vitest (esbuild/vite), and this package IS `"type": "module"`, so +// the build config's NodeNext compiles them as ESM too — and then demands +// explicit `.js` extensions on relative imports, which vitest does not. +// Measured cost of that mismatch here: 19 of the 206 raw diagnostics — +// TS2835 x13 (extension-less relative import), the TS7006 x4 sitting above +// them (an import that does not resolve makes every symbol it names `any`), +// and TS2550 x2 (`Array.prototype.at` against a `lib` older than ES2022). +// Those 19 are about the CHECK, never about the code. Matching vitest is +// fidelity, not laxity. No `DOM` in `lib`, unlike `packages/client`: +// nothing in this layer touches a browser global. +// - ⚠️ Collapsing that cascade EXPOSES errors as well as removing them, so +// 206 − 19 is 191 and not 187: `src/seed-loader.test.ts` gains 4 x TS2322 +// that the unresolved import had been hiding behind `any`. The two +// directions are attributed file by file below; there is no unexplained +// remainder. +// - ⛔ STRICTNESS IS UNTOUCHED. `strict`, `noUnusedLocals`, +// `noUnusedParameters`, `noImplicitReturns`, `noFallthroughCasesInSwitch` +// are inherited from the root config, and `types: ["node"]` restates +// `tsconfig.json`'s. Nothing here may loosen a type rule; if a test does not +// compile, that is the finding. ⛔ Not one `any` and not one +// `@ts-expect-error` was added to any test file to open this gate — that +// shape is what turns a real gate into a phantom one. +// - `rootDir` is INHERITED as `./src` and deliberately not widened. Unlike +// `packages/client` and `packages/rest`, this layer produces no TS6059: +// measured, every file this program admits is already under `src`. Widening +// it "to be safe" would admit files the build config does not and change +// what the gate judges, so it stays as the build config has it. +// +// `include` stops at `src`, matching the build config's root and covering all +// 214 test files. This package has no sibling `scripts/` program to keep +// separate, so unlike `objectql` and `spec` the `typecheck` chain is two links +// and not three. +// +// MEASURED at 224f8ea4a0, workspace closure built first (an error count taken +// against an unbuilt closure is not a reading — unresolved-import cascades +// inflate it): this program reports **191 errors across 27 files**, from a raw +// 206 under the inherited NodeNext semantics. That 206 is the same number +// `scripts/check-type-check-coverage.mjs` recorded for this package in its +// per-PACKAGE `TEST_DEBT` ledger, which is why 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. By code: TS18048 x91 (possibly-undefined), TS18046 x27, TS2339 +// x17, TS2493 x15, TS2345 x10, TS2322 x6, TS6133 x6, TS7006 x4, TS2554 x4, +// TS2353 x4, TS2571 x3, plus 4 singletons (TS7053, TS6196, TS2352, TS2348). +// The five heaviest files are `src/http-dispatcher.actions-type-dispatch.test.ts` +// x30, `src/http-dispatcher.test.ts` x18, +// `src/notifications.hono.integration.test.ts` x16, +// `src/http-dispatcher.actions-identity-addressing.test.ts` x14 and +// `src/action-body-identity.test.ts` x14 — 92 of the 191 between them. +// +// Every one of the 191 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 a constant total, and a file NOT listed there may have no errors at all. +// ⛔ The 191 are NOT repaired here, per this card's triage ruling: seeding the +// ledger and letting the ratchet shrink is the deliverable, and turning the +// onboarding into a 191-error cleanup is how it stops landing at all. +// +// ⚠️ 187 of the 214 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. +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "noEmit": true, + "module": "esnext", + "moduleResolution": "bundler", + "lib": ["ES2022"], + "types": ["node"] + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/scripts/check-type-check-coverage.mjs b/scripts/check-type-check-coverage.mjs index 7a070e6fdd..12fdaecc18 100644 --- a/scripts/check-type-check-coverage.mjs +++ b/scripts/check-type-check-coverage.mjs @@ -937,29 +937,35 @@ const EXEMPT = { // prior note already excluded them ("never this package's debt ... reporting on // its own inherited rootDir"). // +// ── #14504: `@objectstack/runtime` GRADUATED, and it was not paid down ────── +// +// `runtime` (206) left this ledger on 2026-09-03, under the same shape as the +// four above and for the same reason: it now has a `tsconfig.test.json` its +// `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. Not one of the 206 was repaired. +// +// The identical population is now held one level finer, per FILE and per +// SIGNATURE, in `packages/runtime/test-typecheck-debt.json`: **191 errors +// across 27 of the package's 214 test files**, measured at 224f8ea4a0 with the +// closure built. The 206 -> 191 step is the config-tier subtraction this +// ledger's top note describes, attributed in both directions with no +// remainder: -19 that dissolve under the test program's vitest-matching module +// semantics (TS2835 x13, the TS7006 x4 cascading above them, TS2550 x2) and +// +4 that collapsing the cascade EXPOSED (TS2322 x4 in +// src/seed-loader.test.ts, previously masked by an `any` from the unresolved +// import). The 206 recorded here was exact and stayed exact to the end. +// +// ⚠️ The pin half of this gate reported nothing for `runtime` in either +// direction and still does not: measured on the way out, this package's test +// layer holds ZERO `@ts-expect-error` directives, so PINS_CHECKED had no +// subject here. The hole was the 206 errors nothing read, not a dead pin. +// // So the shrink-only guarantee did not loosen here; it moved to a strictly // sharper instrument, one that also reddens on a wholesale substitution of // error IDENTITY at a constant total, which a per-package integer cannot see. const TEST_DEBT = { - '@objectstack/runtime': { - errors: 206, - note: 'TS18048 x91 (possibly-undefined), TS18046 x27, TS2339 x17, TS2493 x15, TS2835 x13, TS2345 x10, ' - + 'TS7006 x8, TS6133 x6, TS2554 x4, TS2353 x4, TS2571 x3, TS2550 x2 -- RE-TALLIED at 206 (#13408). ' - + 'The previous note carried its composition from a 227-era sweep that measured per-entry TOTALS ' - + 'only and said so; this one is a fresh per-code count of the same program the ratchet measures. ' - + 'LOWERED 217 -> 206 (#13408), and the -11 is fully attributed to ONE file: ' - + 'src/http-dispatcher.ready.test.ts held 30 TS18048 reads of the optional ' - + '`HttpDispatcherResult.response` -- 19 added by that card\'s own new /ready suite and 11 that ' - + 'pre-dated it -- and all 30 were replaced by a `responseOf()` narrowing helper, the shape already ' - + 'used by the #8287 suite in src/http-dispatcher.keys.test.ts. That card found them the hard way: ' - + 'the package `typecheck` excludes test files, so its green said nothing about the 19 it had just ' - + 'added, and only this ratchet saw them. Nothing else in the package moved. Earlier lineage: 220 -> ' - + '218 (5ab08428, one of only two entries that ever shrank; TS6133 x25 collapsed to x7 while ' - + 'possibly-undefined grew, so that net -2 hid a much larger churn in both directions) -> 227 ' - + '(e8db1a230, +9 all TS18048 in src/domains/meta-item-envelope.test.ts from #5563 / PR #5895) -> ' - + '217 (ead731756, #12723). Src graduated in #4311 (declares `typecheck`); this is purely the ' - + 'hidden test layer.', - }, '@objectstack/cli': { errors: 144, note: 'TS7006 x59 (implicit any), TS2835 x56 (NodeNext extensions), TS2339 x24, TS2307 x3, TS18046 x2. ' diff --git a/scripts/check-type-source-resolution.mjs b/scripts/check-type-source-resolution.mjs index a4070192b1..cc83534e99 100644 --- a/scripts/check-type-source-resolution.mjs +++ b/scripts/check-type-source-resolution.mjs @@ -491,12 +491,49 @@ const KNOWN_DIST_RESOLVED_TYPE_IMPORTS = { '@objectstack/service-analytics', '@objectstack/service-datasource', '@objectstack/service-package', '@objectstack/spec', '@objectstack/types', ], + // ── #14504 re-baseline, on the onboarding limb above ───────────────────── + // + // This package's `typecheck` script began naming `tsconfig.test.json`, which + // is what onboarding a test layer IS, so the PROGRAM SET moved and this entry + // is re-measured rather than widened. The nine deps after `@objectstack/core` + // that are new here -- `driver-memory`, `driver-sqlite-wasm`, + // `platform-objects`, `plugin-hono-server`, `plugin-sharing`, + // `service-analytics`, `service-job`, `service-messaging`, `service-package` + // -- satisfy CONDITION 1 by measurement and not by assertion: the gate's own + // failure text annotates every one of them `(via tsconfig.test.json)`, and a + // `--list` taken with the wiring reverted (the ONLY difference between the + // two trees) reports this entry WITHOUT any of the nine. They are reached + // only through the program this change onboarded. Six of the nine are this + // package's devDependencies, which its `src/**` cannot import at all and its + // test layer does; the other three (`driver-memory`, `driver-sqlite-wasm`, + // `plugin-hono-server`) are runtime deps whose bare specifier only the test + // layer names. + // + // CONDITION 2 -- the numbers, both from `--list` on the same checkout, the + // wiring in `packages/runtime/package.json` the only difference: + // + // before 114 programs / 78 packages, 56 non-clean, 270 package-dep pairs + // after 115 programs / 78 packages, 56 non-clean, 279 package-dep pairs + // + // so +1 program, +9 pairs, +0 entries and +0 non-clean packages: this entry + // already existed, and nothing that was clean stopped being clean. The + // ratchet is shrink-only from 279. + // + // CONDITION 3 -- reviewed as a re-baseline. `paths` is deliberately NOT the + // tool here, on the onboarding limb's own measured grounds (PR #12570): + // redirecting these specifiers to source would bill other packages' source + // diagnostics into `packages/runtime/test-typecheck-debt.json`, a ledger + // those packages cannot see and nobody can pay down -- and that ledger is + // this change's whole deliverable. '@objectstack/runtime': [ - '@objectstack/core', '@objectstack/driver-sql', '@objectstack/metadata', '@objectstack/metadata-core', + '@objectstack/core', '@objectstack/driver-memory', '@objectstack/driver-sql', + '@objectstack/driver-sqlite-wasm', '@objectstack/metadata', '@objectstack/metadata-core', '@objectstack/metadata-protocol', '@objectstack/objectql', '@objectstack/observability', - '@objectstack/plugin-auth', '@objectstack/plugin-security', '@objectstack/rest', - '@objectstack/service-cluster', '@objectstack/service-datasource', '@objectstack/spec', - '@objectstack/types', + '@objectstack/platform-objects', '@objectstack/plugin-auth', '@objectstack/plugin-hono-server', + '@objectstack/plugin-security', '@objectstack/plugin-sharing', '@objectstack/rest', + '@objectstack/service-analytics', '@objectstack/service-cluster', '@objectstack/service-datasource', + '@objectstack/service-job', '@objectstack/service-messaging', '@objectstack/service-package', + '@objectstack/spec', '@objectstack/types', ], // #14386 re-baseline (the onboarding limb above): a NEW entry, reached ONLY // through `tsconfig.typecheck.json` -- a program that card ADDED (this diff --git a/scripts/regen-artifacts.mjs b/scripts/regen-artifacts.mjs index 81c604c9ad..ab3b19303f 100644 --- a/scripts/regen-artifacts.mjs +++ b/scripts/regen-artifacts.mjs @@ -542,6 +542,28 @@ export const NOT_DRIVER_MANAGED = Object.freeze([ + 'only 6 errors over 2 files, which makes it MORE exposed to the failure this row prevents ' + 'rather than less.', }, + // ── #14504: `packages/runtime`'s starting ledger, same instrument ─────────── + // + // The sixth row this manifest adds for the mechanism, and the largest ledger + // in the family: 191 errors over 27 of the package's 214 test files. Size is + // the reason to read this row rather than skim it — a recomputation on a + // half-merged tree writes a number nobody measured, and at 191 nobody would + // spot the difference by eye. The package's `TEST_DEBT` entry in + // `scripts/check-type-check-coverage.mjs` graduated in the same change, so + // this file is now the ONLY record of that population anywhere in the tree. + { + path: 'packages/runtime/test-typecheck-debt.json', + gen: 'gen:test-typecheck-debt', + owner: '@objectstack/runtime', + 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 ledger in the family (191 errors over 27 files), which makes the failure this row ' + + 'prevents both more likely and harder to see: at that size a recomputed number reads as ' + + 'plausible, and the per-signature keys underneath it would be silently rewritten with it.', + }, { path: 'packages/sdui-parser/objectui-lockstep.json', gen: 'gen:sdui-lockstep',