refactor: team-planex dual-version optimization with v5 architecture

Claude version: add coordinator role with Spawn-and-Stop beat model,
replace role-routed planner/executor with team-worker agents using
lightweight role-specs (~80-110 lines each).

Codex version: inline planning into main flow, remove planner agent,
spawn executors directly per issue without waiting.

Both versions preserve 3 input types (Issue IDs / --text / --plan).
This commit is contained in:
catlog22
2026-02-28 15:31:03 +08:00
parent d14a710797
commit 3788ba1268
11 changed files with 925 additions and 1330 deletions

View File

@@ -1,155 +1,105 @@
--- ---
name: team-planex name: team-planex
description: Unified team skill for plan-and-execute pipeline. 2-member team (planner + executor) with wave pipeline for concurrent planning and execution. All roles invoke this skill with --role arg. Triggers on "team planex". description: Unified team skill for plan-and-execute pipeline. Uses team-worker agent architecture with role-spec files for domain logic. Coordinator orchestrates pipeline, workers are team-worker agents. Triggers on "team planex".
allowed-tools: TeamCreate(*), TeamDelete(*), SendMessage(*), TaskCreate(*), TaskUpdate(*), TaskList(*), TaskGet(*), Task(*), AskUserQuestion(*), Read(*), Write(*), Edit(*), Bash(*), Glob(*), Grep(*) allowed-tools: TeamCreate(*), TeamDelete(*), SendMessage(*), TaskCreate(*), TaskUpdate(*), TaskList(*), TaskGet(*), Task(*), AskUserQuestion(*), Read(*), Write(*), Edit(*), Bash(*), Glob(*), Grep(*)
--- ---
# Team PlanEx # Team PlanEx
2 成员边规划边执行团队。通过逐 Issue 节拍流水线实现 planner 和 executor 并行工作planner 每完成一个 issue 的 solution 后立即创建 EXEC-* 任务含中间产物文件路径executor 从文件加载 solution 开始实现。所有成员通过 `--role=xxx` 路由。 Unified team skill: plan-and-execute pipeline for issue-based development. Built on **team-worker agent architecture** — all worker roles share a single agent definition with role-specific Phase 2-4 loaded from markdown specs.
## Architecture Overview > **Note**: This skill has its own coordinator implementation (`roles/coordinator/role.md`), independent of `team-lifecycle-v5`. It follows the same v5 architectural patterns (team-worker agents, role-specs, Spawn-and-Stop) but with a simplified 2-role pipeline (planner + executor) tailored for plan-and-execute workflows.
## Architecture
``` ```
┌───────────────────────────────────────────── ┌─────────────────────────────────────────────┐
│ Skill(skill="team-planex", args="--role=xxx") │ │ Skill(skill="team-planex", args="需求描述")
└────────────────┬─────────────────────────────┘ └────────────────────────────────────────────┘
│ Role Router │ Always → coordinator
┌───────┴───────┐
┌──────────────┐
│ coordinator │ Phase 1-5 + dispatch/monitor commands
└───┬──────┬───┘
│ │
↓ ↓ ↓ ↓
─────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ planner │ executor │ │ planner │ executor team-worker agents
│ PLAN-* │ EXEC-* │ │ PLAN-* │ EXEC-* with role-spec injection
─────────┘ └──────────┘ └──────────┘ └──────────┘
``` ```
**设计原则**: 只有 2 个角色,没有独立 coordinator。SKILL.md 入口承担轻量编排(创建团队、派发初始任务链),然后 planner 担任 lead 角色持续推进。
## Role Router ## Role Router
This skill is **coordinator-only**. Workers do NOT invoke this skill — they are spawned as `team-worker` agents directly.
### Input Parsing ### Input Parsing
Parse `$ARGUMENTS` to extract `--role`. If absent -> Orchestration Mode (SKILL.md as lightweight coordinator). Parse `$ARGUMENTS`. No `--role` needed — always routes to coordinator.
Optional flags: `--team` (default: "planex"), `--exec` (execution method), `-y`/`--yes` (auto mode). Optional flags: `--exec` (execution method), `-y`/`--yes` (auto mode).
### Role Registry ### Role Registry
| Role | File | Task Prefix | Type | Compact | | Role | Spec | Task Prefix | Type | Inner Loop |
|------|------|-------------|------|---------| |------|------|-------------|------|------------|
| planner | [roles/planner.md](roles/planner.md) | PLAN-* | pipeline (lead) | **压缩后必须重读** | | coordinator | [roles/coordinator/role.md](roles/coordinator/role.md) | (none) | orchestrator | - |
| executor | [roles/executor.md](roles/executor.md) | EXEC-* | pipeline | 压缩后必须重读 | | planner | [role-specs/planner.md](role-specs/planner.md) | PLAN-* | pipeline | true |
| executor | [role-specs/executor.md](role-specs/executor.md) | EXEC-* | pipeline | true |
> **COMPACT PROTECTION**: 角色文件是执行文档,不是参考资料。当 context compression 发生后,角色指令仅剩摘要时,**必须立即 `Read` 对应 role.md 重新加载后再继续执行**。不得基于摘要执行任何 Phase。
### Dispatch ### Dispatch
1. Extract `--role` from arguments Always route to coordinator. Coordinator reads `roles/coordinator/role.md` and executes its phases.
2. If no `--role` -> Orchestration Mode (SKILL.md as lightweight coordinator)
3. Look up role in registry -> Read the role file -> Execute its phases
4. Unknown role -> Error with available role list: planner, executor
## Input Types ### Orchestration Mode
支持 3 种输入方式(通过 args 传入 planner User provides task description.
| 输入类型 | 格式 | 示例 | **Invocation**: `Skill(skill="team-planex", args="<task-description>")`
|----------|------|------|
| Issue IDs | 直接传入 ID | `--role=planner ISS-20260215-001 ISS-20260215-002` |
| 需求文本 | `--text '...'` | `--role=planner --text '实现用户认证模块'` |
| Plan 文件 | `--plan path` | `--role=planner --plan plan/2026-02-15-auth.md` |
## Shared Infrastructure **Lifecycle**:
```
User provides task description
-> coordinator Phase 1-3: Parse input -> TeamCreate -> Create task chain (dispatch)
-> coordinator Phase 4: spawn planner worker (background) -> STOP
-> Worker (team-worker agent) executes -> SendMessage callback -> coordinator advances
-> Loop until pipeline complete -> Phase 5 report + completion action
```
### Role Isolation Rules **User Commands** (wake paused coordinator):
#### Output Tagging强制 | Command | Action |
|---------|--------|
所有角色的输出SendMessage、team_msg必须带 `[role_name]` 标识前缀。 | `check` / `status` | Output execution status graph, no advancement |
| `resume` / `continue` | Check worker states, advance next step |
#### Planner 边界 | `add <issue-ids or --text '...' or --plan path>` | Append new tasks to planner queue |
| 允许 | 禁止 |
|------|------|
| 需求拆解 (issue 创建) | 直接编写/修改代码 |
| 方案设计 (issue-plan-agent) | 调用 code-developer |
| 冲突检查 (inline files_touched) | 运行测试 |
| 创建 EXEC-* 任务 | git commit |
| 监控进度 (消息总线) | |
#### Executor 边界
| 允许 | 禁止 |
|------|------|
| 处理 EXEC-* 前缀的任务 | 创建 issue |
| 调用 code-developer 实现 | 修改 solution/queue |
| 运行测试验证 | 为 planner 创建 PLAN-* 任务 |
| git commit 提交 | 直接与用户交互 (AskUserQuestion) |
| SendMessage 给 planner | |
### Team Configuration
| Key | Value |
|-----|-------|
| name | planex |
| sessionDir | `.workflow/.team/PEX-{slug}-{date}/` |
| artifactsDir | `.workflow/.team/PEX-{slug}-{date}/artifacts/` |
| issueDataDir | `.workflow/issues/` |
### Message Bus
每次 SendMessage 前,先调用 `mcp__ccw-tools__team_msg` 记录:
- 参数: operation="log", team=`<session-id>`, from=`<role>`, to=`<target-role>`, type=`<type>`, summary="[`<role>`] `<summary>`", ref=`<file_path>`
- **注意**: `team` 必须是 **session ID** (如 `PEX-project-2026-02-27`), 不是 team name. 从任务描述的 `Session:` 字段提取.
- **CLI fallback**: 当 MCP 不可用时 -> `ccw team log --team <session-id> --from <role> --to <target> --type <type> --summary "[<role>] ..." --json`
**Message types by role**:
| Role | Types |
|------|-------|
| planner | `wave_ready`, `issue_ready`, `all_planned`, `error` |
| executor | `impl_complete`, `impl_failed`, `wave_done`, `error` |
### Task Lifecycle (Both Roles)
每个 worker 启动后执行相同的任务发现流程:
1. 调用 `TaskList()` 获取所有任务
2. 筛选: subject 匹配本角色前缀 + owner 是本角色 + status 为 pending + blockedBy 为空
3. 无任务 -> idle 等待
4. 有任务 -> `TaskGet` 获取详情 -> `TaskUpdate` 标记 in_progress
5. Phase 2-4: Role-specific (see roles/{role}.md)
6. Phase 5: Report + Loop
**Resume Artifact Check** (防止恢复后重复产出):
- 检查本任务的输出产物是否已存在
- 产物完整 -> 跳到 Phase 5 报告完成
- 产物不完整或不存在 -> 正常执行 Phase 2-4
--- ---
## Wave Pipeline (逐 Issue 节拍) ## Command Execution Protocol
``` When coordinator needs to execute a command (dispatch, monitor):
Issue 1: planner 规划 solution -> 写中间产物 -> 冲突检查 -> 创建 EXEC-* -> issue_ready
↓ (executor 立即开始)
Issue 2: planner 规划 solution -> 写中间产物 -> 冲突检查 -> 创建 EXEC-* -> issue_ready
↓ (executor 并行消费)
Issue N: ...
Final: planner 发送 all_planned -> executor 完成剩余 EXEC-* -> 结束
```
**节拍规则**: 1. **Read the command file**: `roles/coordinator/commands/<command-name>.md`
- planner 每完成一个 issue 的 solution 后,**立即**创建 EXEC-* 任务并发送 `issue_ready` 信号 2. **Follow the workflow** defined in the command file (Phase 2-4 structure)
- solution 写入中间产物文件(`artifacts/solutions/{issueId}.json`EXEC-* 任务包含 `solution_file` 路径 3. **Commands are inline execution guides** - NOT separate agents or subprocesses
- executor 从文件加载 solution无需再调 `ccw issue solution`fallback 兼容旧模式 4. **Execute synchronously** - complete the command workflow before proceeding
- planner 不等待 executor持续推进下一个 issue
- 当 planner 发送 `all_planned` 消息后executor 完成所有剩余任务即可结束 ---
## Input Types
支持 3 种输入方式:
| 输入类型 | 格式 | 示例 |
|----------|------|------|
| Issue IDs | 直接传入 ID | `ISS-20260215-001 ISS-20260215-002` |
| 需求文本 | `--text '...'` | `--text '实现用户认证模块'` |
| Plan 文件 | `--plan path` | `--plan plan/2026-02-15-auth.md` |
## Execution Method Selection ## Execution Method Selection
在编排模式或直接调用 executor 前,**必须先确定执行方式**。支持 3 种执行后端: 支持 3 种执行后端:
| Executor | 后端 | 适用场景 | | Executor | 后端 | 适用场景 |
|----------|------|----------| |----------|------|----------|
@@ -159,251 +109,145 @@ Final: planner 发送 all_planned -> executor 完成剩余 EXEC-* -> 结束
### Selection Decision Table ### Selection Decision Table
| Condition | Execution Method | Code Review | | Condition | Execution Method |
|-----------|-----------------|-------------| |-----------|-----------------|
| `--exec=agent` specified | Agent | Skip | | `--exec=agent` specified | Agent |
| `--exec=codex` specified | Codex | Skip | | `--exec=codex` specified | Codex |
| `--exec=gemini` specified | Gemini | Skip | | `--exec=gemini` specified | Gemini |
| `-y` or `--yes` flag present | Auto (default Agent) | Skip | | `-y` or `--yes` flag present | Auto (default Agent) |
| No flags (interactive) | AskUserQuestion -> user choice | AskUserQuestion -> user choice | | No flags (interactive) | AskUserQuestion -> user choice |
| Auto + task_count <= 3 | Agent | Skip | | Auto + task_count <= 3 | Agent |
| Auto + task_count > 3 | Codex | Skip | | Auto + task_count > 3 | Codex |
### Interactive Prompt (no flags)
当无 `-y`/`--yes` 且无 `--exec` 时,通过 AskUserQuestion 交互选择:
- **执行方式选项**: Agent / Codex / Gemini / Auto
- **代码审查选项**: Skip / Gemini Review / Codex Review / Agent Review
### 通过 args 指定
```bash
# 显式指定
Skill(skill="team-planex", args="--exec=codex ISS-xxx")
Skill(skill="team-planex", args="--exec=agent --text '简单功能'")
# Auto 模式(跳过交互,-y 或 --yes
Skill(skill="team-planex", args="-y --text '添加日志'")
```
--- ---
## Orchestration Mode ## Coordinator Spawn Template
当不带 `--role` 调用时SKILL.md 进入轻量编排模式(无独立 coordinator 角色SKILL.md 自身承担编排)。 ### v5 Worker Spawn (all roles)
**Invocation**: `Skill(skill="team-planex", args="任务描述")` When coordinator spawns workers, use `team-worker` agent with role-spec path:
**Lifecycle**:
```
用户提供任务描述
-> SKILL.md 解析输入Issue IDs / 需求文本 / Plan 文件)
-> 初始化 sessionDir + artifacts 目录
-> 执行方式选择(见 Execution Method Selection
-> 创建 PLAN-001 任务owner: planner
-> Spawn planner agent (后台)
-> Spawn executor agent (后台)
-> 返回planner lead 后续推进)
```
**User Commands** (唤醒 / 检查状态):
| Command | Action |
|---------|--------|
| `check` / `status` | 输出执行状态图,不推进 |
| `resume` / `continue` | 检查 worker 状态,推进下一步 |
| `add <issue-ids or --text '...' or --plan path>` | 追加新任务到 planner 队列,不影响已有任务 |
**`add` 命令处理逻辑**:
1. 解析输入Issue IDs / `--text` / `--plan`
2. 获取当前最大 PLAN-* 序号(`TaskList` 筛选 `PLAN-*` prefix计算下一个序号 N
3. `TaskCreate({ subject: "PLAN-00N: ...", owner: "planner", status: "pending" })`description 写入新 issue IDs 或需求文本
4. 若 planner 已发送 `all_planned`(检查 team_msg 日志),额外 `SendMessage` 通知 planner 有新任务,使其重新进入 Loop Check
5. 若 executor 已退出等待,同样发送消息唤醒 executor 继续轮询 `EXEC-*` 任务
### Coordinator Spawn Template
SKILL.md 编排模式 spawn workers 时使用后台模式 (Spawn-and-Go):
**Planner Spawn**:
``` ```
Task({ Task({
subagent_type: "general-purpose", subagent_type: "team-worker",
description: "Spawn planner worker", description: "Spawn <role> worker",
team_name: <team-name>, team_name: <team-name>,
name: "planner", name: "<role>",
run_in_background: true, run_in_background: true,
prompt: `你是 team "<team-name>" 的 PLANNER。 prompt: `## Role Assignment
role: <role>
role_spec: .claude/skills/team-planex/role-specs/<role>.md
session: <session-folder>
session_id: <session-id>
team_name: <team-name>
requirement: <task-description>
inner_loop: <true|false>
execution_method: <agent|codex|gemini>
## 首要指令 Read role_spec file to load Phase 2-4 domain instructions.
你的所有工作必须通过调用 Skill 获取角色定义后执行: Execute built-in Phase 1 (task discovery) -> role-spec Phase 2-4 -> built-in Phase 5 (report).`
Skill(skill="team-planex", args="--role=planner")
当前输入: <planner-input>
Session: <session-dir>
## 执行配置
executor 的执行方式: <execution-method>
创建 EXEC-* 任务时description 中包含:
execution_method: <method>
code_review: <review-tool>
## 中间产物(必须)
每个 issue 的 solution 写入: <session-dir>/artifacts/solutions/{issueId}.json
EXEC-* 任务 description 必须包含 solution_file 字段指向该文件
每完成一个 issue 立即发送 issue_ready 消息并创建 EXEC-* 任务
## 角色准则
- 只处理 PLAN-* 任务,不执行其他角色工作
- 所有输出带 [planner] 标识前缀
- 仅与 coordinator 通信
- 不使用 TaskCreate 为其他角色创建任务EXEC-* 除外)
- 每次 SendMessage 前先调用 mcp__ccw-tools__team_msg 记录
## 工作流程
1. 调用 Skill -> 获取角色定义和执行逻辑
2. 按 role.md 5-Phase 流程执行
3. team_msg + SendMessage 结果给 coordinator
4. TaskUpdate completed -> 检查下一个任务`
}) })
``` ```
**Executor Spawn**: **Inner Loop roles** (planner, executor): Set `inner_loop: true`. The team-worker agent handles the loop internally.
```
Task({
subagent_type: "general-purpose",
description: "Spawn executor worker",
team_name: <team-name>,
name: "executor",
run_in_background: true,
prompt: `你是 team "<team-name>" 的 EXECUTOR。
## 首要指令
你的所有工作必须通过调用 Skill 获取角色定义后执行:
Skill(skill="team-planex", args="--role=executor")
## 执行配置
默认执行方式: <execution-method>
代码审查: <review-tool>
(每个 EXEC-* 任务 description 中可能包含 execution_method 覆盖)
## Solution 加载
优先从 EXEC-* 任务 description 中的 solution_file 路径读取 solution JSON 文件
无 solution_file 时 fallback 到 ccw issue solution 命令
## 角色准则
- 只处理 EXEC-* 任务,不执行其他角色工作
- 所有输出带 [executor] 标识前缀
- 根据 execution_method 选择执行后端Agent/Codex/Gemini
- 仅与 coordinator 通信
- 每次 SendMessage 前先调用 mcp__ccw-tools__team_msg 记录
## 工作流程
1. 调用 Skill -> 获取角色定义和执行逻辑
2. 按 role.md 5-Phase 流程执行
3. team_msg + SendMessage 结果给 coordinator
4. TaskUpdate completed -> 检查下一个任务`
})
```
--- ---
## Cadence Control ## Pipeline Definitions
**节拍模型**: Wave beat -- planner 持续推进executor 并行消费。每个 wave = planner 完成一个 issue -> executor 开始实现。 ### Pipeline Diagram
``` ```
Wave Beat Cycle (逐 Issue 节拍) Issue-based beat pipeline (逐 Issue 节拍)
=================================================================== ═══════════════════════════════════════════════════
Event SKILL.md (编排) Workers PLAN-001 ──> [planner] issue-1 solution → EXEC-001
------------------------------------------------------------------- issue-2 solution → EXEC-002
用户调用 ---------> ┌─ 解析输入 ─────────┐
│ 初始化 session │
│ 选择执行方式 │
├─ 创建 PLAN-001 ─────┤
│ spawn planner ──────┼──> [Planner] Phase 1-5
│ spawn executor ─────┼──> [Executor] Phase 1 (idle)
└─ 返回 (编排结束) ───┘ │
Wave 1: Planner: issue-1 solution
-> 写产物 -> 创建 EXEC-001
-> issue_ready ---------> Executor 开始 EXEC-001
Wave 2: Planner: issue-2 solution
-> 写产物 -> 创建 EXEC-002
-> issue_ready ---------> Executor 并行消费
... ...
Wave N: Planner: all_planned issue-N solution → EXEC-00N
Executor: 完成剩余 EXEC-* all_planned signal
===================================================================
EXEC-001 ──> [executor] implement issue-1
EXEC-002 ──> [executor] implement issue-2
...
EXEC-00N ──> [executor] implement issue-N
═══════════════════════════════════════════════════
``` ```
**Pipeline 节拍视图**: ### Cadence Control
**Beat model**: Event-driven Spawn-and-Stop. Each beat = coordinator wake -> process callback -> spawn next -> STOP.
``` ```
Wave pipeline (planner lead, executor follows) Beat Cycle (Coordinator Spawn-and-Stop)
────────────────────────────────────────────────────────── ======================================================================
Wave 1 2 3 ... N Final Event Coordinator Workers
│ │ │ │ │ ----------------------------------------------------------------------
P:iss-1 P:iss-2 P:iss-3 P:iss-N P:all_planned 用户调用 ----------> ┌─ Phase 1-3 ──────────┐
↓ ↓ 解析输入
E:exec1 E:exec2 E:exec3 E:execN E:finish TeamCreate │
│ 创建 PLAN-001
(并行消费executor 不等 planner 全部完成) ├─ Phase 4 ─────────────┤
│ spawn planner ────────┼──> [planner] Phase 1-5
P=planner E=executor └─ STOP (idle) ──────────┘ │
callback <─ planner issue_ready ────────────────────────┘
┌─ monitor.handleCallback ─┐
│ 检查新 EXEC-* 任务 │
│ spawn executor ─────────┼──> [executor] Phase 1-5
└─ STOP (idle) ───────────┘ │
callback <─ executor impl_complete ────────┘
┌─ monitor.handleCallback ─┐
│ 标记完成 │
│ 检查下一个 ready task │
└─ spawn/STOP ────────────┘
======================================================================
``` ```
**检查点 (Checkpoint)**: **Checkpoints**:
| 触发条件 | 位置 | 行为 | | 触发条件 | 位置 | 行为 |
|----------|------|------| |----------|------|------|
| Planner 全部完成 | all_planned 信号 | Executor 完成剩余 EXEC-* 后结束 | | Planner 全部完成 | all_planned 信号 | Executor 完成剩余 EXEC-* 后结束 |
| Pipeline 停滞 | 无 ready + 无 running | Planner 检查并 escalate to user | | Pipeline 停滞 | 无 ready + 无 running | Coordinator escalate to user |
| Executor 阻塞 | Executor blocked > 2 tasks | Planner escalate to user | | Executor 阻塞 | blocked > 2 tasks | Coordinator escalate to user |
**Stall 检测**: ### Task Metadata Registry
| 检查项 | 条件 | 处理 |
|--------|------|------|
| Executor 无响应 | in_progress EXEC-* 无回调 | 报告等待中的任务列表 |
| Pipeline 死锁 | 无 ready + 无 running + 有 pending | 检查 blockedBy 依赖链 |
| Planner 规划失败 | issue planning error | Retry once, then skip to next issue |
---
## Task Metadata Registry
| Task ID | Role | Phase | Dependencies | Description | | Task ID | Role | Phase | Dependencies | Description |
|---------|------|-------|-------------|-------------| |---------|------|-------|-------------|-------------|
| PLAN-001 | planner | planning | (none) | 初始规划需求拆解、issue 创建、方案设计 | | PLAN-001 | planner | planning | (none) | 初始规划需求拆解、issue 创建、方案设计 |
| EXEC-001 | executor | execution | PLAN-001 (implicit via issue_ready) | 第一个 issue 的代码实现 | | EXEC-001 | executor | execution | (created by planner at runtime) | 第一个 issue 的代码实现 |
| EXEC-002 | executor | execution | (planner issue_ready) | 第个 issue 的代码实现 | | EXEC-N | executor | execution | (created by planner at runtime) | 第 N 个 issue 的代码实现 |
| EXEC-N | executor | execution | (planner issue_ready) | 第 N 个 issue 的代码实现 |
> 注: EXEC-* 任务由 planner 在运行时逐个创建(逐 Issue 节拍),不预先定义完整任务链。 > 注: EXEC-* 任务由 planner 在运行时逐个创建(逐 Issue 节拍),不预先定义完整任务链。
--- ---
## Wisdom Accumulation (所有角色) ## Completion Action
跨任务知识积累。SKILL.md 编排模式在 session 初始化时创建 `wisdom/` 目录。 When the pipeline completes (all tasks done, coordinator Phase 5):
**目录**:
``` ```
<session-folder>/wisdom/ AskUserQuestion({
├── learnings.md # 模式和洞察 questions: [{
├── decisions.md # 架构和设计决策 question: "Team pipeline complete. What would you like to do?",
├── conventions.md # 代码库约定 header: "Completion",
└── issues.md # 已知风险和问题 multiSelect: false,
options: [
{ label: "Archive & Clean (Recommended)", description: "Archive session, clean up tasks and team resources" },
{ label: "Keep Active", description: "Keep session active for follow-up work or inspection" },
{ label: "Export Results", description: "Export deliverables to a specified location, then clean" }
]
}]
})
``` ```
**Worker 加载** (Phase 2): 从 task description 提取 `Session: <path>`, 读取 wisdom 目录下各文件。 | Choice | Action |
**Worker 贡献** (Phase 4/5): 将本任务发现写入对应 wisdom 文件。 |--------|--------|
| Archive & Clean | Update session status="completed" -> TeamDelete -> output final summary |
| Keep Active | Update session status="paused" -> output resume instructions |
| Export Results | AskUserQuestion for target path -> copy deliverables -> Archive & Clean |
--- ---
@@ -426,14 +270,30 @@ P=planner E=executor
--- ---
## Message Bus
每次 SendMessage 前,先调用 `mcp__ccw-tools__team_msg` 记录:
- 参数: operation="log", team=`<session-id>`, from=`<role>`, to=`<target-role>`, type=`<type>`, summary="[`<role>`] `<summary>`"
- **注意**: `team` 必须是 **session ID** (如 `PEX-project-2026-02-27`), 不是 team name.
**Message types by role**:
| Role | Types |
|------|-------|
| planner | `issue_ready`, `all_planned`, `error` |
| executor | `impl_complete`, `impl_failed`, `error` |
---
## Error Handling ## Error Handling
| Scenario | Resolution | | Scenario | Resolution |
|----------|------------| |----------|------------|
| Unknown --role value | Error with available role list: planner, executor | | Role spec file not found | Error with expected path (role-specs/<name>.md) |
| Missing --role arg | Enter orchestration mode (SKILL.md as lightweight coordinator) | | Command file not found | Fallback to inline execution in coordinator role.md |
| Role file not found | Error with expected path (roles/{name}.md) | | team-worker agent unavailable | Error: requires .claude/agents/team-worker.md |
| Planner issue planning failure | Retry once, then report error and skip to next issue | | Planner issue planning failure | Retry once, then skip to next issue |
| Executor impl failure | Report to planner, continue with next EXEC-* task | | Executor impl failure | Report to coordinator, continue with next EXEC-* task |
| No EXEC-* tasks yet | Executor idles, polls for new tasks | | Pipeline stall | Coordinator monitors, escalate to user |
| Pipeline stall | Planner monitors -- if executor blocked > 2 tasks, escalate to user | | Completion action timeout | Default to Keep Active |

View File

@@ -0,0 +1,102 @@
---
prefix: EXEC
inner_loop: true
message_types:
success: impl_complete
error: impl_failed
---
# Executor
Single-issue implementation agent. Loads solution from artifact file, routes to execution backend (Agent/Codex/Gemini), verifies with tests, commits, and reports completion.
## Phase 2: Task & Solution Loading
| Input | Source | Required |
|-------|--------|----------|
| Issue ID | Task description `Issue ID:` field | Yes |
| Solution file | Task description `Solution file:` field | Yes |
| Session folder | Task description `Session:` field | Yes |
| Execution method | Task description `Execution method:` field | Yes |
| Wisdom | `<session>/wisdom/` | No |
1. Extract issue ID, solution file path, session folder, execution method
2. Load solution JSON from file (file-first)
3. If file not found -> fallback: `ccw issue solution <issueId> --json`
4. Load wisdom files for conventions and patterns
5. Verify solution has required fields: title, tasks
## Phase 3: Implementation
### Backend Selection
| Method | Backend | Agent Type |
|--------|---------|------------|
| `agent` | code-developer subagent | Inline delegation |
| `codex` | `ccw cli --tool codex --mode write` | Background CLI |
| `gemini` | `ccw cli --tool gemini --mode write` | Background CLI |
### Agent Backend
```
Task({
subagent_type: "code-developer",
description: "Implement <issue-title>",
prompt: `Issue: <issueId>
Title: <solution.title>
Solution: <solution JSON>
Implement all tasks from the solution plan.`,
run_in_background: false
})
```
### CLI Backend (Codex/Gemini)
```bash
ccw cli -p "Issue: <issueId>
Title: <solution.title>
Solution Plan: <solution JSON>
Implement all tasks. Follow existing patterns. Run tests." \
--tool <codex|gemini> --mode write
```
Wait for CLI completion before proceeding.
## Phase 4: Verification + Commit
### Test Verification
| Check | Method | Pass Criteria |
|-------|--------|---------------|
| Tests | Detect and run project test command | All pass |
| Syntax | IDE diagnostics or `tsc --noEmit` | No errors |
If tests fail: retry implementation once, then report `impl_failed`.
### Commit
```bash
git add -A
git commit -m "feat(<issueId>): <solution.title>"
```
### Update Issue Status
```bash
ccw issue update <issueId> --status completed
```
### Report
Send `impl_complete` message to coordinator via team_msg + SendMessage:
- summary: `[executor] Implemented <issueId>: <title>`
## Boundaries
| Allowed | Prohibited |
|---------|-----------|
| Load solution from file | Create or modify issues |
| Implement via Agent/Codex/Gemini | Modify solution artifacts |
| Run tests | Spawn additional agents |
| git commit | Direct user interaction |
| Update issue status | Create tasks for other roles |

View File

@@ -0,0 +1,111 @@
---
prefix: PLAN
inner_loop: true
subagents: [issue-plan-agent]
message_types:
success: issue_ready
error: error
---
# Planner
Requirement decomposition → issue creation → solution design → EXEC-* task creation. Processes issues one at a time, creating executor tasks as solutions are completed.
## Phase 2: Context Loading
| Input | Source | Required |
|-------|--------|----------|
| Input type + raw input | Task description | Yes |
| Session folder | Task description `Session:` field | Yes |
| Execution method | Task description `Execution method:` field | Yes |
| Wisdom | `<session>/wisdom/` | No |
1. Extract session path, input type, raw input, execution method from task description
2. Load wisdom files if available
3. Parse input to determine issue list:
| Detection | Condition | Action |
|-----------|-----------|--------|
| Issue IDs | `ISS-\d{8}-\d{6}` pattern | Use directly |
| `--text '...'` | Flag in input | Create issue(s) via `ccw issue create` |
| `--plan <path>` | Flag in input | Read file, parse phases, batch create issues |
## Phase 3: Issue Processing Loop
For each issue, execute in sequence:
### 3a. Generate Solution
Delegate to `issue-plan-agent` subagent:
```
Task({
subagent_type: "issue-plan-agent",
description: "Plan issue <issueId>",
prompt: `issue_ids: ["<issueId>"]
project_root: "<project-root>"
Generate solution for this issue. Auto-bind single solution.`,
run_in_background: false
})
```
### 3b. Write Solution Artifact
Write solution JSON to: `<session>/artifacts/solutions/<issueId>.json`
```json
{
"session_id": "<session-id>",
"issue_id": "<issueId>",
"solution": <solution-from-agent>,
"planned_at": "<ISO timestamp>"
}
```
### 3c. Check Conflicts
Extract `files_touched` from solution. Compare against prior solutions in session.
Overlapping files -> log warning to `wisdom/issues.md`, continue.
### 3d. Create EXEC-* Task
```
TaskCreate({
subject: "EXEC-00N: Implement <issue-title>",
description: `Implement solution for issue <issueId>.
Issue ID: <issueId>
Solution file: <session>/artifacts/solutions/<issueId>.json
Session: <session>
Execution method: <method>
InnerLoop: true`,
activeForm: "Implementing <issue-title>"
})
```
### 3e. Signal issue_ready
Send message via team_msg + SendMessage to coordinator:
- type: `issue_ready`
- summary: `[planner] Solution ready for <issueId>`
### 3f. Continue Loop
Process next issue. Do NOT wait for executor.
## Phase 4: Completion Signal
After all issues processed:
1. Send `all_planned` message to coordinator via team_msg + SendMessage
2. Summary: total issues planned, EXEC-* tasks created
## Boundaries
| Allowed | Prohibited |
|---------|-----------|
| Parse input, create issues | Write/modify business code |
| Generate solutions (issue-plan-agent) | Run tests |
| Write solution artifacts | git commit |
| Create EXEC-* tasks | Call code-developer |
| Conflict checking | Direct user interaction |

View File

@@ -0,0 +1,87 @@
# Command: dispatch
## Purpose
Create the initial task chain for team-planex pipeline. Creates PLAN-001 for planner. EXEC-* tasks are NOT pre-created — planner creates them at runtime per issue.
## Phase 2: Context Loading
| Input | Source | Required |
|-------|--------|----------|
| Input type | Phase 1 requirements | Yes |
| Raw input | Phase 1 requirements | Yes |
| Session folder | Phase 2 session init | Yes |
| Execution method | Phase 1 requirements | Yes |
## Phase 3: Task Chain Creation
### Task Creation
Create a single PLAN-001 task for the planner:
```
TaskCreate({
subject: "PLAN-001: Requirement decomposition and solution design",
description: `Decompose requirements into issues and generate solutions.
Input type: <issues|text|plan>
Input: <raw-input>
Session: <session-folder>
Execution method: <agent|codex|gemini>
## Instructions
1. Parse input to get issue list
2. For each issue: call issue-plan-agent → write solution artifact
3. After each solution: create EXEC-* task (owner: executor) with solution_file path
4. After all issues: send all_planned signal
InnerLoop: true`,
activeForm: "Planning requirements"
})
```
### EXEC-* Task Template (for planner reference)
Planner creates EXEC-* tasks at runtime using this template:
```
TaskCreate({
subject: "EXEC-00N: Implement <issue-title>",
description: `Implement solution for issue <issueId>.
Issue ID: <issueId>
Solution file: <session-folder>/artifacts/solutions/<issueId>.json
Session: <session-folder>
Execution method: <agent|codex|gemini>
InnerLoop: true`,
activeForm: "Implementing <issue-title>"
})
```
### Add Command Task Template
When coordinator handles `add` command, create additional PLAN tasks:
```
TaskCreate({
subject: "PLAN-00N: Additional requirement decomposition",
description: `Additional requirements to decompose.
Input type: <issues|text|plan>
Input: <new-input>
Session: <session-folder>
Execution method: <execution-method>
InnerLoop: true`,
activeForm: "Planning additional requirements"
})
```
## Phase 4: Validation
| Check | Criteria |
|-------|----------|
| PLAN-001 created | TaskList shows PLAN-001 |
| Description complete | Contains Input, Session, Execution method |
| No orphans | All tasks have valid owner |

View File

@@ -0,0 +1,163 @@
# Command: monitor
## Purpose
Event-driven pipeline coordination with Spawn-and-Stop pattern. Three wake-up sources: worker callbacks, user `check`, user `resume`.
## Constants
| Constant | Value | Description |
|----------|-------|-------------|
| SPAWN_MODE | background | All workers spawned via `Task(run_in_background: true)` |
| ONE_STEP_PER_INVOCATION | true | Coordinator does one operation then STOPS |
| WORKER_AGENT | team-worker | All workers are team-worker agents |
## Phase 2: Context Loading
| Input | Source | Required |
|-------|--------|----------|
| Session file | `<session-folder>/team-session.json` | Yes |
| Task list | `TaskList()` | Yes |
| Active workers | session.active_workers[] | Yes |
## Phase 3: Handler Routing
### Wake-up Source Detection
| Priority | Condition | Handler |
|----------|-----------|---------|
| 1 | Message contains `[planner]` or `[executor]` tag | handleCallback |
| 2 | Contains "check" or "status" | handleCheck |
| 3 | Contains "resume", "continue", or "next" | handleResume |
| 4 | None of the above (initial spawn) | handleSpawnNext |
---
### Handler: handleCallback
```
Receive callback from [<role>]
+- Match role: planner or executor
+- Progress update (not final)?
| +- YES -> Update session -> STOP
+- Task status = completed?
| +- YES -> remove from active_workers -> update session
| | +- role = planner?
| | | +- Check for new EXEC-* tasks (planner creates them)
| | | +- -> handleSpawnNext (spawn executor for new EXEC-* tasks)
| | +- role = executor?
| | +- Mark issue done
| | +- -> handleSpawnNext (check for more EXEC-* tasks)
| +- NO -> progress message -> STOP
+- No matching worker found
+- Scan all active workers for completed tasks
+- Found completed -> process -> handleSpawnNext
+- None completed -> STOP
```
---
### Handler: handleCheck
Read-only status report. No advancement.
```
[coordinator] PlanEx Pipeline Status
[coordinator] Progress: <completed>/<total> (<percent>%)
[coordinator] Task Graph:
PLAN-001: <status-icon> <summary>
EXEC-001: <status-icon> <issue-title>
EXEC-002: <status-icon> <issue-title>
...
done=completed >>>=running o=pending
[coordinator] Active Workers:
> <subject> (<role>) - running <elapsed>
[coordinator] Ready to spawn: <subjects>
[coordinator] Commands: 'resume' to advance | 'check' to refresh
```
Then STOP.
---
### Handler: handleResume
```
Load active_workers
+- No active workers -> handleSpawnNext
+- Has active workers -> check each:
+- completed -> mark done, log
+- in_progress -> still running
+- other -> worker failure -> reset to pending
After:
+- Some completed -> handleSpawnNext
+- All running -> report status -> STOP
+- All failed -> handleSpawnNext (retry)
```
---
### Handler: handleSpawnNext
```
Collect task states from TaskList()
+- Filter tasks: PLAN-* and EXEC-* prefixes
+- readySubjects: pending + not blocked (no blockedBy or all blockedBy completed)
+- NONE ready + work in progress -> report waiting -> STOP
+- NONE ready + nothing running -> PIPELINE_COMPLETE -> Phase 5
+- HAS ready tasks -> for each:
+- Inner Loop role AND already has active_worker for that role?
| +- YES -> SKIP spawn (existing worker picks up via inner loop)
| +- NO -> spawn below
+- Determine role from task prefix:
| +- PLAN-* -> planner
| +- EXEC-* -> executor
+- Spawn team-worker:
Task({
subagent_type: "team-worker",
description: "Spawn <role> worker for <subject>",
team_name: <team-name>,
name: "<role>",
run_in_background: true,
prompt: `## Role Assignment
role: <role>
role_spec: .claude/skills/team-planex/role-specs/<role>.md
session: <session-folder>
session_id: <session-id>
team_name: <team-name>
requirement: <task-description>
inner_loop: true
execution_method: <method>`
})
+- Add to session.active_workers
Update session -> output summary -> STOP
```
---
## Phase 4: Validation
| Check | Criteria |
|-------|----------|
| Session state consistent | active_workers matches in_progress tasks |
| No orphaned tasks | Every in_progress has active_worker |
| Pipeline completeness | All expected EXEC-* tasks accounted for |
## Worker Failure Handling
1. Reset task -> pending via TaskUpdate
2. Log via team_msg (type: error)
3. Report to user
## Error Handling
| Scenario | Resolution |
|----------|------------|
| Session file not found | Error, suggest re-initialization |
| Unknown role callback | Log, scan for other completions |
| All workers running on resume | Report status, suggest check later |
| Pipeline stall (no ready + no running + has pending) | Check blockedBy chains, report |

View File

@@ -0,0 +1,154 @@
# Coordinator Role
Orchestrate the team-planex pipeline: parse input, create team, dispatch tasks, monitor progress via Spawn-and-Stop beats. Uses **team-worker agent** for all worker spawns.
## Identity
- **Name**: `coordinator` | **Tag**: `[coordinator]`
- **Responsibility**: Parse input -> Create team -> Dispatch PLAN-001 -> Spawn planner -> Monitor callbacks -> Spawn executors -> Report
## Boundaries
### MUST
- Parse user input (Issue IDs / --text / --plan) and determine execution method
- Create team and initialize session directory
- Dispatch tasks via `commands/dispatch.md`
- Monitor progress via `commands/monitor.md` with Spawn-and-Stop pattern
- Maintain session state (team-session.json)
### MUST NOT
- Execute planning or implementation work directly (delegate to workers)
- Modify solution artifacts or code (workers own their deliverables)
- Call implementation subagents (code-developer, etc.) directly
- Skip dependency validation when creating task chains
---
## Command Execution Protocol
When coordinator needs to execute a command (dispatch, monitor):
1. **Read the command file**: `roles/coordinator/commands/<command-name>.md`
2. **Follow the workflow** defined in the command file
3. **Commands are inline execution guides** - NOT separate agents
4. **Execute synchronously** - complete the command workflow before proceeding
---
## Entry Router
When coordinator is invoked, detect invocation type:
| Detection | Condition | Handler |
|-----------|-----------|---------|
| Worker callback | Message contains `[planner]` or `[executor]` tag | -> handleCallback (monitor.md) |
| Status check | Arguments contain "check" or "status" | -> handleCheck (monitor.md) |
| Manual resume | Arguments contain "resume" or "continue" | -> handleResume (monitor.md) |
| Add tasks | Arguments contain "add" | -> handleAdd |
| Interrupted session | Active/paused session exists in `.workflow/.team/PEX-*` | -> Phase 0 |
| New session | None of above | -> Phase 1 |
For callback/check/resume: load `commands/monitor.md` and execute the appropriate handler, then STOP.
### handleAdd
1. Parse new input (Issue IDs / `--text` / `--plan`)
2. Get current max PLAN-* sequence from `TaskList`
3. `TaskCreate` new PLAN-00N task (owner: planner)
4. If planner already sent `all_planned` (check team_msg) -> `SendMessage` to planner to re-enter loop
5. STOP
---
## Phase 0: Session Resume Check
1. Scan `.workflow/.team/PEX-*/team-session.json` for sessions with status "active" or "paused"
2. No sessions found -> proceed to Phase 1
3. Single session found -> resume (Session Reconciliation)
4. Multiple sessions -> AskUserQuestion for selection
**Session Reconciliation**:
1. Audit TaskList -> reconcile session state vs task status
2. Reset in_progress tasks -> pending (they were interrupted)
3. Rebuild team if needed (TeamCreate + spawn needed workers)
4. Kick first executable task -> Phase 4
---
## Phase 1: Input Parsing + Execution Method
1. **Parse arguments**: Extract input type (Issue IDs / --text / --plan) and optional flags (--exec, -y)
2. **Determine execution method** (see SKILL.md Selection Decision Table):
- Explicit `--exec` flag -> use specified method
- `-y` / `--yes` flag -> Auto mode
- No flags -> AskUserQuestion for method choice
3. **Store requirements**: input_type, raw_input, execution_method
---
## Phase 2: Create Team + Initialize Session
1. Generate session ID: `PEX-<slug>-<date>`
2. Create session folder: `.workflow/.team/<session-id>/`
3. Create subdirectories: `artifacts/solutions/`, `wisdom/`
4. Call `TeamCreate` with team name (default: "planex")
5. Initialize wisdom files (learnings.md, decisions.md, conventions.md, issues.md)
6. Write team-session.json:
```
{
session_id: "<session-id>",
input_type: "<issues|text|plan>",
input: "<raw-input>",
execution_method: "<agent|codex|gemini>",
status: "active",
active_workers: [],
started_at: "<ISO timestamp>"
}
```
---
## Phase 3: Create Task Chain
Delegate to `commands/dispatch.md`:
1. Read `roles/coordinator/commands/dispatch.md`
2. Execute its workflow to create PLAN-001 task
3. PLAN-001 contains input info + execution method in description
---
## Phase 4: Spawn-and-Stop
1. Load `commands/monitor.md`
2. Execute `handleSpawnNext` to find ready tasks and spawn planner worker
3. Output status summary
4. **STOP** (idle, wait for worker callback)
**ONE_STEP_PER_INVOCATION**: true — coordinator does one operation per wake-up, then STOPS.
---
## Phase 5: Report + Completion Action
When all tasks are complete (monitor.md detects PIPELINE_COMPLETE):
1. Load session state -> count completed tasks, duration
2. List deliverables with output paths
3. Update session status -> "completed"
4. Execute Completion Action (see SKILL.md)
---
## Error Handling
| Error | Resolution |
|-------|------------|
| Session file not found | Error, suggest re-initialization |
| Unknown worker callback | Log, scan for other completions |
| Pipeline stall | Check missing tasks, report to user |
| Worker crash | Reset task to pending, re-spawn on next beat |
| All workers running on resume | Report status, suggest check later |

View File

@@ -1,356 +0,0 @@
# Executor Role
Load solution -> Route to backend (Agent/Codex/Gemini) based on execution_method -> Test verification -> Commit. Supports multiple CLI execution backends. Execution method is determined before skill invocation (see SKILL.md Execution Method Selection).
## Identity
- **Name**: `executor` | **Tag**: `[executor]`
- **Task Prefix**: `EXEC-*`
- **Responsibility**: Code implementation (solution -> route to backend -> test -> commit)
## Boundaries
### MUST
- Only process `EXEC-*` prefixed tasks
- All output (SendMessage, team_msg, logs) must carry `[executor]` identifier
- Select execution backend based on `execution_method` field in EXEC-* task
- Notify planner after each issue completes
- Continuously poll for new EXEC-* tasks (planner may create new waves anytime)
### MUST NOT
- Create issues (planner responsibility)
- Modify solution or queue (planner responsibility)
- Call issue-plan-agent or issue-queue-agent
- Interact directly with user (AskUserQuestion)
- Create PLAN-* tasks for planner
---
## Toolbox
### Execution Backends
| Backend | Tool | Invocation | Mode |
|---------|------|------------|------|
| `agent` | code-developer subagent | `Task({ subagent_type: "code-developer" })` | Synchronous |
| `codex` | Codex CLI | `ccw cli --tool codex --mode write` | Background |
| `gemini` | Gemini CLI | `ccw cli --tool gemini --mode write` | Background |
### Direct Capabilities
| Tool | Purpose |
|------|---------|
| `Read` | Read solution plan and queue files |
| `Write` | Write implementation artifacts |
| `Edit` | Edit source code |
| `Bash` | Run tests, git operations, CLI calls |
### CLI Capabilities
| CLI Command | Purpose |
|-------------|---------|
| `ccw issue status <id> --json` | Check issue status |
| `ccw issue solution <id> --json` | Load single issue's bound solution (requires issue ID) |
| `ccw issue update <id> --status executing` | Update issue status to executing |
| `ccw issue update <id> --status completed` | Mark issue as completed |
---
## Message Types
| Type | Direction | Trigger | Description |
|------|-----------|---------|-------------|
| `impl_complete` | executor -> planner | Implementation and tests pass | Single issue implementation complete |
| `impl_failed` | executor -> planner | Implementation failed after retries | Implementation failure |
| `wave_done` | executor -> planner | All EXEC tasks in a wave completed | Entire wave complete |
| `error` | executor -> planner | Blocking error | Execution error |
## Message Bus
Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
**NOTE**: `team` must be **session ID** (e.g., `PEX-project-2026-02-27`), NOT team name. Extract from `Session:` field in task description.
```
mcp__ccw-tools__team_msg({
operation: "log",
team: <session-id>, // e.g., "PEX-project-2026-02-27", NOT "planex"
from: "executor",
to: "planner",
type: <message-type>,
summary: "[executor] <task-prefix> complete: <task-subject>",
ref: <artifact-path>
})
```
**CLI fallback** (when MCP unavailable):
```
Bash("ccw team log --team <session-id> --from executor --to planner --type <message-type> --summary \"[executor] <task-prefix> complete\" --ref <artifact-path> --json")
```
---
## Execution (5-Phase)
### Phase 1: Task Discovery
> See SKILL.md Shared Infrastructure -> Worker Phase 1: Task Discovery
Standard task discovery flow: TaskList -> filter by prefix `EXEC-*` + owner match + pending + unblocked -> TaskGet -> TaskUpdate in_progress.
### Phase 2: Load Solution & Resolve Executor
**Issue ID Extraction**:
Extract issue ID from task description using pattern `ISS-\d{8}-\d{6}`.
If no issue ID found:
1. Log error via team_msg
2. SendMessage error to planner
3. TaskUpdate completed
4. Return to idle
**Solution Loading (Dual Mode)**:
| Mode | Condition | Action |
|------|-----------|--------|
| File-first | Task description contains `solution_file: <path>` | Read JSON file, extract solution.bound |
| CLI fallback | No solution_file field | Call `ccw issue solution <issueId> --json` |
If no bound solution found:
1. Log error via team_msg
2. SendMessage error to planner
3. TaskUpdate completed
4. Return to idle
**Execution Method Resolution**:
| Condition | Executor |
|-----------|----------|
| `execution_method: Agent` in task description | agent |
| `execution_method: Codex` in task description | codex |
| `execution_method: Gemini` in task description | gemini |
| `execution_method: Auto` + task_count <= 3 | agent |
| `execution_method: Auto` + task_count > 3 | codex |
| Unknown or missing | agent (with warning) |
**Code Review Resolution**:
Extract `code_review` from task description. Values: Skip | Gemini Review | Codex Review | Agent Review. Default: Skip.
**Issue Status Update**:
```
Bash("ccw issue update <issueId> --status executing")
```
### Phase 3: Implementation (Multi-Backend Routing)
Route to execution backend based on resolved executor.
#### Option A: Agent Execution
**When**: executor === 'agent' (simple tasks, task_count <= 3)
**Tool call**:
```
Task({
subagent_type: "code-developer",
run_in_background: false,
description: "Implement solution for <issueId>",
prompt: <execution-prompt>
})
```
Synchronous execution - wait for completion before Phase 4.
#### Option B: Codex CLI Execution
**When**: executor === 'codex' (complex tasks, background execution)
**Tool call**:
```
Bash("ccw cli -p \"<execution-prompt>\" --tool codex --mode write --id planex-<issueId>", { run_in_background: true })
```
**Resume on failure**:
```
ccw cli -p "Continue implementation" --resume planex-<issueId> --tool codex --mode write --id planex-<issueId>-retry
```
STOP after spawn - CLI executes in background, wait for task hook callback.
#### Option C: Gemini CLI Execution
**When**: executor === 'gemini' (analysis-heavy tasks, background execution)
**Tool call**:
```
Bash("ccw cli -p \"<execution-prompt>\" --tool gemini --mode write --id planex-<issueId>", { run_in_background: true })
```
STOP after spawn - CLI executes in background, wait for task hook callback.
### Execution Prompt Template
All backends use unified prompt structure:
```
## Issue
ID: <issueId>
Title: <solution-title>
## Solution Plan
<solution-bound-json>
## Implementation Requirements
1. Follow the solution plan tasks in order
2. Write clean, minimal code following existing patterns
3. Run tests after each significant change
4. Ensure all existing tests still pass
5. Do NOT over-engineer - implement exactly what the solution specifies
## Quality Checklist
- [ ] All solution tasks implemented
- [ ] No TypeScript/linting errors
- [ ] Existing tests pass
- [ ] New tests added where appropriate
- [ ] No security vulnerabilities introduced
## Project Guidelines
@.workflow/specs/*.md
```
### Phase 4: Verify & Commit
**Test Detection**:
| Detection | Method |
|-----------|--------|
| package.json scripts.test | Use `npm test` |
| package.json scripts.test:unit | Use `npm run test:unit` |
| No test script found | Skip verification, proceed to commit |
**Test Verification**:
```
Bash("<testCmd> 2>&1 || echo TEST_FAILED")
```
Check output for `TEST_FAILED` or `FAIL` strings.
**Test Failure Handling**:
| Condition | Action |
|-----------|--------|
| Tests failing | Report impl_failed to planner with test output + resume command |
| Tests passing | Proceed to code review (if configured) |
**Code Review (Optional)**:
| Review Tool | Execution |
|-------------|-----------|
| Gemini Review | `ccw cli -p "<review-prompt>" --tool gemini --mode analysis --id planex-review-<issueId>` (background) |
| Codex Review | `ccw cli --tool codex --mode review --uncommitted` (background, no prompt with target flags) |
| Agent Review | Current agent performs inline review against solution convergence criteria |
**Code Review Prompt**:
```
PURPOSE: Code review for <issueId> implementation against solution plan
TASK: Verify solution convergence criteria | Check test coverage | Analyze code quality | Identify issues
MODE: analysis
CONTEXT: @**/* | Memory: Review planex execution for <issueId>
EXPECTED: Quality assessment with issue identification and recommendations
CONSTRAINTS: Focus on solution adherence and code quality | analysis=READ-ONLY
```
**Issue Completion**:
```
Bash("ccw issue update <issueId> --status completed")
```
### Phase 5: Report + Loop
> See SKILL.md Shared Infrastructure -> Worker Phase 5: Report
**Success Report**:
```
mcp__ccw-tools__team_msg({
operation: "log",
team: <session-id>, // e.g., "PEX-project-2026-02-27", NOT "planex"
from: "executor",
to: "planner",
type: "impl_complete",
summary: "[executor] Implementation complete for <issueId> via <executor>, tests passing"
})
SendMessage({
type: "message",
recipient: "planner",
content: `## [executor] Implementation Complete
**Issue**: <issueId>
**Executor**: <executor>
**Solution**: <solution-id>
**Code Review**: <codeReview>
**Status**: All tests passing
**Issue Status**: Updated to resolved`,
summary: "[executor] EXEC complete: <issueId> (<executor>)"
})
TaskUpdate({ taskId: <task-id>, status: "completed" })
```
**Loop Check**:
Query for next `EXEC-*` task with owner=executor, status=pending, blockedBy empty.
| Condition | Action |
|-----------|--------|
| Tasks available | Return to Phase 1 for next task |
| No tasks + planner sent all_planned | Send wave_done and idle |
| No tasks + planner still planning | Idle for more tasks |
**Wave Done Signal**:
```
mcp__ccw-tools__team_msg({
operation: "log",
team: <session-id>, // e.g., "PEX-project-2026-02-27", NOT "planex"
from: "executor",
to: "planner",
type: "wave_done",
summary: "[executor] All EXEC tasks completed"
})
SendMessage({
type: "message",
recipient: "planner",
content: "## [executor] All Tasks Done\n\nAll EXEC-* tasks have been completed. Pipeline finished.",
summary: "[executor] wave_done: all complete"
})
```
---
## Error Handling
| Scenario | Resolution |
|----------|------------|
| No EXEC-* tasks available | Idle, wait for planner to create tasks |
| Solution plan not found | Report error to planner |
| Unknown execution_method | Fallback to `agent` with warning |
| Agent (code-developer) failure | Retry once, then report impl_failed |
| CLI (Codex/Gemini) failure | Provide resume command with fixed ID, report impl_failed |
| CLI timeout | Use fixed ID `planex-{issueId}` for resume |
| Tests failing after implementation | Report impl_failed with test output + resume info |
| Issue status update failure | Log warning, continue with report |
| Dependency not yet complete | Wait - task is blocked by blockedBy |
| All tasks done but planner still planning | Send wave_done, then idle for more |
| Critical issue beyond scope | SendMessage error to planner |

View File

@@ -1,315 +0,0 @@
# Planner Role
Demand decomposition -> Issue creation -> Solution design -> Conflict check -> EXEC task dispatch. Invokes issue-plan-agent internally (per issue), uses inline files_touched conflict check. Dispatches EXEC-* task immediately after each issue's solution is ready. Planner also serves as lead role (no separate coordinator).
## Identity
- **Name**: `planner` | **Tag**: `[planner]`
- **Task Prefix**: `PLAN-*`
- **Responsibility**: Planning lead (requirement -> issues -> solutions -> queue -> dispatch)
## Boundaries
### MUST
- Only process `PLAN-*` prefixed tasks
- All output (SendMessage, team_msg, logs) must carry `[planner]` identifier
- Immediately create `EXEC-*` task after completing each issue's solution and send `issue_ready` signal
- Continue pushing forward without waiting for executor
- Write solution artifacts to `<sessionDir>/artifacts/solutions/{issueId}.json`
### MUST NOT
- Directly write/modify business code (executor responsibility)
- Call code-developer agent
- Run project tests
- git commit code changes
---
## Toolbox
### Subagent Capabilities
| Agent Type | Purpose |
|------------|---------|
| `issue-plan-agent` | Closed-loop planning: ACE exploration + solution generation + binding (single issue granularity) |
### CLI Capabilities
| CLI Command | Purpose |
|-------------|---------|
| `ccw issue create --data '{"title":"..."}' --json` | Create issue from text |
| `ccw issue status <id> --json` | Check issue status |
| `ccw issue solution <id> --json` | Get single issue's solutions (requires issue ID) |
| `ccw issue solutions --status planned --brief` | Batch list all bound solutions (cross-issue) |
| `ccw issue bind <id> <sol-id>` | Bind solution to issue |
### Skill Capabilities
| Skill | Purpose |
|-------|---------|
| `Skill(skill="issue:new", args="--text '...'")` | Create issue from text |
---
## Message Types
| Type | Direction | Trigger | Description |
|------|-----------|---------|-------------|
| `issue_ready` | planner -> executor | Single issue solution + EXEC task created | Per-issue beat signal |
| `wave_ready` | planner -> executor | All issues in a wave dispatched | Wave summary signal |
| `all_planned` | planner -> executor | All waves planning complete | Final signal |
| `error` | planner -> executor | Blocking error | Planning failure |
## Message Bus
Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
**NOTE**: `team` must be **session ID** (e.g., `PEX-project-2026-02-27`), NOT team name. Extract from `Session:` field in task description.
```
mcp__ccw-tools__team_msg({
operation: "log",
team: <session-id>, // e.g., "PEX-project-2026-02-27", NOT "planex"
from: "planner",
to: "executor",
type: <message-type>,
summary: "[planner] <task-prefix> complete: <task-subject>",
ref: <artifact-path>
})
```
**CLI fallback** (when MCP unavailable):
```
Bash("ccw team log --team <session-id> --from planner --to executor --type <message-type> --summary \"[planner] <task-prefix> complete\" --ref <artifact-path> --json")
```
---
## Execution (5-Phase)
### Phase 1: Task Discovery
> See SKILL.md Shared Infrastructure -> Worker Phase 1: Task Discovery
Standard task discovery flow: TaskList -> filter by prefix `PLAN-*` + owner match + pending + unblocked -> TaskGet -> TaskUpdate in_progress.
### Phase 2: Input Parsing
Parse task description and arguments to determine input type.
**Input Type Detection**:
| Detection | Condition | Handler |
|-----------|-----------|---------|
| Issue IDs | Task description contains `ISS-\d{8}-\d{6}` pattern | Path C: Direct to planning |
| Text input | Arguments contain `--text '...'` | Path A: Create issue first |
| Plan file | Arguments contain `--plan <path>` | Path B: Parse and batch create |
| Execution plan JSON | Plan file is `execution-plan.json` from req-plan | Path D: Wave-aware processing |
| Description text | None of above | Treat task description as requirement text |
**Execution Config Extraction**:
From arguments, extract:
- `execution_method`: Agent | Codex | Gemini | Auto (default: Auto)
- `code_review`: Skip | Gemini Review | Codex Review | Agent Review (default: Skip)
### Phase 3: Issue Processing Pipeline
Execute different processing paths based on input type.
#### Path A: Text Input -> Create Issue
**Workflow**:
1. Use `issue:new` skill to create issue from text
2. Capture created issue ID
3. Add to issue list for planning
**Tool calls**:
```
Skill(skill="issue:new", args="--text '<requirement-text>'")
```
#### Path B: Plan File -> Batch Create Issues
**Workflow**:
1. Read plan file content
2. Parse phases/steps from markdown structure
3. For each phase/step, create an issue
4. Add all issue IDs to list for planning
**Plan Parsing Rules**:
- Match `## Phase N: Title` or `## Step N: Title` or `### N. Title`
- Each match creates one issue with title and description
- Fallback: If no phase structure, entire content becomes single issue
#### Path C: Issue IDs -> Direct Planning
Issue IDs are ready, proceed directly to solution planning.
#### Path D: execution-plan.json -> Wave-Aware Processing
**Workflow**:
1. Parse execution-plan.json with waves array
2. For each wave, process issues sequentially
3. For each issue in wave:
- Call issue-plan-agent to generate solution
- Write solution artifact to `<sessionDir>/artifacts/solutions/{issueId}.json`
- Perform inline conflict check
- Create EXEC-* task with solution_file path
- Send issue_ready signal
4. After each wave completes, send wave_ready signal
5. After all waves, send all_planned signal
**Issue Planning (per issue)**:
```
Task({
subagent_type: "issue-plan-agent",
run_in_background: false,
description: "Plan solution for <issueId>",
prompt: `issue_ids: ["<issueId>"]
project_root: "<projectRoot>"
## Requirements
- Generate solution for this issue
- Auto-bind single solution
- Issues come from req-plan decomposition (tags: req-plan)
- Respect dependencies: <issue_dependencies>`
})
```
**Solution Artifact**:
```
Write({
file_path: "<sessionDir>/artifacts/solutions/<issueId>.json",
content: JSON.stringify({
session_id: <sessionId>,
issue_id: <issueId>,
...solution,
execution_config: { execution_method, code_review },
timestamp: <ISO-timestamp>
}, null, 2)
})
```
**EXEC Task Creation**:
```
TaskCreate({
subject: "EXEC-W<waveNum>-<issueId>: Implement <solution-title>",
description: `## Execution Task
**Wave**: <waveNum>
**Issue**: <issueId>
**solution_file**: <solutionFile>
**execution_method**: <method>
**code_review**: <review>`,
activeForm: "Implementing <issueId>",
owner: "executor"
})
```
#### Wave Processing (Path A/B/C Convergence)
For non-execution-plan inputs, process all issues as a single logical wave:
**Workflow**:
1. For each issue in list:
- Call issue-plan-agent
- Write solution artifact
- Perform inline conflict check
- Create EXEC-* task
- Send issue_ready signal
2. After all issues complete, send wave_ready signal
### Phase 4: Inline Conflict Check + Dispatch
Perform conflict detection using files_touched overlap analysis.
**Conflict Detection Rules**:
| Condition | Action |
|-----------|--------|
| File overlap detected | Add blockedBy dependency to previous task |
| Explicit dependency in solution.bound.dependencies.on_issues | Add blockedBy to referenced task |
| No conflict | No blockedBy, task is immediately executable |
**Inline Conflict Check Algorithm**:
1. Get current solution's files_touched (or affected_files)
2. For each previously dispatched solution:
- Check if any files overlap
- If overlap, add previous execTaskId to blockedBy
3. Check explicit dependencies from solution.bound.dependencies.on_issues
4. Return blockedBy array for TaskUpdate
**Wave Summary Signal** (after all issues in wave):
```
mcp__ccw-tools__team_msg({
operation: "log", team: <session-id>, from: "planner", to: "executor", // team = session ID
type: "wave_ready",
summary: "[planner] Wave <waveNum> fully dispatched: <issueCount> issues"
})
SendMessage({
type: "message", recipient: "executor",
content: "## [planner] Wave <waveNum> Complete\nAll issues dispatched, <count> EXEC tasks created.",
summary: "[planner] wave_ready: wave <waveNum>"
})
```
### Phase 5: Report + Finalize
> See SKILL.md Shared Infrastructure -> Worker Phase 5: Report
**Final Signal** (all waves complete):
```
mcp__ccw-tools__team_msg({
operation: "log",
team: <session-id>, // e.g., "PEX-project-2026-02-27", NOT "planex"
from: "planner",
to: "executor",
type: "all_planned",
summary: "[planner] All <waveCount> waves planned, <issueCount> issues total"
})
SendMessage({
type: "message",
recipient: "executor",
content: `## [planner] All Waves Planned
**Total Waves**: <waveCount>
**Total Issues**: <issueCount>
**Status**: All planning complete, waiting for executor to finish remaining EXEC-* tasks
Pipeline complete when executor sends wave_done confirmation.`,
summary: "[planner] all_planned: <waveCount> waves, <issueCount> issues"
})
TaskUpdate({ taskId: <task-id>, status: "completed" })
```
**Loop Check**: Query for next `PLAN-*` task with owner=planner, status=pending, blockedBy empty. If found, return to Phase 1.
---
## Error Handling
| Scenario | Resolution |
|----------|------------|
| No PLAN-* tasks available | Idle, wait for orchestrator |
| Issue creation failure | Retry once with simplified text, then report error |
| issue-plan-agent failure | Retry once, then report error and skip to next issue |
| Inline conflict check failure | Skip conflict detection, create EXEC task without blockedBy |
| Plan file not found | Report error with expected path |
| execution-plan.json parse failure | Fallback to plan_file parsing (Path B) |
| execution-plan.json missing waves | Report error, suggest re-running req-plan |
| Empty input (no issues, no text, no plan) | AskUserQuestion for clarification |
| Solution artifact write failure | Log warning, create EXEC task without solution_file (executor fallback) |
| Wave partially failed | Report partial success, continue with successful issues |
| Critical issue beyond scope | SendMessage error to executor |

View File

@@ -1,34 +1,37 @@
--- ---
name: team-planex name: team-planex
description: | description: |
Beat pipeline: planner decomposes requirements issue-by-issue, orchestrator spawns Inline planning + delegated execution pipeline. Main flow does planning directly,
Codex executor per issue immediately. All execution via Codex CLI only. spawns Codex executor per issue immediately. All execution via Codex CLI only.
--- ---
# Team PlanEx (Codex) # Team PlanEx (Codex)
逐 Issue 节拍流水线。Planner 每完成一个 issue 的 solution 立即输出 `ISSUE_READY` 信号Orchestrator 即刻 spawn 独立 Codex executor 并行实现,无需等待 planner 完成全部规划 主流程内联规划 + 委托执行。SKILL.md 自身完成规划(不再 spawn planner agent每完成一个 issue 的 solution 立即 spawn executor agent 并行实现,无需等待所有规划完成
## Architecture ## Architecture
``` ```
Input (Issue IDs / --text / --plan) ┌────────────────────────────────────────┐
→ Orchestrator: parse input → init session → spawn planner SKILL.md (主流程 = 规划 + 节拍控制) │
→ Beat loop: │ │
wait(planner) → ISSUE_READY:{issueId} → spawn_agent(executor) Phase 1: 解析输入 + 初始化 session │
→ send_input(planner, "Continue") Phase 2: 逐 issue 规划循环 (内联) │
→ ALL_PLANNED:{count} → close_agent(planner) │ ├── issue-plan → 写 solution artifact │
→ wait(all executors) → report ├── spawn executor agent ────────────┼──> [executor] 实现
│ └── continue (不等 executor) │
│ Phase 3: 等待所有 executors │
│ Phase 4: 汇总报告 │
└────────────────────────────────────────┘
``` ```
## Agent Registry ## Agent Registry
| Agent | Role File | Responsibility | | Agent | Role File | Responsibility |
|-------|-----------|----------------| |-------|-----------|----------------|
| `planner` | `~/.codex/agents/planex-planner.md` | Issue decomp → solution design → ISSUE_READY signals |
| `executor` | `~/.codex/agents/planex-executor.md` | Codex CLI implementation per issue | | `executor` | `~/.codex/agents/planex-executor.md` | Codex CLI implementation per issue |
> Both agents must be deployed to `~/.codex/agents/` before use. > Executor agent must be deployed to `~/.codex/agents/` before use.
> Source: `.codex/skills/team-planex/agents/` > Source: `.codex/skills/team-planex/agents/`
--- ---
@@ -39,18 +42,29 @@ Supported input types (parse from `$ARGUMENTS`):
| Type | Detection | Handler | | Type | Detection | Handler |
|------|-----------|---------| |------|-----------|---------|
| Issue IDs | `ISS-\d{8}-\d{6}` regex | Pass directly to planner | | Issue IDs | `ISS-\d{8}-\d{6}` regex | Use directly for planning |
| Text | `--text '...'` flag | Planner creates issue(s) first | | Text | `--text '...'` flag | Create issue(s) first via CLI |
| Plan file | `--plan <path>` flag | Planner reads file, batch creates issues | | Plan file | `--plan <path>` flag | Read file, parse phases, batch create issues |
### Issue Creation (when needed)
For `--text` input:
```bash
ccw issue create --data '{"title":"<title>","description":"<description>"}' --json
```
For `--plan` input:
- Match `## Phase N: Title`, `## Step N: Title`, or `### N. Title`
- Each match → one issue (title + description from section content)
- Fallback: no structure found → entire file as single issue
--- ---
## Session Setup ## Session Setup
Before spawning agents, initialize session directory: Before processing issues, initialize session directory:
```javascript ```javascript
// Generate session slug from input description (max 20 chars, kebab-case)
const slug = toSlug(inputDescription).slice(0, 20) const slug = toSlug(inputDescription).slice(0, 20)
const date = new Date().toISOString().slice(0, 10).replace(/-/g, '') const date = new Date().toISOString().slice(0, 10).replace(/-/g, '')
const sessionDir = `.workflow/.team/PEX-${slug}-${date}` const sessionDir = `.workflow/.team/PEX-${slug}-${date}`
@@ -58,7 +72,6 @@ const artifactsDir = `${sessionDir}/artifacts/solutions`
Bash(`mkdir -p "${artifactsDir}"`) Bash(`mkdir -p "${artifactsDir}"`)
// Write initial session state
Write({ Write({
file_path: `${sessionDir}/team-session.json`, file_path: `${sessionDir}/team-session.json`,
content: JSON.stringify({ content: JSON.stringify({
@@ -74,128 +87,101 @@ Write({
--- ---
## Phase 1: Spawn Planner ## Phase 1: Parse Input + Initialize
1. Parse `$ARGUMENTS` to determine input type
2. Create issues if needed (--text / --plan)
3. Collect all issue IDs
4. Initialize session directory
---
## Phase 2: Inline Planning Loop
For each issue, execute planning inline (no planner agent):
### 2a. Generate Solution via issue-plan-agent
```javascript ```javascript
const plannerAgent = spawn_agent({ const planAgent = spawn_agent({
message: ` message: `
## TASK ASSIGNMENT ## TASK ASSIGNMENT
### MANDATORY FIRST STEPS (Agent Execute) ### MANDATORY FIRST STEPS (Agent Execute)
1. **Read role definition**: ~/.codex/agents/planex-planner.md (MUST read first) 1. **Read role definition**: ~/.codex/agents/issue-plan-agent.md (MUST read first)
2. Run: `ccw spec load --category "planning execution"`
--- ---
## Session issue_ids: ["${issueId}"]
Session directory: ${sessionDir} project_root: "${projectRoot}"
Artifacts directory: ${artifactsDir}
## Input ## Requirements
${inputType === 'issues' ? `Issue IDs: ${issueIds.join(' ')}` : ''} - Generate solution for this issue
${inputType === 'text' ? `Requirement: ${requirementText}` : ''} - Auto-bind single solution
${inputType === 'plan' ? `Plan file: ${planPath}` : ''} - Output solution JSON when complete
## Beat Protocol (CRITICAL)
Process issues one at a time. After completing each issue's solution:
1. Write solution JSON to: ${artifactsDir}/{issueId}.json
2. Output EXACTLY this line: ISSUE_READY:{issueId}
3. STOP and wait — do NOT continue until you receive "Continue"
When ALL issues are processed:
1. Output EXACTLY: ALL_PLANNED:{totalCount}
` `
}) })
const result = wait({ ids: [planAgent], timeout_ms: 600000 })
close_agent({ id: planAgent })
```
### 2b. Write Solution Artifact
```javascript
const solution = parseSolution(result)
Write({
file_path: `${artifactsDir}/${issueId}.json`,
content: JSON.stringify({
session_id: sessionId,
issue_id: issueId,
solution: solution,
planned_at: new Date().toISOString()
}, null, 2)
})
``` ```
--- ### 2c. Spawn Executor Immediately
## Phase 2: Beat Loop
Orchestrator coordinates the planner-executor pipeline:
```javascript ```javascript
const executorIds = [] const executorId = spawn_agent({
const executorIssueMap = {}
while (true) {
// Wait for planner beat signal (up to 10 min per issue)
const plannerOut = wait({ ids: [plannerAgent], timeout_ms: 600000 })
// Handle timeout: urge convergence and retry
if (plannerOut.timed_out) {
send_input({
id: plannerAgent,
message: "Please output ISSUE_READY:{issueId} for current issue or ALL_PLANNED if done."
})
continue
}
const output = plannerOut.status[plannerAgent].completed
// Detect ALL_PLANNED — pipeline complete
if (output.includes('ALL_PLANNED')) {
const match = output.match(/ALL_PLANNED:(\d+)/)
const total = match ? parseInt(match[1]) : executorIds.length
close_agent({ id: plannerAgent })
break
}
// Detect ISSUE_READY — spawn executor immediately
const issueMatch = output.match(/ISSUE_READY:(ISS-\d{8}-\d{6}|[A-Z0-9-]+)/)
if (issueMatch) {
const issueId = issueMatch[1]
const solutionFile = `${artifactsDir}/${issueId}.json`
const executorId = spawn_agent({
message: ` message: `
## TASK ASSIGNMENT ## TASK ASSIGNMENT
### MANDATORY FIRST STEPS (Agent Execute) ### MANDATORY FIRST STEPS (Agent Execute)
1. **Read role definition**: ~/.codex/agents/planex-executor.md (MUST read first) 1. **Read role definition**: ~/.codex/agents/planex-executor.md (MUST read first)
2. Run: `ccw spec load --category "planning execution"`
--- ---
## Issue ## Issue
Issue ID: ${issueId} Issue ID: ${issueId}
Solution file: ${solutionFile} Solution file: ${artifactsDir}/${issueId}.json
Session: ${sessionDir} Session: ${sessionDir}
## Execution ## Execution
Load solution from file → implement via Codex CLI → verify tests → commit → report. Load solution from file → implement via Codex CLI → verify tests → commit → report.
` `
}) })
executorIds.push(executorId) executorIds.push(executorId)
executorIssueMap[executorId] = issueId executorIssueMap[executorId] = issueId
// Signal planner to continue to next issue
send_input({ id: plannerAgent, message: "Continue with next issue." })
continue
}
// Unexpected output: urge convergence
send_input({
id: plannerAgent,
message: "Output ISSUE_READY:{issueId} when solution is ready, or ALL_PLANNED when all done."
})
}
``` ```
### 2d. Continue to Next Issue
Do NOT wait for executor. Proceed to next issue immediately.
--- ---
## Phase 3: Wait All Executors ## Phase 3: Wait All Executors
```javascript ```javascript
if (executorIds.length > 0) { if (executorIds.length > 0) {
// Extended timeout: Codex CLI execution per issue (~10-20 min each)
const execResults = wait({ ids: executorIds, timeout_ms: 1800000 }) const execResults = wait({ ids: executorIds, timeout_ms: 1800000 })
if (execResults.timed_out) { if (execResults.timed_out) {
const completed = executorIds.filter(id => execResults.status[id]?.completed)
const pending = executorIds.filter(id => !execResults.status[id]?.completed) const pending = executorIds.filter(id => !execResults.status[id]?.completed)
// Log pending issues for manual follow-up
if (pending.length > 0) { if (pending.length > 0) {
const pendingIssues = pending.map(id => executorIssueMap[id]) const pendingIssues = pending.map(id => executorIssueMap[id])
Write({ Write({
@@ -216,12 +202,29 @@ if (executorIds.length > 0) {
executorIds.forEach(id => { executorIds.forEach(id => {
try { close_agent({ id }) } catch { /* already closed */ } try { close_agent({ id }) } catch { /* already closed */ }
}) })
}
```
// Final report ---
const completed = summaries.filter(s => s.status === 'completed').length
const failed = summaries.filter(s => s.status === 'timeout').length
return ` ## Phase 4: Report
```javascript
const completed = summaries.filter(s => s.status === 'completed').length
const failed = summaries.filter(s => s.status === 'timeout').length
// Update session
Write({
file_path: `${sessionDir}/team-session.json`,
content: JSON.stringify({
...session,
status: "completed",
completed_at: new Date().toISOString(),
results: { total: executorIds.length, completed, failed }
}, null, 2)
})
return `
## Pipeline Complete ## Pipeline Complete
**Total issues**: ${executorIds.length} **Total issues**: ${executorIds.length}
@@ -232,7 +235,6 @@ ${summaries.map(s => `- ${s.issue_id}: ${s.status}`).join('\n')}
Session: ${sessionDir} Session: ${sessionDir}
` `
}
``` ```
--- ---
@@ -244,29 +246,7 @@ During execution, the user may issue:
| Command | Action | | Command | Action |
|---------|--------| |---------|--------|
| `check` / `status` | Show executor progress summary | | `check` / `status` | Show executor progress summary |
| `resume` / `continue` | Urge stalled planner or executor | | `resume` / `continue` | Urge stalled executor |
| `add <issue-ids>` | `send_input` to planner with new issue IDs |
| `add --text '...'` | `send_input` to planner to create and plan new issue |
| `add --plan <path>` | `send_input` to planner to parse and batch create from plan file |
**`add` handler** (inject mid-execution):
```javascript
// Get current planner agent ID from session state
const session = JSON.parse(Read(`${sessionDir}/team-session.json`))
const plannerAgentId = session.planner_agent_id // saved during Phase 1
send_input({
id: plannerAgentId,
message: `
## NEW ISSUES INJECTED
${newInput}
Process these after current issue (or immediately if idle).
Follow beat protocol: ISSUE_READY → wait for Continue → next issue.
`
})
```
--- ---
@@ -274,9 +254,8 @@ Follow beat protocol: ISSUE_READY → wait for Continue → next issue.
| Scenario | Resolution | | Scenario | Resolution |
|----------|------------| |----------|------------|
| Planner timeout (>10 min per issue) | `send_input` urge convergence, re-enter loop | | issue-plan-agent timeout (>10 min) | Skip issue, log error, continue to next |
| Planner never outputs ISSUE_READY | After 3 retries, `close_agent` + report stall | | issue-plan-agent failure | Retry once, then skip with error log |
| Solution file not written | Executor reports error, logs to `${sessionDir}/errors.json` | | Solution file not written | Executor reports error, logs to `${sessionDir}/errors.json` |
| Executor (Codex CLI) failure | Executor handles resume; logs CLI resume command | | Executor (Codex CLI) failure | Executor handles resume; logs CLI resume command |
| ALL_PLANNED never received | After 60 min total, close planner, wait remaining executors | | No issues to process | Report error: no issues found |
| No issues to process | AskUserQuestion for clarification |

View File

@@ -23,13 +23,13 @@ completion report.
| Action | Allowed | | Action | Allowed |
|--------|---------| |--------|---------|
| Read solution artifact from disk | | | Read solution artifact from disk | Yes |
| Implement via Codex CLI | | | Implement via Codex CLI | Yes |
| Run tests for verification | | | Run tests for verification | Yes |
| git commit completed work | | | git commit completed work | Yes |
| Create or modify issues | | | Create or modify issues | No |
| Spawn subagents | | | Spawn subagents | No |
| Interact with user (AskUserQuestion) | | | Interact with user (AskUserQuestion) | No |
--- ---
@@ -38,7 +38,6 @@ completion report.
### Step 1: Load Context ### Step 1: Load Context
After reading role definition: After reading role definition:
- Run: `ccw spec load --category execution`
- Extract issue ID, solution file path, session dir from task message - Extract issue ID, solution file path, session dir from task message
### Step 2: Load Solution ### Step 2: Load Solution
@@ -52,7 +51,7 @@ const solution = solutionData.solution
If file not found or invalid: If file not found or invalid:
- Log error: `[executor] ERROR: Solution file not found: ${solutionFile}` - Log error: `[executor] ERROR: Solution file not found: ${solutionFile}`
- Output: `EXEC_FAILED:{issueId}:solution_file_missing` - Output: `EXEC_FAILED:${issueId}:solution_file_missing`
- Stop execution - Stop execution
Verify solution has required fields: Verify solution has required fields:
@@ -81,10 +80,9 @@ ${JSON.stringify(solution.bound, null, 2)}
## Implementation Requirements ## Implementation Requirements
1. Follow the solution plan tasks in order 1. Follow the solution plan tasks in order
2. Write clean, minimal code following existing patterns 2. Write clean, minimal code following existing patterns
3. Read .workflow/specs/*.md for project conventions 3. Run tests after each significant change
4. Run tests after each significant change 4. Ensure all existing tests still pass
5. Ensure all existing tests still pass 5. Do NOT over-engineer - implement exactly what the solution specifies
6. Do NOT over-engineer - implement exactly what the solution specifies
## Quality Checklist ## Quality Checklist
- [ ] All solution tasks implemented - [ ] All solution tasks implemented
@@ -92,9 +90,6 @@ ${JSON.stringify(solution.bound, null, 2)}
- [ ] Existing tests pass - [ ] Existing tests pass
- [ ] New tests added where specified in solution - [ ] New tests added where specified in solution
- [ ] No security vulnerabilities introduced - [ ] No security vulnerabilities introduced
## Project Guidelines
@.workflow/specs/*.md
PROMPT_EOF PROMPT_EOF
)" --tool codex --mode write --id planex-${issueId} )" --tool codex --mode write --id planex-${issueId}
``` ```
@@ -120,7 +115,6 @@ if (testCmd) {
const testResult = Bash(`${testCmd} 2>&1 || echo TEST_FAILED`) const testResult = Bash(`${testCmd} 2>&1 || echo TEST_FAILED`)
if (testResult.includes('TEST_FAILED') || testResult.includes('FAIL')) { if (testResult.includes('TEST_FAILED') || testResult.includes('FAIL')) {
// Report failure with resume command
const resumeCmd = `ccw cli -p "Fix failing tests" --resume planex-${issueId} --tool codex --mode write` const resumeCmd = `ccw cli -p "Fix failing tests" --resume planex-${issueId} --tool codex --mode write`
Write({ Write({
@@ -179,7 +173,6 @@ EXEC_DONE:${issueId}
If Codex CLI execution fails or times out: If Codex CLI execution fails or times out:
```bash ```bash
# Resume with same session ID
ccw cli -p "Continue implementation from where stopped" \ ccw cli -p "Continue implementation from where stopped" \
--resume planex-${issueId} \ --resume planex-${issueId} \
--tool codex --mode write \ --tool codex --mode write \
@@ -194,19 +187,19 @@ Resume command is always logged to `${sessionDir}/errors.json` on any failure.
| Scenario | Resolution | | Scenario | Resolution |
|----------|------------| |----------|------------|
| Solution file missing | Output `EXEC_FAILED:{id}:solution_file_missing`, stop | | Solution file missing | Output `EXEC_FAILED:<id>:solution_file_missing`, stop |
| Solution JSON malformed | Output `EXEC_FAILED:{id}:solution_invalid`, stop | | Solution JSON malformed | Output `EXEC_FAILED:<id>:solution_invalid`, stop |
| Issue status update fails | Log warning, continue | | Issue status update fails | Log warning, continue |
| Codex CLI failure | Log resume command to errors.json, output `EXEC_FAILED:{id}:codex_failed` | | Codex CLI failure | Log resume command to errors.json, output `EXEC_FAILED:<id>:codex_failed` |
| Tests failing | Log test output + resume command, output `EXEC_FAILED:{id}:tests_failing` | | Tests failing | Log test output + resume command, output `EXEC_FAILED:<id>:tests_failing` |
| Commit fails | Log warning, still output `EXEC_DONE:{id}` (implementation complete) | | Commit fails | Log warning, still output `EXEC_DONE:<id>` (implementation complete) |
| No test command found | Skip test step, proceed to commit | | No test command found | Skip test step, proceed to commit |
## Key Reminders ## Key Reminders
**ALWAYS**: **ALWAYS**:
- Output `EXEC_DONE:{issueId}` on its own line when implementation succeeds - Output `EXEC_DONE:<issueId>` on its own line when implementation succeeds
- Output `EXEC_FAILED:{issueId}:{reason}` on its own line when implementation fails - Output `EXEC_FAILED:<issueId>:<reason>` on its own line when implementation fails
- Log resume command to errors.json on any failure - Log resume command to errors.json on any failure
- Use `[executor]` prefix in all status messages - Use `[executor]` prefix in all status messages

View File

@@ -1,183 +0,0 @@
---
name: planex-planner
description: |
PlanEx planner agent. Issue decomposition + solution design with beat protocol.
Outputs ISSUE_READY:{id} after each solution, waits for "Continue" signal.
Deploy to: ~/.codex/agents/planex-planner.md
color: blue
---
# PlanEx Planner
Requirement decomposition → issue creation → solution design, one issue at a time.
Outputs `ISSUE_READY:{issueId}` after each solution and waits for orchestrator to signal
"Continue". Only outputs `ALL_PLANNED:{count}` when all issues are processed.
## Identity
- **Tag**: `[planner]`
- **Beat Protocol**: ISSUE_READY per issue → wait → ALL_PLANNED when done
- **Boundary**: Planning only — no code writing, no test running, no git commits
## Core Responsibilities
| Action | Allowed |
|--------|---------|
| Parse input (Issue IDs / text / plan file) | ✅ |
| Create issues via CLI | ✅ |
| Generate solution via issue-plan-agent | ✅ |
| Write solution artifacts to disk | ✅ |
| Output ISSUE_READY / ALL_PLANNED signals | ✅ |
| Write or modify business code | ❌ |
| Run tests or git commit | ❌ |
---
## CLI Toolbox
| Command | Purpose |
|---------|---------|
| `ccw issue create --data '{"title":"...","description":"..."}' --json` | Create issue |
| `ccw issue status <id> --json` | Check issue status |
| `ccw issue plan <id>` | Plan single issue (generates solution) |
---
## Execution Flow
### Step 1: Load Context
After reading role definition, load project context:
- Run: `ccw spec load --category planning`
- Extract session directory and artifacts directory from task message
### Step 2: Parse Input
Determine input type from task message:
| Detection | Condition | Action |
|-----------|-----------|--------|
| Issue IDs | `ISS-\d{8}-\d{6}` pattern | Use directly for planning |
| `--text '...'` | Flag in message | Create issue(s) first via CLI |
| `--plan <path>` | Flag in message | Read file, parse phases, batch create issues |
**Plan file parsing rules** (when `--plan` is used):
- Match `## Phase N: Title`, `## Step N: Title`, or `### N. Title`
- Each match → one issue (title + description from section content)
- Fallback: no structure found → entire file as single issue
### Step 3: Issue Processing Loop (Beat Protocol)
For each issue, execute in sequence:
#### 3a. Generate Solution
Use `issue-plan-agent` subagent to generate and bind solution:
```
spawn_agent({
message: `
## TASK ASSIGNMENT
### MANDATORY FIRST STEPS (Agent Execute)
1. **Read role definition**: ~/.codex/agents/issue-plan-agent.md (MUST read first)
2. Run: `ccw spec load --category planning`
---
issue_ids: ["${issueId}"]
project_root: "${projectRoot}"
## Requirements
- Generate solution for this issue
- Auto-bind single solution
- Output solution JSON when complete
`
})
const result = wait({ ids: [agent], timeout_ms: 600000 })
close_agent({ id: agent })
```
#### 3b. Write Solution Artifact
```javascript
// Extract solution from issue-plan-agent result
const solution = parseSolution(result)
Write({
file_path: `${artifactsDir}/${issueId}.json`,
content: JSON.stringify({
session_id: sessionId,
issue_id: issueId,
solution: solution,
planned_at: new Date().toISOString()
}, null, 2)
})
```
#### 3c. Output Beat Signal
Output EXACTLY (no surrounding text on this line):
```
ISSUE_READY:{issueId}
```
Then STOP. Do not process next issue. Wait for "Continue" message from orchestrator.
### Step 4: After All Issues
When every issue has been processed and confirmed with "Continue":
Output EXACTLY:
```
ALL_PLANNED:{totalCount}
```
Where `{totalCount}` is the integer count of issues planned.
---
## Issue Creation (when needed)
For `--text` input:
```bash
ccw issue create --data '{"title":"<title>","description":"<description>"}' --json
```
Parse returned JSON for `id` field → use as issue ID.
For `--plan` input, create issues one at a time:
```bash
# For each parsed phase/step:
ccw issue create --data '{"title":"<phase-title>","description":"<phase-content>"}' --json
```
Collect all created issue IDs before proceeding to Step 3.
---
## Error Handling
| Scenario | Resolution |
|----------|------------|
| Issue creation failure | Retry once with simplified text, then report error |
| `issue-plan-agent` failure | Retry once, then skip issue with `ISSUE_SKIP:{issueId}:reason` signal |
| Plan file not found | Output error immediately, do not proceed |
| Artifact write failure | Log warning inline, still output ISSUE_READY (executor will handle missing file) |
| "Continue" not received after 5 min | Re-output `ISSUE_READY:{issueId}` once as reminder |
## Key Reminders
**ALWAYS**:
- Output `ISSUE_READY:{issueId}` on its own line with no surrounding text
- Wait after each ISSUE_READY — do NOT auto-continue
- Write solution file before outputting ISSUE_READY
- Use `[planner]` prefix in all status messages
**NEVER**:
- Output multiple ISSUE_READY signals before waiting for "Continue"
- Proceed to next issue without receiving "Continue"
- Write or modify any business logic files
- Run tests or execute git commands