Spec-Driven Development
SkillMediaSpec-driven development workflow for turning feature ideas into structured PRDs, requirements, designs, tickets, and tasks. Uses a state machine approach with EXPLORE → REQUIREMENTS → DESIGN → TASKS → SYNC phases. Each phase has validation gates, checkpointing, and session transcript support for cross-sandbox resumption.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Spec-Driven Development skill
What this skill tells your AI
The instructions your AI receives, as published by kivo360/omoios in .claude/skills/spec-driven-dev/SKILL.md and read by ahel’s review.
A systematic workflow for turning feature ideas into actionable work items that AI agents can execute.
Architecture Note: This skill is designed to work with a state machine orchestrator that executes each phase as a separate Claude SDK session. Each phase saves checkpoints to the database and can resume from any point after failure. See
docs/spec-execution-stability.mdfor the full architecture.
🔴 CRITICAL: Read This Skill Document Thoroughly
YOU MUST follow this skill document exactly. This is not optional guidance—it is the required workflow.
Before Creating ANY Spec Files:
- READ THIS ENTIRE SKILL DOCUMENT - Don't skim. Read every section to understand the required formats.
- CHECK EXISTING FILES - Run
ls -la .omoi_os/to see what already exists. Don't duplicate. - REFERENCE THE TEMPLATES - Every file type has a specific format. Copy the exact structure.
- USE THE CLI TOOLS - Validate with
python spec_cli.py validatebefore syncing.
During Spec Creation:
- REFER BACK TO THIS DOCUMENT OFTEN - When unsure about format, re-read the relevant section.
- COPY FRONTMATTER EXACTLY - Don't improvise. Use the exact field names shown in templates.
- CHECK YOUR WORK - After creating files, run validation to catch errors early.
Output Requirements:
- ALL files MUST have YAML frontmatter - No exceptions
- ALL frontmatter fields MUST match the templates - Use exact field names
- ALL specs MUST be synced - Run
python spec_cli.py sync pushwhen done - ALL IDs MUST follow conventions - TKT-001, TSK-001, REQ-FEATURE-001, etc.
If You're Unsure:
- Re-read this skill document - The answer is here
- Look at the Concrete Example section - Full file contents are provided
- Run validation -
python spec_cli.py validatewill tell you what's wrong
🔄 State Machine Architecture
Overview
Spec generation runs as a state machine with discrete phases. Each phase:
- Receives context from previous phases
- Executes a focused, time-boxed Claude SDK session
- Validates output with evaluators
- Saves checkpoint to database and file system
- Stores session transcript for potential resumption
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ EXPLORE │───▶│ REQUIREMENTS│───▶│ DESIGN │───▶│ TASKS │───▶│ SYNC │
│ (codebase) │ │ (EARS fmt) │ │ (arch+data) │ │ (atomic) │ │ (to API) │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
│ │ │ │ │
▼ ▼ ▼ ▼ ▼
CHECKPOINT CHECKPOINT CHECKPOINT CHECKPOINT COMPLETE
Phase Definitions
| Phase | Purpose | Output | Timeout | Max Turns |
|---|---|---|---|---|
| EXPLORE | Analyze codebase structure, patterns, conventions | explore.json | 3 min | 25 |
| REQUIREMENTS | Generate EARS-format requirements | requirements.json + .omoi_os/requirements/*.md | 5 min | 20 |
| DESIGN | Create architecture, data models, APIs | design.json + .omoi_os/designs/*.md | 5 min | 25 |
| TASKS | Break down into tickets and tasks | tasks.json + .omoi_os/tickets/*.md + .omoi_os/tasks/*.md | 3 min | 15 |
| SYNC | Push all artifacts to OmoiOS API | API sync complete | 2 min | 10 |
Phase Context Flow
Each phase receives accumulated context from all previous phases:
# REQUIREMENTS phase receives:
{
"exploration_context": {
"project_type": "Next.js + FastAPI",
"existing_models": [...],
"conventions": {...},
"related_to_feature": [...]
},
"feature_request": "User's original request"
}
# DESIGN phase receives:
{
"exploration_context": {...},
"requirements": [...], # From REQUIREMENTS phase
"feature_name": "feature-name"
}
# TASKS phase receives:
{
"exploration_context": {...},
"requirements": [...],
"design": {...}, # From DESIGN phase
"feature_name": "feature-name"
}
Evaluator Criteria
Each phase output is validated before proceeding:
| Phase | Evaluator | Pass Criteria |
|---|---|---|
| EXPLORE | ExplorationEvaluator | Has project_type, structure, conventions, related_to_feature |
| REQUIREMENTS | RequirementEvaluator | EARS format, 2+ acceptance criteria per requirement, testable |
| DESIGN | DesignEvaluator | Has architecture, data_model, api_endpoints |
| TASKS | TaskEvaluator | Valid priorities, phases, no circular dependencies, no orphan tasks |
Retry Logic
If validation fails:
- Evaluator returns failure reasons
- State machine retries the phase (max 3 attempts)
- Retry prompt includes previous attempt and failure reasons
- If all retries fail, phase is marked as failed with error details
Session Transcript Persistence
Session transcripts are stored for cross-sandbox resumption:
.omoi_os/
├── phase_data/
│ ├── explore.json # EXPLORE phase output
│ ├── requirements.json # REQUIREMENTS phase output
│ ├── design.json # DESIGN phase output
│ └── tasks.json # TASKS phase output
├── session_transcripts/
│ ├── explore.jsonl # EXPLORE session transcript
│ ├── requirements.jsonl # REQUIREMENTS session transcript
│ └── ...
└── checkpoints/
└── state.json # Current state checkpoint
Environment Variables
When running in a sandbox, these environment variables control execution:
| Variable | Purpose |
|---|---|
SPEC_ID | Spec being generated |
SPEC_PHASE | Current phase (explore/requirements/design/tasks/sync) |
PHASE_DATA_B64 | Base64-encoded previous phase outputs |
RESUME_SESSION_ID | Session ID to resume |
SESSION_TRANSCRIPT_B64 | Transcript for cross-sandbox resumption |
FORK_SESSION | "true" to fork instead of modify |
🚨 MANDATORY: YAML Frontmatter on ALL Files
EVERY file you create in .omoi_os/ MUST begin with YAML frontmatter. This is NON-NEGOTIABLE.
Why Frontmatter is Required
- Programmatic Parsing: The CLI tools, API sync, and orchestrator all parse frontmatter to understand file structure
- Traceability: Frontmatter enables linking requirements → designs → tickets → tasks
- Status Tracking: Status, priority, and dependencies are tracked via frontmatter fields
- API Integration: When syncing to backend, frontmatter provides the structured data
Required Frontmatter by File Type
PRDs (.omoi_os/docs/prd-*.md):
---
id: PRD-{FEATURE}-001
title: {Feature Name} PRD
feature: {feature-name}
created: {YYYY-MM-DD}
updated: {YYYY-MM-DD}
status: draft # draft | review | approved
author: Claude
---
Requirements (.omoi_os/requirements/*.md):
---
id: REQ-{FEATURE}-001
title: {Feature Name} Requirements
feature: {feature-name}
created: {YYYY-MM-DD}
updated: {YYYY-MM-DD}
status: draft # draft | review | approved
category: functional # functional | non-functional | constraint
priority: HIGH # CRITICAL | HIGH | MEDIUM | LOW
prd_ref: docs/prd-{feature-name}.md
design_ref: designs/{feature-name}.md
---
Designs (.omoi_os/designs/*.md):
---
id: DESIGN-{FEATURE}-001
title: {Feature Name} Design
feature: {feature-name}
created: {YYYY-MM-DD}
updated: {YYYY-MM-DD}
status: draft # draft | review | approved
requirements:
- REQ-{FEATURE}-001
# API endpoints (synced to Design panel)
api_endpoints:
- method: POST
path: /api/v1/{resource}
description: Create a new resource
auth_required: true
request_body: '{"field": "value"}'
response: '{"id": "uuid", "field": "value"}'
- method: GET
path: /api/v1/{resource}/{id}
description: Get resource by ID
auth_required: true
path_params: [id]
# Data models (synced to Design panel)
data_models:
- name: ResourceModel
description: Main resource entity
table_name: resources
typed_fields:
- name: id
type: uuid
description: Unique identifier
constraints: [primary_key]
- name: name
type: string
description: Resource name
- name: created_at
type: timestamp
default: now()
relationships:
- belongs_to User
- has_many Items
---
Tickets (.omoi_os/tickets/TKT-*.md):
---
id: TKT-{NNN}
title: {Ticket Title}
created: {YYYY-MM-DD}
updated: {YYYY-MM-DD}
status: backlog # backlog | analyzing | building | testing | done | blocked
priority: HIGH # CRITICAL | HIGH | MEDIUM | LOW
estimate: M # S | M | L | XL
design_ref: designs/{feature-name}.md
requirements:
- REQ-{FEATURE}-FUNC-001
dependencies:
blocked_by: []
blocks: []
---
Tasks (.omoi_os/tasks/TSK-*.md):
---
id: TSK-{NNN}
title: {Task Title}
created: {YYYY-MM-DD}
status: pending # pending | in_progress | review | done | blocked
parent_ticket: TKT-{NNN}
estimate: S # S | M | L
type: implementation # implementation | refactor | test | documentation | research | bugfix
dependencies:
depends_on: []
blocks: []
---
❌ Files Without Frontmatter Will Fail
Files missing frontmatter will:
- Not appear in
spec_cli.py showcommands - Not sync to the API
- Not be tracked in traceability reports
- Not be picked up by the orchestrator
✅ Always Start With Frontmatter
When creating ANY file in .omoi_os/, your FIRST action should be writing the YAML frontmatter block, THEN the content.
🚨 MANDATORY: Use Spec CLI to Sync to Server
After creating files in .omoi_os/, you MUST sync them to the OmoiOS server using the spec CLI. This is NON-NEGOTIABLE.
Why Sync is Required
- Visibility: Specs/tickets/tasks only appear in the dashboard after syncing
- Orchestration: The orchestrator only picks up tasks from the database, not from files
- Traceability: Server-side tracking enables dependency management and status updates
- Persistence: Local files can be lost; server data persists across sandbox restarts
Spec CLI Location
The spec CLI is located at:
/root/.claude/skills/spec-driven-dev/scripts/spec_cli.py
Required Workflow: Create → Validate → Sync
EVERY time you create or modify files in .omoi_os/, follow this workflow:
# Step 1: Navigate to the spec CLI scripts directory
cd /root/.claude/skills/spec-driven-dev/scripts
# Step 2: Validate your specs (check for errors BEFORE syncing)
python spec_cli.py validate
# Step 3: Preview what will be synced (dry run)
# Note: OMOIOS_PROJECT_ID and OMOIOS_API_URL are auto-injected - no need to specify!
python spec_cli.py sync-specs diff
# Step 4: Sync requirements and designs to create specs
python spec_cli.py sync-specs push
# Step 5: Preview ticket/task sync
python spec_cli.py sync diff
# Step 6: Sync tickets and tasks
python spec_cli.py sync push
# Step 7: Verify traceability
python spec_cli.py api-trace
Environment Variables (Auto-Injected by Sandbox)
When the sandbox is created, the orchestrator automatically injects environment variables so that CLI tools and scripts work without manual configuration. This design means:
- No manual URL configuration - The API client knows where to connect
- No credential passing - Authentication is pre-configured
- No project ID lookup - The context is already set
Auto-injected variables:
| Variable | Description | Example Value |
|---|---|---|
OMOIOS_API_URL | API endpoint URL | https://api.omoios.dev |
OMOIOS_API_KEY | Authentication key | sk-... |
OMOIOS_PROJECT_ID | Current project ID | proj-abc123 |
TASK_ID | Current task being executed | task-xyz789 |
AGENT_ID | Agent executing the task | agent-def456 |
EXECUTION_MODE | Skill loading mode | implementation or exploration |
Fallback behavior: If running outside a sandbox (e.g., local development), the CLI falls back to https://api.omoios.dev as the default API URL. You can override any value by passing explicit arguments like --api-url or --project-id if needed.
Bottom line: Just run the commands - no configuration required inside sandboxes.
Quick Reference Commands
# Show all local specs
python spec_cli.py show all
# Show only tickets
python spec_cli.py show tickets
# Show only tasks with blocking status
python spec_cli.py show tasks
# Show dependency graph
python spec_cli.py show graph
# Show ready tasks (not blocked)
python spec_cli.py show ready
# List projects from server (uses OMOIOS_API_URL automatically)
python spec_cli.py projects
# View project details (uses OMOIOS_PROJECT_ID and OMOIOS_API_URL automatically)
python spec_cli.py project
❌ DO NOT Skip Syncing
If you only create local files without syncing:
- Tasks won't be picked up by agents
- Tickets won't appear in the dashboard
- Dependencies won't be tracked
- Status updates won't propagate
The Core Flow
The workflow maps to the state machine phases:
┌─────────────────────────────────────────────────────────────────────────────┐
│ STATE MACHINE PHASES │
│ │
│ EXPLORE ──────▶ REQUIREMENTS ──────▶ DESIGN ──────▶ TASKS ──────▶ SYNC │
│ │ │ │ │ │ │
│ Analyze Define WHAT Define HOW Break into Push to │
│ codebase must happen to build it work items API │
│ context │
│ │
│ explore.json requirements/*.md designs/*.md tickets/*.md API │
│ tasks/*.md synced │
└─────────────────────────────────────────────────────────────────────────────┘
Output Directory: All artifacts go in .omoi_os/
Sync Tool: Use spec_cli.py to push to the API
State Machine: Each phase is a separate SDK session with checkpointing
Phase 1: EXPLORE (Most Important!)
State Machine Phase:
EXPLORE- Timeout: 3 min, Max Turns: 25 Output:.omoi_os/phase_data/explore.json
Why This Phase Matters
The quality of everything downstream depends on deeply understanding the problem AND the existing codebase first. Never skip exploration. Rushing to create specs without understanding leads to wasted work and specs that don't align with existing patterns.
Step 1.1: Explore Existing Context
BEFORE asking questions, gather context:
# Check for existing documentation
Read docs/CLAUDE.md
Read docs/architecture/
ls .omoi_os/
# Search for related code
Grep for related service names, models, patterns
Read existing implementations this feature will integrate with
# Check for prior work
ls .omoi_os/requirements/
ls .omoi_os/tickets/
git log --oneline -20
Step 1.2: Ask Discovery Questions (5-15 Questions)
Structure your questions in categories:
Problem & Value (2-3 questions)
- What specific problem does this solve? What pain exists today?
- What happens if we DON'T build this?
- How will we measure success? What metrics matter?
Users & Journeys (2-3 questions)
- Who are the primary users? Secondary?
- What's the happy path user journey?
- What are the edge cases and error scenarios?
Scope & Boundaries (2-3 questions)
- What is explicitly IN scope?
- What is explicitly OUT of scope? (Very important!)
- Are there existing features this overlaps with?
Technical Context (3-5 questions)
- What existing systems/services will this integrate with?
- What data does this need? Where does it come from?
- Are there performance requirements (latency, throughput, scale)?
- What security/privacy considerations apply?
- Are there any hard technical constraints?
Trade-offs & Risks (2-3 questions)
- Are there multiple valid approaches? Which should we explore?
- What are the trade-offs between approaches?
- What could go wrong? What are the risks?
- What's the timeline/priority?
Step 1.3: Summarize Understanding
After questions are answered, write a summary:
## Feature Summary
**Name**: feature-name (kebab-case)
**One-liner**: Brief description of what this does
**Problem Statement**:
[2-3 sentences about the pain point this solves]
**User Stories**:
1. As a [user], I can [action] so that [benefit]
2. As a [user], I can [action] so that [benefit]
3. ...
**Scope**:
- IN: [list what's included]
- OUT: [list what's explicitly excluded]
**Technical Constraints**:
- [constraint 1]
- [constraint 2]
**Risks Identified**:
- [risk 1]
- [risk 2]
**Success Metrics**:
- [metric 1]
- [metric 2]
Get user confirmation before proceeding!
Step 1.4: Save Exploration Output (State Machine)
When running in the state machine, save the exploration context as JSON:
# .omoi_os/phase_data/explore.json
{
"project_type": "Next.js 15 + FastAPI backend",
"structure": {
"frontend": "frontend/src/",
"backend": "backend/omoi_os/",
"api_routes": "backend/omoi_os/api/routes/",
"models": "backend/omoi_os/models/",
"services": "backend/omoi_os/services/"
},
"existing_models": [
{"name": "Spec", "file": "backend/omoi_os/models/spec.py", "fields": ["id", "title", "description"]},
{"name": "Ticket", "file": "backend/omoi_os/models/ticket.py", "fields": ["id", "title", "status"]}
],
"conventions": {
"naming": "snake_case for backend, camelCase for frontend",
"testing": "pytest for backend, vitest for frontend",
"patterns": ["Repository pattern", "Service layer", "Pydantic schemas"]
},
"related_to_feature": [
{"name": "EventBusService", "file": "services/event_bus.py", "relevance": "Publish events for webhooks"},
{"name": "TaskQueue", "file": "services/task_queue.py", "relevance": "Background processing"}
],
"feature_summary": {
"name": "webhook-notifications",
"problem": "External systems cannot subscribe to OmoiOS events",
"scope_in": ["Webhook subscriptions", "HMAC signing", "Retry logic"],
"scope_out": ["UI management", "Rate limiting (future)"]
}
}
Evaluator Criteria:
- ✓ Has
project_type(non-empty string) - ✓ Has
structure(object with at least one key) - ✓ Has
conventions(object with naming patterns) - ✓ Has
related_to_feature(list, can be empty for greenfield)
Phase 2: PRD (Product Requirements Document)
Purpose
The PRD captures the "why" and "what" at a high level. It's the vision document that everything else traces back to.
Location
.omoi_os/docs/prd-{feature-name}.md
Template
---
id: PRD-{FEATURE}-001
title: {Feature Name} PRD
feature: {feature-name}
created: {date}
updated: {date}
status: draft
author: Claude
---
# {Feature Name}
## Executive Summary
[2-3 paragraph overview of the feature, the problem it solves, and why it matters]
## Problem Statement
### Current State
[Describe the pain point that exists today]
### Desired State
[Describe what the world looks like after this feature ships]
### Impact of Not Building
[What happens if we don't build this?]
## Goals & Success Metrics
### Primary Goals
1. [Goal 1]
2. [Goal 2]
### Success Metrics
| Metric | Current | Target | How Measured |
|--------|---------|--------|--------------|
| [Metric 1] | [baseline] | [target] | [method] |
## User Stories
### Primary User: {User Type}
1. **{Story Title}**
As a {user}, I want to {action} so that {benefit}.
Acceptance Criteria:
- [ ] {criterion 1}
- [ ] {criterion 2}
2. ...
## Scope
### In Scope
- [Feature/capability 1]
- [Feature/capability 2]
### Out of Scope
- [Explicitly excluded 1]
- [Explicitly excluded 2]
### Future Considerations
- [Things we might add later]
## Constraints
### Technical Constraints
- [Constraint 1]
- [Constraint 2]
### Business Constraints
- [Timeline, budget, etc.]
## Risks & Mitigations
| Risk | Likelihood | Impact | Mitigation |
|------|------------|--------|------------|
| [Risk 1] | High/Med/Low | High/Med/Low | [How to mitigate] |
## Dependencies
- [Dependency 1 - what we need from other teams/systems]
- [Dependency 2]
## Open Questions
- [ ] [Question that still needs answering]
- [ ] [Another question]
Phase 3: REQUIREMENTS
State Machine Phase:
REQUIREMENTS(Timeout: 5 min / 20 turns) Transition:EXPLORE→REQUIREMENTS(requires ExplorationEvaluator pass) Next Phase:DESIGN(requires RequirementEvaluator pass)
Purpose
Requirements define the specific, testable behaviors the system must have. Use EARS format (Easy Approach to Requirements Syntax).
Location
.omoi_os/requirements/{feature-name}.md
EARS Format
WHEN [trigger/condition], THE SYSTEM SHALL [action/behavior].
Examples:
- WHEN a user submits valid credentials, THE SYSTEM SHALL create an authenticated session within 2 seconds.
- WHEN a notification is triggered, THE SYSTEM SHALL deliver it to the user within 5 seconds.
- WHEN an API rate limit is exceeded, THE SYSTEM SHALL return a 429 status with retry-after header.
Template
---
id: REQ-{FEATURE}-001
title: {Feature Name} Requirements
feature: {feature-name}
created: {date}
updated: {date}
status: draft
category: functional
priority: HIGH
prd_ref: docs/prd-{feature-name}.md
design_ref: designs/{feature-name}.md
---
# {Feature Name} Requirements
## Overview
[Brief description of what these requirements cover]
## Functional Requirements
### REQ-{FEATURE}-FUNC-001: {Requirement Title}
**Priority**: HIGH | MEDIUM | LOW
**Category**: Functional
WHEN {trigger condition}, THE SYSTEM SHALL {required behavior}.
**Acceptance Criteria**:
- [ ] {Testable criterion 1}
- [ ] {Testable criterion 2}
**Notes**: {Any additional context}
---
### REQ-{FEATURE}-FUNC-002: {Requirement Title}
...
## Non-Functional Requirements
### REQ-{FEATURE}-PERF-001: {Performance Requirement}
**Priority**: HIGH
**Category**: Performance
THE SYSTEM SHALL {performance requirement with measurable target}.
**Metrics**:
- P50 latency: < X ms
- P99 latency: < Y ms
- Throughput: > Z requests/second
---
### REQ-{FEATURE}-SEC-001: {Security Requirement}
**Priority**: HIGH
**Category**: Security
THE SYSTEM SHALL {security requirement}.
## Traceability
| Requirement ID | PRD Section | Design Section | Ticket |
|----------------|-------------|----------------|--------|
| REQ-{FEATURE}-FUNC-001 | User Stories #1 | Component A | TKT-001 |
Step 3.1: Save Requirements Output (State Machine)
After completing requirements, save to .omoi_os/phase_data/requirements.json:
{
"requirements": [
{
"id": "REQ-{FEATURE}-FUNC-001",
"category": "functional",
"priority": "HIGH",
"condition": "WHEN user submits form",
"action": "THE SYSTEM SHALL validate and persist data",
"acceptance_criteria": ["Criterion 1", "Criterion 2"]
}
],
"total_count": 15,
"categories": {
"functional": 10,
"performance": 3,
"security": 2
}
}
RequirementEvaluator Criteria
Shortened here. Read the whole file on GitHub.
Signals
- GitHub stars
- 77
- Forks
- 7
- Last commit
- Jun 2026
Advanced
- Catalog kind
- skill
- Gateway key
spec-driven-dev- Source
- github.com/kivo360/omoios