From 5982541bbfd4540778a451a30ae8922126ca60a4 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 8 Sep 2026 01:35:29 +0000 Subject: [PATCH] docs(core,rest): the closed-set pin headers stop citing a typecheck script core has Both headers explained the pins' placement with "`@objectstack/core` has no `typecheck` script (it is a type-check DEBT ledger entry)". False on this tree: #14613 split a `tsconfig.test.json` out of core's build config and core's `typecheck` names it via `check:test-typecheck --project`, so a directive in core's test layer is compiled, and core carries no DEBT entry either. The pins do not move. The placement conclusion stands on the reason that is true and does not depend on any package's script list: the rest package's test program resolves `@objectstack/core` to the BUILT `dist/index.d.ts`, the contract consumers resolve, while core's own program compiles core's `src` and would read `./types.ts` instead. The rest header also still said the old `type?: string` was refused by the Zod gate "at parse". Measured false (#16049, from #15638): `PluginSchema` had no runtime caller and kernel plugin objects were never parsed. The refusal is on the boot path now -- `PluginLoader.validatePluginContract` runs `PluginSchema` over every plugin object `kernel.use()` loads -- which `packages/core/src/types.ts` already records and this header did not. Comment-only: no pin moves, no `@ts-expect-error` added or deleted, no case touched, and the ratchet and ablation paragraphs are unchanged. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01ADLdAs2pVcH17h9tZKWMBg --- .../core/src/plugin-type-closed-set.test.ts | 21 +++++++--- .../src/plugin-type-closed-set.pin.test.ts | 41 ++++++++++++++----- 2 files changed, 45 insertions(+), 17 deletions(-) diff --git a/packages/core/src/plugin-type-closed-set.test.ts b/packages/core/src/plugin-type-closed-set.test.ts index f7bfcb9b0e..787a2f1365 100644 --- a/packages/core/src/plugin-type-closed-set.test.ts +++ b/packages/core/src/plugin-type-closed-set.test.ts @@ -14,12 +14,21 @@ // The COMPILE-TIME half — a non-member literal or a `string`-typed value no // longer type-checks against the PUBLISHED `Plugin.type` — lives in // `packages/rest/src/plugin-type-closed-set.pin.test.ts`, deliberately NOT -// here: `@objectstack/core` has no `typecheck` script (type-check DEBT ledger -// entry), so a `@ts-expect-error` in this package is a phantom pin no tsc -// program a `typecheck` script runs would ever evaluate — -// `check:type-check-coverage` refuses exactly that. The rest package's -// `tsconfig.test.json` program is compiled by its `typecheck` script and reads -// core's BUILT `.d.ts`, so the pin over there guards the published contract. +// here. The rest package's `tsconfig.test.json` program is compiled by its +// `typecheck` script and resolves `@objectstack/core` to core's BUILT +// `dist/index.d.ts`, so the pin over there guards the contract consumers +// actually resolve. +// +// ⚠️ This used to read as though the split were forced — that +// `@objectstack/core` "has no `typecheck` script (type-check DEBT ledger +// entry)", making a `@ts-expect-error` here a phantom pin +// `check:type-check-coverage` refuses. False on this tree: #14613 split a +// `tsconfig.test.json` out of the build config, `package.json`'s `typecheck` +// NAMES it (via `check:test-typecheck --project`), and this package holds no +// DEBT entry. A directive here WOULD be evaluated — against `./types.ts`, +// this package's own SOURCE. The published `.d.ts` is what those pins are +// about and only the rest program reads it, which is a reason that outlives +// any package's script list. import { describe, it, expect } from 'vitest'; import { CORE_PLUGIN_TYPES, PluginSchema } from '@objectstack/spec/kernel'; diff --git a/packages/rest/src/plugin-type-closed-set.pin.test.ts b/packages/rest/src/plugin-type-closed-set.pin.test.ts index beaeb3d690..3cf35c6109 100644 --- a/packages/rest/src/plugin-type-closed-set.pin.test.ts +++ b/packages/rest/src/plugin-type-closed-set.pin.test.ts @@ -3,18 +3,37 @@ // COMPILE-TIME pins for the closed `Plugin.type` set on the PUBLISHED surface // of `@objectstack/core` (#13925): `type?: PluginType`, a union DERIVED from // the spec's `CORE_PLUGIN_TYPES` (`'standard' | (typeof CORE_PLUGIN_TYPES)[number]`), -// replacing the `type?: string` that let any spelling through while the Zod -// gate (`PluginSchema.type`) refused it at parse. +// replacing the `type?: string` that let any spelling through. // -// Why the pins live in THIS package: `@objectstack/core` has no `typecheck` -// script (it is a type-check DEBT ledger entry), so a `@ts-expect-error` there -// is a phantom pin — no tsc program a `typecheck` script runs ever evaluates -// it, and `check:type-check-coverage` refuses it. This package's -// `tsconfig.test.json` program IS run by its `typecheck` script -// (`check:test-typecheck`, EXACT per-file ratchet: an unlisted file must stay -// at zero errors), and it resolves `@objectstack/core` to the BUILT -// `dist/index.d.ts` — so these directives pin the contract consumers actually -// see. Same placement as `plugin-metadata-retired-fields.pin.test.ts`. +// ⚠️ This header used to end that sentence "while the Zod gate +// (`PluginSchema.type`) refused it at parse". Measured false (#16049, from +// #15638): `PluginSchema` had no runtime caller, kernel plugin objects were +// never parsed, and an off-set `type` was accepted and stored verbatim — the +// compiler was the only arm there was. Since #16049 the runtime arm is on the +// BOOT path: `PluginLoader.validatePluginContract` runs `PluginSchema` over +// every plugin object `kernel.use()` loads and raises +// `PLUGIN_CONTRACT_VIOLATION` naming the first violated key. +// `packages/core/src/types.ts` was corrected when that was measured; this +// header carried the same wording and was missed. +// +// Why the pins live in THIS package: this package's `tsconfig.test.json` +// program IS run by its `typecheck` script (`check:test-typecheck`, EXACT +// per-file ratchet: an unlisted file must stay at zero errors), and it +// resolves `@objectstack/core` to the BUILT `dist/index.d.ts` — so these +// directives pin the contract consumers actually see. +// +// ⚠️ NOT because core cannot compile a pin — this header used to say +// `@objectstack/core` "has no `typecheck` script (it is a type-check DEBT +// ledger entry)", and that is false on this tree. #14613 split a +// `tsconfig.test.json` out of core's build config and core's `typecheck` +// NAMES it (via `check:test-typecheck --project`), so a `@ts-expect-error` +// over there is compiled rather than the phantom pin +// `check:type-check-coverage` refuses, and core holds no DEBT entry. What +// core's program cannot do is read core's own PUBLISHED surface: it compiles +// `src`, so a pin there would read `./types.ts` — the declaration — not the +// `.d.ts` the build emits from it. That reason is durable where the +// script-list one was not. Same placement as +// `plugin-metadata-retired-fields.pin.test.ts`. // // Failure channel, proven able to fail by ablation on the narrowing PR: // reverting `type?: PluginType` to `type?: string` (and rebuilding core's