[GH-ISSUE #3164] fix(ci): invalidate compiler caches for module scopes and imported docs #1103

Closed
opened 2026-10-15 18:31:04 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @N0zoM1z0 on GitHub (Oct 14, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/3164

Originally assigned to: @N0zoM1z0 on GitHub.

Compiler caches can return success after a tracked input changes the TypeScript program into an invalid one. Reproduced on current main, 500e32399a3bc827e17fb4adaa97db3bc0df29b5, with Node 24.18.0, npm 11.16.0 and the locked Turbo 2.11.7. This is independent of the documentation selector fixed in #3119.

Actual repository reproduction

In a clean, isolated worktree with locked dependencies, use a private temporary Turbo cache:

  1. Run turbo run typecheck compile --cache=local:rw --cache-dir <private-cache>: all three tasks (including metadata:check) succeed, with zero cache hits.
  2. Add src/package.json containing {"type":"commonjs"}. The existing TypeScript program uses NodeNext and verbatimModuleSyntax; its ESM declarations are now invalid in that package scope.
  3. The actual task hashes remain unchanged: compile=07142d671fc155a9, typecheck=f1006d56f4a49a79.
  4. Run the same Turbo command: exit 0, 3/3 cached.
  5. Run the real compiler directly, tsc -p tsconfig.build.json --noEmit --pretty false: exit 1, with CommonJS/ESM diagnostics.

The manifest was removed afterward, and the worktree is clean. The private cache was discarded, so this control does not poison ordinary development caches. This was the real repository/compiler/bundler pipeline, not a mocked checker.

Documentation variants

A separate Git fixture uses the production typecheck task definition, real compiler, current tsconfig.json, and a VitePress config importing a typed helper:

  • Warm the valid task, then assign a string to a numeric export in the imported helper. Turbo still exits 0 with the same key; direct tsc exits 1 with TS2322.
  • Warm the valid task, then add a CommonJS package manifest under docs/.vitepress/. Again the key is unchanged, Turbo returns cached success, and direct TypeScript fails.
  • The planner currently treats a documentation package.json as documentation-only. Such module-scope metadata needs the compiler lane as well as documentation validation.

Ownership gap and proposed correction

compile hashes TypeScript source but omits nested source package manifests. typecheck also hashes only the VitePress config itself, omitting imported documentation helpers and nested package scopes affecting its owned source/declaration roots. The root package.json is already an automatic Turbo input; it does not cover these nested manifests.

Track the real compiler inputs at their owning tasks, and route documentation package-scope changes to code checks. Keep the patterns scoped to compiler-owned roots, preserve Markdown reuse and generated-output exclusions, and retain all ordinary test/coverage gates. Do not disable caching or add unrelated checker rules merely because a hash is unchanged.

Required validation

  • Regression controls must fail on this baseline for the correct reason, using real TypeScript and Turbo cold/warm execution.
  • Imported helper and module-scope faults must invalidate the appropriate checker; runtime compilation should remain reusable for documentation-only inputs.
  • Markdown and irrelevant generated VitePress output must retain healthy cache reuse.
  • Re-run the real repository fault control after the fix, restore valid build artifacts, then run relevant static, selection, discovery and application checks.

The whole real-repository fault-control sequence completed in 27.5 s, 161.7 s user+system CPU, with sampled peak summed process-family RSS 5,838 MiB (200 ms samples; shared pages can be counted twice). These are validation costs, not an acceleration claim. A cache hit returning the wrong result is not a performance improvement.

Additional confirmed inputs found during implementation review: imported source .d.mts, test .d.cts, and script .d.cts declarations were also absent from compiler task inputs. Three real TypeScript/Turbo negative controls each reused cached success after the exported literal type changed incompatibly (the compiler should report TS2322). These failed against the first implementation and are fixed by tracking the corresponding TypeScript/declaration extensions in the owning roots. Markdown and generated documentation reuse remain covered.

Originally created by @N0zoM1z0 on GitHub (Oct 14, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/3164 Originally assigned to: @N0zoM1z0 on GitHub. Compiler caches can return success after a tracked input changes the TypeScript program into an invalid one. Reproduced on current `main`, `500e32399a3bc827e17fb4adaa97db3bc0df29b5`, with Node 24.18.0, npm 11.16.0 and the locked Turbo 2.11.7. This is independent of the documentation selector fixed in #3119. ### Actual repository reproduction In a clean, isolated worktree with locked dependencies, use a private temporary Turbo cache: 1. Run `turbo run typecheck compile --cache=local:rw --cache-dir <private-cache>`: all three tasks (including `metadata:check`) succeed, with zero cache hits. 2. Add `src/package.json` containing `{"type":"commonjs"}`. The existing TypeScript program uses NodeNext and `verbatimModuleSyntax`; its ESM declarations are now invalid in that package scope. 3. The actual task hashes remain unchanged: `compile=07142d671fc155a9`, `typecheck=f1006d56f4a49a79`. 4. Run the same Turbo command: exit **0**, **3/3 cached**. 5. Run the real compiler directly, `tsc -p tsconfig.build.json --noEmit --pretty false`: exit **1**, with CommonJS/ESM diagnostics. The manifest was removed afterward, and the worktree is clean. The private cache was discarded, so this control does not poison ordinary development caches. This was the real repository/compiler/bundler pipeline, not a mocked checker. ### Documentation variants A separate Git fixture uses the production `typecheck` task definition, real compiler, current `tsconfig.json`, and a VitePress config importing a typed helper: - Warm the valid task, then assign a string to a numeric export in the imported helper. Turbo still exits 0 with the same key; direct `tsc` exits 1 with TS2322. - Warm the valid task, then add a CommonJS package manifest under `docs/.vitepress/`. Again the key is unchanged, Turbo returns cached success, and direct TypeScript fails. - The planner currently treats a documentation `package.json` as documentation-only. Such module-scope metadata needs the compiler lane as well as documentation validation. ### Ownership gap and proposed correction `compile` hashes TypeScript source but omits nested source package manifests. `typecheck` also hashes only the VitePress config itself, omitting imported documentation helpers and nested package scopes affecting its owned source/declaration roots. The root `package.json` is already an automatic Turbo input; it does not cover these nested manifests. Track the real compiler inputs at their owning tasks, and route documentation package-scope changes to code checks. Keep the patterns scoped to compiler-owned roots, preserve Markdown reuse and generated-output exclusions, and retain all ordinary test/coverage gates. Do not disable caching or add unrelated checker rules merely because a hash is unchanged. ### Required validation - Regression controls must fail on this baseline for the correct reason, using real TypeScript and Turbo cold/warm execution. - Imported helper and module-scope faults must invalidate the appropriate checker; runtime compilation should remain reusable for documentation-only inputs. - Markdown and irrelevant generated VitePress output must retain healthy cache reuse. - Re-run the real repository fault control after the fix, restore valid build artifacts, then run relevant static, selection, discovery and application checks. The whole real-repository fault-control sequence completed in 27.5 s, 161.7 s user+system CPU, with sampled peak summed process-family RSS 5,838 MiB (200 ms samples; shared pages can be counted twice). These are validation costs, not an acceleration claim. A cache hit returning the wrong result is not a performance improvement. Additional confirmed inputs found during implementation review: imported source `.d.mts`, test `.d.cts`, and script `.d.cts` declarations were also absent from compiler task inputs. Three real TypeScript/Turbo negative controls each reused cached success after the exported literal type changed incompatibly (the compiler should report TS2322). These failed against the first implementation and are fixed by tracking the corresponding TypeScript/declaration extensions in the owning roots. Markdown and generated documentation reuse remain covered.
bsakaguchi 2026-10-15 18:31:04 +00:00
  • closed this issue
  • added the
    bug
    label
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#1103
No description provided.