plan-migration.html
21.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" />
<title>最小改造路径 · LemonBoss PRD</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,300;9..144,500;9..144,700&family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="assets/shell.css" />
</head>
<body data-page="plan-migration.html">
<div class="shell">
<aside id="sidebar"></aside>
<main class="page">
<header class="page-head">
<div class="crumb"><span class="pill">08 · PLAN</span><span class="sep">/</span><span>最小改造路径</span></div>
<h1>最小改造路径</h1>
<p class="deck"><b>五</b>个阶段递进,每阶段独立可演示。P0 把 79 个工具实现 + ACP 桥接搭好;P1 不动核心,让 PM+Architect 跑出文档;P2 先单 Unit;P3 才把 L1 + L2 接起来;P4 加 L3 反馈 + UI。每阶段对应一个 PR。</p>
</header>
<article class="body">
<section>
<h2>五阶段总览</h2>
<table>
<thead><tr><th>阶段</th><th>目标</th><th>新增 / 修改</th><th>可演示场景</th></tr></thead>
<tbody>
<tr>
<td><b>P0 · Bootstrap</b><br/><span class="sig">2.5 周</span></td>
<td>把 79 个工具从「签名」变成「可调用 JS」+ 桥接 LemonBoss agent-manager + 提取 6 个 system prompt 到 md 文件</td>
<td><a href="arch-tool-registry.html">tool-registry</a>(34 个独立工具实现)、<a href="arch-acp-bridge.html">acp-bridge</a>、scripts/extract-agent-prompts.js、scripts/phase0-verify.js</td>
<td>跑 <code>scripts/phase0-verify.js</code> 看到 7 个 critical 工具就位 + 一个 mock Agent 调用回环</td>
</tr>
<tr>
<td><b>P1 · Docs MVP</b></td>
<td>能由 PM + Architect 把一段需求转成多页 PRD 站点 + 多页 SDD 站点 + <code>units.json</code> + <code>integration/spec.json</code></td>
<td><code>DocStore</code>、PM / Architect 模板、<code>POST /api/devloop/projects</code></td>
<td>curl 一段中文需求 → 文件系统里看到 PRD/SDD 多页站点 + units.json + integration/spec.json + agent-state/</td>
</tr>
<tr>
<td><b>P2 · L1 单 Unit</b></td>
<td>对单个 Unit 跑 Coder→Tester 重试到通过</td>
<td>Coder / Tester 模板、<code>UnitRegistry</code>、<code>retryWithReflection</code>(新写在 loop-controller.js 内,不抽公共)</td>
<td>故意挖一个 bug 让 Tester 红,看 Coder 反思后绿</td>
</tr>
<tr>
<td><b>P3 · L1 + L2 联动</b></td>
<td>多 Unit 并行 + 集成测试 + 失败回写</td>
<td><code>LoopController</code>、Integrator / BugTriager 模板,复用 <code>scheduler</code></td>
<td>故意写 contract mismatch,看 SDD 自动 patch + 受影响 Unit reset → 重跑 L1</td>
</tr>
<tr>
<td><b>P4 · L3 + UI</b></td>
<td>人类反馈触发增量;前端实时看板</td>
<td><code>DevLoopDashboard.vue</code>、SSE 流、PRD diff 渲染</td>
<td>页面上发新需求 → 看到 PRD 新增 section + 新 Unit 自动入队</td>
</tr>
</tbody>
</table>
</section>
<section>
<h2>P0 · Bootstrap(~2.5 周 / 11.5 天)</h2>
<div class="callout warn">
<b>这是 P1 的<u>前置条件</u>。</b>没有 P0,PM/Architect 的 79 个工具签名都是空中楼阁。详细工时分解 + 工具组织见 <a href="arch-tool-registry.html">arch-tool-registry §⑪</a>。
</div>
<h3>P0 子任务速览</h3>
<table class="dense">
<thead><tr><th>子阶段</th><th>内容</th><th>工时</th><th>难度</th></tr></thead>
<tbody>
<tr><td>P0.A 工具实现</td><td><code>server/src/tools/devloop/</code> 下 7 个文件,34 个独立函数 (~1700 行)</td><td>5 天</td><td>中(cheerio 多)</td></tr>
<tr><td>P0.B 提示提取</td><td><code>scripts/extract-agent-prompts.js</code> 从 6 个 agent HTML §2.2 抽 prompt</td><td>0.5 天</td><td>低(正则)</td></tr>
<tr><td>P0.C 模板注册</td><td><code>system/templates/_registry.json</code> 加 6 条 devloop-* + toolPolicy</td><td>0.5 天</td><td>低</td></tr>
<tr><td>P0.D CLI tools 注入</td><td><code>packages/acp-core/protocol/ClaudeCliProtocol.js</code> 改 ~10 行,按 toolPolicy 生成 --tools json</td><td>1 天</td><td>中</td></tr>
<tr><td>P0.E agent-manager 透传</td><td>加 toolRegistry / toolCtx / onChunk 三个可选参数,~10 行</td><td>0.5 天</td><td>低</td></tr>
<tr><td>P0.F jsonGuard 挂 Bash</td><td>Bash 工具 preExecute 钩子拦截 inline JSON</td><td>0.5 天</td><td>低</td></tr>
<tr><td>P0.G 验证脚本</td><td><code>scripts/phase0-verify.js</code> + <code>phase0-test-call.js</code></td><td>1 天</td><td>低</td></tr>
<tr><td>P0.H 联调</td><td>跑一个 mock PM 调用 → 看 todolist 落盘 + SSE 触发</td><td>2 天</td><td>—</td></tr>
<tr><td><b>P0 合计</b></td><td>—</td><td><b>11 天 ≈ 2.5 周</b></td><td>—</td></tr>
</tbody>
</table>
<h3>验收</h3>
<pre class="code">node scripts/phase0-verify.js
<span class="c"># ✓ All 79 tools registered (34 unique impl)</span>
<span class="c"># ✓ 6 system prompts extracted to system/templates/devloop-*.md</span>
<span class="c"># ✓ _registry.json contains all 6 devloop-* entries</span>
node scripts/phase0-test-call.js
<span class="c"># ✓ Mock PM call → write_todolist tool invoked</span>
<span class="c"># ✓ data/companies/c-test/projects/p-mock/agent-state/pm-todo.json written</span>
<span class="c"># ✓ SSE agent.todolist event emitted</span>
<span class="c"># ✓ No sandbox violations</span></pre>
<div class="callout ok">
<b>关键决策:</b>P0 期间 agent-manager 改动 ≤ 20 行,全是<b>追加可选参数</b>。老调用方(Master Agent / Innovator)不受影响。
</div>
</section>
<section>
<h2>P1 · Docs MVP(~1 周 / 5 天)</h2>
<div class="callout">
<b>建议的 demo 需求:</b>「一个 TODO 列表 API + 前端」。比登录系统更小、不涉及 auth/JWT/bcrypt 等坑、30 分钟能端到端跑通。
预期 Architect 拆出 3 个 Unit:<code>todo-be</code>(POST/GET /todos)· <code>todo-fe</code>(Vue 列表)· 可选 <code>todo-db</code>(SQLite schema)。
登录系统留到 <b>P3 当 contract_mismatch 演示</b>用。
</div>
<h3>新增文件</h3>
<pre class="tree">
server/
├── services/
│ └── <span class="new">doc-store.js</span> <span class="com"># ~140 行</span>
├── routes/
│ └── <span class="new">devloop.js</span> <span class="com"># 只挂 POST /projects · GET /state,~80 行</span>
└── src/core/
└── (LoopController 阶段性 stub)
system/templates/
├── <span class="new">devloop-pm.md</span> <span class="com"># PM system prompt</span>
├── <span class="new">devloop-architect.md</span> <span class="com"># Architect system prompt</span>
└── <span class="new">_registry.json</span> <span class="com"># 追加 6 条(先用 PM + Architect 两条)</span>
</pre>
<h3>验收</h3>
<pre class="code">curl -X POST http://localhost:3010/api/devloop/projects -d @/tmp/req.json
<span class="c"># /tmp/req.json: {"company_id":"c-001","name":"todo-demo","requirement":"做一个 TODO 列表:能新增、列表、Vue 前端"}</span>
<span class="c"># 期望产物(与 data-layout.html 对齐)</span>
data/companies/c-001/projects/p-XXXXXX/
├── project.json ✓ <span class="c"># M-1 项目元数据</span>
├── prd/ ✓ <span class="c"># M-3 多页 PRD 站点</span>
│ ├── index.html
│ ├── reading-guide.html
│ ├── product/{background,personas,...}.html
│ ├── feature/feature-tree.html
│ ├── flow/user-flows.html
│ └── prototype/proto-*.html
├── sdd/ ✓ <span class="c"># M-4 多页 SDD 站点</span>
│ ├── index.html
│ └── mvcp/{model,view,control,process}.html
├── units.json ✓ <span class="c"># M-2 含 l2_rounds / l2_budget 初值</span>
├── integration/spec.json ✓ <span class="c"># Architect 写</span>
├── agent-state/ ✓ <span class="c"># M-10 / M-12 Agent 持久化运行态</span>
│ ├── pm.json · pm-todo.json
│ └── architect.json · architect-todo.json
└── history/ ✓ <span class="c"># 全部 rev 归档</span>
├── prd-rev-001.html
└── sdd-rev-001.html</pre>
</section>
<section>
<h2>P2 · L1 单 Unit(~1.5 周 / 8 天)</h2>
<h3>新增文件</h3>
<pre class="tree">
server/
├── services/
│ └── <span class="new">unit-registry.js</span> <span class="com"># ~120 行</span>
└── src/core/
└── <span class="new">loop-controller.js</span> <span class="com"># runUnit() 单 unit 循环 + retryWithReflection() 内置,~140 行</span>
system/templates/
├── <span class="new">devloop-coder.md</span>
└── <span class="new">devloop-tester.md</span></pre>
<div class="callout warn">
<b>关于反思重试:</b>直接在 <code>loop-controller.js</code> 内写一份 <code>retryWithReflection()</code>。<b>不</b>从 <code>evolution-loop.js</code> 抽公共。原因见 <a href="arch-mapping.html">arch-mapping · 为什么 P1~P4 不抽公共 retry 函数</a>。
</div>
<h3>修改文件</h3>
<ul>
<li><code>server/routes/devloop.js</code> · 加 <code>POST /api/devloop/projects/:pid/run</code>(即 <a href="sdd-control.html">sdd-control · C-3</a>);P2 阶段 handler 临时支持 query <code>?only=<unitId></code> 调用 <code>loopController.runUnit(pid, unitId)</code> 让单 unit 可测,P3 改造 <code>runProject()</code> 后即移除 <code>only</code> 参数,与 C-3 完全等价</li>
<li><code>server/services/evolution-loop.js</code> · <b>不动</b></li>
</ul>
<h3>验收</h3>
<p>跑命令后看到:</p>
<ul>
<li>Unit 状态从 <code>pending → coding → testing → failed → coding → testing → passed</code></li>
<li><code>coder.log</code> 第二条决策明显引用了第一条的失败原因(说明反思生效)</li>
<li>沙箱越权(试图改其他 unit code)被工具层拒绝</li>
</ul>
</section>
<section>
<h2>P3 · L1 + L2 联动(~3 周 / 15 天)</h2>
<h3>新增 / 完善</h3>
<pre class="tree">
server/src/core/loop-controller.js <span class="com"># 完整 runProject() 主循环(去掉 P2 的 ?only= 临时入口)</span>
system/templates/
├── <span class="new">devloop-integrator.md</span>
└── <span class="new">devloop-triager.md</span>
server/services/
├── <span class="new">sse-broker.js</span> <span class="com"># SSE 订阅管理 + stream.log replay,~80 行</span>
└── <span class="new">bug-tracker.js</span> <span class="com"># 写 bugs.ndjson + GET /bugs 端点支持,~80 行</span>
server/routes/devloop.js <span class="com"># 加 C-5 GET /api/devloop/projects/:pid/stream + GET /:pid/bugs</span>
<span class="c"># 同步生成的 append-only 产物(与 data-layout.html 对齐)</span>
projects/{pid}/
├── timeline.ndjson <span class="com"># M-13 全流程统一日志(loop-controller / agent-bridge 写)</span>
├── bugs.ndjson <span class="com"># M-14 跨 run bug 台账(bug-tracker 写)</span>
├── changelog.ndjson <span class="com"># M-15 PRD/SDD/units rev 变更流(DocStore 写)</span>
└── stream.log <span class="com"># SSE 客户端视角日志(sse-broker 写,7 天滚动)</span></pre>
<h3>验收</h3>
<p>P3 必须在 <b>4 类 L2 分支</b>(参见 <a href="sdd-process.html">sdd-process · P-2</a>)下都跑通:</p>
<h4>① <code>contract_mismatch</code> · 自动 patch SDD</h4>
<ol>
<li>需求 = 「一个登录系统:邮箱密码 + token,前端展示」</li>
<li>在 Architect 生成的 SDD 中<b>故意</b>插入矛盾(auth-be 写 401,auth-fe 假设 403)</li>
<li>L1 全部 passed → L2 集成失败</li>
<li>BugTriager 给出 <code>contract_mismatch</code>,confidence ≥ 0.5</li>
<li>Architect 自动 patch SDD(mode=patch)→ <code>sdd.updated</code> 事件</li>
<li>auth-be + auth-fe reset → 重跑 L1(计 1 个 l2_round)</li>
<li>第二次 L2 通过 → <code>project.shipped</code></li>
</ol>
<h4>② <code>impl_bug</code> · 不改 SDD,仅 reset</h4>
<ul>
<li>SDD 正确,故意把 auth-be 实现写成 password 字段名打错</li>
<li>BugTriager 归因 <code>impl_bug</code> → SDD 不动 → 仅 auth-be reset → 重跑 L1(<b>不</b>烧 l2_round 预算)</li>
</ul>
<h4>③ <code>spec_ambiguous</code> / confidence < 0.5 · 升 L3 等待人类</h4>
<ul>
<li>需求中故意留模糊点(如「token 续期策略」未定)</li>
<li>Triager 给出 <code>spec_ambiguous</code> 或 confidence < 0.5</li>
<li>SSE 收到 <code>human_intervention_needed</code>(reason=<code>low_confidence_triage</code>)→ LoopController 进入 <code>l2_blocked</code>,<b>不</b>自动 patch</li>
</ul>
<h4>④ <code>infra_flake</code> · 直接重跑</h4>
<ul>
<li>模拟 Integrator 进程超时(kill -9)→ 归因 <code>infra_flake</code> → 直接 <code>runL2()</code> 重跑,<b>不</b>烧预算、<b>不</b>动 Unit</li>
</ul>
<h4>⑤ 可观测性产物校验(4 类分支跑完后统一检查)</h4>
<ul>
<li><code>bugs.ndjson</code> 含上述每次 triage 结果(open → fixing → fixed → verified 状态机轨迹)</li>
<li><code>changelog.ndjson</code> 至少 1 条 sdd-rev 变更(来自分支 ①)</li>
<li><code>timeline.ndjson</code> 含完整事件链路(unit.state / integration.result / triage.result / sdd.updated)</li>
<li>SSE <code>GET /api/devloop/projects/:pid/stream</code> 用 Last-Event-ID 重连后能 replay 缺失事件</li>
</ul>
<h3>桥梁:极简 Status Page</h3>
<p>P3 末尾顺手做一个 <b>~100 行的纯静态 HTML status page</b>(不上 Vue 路由,单文件放 <code>server/public/devloop-status.html</code>),轮询 <code>GET /api/devloop/projects/:pid/state</code> 渲染 DAG 与 loop 状态条。作用:</p>
<ul>
<li>给 P3 后期调试时一个可视化窗口(眼看 unit 状态翻飞比 tail 文件直观)</li>
<li>作为 P4 完整 Dashboard 的功能预演 — 提前发现交互问题</li>
<li>~100 行,不算进 P4 工作量</li>
</ul>
</section>
<section>
<h2>P4 · L3 + UI(~2 周 / 10 天)</h2>
<h3>新增</h3>
<pre class="tree">
web/src/views/
├── <span class="new">DevLoopDashboard.vue</span> <span class="com"># ~400 行</span>
└── <span class="new">DevLoopOps.vue</span> <span class="com"># Ops 容器(4 个 tab:Bugs / Loops / Changelog / Progress)</span>
web/src/components/devloop/ <span class="com"># Dashboard 子组件</span>
├── <span class="new">DashboardHeader.vue</span>
├── <span class="new">LoopStatusBar.vue</span>
├── <span class="new">UnitsDAG.vue</span> <span class="com"># 复用 PipelineEditor 渲染层</span>
├── <span class="new">LiveAgentStream.vue</span>
├── <span class="new">PrdDiffPanel.vue</span>
└── <span class="new">FeedbackModal.vue</span>
web/src/components/devloop/ops/ <span class="com"># Ops 子页(与 ops-*.html wireframe 对齐)</span>
├── <span class="new">BuglistView.vue</span> <span class="com"># 渲染 bugs.ndjson(M-14)</span>
├── <span class="new">LoopLogView.vue</span> <span class="com"># 按 L1/L2/L3 分组 timeline.ndjson</span>
├── <span class="new">ChangelogView.vue</span> <span class="com"># 渲染 changelog.ndjson(M-15)</span>
└── <span class="new">ProgressView.vue</span> <span class="com"># 项目实时进度聚合</span>
web/src/router/index.js <span class="com"># 加 /devloop/:pid 主路由 + /devloop/:pid/ops/{bugs,loops,changelog,progress} 4 个子路由</span>
server/routes/devloop.js <span class="com"># 加 C-6 POST /:pid/sign-off + C-7 POST /:pid/abandon(参见 sdd-control)</span></pre>
<h3>验收</h3>
<ul>
<li>打开 <code>http://localhost:5173/devloop/p-XXXXXX</code> 看到 wireframe 描述的全部 4 个区域</li>
<li>点 「+ NEW REQUIREMENT」发新需求 → PRD diff 区出现新 section(触发 PM incremental 模式)</li>
<li>Live 流实时滚动 Agent 输出(断网 5s 后自动重连,用 Last-Event-ID replay)</li>
<li>DAG 节点点击展开抽屉,看 unit 的最近 3 次 run</li>
<li>4 个 Ops 子页都能打开:<code>/ops/bugs</code> · <code>/ops/loops</code> · <code>/ops/changelog</code> · <code>/ops/progress</code></li>
<li>项目交付后点 「Sign Off」按钮 → <code>POST /api/devloop/projects/:pid/sign-off</code> → 状态变 <code>shipped-final</code>,前端拒绝再发新反馈</li>
<li>异常项目点 「Abandon」按钮 → <code>POST /api/devloop/projects/:pid/abandon</code> → 状态变 <code>abandoned</code>,SSE 发 close 帧</li>
</ul>
</section>
<section>
<h2>成本估算</h2>
<table class="dense">
<thead><tr><th>类型</th><th>文件数</th><th>预估行数</th><th>难度</th></tr></thead>
<tbody>
<tr><td>新增 JS(后端)</td><td>6 (<code>doc-store</code> · <code>devloop</code> route · <code>unit-registry</code> · <code>loop-controller</code> · <code>sse-broker</code> · <code>bug-tracker</code>)</td><td>~800</td><td>中</td></tr>
<tr><td>新增 Agent 模板</td><td>6 (PM · Architect · Coder · Tester · Integrator · Triager)</td><td>~900</td><td>中(参考 <a href="agents-pm.html">agents-pm</a> / <a href="agents-architect.html">agents-architect</a>,单模板 ~150 行 + 多个 few-shot 例子)</td></tr>
<tr><td>新增 Vue 组件</td><td>12 (Dashboard 1 + Ops 容器 1 + dashboard 子组件 6 + ops 子页 4)</td><td>~1650</td><td>中</td></tr>
<tr><td>修改既有</td><td>3 (<code>server/index.js</code> 挂路由 · <code>_registry.json</code> 加 6 条 · <code>web/src/router/index.js</code> 加 5 条路由)</td><td>~50</td><td>低</td></tr>
<tr><td>新增包依赖</td><td>1 (<code>cheerio</code>)</td><td>—</td><td>—</td></tr>
<tr><td><b>合计</b></td><td><b>27</b></td><td><b>~3400 行</b></td><td>—</td></tr>
</tbody>
</table>
<p class="sig">较早前版本(20 文件 / ~1580 行)低估了:① Agent 模板单文件实际 prompt 长度(PM/Architect 当前 PRD 已揭示需 200-300 行 prompt + 数个 few-shot);② Dashboard 子组件粒度(DAG / 抽屉 / diff 渲染单组件就 100+ 行);③ Ops 4 个子页此前未计入。</p>
<h3>时间预算</h3>
<p>单人 Claude Code 协同开发:<b>P0(11 天)</b> → P1(5 天)→ P2(8 天)→ P3(18 天)→ P4(15 天)= 约 <b>9.5 周</b>。每阶段末 1 天用于演示 + 写迭代 PR 描述。</p>
<ul>
<li><b>P0(11 天)</b>:79 工具实现 + ACP 桥接 + 提示提取 + 验证脚本,是 P1 的前置(详见上方 P0 表格 + <a href="arch-tool-registry.html">tool-registry §⑪</a>)</li>
<li><b>P3 +3 天</b>:增加 4 类 L2 分支演示(contract_mismatch / impl_bug / spec_ambiguous / infra_flake)+ 可观测性产物(bugs/changelog/timeline.ndjson)+ bug-tracker 服务</li>
<li><b>P4 +5 天</b>:Ops 4 个子页(Bugs / Loops / Changelog / Progress)+ sign-off / abandon 端点联调</li>
</ul>
<p class="sig">早期版本估算 4 周过紧,6 周漏了 P0,7 周漏了 P0 — 现在 9.5 周是<b>含 P0 + 含 Ops + 含多分支演示</b>的诚实估算。参考 <a href="plan-cost-concurrency.html">成本预算</a> 看实际 token / 美元数字。</p>
</section>
<section>
<h2>「自举」乐趣</h2>
<div class="callout ok">
<b>P4 完成后</b>,你可以让 LemonBoss DevLoop 系统去开发 <b>LemonBoss 自己</b>的下一个 feature。换句话说:用 v1 的 DevLoop 写 v1.1 的代码。这是验证三层 Loop 是否真的「能自我迭代」的最朴素方式。
</div>
</section>
</article>
<nav class="prev-next"></nav>
<footer class="site"><div><b>Section</b>08 · Plan</div><div><b>Page</b>plan-migration.html</div></footer>
</main>
</div>
<script src="assets/shell.js"></script>
</body>
</html>