.claude/skills/spec-driven-dev/SKILL.md
Spec-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.
npx skillsauth add kivo360/omoios spec-driven-devInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
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.
YOU MUST follow this skill document exactly. This is not optional guidance—it is the required workflow.
ls -la .omoi_os/ to see what already exists. Don't duplicate.python spec_cli.py validate before syncing.python spec_cli.py sync push when donepython spec_cli.py validate will tell you what's wrongSpec generation runs as a state machine with discrete phases. Each phase:
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ EXPLORE │───▶│ REQUIREMENTS│───▶│ DESIGN │───▶│ TASKS │───▶│ SYNC │
│ (codebase) │ │ (EARS fmt) │ │ (arch+data) │ │ (atomic) │ │ (to API) │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
│ │ │ │ │
▼ ▼ ▼ ▼ ▼
CHECKPOINT CHECKPOINT CHECKPOINT CHECKPOINT COMPLETE
| 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 |
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"
}
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 |
If validation fails:
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
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 |
EVERY file you create in .omoi_os/ MUST begin with YAML frontmatter. This is NON-NEGOTIABLE.
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 missing frontmatter will:
spec_cli.py show commandsWhen creating ANY file in .omoi_os/, your FIRST action should be writing the YAML frontmatter block, THEN the content.
After creating files in .omoi_os/, you MUST sync them to the OmoiOS server using the spec CLI. This is NON-NEGOTIABLE.
The spec CLI is located at:
/root/.claude/skills/spec-driven-dev/scripts/spec_cli.py
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
When the sandbox is created, the orchestrator automatically injects environment variables so that CLI tools and scripts work without manual configuration. This design means:
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.
# 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
If you only create local files without syncing:
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
State Machine Phase:
EXPLORE- Timeout: 3 min, Max Turns: 25 Output:.omoi_os/phase_data/explore.json
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.
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
Structure your questions in categories:
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!
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:
project_type (non-empty string)structure (object with at least one key)conventions (object with naming patterns)related_to_feature (list, can be empty for greenfield)The PRD captures the "why" and "what" at a high level. It's the vision document that everything else traces back to.
.omoi_os/docs/prd-{feature-name}.md
---
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]
State Machine Phase:
REQUIREMENTS(Timeout: 5 min / 20 turns) Transition:EXPLORE→REQUIREMENTS(requires ExplorationEvaluator pass) Next Phase:DESIGN(requires RequirementEvaluator pass)
Requirements define the specific, testable behaviors the system must have. Use EARS format (Easy Approach to Requirements Syntax).
.omoi_os/requirements/{feature-name}.md
WHEN [trigger/condition], THE SYSTEM SHALL [action/behavior].
Examples:
---
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 |
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
}
}
| Criterion | Threshold | Description | |-----------|-----------|-------------| | EARS format compliance | 100% | All requirements use WHEN/SHALL format | | Acceptance criteria | All present | Every requirement has testable criteria | | Traceability | Complete | Links to PRD sections documented | | Priority distribution | Reasonable | Not all HIGH priority | | Requirement count | 5-50 | Reasonable scope for feature |
State Machine Phase:
DESIGN(Timeout: 5 min / 25 turns) Transition:REQUIREMENTS→DESIGN(requires RequirementEvaluator pass) Next Phase:TASKS(requires DesignEvaluator pass)
The design document defines HOW to implement the requirements. It covers architecture, data models, APIs, and implementation details.
.omoi_os/designs/{feature-name}.md
---
id: DESIGN-{FEATURE}-001
title: {Feature Name} Design
feature: {feature-name}
created: {date}
updated: {date}
status: draft
requirements:
- REQ-{FEATURE}-001
# API Endpoints - These sync to the Design panel's "API Specification" section
api_endpoints:
- method: POST
path: /api/v1/{resource}
description: Create a new resource
auth_required: true
request_body: '{"name": "string", "config": {}}'
response: '{"id": "uuid", "name": "string", "created_at": "timestamp"}'
error_responses:
400: Validation error
401: Unauthorized
409: Resource already exists
- method: GET
path: /api/v1/{resource}/{id}
description: Get resource by ID
auth_required: true
path_params: [id]
response: '{"id": "uuid", "name": "string", "status": "string"}'
error_responses:
404: Resource not found
- method: GET
path: /api/v1/{resource}
description: List all resources
auth_required: true
query_params:
limit: Maximum number of results
offset: Pagination offset
status: Filter by status
- method: PUT
path: /api/v1/{resource}/{id}
description: Update resource
auth_required: true
path_params: [id]
- method: DELETE
path: /api/v1/{resource}/{id}
description: Delete resource
auth_required: true
path_params: [id]
# Data Models - These sync to the Design panel's "Data Model" section
data_models:
- name: {ResourceName}
description: Main entity for this feature
table_name: {table_name}
typed_fields:
- name: id
type: uuid
description: Unique identifier
constraints: [primary_key]
- name: name
type: string
description: Display name
nullable: false
- name: status
type: string
description: Current status
default: "'pending'"
- name: config
type: jsonb
description: Configuration data
nullable: true
- name: created_at
type: timestamp
default: now()
- name: updated_at
type: timestamp
default: now()
relationships:
- belongs_to Project (project_id)
- has_many Tasks
---
# {Feature Name} Design
## Overview
[Brief description of the technical approach]
## Architecture Overview
```mermaid
flowchart TB
subgraph External
User[User]
ExtAPI[External API]
end
subgraph System
API[API Layer]
Service[Service Layer]
DB[(Database)]
end
User --> API
API --> Service
Service --> DB
Service --> ExtAPI
[Describe the main components and their responsibilities]
| Component | Responsibility | Technology | |-----------|---------------|------------| | {Component 1} | {What it does} | {Stack} |
The data models are defined in the frontmatter above and will sync to the Design panel. Additional SQL details can be added here:
CREATE TABLE {table_name} (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
{column} {type} {constraints},
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
CREATE INDEX idx_{table}_{column} ON {table}({column});
from pydantic import BaseModel, Field
from datetime import datetime
from uuid import UUID
class {ModelName}(BaseModel):
id: UUID
{field}: {type} = Field(description="{description}")
created_at: datetime
updated_at: datetime
The API endpoints are defined in the frontmatter above and will sync to the Design panel. Additional request/response examples can be documented here:
Request:
{
"name": "My Resource",
"config": {}
}
Response (201):
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "My Resource",
"status": "pending",
"created_at": "2025-01-01T00:00:00Z"
}
Error Response (400):
{
"error": "validation_error",
"message": "Field 'name' is required"
}
[Describe any complex algorithms or business logic]
# Pseudocode for complex logic
def process_feature(input):
# Step 1: Validate
# Step 2: Transform
# Step 3: Persist
# Step 4: Notify
pass
stateDiagram-v2
[*] --> Created
Created --> Processing : start
Processing --> Completed : success
Processing --> Failed : error
Failed --> Processing : retry
Completed --> [*]
| System | Integration Type | Purpose | |--------|-----------------|---------| | {System 1} | REST API | {Why} | | {System 2} | Event Bus | {Why} |
| Parameter | Default | Range | Description | |-----------|---------|-------|-------------| | {param} | {default} | {range} | {description} |
### Step 4.1: Save Design Output (State Machine)
After completing design, save to `.omoi_os/phase_data/design.json`:
```json
{
"api_endpoints": [
{
"method": "POST",
"path": "/api/v1/resource",
"description": "Create resource",
"request_schema": "ResourceCreate",
"response_schema": "Resource"
}
],
"data_models": [
{
"name": "Resource",
"table_name": "resources",
"fields": [
{"name": "id", "type": "uuid", "primary_key": true},
{"name": "name", "type": "string", "nullable": false}
]
}
],
"components": [
{
"name": "ResourceService",
"layer": "service",
"responsibilities": ["CRUD operations", "Validation"]
}
]
}
| Criterion | Threshold | Description | |-----------|-----------|-------------| | API endpoints defined | All from requirements | Every requirement has implementation path | | Data models complete | All entities covered | Schema for each data entity | | Architecture diagram | Present | High-level system overview | | Component responsibilities | Clear | Each component has defined role | | Security considerations | Documented | Auth, validation, etc. addressed |
Note: In the state machine, TICKETS and TASKS are combined into a single
TASKSphase for generation efficiency. The evaluator validates both ticket and task structures together.
Tickets are the parent work items that group related tasks. One ticket typically maps to one major component or capability from the design.
.omoi_os/tickets/TKT-{NNN}.md
Generate sequential IDs: TKT-001, TKT-002, etc.
Check existing: ls .omoi_os/tickets/
---
id: TKT-{NNN}
title: {Ticket Title}
created: {YYYY-MM-DD}
updated: {YYYY-MM-DD}
status: backlog
priority: HIGH
estimate: M
design_ref: designs/{feature-name}.md
requirements:
- REQ-{FEATURE}-FUNC-001
- REQ-{FEATURE}-FUNC-002
dependencies:
blocked_by: []
blocks: []
---
# TKT-{NNN}: {Ticket Title}
## Description
[Clear description of what this ticket accomplishes]
## Acceptance Criteria
- [ ] {Criterion 1 - specific and testable}
- [ ] {Criterion 2}
- [ ] {Criterion 3}
- [ ] All tests pass
- [ ] Code reviewed and approved
## Technical Notes
[Any technical context or decisions relevant to implementation]
## Tasks
- TSK-{NNN}: {Task 1 title}
- TSK-{NNN}: {Task 2 title}
- TSK-{NNN}: {Task 3 title}
## Dependencies
**Blocked By**: {List tickets that must complete first, or "None"}
**Blocks**: {List tickets waiting on this one, or "None"}
## Estimate
**Size**: S | M | L | XL
**Rationale**: {Why this estimate}
State Machine Phase:
TASKS(Timeout: 3 min / 15 turns) Transition:DESIGN→TASKS(requires DesignEvaluator pass) Next Phase:SYNC(requires TaskEvaluator pass)
Tasks are atomic units of work that an AI agent can complete in a single session. They should be specific, self-contained, and have clear deliverables.
.omoi_os/tasks/TSK-{NNN}.md
Generate sequential IDs: TSK-001, TSK-002, etc.
Check existing: ls .omoi_os/tasks/
---
id: TSK-{NNN}
title: {Task Title}
created: {YYYY-MM-DD}
status: pending
parent_ticket: TKT-{NNN}
estimate: S
type: implementation
dependencies:
depends_on: []
blocks: []
---
# TSK-{NNN}: {Task Title}
## Objective
[One sentence describing what this task accomplishes]
## Context
[Brief context about why this task exists and how it fits into the bigger picture]
## Deliverables
- [ ] `{path/to/file.py}` - {What this file does}
- [ ] `{path/to/test_file.py}` - {Tests for the above}
## Implementation Notes
[Specific guidance for how to implement this]
```python
# Example code structure or pseudocode
class FeatureService:
def do_thing(self):
pass
Depends On: {List task IDs that must complete first, or "None"} Blocks: {List task IDs waiting on this one, or "None"}
Size: S (< 2 hours) | M (2-4 hours) | L (4-8 hours)
### Task Generation Rules
1. **Atomic** - Can be completed in a single focused session (1-4 hours ideal)
2. **Self-contained** - All context needed is in the task
3. **Clear deliverable** - Specific files, tests, or outcomes
4. **Testable** - Clear acceptance criteria that can be verified
5. **Dependencies explicit** - What must complete before this can start
### Task Types
- `implementation` - Write new code
- `refactor` - Improve existing code
- `test` - Write tests
- `documentation` - Write docs
- `research` - Investigate options
- `bugfix` - Fix a specific bug
### Step 6.1: Save Tasks Output (State Machine)
After completing tasks, save to `.omoi_os/phase_data/tasks.json`:
```json
{
"tickets": [
{
"id": "TKT-001",
"title": "Implement Resource API",
"priority": "HIGH",
"estimate": "M",
"tasks": ["TSK-001", "TSK-002", "TSK-003"],
"dependencies": {"blocked_by": [], "blocks": ["TKT-002"]}
}
],
"tasks": [
{
"id": "TSK-001",
"title": "Create ResourceService",
"parent_ticket": "TKT-001",
"type": "implementation",
"estimate": "M",
"deliverables": ["omoi_os/services/resource_service.py"],
"dependencies": {"depends_on": [], "blocks": ["TSK-002"]}
}
],
"dependency_graph": {
"TSK-001": [],
"TSK-002": ["TSK-001"],
"TSK-003": ["TSK-002"]
}
}
| Criterion | Threshold | Description | |-----------|-----------|-------------| | Ticket coverage | All design components | Every component has a ticket | | Task atomicity | 1-4 hours each | Tasks completable in single session | | Dependency graph | Valid DAG | No circular dependencies | | Deliverables specified | All tasks | Every task has file deliverables | | Acceptance criteria | All tasks | Testable criteria for each task | | Ticket-task ratio | 2-5 tasks/ticket | Reasonable task grouping |
State Machine Phase:
SYNC(Timeout: 2 min / 10 turns) Transition:TASKS→SYNC(requires TaskEvaluator pass) Final State:COMPLETE(spec ready for execution)
After creating all artifacts locally, sync them to the OmoiOS API:
# Navigate to scripts directory
cd /root/.claude/skills/spec-driven-dev/scripts
# 1. Validate local specs first
python spec_cli.py validate
# 2. Preview what you have
python spec_cli.py show all
# 3. Find your project ID (if not in env)
python spec_cli.py projects
# 4. Dry-run sync to see what would change
python spec_cli.py sync diff
# 5. Push to API
python spec_cli.py sync push
# 6. Verify in API
python spec_cli.py project
"I want to add webhook notifications so external systems can subscribe to events"
Claude: Before designing, let me explore the codebase and ask some questions.
[Reads docs/CLAUDE.md, checks .omoi_os/ for existing specs, searches for event-related code]
Found: We have an EventBusService for internal pub/sub. No existing webhook specs.
Now I need to understand the feature better:
**Problem & Value:**
1. What specific external systems need to receive notifications?
2. What events should be subscribable? (task complete, PR ready, agent stuck?)
3. What happens if a webhook delivery fails?
**Scope:**
4. Should users configure webhooks via UI, API, or both?
5. Do we need authentication for webhook endpoints (HMAC signing)?
6. Is retry logic needed? How many retries?
**Technical:**
7. Should webhooks integrate with the existing EventBusService?
8. What's the expected volume of webhook deliveries per day?
9. Do we need rate limiting per subscriber?
**Constraints:**
10. Are there any specific protocols required (Slack, Discord, custom)?
11. What's the timeline for this feature?
"We need Slack and Discord initially, plus generic HTTP. Events: task_completed, ticket_status_changed, agent_error. HMAC signing required. 3 retries with exponential backoff. Use existing EventBusService. Volume: ~1000/day initially."
Write .omoi_os/docs/prd-webhook-notifications.md
Write .omoi_os/requirements/webhook-notifications.md with EARS-format requirements
Write .omoi_os/designs/webhook-notifications.md with architecture, data models, APIs
.omoi_os/tickets/TKT-001.md - Webhook Infrastructure (models, service, delivery).omoi_os/tickets/TKT-002.md - Slack/Discord FormattersFor TKT-001:
TSK-001.md - Add webhook URL fields to Organization modelTSK-002.md - Create database migrationTSK-003.md - Implement WebhookDeliveryServiceTSK-004.md - Implement WebhookNotificationServiceTSK-005.md - Update API routes for webhook managementTSK-006.md - Write testsFor TKT-002:
TSK-007.md - Implement SlackWebhookFormatterTSK-008.md - Implement DiscordWebhookFormattercd /root/.claude/skills/spec-driven-dev/scripts
python spec_cli.py validate
python spec_cli.py sync push
This section shows exact file contents you should create. Copy these patterns for your specs.
File: .omoi_os/tickets/TKT-001.md
---
id: TKT-001
title: Webhook Infrastructure Setup
created: 2025-01-15
updated: 2025-01-15
status: backlog
priority: HIGH
type: feature
feature: webhook-notifications
estimate: 3d
requirements:
- REQ-WEBHOOK-FUNC-001
- REQ-WEBHOOK-FUNC-002
dependencies:
blocked_by: []
blocks:
- TKT-002
---
# TKT-001: Webhook Infrastructure Setup
## Objective
Set up the core webhook infrastructure including database models, delivery service with retry logic, and API endpoints for webhook management.
## Scope
### In Scope
- WebhookSubscription database model
- WebhookDelivery model for tracking delivery attempts
- WebhookDeliveryService with exponential backoff retry
- CRUD API endpoints for webhook subscriptions
- HMAC signature generation for payload verification
### Out of Scope
- Platform-specific formatters (Slack, Discord) - covered in TKT-002
- UI for webhook management - future ticket
## Acceptance Criteria
- [ ] WebhookSubscription model with url, secret, events[], active fields
- [ ] WebhookDelivery model tracks each delivery attempt with status
- [ ] Service delivers webhooks with 3 retries and exponential backoff
- [ ] All endpoints require authentication
- [ ] Webhook payloads include HMAC-SHA256 signature header
- [ ] Unit tests cover delivery retry logic
- [ ] Integration tests verify end-to-end webhook delivery
## Technical Notes
- Integrate with existing EventBusService to subscribe to events
- Use background task for async delivery (don't block event processing)
- Store webhook secret encrypted at rest
## Tasks
- TSK-001: Add webhook models to database
- TSK-002: Create database migration
- TSK-003: Implement WebhookDeliveryService
- TSK-004: Implement WebhookNotificationService
- TSK-005: Add API routes for webhook CRUD
- TSK-006: Write comprehensive tests
File: .omoi_os/tasks/TSK-003.md
---
id: TSK-003
title: Implement WebhookDeliveryService
created: 2025-01-15
status: pending
priority: HIGH
type: implementation
parent_ticket: TKT-001
estimate: 4h
dependencies:
depends_on:
- TSK-001
- TSK-002
blocks:
- TSK-004
---
# TSK-003: Implement WebhookDeliveryService
## Objective
Create a service that handles the actual HTTP delivery of webhook payloads with retry logic, signature generation, and delivery tracking.
## Implementation Details
### File Location
`omoi_os/services/webhook_delivery.py`
### Class Structure
```python
class WebhookDeliveryService:
def __init__(self, db: DatabaseService):
self.db = db
self.http_client = httpx.AsyncClient(timeout=30.0)
async def deliver(
self,
subscription: WebhookSubscription,
event_type: str,
payload: dict,
) -> WebhookDelivery:
"""Deliver webhook with retry logic."""
...
def _generate_signature(self, payload: bytes, secret: str) -> str:
"""Generate HMAC-SHA256 signature."""
...
async def _attempt_delivery(
self,
url: str,
payload: dict,
headers: dict,
) -> tuple[bool, int, str]:
"""Single delivery attempt. Returns (success, status_code, response)."""
...
X-OmoiOS-Event: {event_type}
X-OmoiOS-Delivery: {delivery_id}
X-OmoiOS-Signature: sha256={signature}
Content-Type: application/json
# Run unit tests
uv run pytest tests/unit/services/test_webhook_delivery.py -v
# Test signature generation
uv run python -c "
from omoi_os.services.webhook_delivery import WebhookDeliveryService
svc = WebhookDeliveryService(None)
sig = svc._generate_signature(b'{\"test\": true}', 'secret')
print(f'Signature: {sig}')
"
### Running the Complete Flow
After creating your spec files, run these commands:
```bash
# Navigate to the scripts directory
cd /root/.claude/skills/spec-driven-dev/scripts
# Step 1: Validate all specs (checks frontmatter, references, structure)
python spec_cli.py validate
# Expected output:
# ✓ Validation passed!
# - 2 tickets validated
# - 6 tasks validated
# - All dependencies resolved
# - All references valid
# Step 2: Preview what will be synced (dry run)
python spec_cli.py sync diff
# Expected output:
# Connecting to https://api.omoios.dev...
# Connected!
#
# Sync Results:
# ------------------------------------------------------------
# [CREATE] ticket TKT-001
# Would create: Webhook Infrastructure Setup
# [CREATE] ticket TKT-002
# Would create: Platform-Specific Formatters
# [CREATE] task TSK-001
# Would create: Add webhook models to database
# ... (more tasks)
# ------------------------------------------------------------
# Summary: 8 would be created, 0 updated, 0 skipped
# Step 3: Actually sync to the API
python spec_cli.py sync push
# Expected output:
# Connecting to https://api.omoios.dev...
# Connected!
# Syncing to API...
#
# Sync Results:
# ------------------------------------------------------------
# [CREATE] ticket TKT-001
# Created with API ID: 550e8400-e29b-41d4-a716-446655440000
# [CREATE] task TSK-001
# Created with API ID: 550e8400-e29b-41d4-a716-446655440001
# ... (more items)
# ------------------------------------------------------------
# Summary: 8 created, 0 updated, 0 skipped, 0 failed
# Step 4: Verify what's in the project
python spec_cli.py project
# Expected output:
# ══════════════════════════════════════════════════════════════
# PROJECT: My Project
# ══════════════════════════════════════════════════════════════
#
# TICKETS (2 total)
# ──────────────────────────────────────────────────────────────
# • TKT-001: Webhook Infrastructure Setup [backlog]
# └── 6 tasks
# • TKT-002: Platform-Specific Formatters [backlog]
# └── 2 tasks
Issue: "Validation failed - missing frontmatter"
# Check which files are missing frontmatter
python spec_cli.py validate
# Solution: Add YAML frontmatter block at the top of each file
# Every file MUST start with --- and end the frontmatter with ---
Issue: "Dependency not found: TSK-099"
# Your task references a dependency that doesn't exist
# Solution: Either create TSK-099.md or remove it from depends_on
Issue: "Connection refused" or timeout
# Check if API URL is correct
echo $OMOIOS_API_URL
# In sandbox, this should be auto-injected
# If empty, the CLI falls back to https://api.omoios.dev
.omoi_os/
├── docs/ # PRDs and high-level documents
│ └── prd-{feature}.md
├── requirements/ # EARS-format requirements
│ └── {feature}.md
├── designs/ # Technical designs
│ └── {feature}.md
├── tickets/ # Parent work items
│ ├── TKT-001.md
│ └── TKT-002.md
└── tasks/ # Atomic work units
├── TSK-001.md
├── TSK-002.md
└── ...
python spec_cli.py show all # Everything
python spec_cli.py show requirements # Just requirements
python spec_cli.py show designs # Just designs
python spec_cli.py show tickets # Just tickets
python spec_cli.py show tasks # Just tasks
python spec_cli.py show graph # Task dependency graph
python spec_cli.py show ticket-graph # Ticket dependency graph
python spec_cli.py show traceability # Full traceability matrix
python spec_cli.py show ready # Tasks ready to work on
python spec_cli.py validate # Check for issues
python spec_cli.py projects # List projects
python spec_cli.py sync diff --project-id <uuid> # Preview changes
python spec_cli.py sync push --project-id <uuid> # Push to API
python spec_cli.py project <uuid> # View project in API
python spec_cli.py api-trace <uuid> # Full API traceability
The orchestrator injects these environment variables into each sandbox session:
| Variable | Purpose | Example |
|----------|---------|---------|
| SPEC_ID | Current spec being generated | 550e8400-... |
| SPEC_PHASE | Current phase name | EXPLORE, REQUIREMENTS, etc. |
| PHASE_DATA_B64 | Base64-encoded prior phase outputs | eyJwcm9qZWN0X3R5cGUi... |
| RESUME_SESSION_ID | Session ID for resumption | session-123-abc |
| SESSION_TRANSCRIPT_B64 | Base64-encoded conversation history | W3sicm9sZSI6InVz... |
| FORK_SESSION | Whether to fork from existing session | true or false |
| OMOIOS_API_URL | API endpoint for sync | https://api.omoios.dev |
Each sandbox MUST have access to:
# Core imports for spec generation
from omoi_os.schemas.spec_generation import (
SpecPhase,
ExplorationContext,
RequirementsOutput,
DesignOutput,
TasksOutput,
)
from omoi_os.services.spec_state_machine import SpecStateMachine
from omoi_os.evaluators import (
ExplorationEvaluator,
RequirementEvaluator,
DesignEvaluator,
TaskEvaluator,
)
Sandboxes need read/write access to:
./ # Project root
./.omoi_os/ # Spec artifacts directory
./.omoi_os/phase_data/ # JSON outputs from each phase
./.omoi_os/docs/ # PRD documents
./.omoi_os/requirements/ # Requirement documents
./.omoi_os/designs/ # Design documents
./.omoi_os/tickets/ # Ticket markdown files
./.omoi_os/tasks/ # Task markdown files
For cross-sandbox resumption, transcripts are saved:
{
"session_id": "session-123-abc",
"spec_id": "550e8400-...",
"phase": "REQUIREMENTS",
"turn_count": 15,
"messages": [
{"role": "user", "content": "..."},
{"role": "assistant", "content": "..."}
],
"phase_data": {
"explore": {...},
"requirements": {...}
},
"created_at": "2025-01-10T...",
"updated_at": "2025-01-10T..."
}
If a phase times out:
.omoi_os/phase_data/{phase}.partial.jsonIf you lose context mid-conversation:
# 1. Check what exists locally
ls .omoi_os/
cat .omoi_os/docs/prd-*.md
cat .omoi_os/requirements/*.md
cat .omoi_os/designs/*.md
# 2. View the full state
python spec_cli.py show all
# 3. Check what's in the API
python spec_cli.py project
Then resume from where you left off based on what's complete and what's missing.
development
Spec-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.
development
Generate comprehensive tests including unit, integration, and property-based tests
development
Spec-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.
development
Plan safe refactoring with dependency analysis, impact assessment, and rollback strategies