mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-28 09:23:08 +08:00
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:
@@ -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 |
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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 |
|
||||||
|
|||||||
@@ -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 |
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 |
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|||||||
@@ -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 按需 spawn(monitor.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
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -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 状态判断 |
|
||||||
|
|||||||
@@ -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) 中按阶段按需 spawn(Stop-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({
|
||||||
|
|||||||
@@ -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 },
|
||||||
|
|||||||
@@ -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 |
|
||||||
|
|||||||
@@ -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 |
|
||||||
|
|||||||
@@ -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 |
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|||||||
Reference in New Issue
Block a user