From b45912f4b50a8c5e1736b5cc4c98ac98b67adad9 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 11 Sep 2026 17:18:05 +0000 Subject: [PATCH] docs(rest): replace the slot-lookup pin's false "no tsc program compiles this" premise with the measured reason MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `rest-api-plugin-slot-lookups.test.ts`'s docblock justified its runtime pin by asserting that `packages/rest` "declares no `typecheck` script (it is a DEBT/TEST_DEBT ledger entry), so NO tsc program compiles this file". Measured on this tree, all three halves are false: - `@objectstack/rest`'s `typecheck` is `tsc --noEmit && pnpm check:test-typecheck`, whose second half runs `--project tsconfig.test.json`; - the `DEBT` object literal in `scripts/check-type-check-coverage.mjs` holds 4 keys and `TEST_DEBT` holds 1 (`@objectstack/http-conformance`); neither names `@objectstack/rest`; - `tsc --listFiles -p tsconfig.test.json` puts this file in a 742-file program (firing controls: `rest-api-plugin.ts` and `rest.test.ts` both present; nonsense control: absent), while the build program `tsconfig.json` carries 558 files and zero `.test.ts`. So the "a type-level pin here would be a phantom" ground is dead: a `@ts-expect-error` written here is live. The docblock now states the reason that actually holds, derived from this file's own subject — the property is not expressible as a type, because the providers are positional parameters sharing one identical type and the slot name each resolves is a bare `string` literal handed to `getService(name: string): T`, so "this argument resolves that slot" is a value-level identity only invocation can observe. Docblock only: no pin moved, no directive deleted, no case body touched. Claude-Session: https://claude.ai/code/session_01TSf4DV7ziu4V5j73e46b7c Co-authored-by: Claude --- .../src/rest-api-plugin-slot-lookups.test.ts | 35 +++++++++++++++---- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/packages/rest/src/rest-api-plugin-slot-lookups.test.ts b/packages/rest/src/rest-api-plugin-slot-lookups.test.ts index 05e1002ca9..4be1283dfc 100644 --- a/packages/rest/src/rest-api-plugin-slot-lookups.test.ts +++ b/packages/rest/src/rest-api-plugin-slot-lookups.test.ts @@ -11,13 +11,34 @@ * (`(environmentId?) => Promise`), so a provider that resolves the * wrong slot name is assignable everywhere and invisible to the compiler. * - * Why a RUNTIME pin and not a type-level one. `packages/rest/tsconfig.json` - * excludes its `.test.ts` files and the package declares no `typecheck` script - * (it is a DEBT/TEST_DEBT ledger entry), so NO tsc program compiles this file. A - * `@ts-expect-error` or an `Assert< Equal< … > >` written here would evaluate - * never and stay green if it were deleted — the phantom-check shape AGENTS.md - * bans and #5286 / #5449 paid for. What IS checkable here is the wiring, so - * that is what this pins: + * Why a RUNTIME pin and not a type-level one. ⚠️ NOT because nothing compiles + * this file. `packages/rest/tsconfig.json` does exclude its `.test.ts` files, + * but that is the BUILD config alone: the sibling `tsconfig.test.json` puts + * this layer back in front of tsc (`include: ["src/**\/*"]`) and the package's + * own `typecheck` NAMES it — `tsc --noEmit && pnpm check:test-typecheck`, whose + * second half runs `--project tsconfig.test.json`. This header used to say the + * package "declares no `typecheck` script (it is a DEBT/TEST_DEBT ledger + * entry), so NO tsc program compiles this file"; all three halves are false on + * this tree — the script exists, neither the `DEBT` nor the `TEST_DEBT` object + * literal in `scripts/check-type-check-coverage.mjs` names `@objectstack/rest`, + * and `tsc --listFiles -p tsconfig.test.json` lists this file. A + * `@ts-expect-error` written here is LIVE and reports TS2578 the moment it + * suppresses nothing — not the phantom-check shape AGENTS.md bans and + * #5286 / #5449 paid for. + * + * It is a runtime pin for a reason that outlives any script list: the property + * is not expressible as a type. `RestServer` receives the providers as + * POSITIONAL parameters declared with one identical type, + * `(environmentId?: string) => Promise`, so every permutation + * of them is assignable and no assertion over that signature can go red when + * the wiring is wrong. And the slot name a provider resolves is a string + * literal handed to `PluginContext.getService(name: string): T` — a bare + * `string` parameter whose `T` the CALLER supplies, so neither the argument type + * nor the result type carries evidence of which slot was read. "This argument + * resolves that slot" is a value-level identity between a position and a literal + * inside a closure body: only invoking the closure observes it, and the same + * holds for the SET of slot names, which exists only as the `getService` calls + * `init`/`start` actually make. So that is what this pins: * * 1. every provider resolves the slot it is NAMED for (the mapping the B4 * types assert, verified against the registry), and