mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-05 01:50:27 +08:00
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:
664
.claude/commands/ccw.md
Normal file
664
.claude/commands/ccw.md
Normal 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"
|
||||
```
|
||||
@@ -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**
|
||||
@@ -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 智能推荐基于任务分析,非查表静态推荐
|
||||
@@ -1,9 +0,0 @@
|
||||
# action-abort
|
||||
|
||||
中止会话,保存状态
|
||||
|
||||
```javascript
|
||||
updateState({ status: 'aborted' });
|
||||
|
||||
console.log(`会话已中止: ${workDir}`);
|
||||
```
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
```
|
||||
@@ -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
|
||||
@@ -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' });
|
||||
```
|
||||
@@ -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}`);
|
||||
```
|
||||
@@ -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++;
|
||||
}
|
||||
```
|
||||
@@ -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++`
|
||||
@@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -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" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
@@ -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-verify(TDD 验证)
|
||||
|
||||
**模板**:
|
||||
```
|
||||
任务: {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
|
||||
```
|
||||
@@ -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`。
|
||||
@@ -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 目录)
|
||||
|
||||
|
||||
|
||||
@@ -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 };
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
669
ccw/src/tools/command-registry.test.ts
Normal file
669
ccw/src/tools/command-registry.test.ts
Normal 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);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user