feat: migrate all codex team skills from spawn_agents_on_csv to spawn_agent + wait_agent architecture

- Delete 21 old team skill directories using CSV-wave pipeline pattern (~100+ files)
- Delete old team-lifecycle (v3) and team-planex-v2
- Create generic team-worker.toml and team-supervisor.toml (replacing tlv4-specific TOMLs)
- Convert 19 team skills from Claude Code format (Agent/SendMessage/TaskCreate)
  to Codex format (spawn_agent/wait_agent/tasks.json/request_user_input)
- Update team-lifecycle-v4 to use generic agent types (team_worker/team_supervisor)
- Convert all coordinator role files: dispatch.md, monitor.md, role.md
- Convert all worker role files: remove run_in_background, fix Bash syntax
- Convert all specs/pipelines.md references
- Final state: 20 team skills, 217 .md files, zero Claude Code API residuals

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
catlog22
2026-03-24 16:54:48 +08:00
parent 54283e5dbb
commit 1e560ab8e8
334 changed files with 28996 additions and 35516 deletions

View File

@@ -0,0 +1,512 @@
# Team Lifecycle v4 — Codex 迁移计划
## 目标
将 Claude Code 版 `.claude/skills/team-lifecycle-v4` 迁移到 Codex 版 `.codex/skills/team-lifecycle-v4`,采用 **通用 worker + role 文档注入** 模式(与 Claude Code 设计对齐),去掉 `spawn_agents_on_csv`,用 `spawn_agent` + `wait_agent` + `send_input` + `close_agent` 实现同构编排。
## 设计原则
1. **通用 agentrole 文档区分角色** — 只定义 2 个 TOMLworker + supervisor角色差异由 `roles/<role>/role.md` 决定
2. **role 文档直接复用**`.claude/skills/` 中的 roles/specs/templates 原样迁移
3. **items 结构化传参** — 取代 message 字符串,分段传递角色分配、任务描述、上游上下文
4. **JSON 取代 CSV**`tasks.json` 管理状态,`discoveries/{id}.json` 分文件写入
5. **两版同构** — Codex 调用原语与 Claude Code 形成 1:1 映射
## 平台调用映射
| 编排概念 | Claude Code | Codex |
|---------|------------|-------|
| Worker spawn | `Agent({ subagent_type: "team-worker", prompt })` | `spawn_agent({ agent_type: "tlv4_worker", items })` |
| Supervisor spawn | `Agent({ subagent_type: "team-supervisor", prompt })` | `spawn_agent({ agent_type: "tlv4_supervisor", items })` |
| Supervisor wake | `SendMessage({ recipient: "supervisor", content })` | `send_input({ id: supervisorId, items })` |
| Supervisor shutdown | `SendMessage({ type: "shutdown_request" })` | `close_agent({ id: supervisorId })` |
| 等待完成 | 后台回调 -> monitor.md | `wait_agent({ ids, timeout_ms })` |
| 任务状态 | `TaskCreate` / `TaskUpdate` | `tasks.json` 文件读写 |
| 团队管理 | `TeamCreate` / `TeamDelete` | session folder init / cleanup |
| 消息总线 | `mcp__ccw-tools__team_msg` | `discoveries/{id}.json` + `session-state.json` |
| 用户交互 | `AskUserQuestion` | `request_user_input` |
| 角色加载 | prompt 中 `@roles/<role>/role.md` | items text 中指示 `Read roles/<role>/role.md` |
## 目录结构 (迁移后)
```
.codex/
├── agents/
│ ├── tlv4-worker.toml # 通用 worker (NEW)
│ └── tlv4-supervisor.toml # 驻留 supervisor (NEW)
└── skills/
└── team-lifecycle-v4/
├── SKILL.md # 主编排 (REWRITE)
├── MIGRATION-PLAN.md # 本文档
├── roles/ # 从 .claude/ 复制
│ ├── coordinator/
│ │ ├── role.md
│ │ └── commands/
│ │ ├── analyze.md
│ │ ├── dispatch.md
│ │ └── monitor.md
│ ├── analyst/role.md
│ ├── writer/role.md
│ ├── planner/role.md
│ ├── executor/
│ │ ├── role.md
│ │ └── commands/
│ │ ├── implement.md
│ │ └── fix.md
│ ├── tester/role.md
│ ├── reviewer/
│ │ ├── role.md
│ │ └── commands/
│ │ ├── review-code.md
│ │ └── review-spec.md
│ └── supervisor/role.md
├── specs/ # 从 .claude/ 复制
│ ├── pipelines.md
│ ├── quality-gates.md
│ └── knowledge-transfer.md
├── templates/ # 从 .claude/ 复制
│ ├── product-brief.md
│ ├── requirements.md
│ ├── architecture.md
│ └── epics.md
└── schemas/
└── tasks-schema.md # REWRITE: CSV -> JSON
```
---
## 步骤 1: Agent TOML 定义
### `.codex/agents/tlv4-worker.toml`
```toml
name = "tlv4_worker"
description = "Generic team-lifecycle-v4 worker. Role-specific behavior loaded from role.md at spawn time."
model = "gpt-5.4"
model_reasoning_effort = "high"
sandbox_mode = "workspace-write"
developer_instructions = """
You are a team-lifecycle-v4 worker agent.
## Boot Protocol
1. Read role_spec file path from your task assignment (MUST read first)
2. Read session state from session path
3. Execute role-specific Phase 2-4 defined in role.md
4. Write deliverables to session artifacts directory
5. Write findings to discoveries/{task_id}.json
6. Report via report_agent_job_result
## Output Schema
{
"id": "<task_id>",
"status": "completed | failed",
"findings": "<max 500 chars>",
"quality_score": "<0-100, reviewer only>",
"supervision_verdict": "",
"error": ""
}
"""
```
### `.codex/agents/tlv4-supervisor.toml`
```toml
name = "tlv4_supervisor"
description = "Resident supervisor for team-lifecycle-v4. Woken via send_input for checkpoint verification."
model = "gpt-5.4"
model_reasoning_effort = "high"
sandbox_mode = "read-only"
developer_instructions = """
You are a team-lifecycle-v4 supervisor agent (resident pattern).
## Boot Protocol
1. Read role_spec file path from your task assignment (MUST read first)
2. Load baseline context from session
3. Report ready, wait for checkpoint requests via send_input
## Per Checkpoint
1. Read artifacts specified in checkpoint request
2. Verify cross-artifact consistency per role.md definitions
3. Issue verdict: pass (>= 0.8), warn (0.5-0.79), block (< 0.5)
4. Write report to artifacts/CHECKPOINT-{id}-report.md
5. Report findings
## Constraints
- Read-only: never modify artifacts
- Never issue pass when critical inconsistencies exist
- Never block for minor style issues
"""
```
---
## 步骤 2: SKILL.md 改写
### 核心变更
| 区域 | 现状 | 改写后 |
|------|------|--------|
| allowed-tools | `spawn_agents_on_csv, spawn_agent, wait, send_input, close_agent, ...` | `spawn_agent, wait_agent, send_input, close_agent, report_agent_job_result, Read, Write, Edit, Bash, Glob, Grep, request_user_input` |
| 执行模型 | hybrid: CSV wave (primary) + spawn_agent (secondary) | 统一: spawn_agent + wait_agent (all tasks) |
| 状态管理 | tasks.csv (CSV) | tasks.json (JSON) |
| 发现板 | discoveries.ndjson (共享追加) | discoveries/{task_id}.json (分文件) |
| exec_mode 分类 | csv-wave / interactive | 移除 — 所有任务统一用 spawn_agent |
| wave CSV 构建 | 生成 wave-{N}.csv, spawn_agents_on_csv | 循环 spawn_agent + 批量 wait_agent |
### Worker Spawn Template
```javascript
// 对齐 Claude Code 的 Agent({ subagent_type: "team-worker", prompt }) 模式
spawn_agent({
agent_type: "tlv4_worker",
items: [
// 段 1: 角色分配 (对齐 Claude Code prompt 的 Role Assignment 块)
{ type: "text", text: `## Role Assignment
role: ${task.role}
role_spec: ${skillRoot}/roles/${task.role}/role.md
session: ${sessionFolder}
session_id: ${sessionId}
requirement: ${requirement}
inner_loop: ${hasInnerLoop(task.role)}` },
// 段 2: 读取指示 (核心 — 保持 role 文档引用模式)
{ type: "text", text: `Read role_spec file (${skillRoot}/roles/${task.role}/role.md) to load Phase 2-4 domain instructions.
Execute built-in Phase 1 (task discovery) -> role Phase 2-4 -> built-in Phase 5 (report).` },
// 段 3: 任务上下文
{ type: "text", text: `## Task Context
task_id: ${task.id}
title: ${task.title}
description: ${task.description}
pipeline_phase: ${task.pipeline_phase}` },
// 段 4: 上游发现
{ type: "text", text: `## Upstream Context\n${task.prev_context}` }
]
})
```
### Supervisor Spawn Template
```javascript
// Spawn — 一次 (Phase 2 init, 对齐 Claude Code Agent({ subagent_type: "team-supervisor" }))
const supervisorId = spawn_agent({
agent_type: "tlv4_supervisor",
items: [
{ type: "text", text: `## Role Assignment
role: supervisor
role_spec: ${skillRoot}/roles/supervisor/role.md
session: ${sessionFolder}
session_id: ${sessionId}
requirement: ${requirement}
Read role_spec file (${skillRoot}/roles/supervisor/role.md) to load checkpoint definitions.
Init: load baseline context, report ready, go idle.
Wake cycle: orchestrator sends checkpoint requests via send_input.` }
]
})
```
### Supervisor Wake Template
```javascript
// 对齐 Claude Code SendMessage({ recipient: "supervisor", content })
send_input({
id: supervisorId,
items: [
{ type: "text", text: `## Checkpoint Request
task_id: ${task.id}
scope: [${task.deps}]
pipeline_progress: ${done}/${total} tasks completed` }
]
})
wait_agent({ ids: [supervisorId], timeout_ms: 300000 })
```
### Supervisor Shutdown
```javascript
// 对齐 Claude Code SendMessage({ type: "shutdown_request" })
close_agent({ id: supervisorId })
```
### Wave 执行引擎
```javascript
for (let wave = 1; wave <= maxWave; wave++) {
const state = JSON.parse(Read(`${sessionFolder}/tasks.json`))
const waveTasks = Object.values(state.tasks).filter(t => t.wave === wave && t.status === 'pending')
// 跳过依赖失败的任务
const executableTasks = []
for (const task of waveTasks) {
if (task.deps.some(d => ['failed', 'skipped'].includes(state.tasks[d]?.status))) {
state.tasks[task.id].status = 'skipped'
state.tasks[task.id].error = 'Dependency failed or skipped'
continue
}
executableTasks.push(task)
}
// 构建 prev_context
for (const task of executableTasks) {
const contextParts = task.context_from
.map(id => {
const prev = state.tasks[id]
if (prev?.status === 'completed' && prev.findings) {
return `[Task ${id}: ${prev.title}] ${prev.findings}`
}
try {
const disc = JSON.parse(Read(`${sessionFolder}/discoveries/${id}.json`))
return `[Task ${id}] ${disc.findings || JSON.stringify(disc.key_findings || '')}`
} catch { return null }
})
.filter(Boolean)
task.prev_context = contextParts.join('\n') || 'No previous context available'
}
// 分离普通任务和 CHECKPOINT 任务
const regularTasks = executableTasks.filter(t => !t.id.startsWith('CHECKPOINT-'))
const checkpointTasks = executableTasks.filter(t => t.id.startsWith('CHECKPOINT-'))
// 1) 并发 spawn 普通任务
const agentMap = [] // [{ agentId, taskId }]
for (const task of regularTasks) {
state.tasks[task.id].status = 'in_progress'
const agentId = spawn_agent({
agent_type: "tlv4_worker",
items: [
{ type: "text", text: `## Role Assignment
role: ${task.role}
role_spec: ${skillRoot}/roles/${task.role}/role.md
session: ${sessionFolder}
session_id: ${sessionId}
requirement: ${requirement}
inner_loop: ${hasInnerLoop(task.role)}` },
{ type: "text", text: `Read role_spec file (${skillRoot}/roles/${task.role}/role.md) to load Phase 2-4 domain instructions.
Execute built-in Phase 1 (task discovery) -> role Phase 2-4 -> built-in Phase 5 (report).` },
{ type: "text", text: `## Task Context
task_id: ${task.id}
title: ${task.title}
description: ${task.description}
pipeline_phase: ${task.pipeline_phase}` },
{ type: "text", text: `## Upstream Context\n${task.prev_context}` }
]
})
agentMap.push({ agentId, taskId: task.id })
}
// 2) 批量等待
if (agentMap.length > 0) {
wait_agent({ ids: agentMap.map(a => a.agentId), timeout_ms: 900000 })
}
// 3) 收集结果,合并到 tasks.json
for (const { agentId, taskId } of agentMap) {
try {
const disc = JSON.parse(Read(`${sessionFolder}/discoveries/${taskId}.json`))
state.tasks[taskId].status = disc.status || 'completed'
state.tasks[taskId].findings = disc.findings || ''
state.tasks[taskId].quality_score = disc.quality_score || null
state.tasks[taskId].error = disc.error || null
} catch {
state.tasks[taskId].status = 'failed'
state.tasks[taskId].error = 'No discovery file produced'
}
close_agent({ id: agentId })
}
// 4) 执行 CHECKPOINT 任务 (send_input 唤醒 supervisor)
for (const task of checkpointTasks) {
send_input({
id: supervisorId,
items: [
{ type: "text", text: `## Checkpoint Request
task_id: ${task.id}
scope: [${task.deps.join(', ')}]
pipeline_progress: ${completedCount}/${totalCount} tasks completed` }
]
})
wait_agent({ ids: [supervisorId], timeout_ms: 300000 })
// 读取 checkpoint 报告
try {
const report = Read(`${sessionFolder}/artifacts/${task.id}-report.md`)
const verdict = parseVerdict(report) // pass | warn | block
state.tasks[task.id].status = 'completed'
state.tasks[task.id].findings = `Verdict: ${verdict.decision} (score: ${verdict.score})`
state.tasks[task.id].supervision_verdict = verdict.decision
if (verdict.decision === 'block') {
const action = request_user_input({
questions: [{
question: `Checkpoint ${task.id} BLOCKED (score: ${verdict.score}). Choose action.`,
header: "Blocked",
id: "blocked_action",
options: [
{ label: "Override", description: "Proceed despite block" },
{ label: "Revise upstream", description: "Go back and fix issues" },
{ label: "Abort", description: "Stop pipeline" }
]
}]
})
// Handle user choice...
}
} catch {
state.tasks[task.id].status = 'failed'
state.tasks[task.id].error = 'Supervisor report not produced'
}
}
// 5) 持久化 tasks.json
Write(`${sessionFolder}/tasks.json`, JSON.stringify(state, null, 2))
}
```
---
## 步骤 3: 复制 Role 文档
`.claude/skills/team-lifecycle-v4/` 复制以下目录到 `.codex/skills/team-lifecycle-v4/`
| 源 | 目标 | 说明 |
|----|------|------|
| `roles/` (全部) | `roles/` | 原样复制coordinator 中平台相关调用需适配 |
| `specs/pipelines.md` | `specs/pipelines.md` | 原样复制 |
| `specs/quality-gates.md` | `specs/quality-gates.md` | 原样复制 |
| `specs/knowledge-transfer.md` | `specs/knowledge-transfer.md` | 需适配: team_msg -> discoveries/ 文件 |
| `templates/` (全部) | `templates/` | 原样复制 |
### Role 文档适配点
**`roles/coordinator/role.md`** — 需改写:
- Phase 2: `TeamCreate` -> session folder init
- Phase 3: `TaskCreate` -> tasks.json 写入
- Phase 4: `Agent(team-worker)` -> `spawn_agent(tlv4_worker)`
- monitor.md 中 callback 处理 -> `wait_agent` 结果处理
**`roles/coordinator/commands/monitor.md`** — 需改写:
- handleCallback -> wait_agent 结果解析
- handleSpawnNext -> spawn_agent 循环
- SendMessage(supervisor) -> send_input(supervisorId)
**`specs/knowledge-transfer.md`** — 需适配:
- `team_msg(operation="get_state")` -> 读 tasks.json
- `team_msg(type="state_update")` -> 写 discoveries/{id}.json
- 探索缓存协议保持不变
**其余 role 文档** (analyst, writer, planner, executor, tester, reviewer, supervisor):
- 核心执行逻辑不变
- `ccw cli` 调用保持不变 (CLI 工具两侧通用)
- 发现产出改为写 `discoveries/{task_id}.json` (替代 team_msg)
- `report_agent_job_result` 替代 team_msg state_update
---
## 步骤 4: Tasks Schema 改写
### 现状: tasks.csv
```csv
id,title,description,role,pipeline_phase,deps,context_from,exec_mode,wave,status,findings,quality_score,supervision_verdict,error
```
### 改写后: tasks.json
```json
{
"session_id": "tlv4-auth-system-20260324",
"pipeline": "full-lifecycle",
"requirement": "Design and implement user authentication system",
"created_at": "2026-03-24T10:00:00+08:00",
"supervision": true,
"completed_waves": [],
"active_agents": {},
"tasks": {
"RESEARCH-001": {
"title": "Domain research",
"description": "Explore domain, extract structured context...",
"role": "analyst",
"pipeline_phase": "research",
"deps": [],
"context_from": [],
"wave": 1,
"status": "pending",
"findings": null,
"quality_score": null,
"supervision_verdict": null,
"error": null
},
"DRAFT-001": {
"title": "Product brief",
"description": "Generate product brief from research context...",
"role": "writer",
"pipeline_phase": "product-brief",
"deps": ["RESEARCH-001"],
"context_from": ["RESEARCH-001"],
"wave": 2,
"status": "pending",
"findings": null,
"quality_score": null,
"supervision_verdict": null,
"error": null
}
}
}
```
### 发现文件: discoveries/{task_id}.json
```json
{
"task_id": "RESEARCH-001",
"worker": "RESEARCH-001",
"timestamp": "2026-03-24T10:15:00+08:00",
"type": "research",
"status": "completed",
"findings": "Explored domain: identified OAuth2+RBAC pattern, 5 integration points.",
"quality_score": null,
"supervision_verdict": null,
"error": null,
"data": {
"dimension": "domain",
"findings": ["Auth system needs OAuth2 + RBAC"],
"constraints": ["Must support SSO"],
"integration_points": ["User service API"]
},
"artifacts_produced": ["spec/discovery-context.json"]
}
```
---
## 步骤 5: 删除旧文件
迁移完成后,删除 Codex 版中不再需要的文件:
| 文件 | 原因 |
|------|------|
| `agents/agent-instruction.md` | 角色逻辑在 roles/ 中,通用协议在 TOML developer_instructions 中 |
| `agents/requirement-clarifier.md` | 需求澄清逻辑合并到 coordinator/role.md Phase 1 |
| `agents/supervisor.md` | 迁移到 roles/supervisor/role.md |
| `agents/quality-gate.md` | 迁移到 roles/reviewer/role.md (QUALITY-* 任务处理) |
| `schemas/tasks-schema.md` (旧版) | 被 JSON schema 版本替代 |
---
## 实施顺序
| 步骤 | 内容 | 依赖 | 复杂度 |
|------|------|------|--------|
| **1** | 创建 2 个 TOML agent 定义 | 无 | 低 |
| **2** | 复制 roles/specs/templates 从 .claude/ | 无 | 低 (纯复制) |
| **3** | 改写 tasks-schema.md (CSV -> JSON) | 无 | 低 |
| **4** | 改写 SKILL.md 主编排 | 1, 2, 3 | 高 (核心工作) |
| **5** | 适配 coordinator role.md + commands/ | 4 | 中 |
| **6** | 适配 knowledge-transfer.md | 3 | 低 |
| **7** | 适配 worker role 文档 (发现产出方式) | 3 | 低 |
| **8** | 删除旧文件,清理 | 全部 | 低 |
步骤 1-3 可并行,步骤 4 是关键路径,步骤 5-7 依赖步骤 4 但可并行。