mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-12 02:37:45 +08:00
Changed loadClaudeCliTools() to only load tools explicitly defined in user config. Previously, DEFAULT_TOOLS_CONFIG.tools was spread before user tools, causing all default tools to be loaded even if not present in user config. User config now has complete control over which tools are loaded.
350 lines
12 KiB
Markdown
350 lines
12 KiB
Markdown
---
|
||
description: Stateless iterative development loop workflow with documented progress. Supports develop, debug, and validate phases with file-based state tracking. Triggers on "ccw-loop", "dev loop", "development loop".
|
||
argument-hint: TASK="<task description>" [--loop-id=<id>] [--auto]
|
||
---
|
||
|
||
# CCW Loop - Codex Stateless Iterative Development Workflow
|
||
|
||
Stateless iterative development loop using Codex subagent pattern. Supports develop, debug, and validate phases with file-based state tracking.
|
||
|
||
## Arguments
|
||
|
||
| Arg | Required | Description |
|
||
|-----|----------|-------------|
|
||
| TASK | No | Task description (for new loop, mutually exclusive with --loop-id) |
|
||
| --loop-id | No | Existing loop ID to continue (from API or previous session) |
|
||
| --auto | No | Auto-cycle mode (develop -> debug -> validate -> complete) |
|
||
|
||
## Unified Architecture (Codex Subagent Pattern)
|
||
|
||
```
|
||
+-------------------------------------------------------------+
|
||
| Dashboard (UI) |
|
||
| [Create] [Start] [Pause] [Resume] [Stop] [View Progress] |
|
||
+-------------------------------------------------------------+
|
||
|
|
||
v
|
||
+-------------------------------------------------------------+
|
||
| loop-v2-routes.ts (Control Plane) |
|
||
| |
|
||
| State: .workflow/.loop/{loopId}.json (MASTER) |
|
||
| Tasks: .workflow/.loop/{loopId}.tasks.jsonl |
|
||
| |
|
||
| /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) |
|
||
| |
|
||
| Codex Pattern: spawn_agent -> wait -> send_input -> close |
|
||
| |
|
||
| Reads/Writes: .workflow/.loop/{loopId}.json (unified state) |
|
||
| Writes: .workflow/.loop/{loopId}.progress/* (progress files) |
|
||
| |
|
||
| BEFORE each action: |
|
||
| -> Check status: paused/stopped -> exit gracefully |
|
||
| -> running -> continue with action |
|
||
| |
|
||
| Actions: init -> develop -> debug -> validate -> complete |
|
||
+-------------------------------------------------------------+
|
||
```
|
||
|
||
## Key Design Principles (Codex Adaptation)
|
||
|
||
1. **Unified State**: API and Skill share `.workflow/.loop/{loopId}.json` state file
|
||
2. **Control Signals**: Skill checks status field before each action (paused/stopped)
|
||
3. **File-Driven**: All progress documented in `.workflow/.loop/{loopId}.progress/`
|
||
4. **Resumable**: Continue any loop with `--loop-id`
|
||
5. **Dual Trigger**: Supports API trigger (`--loop-id`) and direct call (task description)
|
||
6. **Single Agent Deep Interaction**: Use send_input for multi-phase execution instead of multiple agents
|
||
|
||
## Subagent 机制
|
||
|
||
### 核心 API
|
||
|
||
| API | 作用 |
|
||
|-----|------|
|
||
| `spawn_agent({ message })` | 创建 subagent,返回 `agent_id` |
|
||
| `wait({ ids, timeout_ms })` | 等待结果(唯一取结果入口) |
|
||
| `send_input({ id, message })` | 继续交互/追问 |
|
||
| `close_agent({ id })` | 关闭回收(不可逆) |
|
||
|
||
### 可用模式
|
||
|
||
- **单 Agent 深度交互**: 一个 agent 多阶段,`send_input` 继续
|
||
- **多 Agent 并行**: 主协调器 + 多 worker,`wait({ ids: [...] })` 批量等待
|
||
- **混合模式**: 按需组合
|
||
|
||
## Execution Modes
|
||
|
||
### Mode 1: Interactive
|
||
|
||
User manually selects each action, suitable for complex tasks.
|
||
|
||
```
|
||
User -> Select action -> Execute -> View results -> Select next action
|
||
```
|
||
|
||
### Mode 2: Auto-Loop
|
||
|
||
Automatic execution in preset order, suitable for standard development flow.
|
||
|
||
```
|
||
Develop -> Debug -> Validate -> (if issues) -> Develop -> ...
|
||
```
|
||
|
||
## Session Structure (Unified Location)
|
||
|
||
```
|
||
.workflow/.loop/
|
||
+-- {loopId}.json # Master state file (API + Skill shared)
|
||
+-- {loopId}.tasks.jsonl # Task list (API managed)
|
||
+-- {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)
|
||
```
|
||
|
||
## Implementation (Codex Subagent Pattern)
|
||
|
||
### Session Setup
|
||
|
||
```javascript
|
||
// Helper: Get UTC+8 (China Standard Time) ISO string
|
||
const getUtc8ISOString = () => new Date(Date.now() + 8 * 60 * 60 * 1000).toISOString()
|
||
|
||
// loopId source:
|
||
// 1. API trigger: from --loop-id parameter
|
||
// 2. Direct call: generate new loop-v2-{timestamp}-{random}
|
||
|
||
const loopId = args['--loop-id'] || (() => {
|
||
const timestamp = getUtc8ISOString().replace(/[-:]/g, '').split('.')[0]
|
||
const random = Math.random().toString(36).substring(2, 10)
|
||
return `loop-v2-${timestamp}-${random}`
|
||
})()
|
||
|
||
const loopFile = `.workflow/.loop/${loopId}.json`
|
||
const progressDir = `.workflow/.loop/${loopId}.progress`
|
||
|
||
// Create progress directory
|
||
mkdir -p "${progressDir}"
|
||
```
|
||
|
||
### Main Execution Flow (Single Agent Deep Interaction)
|
||
|
||
```javascript
|
||
// ==================== CODEX CCW-LOOP: SINGLE AGENT ORCHESTRATOR ====================
|
||
|
||
// Step 1: Read or create initial state
|
||
let state = null
|
||
if (existingLoopId) {
|
||
state = JSON.parse(Read(`.workflow/.loop/${loopId}.json`))
|
||
if (!state) {
|
||
console.error(`Loop not found: ${loopId}`)
|
||
return
|
||
}
|
||
} else {
|
||
state = createInitialState(loopId, taskDescription)
|
||
Write(`.workflow/.loop/${loopId}.json`, JSON.stringify(state, null, 2))
|
||
}
|
||
|
||
// Step 2: Create orchestrator agent (single agent handles all phases)
|
||
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: .workflow/project-tech.json
|
||
3. Read: .workflow/project-guidelines.json
|
||
|
||
---
|
||
|
||
## LOOP CONTEXT
|
||
|
||
- **Loop ID**: ${loopId}
|
||
- **State File**: .workflow/.loop/${loopId}.json
|
||
- **Progress Dir**: ${progressDir}
|
||
- **Mode**: ${mode} // 'interactive' or 'auto'
|
||
|
||
## CURRENT STATE
|
||
|
||
${JSON.stringify(state, null, 2)}
|
||
|
||
## TASK DESCRIPTION
|
||
|
||
${taskDescription}
|
||
|
||
## EXECUTION INSTRUCTIONS
|
||
|
||
You are executing CCW Loop orchestrator. Your job:
|
||
|
||
1. **Check Control Signals**
|
||
- Read .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/phases/actions/
|
||
- Update progress files in ${progressDir}/
|
||
- Update state in .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 3: Main orchestration loop
|
||
let iteration = 0
|
||
const maxIterations = state.max_iterations || 10
|
||
|
||
while (iteration < maxIterations) {
|
||
iteration++
|
||
|
||
// Wait for agent output
|
||
const result = wait({ ids: [agent], timeout_ms: 600000 })
|
||
const output = result.status[agent].completed
|
||
|
||
// Parse action result
|
||
const actionResult = parseActionResult(output)
|
||
|
||
// Handle different outcomes
|
||
switch (actionResult.next_action) {
|
||
case 'COMPLETED':
|
||
case 'PAUSED':
|
||
case 'STOPPED':
|
||
close_agent({ id: agent })
|
||
return actionResult
|
||
|
||
case 'WAITING_INPUT':
|
||
// Interactive mode: display menu, get user choice
|
||
const userChoice = await displayMenuAndGetChoice(actionResult)
|
||
|
||
// Send user choice back to agent
|
||
send_input({
|
||
id: agent,
|
||
message: `
|
||
## USER INPUT RECEIVED
|
||
|
||
Action selected: ${userChoice.action}
|
||
${userChoice.data ? `Additional data: ${JSON.stringify(userChoice.data)}` : ''}
|
||
|
||
## EXECUTE SELECTED ACTION
|
||
|
||
Follow instructions for: ${userChoice.action}
|
||
Update state and progress files accordingly.
|
||
`
|
||
})
|
||
break
|
||
|
||
default:
|
||
// Auto mode: agent continues to next action
|
||
// Check if we need to prompt for continuation
|
||
if (actionResult.next_action && actionResult.next_action !== 'NONE') {
|
||
send_input({
|
||
id: agent,
|
||
message: `
|
||
## CONTINUE EXECUTION
|
||
|
||
Previous action completed: ${actionResult.action}
|
||
Result: ${actionResult.status}
|
||
|
||
## EXECUTE NEXT ACTION
|
||
|
||
Continue with: ${actionResult.next_action}
|
||
`
|
||
})
|
||
}
|
||
}
|
||
|
||
// Update iteration count in state
|
||
const currentState = JSON.parse(Read(`.workflow/.loop/${loopId}.json`))
|
||
currentState.current_iteration = iteration
|
||
currentState.updated_at = getUtc8ISOString()
|
||
Write(`.workflow/.loop/${loopId}.json`, JSON.stringify(currentState, null, 2))
|
||
}
|
||
|
||
// Step 4: Cleanup
|
||
close_agent({ id: agent })
|
||
```
|
||
|
||
## Action Catalog
|
||
|
||
| Action | Purpose | Output Files | Trigger |
|
||
|--------|---------|--------------|---------|
|
||
| [action-init](phases/actions/action-init.md) | Initialize loop session | meta.json, state.json | First run |
|
||
| [action-develop](phases/actions/action-develop.md) | Execute development task | progress.md, tasks.json | Has pending tasks |
|
||
| [action-debug](phases/actions/action-debug.md) | Hypothesis-driven debug | understanding.md, hypotheses.json | Needs debugging |
|
||
| [action-validate](phases/actions/action-validate.md) | Test and validate | validation.md, test-results.json | Needs validation |
|
||
| [action-complete](phases/actions/action-complete.md) | Complete loop | summary.md | All done |
|
||
| [action-menu](phases/actions/action-menu.md) | Display action menu | - | Interactive mode |
|
||
|
||
## Usage
|
||
|
||
```bash
|
||
# Start new loop (direct call)
|
||
/ccw-loop TASK="Implement user authentication"
|
||
|
||
# Continue existing loop (API trigger or manual resume)
|
||
/ccw-loop --loop-id=loop-v2-20260122-abc123
|
||
|
||
# Auto-cycle mode
|
||
/ccw-loop --auto TASK="Fix login bug and add tests"
|
||
|
||
# API triggered auto-cycle
|
||
/ccw-loop --loop-id=loop-v2-20260122-abc123 --auto
|
||
```
|
||
|
||
## Reference Documents
|
||
|
||
| Document | Purpose |
|
||
|----------|---------|
|
||
| [phases/orchestrator.md](phases/orchestrator.md) | Orchestrator: state reading + action selection |
|
||
| [phases/state-schema.md](phases/state-schema.md) | State structure definition |
|
||
| [specs/loop-requirements.md](specs/loop-requirements.md) | Loop requirements specification |
|
||
| [specs/action-catalog.md](specs/action-catalog.md) | Action catalog |
|
||
|
||
## Error Handling
|
||
|
||
| Situation | Action |
|
||
|-----------|--------|
|
||
| Session not found | Create new session |
|
||
| State file corrupted | Rebuild from file contents |
|
||
| Agent timeout | send_input to request convergence |
|
||
| Agent unexpectedly closed | Re-spawn, paste previous output |
|
||
| Tests fail | Loop back to develop/debug |
|
||
| >10 iterations | Warn user, suggest break |
|
||
|
||
## Codex Best Practices Applied
|
||
|
||
1. **Role Path Passing**: Agent reads role file itself (no content embedding)
|
||
2. **Single Agent Deep Interaction**: Use send_input for multi-phase instead of multiple agents
|
||
3. **Delayed close_agent**: Only close after confirming no more interaction needed
|
||
4. **Context Reuse**: Same agent maintains all exploration context automatically
|
||
5. **Explicit wait()**: Always use wait({ ids }) to get results, not close_agent
|