flow-coordinator
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseFlow Coordinator
工作流协调器
Lightweight workflow coordinator supporting two workflow formats:
- Legacy Templates: Command chains with slash-command execution
- Unified Workflows: DAG-based PromptTemplate nodes (spec: )
spec/unified-workflow-spec.md
轻量级工作流协调器,支持两种工作流格式:
- 传统模板:采用斜杠命令执行的命令链
- 统一工作流:基于DAG的PromptTemplate节点(规范:)
spec/unified-workflow-spec.md
Specification Reference
规范参考
- Unified Workflow Spec: @spec/unified-workflow-spec.md
- Demo Workflow:
ccw/data/flows/demo-unified-workflow.json
- 统一工作流规范:@spec/unified-workflow-spec.md
- 演示工作流:
ccw/data/flows/demo-unified-workflow.json
Architecture
架构
User Task → Detect Format → Select Workflow → Init Status → Execute → Complete
│ │
├─ Legacy Template │
│ └─ Sequential cmd execution │
│ │
└─ Unified Workflow │
└─ DAG traversal with contextRefs │
│
└──────────────── Resume (from status.json) ──────────────┘
Execution Modes:
├─ analysis → Read-only, CLI --mode analysis
├─ write → File changes, CLI --mode write
├─ mainprocess → Blocking, synchronous
└─ async → Background, ccw cliUser Task → Detect Format → Select Workflow → Init Status → Execute → Complete
│ │
├─ Legacy Template │
│ └─ Sequential cmd execution │
│ │
└─ Unified Workflow │
└─ DAG traversal with contextRefs │
│
└──────────────── Resume (from status.json) ──────────────┘
Execution Modes:
├─ analysis → Read-only, CLI --mode analysis
├─ write → File changes, CLI --mode write
├─ mainprocess → Blocking, synchronous
└─ async → Background, ccw cliCore Concepts
核心概念
Dual Format Support:
- Legacy: with
templates/*.json,cmd,argsexecution - Unified: with
ccw/data/flows/*.json,nodes,edgescontextRefs
Unified PromptTemplate Model: All workflow steps are natural language instructions with:
- : What to execute (natural language)
instruction - : Optional slash command name (e.g., "workflow:plan")
slashCommand - : Optional arguments for slash command (supports {{variable}})
slashArgs - : Name for output reference
outputName - : References to previous step outputs
contextRefs - : Optional CLI tool (gemini/qwen/codex/claude)
tool - : Execution mode (analysis/write/mainprocess/async)
mode
DAG Execution: Unified workflows execute as directed acyclic graphs with parallel branches and conditional edges.
Dynamic Discovery: Both formats discovered at runtime via Glob.
双格式支持:
- 传统模板:,包含
templates/*.json、cmd、args字段execution - 统一工作流:,包含
ccw/data/flows/*.json、nodes、edges字段contextRefs
统一PromptTemplate模型:所有工作流步骤均为自然语言指令,包含以下字段:
- : 要执行的内容(自然语言)
instruction - : 可选斜杠命令名称(例如 "workflow:plan")
slashCommand - : 斜杠命令的可选参数(支持 {{variable}} 变量)
slashArgs - : 输出引用名称
outputName - : 对之前步骤输出的引用
contextRefs - : 可选CLI工具(gemini/qwen/codex/claude)
tool - : 执行模式(analysis/write/mainprocess/async)
mode
DAG执行:统一工作流以有向无环图的形式执行,支持并行分支和条件边。
动态发现:两种格式的工作流均通过Glob在运行时自动发现。
Execution Flow
执行流程
javascript
async function execute(task) {
// 1. Discover and select template
const templates = await discoverTemplates();
const template = await selectTemplate(templates);
// 2. Init status
const sessionId = `fc-${timestamp()}`;
const statusPath = `.workflow/.flow-coordinator/${sessionId}/status.json`;
const status = initStatus(template, task);
write(statusPath, JSON.stringify(status, null, 2));
// 3. Execute steps based on execution config
await executeSteps(status, statusPath);
}
async function executeSteps(status, statusPath) {
for (let i = status.current; i < status.steps.length; i++) {
const step = status.steps[i];
status.current = i;
// Execute based on step mode (all steps use slash-command type)
const execConfig = step.execution || { type: 'slash-command', mode: 'mainprocess' };
if (execConfig.mode === 'async') {
// Async execution - stop and wait for hook callback
await executeSlashCommandAsync(step, status, statusPath);
break;
} else {
// Mainprocess execution - continue immediately
await executeSlashCommandSync(step, status);
step.status = 'done';
write(statusPath, JSON.stringify(status, null, 2));
}
}
// All steps complete
if (status.current >= status.steps.length) {
status.complete = true;
write(statusPath, JSON.stringify(status, null, 2));
}
}javascript
async function execute(task) {
// 1. Discover and select template
const templates = await discoverTemplates();
const template = await selectTemplate(templates);
// 2. Init status
const sessionId = `fc-${timestamp()}`;
const statusPath = `.workflow/.flow-coordinator/${sessionId}/status.json`;
const status = initStatus(template, task);
write(statusPath, JSON.stringify(status, null, 2));
// 3. Execute steps based on execution config
await executeSteps(status, statusPath);
}
async function executeSteps(status, statusPath) {
for (let i = status.current; i < status.steps.length; i++) {
const step = status.steps[i];
status.current = i;
// Execute based on step mode (all steps use slash-command type)
const execConfig = step.execution || { type: 'slash-command', mode: 'mainprocess' };
if (execConfig.mode === 'async') {
// Async execution - stop and wait for hook callback
await executeSlashCommandAsync(step, status, statusPath);
break;
} else {
// Mainprocess execution - continue immediately
await executeSlashCommandSync(step, status);
step.status = 'done';
write(statusPath, JSON.stringify(status, null, 2));
}
}
// All steps complete
if (status.current >= status.steps.length) {
status.complete = true;
write(statusPath, JSON.stringify(status, null, 2));
}
}Unified Workflow Execution
统一工作流执行
For workflows using the unified PromptTemplate format ():
ccw/data/flows/*.jsonjavascript
async function executeUnifiedWorkflow(workflow, task) {
// 1. Initialize execution state
const sessionId = `ufc-${timestamp()}`;
const statusPath = `.workflow/.flow-coordinator/${sessionId}/status.json`;
const state = {
id: sessionId,
workflow: workflow.id,
goal: task,
nodeStates: {}, // nodeId -> { status, result, error }
outputs: {}, // outputName -> result
complete: false
};
// 2. Topological sort for execution order
const executionOrder = topologicalSort(workflow.nodes, workflow.edges);
// 3. Execute nodes respecting DAG dependencies
await executeDAG(workflow, executionOrder, state, statusPath);
}
async function executeDAG(workflow, order, state, statusPath) {
for (const nodeId of order) {
const node = workflow.nodes.find(n => n.id === nodeId);
const data = node.data;
// Check if all dependencies are satisfied
if (!areDependenciesSatisfied(nodeId, workflow.edges, state)) {
continue; // Will be executed when dependencies complete
}
// Build instruction from slashCommand or raw instruction
let instruction = buildNodeInstruction(data, state.outputs);
// Execute based on mode
state.nodeStates[nodeId] = { status: 'running' };
write(statusPath, JSON.stringify(state, null, 2));
const result = await executeNode(instruction, data.tool, data.mode);
// Store output for downstream nodes
state.nodeStates[nodeId] = { status: 'completed', result };
if (data.outputName) {
state.outputs[data.outputName] = result;
}
write(statusPath, JSON.stringify(state, null, 2));
}
state.complete = true;
write(statusPath, JSON.stringify(state, null, 2));
}
/**
* Build node instruction from slashCommand or raw instruction
* Handles slashCommand/slashArgs fields from frontend orchestrator
*/
function buildNodeInstruction(data, outputs) {
const refs = data.contextRefs || [];
// If slashCommand is set, construct instruction from it
if (data.slashCommand) {
// Resolve variables in slashArgs
const args = data.slashArgs
? resolveContextRefs(data.slashArgs, refs, outputs)
: '';
// Build slash command instruction
let instruction = `/${data.slashCommand}${args ? ' ' + args : ''}`;
// Append additional instruction if provided
if (data.instruction) {
const additionalInstruction = resolveContextRefs(data.instruction, refs, outputs);
instruction = `${instruction}\n\n${additionalInstruction}`;
}
return instruction;
}
// Fallback: use raw instruction with context refs resolved
return resolveContextRefs(data.instruction || '', refs, outputs);
}
function resolveContextRefs(instruction, refs, outputs) {
let resolved = instruction;
for (const ref of refs) {
const value = outputs[ref];
const placeholder = `{{${ref}}}`;
resolved = resolved.replace(new RegExp(placeholder, 'g'),
typeof value === 'object' ? JSON.stringify(value) : String(value));
}
return resolved;
}
async function executeNode(instruction, tool, mode) {
// Build CLI command based on tool and mode
const cliTool = tool || 'gemini';
const cliMode = mode === 'write' ? 'write' : 'analysis';
if (mode === 'async') {
// Background execution
return Bash(
`ccw cli -p "${escapePrompt(instruction)}" --tool ${cliTool} --mode ${cliMode}`,
{ run_in_background: true }
);
} else {
// Synchronous execution
return Bash(
`ccw cli -p "${escapePrompt(instruction)}" --tool ${cliTool} --mode ${cliMode}`
);
}
}对于使用统一PromptTemplate格式的工作流():
ccw/data/flows/*.jsonjavascript
async function executeUnifiedWorkflow(workflow, task) {
// 1. Initialize execution state
const sessionId = `ufc-${timestamp()}`;
const statusPath = `.workflow/.flow-coordinator/${sessionId}/status.json`;
const state = {
id: sessionId,
workflow: workflow.id,
goal: task,
nodeStates: {}, // nodeId -> { status, result, error }
outputs: {}, // outputName -> result
complete: false
};
// 2. Topological sort for execution order
const executionOrder = topologicalSort(workflow.nodes, workflow.edges);
// 3. Execute nodes respecting DAG dependencies
await executeDAG(workflow, executionOrder, state, statusPath);
}
async function executeDAG(workflow, order, state, statusPath) {
for (const nodeId of order) {
const node = workflow.nodes.find(n => n.id === nodeId);
const data = node.data;
// Check if all dependencies are satisfied
if (!areDependenciesSatisfied(nodeId, workflow.edges, state)) {
continue; // Will be executed when dependencies complete
}
// Build instruction from slashCommand or raw instruction
let instruction = buildNodeInstruction(data, state.outputs);
// Execute based on mode
state.nodeStates[nodeId] = { status: 'running' };
write(statusPath, JSON.stringify(state, null, 2));
const result = await executeNode(instruction, data.tool, data.mode);
// Store output for downstream nodes
state.nodeStates[nodeId] = { status: 'completed', result };
if (data.outputName) {
state.outputs[data.outputName] = result;
}
write(statusPath, JSON.stringify(state, null, 2));
}
state.complete = true;
write(statusPath, JSON.stringify(state, null, 2));
}
/**
* Build node instruction from slashCommand or raw instruction
* Handles slashCommand/slashArgs fields from frontend orchestrator
*/
function buildNodeInstruction(data, outputs) {
const refs = data.contextRefs || [];
// If slashCommand is set, construct instruction from it
if (data.slashCommand) {
// Resolve variables in slashArgs
const args = data.slashArgs
? resolveContextRefs(data.slashArgs, refs, outputs)
: '';
// Build slash command instruction
let instruction = `/${data.slashCommand}${args ? ' ' + args : ''}`;
// Append additional instruction if provided
if (data.instruction) {
const additionalInstruction = resolveContextRefs(data.instruction, refs, outputs);
instruction = `${instruction}\n\n${additionalInstruction}`;
}
return instruction;
}
// Fallback: use raw instruction with context refs resolved
return resolveContextRefs(data.instruction || '', refs, outputs);
}
function resolveContextRefs(instruction, refs, outputs) {
let resolved = instruction;
for (const ref of refs) {
const value = outputs[ref];
const placeholder = `{{${ref}}}`;
resolved = resolved.replace(new RegExp(placeholder, 'g'),
typeof value === 'object' ? JSON.stringify(value) : String(value));
}
return resolved;
}
async function executeNode(instruction, tool, mode) {
// Build CLI command based on tool and mode
const cliTool = tool || 'gemini';
const cliMode = mode === 'write' ? 'write' : 'analysis';
if (mode === 'async') {
// Background execution
return Bash(
`ccw cli -p "${escapePrompt(instruction)}" --tool ${cliTool} --mode ${cliMode}`,
{ run_in_background: true }
);
} else {
// Synchronous execution
return Bash(
`ccw cli -p "${escapePrompt(instruction)}" --tool ${cliTool} --mode ${cliMode}`
);
}
}Unified Workflow Discovery
统一工作流发现
javascript
async function discoverUnifiedWorkflows() {
const files = Glob('*.json', { path: 'ccw/data/flows/' });
const workflows = [];
for (const file of files) {
const content = JSON.parse(Read(file));
// Detect unified format by checking for 'nodes' array
if (content.nodes && Array.isArray(content.nodes)) {
workflows.push({
id: content.id,
name: content.name,
description: content.description,
nodeCount: content.nodes.length,
format: 'unified',
file: file
});
}
}
return workflows;
}javascript
async function discoverUnifiedWorkflows() {
const files = Glob('*.json', { path: 'ccw/data/flows/' });
const workflows = [];
for (const file of files) {
const content = JSON.parse(Read(file));
// Detect unified format by checking for 'nodes' array
if (content.nodes && Array.isArray(content.nodes)) {
workflows.push({
id: content.id,
name: content.name,
description: content.description,
nodeCount: content.nodes.length,
format: 'unified',
file: file
});
}
}
return workflows;
}Format Detection
格式检测
javascript
function detectWorkflowFormat(content) {
if (content.nodes && content.edges) {
return 'unified'; // PromptTemplate DAG format
}
if (content.steps && content.steps[0]?.cmd) {
return 'legacy'; // Command chain format
}
throw new Error('Unknown workflow format');
}javascript
function detectWorkflowFormat(content) {
if (content.nodes && content.edges) {
return 'unified'; // PromptTemplate DAG format
}
if (content.steps && content.steps[0]?.cmd) {
return 'legacy'; // Command chain format
}
throw new Error('Unknown workflow format');
}Legacy Template Discovery
传统模板发现
Dynamic query - never hardcode template list:
javascript
async function discoverTemplates() {
// Discover all JSON templates
const files = Glob('*.json', { path: 'templates/' });
// Parse each template
const templates = [];
for (const file of files) {
const content = JSON.parse(Read(file));
templates.push({
name: content.name,
description: content.description,
steps: content.steps.map(s => s.cmd).join(' → '),
file: file
});
}
return templates;
}动态查询 - 切勿硬编码模板列表:
javascript
async function discoverTemplates() {
// Discover all JSON templates
const files = Glob('*.json', { path: 'templates/' });
// Parse each template
const templates = [];
for (const file of files) {
const content = JSON.parse(Read(file));
templates.push({
name: content.name,
description: content.description,
steps: content.steps.map(s => s.cmd).join(' → '),
file: file
});
}
return templates;
}Template Selection
模板选择
User chooses from discovered templates:
javascript
async function selectTemplate(templates) {
// Build options from discovered templates
const options = templates.slice(0, 4).map(t => ({
label: t.name,
description: t.steps
}));
const response = await AskUserQuestion({
questions: [{
question: 'Select workflow template:',
header: 'Template',
options: options,
multiSelect: false
}]
});
// Handle "Other" - show remaining templates or custom input
if (response.template === 'Other') {
return await selectFromRemainingTemplates(templates.slice(4));
}
return templates.find(t => t.name === response.template);
}用户从已发现的模板中进行选择:
javascript
async function selectTemplate(templates) {
// Build options from discovered templates
const options = templates.slice(0, 4).map(t => ({
label: t.name,
description: t.steps
}));
const response = await AskUserQuestion({
questions: [{
question: 'Select workflow template:',
header: 'Template',
options: options,
multiSelect: false
}]
});
// Handle "Other" - show remaining templates or custom input
if (response.template === 'Other') {
return await selectFromRemainingTemplates(templates.slice(4));
}
return templates.find(t => t.name === response.template);
}Status Schema
状态Schema
Creation: Copy template JSON → Update , , , set all steps
idtemplategoalstatus: "pending"Location:
.workflow/.flow-coordinator/{session-id}/status.jsonCore Fields:
- : Session ID (fc-YYYYMMDD-HHMMSS)
id - : Template name
template - : User task description
goal - : Current step index
current - : Step array from template (with runtime
steps[],status,session)taskId - : All steps done?
complete
Step Status: → → | |
pendingrunningdonefailedskipped创建方式:复制模板JSON → 更新、、,将所有步骤的设置为
idtemplategoalstatus"pending"存储位置:
.workflow/.flow-coordinator/{session-id}/status.json核心字段:
- : 会话ID(fc-YYYYMMDD-HHMMSS格式)
id - : 模板名称
template - : 用户任务描述
goal - : 当前步骤索引
current - : 来自模板的步骤数组(包含运行时的
steps[]、status、session字段)taskId - : 是否所有步骤已完成?
complete
步骤状态: → → | |
pendingrunningdonefailedskippedExtended Template Schema
扩展模板Schema
Templates stored in: (discovered at runtime via Glob)
templates/*.jsonTemplateStep Fields:
- : Full command path (e.g.,
cmd,/workflow:lite-plan)/workflow:execute - : Arguments with
args?and{{goal}}placeholders{{prev}} - : Minimum execution unit name (groups related commands)
unit? - : Can be skipped by user
optional? - : Type and mode configuration
execution- : Always
type(for all workflow commands)'slash-command' - :
mode(blocking) or'mainprocess'(background)'async'
- : Natural language guidance for context assembly
contextHint?
Template Example:
json
{
"name": "rapid",
"steps": [
{
"cmd": "/workflow:lite-plan",
"args": "\"{{goal}}\"",
"unit": "quick-implementation",
"execution": { "type": "slash-command", "mode": "mainprocess" },
"contextHint": "Create lightweight implementation plan"
},
{
"cmd": "/workflow:lite-execute",
"args": "--in-memory",
"unit": "quick-implementation",
"execution": { "type": "slash-command", "mode": "async" },
"contextHint": "Execute plan from previous step"
}
]
}模板存储位置:(通过Glob在运行时自动发现)
templates/*.jsonTemplateStep字段:
- : 完整命令路径(例如
cmd、/workflow:lite-plan)/workflow:execute - : 包含
args?和{{goal}}占位符的参数{{prev}} - : 最小执行单元名称(用于分组相关命令)
unit? - : 是否可由用户跳过
optional? - : 类型和模式配置
execution- : 始终为
type(适用于所有工作流命令)'slash-command' - :
mode(阻塞式)或'mainprocess'(后台执行)'async'
- : 用于上下文组装的自然语言指导
contextHint?
模板示例:
json
{
"name": "rapid",
"steps": [
{
"cmd": "/workflow:lite-plan",
"args": "\"{{goal}}\"",
"unit": "quick-implementation",
"execution": { "type": "slash-command", "mode": "mainprocess" },
"contextHint": "Create lightweight implementation plan"
},
{
"cmd": "/workflow:lite-execute",
"args": "--in-memory",
"unit": "quick-implementation",
"execution": { "type": "slash-command", "mode": "async" },
"contextHint": "Execute plan from previous step"
}
]
}Execution Implementation
执行实现
Mainprocess Mode (Blocking)
Mainprocess模式(阻塞式)
javascript
async function executeSlashCommandSync(step, status) {
// Build command: /workflow:cmd -y args
const cmd = buildCommand(step, status);
const result = await SlashCommand({ command: cmd });
step.session = result.session_id;
step.status = 'done';
return result;
}javascript
async function executeSlashCommandSync(step, status) {
// Build command: /workflow:cmd -y args
const cmd = buildCommand(step, status);
const result = await SlashCommand({ command: cmd });
step.session = result.session_id;
step.status = 'done';
return result;
}Async Mode (Background)
Async模式(后台执行)
javascript
async function executeSlashCommandAsync(step, status, statusPath) {
// Build prompt: /workflow:cmd -y args + context
const prompt = buildCommandPrompt(step, status);
step.status = 'running';
write(statusPath, JSON.stringify(status, null, 2));
// Execute via ccw cli in background
const taskId = Bash(
`ccw cli -p "${escapePrompt(prompt)}" --tool claude --mode write`,
{ run_in_background: true }
).task_id;
step.taskId = taskId;
write(statusPath, JSON.stringify(status, null, 2));
console.log(`Executing: ${step.cmd} (async)`);
console.log(`Resume: /flow-coordinator --resume ${status.id}`);
}javascript
async function executeSlashCommandAsync(step, status, statusPath) {
// Build prompt: /workflow:cmd -y args + context
const prompt = buildCommandPrompt(step, status);
step.status = 'running';
write(statusPath, JSON.stringify(status, null, 2));
// Execute via ccw cli in background
const taskId = Bash(
`ccw cli -p "${escapePrompt(prompt)}" --tool claude --mode write`,
{ run_in_background: true }
).task_id;
step.taskId = taskId;
write(statusPath, JSON.stringify(status, null, 2));
console.log(`Executing: ${step.cmd} (async)`);
console.log(`Resume: /flow-coordinator --resume ${status.id}`);
}Prompt Building
提示词构建
Prompts are built in format: + context
/workflow:cmd -y argsjavascript
function buildCommandPrompt(step, status) {
// step.cmd already contains full path: /workflow:lite-plan, /workflow:execute, etc.
let prompt = `${step.cmd} -y`;
// Add arguments (with placeholder replacement)
if (step.args) {
const args = step.args
.replace('{{goal}}', status.goal)
.replace('{{prev}}', getPreviousSessionId(status));
prompt += ` ${args}`;
}
// Add context based on contextHint
if (step.contextHint) {
const context = buildContextFromHint(step.contextHint, status);
prompt += `\n\nContext:\n${context}`;
} else {
// Default context: previous session IDs
const previousContext = collectPreviousResults(status);
if (previousContext) {
prompt += `\n\nPrevious results:\n${previousContext}`;
}
}
return prompt;
}
function buildContextFromHint(hint, status) {
// Parse contextHint instruction and build context accordingly
// Examples:
// "Summarize IMPL_PLAN.md" → read and summarize plan
// "List test coverage gaps" → analyze previous test results
// "Pass session ID" → just return session reference
return parseAndBuildContext(hint, status);
}提示词采用以下格式构建: + 上下文
/workflow:cmd -y argsjavascript
function buildCommandPrompt(step, status) {
// step.cmd already contains full path: /workflow:lite-plan, /workflow:execute, etc.
let prompt = `${step.cmd} -y`;
// Add arguments (with placeholder replacement)
if (step.args) {
const args = step.args
.replace('{{goal}}', status.goal)
.replace('{{prev}}', getPreviousSessionId(status));
prompt += ` ${args}`;
}
// Add context based on contextHint
if (step.contextHint) {
const context = buildContextFromHint(step.contextHint, status);
prompt += `\n\nContext:\n${context}`;
} else {
// Default context: previous session IDs
const previousContext = collectPreviousResults(status);
if (previousContext) {
prompt += `\n\nPrevious results:\n${previousContext}`;
}
}
return prompt;
}
function buildContextFromHint(hint, status) {
// Parse contextHint instruction and build context accordingly
// Examples:
// "Summarize IMPL_PLAN.md" → read and summarize plan
// "List test coverage gaps" → analyze previous test results
// "Pass session ID" → just return session reference
return parseAndBuildContext(hint, status);
}Example Prompt Output
提示词输出示例
/workflow:lite-plan -y "Implement user registration"
Context:
Task: Implement user registration
Previous results:
- None (first step)/workflow:execute -y --in-memory
Context:
Task: Implement user registration
Previous results:
- lite-plan: WFS-plan-20250130 (planning-context.md)/workflow:lite-plan -y "Implement user registration"
Context:
Task: Implement user registration
Previous results:
- None (first step)/workflow:execute -y --in-memory
Context:
Task: Implement user registration
Previous results:
- lite-plan: WFS-plan-20250130 (planning-context.md)User Interaction
用户交互
Step 1: Select Template
步骤1:选择模板
Select workflow template:
○ rapid lite-plan → lite-execute → test-cycle-execute
○ coupled plan → plan-verify → execute → review → test
○ bugfix lite-fix → lite-execute → test-cycle-execute
○ tdd tdd-plan → execute → tdd-verify
○ Other (more templates or custom)Select workflow template:
○ rapid lite-plan → lite-execute → test-cycle-execute
○ coupled plan → plan-verify → execute → review → test
○ bugfix lite-fix → lite-execute → test-cycle-execute
○ tdd tdd-plan → execute → tdd-verify
○ Other (more templates or custom)Step 2: Review Execution Plan
步骤2:查看执行计划
Template: coupled
Steps:
1. /workflow:plan (slash-command mainprocess)
2. /workflow:plan-verify (slash-command mainprocess)
3. /workflow:execute (slash-command async)
4. /workflow:review-session-cycle (slash-command mainprocess)
5. /workflow:review-cycle-fix (slash-command mainprocess)
6. /workflow:test-fix-gen (slash-command mainprocess)
7. /workflow:test-cycle-execute (slash-command async)
Proceed? [Confirm / Cancel]Template: coupled
Steps:
1. /workflow:plan (slash-command mainprocess)
2. /workflow:plan-verify (slash-command mainprocess)
3. /workflow:execute (slash-command async)
4. /workflow:review-session-cycle (slash-command mainprocess)
5. /workflow:review-cycle-fix (slash-command mainprocess)
6. /workflow:test-fix-gen (slash-command mainprocess)
7. /workflow:test-cycle-execute (slash-command async)
Proceed? [Confirm / Cancel]Resume Capability
恢复功能
javascript
async function resume(sessionId) {
const statusPath = `.workflow/.flow-coordinator/${sessionId}/status.json`;
const status = JSON.parse(Read(statusPath));
// Find first incomplete step
status.current = status.steps.findIndex(s => s.status !== 'done');
if (status.current === -1) {
console.log('All steps complete');
return;
}
// Continue executing steps
await executeSteps(status, statusPath);
}javascript
async function resume(sessionId) {
const statusPath = `.workflow/.flow-coordinator/${sessionId}/status.json`;
const status = JSON.parse(Read(statusPath));
// Find first incomplete step
status.current = status.steps.findIndex(s => s.status !== 'done');
if (status.current === -1) {
console.log('All steps complete');
return;
}
// Continue executing steps
await executeSteps(status, statusPath);
}Available Templates
可用模板
Templates discovered from :
templates/*.json| Template | Use Case | Steps |
|---|---|---|
| rapid | Simple feature | /workflow:lite-plan → /workflow:lite-execute → /workflow:test-cycle-execute |
| coupled | Complex feature | /workflow:plan → /workflow:plan-verify → /workflow:execute → /workflow:review-session-cycle → /workflow:test-fix-gen |
| bugfix | Bug fix | /workflow:lite-fix → /workflow:lite-execute → /workflow:test-cycle-execute |
| tdd | Test-driven | /workflow:tdd-plan → /workflow:execute → /workflow:tdd-verify |
| test-fix | Fix failing tests | /workflow:test-fix-gen → /workflow:test-cycle-execute |
| brainstorm | Exploration | /workflow:brainstorm-with-file |
| debug | Debug with docs | /workflow:debug-with-file |
| analyze | Collaborative analysis | /workflow:analyze-with-file |
| issue | Issue workflow | /workflow:issue:plan → /workflow:issue:queue → /workflow:issue:execute |
从中发现的模板:
templates/*.json| 模板名称 | 使用场景 | 步骤 |
|---|---|---|
| rapid | 简单功能开发 | /workflow:lite-plan → /workflow:lite-execute → /workflow:test-cycle-execute |
| coupled | 复杂功能开发 | /workflow:plan → /workflow:plan-verify → /workflow:execute → /workflow:review-session-cycle → /workflow:test-fix-gen |
| bugfix | Bug修复 | /workflow:lite-fix → /workflow:lite-execute → /workflow:test-cycle-execute |
| tdd | 测试驱动开发 | /workflow:tdd-plan → /workflow:execute → /workflow:tdd-verify |
| test-fix | 修复失败测试 | /workflow:test-fix-gen → /workflow:test-cycle-execute |
| brainstorm | 需求探索 | /workflow:brainstorm-with-file |
| debug | 结合文档调试 | /workflow:debug-with-file |
| analyze | 协作分析 | /workflow:analyze-with-file |
| issue | 问题处理工作流 | /workflow:issue:plan → /workflow:issue:queue → /workflow:issue:execute |
Design Principles
设计原则
- Minimal fields: Only essential tracking data
- Flat structure: No nested objects beyond steps array
- Step-level execution: Each step defines how it's executed
- Resumable: Any step can be resumed from status
- Human readable: Clear JSON format
- 最少字段:仅跟踪必要的状态数据
- 扁平结构:除步骤数组外无嵌套对象
- 步骤级执行:每个步骤定义自身的执行方式
- 可恢复:可从状态文件恢复任意步骤的执行
- 易读性:清晰的JSON格式
Reference Documents
参考文档
| Document | Purpose |
|---|---|
| spec/unified-workflow-spec.md | Unified PromptTemplate workflow specification |
| ccw/data/flows/*.json | Unified workflows (DAG format, dynamic discovery) |
| templates/*.json | Legacy workflow templates (command chain format) |
| 文档 | 用途 |
|---|---|
| spec/unified-workflow-spec.md | 统一PromptTemplate工作流规范 |
| ccw/data/flows/*.json | 统一工作流(DAG格式,动态发现) |
| templates/*.json | 传统工作流模板(命令链格式) |
Demo Workflows (Unified Format)
演示工作流(统一格式)
| File | Description | Nodes |
|---|---|---|
| Auth implementation | 7 nodes: Analyze → Plan → Implement → Review → Tests → Report |
| CI/CD pipeline | 8 nodes: Parallel checks → Merge → Conditional notify |
| Analysis pipeline | 3 nodes: Explore → Analyze → Report |
| 文件 | 描述 | 节点数 |
|---|---|---|
| 认证功能实现 | 7个节点:分析 → 规划 → 实现 → 评审 → 测试 → 报告 |
| CI/CD流水线 | 8个节点:并行检查 → 合并 → 条件通知 |
| 分析流水线 | 3个节点:探索 → 分析 → 报告 |