diff --git a/.changeset/6465-stale-typecheck-headers.md b/.changeset/6465-stale-typecheck-headers.md new file mode 100644 index 0000000000..755b985bf4 --- /dev/null +++ b/.changeset/6465-stale-typecheck-headers.md @@ -0,0 +1,33 @@ +--- +--- + +Comment-only fix: eleven test headers across `@object-ui/app-shell` and +`@object-ui/core` still described a type-checking arrangement that no longer +exists. Two distinct stale claims, both now corrected: + +1. **"this package's tests are compiled by nothing."** Both packages graduated + in objectui#4040; each `type-check` script is now + `tsc --noEmit && tsc -p tsconfig.test.json`, and `TEST_DEBT` in + `scripts/check-type-check-coverage.mjs` is literally `{}`. +2. **Present-tense citations of `tsconfig.typetests.json`,** of which zero exist + repo-wide (objectui#4291 retired the last of them). Several headers told the + reader that a listing in such a project is what makes their assertions + load-bearing — a file the reader cannot find. + +Both matter beyond tidiness because several of these headers *prescribe*: one +said a `@ts-expect-error` here "would be read by no compiler", another that "a +new type-assertion test file is unchecked until it is added to that include +list". Both instruct the next author away from assertions that are in fact +checked, and away from the config that checks them. That is the same shape +objectui#6426 was filed and fixed for in `@object-ui/plugin-dashboard`. + +Where a header is now positive ("this file IS compiled"), the claim was +confirmed for **that file**, not inferred from the package-level coverage +reading: `tsc -p tsconfig.test.json --listFiles` lists all 8 edited app-shell +files (of 4455) and all 4 edited core files (of 634), and both projects exit 0. +Surviving mentions of `TEST_DEBT` and `tsconfig.typetests.json` in these files +are deliberate, and are now past-tense — they record why the header used to say +otherwise. + +No behaviour change, no public surface change, no assertion or directive +touched. diff --git a/packages/app-shell/src/__tests__/spec-symbol-parity.test.ts b/packages/app-shell/src/__tests__/spec-symbol-parity.test.ts index 9b7d103028..acfcde1fb8 100644 --- a/packages/app-shell/src/__tests__/spec-symbol-parity.test.ts +++ b/packages/app-shell/src/__tests__/spec-symbol-parity.test.ts @@ -48,13 +48,20 @@ * 0 — the type half of this "tripwire" was, literally, commentary. Which is the * same landmine this file's own header cites objectui#3009 for. * - * They are now compiled by `packages/app-shell/tsconfig.typetests.json`, chained - * from this package's `type-check` script, i.e. run by the CI `Type Check` job. - * That project lists its files EXPLICITLY (app-shell's wider test tree still has - * a pre-existing error backlog, tracked as TEST_DEBT), so **a new - * type-assertion test file is unchecked until it is added to that include - * list** — and `scripts/check-type-check-coverage.mjs` fails if the chaining is - * ever dropped, so the gate cannot go quiet again the way it did here. + * They are now compiled by `packages/app-shell/tsconfig.test.json`, chained from + * this package's `type-check` script (`tsc --noEmit && tsc -p tsconfig.test.json`), + * i.e. run by the CI `Type Check` job. That project takes the whole test tree by + * GLOB — `src/**\/*.test.ts` and `src/**\/*.test.tsx` — so **a new type-assertion + * test file under `src/` is checked from the moment it is written**, with nothing + * to register anywhere. + * + * That last sentence used to say the opposite, and the opposite used to be true: + * a narrow `tsconfig.typetests.json` named its files one at a time while the rest + * of this tree sat in TEST_DEBT, and a file was decoration until someone added it + * to that list. The package graduated in objectui#4040 and the narrow project was + * retired with it (objectui#4291 retired the last of them repo-wide; the debt + * table is now empty). `scripts/check-type-check-coverage.mjs` fails if the + * chaining is ever dropped, so the gate cannot go quiet again the way it did here. */ import { describe, it, expect } from 'vitest'; @@ -294,7 +301,7 @@ describe('re-exported values are the spec binding itself', () => { /** * Compile-time assertions. A violation is a `tsc` error, not a runtime failure — - * so it surfaces only under `tsconfig.typetests.json` (see the file header), not + * so it surfaces only under `tsconfig.test.json` (see the file header), not * under vitest. */ type Assert = T; diff --git a/packages/app-shell/src/utils/resolveActionParams.test.ts b/packages/app-shell/src/utils/resolveActionParams.test.ts index 4b3dc00afc..8180dc1862 100644 --- a/packages/app-shell/src/utils/resolveActionParams.test.ts +++ b/packages/app-shell/src/utils/resolveActionParams.test.ts @@ -386,7 +386,7 @@ describe('resolveActionParams — field-inherited option keys (objectui#3559)', /** * A `select` field whose options carry the full declared vocabulary. Authoring * this literal is itself the type-level half of the fix: this file is compiled - * by `tsconfig.typetests.json`, so a `RuntimeField.options` re-narrowed to + * by `tsconfig.test.json`, so a `RuntimeField.options` re-narrowed to * `{ label, value }` fails excess-property checking right here rather than * silently reverting the behaviour below. */ @@ -499,7 +499,7 @@ describe('resolveActionParams — field-inherited option keys (objectui#3559)', it('keeps `label` and `value` required on a param option (type-level)', () => { // The catch-all widens the vocabulary; it must not dissolve the two keys - // this layer itself reads. Compiled by `tsconfig.typetests.json`, so these + // this layer itself reads. Compiled by `tsconfig.test.json`, so these // assertions are checked — a re-widening to `Record< string, unknown >` // turns the unused suppressions into errors. const complete: ActionParamOption = { label: 'Standard', value: 'standard', color: 'gray' }; diff --git a/packages/app-shell/src/views/metadata-admin/inspectors/InspectorComboField.naming.types.test.tsx b/packages/app-shell/src/views/metadata-admin/inspectors/InspectorComboField.naming.types.test.tsx index 8ca29a83c6..a52ef35e84 100644 --- a/packages/app-shell/src/views/metadata-admin/inspectors/InspectorComboField.naming.types.test.tsx +++ b/packages/app-shell/src/views/metadata-admin/inspectors/InspectorComboField.naming.types.test.tsx @@ -17,18 +17,25 @@ * * ## Why this file exists separately, and why it is listed * - * The assertions below are its entire point, so it is listed in - * `packages/app-shell/tsconfig.typetests.json`. That listing is the difference - * between a pin and a decoration: the package's build tsconfig excludes - * `**\/*.test.tsx`, and vitest erases types before running, so a - * `@ts-expect-error` written in an ordinary `*.test.tsx` file in this directory - * is read by NO compiler — it neither fails when the error disappears nor when - * the error was never there. This was drafted that way first, and the mutation + * The assertions below are its entire point, and + * `packages/app-shell/tsconfig.test.json` is what makes them a pin rather than a + * decoration: it compiles every `src/**\/*.test.tsx` in the package and is + * chained off the package's `type-check` script. SOME such project is + * load-bearing — the package's build tsconfig excludes `**\/*.test.tsx` and + * vitest erases types before running, so with none of it a `@ts-expect-error` + * would be read by NO compiler, failing neither when the error disappears nor + * when it was never there. This file was drafted that way first and the mutation * run said so: making naming optional again produced a completely green - * `tsc --noEmit`. That is objectui#3009's failure verbatim (assertions that - * never ran, under a header calling them the real enforcement), and - * `tsconfig.typetests.json`'s own header warns about it — so the type-level - * cases moved here, out of `_shared.labels.test.tsx`, where they are compiled. + * `tsc --noEmit`. That is objectui#3009's failure verbatim — assertions that + * never ran, under a header calling them the real enforcement. + * + * What has changed is the SHAPE of that coverage, and it retires one reason this + * file is separate. A narrow `tsconfig.typetests.json` used to name a handful of + * files one by one, so the type-level cases were moved here, out of + * `_shared.labels.test.tsx`, to sit on that list. Coverage is by glob now and + * BOTH files are compiled (the package graduated in objectui#4040 and the narrow + * project was retired with it), so the separation is a readability preference + * today, not a requirement — a directive in either file is checked. * * The runtime `expect` at the bottom is deliberately thin: the DOM consequences * (which element carries the id, what the accessible name resolves to, that the diff --git a/packages/app-shell/src/views/metadata-admin/inspectors/_shared.labels.test.tsx b/packages/app-shell/src/views/metadata-admin/inspectors/_shared.labels.test.tsx index 6170b6f85a..de8e8f417c 100644 --- a/packages/app-shell/src/views/metadata-admin/inspectors/_shared.labels.test.tsx +++ b/packages/app-shell/src/views/metadata-admin/inspectors/_shared.labels.test.tsx @@ -426,12 +426,17 @@ describe('InspectorComboField — a combo without a visible label is still named // The type-level half of this contract — that a combo with NO name, or with // two names, does not compile — is pinned in - // `InspectorComboField.naming.types.test.tsx`, not here. A `@ts-expect-error` - // in this file would be read by no compiler: the package's build tsconfig - // excludes `**/*.test.tsx` and vitest erases types, so it would neither fail - // when the error disappeared nor when it was never there (objectui#3009). That - // sibling file is listed in `tsconfig.typetests.json`, which is what makes its - // directives load-bearing. + // `InspectorComboField.naming.types.test.tsx`, not here. That split is a + // PREFERENCE, not a constraint: do not read it as a rule against writing a + // `@ts-expect-error` in this file. It WAS a constraint when this note was + // written — the package's build tsconfig excludes `**/*.test.tsx` and vitest + // erases types, so a directive here would have failed neither when the error + // disappeared nor when it was never there (objectui#3009). + // + // `tsconfig.test.json` now compiles every `src/**/*.test.tsx` in the package, + // this file and that sibling alike, chained off the package's `type-check` + // script. A directive in either is load-bearing: when the error it expects + // stops happening, `tsc` reports the directive UNUSED (TS2578). }); /* ───────────────────────── the counter-example holds ─────────────────────── */ diff --git a/packages/app-shell/src/views/metadata-admin/previews/flow-designer-edge.types.test.ts b/packages/app-shell/src/views/metadata-admin/previews/flow-designer-edge.types.test.ts index ce358274d6..00b6d66d8d 100644 --- a/packages/app-shell/src/views/metadata-admin/previews/flow-designer-edge.types.test.ts +++ b/packages/app-shell/src/views/metadata-admin/previews/flow-designer-edge.types.test.ts @@ -13,11 +13,16 @@ * DESCRIBE a spec-rejected condition cannot send the next reader down that road * either — which is only true for as long as somebody checks, hence this file. * - * The assertions below are the file's entire point, so it is listed in - * `packages/app-shell/tsconfig.typetests.json`. Without that listing they would - * be commentary: the package's build tsconfig excludes `**\/*.test.ts`, and - * vitest erases types before running (objectui#3181 — the same trap - * `src/__tests__/spec-symbol-parity.test.ts` documents in its header). The + * The assertions below are the file's entire point, and what makes them a check + * rather than commentary is `packages/app-shell/tsconfig.test.json`: it compiles + * every `src/**\/*.test.ts` in the package, this file included, and is chained + * off the package's `type-check` script. Without some such project they WOULD be + * commentary — the package's build tsconfig excludes `**\/*.test.ts`, and vitest + * erases types before running (objectui#3181 — the same trap + * `src/__tests__/spec-symbol-parity.test.ts` documents in its header). Coverage + * is by glob, so this file earns it by living under `src/`, not by appearing on + * a list; the narrow `tsconfig.typetests.json` that used to name it was retired + * when the package graduated (objectui#4040). The * runtime case at the bottom is real too: it walks an envelope through * `conditionText`, the reader every consumer of this type goes through. */ diff --git a/packages/app-shell/src/views/metadata-admin/previews/simulator/__tests__/flow-sim-edge.types.test.ts b/packages/app-shell/src/views/metadata-admin/previews/simulator/__tests__/flow-sim-edge.types.test.ts index d45f401be7..70b720dcff 100644 --- a/packages/app-shell/src/views/metadata-admin/previews/simulator/__tests__/flow-sim-edge.types.test.ts +++ b/packages/app-shell/src/views/metadata-admin/previews/simulator/__tests__/flow-sim-edge.types.test.ts @@ -21,10 +21,14 @@ * `undefined`) and skipped envelope guards the engine evaluates. The assertions * below make the local type incapable of describing either error again. * - * The assertions ARE the file, so it is listed in - * `packages/app-shell/tsconfig.typetests.json`: the package's build tsconfig - * excludes `**\/*.test.ts` and vitest erases types before running - * (objectui#3181), so unlisted they would be commentary, not a check. + * The assertions ARE the file, and `packages/app-shell/tsconfig.test.json` is + * what makes them a check: it compiles every `src/**\/*.test.ts` in the package, + * this file included, chained off the package's `type-check` script. Uncompiled + * they would be commentary — the package's build tsconfig excludes + * `**\/*.test.ts` and vitest erases types before running (objectui#3181). + * Coverage is by glob, not by a listing: the narrow `tsconfig.typetests.json` + * that used to name this file was retired when the package graduated + * (objectui#4040). */ import { describe, it, expect } from 'vitest'; diff --git a/packages/app-shell/src/views/metadata-admin/previews/simulator/__tests__/flow-simulator.test.ts b/packages/app-shell/src/views/metadata-admin/previews/simulator/__tests__/flow-simulator.test.ts index 1596218486..9afd1ea2ed 100644 --- a/packages/app-shell/src/views/metadata-admin/previews/simulator/__tests__/flow-simulator.test.ts +++ b/packages/app-shell/src/views/metadata-admin/previews/simulator/__tests__/flow-simulator.test.ts @@ -21,12 +21,19 @@ const run = (nodes: SimNode[], edges: SimEdge[], seed = {}, mocks = {}) => { * is THE canonical persisted form, and a fixture that spells it by hand could * drift from what the spec actually emits (objectui#3216). * - * The `SimEdge` return annotation states the matching type-level claim, but do - * not read it as a proof: `tsc` never sees this file (the package tsconfig - * excludes `**\/*.test.ts`, and app-shell's test tree is still TEST_DEBT), and - * vitest erases types. The enforced version lives next door in - * `flow-sim-edge.types.test.ts`, which IS compiled — `PersistedEdge extends - * SimEdge`. + * The `SimEdge` return annotation states the matching type-level claim, and it + * is checked: `packages/app-shell/tsconfig.test.json` compiles every + * `src/**\/*.test.ts` in the package, this file included, and the package's + * `type-check` script chains it (`tsc --noEmit && tsc -p tsconfig.test.json`), + * which is what CI's Type Check job runs. That was NOT so when this note was + * written — the build tsconfig excludes `**\/*.test.ts`, app-shell's test tree + * was then TEST_DEBT, and vitest erases types, so `tsc` saw nothing here + * (objectui#3181). The package graduated in objectui#4040 and the debt table is + * now empty. + * + * Still read the pin next door in `flow-sim-edge.types.test.ts` as the stronger + * one: `PersistedEdge extends SimEdge` constrains the TYPE, where an annotation + * on this helper only constrains what this helper returns. */ const specEdge = (e: Record): SimEdge => FlowEdgeSchema.parse(e); diff --git a/packages/core/src/actions/__tests__/ActionParamDef.options.test.ts b/packages/core/src/actions/__tests__/ActionParamDef.options.test.ts index 0a261c4e35..50793ac675 100644 --- a/packages/core/src/actions/__tests__/ActionParamDef.options.test.ts +++ b/packages/core/src/actions/__tests__/ActionParamDef.options.test.ts @@ -18,12 +18,19 @@ * type and the predicate stopped narrowing action dialogs. `ActionParamOption` * now names the two keys the param layer itself uses and passes the rest through. * - * Scope of this file, stated honestly: vitest does not typecheck, and this package - * excludes its own test files from `tsc` (TEST_DEBT in - * `scripts/check-type-check-coverage.mjs`), so nothing here can fail because a - * TYPE re-narrowed. The type half is pinned where it is actually compiled — in - * `@object-ui/app-shell`'s `utils/resolveActionParams.test.ts`, which - * `tsconfig.typetests.json` lists. What these cases hold is the behavioural + * Scope of this file, stated honestly: vitest does not typecheck, but this file + * IS compiled — `packages/core/tsconfig.test.json` takes the package's test tree + * by glob and is chained off the package's `type-check` script. That was not so + * when this note was written: `@object-ui/core` was then TEST_DEBT in + * `scripts/check-type-check-coverage.mjs` and nothing here could fail for a type + * reason at all. The package graduated in objectui#4040 and the debt table is now + * empty. Note what still limits the type reach of THIS file specifically: the + * deliberate `as OptionLike[]` seam described below opts its cases out of the + * narrowing check, compiler or no compiler. + * + * So the type half stays pinned where the narrowing actually bites — in + * `@object-ui/app-shell`'s `utils/resolveActionParams.test.ts`, compiled by that + * package's own `tsconfig.test.json`. What these cases hold is the behavioural * agreement: an option list of the shape a resolved param carries is filtered by * this package's own predicate reader, per option, on the keys it declares. * diff --git a/packages/core/src/actions/__tests__/actionDef-closed-surface.test.ts b/packages/core/src/actions/__tests__/actionDef-closed-surface.test.ts index f2855f2fc8..45d13007ed 100644 --- a/packages/core/src/actions/__tests__/actionDef-closed-surface.test.ts +++ b/packages/core/src/actions/__tests__/actionDef-closed-surface.test.ts @@ -32,16 +32,18 @@ * diagnostics against a control interface carrying nothing but an index * signature — which is what proves the REJECTIONS come from the promotion and * not from some unrelated error. This file states the same contract as ordinary - * TypeScript that CI compiles directly (via `tsconfig.typetests.json`), so the + * TypeScript that CI compiles directly (via `tsconfig.test.json`), so the * pin survives even if the harness's compiler-host plumbing ever breaks, and a * reader can see the rejected spellings without decoding a test harness. * * These assertions are TYPES: this package's own `tsconfig.json` is the BUILD - * config and excludes `src/**` test files, so without the explicit entry in - * `tsconfig.typetests.json` (chained off `type-check`, enforced by - * `scripts/check-type-check-coverage.mjs`) nothing would compile this file and - * every pin below would be decoration — the "declared != enforced" landmine - * objectstack#4115 exists to remove. + * config and excludes `src/**` test files, so without `tsconfig.test.json` + * (which takes the test tree by GLOB, is chained off `type-check`, and is + * enforced by `scripts/check-type-check-coverage.mjs`) nothing would compile this + * file and every pin below would be decoration — the "declared != enforced" + * landmine objectstack#4115 exists to remove. There is no list entry to earn: + * the narrow `tsconfig.typetests.json` that once named this file by hand was + * retired when the package graduated (objectui#4040). */ import { describe, it, expect, vi } from 'vitest'; diff --git a/packages/core/src/actions/__tests__/actionKeys.types.test.ts b/packages/core/src/actions/__tests__/actionKeys.types.test.ts index c33af59c65..68b83a16d6 100644 --- a/packages/core/src/actions/__tests__/actionKeys.types.test.ts +++ b/packages/core/src/actions/__tests__/actionKeys.types.test.ts @@ -133,7 +133,7 @@ const CASES: readonly Case[] = [ // `rejected: true` row here goes red for a reason that has nothing to do with // `ActionDef`. Measured: green locally after a build, red in CI without one. // - // `tsconfig.typetests.json` has no such problem — it is a real project in the + // `tsconfig.test.json` has no such problem — it is a real project in the // dependency graph, so CI's Type Check job builds `@object-ui/types` before // compiling it, and the `@ts-expect-error` on `{ description: 42 }` there is // enforced for real. Splitting the two `description` pins out is therefore diff --git a/packages/core/src/utils/__tests__/dataset-result-field-spec-parity.test.ts b/packages/core/src/utils/__tests__/dataset-result-field-spec-parity.test.ts index 622fba08a7..c049aed6fc 100644 --- a/packages/core/src/utils/__tests__/dataset-result-field-spec-parity.test.ts +++ b/packages/core/src/utils/__tests__/dataset-result-field-spec-parity.test.ts @@ -20,11 +20,17 @@ * The assertions below are TYPES. `Assert< Equal< Local, Spec > >` is a compile * error or it is nothing — and this package's own `tsconfig.json` is the BUILD * config, which excludes every `.test.ts` file under `src` (correctly: a test - * must not emit into `dist`), while `@object-ui/core` is still in - * `scripts/check-type-check-coverage.mjs`'s TEST_DEBT, so no other `tsc` - * invocation reads this tree either. `packages/core/tsconfig.typetests.json` - * lists this file explicitly and is chained off the package's `type-check` - * script; without that project these pins would be the "declared != enforced" + * must not emit into `dist`). What compiles them is + * `packages/core/tsconfig.test.json`, which takes the package's test tree by + * glob — this file included — and is chained off the package's `type-check` + * script (`tsc --noEmit && tsc -p tsconfig.test.json`), the script CI's Type + * Check job runs. That coverage arrived late: `@object-ui/core` sat in + * `scripts/check-type-check-coverage.mjs`'s TEST_DEBT with a narrow + * `tsconfig.typetests.json` naming this file by hand, until the package + * graduated in objectui#4040 and the narrow project was retired with it. The + * debt table is now empty. + * + * Without SOME such project these pins would be the "declared != enforced" * landmine objectstack#4115 exists to remove, sitting inside a guard for it * (objectui#3009 found precisely that: reverting a derived alias produced zero * errors under a header calling the assertions "the real enforcement").