Agent-alchemy create-tdd-tasks
Transform SDD tasks into test-first TDD task pairs. Reads existing tasks from /create-tasks and generates paired test tasks with RED-GREEN dependencies. Use when user says "create tdd tasks", "add tdd pairs", "convert to tdd", or wants to apply test-first ordering to SDD tasks.
git clone https://github.com/sequenzia/agent-alchemy
T=$(mktemp -d) && git clone --depth=1 https://github.com/sequenzia/agent-alchemy "$T" && mkdir -p ~/.claude/skills && cp -r "$T/claude/tdd-tools/skills/create-tdd-tasks" ~/.claude/skills/sequenzia-agent-alchemy-create-tdd-tasks && rm -rf "$T"
claude/tdd-tools/skills/create-tdd-tasks/SKILL.mdCreate TDD Tasks Skill
Transform existing SDD implementation tasks into test-first TDD task pairs. For each implementation task, this skill creates a paired test task that must complete first, enforcing test-first development at the pipeline level.
This skill bridges the SDD pipeline (
/create-tasks) and TDD execution (/execute-tdd-tasks), converting a standard task list into one where every implementation task is preceded by a failing-test-writing task.
CRITICAL: Complete ALL 8 phases. The workflow is not complete until Phase 8: Report is finished. After completing each phase, immediately proceed to the next phase without waiting for user prompts.
Core Principles
- Test-first at the pipeline level -- Every implementation task gets a paired test task that blocks it. Tests are written before implementation begins.
- Preserve existing dependencies -- TDD pairs are inserted into the existing SDD dependency chain without breaking any original relationships.
- Merge mode awareness -- Re-running this skill on a task list that already has TDD pairs detects and skips existing pairs instead of creating duplicates.
- Criteria-to-tests conversion -- Acceptance criteria from SDD tasks are converted into test descriptions for the paired test task.
- Minimal metadata additions -- Only
,tdd_mode
, andtdd_phase
are added. All existing metadata is preserved.paired_task_id
Critical Rules
AskUserQuestion is MANDATORY
IMPORTANT: You MUST use the
AskUserQuestion tool for ALL questions to the user. Never ask questions through regular text output.
- Preview confirmation -> AskUserQuestion
- Anomaly resolution -> AskUserQuestion
- Error recovery options -> AskUserQuestion
Text output should only be used for:
- Presenting TDD pair previews and summaries
- Reporting completion status
- Displaying dependency chain visualizations
NEVER do this (asking via text output):
Should I proceed with creating 12 TDD task pairs? 1. Yes 2. No
ALWAYS do this (using AskUserQuestion tool):
AskUserQuestion: questions: - header: "Confirm TDD Pair Creation" question: "Ready to create 12 TDD task pairs?" options: - label: "Yes, create pairs" description: "Create test tasks and set TDD dependencies" - label: "Show details" description: "See full list of pairs before creating" - label: "Cancel" description: "Don't create TDD pairs" multiSelect: false
Plan Mode Behavior
CRITICAL: This skill transforms tasks, NOT creates an implementation plan. When invoked during Claude Code's plan mode:
- DO NOT create a plan for how to implement TDD
- DO NOT defer task transformation to an "execution phase"
- DO proceed with the full TDD task generation workflow immediately
- DO create test tasks using TaskCreate as normal
The TDD task pairs are planning artifacts themselves -- generating them IS the planning activity.
Soft Dependency on sdd-tools
This skill is part of the
tdd-tools plugin and works with agents in the same plugin (tdd-executor, test-writer). It bridges the SDD pipeline (/create-tasks from sdd-tools) and TDD execution (/execute-tdd-tasks). The sdd-tools plugin is expected to be installed since TDD tasks are generated from SDD tasks created by /create-tasks.
Phase 1: Validate & Load References
Goal: Verify prerequisites and load reference materials.
Step 1: Parse Arguments
Check
$ARGUMENTS for optional --task-group filter:
- If
is present, extract the group name for filtering--task-group <group> - If no arguments provided, process all tasks
Step 3: Load Reference Files
Read the TDD decomposition and dependency reference files:
-- Task pairing rules, naming conventions, metadata, merge mode detectionreferences/tdd-decomposition-patterns.md
-- Dependency insertion algorithm, circular dependency detection and breakingreferences/tdd-dependency-rules.md
Phase 2: Read Existing Tasks
Goal: Load the current task list and identify tasks to transform.
Step 1: Get All Tasks
Use
TaskList to retrieve all current tasks.
Step 2: Apply Group Filter
If
--task-group was specified:
- Filter to only tasks where
matches the specified groupmetadata.task_group - Tasks outside the group are not modified
If no
--task-group specified:
- Process all tasks regardless of group
Step 3: Validate Task List
Handle empty/missing states:
Empty task list (no tasks at all):
No tasks found. Please run /create-tasks first to generate implementation tasks from a spec. Usage: /agent-alchemy-sdd:create-tasks <spec-path>
No tasks matching --task-group filter:
No tasks found for group "{group}". Available task groups: - {group1} ({n} tasks) - {group2} ({n} tasks) Try: /create-tdd-tasks --task-group {group1}
Step 4: Classify Tasks
For each task, determine if it should receive a TDD pair:
Eligible for TDD pairing:
- Implementation tasks (subjects like "Create X", "Implement X", "Build X", "Add X")
- Business logic tasks
- API/endpoint tasks
- Data model tasks
- UI/frontend tasks
Skip (no TDD pair created):
- Tasks already marked with
in metadatatdd_mode: true - Test tasks (subjects like "Add tests for X", "Write tests for X", or tasks with
intest
)task_uid - Configuration/setup tasks (subjects like "Configure X", "Set up X")
- Documentation tasks (subjects like "Document X", "Write docs for X")
Record the classification for each task: eligible, skipped (with reason).
Phase 3: Detect Existing TDD Pairs (Merge Mode)
Goal: Identify tasks that already have TDD pairs to avoid duplication.
Detection Algorithm
For each eligible task, check if it already has a TDD pair using these 4 signals (any match means paired):
- Metadata check: Task has
in metadatatdd_mode: true - Paired task check: Task has
in metadata, and the paired task exists in the task listpaired_task_id - UID check: A task exists with
equal to this task'stask_uid
+task_uid:red - Subject check: A task with subject
exists in the same"Write tests for {this task's subject}"task_group
Merge Behavior
For tasks with existing TDD pairs:
| Existing Pair Status | Action |
|---|---|
| Both tasks pending | Skip -- pair already exists |
| Test completed, impl pending | Skip -- pair progressing normally |
| Test completed, impl completed | Skip -- pair fully done |
| Test completed, impl in_progress | Skip -- pair in progress |
| Test pending, impl completed | Flag as anomaly -- impl completed without tests |
| Only impl exists, test missing | Treat as unpaired -- create the test task |
| Only test exists, impl missing | Flag as orphan -- ask user |
Report Merge Status
If any existing pairs detected:
TDD PAIR STATUS: - {n} tasks already have TDD pairs (will skip) - {m} tasks need TDD pairs (will create) - {k} anomalies detected (need user input)
If anomalies exist, use AskUserQuestion to resolve each one:
AskUserQuestion: questions: - header: "TDD Pair Anomaly" question: "Task #{id} '{subject}' was completed without its test task. What should I do?" options: - label: "Create test task anyway" description: "Add a test task for documentation/coverage purposes" - label: "Skip this task" description: "Leave it as-is without a test pair" multiSelect: false
Phase 4: Generate Test Tasks
Goal: Create test task definitions for each eligible unpaired implementation task.
For each eligible task that needs a TDD pair, generate a paired test task.
Step 1: Determine Test Task Subject
Follow the naming convention:
"Write tests for {original task subject}"
Examples:
- "Create User data model" -> "Write tests for Create User data model"
- "Implement POST /auth/login endpoint" -> "Write tests for Implement POST /auth/login endpoint"
Step 2: Infer Test File Path
Determine the test file path based on the implementation task context:
- If implementation task references source files, derive test file path from project conventions
- Common patterns:
->src/foo.ts
,tests/foo.test.ts
->src/foo.pytests/test_foo.py - If no source files referenced, use the task subject to infer a path
Step 3: Detect Test Framework
Determine the test framework using project detection:
- Check for config files:
,jest.config.*
,vitest.config.*
,pytest.ini
,pyproject.tomlsetup.cfg - Check existing test files for import patterns
- Check
for test dependenciespackage.json - Default to the most common framework for the detected language
Step 4: Convert Acceptance Criteria to Test Descriptions
If the implementation task HAS acceptance criteria (
**Acceptance Criteria:** section):
Convert each criterion into a test description:
**Test Descriptions:** _From Functional Criteria:_ - [ ] Test that {criterion rephrased as test assertion} _From Edge Cases:_ - [ ] Test that {edge case rephrased as test assertion} _From Error Handling:_ - [ ] Test that {error scenario rephrased as test assertion} _From Performance:_ (if applicable) - [ ] Test that {performance target as measurable assertion}
If the implementation task LACKS acceptance criteria:
Generate basic test descriptions from the subject and description:
- Parse the subject for intent ("Create X" -> test X exists and has expected structure)
- Extract testable statements from description ("should...", "must...", "returns...", "validates...")
- Generate minimal test descriptions:
**Test Descriptions:** _Inferred from task description:_ - [ ] Test that {subject entity} can be created/initialized - [ ] Test that {subject entity} has expected structure/interface - [ ] Test that {described behavior} works as described
Step 5: Build Test Task Definition
Assemble the complete test task:
subject: "Write tests for {original subject}" description: | Write failing tests for: {original task subject} Test file: {inferred test file path} Test framework: {detected framework} Original task: #{original_task_id} {test descriptions from Step 4} **Acceptance Criteria:** _Functional:_ - [ ] All test descriptions converted into runnable test functions - [ ] Tests follow project test conventions (naming, structure, fixtures) - [ ] Tests are discoverable by the test runner - [ ] Tests fail when run without implementation (RED state) _Edge Cases:_ - [ ] Tests handle import errors gracefully when implementation module does not exist _Error Handling:_ - [ ] Test file is syntactically valid even when implementation is missing Source: {original source reference} activeForm: "Writing tests for {original subject}" metadata: tdd_mode: true tdd_phase: "red" paired_task_id: "{original_task_id}" priority: {inherited from original} complexity: {S or M -- test files are typically smaller} source_section: {inherited from original} spec_path: {inherited from original} feature_name: {inherited from original} task_uid: "{original_task_uid}:red" task_group: {inherited from original}
Step 6: Plan Implementation Task Updates
For each original implementation task, plan the metadata update:
metadata additions: tdd_mode: true tdd_phase: "green" paired_task_id: "{test_task_id}" # Will be set after test task creation
Phase 5: Set Dependencies
Goal: Insert TDD pairs into the existing dependency chain.
Apply the insertion algorithm from
tdd-dependency-rules.md:
For Each TDD Pair
Given implementation task
#N with existing dependencies blockedBy: [A, B, ...]:
- Test task inherits upstream dependencies: Test task
gets#T
(same as original)blockedBy: [A, B, ...] - Implementation task gains test dependency: Task
adds#N
to its#T
listblockedBy - Downstream tasks unchanged: Tasks that depend on
continue to depend on#N#N
Dependency Insertion Example
Before: Model (#1) --> API (#2) --> UI (#3) After: Test-Model (#4) blockedBy: [] Model (#1) blockedBy: [#4] Test-API (#5) blockedBy: [#1] API (#2) blockedBy: [#1, #5] Test-UI (#6) blockedBy: [#2] UI (#3) blockedBy: [#2, #6]
Circular Dependency Detection
After planning all insertions, validate the full dependency graph:
- Build the complete graph from all tasks (original + new test tasks)
- Run topological sort
- If sort fails, a cycle exists
Breaking cycles (weakest-link strategy):
Score each dependency link in the cycle:
- TDD pair link (test -> impl): score 1 (weakest)
- Same-feature cross-layer: score 2
- Cross-feature dependency: score 3 (strongest)
Remove the dependency with the lowest score. Log a warning:
WARNING: Circular dependency detected after TDD pair insertion. Cycle: {task chain} Broken at: {removed link} Reason: TDD pair link is weakest (score: 1) Impact: {explanation of what may run out of order}
Add
needs_review: true and circular_dep_break: true to the affected task's metadata.
Phase 6: Preview & Confirm
Goal: Present the TDD transformation plan and get user approval.
Display Preview
Present a summary of the planned changes:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ TDD TASK PAIR GENERATION PREVIEW ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ SUMMARY: Total implementation tasks: {count} Eligible for TDD pairing: {eligible} Already have TDD pairs: {skipped} (merge mode) New TDD pairs to create: {new_pairs} Tasks skipped (test/config/docs): {skipped_ineligible} NEW TDD PAIRS: Test Task | Blocks | Phase ───────────────────────────────────────────────────────────── Write tests for {subject1} | #{impl_id1} | RED Write tests for {subject2} | #{impl_id2} | RED ... DEPENDENCY CHAIN (after insertion): {visualization of the dependency chain with TDD pairs inserted} {If circular deps detected and broken:} WARNINGS: - Circular dependency broken at: {link} ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Get Confirmation
Use AskUserQuestion to confirm:
AskUserQuestion: questions: - header: "Confirm TDD Pair Creation" question: "Ready to create {n} TDD task pairs?" options: - label: "Yes, create pairs" description: "Create test tasks and update implementation tasks with TDD metadata" - label: "Show task details" description: "See full test task descriptions before creating" - label: "Cancel" description: "Don't create TDD pairs" multiSelect: false
If user selects "Show task details":
- Display each test task's full description
- Show the criteria-to-test conversion
- Then ask for confirmation again
If user selects "Cancel":
- Stop without creating any tasks
- Report cancellation
Phase 7: Create Tasks
Goal: Create test tasks and update implementation tasks with TDD metadata.
Step 1: Create Test Tasks
For each planned test task, use
TaskCreate:
TaskCreate: subject: "Write tests for {original subject}" description: {generated description from Phase 4} activeForm: "Writing tests for {original subject}" metadata: tdd_mode: true tdd_phase: "red" paired_task_id: "{impl_task_id}" priority: {inherited} complexity: {estimated} source_section: {inherited} spec_path: {inherited} feature_name: {inherited} task_uid: "{original_uid}:red" task_group: {inherited}
Capture the returned task ID for each created test task.
Step 2: Update Implementation Tasks
For each paired implementation task, use
TaskUpdate:
TaskUpdate: taskId: "{impl_task_id}" metadata: tdd_mode: true tdd_phase: "green" paired_task_id: "{test_task_id}"
Step 3: Set Dependencies
For each TDD pair, set the dependency relationships:
TaskUpdate: taskId: "{impl_task_id}" addBlockedBy: ["{test_task_id}"]
For test tasks that need upstream dependencies (inheriting from the original impl task):
TaskUpdate: taskId: "{test_task_id}" addBlockedBy: ["{upstream_dep_1}", "{upstream_dep_2}"]
Step 4: Handle Circular Dependency Breaks
If any circular dependencies were detected and broken in Phase 5:
TaskUpdate: taskId: "{affected_task_id}" metadata: needs_review: true circular_dep_break: true
Phase 8: Report
Goal: Present the final summary of created TDD task pairs.
Completion Report
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ TDD TASK PAIR CREATION COMPLETE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Created {n} TDD task pairs Set {m} dependency relationships TDD PAIRS CREATED: Test Task (RED) | Impl Task (GREEN) | Test Blocks ───────────────────────────────────────────────────────────────────────────────── #{test_id}: Write tests for {subj} | #{impl_id}: {subj} | #{impl_id} ... DEPENDENCY CHAIN: {visual representation of the full dependency chain} {If --task-group was used:} Group: {group} Tasks in group: {total} TDD pairs added: {new} {If merge mode detected:} MERGE MODE: Existing pairs preserved: {n} New pairs created: {m} {If circular deps broken:} WARNINGS: {n} circular dependencies detected and broken. Review recommended. NEXT STEPS: Run /execute-tdd-tasks to execute TDD pairs with RED-GREEN-REFACTOR workflow. Run /execute-tdd-tasks --task-group {group} for group-specific execution. ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Error Handling
Empty Task List
If TaskList returns no tasks:
- Inform user to run
first/create-tasks - Provide usage example
- Stop
No Matching Group
If
--task-group filter matches zero tasks:
- List available groups with task counts
- Suggest a valid group
- Stop
All Tasks Already Paired
If merge mode detects that all eligible tasks already have TDD pairs:
All eligible tasks already have TDD pairs. Nothing to create. TDD pair status: - {n} active TDD pairs - {m} completed TDD pairs - {k} tasks skipped (test/config/docs)
TaskCreate Failures
If a TaskCreate call fails:
- Log the failure
- Continue with remaining tasks
- Report partial results in Phase 8 with failed tasks listed
Example Usage
Convert all tasks to TDD pairs
/agent-alchemy-tdd:create-tdd-tasks
Convert a specific group
/agent-alchemy-tdd:create-tdd-tasks --task-group user-authentication
Re-run (merge mode)
/agent-alchemy-tdd:create-tdd-tasks --task-group user-authentication
If TDD pairs already exist for some tasks, they will be detected and skipped.
Important Notes
- Never create duplicate test tasks -- always check merge mode signals first
- Preserve all existing task dependencies -- TDD pairs are inserted, not replacing
- Test tasks always block their paired implementation task
- Test task metadata always inherits
,task_group
,priority
,feature_name
, andspec_path
from the originalsource_section - Task UIDs for test tasks append
to the original UID:red - Always use imperative mood for subjects ("Write tests for X" not "Tests for X")
- Always include activeForm in present continuous ("Writing tests for X")
- Tasks with
are never paired again (prevents double-pairing)tdd_mode: true
Reference Files
-- Task pairing rules, naming conventions, criteria conversion, merge modereferences/tdd-decomposition-patterns.md
-- Dependency insertion algorithm, circular dependency detection and breakingreferences/tdd-dependency-rules.md