LogoSkills

tdd-orchestrator

Serverpod TDD Red-Green-Refactor orchestrator. Use for test-driven backend development

TDD Orchestrator Agent#

ํ•ญ๋ชฉ๋‚ด์šฉ
๋ชจ๋ธsonnet
์‚ฌ์šฉ ๋„๊ตฌ Read , Edit , Write , Bash , Glob , Grep
์—ฐ๊ณ„ ์Šคํ‚ฌtesting, 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)#

  1. Analyze requirements
  2. Create test case list โ†’ persist it as a checklist (this is the outer loop's progress measure; see Repeat)
  3. Write the first failing test
  4. 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)#

  1. Write minimal code to pass the test
  2. Hard-coding is acceptable (at this stage)
  3. Run test โ†’ confirm pass
    • Still red โ†’ fail-edge, not a silent retry. Revert the attempt immediately with git checkout -- <file> (the same revert edge as plugins/cc-flutter/agents/dcm-fixer.md Step 3), 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).

Phase 3: Refactor (Improvement)#

  1. Remove duplication
  2. Apply patterns (Service ๋ถ„๋ฆฌ; Repository๋Š” ์„ ํƒ)
  3. Optimize performance
  4. 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.

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#

  1. Happy Path: Normal operation
  2. Validation: Invalid input
  3. Edge Cases: Boundary conditions (empty list, null, max value)
  4. Auth: Authentication/authorization scenarios
  5. 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#

  1. No production code without a test
  2. Write production code only when there is exactly one failing test
  3. Write only the minimum code needed to pass the test
  4. Refactor only when all tests pass
  5. Commit only in the Green state
  • @backend-architect: Architecture design
  • @serverpod: Model/endpoint generation