Skip to content

Commit aac4af4

Browse files
committed
docs: design supervisor recursive planning
1 parent 779c8b5 commit aac4af4

1 file changed

Lines changed: 380 additions & 0 deletions

File tree

Lines changed: 380 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,380 @@
1+
# Supervisor 递归规划与执行粒度控制设计
2+
3+
> **版本:** 1.0
4+
> **日期:** 2026-06-07
5+
> **状态:** Draft(待评审)
6+
> **作者:** Spencer + Codex
7+
8+
## 1. 背景
9+
10+
当前 Supervisor 已经具备目标记忆、初始 decomposition、进展评估和 guidance 注入能力。现有实现会在目标没有 decomposition 时调用 `mode="decompose"` 生成 `items`,之后每轮通过 `mode="evaluate"` 判断进展、更新 `itemUpdates`、生成 guidance 并注入给 agent。
11+
12+
这个机制可以监督进展,但它默认把 decomposition items 当作可执行粒度。对于大目标,这会导致计划节点过粗。例如“写一部 100 万字小说”可能被拆成 5 个阶段,每个阶段仍然是 20 万字级别。Supervisor 随后会把这种粗节点作为当前执行目标推进,AI 单次任务过大,质量、上下文控制和验收都会变差。
13+
14+
本设计的核心不是“失败后纠偏”,而是:**Supervisor 在下发任务前必须判断当前节点是否适合 AI 执行;不适合时只递归拆当前 active branch,直到形成可执行 leaf。**
15+
16+
## 2. 目标
17+
18+
- 初始计划允许保持高层结构,不要求一开始拆完整棵树。
19+
- Supervisor 只对当前 active branch 递归拆分,未轮到的 sibling 保持粗粒度占位。
20+
- 每个即将下发给 agent 的任务必须通过类型化 `ready_check`
21+
- 支持 coding、writing、research、design、generic 等任务类型的不同粒度标准。
22+
- UI 可以展示类似思维导图的整体计划树,同时执行逻辑只关注 current leaf path 和 next executable item。
23+
- 使用 `maxDepth` 防止无限递归拆分。
24+
- 达到 `maxDepth` 仍不 ready 时,生成前置准备任务或范围受限任务,而不是继续无限拆树或把大任务硬塞给 agent。
25+
- 保持旧 `items` memory 可读,并提供迁移到树状结构的路径。
26+
27+
## 3. 非目标
28+
29+
- 不一次性实现完整项目管理系统、跨 session 编排或多 agent 分工。
30+
- 不要求初始规划展开整棵深层树。
31+
- 不做完整 plan version diff UI;MVP 只记录 `planRevision`
32+
- 不把“任务类型粒度标准”做成用户可配置规则引擎;先内置一组默认标准。
33+
- 不改变 provider headless 命令抽象,只扩展 Supervisor evaluator 的 prompt schema 和解析逻辑。
34+
35+
## 4. 现状与差距
36+
37+
当前核心结构:
38+
39+
- `SupervisorTargetMemory.items` 是扁平工作项列表。
40+
- `decompositionGenerated` 表示是否已生成初始 decomposition。
41+
- `activeItemId` 指向当前 item。
42+
- `stalledCount` 只基于是否有 `progressSummary``itemUpdates` 粗略累计。
43+
- evaluator prompt 明确要求 normal evaluation cycle 不重写 decomposition structure。
44+
45+
这导致三个限制:
46+
47+
1. **没有任务 ready gate**:一个 item 是否适合下发给 AI 执行没有独立判断。
48+
2. **没有递归拆分 active item 的流程**:初始 item 太大时,只能在旧计划内给 guidance。
49+
3. **没有树状表达**:UI 和 memory 无法表达“高层 mind map + 当前 leaf path”的关系。
50+
51+
## 5. 核心设计
52+
53+
采用 **Lazy Recursive Decomposition**
54+
55+
```text
56+
user objective
57+
-> generate top-level plan nodes
58+
-> select active node
59+
-> ready_check(active node)
60+
-> too_large: decompose this node only, then check first child
61+
-> ready: generate executable guidance and inject
62+
-> too_small: move execution scope upward or merge scope
63+
-> maxDepth reached and still not ready: create executable preparatory/range-limited task
64+
-> evaluate leaf completion
65+
-> mark leaf done
66+
-> roll up parent status
67+
-> select next sibling
68+
```
69+
70+
重要约束:
71+
72+
- 初始计划只需要 3-7 个高层节点。
73+
- sibling 不提前深拆。
74+
- 当前 active branch 可以一次递归拆到 ready,只受 `maxDepth` 限制。
75+
- MVP 不引入“一轮最多拆几次”的限制,避免首次执行停在不可执行的中间层。
76+
77+
## 6. Ready Check
78+
79+
`ready_check` 判断的是:**当前节点现在能不能交给 AI 执行,并期待质量稳定、验收清楚。**
80+
81+
建议 evaluator 输出:
82+
83+
```json
84+
{
85+
"mode": "ready_check",
86+
"nodeId": "node_1",
87+
"taskType": "writing",
88+
"granularity": "too_large",
89+
"reason": "The node asks for an entire 200k-word volume, which is too broad for one high-quality execution step.",
90+
"recommendedUnit": "scene_card_or_scene_draft",
91+
"qualityRisk": "large_scope_quality_loss",
92+
"missingInputs": ["scene conflict", "character motivation"],
93+
"confidence": "high"
94+
}
95+
```
96+
97+
`granularity` 含义:
98+
99+
- `too_large`:节点过大,需要继续拆当前节点。
100+
- `ready`:节点适合作为下一次执行任务。
101+
- `too_small`:节点过碎,执行会破坏质量或上下文,应提升到 parent 或合并相邻范围。
102+
103+
任务类型默认标准:
104+
105+
| 类型 | 合适执行粒度示例 | 过大示例 | 过碎示例 |
106+
| --- | --- | --- | --- |
107+
| `writing` | 人物卡、设定卡、章节大纲、场景卡、1500-3000 字场景正文 | 整卷正文、20 万字阶段 | 单句、单段 |
108+
| `coding` | 一个可验证行为、一个失败测试到通过、一个小模块边界内改动 | 多子系统重构、完整平台功能 | 改一个变量名但没有独立价值 |
109+
| `research` | 一个明确问题的资料收集和结论 | 开放式行业研究 | 单个搜索关键词 |
110+
| `design` | 一个组件/流程/模型的具体设计段落 | 整个产品系统重设 | 单个文案词替换 |
111+
| `generic` | 产物和验收都清楚的小步骤 | 无边界大目标 | 无独立产物的小动作 |
112+
113+
## 7. 计划树数据模型
114+
115+
新增树状 plan memory。旧 `items` 保留兼容读取,但新写入以 `planTree` 为主。
116+
117+
```ts
118+
type SupervisorPlanNodeStatus = "pending" | "in_progress" | "done" | "blocked";
119+
type SupervisorTaskType = "coding" | "writing" | "research" | "design" | "generic";
120+
type SupervisorGranularity = "too_large" | "ready" | "too_small";
121+
122+
interface SupervisorPlanNodeReadyCheck {
123+
granularity: SupervisorGranularity;
124+
reason: string;
125+
recommendedUnit?: string;
126+
qualityRisk?: string;
127+
missingInputs?: string[];
128+
confidence?: "low" | "medium" | "high";
129+
checkedAt: number;
130+
}
131+
132+
interface SupervisorPlanNodeExecution {
133+
executable: boolean;
134+
guidance?: string;
135+
lastInjectedAt?: number;
136+
}
137+
138+
interface SupervisorPlanNode {
139+
id: string;
140+
parentId?: string;
141+
title: string;
142+
objective: string;
143+
deliverable: string;
144+
acceptanceCriteria: string[];
145+
status: SupervisorPlanNodeStatus;
146+
taskType: SupervisorTaskType;
147+
depth: number;
148+
children: SupervisorPlanNode[];
149+
readyCheck?: SupervisorPlanNodeReadyCheck;
150+
execution?: SupervisorPlanNodeExecution;
151+
}
152+
153+
interface SupervisorTargetMemory {
154+
planTree?: SupervisorPlanNode;
155+
activeNodeId?: string;
156+
activeLeafPath?: string[];
157+
maxDepth: number;
158+
planRevision: number;
159+
}
160+
```
161+
162+
旧字段兼容:
163+
164+
- 如果 memory 只有 `items`,加载时生成 synthetic root。
165+
- 每个 legacy item 成为 root child。
166+
- `activeItemId` 映射为 `activeNodeId`
167+
- `decompositionGenerated` 可由 `planTree.children.length > 0` 推导,但 MVP 可以保留字段避免大范围破坏。
168+
169+
## 8. Evaluator 模式
170+
171+
在现有 `decompose``evaluate` 基础上增加两个模式:
172+
173+
### 8.1 `ready_check`
174+
175+
输入:
176+
177+
- user objective
178+
- current target memory
179+
- active node
180+
- active leaf path
181+
- task type hints
182+
- terminal/headless snapshot
183+
- latest user input
184+
185+
输出:
186+
187+
- `granularity`
188+
- `reason`
189+
- `recommendedUnit`
190+
- `missingInputs`
191+
- `qualityRisk`
192+
- `confidence`
193+
194+
### 8.2 `decompose_child`
195+
196+
只拆当前 active node,不处理 sibling。
197+
198+
输出:
199+
200+
```json
201+
{
202+
"mode": "decompose_child",
203+
"parentNodeId": "node_1",
204+
"children": [
205+
{
206+
"id": "node_1_1",
207+
"title": "Write the scene card",
208+
"objective": "Define the first scene before drafting prose",
209+
"deliverable": "A 500-800 word scene card",
210+
"acceptanceCriteria": ["characters are named", "conflict is explicit", "ending hook is defined"],
211+
"taskType": "writing",
212+
"status": "in_progress"
213+
}
214+
],
215+
"activeNodeId": "node_1_1",
216+
"progressSummary": "Split the first volume node into executable writing preparation steps."
217+
}
218+
```
219+
220+
### 8.3 `executable_task`
221+
222+
`ready_check` 返回 `ready`,或达到 `maxDepth` 仍不 ready 时使用。
223+
224+
它生成下发给 agent 的具体 guidance。达到 `maxDepth` 的 fallback guidance 必须把任务转成前置准备任务或范围受限任务。
225+
226+
示例:
227+
228+
```text
229+
Do not draft the full chapter yet. First create a scene card for scene 1:
230+
- characters
231+
- scene goal
232+
- conflict
233+
- emotional turn
234+
- ending hook
235+
- 500-800 words
236+
```
237+
238+
## 9. Runtime Flow
239+
240+
Manager 层新增 `prepareExecutableNode` 流程:
241+
242+
```text
243+
prepareExecutableNode(supervisor, context, memory)
244+
ensurePlanTree()
245+
node = resolveActiveNode()
246+
loop:
247+
check = evaluator.ready_check(node)
248+
saveReadyCheck(node, check)
249+
250+
if check.granularity == "ready":
251+
guidance = evaluator.executable_task(node)
252+
saveExecution(node, guidance)
253+
return { node, guidance }
254+
255+
if check.granularity == "too_small":
256+
node = selectParentOrMergedScope(node)
257+
continue
258+
259+
if node.depth < memory.maxDepth:
260+
children = evaluator.decompose_child(node)
261+
attachChildren(node, children)
262+
node = firstActiveChild(children)
263+
continue
264+
265+
fallback = evaluator.executable_task(node, { fallback: true, readyCheck: check })
266+
saveExecution(node, fallback.guidance)
267+
return { node, guidance: fallback.guidance }
268+
```
269+
270+
执行结束后的现有 `evaluate` 继续负责验收当前 executable leaf:
271+
272+
- 有证据满足 acceptance criteria 时标记 leaf done。
273+
- leaf done 后选择下一个 pending sibling。
274+
- sibling 不存在时,父节点在所有 children done 后 roll up 为 done。
275+
- 如果 parent done,继续向上 roll up。
276+
- 下一个 active node 再进入 `ready_check`
277+
278+
## 10. UI 展示
279+
280+
UI 分为两块:
281+
282+
### 10.1 Mind Map / Tree View
283+
284+
展示完整计划树:
285+
286+
- 高层节点可保持粗粒度。
287+
- 已拆分的 active branch 展开。
288+
- 未轮到的 sibling 可显示为折叠节点。
289+
- 节点状态包括 pending、in progress、done、blocked。
290+
- 节点可展示 ready check 标签:too large、ready、too small。
291+
292+
### 10.2 Execution Focus Panel
293+
294+
只展示执行所需内容:
295+
296+
- current leaf path,例如 `小说 > 第一卷 > 第一幕 > 第 1 章 > 第 1 场`
297+
- 当前 ready check 结果
298+
- next executable item
299+
- deliverable
300+
- acceptance criteria
301+
- 最近 guidance
302+
303+
这保证用户能看到全局 mind map,但 Supervisor 执行逻辑只关注 current leaf path 和 next executable item。
304+
305+
## 11. 错误与边界
306+
307+
- evaluator 返回非法 JSON:当前 cycle failed,保留旧 plan tree,不覆盖 memory。
308+
- `decompose_child` 返回空 children:标记 supervisor error,提示 decomposition failed。
309+
- `ready_check` 缺少 `granularity`:按 evaluator 输出非法处理。
310+
- `too_small` 无可提升 parent:将当前 node 标记为 ready,并要求 executable guidance 合并必要上下文。
311+
- 达到 `maxDepth``too_large`:生成前置准备任务或范围受限任务,不继续拆。
312+
- 用户修改 objective:重置 plan tree,`planRevision += 1`
313+
- 旧 memory 迁移失败:保留旧 `items` 路径,并记录 errorReason,避免丢失 supervisor。
314+
315+
## 12. 测试计划
316+
317+
Server evaluator tests:
318+
319+
- 解析 `ready_check` 输出。
320+
- 拒绝缺少 `granularity` 的 ready check。
321+
- 解析 `decompose_child` children。
322+
- 拒绝空 children。
323+
- 解析 fallback `executable_task` guidance。
324+
325+
Server manager tests:
326+
327+
- 没有 `planTree` 时从高层 objective 生成 root children。
328+
- legacy `items` 可以迁移成 synthetic root。
329+
- active node `too_large` 且未到 `maxDepth` 时只拆当前节点。
330+
- sibling 不被提前拆分。
331+
- current branch 递归拆到 ready 后注入 guidance。
332+
- 达到 `maxDepth` 仍不 ready 时生成 fallback executable task。
333+
- leaf done 后推进到下一个 sibling。
334+
- 所有 children done 后 parent roll up 为 done。
335+
336+
Web tests:
337+
338+
- tree view 渲染 root、children、active branch。
339+
- execution focus panel 展示 active leaf path、ready check、deliverable、acceptance criteria。
340+
- legacy supervisor memory 仍可展示基本状态。
341+
342+
Integration tests:
343+
344+
- 创建 supervisor 后,首次 trigger 可以生成高层树并递归到 executable leaf。
345+
- agent 完成 leaf 后,下一次 trigger 推进到 sibling。
346+
- evaluator failure 不破坏已有 plan tree。
347+
348+
## 13. 实施分期建议
349+
350+
### Phase 1: Backend tree memory and evaluator schemas
351+
352+
- 增加 plan node 类型。
353+
- 实现 legacy `items` 到 tree 的兼容转换。
354+
- 扩展 evaluator result parser。
355+
- 加 ready check、decompose child、executable task 单测。
356+
357+
### Phase 2: Manager recursive preparation flow
358+
359+
- 增加 `prepareExecutableNode`
360+
- 在注入 guidance 前先执行 ready gate。
361+
- 实现 maxDepth fallback。
362+
- 实现 leaf completion 和 parent rollup。
363+
364+
### Phase 3: UI mind map and execution focus
365+
366+
- 在 details 中展示 tree/mind map。
367+
- 展示 active leaf path 和 ready check。
368+
- 保持现有 card 操作不变。
369+
370+
## 14. 验收标准
371+
372+
该设计实现完成后,应满足:
373+
374+
1. “写 100 万字小说”这类大目标不会直接下发“写第一卷 20 万字”给 agent。
375+
2. 初始计划可以只生成高层节点。
376+
3. Supervisor 只递归拆当前 active branch。
377+
4. 当前 leaf 只有通过 ready check 后才会被注入给 agent。
378+
5. 达到 maxDepth 仍不 ready 时,会生成前置准备任务或范围受限任务。
379+
6. UI 能看到全局计划树和当前执行路径。
380+
7. 旧 supervisor memory 不会因为新模型无法读取。

0 commit comments

Comments
 (0)