home / skills / catlog22 / claude-code-workflow / ccw-loop

ccw-loop skill

/.codex/skills/ccw-loop

This skill orchestrates stateless iterative development loops with file-based state tracking, enabling auto or manual develop, debug, and validate phases.

npx playbooks add skill catlog22/claude-code-workflow --skill ccw-loop

Review the files below or copy the command above to add this skill to your agents.

Files (11)
SKILL.md
12.0 KB
---
name: CCW Loop
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

Overview

This skill implements a stateless iterative development loop for file-based progress tracking and resumable workflows. It supports develop, debug, and validate phases and can run interactively or in automatic cycles. The workflow is driven by a unified state file and progress directory for transparent, resumable execution.

How this skill works

The skill creates or resumes a loop identified by a loop ID and stores master state in .workflow/.loop/{loopId}.json. It spawns a single orchestrator agent that uses spawn_agent, wait, send_input, and close_agent to execute multi-phase actions and write progress into .workflow/.loop/{loopId}.progress/. The agent checks control signals (running/paused/failed) before each action and updates state and progress files after each step.

When to use it

  • Start new feature, bugfix, or test-driven task that benefits from documented iterations.
  • Resume interrupted development work with preserved state and progress files.
  • Run automated cycles for standard develop->debug->validate flows.
  • Use interactive mode for complex tasks requiring manual choices.
  • Integrate with a dashboard or CLI for pause/resume/stop control.

Best practices

  • Keep project guidelines and tech context files in .workflow so the orchestrator can read them first.
  • Prefer single-agent deep interaction: use send_input to continue phases rather than spawning many agents.
  • Write meaningful progress entries (develop.md, debug.md, validate.md) so reviews are traceable.
  • Use --loop-id to resume instead of creating duplicate loops.
  • Set sensible max_iterations and add checkpoints to avoid runaway loops.

Example use cases

  • Implement a new endpoint: run develop to add code, debug to reproduce failures, validate with tests, and produce summary.md.
  • Triage and fix a production bug: resume the loop, reproduce in debug, apply fixes, and validate.
  • Automated CI task: trigger auto-loop to run develop->debug->validate for routine maintenance.
  • Collaborative sessions: share loop ID so multiple contributors can resume and inspect progress files.

FAQ

How do I resume a previously interrupted loop?

Pass --loop-id with the loop ID or call the skill with the existing loop ID. The skill will read .workflow/.loop/{loopId}.json and continue from the saved state.

What happens when the loop status is paused or failed?

The orchestrator checks the status before each action. If status is paused or failed the agent exits gracefully and awaits resume or restart commands; no progress is lost.