/gaia-atdd
user-facingWhat it does
/gaia-atdd generates Acceptance Test-Driven Development
(ATDD) artifacts from a story's acceptance criteria. Each AC is
transformed into a failing test skeleton in
Given/When/Then format -- the red phase of TDD. The
tests describe expected behavior that must fail because the
implementation does not exist yet. No implementation code is written.
The command supports two invocation modes:
-
Single-story mode -- pass a story key
(e.g.,
/gaia-atdd E3-S7) to generate ATDD for one specific story. -
Batch mode -- invoke without arguments
(
/gaia-atdd) to scan.gaia/artifacts/planning-artifacts/epics-and-stories.mdfor all high-risk stories, then choose which ones to process via an interactive menu.
After generation, the command optionally offers to execute the generated tests to confirm they fail (red-phase verification).
When to use it
-
A high-risk story is about to enter development and needs
acceptance test coverage before implementation begins.
/gaia-dev-storyenforces an ATDD gate for high-risk stories -- run this command first to satisfy it. - Sprint planning identified multiple high-risk stories and you want to seed failing tests across the entire high-risk scope in one pass instead of running the command story by story.
- You want to verify that acceptance criteria are testable before committing to development -- writing Given/When/Then skeletons surfaces ambiguous or untestable ACs early.
For stories with risk: medium or risk: low,
ATDD is optional. If you invoke the command for a non-high-risk story,
it proceeds normally but notes in the output header that ATDD was
invoked explicitly.
Prerequisites
-
A story file must exist. The file lives inside
its epic directory at
.gaia/artifacts/implementation-artifacts/epic-{epic_key}-{slug}/stories/{story_key}-{slug}.md(epic-grouped layout). If it does not exist, the command stops with "Story file not found for {story_key}". Create it first with/gaia-create-story. -
The story file must have acceptance criteria. The
file must contain an
## Acceptance Criteriasection with at least one AC entry. If the section is missing or empty, the command exits with "No acceptance criteria found for {story_key}". -
For batch mode: epics-and-stories.md must exist.
Batch discovery reads
.gaia/artifacts/planning-artifacts/epics-and-stories.md. If the file is missing or unreadable, the command halts with an error. Run/gaia-create-epicsto create it. -
For red-phase execution (optional): a test runner must be
configured. Step 5b reads
config/test-environment.yamland the Test Execution Bridge configuration. If no runner is configured, red-phase execution is skipped with a warning -- it does not fail the overall invocation.
Orchestration mode
When /gaia-atdd starts in subagent mode (Mode A -- the default), the framework emits a one-shot warning to your conversation. The warning text:
────────────────────────────────────────────────────────────────────────────
GAIA orchestration: running in subagent mode (Mode A)
The skill you're invoking belongs to a class (heavy-procedural or
conversational) whose output benefits from cross-step context. Mode A
dispatches each sub-agent in its own forked context, so context may
be lossy between steps — sub-agents return summaries, not full reasoning.
For the full-fidelity experience, enable Mode B (Agent Teams):
1. Set CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 in your environment.
2. Add orchestration.mode: team to .gaia/config/project-config.yaml.
Mode B uses persistent teammates that preserve in-conversation state
across dispatches. See the orchestration contract for details.
This warning is shown once per session.
────────────────────────────────────────────────────────────────────────────
Why Mode B is better for this command
The /gaia-atdd skill declares orchestration_class: heavy-procedural in its SKILL.md frontmatter. Heavy-procedural skills produce output that benefits from cross-step context -- under Mode A every sub-agent dispatch runs in its own forked context and can only return a summary back to the orchestrator, losing the full reasoning trace of every prior step. Mode B uses persistent teammates that retain in-conversation state across dispatches, so each agent's contribution can build on what was said before instead of receiving only a summary.
How to enable Mode B
Both steps are required. If either is missing, the framework falls back silently to Mode A and the warning fires again on the next session.
Step 1 -- set the environment variable:
export CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1
Add this to your shell rc file to persist across sessions, or set it in Claude Code's settings.json.
Step 2 -- add the YAML block to .gaia/config/project-config.yaml:
orchestration:
mode: team
One-shot semantics
The warning is emitted once per Claude Code session. A marker file at _memory/checkpoints/orchestration-warning-shown.<session-id> suppresses the warning for the rest of the session. Starting a new session re-emits the warning once.
How to invoke
Single-story mode
/gaia-atdd E3-S7
Pass a story key in E{n}-S{n} format. The command
generates ATDD for that one story.
Batch mode
/gaia-atdd
Invoke without arguments. The command discovers all high-risk stories
from epics-and-stories.md and presents a menu to choose
which ones to process.
What it does step by step
-
Validate input
If a story key was provided, validates it matches the
E{n}-S{n}format and confirms the key exists inepics-and-stories.md. If the format is wrong, exits with "Invalid story key format". If the key is not found, exits with "Story {key} not found in epics-and-stories.md" -- it does NOT fall back to batch mode. -
Batch discovery (argumentless only)
When invoked without a story key, scans
epics-and-stories.mdfor stories whose risk column is exactlyhigh(medium and low are excluded). Presents a selection menu:- all -- generate ATDD for every discovered high-risk story.
-
select -- pick specific stories by number
(e.g.,
1,3). Invalid selections re-prompt the menu. - skip -- exit without generating anything.
When exactly one high-risk story is found, the menu collapses to
[all / skip](noselectoption). When zero high-risk stories are found, the command exits gracefully with "No high-risk stories found -- nothing to generate". -
Load story file
Searches
.gaia/artifacts/implementation-artifacts/epic-{epic_key}-{slug}/stories/{story_key}-{slug}.mdfor the story file. Reads the story title, risk level, and every entry in the## Acceptance Criteriasection. Stories with zero ACs are skipped with a warning. -
Generate AC-to-test mapping
For each acceptance criterion (AC1, AC2, AC-EC1, etc.):
- Extracts the AC identifier and description.
- Transforms the AC into a Given/When/Then test skeleton with a descriptive test name.
- Maintains a strict 1:1 mapping -- each AC produces exactly one test.
-
Write ATDD artifact
Writes the artifact to
.gaia/artifacts/test-artifacts/atdd-{story_key}.mdusing an atomic write (temp file then rename) to prevent corruption if interrupted. The artifact contains:- Header with story key, title, risk level, and generation date.
- AC-to-test mapping table (AC ID, description, test name).
- Test skeletons in Given/When/Then format.
- Summary confirming total ACs, total tests, and that all tests are in failing/red state.
If the artifact already exists from a prior run, it is overwritten with a logged warning. If the output exceeds 10KB, a size warning is displayed.
- Validation Verifies: every AC has exactly one test, no test references a nonexistent AC, all tests use Given/When/Then format, and the output file was written successfully.
-
Red-phase execution (optional)
Prompts: "Run generated tests now to confirm red phase? [y/N]".
On
y, executes the tests via the configured Test Execution Bridge runner. Each test has a per-test timeout (default 30s). All tests are expected to fail -- if any unexpectedly pass, a warning is logged. Onn(default), this step is skipped entirely.
Batch mode iteration
In batch mode, Steps 3 through 7 run as a self-contained sub-invocation for each selected story. A failure on one story (missing file, empty ACs) emits a warning and continues to the next -- it does not abort the batch. At the end, a summary distinguishes stories that were generated (new artifact) from those that were overwritten (prior artifact existed).
Inputs
| Input | Source | Description | Example |
|---|---|---|---|
story-key |
Command argument (optional) |
The story to generate ATDD for, in E{n}-S{n}
format. Omit to enter batch mode.
|
/gaia-atdd E3-S7 |
| Story file | .gaia/artifacts/implementation-artifacts/epic-{epic_key}-{slug}/stories/{story_key}-{slug}.md |
Contains the acceptance criteria that are transformed into test skeletons. Also provides story title and risk level. | -- |
| Epics and stories | .gaia/artifacts/planning-artifacts/epics-and-stories.md |
Used in both modes: single-story mode verifies the key exists; batch mode filters for high-risk entries. | -- |
| Test environment config | config/test-environment.yaml |
Read during optional Step 5b (red-phase execution) to locate the configured test runner. Not required if you skip red-phase execution. | -- |
| API testing patterns | Skill knowledge fragment | Schema validation and contract test patterns loaded during AC-to-test transformation for API-related acceptance criteria. | -- |
Outputs
| Output | Location | Description |
|---|---|---|
| ATDD artifact | .gaia/artifacts/test-artifacts/atdd-{story_key}.md |
Given/When/Then test skeletons for every AC in the story, plus the AC-to-test traceability table. One file per story. |
| Red-phase results (optional) | Console output | Pass/fail counts from executing the generated tests. All tests are expected to fail (red phase). |
| Checkpoint files | _memory/checkpoints/ |
Written after each step to enable
/gaia-resume if
the session is interrupted.
|
Example session
Single-story mode
Suppose story E3-S7 has the following acceptance criteria in its story file:
## Acceptance Criteria
- [ ] **AC1:** Given a user submits valid registration credentials,
when the registration endpoint is called, then a new user
account is created and a 201 response is returned.
- [ ] **AC2:** Given a user submits an email that is already registered,
when the registration endpoint is called, then a 409 Conflict
response is returned with a descriptive error message.
- [ ] **AC-EC1:** Given the database is unreachable, when the
registration endpoint is called, then a 503 Service Unavailable
response is returned and the error is logged.
Running /gaia-atdd E3-S7 produces:
> /gaia-atdd E3-S7
Validating story key E3-S7...
Format: valid (E{n}-S{n}).
Lookup: found in epics-and-stories.md.
Loading story file...
Path: .gaia/artifacts/implementation-artifacts/epic-E3-security/stories/E3-S7-user-registration.md
Title: User registration
Risk: high
Acceptance criteria: 3 (AC1, AC2, AC-EC1)
Generating AC-to-test mapping...
| AC | Description | Test Name |
|--------|--------------------------------------|---------------------------------------|
| AC1 | Valid registration creates account | test_valid_registration_creates_user |
| AC2 | Duplicate email returns 409 | test_duplicate_email_returns_conflict |
| AC-EC1 | Database unreachable returns 503 | test_db_unreachable_returns_503 |
Writing test skeletons...
## Test: test_valid_registration_creates_user (AC1)
**Given** a user submits valid registration credentials
- email: "newuser@example.com"
- password: meets minimum complexity requirements
**When** the registration endpoint POST /api/register is called
**Then** a new user account is created in the database
- AND a 201 Created response is returned
- AND the response body contains the new user ID
**Status:** FAILING (red phase -- implementation does not exist)
## Test: test_duplicate_email_returns_conflict (AC2)
**Given** a user submits an email that is already registered
- existing user with email "existing@example.com" in database
**When** the registration endpoint POST /api/register is called
with email "existing@example.com"
**Then** a 409 Conflict response is returned
- AND the response body contains a descriptive error message
- AND no duplicate account is created
**Status:** FAILING (red phase -- implementation does not exist)
## Test: test_db_unreachable_returns_503 (AC-EC1)
**Given** the database is unreachable
- database connection pool returns connection timeout
**When** the registration endpoint POST /api/register is called
**Then** a 503 Service Unavailable response is returned
- AND the error is logged with severity ERROR
- AND no partial user record is created
**Status:** FAILING (red phase -- implementation does not exist)
Artifact written to: .gaia/artifacts/test-artifacts/atdd-E3-S7.md
3 ACs mapped to 3 tests. All tests in red (failing) state.
Validation: PASSED
- Every AC has exactly one test: YES
- No orphan tests: YES
- All tests use Given/When/Then: YES
Run generated tests now to confirm red phase? [y/N]
> n
Done. ATDD artifact ready at .gaia/artifacts/test-artifacts/atdd-E3-S7.md
Batch mode
> /gaia-atdd
Scanning epics-and-stories.md for high-risk stories...
Found 3 high-risk stories:
1. E3-S7 User registration (risk: high, 3 ACs)
2. E3-S12 Password reset flow (risk: high, 5 ACs)
3. E5-S3 Payment processing webhook (risk: high, 7 ACs)
[all / select / skip]
> select
Enter story numbers (comma-separated): 1,3
Processing E3-S7 (1/2)...
Loaded 3 ACs. Generating test skeletons...
Artifact written to: .gaia/artifacts/test-artifacts/atdd-E3-S7.md (generated)
Processing E5-S3 (2/2)...
Loaded 7 ACs. Generating test skeletons...
Overwriting existing ATDD artifact at .gaia/artifacts/test-artifacts/atdd-E5-S3.md
Artifact written to: .gaia/artifacts/test-artifacts/atdd-E5-S3.md (overwritten)
Batch summary:
Generated: 1 (E3-S7)
Overwritten: 1 (E5-S3)
Skipped: 1 (E3-S12 -- not selected)
Run generated tests now to confirm red phase? [y/N]
> n
Done.
What to run next
-
/gaia-dev-story-- implement the story. For high-risk stories, the ATDD gate is now satisfied and development can begin. -
/gaia-edit-test-plan-- add the generated acceptance tests to the project test plan if your project maintains one. -
/gaia-test-strategy-- review or create the overall test strategy if one does not exist yet.
Troubleshooting
"Invalid story key format"
The story key must match the E{n}-S{n} pattern (for
example, E3-S7). Keys like S7 or
E3S7 are rejected. Include the full epic prefix.
"Story {key} not found in epics-and-stories.md"
The key you provided does not appear in
.gaia/artifacts/planning-artifacts/epics-and-stories.md. Verify
the key is correct. The command does not fall back to batch mode
when a specific key is given -- if you intended batch discovery,
invoke /gaia-atdd without arguments.
"Story file not found for {story_key}"
The story key exists in epics-and-stories.md but no
corresponding file was found under
.gaia/artifacts/implementation-artifacts/. Run
/gaia-create-story {key}
to create the story file first.
"No acceptance criteria found for {story_key}"
The story file exists but its ## Acceptance Criteria
section is missing or empty. Edit the story file to add ACs before
running ATDD, or use
/gaia-fix-story
to address validation findings.
"No high-risk stories found -- nothing to generate"
Batch mode found no stories with risk: high in
epics-and-stories.md. If you want to generate ATDD
for a specific medium- or low-risk story, use single-story mode:
/gaia-atdd E3-S7.
"Cannot read .gaia/artifacts/planning-artifacts/epics-and-stories.md"
The epics file is missing or unreadable. Run
/gaia-create-epics
to create the breakdown first.
"Test runner not configured -- skipping red-phase execution"
You opted to run red-phase tests, but no test runner is configured
in config/test-environment.yaml or the
Test Execution Bridge is disabled. The ATDD artifact is still
written -- only the optional execution step is skipped. Configure
a test runner or enable the bridge to use this feature.
"ATDD output exceeds 10KB"
The story has many acceptance criteria (typically 20+) and the generated artifact is large. This is a warning only -- no content is truncated. Review the artifact for completeness and consider whether the story should be split into smaller stories.
I keep seeing the GAIA orchestration warning every time I start this command
The warning is shown once per session, so if it fires again that's a new session -- not a per-skill repeat. If you want to silence it entirely, enable Mode B (full-fidelity orchestration via Agent Teams). Both of these conditions must be true:
echo $CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMSreturns1(not empty).gaia/config/project-config.yamlcontains:orchestration: mode: team
If either is missing the framework silently uses Mode A and re-emits the warning each session.