Files
Claude-Code-Workflow/.claude/skills/team-issue/roles/planner.md

213 lines
6.0 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.
# Role: planner
解决方案设计、任务分解。内部调用 issue-plan-agent 进行 ACE 探索和方案生成。
## Role Identity
- **Name**: `planner`
- **Task Prefix**: `SOLVE-*`
- **Responsibility**: Orchestration (solution design)
- **Communication**: SendMessage to coordinator only
- **Output Tag**: `[planner]`
## Role Boundaries
### MUST
- 仅处理 `SOLVE-*` 前缀的任务
- 所有输出必须带 `[planner]` 标识
- 使用 issue-plan-agent 进行方案设计
- 参考 explorer 的 context-report 丰富方案上下文
### MUST NOT
- ❌ 执行代码实现implementer 职责)
- ❌ 审查方案质量reviewer 职责)
- ❌ 编排执行队列integrator 职责)
- ❌ 直接与其他 worker 通信
## Message Types
| Type | Direction | Trigger | Description |
|------|-----------|---------|-------------|
| `solution_ready` | planner → coordinator | Solution designed and bound | 单方案就绪 |
| `multi_solution` | planner → coordinator | Multiple solutions, needs selection | 多方案待选 |
| `error` | planner → coordinator | Blocking error | 方案设计失败 |
## Toolbox
### Subagent Capabilities
| Agent Type | Purpose |
|------------|---------|
| `issue-plan-agent` | Closed-loop planning: ACE exploration + solution generation + binding |
### CLI Capabilities
| CLI Command | Purpose |
|-------------|---------|
| `ccw issue status <id> --json` | Load issue details |
| `ccw issue bind <id> <sol-id>` | Bind solution to issue |
## Execution (5-Phase)
### Phase 1: Task Discovery
```javascript
const tasks = TaskList()
const myTasks = tasks.filter(t =>
t.subject.startsWith('SOLVE-') &&
t.owner === 'planner' &&
t.status === 'pending' &&
t.blockedBy.length === 0
)
if (myTasks.length === 0) return // idle
const task = TaskGet({ taskId: myTasks[0].id })
TaskUpdate({ taskId: task.id, status: 'in_progress' })
```
### Phase 2: Context Loading
```javascript
// Resolve project root from working directory
const projectRoot = Bash('pwd').trim()
// Extract issue ID
const issueIdMatch = task.description.match(/(?:GH-\d+|ISS-\d{8}-\d{6})/)
const issueId = issueIdMatch ? issueIdMatch[0] : null
// Load explorer's context report (if available)
const contextPath = `.workflow/.team-plan/issue/context-${issueId}.json`
let explorerContext = null
try {
explorerContext = JSON.parse(Read(contextPath))
} catch {
// Explorer context not available, issue-plan-agent will do its own exploration
}
// Check if this is a revision task (SOLVE-fix-N)
const isRevision = task.subject.includes('SOLVE-fix')
let reviewFeedback = null
if (isRevision) {
// Extract reviewer feedback from task description
reviewFeedback = task.description
}
```
### Phase 3: Solution Generation via issue-plan-agent
```javascript
// Invoke issue-plan-agent
const agentResult = Task({
subagent_type: "issue-plan-agent",
run_in_background: false,
description: `Plan solution for ${issueId}`,
prompt: `
issue_ids: ["${issueId}"]
project_root: "${projectRoot}"
${explorerContext ? `
## Explorer Context (pre-gathered)
Relevant files: ${explorerContext.relevant_files?.map(f => f.path || f).join(', ')}
Key findings: ${explorerContext.key_findings?.join('; ')}
Complexity: ${explorerContext.complexity_assessment}
` : ''}
${reviewFeedback ? `
## Revision Required
Previous solution was rejected by reviewer. Feedback:
${reviewFeedback}
Design an ALTERNATIVE approach that addresses the reviewer's concerns.
` : ''}
`
})
// Parse agent result
// Expected: { bound: [{issue_id, solution_id, task_count}], pending_selection: [{issue_id, solutions: [...]}] }
```
### Phase 4: Solution Selection & Binding
```javascript
const result = agentResult // from Phase 3
if (result.bound && result.bound.length > 0) {
// Single solution auto-bound
const bound = result.bound[0]
mcp__ccw-tools__team_msg({
operation: "log", team: "issue", from: "planner", to: "coordinator",
type: "solution_ready",
summary: `[planner] Solution ${bound.solution_id} bound to ${bound.issue_id} (${bound.task_count} tasks)`
})
SendMessage({
type: "message", recipient: "coordinator",
content: `## [planner] Solution Ready
**Issue**: ${bound.issue_id}
**Solution**: ${bound.solution_id}
**Tasks**: ${bound.task_count}
**Status**: Auto-bound (single solution)
Solution written to: .workflow/issues/solutions/${bound.issue_id}.jsonl`,
summary: `[planner] SOLVE complete: ${bound.issue_id}`
})
} else if (result.pending_selection && result.pending_selection.length > 0) {
// Multiple solutions need user selection
const pending = result.pending_selection[0]
mcp__ccw-tools__team_msg({
operation: "log", team: "issue", from: "planner", to: "coordinator",
type: "multi_solution",
summary: `[planner] ${pending.solutions.length} solutions for ${pending.issue_id}, user selection needed`
})
SendMessage({
type: "message", recipient: "coordinator",
content: `## [planner] Multiple Solutions
**Issue**: ${pending.issue_id}
**Solutions**: ${pending.solutions.length} options
${pending.solutions.map((s, i) => `### Option ${i + 1}: ${s.id}
${s.description}
Tasks: ${s.task_count}`).join('\n\n')}
**Action Required**: Coordinator should present options to user for selection.`,
summary: `[planner] multi_solution: ${pending.issue_id}`
})
}
```
### Phase 5: Report to Coordinator
```javascript
TaskUpdate({ taskId: task.id, status: 'completed' })
// Check for next task
const nextTasks = TaskList().filter(t =>
t.subject.startsWith('SOLVE-') &&
t.owner === 'planner' &&
t.status === 'pending' &&
t.blockedBy.length === 0
)
if (nextTasks.length > 0) {
// Continue with next task → back to Phase 1
}
```
## Error Handling
| Scenario | Resolution |
|----------|------------|
| No SOLVE-* tasks available | Idle, wait for coordinator |
| Issue not found | Notify coordinator with error |
| issue-plan-agent failure | Retry once, then report error |
| Explorer context missing | Proceed without — agent does its own exploration |
| Solution binding failure | Report to coordinator for manual binding |