Skip to content
Development
Skill

/tdd

The test-first gate. Routed to by /feature (after the spec is approved), /fix, and /refactor before any implementation code is written. Six gated phases — obligation scan, red, green, obligation verify, coverage, lint. No feature code exists before Phase 1 clears; nothing

From plugin
codearbiter
14562 skills19 agents42 commands
Install
$ npx -y skills add arbiterForge/codeArbiter --skill tdd --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/tdd

Context preview

The summary Claude sees to decide when to auto-load this skill.

The test-first gate. Routed to by /feature (after the spec is approved), /fix, and /refactor before any implementation code is written. Six gated phases — obligation scan, red, green, obligation verify, coverage, lint. No feature code exists before Phase 1 clears; nothing

SKILL.md

tdd.SKILL.md
name: tdd
description: The test-first gate. Routed to by /feature (after the spec is approved), /fix, and /refactor before any implementation code is written. Six gated phases — obligation scan, red, green, obligation verify, coverage, lint. No feature code exists before Phase 1 clears; nothing reaches commit-gate until all six are green.
disable-model-invocation: true

tdd

Test-first, or it does not ship. Routed to by `/feature` (after spec approval), `/fix`, and `/refactor`.

Pre-flight

Read these, or STOP and surface the gap — never guess a command or a threshold:

  • `{{PROJECT_DIR}}/.codearbiter/CONTEXT.md` — the `stage:` frontmatter (the maturity value) and project context.
  • `{{PROJECT_DIR}}/.codearbiter/tech-stack.md` — test, coverage, and lint invocations; file layout; mock patterns.
  • `{{PROJECT_DIR}}/.codearbiter/coding-standards.md` — style, structure, naming. Required for Phase 3.
  • `{{PROJECT_DIR}}/.codearbiter/specs/<slug>.md` — the approved spec, when `/feature` produced one. It is the primary obligation source.
  • `{{PROJECT_DIR}}/.codearbiter/security-controls.md` — only when the change touches a security boundary (auth, crypto, secrets, a trust boundary). Optional; absent on most changes.
  • `{{PROJECT_DIR}}/.codearbiter/code-map.md` — if present, a coarse concern→path→role map to orient before writing tests and code. Absent is fine — it is read-on-demand, populated by context-creation or commit-gate heal.

Phase 1 — Obligation scan · gate: BLOCK

An **obligation** is one verifiable claim about the change: (a) a unique ID, (b) a source citation, (c) a status. Status moves `OPEN → MAPPED → COVERED`; an obligation Phase 4 cannot tie to a passing test is `MISSING`. "We should test X" is not an obligation.

Derive every obligation before any code is written, and record each as `ID · source · OPEN`:

  • **Spec** — one obligation per acceptance criterion in the approved spec.
  • **Contract** — API and input-validation invariants, error responses, boundary conditions.
  • **Security** — only when `security-controls.md` applies: the assertion that the security-relevant boundary holds.

Gate: the obligation list is complete. **Auto-pass** when every obligation maps one-to-one onto the acceptance criteria of an already-approved spec (full-lane spec or small-lane mini-spec) — the user approved that list once; do not re-ask. **User review is required** only for obligations derived BEYOND the spec (Contract and Security rows): surface just those additions, not the whole list. Under `/sprint`, spec-derived obligations auto-pass the same way and beyond-spec additions are SMARTS-decided and logged like any other auto-decision. A partial list never passes either way.

Phase 2 — Red · gate: BLOCK

Write one or more failing tests per obligation. Bind each test ID to its obligation ID and move that obligation `OPEN → MAPPED`. Run the test command from `tech-stack.md`.

  • Every new test MUST fail, and fail **for the right reason** — the assertion, not an import error or a typo. A new test that passes with no implementation is wrong; fix it before continuing.
  • Every pre-existing test MUST stay green. One that breaks here is a conflict — stop and surface it.

Reject the standard traps: asserting on a mock instead of behavior; a test that can never fail; a snapshot so broad it asserts nothing; coupling to an implementation detail instead of observable behavior; asserting on the framework's behavior rather than your own.

The reasons to skip red are known. Hearing one is the tell that this gate is about to be waived — never the license to waive it:

| excuse | reality | |---|---| | "Too simple to fail first." | Simple changes have the cheapest red tests — and "too simple to test" and "too simple to break" have never been the same claim. | | "I'll write the test right after." | A test written after green has never been seen red: it is authored against the implementation it was meant to constrain, and its power to catch the bug is never demonstrated. | | "The test would just restate the implementation." | Then it is aimed at the wrong seam — assert the observable behavior, not the wiring. A change with no observable behavior to assert is a design finding, not an exemption. | | "The existing suite already covers this." | Then the failing test is impossible to write — try it. If it genuinely cannot go red, the obligation is already COVERED and Phase 4 records exactly that; if it goes red, the claim was wrong and you are holding the proof. |

Gate: the runner confirms new tests red (for the right reason) and existing tests green, with every obligation `MAPPED` to a failing test. No implementation code is written until this gate clears.

Phase 3 — Green · gate: BLOCK

Write the **minimum** implementation that satisfies the Phase 2 tests — no speculative logic, no gold-plating — to the conventions in `coding-standards.md`. Run the full suite. A broken pre-existing test is a regression: fix it.

Gate: full suite green, reached by satisfying the Phase 2 tests — not by weakening them. A test's assertions MUST be unchanged between red and green; only fixtures and setup may move. A relaxed assertion is a gate violation.

Phase 4 — Obligation verify · gate: BLOCK

Walk the Phase 1 list item by item. Each `MAPPED` obligation moves to `COVERED` (a real passing test that exercises the claim) or `MISSING` (no test truly covers it). For security-relevant or contract-critical logic, dispatch the `coverage-auditor` agent (`{{PLUGIN_ROOT}}/agents/coverage-auditor.md`) to confirm the tests exercise the claim.

A `MISSING` obligation returns the workflow to Phase 2 — author a correct failing test, then re-run Phase 3 — and loops until it is `COVERED`.

**Stakes:** when you block on a `MISSING` obligation, state what the untested seam leaves exposed, not just that it is `MISSING` — one line naming the consequence: "this error path is untested; a 500 here would reach users silently." The block is

Read more
Ships withcodearbiter

When you can't trust yourself with your code base, trust Arbiter.

Get the whole plugin

Other skills on codearbiter.