Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 14 additions & 16 deletions SKILL.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
---
skill: tdd
trigger: "Use when the user invokes /tdd or asks to do TDD on a feature. Accepts a plan file path or an inline feature description. Guides the developer through Red-Green-Refactor cycles."
name: tdd
description: "Use when the user invokes /tdd or asks to do TDD on a feature. Accepts a plan file path or inline feature description. Writes failing tests, implements minimal passing code, runs the full test suite, and suggests refactoring β€” guiding the developer through strict Red-Green-Refactor cycles."
arguments:
- name: input
description: "Either a path to a markdown plan file OR an inline description of the feature to implement via TDD (e.g., '/tdd plan.md' or '/tdd add JWT authentication with refresh tokens')"
---

# TDD Skill β€” Red-Green-Refactor

You are guiding the developer through strict Test-Driven Development. You write code directly to the real files β€” the user can always undo with git. Pause only when the user's input is needed, not at every step.
Guide the developer through strict Test-Driven Development. Write code directly to real files β€” the user can always undo with git. Pause only when user input is needed.

## Phase 1: Setup

1. Determine the input type:
- **If the input is a file path** (ends in `.md`, `.txt`, or exists on disk): read the plan file.
- **If the input is an inline description** (e.g., `"add JWT authentication with refresh tokens"`): use it directly as the feature specification. Ask clarifying questions with `AskUserQuestion` only if the description is too vague to decompose into increments (e.g., "build an app"). A single sentence like "add user login with email and password" is enough to start.
- **File path** (ends in `.md`, `.txt`, or exists on disk): read the plan file.
- **Inline description** (e.g., `"add JWT authentication with refresh tokens"`): use it directly as the feature specification. Ask clarifying questions with `AskUserQuestion` only if the description is too vague to decompose into increments (e.g., "build an app").
2. Detect the language and test framework from the project. If ambiguous, ask:
- Python β†’ pytest
- TypeScript β†’ vitest
Expand All @@ -33,33 +33,33 @@ For each increment, follow Red-Green-Refactor strictly. Mark the current increme
### RED β€” Write a Failing Test

1. Write the failing test **directly to the real test file** (e.g., `tests/test_feature.py`, following existing project conventions). Show the test in a fenced code block and briefly explain what behavior it verifies.
2. Run the test using the appropriate runner (see language-configs.md). Use `Bash`.
3. Confirm the test **fails**. If it passes unexpectedly, stop and flag this:
- "The test passed already β€” this means either the behavior is already implemented or the test isn't asserting the right thing. Let's investigate before moving on."
2. Run the test using the appropriate runner (see `references/language-configs.md`). Use `Bash`.
3. Confirm the test **fails**. If it passes unexpectedly, stop and flag:
- "The test passed already β€” the behavior is either already implemented or the test isn't asserting the right thing. Let's investigate before moving on."
4. Pause with `AskUserQuestion`:
- "RED: test fails as expected. Review the test above β€” ready to move to GREEN?"
- Options: "Looks good, write the code" / "I want to change the test first"

### GREEN β€” Write Minimal Code to Pass

5. Write the **minimal** production code **directly to the real source file** to make the failing test pass. Show it in a fenced code block. Write only enough to pass, nothing more.
5. Write the **minimal** production code **directly to the real source file** to make the failing test pass. Show it in a fenced code block.
6. Run **all** tests (not just the new one). Use `Bash`.
7. If all tests **pass**, move directly to REFACTOR β€” no pause needed.
7. If all tests **pass**, move directly to REFACTOR.
8. If any test **fails**, show the failure output and pause:
- "A test failed unexpectedly. Here's the output. Want me to fix it, or do you want to handle it?"
- Options: "Fix it" / "I'll handle it"

### REFACTOR β€” Improve the Code

9. Review the current code. If refactoring opportunities exist (duplication, naming, extraction, simplification), apply them directly and run all tests to confirm green. Show what you changed in a fenced code block.
10. If no refactoring is needed, say so and move on β€” no pause.
9. Review the current code for duplication, naming, extraction, or simplification opportunities. Apply improvements directly and run all tests to confirm green. Show what changed in a fenced code block.
10. If no refactoring is needed, say so and move on.
11. If refactoring causes a test failure, revert and pause to discuss.

### NEXT

12. Mark the increment as `completed` via `TaskUpdate`.
13. Briefly summarize: what test was added, what code was written, what was refactored (if anything).
14. Move directly to the next increment β€” go back to RED. No pause between increments.
14. Move directly to the next increment β€” go back to RED.

## Phase 3: Wrap-up

Expand All @@ -72,9 +72,7 @@ After all increments are complete:

## Rules

- **Write directly to real files.** No temp files, no asking the user to move code. The user has git for undo.
- **Pause only when needed:** after RED confirms failure (so the user can review the test), and when something goes wrong (unexpected pass, test failure at GREEN, refactoring breakage). Do NOT pause at GREEN success or REFACTOR success.
- **Run the full test suite** at Green and Refactor steps, not just the new test.
- **Write directly to real files.** No temp files, no asking the user to move code.
- **Keep tests behavior-focused.** Test what the code does, not how it does it.
- **Simplest case first.** Start with the degenerate/edge case, build toward the general case.
- **One assertion per test** when possible. Each test should verify one behavior.
Expand Down