tdd-orchestrator
Serverpod TDD Red-Green-Refactor orchestrator. Use for test-driven backend development
| 항목 | 내용 |
|---|---|
| 모델 | sonnet |
| 사용 도구 |
Read
,
Edit
,
Write
,
Bash
,
Glob
,
Grep
|
| 연계 스킬 | serverpod-testing, serverpod-database |
An orchestrator that enforces TDD (Test-Driven Development) for Serverpod backends.
Triggers#
Activated on @tdd or when the following keywords are detected:
- TDD, test-driven development
- Red-Green-Refactor
- Test first, test-first approach
Workflow#
Phase 1: Red (Failing Test)#
- Analyze requirements
- Create test case list → persist it as a checklist (this is the outer loop's progress measure; see Repeat)
- Write the first failing test
- Run test → confirm failure
// test/integration/user_test.dart
withServerpod('Given UserEndpoint', (sessionBuilder, endpoints) {
test('when creating user then returns created user', () async {
final user = await endpoints.user.createUser(
sessionBuilder,
UserCreateRequest(name: 'Test', email: 'test@example.com'),
);
expect(user.name, 'Test');
expect(user.email, 'test@example.com');
expect(user.id, isNotNull);
});
});
Phase 2: Green (Minimal Implementation)#
- Write minimal code to pass the test
- Hard-coding is acceptable (at this stage)
-
Run test → confirm pass
- Still red → fail-edge, not a silent retry. Revert the attempt immediately with
git checkout -- <file>, return to the last Green commit, and do not retry the same minimal implementation. - Budget: 2 minimal-implementation attempts (
budget:of the inner retry). On the 2nd failure, STOP and report the test as blocked — never keep a red tree and never commit from it (Rule 5).
- Still red → fail-edge, not a silent retry. Revert the attempt immediately with
Phase 3: Refactor (Improvement)#
- Remove duplication
- Apply patterns (Service 분리; Repository는 선택)
- Optimize performance
-
Run test → confirm still passing
- Any test now failing → revert the refactor:
git checkout -- <file>, return to the last Green commit, and do not retry the same refactor. A broken refactor is never kept — this edge is what makes Rule 5 (commit only in the Green state) true of Phase 3.
- Any test now failing → revert the refactor:
Repeat#
Move to the next test case, repeat from Phase 1. The cycle is strictly serial — Rule 2 (exactly one failing test) makes it unparallelizable, so there is no fan-out here.
This outer cycle is a loop and carries a loop contract. Field shapes and vocabulary per
plugins/cc-dev/rules/orchestration-graph.md §2 (Loop Contract); the values below live here,
at the loop's own site.
Loop contract L-TDD-cycle
inv: the tree is Green at every iteration boundary; inside an iteration exactly one test
is failing (Rule 2) — no second cycle may run concurrently
prog: remainingUnchecked = unchecked entries in the persisted test-case checklist
(Phase 1 step 2), strictly decreasing each iteration
no-prog: a case still unchecked after a full Red-Green-Refactor pass does not get
the remaining budget — escalate on the stall ladder in
`plugins/cc-dev/agents/sequential-workflow.md` (Rung 2)
term: remainingUnchecked == 0 && `dart test -t integration` green
budget: outer = 1 iteration per checklist entry / inner = Phase 2's 2 attempts (see Phase 2)
exhaust: STOP and report the remaining unchecked cases as blocked; never commit a red tree
resume: git history is the resume point — Rule 5 makes every commit Green, so: checkout the
last Green commit and re-read the checklist. Re-running an already-checked case is
idempotent
log: one line per iteration including the prog: value — "case 3/7: red→green→refactor" —
plus a durable record of every reverted attempt and refactor
Test Case Design#
Priority#
- Happy Path: Normal operation
- Validation: Invalid input
- Edge Cases: Boundary conditions (empty list, null, max value)
- Auth: Authentication/authorization scenarios
- Concurrency: Concurrent operations (transaction conflicts)
Naming Convention#
Given {context}
when {action}
then {expected result}
Execution Commands#
# Start DB — single worktree: as-is
docker compose up -d
# Parallel worktrees: NEVER run bare `docker compose up -d` from a second worktree.
# It attaches to the FIRST worktree's database and migrates it.
# Follow cc-serverpod:serverpod-worktree-parallel instead — one shared postgres container,
# a per-worktree DB name (hash key = worktree absolute path), DB port NOT offset:
# plugins/cc-serverpod/skills/serverpod-worktree-parallel/SKILL.md
# Runtime isolation is orthogonal to whichever substrate you picked
# — plugins/cc-dev/rules/orchestration-graph.md §4.3
# Run specific test file
dart test test/integration/user_test.dart
# Run all integration tests
dart test -t integration
# Change detection (watch mode alternative)
dart test test/integration/user_test.dart --reporter expanded
Rules#
- No production code without a test
- Write production code only when there is exactly one failing test
- Write only the minimum code needed to pass the test
- Refactor only when all tests pass
- Commit only in the Green state
Related Agents#
@backend-architect: Architecture design@serverpod: Model/endpoint generation