Overview
The /sdd-apply command launches the implementer sub-agent to write code based on the generated specs, design, and tasks. It works through tasks in phases, checking off items as it completes them.
v2.0 Enhancement : Now supports Test-Driven Development (TDD) workflow when enabled.
Usage
Optional. The change to implement. If omitted, applies the most recent active change.
What It Does
1. Loads Planning Artifacts
Reads:
proposal.md - Understands intent and scope
specs/*.md - Gets acceptance criteria
design.md - Learns technical approach
tasks.md - Sees implementation checklist
2. Implements Tasks
For each incomplete task:
Read Context
Relevant spec scenarios (acceptance criteria)
Design decisions (technical approach)
Existing code patterns in project
Write Code
Standard Workflow :
Implement the task following specs
TDD Workflow (if enabled):
Write failing test first (RED)
Implement minimum code to pass (GREEN)
Refactor for quality (REFACTOR)
Mark Complete
Updates tasks.md: - [ ] → - [x]
Save Progress
Persists apply-progress artifact with completed tasks
3. Batches Work
Implements tasks in logical phases:
Phase 1: Foundation - Core infrastructure
Phase 2: Implementation - Main functionality
Phase 3: Testing & Polish - Tests and refinements
Pauses between phases for user confirmation.
4. Reports Progress
Shows:
Files created/modified
Tasks completed
Next phase preview
Example Usage
Standard Implementation
Output:
## Loading artifacts for: add-dark-mode
✓ Proposal loaded
✓ Specs loaded (2 files, 11 scenarios)
✓ Design loaded
✓ Tasks loaded (9 tasks across 3 phases)
---
## Implementing Phase 1: Foundation
### Task 1.1: Create ThemeContext and provider ✓
Created `src/context/ThemeContext.tsx` (87 lines)
```tsx
import { createContext , useContext , useEffect , useState } from 'react' ;
type Theme = 'light' | 'dark' ;
interface ThemeContextValue {
theme : Theme ;
setTheme : ( theme : Theme ) => void ;
toggleTheme : () => void ;
}
const ThemeContext = createContext < ThemeContextValue | undefined >( undefined );
export function ThemeProvider ({ children } : { children : React . ReactNode }) {
const [ theme , setThemeState ] = useState < Theme >(() => {
// Check localStorage first
const stored = localStorage . getItem ( 'theme' );
if ( stored === 'dark' || stored === 'light' ) return stored ;
// Fall back to system preference
if ( window . matchMedia ( '(prefers-color-scheme: dark)' ). matches ) {
return 'dark' ;
}
return 'light' ;
});
// Persist theme changes
useEffect (() => {
localStorage . setItem ( 'theme' , theme );
document . documentElement . classList . toggle ( 'dark' , theme === 'dark' );
}, [ theme ]);
// Listen for system preference changes
useEffect (() => {
const mediaQuery = window . matchMedia ( '(prefers-color-scheme: dark)' );
const handler = ( e : MediaQueryListEvent ) => {
if ( ! localStorage . getItem ( 'theme' )) {
setThemeState ( e . matches ? 'dark' : 'light' );
}
};
mediaQuery . addEventListener ( 'change' , handler );
return () => mediaQuery . removeEventListener ( 'change' , handler );
}, []);
const setTheme = ( newTheme : Theme ) => setThemeState ( newTheme );
const toggleTheme = () => setThemeState ( t => t === 'light' ? 'dark' : 'light' );
return (
< ThemeContext.Provider value = { { theme , setTheme , toggleTheme } } >
{ children }
</ ThemeContext.Provider >
);
}
export function useTheme () {
const context = useContext ( ThemeContext );
if ( ! context ) throw new Error ( 'useTheme must be used within ThemeProvider' );
return context ;
}
✅ Satisfies spec scenario: “Theme context provides current theme and toggle function”
Task 1.2: Add CSS custom properties ✓
Modified src/styles/globals.css
Added:
12 CSS custom properties for colors
Light mode definitions (default)
Dark mode overrides in .dark class
:root {
/* Light mode (default) */
--color-bg : #ffffff ;
--color-text : #1a1a1a ;
--color-border : #e5e5e5 ;
--color-primary : #3b82f6 ;
/* ... 8 more variables */
}
.dark {
/* Dark mode overrides */
--color-bg : #1a1a1a ;
--color-text : #f5f5f5 ;
--color-border : #333333 ;
--color-primary : #60a5fa ;
/* ... 8 more variables */
}
/* Apply to all elements */
body {
background-color : var ( --color-bg );
color : var ( --color-text );
}
✅ Satisfies spec requirement: “System SHALL support light and dark color schemes”
Task 1.3: Wrap app with ThemeProvider ✓
Modified src/components/Layout.tsx
import { ThemeProvider } from '@/context/ThemeContext' ;
export default function Layout ({ children } : { children : React . ReactNode }) {
return (
< ThemeProvider >
< div className = "min-h-screen" >
{ children }
</ div >
</ ThemeProvider >
);
}
Phase 1 Complete ✓
Progress : 3/9 tasks done
Files Changed :
Created: src/context/ThemeContext.tsx
Modified: src/styles/globals.css
Modified: src/components/Layout.tsx
Next : Phase 2 (Implementation) - 4 tasks
Continue with Phase 2?
### TDD Workflow Example
```bash
# With tdd: true in config
/sdd-apply
Output:
## TDD Mode Enabled
Following RED-GREEN-REFACTOR cycle for each task.
---
## Task 1.1: Create CSV serialization service
### RED: Write Failing Test
Created `src/services/__tests__/csv-serializer.test.ts`
```typescript
import { CsvSerializer } from '../csv-serializer' ;
describe ( 'CsvSerializer' , () => {
it ( 'should convert observations to CSV format' , () => {
const observations = [
{ id: 1 , title: 'Test' , content: 'Data' , createdAt: '2024-01-01' },
{ id: 2 , title: 'Test 2' , content: 'More data' , createdAt: '2024-01-02' },
];
const csv = CsvSerializer . serialize ( observations );
expect ( csv ). toContain ( 'id,title,content,createdAt' );
expect ( csv ). toContain ( '1,Test,Data,2024-01-01' );
expect ( csv ). toContain ( '2,"Test 2","More data",2024-01-02' );
});
});
Run test: npm test csv-serializer.test.ts
❌ FAIL - Module not found: Cannot resolve ’../csv-serializer’
GREEN: Make Test Pass
Created src/services/csv-serializer.ts
import { stringify } from 'csv-stringify/sync' ;
export class CsvSerializer {
static serialize < T extends Record < string , any >>( data : T []) : string {
if ( data . length === 0 ) return '' ;
return stringify ( data , {
header: true ,
quoted: true ,
});
}
}
Run test: npm test csv-serializer.test.ts
✅ PASS - 1 test passed (12ms)
REFACTOR: Improve Quality
Added TypeScript generics for type safety
Extracted options to constant
Added JSDoc comments
Final implementation:
import { stringify , Options } from 'csv-stringify/sync' ;
const CSV_OPTIONS : Options = {
header: true ,
quoted: true ,
quoted_empty: true ,
encoding: 'utf8' ,
};
/**
* Serializes data to CSV format.
* @param data Array of objects to convert
* @returns CSV string with headers
*/
export class CsvSerializer {
static serialize < T extends Record < string , any >>( data : T []) : string {
if ( data . length === 0 ) return '' ;
return stringify ( data , CSV_OPTIONS );
}
}
Run test: npm test csv-serializer.test.ts
✅ PASS - 1 test passed (11ms)
✅ Task 1.1 Complete
TDD Cycle : RED → GREEN → REFACTOR ✓
Test Coverage : 100% for CsvSerializer
Proceeding to Task 1.2…
## TDD Configuration
Enable TDD workflow in `openspec/config.yaml`:
```yaml
schema: spec-driven
tdd: true
test_command: npm test
context: |
Tech stack: Node.js, TypeScript, Jest
Testing: Test-Driven Development (RED-GREEN-REFACTOR)
Enable Test-Driven Development workflow
Command to run tests (e.g., npm test, pytest, go test)
Implementation Patterns
The implementer sub-agent follows these patterns:
1. Read Before Writing
Always reads existing code in the affected area:
Current implementation patterns
Naming conventions
Import styles
Error handling approaches
2. Follow Existing Conventions
Matches:
File structure
Naming patterns
Code organization
Comment style
3. Satisfy Specs
Each implementation directly addresses spec scenarios:
✅ Satisfies spec scenario: "User can toggle theme with button click"
4. Apply Design Decisions
Follows architecture choices from design.md:
Component structure
Data flow patterns
State management approach
API contracts
Progress Tracking
As tasks complete, tasks.md updates:
Before:
## Phase 1: Foundation
- [ ] 1.1 Create ThemeContext
- [ ] 1.2 Add CSS variables
- [ ] 1.3 Wrap app with provider
After:
## Phase 1: Foundation
- [ x ] 1.1 Create ThemeContext
- [ x ] 1.2 Add CSS variables
- [ x ] 1.3 Wrap app with provider
When to Use
After Planning All planning artifacts (proposal, specs, design, tasks) exist
Reviewed Plan You’ve reviewed and approved the implementation plan
Ready to Code Ready for the implementer to write actual code
Incremental Progress Want to implement in phases with checkpoints
Don’t run /sdd-apply without reviewing tasks.md first. The implementer follows the task list exactly.
Pausing and Resuming
You can pause between phases:
Phase 1 complete (3/9 tasks done).
Continue with Phase 2?
Options:
Type “yes” or “continue” → Proceed to Phase 2
Type “pause” → Stop and review code
Type “revise task 2.1” → Modify a task before continuing
Run /sdd-apply again later → Resumes where it left off
Error Handling
If implementation fails:
❌ Task 2.3 failed: TypeScript compilation error
Error in src/components/ThemeToggle.tsx:12
Property 'theme' does not exist on type '{}'
**Action** : Fixing type annotation...
**Retry** : Implementing task 2.3 again...
✅ Task 2.3 Complete (retry successful)
The implementer:
Detects the error
Analyzes the issue
Fixes the problem
Retries the task
Progress Artifact
Progress is saved to apply-progress artifact:
{
"change" : "add-dark-mode" ,
"tasks_total" : 9 ,
"tasks_complete" : 6 ,
"current_phase" : "Phase 2: Implementation" ,
"files_modified" : [
"src/context/ThemeContext.tsx" ,
"src/styles/globals.css" ,
"src/components/Layout.tsx" ,
"src/components/ThemeToggle.tsx" ,
"src/hooks/useTheme.ts"
],
"last_updated" : "2024-03-04T10:23:45Z"
}
Best Practices
Before running /sdd-apply, read through the task list. Ensure tasks are:
Small enough (< 4 hours each)
In logical order
Well-described
Don’t try to complete all tasks in one go. Pause between phases to:
Test implemented code
Review for quality
Catch issues early
Use TDD for critical code
Enable TDD for:
Business logic
API endpoints
Utility functions
Complex algorithms
Check which files are being modified. If the implementer touches unexpected files, pause and investigate.