name: lean-loop description: > Lightweight TDD system with PLAN/APPLY/UNIFY heartbeat cycle for structured development. Use when: implementing features with test-driven development, writing acceptance criteria, doing red-green-refactor cycles, planning before coding, or when user mentions "lean loop", "tdd workflow", "plan then code", "acceptance criteria", or structured development. Creates .system/ tracking files automatically if missing.
Lean Loop: Structured TDD Workflow
A disciplined heartbeat cycle (PLAN → APPLY → UNIFY) for building software with acceptance-criteria-driven development, strict TDD, and mandatory reconciliation.
Initialization
Before starting the loop, ensure the project has operational state files:
- Check if
.system/directory exists in the project root - If missing, create it by copying templates from this skill's bundled
templates/directory:.system/PLAN.md←templates/plan-template.md.system/STATE.md←templates/state-template.md.system/LOG.md←templates/log-template.md.system/TDD_RULES.md←templates/tdd-rules-template.md
- Read
.system/STATE.mdto understand current project state - Read
.system/TDD_RULES.mdto load execution rules
Philosophy
- In-Session Context: All implementation happens in the main session. Do not use subagents for APPLY tasks — they lose context and reduce quality.
- Vertical Slicing: Build one behavior end-to-end ("Tracer Bullets" from The Pragmatic Programmer) rather than horizontal layers.
- Acceptance-Driven: Define "Done" via clear Acceptance Criteria before writing any code.
- Behavior-First TDD: Test public interfaces, not internal implementation.
- Deep Modules: Small public interfaces that hide complex implementations (A Philosophy of Software Design).
The Heartbeat: PLAN → APPLY → UNIFY
Phase 1: PLAN
Fill in .system/PLAN.md with:
- Objective — one clear, specific goal
- Acceptance Criteria — Given/When/Then format, each testable independently
- Boundaries — files/modules that must NOT change
- Tasks — broken into rows: Files | Action | Depends | Verify | AC Ref
PLAN Gate: AC Quality Checklist
Before setting status to APPROVED, verify every AC passes all five checks. If any fail — refine the AC, do not proceed.
| # | Check | Pass | Fail |
|---|---|---|---|
| 1 | Specific input — "Given" names concrete values or exact state | Given user is logged in | Given the system is ready |
| 2 | Observable action — "When" describes a single triggerable action | When POST /api/users with {name:"X"} | When the user does stuff |
| 3 | Verifiable outcome — "Then" states something a test can assert | Then response status is 201 | Then it works correctly |
| 4 | Independent — AC can be tested without depending on another AC passing first | AC-1 and AC-2 are decoupled | AC-2 only works if AC-1 ran |
| 5 | No leakage — AC doesn't prescribe internal implementation | Then returns sorted list | Then uses quicksort internally |
Gate command for AI:
When asked to validate the PLAN, output each AC with PASS/FAIL per row. If any FAIL, halt and ask the user to refine before setting APPROVED.
Rule: Set PLAN status to
APPROVEDonly after all ACs pass the checklist.
Phase 2: APPLY
Execute Red-Green-Refactor cycles strictly. For each behavior:
- RED — Write ONE test for ONE behavior. Confirm it fails with actual console output. Never guess error messages.
- GREEN — Write only the minimal code to make the test pass. No future-proofing. No extra features.
- REFACTOR — Improve design (deepen modules, remove duplication) only when test is green.
Strict rules:
- One test at a time. One behavior at a time.
- Smallest viable change: touch fewest files possible.
- If work expands beyond original ACs — STOP and return to PLAN.
- Test public interfaces, not internals. Mock only external APIs, databases, time, randomness.
Phase 3: UNIFY (Mandatory)
After every APPLY session, perform reconciliation. No exceptions.
Checklist:
- All tests are green — run the full test suite
- All Acceptance Criteria are satisfied — check each one explicitly
- Update
.system/STATE.md— current phase, next action, progress - Document in
.system/LOG.md:- Technical decisions made (if any)
- Deferred issues / technical debt (if any)
- RED phase failures (if any — console facts only)
- Compare planned vs. actually done
UNIFY Command for AI
When the user says "Run UNIFY", execute these steps in order and output results:
=== UNIFY ===
1. TEST SUITE:
[paste full test output here]
2. AC VERIFICATION:
AC-1: [quote the AC] → ✅ / ❌ [why]
AC-2: [quote the AC] → ✅ / ❌ [why]
...
3. PLAN vs ACTUAL:
Planned: [copy Objective from PLAN.md]
Actually done: [list files changed, commands run]
4. DEBT / DEFERRED:
- [anything left over or skipped, or "None"]
5. NEXT ACTION:
[exactly one specific task]
Status: PASS → proceed to next PLAN
FAIL → stay in APPLY, fix outstanding ACs
=== END UNIFY ===
After outputting this, update .system/STATE.md and append to .system/LOG.md automatically.
Exceptions (When to Break TDD)
Rare cases only. All must be documented in .system/LOG.md:
- Hotfixes — production bugs requiring immediate recovery (write tests later)
- Legacy Code — too tightly coupled, testing would require massive refactoring
- Spikes — exploratory code for hypothesis validation, will be thrown away
Anti-Patterns
- Skipping UNIFY ("tests pass, good enough")
- Writing multiple tests before making any pass
- Adding code not required by current AC ("might need it later")
- Using subagents for APPLY phase implementation
- Refactoring during RED phase
- Proceeding to APPLY with vague or untestable ACs
- Ignoring
.system/STATE.mdbetween sessions
Template Files
Bundled templates for .system/ initialization: