feat: Add orchestrator template and roles for executor and planner

- Created a new orchestrator template for Codex skill design, detailing structure and execution phases.
- Introduced the executor role with responsibilities for task execution, including routing to backends and handling implementation.
- Added the planner role for requirement breakdown, issue creation, and task dispatching, ensuring a structured planning process.
This commit is contained in:
catlog22
2026-02-16 00:17:15 +08:00
parent dc03862ca7
commit a4fff6a591
36 changed files with 4168 additions and 2589 deletions

View File

@@ -1,465 +0,0 @@
---
name: ccw-loop
description: Stateless iterative development loop with single-agent deep interaction. Supports develop, debug, validate phases with file-based state tracking. Triggers on "ccw-loop", "dev loop", "development loop", "开发循环", "迭代开发".
allowed-tools: spawn_agent, wait, send_input, close_agent, AskUserQuestion, Read, Write, Edit, Bash, Glob, Grep
---
# CCW Loop - Stateless Iterative Development Workflow
Stateless iterative development loop using Codex single-agent deep interaction pattern. One agent handles all phases (develop → debug → validate → complete) via `send_input`, with file-based state tracking and Dashboard integration.
## Architecture Overview
```
+-------------------------------------------------------------+
| Dashboard (UI) |
| [Create] [Start] [Pause] [Resume] [Stop] [View Progress] |
+-------------------------------------------------------------+
|
v
+-------------------------------------------------------------+
| loop-v2-routes.ts (Control Plane) |
| |
| State: {projectRoot}/.workflow/.loop/{loopId}.json (MASTER) |
| Tasks: {projectRoot}/.workflow/.loop/{loopId}/.task/*.json |
| |
| /start -> Trigger ccw-loop skill with --loop-id |
| /pause -> Set status='paused' (skill checks before action) |
| /stop -> Set status='failed' (skill terminates) |
| /resume -> Set status='running' (skill continues) |
+-------------------------------------------------------------+
|
v
+-------------------------------------------------------------+
| ccw-loop Skill (Execution Plane) |
| |
| Single Agent Deep Interaction: |
| spawn_agent -> wait -> send_input -> ... -> close_agent |
| |
| Actions: INIT -> DEVELOP -> DEBUG -> VALIDATE -> COMPLETE |
+-------------------------------------------------------------+
```
## Key Design Principles
1. **Single Agent Deep Interaction**: One agent handles entire loop lifecycle via `send_input` (no multi-agent overhead)
2. **Unified State**: API and Skill share `{projectRoot}/.workflow/.loop/{loopId}.json` state file
3. **Control Signals**: Skill checks `status` field before each action (paused/stopped → graceful exit)
4. **File-Driven Progress**: All progress documented in `{projectRoot}/.workflow/.loop/{loopId}.progress/`
5. **Resumable**: Continue any loop with `--loop-id`
6. **Dual Trigger**: Supports API trigger (`--loop-id`) and direct call (task description)
## Arguments
| Arg | Required | Description |
|-----|----------|-------------|
| TASK | One of TASK or --loop-id | Task description (for new loop) |
| --loop-id | One of TASK or --loop-id | Existing loop ID to continue |
| --auto | No | Auto-cycle mode (develop → debug → validate → complete) |
## Prep Package Integration
When `prep-package.json` exists at `{projectRoot}/.workflow/.loop/prep-package.json`, Phase 1 consumes it to:
- Load pre-built task list from `.task/*.json` files instead of generating tasks from scratch
- Apply auto-loop config (max_iterations, timeout)
- Preserve source provenance and convergence criteria from upstream planning/analysis skills
Prep packages are generated by the interactive prompt `/prompts:prep-loop`, which accepts JSONL from:
- `collaborative-plan-with-file` (.task/*.json)
- `analyze-with-file` (.task/*.json)
- `brainstorm-to-cycle` (cycle-task.md → converted to task format)
See [phases/00-prep-checklist.md](phases/00-prep-checklist.md) for schema and validation rules.
## Execution Modes
### Mode 1: Interactive
User manually selects each action via menu.
```
User -> MENU -> Select action -> Execute -> View results -> MENU -> ...
```
### Mode 2: Auto-Loop
Automatic execution using `selectNextAction` logic.
```
INIT -> DEVELOP -> ... -> VALIDATE -> (if fail) -> DEBUG -> VALIDATE -> COMPLETE
```
## Execution Flow
```
Input Parsing:
└─ Parse arguments (TASK | --loop-id + --auto)
└─ Convert to structured context (loopId, state, progressDir)
Phase 1: Session Initialization
└─ Ref: phases/01-session-init.md
├─ Create new loop OR resume existing loop
├─ Initialize state file and directory structure
└─ Output: loopId, state, progressDir
Phase 2: Orchestration Loop
└─ Ref: phases/02-orchestration-loop.md
├─ Spawn single executor agent
├─ Main while loop: wait → parse → dispatch → send_input
├─ Handle: COMPLETED / PAUSED / STOPPED / WAITING_INPUT / next action
├─ Update iteration count per cycle
└─ close_agent on exit
```
**Phase Reference Documents** (read on-demand when phase executes):
| Phase | Document | Purpose |
|-------|----------|---------|
| 0 | [phases/00-prep-checklist.md](phases/00-prep-checklist.md) | Prep package schema and validation rules |
| 1 | [phases/01-session-init.md](phases/01-session-init.md) | Argument parsing, state creation/resume, directory init |
| 2 | [phases/02-orchestration-loop.md](phases/02-orchestration-loop.md) | Agent spawn, main loop, result parsing, send_input dispatch |
## Data Flow
```
User Input (TASK | --loop-id + --auto)
[Parse Arguments]
↓ loopId, state, progressDir
Phase 1: Session Initialization
↓ loopId, state (initialized/resumed), progressDir
Phase 2: Orchestration Loop
↓ spawn agent → [INIT] → wait → parse
┌─── Main Loop (while iteration < max) ──────────┐
│ wait() → parseActionResult(output) │
│ ├─ COMPLETED → close_agent, return │
│ ├─ PAUSED → close_agent, return │
│ ├─ STOPPED → close_agent, return │
│ ├─ WAITING_INPUT → collect input → send_input │
│ └─ next_action → send_input(continue) │
│ Update iteration in state file │
└──────────────────────────────────────────────────┘
close_agent → return finalState
```
## Session Structure
```
{projectRoot}/.workflow/.loop/
├── {loopId}.json # Master state file (API + Skill shared)
├── {loopId}/.task/ # Task files directory (API managed)
│ └── TASK-{id}.json # Individual task files (task-schema.json)
└── {loopId}.progress/ # Skill progress files
├── develop.md # Development progress timeline
├── debug.md # Understanding evolution document
├── validate.md # Validation report
├── changes.log # Code changes log (NDJSON)
├── debug.log # Debug log (NDJSON)
├── hypotheses.json # Debug hypotheses tracking
├── test-results.json # Test execution results
├── coverage.json # Coverage data
└── summary.md # Completion summary
```
## State Management
Master state file: `{projectRoot}/.workflow/.loop/{loopId}.json`
```json
{
"loop_id": "loop-v2-20260122T100000-abc123",
"title": "Task title",
"description": "Full task description",
"max_iterations": 10,
"status": "created | running | paused | completed | failed | user_exit",
"current_iteration": 0,
"created_at": "ISO8601",
"updated_at": "ISO8601",
"completed_at": "ISO8601 (optional)",
"failure_reason": "string (optional)",
"skill_state": {
"current_action": "init | develop | debug | validate | complete | null",
"last_action": "string | null",
"completed_actions": [],
"mode": "interactive | auto",
"develop": {
"total": 0, "completed": 0, "current_task": null,
"tasks": [{ "id": "task-001", "description": "...", "tool": "gemini", "mode": "write", "status": "pending", "files_changed": [], "created_at": "ISO8601", "completed_at": null }],
"last_progress_at": null
},
"debug": {
"active_bug": null, "hypotheses_count": 0,
"hypotheses": [{ "id": "H1", "description": "...", "testable_condition": "...", "logging_point": "file:func:line", "evidence_criteria": { "confirm": "...", "reject": "..." }, "likelihood": 1, "status": "pending", "evidence": null, "verdict_reason": null }],
"confirmed_hypothesis": null, "iteration": 0, "last_analysis_at": null
},
"validate": {
"pass_rate": 0, "coverage": 0,
"test_results": [{ "test_name": "...", "suite": "...", "status": "passed | failed | skipped", "duration_ms": 0, "error_message": null, "stack_trace": null }],
"passed": false, "failed_tests": [], "last_run_at": null
},
"errors": [{ "action": "...", "message": "...", "timestamp": "ISO8601" }],
"summary": { "duration": 0, "iterations": 0, "develop": {}, "debug": {}, "validate": {} }
}
}
```
**Control Signal Checking**: Agent checks `state.status` before every action:
- `running` → continue
- `paused` → exit gracefully, wait for resume
- `failed` → terminate
- Other → stop
**Recovery**: If state corrupted, rebuild `skill_state` from `{projectRoot}/.workflow/.loop/{loopId}.progress/` markdown files and logs.
## Action Catalog
| Action | Purpose | Preconditions | Output Files | Trigger |
|--------|---------|---------------|--------------|---------|
| [INIT](actions/action-init.md) | Initialize session | status=running, skill_state=null | develop.md, state.json | First run |
| [DEVELOP](actions/action-develop.md) | Execute dev task | pending tasks > 0 | develop.md, changes.log | Has pending tasks |
| [DEBUG](actions/action-debug.md) | Hypothesis debug | needs debugging | debug.md, debug.log | Test failures |
| [VALIDATE](actions/action-validate.md) | Run tests | needs validation | validate.md, test-results.json | After develop/debug |
| [COMPLETE](actions/action-complete.md) | Finish loop | all done | summary.md | All tasks done |
| [MENU](actions/action-menu.md) | Display menu | interactive mode | - | Interactive mode |
### Action Flow
```
spawn_agent (ccw-loop-executor)
|
v
+-------+
| INIT | (if skill_state is null)
+-------+
|
v
+-------+ send_input
| MENU | <------------- (user selection in interactive mode)
+-------+
|
+---+---+---+---+
| | | | |
v v v v v
DEV DBG VAL CMP EXIT
|
v
wait() -> get result
|
v
[Loop continues via send_input]
|
v
close_agent()
```
### Action Dependencies
| Action | Depends On | Leads To |
|--------|------------|----------|
| INIT | - | MENU or DEVELOP |
| MENU | INIT | User selection |
| DEVELOP | INIT | DEVELOP, DEBUG, VALIDATE |
| DEBUG | INIT | DEVELOP, VALIDATE |
| VALIDATE | DEVELOP or DEBUG | COMPLETE, DEBUG, DEVELOP |
| COMPLETE | - | Terminal |
### Action Sequences
```
Happy Path (Auto): INIT → DEVELOP → DEVELOP → VALIDATE (pass) → COMPLETE
Debug Iteration: INIT → DEVELOP → VALIDATE (fail) → DEBUG → VALIDATE (pass) → COMPLETE
Interactive Path: INIT → MENU → DEVELOP → MENU → VALIDATE → MENU → COMPLETE
```
## Auto Mode Selection Logic
```javascript
function selectNextAction(state) {
const skillState = state.skill_state
// 1. Terminal conditions
if (state.status === 'completed') return null
if (state.status === 'failed') return null
if (state.current_iteration >= state.max_iterations) return 'COMPLETE'
// 2. Initialization check
if (!skillState) return 'INIT'
// 3. Auto selection based on state
const hasPendingDevelop = skillState.develop.tasks.some(t => t.status === 'pending')
if (hasPendingDevelop) return 'DEVELOP'
if (skillState.last_action === 'DEVELOP') {
if (skillState.develop.completed < skillState.develop.total) return 'DEBUG'
}
if (skillState.last_action === 'DEBUG' || skillState.debug.confirmed_hypothesis) {
return 'VALIDATE'
}
if (skillState.last_action === 'VALIDATE') {
if (!skillState.validate.passed) return 'DEVELOP'
}
if (skillState.validate.passed && !hasPendingDevelop) return 'COMPLETE'
return 'DEVELOP'
}
```
## Coordination Protocol
### Agent → Orchestrator (ACTION_RESULT)
Every action MUST output:
```
ACTION_RESULT:
- action: {ACTION_NAME}
- status: success | failed | needs_input
- message: {user-facing message}
- state_updates: { ... }
FILES_UPDATED:
- {file_path}: {description}
NEXT_ACTION_NEEDED: {ACTION_NAME} | WAITING_INPUT | COMPLETED | PAUSED
```
### Orchestrator → Agent (send_input)
Auto mode continuation:
```
## CONTINUE EXECUTION
Previous action completed: {action}
Result: {status}
## EXECUTE NEXT ACTION
Continue with: {next_action}
Read action instructions and execute.
Output ACTION_RESULT when complete.
```
Interactive mode user input:
```
## USER INPUT RECEIVED
Action selected: {action}
## EXECUTE SELECTED ACTION
Read action instructions and execute: {action}
Update state and progress files accordingly.
Output ACTION_RESULT when complete.
```
### Codex Subagent API
| API | Purpose |
|-----|---------|
| `spawn_agent({ message })` | Create subagent, returns `agent_id` |
| `wait({ ids, timeout_ms })` | Wait for results (only way to get output) |
| `send_input({ id, message })` | Continue interaction / follow-up |
| `close_agent({ id })` | Close and reclaim (irreversible) |
**Rules**: Single agent for entire loop. `send_input` for multi-phase. `close_agent` only after confirming no more interaction needed.
## TodoWrite Pattern
### Phase-Level Tracking (Attached)
```json
[
{"content": "Phase 1: Session Initialization", "status": "completed"},
{"content": "Phase 2: Orchestration Loop", "status": "in_progress"},
{"content": " → Action: INIT", "status": "completed"},
{"content": " → Action: DEVELOP (task 1/3)", "status": "in_progress"},
{"content": " → Action: VALIDATE", "status": "pending"},
{"content": " → Action: COMPLETE", "status": "pending"}
]
```
### Iteration Tracking (Collapsed)
```json
[
{"content": "Phase 1: Session Initialization", "status": "completed"},
{"content": "Iteration 1: DEVELOP x3 + VALIDATE (pass)", "status": "completed"},
{"content": "Phase 2: COMPLETE", "status": "in_progress"}
]
```
## Core Rules
1. **Start Immediately**: First action is TodoWrite initialization, then Phase 1 execution
2. **Progressive Phase Loading**: Read phase docs ONLY when that phase is about to execute
3. **Parse Every Output**: Extract ACTION_RESULT from agent output for next decision
4. **Auto-Continue**: After each action, execute next pending action automatically (auto mode)
5. **Track Progress**: Update TodoWrite dynamically with attachment/collapse pattern
6. **Single Writer**: Orchestrator updates master state file; agent writes to progress files
7. **File References**: Pass file paths between orchestrator and agent, not content
8. **DO NOT STOP**: Continuous execution until COMPLETED, PAUSED, STOPPED, or max iterations
## Error Handling
| Error Type | Recovery |
|------------|----------|
| Agent timeout | send_input requesting convergence, then retry |
| State corrupted | Rebuild from progress markdown files and logs |
| Agent closed unexpectedly | Re-spawn with previous output in message |
| Action failed | Log error, continue or prompt user |
| Tests fail | Loop back to DEVELOP or DEBUG |
| Max iterations reached | Generate summary with remaining issues documented |
| Session not found | Create new session |
## Coordinator Checklist
### Before Each Phase
- [ ] Read phase reference document
- [ ] Check current state for dependencies
- [ ] Update TodoWrite with phase tasks
### After Each Phase
- [ ] Parse agent outputs (ACTION_RESULT)
- [ ] Update master state file (iteration count, updated_at)
- [ ] Collapse TodoWrite sub-tasks
- [ ] Determine next action (continue / iterate / complete)
## Reference Documents
| Document | Purpose |
|----------|---------|
| [actions/](actions/) | Action definitions (INIT, DEVELOP, DEBUG, VALIDATE, COMPLETE, MENU) |
## Usage
```bash
# Start new loop (direct call)
/ccw-loop TASK="Implement user authentication"
# Auto-cycle mode
/ccw-loop --auto TASK="Fix login bug and add tests"
# Continue existing loop
/ccw-loop --loop-id=loop-v2-20260122-abc123
# API triggered auto-cycle
/ccw-loop --loop-id=loop-v2-20260122-abc123 --auto
```

View File

@@ -1,269 +0,0 @@
# Action: COMPLETE
Complete CCW Loop session and generate summary report.
## Purpose
- Generate completion report
- Aggregate all phase results
- Provide follow-up recommendations
- Offer expansion to issues
- Mark status as completed
## Preconditions
- [ ] state.status === 'running'
- [ ] state.skill_state !== null
## Execution Steps
### Step 1: Verify Control Signals
```javascript
const state = JSON.parse(Read(`${projectRoot}/.workflow/.loop/${loopId}.json`))
if (state.status !== 'running') {
return {
action: 'COMPLETE',
status: 'failed',
message: `Cannot complete: status is ${state.status}`,
next_action: state.status === 'paused' ? 'PAUSED' : 'STOPPED'
}
}
```
### Step 2: Aggregate Statistics
```javascript
const stats = {
// Time statistics
duration: Date.now() - new Date(state.created_at).getTime(),
iterations: state.current_iteration,
// Development statistics
develop: {
total_tasks: state.skill_state.develop.total,
completed_tasks: state.skill_state.develop.completed,
completion_rate: state.skill_state.develop.total > 0
? ((state.skill_state.develop.completed / state.skill_state.develop.total) * 100).toFixed(1)
: 0
},
// Debug statistics
debug: {
iterations: state.skill_state.debug.iteration,
hypotheses_tested: state.skill_state.debug.hypotheses.length,
root_cause_found: state.skill_state.debug.confirmed_hypothesis !== null
},
// Validation statistics
validate: {
runs: state.skill_state.validate.test_results.length,
passed: state.skill_state.validate.passed,
coverage: state.skill_state.validate.coverage,
failed_tests: state.skill_state.validate.failed_tests.length
}
}
```
### Step 3: Generate Summary Report
```javascript
const timestamp = getUtc8ISOString()
const summaryReport = `# CCW Loop Session Summary
**Loop ID**: ${loopId}
**Task**: ${state.description}
**Started**: ${state.created_at}
**Completed**: ${timestamp}
**Duration**: ${formatDuration(stats.duration)}
---
## Executive Summary
${state.skill_state.validate.passed
? 'All tests passed, validation successful'
: state.skill_state.develop.completed === state.skill_state.develop.total
? 'Development complete, validation not passed - needs debugging'
: 'Task partially complete - pending items remain'}
---
## Development Phase
| Metric | Value |
|--------|-------|
| Total Tasks | ${stats.develop.total_tasks} |
| Completed | ${stats.develop.completed_tasks} |
| Completion Rate | ${stats.develop.completion_rate}% |
### Completed Tasks
${state.skill_state.develop.tasks.filter(t => t.status === 'completed').map(t => `
- ${t.description}
- Files: ${t.files_changed?.join(', ') || 'N/A'}
- Completed: ${t.completed_at}
`).join('\n')}
### Pending Tasks
${state.skill_state.develop.tasks.filter(t => t.status !== 'completed').map(t => `
- ${t.description}
`).join('\n') || '_None_'}
---
## Debug Phase
| Metric | Value |
|--------|-------|
| Iterations | ${stats.debug.iterations} |
| Hypotheses Tested | ${stats.debug.hypotheses_tested} |
| Root Cause Found | ${stats.debug.root_cause_found ? 'Yes' : 'No'} |
${stats.debug.root_cause_found ? `
### Confirmed Root Cause
${state.skill_state.debug.confirmed_hypothesis}: ${state.skill_state.debug.hypotheses.find(h => h.id === state.skill_state.debug.confirmed_hypothesis)?.description}
` : ''}
---
## Validation Phase
| Metric | Value |
|--------|-------|
| Test Runs | ${stats.validate.runs} |
| Status | ${stats.validate.passed ? 'PASSED' : 'FAILED'} |
| Coverage | ${stats.validate.coverage || 'N/A'}% |
| Failed Tests | ${stats.validate.failed_tests} |
---
## Recommendations
${generateRecommendations(stats, state)}
---
## Session Artifacts
| File | Description |
|------|-------------|
| \`develop.md\` | Development progress timeline |
| \`debug.md\` | Debug exploration and learnings |
| \`validate.md\` | Validation report |
| \`test-results.json\` | Test execution results |
---
*Generated by CCW Loop at ${timestamp}*
`
Write(`${progressDir}/summary.md`, summaryReport)
```
### Step 4: Update State to Completed
```javascript
state.status = 'completed'
state.completed_at = timestamp
state.updated_at = timestamp
state.skill_state.last_action = 'COMPLETE'
state.skill_state.summary = stats
Write(`${projectRoot}/.workflow/.loop/${loopId}.json`, JSON.stringify(state, null, 2))
```
## Output Format
```
ACTION_RESULT:
- action: COMPLETE
- status: success
- message: Loop completed. Duration: {duration}, Iterations: {N}
- state_updates: {
"status": "completed",
"completed_at": "{timestamp}"
}
FILES_UPDATED:
- {projectRoot}/.workflow/.loop/{loopId}.json: Status set to completed
- {projectRoot}/.workflow/.loop/{loopId}.progress/summary.md: Summary report generated
NEXT_ACTION_NEEDED: COMPLETED
```
## Expansion Options
After completion, offer expansion to issues:
```
## Expansion Options
Would you like to create follow-up issues?
1. [test] Add more test cases
2. [enhance] Feature enhancements
3. [refactor] Code refactoring
4. [doc] Documentation updates
5. [none] No expansion needed
Select options (comma-separated) or 'none':
```
## Helper Functions
```javascript
function formatDuration(ms) {
const seconds = Math.floor(ms / 1000)
const minutes = Math.floor(seconds / 60)
const hours = Math.floor(minutes / 60)
if (hours > 0) {
return `${hours}h ${minutes % 60}m`
} else if (minutes > 0) {
return `${minutes}m ${seconds % 60}s`
} else {
return `${seconds}s`
}
}
function generateRecommendations(stats, state) {
const recommendations = []
if (stats.develop.completion_rate < 100) {
recommendations.push('- Complete remaining development tasks')
}
if (!stats.validate.passed) {
recommendations.push('- Fix failing tests')
}
if (stats.validate.coverage && stats.validate.coverage < 80) {
recommendations.push(`- Improve test coverage (current: ${stats.validate.coverage}%)`)
}
if (recommendations.length === 0) {
recommendations.push('- Consider code review')
recommendations.push('- Update documentation')
recommendations.push('- Prepare for deployment')
}
return recommendations.join('\n')
}
```
## Error Handling
| Error Type | Recovery |
|------------|----------|
| Report generation failed | Show basic stats, skip file write |
| Issue creation failed | Log error, continue completion |
## Next Actions
- None (terminal state)
- To continue: Use `/ccw-loop --loop-id={loopId}` to reopen (will set status back to running)

View File

@@ -1,286 +0,0 @@
# Action: DEBUG
Hypothesis-driven debugging with understanding evolution documentation.
## Purpose
- Locate error source
- Generate testable hypotheses
- Add NDJSON instrumentation
- Analyze log evidence
- Correct understanding based on evidence
- Apply fixes
## Preconditions
- [ ] state.status === 'running'
- [ ] state.skill_state !== null
## Mode Detection
```javascript
const understandingPath = `${progressDir}/debug.md`
const debugLogPath = `${progressDir}/debug.log`
const understandingExists = fs.existsSync(understandingPath)
const logHasContent = fs.existsSync(debugLogPath) && fs.statSync(debugLogPath).size > 0
const debugMode = logHasContent ? 'analyze' : (understandingExists ? 'continue' : 'explore')
```
## Execution Steps
### Mode: Explore (First Debug)
#### Step E1: Get Bug Description
```javascript
// From test failures or user input
const bugDescription = state.skill_state.validate?.failed_tests?.[0]
|| await getUserInput('Describe the bug:')
```
#### Step E2: Search Codebase
```javascript
// Use ACE search_context to find related code
const searchResults = mcp__ace-tool__search_context({
project_root_path: '.',
query: `code related to: ${bugDescription}`
})
```
#### Step E3: Generate Hypotheses
```javascript
const hypotheses = [
{
id: 'H1',
description: 'Most likely cause',
testable_condition: 'What to check',
logging_point: 'file.ts:functionName:42',
evidence_criteria: {
confirm: 'If we see X, hypothesis confirmed',
reject: 'If we see Y, hypothesis rejected'
},
likelihood: 1,
status: 'pending',
evidence: null,
verdict_reason: null
},
// H2, H3...
]
```
#### Step E4: Create Understanding Document
```javascript
const initialUnderstanding = `# Understanding Document
**Loop ID**: ${loopId}
**Bug Description**: ${bugDescription}
**Started**: ${getUtc8ISOString()}
---
## Exploration Timeline
### Iteration 1 - Initial Exploration (${getUtc8ISOString()})
#### Current Understanding
Based on bug description and code search:
- Error pattern: [identified pattern]
- Affected areas: [files/modules]
- Initial hypothesis: [first thoughts]
#### Evidence from Code Search
[Search results summary]
#### Hypotheses
${hypotheses.map(h => `
**${h.id}**: ${h.description}
- Testable condition: ${h.testable_condition}
- Logging point: ${h.logging_point}
- Likelihood: ${h.likelihood}
`).join('\n')}
---
## Current Consolidated Understanding
[Summary of what we know so far]
`
Write(understandingPath, initialUnderstanding)
Write(`${progressDir}/hypotheses.json`, JSON.stringify({ hypotheses, iteration: 1 }, null, 2))
```
#### Step E5: Add NDJSON Logging Points
```javascript
// For each hypothesis, add instrumentation
for (const hypothesis of hypotheses) {
const [file, func, line] = hypothesis.logging_point.split(':')
const logStatement = `console.log(JSON.stringify({
hid: "${hypothesis.id}",
ts: Date.now(),
func: "${func}",
data: { /* relevant context */ }
}))`
// Add to file using Edit tool
}
```
### Mode: Analyze (Has Logs)
#### Step A1: Parse Debug Log
```javascript
const logContent = Read(debugLogPath)
const entries = logContent.split('\n')
.filter(l => l.trim())
.map(l => JSON.parse(l))
// Group by hypothesis ID
const byHypothesis = entries.reduce((acc, e) => {
acc[e.hid] = acc[e.hid] || []
acc[e.hid].push(e)
return acc
}, {})
```
#### Step A2: Evaluate Evidence
```javascript
const hypothesesData = JSON.parse(Read(`${progressDir}/hypotheses.json`))
for (const hypothesis of hypothesesData.hypotheses) {
const evidence = byHypothesis[hypothesis.id] || []
// Evaluate against criteria
if (matchesConfirmCriteria(evidence, hypothesis.evidence_criteria.confirm)) {
hypothesis.status = 'confirmed'
hypothesis.evidence = evidence
hypothesis.verdict_reason = 'Evidence matches confirm criteria'
} else if (matchesRejectCriteria(evidence, hypothesis.evidence_criteria.reject)) {
hypothesis.status = 'rejected'
hypothesis.evidence = evidence
hypothesis.verdict_reason = 'Evidence matches reject criteria'
} else {
hypothesis.status = 'inconclusive'
hypothesis.evidence = evidence
hypothesis.verdict_reason = 'Insufficient evidence'
}
}
```
#### Step A3: Update Understanding
```javascript
const iteration = hypothesesData.iteration + 1
const timestamp = getUtc8ISOString()
const analysisEntry = `
### Iteration ${iteration} - Evidence Analysis (${timestamp})
#### Log Analysis Results
${hypothesesData.hypotheses.map(h => `
**${h.id}**: ${h.status.toUpperCase()}
- Evidence: ${JSON.stringify(h.evidence?.slice(0, 3))}
- Reasoning: ${h.verdict_reason}
`).join('\n')}
#### Corrected Understanding
[Any corrections to previous assumptions]
${confirmedHypothesis ? `
#### Root Cause Identified
**${confirmedHypothesis.id}**: ${confirmedHypothesis.description}
` : `
#### Next Steps
[What to investigate next]
`}
---
`
const existingUnderstanding = Read(understandingPath)
Write(understandingPath, existingUnderstanding + analysisEntry)
```
### Step: Update State
```javascript
state.skill_state.debug.active_bug = bugDescription
state.skill_state.debug.hypotheses = hypothesesData.hypotheses
state.skill_state.debug.hypotheses_count = hypothesesData.hypotheses.length
state.skill_state.debug.iteration = iteration
state.skill_state.debug.last_analysis_at = timestamp
if (confirmedHypothesis) {
state.skill_state.debug.confirmed_hypothesis = confirmedHypothesis.id
}
state.skill_state.last_action = 'DEBUG'
state.updated_at = timestamp
Write(`${projectRoot}/.workflow/.loop/${loopId}.json`, JSON.stringify(state, null, 2))
```
## Output Format
```
ACTION_RESULT:
- action: DEBUG
- status: success
- message: {Mode description} - {result summary}
- state_updates: {
"debug.iteration": {N},
"debug.confirmed_hypothesis": "{id or null}"
}
FILES_UPDATED:
- {projectRoot}/.workflow/.loop/{loopId}.progress/debug.md: Understanding updated
- {projectRoot}/.workflow/.loop/{loopId}.progress/hypotheses.json: Hypotheses updated
- [Source files]: Instrumentation added
NEXT_ACTION_NEEDED: {DEBUG | VALIDATE | DEVELOP | MENU}
```
## Next Action Selection
```javascript
if (confirmedHypothesis) {
// Root cause found, apply fix and validate
return 'VALIDATE'
} else if (allRejected) {
// Generate new hypotheses
return 'DEBUG'
} else {
// Need more evidence - prompt user to reproduce bug
return 'WAITING_INPUT' // User needs to trigger bug
}
```
## Error Handling
| Error Type | Recovery |
|------------|----------|
| Empty debug.log | Prompt user to reproduce bug |
| All hypotheses rejected | Generate new hypotheses |
| >5 iterations | Suggest escalation |
## Next Actions
- Root cause found: `VALIDATE`
- Need more evidence: `DEBUG` (after reproduction)
- All rejected: `DEBUG` (new hypotheses)

View File

@@ -1,183 +0,0 @@
# Action: DEVELOP
Execute development task and record progress to develop.md.
## Purpose
- Execute next pending development task
- Implement code changes
- Record progress to Markdown file
- Update task status in state
## Preconditions
- [ ] state.status === 'running'
- [ ] state.skill_state !== null
- [ ] state.skill_state.develop.tasks.some(t => t.status === 'pending')
## Execution Steps
### Step 1: Verify Control Signals
```javascript
const state = JSON.parse(Read(`${projectRoot}/.workflow/.loop/${loopId}.json`))
if (state.status !== 'running') {
return {
action: 'DEVELOP',
status: 'failed',
message: `Cannot develop: status is ${state.status}`,
next_action: state.status === 'paused' ? 'PAUSED' : 'STOPPED'
}
}
```
### Step 2: Find Next Pending Task
```javascript
const tasks = state.skill_state.develop.tasks
const currentTask = tasks.find(t => t.status === 'pending')
if (!currentTask) {
return {
action: 'DEVELOP',
status: 'success',
message: 'All development tasks completed',
next_action: mode === 'auto' ? 'VALIDATE' : 'MENU'
}
}
// Mark as in_progress
currentTask.status = 'in_progress'
```
### Step 3: Execute Development Task
```javascript
console.log(`Executing task: ${currentTask.description}`)
// Use appropriate tools based on task type
// - ACE search_context for finding patterns
// - Read for loading files
// - Edit/Write for making changes
// Record files changed
const filesChanged = []
// Implementation logic...
```
### Step 4: Record Changes to Log (NDJSON)
```javascript
const changesLogPath = `${progressDir}/changes.log`
const timestamp = getUtc8ISOString()
const changeEntry = {
timestamp: timestamp,
task_id: currentTask.id,
description: currentTask.description,
files_changed: filesChanged,
result: 'success'
}
// Append to NDJSON log
const existingLog = Read(changesLogPath) || ''
Write(changesLogPath, existingLog + JSON.stringify(changeEntry) + '\n')
```
### Step 5: Update Progress Document
```javascript
const progressPath = `${progressDir}/develop.md`
const iteration = state.skill_state.develop.completed + 1
const progressEntry = `
### Iteration ${iteration} - ${currentTask.description} (${timestamp})
#### Task Details
- **ID**: ${currentTask.id}
- **Tool**: ${currentTask.tool}
- **Mode**: ${currentTask.mode}
#### Implementation Summary
[Implementation description]
#### Files Changed
${filesChanged.map(f => `- \`${f}\``).join('\n') || '- No files changed'}
#### Status: COMPLETED
---
`
const existingProgress = Read(progressPath)
Write(progressPath, existingProgress + progressEntry)
```
### Step 6: Update State
```javascript
currentTask.status = 'completed'
currentTask.completed_at = timestamp
currentTask.files_changed = filesChanged
state.skill_state.develop.completed += 1
state.skill_state.develop.current_task = null
state.skill_state.develop.last_progress_at = timestamp
state.skill_state.last_action = 'DEVELOP'
state.skill_state.completed_actions.push('DEVELOP')
state.updated_at = timestamp
Write(`${projectRoot}/.workflow/.loop/${loopId}.json`, JSON.stringify(state, null, 2))
```
## Output Format
```
ACTION_RESULT:
- action: DEVELOP
- status: success
- message: Task completed: {task_description}
- state_updates: {
"develop.completed": {N},
"develop.last_progress_at": "{timestamp}"
}
FILES_UPDATED:
- {projectRoot}/.workflow/.loop/{loopId}.json: Task status updated
- {projectRoot}/.workflow/.loop/{loopId}.progress/develop.md: Progress entry added
- {projectRoot}/.workflow/.loop/{loopId}.progress/changes.log: Change entry added
NEXT_ACTION_NEEDED: {DEVELOP | DEBUG | VALIDATE | MENU}
```
## Auto Mode Next Action Selection
```javascript
const pendingTasks = tasks.filter(t => t.status === 'pending')
if (pendingTasks.length > 0) {
return 'DEVELOP' // More tasks to do
} else {
return 'DEBUG' // All done, check for issues
}
```
## Error Handling
| Error Type | Recovery |
|------------|----------|
| Task execution failed | Mark task as failed, continue to next |
| File write failed | Retry once, then report error |
| All tasks done | Move to DEBUG or VALIDATE |
## Next Actions
- More pending tasks: `DEVELOP`
- All tasks complete: `DEBUG` (auto) or `MENU` (interactive)
- Task failed: `DEVELOP` (retry) or `DEBUG` (investigate)

View File

@@ -1,174 +0,0 @@
# Action: INIT
Initialize CCW Loop session, create directory structure and initial state.
## Purpose
- Create session directory structure
- Initialize state file with skill_state
- Analyze task description to generate development tasks
- Prepare execution environment
## Preconditions
- [ ] state.status === 'running'
- [ ] state.skill_state === null
## Execution Steps
### Step 1: Verify Control Signals
```javascript
const state = JSON.parse(Read(`${projectRoot}/.workflow/.loop/${loopId}.json`))
if (state.status !== 'running') {
return {
action: 'INIT',
status: 'failed',
message: `Cannot init: status is ${state.status}`,
next_action: state.status === 'paused' ? 'PAUSED' : 'STOPPED'
}
}
```
### Step 2: Create Directory Structure
```javascript
const progressDir = `${projectRoot}/.workflow/.loop/${loopId}.progress`
// Directories created by orchestrator, verify they exist
// mkdir -p ${progressDir}
```
### Step 3: Analyze Task and Generate Tasks
```javascript
// Check if prep tasks already loaded by orchestrator (from prep-package)
// If skill_state already has tasks (pre-populated by Phase 1), skip generation
const existingTasks = state.skill_state?.develop?.tasks
if (existingTasks && existingTasks.length > 0) {
console.log(`✓ Using ${existingTasks.length} pre-built tasks from prep-package`)
console.log(` Source: ${state.prep_source?.tool || 'unknown'}`)
// Skip to Step 4 — tasks already available
tasks = existingTasks
} else {
// No prep tasks — analyze task description and generate 3-7 development tasks
const taskDescription = state.description
// Generate 3-7 development tasks based on analysis
// Use ACE search or smart_search to find relevant patterns
tasks = [
{
id: 'task-001',
description: 'Task description based on analysis',
tool: 'gemini',
mode: 'write',
status: 'pending',
priority: 1,
files: [],
created_at: getUtc8ISOString(),
completed_at: null
}
// ... more tasks
]
}
```
### Step 4: Initialize Progress Document
```javascript
const progressPath = `${progressDir}/develop.md`
const progressInitial = `# Development Progress
**Loop ID**: ${loopId}
**Task**: ${taskDescription}
**Started**: ${getUtc8ISOString()}
---
## Task List
${tasks.map((t, i) => `${i + 1}. [ ] ${t.description}`).join('\n')}
---
## Progress Timeline
`
Write(progressPath, progressInitial)
```
### Step 5: Update State
```javascript
const skillState = {
current_action: 'init',
last_action: null,
completed_actions: [],
mode: mode,
develop: {
total: tasks.length,
completed: 0,
current_task: null,
tasks: tasks,
last_progress_at: null
},
debug: {
active_bug: null,
hypotheses_count: 0,
hypotheses: [],
confirmed_hypothesis: null,
iteration: 0,
last_analysis_at: null
},
validate: {
pass_rate: 0,
coverage: 0,
test_results: [],
passed: false,
failed_tests: [],
last_run_at: null
},
errors: []
}
state.skill_state = skillState
state.updated_at = getUtc8ISOString()
Write(`${projectRoot}/.workflow/.loop/${loopId}.json`, JSON.stringify(state, null, 2))
```
## Output Format
```
ACTION_RESULT:
- action: INIT
- status: success
- message: Session initialized with {N} development tasks
FILES_UPDATED:
- {projectRoot}/.workflow/.loop/{loopId}.json: skill_state initialized
- {projectRoot}/.workflow/.loop/{loopId}.progress/develop.md: Progress document created
NEXT_ACTION_NEEDED: {DEVELOP (auto) | MENU (interactive)}
```
## Error Handling
| Error Type | Recovery |
|------------|----------|
| Directory creation failed | Report error, stop |
| Task analysis failed | Create single generic task |
| State write failed | Retry once, then stop |
## Next Actions
- Success (auto mode): `DEVELOP`
- Success (interactive): `MENU`
- Failed: Report error

View File

@@ -1,205 +0,0 @@
# Action: MENU
Display interactive action menu for user selection.
## Purpose
- Show current state summary
- Display available actions
- Wait for user selection
- Return selected action
## Preconditions
- [ ] state.status === 'running'
- [ ] state.skill_state !== null
- [ ] mode === 'interactive'
## Execution Steps
### Step 1: Verify Control Signals
```javascript
const state = JSON.parse(Read(`${projectRoot}/.workflow/.loop/${loopId}.json`))
if (state.status !== 'running') {
return {
action: 'MENU',
status: 'failed',
message: `Cannot show menu: status is ${state.status}`,
next_action: state.status === 'paused' ? 'PAUSED' : 'STOPPED'
}
}
```
### Step 2: Generate Status Summary
```javascript
// Development progress
const developProgress = state.skill_state.develop.total > 0
? `${state.skill_state.develop.completed}/${state.skill_state.develop.total} (${((state.skill_state.develop.completed / state.skill_state.develop.total) * 100).toFixed(0)}%)`
: 'Not started'
// Debug status
const debugStatus = state.skill_state.debug.confirmed_hypothesis
? 'Root cause found'
: state.skill_state.debug.iteration > 0
? `Iteration ${state.skill_state.debug.iteration}`
: 'Not started'
// Validation status
const validateStatus = state.skill_state.validate.passed
? 'PASSED'
: state.skill_state.validate.test_results.length > 0
? `FAILED (${state.skill_state.validate.failed_tests.length} failures)`
: 'Not run'
```
### Step 3: Display Menu
```javascript
const menuDisplay = `
================================================================
CCW Loop - ${loopId}
================================================================
Task: ${state.description}
Iteration: ${state.current_iteration}
+-----------------------------------------------------+
| Phase | Status |
+-----------------------------------------------------+
| Develop | ${developProgress.padEnd(35)}|
| Debug | ${debugStatus.padEnd(35)}|
| Validate | ${validateStatus.padEnd(35)}|
+-----------------------------------------------------+
================================================================
MENU_OPTIONS:
1. [develop] Continue Development - ${state.skill_state.develop.total - state.skill_state.develop.completed} tasks pending
2. [debug] Start Debugging - ${debugStatus}
3. [validate] Run Validation - ${validateStatus}
4. [status] View Detailed Status
5. [complete] Complete Loop
6. [exit] Exit (save and quit)
`
console.log(menuDisplay)
```
## Output Format
```
ACTION_RESULT:
- action: MENU
- status: success
- message: ${menuDisplay}
MENU_OPTIONS:
1. [develop] Continue Development - {N} tasks pending
2. [debug] Start Debugging - {status}
3. [validate] Run Validation - {status}
4. [status] View Detailed Status
5. [complete] Complete Loop
6. [exit] Exit (save and quit)
NEXT_ACTION_NEEDED: WAITING_INPUT
```
## User Input Handling
When user provides input, orchestrator sends it back via `send_input`:
```javascript
// User selects "develop"
send_input({
id: agent,
message: `
## USER INPUT RECEIVED
Action selected: develop
## EXECUTE SELECTED ACTION
Execute DEVELOP action.
`
})
```
## Status Detail View
If user selects "status":
```javascript
const detailView = `
## Detailed Status
### Development Progress
${Read(`${progressDir}/develop.md`)?.substring(0, 1000) || 'No progress recorded'}
### Debug Status
${state.skill_state.debug.hypotheses.length > 0
? state.skill_state.debug.hypotheses.map(h => ` ${h.id}: ${h.status} - ${h.description.substring(0, 50)}...`).join('\n')
: ' No debugging started'}
### Validation Results
${state.skill_state.validate.test_results.length > 0
? ` Last run: ${state.skill_state.validate.last_run_at}
Pass rate: ${state.skill_state.validate.pass_rate}%`
: ' No validation run yet'}
`
console.log(detailView)
// Return to menu
return {
action: 'MENU',
status: 'success',
message: detailView,
next_action: 'MENU' // Show menu again
}
```
## Exit Handling
If user selects "exit":
```javascript
// Save current state
state.status = 'user_exit'
state.updated_at = getUtc8ISOString()
Write(`${projectRoot}/.workflow/.loop/${loopId}.json`, JSON.stringify(state, null, 2))
return {
action: 'MENU',
status: 'success',
message: 'Session saved. Use --loop-id to resume.',
next_action: 'COMPLETED'
}
```
## Action Mapping
| User Selection | Next Action |
|----------------|-------------|
| develop | DEVELOP |
| debug | DEBUG |
| validate | VALIDATE |
| status | MENU (after showing details) |
| complete | COMPLETE |
| exit | COMPLETED (save and exit) |
## Error Handling
| Error Type | Recovery |
|------------|----------|
| Invalid selection | Show menu again |
| User cancels | Return to menu |
## Next Actions
Based on user selection - forwarded via `send_input` by orchestrator.

View File

@@ -1,250 +0,0 @@
# Action: VALIDATE
Run tests and verify implementation, record results to validate.md.
## Purpose
- Run unit tests
- Run integration tests
- Check code coverage
- Generate validation report
- Determine pass/fail status
## Preconditions
- [ ] state.status === 'running'
- [ ] state.skill_state !== null
- [ ] (develop.completed > 0) OR (debug.confirmed_hypothesis !== null)
## Execution Steps
### Step 1: Verify Control Signals
```javascript
const state = JSON.parse(Read(`${projectRoot}/.workflow/.loop/${loopId}.json`))
if (state.status !== 'running') {
return {
action: 'VALIDATE',
status: 'failed',
message: `Cannot validate: status is ${state.status}`,
next_action: state.status === 'paused' ? 'PAUSED' : 'STOPPED'
}
}
```
### Step 2: Detect Test Framework
```javascript
const packageJson = JSON.parse(Read('package.json') || '{}')
const testScript = packageJson.scripts?.test || 'npm test'
const coverageScript = packageJson.scripts?.['test:coverage']
```
### Step 3: Run Tests
```javascript
const testResult = await Bash({
command: testScript,
timeout: 300000 // 5 minutes
})
// Parse test output based on framework
const testResults = parseTestOutput(testResult.stdout, testResult.stderr)
```
### Step 4: Run Coverage (if available)
```javascript
let coverageData = null
if (coverageScript) {
const coverageResult = await Bash({
command: coverageScript,
timeout: 300000
})
coverageData = parseCoverageReport(coverageResult.stdout)
Write(`${progressDir}/coverage.json`, JSON.stringify(coverageData, null, 2))
}
```
### Step 5: Generate Validation Report
```javascript
const timestamp = getUtc8ISOString()
const iteration = (state.skill_state.validate.test_results?.length || 0) + 1
const validationReport = `# Validation Report
**Loop ID**: ${loopId}
**Task**: ${state.description}
**Validated**: ${timestamp}
---
## Iteration ${iteration} - Validation Run
### Test Execution Summary
| Metric | Value |
|--------|-------|
| Total Tests | ${testResults.total} |
| Passed | ${testResults.passed} |
| Failed | ${testResults.failed} |
| Skipped | ${testResults.skipped} |
| Duration | ${testResults.duration_ms}ms |
| **Pass Rate** | **${((testResults.passed / testResults.total) * 100).toFixed(1)}%** |
### Coverage Report
${coverageData ? `
| File | Statements | Branches | Functions | Lines |
|------|------------|----------|-----------|-------|
${coverageData.files.map(f => `| ${f.path} | ${f.statements}% | ${f.branches}% | ${f.functions}% | ${f.lines}% |`).join('\n')}
**Overall Coverage**: ${coverageData.overall.statements}%
` : '_No coverage data available_'}
### Failed Tests
${testResults.failed > 0 ? testResults.failures.map(f => `
#### ${f.test_name}
- **Suite**: ${f.suite}
- **Error**: ${f.error_message}
`).join('\n') : '_All tests passed_'}
---
## Validation Decision
**Result**: ${testResults.failed === 0 ? 'PASS' : 'FAIL'}
${testResults.failed > 0 ? `
### Next Actions
1. Review failed tests
2. Debug failures using DEBUG action
3. Fix issues and re-run validation
` : `
### Next Actions
1. Consider code review
2. Complete loop
`}
`
Write(`${progressDir}/validate.md`, validationReport)
```
### Step 6: Save Test Results
```javascript
const testResultsData = {
iteration,
timestamp,
summary: {
total: testResults.total,
passed: testResults.passed,
failed: testResults.failed,
skipped: testResults.skipped,
pass_rate: ((testResults.passed / testResults.total) * 100).toFixed(1),
duration_ms: testResults.duration_ms
},
tests: testResults.tests,
failures: testResults.failures,
coverage: coverageData?.overall || null
}
Write(`${progressDir}/test-results.json`, JSON.stringify(testResultsData, null, 2))
```
### Step 7: Update State
```javascript
const validationPassed = testResults.failed === 0 && testResults.passed > 0
state.skill_state.validate.test_results.push(testResultsData)
state.skill_state.validate.pass_rate = parseFloat(testResultsData.summary.pass_rate)
state.skill_state.validate.coverage = coverageData?.overall?.statements || 0
state.skill_state.validate.passed = validationPassed
state.skill_state.validate.failed_tests = testResults.failures.map(f => f.test_name)
state.skill_state.validate.last_run_at = timestamp
state.skill_state.last_action = 'VALIDATE'
state.updated_at = timestamp
Write(`${projectRoot}/.workflow/.loop/${loopId}.json`, JSON.stringify(state, null, 2))
```
## Output Format
```
ACTION_RESULT:
- action: VALIDATE
- status: success
- message: Validation {PASSED | FAILED} - {pass_count}/{total_count} tests passed
- state_updates: {
"validate.passed": {true | false},
"validate.pass_rate": {N},
"validate.failed_tests": [{list}]
}
FILES_UPDATED:
- {projectRoot}/.workflow/.loop/{loopId}.progress/validate.md: Validation report created
- {projectRoot}/.workflow/.loop/{loopId}.progress/test-results.json: Test results saved
- {projectRoot}/.workflow/.loop/{loopId}.progress/coverage.json: Coverage data saved (if available)
NEXT_ACTION_NEEDED: {COMPLETE | DEBUG | DEVELOP | MENU}
```
## Next Action Selection
```javascript
if (validationPassed) {
const pendingTasks = state.skill_state.develop.tasks.filter(t => t.status === 'pending')
if (pendingTasks.length === 0) {
return 'COMPLETE'
} else {
return 'DEVELOP'
}
} else {
// Tests failed - need debugging
return 'DEBUG'
}
```
## Test Output Parsers
### Jest/Vitest Parser
```javascript
function parseJestOutput(stdout) {
const summaryMatch = stdout.match(/Tests:\s+(\d+)\s+passed.*?(\d+)\s+failed.*?(\d+)\s+total/)
// ... implementation
}
```
### Pytest Parser
```javascript
function parsePytestOutput(stdout) {
const summaryMatch = stdout.match(/(\d+)\s+passed.*?(\d+)\s+failed/)
// ... implementation
}
```
## Error Handling
| Error Type | Recovery |
|------------|----------|
| Tests don't run | Check test script config, report error |
| All tests fail | Suggest DEBUG action |
| Coverage tool missing | Skip coverage, run tests only |
| Timeout | Increase timeout or split tests |
## Next Actions
- Validation passed, no pending: `COMPLETE`
- Validation passed, has pending: `DEVELOP`
- Validation failed: `DEBUG`

View File

@@ -1,116 +0,0 @@
# Phase 0: Prep Package Schema & Integration
Schema reference for `prep-package.json` consumed by ccw-loop Phase 1. Generated by interactive prompt `/prompts:prep-loop`.
## prep-package.json Schema
```json
{
"version": "1.0.0",
"generated_at": "ISO8601 (UTC+8)",
"prep_status": "ready | cancelled | needs_refinement",
"target_skill": "ccw-loop",
"environment": {
"project_root": "absolute path",
"tech_stack": "string",
"test_framework": "string"
},
"source": {
"tool": "collaborative-plan-with-file | analyze-with-file | brainstorm-to-cycle | manual",
"session_id": "string",
"task_dir": "absolute path to source .task/ directory",
"task_count": "number",
"tasks_with_convergence": "number"
},
"tasks": {
"total": "number",
"by_priority": { "high": 0, "medium": 0, "low": 0 },
"by_type": { "feature": 0, "fix": 0, "refactor": 0, "enhancement": 0, "testing": 0 }
},
"auto_loop": {
"enabled": true,
"no_confirmation": true,
"max_iterations": 10,
"timeout_per_action_ms": 600000
}
}
```
## .task/*.json Schema (task-schema.json)
One task per file in `.task/` directory, each following `task-schema.json` with ccw-loop extended fields:
```json
{
"id": "task-001",
"description": "Title: detailed description",
"tool": "gemini",
"mode": "write",
"status": "pending",
"priority": 1,
"files_changed": ["path/to/file.ts"],
"created_at": "ISO8601",
"completed_at": null,
"_source": { "tool": "collaborative-plan-with-file", "session_id": "...", "original_id": "TASK-001" },
"_convergence": { "criteria": ["..."], "verification": "...", "definition_of_done": "..." },
"_type": "feature",
"_effort": "medium",
"_depends_on": []
}
```
## Validation Rules
| # | Check | Condition | On Failure |
|---|-------|-----------|------------|
| 1 | prep_status | `=== "ready"` | Skip prep, use default INIT |
| 2 | target_skill | `=== "ccw-loop"` | Skip prep, use default INIT |
| 3 | project_root | Matches current `projectRoot` | Skip prep, warn mismatch |
| 4 | freshness | `generated_at` within 24h | Skip prep, warn stale |
| 5 | tasks dir | `.task/` directory exists with *.json files | Skip prep, use default INIT |
| 6 | tasks content | At least 1 valid task JSON in `.task/` | Skip prep, use default INIT |
## Integration Points
### Phase 1: Session Initialization
```javascript
// Load prep-package.json (generated by /prompts:prep-loop)
let prepPackage = null
const prepPath = `${projectRoot}/.workflow/.loop/prep-package.json`
if (fs.existsSync(prepPath)) {
const raw = JSON.parse(Read(prepPath))
const checks = validateLoopPrepPackage(raw, projectRoot)
if (checks.valid) {
prepPackage = raw
// Load pre-built tasks from .task/*.json
const taskDir = `${projectRoot}/.workflow/.loop/.task`
const prepTasks = loadPrepTasks(taskDir)
// → Inject into state.skill_state.develop.tasks
// → Set max_iterations from auto_loop config
} else {
console.warn(`⚠ Prep package failed validation, using default INIT`)
prepPackage = null
}
}
```
### INIT Action (action-init.md)
When prep tasks are loaded:
- **Skip** Step 3 (Analyze Task and Generate Tasks) — tasks already provided
- **Use** prep tasks directly in Step 5 (Update State)
- **Preserve** `_convergence` fields for VALIDATE action reference
### VALIDATE Action
When `_convergence` exists on a task:
- Use `convergence.verification` as validation command/steps
- Use `convergence.criteria` as pass/fail conditions
- Fall back to default test validation if `_convergence` is null

View File

@@ -1,300 +0,0 @@
# Phase 1: Session Initialization
Create or resume a development loop, initialize state file and directory structure.
## Objective
- Parse user arguments (TASK, --loop-id, --auto)
- Create new loop with unique ID OR resume existing loop
- Initialize directory structure for progress files
- Create master state file
- Output: loopId, state, progressDir
## Execution
### Step 0: Determine Project Root
```javascript
// Step 0: Determine Project Root
const projectRoot = Bash('git rev-parse --show-toplevel 2>/dev/null || pwd').trim()
```
### Step 1.1: Parse Arguments & Load Prep Package
```javascript
const { loopId: existingLoopId, task, mode = 'interactive' } = options
// Validate mutual exclusivity
if (!existingLoopId && !task) {
console.error('Either --loop-id or task description is required')
return { status: 'error', message: 'Missing loopId or task' }
}
// Determine mode
const executionMode = options['--auto'] ? 'auto' : 'interactive'
// ── Prep Package: Detect → Validate → Consume ──
let prepPackage = null
let prepTasks = null
const prepPath = `${projectRoot}/.workflow/.loop/prep-package.json`
if (fs.existsSync(prepPath)) {
const raw = JSON.parse(Read(prepPath))
const checks = validateLoopPrepPackage(raw, projectRoot)
if (checks.valid) {
prepPackage = raw
// Load pre-built tasks
const taskDir = `${projectRoot}/.workflow/.loop/.task`
prepTasks = loadPrepTasks(taskDir)
if (prepTasks && prepTasks.length > 0) {
console.log(`✓ Prep package loaded: ${prepTasks.length} tasks from ${prepPackage.source.tool}`)
console.log(` Checks passed: ${checks.passed.join(', ')}`)
} else {
console.warn(`Warning: Prep tasks directory empty or invalid, falling back to default INIT`)
prepPackage = null
prepTasks = null
}
} else {
console.warn(`⚠ Prep package found but failed validation:`)
checks.failures.forEach(f => console.warn(`${f}`))
console.warn(` → Falling back to default behavior (prep-package ignored)`)
prepPackage = null
}
}
/**
* Validate prep-package.json integrity before consumption.
* Returns { valid: bool, passed: string[], failures: string[] }
*/
function validateLoopPrepPackage(prep, projectRoot) {
const passed = []
const failures = []
// Check 1: prep_status must be "ready"
if (prep.prep_status === 'ready') {
passed.push('status=ready')
} else {
failures.push(`prep_status is "${prep.prep_status}", expected "ready"`)
}
// Check 2: target_skill must match
if (prep.target_skill === 'ccw-loop') {
passed.push('target_skill match')
} else {
failures.push(`target_skill is "${prep.target_skill}", expected "ccw-loop"`)
}
// Check 3: project_root must match current project
if (prep.environment?.project_root === projectRoot) {
passed.push('project_root match')
} else {
failures.push(`project_root mismatch: prep="${prep.environment?.project_root}", current="${projectRoot}"`)
}
// Check 4: generated_at must be within 24 hours
const generatedAt = new Date(prep.generated_at)
const hoursSince = (Date.now() - generatedAt.getTime()) / (1000 * 60 * 60)
if (hoursSince <= 24) {
passed.push(`age=${Math.round(hoursSince)}h`)
} else {
failures.push(`prep-package is ${Math.round(hoursSince)}h old (max 24h), may be stale`)
}
// Check 5: .task/ directory must exist with task files
const taskDir = `${projectRoot}/.workflow/.loop/.task`
const taskFiles = Glob(`${taskDir}/*.json`)
if (fs.existsSync(taskDir) && taskFiles.length > 0) {
passed.push(`.task/ exists (${taskFiles.length} files)`)
} else {
failures.push('.task/ directory not found or empty')
}
// Check 6: task count > 0
if ((prep.tasks?.total || 0) > 0) {
passed.push(`tasks=${prep.tasks.total}`)
} else {
failures.push('task count is 0')
}
return {
valid: failures.length === 0,
passed,
failures
}
}
/**
* Load pre-built tasks from .task/*.json directory.
* Returns array of task objects or null on failure.
*/
function loadPrepTasks(taskDir) {
if (!fs.existsSync(taskDir)) return null
const taskFiles = Glob(`${taskDir}/*.json`).sort()
const tasks = []
for (const filePath of taskFiles) {
try {
const content = Read(filePath)
const task = JSON.parse(content)
if (task.id && task.description) {
tasks.push(task)
}
} catch (e) {
console.warn(`Warning: Skipping invalid task file ${filePath}: ${e.message}`)
}
}
return tasks.length > 0 ? tasks : null
}
```
### Step 1.2: Utility Functions
```javascript
const getUtc8ISOString = () => new Date(Date.now() + 8 * 60 * 60 * 1000).toISOString()
function readLoopState(loopId) {
const stateFile = `${projectRoot}/.workflow/.loop/${loopId}.json`
if (!fs.existsSync(stateFile)) {
return null
}
return JSON.parse(Read(stateFile))
}
```
### Step 1.3: New Loop Creation
When `TASK` is provided (no `--loop-id`):
```javascript
// Generate unique loop ID
const timestamp = getUtc8ISOString().replace(/[-:]/g, '').split('.')[0]
const random = Math.random().toString(36).substring(2, 10)
const loopId = `loop-v2-${timestamp}-${random}`
console.log(`Creating new loop: ${loopId}`)
```
#### Create Directory Structure
```bash
mkdir -p ${projectRoot}/.workflow/.loop/${loopId}.progress
```
#### Initialize State File
```javascript
function createLoopState(loopId, taskDescription) {
const stateFile = `${projectRoot}/.workflow/.loop/${loopId}.json`
const now = getUtc8ISOString()
const state = {
// API compatible fields
loop_id: loopId,
title: taskDescription.substring(0, 100),
description: taskDescription,
max_iterations: prepPackage?.auto_loop?.max_iterations || 10,
status: 'running',
current_iteration: 0,
created_at: now,
updated_at: now,
// Skill extension fields
// When prep tasks available, pre-populate skill_state instead of null
skill_state: prepTasks ? {
current_action: 'init',
last_action: null,
completed_actions: [],
mode: executionMode,
develop: {
total: prepTasks.length,
completed: 0,
current_task: null,
tasks: prepTasks,
last_progress_at: null
},
debug: {
active_bug: null,
hypotheses_count: 0,
hypotheses: [],
confirmed_hypothesis: null,
iteration: 0,
last_analysis_at: null
},
validate: {
pass_rate: 0,
coverage: 0,
test_results: [],
passed: false,
failed_tests: [],
last_run_at: null
},
errors: []
} : null,
// Prep package metadata (for traceability)
prep_source: prepPackage?.source || null
}
Write(stateFile, JSON.stringify(state, null, 2))
return state
}
```
### Step 1.4: Resume Existing Loop
When `--loop-id` is provided:
```javascript
const loopId = existingLoopId
const state = readLoopState(loopId)
if (!state) {
console.error(`Loop not found: ${loopId}`)
return { status: 'error', message: 'Loop not found' }
}
console.log(`Resuming loop: ${loopId}`)
console.log(`Status: ${state.status}`)
```
### Step 1.5: Control Signal Check
Before proceeding, verify loop status allows continuation:
```javascript
function checkControlSignals(loopId) {
const state = readLoopState(loopId)
switch (state?.status) {
case 'paused':
return { continue: false, action: 'pause_exit' }
case 'failed':
return { continue: false, action: 'stop_exit' }
case 'running':
return { continue: true, action: 'continue' }
default:
return { continue: false, action: 'stop_exit' }
}
}
```
## Output
- **Variable**: `loopId` - Unique loop identifier
- **Variable**: `state` - Initialized or resumed loop state object
- **Variable**: `progressDir` - `${projectRoot}/.workflow/.loop/${loopId}.progress`
- **Variable**: `mode` - `'interactive'` or `'auto'`
- **TodoWrite**: Mark Phase 1 completed, Phase 2 in_progress
## Next Phase
Return to orchestrator, then auto-continue to [Phase 2: Orchestration Loop](02-orchestration-loop.md).

View File

@@ -1,309 +0,0 @@
# Phase 2: Orchestration Loop
Spawn single executor agent and run main orchestration loop until completion, pause, or max iterations.
## Objective
- Spawn single executor agent with loop context
- Run main while loop: wait → parse → dispatch → send_input
- Handle terminal conditions (COMPLETED, PAUSED, STOPPED)
- Handle interactive mode (WAITING_INPUT → user choice → send_input)
- Handle auto mode (next action → send_input)
- Update iteration count per cycle
- Close agent on exit
## Execution
### Step 2.1: Spawn Executor Agent
```javascript
const agent = spawn_agent({
message: `
## TASK ASSIGNMENT
### MANDATORY FIRST STEPS (Agent Execute)
1. **Read role definition**: ~/.codex/agents/ccw-loop-executor.md (MUST read first)
2. Read: ${projectRoot}/.workflow/project-tech.json (if exists)
3. Read: ${projectRoot}/.workflow/project-guidelines.json (if exists)
---
## LOOP CONTEXT
- **Loop ID**: ${loopId}
- **State File**: ${projectRoot}/.workflow/.loop/${loopId}.json
- **Progress Dir**: ${progressDir}
- **Mode**: ${mode}
## CURRENT STATE
${JSON.stringify(state, null, 2)}
## TASK DESCRIPTION
${state.description || task}
## EXECUTION INSTRUCTIONS
You are executing CCW Loop orchestrator. Your job:
1. **Check Control Signals**
- Read ${projectRoot}/.workflow/.loop/${loopId}.json
- If status === 'paused' -> Output "PAUSED" and stop
- If status === 'failed' -> Output "STOPPED" and stop
- If status === 'running' -> Continue
2. **Select Next Action**
Based on skill_state:
- If not initialized -> Execute INIT
- If mode === 'interactive' -> Output MENU and wait for input
- If mode === 'auto' -> Auto-select based on state
3. **Execute Action**
- Follow action instructions from ~/.codex/skills/ccw-loop/actions/
- Update progress files in ${progressDir}/
- Update state in ${projectRoot}/.workflow/.loop/${loopId}.json
4. **Output Format**
\`\`\`
ACTION_RESULT:
- action: {action_name}
- status: success | failed | needs_input
- message: {user message}
- state_updates: {JSON of skill_state updates}
NEXT_ACTION_NEEDED: {action_name} | WAITING_INPUT | COMPLETED | PAUSED
\`\`\`
## FIRST ACTION
${!state.skill_state ? 'Execute: INIT' : mode === 'auto' ? 'Auto-select next action' : 'Show MENU'}
`
})
```
### Step 2.2: Main Orchestration Loop
```javascript
let iteration = state.current_iteration || 0
const maxIterations = state.max_iterations || 10
let continueLoop = true
while (continueLoop && iteration < maxIterations) {
iteration++
// Wait for agent output
const result = wait({ ids: [agent], timeout_ms: 600000 })
// Handle timeout
if (result.timed_out) {
console.log('Agent timeout, requesting convergence...')
send_input({
id: agent,
message: `
## TIMEOUT NOTIFICATION
Execution timeout reached. Please:
1. Output current progress
2. Save any pending state updates
3. Return ACTION_RESULT with current status
`
})
continue
}
const output = result.status[agent].completed
// Parse action result
const actionResult = parseActionResult(output)
console.log(`\n[Iteration ${iteration}] Action: ${actionResult.action}, Status: ${actionResult.status}`)
// Update iteration in state
state = readLoopState(loopId)
state.current_iteration = iteration
state.updated_at = getUtc8ISOString()
Write(`${projectRoot}/.workflow/.loop/${loopId}.json`, JSON.stringify(state, null, 2))
// Handle different outcomes
switch (actionResult.next_action) {
case 'COMPLETED':
console.log('Loop completed successfully')
continueLoop = false
break
case 'PAUSED':
console.log('Loop paused by API, exiting gracefully')
continueLoop = false
break
case 'STOPPED':
console.log('Loop stopped by API')
continueLoop = false
break
case 'WAITING_INPUT':
// Interactive mode: display menu, get user choice
if (mode === 'interactive') {
const userChoice = await displayMenuAndGetChoice(actionResult)
send_input({
id: agent,
message: `
## USER INPUT RECEIVED
Action selected: ${userChoice.action}
${userChoice.data ? `Additional data: ${JSON.stringify(userChoice.data)}` : ''}
## EXECUTE SELECTED ACTION
Read action instructions and execute: ${userChoice.action}
Update state and progress files accordingly.
Output ACTION_RESULT when complete.
`
})
}
break
default:
// Continue with next action
if (actionResult.next_action && actionResult.next_action !== 'NONE') {
send_input({
id: agent,
message: `
## CONTINUE EXECUTION
Previous action completed: ${actionResult.action}
Result: ${actionResult.status}
${actionResult.message ? `Message: ${actionResult.message}` : ''}
## EXECUTE NEXT ACTION
Continue with: ${actionResult.next_action}
Read action instructions and execute.
Output ACTION_RESULT when complete.
`
})
} else {
if (actionResult.status === 'failed') {
console.log(`Action failed: ${actionResult.message}`)
}
continueLoop = false
}
}
}
```
### Step 2.3: Iteration Limit Check
```javascript
if (iteration >= maxIterations) {
console.log(`\nReached maximum iterations (${maxIterations})`)
console.log('Consider breaking down the task or taking a break.')
}
```
### Step 2.4: Cleanup
```javascript
close_agent({ id: agent })
console.log('\n=== CCW Loop Orchestrator Finished ===')
const finalState = readLoopState(loopId)
return {
status: finalState.status,
loop_id: loopId,
iterations: iteration,
final_state: finalState
}
```
## Helper Functions
### parseActionResult
```javascript
function parseActionResult(output) {
const result = {
action: 'unknown',
status: 'unknown',
message: '',
state_updates: {},
next_action: 'NONE'
}
// Parse ACTION_RESULT block
const actionMatch = output.match(/ACTION_RESULT:\s*([\s\S]*?)(?:FILES_UPDATED:|NEXT_ACTION_NEEDED:|$)/)
if (actionMatch) {
const lines = actionMatch[1].split('\n')
for (const line of lines) {
const match = line.match(/^-\s*(\w+):\s*(.+)$/)
if (match) {
const [, key, value] = match
if (key === 'state_updates') {
try {
result.state_updates = JSON.parse(value)
} catch (e) {
// Try parsing multi-line JSON
}
} else {
result[key] = value.trim()
}
}
}
}
// Parse NEXT_ACTION_NEEDED
const nextMatch = output.match(/NEXT_ACTION_NEEDED:\s*(\S+)/)
if (nextMatch) {
result.next_action = nextMatch[1]
}
return result
}
```
### displayMenuAndGetChoice
```javascript
async function displayMenuAndGetChoice(actionResult) {
const menuMatch = actionResult.message.match(/MENU_OPTIONS:\s*([\s\S]*?)(?:WAITING_INPUT:|$)/)
if (menuMatch) {
console.log('\n' + menuMatch[1])
}
const response = await ASK_USER([{
id: "Action", type: "select",
prompt: "Select next action:",
options: [
{ label: "develop", description: "Continue development" },
{ label: "debug", description: "Start debugging" },
{ label: "validate", description: "Run validation" },
{ label: "complete", description: "Complete loop" },
{ label: "exit", description: "Exit and save" }
]
}]) // BLOCKS (wait for user response)
return { action: response["Action"] }
}
```
## Termination Conditions
1. **API Paused**: `state.status === 'paused'` (Skill exits, wait for resume)
2. **API Stopped**: `state.status === 'failed'` (Skill terminates)
3. **Task Complete**: `NEXT_ACTION_NEEDED === 'COMPLETED'`
4. **Iteration Limit**: `current_iteration >= max_iterations`
5. **User Exit**: User selects 'exit' in interactive mode
## Output
- **Variable**: `finalState` - Final loop state after all iterations
- **Return**: `{ status, loop_id, iterations, final_state }`
- **TodoWrite**: Mark Phase 2 completed
## Next Phase
None. Phase 2 is the terminal phase of the orchestrator.