fix(gate): make TDD enforcement work on non-git/generated projects#11
Conversation
The 0.14.0 TDD gate scoped test-sibling-required to `git diff`, so it no-op'd in any non-git directory — including a freshly generated project, which therefore shipped with zero tests and a green gate (reported on a generated tictactoe app). - Scope enforcement to the files the AGENT actually wrote this session (ctx.touched, populated in runToolCalls) instead of git. Works in any dir. - The rule iterates the changed set directly (not sourceFiles ∩ changed), so a root-level file is covered too, not just files under src/. - Exempt presentational `.tsx`/`.jsx` components (testing every component in-loop makes from-scratch web builds get stuck — the buildStaged canary); enforce on `.ts` logic. Put testable logic in `.ts`. - Drop the git dependency (gitChangedFiles) entirely. New tdd-enforcement.test.ts proves it on a NON-git project: an untested .ts logic file stays red, adding the test goes green, TSFORGE_TDD=0 opts out. Full validate 1075 pass.
There was a problem hiding this comment.
Code Review
This pull request replaces the git-based changed files detection with an in-memory tracking mechanism (ctx.touched) to record files created or edited by the agent during a session. This ensures change-scoped meta-rules, such as test-sibling-required, function correctly in non-git environments. Additionally, .tsx and .jsx files are now exempt from test-sibling requirements, and a new test suite has been added to verify TDD enforcement in non-git projects. Feedback on these changes includes a recommendation to lazily initialize ctx.touched to prevent potential runtime errors if it is undefined, and a suggestion to normalize path separators to forward slashes in the rule's warning message for cross-platform consistency.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
…essage path separators
The bug
TDD enforcement (
test-sibling-required, default ON since 0.14.0) populated its "files the agent changed" list from `git diff`. In a non-git project that returns nothing, so the rule short-circuited with zero violations — a freshly generated app (e.g. a scaffolded Vite/React project) shipped with zero tests and a green gate. That's the headline use case: scaffold a new project with tsforge.It worked in tsforge's own repo (a git repo), which is why our evals never caught it.
The fix
Stop asking git. Enforcement now reads `ctx.touched` — the set of files the agent actually wrote this session, tracked in-process in `runToolCalls` and threaded into `settleGate`. Works regardless of whether the directory is a git repo.
Strictly a superset of the old behavior:
The `test-sibling-required` rule now iterates `changedFiles` directly (not `sourceFiles ∩ changed`), with a local `seen` dedup. `.tsx`/`.jsx` components remain exempt by design (in-loop unit tests for presentational components are low-value and stall from-scratch web builds); `.ts` logic is enforced. `TSFORGE_TDD=0` still opts out (downgrades error→warn).
Verification
Follow-up (not in this PR)
The live run surfaced a separate papercut: under TS6 + `moduleResolution: "bundler"`, `import ... from "bun:test"` is rejected (`TS2664`/`TS2307`), so the model spent extra turns before working around it with ambient globals. Worth a future `bun:test` shim / pre-seeded test globals so generated projects don't trip on it.