chore(build): make typecheck cacheable and incremental - #372
Conversation
…oFile tsc -p tsconfig.json --noEmit produced no artifact, so turbo's typecheck task (no outputs declared) was always a cold, non-incremental full check on every cache miss across all 50 packages with a typecheck script. Add per-package incremental:true + tsBuildInfoFile:".tsbuildinfo" to every package/app tsconfig a typecheck script actually runs (tsBuildInfoFile resolves relative to the declaring config, so this must be per-package, not in tsconfig.base.json, or all packages would collide on one file). Declare outputs:[".tsbuildinfo", "**/.tsbuildinfo"] on turbo.json's typecheck task so the buildinfo is cached and content-hashed alongside the task. Packages that also have a tsconfig.build.json (declaration-emit config used by the build script) get their own distinct tsBuildInfoFile (.build.tsbuildinfo) there: it extends the same tsconfig.json, so it would otherwise silently inherit the same buildinfo path as the typecheck config and race with it when turbo runs a package's build and typecheck tasks concurrently (build has no dependency on that package's own typecheck), corrupting the shared file and dropping declaration output under load. Verified: cold `turbo run typecheck --force` green across all 92 tasks; an immediate re-run is FULL TURBO (92/92 cached); planting a type error in @conciv/ui-kit-system correctly invalidates and fails @conciv/ui-kit-tap's typecheck (cache miss, not a stale hit) once reverted. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Warning Review limit reached
Next review available in: 5 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (72)
Comment |
There was a problem hiding this comment.
Pull request overview
Makes TypeScript typechecks incremental and allows Turbo to cache their build-info artifacts without build/typecheck write conflicts.
Changes:
- Enables incremental typechecking across all 50 workspaces.
- Caches root and nested
.tsbuildinfooutputs. - Gives declaration builds separate
.build.tsbuildinfofiles.
Reviewed changes
Copilot reviewed 72 out of 72 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
turbo.json |
Caches typecheck build-info outputs. |
packages/vitest-config/tsconfig.json |
Enables incremental typechecking. |
packages/uno-preset/tsconfig.json |
Enables incremental typechecking. |
packages/uno-preset/tsconfig.build.json |
Isolates build metadata. |
packages/ui-kit-terminal/tsconfig.json |
Enables incremental typechecking. |
packages/ui-kit-terminal/tsconfig.build.json |
Isolates build metadata. |
packages/ui-kit-tap/tsconfig.json |
Enables incremental typechecking. |
packages/ui-kit-tap/tsconfig.build.json |
Isolates build metadata. |
packages/ui-kit-system/tsconfig.json |
Enables incremental typechecking. |
packages/ui-kit-system/tsconfig.build.json |
Isolates build metadata. |
packages/ui-kit-chat/tsconfig.json |
Enables incremental typechecking. |
packages/ui-kit-chat/tsconfig.build.json |
Isolates build metadata. |
packages/ui-kit-chat-tools/tsconfig.json |
Enables incremental typechecking. |
packages/ui-kit-chat-tools/tsconfig.build.json |
Isolates build metadata. |
packages/try/tsconfig.json |
Enables incremental typechecking. |
packages/tools/tsconfig.json |
Enables incremental typechecking. |
packages/storage-history/tsconfig.json |
Enables incremental typechecking. |
packages/solid/tsconfig.json |
Enables incremental typechecking. |
packages/solid-streamdown/tsconfig.json |
Enables incremental typechecking. |
packages/solid-streamdown/tsconfig.build.json |
Isolates build metadata. |
packages/solid-diffs/tsconfig.json |
Enables incremental typechecking. |
packages/solid-diffs/tsconfig.build.json |
Isolates build metadata. |
packages/serve/tsconfig.json |
Enables incremental typechecking. |
packages/react/tsconfig.json |
Enables incremental typechecking. |
packages/publish/tsconfig.json |
Enables incremental typechecking. |
packages/protocol/tsconfig.json |
Enables incremental typechecking. |
packages/protocol/tsconfig.build.json |
Isolates build metadata. |
packages/preact/tsconfig.json |
Enables incremental typechecking. |
packages/plugin/tsconfig.json |
Enables incremental typechecking. |
packages/page/tsconfig.json |
Enables incremental typechecking. |
packages/oxlint-plugin/tsconfig.json |
Enables incremental typechecking. |
packages/mascot/tsconfig.json |
Enables incremental typechecking. |
packages/it/tsconfig.json |
Enables incremental typechecking. |
packages/harness/tsconfig.json |
Enables incremental typechecking. |
packages/harness-testkit/tsconfig.json |
Enables incremental typechecking. |
packages/harness-init/tsconfig.json |
Enables incremental typechecking. |
packages/grab/tsconfig.json |
Enables incremental typechecking. |
packages/extensions/whiteboard/tsconfig.json |
Enables incremental typechecking. |
packages/extensions/whiteboard/tsconfig.build.json |
Isolates build metadata. |
packages/extensions/try-it/tsconfig.json |
Enables incremental typechecking. |
packages/extensions/try-it/tsconfig.build.json |
Isolates build metadata. |
packages/extensions/test-runner/tsconfig.json |
Enables incremental typechecking. |
packages/extensions/test-runner/tsconfig.build.json |
Isolates build metadata. |
packages/extensions/terminal/tsconfig.json |
Enables incremental typechecking. |
packages/extensions/terminal/tsconfig.build.json |
Isolates build metadata. |
packages/extensions/tanstack/tsconfig.json |
Enables incremental typechecking. |
packages/extensions/tanstack/tsconfig.build.json |
Isolates build metadata. |
packages/extensions/tanstack/test/host/tsconfig.json |
Adds nested incremental metadata. |
packages/extensions/tanstack/test/host/conciv/tsconfig.json |
Adds nested incremental metadata. |
packages/extensions/recorder/tsconfig.json |
Enables incremental typechecking. |
packages/extensions/recorder/tsconfig.build.json |
Isolates build metadata. |
packages/extensions/page/tsconfig.json |
Enables incremental typechecking. |
packages/extensions/page/tsconfig.build.json |
Isolates build metadata. |
packages/extensions/ios/tsconfig.json |
Enables incremental typechecking. |
packages/extensions/ios/tsconfig.build.json |
Isolates build metadata. |
packages/extension/tsconfig.json |
Enables incremental typechecking. |
packages/extension-testkit/tsconfig.json |
Enables incremental typechecking. |
packages/extension-compiler/tsconfig.json |
Enables incremental typechecking. |
packages/embed/tsconfig.json |
Enables incremental typechecking. |
packages/embed/tsconfig.build.json |
Isolates build metadata. |
packages/db/tsconfig.json |
Enables incremental typechecking. |
packages/core/tsconfig.json |
Enables incremental typechecking. |
packages/contract/tsconfig.json |
Enables incremental typechecking. |
packages/client/tsconfig.json |
Enables incremental typechecking. |
packages/cli/tsconfig.json |
Enables incremental typechecking. |
packages/bundle-size/tsconfig.json |
Enables incremental typechecking. |
e2e/e2e-utils/tsconfig.json |
Enables incremental typechecking. |
apps/storybook/tsconfig.json |
Enables incremental typechecking. |
apps/site/tsconfig.json |
Enables incremental typechecking. |
apps/examples/tanstack-start/tsconfig.json |
Enables incremental app typechecking. |
apps/examples/tanstack-start/conciv/extensions/tsconfig.json |
Adds nested incremental metadata. |
apps/conciv/tsconfig.json |
Enables incremental typechecking. |
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Before
turbo.json'stypechecktask declared nooutputs:Every package's
typecheckscript istsc -p tsconfig.json --noEmit, which produces no artifact.With no output to hash/restore, tsc had no incremental state either, so every cache miss was a full
cold typecheck — across all 50 packages/apps with a
typecheckscript (the dispatch estimated 40 froma shallower glob; the real count, including
packages/extensions/*ande2e/e2e-utils, is 50).After
typecheckscript actually runs gets"incremental": trueand"tsBuildInfoFile": ".tsbuildinfo"incompilerOptions. This must be per-package rather than intsconfig.base.json:tsBuildInfoFileresolves relative to the config file that declares it(TS docs), so putting it in the shared
base would make all packages collide on one root
.tsbuildinfo.turbo.json'stypechecktask now declares"outputs": [".tsbuildinfo", "**/.tsbuildinfo"](theglob also covers nested tsconfigs, e.g.
@conciv/extension-tanstack'stest/host/tsconfig.jsonandtest/host/conciv/tsconfig.json, and the example app'sconciv/extensions/tsconfig.json)..gitignore's existing*.tsbuildinfo(line 4) already covers the per-package.tsbuildinfopath —confirmed with
git check-ignore, no duplicate entry added.A bug this surfaced and fixed along the way
18 packages also have a
tsconfig.build.json(declaration-emit config used by thebuildscript, e.g.tsc -p tsconfig.build.json) thatextends: "./tsconfig.json". Sincebuildhas no dependency on thatsame package's own
typechecktask, turbo can run both concurrently — and becausetsconfig.build.jsoninherits
tsBuildInfoFilefrom the tsconfig.json I just edited, bothtscinvocations would write tothe same
.tsbuildinfofile at once. This reproduced as real breakage: a forced full run intermittentlydropped
.d.tsoutput for@conciv/ui-kit-system,@conciv/protocol,@conciv/solid-streamdown, etc.,which cascaded into downstream build failures. Fixed by giving each of those 18
tsconfig.build.jsonfiles its own distinct
"tsBuildInfoFile": ".build.tsbuildinfo"(still covered by the same gitignoreglob, verified separately).
Verification (foreground, full machine under load ~260-300 all day)
1. Cold run — green.
2. Warm run — full cache hit.
3. The one that matters — a dependency change still invalidates dependents, and doesn't get a false
cache hit. Planted a real type error in
@conciv/ui-kit-system(LIST_PANEL_MESSAGEchanged from astringexport to anumber), which is consumed asclass={LIST_PANEL_MESSAGE}in@conciv/ui-kit-tap/src/suggestion-listbox.tsx:Cache miss (not a stale hit) and a genuine failure at the exact usage site. Reverted the planted error
afterward and confirmed a clean tree (
git statusshows only the intended 72-file diff — 53tsconfig.json+ 18tsconfig.build.json+turbo.json) and that the re-run goes back to a legitimatecached pass.
Also confirmed: 71
.tsbuildinfofiles were produced across the tree after the cold run, andgit statusis clean of them (all covered by the existing*.tsbuildinfogitignore pattern).Gates
pnpm lint— 97/97 tasks, 0 errors (pre-existing warnings in an unrelated React example app only)pnpm format:check— all files correctly formattedpnpm exec fallow audit --changed-since main --format json— verdictpass, 0 introduced findings(
dead_code_introduced: 0,complexity_introduced: 0,duplication_introduced: 0)No changeset: this is build config only, no published package behavior changes.
🤖 Generated with Claude Code