Test-Driven Development workflow. Use for ALL code changes - features, bug fixes, refactoring. TDD is non-negotiable.
TDD is the fundamental practice for new or changed observable behavior: every such production change must be written in response to a failing behavior test.
Pure behavior-preserving work is different. refactoring and reduce-system-complexity begin from passing proportionate preservation evidence and stay behaviorally green while internal structure changes. At the end-of-phase PR-readiness gate, use mutation testing where meaningful; otherwise record reachability, configuration, contract, integration, or operational evidence and mark mutation N/A. Do not manufacture a failing test or structural mutant merely to make a REFACTOR slice look RED. If the work changes behavior or fixes a disputed bug, return to RED.
In this skill, a phase means one PR-sized, independently mergeable slice: the accumulated scope of one branch and PR. It does not mean a multi-PR feature or the numbered lifecycle phases in README.md.
For how to write good tests, load the testing skill. This skill focuses on the TDD workflow/process. For mutation-aware test planning, load the mutation-testing skill and use its resources/mutator-rules.md resource as the source of truth.
The RED-GREEN-REFACTOR inner loop must optimize for fast, relevant feedback. Do not run the full test suite after every edit.
Before RED, inspect package scripts, test configuration, and runner help. Repository-owned commands take precedence over generic examples:
--changed <real-base> --watch only when the installed version and repository configuration have the required live proof.Read resources/vitest-watch-feedback.md before selecting, adding, or changing a reusable Vitest watcher. It is the canonical detail for seed strategies, native discovery, blind spots, and the required live process proof.
vitest --changed <real-base> --watch is diff-selected for its initial execution. Vitest clears the VCS selectors after that selection; it does not continuously recompute VCS impact after every save. Later reruns use retained Vite module graphs. In Vitest 4.1.10's ordinary Node/SSR path, initial changed selection statically analyzes every discovered test specification, so an imported implementation edit can rerun its test even when the clean-start initial execution reported no affected tests. Later reruns are therefore not limited to tests that executed initially.
Do not generalize that Vitest 4.1.10 implementation detail to other versions, Browser Mode, dynamic/non-import dependencies, or arbitrary repository configurations. Prefer a behaviorally proven repository-owned command such as pnpm test:watch for standard development, a clean refactoring baseline, or a watcher started before RED. A repository may safely run its complete relevant tier once to populate the graph. For strict TDD, starting a proven diff-selected watcher after RED makes it straightforward to confirm that the expected test actually executed. Do not replace a repository command with a generic raw Vitest example.
Examples (adapt to the repository; the first existing command that satisfies the required behavior wins):
# Repository-owned graph-complete watch, when defined and proven
pnpm test:watch
# Vitest diff-selected initial execution: use only after repository-level proof
pnpm exec vitest --changed origin/main --watch
# Vitest fallbacks: mechanically derived affected sources or one-shots
pnpm exec vitest related src/example.ts --watch
pnpm exec vitest related --run src/example.ts
pnpm exec vitest --changed origin/main --run
# Exact selector: RED/debug only
pnpm exec vitest run tests/example.test.ts -t "rejects empty names"
# Jest: repository/runner changed watch, or affected one-shot
pnpm exec jest --watch
pnpm exec jest --watch --changedSince=origin/main
pnpm exec jest --findRelatedTests src/example.ts --watch=false
pnpm exec jest --onlyChanged --watch=false
pnpm exec jest --changedSince=origin/main --watch=false
pnpm exec jest --runTestsByPath tests/example.test.ts -t "rejects empty names"
# Playwright: runner-selected affected one-shot (heuristic; inspect the selected tests)
pnpm exec playwright test --only-changed
pnpm exec playwright test --only-changed=origin/main
Vitest natively discovers a new matching test file when include globs remain open. Confirm that the new test actually executes and loads its implementation before trusting later implementation reruns. Do not add custom filesystem listeners or call rerun APIs unless live proof shows native discovery is insufficient; doing both can execute a new test twice.
vitest related <sources...> is a fallback only when every source path is derived mechanically. It implicitly permits an empty result to pass, so confirm an expected test executed. Do not use --passWithNoTests as evidence. Do not use --standalone: it either skips the initial run without a file filter or reduces the workflow to a supplied filter.
Ctrl+C before PR gates or task handoff. Do not leave background watchers behind.vitest in an interactive TTY, vitest watch, vitest --watch, vitest --watch=true, vitest -w, and vitest -w=true. Finite Vitest commands must force termination with vitest run, --run, or --watch=false.vitest run --watch and vitest watch --watch=false are not finite.Explicit watch remains long-lived even without a TTY; it does not become a finite command in CI. Bare vitest can default to watch when stdin is a TTY and neither CI nor Vitest's agent detection disables it. Never rely on environment auto-detection to make a finite command terminate. For other runners, prefer a tested repository-owned watcher, then native changed/affected selection, dependency-aware selection from a complete mechanically derived source list, the graph-derived affected package/project set, and finally an affected one-shot. Exact selectors remain RED/debug-only.
Run changed/affected selection from the repository root through the project-defined test command, root Vitest projects configuration, or monorepo orchestrator that owns the complete workspace dependency graph. A shared-package edit may affect tests in several consumers, so do not cd into one package or add --project based only on the file being edited. A project filter is safe only when Vitest or the repository's package/task graph mechanically derived the complete affected project set, including transitive dependents.
Confirm the root configuration enumerates every relevant project and that cross-package imports are graph-visible. Filesystem reads, subprocess targets, generated output, templates, proxy-fetched dependencies, type-only relationships, file-scanning repository guards, browser-mode tests, and Docker-backed tiers may need repository-specific triggers or separate commands. Preserve watchTriggerPatterns and forceRerunTriggers where configured. Restart/reseed only repairs stale or newly graph-visible relationships; configure an explicit mapping or run the owning suite/tier for dependencies the graph cannot represent.
Watch mode is an inner-loop accelerator, not PR evidence. The pre-PR record must come from a completed non-watch full run against the final tree.
Repository-specific test, coverage, mutation, and evidence-freshness rules take precedence. Use this distribution's freshness model (the panel-review skill's references/pr-readiness.md) only when the target repository has not defined a stricter invalidation rule. This global guidance must never weaken a repository rule that invalidates evidence after later production or applicable test changes.
refactoring skill only when restructuring is applicable; record N/A otherwiseRepeat RED-GREEN-REFACTOR as needed until the phase's PR scope is complete. Do not run the automated mutation harness after each increment, refactor, or commit. Whether or not the harness ran, the final reply must state the mutation gate outcome in one line β Mutation: ran, X killed / Y survived (score Z%), Mutation: N/A β <rationale> ; alternate evidence: <what>, or Mutation: deferred to the PR gate β this slice is not yet PR-ready. An unstated gate is an unrecorded gate.
Run this gate once the implementation and refactoring phase is complete and the work is otherwise ready to become a PR:
mutation-testing against the accumulated branch/PR scope where meaningful and produce a killed/survived/score report. Otherwise record an explicit N/A rationale plus proportionate reachability, configuration, contract, integration, or operational evidence.Capture the expected RED failure, the GREEN pass, and the final non-watch verification, and state all three in the final reply: name the RED run (the selector used and the failure it produced, e.g. pinNote is not a function), the GREEN run, and the completed non-watch full run. A reply that reports only passing counts has not reported TDD evidence. Existing commit history may corroborate the sequence, but do not reshape commits merely to perform TDD theatre; follow the repository's delivery policy.
Coverage is a diagnostic, not a universal target. Run the repository's coverage command when policy requires it or when making a coverage claim. Verify the exact lines, branches, statements, and functions claimed, then ask whether any gap represents untested behavior. A high percentage does not prove test quality; use the testing skill's coverage-theatre checks and mutation or alternate evidence where proportionate.
N/A plus proportionate alternate evidence), address valuable survivors within that gate, and complete the repository-defined non-watch PR checks. Apply the target repository's evidence-invalidation rule; use this distribution's freshness model (panel-review skill, references/pr-readiness.md) only when no stricter repository rule exists# 1. If the repository requires its watcher before the first edit, start it now:
# pnpm test:watch
# 2. Write failing test
it('should reject empty user names', () => {
const result = createUser({ id: 'user-123', name: '' });
expect(result.success).toBe(false);
}); # β Test fails (no implementation)
# 3. If it is not already running, start the tested repository watcher now.
# Starting after RED makes the expected initial execution easy to verify when
# the repository does not mandate an earlier start.
pnpm test:watch
# If no repository watcher exists and this Vitest version/configuration has
# passed the live proof:
pnpm exec vitest --changed origin/main --watch
# Or use an affected one-shot:
pnpm exec vitest --changed origin/main --run
# 4. Confirm the expected RED test executed, then implement minimum code
if (user.name === '') {
return { success: false, error: 'Name required' };
} # β
Test passes
# 5. Refactor if needed (extract validation, improve naming)
# 6. Repeat RED-GREEN-REFACTOR increments without running the mutation harness
# 7. After the final edit, stop the watcher with Ctrl+C. When the accumulated work
# is otherwise ready to create the PR, run the
# end-of-phase mutation gate once and address valuable survivors within it.
# 8. Exit watch mode and finish the remaining PR verification, including the
# inspected repository-defined complete non-watch test gate.
# If later verification changes mutation-relevant production or applicable
# tests/evidence, apply the target repository's invalidation rule and rerun
# the evidence it invalidates; use this distribution's review
# pr-readiness freshness model only when no stricter rule exists. Keep
# final-tree verification current.
Before submitting PR:
N/A plus proportionate alternate evidenceExample PR Description:
## Summary
Adds support for user role-based permissions with configurable access levels.
## Behavior Changes
- Users can now have multiple roles with fine-grained permissions
- Permission check via `hasPermission(user, resource, action)`
- Default role assigned if not specified
## Test Evidence
β
42/42 tests passing
β
Repository coverage gate passed (see attached report)
## TDD Evidence
RED: expected permission test failed before production changes
GREEN: focused permission tests passed after the minimum implementation
REFACTOR: affected tests remained green after permission resolution was simplified
After GREEN establishes a passing behavior-test baseline, assess and classify improvement opportunities when restructuring is applicable. For the priority classification table and detailed methodology, load the refactoring skill β it owns that guidance. Mutation testing verifies the accumulated result later at the end-of-phase PR-readiness gate.
--passWithNoTests as passing RED/GREEN evidence--changed --watch recomputes VCS impact after every save, or that later reruns are limited to tests executed by the initial VCS-selected runFor detailed testing anti-patterns, load the testing skill.
Before marking work complete:
N/A plus proportionate alternate evidence, or explicitly deferred to the PR gate because this slice is not yet PR-ready; never left unstatedN/A