Loading...
Loading...
Compare original and translation side by side
--role=xxx--role=xxx┌──────────────────────────────────────────────┐
│ Skill(skill="team-planex", args="--role=xxx") │
└────────────────┬─────────────────────────────┘
│ Role Router
┌───────┴───────┐
↓ ↓
┌─────────┐ ┌──────────┐
│ planner │ │ executor │
│ PLAN-* │ │ EXEC-* │
└─────────┘ └──────────┘┌──────────────────────────────────────────────┐
│ Skill(skill="team-planex", args="--role=xxx") │
└────────────────┬─────────────────────────────┘
│ Role Router
┌───────┴───────┐
↓ ↓
┌─────────┐ ┌──────────┐
│ planner │ │ executor │
│ PLAN-* │ │ EXEC-* │
└─────────┘ └──────────┘const args = "$ARGUMENTS"
const roleMatch = args.match(/--role[=\s]+(\w+)/)
if (!roleMatch) {
// No --role: orchestration mode (lightweight coordinator)
// → See "Orchestration Mode" section below
}
const role = roleMatch[1]
const teamName = args.match(/--team[=\s]+([\w-]+)/)?.[1] || "planex"const args = "$ARGUMENTS"
const roleMatch = args.match(/--role[=\s]+(\w+)/)
if (!roleMatch) {
// 未传入--role:进入编排模式(轻量协调器)
// → 详见下方「编排模式」章节
}
const role = roleMatch[1]
const teamName = args.match(/--team[=\s]+([\w-]+)/)?.[1] || "planex"const VALID_ROLES = {
"planner": { file: "roles/planner.md", prefix: "PLAN" },
"executor": { file: "roles/executor.md", prefix: "EXEC" }
}
if (!VALID_ROLES[role]) {
throw new Error(`Unknown role: ${role}. Available: ${Object.keys(VALID_ROLES).join(', ')}`)
}
// Read and execute role-specific logic
Read(VALID_ROLES[role].file)
// → Execute the 5-phase process defined in that fileconst VALID_ROLES = {
"planner": { file: "roles/planner.md", prefix: "PLAN" },
"executor": { file: "roles/executor.md", prefix: "EXEC" }
}
if (!VALID_ROLES[role]) {
throw new Error(`Unknown role: ${role}. Available: ${Object.keys(VALID_ROLES).join(', ')}`)
}
// 读取并执行角色专属逻辑
Read(VALID_ROLES[role].file)
// → 执行该文件中定义的5阶段流程| Role | Task Prefix | Responsibility | Reuses Agent | Role File |
|---|---|---|---|---|
| PLAN-* | 需求拆解 → issue 创建 → 方案设计 → 队列编排 → EXEC 任务派发 | issue-plan-agent, issue-queue-agent | roles/planner.md |
| EXEC-* | 加载 solution → 代码实现 → 测试 → 提交 | code-developer | roles/executor.md |
| 角色 | 任务前缀 | 职责 | 复用Agent | 角色文件 |
|---|---|---|---|---|
| PLAN-* | 需求拆解→创建Issue→方案设计→队列编排→派发EXEC-*任务 | issue-plan-agent, issue-queue-agent | roles/planner.md |
| EXEC-* | 加载方案→代码实现→测试验证→提交代码 | code-developer | roles/executor.md |
| 输入类型 | 格式 | 示例 |
|---|---|---|
| Issue IDs | 直接传入 ID | |
| 需求文本 | | |
| Plan 文件 | | |
| 输入类型 | 格式 | 示例 |
|---|---|---|
| Issue ID | 直接传入ID | |
| 需求文本 | | |
| 规划文件 | | |
SendMessage({ content: `## [${role}] ...`, summary: `[${role}] ...` })
mcp__ccw-tools__team_msg({ summary: `[${role}] ...` })SendMessage({ content: `## [${role}] ...`, summary: `[${role}] ...` })
mcp__ccw-tools__team_msg({ summary: `[${role}] ...` })| 允许 | 禁止 |
|---|---|
| 需求拆解 (issue 创建) | ❌ 直接编写/修改代码 |
| 方案设计 (issue-plan-agent) | ❌ 调用 code-developer |
| 队列编排 (issue-queue-agent) | ❌ 运行测试 |
| 创建 EXEC-* 任务 | ❌ git commit |
| 监控进度 (消息总线) |
| 允许操作 | 禁止操作 |
|---|---|
| 需求拆解(创建Issue) | ❌ 直接编写/修改代码 |
| 方案设计(调用issue-plan-agent) | ❌ 调用code-developer |
| 队列编排(调用issue-queue-agent) | ❌ 运行测试 |
| 创建EXEC-*任务 | ❌ Git提交 |
| 通过消息总线监控进度 |
| 允许 | 禁止 |
|---|---|
| 处理 EXEC-* 前缀的任务 | ❌ 创建 issue |
| 调用 code-developer 实现 | ❌ 修改 solution/queue |
| 运行测试验证 | ❌ 为 planner 创建 PLAN-* 任务 |
| git commit 提交 | ❌ 直接与用户交互 (AskUserQuestion) |
| SendMessage 给 planner |
| 允许操作 | 禁止操作 |
|---|---|
| 处理带EXEC-*前缀的任务 | ❌ 创建Issue |
| 调用code-developer实现功能 | ❌ 修改方案/任务队列 |
| 运行测试验证 | ❌ 为Planner创建PLAN-*任务 |
| Git提交代码 | ❌ 直接与用户交互(调用AskUserQuestion) |
| 向Planner发送消息 |
const TEAM_CONFIG = {
name: "planex",
sessionDir: ".workflow/.team/PEX-{slug}-{date}/",
msgDir: ".workflow/.team-msg/planex/",
issueDataDir: ".workflow/issues/"
}const TEAM_CONFIG = {
name: "planex",
sessionDir: ".workflow/.team/PEX-{slug}-{date}/",
msgDir: ".workflow/.team-msg/planex/",
issueDataDir: ".workflow/issues/"
}mcp__ccw-tools__team_msg({
operation: "log",
team: teamName,
from: role,
to: role === "planner" ? "executor" : "planner",
type: "<type>",
summary: `[${role}] <summary>`,
ref: "<file_path>"
})| Role | Types |
|---|---|
| planner | |
| executor | |
mcp__ccw-tools__team_msg({
operation: "log",
team: teamName,
from: role,
to: role === "planner" ? "executor" : "planner",
type: "<type>",
summary: `[${role}] <summary>`,
ref: "<file_path>"
})| 角色 | 消息类型 |
|---|---|
| Planner | |
| Executor | |
Bash(`ccw team log --team "${teamName}" --from "${role}" --to "${role === 'planner' ? 'executor' : 'planner'}" --type "<type>" --summary "<summary>" --json`)Bash(`ccw team log --team "${teamName}" --from "${role}" --to "${role === 'planner' ? 'executor' : 'planner'}" --type "<type>" --summary "<summary>" --json`)const tasks = TaskList()
const myTasks = tasks.filter(t =>
t.subject.startsWith(`${VALID_ROLES[role].prefix}-`) &&
t.owner === role &&
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-4: Role-specific (see roles/{role}.md)
// Phase 5: Report + Loopconst tasks = TaskList()
const myTasks = tasks.filter(t =>
t.subject.startsWith(`${VALID_ROLES[role].prefix}-`) &&
t.owner === role &&
t.status === 'pending' &&
t.blockedBy.length === 0
)
if (myTasks.length === 0) return // 无待处理任务,进入空闲状态
const task = TaskGet({ taskId: myTasks[0].id })
TaskUpdate({ taskId: task.id, status: 'in_progress' })
// 阶段2-4:角色专属流程(详见roles/{role}.md)
// 阶段5:结果上报+循环执行Wave 1: planner 创建 issues + 规划 solutions + 形成 queue
↓ (queue ready → 创建 EXEC-* 任务)
Wave 1 执行: executor 开始实现 ←→ planner 继续规划 Wave 2
↓
Wave 2 执行: executor 实现 Wave 2 ←→ planner 规划 Wave 3
...
Final: planner 发送 all_planned → executor 完成剩余 EXEC-* → 结束all_plannedWave 1:Planner创建Issue+规划方案+形成任务队列
↓(队列就绪→创建EXEC-*任务)
Wave 1执行:Executor开始实现 ←→ Planner继续规划Wave 2
↓
Wave 2执行:Executor实现Wave2任务 ←→ Planner规划Wave3
...
最终阶段:Planner发送all_planned消息→Executor完成剩余EXEC-*任务→流程结束all_planned| Executor | 后端 | 适用场景 |
|---|---|---|
| code-developer subagent | 简单任务、同步执行 |
| | 复杂任务、后台执行 |
| | 分析类任务、后台执行 |
| 执行器 | 后端 | 适用场景 |
|---|---|---|
| code-developer子Agent | 简单任务、同步执行 |
| | 复杂任务、后台执行 |
| | 分析类任务、后台执行 |
// ★ 统一 auto mode 检测:-y/--yes 从 $ARGUMENTS 或 ccw 传播
const autoYes = /\b(-y|--yes)\b/.test(args)
const explicitExec = args.match(/--exec[=\s]+(agent|codex|gemini|auto)/i)?.[1]
let executionConfig
if (explicitExec) {
// 显式指定
executionConfig = {
executionMethod: explicitExec.charAt(0).toUpperCase() + explicitExec.slice(1),
codeReviewTool: "Skip"
}
} else if (autoYes) {
// Auto 模式:默认 Agent + Skip review
executionConfig = { executionMethod: "Auto", codeReviewTool: "Skip" }
} else {
// 交互选择
executionConfig = AskUserQuestion({
questions: [
{
question: "选择执行方式:",
header: "Execution",
multiSelect: false,
options: [
{ label: "Agent", description: "code-developer agent(同步,适合简单任务)" },
{ label: "Codex", description: "Codex CLI(后台,适合复杂任务)" },
{ label: "Gemini", description: "Gemini CLI(后台,适合分析类任务)" },
{ label: "Auto", description: "根据任务复杂度自动选择" }
]
},
{
question: "执行后是否进行代码审查?",
header: "Code Review",
multiSelect: false,
options: [
{ label: "Skip", description: "不审查" },
{ label: "Gemini Review", description: "Gemini CLI 审查" },
{ label: "Codex Review", description: "Git-aware review(--uncommitted)" },
{ label: "Agent Review", description: "当前 agent 审查" }
]
}
]
})
}
// Auto 解析:根据 solution task_count 决定
function resolveExecutor(taskCount) {
if (executionConfig.executionMethod === 'Auto') {
return taskCount <= 3 ? 'agent' : 'codex'
}
return executionConfig.executionMethod.toLowerCase()
}// ★ 自动模式统一检测:-y/--yes参数从$ARGUMENTS或ccw工具传播
const autoYes = /\b(-y|--yes)\b/.test(args)
const explicitExec = args.match(/--exec[=\s]+(agent|codex|gemini|auto)/i)?.[1]
let executionConfig
if (explicitExec) {
// 显式指定执行方式
executionConfig = {
executionMethod: explicitExec.charAt(0).toUpperCase() + explicitExec.slice(1),
codeReviewTool: "Skip"
}
} else if (autoYes) {
// 自动模式:默认使用Agent+跳过审查
executionConfig = { executionMethod: "Auto", codeReviewTool: "Skip" }
} else {
// 交互模式:让用户选择
executionConfig = AskUserQuestion({
questions: [
{
question: "选择执行方式:",
header: "Execution",
multiSelect: false,
options: [
{ label: "Agent", description: "code-developer Agent(同步执行,适合简单任务)" },
{ label: "Codex", description: "Codex CLI(后台执行,适合复杂任务)" },
{ label: "Gemini", description: "Gemini CLI(后台执行,适合分析类任务)" },
{ label: "Auto", description: "根据任务复杂度自动选择" }
]
},
{
question: "执行后是否进行代码审查?",
header: "Code Review",
multiSelect: false,
options: [
{ label: "Skip", description: "不审查" },
{ label: "Gemini Review", description: "Gemini CLI审查" },
{ label: "Codex Review", description: "Git感知审查(--uncommitted)" },
{ label: "Agent Review", description: "当前Agent审查" }
]
}
]
})
}
// Auto模式解析:根据方案中的任务数量决定执行方式
function resolveExecutor(taskCount) {
if (executionConfig.executionMethod === 'Auto') {
return taskCount <= 3 ? 'agent' : 'codex'
}
return executionConfig.executionMethod.toLowerCase()
}undefinedundefinedundefinedundefined--role// 1. 创建团队
TeamCreate({ team_name: teamName })
// 2. 解析输入参数
const issueIds = args.match(/ISS-\d{8}-\d{6}/g) || []
const textMatch = args.match(/--text\s+['"]([^'"]+)['"]/)
const planMatch = args.match(/--plan\s+(\S+)/)
let plannerInput = args // 透传给 planner
// 3. 执行方式选择(见上方 Execution Method Selection)
// executionConfig 已确定: { executionMethod, codeReviewTool }
// 4. 创建初始 PLAN-* 任务
TaskCreate({
subject: "PLAN-001: 初始规划",
description: `规划任务。输入: ${plannerInput}`,
activeForm: "规划中",
owner: "planner"
})
// 5. Spawn planner agent
Task({
subagent_type: "general-purpose",
team_name: teamName,
name: "planner",
prompt: `你是 team "${teamName}" 的 PLANNER。
当你收到 PLAN-* 任务时,调用 Skill(skill="team-planex", args="--role=planner") 执行。
当前输入: ${plannerInput}--role// 1. 创建团队
TeamCreate({ team_name: teamName })
// 2. 解析输入参数
const issueIds = args.match(/ISS-\d{8}-\d{6}/g) || []
const textMatch = args.match(/--text\s+['"]([^'"]+)['"]/)
const planMatch = args.match(/--plan\s+(\S+)/)
let plannerInput = args // 直接透传给Planner
// 3. 确定执行方式(详见上方「执行方式选择」章节)
// executionConfig已确定: { executionMethod, codeReviewTool }
// 4. 创建初始PLAN-*任务
TaskCreate({
subject: "PLAN-001: 初始规划",
description: `规划任务。输入参数: ${plannerInput}`,
activeForm: "规划中",
owner: "planner"
})
// 5. 启动Planner Agent
Task({
subagent_type: "general-purpose",
team_name: teamName,
name: "planner",
prompt: `你是团队"${teamName}"的PLANNER。
当你收到PLAN-*任务时,调用Skill(skill="team-planex", args="--role=planner")执行。
当前输入参数: ${plannerInput}undefinedundefined| Scenario | Resolution |
|---|---|
| Unknown --role value | Error with available role list |
| Missing --role arg | Enter orchestration mode |
| Role file not found | Error with expected path (roles/{name}.md) |
| Planner wave failure | Retry once, then report error and halt pipeline |
| Executor impl failure | Report to planner, continue with next EXEC-* task |
| No EXEC-* tasks yet | Executor idles, polls for new tasks |
| Pipeline stall | Planner monitors — if executor blocked > 2 tasks, escalate to user |
| 场景 | 处理方式 |
|---|---|
| 传入未知的--role值 | 抛出错误并列出可用角色 |
| 未传入--role参数 | 进入编排模式 |
| 角色文件未找到 | 抛出错误并提示预期路径(roles/{name}.md) |
| Planner波次规划失败 | 重试一次,若仍失败则上报错误并终止流水线 |
| Executor任务实现失败 | 向Planner上报错误,继续处理下一个EXEC-*任务 |
| 暂无EXEC-*任务 | Executor进入空闲状态,持续轮询新任务 |
| 流水线停滞 | Planner监控:若Executor阻塞任务超过2个,则升级通知用户 |