feat: Add main workflow orchestrator (ccw) with intent analysis and command execution

- Implemented the ccw command as a main workflow orchestrator.
- Added a 5-phase workflow including intent analysis, requirement clarification, workflow selection, user confirmation, and command execution.
- Developed functions for analyzing user input, selecting workflows, and executing command chains.
- Integrated TODO tracking for command execution progress.
- Created comprehensive tests for the CommandRegistry, covering YAML parsing, command retrieval, and error handling.
This commit is contained in:
catlog22
2026-01-24 13:43:47 +08:00
parent 44b8269a74
commit 24efef7f17
21 changed files with 1333 additions and 4199 deletions

664
.claude/commands/ccw.md Normal file
View File

@@ -0,0 +1,664 @@
---
name: ccw
description: Main workflow orchestrator - analyze intent, select workflow, execute command chain in main process
argument-hint: "\"task description\""
allowed-tools: SlashCommand(*), TodoWrite(*), AskUserQuestion(*), Read(*), Grep(*), Glob(*)
---
# CCW Command - Main Workflow Orchestrator
Main process workflow orchestrator: intent analysis → workflow selection → command chain execution.
**Execution Model**: Execute command chain directly in main process using SlashCommand.
## 5-Phase Workflow
### Phase 1: Analyze Intent
Analyze user input to extract task intent and characteristics.
```javascript
function analyzeIntent(input) {
return {
goal: extractGoal(input), // Main objective
scope: extractScope(input), // Affected scope
constraints: extractConstraints(input), // Constraints
task_type: detectTaskType(input), // Task type
complexity: assessComplexity(input), // Complexity level
clarity_score: calculateClarity(input) // Requirement clarity (0-3)
};
}
// Task type detection (priority order)
function detectTaskType(text) {
if (/urgent|production|critical/.test(text) && /fix|bug/.test(text)) return 'bugfix-hotfix';
if (/fix|bug|error|crash|fail|debug/.test(text)) return 'bugfix';
if (/issues?|batch/.test(text) && /fix|resolve/.test(text)) return 'issue-batch';
if (/uncertain|explore|research|what if/.test(text)) return 'exploration';
if (/multi-perspective|compare|cross-verify/.test(text)) return 'multi-perspective';
if (/quick|simple|small/.test(text) && /feature|function/.test(text)) return 'quick-task';
if (/ui|design|component|style/.test(text)) return 'ui-design';
if (/tdd|test-driven|test first/.test(text)) return 'tdd';
if (/test fail|fix test|failing test/.test(text)) return 'test-fix';
if (/review|code review/.test(text)) return 'review';
if (/docs|documentation|readme/.test(text)) return 'documentation';
return 'feature';
}
// Complexity assessment
function assessComplexity(text) {
let score = 0;
if (/refactor|migrate|architect|system/.test(text)) score += 2;
if (/multiple|across|all|entire/.test(text)) score += 2;
if (/integrate|api|database/.test(text)) score += 1;
if (/security|performance|scale/.test(text)) score += 1;
return score >= 4 ? 'high' : score >= 2 ? 'medium' : 'low';
}
// Requirement clarity calculation
function calculateClarity(text) {
let score = 0;
if (/create|fix|refactor|optimize|analyze/.test(text)) score += 0.5; // Has action
if (/\.(ts|js|py|java|go|md)/.test(text)) score += 0.5; // Has file path
if (/for|because|to achieve/.test(text)) score += 0.5; // Has goal
if (/must|should|no|without/.test(text)) score += 0.5; // Has constraints
if (/uncertain|maybe|how to/.test(text)) score -= 0.5; // Has uncertainty
return Math.max(0, Math.min(3, score));
}
```
**Display to user**:
```
Intent Analysis:
Type: [task_type]
Goal: [goal]
Complexity: [complexity]
Clarity: [clarity_score]/3
```
---
### Phase 1.5: Requirement Clarification (if needed)
When clarity_score < 2, clarify requirements through questions.
```javascript
async function clarifyRequirements(analysis) {
if (analysis.clarity_score >= 2) return analysis;
const questions = generateClarificationQuestions(analysis);
const answers = await AskUserQuestion({ questions });
// Update analysis based on user answers
return updateAnalysis(analysis, answers);
}
function generateClarificationQuestions(analysis) {
const questions = [];
if (!analysis.goal) {
questions.push({
question: "What is the main goal of this task?",
header: "Goal",
options: [
{ label: "Create new feature", description: "Implement new functionality" },
{ label: "Fix issue", description: "Fix bugs or errors" },
{ label: "Optimize/Improve", description: "Refactor or performance optimization" },
{ label: "Analyze/Research", description: "Explore or analyze code" }
],
multiSelect: false
});
}
if (!analysis.scope || analysis.scope.length === 0) {
questions.push({
question: "What is the scope of this task?",
header: "Scope",
options: [
{ label: "Single file", description: "Modify single file" },
{ label: "Single module", description: "One functional module" },
{ label: "Multiple modules", description: "Cross-module changes" },
{ label: "Entire system", description: "System-level changes" }
],
multiSelect: false
});
}
if (!analysis.constraints || analysis.constraints.length === 0) {
questions.push({
question: "Any special requirements or constraints?",
header: "Constraints",
options: [
{ label: "No constraints", description: "No special requirements" },
{ label: "Backward compatible", description: "Maintain compatibility" },
{ label: "Skip tests", description: "No test execution needed" },
{ label: "Urgent hotfix", description: "Production issue" }
],
multiSelect: true
});
}
return questions;
}
```
---
### Phase 2: Select Workflow & Build Command Chain
Select workflow level and build command chain based on intent analysis.
```javascript
function selectWorkflow(analysis) {
const { task_type, complexity, constraints } = analysis;
// Level mapping
const levelMap = {
'bugfix-hotfix': { level: 2, flow: 'bugfix.hotfix' },
'bugfix': { level: 2, flow: 'bugfix.standard' },
'issue-batch': { level: 'Issue', flow: 'issue' },
'exploration': { level: 4, flow: 'full' },
'multi-perspective': { level: 2, flow: 'multi-cli-plan' },
'quick-task': { level: 1, flow: 'lite-lite-lite' },
'ui-design': { level: complexity === 'high' ? 4 : 3, flow: 'ui' },
'tdd': { level: 3, flow: 'tdd' },
'test-fix': { level: 3, flow: 'test-fix-gen' },
'review': { level: 3, flow: 'review-fix' },
'documentation': { level: 2, flow: 'docs' },
'feature': { level: complexity === 'high' ? 3 : 2, flow: complexity === 'high' ? 'coupled' : 'rapid' }
};
const selected = levelMap[task_type] || levelMap['feature'];
return buildCommandChain(selected, analysis);
}
// Build command chain (port-based matching)
function buildCommandChain(workflow, analysis) {
const chains = {
// Level 1 - Rapid
'lite-lite-lite': [
{ cmd: '/workflow:lite-lite-lite', args: `"${analysis.goal}"` }
],
// Level 2 - Lightweight
'rapid': [
{ cmd: '/workflow:lite-plan', args: `"${analysis.goal}"` },
{ cmd: '/workflow:lite-execute', args: '--in-memory' },
...(analysis.constraints?.includes('skip-tests') ? [] : [
{ cmd: '/workflow:test-cycle-execute', args: '' }
])
],
'bugfix.standard': [
{ cmd: '/workflow:lite-fix', args: `"${analysis.goal}"` },
...(analysis.constraints?.includes('skip-tests') ? [] : [
{ cmd: '/workflow:test-cycle-execute', args: '' }
])
],
'bugfix.hotfix': [
{ cmd: '/workflow:lite-fix', args: `--hotfix "${analysis.goal}"` }
],
'multi-cli-plan': [
{ cmd: '/workflow:multi-cli-plan', args: `"${analysis.goal}"` },
{ cmd: '/workflow:lite-execute', args: '--in-memory' },
...(analysis.constraints?.includes('skip-tests') ? [] : [
{ cmd: '/workflow:test-cycle-execute', args: '' }
])
],
'docs': [
{ cmd: '/workflow:lite-plan', args: `"${analysis.goal}"` },
{ cmd: '/workflow:lite-execute', args: '--in-memory' }
],
// Level 3 - Standard
'coupled': [
{ cmd: '/workflow:plan', args: `"${analysis.goal}"` },
{ cmd: '/workflow:plan-verify', args: '' },
{ cmd: '/workflow:execute', args: '' },
{ cmd: '/workflow:review-session-cycle', args: '' },
...(analysis.constraints?.includes('skip-tests') ? [] : [
{ cmd: '/workflow:test-cycle-execute', args: '' }
])
],
'tdd': [
{ cmd: '/workflow:tdd-plan', args: `"${analysis.goal}"` },
{ cmd: '/workflow:execute', args: '' },
{ cmd: '/workflow:tdd-verify', args: '' }
],
'test-fix-gen': [
{ cmd: '/workflow:test-fix-gen', args: `"${analysis.goal}"` },
{ cmd: '/workflow:test-cycle-execute', args: '' }
],
'review-fix': [
{ cmd: '/workflow:review', args: '' },
{ cmd: '/workflow:review-fix', args: '' },
{ cmd: '/workflow:test-cycle-execute', args: '' }
],
'ui': [
{ cmd: '/workflow:ui-design:explore-auto', args: `"${analysis.goal}"` },
{ cmd: '/workflow:plan', args: '' },
{ cmd: '/workflow:execute', args: '' }
],
// Level 4 - Brainstorm
'full': [
{ cmd: '/workflow:brainstorm:auto-parallel', args: `"${analysis.goal}"` },
{ cmd: '/workflow:plan', args: '' },
{ cmd: '/workflow:plan-verify', args: '' },
{ cmd: '/workflow:execute', args: '' },
{ cmd: '/workflow:test-cycle-execute', args: '' }
],
// Issue Workflow
'issue': [
{ cmd: '/issue:discover', args: '' },
{ cmd: '/issue:plan', args: '--all-pending' },
{ cmd: '/issue:queue', args: '' },
{ cmd: '/issue:execute', args: '' }
]
};
return chains[workflow.flow] || chains['rapid'];
}
```
**Display to user**:
```
Selected Workflow: Level [X] - [flow_name]
Pipeline:
requirement -> lite-plan -> plan -> lite-execute -> code -> test-cycle-execute -> test-passed
Commands:
1. /workflow:lite-plan
2. /workflow:lite-execute
3. /workflow:test-cycle-execute
Proceed? [Confirm / Adjust / Cancel]
```
---
### Phase 3: User Confirmation (Optional)
Get user confirmation or adjust command chain.
```javascript
async function getUserConfirmation(chain, analysis) {
const response = await AskUserQuestion({
questions: [{
question: "Execute this command chain?",
header: "Confirm",
options: [
{ label: "Confirm", description: "Start execution" },
{ label: "Adjust", description: "Modify commands" },
{ label: "Cancel", description: "Abort" }
],
multiSelect: false
}]
});
if (response.Confirm === "Cancel") {
throw new Error("User cancelled");
}
if (response.Confirm === "Adjust") {
return await adjustChain(chain);
}
return chain;
}
async function adjustChain(chain) {
// Show current chain, allow user to remove or reorder
const adjustOptions = chain.map((step, i) => ({
label: `${i + 1}. ${step.cmd}`,
description: step.args || "No arguments"
}));
const response = await AskUserQuestion({
questions: [{
question: "Select commands to keep (multi-select)",
header: "Adjust",
options: adjustOptions,
multiSelect: true
}]
});
// Rebuild chain based on user selection
return rebuildChain(chain, response);
}
```
---
### Phase 4: Setup TODO Tracking
Initialize TodoWrite to track command execution progress.
```javascript
function setupTodoTracking(chain, workflow) {
const todos = chain.map((step, i) => ({
content: `CCW:${workflow}: [${i + 1}/${chain.length}] ${step.cmd}`,
status: i === 0 ? 'in_progress' : 'pending',
activeForm: `Executing ${step.cmd}`
}));
TodoWrite({ todos });
}
```
**Display to user**:
```
TODO Tracking Initialized:
-> CCW:rapid: [1/3] /workflow:lite-plan
CCW:rapid: [2/3] /workflow:lite-execute
CCW:rapid: [3/3] /workflow:test-cycle-execute
```
---
### Phase 5: Execute Command Chain
Execute commands sequentially, update TODO status.
```javascript
async function executeCommandChain(chain, workflow, analysis) {
let previousResult = null;
for (let i = 0; i < chain.length; i++) {
const step = chain[i];
console.log(`\n[${i + 1}/${chain.length}] Executing: ${step.cmd}`);
try {
// Assemble full command
const fullCommand = assembleCommand(step, previousResult, analysis);
// Execute via SlashCommand (in main process)
const result = await SlashCommand({
command: fullCommand
});
// Record result
previousResult = {
command: step.cmd,
success: true,
output: result
};
// Update TODO status
updateTodoStatus(i, chain.length, workflow, 'completed');
console.log(`Done: ${step.cmd}`);
} catch (error) {
console.error(`Failed: ${step.cmd}: ${error.message}`);
// Ask user how to handle error
const action = await handleError(step, error, i, chain.length);
if (action === 'retry') {
i--; // Retry current step
} else if (action === 'abort') {
console.log("Workflow aborted");
return { success: false, error: error.message, completed: i };
}
// 'skip' - continue to next step
}
}
console.log("\nWorkflow completed successfully!");
return { success: true, completed: chain.length };
}
// Assemble command arguments
function assembleCommand(step, previousResult, analysis) {
let command = step.cmd;
// Dynamically assemble arguments based on command type
if (step.args) {
// Use existing arguments
command += ` ${step.args}`;
} else if (previousResult?.session_id) {
// Use previous step's session
command += ` --session="${previousResult.session_id}"`;
} else if (previousResult?.plan_exists) {
// execute command uses --resume-session
if (step.cmd.includes('execute')) {
command += ` --resume-session="${previousResult.session_id}"`;
}
}
return command;
}
// Update TODO status
function updateTodoStatus(currentIndex, total, workflow, status) {
const todos = getAllCurrentTodos(); // Get all current todos
const updatedTodos = todos.map((todo, i) => {
if (todo.content.startsWith(`CCW:${workflow}:`)) {
const stepIndex = extractStepIndex(todo.content);
if (stepIndex === currentIndex + 1) {
return { ...todo, status };
}
if (stepIndex === currentIndex + 2 && status === 'completed') {
return { ...todo, status: 'in_progress' };
}
}
return todo;
});
TodoWrite({ todos: updatedTodos });
}
// Error handling
async function handleError(step, error, index, total) {
const response = await AskUserQuestion({
questions: [{
question: `Command ${step.cmd} failed. How to proceed?`,
header: "Error",
options: [
{ label: "Retry", description: "Re-execute this command" },
{ label: "Skip", description: "Skip and continue next" },
{ label: "Abort", description: "Stop execution" }
],
multiSelect: false
}]
});
const actionMap = {
"Retry": "retry",
"Skip": "skip",
"Abort": "abort"
};
return actionMap[response.Error] || "abort";
}
```
---
## Execution Flow Summary
```
User Input
|
Phase 1: Analyze Intent
|-- Extract: goal, scope, constraints, task_type, complexity, clarity
+-- If clarity < 2 -> Phase 1.5: Clarify Requirements
|
Phase 2: Select Workflow & Build Chain
|-- Map task_type -> Level (1/2/3/4/Issue)
|-- Select flow based on complexity
+-- Build command chain (port-based)
|
Phase 3: User Confirmation (optional)
|-- Show pipeline visualization
+-- Allow adjustment
|
Phase 4: Setup TODO Tracking
+-- Create todos with CCW prefix
|
Phase 5: Execute Command Chain
|-- For each command:
| |-- Assemble full command
| |-- Execute via SlashCommand
| |-- Update TODO status
| +-- Handle errors (retry/skip/abort)
+-- Return workflow result
```
---
## Pipeline Examples
### Simple Feature (Level 2 - Rapid)
```
Input: "Add user profile API endpoint"
Analysis:
Type: feature
Complexity: low
Level: 2
Pipeline:
requirement -> lite-plan -> plan -> lite-execute -> code -> test-cycle-execute -> test-passed
Execution:
1. SlashCommand("/workflow:lite-plan \"Add user profile API endpoint\"")
2. SlashCommand("/workflow:lite-execute --in-memory")
3. SlashCommand("/workflow:test-cycle-execute")
```
### Bug Fix (Level 2 - Bugfix)
```
Input: "Fix login timeout issue"
Analysis:
Type: bugfix
Complexity: low
Level: 2
Pipeline:
bug-report -> lite-fix -> fixed-code -> test-cycle-execute -> test-passed
Execution:
1. SlashCommand("/workflow:lite-fix \"Fix login timeout issue\"")
2. SlashCommand("/workflow:test-cycle-execute")
```
### Complex Feature (Level 3 - Coupled)
```
Input: "Implement OAuth2 authentication system"
Analysis:
Type: feature
Complexity: high
Level: 3
Pipeline:
requirement -> plan -> detailed-plan -> plan-verify -> verified-plan -> execute -> code
-> review-session-cycle -> review-passed -> test-cycle-execute -> test-passed
Execution:
1. SlashCommand("/workflow:plan \"Implement OAuth2...\"")
2. SlashCommand("/workflow:plan-verify")
3. SlashCommand("/workflow:execute")
4. SlashCommand("/workflow:review-session-cycle")
5. SlashCommand("/workflow:test-cycle-execute")
```
### TDD Workflow (Level 3)
```
Input: "Implement authentication with TDD"
Analysis:
Type: tdd
Complexity: medium
Level: 3
Pipeline:
requirement -> tdd-plan -> tdd-tasks -> execute -> code -> tdd-verify -> tdd-verified
Execution:
1. SlashCommand("/workflow:tdd-plan \"Implement authentication...\"")
2. SlashCommand("/workflow:execute")
3. SlashCommand("/workflow:tdd-verify")
```
### Exploration (Level 4 - Brainstorm)
```
Input: "Uncertain about real-time notification architecture"
Analysis:
Type: exploration
Clarity: 1.5 -> needs clarification
Level: 4
Pipeline:
exploration-topic -> brainstorm:auto-parallel -> analysis -> plan -> detailed-plan
-> execute -> code -> test-cycle-execute -> test-passed
Execution:
1. SlashCommand("/workflow:brainstorm:auto-parallel \"Real-time notification...\"")
2. SlashCommand("/workflow:plan")
3. SlashCommand("/workflow:plan-verify")
4. SlashCommand("/workflow:execute")
5. SlashCommand("/workflow:test-cycle-execute")
```
---
## Key Design Principles
1. **Main Process Execution** - Use SlashCommand in main process, no external CLI
2. **Intent-Driven** - Auto-select workflow based on task intent
3. **Port-Based Chaining** - Build command chain using port matching
4. **Progressive Clarification** - Low clarity triggers clarification phase
5. **TODO Tracking** - Use CCW prefix to isolate workflow todos
6. **Error Resilient** - Support retry/skip/abort error handling
7. **User Control** - Optional user confirmation at each phase
---
## Difference from ccw-coordinator
| Aspect | ccw | ccw-coordinator |
|--------|-----|-----------------|
| **Execution** | SlashCommand (main process) | Bash + ccw cli (external) |
| **Workflow Selection** | Auto by intent | Manual chain building |
| **Intent Analysis** | 5-phase with clarity check | 3-phase requirement analysis |
| **Error Handling** | Interactive retry/skip/abort | Retry/skip/abort via AskUser |
| **State Tracking** | TodoWrite only | state.json + TodoWrite |
| **Use Case** | Auto workflow selection | Manual command orchestration |
---
## Usage
```bash
# Auto-select workflow
ccw "Add user authentication"
# Complex requirement (triggers clarification)
ccw "Optimize system performance"
# Bug fix
ccw "Fix memory leak in WebSocket handler"
# TDD development
ccw "Implement user registration with TDD"
# Exploratory task
ccw "Uncertain about architecture for real-time notifications"
```

View File

@@ -1,161 +0,0 @@
# CCW Coordinator
交互式命令编排工具:选择命令 → 形成命令链 → 通过 ccw cli 调用 Claude 循环执行
## 核心特性
-**仅支持 Claude**:所有执行通过 `ccw cli --tool claude` 调用
-**命令在提示词中**:提示词直接包含完整命令调用(如 `/workflow:lite-plan --yes "任务"`
-**智能参数组装**:根据命令 YAML 头自动生成正确参数
-**循环执行**:每次根据上次完成情况组装下个命令的提示词
## 使用
```
/ccw-coordinator
/coordinator
```
## 流程
1. **用户描述任务**(如"实现用户注册功能"
2. **Claude 推荐命令链**(如 lite-plan → lite-execute → test-cycle-execute
3. **用户确认或调整**(可以修改顺序或添加/删除命令)
4. **循环执行**
- 第1个命令`ccw cli -p "任务: xxx\n/workflow:lite-plan --yes \"xxx\"" --tool claude`
- 第2个命令`ccw cli -p "任务: xxx\n前序: ...\n/workflow:lite-execute --yes --in-memory" --tool claude`
- ... 以此类推
5. **生成报告**(保存到 `.workflow/.ccw-coordinator/{timestamp}/`
## 示例场景
### 标准开发流程
**任务**:实现用户注册功能
**推荐命令链**
```
1. /workflow:lite-plan
2. /workflow:lite-execute
3. /workflow:test-cycle-execute
```
**执行过程**
- `lite-plan` → 生成 IMPL_PLAN.md 和探索文件
- `lite-execute --in-memory` → 使用规划执行任务
- `test-cycle-execute --session="WFS-xxx"` → 运行测试
### Bug 修复
**任务**:修复登录页面验证失败问题
**推荐命令链**
```
1. /workflow:lite-fix
```
**执行过程**
- `lite-fix --yes "修复登录页面验证失败问题"` → 独立修复(不依赖规划)
### 完整规划流程
**任务**:重构认证模块
**推荐命令链**
```
1. /workflow:plan
2. /workflow:execute
3. /workflow:review-session-cycle
```
**执行过程**
- `plan` → 生成完整规划文档
- `execute --resume-session="WFS-xxx"` → 执行规划
- `review-session-cycle --session="WFS-xxx"` → 审查改动
## 提示词示例
### 第一个命令
```
任务: 实现用户注册功能,包括邮箱验证和密码加密
/workflow:lite-plan --yes "实现用户注册功能,包括邮箱验证和密码加密"
```
### 第二个命令
```
任务: 实现用户注册功能,包括邮箱验证和密码加密
前序完成:
- /workflow:lite-plan: WFS-register-2025-01-24 (IMPL_PLAN.md, exploration-architecture.json)
/workflow:lite-execute --yes --in-memory
```
### 第三个命令
```
任务: 实现用户注册功能,包括邮箱验证和密码加密
前序完成:
- /workflow:lite-plan: WFS-register-2025-01-24 (IMPL_PLAN.md)
- /workflow:lite-execute: WFS-register-2025-01-24 (完成)
/workflow:test-cycle-execute --yes --session="WFS-register-2025-01-24"
```
## 架构说明
```
用户触发: /ccw-coordinator
Orchestrator (主流程状态机)
├─ action-init (初始化会话)
├─ action-command-selection (选择命令Claude 推荐)
├─ action-command-build (调整命令链,可选)
├─ action-command-execute (循环调用 ccw cli)
│ └─ for each command:
│ 1. 组装提示词
│ 2. ccw cli --tool claude
│ 3. 解析产物
│ 4. 更新状态
└─ action-complete (生成报告)
```
## 输出结构
```
.workflow/.ccw-coordinator/{timestamp}/
├── state.json # 会话状态(命令链、执行结果)
├── command-chain.json # 编排的完整命令链
├── execution-log.md # 执行日志
├── final-summary.md # 最终报告
├── commands/ # 各命令执行详情
│ ├── 01-workflow-lite-plan.log
│ ├── 02-workflow-lite-execute.log
│ └── 03-workflow-test-cycle-execute.log
└── logs/ # 错误和警告
├── errors.log
└── warnings.log
```
## 文件说明
| 文件 | 用途 |
|------|------|
| SKILL.md | Skill 入口和架构说明 |
| phases/orchestrator.md | 编排器实现(状态机决策逻辑) |
| phases/state-schema.md | 状态结构定义 |
| phases/actions/action-command-execute.md | **核心**:循环执行逻辑 |
| specs/specs.md | 命令库、验证规则、注册表 |
| tools/chain-validate.cjs | 命令链验证工具 |
| tools/command-registry.cjs | 命令注册表(按需提取 YAML 头) |
## 详细文档
- 架构和设计原则 → **SKILL.md**
- 执行逻辑和提示词组装 → **phases/actions/action-command-execute.md**
- 命令库和验证规则 → **specs/specs.md**

View File

@@ -1,411 +0,0 @@
---
name: ccw-coordinator
description: Interactive command orchestration tool for building and executing Claude CLI command chains. Triggers on "coordinator", "ccw-coordinator", "命令编排", "command chain", "orchestrate commands", "编排CLI命令".
allowed-tools: Task, AskUserQuestion, Read, Write, Bash, Glob, Grep
---
# CCW Coordinator
交互式命令编排工具:允许用户依次选择命令,形成命令链,然后通过 ccw cli 调用 Claude 循环执行每个命令。
**核心特性**
- **保持为 Skill**:用户通过 `/ccw-coordinator` 触发
- **仅支持 Claude**:所有执行通过 `ccw cli --tool claude` 调用
- **命令在提示词中体现**:提示词直接包含完整命令调用(如 `/workflow:lite-plan --yes "任务"`
- **智能参数组装**:根据命令 YAML 头的 `argument-hint` 组装正确参数
- **循环执行**:每次根据上次完成情况和下个命令参数动态组装提示词
## Architecture Overview
```
用户: /ccw-coordinator
┌─────────────────────────────────────────────────────────────────┐
│ Orchestrator (主流程状态机) │
│ 直接在 Claude Code 主流程中运行 │
└───────────────┬─────────────────────────────────────────────────┘
┌───────────┼───────────┬───────────────┐
↓ ↓ ↓ ↓
┌─────────┐ ┌──────────────┐ ┌────────────┐ ┌──────────┐
│ Init │ │ Command │ │ Command │ │ Execute │ ← 核心
│ │ │ Selection │ │ Build │ │ │
│ 初始化 │ │ 选择命令 │ │ 编排调整 │ │ 循环调用 │
│ 会话 │ │ 推荐确认 │ │ (可选) │ │ ccw cli │
└─────────┘ └──────────────┘ └────────────┘ └────┬─────┘
│ │ │ │
└───────────────┼──────────────┴──────────────┘
│ │
↓ │
┌──────────────┐ │
│ Complete │ │
│ 生成报告 │ │
└──────────────┘ │
┌──────────────────────────────┘
│ 循环执行每个命令
┌───────────────────────────────────────┐
│ action-command-execute │
│ for each command in chain: │
│ 1. 组装提示词 │
│ 2. 调用 ccw cli --tool claude │
│ 3. 解析产物 │
│ 4. 更新状态 │
└───────────────────┬───────────────────┘
┌───────────────────────────────┐
│ ccw cli -p " │
│ 任务: xxx │
│ 前序: /workflow:lite-plan │
│ /workflow:lite-execute ..." │
│ --tool claude --mode write │
└───────────────┬───────────────┘
┌───────────────┐
│ Claude 执行 │
│ workflow 命令 │
└───────────────┘
```
## Key Design Principles
1. **智能推荐**Claude 根据用户任务描述自动推荐最优命令链
2. **交互式编排**:用户通过交互界面选择和编排命令,实时反馈推荐
3. **状态持久化**:会话状态保存到 `state.json`,支持中途暂停和恢复
4. **仅支持 Claude**:所有执行通过 `ccw cli --tool claude` 调用
5. **命令在提示词中**:提示词直接包含完整命令调用,不是告诉 Claude 去执行什么
6. **智能参数组装**:根据命令的 YAML 头 `argument-hint` 动态生成参数
7. **循环执行**:每个命令执行后立即更新状态,根据产物组装下个命令的提示词
8. **自动确认**:所有命令自动添加 `-y` 参数,跳过交互式确认
9. **产物追踪**:自动提取会话 ID 和产物文件,用于后续命令链接
## Intelligent Prompt Generation
执行命令时,系统智能生成 `ccw cli -p` 提示词。
### 核心原则
**提示词直接包含完整命令调用**,而不是告诉 Claude 去执行什么:
```
✅ 正确:
任务: 实现用户注册
/workflow:lite-plan --yes "实现用户注册"
❌ 错误:
任务: 实现用户注册
命令: /workflow:lite-plan
参数格式: [--yes] "task"
执行要求: 请执行 lite-plan 命令
```
### 提示词构成
```javascript
// 集成命令注册表(按需提取)
const registry = new CommandRegistry();
const commandMeta = registry.getCommands(commandNames);
function generatePrompt(cmd, state, commandMeta) {
// 1. 任务描述
let prompt = `任务: ${state.task_description}\n`;
// 2. 前序完成情况
if (state.execution_results.length > 0) {
const previousOutputs = state.execution_results
.filter(r => r.status === 'success')
.map(r => {
if (r.summary?.session) {
return `- ${r.command}: ${r.summary.session} (${r.summary.files?.join(', ')})`;
}
return `- ${r.command}: 已完成`;
})
.join('\n');
prompt += `\n前序完成:\n${previousOutputs}\n`;
}
// 3. 组装完整命令行(关键)
const commandLine = assembleCommandLine(cmd, state, commandMeta);
prompt += `\n${commandLine}`;
return prompt;
}
// 根据 argument-hint 智能组装参数
function assembleCommandLine(cmd, state, commandMeta) {
let commandLine = cmd.command; // /workflow:lite-plan
// 添加 --yes 标志
commandLine += ' --yes';
// 根据命令类型添加特定参数
const cmdName = cmd.command.split(':').pop();
if (cmdName === 'lite-plan') {
commandLine += ` "${state.task_description}"`;
} else if (cmdName === 'lite-execute') {
// 如果有前序规划,使用 --in-memory
if (state.execution_results.some(r => r.command.includes('plan'))) {
commandLine += ' --in-memory';
} else {
commandLine += ` "${state.task_description}"`;
}
}
// ... 其他命令类型
return commandLine;
}
```
### 产物追踪
每个命令执行后自动提取关键产物:
```javascript
{
command: "/workflow:lite-plan",
status: "success",
output: "...",
summary: {
session: "WFS-plan-20250123", // 会话ID
files: [".workflow/IMPL_PLAN.md"], // 产物文件
timestamp: "2025-01-23T10:30:00Z"
}
}
```
### 命令调用示例
**第一个命令lite-plan**
```bash
ccw cli -p "任务: 实现用户认证功能
/workflow:lite-plan --yes \"实现用户认证功能\"" --tool claude --mode write -y
```
**第二个命令lite-execute**
```bash
ccw cli -p "任务: 实现用户认证功能
前序完成:
- /workflow:lite-plan: WFS-auth-2025-01-24 (IMPL_PLAN.md, exploration-architecture.json)
/workflow:lite-execute --yes --in-memory" --tool claude --mode write -y
```
**第三个命令test-cycle-execute**
```bash
ccw cli -p "任务: 实现用户认证功能
前序完成:
- /workflow:lite-plan: WFS-auth-2025-01-24 (IMPL_PLAN.md)
- /workflow:lite-execute: WFS-auth-2025-01-24 (完成)
/workflow:test-cycle-execute --yes --session=\"WFS-auth-2025-01-24\"" --tool claude --mode write -y
```
### 命令注册表集成
- **位置**: `tools/command-registry.js` (skill 内置)
- **工作模式**: 按需提取(只提取用户任务链中的命令)
- **功能**: 自动查找全局 `.claude/commands/workflow` 目录,解析命令 YAML 头元数据
- **作用**: 确保提示词包含准确的命令参数和上下文
详见 `tools/README.md`
---
## Execution Flow
### Orchestrator Execution Loop
```javascript
1. 初始化会话
2. 循环执行直到完成
读取当前状态
选择下一个动作根据状态和用户意图
执行动作更新状态
检查终止条件
3. 生成最终报告
```
### Action Sequence (Typical)
```
action-init
↓ (status: pending → running)
action-command-selection (可重复)
↓ (添加命令到链)
action-command-build (可选)
↓ (调整命令顺序)
action-command-execute
↓ (依次执行所有命令)
action-complete
↓ (status: running → completed)
```
## State Management
### Initial State
```json
{
"status": "pending",
"task_description": "",
"command_chain": [],
"confirmed": false,
"error_count": 0,
"execution_results": [],
"current_command_index": 0,
"started_at": null
}
```
### State Transitions
```
pending → running (init) → running → completed (execute)
aborted (error or user exit)
```
## Directory Setup
```javascript
const timestamp = new Date().toISOString().slice(0,19).replace(/[-:T]/g, '');
const workDir = `.workflow/.ccw-coordinator/${timestamp}`;
Bash(`mkdir -p "${workDir}"`);
Bash(`mkdir -p "${workDir}/commands"`);
Bash(`mkdir -p "${workDir}/logs"`);
```
## Output Structure
```
.workflow/.ccw-coordinator/{timestamp}/
├── state.json # 当前会话状态
├── command-chain.json # 编排的完整命令链
├── execution-log.md # 执行日志
├── final-summary.md # 最终报告
├── commands/ # 各命令执行详情
│ ├── 01-command.log
│ ├── 02-command.log
│ └── ...
└── logs/ # 错误和警告日志
├── errors.log
└── warnings.log
```
## Reference Documents
| Document | Purpose |
|----------|---------|
| [phases/orchestrator.md](phases/orchestrator.md) | 编排器实现 |
| [phases/state-schema.md](phases/state-schema.md) | 状态结构定义 |
| [phases/actions/action-init.md](phases/actions/action-init.md) | 初始化动作 |
| [phases/actions/action-command-selection.md](phases/actions/action-command-selection.md) | 命令选择动作 |
| [phases/actions/action-command-build.md](phases/actions/action-command-build.md) | 命令编排动作 |
| [phases/actions/action-command-execute.md](phases/actions/action-command-execute.md) | 命令执行动作 |
| [phases/actions/action-complete.md](phases/actions/action-complete.md) | 完成动作 |
| [phases/actions/action-abort.md](phases/actions/action-abort.md) | 中止动作 |
| [specs/specs.md](specs/specs.md) | 命令库、验证规则、注册表 |
| [tools/chain-validate.cjs](tools/chain-validate.cjs) | 验证工具 |
| [tools/command-registry.cjs](tools/command-registry.cjs) | 命令注册表工具 |
---
## Usage Examples
### 快速命令链
用户想要执行:规划 → 执行 → 测试
```
1. 触发 /ccw-coordinator
2. 描述任务:"实现用户注册功能"
3. Claude推荐: plan → execute → test-cycle-execute
4. 用户确认
5. 执行命令链
```
### 复杂工作流
用户想要执行:规划 → 执行 → 审查 → 修复
```
1. 触发 /ccw-coordinator
2. 描述任务:"重构认证模块"
3. Claude推荐: plan → execute → review-session-cycle → review-fix
4. 用户可调整命令顺序
5. 确认执行
6. 实时查看执行进度
```
### 紧急修复
用户想要快速修复bug
```
1. 触发 /ccw-coordinator
2. 描述任务:"修复生产环境登录bug"
3. Claude推荐: lite-fix --hotfix → test-cycle-execute
4. 用户确认
5. 快速执行修复
```
## Constraints and Rules
### 1. 命令推荐约束
- **智能推荐优先**: 必须先基于用户任务描述进行智能推荐,而非直接展示命令库
- **不使用静态映射**: 禁止使用查表或硬编码的推荐逻辑(如 `if task=bug则推荐lite-fix`
- **推荐必须说明理由**: Claude 推荐命令链时必须解释为什么这样推荐
- **用户保留选择权**: 推荐后,用户可选择:使用推荐/调整/手动选择
### 2. 验证约束
- **执行前必须验证**: 使用 `chain-validate.js` 验证命令链合法性
- **不合法必须提示**: 如果验证失败,必须明确告知用户错误原因和修复方法
- **允许用户覆盖**: 验证失败时,询问用户是否仍要执行(警告模式)
### 3. 执行约束
- **顺序执行**: 命令必须严格按照 command_chain 中的 order 顺序执行
- **错误处理**: 单个命令失败时,询问用户:重试/跳过/中止
- **错误上限**: 连续 3 次错误自动中止会话
- **实时反馈**: 每个命令执行时显示进度(如 `[2/5] 执行: lite-execute`
### 4. 状态管理约束
- **状态持久化**: 每次状态更新必须立即写入磁盘
- **单一数据源**: 状态只保存在 `state.json`,禁止多个状态文件
- **原子操作**: 状态更新必须使用 read-modify-write 模式,避免并发冲突
### 5. 用户体验约束
- **最小交互**: 默认使用智能推荐 + 一次确认,避免多次询问
- **清晰输出**: 每个步骤输出必须包含:当前状态、可用选项、建议操作
- **可恢复性**: 会话中断后,用户可从上次状态恢复
### 6. 禁止行为
-**禁止跳过推荐步骤**: 不能直接进入手动选择,必须先尝试推荐
-**禁止静态推荐**: 不能使用 recommended-chains.json 查表
-**禁止无验证执行**: 不能跳过链条验证直接执行
-**禁止静默失败**: 错误必须明确报告,不能静默跳过
## Notes
- 编排器使用状态机模式,确保执行流程的可靠性
- 所有命令链和执行结果都被持久化保存,支持后续查询和调试
- 支持用户中途修改命令链(在执行前)
- 执行错误会自动记录,支持重试机制
- Claude 智能推荐基于任务分析,非查表静态推荐

View File

@@ -1,9 +0,0 @@
# action-abort
中止会话,保存状态
```javascript
updateState({ status: 'aborted' });
console.log(`会话已中止: ${workDir}`);
```

View File

@@ -1,40 +0,0 @@
# action-command-build
调整命令链顺序或删除命令
## 流程
1. 显示当前命令链
2. 让用户调整(重新排序、删除)
3. 确认执行
## 伪代码
```javascript
// 显示链
console.log('命令链:');
state.command_chain.forEach((cmd, i) => {
console.log(`${i+1}. ${cmd.command}`);
});
// 询问用户
const action = await AskUserQuestion({
options: [
'继续执行',
'删除命令',
'重新排序',
'返回选择'
]
});
// 处理用户操作
if (action === '继续执行') {
updateState({confirmed: true, status: 'executing'});
}
// ... 其他操作
```
## 状态更新
- command_chain (可能修改)
- confirmed = true 时状态转为 executing

View File

@@ -1,349 +0,0 @@
# action-command-execute
循环执行命令链,通过 ccw cli 调用 Claude 执行每个命令。
## 核心原则
1. **仅支持 Claude**:所有执行通过 `ccw cli --tool claude` 调用
2. **命令在提示词中体现**:提示词直接包含完整的命令调用(如 `/workflow:lite-plan --yes "任务"`
3. **智能参数组装**:根据命令的 `argument-hint` 组装正确的参数
4. **循环执行**:每次根据上次完成情况和下个命令参数组装提示词
## 命令注册表集成
```javascript
// 从 ./tools/command-registry.cjs 按需提取命令元数据
const CommandRegistry = require('./tools/command-registry.cjs');
const registry = new CommandRegistry();
// 只提取当前任务链中的命令
const commandNames = command_chain.map(cmd => cmd.command);
const commandMeta = registry.getCommands(commandNames);
```
## 参数组装逻辑
根据命令的 `argument-hint` 和执行上下文,智能组装命令行参数:
```javascript
function assembleCommandLine(cmd, state, commandMeta) {
const cmdInfo = commandMeta[cmd.command];
const { task_description, execution_results } = state;
let commandLine = cmd.command; // e.g., /workflow:lite-plan
// 1. 添加 --yes 标志(跳过确认)
commandLine += ' --yes';
// 2. 根据命令类型添加特定参数
const cmdName = cmd.command.split(':').pop(); // lite-plan, lite-execute, etc.
switch (cmdName) {
case 'lite-plan':
case 'plan':
case 'multi-cli-plan':
case 'tdd-plan':
// 规划命令:需要任务描述
commandLine += ` "${task_description}"`;
break;
case 'lite-execute':
// 执行命令:如果有前序规划产物,使用 --in-memory
if (execution_results.some(r =>
r.command.includes('plan') && r.status === 'success'
)) {
commandLine += ' --in-memory';
} else {
commandLine += ` "${task_description}"`;
}
break;
case 'execute':
// 标准执行:可能需要 --resume-session
const planResult = execution_results.find(r =>
r.command.includes('plan') && r.status === 'success'
);
if (planResult?.summary?.session) {
commandLine += ` --resume-session="${planResult.summary.session}"`;
}
break;
case 'lite-fix':
// 修复命令:如果有 hotfix 标志
if (cmd.hotfix) {
commandLine += ' --hotfix';
}
commandLine += ` "${task_description}"`;
break;
case 'test-cycle-execute':
case 'test-gen':
case 'test-fix-gen':
// 测试命令:使用前序会话
const execResult = execution_results.find(r =>
(r.command.includes('execute') || r.command.includes('fix')) &&
r.status === 'success'
);
if (execResult?.summary?.session) {
commandLine += ` --session="${execResult.summary.session}"`;
}
break;
case 'review-session-cycle':
case 'review-module-cycle':
case 'review-fix':
// 审查命令:使用前序会话
const prevSession = execution_results
.filter(r => r.status === 'success' && r.summary?.session)
.pop()?.summary?.session;
if (prevSession) {
commandLine += ` --session="${prevSession}"`;
}
break;
default:
// 其他命令:尝试传递任务描述
if (cmdInfo?.argumentHint?.includes('task') ||
cmdInfo?.argumentHint?.includes('description')) {
commandLine += ` "${task_description}"`;
}
}
// 3. 添加用户自定义参数(如果有)
if (cmd.customArgs) {
commandLine += ` ${cmd.customArgs}`;
}
return commandLine;
}
```
## 提示词生成
提示词结构:任务描述 + 前序完成 + 完整命令行
```javascript
function generatePrompt(cmd, state, commandMeta) {
const { task_description, execution_results } = state;
// 1. 任务描述
let prompt = `任务: ${task_description}\n`;
// 2. 前序完成情况
const successResults = execution_results.filter(r => r.status === 'success');
if (successResults.length > 0) {
const previousOutputs = successResults
.map(r => {
const summary = r.summary;
if (summary?.session) {
const files = summary.files?.length > 0
? summary.files.join(', ')
: '完成';
return `- ${r.command}: ${summary.session} (${files})`;
}
return `- ${r.command}: 已完成`;
})
.join('\n');
prompt += `\n前序完成:\n${previousOutputs}\n`;
}
// 3. 组装完整命令行(关键)
const commandLine = assembleCommandLine(cmd, state, commandMeta);
prompt += `\n${commandLine}`;
return prompt;
}
```
### 提示词示例
**第一个命令lite-plan**
```
任务: 实现用户注册功能,包括邮箱验证和密码加密
/workflow:lite-plan --yes "实现用户注册功能,包括邮箱验证和密码加密"
```
**第二个命令lite-execute**
```
任务: 实现用户注册功能,包括邮箱验证和密码加密
前序完成:
- /workflow:lite-plan: WFS-register-2025-01-24 (IMPL_PLAN.md, exploration-architecture.json)
/workflow:lite-execute --yes --in-memory
```
**第三个命令test-cycle-execute**
```
任务: 实现用户注册功能,包括邮箱验证和密码加密
前序完成:
- /workflow:lite-plan: WFS-register-2025-01-24 (IMPL_PLAN.md)
- /workflow:lite-execute: WFS-register-2025-01-24 (完成)
/workflow:test-cycle-execute --yes --session="WFS-register-2025-01-24"
```
## 执行逻辑
```javascript
for (let i = current_command_index; i < command_chain.length; i++) {
const cmd = command_chain[i];
console.log(`[${i+1}/${command_chain.length}] 执行: ${cmd.command}`);
// 1. 生成智能提示词
const prompt = generatePrompt(cmd, state, commandMeta);
// 2. 转义提示词中的特殊字符
const escapedPrompt = prompt
.replace(/\\/g, '\\\\')
.replace(/"/g, '\\"')
.replace(/\n/g, '\\n');
try {
// 3. 调用 ccw cli仅支持 claude
const result = Bash(`ccw cli -p "${escapedPrompt}" --tool claude --mode write -y`, {
run_in_background: true
});
// 4. 等待执行完成(通过 hook 回调)
// ... 等待逻辑由调用者处理
// 5. 解析输出,提取产物
const summary = extractSummary(result.stdout);
// 6. 记录执行结果
execution_results.push({
command: cmd.command,
status: result.exit_code === 0 ? 'success' : 'failed',
exit_code: result.exit_code,
output: result.stdout,
summary: summary
});
// 7. 更新命令状态
command_chain[i].status = 'completed';
current_command_index = i + 1;
} catch (error) {
error_count++;
command_chain[i].status = 'failed';
// 错误上限检查
if (error_count >= 3) {
console.log('连续错误超过3次中止执行');
break;
}
// 用户决策
const action = await AskUserQuestion({
questions: [{
question: `命令 ${cmd.command} 执行失败,如何处理?`,
header: "Error",
multiSelect: false,
options: [
{ label: "重试", description: "重新执行此命令" },
{ label: "跳过", description: "跳过此命令,继续下一个" },
{ label: "中止", description: "终止整个命令链" }
]
}]
});
if (action.answers['Error'] === '重试') i--;
if (action.answers['Error'] === '中止') break;
}
// 8. 持久化状态
updateState({
command_chain,
execution_results,
current_command_index,
error_count
});
}
```
## 产物提取
```javascript
function extractSummary(output) {
// 从 ccw cli 输出提取关键产物信息
// 1. 提取会话 ID (WFS-* 或其他格式)
const sessionMatch = output.match(/WFS-[\w-]+/);
// 2. 提取产物文件路径
const fileMatches = output.match(/\.workflow\/[^\s\n\r"']+/g);
// 3. 提取完成状态
const isSuccess = /✓|completed|success|完成/i.test(output);
return {
session: sessionMatch?.[0] || null,
files: fileMatches ? [...new Set(fileMatches)] : [], // 去重
status: isSuccess ? 'success' : 'unknown',
timestamp: new Date().toISOString()
};
}
```
## 状态更新
每次命令执行后立即更新 `state.json`
```javascript
function updateState(updates) {
const statePath = `${workDir}/state.json`;
const currentState = JSON.parse(Read(statePath));
const newState = {
...currentState,
...updates,
updated_at: new Date().toISOString()
};
Write(statePath, JSON.stringify(newState, null, 2));
}
```
### 更新字段
| 字段 | 说明 |
|------|------|
| `execution_results` | 每个命令的执行结果(含 summary 产物信息) |
| `command_chain[].status` | 各命令状态pending/in_progress/completed/failed |
| `current_command_index` | 当前执行到的命令索引 |
| `error_count` | 连续错误计数 |
## 日志记录
每个命令执行详情保存到独立日志:
```javascript
function logCommandExecution(index, cmd, result, workDir) {
const logPath = `${workDir}/commands/${String(index + 1).padStart(2, '0')}-${cmd.command.replace(/[/:]/g, '-')}.log`;
const logContent = `
# Command Execution Log
Command: ${cmd.command}
Status: ${result.status}
Exit Code: ${result.exit_code}
Timestamp: ${new Date().toISOString()}
## Prompt
${result.prompt}
## Output
${result.output}
## Summary
Session: ${result.summary?.session || 'N/A'}
Files: ${result.summary?.files?.join(', ') || 'N/A'}
`;
Write(logPath, logContent);
}
```

View File

@@ -1,48 +0,0 @@
# action-command-selection
## 流程
1. 问用户任务
2. Claude推荐命令链
3. 用户确认/手动选择
4. 添加到command_chain
## 伪代码
```javascript
// 1. 获取用户任务描述
const taskInput = await AskUserQuestion({
question: '请描述您的任务',
options: [
{ label: '手动选择命令', value: 'manual' }
]
});
// 保存任务描述到状态
updateState({ task_description: taskInput.text || taskInput.value });
// 2. 若用户描述任务Claude推荐
if (taskInput.text) {
console.log('推荐: ', recommendChain(taskInput.text));
const confirm = await AskUserQuestion({
question: '是否使用推荐链?',
options: ['使用推荐', '调整', '手动选择']
});
if (confirm === '使用推荐') {
addCommandsToChain(recommendedChain);
updateState({ confirmed: true });
return;
}
}
// 3. 手动选择
const commands = loadCommandLibrary();
const selected = await AskUserQuestion(commands);
addToChain(selected);
```
## 状态更新
- task_description = 用户任务描述
- command_chain.push(newCommand)
- 如果用户确认: confirmed = true

View File

@@ -1,25 +0,0 @@
# action-complete
生成执行报告
```javascript
const success = execution_results.filter(r => r.status === 'success').length;
const failed = execution_results.filter(r => r.status === 'failed').length;
const duration = Date.now() - new Date(started_at).getTime();
const report = `
# 执行报告
- 会话: ${session_id}
- 耗时: ${Math.round(duration/1000)}s
- 成功: ${success}
- 失败: ${failed}
## 命令详情
${command_chain.map((c, i) => `${i+1}. ${c.command} - ${c.status}`).join('\n')}
`;
Write(`${workDir}/final-report.md`, report);
updateState({ status: 'completed' });
```

View File

@@ -1,26 +0,0 @@
# action-init
初始化编排会话
```javascript
const timestamp = Date.now();
const workDir = `.workflow/.ccw-coordinator/${timestamp}`;
Bash(`mkdir -p "${workDir}"`);
const state = {
session_id: `coord-${timestamp}`,
status: 'running',
started_at: new Date().toISOString(),
task_description: '',
command_chain: [],
current_command_index: 0,
execution_results: [],
confirmed: false,
error_count: 0
};
Write(`${workDir}/state.json`, JSON.stringify(state, null, 2));
console.log(`会话已初始化: ${workDir}`);
```

View File

@@ -1,59 +0,0 @@
# Orchestrator
状态驱动编排:读状态 → 选动作 → 执行 → 更新状态
## 决策逻辑
```javascript
function selectNextAction(state) {
if (['completed', 'aborted'].includes(state.status)) return null;
if (state.error_count >= 3) return 'action-abort';
switch (state.status) {
case 'pending':
return 'action-init';
case 'running':
return state.confirmed && state.command_chain.length > 0
? 'action-command-execute'
: 'action-command-selection';
case 'executing':
const pending = state.command_chain.filter(c => c.status === 'pending');
return pending.length === 0 ? 'action-complete' : 'action-command-execute';
default:
return 'action-abort';
}
}
```
## 执行循环
```javascript
const timestamp = Date.now();
const workDir = `.workflow/.ccw-coordinator/${timestamp}`;
Bash(`mkdir -p "${workDir}"`);
const state = {
session_id: `coord-${timestamp}`,
status: 'pending',
started_at: new Date().toISOString(),
task_description: '', // 从 action-command-selection 获取
command_chain: [],
current_command_index: 0,
execution_results: [],
confirmed: false,
error_count: 0
};
Write(`${workDir}/state.json`, JSON.stringify(state, null, 2));
let iterations = 0;
while (iterations < 50) {
const state = JSON.parse(Read(`${workDir}/state.json`));
const nextAction = selectNextAction(state);
if (!nextAction) break;
console.log(`[${nextAction}]`);
// 执行 phases/actions/{nextAction}.md
iterations++;
}
```

View File

@@ -1,66 +0,0 @@
# State Schema
```typescript
interface State {
session_id: string;
status: 'pending' | 'running' | 'executing' | 'completed' | 'aborted';
started_at: string;
task_description: string; // 用户任务描述
command_chain: Command[];
current_command_index: number;
execution_results: ExecutionResult[];
confirmed: boolean;
error_count: number;
}
interface Command {
id: string;
order: number;
command: string;
status: 'pending' | 'running' | 'completed' | 'failed';
result?: ExecutionResult;
}
interface ExecutionResult {
command: string;
status: 'success' | 'failed';
exit_code: number;
output?: string;
summary?: { // 提取的关键产物
session?: string;
files?: string[];
timestamp: string;
};
}
```
## 状态转移
```
pending → running → executing → completed
↓ ↓
(abort) (error → abort)
```
## 初始化
```javascript
{
session_id: generateId(),
status: 'pending',
started_at: new Date().toISOString(),
task_description: '', // 从用户输入获取
command_chain: [],
current_command_index: 0,
execution_results: [],
confirmed: false,
error_count: 0
}
```
## 更新
- 添加命令: `command_chain.push(cmd)`
- 确认执行: `confirmed = true, status = 'executing'`
- 记录执行: `execution_results.push(...), current_command_index++`
- 错误计数: `error_count++`

View File

@@ -1,66 +0,0 @@
{
"skill_name": "ccw-coordinator",
"display_name": "CCW Coordinator",
"description": "Interactive command orchestration - select, build, and execute workflow command chains",
"execution_mode": "autonomous",
"version": "1.0.0",
"triggers": [
"coordinator",
"ccw-coordinator",
"命令编排",
"command chain"
],
"allowed_tools": [
"Task",
"AskUserQuestion",
"Read",
"Write",
"Bash"
],
"actions": [
{
"id": "action-init",
"name": "Init",
"description": "Initialize orchestration session"
},
{
"id": "action-command-selection",
"name": "Select Commands",
"description": "Interactive command selection from library"
},
{
"id": "action-command-build",
"name": "Build Chain",
"description": "Adjust and confirm command chain"
},
{
"id": "action-command-execute",
"name": "Execute",
"description": "Execute command chain sequentially"
},
{
"id": "action-complete",
"name": "Complete",
"description": "Generate final report"
},
{
"id": "action-abort",
"name": "Abort",
"description": "Abort session and save state"
}
],
"termination_conditions": [
"user_exit",
"task_completed",
"error"
],
"output": {
"location": ".workflow/.ccw-coordinator/{timestamp}",
"artifacts": [
"state.json",
"command-chain.json",
"execution-log.md",
"final-report.md"
]
}
}

View File

@@ -1,169 +0,0 @@
# Command Library
CCW Coordinator 支持的命令库。基于 CCW workflow 命令系统。
## Command Categories
### Planning Commands
| Command | Description | Level |
|---------|-------------|-------|
| `/workflow:lite-plan` | 轻量级规划 | L2 |
| `/workflow:plan` | 标准规划 | L3 |
| `/workflow:multi-cli-plan` | 多CLI协作规划 | L2 |
| `/workflow:brainstorm:auto-parallel` | 头脑风暴规划 | L4 |
| `/workflow:tdd-plan` | TDD规划 | L3 |
### Execution Commands
| Command | Description | Level |
|---------|-------------|-------|
| `/workflow:lite-execute` | 轻量级执行 | L2 |
| `/workflow:execute` | 标准执行 | L3 |
| `/workflow:test-cycle-execute` | 测试循环执行 | L3 |
### BugFix Commands
| Command | Description | Level |
|---------|-------------|-------|
| `/workflow:lite-fix` | 轻量级修复 | L2 |
| `/workflow:lite-fix --hotfix` | 紧急修复 | L2 |
### Testing Commands
| Command | Description | Level |
|---------|-------------|-------|
| `/workflow:test-gen` | 测试生成 | L3 |
| `/workflow:test-fix-gen` | 测试修复生成 | L3 |
| `/workflow:tdd-verify` | TDD验证 | L3 |
### Review Commands
| Command | Description | Level |
|---------|-------------|-------|
| `/workflow:review-session-cycle` | 会话审查 | L3 |
| `/workflow:review-module-cycle` | 模块审查 | L3 |
| `/workflow:review-fix` | 审查修复 | L3 |
| `/workflow:plan-verify` | 计划验证 | L3 |
### Documentation Commands
| Command | Description | Level |
|---------|-------------|-------|
| `/memory:docs` | 生成文档 | L2 |
| `/memory:update-related` | 更新相关文档 | L2 |
| `/memory:update-full` | 全面更新文档 | L2 |
### Issue Commands
| Command | Description | Level |
|---------|-------------|-------|
| `/issue:discover` | 发现Issue | Supplementary |
| `/issue:discover-by-prompt` | 基于提示发现Issue | Supplementary |
| `/issue:plan --all-pending` | 规划所有待处理Issue | Supplementary |
| `/issue:queue` | 排队Issue | Supplementary |
| `/issue:execute` | 执行Issue | Supplementary |
## Command Chains (Recommended)
### 标准开发流程
```
1. /workflow:lite-plan
2. /workflow:lite-execute
3. /workflow:test-cycle-execute
```
### 完整规划流程
```
1. /workflow:plan
2. /workflow:plan-verify
3. /workflow:execute
4. /workflow:review-session-cycle
```
### TDD 流程
```
1. /workflow:tdd-plan
2. /workflow:execute
3. /workflow:tdd-verify
```
### Issue 批处理流程
```
1. /issue:plan --all-pending
2. /issue:queue
3. /issue:execute
```
## JSON Format
```json
{
"workflow_commands": [
{
"category": "Planning",
"commands": [
{ "name": "/workflow:lite-plan", "description": "轻量级规划" },
{ "name": "/workflow:plan", "description": "标准规划" },
{ "name": "/workflow:multi-cli-plan", "description": "多CLI协作规划" },
{ "name": "/workflow:brainstorm:auto-parallel", "description": "头脑风暴" },
{ "name": "/workflow:tdd-plan", "description": "TDD规划" }
]
},
{
"category": "Execution",
"commands": [
{ "name": "/workflow:lite-execute", "description": "轻量级执行" },
{ "name": "/workflow:execute", "description": "标准执行" },
{ "name": "/workflow:test-cycle-execute", "description": "测试循环执行" }
]
},
{
"category": "BugFix",
"commands": [
{ "name": "/workflow:lite-fix", "description": "轻量级修复" },
{ "name": "/workflow:lite-fix --hotfix", "description": "紧急修复" }
]
},
{
"category": "Testing",
"commands": [
{ "name": "/workflow:test-gen", "description": "测试生成" },
{ "name": "/workflow:test-fix-gen", "description": "测试修复" },
{ "name": "/workflow:tdd-verify", "description": "TDD验证" }
]
},
{
"category": "Review",
"commands": [
{ "name": "/workflow:review-session-cycle", "description": "会话审查" },
{ "name": "/workflow:review-module-cycle", "description": "模块审查" },
{ "name": "/workflow:review-fix", "description": "审查修复" },
{ "name": "/workflow:plan-verify", "description": "计划验证" }
]
},
{
"category": "Documentation",
"commands": [
{ "name": "/memory:docs", "description": "生成文档" },
{ "name": "/memory:update-related", "description": "更新相关文档" },
{ "name": "/memory:update-full", "description": "全面更新文档" }
]
},
{
"category": "Issues",
"commands": [
{ "name": "/issue:discover", "description": "发现Issue" },
{ "name": "/issue:discover-by-prompt", "description": "基于提示发现Issue" },
{ "name": "/issue:plan --all-pending", "description": "规划所有待处理Issue" },
{ "name": "/issue:queue", "description": "排队Issue" },
{ "name": "/issue:execute", "description": "执行Issue" }
]
}
]
}
```

View File

@@ -1,544 +0,0 @@
# Prompt Templates for CLI Execution
通过 `ccw cli --tool claude` 执行各类命令的提示词模板和实际示例。
---
## 模板格式
```
任务: {task_description}
{前序完成信息(如果有)}
{完整的命令调用}
```
### 组件说明
| 组件 | 说明 | 例子 |
|------|------|------|
| `任务:` | 用户的任务描述 | "实现用户注册功能" |
| 前序完成 | 已完成命令的会话和产物 | "- /workflow:lite-plan: WFS-001 (IMPL_PLAN.md)" |
| 命令行 | 完整的命令调用 | "/workflow:lite-plan --yes \"任务\"" |
---
## 1. 规划命令 (Planning)
### 1.1 lite-plan
**模板**
```
任务: {task_description}
/workflow:lite-plan --yes "{task_description}"
```
**实例 - 简单任务**
```
任务: 添加用户登出功能
/workflow:lite-plan --yes "添加用户登出功能"
```
**实例 - 复杂任务**
```
任务: 重构认证模块,实现 JWT 刷新令牌和会话管理
/workflow:lite-plan --yes "重构认证模块,实现 JWT 刷新令牌和会话管理"
```
**实例 - 带探索强制**
```
任务: 优化数据库查询性能
/workflow:lite-plan --yes --explore "优化数据库查询性能"
```
### 1.2 plan
**模板**
```
任务: {task_description}
/workflow:plan --yes "{task_description}"
```
**实例**
```
任务: 实现支付系统集成 (Stripe)
/workflow:plan --yes "实现支付系统集成 (Stripe)"
```
### 1.3 multi-cli-plan
**模板**
```
任务: {task_description}
/workflow:multi-cli-plan --yes "{task_description}"
```
**实例**
```
任务: 设计微服务架构并实现 API 网关
/workflow:multi-cli-plan --yes "设计微服务架构并实现 API 网关"
```
---
## 2. 执行命令 (Execution)
### 2.1 lite-execute有规划产物
**模板**
```
任务: {task_description}
前序完成:
- /workflow:lite-plan: {session_id} ({artifact_files})
/workflow:lite-execute --yes --in-memory
```
**实例**
```
任务: 实现用户注册功能
前序完成:
- /workflow:lite-plan: WFS-register-2025-01-24 (IMPL_PLAN.md, exploration-architecture.json, exploration-security.json)
/workflow:lite-execute --yes --in-memory
```
### 2.2 lite-execute无规划产物
**模板**
```
任务: {task_description}
/workflow:lite-execute --yes "{task_description}"
```
**实例**
```
任务: 修复页面布局响应式问题
/workflow:lite-execute --yes "修复页面布局响应式问题"
```
### 2.3 execute有规划会话
**模板**
```
任务: {task_description}
前序完成:
- /workflow:plan: {session_id} ({artifact_files})
/workflow:execute --yes --resume-session="{session_id}"
```
**实例**
```
任务: 实现微服务网关
前序完成:
- /workflow:plan: WFS-gateway-2025-01-24 (IMPL_PLAN.md, .workflow/tasks/)
/workflow:execute --yes --resume-session="WFS-gateway-2025-01-24"
```
---
## 3. Bug 修复命令 (BugFix)
### 3.1 lite-fix轻量级修复
**模板**
```
任务: {task_description}
/workflow:lite-fix --yes "{task_description}"
```
**实例**
```
任务: 修复登录表单验证失败问题
/workflow:lite-fix --yes "修复登录表单验证失败问题"
```
### 3.2 lite-fix --hotfix紧急修复
**模板**
```
任务: {task_description}
/workflow:lite-fix --yes --hotfix "{task_description}"
```
**实例**
```
任务: 紧急修复生产环境支付流程中断
/workflow:lite-fix --yes --hotfix "紧急修复生产环境支付流程中断"
```
---
## 4. 测试命令 (Testing)
### 4.1 test-cycle-execute有前序执行
**模板**
```
任务: {task_description}
前序完成:
- /workflow:lite-execute: {session_id} ({artifact_files})
/workflow:test-cycle-execute --yes --session="{session_id}"
```
**实例**
```
任务: 实现用户注册功能
前序完成:
- /workflow:lite-plan: WFS-register-2025-01-24 (IMPL_PLAN.md)
- /workflow:lite-execute: WFS-register-2025-01-24 (完成)
/workflow:test-cycle-execute --yes --session="WFS-register-2025-01-24"
```
### 4.2 test-gen生成测试
**模板**
```
任务: {task_description}
/workflow:test-gen --yes "{task_description}"
```
**实例**
```
任务: 为认证模块生成单元测试
/workflow:test-gen --yes "为认证模块生成单元测试"
```
### 4.3 test-fix-gen生成测试和修复
**模板**
```
任务: {task_description}
/workflow:test-fix-gen --yes "{task_description}"
```
**实例**
```
任务: 生成并修复数据库连接超时问题的测试
/workflow:test-fix-gen --yes "生成并修复数据库连接超时问题的测试"
```
---
## 5. 代码审查命令 (Review)
### 5.1 review-session-cycle审查执行会话
**模板**
```
任务: {task_description}
前序完成:
- /workflow:execute: {session_id} ({artifact_files})
/workflow:review-session-cycle --yes --session="{session_id}"
```
**实例**
```
任务: 实现支付系统集成
前序完成:
- /workflow:plan: WFS-payment-2025-01-24 (IMPL_PLAN.md)
- /workflow:execute: WFS-payment-2025-01-24 (完成)
/workflow:review-session-cycle --yes --session="WFS-payment-2025-01-24"
```
### 5.2 review-module-cycle审查特定模块
**模板**
```
任务: {task_description}
/workflow:review-module-cycle --yes "{module_path}" --dimensions="{dimensions}"
```
**实例**
```
任务: 审查认证模块的安全性
/workflow:review-module-cycle --yes "src/auth" --dimensions="security,error-handling"
```
### 5.3 review-fix审查和修复
**模板**
```
任务: {task_description}
前序完成:
- /workflow:review-session-cycle: {session_id} ({findings})
/workflow:review-fix --yes --session="{session_id}"
```
**实例**
```
任务: 修复代码审查发现的问题
前序完成:
- /workflow:review-session-cycle: WFS-payment-2025-01-24 (审查完成)
/workflow:review-fix --yes --session="WFS-payment-2025-01-24"
```
---
## 6. 验证命令 (Verification)
### 6.1 plan-verify计划验证
**模板**
```
任务: {task_description}
前序完成:
- /workflow:plan: {session_id} (IMPL_PLAN.md)
/workflow:plan-verify --yes --session="{session_id}"
```
**实例**
```
任务: 验证支付系统实现计划
前序完成:
- /workflow:plan: WFS-payment-2025-01-24 (IMPL_PLAN.md)
/workflow:plan-verify --yes --session="WFS-payment-2025-01-24"
```
### 6.2 tdd-verifyTDD 验证)
**模板**
```
任务: {task_description}
前序完成:
- /workflow:execute: {session_id} (完成)
/workflow:tdd-verify --yes --session="{session_id}"
```
**实例**
```
任务: 验证 TDD 流程合规性
前序完成:
- /workflow:execute: WFS-tdd-auth-2025-01-24 (完成)
/workflow:tdd-verify --yes --session="WFS-tdd-auth-2025-01-24"
```
---
## 7. 常见命令链提示词
### 7.1 标准开发流程plan → execute → test
**第 1 步 - 规划**
```
任务: 实现用户注册功能,包括邮箱验证和密码加密
/workflow:lite-plan --yes "实现用户注册功能,包括邮箱验证和密码加密"
```
**第 2 步 - 执行**
```
任务: 实现用户注册功能,包括邮箱验证和密码加密
前序完成:
- /workflow:lite-plan: WFS-register-2025-01-24 (IMPL_PLAN.md, exploration-architecture.json, exploration-security.json)
/workflow:lite-execute --yes --in-memory
```
**第 3 步 - 测试**
```
任务: 实现用户注册功能,包括邮箱验证和密码加密
前序完成:
- /workflow:lite-plan: WFS-register-2025-01-24 (IMPL_PLAN.md)
- /workflow:lite-execute: WFS-register-2025-01-24 (完成)
/workflow:test-cycle-execute --yes --session="WFS-register-2025-01-24"
```
### 7.2 完整规划流程plan → execute → review → review-fix
**第 1 步 - 规划**
```
任务: 重构认证模块,实现 OAuth2 和会话管理
/workflow:plan --yes "重构认证模块,实现 OAuth2 和会话管理"
```
**第 2 步 - 执行**
```
任务: 重构认证模块,实现 OAuth2 和会话管理
前序完成:
- /workflow:plan: WFS-auth-2025-01-24 (IMPL_PLAN.md, .workflow/tasks/)
/workflow:execute --yes --resume-session="WFS-auth-2025-01-24"
```
**第 3 步 - 审查**
```
任务: 重构认证模块,实现 OAuth2 和会话管理
前序完成:
- /workflow:plan: WFS-auth-2025-01-24 (IMPL_PLAN.md)
- /workflow:execute: WFS-auth-2025-01-24 (完成)
/workflow:review-session-cycle --yes --session="WFS-auth-2025-01-24"
```
**第 4 步 - 审查修复**
```
任务: 重构认证模块,实现 OAuth2 和会话管理
前序完成:
- /workflow:plan: WFS-auth-2025-01-24 (IMPL_PLAN.md)
- /workflow:execute: WFS-auth-2025-01-24 (完成)
- /workflow:review-session-cycle: WFS-auth-2025-01-24 (审查完成)
/workflow:review-fix --yes --session="WFS-auth-2025-01-24"
```
### 7.3 Bug 修复 + 测试
**第 1 步 - 修复**
```
任务: 修复页面加载超时问题
/workflow:lite-fix --yes "修复页面加载超时问题"
```
**第 2 步 - 测试**
```
任务: 修复页面加载超时问题
前序完成:
- /workflow:lite-fix: WFS-fix-timeout-2025-01-24 (完成)
/workflow:test-cycle-execute --yes --session="WFS-fix-timeout-2025-01-24"
```
---
## 8. 参数组装规则
### 规则 1任务描述
- 规划命令(`lite-plan`, `plan` 等)**必须** 包含任务描述
- 格式:`命令 --yes "任务描述"`
### 规则 2会话复用
- 执行命令在有规划产物时使用 `--in-memory`
- 其他命令使用 `--session="WFS-xxx"` 引用前序会话
### 规则 3自动确认
- 所有命令都添加 `--yes` 标志跳过交互式确认
### 规则 4文件路径
- 需要文件路径时(如 `review-module-cycle`),使用相对于项目根的路径
- 例:`src/auth`, `src/modules/payment`
---
## 9. 特殊情况处理
### 9.1 特殊字符转义
**问题**:提示词中包含双引号
**解决**
```bash
# 在双引号内使用 \"
ccw cli -p "任务: 实现 \"特殊\" 功能\n/workflow:lite-plan ..." --tool claude
```
### 9.2 多行任务描述
**问题**:任务描述很长
**解决**
```
任务: 实现完整的支付系统,包括:
- Stripe 集成
- 订单管理
- 发票生成
- 退款处理
/workflow:plan --yes "实现完整的支付系统Stripe 集成、订单管理、发票生成、退款处理"
```
### 9.3 特殊路径处理
**问题**:路径包含空格
**解决**
```
任务: 审查用户管理模块
/workflow:review-module-cycle --yes "src/modules/user management" --dimensions="security"
```
---
## 10. 调试技巧
### 查看实际调用
`action-command-execute.md` 中添加日志:
```javascript
console.log(`[DEBUG] Assembling prompt for: ${cmd.command}`)
console.log(`[DEBUG] Prompt:\n${prompt}`)
console.log(`[DEBUG] CLI Call:\nccw cli -p "${escapedPrompt}" --tool claude --mode write -y`)
```
### 验证产物提取
检查 `.workflow/.ccw-coordinator/{timestamp}/commands/` 目录下的日志文件,查看 CLI 输出和产物提取结果。
### 测试提示词
手动调用 ccw cli 测试:
```bash
ccw cli -p "任务: 测试任务\n/workflow:lite-plan --yes \"测试任务\"" --tool claude --mode write -y
```

View File

@@ -1,371 +0,0 @@
# CCW Coordinator Specifications
命令库、验证规则和注册表一体化规范。
---
## 命令库
### Planning Commands
| Command | Description | Level |
|---------|-------------|-------|
| `/workflow:lite-plan` | 轻量级规划 | L2 |
| `/workflow:plan` | 标准规划 | L3 |
| `/workflow:multi-cli-plan` | 多CLI协作规划 | L2 |
| `/workflow:brainstorm:auto-parallel` | 头脑风暴规划 | L4 |
| `/workflow:tdd-plan` | TDD规划 | L3 |
### Execution Commands
| Command | Description | Level |
|---------|-------------|-------|
| `/workflow:lite-execute` | 轻量级执行 | L2 |
| `/workflow:execute` | 标准执行 | L3 |
| `/workflow:test-cycle-execute` | 测试循环执行 | L3 |
### BugFix Commands
| Command | Description | Level |
|---------|-------------|-------|
| `/workflow:lite-fix` | 轻量级修复 | L2 |
| `/workflow:lite-fix --hotfix` | 紧急修复 | L2 |
### Testing Commands
| Command | Description | Level |
|---------|-------------|-------|
| `/workflow:test-gen` | 测试生成 | L3 |
| `/workflow:test-fix-gen` | 测试修复生成 | L3 |
| `/workflow:tdd-verify` | TDD验证 | L3 |
### Review Commands
| Command | Description | Level |
|---------|-------------|-------|
| `/workflow:review-session-cycle` | 会话审查 | L3 |
| `/workflow:review-module-cycle` | 模块审查 | L3 |
| `/workflow:review-fix` | 审查修复 | L3 |
| `/workflow:plan-verify` | 计划验证 | L3 |
### Documentation Commands
| Command | Description | Level |
|---------|-------------|-------|
| `/memory:docs` | 生成文档 | L2 |
| `/memory:update-related` | 更新相关文档 | L2 |
| `/memory:update-full` | 全面更新文档 | L2 |
### Issue Commands
| Command | Description |
|---------|-------------|
| `/issue:discover` | 发现Issue |
| `/issue:discover-by-prompt` | 基于提示发现Issue |
| `/issue:plan --all-pending` | 规划所有待处理Issue |
| `/issue:queue` | 排队Issue |
| `/issue:execute` | 执行Issue |
---
## 命令链推荐
### 标准开发流程
```
1. /workflow:lite-plan
2. /workflow:lite-execute
3. /workflow:test-cycle-execute
```
### 完整规划流程
```
1. /workflow:plan
2. /workflow:plan-verify
3. /workflow:execute
4. /workflow:review-session-cycle
```
### TDD 流程
```
1. /workflow:tdd-plan
2. /workflow:execute
3. /workflow:tdd-verify
```
### Issue 批处理流程
```
1. /issue:plan --all-pending
2. /issue:queue
3. /issue:execute
```
---
## 验证规则
### Rule 1: Single Planning Command
每条链最多包含一个规划命令。
| 有效 | 无效 |
|------|------|
| `plan → execute` | `plan → lite-plan → execute` |
### Rule 2: Compatible Pairs
规划和执行命令必须兼容。
| Planning | Execution | 兼容 |
|----------|-----------|------|
| lite-plan | lite-execute | ✓ |
| lite-plan | execute | ✗ |
| multi-cli-plan | lite-execute | ✓ |
| multi-cli-plan | execute | ✓ |
| plan | execute | ✓ |
| plan | lite-execute | ✗ |
| tdd-plan | execute | ✓ |
| tdd-plan | lite-execute | ✗ |
### Rule 3: Testing After Execution
测试命令必须在执行命令之后。
| 有效 | 无效 |
|------|------|
| `execute → test-cycle-execute` | `test-cycle-execute → execute` |
### Rule 4: Review After Execution
审查命令必须在执行命令之后。
| 有效 | 无效 |
|------|------|
| `execute → review-session-cycle` | `review-session-cycle → execute` |
### Rule 5: BugFix Standalone
`lite-fix` 必须单独执行,不能与其他命令组合。
| 有效 | 无效 |
|------|------|
| `lite-fix` | `plan → lite-fix → execute` |
| `lite-fix --hotfix` | `lite-fix → test-cycle-execute` |
### Rule 6: Dependency Satisfaction
每个命令的依赖必须在前面执行。
```javascript
test-fix-gen test-cycle-execute
test-cycle-execute
```
### Rule 7: No Redundancy
链条中不能有重复的命令。
| 有效 | 无效 |
|------|------|
| `plan → execute → test` | `plan → plan → execute` |
### Rule 8: Command Exists
所有命令必须在此规范中定义。
---
## 反模式(避免)
### ❌ Pattern 1: Multiple Planning
```
plan → lite-plan → execute
```
**问题**: 重复分析,浪费时间
**修复**: 选一个规划命令
### ❌ Pattern 2: Test Without Context
```
test-cycle-execute (独立执行)
```
**问题**: 没有执行上下文,无法工作
**修复**: 先执行 `execute``test-fix-gen`
### ❌ Pattern 3: BugFix with Planning
```
plan → execute → lite-fix
```
**问题**: lite-fix 是独立命令,不应与规划混合
**修复**: 用 `lite-fix` 单独修复,或用 `plan → execute` 做大改
### ❌ Pattern 4: Review Without Changes
```
review-session-cycle (独立执行)
```
**问题**: 没有 git 改动可审查
**修复**: 先执行 `execute` 生成改动
### ❌ Pattern 5: TDD Misuse
```
tdd-plan → lite-execute
```
**问题**: lite-execute 无法处理 TDD 任务结构
**修复**: 用 `tdd-plan → execute → tdd-verify`
---
## 命令注册表
### 命令元数据结构
```json
{
"command_name": {
"category": "Planning|Execution|Testing|Review|BugFix|Maintenance",
"level": "L0|L1|L2|L3",
"description": "命令描述",
"inputs": ["input1", "input2"],
"outputs": ["output1", "output2"],
"dependencies": ["依赖命令"],
"parameters": [
{"name": "--flag", "type": "string|boolean|number", "default": "value"}
],
"chain_position": "start|middle|middle_or_end|end|standalone",
"next_recommended": ["推荐的下一个命令"]
}
}
```
### 命令分组
| Group | Commands |
|-------|----------|
| planning | lite-plan, multi-cli-plan, plan, tdd-plan |
| execution | lite-execute, execute, develop-with-file |
| testing | test-gen, test-fix-gen, test-cycle-execute, tdd-verify |
| review | review-session-cycle, review-module-cycle, review-fix |
| bugfix | lite-fix, debug, debug-with-file |
| maintenance | clean, replan |
| verification | plan-verify, tdd-verify |
### 兼容性矩阵
| 组合 | 状态 |
|------|------|
| lite-plan + lite-execute | ✓ compatible |
| lite-plan + execute | ✗ incompatible - use plan |
| multi-cli-plan + lite-execute | ✓ compatible |
| plan + execute | ✓ compatible |
| plan + lite-execute | ✗ incompatible - use lite-plan |
| tdd-plan + execute | ✓ compatible |
| execute + test-cycle-execute | ✓ compatible |
| lite-execute + test-cycle-execute | ✓ compatible |
| test-fix-gen + test-cycle-execute | ✓ required |
| review-session-cycle + review-fix | ✓ compatible |
| lite-fix + test-cycle-execute | ✗ incompatible - lite-fix standalone |
---
## 验证工具
### chain-validate.cjs
位置: `tools/chain-validate.cjs`
验证命令链合法性:
```bash
node tools/chain-validate.cjs plan execute test-cycle-execute
```
输出:
```
{
"valid": true,
"errors": [],
"warnings": []
}
```
## 命令注册表
### 工具位置
位置: `tools/command-registry.cjs` (skill 内置)
### 工作模式
**按需提取**: 只提取用户确定的任务链中的命令,不是全量扫描。
```javascript
// 用户任务链: [lite-plan, lite-execute]
const commandNames = command_chain.map(cmd => cmd.command);
const commandMeta = registry.getCommands(commandNames);
// 只提取这 2 个命令的元数据
```
### 功能
- 自动查找全局 `.claude/commands/workflow` 目录(相对路径 > 用户 home
- 按需提取指定命令的 YAML 头元数据
- 缓存机制避免重复读取
- 提供批量查询接口
### 集成方式
在 action-command-execute 中自动集成:
```javascript
const CommandRegistry = require('./tools/command-registry.cjs');
const registry = new CommandRegistry();
// 只提取任务链中的命令
const commandNames = command_chain.map(cmd => cmd.command);
const commandMeta = registry.getCommands(commandNames);
// 使用元数据生成提示词
const cmdInfo = commandMeta[cmd.command];
// {
// name: 'lite-plan',
// description: '轻量级规划...',
// argumentHint: '[-e|--explore] "task description"',
// allowedTools: [...],
// filePath: '...'
// }
```
### 提示词生成
智能提示词直接包含完整命令调用:
1. **任务描述**: 用户的任务描述
2. **前序产物**: 已完成命令的会话和产物信息
3. **完整命令行**: 下个命令的完整调用(通过 `argument-hint` 组装)
**✅ 正确示例**
```
任务: 实现用户注册功能
前序完成:
- /workflow:lite-plan: WFS-plan-001 (IMPL_PLAN.md)
/workflow:lite-execute --yes --in-memory
```
**❌ 旧的错误示例**(不再使用):
```
任务: 实现用户注册功能
前序完成:
- /workflow:lite-plan: WFS-plan-001 (IMPL_PLAN.md)
命令: /workflow:lite-execute [--resume-session="session-id"]
```
详见 `tools/README.md``specs/prompt-templates.md`

View File

@@ -1,117 +0,0 @@
# CCW Coordinator Tools
## command-registry.cjs
命令注册表工具:获取和提取命令元数据。
### 功能
- **按需提取**: 只提取指定命令的完整信息name, description, argumentHint, allowedTools 等)
- **全量获取**: 获取所有命令的名称和描述(快速查询)
- **自动查找**: 从全局 `.claude/commands/workflow` 目录读取(项目相对路径 > 用户 home
- **缓存机制**: 避免重复读取文件
### 编程接口
```javascript
const CommandRegistry = require('./tools/command-registry.cjs');
const registry = new CommandRegistry();
// 1. 获取所有命令的名称和描述(快速)
const allCommands = registry.getAllCommandsSummary();
// {
// "/workflow:lite-plan": {
// name: 'lite-plan',
// description: '轻量级规划...'
// },
// "/workflow:lite-execute": { ... }
// }
// 2. 按需提取指定命令的完整信息
const commands = registry.getCommands([
'/workflow:lite-plan',
'/workflow:lite-execute'
]);
// {
// "/workflow:lite-plan": {
// name: 'lite-plan',
// description: '...',
// argumentHint: '[-e|--explore] "task description"',
// allowedTools: [...],
// filePath: '...'
// },
// ...
// }
```
### 命令行接口
```bash
# 获取所有命令的名称和描述
node .claude/skills/ccw-coordinator/tools/command-registry.cjs
node .claude/skills/ccw-coordinator/tools/command-registry.cjs --all
# 输出: 23 个命令的简明列表 (name + description)
```
```bash
# 按需提取指定命令的完整信息
node .claude/skills/ccw-coordinator/tools/command-registry.cjs lite-plan lite-execute
# 输出: 完整信息 (name, description, argumentHint, allowedTools, filePath)
```
### 集成用途
`action-command-execute` 中使用:
```javascript
// 1. 初始化时只提取任务链中的命令(完整信息)
const commandNames = command_chain.map(cmd => cmd.command);
const commandMeta = registry.getCommands(commandNames);
// 2. 参数组装时使用 argumentHint
function assembleCommandLine(cmd, state, commandMeta) {
const cmdInfo = commandMeta[cmd.command];
let commandLine = cmd.command; // /workflow:lite-plan
commandLine += ' --yes'; // 自动确认
// 根据 argumentHint 智能组装参数
const cmdName = cmd.command.split(':').pop();
if (cmdName === 'lite-plan') {
commandLine += ` "${state.task_description}"`;
} else if (cmdName === 'lite-execute' && hasPlanResult(state)) {
commandLine += ' --in-memory';
}
return commandLine;
}
// 3. 生成提示词(直接包含完整命令)
function generatePrompt(cmd, state, commandMeta) {
let prompt = `任务: ${state.task_description}\n`;
// 添加前序完成
if (state.execution_results.length > 0) {
prompt += `\n前序完成:\n${formatResults(state.execution_results)}\n`;
}
// 组装完整命令行(关键)
const commandLine = assembleCommandLine(cmd, state, commandMeta);
prompt += `\n${commandLine}`;
return prompt;
}
```
确保 `ccw cli -p "..."` 提示词直接包含完整命令调用,而不是准则。
### 目录查找逻辑
自动查找顺序:
1. `.claude/commands/workflow` (相对于当前工作目录)
2. `~/.claude/commands/workflow` (用户 home 目录)

View File

@@ -1,320 +0,0 @@
#!/usr/bin/env node
/**
* Chain Validation Tool
*
* Validates workflow command chains against defined rules.
*
* Usage:
* node chain-validate.js plan execute test-cycle-execute
* node chain-validate.js --json "plan,execute,test-cycle-execute"
* node chain-validate.js --file custom-chain.json
*/
const fs = require('fs');
const path = require('path');
// Optional registry loading - gracefully degrade if not found
let registry = null;
try {
const registryPath = path.join(__dirname, '..', 'specs', 'chain-registry.json');
if (fs.existsSync(registryPath)) {
registry = JSON.parse(fs.readFileSync(registryPath, 'utf8'));
}
} catch (error) {
// Registry not available - dependency validation will be skipped
}
class ChainValidator {
constructor(registry) {
this.registry = registry;
this.errors = [];
this.warnings = [];
}
validate(chain) {
this.errors = [];
this.warnings = [];
this.validateSinglePlanning(chain);
this.validateCompatiblePairs(chain);
this.validateTestingPosition(chain);
this.validateReviewPosition(chain);
this.validateBugfixStandalone(chain);
this.validateDependencies(chain);
this.validateNoRedundancy(chain);
this.validateCommandExistence(chain);
return {
valid: this.errors.length === 0,
errors: this.errors,
warnings: this.warnings
};
}
validateSinglePlanning(chain) {
const planningCommands = chain.filter(cmd =>
['plan', 'lite-plan', 'multi-cli-plan', 'tdd-plan'].includes(cmd)
);
if (planningCommands.length > 1) {
this.errors.push({
rule: 'Single Planning Command',
message: `Too many planning commands: ${planningCommands.join(', ')}`,
severity: 'error'
});
}
}
validateCompatiblePairs(chain) {
const compatibility = {
'lite-plan': ['lite-execute'],
'multi-cli-plan': ['lite-execute', 'execute'],
'plan': ['execute'],
'tdd-plan': ['execute']
};
const planningCmd = chain.find(cmd =>
['plan', 'lite-plan', 'multi-cli-plan', 'tdd-plan'].includes(cmd)
);
const executionCmd = chain.find(cmd =>
['execute', 'lite-execute'].includes(cmd)
);
if (planningCmd && executionCmd) {
const compatible = compatibility[planningCmd] || [];
if (!compatible.includes(executionCmd)) {
this.errors.push({
rule: 'Compatible Pairs',
message: `${planningCmd} incompatible with ${executionCmd}`,
fix: `Use ${planningCmd} with ${compatible.join(' or ')}`,
severity: 'error'
});
}
}
}
validateTestingPosition(chain) {
const executionIdx = chain.findIndex(cmd =>
['execute', 'lite-execute', 'develop-with-file'].includes(cmd)
);
const testingIdx = chain.findIndex(cmd =>
['test-cycle-execute', 'tdd-verify', 'test-gen', 'test-fix-gen'].includes(cmd)
);
if (testingIdx !== -1 && executionIdx !== -1 && executionIdx > testingIdx) {
this.errors.push({
rule: 'Testing After Execution',
message: 'Testing commands must come after execution',
severity: 'error'
});
}
if (testingIdx !== -1 && executionIdx === -1) {
const hasTestGen = chain.some(cmd => ['test-gen', 'test-fix-gen'].includes(cmd));
if (!hasTestGen) {
this.warnings.push({
rule: 'Testing After Execution',
message: 'test-cycle-execute without execution context - needs test-gen or execute first',
severity: 'warning'
});
}
}
}
validateReviewPosition(chain) {
const executionIdx = chain.findIndex(cmd =>
['execute', 'lite-execute'].includes(cmd)
);
const reviewIdx = chain.findIndex(cmd =>
cmd.includes('review')
);
if (reviewIdx !== -1 && executionIdx !== -1 && executionIdx > reviewIdx) {
this.errors.push({
rule: 'Review After Changes',
message: 'Review commands must come after execution',
severity: 'error'
});
}
if (reviewIdx !== -1 && executionIdx === -1) {
const isModuleReview = chain[reviewIdx] === 'review-module-cycle';
if (!isModuleReview) {
this.warnings.push({
rule: 'Review After Changes',
message: 'Review without execution - needs git changes to review',
severity: 'warning'
});
}
}
}
validateBugfixStandalone(chain) {
if (chain.includes('lite-fix')) {
const others = chain.filter(cmd => cmd !== 'lite-fix');
if (others.length > 0) {
this.errors.push({
rule: 'BugFix Standalone',
message: 'lite-fix must be standalone, cannot combine with other commands',
fix: 'Use lite-fix alone OR use plan + execute for larger changes',
severity: 'error'
});
}
}
}
validateDependencies(chain) {
// Skip if registry not available
if (!this.registry || !this.registry.commands) {
return;
}
for (let i = 0; i < chain.length; i++) {
const cmd = chain[i];
const cmdMeta = this.registry.commands[cmd];
if (!cmdMeta) continue;
const deps = cmdMeta.dependencies || [];
const depsOptional = cmdMeta.dependencies_optional || false;
if (deps.length > 0 && !depsOptional) {
const hasDependency = deps.some(dep => {
const depIdx = chain.indexOf(dep);
return depIdx !== -1 && depIdx < i;
});
if (!hasDependency) {
this.errors.push({
rule: 'Dependency Satisfaction',
message: `${cmd} requires ${deps.join(' or ')} before it`,
severity: 'error'
});
}
}
}
}
validateNoRedundancy(chain) {
const seen = new Set();
const duplicates = [];
for (const cmd of chain) {
if (seen.has(cmd)) {
duplicates.push(cmd);
}
seen.add(cmd);
}
if (duplicates.length > 0) {
this.errors.push({
rule: 'No Redundant Commands',
message: `Duplicate commands: ${duplicates.join(', ')}`,
severity: 'error'
});
}
}
validateCommandExistence(chain) {
// Skip if registry not available
if (!this.registry || !this.registry.commands) {
return;
}
for (const cmd of chain) {
if (!this.registry.commands[cmd]) {
this.errors.push({
rule: 'Command Existence',
message: `Unknown command: ${cmd}`,
severity: 'error'
});
}
}
}
}
function main() {
const args = process.argv.slice(2);
if (args.length === 0) {
console.log('Usage:');
console.log(' chain-validate.js <command1> <command2> ...');
console.log(' chain-validate.js --json "cmd1,cmd2,cmd3"');
console.log(' chain-validate.js --file chain.json');
process.exit(1);
}
let chain;
if (args[0] === '--json') {
chain = args[1].split(',').map(s => s.trim());
} else if (args[0] === '--file') {
const filePath = args[1];
// SEC-001: 路径遍历验证 - 只允许访问工作目录下的文件
const resolvedPath = path.resolve(filePath);
const workDir = path.resolve('.');
if (!resolvedPath.startsWith(workDir)) {
console.error('Error: File path must be within current working directory');
process.exit(1);
}
// CORR-001: JSON 解析错误处理
let fileContent;
try {
fileContent = JSON.parse(fs.readFileSync(resolvedPath, 'utf8'));
} catch (error) {
console.error(`Error: Failed to parse JSON file ${filePath}: ${error.message}`);
process.exit(1);
}
// CORR-002: 嵌套属性 null 检查
chain = fileContent.chain || fileContent.steps?.map(s => s.command) || [];
if (chain.length === 0) {
console.error('Error: No valid chain found in file (expected "chain" array or "steps" with "command" fields)');
process.exit(1);
}
} else {
chain = args;
}
const validator = new ChainValidator(registry);
const result = validator.validate(chain);
console.log('\n=== Chain Validation Report ===\n');
console.log('Chain:', chain.join(' → '));
console.log('');
if (result.valid) {
console.log('✓ Chain is valid!\n');
} else {
console.log('✗ Chain has errors:\n');
result.errors.forEach(err => {
console.log(` [${err.rule}] ${err.message}`);
if (err.fix) {
console.log(` Fix: ${err.fix}`);
}
});
console.log('');
}
if (result.warnings.length > 0) {
console.log('⚠ Warnings:\n');
result.warnings.forEach(warn => {
console.log(` [${warn.rule}] ${warn.message}`);
});
console.log('');
}
process.exit(result.valid ? 0 : 1);
}
if (require.main === module) {
main();
}
module.exports = { ChainValidator };

View File

@@ -1,255 +0,0 @@
#!/usr/bin/env node
/**
* Command Registry Tool
*
* 功能:
* 1. 根据命令名称查找并提取 YAML 头
* 2. 从全局 .claude/commands/workflow 目录读取
* 3. 支持按需提取(不是全量扫描)
*/
const fs = require('fs');
const path = require('path');
const os = require('os');
class CommandRegistry {
constructor(commandDir = null) {
// 优先使用传入的目录
if (commandDir) {
this.commandDir = commandDir;
} else {
// 自动查找 .claude/commands/workflow
this.commandDir = this.findCommandDir();
}
this.cache = {};
}
/**
* 自动查找 .claude/commands/workflow 目录
* 支持: 项目相对路径、用户 home 目录
*/
findCommandDir() {
// 1. 尝试相对于当前工作目录
const relativePath = path.join('.claude', 'commands', 'workflow');
if (fs.existsSync(relativePath)) {
return path.resolve(relativePath);
}
// 2. 尝试用户 home 目录
const homeDir = os.homedir();
const homeCommandDir = path.join(homeDir, '.claude', 'commands', 'workflow');
if (fs.existsSync(homeCommandDir)) {
return homeCommandDir;
}
// 未找到时返回 null后续操作会失败并提示
return null;
}
/**
* 解析 YAML 头 (简化版本)
*
* 限制:
* - 只支持简单的 key: value 对 (单行值)
* - 不支持多行值、嵌套对象、复杂列表
* - allowed-tools 字段支持逗号分隔的字符串,自动转为数组
*
* 示例:
* ---
* name: lite-plan
* description: "Lightweight planning workflow"
* allowed-tools: Read, Write, Bash
* ---
*/
parseYamlHeader(content) {
// 处理 Windows 行结尾 (\r\n)
const match = content.match(/^---[\r\n]+([\s\S]*?)[\r\n]+---/);
if (!match) return null;
const yamlContent = match[1];
const result = {};
try {
const lines = yamlContent.split(/[\r\n]+/);
for (const line of lines) {
const trimmed = line.trim();
if (!trimmed || trimmed.startsWith('#')) continue; // 跳过空行和注释
const colonIndex = trimmed.indexOf(':');
if (colonIndex === -1) continue;
const key = trimmed.substring(0, colonIndex).trim();
const value = trimmed.substring(colonIndex + 1).trim();
if (!key) continue; // 跳过无效行
// 去除引号 (单引号或双引号)
let cleanValue = value.replace(/^["']|["']$/g, '');
// allowed-tools 字段特殊处理:转为数组
// 支持格式: "Read, Write, Bash" 或 "Read,Write,Bash"
if (key === 'allowed-tools') {
cleanValue = Array.isArray(cleanValue)
? cleanValue
: cleanValue.split(',').map(t => t.trim()).filter(t => t);
}
result[key] = cleanValue;
}
} catch (error) {
console.error('YAML parsing error:', error.message);
return null;
}
return result;
}
/**
* 获取单个命令的元数据
* @param {string} commandName 命令名称 (e.g., "lite-plan" 或 "/workflow:lite-plan")
* @returns {object|null} 命令信息或 null
*/
getCommand(commandName) {
if (!this.commandDir) {
console.error('ERROR: .claude/commands/workflow 目录未找到');
return null;
}
// 标准化命令名称
const normalized = commandName.startsWith('/workflow:')
? commandName.substring('/workflow:'.length)
: commandName;
// 检查缓存
if (this.cache[normalized]) {
return this.cache[normalized];
}
// 读取命令文件
const filePath = path.join(this.commandDir, `${normalized}.md`);
if (!fs.existsSync(filePath)) {
return null;
}
try {
const content = fs.readFileSync(filePath, 'utf-8');
const header = this.parseYamlHeader(content);
if (header && header.name) {
const result = {
name: header.name,
command: `/workflow:${header.name}`,
description: header.description || '',
argumentHint: header['argument-hint'] || '',
allowedTools: Array.isArray(header['allowed-tools'])
? header['allowed-tools']
: (header['allowed-tools'] ? [header['allowed-tools']] : []),
filePath: filePath
};
// 缓存结果
this.cache[normalized] = result;
return result;
}
} catch (error) {
console.error(`读取命令失败 ${filePath}:`, error.message);
}
return null;
}
/**
* 批量获取多个命令的元数据
* @param {array} commandNames 命令名称数组
* @returns {object} 命令信息映射
*/
getCommands(commandNames) {
const result = {};
for (const name of commandNames) {
const cmd = this.getCommand(name);
if (cmd) {
result[cmd.command] = cmd;
}
}
return result;
}
/**
* 获取所有命令的名称和描述
* @returns {object} 命令名称和描述的映射
*/
getAllCommandsSummary() {
const result = {};
const commandDir = this.commandDir;
if (!commandDir) {
return result;
}
try {
const files = fs.readdirSync(commandDir);
for (const file of files) {
if (!file.endsWith('.md')) continue;
const filePath = path.join(commandDir, file);
const stat = fs.statSync(filePath);
if (stat.isDirectory()) continue;
try {
const content = fs.readFileSync(filePath, 'utf-8');
const header = this.parseYamlHeader(content);
if (header && header.name) {
const commandName = `/workflow:${header.name}`;
result[commandName] = {
name: header.name,
description: header.description || ''
};
}
} catch (error) {
// 跳过读取失败的文件
continue;
}
}
} catch (error) {
// 目录读取失败
return result;
}
return result;
}
/**
* 生成注册表 JSON
*/
toJSON(commands = null) {
const data = commands || this.cache;
return JSON.stringify(data, null, 2);
}
}
// CLI 模式
if (require.main === module) {
const args = process.argv.slice(2);
if (args.length === 0 || args[0] === '--all') {
// 获取所有命令的名称和描述
const registry = new CommandRegistry();
const commands = registry.getAllCommandsSummary();
console.log(JSON.stringify(commands, null, 2));
process.exit(0);
}
const registry = new CommandRegistry();
const commands = registry.getCommands(args);
console.log(JSON.stringify(commands, null, 2));
}
module.exports = CommandRegistry;

View File

@@ -1,522 +0,0 @@
---
name: ccw
description: Stateless workflow orchestrator. Auto-selects optimal workflow based on task intent. Triggers "ccw", "workflow".
allowed-tools: Task(*), SlashCommand(*), AskUserQuestion(*), Read(*), Bash(*), Grep(*), TodoWrite(*)
---
# CCW - Claude Code Workflow Orchestrator
无状态工作流协调器,根据任务意图自动选择最优工作流。
## Workflow System Overview
CCW 提供两个工作流系统:**Main Workflow** 和 **Issue Workflow**,协同覆盖完整的软件开发生命周期。
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ Main Workflow │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Level 1 │ → │ Level 2 │ → │ Level 3 │ → │ Level 4 │ │
│ │ Rapid │ │ Lightweight │ │ Standard │ │ Brainstorm │ │
│ │ │ │ │ │ │ │ │ │
│ │ lite-lite- │ │ lite-plan │ │ plan │ │ brainstorm │ │
│ │ lite │ │ lite-fix │ │ tdd-plan │ │ :auto- │ │
│ │ │ │ multi-cli- │ │ test-fix- │ │ parallel │ │
│ │ │ │ plan │ │ gen │ │ ↓ │ │
│ │ │ │ │ │ │ │ plan │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
│ Complexity: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━▶ │
│ Low High │
└─────────────────────────────────────────────────────────────────────────────┘
│ After development
┌─────────────────────────────────────────────────────────────────────────────┐
│ Issue Workflow │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Accumulate │ → │ Plan │ → │ Execute │ │
│ │ Discover & │ │ Batch │ │ Parallel │ │
│ │ Collect │ │ Planning │ │ Execution │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ Supplementary role: Maintain main branch stability, worktree isolation │
└─────────────────────────────────────────────────────────────────────────────┘
```
## Architecture
```
┌─────────────────────────────────────────────────────────────────┐
│ CCW Orchestrator (CLI-Enhanced + Requirement Analysis) │
├─────────────────────────────────────────────────────────────────┤
│ Phase 1 │ Input Analysis (rule-based, fast path) │
│ Phase 1.5 │ CLI Classification (semantic, smart path) │
│ Phase 1.75 │ Requirement Clarification (clarity < 2) │
│ Phase 2 │ Level Selection (intent → level → workflow) │
│ Phase 2.5 │ CLI Action Planning (high complexity) │
│ Phase 3 │ User Confirmation (optional) │
│ Phase 4 │ TODO Tracking Setup │
│ Phase 5 │ Execution Loop │
└─────────────────────────────────────────────────────────────────┘
```
## Level Quick Reference
| Level | Name | Workflows | Artifacts | Execution |
|-------|------|-----------|-----------|-----------|
| **1** | Rapid | `lite-lite-lite` | None | Direct execute |
| **2** | Lightweight | `lite-plan`, `lite-fix`, `multi-cli-plan` | Memory/Lightweight files | → `lite-execute` |
| **3** | Standard | `plan`, `tdd-plan`, `test-fix-gen` | Session persistence | → `execute` / `test-cycle-execute` |
| **4** | Brainstorm | `brainstorm:auto-parallel``plan` | Multi-role analysis + Session | → `execute` |
| **-** | Issue | `discover``plan``queue``execute` | Issue records | Worktree isolation (optional) |
## Workflow Selection Decision Tree
```
Start
├─ Is it post-development maintenance?
│ ├─ Yes → Issue Workflow
│ └─ No ↓
├─ Are requirements clear?
│ ├─ Uncertain → Level 4 (brainstorm:auto-parallel)
│ └─ Clear ↓
├─ Need persistent Session?
│ ├─ Yes → Level 3 (plan / tdd-plan / test-fix-gen)
│ └─ No ↓
├─ Need multi-perspective / solution comparison?
│ ├─ Yes → Level 2 (multi-cli-plan)
│ └─ No ↓
├─ Is it a bug fix?
│ ├─ Yes → Level 2 (lite-fix)
│ └─ No ↓
├─ Need planning?
│ ├─ Yes → Level 2 (lite-plan)
│ └─ No → Level 1 (lite-lite-lite)
```
## Intent Classification
### Priority Order (with Level Mapping)
| Priority | Intent | Patterns | Level | Flow |
|----------|--------|----------|-------|------|
| 1 | bugfix/hotfix | `urgent,production,critical` + bug | L2 | `bugfix.hotfix` |
| 1 | bugfix | `fix,bug,error,crash,fail` | L2 | `bugfix.standard` |
| 2 | issue batch | `issues,batch` + `fix,resolve` | Issue | `issue` |
| 3 | exploration | `不确定,explore,研究,what if` | L4 | `full` |
| 3 | multi-perspective | `多视角,权衡,比较方案,cross-verify` | L2 | `multi-cli-plan` |
| 4 | quick-task | `快速,简单,small,quick` + feature | L1 | `lite-lite-lite` |
| 5 | ui design | `ui,design,component,style` | L3/L4 | `ui` |
| 6 | tdd | `tdd,test-driven,先写测试` | L3 | `tdd` |
| 7 | test-fix | `测试失败,test fail,fix test` | L3 | `test-fix-gen` |
| 8 | review | `review,审查,code review` | L3 | `review-fix` |
| 9 | documentation | `文档,docs,readme` | L2 | `docs` |
| 99 | feature | complexity-based | L2/L3 | `rapid`/`coupled` |
### Quick Selection Guide
| Scenario | Recommended Workflow | Level |
|----------|---------------------|-------|
| Quick fixes, config adjustments | `lite-lite-lite` | 1 |
| Clear single-module features | `lite-plan → lite-execute` | 2 |
| Bug diagnosis and fix | `lite-fix` | 2 |
| Production emergencies | `lite-fix --hotfix` | 2 |
| Technology selection, solution comparison | `multi-cli-plan → lite-execute` | 2 |
| Multi-module changes, refactoring | `plan → verify → execute` | 3 |
| Test-driven development | `tdd-plan → execute → tdd-verify` | 3 |
| Test failure fixes | `test-fix-gen → test-cycle-execute` | 3 |
| New features, architecture design | `brainstorm:auto-parallel → plan → execute` | 4 |
| Post-development issue fixes | Issue Workflow | - |
### Complexity Assessment
```javascript
function assessComplexity(text) {
let score = 0
if (/refactor|重构|migrate|迁移|architect|架构|system|系统/.test(text)) score += 2
if (/multiple|多个|across|跨|all|所有|entire|整个/.test(text)) score += 2
if (/integrate|集成|api|database|数据库/.test(text)) score += 1
if (/security|安全|performance|性能|scale|扩展/.test(text)) score += 1
return score >= 4 ? 'high' : score >= 2 ? 'medium' : 'low'
}
```
| Complexity | Flow |
|------------|------|
| high | `coupled` (plan → verify → execute) |
| medium/low | `rapid` (lite-plan → lite-execute) |
### Dimension Extraction (WHAT/WHERE/WHY/HOW)
从用户输入提取四个维度,用于需求澄清和工作流选择:
| 维度 | 提取内容 | 示例模式 |
|------|----------|----------|
| **WHAT** | action + target | `创建/修复/重构/优化/分析` + 目标对象 |
| **WHERE** | scope + paths | `file/module/system` + 文件路径 |
| **WHY** | goal + motivation | `为了.../因为.../目的是...` |
| **HOW** | constraints + preferences | `必须.../不要.../应该...` |
**Clarity Score** (0-3):
- +0.5: 有明确 action
- +0.5: 有具体 target
- +0.5: 有文件路径
- +0.5: scope 不是 unknown
- +0.5: 有明确 goal
- +0.5: 有约束条件
- -0.5: 包含不确定词 (`不知道/maybe/怎么`)
### Requirement Clarification
`clarity_score < 2` 时触发需求澄清:
```javascript
if (dimensions.clarity_score < 2) {
const questions = generateClarificationQuestions(dimensions)
// 生成问题:目标是什么? 范围是什么? 有什么约束?
AskUserQuestion({ questions })
}
```
**澄清问题类型**:
- 目标不明确 → "你想要对什么进行操作?"
- 范围不明确 → "操作的范围是什么?"
- 目的不明确 → "这个操作的主要目标是什么?"
- 复杂操作 → "有什么特殊要求或限制?"
## TODO Tracking Protocol
### CRITICAL: Append-Only Rule
CCW 创建的 Todo **必须附加到现有列表**,不能覆盖用户的其他 Todo。
### Implementation
```javascript
// 1. 使用 CCW 前缀隔离工作流 todo
const prefix = `CCW:${flowName}`
// 2. 创建新 todo 时使用前缀格式
TodoWrite({
todos: [
...existingNonCCWTodos, // 保留用户的 todo
{ content: `${prefix}: [1/N] /command:step1`, status: "in_progress", activeForm: "..." },
{ content: `${prefix}: [2/N] /command:step2`, status: "pending", activeForm: "..." }
]
})
// 3. 更新状态时只修改匹配前缀的 todo
```
### Todo Format
```
CCW:{flow}: [{N}/{Total}] /command:name
```
### Visual Example
```
✓ CCW:rapid: [1/2] /workflow:lite-plan
→ CCW:rapid: [2/2] /workflow:lite-execute
用户自己的 todo保留不动
```
### Status Management
- 开始工作流:创建所有步骤 todo第一步 `in_progress`
- 完成步骤:当前步骤 `completed`,下一步 `in_progress`
- 工作流结束:所有 CCW todo 标记 `completed`
## Execution Flow
```javascript
// 1. Check explicit command
if (input.startsWith('/workflow:') || input.startsWith('/issue:')) {
SlashCommand(input)
return
}
// 2. Classify intent
const intent = classifyIntent(input) // See command.json intent_rules
// 3. Select flow
const flow = selectFlow(intent) // See command.json flows
// 4. Create todos with CCW prefix
createWorkflowTodos(flow)
// 5. Dispatch first command
SlashCommand(flow.steps[0].command, args: input)
```
## CLI Tool Integration
CCW 在特定条件下自动注入 CLI 调用:
| Condition | CLI Inject |
|-----------|------------|
| 大量代码上下文 (≥50k chars) | `gemini --mode analysis` |
| 高复杂度任务 | `gemini --mode analysis` |
| Bug 诊断 | `gemini --mode analysis` |
| 多任务执行 (≥3 tasks) | `codex --mode write` |
### CLI Enhancement Phases
**Phase 1.5: CLI-Assisted Classification**
当规则匹配不明确时,使用 CLI 辅助分类:
| 触发条件 | 说明 |
|----------|------|
| matchCount < 2 | 多个意图模式匹配 |
| complexity = high | 高复杂度任务 |
| input > 100 chars | 长输入需要语义理解 |
**Phase 2.5: CLI-Assisted Action Planning**
高复杂度任务的工作流优化:
| 触发条件 | 说明 |
|----------|------|
| complexity = high | 高复杂度任务 |
| steps >= 3 | 多步骤工作流 |
| input > 200 chars | 复杂需求描述 |
CLI 可返回建议:`use_default` | `modify` (调整步骤) | `upgrade` (升级工作流)
## Continuation Commands
工作流执行中的用户控制命令:
| 命令 | 作用 |
|------|------|
| `continue` | 继续执行下一步 |
| `skip` | 跳过当前步骤 |
| `abort` | 终止工作流 |
| `/workflow:*` | 切换到指定命令 |
| 自然语言 | 重新分析意图 |
## Workflow Flow Details
### Issue Workflow (Main Workflow 补充机制)
Issue Workflow 是 Main Workflow 的**补充机制**,专注于开发后的持续维护。
#### 设计理念
| 方面 | Main Workflow | Issue Workflow |
|------|---------------|----------------|
| **用途** | 主要开发周期 | 开发后维护 |
| **时机** | 功能开发阶段 | 主工作流完成后 |
| **范围** | 完整功能实现 | 针对性修复/增强 |
| **并行性** | 依赖分析 → Agent 并行 | Worktree 隔离 (可选) |
| **分支模型** | 当前分支工作 | 可使用隔离的 worktree |
#### 为什么 Main Workflow 不自动使用 Worktree
**依赖分析已解决并行性问题**
1. 规划阶段 (`/workflow:plan`) 执行依赖分析
2. 自动识别任务依赖和关键路径
3. 划分为**并行组**(独立任务)和**串行链**(依赖任务)
4. Agent 并行执行独立任务,无需文件系统隔离
#### 两阶段生命周期
```
┌─────────────────────────────────────────────────────────────────────┐
│ Phase 1: Accumulation (积累阶段) │
│ │
│ Triggers: 任务完成后的 review、代码审查发现、测试失败 │
│ │
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
│ │ discover │ │ discover- │ │ new │ │
│ │ Auto-find │ │ by-prompt │ │ Manual │ │
│ └────────────┘ └────────────┘ └────────────┘ │
│ │
│ 持续积累 issues 到待处理队列 │
└─────────────────────────────────────────────────────────────────────┘
│ 积累足够后
┌─────────────────────────────────────────────────────────────────────┐
│ Phase 2: Batch Resolution (批量解决阶段) │
│ │
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
│ │ plan │ ──→ │ queue │ ──→ │ execute │ │
│ │ --all- │ │ Optimize │ │ Parallel │ │
│ │ pending │ │ order │ │ execution │ │
│ └────────────┘ └────────────┘ └────────────┘ │
│ │
│ 支持 worktree 隔离,保持主分支稳定 │
└─────────────────────────────────────────────────────────────────────┘
```
#### 与 Main Workflow 的协作
```
开发迭代循环
┌─────────────────────────────────────────────────────────────────────┐
│ │
│ ┌─────────┐ ┌─────────┐ │
│ │ Feature │ ──→ Main Workflow ──→ Done ──→│ Review │ │
│ │ Request │ (Level 1-4) └────┬────┘ │
│ └─────────┘ │ │
│ ▲ │ 发现 Issues │
│ │ ▼ │
│ │ ┌─────────┐ │
│ 继续 │ │ Issue │ │
│ 新功能│ │ Workflow│ │
│ │ └────┬────┘ │
│ │ ┌──────────────────────────────┘ │
│ │ │ 修复完成 │
│ │ ▼ │
│ ┌────┴────┐◀────── │
│ │ Main │ Merge │
│ │ Branch │ back │
│ └─────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘
```
#### 命令列表
**积累阶段:**
```bash
/issue:discover # 多视角自动发现
/issue:discover-by-prompt # 基于提示发现
/issue:new # 手动创建
```
**批量解决阶段:**
```bash
/issue:plan --all-pending # 批量规划所有待处理
/issue:queue # 生成优化执行队列
/issue:execute # 并行执行
```
### lite-lite-lite vs multi-cli-plan
| 维度 | lite-lite-lite | multi-cli-plan |
|------|---------------|----------------|
| **产物** | 无文件 | IMPL_PLAN.md + plan.json + synthesis.json |
| **状态** | 无状态 | 持久化 session |
| **CLI选择** | 自动分析任务类型选择 | 配置驱动 |
| **迭代** | 通过 AskUser | 多轮收敛 |
| **执行** | 直接执行 | 通过 lite-execute |
| **适用** | 快速修复、简单功能 | 复杂多步骤实现 |
**选择指南**
- 任务清晰、改动范围小 → `lite-lite-lite`
- 需要多视角分析、复杂架构 → `multi-cli-plan`
### multi-cli-plan vs lite-plan
| 维度 | multi-cli-plan | lite-plan |
|------|---------------|-----------|
| **上下文** | ACE 语义搜索 | 手动文件模式 |
| **分析** | 多 CLI 交叉验证 | 单次规划 |
| **迭代** | 多轮直到收敛 | 单轮 |
| **置信度** | 高 (共识驱动) | 中 (单一视角) |
| **适用** | 需要多视角的复杂任务 | 直接明确的实现 |
**选择指南**
- 需求明确、路径清晰 → `lite-plan`
- 需要权衡、多方案比较 → `multi-cli-plan`
## Artifact Flow Protocol
工作流产出的自动流转机制,支持不同格式产出间的意图提取和完成度判断。
### 产出格式
| 命令 | 产出位置 | 格式 | 关键字段 |
|------|----------|------|----------|
| `/workflow:lite-plan` | memory://plan | structured_plan | tasks, files, dependencies |
| `/workflow:plan` | .workflow/{session}/IMPL_PLAN.md | markdown_plan | phases, tasks, risks |
| `/workflow:execute` | execution_log.json | execution_report | completed_tasks, errors |
| `/workflow:test-cycle-execute` | test_results.json | test_report | pass_rate, failures, coverage |
| `/workflow:review-session-cycle` | review_report.md | review_report | findings, severity_counts |
### 意图提取 (Intent Extraction)
流转到下一步时,自动提取关键信息:
```
plan → execute:
提取: tasks (未完成), priority_order, files_to_modify, context_summary
execute → test:
提取: modified_files, test_scope (推断), pending_verification
test → fix:
条件: pass_rate < 0.95
提取: failures, error_messages, affected_files, suggested_fixes
review → fix:
条件: critical > 0 OR high > 3
提取: findings (critical/high), fix_priority, affected_files
```
### 完成度判断
**Test 完成度路由**:
```
pass_rate >= 0.95 AND coverage >= 0.80 → complete
pass_rate >= 0.95 AND coverage < 0.80 → add_more_tests
pass_rate >= 0.80 → fix_failures_then_continue
pass_rate < 0.80 → major_fix_required
```
**Review 完成度路由**:
```
critical == 0 AND high <= 3 → complete_or_optional_fix
critical > 0 → mandatory_fix
high > 3 → recommended_fix
```
### 流转决策模式
**plan_execute_test**:
```
plan → execute → test
↓ (if test fail)
extract_failures → fix → test (max 3 iterations)
↓ (if still fail)
manual_intervention
```
**iterative_improvement**:
```
execute → test → fix → test → ...
loop until: pass_rate >= 0.95 OR iterations >= 3
```
### 使用示例
```javascript
// 执行完成后,根据产出决定下一步
const result = await execute(plan)
// 提取意图流转到测试
const testContext = extractIntent('execute_to_test', result)
// testContext = { modified_files, test_scope, pending_verification }
// 测试完成后,根据完成度决定路由
const testResult = await test(testContext)
const nextStep = evaluateCompletion('test', testResult)
// nextStep = 'fix_failures_then_continue' if pass_rate = 0.85
```
## Reference
- [command.json](command.json) - 命令元数据、Flow 定义、意图规则、Artifact Flow

View File

@@ -1,641 +0,0 @@
{
"_metadata": {
"version": "2.0.0",
"description": "Unified CCW command index with capabilities, flows, and intent rules"
},
"capabilities": {
"explore": {
"description": "Codebase exploration and context gathering",
"commands": ["/workflow:init", "/workflow:tools:gather", "/memory:load"],
"agents": ["cli-explore-agent", "context-search-agent"]
},
"brainstorm": {
"description": "Multi-perspective analysis and ideation",
"commands": ["/workflow:brainstorm:auto-parallel", "/workflow:brainstorm:artifacts", "/workflow:brainstorm:synthesis"],
"roles": ["product-manager", "system-architect", "ux-expert", "data-architect", "api-designer"]
},
"plan": {
"description": "Task planning and decomposition",
"commands": ["/workflow:lite-plan", "/workflow:plan", "/workflow:tdd-plan", "/task:create", "/task:breakdown"],
"agents": ["cli-lite-planning-agent", "action-planning-agent"]
},
"verify": {
"description": "Plan and quality verification",
"commands": ["/workflow:plan-verify", "/workflow:tdd-verify"]
},
"execute": {
"description": "Task execution and implementation",
"commands": ["/workflow:lite-execute", "/workflow:execute", "/task:execute"],
"agents": ["code-developer", "cli-execution-agent", "universal-executor"]
},
"bugfix": {
"description": "Bug diagnosis and fixing",
"commands": ["/workflow:lite-fix"],
"agents": ["code-developer"]
},
"test": {
"description": "Test generation and execution",
"commands": ["/workflow:test-gen", "/workflow:test-fix-gen", "/workflow:test-cycle-execute"],
"agents": ["test-fix-agent"]
},
"review": {
"description": "Code review and quality analysis",
"commands": ["/workflow:review-session-cycle", "/workflow:review-module-cycle", "/workflow:review", "/workflow:review-fix"]
},
"issue": {
"description": "Issue lifecycle management - discover, accumulate, batch resolve",
"commands": ["/issue:new", "/issue:discover", "/issue:discover-by-prompt", "/issue:plan", "/issue:queue", "/issue:execute", "/issue:manage"],
"agents": ["issue-plan-agent", "issue-queue-agent", "cli-explore-agent"],
"lifecycle": {
"accumulation": {
"description": "任务完成后进行需求扩展、bug分析、测试发现",
"triggers": ["post-task review", "code review findings", "test failures"],
"commands": ["/issue:discover", "/issue:discover-by-prompt", "/issue:new"]
},
"batch_resolution": {
"description": "积累的issue集中规划和并行执行",
"flow": ["plan", "queue", "execute"],
"commands": ["/issue:plan --all-pending", "/issue:queue", "/issue:execute"]
}
}
},
"ui-design": {
"description": "UI design and prototyping",
"commands": ["/workflow:ui-design:explore-auto", "/workflow:ui-design:imitate-auto", "/workflow:ui-design:design-sync"],
"agents": ["ui-design-agent"]
},
"memory": {
"description": "Documentation and knowledge management",
"commands": ["/memory:docs", "/memory:update-related", "/memory:update-full", "/memory:skill-memory"],
"agents": ["doc-generator", "memory-bridge"]
}
},
"flows": {
"_level_guide": {
"L1": "Rapid - No artifacts, direct execution",
"L2": "Lightweight - Memory/lightweight files, → lite-execute",
"L3": "Standard - Session persistence, → execute/test-cycle-execute",
"L4": "Brainstorm - Multi-role analysis + Session, → execute"
},
"lite-lite-lite": {
"name": "Ultra-Rapid Execution",
"level": "L1",
"description": "零文件 + 自动CLI选择 + 语义描述 + 直接执行",
"complexity": ["low"],
"artifacts": "none",
"steps": [
{ "phase": "clarify", "description": "需求澄清 (AskUser if needed)" },
{ "phase": "auto-select", "description": "任务分析 → 自动选择CLI组合" },
{ "phase": "multi-cli", "description": "并行多CLI分析" },
{ "phase": "decision", "description": "展示结果 → AskUser决策" },
{ "phase": "execute", "description": "直接执行 (无中间文件)" }
],
"cli_hints": {
"analysis": { "tool": "auto", "mode": "analysis", "parallel": true },
"execution": { "tool": "auto", "mode": "write" }
},
"estimated_time": "10-30 min"
},
"rapid": {
"name": "Rapid Iteration",
"level": "L2",
"description": "内存规划 + 直接执行",
"complexity": ["low", "medium"],
"artifacts": "memory://plan",
"steps": [
{ "command": "/workflow:lite-plan", "optional": false, "auto_continue": true },
{ "command": "/workflow:lite-execute", "optional": false }
],
"cli_hints": {
"explore_phase": { "tool": "gemini", "mode": "analysis", "trigger": "needs_exploration" },
"execution": { "tool": "codex", "mode": "write", "trigger": "complexity >= medium" }
},
"estimated_time": "15-45 min"
},
"multi-cli-plan": {
"name": "Multi-CLI Collaborative Planning",
"level": "L2",
"description": "ACE上下文 + 多CLI协作分析 + 迭代收敛 + 计划生成",
"complexity": ["medium", "high"],
"artifacts": ".workflow/.multi-cli-plan/{session}/",
"steps": [
{ "command": "/workflow:multi-cli-plan", "optional": false, "phases": [
"context_gathering: ACE语义搜索",
"multi_cli_discussion: cli-discuss-agent多轮分析",
"present_options: 展示解决方案",
"user_decision: 用户选择",
"plan_generation: cli-lite-planning-agent生成计划"
]},
{ "command": "/workflow:lite-execute", "optional": false }
],
"vs_lite_plan": {
"context": "ACE semantic search vs Manual file patterns",
"analysis": "Multi-CLI cross-verification vs Single-pass planning",
"iteration": "Multiple rounds until convergence vs Single round",
"confidence": "High (consensus-based) vs Medium (single perspective)",
"best_for": "Complex tasks needing multiple perspectives vs Straightforward implementations"
},
"agents": ["cli-discuss-agent", "cli-lite-planning-agent"],
"cli_hints": {
"discussion": { "tools": ["gemini", "codex", "claude"], "mode": "analysis", "parallel": true },
"planning": { "tool": "gemini", "mode": "analysis" }
},
"estimated_time": "30-90 min"
},
"coupled": {
"name": "Standard Planning",
"level": "L3",
"description": "完整规划 + 验证 + 执行",
"complexity": ["medium", "high"],
"artifacts": ".workflow/active/{session}/",
"steps": [
{ "command": "/workflow:plan", "optional": false },
{ "command": "/workflow:plan-verify", "optional": false, "auto_continue": true },
{ "command": "/workflow:execute", "optional": false },
{ "command": "/workflow:review", "optional": true }
],
"cli_hints": {
"pre_analysis": { "tool": "gemini", "mode": "analysis", "trigger": "always" },
"execution": { "tool": "codex", "mode": "write", "trigger": "always" }
},
"estimated_time": "2-4 hours"
},
"full": {
"name": "Full Exploration (Brainstorm)",
"level": "L4",
"description": "头脑风暴 + 规划 + 执行",
"complexity": ["high"],
"artifacts": ".workflow/active/{session}/.brainstorming/",
"steps": [
{ "command": "/workflow:brainstorm:auto-parallel", "optional": false, "confirm_before": true },
{ "command": "/workflow:plan", "optional": false },
{ "command": "/workflow:plan-verify", "optional": true, "auto_continue": true },
{ "command": "/workflow:execute", "optional": false }
],
"cli_hints": {
"role_analysis": { "tool": "gemini", "mode": "analysis", "trigger": "always", "parallel": true },
"execution": { "tool": "codex", "mode": "write", "trigger": "task_count >= 3" }
},
"estimated_time": "1-3 hours"
},
"bugfix": {
"name": "Bug Fix",
"level": "L2",
"description": "智能诊断 + 修复 (5 phases)",
"complexity": ["low", "medium"],
"artifacts": ".workflow/.lite-fix/{bug-slug}-{date}/",
"variants": {
"standard": [{ "command": "/workflow:lite-fix", "optional": false }],
"hotfix": [{ "command": "/workflow:lite-fix --hotfix", "optional": false }]
},
"phases": [
"Phase 1: Bug Analysis & Diagnosis (severity pre-assessment)",
"Phase 2: Clarification (optional, AskUserQuestion)",
"Phase 3: Fix Planning (Low/Medium → Claude, High/Critical → cli-lite-planning-agent)",
"Phase 4: Confirmation & Selection",
"Phase 5: Execute (→ lite-execute --mode bugfix)"
],
"cli_hints": {
"diagnosis": { "tool": "gemini", "mode": "analysis", "trigger": "always" },
"fix": { "tool": "codex", "mode": "write", "trigger": "severity >= medium" }
},
"estimated_time": "10-30 min"
},
"issue": {
"name": "Issue Lifecycle",
"level": "Supplementary",
"description": "发现积累 → 批量规划 → 队列优化 → 并行执行 (Main Workflow 补充机制)",
"complexity": ["medium", "high"],
"artifacts": ".workflow/.issues/",
"purpose": "Post-development continuous maintenance, maintain main branch stability",
"phases": {
"accumulation": {
"description": "项目迭代中持续发现和积累issue",
"commands": ["/issue:discover", "/issue:discover-by-prompt", "/issue:new"],
"trigger": "post-task, code-review, test-failure"
},
"resolution": {
"description": "集中规划和执行积累的issue",
"steps": [
{ "command": "/issue:plan --all-pending", "optional": false },
{ "command": "/issue:queue", "optional": false },
{ "command": "/issue:execute", "optional": false }
]
}
},
"worktree_support": {
"description": "可选的 worktree 隔离,保持主分支稳定",
"use_case": "主开发完成后的 issue 修复"
},
"cli_hints": {
"discovery": { "tool": "gemini", "mode": "analysis", "trigger": "perspective_analysis", "parallel": true },
"solution_generation": { "tool": "gemini", "mode": "analysis", "trigger": "always", "parallel": true },
"batch_execution": { "tool": "codex", "mode": "write", "trigger": "always" }
},
"estimated_time": "1-4 hours"
},
"tdd": {
"name": "Test-Driven Development",
"level": "L3",
"description": "TDD规划 + 执行 + 验证 (6 phases)",
"complexity": ["medium", "high"],
"artifacts": ".workflow/active/{session}/",
"steps": [
{ "command": "/workflow:tdd-plan", "optional": false },
{ "command": "/workflow:plan-verify", "optional": true, "auto_continue": true },
{ "command": "/workflow:execute", "optional": false },
{ "command": "/workflow:tdd-verify", "optional": false }
],
"tdd_structure": {
"description": "Each IMPL task contains complete internal Red-Green-Refactor cycle",
"meta": "tdd_workflow: true",
"flow_control": "implementation_approach contains 3 steps (red/green/refactor)"
},
"cli_hints": {
"test_strategy": { "tool": "gemini", "mode": "analysis", "trigger": "always" },
"red_green_refactor": { "tool": "codex", "mode": "write", "trigger": "always" }
},
"estimated_time": "1-3 hours"
},
"test-fix": {
"name": "Test Fix Generation",
"level": "L3",
"description": "测试修复生成 + 执行循环 (5 phases)",
"complexity": ["medium", "high"],
"artifacts": ".workflow/active/WFS-test-{session}/",
"dual_mode": {
"session_mode": { "input": "WFS-xxx", "context_source": "Source session summaries" },
"prompt_mode": { "input": "Text/file path", "context_source": "Direct codebase analysis" }
},
"steps": [
{ "command": "/workflow:test-fix-gen", "optional": false },
{ "command": "/workflow:test-cycle-execute", "optional": false }
],
"task_structure": [
"IMPL-001.json (test understanding & generation)",
"IMPL-001.5-review.json (quality gate)",
"IMPL-002.json (test execution & fix cycle)"
],
"cli_hints": {
"analysis": { "tool": "gemini", "mode": "analysis", "trigger": "always" },
"fix_cycle": { "tool": "codex", "mode": "write", "trigger": "pass_rate < 0.95" }
},
"estimated_time": "1-2 hours"
},
"ui": {
"name": "UI-First Development",
"level": "L3/L4",
"description": "UI设计 + 规划 + 执行",
"complexity": ["medium", "high"],
"artifacts": ".workflow/active/{session}/",
"variants": {
"explore": [
{ "command": "/workflow:ui-design:explore-auto", "optional": false },
{ "command": "/workflow:ui-design:design-sync", "optional": false, "auto_continue": true },
{ "command": "/workflow:plan", "optional": false },
{ "command": "/workflow:execute", "optional": false }
],
"imitate": [
{ "command": "/workflow:ui-design:imitate-auto", "optional": false },
{ "command": "/workflow:ui-design:design-sync", "optional": false, "auto_continue": true },
{ "command": "/workflow:plan", "optional": false },
{ "command": "/workflow:execute", "optional": false }
]
},
"estimated_time": "2-4 hours"
},
"review-fix": {
"name": "Review and Fix",
"level": "L3",
"description": "多维审查 + 自动修复",
"complexity": ["medium"],
"artifacts": ".workflow/active/{session}/review_report.md",
"steps": [
{ "command": "/workflow:review-session-cycle", "optional": false },
{ "command": "/workflow:review-fix", "optional": true }
],
"cli_hints": {
"multi_dimension_review": { "tool": "gemini", "mode": "analysis", "trigger": "always", "parallel": true },
"auto_fix": { "tool": "codex", "mode": "write", "trigger": "findings_count >= 3" }
},
"estimated_time": "30-90 min"
},
"docs": {
"name": "Documentation",
"level": "L2",
"description": "批量文档生成",
"complexity": ["low", "medium"],
"variants": {
"incremental": [{ "command": "/memory:update-related", "optional": false }],
"full": [
{ "command": "/memory:docs", "optional": false },
{ "command": "/workflow:execute", "optional": false }
]
},
"estimated_time": "15-60 min"
}
},
"intent_rules": {
"_level_mapping": {
"description": "Intent → Level → Flow mapping guide",
"L1": ["lite-lite-lite"],
"L2": ["rapid", "bugfix", "multi-cli-plan", "docs"],
"L3": ["coupled", "tdd", "test-fix", "review-fix", "ui"],
"L4": ["full"],
"Supplementary": ["issue"]
},
"bugfix": {
"priority": 1,
"level": "L2",
"variants": {
"hotfix": {
"patterns": ["hotfix", "urgent", "production", "critical", "emergency", "紧急", "生产环境", "线上"],
"flow": "bugfix.hotfix"
},
"standard": {
"patterns": ["fix", "bug", "error", "issue", "crash", "broken", "fail", "wrong", "修复", "错误", "崩溃"],
"flow": "bugfix.standard"
}
}
},
"issue_batch": {
"priority": 2,
"level": "Supplementary",
"patterns": {
"batch": ["issues", "batch", "queue", "多个", "批量"],
"action": ["fix", "resolve", "处理", "解决"]
},
"require_both": true,
"flow": "issue"
},
"exploration": {
"priority": 3,
"level": "L4",
"patterns": ["不确定", "不知道", "explore", "研究", "分析一下", "怎么做", "what if", "探索"],
"flow": "full"
},
"multi_perspective": {
"priority": 3,
"level": "L2",
"patterns": ["多视角", "权衡", "比较方案", "cross-verify", "多CLI", "协作分析"],
"flow": "multi-cli-plan"
},
"quick_task": {
"priority": 4,
"level": "L1",
"patterns": ["快速", "简单", "small", "quick", "simple", "trivial", "小改动"],
"flow": "lite-lite-lite"
},
"ui_design": {
"priority": 5,
"level": "L3/L4",
"patterns": ["ui", "界面", "design", "设计", "component", "组件", "style", "样式", "layout", "布局"],
"variants": {
"imitate": { "triggers": ["参考", "模仿", "像", "类似"], "flow": "ui.imitate" },
"explore": { "triggers": [], "flow": "ui.explore" }
}
},
"tdd": {
"priority": 6,
"level": "L3",
"patterns": ["tdd", "test-driven", "测试驱动", "先写测试", "test first"],
"flow": "tdd"
},
"test_fix": {
"priority": 7,
"level": "L3",
"patterns": ["测试失败", "test fail", "fix test", "test error", "pass rate", "coverage gap"],
"flow": "test-fix"
},
"review": {
"priority": 8,
"level": "L3",
"patterns": ["review", "审查", "检查代码", "code review", "质量检查"],
"flow": "review-fix"
},
"documentation": {
"priority": 9,
"level": "L2",
"patterns": ["文档", "documentation", "docs", "readme"],
"variants": {
"incremental": { "triggers": ["更新", "增量"], "flow": "docs.incremental" },
"full": { "triggers": ["全部", "完整"], "flow": "docs.full" }
}
},
"feature": {
"priority": 99,
"complexity_map": {
"high": { "level": "L3", "flow": "coupled" },
"medium": { "level": "L2", "flow": "rapid" },
"low": { "level": "L1", "flow": "lite-lite-lite" }
}
}
},
"complexity_indicators": {
"high": {
"threshold": 4,
"patterns": {
"architecture": { "keywords": ["refactor", "重构", "migrate", "迁移", "architect", "架构", "system", "系统"], "weight": 2 },
"multi_module": { "keywords": ["multiple", "多个", "across", "跨", "all", "所有", "entire", "整个"], "weight": 2 },
"integration": { "keywords": ["integrate", "集成", "api", "database", "数据库"], "weight": 1 },
"quality": { "keywords": ["security", "安全", "performance", "性能", "scale", "扩展"], "weight": 1 }
}
},
"medium": { "threshold": 2 },
"low": { "threshold": 0 }
},
"cli_tools": {
"gemini": {
"strengths": ["超长上下文", "深度分析", "架构理解", "执行流追踪"],
"triggers": ["分析", "理解", "设计", "架构", "诊断"],
"mode": "analysis"
},
"qwen": {
"strengths": ["代码模式识别", "多维度分析"],
"triggers": ["评估", "对比", "验证"],
"mode": "analysis"
},
"codex": {
"strengths": ["精确代码生成", "自主执行"],
"triggers": ["实现", "重构", "修复", "生成"],
"mode": "write"
}
},
"cli_injection_rules": {
"context_gathering": { "trigger": "file_read >= 50k OR module_count >= 5", "inject": "gemini --mode analysis" },
"pre_planning_analysis": { "trigger": "complexity === high", "inject": "gemini --mode analysis" },
"debug_diagnosis": { "trigger": "intent === bugfix AND root_cause_unclear", "inject": "gemini --mode analysis" },
"code_review": { "trigger": "step === review", "inject": "gemini --mode analysis" },
"implementation": { "trigger": "step === execute AND task_count >= 3", "inject": "codex --mode write" }
},
"artifact_flow": {
"_description": "定义工作流产出的格式、意图提取和流转规则",
"outputs": {
"/workflow:lite-plan": {
"artifact": "memory://plan",
"format": "structured_plan",
"fields": ["tasks", "files", "dependencies", "approach"]
},
"/workflow:plan": {
"artifact": ".workflow/{session}/IMPL_PLAN.md",
"format": "markdown_plan",
"fields": ["phases", "tasks", "dependencies", "risks", "test_strategy"]
},
"/workflow:multi-cli-plan": {
"artifact": ".workflow/.multi-cli-plan/{session}/",
"format": "multi_file",
"files": ["IMPL_PLAN.md", "plan.json", "synthesis.json"],
"fields": ["consensus", "divergences", "recommended_approach", "tasks"]
},
"/workflow:lite-execute": {
"artifact": "git_changes",
"format": "code_diff",
"fields": ["modified_files", "added_files", "deleted_files", "build_status"]
},
"/workflow:execute": {
"artifact": ".workflow/{session}/execution_log.json",
"format": "execution_report",
"fields": ["completed_tasks", "pending_tasks", "errors", "warnings"]
},
"/workflow:test-cycle-execute": {
"artifact": ".workflow/{session}/test_results.json",
"format": "test_report",
"fields": ["pass_rate", "failures", "coverage", "duration"]
},
"/workflow:review-session-cycle": {
"artifact": ".workflow/{session}/review_report.md",
"format": "review_report",
"fields": ["findings", "severity_counts", "recommendations"]
},
"/workflow:lite-fix": {
"artifact": "git_changes",
"format": "fix_report",
"fields": ["root_cause", "fix_applied", "files_modified", "verification_status"]
}
},
"intent_extraction": {
"plan_to_execute": {
"from": ["lite-plan", "plan", "multi-cli-plan"],
"to": ["lite-execute", "execute"],
"extract": {
"tasks": "$.tasks[] | filter(status != 'completed')",
"priority_order": "$.tasks | sort_by(priority)",
"files_to_modify": "$.tasks[].files | flatten | unique",
"dependencies": "$.dependencies",
"context_summary": "$.approach OR $.recommended_approach"
}
},
"execute_to_test": {
"from": ["lite-execute", "execute"],
"to": ["test-cycle-execute", "test-fix-gen"],
"extract": {
"modified_files": "$.modified_files",
"test_scope": "infer_from($.modified_files)",
"build_status": "$.build_status",
"pending_verification": "$.completed_tasks | needs_test"
}
},
"test_to_fix": {
"from": ["test-cycle-execute"],
"to": ["lite-fix", "review-fix"],
"condition": "$.pass_rate < 0.95",
"extract": {
"failures": "$.failures",
"error_messages": "$.failures[].message",
"affected_files": "$.failures[].file",
"suggested_fixes": "$.failures[].suggested_fix"
}
},
"review_to_fix": {
"from": ["review-session-cycle", "review-module-cycle"],
"to": ["review-fix"],
"condition": "$.severity_counts.critical > 0 OR $.severity_counts.high > 3",
"extract": {
"findings": "$.findings | filter(severity in ['critical', 'high'])",
"fix_priority": "$.findings | group_by(category) | sort_by(severity)",
"affected_files": "$.findings[].file | unique"
}
}
},
"completion_criteria": {
"plan": {
"required": ["has_tasks", "has_files"],
"optional": ["has_tests", "no_blocking_risks"],
"threshold": 0.8,
"routing": {
"complete": "proceed_to_execute",
"incomplete": "clarify_requirements"
}
},
"execute": {
"required": ["all_tasks_attempted", "no_critical_errors"],
"optional": ["build_passes", "lint_passes"],
"threshold": 1.0,
"routing": {
"complete": "proceed_to_test_or_review",
"partial": "continue_execution",
"failed": "diagnose_and_retry"
}
},
"test": {
"metrics": {
"pass_rate": { "target": 0.95, "minimum": 0.80 },
"coverage": { "target": 0.80, "minimum": 0.60 }
},
"routing": {
"pass_rate >= 0.95 AND coverage >= 0.80": "complete",
"pass_rate >= 0.95 AND coverage < 0.80": "add_more_tests",
"pass_rate >= 0.80": "fix_failures_then_continue",
"pass_rate < 0.80": "major_fix_required"
}
},
"review": {
"metrics": {
"critical_findings": { "target": 0, "maximum": 0 },
"high_findings": { "target": 0, "maximum": 3 }
},
"routing": {
"critical == 0 AND high <= 3": "complete_or_optional_fix",
"critical > 0": "mandatory_fix",
"high > 3": "recommended_fix"
}
}
},
"flow_decisions": {
"_description": "根据产出完成度决定下一步",
"patterns": {
"plan_execute_test": {
"sequence": ["plan", "execute", "test"],
"on_test_fail": {
"action": "extract_failures_and_fix",
"max_iterations": 3,
"fallback": "manual_intervention"
}
},
"plan_execute_review": {
"sequence": ["plan", "execute", "review"],
"on_review_issues": {
"action": "prioritize_and_fix",
"auto_fix_threshold": "severity < high"
}
},
"iterative_improvement": {
"sequence": ["execute", "test", "fix"],
"loop_until": "pass_rate >= 0.95 OR iterations >= 3",
"on_loop_exit": "report_status"
}
}
}
}
}

View File

@@ -0,0 +1,669 @@
/**
* CommandRegistry Tests
*
* Test coverage:
* - YAML header parsing
* - Command metadata extraction
* - Directory detection (relative and home)
* - Caching mechanism
* - Batch operations
* - Categorization
* - Error handling
*/
import { CommandRegistry, createCommandRegistry, getAllCommandsSync, getCommandSync } from './command-registry';
import * as fs from 'fs';
import * as path from 'path';
import * as os from 'os';
// Mock fs module
jest.mock('fs');
jest.mock('os');
describe('CommandRegistry', () => {
const mockReadFileSync = fs.readFileSync as jest.MockedFunction<typeof fs.readFileSync>;
const mockExistsSync = fs.existsSync as jest.MockedFunction<typeof fs.existsSync>;
const mockReaddirSync = fs.readdirSync as jest.MockedFunction<typeof fs.readdirSync>;
const mockStatSync = fs.statSync as jest.MockedFunction<typeof fs.statSync>;
const mockHomedir = os.homedir as jest.MockedFunction<typeof os.homedir>;
// Sample YAML headers
const sampleLitePlanYaml = `---
name: lite-plan
description: Quick planning for simple features
argument-hint: "\"feature description\""
allowed-tools: Task(*), Read(*), Write(*), Bash(*)
---
# Content here`;
const sampleExecuteYaml = `---
name: execute
description: Execute implementation from plan
argument-hint: "--resume-session=\"WFS-xxx\""
allowed-tools: Task(*), Bash(*)
---
# Content here`;
const sampleTestYaml = `---
name: test-cycle-execute
description: Run tests and fix failures
argument-hint: "--session=\"WFS-xxx\""
allowed-tools: Task(*), Bash(*)
---
# Content here`;
const sampleReviewYaml = `---
name: review
description: Code review workflow
argument-hint: "--session=\"WFS-xxx\""
allowed-tools: Task(*), Read(*)
---
# Content here`;
beforeEach(() => {
jest.clearAllMocks();
});
describe('constructor & directory detection', () => {
it('should use provided command directory', () => {
const customDir = '/custom/path';
const registry = new CommandRegistry(customDir);
expect((registry as any).commandDir).toBe(customDir);
});
it('should auto-detect relative .claude/commands/workflow directory', () => {
mockExistsSync.mockImplementation((path: string) => {
return path === '.claude/commands/workflow';
});
const registry = new CommandRegistry();
expect((registry as any).commandDir).toBe('.claude/commands/workflow');
expect(mockExistsSync).toHaveBeenCalledWith('.claude/commands/workflow');
});
it('should auto-detect home directory ~/.claude/commands/workflow', () => {
mockExistsSync.mockImplementation((checkPath: string) => {
return checkPath === path.join('/home/user', '.claude', 'commands', 'workflow');
});
mockHomedir.mockReturnValue('/home/user');
const registry = new CommandRegistry();
expect((registry as any).commandDir).toBe(
path.join('/home/user', '.claude', 'commands', 'workflow')
);
});
it('should return null if no command directory found', () => {
mockExistsSync.mockReturnValue(false);
mockHomedir.mockReturnValue('/home/user');
const registry = new CommandRegistry();
expect((registry as any).commandDir).toBeNull();
});
});
describe('parseYamlHeader', () => {
it('should parse simple YAML header with Unix line endings', () => {
const yaml = `---
name: test-command
description: Test description
argument-hint: "\"test\""
allowed-tools: Task(*), Read(*)
---
Content here`;
const registry = new CommandRegistry('/fake/path');
const result = (registry as any).parseYamlHeader(yaml);
expect(result).toEqual({
name: 'test-command',
description: 'Test description',
'argument-hint': '"test"',
'allowed-tools': 'Task(*), Read(*)'
});
});
it('should parse YAML header with Windows line endings (\\r\\n)', () => {
const yaml = `---\r\nname: test-command\r\ndescription: Test\r\n---`;
const registry = new CommandRegistry('/fake/path');
const result = (registry as any).parseYamlHeader(yaml);
expect(result).toEqual({
name: 'test-command',
description: 'Test'
});
});
it('should handle quoted values', () => {
const yaml = `---
name: "cmd"
description: 'double quoted'
---`;
const registry = new CommandRegistry('/fake/path');
const result = (registry as any).parseYamlHeader(yaml);
expect(result).toEqual({
name: 'cmd',
description: 'double quoted'
});
});
it('should parse allowed-tools and trim spaces', () => {
const yaml = `---
name: test
allowed-tools: Task(*), Read(*) , Write(*), Bash(*)
---`;
const registry = new CommandRegistry('/fake/path');
const result = (registry as any).parseYamlHeader(yaml);
expect(result['allowed-tools']).toBe('Task(*), Read(*), Write(*), Bash(*)');
});
it('should skip comments and empty lines', () => {
const yaml = `---
# This is a comment
name: test-command
# Another comment
description: Test
---`;
const registry = new CommandRegistry('/fake/path');
const result = (registry as any).parseYamlHeader(yaml);
expect(result).toEqual({
name: 'test-command',
description: 'Test'
});
});
it('should return null for missing YAML markers', () => {
const yaml = `name: test-command
description: Test`;
const registry = new CommandRegistry('/fake/path');
const result = (registry as any).parseYamlHeader(yaml);
expect(result).toBeNull();
});
it('should return null for malformed YAML', () => {
const yaml = `---
invalid yaml content without colons
---`;
const registry = new CommandRegistry('/fake/path');
const result = (registry as any).parseYamlHeader(yaml);
expect(result).toEqual({});
});
});
describe('getCommand', () => {
it('should get command metadata by name', () => {
const cmdDir = '/workflows';
mockExistsSync.mockImplementation((checkPath: string) => {
return checkPath === path.join(cmdDir, 'lite-plan.md');
});
mockReadFileSync.mockReturnValue(sampleLitePlanYaml);
const registry = new CommandRegistry(cmdDir);
const result = registry.getCommand('lite-plan');
expect(result).toEqual({
name: 'lite-plan',
command: '/workflow:lite-plan',
description: 'Quick planning for simple features',
argumentHint: '"feature description"',
allowedTools: ['Task(*)', 'Read(*)', 'Write(*)', 'Bash(*)'],
filePath: path.join(cmdDir, 'lite-plan.md')
});
});
it('should normalize /workflow: prefix', () => {
const cmdDir = '/workflows';
mockExistsSync.mockReturnValue(true);
mockReadFileSync.mockReturnValue(sampleLitePlanYaml);
const registry = new CommandRegistry(cmdDir);
const result = registry.getCommand('/workflow:lite-plan');
expect(result?.name).toBe('lite-plan');
});
it('should use cache for repeated requests', () => {
const cmdDir = '/workflows';
mockExistsSync.mockReturnValue(true);
mockReadFileSync.mockReturnValue(sampleLitePlanYaml);
const registry = new CommandRegistry(cmdDir);
registry.getCommand('lite-plan');
registry.getCommand('lite-plan');
// readFileSync should only be called once due to cache
expect(mockReadFileSync).toHaveBeenCalledTimes(1);
});
it('should return null if command file not found', () => {
const cmdDir = '/workflows';
mockExistsSync.mockReturnValue(false);
const registry = new CommandRegistry(cmdDir);
const result = registry.getCommand('nonexistent');
expect(result).toBeNull();
});
it('should return null if no command directory', () => {
mockExistsSync.mockReturnValue(false);
mockHomedir.mockReturnValue('/home/user');
const registry = new CommandRegistry();
const result = registry.getCommand('lite-plan');
expect(result).toBeNull();
});
it('should return null if YAML header is invalid', () => {
const cmdDir = '/workflows';
mockExistsSync.mockReturnValue(true);
mockReadFileSync.mockReturnValue('No YAML header here');
const registry = new CommandRegistry(cmdDir);
const result = registry.getCommand('lite-plan');
expect(result).toBeNull();
});
it('should parse allowedTools correctly', () => {
const cmdDir = '/workflows';
mockExistsSync.mockReturnValue(true);
mockReadFileSync.mockReturnValue(sampleExecuteYaml);
const registry = new CommandRegistry(cmdDir);
const result = registry.getCommand('execute');
expect(result?.allowedTools).toEqual(['Task(*)', 'Bash(*)']);
});
it('should handle empty allowedTools', () => {
const yaml = `---
name: minimal-cmd
description: Minimal command
---`;
const cmdDir = '/workflows';
mockExistsSync.mockReturnValue(true);
mockReadFileSync.mockReturnValue(yaml);
const registry = new CommandRegistry(cmdDir);
const result = registry.getCommand('minimal-cmd');
expect(result?.allowedTools).toEqual([]);
});
});
describe('getCommands', () => {
it('should get multiple commands', () => {
const cmdDir = '/workflows';
mockExistsSync.mockReturnValue(true);
mockReadFileSync.mockImplementation((filePath: string) => {
if (filePath.includes('lite-plan')) return sampleLitePlanYaml;
if (filePath.includes('execute')) return sampleExecuteYaml;
return '';
});
const registry = new CommandRegistry(cmdDir);
const result = registry.getCommands(['lite-plan', 'execute', 'nonexistent']);
expect(result.size).toBe(2);
expect(result.has('/workflow:lite-plan')).toBe(true);
expect(result.has('/workflow:execute')).toBe(true);
});
it('should skip nonexistent commands', () => {
const cmdDir = '/workflows';
mockExistsSync.mockReturnValue(false);
const registry = new CommandRegistry(cmdDir);
const result = registry.getCommands(['nonexistent1', 'nonexistent2']);
expect(result.size).toBe(0);
});
});
describe('getAllCommandsSummary', () => {
it('should get all commands summary', () => {
const cmdDir = '/workflows';
mockExistsSync.mockReturnValue(true);
mockReaddirSync.mockReturnValue(['lite-plan.md', 'execute.md', 'test.md'] as any);
mockStatSync.mockReturnValue({ isDirectory: () => false } as any);
mockReadFileSync.mockImplementation((filePath: string) => {
if (filePath.includes('lite-plan')) return sampleLitePlanYaml;
if (filePath.includes('execute')) return sampleExecuteYaml;
if (filePath.includes('test')) return sampleTestYaml;
return '';
});
const registry = new CommandRegistry(cmdDir);
const result = registry.getAllCommandsSummary();
expect(result.size).toBe(3);
expect(result.get('/workflow:lite-plan')).toEqual({
name: 'lite-plan',
description: 'Quick planning for simple features'
});
});
it('should skip directories', () => {
const cmdDir = '/workflows';
mockExistsSync.mockReturnValue(true);
mockReaddirSync.mockReturnValue(['file.md', 'directory'] as any);
mockStatSync.mockImplementation((filePath: string) => ({
isDirectory: () => filePath.includes('directory')
} as any));
mockReadFileSync.mockReturnValue(sampleLitePlanYaml);
const registry = new CommandRegistry(cmdDir);
const result = registry.getAllCommandsSummary();
// Only file.md should be processed
expect(mockReadFileSync).toHaveBeenCalledTimes(1);
});
it('should skip files with invalid YAML headers', () => {
const cmdDir = '/workflows';
mockExistsSync.mockReturnValue(true);
mockReaddirSync.mockReturnValue(['valid.md', 'invalid.md'] as any);
mockStatSync.mockReturnValue({ isDirectory: () => false } as any);
mockReadFileSync.mockImplementation((filePath: string) => {
if (filePath.includes('valid')) return sampleLitePlanYaml;
return 'No YAML header';
});
const registry = new CommandRegistry(cmdDir);
const result = registry.getAllCommandsSummary();
expect(result.size).toBe(1);
});
it('should return empty map if no command directory', () => {
mockExistsSync.mockReturnValue(false);
mockHomedir.mockReturnValue('/home/user');
const registry = new CommandRegistry();
const result = registry.getAllCommandsSummary();
expect(result.size).toBe(0);
});
it('should handle directory read errors gracefully', () => {
const cmdDir = '/workflows';
mockExistsSync.mockReturnValue(true);
mockReaddirSync.mockImplementation(() => {
throw new Error('Permission denied');
});
const registry = new CommandRegistry(cmdDir);
const result = registry.getAllCommandsSummary();
expect(result.size).toBe(0);
});
});
describe('getAllCommandsByCategory', () => {
it('should categorize commands by name patterns', () => {
const cmdDir = '/workflows';
mockExistsSync.mockReturnValue(true);
mockReaddirSync.mockReturnValue(['lite-plan.md', 'execute.md', 'test-cycle-execute.md', 'review.md'] as any);
mockStatSync.mockReturnValue({ isDirectory: () => false } as any);
mockReadFileSync.mockImplementation((filePath: string) => {
if (filePath.includes('lite-plan')) return sampleLitePlanYaml;
if (filePath.includes('execute')) return sampleExecuteYaml;
if (filePath.includes('test')) return sampleTestYaml;
if (filePath.includes('review')) return sampleReviewYaml;
return '';
});
const registry = new CommandRegistry(cmdDir);
const result = registry.getAllCommandsByCategory();
expect(result.planning.length).toBe(1);
expect(result.execution.length).toBe(1);
expect(result.testing.length).toBe(1);
expect(result.review.length).toBe(1);
expect(result.other.length).toBe(0);
expect(result.planning[0].name).toBe('lite-plan');
expect(result.execution[0].name).toBe('execute');
});
it('should handle commands matching multiple patterns', () => {
const yamlMultiMatch = `---
name: test-plan
description: TDD planning
allowed-tools: Task(*)
---`;
const cmdDir = '/workflows';
mockExistsSync.mockReturnValue(true);
mockReaddirSync.mockReturnValue(['test-plan.md'] as any);
mockStatSync.mockReturnValue({ isDirectory: () => false } as any);
mockReadFileSync.mockReturnValue(yamlMultiMatch);
const registry = new CommandRegistry(cmdDir);
const result = registry.getAllCommandsByCategory();
// Should match 'plan' pattern (planning)
expect(result.planning.length).toBe(1);
});
});
describe('toJSON', () => {
it('should serialize cached commands to JSON', () => {
const cmdDir = '/workflows';
mockExistsSync.mockReturnValue(true);
mockReadFileSync.mockReturnValue(sampleLitePlanYaml);
const registry = new CommandRegistry(cmdDir);
registry.getCommand('lite-plan');
const json = registry.toJSON();
expect(json['/workflow:lite-plan']).toEqual({
name: 'lite-plan',
command: '/workflow:lite-plan',
description: 'Quick planning for simple features',
argumentHint: '"feature description"',
allowedTools: ['Task(*)', 'Read(*)', 'Write(*)', 'Bash(*)'],
filePath: path.join(cmdDir, 'lite-plan.md')
});
});
it('should only include cached commands', () => {
const cmdDir = '/workflows';
mockExistsSync.mockReturnValue(true);
mockReadFileSync.mockImplementation((filePath: string) => {
if (filePath.includes('lite-plan')) return sampleLitePlanYaml;
return sampleExecuteYaml;
});
const registry = new CommandRegistry(cmdDir);
registry.getCommand('lite-plan');
// Don't call getCommand for 'execute'
const json = registry.toJSON();
expect(Object.keys(json).length).toBe(1);
expect(json['/workflow:lite-plan']).toBeDefined();
expect(json['/workflow:execute']).toBeUndefined();
});
});
describe('exported functions', () => {
it('createCommandRegistry should create new instance', () => {
mockExistsSync.mockReturnValue(true);
const registry = createCommandRegistry('/custom/path');
expect((registry as any).commandDir).toBe('/custom/path');
});
it('getAllCommandsSync should return all commands', () => {
mockExistsSync.mockReturnValue(true);
mockReaddirSync.mockReturnValue(['lite-plan.md'] as any);
mockStatSync.mockReturnValue({ isDirectory: () => false } as any);
mockReadFileSync.mockReturnValue(sampleLitePlanYaml);
mockHomedir.mockReturnValue('/home/user');
const result = getAllCommandsSync();
expect(result.size).toBeGreaterThanOrEqual(1);
});
it('getCommandSync should return specific command', () => {
mockExistsSync.mockReturnValue(true);
mockReadFileSync.mockReturnValue(sampleLitePlanYaml);
mockHomedir.mockReturnValue('/home/user');
const result = getCommandSync('lite-plan');
expect(result?.name).toBe('lite-plan');
});
});
describe('edge cases', () => {
it('should handle file read errors', () => {
const cmdDir = '/workflows';
mockExistsSync.mockReturnValue(true);
mockReadFileSync.mockImplementation(() => {
throw new Error('File read error');
});
const registry = new CommandRegistry(cmdDir);
const result = registry.getCommand('lite-plan');
expect(result).toBeNull();
});
it('should handle YAML parsing errors', () => {
const cmdDir = '/workflows';
mockExistsSync.mockReturnValue(true);
// Return something that will cause parsing to fail
mockReadFileSync.mockReturnValue('---\ninvalid: : : yaml\n---');
const registry = new CommandRegistry(cmdDir);
const result = registry.getCommand('lite-plan');
// Should return null since name is not in result
expect(result).toBeNull();
});
it('should handle empty command directory', () => {
const cmdDir = '/workflows';
mockExistsSync.mockReturnValue(true);
mockReaddirSync.mockReturnValue([] as any);
const registry = new CommandRegistry(cmdDir);
const result = registry.getAllCommandsSummary();
expect(result.size).toBe(0);
});
it('should handle non-md files in command directory', () => {
const cmdDir = '/workflows';
mockExistsSync.mockReturnValue(true);
mockReaddirSync.mockReturnValue(['lite-plan.md', 'readme.txt', '.gitignore'] as any);
mockStatSync.mockReturnValue({ isDirectory: () => false } as any);
mockReadFileSync.mockReturnValue(sampleLitePlanYaml);
const registry = new CommandRegistry(cmdDir);
const result = registry.getAllCommandsSummary();
expect(result.size).toBe(1);
});
});
describe('integration tests', () => {
it('should work with full workflow', () => {
const cmdDir = '/workflows';
mockExistsSync.mockReturnValue(true);
mockReaddirSync.mockReturnValue(['lite-plan.md', 'execute.md', 'test-cycle-execute.md'] as any);
mockStatSync.mockReturnValue({ isDirectory: () => false } as any);
mockReadFileSync.mockImplementation((filePath: string) => {
if (filePath.includes('lite-plan')) return sampleLitePlanYaml;
if (filePath.includes('execute')) return sampleExecuteYaml;
if (filePath.includes('test')) return sampleTestYaml;
return '';
});
const registry = new CommandRegistry(cmdDir);
// Get all summary
const summary = registry.getAllCommandsSummary();
expect(summary.size).toBe(3);
// Get by category
const byCategory = registry.getAllCommandsByCategory();
expect(byCategory.planning.length).toBe(1);
expect(byCategory.execution.length).toBe(1);
expect(byCategory.testing.length).toBe(1);
// Get specific command
const cmd = registry.getCommand('lite-plan');
expect(cmd?.name).toBe('lite-plan');
// Get multiple commands
const multiple = registry.getCommands(['lite-plan', 'execute']);
expect(multiple.size).toBe(2);
// Convert to JSON
const json = registry.toJSON();
expect(Object.keys(json).length).toBeGreaterThan(0);
});
it('should maintain cache across operations', () => {
const cmdDir = '/workflows';
mockExistsSync.mockReturnValue(true);
mockReaddirSync.mockReturnValue(['lite-plan.md', 'execute.md'] as any);
mockStatSync.mockReturnValue({ isDirectory: () => false } as any);
mockReadFileSync.mockImplementation((filePath: string) => {
if (filePath.includes('lite-plan')) return sampleLitePlanYaml;
return sampleExecuteYaml;
});
const registry = new CommandRegistry(cmdDir);
// First call
registry.getCommand('lite-plan');
const initialCallCount = mockReadFileSync.mock.calls.length;
// getAllCommandsSummary will read all files
registry.getAllCommandsSummary();
const afterSummaryCallCount = mockReadFileSync.mock.calls.length;
// Second getCommand should use cache
registry.getCommand('lite-plan');
const finalCallCount = mockReadFileSync.mock.calls.length;
// lite-plan.md should only be read twice:
// 1. Initial getCommand
// 2. getAllCommandsSummary (must read all files)
// Not again in second getCommand due to cache
expect(finalCallCount).toBe(afterSummaryCallCount);
});
});
});