fix(skills): replace polling/pre-spawning with Stop-Wait pattern across all team coordinators

All team coordinator roles now follow the Stop-Wait design principle:
- Phase 2: Remove worker pre-spawning, workers are spawned per-stage in Phase 4
- Phase 4: Add Stop-Wait principle note (synchronous Task calls instead of polling)
- monitor.md: Replace while+sleep polling loops with synchronous Task execution

Teams updated: team-brainstorm, team-frontend, team-issue, team-iterdev,
team-lifecycle, team-lifecycle-v2, team-quality-assurance, team-tech-debt,
team-testing, team-uidesign, team-ultra-analyze
This commit is contained in:
catlog22
2026-02-24 00:05:29 +08:00
parent 695045787f
commit e92c6ce0b1
17 changed files with 616 additions and 445 deletions

View File

@@ -94,7 +94,7 @@ AskUserQuestion({
}) })
``` ```
### Phase 2: Create Team + Spawn Workers ### Phase 2: Create Team + Initialize Session
```javascript ```javascript
TeamCreate({ team_name: teamName }) TeamCreate({ team_name: teamName })
@@ -135,7 +135,9 @@ const teamSession = {
Write(`${sessionFolder}/team-session.json`, JSON.stringify(teamSession, null, 2)) Write(`${sessionFolder}/team-session.json`, JSON.stringify(teamSession, null, 2))
``` ```
Spawn workers (see SKILL.md Coordinator Spawn Template). // ⚠️ Workers are NOT pre-spawned here.
// Workers are spawned per-stage in Phase 4 via Stop-Wait Task(run_in_background: false).
// See SKILL.md Coordinator Spawn Template for worker prompt templates.
### Phase 3: Create Task Chain ### Phase 3: Create Task Chain
@@ -212,6 +214,13 @@ TaskUpdate({ taskId: evalId, owner: "evaluator", addBlockedBy: [synthId] })
### Phase 4: Coordination Loop + Generator-Critic Control ### Phase 4: Coordination Loop + Generator-Critic Control
> **设计原则Stop-Wait**: 模型执行没有时间概念,禁止任何形式的轮询等待。
> - ❌ 禁止: `while` 循环 + `sleep` + 检查状态
> - ✅ 采用: 同步 `Task(run_in_background: false)` 调用Worker 返回 = 阶段完成信号
>
> 按 Phase 3 创建的任务链顺序,逐阶段 spawn worker 同步执行。
> Worker prompt 使用 SKILL.md Coordinator Spawn Template。
| Received Message | Action | | Received Message | Action |
|-----------------|--------| |-----------------|--------|
| ideator: ideas_ready | Read ideas → team_msg log → TaskUpdate completed → unblock CHALLENGE | | ideator: ideas_ready | Read ideas → team_msg log → TaskUpdate completed → unblock CHALLENGE |

View File

@@ -149,7 +149,7 @@ AskUserQuestion({
}) })
``` ```
### Phase 2: Create Team + Session + Spawn Teammates ### Phase 2: Create Team + Initialize Session
```javascript ```javascript
// Create session directory // Create session directory
@@ -183,9 +183,11 @@ Write(`${sessionFolder}/shared-memory.json`, JSON.stringify({
industry_context: { industry: industryChoice, config: industry } industry_context: { industry: industryChoice, config: industry }
}, null, 2)) }, null, 2))
// Create team and spawn workers // Create team
TeamCreate({ team_name: teamName }) TeamCreate({ team_name: teamName })
// → Spawn analyst, architect, developer, qa (see SKILL.md Coordinator Spawn Template) // ⚠️ Workers are NOT pre-spawned here.
// Workers are spawned per-stage in Phase 4 via Stop-Wait Task(run_in_background: false).
// See SKILL.md Coordinator Spawn Template for worker prompt templates.
``` ```
### Phase 3: Create Task Chain ### Phase 3: Create Task Chain
@@ -227,6 +229,13 @@ if (pipeline === 'system') {
### Phase 4: Coordination Loop ### Phase 4: Coordination Loop
> **设计原则Stop-Wait**: 模型执行没有时间概念,禁止任何形式的轮询等待。
> - ❌ 禁止: `while` 循环 + `sleep` + 检查状态
> - ✅ 采用: 同步 `Task(run_in_background: false)` 调用Worker 返回 = 阶段完成信号
>
> 按 Phase 3 创建的任务链顺序,逐阶段 spawn worker 同步执行。
> Worker prompt 使用 SKILL.md Coordinator Spawn Template。
Receive teammate messages, dispatch based on content. Receive teammate messages, dispatch based on content.
**Before each decision**: `team_msg list` to check recent messages. **Before each decision**: `team_msg list` to check recent messages.
**After each decision**: `team_msg log` to record. **After each decision**: `team_msg log` to record.

View File

@@ -136,38 +136,18 @@ function detectMode(issueIds, userMode) {
} }
``` ```
### Phase 2: Create Team + Spawn Workers ### Phase 2: Create Team + Initialize Session
```javascript ```javascript
TeamCreate({ team_name: "issue" }) TeamCreate({ team_name: "issue" })
// Spawn workers based on mode // ⚠️ Workers are NOT pre-spawned here.
const workersToSpawn = mode === 'quick' // Workers are spawned per-stage in Phase 4 via Stop-Wait Task(run_in_background: false).
? ['explorer', 'planner', 'integrator', 'implementer'] // No reviewer in quick mode // See SKILL.md Coordinator Spawn Template for worker prompt templates.
: ['explorer', 'planner', 'reviewer', 'integrator', 'implementer'] //
// Worker roles available (spawned on-demand per pipeline stage):
for (const workerName of workersToSpawn) { // quick mode: explorer, planner, integrator, implementer
Task({ // full mode: explorer, planner, reviewer, integrator, implementer
subagent_type: "general-purpose",
team_name: "issue",
name: workerName,
prompt: `你是 team "issue" 的 ${workerName.toUpperCase()}
当你收到任务时,调用 Skill(skill="team-issue", args="--role=${workerName}") 执行。
当前需求: 处理 issue ${issueIds.join(', ')},模式: ${mode}
约束: CLI-first data access, 所有 issue 操作通过 ccw issue 命令
## 角色准则(强制)
- 所有输出必须带 [${workerName}] 标识前缀
- 仅与 coordinator 通信
- 每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录
工作流程:
1. TaskList → 找到分配给你的任务
2. Skill(skill="team-issue", args="--role=${workerName}") 执行
3. team_msg log + SendMessage 结果给 coordinator
4. TaskUpdate completed → 检查下一个任务`
})
}
``` ```
### Phase 3: Create Task Chain ### Phase 3: Create Task Chain
@@ -323,6 +303,13 @@ const marshalId = TaskCreate({
### Phase 4: Coordination Loop ### Phase 4: Coordination Loop
> **设计原则Stop-Wait**: 模型执行没有时间概念,禁止任何形式的轮询等待。
> - ❌ 禁止: `while` 循环 + `sleep` + 检查状态
> - ✅ 采用: 同步 `Task(run_in_background: false)` 调用Worker 返回 = 阶段完成信号
>
> 按 Phase 3 创建的任务链顺序,逐阶段 spawn worker 同步执行。
> Worker prompt 使用 SKILL.md Coordinator Spawn Template。
Receive teammate messages, dispatch based on type. Receive teammate messages, dispatch based on type.
| Received Message | Action | | Received Message | Action |

View File

@@ -112,7 +112,9 @@ const teamSession = {
Write(`${sessionFolder}/team-session.json`, JSON.stringify(teamSession, null, 2)) Write(`${sessionFolder}/team-session.json`, JSON.stringify(teamSession, null, 2))
``` ```
Spawn workers (see SKILL.md Coordinator Spawn Template). // ⚠️ Workers are NOT pre-spawned here.
// Workers are spawned per-stage in Phase 4 via Stop-Wait Task(run_in_background: false).
// See SKILL.md Coordinator Spawn Template for worker prompt templates.
### Phase 3: Create Task Chain + Update Ledger ### Phase 3: Create Task Chain + Update Ledger
@@ -161,6 +163,13 @@ TaskUpdate({ taskId: reviewId, owner: "reviewer", addBlockedBy: [devId] })
### Phase 4: Coordination Loop + GC Control + Ledger Updates ### Phase 4: Coordination Loop + GC Control + Ledger Updates
> **设计原则Stop-Wait**: 模型执行没有时间概念,禁止任何形式的轮询等待。
> - ❌ 禁止: `while` 循环 + `sleep` + 检查状态
> - ✅ 采用: 同步 `Task(run_in_background: false)` 调用Worker 返回 = 阶段完成信号
>
> 按 Phase 3 创建的任务链顺序,逐阶段 spawn worker 同步执行。
> Worker prompt 使用 SKILL.md Coordinator Spawn Template。
| Received Message | Action | | Received Message | Action |
|-----------------|--------| |-----------------|--------|
| architect: design_ready | Read design → update ledger → unblock DEV | | architect: design_ready | Read design → update ledger → unblock DEV |

View File

@@ -10,62 +10,66 @@
## Coordination Loop ## Coordination Loop
> **设计原则**: 模型执行没有时间概念,禁止任何形式的轮询等待。
> 使用同步 `Task(run_in_background: false)` 调用作为等待机制。
> Worker 返回 = 阶段完成信号(天然回调),无需 sleep 轮询。
```javascript ```javascript
Output("[coordinator] Entering coordination loop...") Output("[coordinator] Entering coordination loop (Stop-Wait mode)...")
let loopActive = true // Sequentially execute each task by spawning its worker
let checkpointPending = false const allTasks = TaskList()
const pendingTasks = allTasks.filter(t => t.status !== 'completed' && t.assigned_to !== 'coordinator')
while (loopActive) { for (const task of pendingTasks) {
// Load current session state // Check if all dependencies are met
const session = Read(sessionFile) const allDepsMet = (task.dependencies || []).every(depId => {
const teamState = TeamGet(session.team_id) const dep = TaskGet(depId)
const allTasks = teamState.tasks return dep.status === "completed"
})
// Check for incoming messages if (!allDepsMet) {
const messages = TeamGetMessages(session.team_id) Output(`[coordinator] Task ${task.task_id} blocked by dependencies, skipping`)
continue
for (const message of messages) {
Output(`[coordinator] Received message: ${message.type} from ${message.sender}`)
switch (message.type) {
case "task_complete":
handleTaskComplete(message)
break
case "task_blocked":
handleTaskBlocked(message)
break
case "discussion_needed":
handleDiscussionNeeded(message)
break
case "research_complete":
handleResearchComplete(message)
break
default:
Output(`[coordinator] Unknown message type: ${message.type}`)
}
} }
// Check if all tasks complete Output(`[coordinator] Starting task: ${task.task_id} (assigned to: ${task.assigned_to})`)
const completedTasks = allTasks.filter(t => t.status === "completed")
const totalTasks = allTasks.length
if (completedTasks.length === totalTasks) { // Mark as active
Output("[coordinator] All tasks completed!") TaskUpdate(task.task_id, {
loopActive = false status: "active",
break started_at: new Date().toISOString()
})
// Spawn worker — blocks until worker returns (Stop-Wait)
Task({
subagent_type: "general-purpose",
prompt: `Execute task ${task.task_id}: ${task.description}
Assigned role: ${task.assigned_to}
When complete, mark TaskUpdate(${task.task_id}, { status: "completed" })`,
run_in_background: false
})
// Worker returned — check status
const completedTask = TaskGet(task.task_id)
Output(`[coordinator] Task ${task.task_id} status: ${completedTask.status}`)
if (completedTask.status === "completed") {
handleTaskComplete({ task_id: task.task_id, output: completedTask.output })
} }
// Update session progress // Update session progress
session.tasks_completed = completedTasks.length const session = Read(sessionFile)
const allTasksNow = TaskList()
session.tasks_completed = allTasksNow.filter(t => t.status === "completed").length
Write(sessionFile, session) Write(sessionFile, session)
// Sleep before next iteration // Check if all tasks complete
sleep(5000) // 5 seconds const remaining = allTasksNow.filter(t => t.status !== "completed" && t.assigned_to !== 'coordinator')
if (remaining.length === 0) {
Output("[coordinator] All tasks completed!")
break
}
} }
Output("[coordinator] Coordination loop complete") Output("[coordinator] Coordination loop complete")

View File

@@ -377,9 +377,9 @@ goto Phase2
--- ---
### Phase 2: Create Team + Spawn Workers ### Phase 2: Create Team + Initialize Session
**Purpose**: Initialize team and spawn worker subagents **Purpose**: Initialize team and session state
```javascript ```javascript
Output("[coordinator] Phase 2: Team Creation") Output("[coordinator] Phase 2: Team Creation")
@@ -430,43 +430,17 @@ const sessionData = {
Write(sessionFile, sessionData) Write(sessionFile, sessionData)
Output(`[coordinator] Session file created: ${sessionFile}`) Output(`[coordinator] Session file created: ${sessionFile}`)
// Spawn workers conditionally based on pipeline mode // ⚠️ Workers are NOT pre-spawned here.
const isFE = ['fe-only', 'fullstack', 'full-lifecycle-fe'].includes(requirements.mode) // Workers are spawned per-stage in Phase 4 via Stop-Wait Task(run_in_background: false).
const isBE = ['impl-only', 'fullstack', 'full-lifecycle', 'full-lifecycle-fe'].includes(requirements.mode) // See SKILL.md Coordinator Spawn Template for worker prompt templates.
const isSpec = ['spec-only', 'full-lifecycle', 'full-lifecycle-fe'].includes(requirements.mode) //
// Worker roles by mode (spawned on-demand):
if (isSpec) { // spec-only: spec-writer
TeamSpawn({ team_id: teamId, role: "spec-writer", count: 1 }) // impl-only: implementer
Output("[coordinator] Spawned spec-writer") // fe-only: fe-developer, fe-qa
} // fullstack: implementer, fe-developer, fe-qa
// full-lifecycle / full-lifecycle-fe: spec-writer + relevant impl roles
if (isBE) { // Always available: researcher (for ambiguity resolution)
TeamSpawn({ team_id: teamId, role: "implementer", count: 1 })
Output("[coordinator] Spawned implementer")
}
if (isFE) {
TeamSpawn({ team_id: teamId, role: "fe-developer", count: 1 })
Output("[coordinator] Spawned fe-developer")
TeamSpawn({ team_id: teamId, role: "fe-qa", count: 1 })
Output("[coordinator] Spawned fe-qa")
// Initialize shared memory for frontend pipeline
const sharedMemoryPath = `${sessionFolder}/shared-memory.json`
Write(sharedMemoryPath, JSON.stringify({
design_intelligence: {},
design_token_registry: {},
component_inventory: [],
style_decisions: [],
qa_history: [],
industry_context: {}
}, null, 2))
Output("[coordinator] Initialized shared-memory.json for frontend pipeline")
}
// Always spawn researcher for ambiguity resolution
TeamSpawn({ team_id: teamId, role: "researcher", count: 1 })
Output("[coordinator] Spawned researcher")
goto Phase3 goto Phase3
``` ```
@@ -495,6 +469,13 @@ goto Phase4
**Purpose**: Monitor task progress and route messages **Purpose**: Monitor task progress and route messages
> **设计原则Stop-Wait**: 模型执行没有时间概念,禁止任何形式的轮询等待。
> - ❌ 禁止: `while` 循环 + `sleep` + 检查状态
> - ✅ 采用: 同步 `Task(run_in_background: false)` 调用Worker 返回 = 阶段完成信号
>
> 按 Phase 3 创建的任务链顺序,逐阶段 spawn worker 同步执行。
> Worker prompt 使用 SKILL.md Coordinator Spawn Template。
```javascript ```javascript
Output("[coordinator] Phase 4: Coordination Loop") Output("[coordinator] Phase 4: Coordination Loop")

View File

@@ -188,15 +188,11 @@ if (isResume) {
if (meta) neededRoles.add(meta.owner) if (meta) neededRoles.add(meta.owner)
}) })
// Spawn only needed workers using Phase 2 spawn template (see SKILL.md Coordinator Spawn Template) // Spawn only needed workers using Phase 4 Stop-Wait pattern (see SKILL.md Coordinator Spawn Template)
// Each worker is spawned with prompt that: // Workers are spawned per-stage via Task(run_in_background: false) in Phase 4 coordination loop.
// 1. Identifies their role // neededRoles is used to determine which workers will be spawned on-demand.
// 2. Instructs to call Skill(skill="team-lifecycle", args="--role=<name>")
// 3. Includes session context: taskDescription, sessionFolder, constraints
// 4. Instructs immediate TaskList polling on startup
neededRoles.forEach(role => { neededRoles.forEach(role => {
// → Use SKILL.md Coordinator Spawn Template for each role // → Worker prompt template in SKILL.md (spawned per-stage in Phase 4, not pre-spawned here)
// → Worker prompt includes: "Session: ${sessionFolder}", "需求: ${taskDescription}"
}) })
// ============================================================ // ============================================================
@@ -419,7 +415,7 @@ if (mode === 'impl-only' || mode === 'full-lifecycle') {
} }
``` ```
### Phase 2: Create Team + Spawn Workers ### Phase 2: Create Team + Initialize Session
```javascript ```javascript
TeamCreate({ team_name: teamName }) TeamCreate({ team_name: teamName })
@@ -462,9 +458,11 @@ const teamSession = {
Write(`${sessionFolder}/team-session.json`, JSON.stringify(teamSession, null, 2)) Write(`${sessionFolder}/team-session.json`, JSON.stringify(teamSession, null, 2))
``` ```
**Conditional spawn based on mode** (see SKILL.md Coordinator Spawn Template for full prompts): **Workers are NOT pre-spawned here.** Workers are spawned per-stage in Phase 4 via Stop-Wait `Task(run_in_background: false)`. See SKILL.md Coordinator Spawn Template for worker prompt templates.
| Mode | Spawned Workers | Worker roles by mode (spawned on-demand):
| Mode | Worker Roles |
|------|-----------------| |------|-----------------|
| spec-only | analyst, writer, discussant, reviewer (4) | | spec-only | analyst, writer, discussant, reviewer (4) |
| impl-only | planner, executor, tester, reviewer (4) | | impl-only | planner, executor, tester, reviewer (4) |
@@ -562,6 +560,13 @@ TaskUpdate({ taskId: planId, owner: "planner", addBlockedBy: [discuss6Id] })
### Phase 4: Coordination Loop ### Phase 4: Coordination Loop
> **设计原则Stop-Wait**: 模型执行没有时间概念,禁止任何形式的轮询等待。
> - ❌ 禁止: `while` 循环 + `sleep` + 检查状态
> - ✅ 采用: 同步 `Task(run_in_background: false)` 调用Worker 返回 = 阶段完成信号
>
> 按 Phase 3 创建的任务链顺序,逐阶段 spawn worker 同步执行。
> Worker prompt 使用 SKILL.md Coordinator Spawn Template。
Receive teammate messages and make dispatch decisions. **Before each decision: `team_msg list` to review recent messages. After each decision: `team_msg log` to record.** Receive teammate messages and make dispatch decisions. **Before each decision: `team_msg list` to review recent messages. After each decision: `team_msg log` to record.**
#### Spec Messages #### Spec Messages

View File

@@ -20,8 +20,15 @@
### 设计原则 ### 设计原则
> **模型执行没有时间概念**。禁止空转 while 循环检查状态。 > **模型执行没有时间概念,禁止任何形式的轮询等待。**
> 使用固定 sleep 间隔 + 最大轮询次数,避免无意义的 API 调用浪费。 >
> - ❌ 禁止: `while` 循环 + `sleep` + 检查状态(空转浪费 API 轮次)
> - ❌ 禁止: `Bash(sleep N)` / `Bash(timeout /t N)` 作为等待手段
> - ✅ 采用: 同步 `Task()` 调用(`run_in_background: false`call 本身即等待
> - ✅ 采用: Worker 返回 = 阶段完成信号(天然回调)
>
> **原理**: `Task(run_in_background: false)` 是阻塞调用coordinator 自动挂起直到 worker 返回。
> 无需 sleep无需轮询无需消息总线监控。Worker 的返回就是回调。
### Decision Logic ### Decision Logic
@@ -47,14 +54,16 @@ const routingTable = {
} }
``` ```
### 等待策略常量 ### Stage-Worker 映射表
```javascript ```javascript
const POLL_INTERVAL_SEC = 300 // 每次检查间隔 5 分钟(测试执行可能很慢) const STAGE_WORKER_MAP = {
const MAX_POLLS_PER_STAGE = 6 // 单阶段最多等待 6 次(~30 分钟) 'SCOUT': { role: 'scout', skillArgs: '--role=scout' },
const SLEEP_CMD = process.platform === 'win32' 'QASTRAT': { role: 'strategist', skillArgs: '--role=strategist' },
? `timeout /t ${POLL_INTERVAL_SEC} /nobreak >nul 2>&1` 'QAGEN': { role: 'generator', skillArgs: '--role=generator' },
: `sleep ${POLL_INTERVAL_SEC}` 'QARUN': { role: 'executor', skillArgs: '--role=executor' },
'QAANA': { role: 'analyst', skillArgs: '--role=analyst' }
}
// ★ 统一 auto mode 检测:-y/--yes 从 $ARGUMENTS 或 ccw 传播 // ★ 统一 auto mode 检测:-y/--yes 从 $ARGUMENTS 或 ccw 传播
const autoYes = /\b(-y|--yes)\b/.test(args) const autoYes = /\b(-y|--yes)\b/.test(args)
@@ -83,94 +92,125 @@ const pipelineTasks = allTasks
.sort((a, b) => Number(a.id) - Number(b.id)) .sort((a, b) => Number(a.id) - Number(b.id))
``` ```
### Step 2: Stage-Driven Execution ### Step 2: Sequential Stage Execution (Stop-Wait)
> **核心改动**: 不再使用 while 轮询循环。按 pipeline 阶段顺序,逐阶段等待完成 > **核心**: 逐阶段 spawn worker同步阻塞等待返回
> 每个阶段sleep → 检查消息 → 确认任务状态 → 处理结果 → 下一阶段 > Worker 返回 = 阶段完成。无 sleep、无轮询、无消息总线监控
```javascript ```javascript
// 按依赖顺序处理每个阶段 // 按依赖顺序处理每个阶段
for (const stageTask of pipelineTasks) { for (const stageTask of pipelineTasks) {
// --- 等待当前阶段完成 --- // 1. 提取阶段前缀 → 确定 worker 角色
let stageComplete = false const stagePrefix = stageTask.subject.match(/^([\w-]+)-\d/)?.[1]?.replace(/-L\d$/, '')
let pollCount = 0 const workerConfig = STAGE_WORKER_MAP[stagePrefix]
while (!stageComplete && pollCount < MAX_POLLS_PER_STAGE) { if (!workerConfig) {
// ★ 固定等待sleep 30s让 worker 有执行时间
Bash(SLEEP_CMD)
pollCount++
// 1. 检查消息总线(主要信号源)
const messages = mcp__ccw-tools__team_msg({
operation: "list",
team: teamName,
last: 5
})
// 2. 路由消息
for (const msg of messages) {
const handler = routingTable[msg.type]
if (!handler) continue
processMessage(msg, handler)
}
// 3. 确认任务状态(兜底)
const currentTask = TaskGet({ taskId: stageTask.id })
stageComplete = currentTask.status === 'completed' || currentTask.status === 'deleted'
}
// --- 阶段超时处理 ---
if (!stageComplete) {
const elapsedMin = Math.round(pollCount * POLL_INTERVAL_SEC / 60)
if (autoYes) {
// 自动模式:记录日志,自动跳过
mcp__ccw-tools__team_msg({ mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator", operation: "log", team: teamName, from: "coordinator",
to: "user", type: "error", to: "user", type: "error",
summary: `[coordinator] [auto] 阶段 ${stageTask.subject} 超时 (${elapsedMin}min),自动跳过` summary: `[coordinator] 未知阶段前缀: ${stagePrefix}跳过`
})
continue
}
// 2. 标记任务为执行中
TaskUpdate({ taskId: stageTask.id, status: 'in_progress' })
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator",
to: workerConfig.role, type: "task_unblocked",
summary: `[coordinator] 启动阶段: ${stageTask.subject}${workerConfig.role}`
})
// 3. 同步 spawn worker — 阻塞直到 worker 返回Stop-Wait 核心)
const workerResult = Task({
subagent_type: "general-purpose",
prompt: `你是 team "${teamName}" 的 ${workerConfig.role.toUpperCase()}
## ⚠️ 首要指令MUST
Skill(skill="team-quality-assurance", args="${workerConfig.skillArgs}")
## 当前任务
- 任务 ID: ${stageTask.id}
- 任务: ${stageTask.subject}
- 描述: ${stageTask.description || taskDescription}
- Session: ${sessionFolder}
## 角色准则(强制)
- 所有输出必须带 [${workerConfig.role}] 标识前缀
- 仅与 coordinator 通信
## 工作流程
1. Skill(skill="team-quality-assurance", args="${workerConfig.skillArgs}") 获取角色定义
2. 执行任务 → 汇报结果
3. TaskUpdate({ taskId: "${stageTask.id}", status: "completed" })`,
run_in_background: false
})
// 4. Worker 已返回 — 直接处理结果
const taskState = TaskGet({ taskId: stageTask.id })
if (taskState.status !== 'completed') {
// Worker 返回但未标记 completed → 异常处理
if (autoYes) {
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator",
to: "user", type: "error",
summary: `[coordinator] [auto] 阶段 ${stageTask.subject} 未完成,自动跳过`
}) })
TaskUpdate({ taskId: stageTask.id, status: 'deleted' }) TaskUpdate({ taskId: stageTask.id, status: 'deleted' })
continue continue
} }
// 交互模式:由用户决定
const decision = AskUserQuestion({ const decision = AskUserQuestion({
questions: [{ questions: [{
question: `阶段 "${stageTask.subject}" 已等待 ${elapsedMin} 分钟仍未完成。如何处理?`, question: `阶段 "${stageTask.subject}" worker 返回但未完成。如何处理?`,
header: "Stage Wait", header: "Stage Fail",
multiSelect: false, multiSelect: false,
options: [ options: [
{ label: "继续等待", description: `再等 ${MAX_POLLS_PER_STAGE} 轮(~${Math.round(MAX_POLLS_PER_STAGE * POLL_INTERVAL_SEC / 60)}min` }, { label: "重试", description: "重新 spawn worker 执行此阶段" },
{ label: "跳过此阶段", description: "标记为跳过,继续后续流水线" }, { label: "跳过", description: "标记为跳过,继续后续流水线" },
{ label: "终止流水线", description: "停止整个 QA 流程,汇报当前结果" } { label: "终止", description: "停止整个 QA 流程,汇报当前结果" }
] ]
}] }]
}) })
const answer = decision["Stage Wait"] const answer = decision["Stage Fail"]
if (answer === "跳过") {
if (answer === "继续等待") {
// 重置计数器,继续等待当前阶段
pollCount = 0
// 重新进入当前阶段的等待循环(需要用 while 包裹,此处用 goto 语义)
continue // 注意:实际执行中需要将 for 改为可重入的逻辑
} else if (answer === "跳过此阶段") {
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator",
to: "user", type: "error",
summary: `[coordinator] 用户选择跳过阶段 ${stageTask.subject}`
})
TaskUpdate({ taskId: stageTask.id, status: 'deleted' }) TaskUpdate({ taskId: stageTask.id, status: 'deleted' })
continue continue
} else { } else if (answer === "终止") {
// 终止流水线
mcp__ccw-tools__team_msg({ mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator", operation: "log", team: teamName, from: "coordinator",
to: "user", type: "shutdown", to: "user", type: "shutdown",
summary: `[coordinator] 用户终止流水线,当前阶段: ${stageTask.subject}` summary: `[coordinator] 用户终止流水线,当前阶段: ${stageTask.subject}`
}) })
break // 跳出 for 循环,进入 Step 3 汇报 break
}
// 重试: continue to next iteration will re-process if logic wraps
} else {
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator",
to: "user", type: "quality_gate",
summary: `[coordinator] 阶段完成: ${stageTask.subject}`
})
}
// 5. 阶段间检查QARUN 阶段检查覆盖率,决定 GC 循环)
if (stagePrefix === 'QARUN') {
const latestMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`))
const coverage = latestMemory.execution_results?.coverage || 0
const targetLayer = stageTask.metadata?.layer || 'L1'
const target = coverageTargets[targetLayer] || 80
if (coverage < target && gcIteration < MAX_GC_ITERATIONS) {
gcIteration++
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator",
to: "generator", type: "gc_loop_trigger",
summary: `[coordinator] GC循环 #${gcIteration}: 覆盖率 ${coverage}% < ${target}%,请修复`
})
// 创建 GC 修复任务追加到 pipeline
} }
} }
} }
@@ -284,10 +324,8 @@ const summary = {
| Scenario | Resolution | | Scenario | Resolution |
|----------|------------| |----------|------------|
| Message bus unavailable | Fall back to TaskList polling only | | Worker 返回但未 completed (交互模式) | AskUserQuestion: 重试 / 跳过 / 终止 |
| Stage timeout (交互模式) | AskUserQuestion继续等待 / 跳过 / 终止流水线 | | Worker 返回但未 completed (自动模式) | 自动跳过,记录日志 |
| Stage timeout (自动模式 `-y`/`--yes``autoYes`) | 自动跳过,记录日志,继续流水线 | | Worker spawn 失败 | 重试一次,仍失败则上报用户 |
| Teammate unresponsive (2x no response) | Respawn teammate with same task |
| Deadlock detected (tasks blocked indefinitely) | Identify cycle, manually unblock |
| Quality gate FAIL | Report to user, suggest targeted re-run | | Quality gate FAIL | Report to user, suggest targeted re-run |
| GC loop stuck >3 iterations | Accept current coverage, continue pipeline | | GC loop stuck >3 iterations | Accept current coverage, continue pipeline |

View File

@@ -99,7 +99,7 @@ if (!autoYes && (!taskDescription || taskDescription.length < 10)) {
} }
``` ```
### Phase 2: Create Team + Spawn Teammates ### Phase 2: Create Team + Initialize Session
```javascript ```javascript
const teamName = "quality-assurance" const teamName = "quality-assurance"
@@ -121,8 +121,10 @@ Write(`${sessionFolder}/shared-memory.json`, JSON.stringify({
TeamCreate({ team_name: teamName }) TeamCreate({ team_name: teamName })
// Spawn teammates (see SKILL.md Coordinator Spawn Template) // ⚠️ Workers are NOT pre-spawned here.
// Scout, Strategist, Generator, Executor, Analyst // Workers are spawned per-stage in Phase 4 via Stop-Wait Task(run_in_background: false).
// See SKILL.md Coordinator Spawn Template for worker prompt templates.
// Worker roles: Scout, Strategist, Generator, Executor, Analyst
``` ```
### Phase 3: Create Task Chain ### Phase 3: Create Task Chain
@@ -151,6 +153,13 @@ SCOUT-001 → QASTRAT-001 → [QAGEN-001(L1) + QAGEN-002(L2)](parallel) → [QAR
### Phase 4: Coordination Loop ### Phase 4: Coordination Loop
> **设计原则Stop-Wait**: 模型执行没有时间概念,禁止任何形式的轮询等待。
> - ❌ 禁止: `while` 循环 + `sleep` + 检查状态
> - ✅ 采用: 同步 `Task(run_in_background: false)` 调用Worker 返回 = 阶段完成信号
>
> 按 Phase 3 创建的任务链顺序,逐阶段 spawn worker 同步执行。
> Worker prompt 使用 SKILL.md Coordinator Spawn Template。
```javascript ```javascript
// Read commands/monitor.md for full implementation // Read commands/monitor.md for full implementation
Read("commands/monitor.md") Read("commands/monitor.md")

View File

@@ -243,14 +243,21 @@ TDFIX → TDVAL → (if regression or quality drop) → TDFIX-fix → TDVAL-2
## Coordinator Spawn Template ## Coordinator Spawn Template
> **注意**: 以下模板作为 worker prompt 参考。在 Stop-Wait 策略下coordinator 不再在 Phase 2 预先 spawn 所有 worker。
> 而是在 Phase 4 (monitor) 中,按 pipeline 阶段逐个 spawn worker同步阻塞 `Task(run_in_background: false)`
> worker 返回即阶段完成。详见 `roles/coordinator/commands/monitor.md`。
```javascript ```javascript
TeamCreate({ team_name: teamName }) TeamCreate({ team_name: teamName })
// Scanner // Worker 按需 spawnmonitor.md Phase 4 调用)
// 以下为各角色的 prompt 模板参考:
```
### Scanner Prompt Template
```javascript
Task({ Task({
subagent_type: "general-purpose", subagent_type: "general-purpose",
team_name: teamName,
name: "scanner",
prompt: `你是 team "${teamName}" 的 SCANNER。 prompt: `你是 team "${teamName}" 的 SCANNER。
## ⚠️ 首要指令MUST ## ⚠️ 首要指令MUST
@@ -274,14 +281,15 @@ Skill(skill="team-tech-debt", args="--role=scanner")
1. 调用 Skill(skill="team-tech-debt", args="--role=scanner") 获取角色定义和执行逻辑 1. 调用 Skill(skill="team-tech-debt", args="--role=scanner") 获取角色定义和执行逻辑
2. 按 role.md 中的 5-Phase 流程执行TaskList → 找到 TDSCAN-* 任务 → 执行 → 汇报) 2. 按 role.md 中的 5-Phase 流程执行TaskList → 找到 TDSCAN-* 任务 → 执行 → 汇报)
3. team_msg log + SendMessage 结果给 coordinator带 [scanner] 标识) 3. team_msg log + SendMessage 结果给 coordinator带 [scanner] 标识)
4. TaskUpdate completed → 检查下一个任务 → 回到步骤 1` 4. TaskUpdate completed → 检查下一个任务 → 回到步骤 1`,
run_in_background: false // 同步阻塞
}) })
```
// Assessor ### Assessor Prompt Template
```javascript
Task({ Task({
subagent_type: "general-purpose", subagent_type: "general-purpose",
team_name: teamName,
name: "assessor",
prompt: `你是 team "${teamName}" 的 ASSESSOR。 prompt: `你是 team "${teamName}" 的 ASSESSOR。
## ⚠️ 首要指令MUST ## ⚠️ 首要指令MUST
@@ -302,14 +310,15 @@ Skill(skill="team-tech-debt", args="--role=assessor")
1. Skill(skill="team-tech-debt", args="--role=assessor") 获取角色定义 1. Skill(skill="team-tech-debt", args="--role=assessor") 获取角色定义
2. TaskList → 找到 TDEVAL-* 任务 → 执行 → 汇报 2. TaskList → 找到 TDEVAL-* 任务 → 执行 → 汇报
3. team_msg log + SendMessage 结果给 coordinator 3. team_msg log + SendMessage 结果给 coordinator
4. TaskUpdate completed → 检查下一个任务` 4. TaskUpdate completed`,
run_in_background: false
}) })
```
// Planner ### Planner Prompt Template
```javascript
Task({ Task({
subagent_type: "general-purpose", subagent_type: "general-purpose",
team_name: teamName,
name: "planner",
prompt: `你是 team "${teamName}" 的 PLANNER。 prompt: `你是 team "${teamName}" 的 PLANNER。
## ⚠️ 首要指令MUST ## ⚠️ 首要指令MUST
@@ -330,14 +339,15 @@ Skill(skill="team-tech-debt", args="--role=planner")
1. Skill(skill="team-tech-debt", args="--role=planner") 获取角色定义 1. Skill(skill="team-tech-debt", args="--role=planner") 获取角色定义
2. TaskList → 找到 TDPLAN-* 任务 → 执行 → 汇报 2. TaskList → 找到 TDPLAN-* 任务 → 执行 → 汇报
3. team_msg log + SendMessage 结果给 coordinator 3. team_msg log + SendMessage 结果给 coordinator
4. TaskUpdate completed → 检查下一个任务` 4. TaskUpdate completed`,
run_in_background: false
}) })
```
// Executor ### Executor Prompt Template
```javascript
Task({ Task({
subagent_type: "general-purpose", subagent_type: "general-purpose",
team_name: teamName,
name: "executor",
prompt: `你是 team "${teamName}" 的 EXECUTOR。 prompt: `你是 team "${teamName}" 的 EXECUTOR。
## ⚠️ 首要指令MUST ## ⚠️ 首要指令MUST
@@ -358,14 +368,15 @@ Skill(skill="team-tech-debt", args="--role=executor")
1. Skill(skill="team-tech-debt", args="--role=executor") 获取角色定义 1. Skill(skill="team-tech-debt", args="--role=executor") 获取角色定义
2. TaskList → 找到 TDFIX-* 任务 → 执行 → 汇报 2. TaskList → 找到 TDFIX-* 任务 → 执行 → 汇报
3. team_msg log + SendMessage 结果给 coordinator 3. team_msg log + SendMessage 结果给 coordinator
4. TaskUpdate completed → 检查下一个任务` 4. TaskUpdate completed`,
run_in_background: false
}) })
```
// Validator ### Validator Prompt Template
```javascript
Task({ Task({
subagent_type: "general-purpose", subagent_type: "general-purpose",
team_name: teamName,
name: "validator",
prompt: `你是 team "${teamName}" 的 VALIDATOR。 prompt: `你是 team "${teamName}" 的 VALIDATOR。
## ⚠️ 首要指令MUST ## ⚠️ 首要指令MUST
@@ -386,7 +397,8 @@ Skill(skill="team-tech-debt", args="--role=validator")
1. Skill(skill="team-tech-debt", args="--role=validator") 获取角色定义 1. Skill(skill="team-tech-debt", args="--role=validator") 获取角色定义
2. TaskList → 找到 TDVAL-* 任务 → 执行 → 汇报 2. TaskList → 找到 TDVAL-* 任务 → 执行 → 汇报
3. team_msg log + SendMessage 结果给 coordinator 3. team_msg log + SendMessage 结果给 coordinator
4. TaskUpdate completed → 检查下一个任务` 4. TaskUpdate completed`,
run_in_background: false
}) })
``` ```

View File

@@ -1,12 +1,12 @@
# Command: monitor # Command: monitor
> 阶段驱动的协调循环。按 pipeline 阶段顺序等待 worker 完成,路由消息,处理 Fix-Verify 循环,检测完成 > 停止等待Stop-Wait协调。按 pipeline 阶段顺序,逐阶段 spawn worker 同步执行worker 返回即阶段完成,无需轮询
## When to Use ## When to Use
- Phase 4 of Coordinator - Phase 4 of Coordinator
- 任务链已创建并分发 - 任务链已创建dispatch 完成)
- 需要持续监控直到所有任务完成 - 需要逐阶段驱动 worker 执行直到所有任务完成
**Trigger conditions**: **Trigger conditions**:
- dispatch 完成后立即启动 - dispatch 完成后立即启动
@@ -16,199 +16,225 @@
### Delegation Mode ### Delegation Mode
**Mode**: Stage-driven按阶段顺序等待,非轮询) **Mode**: Stop-Wait同步阻塞 Task call,非轮询)
### 设计原则 ### 设计原则
> **模型执行没有时间概念**。禁止空转 while 循环检查状态。 > **模型执行没有时间概念,禁止任何形式的轮询等待。**
> 使用固定 sleep 间隔 + 最大轮询次数,避免无意义的 API 调用浪费。 >
> - ❌ 禁止: `while` 循环 + `sleep` + 检查状态(空转浪费 API 轮次)
> - ❌ 禁止: `Bash(sleep N)` / `Bash(timeout /t N)` 作为等待手段
> - ✅ 采用: 同步 `Task()` 调用(`run_in_background: false`call 本身即等待
> - ✅ 采用: Worker 返回 = 阶段完成信号(天然回调)
>
> **原理**: `Task(run_in_background: false)` 是阻塞调用coordinator 自动挂起直到 worker 返回。
> 无需 sleep无需轮询无需消息总线监控。Worker 的返回就是回调。
### Decision Logic ### Stage-Worker 映射表
```javascript ```javascript
// 消息路由表 const STAGE_WORKER_MAP = {
const routingTable = { 'TDSCAN': { role: 'scanner', skillArgs: '--role=scanner' },
// Scanner 完成 'TDEVAL': { role: 'assessor', skillArgs: '--role=assessor' },
'scan_complete': { action: 'Mark TDSCAN complete, unblock TDEVAL' }, 'TDPLAN': { role: 'planner', skillArgs: '--role=planner' },
'debt_items_found': { action: 'Mark TDSCAN complete with items, unblock TDEVAL' }, 'TDFIX': { role: 'executor', skillArgs: '--role=executor' },
// Assessor 完成 'TDVAL': { role: 'validator', skillArgs: '--role=validator' }
'assessment_complete': { action: 'Mark TDEVAL complete, unblock TDPLAN' },
// Planner 完成
'plan_ready': { action: 'Mark TDPLAN complete, unblock TDFIX' },
'plan_revision': { action: 'Plan revised, re-evaluate dependencies' },
// Executor 完成
'fix_complete': { action: 'Mark TDFIX complete, unblock TDVAL' },
'fix_progress': { action: 'Log progress, continue waiting' },
// Validator 完成
'validation_complete': { action: 'Mark TDVAL complete, evaluate quality gate', special: 'quality_gate' },
'regression_found': { action: 'Evaluate regression, decide Fix-Verify loop', special: 'fix_verify_decision' },
// 错误
'error': { action: 'Assess severity, retry or escalate', special: 'error_handler' }
} }
``` ```
### 等待策略常量
```javascript
const POLL_INTERVAL_SEC = 300 // 每次检查间隔 5 分钟
const MAX_POLLS_PER_STAGE = 6 // 单阶段最多等待 6 次(~30 分钟)
const SLEEP_CMD = process.platform === 'win32'
? `timeout /t ${POLL_INTERVAL_SEC} /nobreak >nul 2>&1`
: `sleep ${POLL_INTERVAL_SEC}`
// 统一 auto mode 检测
const autoYes = /\b(-y|--yes)\b/.test(args)
```
## Execution Steps ## Execution Steps
### Step 1: Context Preparation ### Step 1: Context Preparation
```javascript ```javascript
// 从 shared memory 获取上下文
const sharedMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`)) const sharedMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`))
let fixVerifyIteration = 0 let fixVerifyIteration = 0
const MAX_FIX_VERIFY_ITERATIONS = 3 const MAX_FIX_VERIFY_ITERATIONS = 3
// 获取 pipeline 阶段列表 // 获取 pipeline 阶段列表(按创建顺序 = 依赖顺序)
const allTasks = TaskList() const allTasks = TaskList()
const pipelineTasks = allTasks const pipelineTasks = allTasks
.filter(t => t.owner && t.owner !== 'coordinator') .filter(t => t.owner && t.owner !== 'coordinator')
.sort((a, b) => Number(a.id) - Number(b.id)) .sort((a, b) => Number(a.id) - Number(b.id))
// 统一 auto mode 检测
const autoYes = /\b(-y|--yes)\b/.test(args)
``` ```
### Step 2: Stage-Driven Execution ### Step 2: Sequential Stage Execution (Stop-Wait)
> **核心**: 按 pipeline 阶段顺序,逐阶段等待完成 > **核心**: 逐阶段 spawn worker同步阻塞等待返回
> 每个阶段sleep → 检查消息 → 确认任务状态 → 处理结果 → 下一阶段 > Worker 返回 = 阶段完成。无 sleep、无轮询、无消息总线监控
```javascript ```javascript
for (const stageTask of pipelineTasks) { for (const stageTask of pipelineTasks) {
let stageComplete = false // 1. 提取阶段前缀 → 确定 worker 角色
let pollCount = 0 const stagePrefix = stageTask.subject.match(/^(TD\w+)-/)?.[1]
const workerConfig = STAGE_WORKER_MAP[stagePrefix]
while (!stageComplete && pollCount < MAX_POLLS_PER_STAGE) { if (!workerConfig) {
Bash(SLEEP_CMD) mcp__ccw-tools__team_msg({
pollCount++ operation: "log", team: teamName, from: "coordinator",
to: "user", type: "error",
summary: `[coordinator] 未知阶段前缀: ${stagePrefix},跳过`
})
continue
}
// 1. 检查消息总线 // 2. 标记任务为执行中
const messages = mcp__ccw-tools__team_msg({ TaskUpdate({ taskId: stageTask.id, status: 'in_progress' })
operation: "list",
team: teamName, mcp__ccw-tools__team_msg({
last: 5 operation: "log", team: teamName, from: "coordinator",
to: workerConfig.role, type: "task_unblocked",
summary: `[coordinator] 启动阶段: ${stageTask.subject}${workerConfig.role}`
}) })
// 2. 路由消息 // 3. 同步 spawn worker — 阻塞直到 worker 返回Stop-Wait 核心)
for (const msg of messages) { // Task() 本身就是等待机制,无需 sleep/poll
const handler = routingTable[msg.type] const workerResult = Task({
if (!handler) continue subagent_type: "general-purpose",
processMessage(msg, handler) prompt: buildWorkerPrompt(stageTask, workerConfig, sessionFolder, taskDescription),
run_in_background: false // ← 同步阻塞 = 天然回调
})
// 4. Worker 已返回 — 直接处理结果(无需检查状态)
const taskState = TaskGet({ taskId: stageTask.id })
if (taskState.status !== 'completed') {
// Worker 返回但未标记 completed → 异常处理
handleStageFailure(stageTask, taskState, workerConfig, autoYes)
} else {
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator",
to: "user", type: "quality_gate",
summary: `[coordinator] 阶段完成: ${stageTask.subject}`
})
} }
// 3. 确认任务状态 // 5. 阶段间质量检查(仅 TDVAL 阶段)
const currentTask = TaskGet({ taskId: stageTask.id }) if (stagePrefix === 'TDVAL') {
stageComplete = currentTask.status === 'completed' || currentTask.status === 'deleted' const needsFixVerify = evaluateValidationResult(sessionFolder)
if (needsFixVerify && fixVerifyIteration < MAX_FIX_VERIFY_ITERATIONS) {
fixVerifyIteration++
const fixVerifyTasks = createFixVerifyTasks(fixVerifyIteration, sessionFolder)
// 将 Fix-Verify 任务追加到 pipeline 末尾继续执行
pipelineTasks.push(...fixVerifyTasks)
} }
}
}
```
// 阶段超时处理 ### Step 2.1: Worker Prompt Builder
if (!stageComplete) {
const elapsedMin = Math.round(pollCount * POLL_INTERVAL_SEC / 60)
```javascript
function buildWorkerPrompt(stageTask, workerConfig, sessionFolder, taskDescription) {
return `你是 team "${teamName}" 的 ${workerConfig.role.toUpperCase()}
## ⚠️ 首要指令MUST
你的所有工作必须通过调用 Skill 获取角色定义后执行,禁止自行发挥:
Skill(skill="team-tech-debt", args="${workerConfig.skillArgs}")
此调用会加载你的角色定义role.md、可用命令commands/*.md和完整执行逻辑。
## 当前任务
- 任务 ID: ${stageTask.id}
- 任务: ${stageTask.subject}
- 描述: ${stageTask.description || taskDescription}
- Session: ${sessionFolder}
## 角色准则(强制)
- 你只能处理 ${stageTask.subject.match(/^(TD\w+)-/)?.[1] || 'TD'}-* 前缀的任务
- 所有输出必须带 [${workerConfig.role}] 标识前缀
- 仅与 coordinator 通信,不得直接联系其他 worker
## 消息总线(必须)
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
## 工作流程(严格按顺序)
1. 调用 Skill(skill="team-tech-debt", args="${workerConfig.skillArgs}") 获取角色定义和执行逻辑
2. 按 role.md 中的 5-Phase 流程执行
3. team_msg log + SendMessage 结果给 coordinator
4. TaskUpdate({ taskId: "${stageTask.id}", status: "completed" })`
}
```
### Step 2.2: Stage Failure Handler
```javascript
function handleStageFailure(stageTask, taskState, workerConfig, autoYes) {
if (autoYes) { if (autoYes) {
mcp__ccw-tools__team_msg({ mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator", operation: "log", team: teamName, from: "coordinator",
to: "user", type: "error", to: "user", type: "error",
summary: `[coordinator] [auto] 阶段 ${stageTask.subject} 超时 (${elapsedMin}min),自动跳过` summary: `[coordinator] [auto] 阶段 ${stageTask.subject} 未完成 (status=${taskState.status}),自动跳过`
}) })
TaskUpdate({ taskId: stageTask.id, status: 'deleted' }) TaskUpdate({ taskId: stageTask.id, status: 'deleted' })
continue return 'skip'
} }
const decision = AskUserQuestion({ const decision = AskUserQuestion({
questions: [{ questions: [{
question: `阶段 "${stageTask.subject}" 已等待 ${elapsedMin} 分钟仍未完成。如何处理?`, question: `阶段 "${stageTask.subject}" worker 返回但未完成 (status=${taskState.status})。如何处理?`,
header: "Stage Wait", header: "Stage Fail",
multiSelect: false, multiSelect: false,
options: [ options: [
{ label: "继续等待", description: `再等 ${MAX_POLLS_PER_STAGE}` }, { label: "重试", description: "重新 spawn worker 执行此阶段" },
{ label: "跳过此阶段", description: "标记为跳过,继续后续流水线" }, { label: "跳过", description: "标记为跳过,继续后续流水线" },
{ label: "终止流水线", description: "停止整个流程,汇报当前结果" } { label: "终止", description: "停止整个流程,汇报当前结果" }
] ]
}] }]
}) })
const answer = decision["Stage Wait"] const answer = decision["Stage Fail"]
if (answer === "跳过此阶段") { if (answer === "重试") {
// 重新 spawn worker递归单次
TaskUpdate({ taskId: stageTask.id, status: 'in_progress' })
const retryResult = Task({
subagent_type: "general-purpose",
prompt: buildWorkerPrompt(stageTask, workerConfig, sessionFolder, taskDescription),
run_in_background: false
})
const retryState = TaskGet({ taskId: stageTask.id })
if (retryState.status !== 'completed') {
TaskUpdate({ taskId: stageTask.id, status: 'deleted' }) TaskUpdate({ taskId: stageTask.id, status: 'deleted' })
continue }
} else if (answer === "终止流水线") { return 'retried'
} else if (answer === "跳过") {
TaskUpdate({ taskId: stageTask.id, status: 'deleted' })
return 'skip'
} else {
mcp__ccw-tools__team_msg({ mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator", operation: "log", team: teamName, from: "coordinator",
to: "user", type: "shutdown", to: "user", type: "shutdown",
summary: `[coordinator] 用户终止流水线,当前阶段: ${stageTask.subject}` summary: `[coordinator] 用户终止流水线,当前阶段: ${stageTask.subject}`
}) })
break return 'abort'
}
} }
} }
``` ```
### Step 2.1: Message Processing (processMessage) ### Step 2.3: Validation Evaluation
```javascript ```javascript
function processMessage(msg, handler) { function evaluateValidationResult(sessionFolder) {
switch (handler.special) {
case 'quality_gate': {
const latestMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`)) const latestMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`))
const debtBefore = latestMemory.debt_score_before || 0 const debtBefore = latestMemory.debt_score_before || 0
const debtAfter = latestMemory.debt_score_after || 0 const debtAfter = latestMemory.debt_score_after || 0
const regressions = latestMemory.validation_results?.regressions || 0
const improved = debtAfter < debtBefore const improved = debtAfter < debtBefore
let status = 'PASS' let status = 'PASS'
if (!improved && latestMemory.validation_results?.regressions > 0) status = 'FAIL' if (!improved && regressions > 0) status = 'FAIL'
else if (!improved) status = 'CONDITIONAL' else if (!improved) status = 'CONDITIONAL'
mcp__ccw-tools__team_msg({ mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator", operation: "log", team: teamName, from: "coordinator",
to: "user", type: "quality_gate", to: "user", type: "quality_gate",
summary: `[coordinator] 质量门控: ${status} (债务分 ${debtBefore}${debtAfter})` summary: `[coordinator] 质量门控: ${status} (债务分 ${debtBefore}${debtAfter}, 回归 ${regressions})`
}) })
break
}
case 'fix_verify_decision': { return regressions > 0
const regressions = msg.data?.regressions || 0
if (regressions > 0 && fixVerifyIteration < MAX_FIX_VERIFY_ITERATIONS) {
fixVerifyIteration++
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator",
to: "executor", type: "task_unblocked",
summary: `[coordinator] Fix-Verify #${fixVerifyIteration}: 发现 ${regressions} 个回归,请修复`,
data: { iteration: fixVerifyIteration, regressions }
})
// 创建 Fix-Verify 修复任务(参见 dispatch.md createFixVerifyTasks
} else {
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator",
to: "user", type: "quality_gate",
summary: `[coordinator] Fix-Verify 循环已达上限(${MAX_FIX_VERIFY_ITERATIONS}),接受当前结果`
})
}
break
}
case 'error_handler': {
const severity = msg.data?.severity || 'medium'
if (severity === 'critical') {
SendMessage({
content: `## [coordinator] Critical Error from ${msg.from}\n\n${msg.summary}`,
summary: `[coordinator] Critical error: ${msg.summary}`
})
}
break
}
}
} }
``` ```
@@ -237,19 +263,15 @@ const summary = {
### Tasks: [completed]/[total] ### Tasks: [completed]/[total]
### Fix-Verify Iterations: [count] ### Fix-Verify Iterations: [count]
### Debt Score: [before] → [after] ### Debt Score: [before] → [after]
### Message Log (last 10)
- [timestamp] [from] → [to]: [type] - [summary]
``` ```
## Error Handling ## Error Handling
| Scenario | Resolution | | Scenario | Resolution |
|----------|------------| |----------|------------|
| Message bus unavailable | Fall back to TaskList polling only | | Worker 返回但未 completed (交互模式) | AskUserQuestion: 重试 / 跳过 / 终止 |
| Stage timeout (交互模式) | AskUserQuestion: 继续等待 / 跳过 / 终止 | | Worker 返回但未 completed (自动模式) | 自动跳过,记录日志 |
| Stage timeout (自动模式 `-y`/`--yes`) | 自动跳过,记录日志 | | Worker spawn 失败 | 重试一次,仍失败则上报用户 |
| Teammate unresponsive (2x no response) | Respawn teammate with same task |
| Deadlock detected | Identify cycle, manually unblock |
| Quality gate FAIL | Report to user, suggest targeted re-run | | Quality gate FAIL | Report to user, suggest targeted re-run |
| Fix-Verify loop stuck >3 iterations | Accept current state, continue pipeline | | Fix-Verify loop stuck >3 iterations | Accept current state, continue pipeline |
| Shared memory 读取失败 | 降级为 TaskList 状态判断 |

View File

@@ -121,7 +121,7 @@ if (!autoYes && (!taskDescription || taskDescription.length < 10)) {
} }
``` ```
### Phase 2: Create Team + Spawn Teammates ### Phase 2: Create Team + Initialize Session
```javascript ```javascript
const teamName = "tech-debt" const teamName = "tech-debt"
@@ -143,8 +143,9 @@ Write(`${sessionFolder}/shared-memory.json`, JSON.stringify({
TeamCreate({ team_name: teamName }) TeamCreate({ team_name: teamName })
// Spawn teammates (see SKILL.md Coordinator Spawn Template) // ⚠️ 不在此阶段 spawn worker
// Scanner, Assessor, Planner, Executor, Validator // Worker 在 Phase 4 (monitor) 中按阶段按需 spawnStop-Wait 策略)
// 这避免了 worker 先启动但无任务可做的鸡生蛋问题
``` ```
### Phase 3: Create Task Chain ### Phase 3: Create Task Chain
@@ -171,28 +172,33 @@ TDSCAN-001(扫描) → TDEVAL-001(评估) → TDPLAN-001(规划) → TDFIX-001(
TDPLAN-001(规划) → TDFIX-001(修复) → TDVAL-001(验证) TDPLAN-001(规划) → TDFIX-001(修复) → TDVAL-001(验证)
``` ```
### Phase 4: Coordination Loop ### Phase 4: Sequential Stage Execution (Stop-Wait)
```javascript ```javascript
// Read commands/monitor.md for full implementation // Read commands/monitor.md for full implementation
Read("commands/monitor.md") Read("commands/monitor.md")
``` ```
| Received Message | Action | > **策略**: 逐阶段 spawn worker同步阻塞等待返回。Worker 返回即阶段完成,无需轮询。
|-----------------|--------| >
| `scan_complete` | 标记 TDSCAN complete → 解锁 TDEVAL | > - ❌ 禁止: while 循环 + sleep + 检查状态
| `assessment_complete` | 标记 TDEVAL complete → 解锁 TDPLAN | > - ✅ 采用: `Task(run_in_background: false)` 同步调用 = 天然回调
| `plan_ready` | 标记 TDPLAN complete → 解锁 TDFIX |
| `fix_complete` | 标记 TDFIX complete → 解锁 TDVAL |
| `validation_complete` | 标记 TDVAL complete → 评估质量门控 |
| `regression_found` | 评估回归 → 触发 Fix-Verify 循环max 3 |
| Worker: `error` | 评估严重性 → 重试或上报用户 |
**Fix-Verify 循环逻辑**: **阶段流转**:
| 当前阶段 | Worker | 完成后 |
|----------|--------|--------|
| TDSCAN-001 | scanner | → 启动 TDEVAL |
| TDEVAL-001 | assessor | → 启动 TDPLAN |
| TDPLAN-001 | planner | → 启动 TDFIX |
| TDFIX-001 | executor | → 启动 TDVAL |
| TDVAL-001 | validator | → 评估质量门控 |
**Fix-Verify 循环**TDVAL 阶段发现回归时):
```javascript ```javascript
if (regressionFound && fixVerifyIteration < 3) { if (regressionFound && fixVerifyIteration < 3) {
fixVerifyIteration++ fixVerifyIteration++
// 创建 TDFIX-fix 任务 → TDVAL 重新验证 // 创建 TDFIX-fix + TDVAL-verify 任务,追加到 pipeline 继续执行
} else if (fixVerifyIteration >= 3) { } else if (fixVerifyIteration >= 3) {
// 接受当前状态,继续汇报 // 接受当前状态,继续汇报
mcp__ccw-tools__team_msg({ mcp__ccw-tools__team_msg({

View File

@@ -103,7 +103,6 @@ mcp__ccw-tools__team_msg({ summary: `[${role}] ...` })
const TEAM_CONFIG = { const TEAM_CONFIG = {
name: "testing", name: "testing",
sessionDir: ".workflow/.team/TST-{slug}-{date}/", sessionDir: ".workflow/.team/TST-{slug}-{date}/",
msgDir: ".workflow/.team-msg/testing/",
sharedMemory: "shared-memory.json", sharedMemory: "shared-memory.json",
testLayers: { testLayers: {
L1: { name: "Unit Tests", coverage_target: 80 }, L1: { name: "Unit Tests", coverage_target: 80 },

View File

@@ -86,7 +86,7 @@ AskUserQuestion({
}) })
``` ```
### Phase 2: Create Team + Spawn Workers ### Phase 2: Create Team + Initialize Session
```javascript ```javascript
TeamCreate({ team_name: teamName }) TeamCreate({ team_name: teamName })
@@ -130,7 +130,9 @@ const teamSession = {
Write(`${sessionFolder}/team-session.json`, JSON.stringify(teamSession, null, 2)) Write(`${sessionFolder}/team-session.json`, JSON.stringify(teamSession, null, 2))
``` ```
Spawn workers (see SKILL.md Coordinator Spawn Template). // ⚠️ Workers are NOT pre-spawned here.
// Workers are spawned per-stage in Phase 4 via Stop-Wait Task(run_in_background: false).
// See SKILL.md Coordinator Spawn Template for worker prompt templates.
### Phase 3: Create Task Chain ### Phase 3: Create Task Chain
@@ -178,6 +180,13 @@ TaskUpdate({ taskId: anaId, owner: "analyst", addBlockedBy: [run2Id] })
### Phase 4: Coordination Loop + Generator-Critic Control ### Phase 4: Coordination Loop + Generator-Critic Control
> **设计原则Stop-Wait**: 模型执行没有时间概念,禁止任何形式的轮询等待。
> - ❌ 禁止: `while` 循环 + `sleep` + 检查状态
> - ✅ 采用: 同步 `Task(run_in_background: false)` 调用Worker 返回 = 阶段完成信号
>
> 按 Phase 3 创建的任务链顺序,逐阶段 spawn worker 同步执行。
> Worker prompt 使用 SKILL.md Coordinator Spawn Template。
| Received Message | Action | | Received Message | Action |
|-----------------|--------| |-----------------|--------|
| strategist: strategy_ready | Read strategy → team_msg log → TaskUpdate completed | | strategist: strategy_ready | Read strategy → team_msg log → TaskUpdate completed |

View File

@@ -125,7 +125,7 @@ const industryConfig = {
}[industryChoice] || { strictness: 'standard', mustHave: [] } }[industryChoice] || { strictness: 'standard', mustHave: [] }
``` ```
### Phase 2: Create Team + Spawn Workers ### Phase 2: Create Team + Initialize Session
```javascript ```javascript
TeamCreate({ team_name: teamName }) TeamCreate({ team_name: teamName })
@@ -174,7 +174,9 @@ const teamSession = {
} }
Write(`${sessionFolder}/team-session.json`, JSON.stringify(teamSession, null, 2)) Write(`${sessionFolder}/team-session.json`, JSON.stringify(teamSession, null, 2))
// Spawn 4 workers (see SKILL.md Coordinator Spawn Template) // ⚠️ Workers are NOT pre-spawned here.
// Workers are spawned per-stage in Phase 4 via Stop-Wait Task(run_in_background: false).
// See SKILL.md Coordinator Spawn Template for worker prompt templates.
``` ```
### Phase 3: Create Task Chain ### Phase 3: Create Task Chain
@@ -246,6 +248,13 @@ TaskUpdate({ taskId: audit3Id, owner: "reviewer", addBlockedBy: [build2Id] })
### Phase 4: Coordination Loop ### Phase 4: Coordination Loop
> **设计原则Stop-Wait**: 模型执行没有时间概念,禁止任何形式的轮询等待。
> - ❌ 禁止: `while` 循环 + `sleep` + 检查状态
> - ✅ 采用: 同步 `Task(run_in_background: false)` 调用Worker 返回 = 阶段完成信号
>
> 按 Phase 3 创建的任务链顺序,逐阶段 spawn worker 同步执行。
> Worker prompt 使用 SKILL.md Coordinator Spawn Template。
#### Message Handling #### Message Handling
| Received Message | Action | | Received Message | Action |

View File

@@ -20,8 +20,15 @@
### 设计原则 ### 设计原则
> **模型执行没有时间概念**。禁止空转 while 循环检查状态。 > **模型执行没有时间概念,禁止任何形式的轮询等待。**
> 使用固定 sleep 间隔 + 最大轮询次数,避免无意义的 API 调用浪费。 >
> - ❌ 禁止: `while` 循环 + `sleep` + 检查状态(空转浪费 API 轮次)
> - ❌ 禁止: `Bash(sleep N)` / `Bash(timeout /t N)` 作为等待手段
> - ✅ 采用: 同步 `Task()` 调用(`run_in_background: false`call 本身即等待
> - ✅ 采用: Worker 返回 = 阶段完成信号(天然回调)
>
> **原理**: `Task(run_in_background: false)` 是阻塞调用coordinator 自动挂起直到 worker 返回。
> 无需 sleep无需轮询无需消息总线监控。Worker 的返回就是回调。
### Decision Logic ### Decision Logic
@@ -41,14 +48,15 @@ const routingTable = {
} }
``` ```
### 等待策略常量 ### Stage-Worker 映射表
```javascript ```javascript
const POLL_INTERVAL_SEC = 300 // 每次检查间隔 5 分钟 const STAGE_WORKER_MAP = {
const MAX_POLLS_PER_STAGE = 6 // 单阶段最多等待 6 次(~30 分钟) 'EXPLORE': { role: 'explorer', skillArgs: '--role=explorer' },
const SLEEP_CMD = process.platform === 'win32' 'ANALYZE': { role: 'analyst', skillArgs: '--role=analyst' },
? `timeout /t ${POLL_INTERVAL_SEC} /nobreak >nul 2>&1` 'DISCUSS': { role: 'discussant', skillArgs: '--role=discussant' },
: `sleep ${POLL_INTERVAL_SEC}` 'SYNTH': { role: 'synthesizer', skillArgs: '--role=synthesizer' }
}
// ★ 统一 auto mode 检测 // ★ 统一 auto mode 检测
const autoYes = /\b(-y|--yes)\b/.test(args) const autoYes = /\b(-y|--yes)\b/.test(args)
@@ -72,9 +80,10 @@ const pipelineTasks = allTasks
.sort((a, b) => Number(a.id) - Number(b.id)) .sort((a, b) => Number(a.id) - Number(b.id))
``` ```
### Step 2: Stage-Driven Execution (Exploration + Analysis) ### Step 2: Sequential Stage Execution (Stop-Wait) — Exploration + Analysis
> 按 pipeline 阶段顺序,逐阶段等待完成 > **核心**: 逐阶段 spawn worker同步阻塞等待返回
> Worker 返回 = 阶段完成。无 sleep、无轮询、无消息总线监控。
```javascript ```javascript
// 处理 EXPLORE 和 ANALYZE 阶段 // 处理 EXPLORE 和 ANALYZE 阶段
@@ -83,33 +92,57 @@ const preDiscussionTasks = pipelineTasks.filter(t =>
) )
for (const stageTask of preDiscussionTasks) { for (const stageTask of preDiscussionTasks) {
let stageComplete = false // 1. 提取阶段前缀 → 确定 worker 角色
let pollCount = 0 const stagePrefix = stageTask.subject.match(/^(\w+)-/)?.[1]
const workerConfig = STAGE_WORKER_MAP[stagePrefix]
while (!stageComplete && pollCount < MAX_POLLS_PER_STAGE) { if (!workerConfig) continue
Bash(SLEEP_CMD)
pollCount++
// 1. 检查消息总线 // 2. 标记任务为执行中
const messages = mcp__ccw-tools__team_msg({ TaskUpdate({ taskId: stageTask.id, status: 'in_progress' })
operation: "list", team: teamName, last: 5
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator",
to: workerConfig.role, type: "task_unblocked",
summary: `[coordinator] 启动阶段: ${stageTask.subject}${workerConfig.role}`
}) })
// 2. 路由消息 // 3. 同步 spawn worker — 阻塞直到 worker 返回Stop-Wait 核心)
for (const msg of messages) { const workerResult = Task({
const handler = routingTable[msg.type] subagent_type: "general-purpose",
if (!handler) continue prompt: `你是 team "${teamName}" 的 ${workerConfig.role.toUpperCase()}
processMessage(msg, handler)
}
// 3. 确认任务状态(兜底 ## ⚠️ 首要指令MUST
const currentTask = TaskGet({ taskId: stageTask.id }) Skill(skill="team-ultra-analyze", args="${workerConfig.skillArgs}")
stageComplete = currentTask.status === 'completed' || currentTask.status === 'deleted'
}
// 阶段超时处理 ## 当前任务
if (!stageComplete) { - 任务 ID: ${stageTask.id}
handleStageTimeout(stageTask, pollCount, autoYes) - 任务: ${stageTask.subject}
- 描述: ${stageTask.description || taskDescription}
- Session: ${sessionFolder}
## 角色准则(强制)
- 所有输出必须带 [${workerConfig.role}] 标识前缀
- 仅与 coordinator 通信
## 工作流程
1. Skill(skill="team-ultra-analyze", args="${workerConfig.skillArgs}") 获取角色定义
2. 执行任务 → 汇报结果
3. TaskUpdate({ taskId: "${stageTask.id}", status: "completed" })`,
run_in_background: false
})
// 4. Worker 已返回 — 检查结果
const taskState = TaskGet({ taskId: stageTask.id })
if (taskState.status !== 'completed') {
handleStageTimeout(stageTask, 0, autoYes)
} else {
mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator",
to: "user", type: "quality_gate",
summary: `[coordinator] 阶段完成: ${stageTask.subject}`
})
} }
} }
``` ```
@@ -164,9 +197,21 @@ if (MAX_DISCUSSION_ROUNDS === 0) {
// Then enter discussion loop // Then enter discussion loop
while (discussionRound < MAX_DISCUSSION_ROUNDS) { while (discussionRound < MAX_DISCUSSION_ROUNDS) {
// 等待当前 DISCUSS 任务完成 // 等待当前 DISCUSS 任务完成Stop-Wait: spawn discussant worker
const currentDiscussId = `DISCUSS-${String(discussionRound + 1).padStart(3, '0')}` const currentDiscussId = `DISCUSS-${String(discussionRound + 1).padStart(3, '0')}`
// ... wait for completion (same pattern as Step 2) const discussTask = pipelineTasks.find(t => t.subject.startsWith(currentDiscussId))
if (discussTask) {
TaskUpdate({ taskId: discussTask.id, status: 'in_progress' })
const discussResult = Task({
subagent_type: "general-purpose",
prompt: `你是 team "${teamName}" 的 DISCUSSANT。
Skill(skill="team-ultra-analyze", args="--role=discussant")
当前任务: ${discussTask.subject}
Session: ${sessionFolder}
TaskUpdate({ taskId: "${discussTask.id}", status: "completed" })`,
run_in_background: false
})
}
// 收集用户反馈 // 收集用户反馈
const feedbackResult = AskUserQuestion({ const feedbackResult = AskUserQuestion({
@@ -291,14 +336,12 @@ ${data.updated_understanding || '(Updated by discussant)'}
Write(`${sessionFolder}/discussion.md`, currentContent + roundContent) Write(`${sessionFolder}/discussion.md`, currentContent + roundContent)
} }
function handleStageTimeout(stageTask, pollCount, autoYes) { function handleStageTimeout(stageTask, _unused, autoYes) {
const elapsedMin = Math.round(pollCount * POLL_INTERVAL_SEC / 60)
if (autoYes) { if (autoYes) {
mcp__ccw-tools__team_msg({ mcp__ccw-tools__team_msg({
operation: "log", team: teamName, from: "coordinator", operation: "log", team: teamName, from: "coordinator",
to: "user", type: "error", to: "user", type: "error",
summary: `[coordinator] [auto] 阶段 ${stageTask.subject} 超时 (${elapsedMin}min),自动跳过` summary: `[coordinator] [auto] 阶段 ${stageTask.subject} worker 返回但未完成,自动跳过`
}) })
TaskUpdate({ taskId: stageTask.id, status: 'deleted' }) TaskUpdate({ taskId: stageTask.id, status: 'deleted' })
return return
@@ -306,18 +349,18 @@ function handleStageTimeout(stageTask, pollCount, autoYes) {
const decision = AskUserQuestion({ const decision = AskUserQuestion({
questions: [{ questions: [{
question: `阶段 "${stageTask.subject}" 已等待 ${elapsedMin} 分钟仍未完成。如何处理?`, question: `阶段 "${stageTask.subject}" worker 返回但未完成。如何处理?`,
header: "Stage Wait", header: "Stage Fail",
multiSelect: false, multiSelect: false,
options: [ options: [
{ label: "继续等待", description: `再等 ${MAX_POLLS_PER_STAGE}` }, { label: "重试", description: "重新 spawn worker 执行此阶段" },
{ label: "跳过此阶段", description: "标记为跳过,继续后续流水线" }, { label: "跳过此阶段", description: "标记为跳过,继续后续流水线" },
{ label: "终止流水线", description: "停止整个分析流程" } { label: "终止流水线", description: "停止整个分析流程" }
] ]
}] }]
}) })
const answer = decision["Stage Wait"] const answer = decision["Stage Fail"]
if (answer === "跳过此阶段") { if (answer === "跳过此阶段") {
TaskUpdate({ taskId: stageTask.id, status: 'deleted' }) TaskUpdate({ taskId: stageTask.id, status: 'deleted' })
} else if (answer === "终止流水线") { } else if (answer === "终止流水线") {
@@ -333,8 +376,20 @@ function handleStageTimeout(stageTask, pollCount, autoYes) {
### Step 4: Wait for Synthesis + Result Processing ### Step 4: Wait for Synthesis + Result Processing
```javascript ```javascript
// 等待 SYNTH-001 完成 // 等待 SYNTH-001 完成Stop-Wait: spawn synthesizer worker
// ... same wait pattern const synthTask = pipelineTasks.find(t => t.subject.startsWith('SYNTH-'))
if (synthTask) {
TaskUpdate({ taskId: synthTask.id, status: 'in_progress' })
const synthResult = Task({
subagent_type: "general-purpose",
prompt: `你是 team "${teamName}" 的 SYNTHESIZER。
Skill(skill="team-ultra-analyze", args="--role=synthesizer")
当前任务: ${synthTask.subject}
Session: ${sessionFolder}
TaskUpdate({ taskId: "${synthTask.id}", status: "completed" })`,
run_in_background: false
})
}
// 汇总所有结果 // 汇总所有结果
const finalMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`)) const finalMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`))
@@ -368,9 +423,8 @@ const summary = {
| Scenario | Resolution | | Scenario | Resolution |
|----------|------------| |----------|------------|
| Message bus unavailable | Fall back to TaskList polling only | | Worker 返回但未 completed (交互模式) | AskUserQuestion: 重试 / 跳过 / 终止 |
| Stage timeout (交互模式) | AskUserQuestion继续等待 / 跳过 / 终止 | | Worker 返回但未 completed (自动模式) | 自动跳过,记录日志 |
| Stage timeout (自动模式) | 自动跳过,记录日志 | | Worker spawn 失败 | 重试一次,仍失败则上报用户 |
| Teammate unresponsive (2x) | Respawn teammate with same task |
| Discussion loop stuck >5 rounds | Force synthesis, offer continuation | | Discussion loop stuck >5 rounds | Force synthesis, offer continuation |
| Synthesis fails | Report partial results from analyses | | Synthesis fails | Report partial results from analyses |

View File

@@ -163,7 +163,7 @@ if (!autoYes) {
} }
``` ```
### Phase 2: Create Team + Spawn Teammates ### Phase 2: Create Team + Initialize Session
```javascript ```javascript
const teamName = "ultra-analyze" const teamName = "ultra-analyze"
@@ -210,7 +210,9 @@ Write(`${sessionFolder}/discussion.md`, `# Analysis Discussion
TeamCreate({ team_name: teamName }) TeamCreate({ team_name: teamName })
// Spawn teammates (see SKILL.md Coordinator Spawn Template) // ⚠️ Workers are NOT pre-spawned here.
// Workers are spawned per-stage in Phase 4 via Stop-Wait Task(run_in_background: false).
// See SKILL.md Coordinator Spawn Template for worker prompt templates.
// Quick mode: 1 explorer + 1 analyst (single agents) // Quick mode: 1 explorer + 1 analyst (single agents)
// Standard/Deep mode: N explorers + N analysts (parallel agents with distinct names) // Standard/Deep mode: N explorers + N analysts (parallel agents with distinct names)
// explorer-1, explorer-2... / analyst-1, analyst-2... for true parallel execution // explorer-1, explorer-2... / analyst-1, analyst-2... for true parallel execution
@@ -243,6 +245,13 @@ EXPLORE-001 → ANALYZE-001 → SYNTH-001
### Phase 4: Discussion Loop + Coordination ### Phase 4: Discussion Loop + Coordination
> **设计原则Stop-Wait**: 模型执行没有时间概念,禁止任何形式的轮询等待。
> - ❌ 禁止: `while` 循环 + `sleep` + 检查状态
> - ✅ 采用: 同步 `Task(run_in_background: false)` 调用Worker 返回 = 阶段完成信号
>
> 按 Phase 3 创建的任务链顺序,逐阶段 spawn worker 同步执行。
> Worker prompt 使用 SKILL.md Coordinator Spawn Template。
```javascript ```javascript
// Read commands/monitor.md for full implementation // Read commands/monitor.md for full implementation
Read("commands/monitor.md") Read("commands/monitor.md")