| name | apd-tdd |
| description | MANDATORY during the APD builder phase on Codex (between apd:apd_advance_pipeline('spec', ...) and apd:apd_advance_pipeline('builder')) whenever implementing a feature, fixing a bug, or writing new code. Write a FAILING test first, watch it fail, write minimal code to pass, refactor while green. Every file write goes through apd:apd_guard_write(apd_role, file_path); scope is enforced server-side from .apd/agents/<apd_role>.md. Triggers on "implement", "add feature", "fix bug", "write code", "TDD", "test-first", "builder". |
APD Test-Driven Development (Codex)
On Codex this skill applies to the native builder subagent dispatched between
apd:apd_advance_pipeline('spec', ...) and
apd:apd_advance_pipeline('builder'). The orchestrator coordinates the phase
and must not implement source changes itself.
When to use / When to skip
Use when:
- You are inside the APD builder phase
- You are about to write or modify production code (any non-test source file)
- You are fixing a bug that has reached Phase 4 of
apd-debug
Skip when:
- You are reading code without modifying it
- You are running an existing test suite (use shell directly)
- You are editing documentation, configuration, or scaffolding files
The Iron Law
NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST
Write code before the test? Delete it. Start over. No exceptions.
Red → Green → Refactor
1. RED — failing test first
Write ONE minimal test that describes the behavior you want. Run it.
Watch it fail. If it passes on the first run, you are testing existing
behavior — fix the test to actually describe the new requirement.
Before each test-file write, call
apd:apd_guard_write(apd_role="<role>", file_path="<path>"). The server reads
scope from .apd/agents/<role>.md on every call — you only pass the role
name and target path. Use apd:apd_list_agents() to discover which roles are
defined. (Argument is apd_role, not role, to avoid Codex's
multi_agent role-mismatch approval prompt.)
2. GREEN — minimal code to pass
Write the SIMPLEST code that makes the test pass. Nothing more.
- No extra features
- No "while I'm here" improvements
- No over-engineering
3. REFACTOR — clean up (tests stay green)
Only once green: remove duplication, improve names, extract helpers. If a
test goes red during refactoring, revert immediately.
4. Next behavior
Pick the next behavior. Write the next failing test. Repeat.
Scope enforcement on every write
Builder scope is declared in the agent frontmatter
(.apd/agents/<role>.md, scope: list). Call
apd:apd_guard_write(apd_role="<role>", file_path="<path>") before every
Write/Edit — the server reads scope from the agent file itself, so the
role name is the only handle you need (and can't widen).
Do NOT bypass with direct Bash writes — guard-bash-scope blocks writes
into .apd/pipeline/ and reviewed-files scope, and the verifier will
fail the cycle.
Common rationalizations
| Excuse | Reality |
|---|
| "Too simple to test" | Simple code breaks. Test takes 30 seconds. |
| "I'll test after" | Tests that pass immediately prove nothing. WATCH them fail first. |
| "Need to explore first" | Fine. Throw away exploration code, then start with TDD. |
| "TDD will slow me down" | TDD is faster than debugging. Every time. |
| "Manual test is faster" | Manual testing doesn't prove edge cases or prevent regressions. |
| "I can't test this" | You can't test the CURRENT design. Simplify the design. |
Exit criteria
You're done when:
- Every new function has a test you watched fail
- All tests pass locally — both new and the prior suite (no regressions)
- Edge cases are covered (empty input, invalid input, boundary values)
- Every write went through
apd:apd_guard_write(apd_role=..., file_path=...)
- No unrelated files touched outside the agent's
scope:
- Refactor pass left tests green
Hand-off
- After this skill completes → call
apd:apd_advance_pipeline('builder')
- Then return control to the orchestrator, which dispatches the primary reviewer and calls
apd:apd_advance_pipeline('reviewer') — that step writes .adversarial-pending as the green light for the adversarial subagent
- Do NOT call
apd:apd_adversarial_pass before reviewer.done exists; the pre-flight gate refuses the call
- If a test goes red unexpectedly → switch to
apd-debug (Phase 4 of debug uses this skill again)
- Never skip — even for "trivial" changes. Especially for trivial changes.