Skip to main content

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

/sdd-apply [change-name]
change-name
string
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:
1

Read Context

  • Relevant spec scenarios (acceptance criteria)
  • Design decisions (technical approach)
  • Existing code patterns in project
2

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)
3

Mark Complete

Updates tasks.md: - [ ]- [x]
4

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

/sdd-apply
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)
tdd
boolean
default:"false"
Enable Test-Driven Development workflow
test_command
string
required
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:
  1. Detects the error
  2. Analyzes the issue
  3. Fixes the problem
  4. 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
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.
  • /sdd-verify - Validate implementation after /sdd-apply
  • /sdd-continue - Alternative for phase-by-phase work
  • /sdd-ff - Generate all planning artifacts first

Build docs developers (and LLMs) love