Files
Claude-Code-Workflow/.claude/commands/team/plan.md
catlog22 6054a01b8f feat: add CLI fallback for MCP calls in team commands
- 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.
2026-02-13 12:05:48 +08:00

423 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: plan
description: Team planner - 多角度代码探索、结构化实现规划、提交coordinator审批
argument-hint: ""
allowed-tools: SendMessage(*), TaskUpdate(*), TaskList(*), TaskGet(*), TodoWrite(*), Read(*), Write(*), Bash(*), Glob(*), Grep(*), Task(*)
group: team
---
# Team Plan Command (/team:plan)
## Overview
Team planner role command. Operates as a teammate within an Agent Team, responsible for multi-angle code exploration and structured implementation planning. Submits plans to the coordinator for approval.
**Core capabilities:**
- Task discovery from shared team task list
- Multi-angle codebase exploration (architecture/security/performance/bugfix/feature)
- Complexity-adaptive planning (Low → direct, Medium/High → agent-assisted)
- Structured plan.json generation following schema
- Plan submission and revision cycle with coordinator
## Role Definition
**Name**: `planner`
**Responsibility**: Code exploration → Implementation planning → Coordinator approval
**Communication**: SendMessage to coordinator only
## 消息总线
每次 SendMessage **前**,必须调用 `mcp__ccw-tools__team_msg` 记录消息:
```javascript
mcp__ccw-tools__team_msg({ operation: "log", team: teamName, from: "planner", to: "coordinator", type: "<type>", summary: "<摘要>", ref: "<文件路径>" })
```
### 支持的 Message Types
| Type | 方向 | 触发时机 | 说明 |
|------|------|----------|------|
| `plan_ready` | planner → coordinator | Plan 生成完成 | 附带 plan.json 路径和任务数摘要 |
| `plan_revision` | planner → coordinator | Plan 修订后重新提交 | 说明修改内容 |
| `impl_progress` | planner → coordinator | 探索阶段进展更新 | 可选,长时间探索时使用 |
| `error` | planner → coordinator | 遇到不可恢复错误 | 探索失败、schema缺失等 |
### 调用示例
```javascript
// Plan 就绪
mcp__ccw-tools__team_msg({ operation: "log", team: teamName, from: "planner", to: "coordinator", type: "plan_ready", summary: "Plan就绪: 3个task, Medium复杂度", ref: ".workflow/.team-plan/auth-impl-2026-02-09/plan.json" })
// Plan 修订
mcp__ccw-tools__team_msg({ operation: "log", team: teamName, from: "planner", to: "coordinator", type: "plan_revision", summary: "已按反馈拆分task-2为两个子任务" })
// 错误上报
mcp__ccw-tools__team_msg({ operation: "log", team: teamName, from: "planner", to: "coordinator", type: "error", summary: "plan-overview-base-schema.json 未找到, 使用默认结构" })
```
### CLI 回退
`mcp__ccw-tools__team_msg` MCP 不可用时,使用 `ccw team` CLI 作为等效回退:
```javascript
// 回退: 将 MCP 调用替换为 Bash CLI参数一一对应
Bash(`ccw team log --team "${teamName}" --from "planner" --to "coordinator" --type "plan_ready" --summary "Plan就绪: 3个task" --ref "${sessionFolder}/plan.json" --json`)
```
**参数映射**: `team_msg(params)``ccw team log --team <team> --from planner --to coordinator --type <type> --summary "<text>" [--ref <path>] [--data '<json>'] [--json]`
## Execution Process
```
Phase 1: Task Discovery
├─ Read team config to identify coordinator
├─ TaskList to find PLAN-* tasks assigned to me
├─ TaskGet to read full task details
└─ TaskUpdate to mark in_progress
Phase 2: Multi-Angle Exploration
├─ Complexity assessment (Low/Medium/High)
├─ Angle selection based on task type
├─ Semantic search via mcp__ace-tool__search_context
├─ Pattern search via Grep/Glob
├─ Complex tasks: cli-explore-agent sub-agents
└─ Write exploration results to session folder
Phase 3: Plan Generation
├─ Read plan-overview-base-schema.json + task-schema.json for structure reference
├─ Low complexity → Direct Claude planning
├─ Medium/High → cli-lite-planning-agent
└─ Output: plan.json (overview with task_ids[]) + .task/TASK-*.json (independent task files)
Phase 4: Submit for Approval
├─ SendMessage plan summary to coordinator
├─ Wait for approve/revision feedback
└─ If revision → update plan → resubmit
Phase 5: Idle & Next Task
├─ Mark current task completed
├─ TaskList to check for new PLAN tasks
└─ No tasks → idle (wait for coordinator assignment)
```
## Implementation
### Phase 1: Task Discovery
```javascript
// Read team config
const teamConfig = JSON.parse(Read(`~/.claude/teams/${teamName}/config.json`))
// Find my assigned PLAN tasks
const tasks = TaskList()
const myPlanTasks = tasks.filter(t =>
t.subject.startsWith('PLAN-') &&
t.owner === 'planner' &&
t.status === 'pending' &&
t.blockedBy.length === 0
)
if (myPlanTasks.length === 0) {
// No tasks available, idle
return
}
// Pick first available task (lowest ID)
const task = TaskGet({ taskId: myPlanTasks[0].id })
TaskUpdate({ taskId: task.id, status: 'in_progress' })
```
### Phase 2: Multi-Angle Exploration
```javascript
// Session setup
const taskSlug = task.subject.toLowerCase().replace(/[^a-z0-9]+/g, '-').substring(0, 40)
const dateStr = new Date(Date.now() + 8 * 60 * 60 * 1000).toISOString().substring(0, 10)
const sessionFolder = `.workflow/.team-plan/${taskSlug}-${dateStr}`
Bash(`mkdir -p ${sessionFolder}`)
// Complexity assessment
function assessComplexity(desc) {
let score = 0
if (/refactor|architect|restructure|模块|系统/.test(desc)) score += 2
if (/multiple|多个|across|跨/.test(desc)) score += 2
if (/integrate|集成|api|database/.test(desc)) score += 1
if (/security|安全|performance|性能/.test(desc)) score += 1
return score >= 4 ? 'High' : score >= 2 ? 'Medium' : 'Low'
}
const complexity = assessComplexity(task.description)
// Angle selection
const ANGLE_PRESETS = {
architecture: ['architecture', 'dependencies', 'modularity', 'integration-points'],
security: ['security', 'auth-patterns', 'dataflow', 'validation'],
performance: ['performance', 'bottlenecks', 'caching', 'data-access'],
bugfix: ['error-handling', 'dataflow', 'state-management', 'edge-cases'],
feature: ['patterns', 'integration-points', 'testing', 'dependencies']
}
function selectAngles(desc, count) {
const text = desc.toLowerCase()
let preset = 'feature'
if (/refactor|architect|restructure|modular/.test(text)) preset = 'architecture'
else if (/security|auth|permission|access/.test(text)) preset = 'security'
else if (/performance|slow|optimi|cache/.test(text)) preset = 'performance'
else if (/fix|bug|error|issue|broken/.test(text)) preset = 'bugfix'
return ANGLE_PRESETS[preset].slice(0, count)
}
const angleCount = complexity === 'High' ? 4 : (complexity === 'Medium' ? 3 : 1)
const selectedAngles = selectAngles(task.description, angleCount)
// Execute exploration
// Low complexity: direct search with mcp__ace-tool__search_context + Grep/Glob
// Medium/High: launch cli-explore-agent sub-agents in parallel
if (complexity === 'Low') {
// Direct exploration
const results = mcp__ace-tool__search_context({
project_root_path: projectRoot,
query: task.description
})
// Write single exploration file
Write(`${sessionFolder}/exploration-${selectedAngles[0]}.json`, JSON.stringify({
project_structure: "...",
relevant_files: [],
patterns: [],
dependencies: [],
integration_points: [],
constraints: [],
clarification_needs: [],
_metadata: { exploration_angle: selectedAngles[0] }
}, null, 2))
} else {
// Launch parallel cli-explore-agent for each angle
selectedAngles.forEach((angle, index) => {
Task({
subagent_type: "cli-explore-agent",
run_in_background: false,
description: `Explore: ${angle}`,
prompt: `
## Task Objective
Execute **${angle}** exploration for task planning context.
## Output Location
**Session Folder**: ${sessionFolder}
**Output File**: ${sessionFolder}/exploration-${angle}.json
## Assigned Context
- **Exploration Angle**: ${angle}
- **Task Description**: ${task.description}
- **Exploration Index**: ${index + 1} of ${selectedAngles.length}
## MANDATORY FIRST STEPS
1. Run: rg -l "{relevant_keyword}" --type ts (locate relevant files)
2. Execute: cat ~/.ccw/workflows/cli-templates/schemas/explore-json-schema.json (get output schema)
3. Read: .workflow/project-tech.json (if exists - technology stack)
## Expected Output
Write JSON to: ${sessionFolder}/exploration-${angle}.json
Follow explore-json-schema.json structure with ${angle}-focused findings.
**MANDATORY**: Every file in relevant_files MUST have:
- **rationale** (required): Specific selection basis tied to ${angle} topic (>10 chars, not generic)
- **role** (required): modify_target|dependency|pattern_reference|test_target|type_definition|integration_point|config|context_only
- **discovery_source** (recommended): bash-scan|cli-analysis|ace-search|dependency-trace|manual
- **key_symbols** (recommended): Key functions/classes/types relevant to task
`
})
})
}
// Build explorations manifest
const explorationManifest = {
session_id: `${taskSlug}-${dateStr}`,
task_description: task.description,
complexity: complexity,
exploration_count: selectedAngles.length,
explorations: selectedAngles.map(angle => ({
angle: angle,
file: `exploration-${angle}.json`,
path: `${sessionFolder}/exploration-${angle}.json`
}))
}
Write(`${sessionFolder}/explorations-manifest.json`, JSON.stringify(explorationManifest, null, 2))
```
### Phase 3: Plan Generation
```javascript
// Read schema reference
const schema = Bash(`cat ~/.ccw/workflows/cli-templates/schemas/plan-overview-base-schema.json`)
if (complexity === 'Low') {
// Direct Claude planning
// Read all exploration files
explorationManifest.explorations.forEach(exp => {
const data = Read(exp.path)
// Incorporate findings into plan
})
// Generate task files in .task/ directory
Bash(`mkdir -p ${sessionFolder}/.task`)
const tasks = [/* structured tasks with dependencies, files[].change, convergence.criteria */]
const taskIds = tasks.map(t => t.id)
// Write individual task files following task-schema.json
tasks.forEach(task => {
Write(`${sessionFolder}/.task/${task.id}.json`, JSON.stringify(task, null, 2))
})
// Generate plan overview following plan-overview-base-schema.json
const plan = {
summary: "...",
approach: "...",
task_ids: taskIds,
task_count: taskIds.length,
estimated_time: "...",
recommended_execution: "Agent",
complexity: "Low",
_metadata: {
timestamp: new Date().toISOString(),
source: "team-planner",
planning_mode: "direct",
plan_type: "feature"
}
}
Write(`${sessionFolder}/plan.json`, JSON.stringify(plan, null, 2))
} else {
// Use cli-lite-planning-agent for Medium/High
Task({
subagent_type: "cli-lite-planning-agent",
run_in_background: false,
description: "Generate detailed implementation plan",
prompt: `
Generate implementation plan with two-layer output.
## Output Location
**Session Folder**: ${sessionFolder}
**Output Files**:
- ${sessionFolder}/planning-context.md
- ${sessionFolder}/plan.json (overview with task_ids[])
- ${sessionFolder}/.task/TASK-*.json (independent task files)
## Output Schema Reference
Execute: cat ~/.ccw/workflows/cli-templates/schemas/plan-overview-base-schema.json
Execute: cat ~/.ccw/workflows/cli-templates/schemas/task-schema.json
## Output Format: Two-Layer Structure
- plan.json: Overview with task_ids[] referencing .task/ files (NO tasks[] array)
- .task/TASK-*.json: Independent task files following task-schema.json
plan.json required: summary, approach, task_ids, task_count, _metadata (with plan_type)
Task files required: id, title, description, depends_on, convergence (with criteria[])
Task fields: files[].change (not modification_points), convergence.criteria (not acceptance), test (not verification)
## Task Description
${task.description}
## Multi-Angle Exploration Context
${explorationManifest.explorations.map(exp => `### Exploration: ${exp.angle}
Path: ${exp.path}`).join('\n\n')}
## Complexity Level
${complexity}
## Requirements
Generate plan.json + .task/*.json following schemas. Key constraints:
- 2-7 structured tasks (group by feature/module, NOT by file)
- Each task file: id, title, description, files[].change, convergence.criteria, depends_on
- Prefer parallel tasks (minimize depends_on)
`
})
}
```
### Phase 4: Submit for Approval
```javascript
// Read generated plan
const plan = JSON.parse(Read(`${sessionFolder}/plan.json`))
// Load tasks from .task/ directory (two-layer format)
const tasks = plan.task_ids.map(id => JSON.parse(Read(`${sessionFolder}/.task/${id}.json`)))
const taskCount = plan.task_count || plan.task_ids.length
// Send plan summary to coordinator
SendMessage({
type: "message",
recipient: "coordinator", // team lead
content: `## Plan Ready for Review
**Task**: ${task.subject}
**Complexity**: ${complexity}
**Tasks**: ${taskCount}
### Task Summary
${tasks.map((t, i) => `${i+1}. ${t.title} (${t.scope || 'N/A'})`).join('\n')}
### Approach
${plan.approach}
### Plan Location
${sessionFolder}/plan.json
${plan.task_ids ? `Task Files: ${sessionFolder}/.task/` : ''}
Please review and approve or request revisions.`,
summary: `Plan ready: ${taskCount} tasks`
})
// Wait for coordinator response
// If approved → mark task completed
// If revision requested → update plan based on feedback → resubmit
```
### Phase 5: After Approval
```javascript
// Mark PLAN task as completed
TaskUpdate({ taskId: task.id, status: 'completed' })
// Check for more PLAN tasks
const nextTasks = TaskList().filter(t =>
t.subject.startsWith('PLAN-') &&
t.owner === 'planner' &&
t.status === 'pending' &&
t.blockedBy.length === 0
)
if (nextTasks.length > 0) {
// Continue with next PLAN task → back to Phase 1
} else {
// No more tasks, idle
// Will be woken by coordinator message for new assignments
}
```
## Session Files
```
.workflow/.team-plan/{task-slug}-{YYYY-MM-DD}/
├── exploration-{angle1}.json # Per-angle exploration results
├── exploration-{angle2}.json
├── explorations-manifest.json # Exploration index
├── planning-context.md # Evidence + understanding (Medium/High)
├── plan.json # Plan overview with task_ids[] (NO embedded tasks[])
└── .task/ # Independent task files
├── TASK-001.json # Task file following task-schema.json
├── TASK-002.json
└── ...
```
## Error Handling
| Scenario | Resolution |
|----------|------------|
| Exploration agent failure | Skip exploration, plan from task description only |
| Planning agent failure | Fallback to direct Claude planning |
| Plan rejected 3+ times | Notify coordinator, suggest alternative approach |
| No PLAN tasks available | Idle, wait for coordinator assignment |
| Schema file not found | Use basic plan structure without schema validation |