Skip to content

perf(gate): incremental TS gate — tsc --incremental + eslint --cache (closes #213)#214

Open
yuyu04 wants to merge 1 commit into
qwerfunch:developfrom
yuyu04:feature/incremental-ts-gate
Open

perf(gate): incremental TS gate — tsc --incremental + eslint --cache (closes #213)#214
yuyu04 wants to merge 1 commit into
qwerfunch:developfrom
yuyu04:feature/incremental-ts-gate

Conversation

@yuyu04

@yuyu04 yuyu04 commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Summary

The TypeScript type & lint gates re-ran from scratch every gate. They now reuse a build cache — tsc --noEmit --incremental + eslint --cache — written under .cladding/cache/. Closes #213.

Why (measured, cladding's own repo)

clad check runs tsc --noEmit and eslint . over the whole tree every time, with no incremental/cache flags.

cold warm re-run
tsc 2.7s 1.1s
eslint 2.5s 0.6s
~3.4s saved/re-run

The win lands on the local dev loop (pre-commit/pre-push hooks, where the cache persists). Cold CI checkouts just rebuild the cache — no regression.

Soundness (the critical property)

A gate must never pass a broken tree. Verified by injecting a type error into an existing included file with a STALE build-info present:

plain tsc --noEmit tsc --incremental (stale build-info)
exit 2 (caught) 2 (caught)

tsc --incremental rebuilds the affected program slice; eslint --cache keys the cache on file + config hash. The cache only skips proven-unchanged work.

Explicitly NOT scoped (would be unsound)

Test execution (~20s — the dominant gate cost) is not scoped to changed files: a gate certifies the whole tree, and vitest --changed/test-selection could let a regression in an "unrelated" file slip through. Left as a full run.

Measurement also surfaced a separate sound win: the suite runs twice per pre-push — the unit stage (vitest run) and the coverage stage (vitest run --coverage) ≈ 9.5s — dedupable (same pattern as the secretlint/madge memo). Filed as a follow-up; not in this PR.

What's in the box

  • src/stages/toolchain/detect.ts — TS type/lint gate args gain --incremental --tsBuildInfoFile .cladding/cache/tsc.tsbuildinfo and --cache --cache-location .cladding/cache/eslint. Caches under .cladding/ (gitignored) — zero pollution of the managed project. test/coverage gates unchanged.
  • tests/stages/incremental-gate.test.ts — blind-authored (5): the flags + cache paths are present, paths stay under .cladding/, test/coverage unchanged, non-TS languages unaffected.
  • tests/stages/toolchain.test.ts — existing arg-pins updated to the new commands.

Feature cycle

spec/features/incremental-ts-gate-bfe14aac.yaml (F-bfe14aac, 4 ACs) → implement → blind tests → clad done GREEN. Single clean commit on develop.

🤖 Generated with Claude Code

…(F-bfe14aac)

The TypeScript type and lint gates re-ran from scratch every gate. They now
reuse a build cache: `tsc --noEmit --incremental` (build-info file) and
`eslint --cache`, both under `.cladding/cache/` (already gitignored, so a
managed project's tree stays clean).

Measured on cladding's own repo (unchanged re-run — the local pre-commit/
pre-push loop): tsc 2.7s → 1.1s, eslint 2.5s → 0.6s (~3.4s saved).

SOUND, not a shortcut: with a stale build-info present, a newly-introduced
type error in an included file is STILL caught (verified — tsc rebuilds the
affected program slice; eslint --cache keys on file+config hash). Cold runs
(fresh CI checkout) just rebuild the cache — no regression.

Test execution is deliberately NOT scoped: a gate must certify the whole tree,
so changed-files / test-selection (unsound for a gate) was avoided. The
dominant test cost (~20s) and the unit+coverage double-run (~9.5s) are noted
as separate follow-ups.

Existing toolchain arg-pins updated; blind-authored test (incremental-gate.test.ts, 5).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@yuyu04 yuyu04 force-pushed the feature/incremental-ts-gate branch from 799126f to 147e83f Compare July 2, 2026 01:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant