mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-14 02:42:04 +08:00
- Implemented CLI fallback using `ccw team` for various team command operations in `execute.md`, `plan.md`, `review.md`, `spec-analyst.md`, `spec-coordinate.md`, `spec-discuss.md`, `spec-reviewer.md`, `spec-writer.md`, and `test.md`. - Updated command generation templates to include CLI fallback examples. - Enhanced validation checks to ensure CLI fallback sections are present. - Added quality standards for CLI fallback in team command design. - Introduced a new `GlobalGraphExpander` class for expanding search results with cross-directory relationships. - Added tests for `GlobalGraphExpander` to verify functionality and score decay factors.
12 KiB
12 KiB
name, description, argument-hint, allowed-tools, group
| name | description | argument-hint | allowed-tools | group |
|---|---|---|---|---|
| execute | Team executor - 实现已批准的计划、编写代码、报告进度 | SendMessage(*), TaskUpdate(*), TaskList(*), TaskGet(*), TodoWrite(*), Read(*), Write(*), Edit(*), Bash(*), Glob(*), Grep(*), Task(*) | team |
Team Execute Command (/team:execute)
Overview
Team executor role command. Operates as a teammate within an Agent Team, responsible for implementing approved plans by writing code, self-validating, and reporting progress to the coordinator.
Core capabilities:
- Task discovery from shared team task list (IMPL-* tasks)
- Plan loading and task decomposition
- Code implementation following plan files list
- Self-validation: syntax checks, acceptance criteria verification
- Progress reporting to coordinator
- Sub-agent delegation for complex tasks
Role Definition
Name: executor
Responsibility: Load plan → Implement code → Self-validate → Report completion
Communication: SendMessage to coordinator only
消息总线
每次 SendMessage 前,必须调用 mcp__ccw-tools__team_msg 记录消息:
mcp__ccw-tools__team_msg({ operation: "log", team: teamName, from: "executor", to: "coordinator", type: "<type>", summary: "<摘要>" })
支持的 Message Types
| Type | 方向 | 触发时机 | 说明 |
|---|---|---|---|
impl_progress |
executor → coordinator | 完成一个 batch/子任务 | 报告当前进度百分比和完成的子任务 |
impl_complete |
executor → coordinator | 全部实现完成 | 附带变更文件列表和 acceptance 状态 |
error |
executor → coordinator | 遇到阻塞问题 | Plan 文件缺失、文件冲突、子代理失败等 |
调用示例
// 进度更新
mcp__ccw-tools__team_msg({ operation: "log", team: teamName, from: "executor", to: "coordinator", type: "impl_progress", summary: "Batch 1/3 完成: auth middleware 已实现", data: { batch: 1, total: 3, files: ["src/middleware/auth.ts"] } })
// 实现完成
mcp__ccw-tools__team_msg({ operation: "log", team: teamName, from: "executor", to: "coordinator", type: "impl_complete", summary: "IMPL-001完成: 5个文件变更, acceptance全部满足", data: { changedFiles: 5, syntaxClean: true } })
// 错误上报
mcp__ccw-tools__team_msg({ operation: "log", team: teamName, from: "executor", to: "coordinator", type: "error", summary: "plan.json路径无效, 无法加载实现计划" })
CLI 回退
当 mcp__ccw-tools__team_msg MCP 不可用时,使用 ccw team CLI 作为等效回退:
// 回退: 将 MCP 调用替换为 Bash CLI(参数一一对应)
Bash(`ccw team log --team "${teamName}" --from "executor" --to "coordinator" --type "impl_complete" --summary "IMPL-001完成: 5个文件变更" --json`)
// 带 data 参数
Bash(`ccw team log --team "${teamName}" --from "executor" --to "coordinator" --type "impl_progress" --summary "Batch 1/3 完成" --data '{"batch":1,"total":3}' --json`)
参数映射: team_msg(params) → ccw team log --team <team> --from executor --to coordinator --type <type> --summary "<text>" [--ref <path>] [--data '<json>'] [--json]
Execution Process
Phase 1: Task & Plan Loading
├─ TaskList to find unblocked IMPL-* tasks assigned to me
├─ TaskGet to read full task details
├─ TaskUpdate to mark in_progress
└─ Load plan.json from plan path in task description
Phase 2: Task Grouping
├─ Extract depends_on from plan tasks
├─ Independent tasks → parallel batch
└─ Dependent tasks → sequential batches
Phase 3: Code Implementation
├─ For each task in plan:
│ ├─ Read files list
│ ├─ Read reference patterns
│ ├─ Implement changes (Edit/Write)
│ ├─ Complex tasks → code-developer sub-agent
│ └─ Simple tasks → direct file editing
└─ SendMessage progress updates for complex tasks
Phase 4: Self-Validation
├─ Syntax check (tsc --noEmit for TypeScript)
├─ Verify acceptance criteria from plan
├─ Run affected unit tests (if identifiable)
└─ Fix any immediate issues
Phase 5: Completion Report
├─ Compile changed files list
├─ Summarize acceptance criteria status
├─ SendMessage report to coordinator
├─ Mark IMPL task completed
└─ Check TaskList for next IMPL task
Implementation
Phase 1: Task & Plan Loading
// Find my assigned IMPL tasks
const tasks = TaskList()
const myImplTasks = tasks.filter(t =>
t.subject.startsWith('IMPL-') &&
t.owner === 'executor' &&
t.status === 'pending' &&
t.blockedBy.length === 0 // Not blocked
)
if (myImplTasks.length === 0) {
// No tasks available, idle
return
}
// Pick first available task (lowest ID)
const task = TaskGet({ taskId: myImplTasks[0].id })
TaskUpdate({ taskId: task.id, status: 'in_progress' })
// Extract plan path from task description
const planPathMatch = task.description.match(/\.workflow\/\.team-plan\/[^\s]+\/plan\.json/)
const planPath = planPathMatch ? planPathMatch[0] : null
if (!planPath) {
SendMessage({
type: "message",
recipient: "coordinator",
content: `Cannot find plan.json path in task description for ${task.subject}. Please provide plan location.`,
summary: "Plan path not found"
})
return
}
const plan = JSON.parse(Read(planPath))
Phase 2: Task Grouping
// Extract dependencies and group tasks
function extractDependencies(planTasks) {
const taskIdToIndex = {}
planTasks.forEach((t, i) => { taskIdToIndex[t.id] = i })
return planTasks.map((task, i) => {
const deps = (task.depends_on || [])
.map(depId => taskIdToIndex[depId])
.filter(idx => idx !== undefined && idx < i)
return { ...task, taskIndex: i, dependencies: deps }
})
}
function createBatches(planTasks) {
const tasksWithDeps = extractDependencies(planTasks)
const processed = new Set()
const batches = []
// Phase 1: Independent tasks → single parallel batch
const independent = tasksWithDeps.filter(t => t.dependencies.length === 0)
if (independent.length > 0) {
independent.forEach(t => processed.add(t.taskIndex))
batches.push({ type: 'parallel', tasks: independent })
}
// Phase 2+: Dependent tasks in order
let remaining = tasksWithDeps.filter(t => !processed.has(t.taskIndex))
while (remaining.length > 0) {
const ready = remaining.filter(t => t.dependencies.every(d => processed.has(d)))
if (ready.length === 0) break // circular dependency guard
ready.forEach(t => processed.add(t.taskIndex))
batches.push({ type: ready.length > 1 ? 'parallel' : 'sequential', tasks: ready })
remaining = remaining.filter(t => !processed.has(t.taskIndex))
}
return batches
}
const batches = createBatches(plan.tasks)
Phase 3: Code Implementation
// Unified Task Prompt Builder (from lite-execute)
function buildExecutionPrompt(planTask) {
return `
## ${planTask.title}
**Scope**: \`${planTask.scope}\` | **Action**: ${planTask.action || 'implement'}
### Files
${(planTask.files || []).map(f => `- **${f.path}** → \`${f.target}\`: ${f.change}`).join('\n')}
### How to do it
${planTask.description}
${(planTask.implementation || []).map(step => `- ${step}`).join('\n')}
### Reference
- Pattern: ${planTask.reference?.pattern || 'N/A'}
- Files: ${planTask.reference?.files?.join(', ') || 'N/A'}
### Done when
${(planTask.convergence?.criteria || []).map(c => `- [ ] ${c}`).join('\n')}
`
}
// Execute each batch
const changedFiles = []
const previousResults = []
for (const batch of batches) {
if (batch.tasks.length === 1 && isSimpleTask(batch.tasks[0])) {
// Simple task: direct implementation
const t = batch.tasks[0]
// Read target files, apply modifications using Edit/Write
for (const f of (t.files || [])) {
const content = Read(f.path)
// Apply change based on file entry description
Edit({ file_path: f.path, old_string: "...", new_string: "..." })
changedFiles.push(f.path)
}
} else {
// Complex task(s): delegate to code-developer sub-agent
const prompt = batch.tasks.map(buildExecutionPrompt).join('\n\n---\n')
Task({
subagent_type: "code-developer",
run_in_background: false,
description: batch.tasks.map(t => t.title).join(' | '),
prompt: `## Goal
${plan.summary}
## Tasks
${prompt}
## Context
### Project Guidelines
@.workflow/project-guidelines.json
Complete each task according to its "Done when" checklist.`
})
// Collect changed files from sub-agent results
batch.tasks.forEach(t => {
(t.files || []).forEach(f => changedFiles.push(f.path))
})
}
previousResults.push({
batchType: batch.type,
tasks: batch.tasks.map(t => t.title),
status: 'completed'
})
}
Phase 4: Self-Validation
// Step 1: Syntax check
const syntaxResult = Bash(`tsc --noEmit 2>&1 || true`)
const hasSyntaxErrors = syntaxResult.includes('error TS')
if (hasSyntaxErrors) {
// Attempt to fix syntax errors
// Parse error locations, apply fixes
console.log('Syntax errors detected, attempting fix...')
}
// Step 2: Verify acceptance criteria
const acceptanceStatus = plan.tasks.map(t => ({
title: t.title,
criteria: (t.convergence?.criteria || []).map(c => ({
criterion: c,
met: true // Evaluate based on implementation
}))
}))
// Step 3: Run affected tests (if identifiable)
const testFiles = changedFiles
.map(f => f.replace(/\/src\//, '/tests/').replace(/\.(ts|js)$/, '.test.$1'))
.filter(f => Bash(`test -f ${f} && echo exists || true`).includes('exists'))
if (testFiles.length > 0) {
const testResult = Bash(`npx jest ${testFiles.join(' ')} --passWithNoTests 2>&1 || true`)
// Parse test results
}
Phase 5: Completion Report
// Compile report
const report = {
task: task.subject,
changedFiles: [...new Set(changedFiles)],
newFiles: changedFiles.filter(f => /* detect new files */),
acceptanceStatus: acceptanceStatus,
syntaxClean: !hasSyntaxErrors,
testsPassed: testFiles.length > 0 ? testResult.includes('passed') : 'N/A'
}
// Send to coordinator
SendMessage({
type: "message",
recipient: "coordinator",
content: `## Implementation Complete
**Task**: ${task.subject}
### Changed Files
${report.changedFiles.map(f => `- ${f}`).join('\n')}
### Acceptance Criteria
${acceptanceStatus.map(t => `**${t.title}**: ${t.criteria.every(c => c.met) ? 'All met' : 'Partial'}`).join('\n')}
### Validation
- Syntax: ${report.syntaxClean ? 'Clean' : 'Has errors (attempted fix)'}
- Tests: ${report.testsPassed}
Implementation is ready for testing and review.`,
summary: `IMPL complete: ${report.changedFiles.length} files changed`
})
// Mark task completed
TaskUpdate({ taskId: task.id, status: 'completed' })
// Check for next IMPL task
const nextTasks = TaskList().filter(t =>
t.subject.startsWith('IMPL-') &&
t.owner === 'executor' &&
t.status === 'pending' &&
t.blockedBy.length === 0
)
if (nextTasks.length > 0) {
// Continue with next task → back to Phase 1
}
Helper Functions
function isSimpleTask(task) {
return (task.files || []).length <= 2 &&
!task.code_skeleton &&
(task.risks || []).length === 0
}
Error Handling
| Scenario | Resolution |
|---|---|
| Plan file not found | Notify coordinator, request plan location |
| Syntax errors after implementation | Attempt auto-fix, report remaining errors |
| Sub-agent failure | Retry once, then attempt direct implementation |
| File conflict / merge issue | Notify coordinator, request guidance |
| Test failures in self-validation | Report in completion message, let tester handle |
| Circular dependencies in plan | Execute in plan order, ignore dependency chain |