08 · PLAN/最小改造路径

最小改造路径

五个阶段递进,每阶段独立可演示。P0 把 79 个工具实现 + ACP 桥接搭好;P1 不动核心,让 PM+Architect 跑出文档;P2 先单 Unit;P3 才把 L1 + L2 接起来;P4 加 L3 反馈 + UI。每阶段对应一个 PR。

第一天 Quick-Start · 从零起步

「我装好仓库 cd 进去,第一行命令该是什么」—— 答案:

# 1. 拉仓库 + 装依赖
git clone gitlab-wuwei.hexpm.com:yibo/lemonboss.git
cd lemonboss
pnpm install                                          # LemonBoss 用 pnpm workspace

# 2. 配 .env
cp .env.example .env
# 编辑设置 PORT=3010 等;v1 不需要 OPEN_API_KEYS

# 3. 浏览本 PRD (推荐先扫一遍 index → reading-guide)
open docs/prd/newfunction/index.html                  # macOS
# 或: python3 -m http.server -d docs/prd/newfunction 8000 → open localhost:8000

# 4. 验证文档侧 tooling 已经就绪
node scripts/extract-manifest.js                      # 期望: 54 MVCP defs 100%
node scripts/build-search-index.js                    # 期望: 51 pages 195KB

# 5. 从 P0.0 开始动代码 (按 §五阶段总览 P0 表格顺序)
mkdir -p server/services
# 第一个文件: server/services/path-resolver.js  (所有人都依赖它)
# 第二个文件: server/services/doc-store.js
# ...按 §P0 子任务速览 P0.0 行的服务清单顺次实现

# 6. P0.B 启用 Mock Claude CLI 模式 (一旦工具骨架在)
#    详见 arch-acp-bridge.html · Mock Mode 章节
MOCK_CLAUDE=1 node scripts/phase0-verify.js           # 工具流跑通,不烧 token

# 7. 真跑 P0 验证 (P0.J 完成后)
node scripts/phase0-verify.js                         # ✓ All 79 tools + 1 mock PM call
node scripts/phase0-test-call.js                      # ✓ todolist 落盘 + SSE 触发

# 8. 进 P1: 准备启动真实 Agent
PORT=3010 node server/index.js &                      # server 起来
node scripts/devloop-new.js \
  --name "Auto TODO" \
  --requirement "做一个 TODO API + Vue 前端"     # sandbox 模式
# 期望: 30-60s 内 data/.../projects/p-XXXXXX/prd/ 完整生成

第一天能 100% 跑通到第 4 步(文档侧验证);P0.0 实施开始后第 5 步以下才有意义。

五阶段总览

阶段目标新增 / 修改可演示场景
P0 · Bootstrap
3.5 周
服务层 7 件套(pathResolver/docStore/unitRegistry/bugTracker/timelineLogger/sseBroker/GitVault)+ 79 工具实现 + Mock Claude CLI 模式 + ACP 桥接 + 系统提示提取 + git 集成 7 个 server/services/*.js、tool-registry(34 工具)、acp-bridge + Mock 模式、git-versioning、scripts/extract-agent-prompts.js、scripts/phase0-verify.js MOCK_CLAUDE=1 phase0-verify 通过 → 真跑 phase0-verify 通过 → 一个 mock PM call 落 todolist + .git 初始化 + 首个 prd commit
P1 · Docs MVP 能由 PM + Architect 把一段需求转成多页 PRD 站点 + 多页 SDD 站点 + units.json + integration/spec.json DocStore、PM / Architect 模板、POST /api/devloop/projects curl 一段中文需求 → 文件系统里看到 PRD/SDD 多页站点 + units.json + integration/spec.json + agent-state/
P2 · L1 单 Unit 对单个 Unit 跑 Coder→Tester 重试到通过 Coder / Tester 模板、UnitRegistry、retryWithReflection(新写在 loop-controller.js 内,不抽公共) 故意挖一个 bug 让 Tester 红,看 Coder 反思后绿
P3 · L1 + L2 联动 多 Unit 并行 + 集成测试 + 失败回写 LoopController、Integrator / BugTriager 模板,复用 scheduler 故意写 contract mismatch,看 SDD 自动 patch + 受影响 Unit reset → 重跑 L1
P4 · L3 + UI 人类反馈触发增量;前端实时看板 DevLoopDashboard.vue、SSE 流、PRD diff 渲染 页面上发新需求 → 看到 PRD 新增 section + 新 Unit 自动入队

P0 · Bootstrap(~2.5 周 / 11.5 天)

这是 P1 的前置条件。没有 P0,PM/Architect 的 79 个工具签名都是空中楼阁。详细工时分解 + 工具组织见 arch-tool-registry §⑪。

P0 子任务速览

子阶段内容工时难度
P0.0 服务层 7 件套
所有其他都依赖它
server/services/ 顺次实现:
① path-resolver.js(~80 行;第一个写,其余都依赖它)
② doc-store.js(~140 行;prd/sdd/units IO + cheerio 校验)
③ unit-registry.js(~120 行;Unit FSM + l2GateOpen)
④ bug-tracker.js(~110 行;bugs.ndjson CRUD + dedupKey)
⑤ timeline-logger.js + changelog-writer.js(~80 行合计)
⑥ sse-broker.js(~80 行;订阅 + 心跳 + replay)
⑦ git-vault.js(~150 行;spawn git wrapper + per-pid mutex)
4.5 天低中(独立实现 · 每个文件可单测)
P0.A 工具实现
需 P0.0 完成
server/src/tools/devloop/ 下 7 个文件,34 个独立函数 (~1700 行)。每个工具 wrapper 通过 ctx 引用 P0.0 的服务5 天中(cheerio 多)
P0.A2 Mock Claude CLI 模式
开发期省 token
给 ClaudeCliProtocol 加 MOCK_CLAUDE=1 分支,读 system/mock-responses/{agent}/*.json 当 stub 回复。详见 acp-bridge · Mock Mode 0.5 天低
P0.B 提示提取scripts/extract-agent-prompts.js 从 6 个 agent HTML §2.2 抽 prompt0.5 天低(正则)
P0.C 模板注册system/agents/_registry.json 加 6 条 devloop-* + toolPolicy0.5 天低
P0.D CLI tools 注入packages/acp-core/protocol/ClaudeCliProtocol.js 改 ~10 行,按 toolPolicy 生成 --tools json1 天中
P0.E agent-manager 透传加 toolRegistry / toolCtx / onChunk 三个可选参数,~10 行0.5 天低
P0.F jsonGuard 挂 BashBash 工具 preExecute 钩子拦截 inline JSON0.5 天低
P0.G 验证脚本scripts/phase0-verify.js + phase0-test-call.js1 天低
P0.H 联调跑一个 mock PM 调用 → 看 todolist 落盘 + SSE 触发2 天—
P0.I git 集成到 LoopControllercreateProject 时 git init + .gitignore 模板;callAgentWithPersistence success 分支加 commitAfterAgent;recoverOnBoot 加 git status 检查(GitVault 已在 P0.0 ⑦ 落盘)1 天中
P0.J git 验证phase0-verify 加:项目初始化后 .git 存在 + 一次 mock commit + tag · listTags0.5 天低
P0 合计—17 天 ≈ 3.5 周—

验收

node scripts/phase0-verify.js
# ✓ All 79 tools registered (34 unique impl)
# ✓ 6 system prompts extracted to system/agents/devloop-*/prompt.md
# ✓ _registry.json contains all 6 devloop-* entries

node scripts/phase0-test-call.js
# ✓ Mock PM call → write_todolist tool invoked
# ✓ data/companies/c-test/projects/p-mock/agent-state/pm-todo.json written
# ✓ SSE agent.todolist event emitted
# ✓ No sandbox violations
关键决策:P0 期间 agent-manager 改动 ≤ 20 行,全是追加可选参数。老调用方(Master Agent / Innovator)不受影响。

P1 · Docs MVP(~1 周 / 5 天)

建议的 demo 需求:「一个 TODO 列表 API + 前端」。比登录系统更小、不涉及 auth/JWT/bcrypt 等坑、30 分钟能端到端跑通。 预期 Architect 拆出 3 个 Unit:todo-be(POST/GET /todos)· todo-fe(Vue 列表)· 可选 todo-db(SQLite schema)。 登录系统留到 P3 当 contract_mismatch 演示用。

新增文件

server/
├── services/
│   └── doc-store.js             # ~140 行
├── routes/
│   └── devloop.js                # 只挂 POST /projects · GET /state,~80 行
└── src/core/
    └── (LoopController 阶段性 stub)

system/agents/
├── devloop-pm.md                 # PM system prompt
├── devloop-architect.md          # Architect system prompt
└── _registry.json                # 追加 6 条(先用 PM + Architect 两条)
        

验收

curl -X POST http://localhost:3010/api/devloop/projects -d @/tmp/req.json
# /tmp/req.json: {"company_id":"c-001","name":"todo-demo","requirement":"做一个 TODO 列表:能新增、列表、Vue 前端"}

# 期望产物(与 data-layout.html 对齐)
data/companies/c-001/projects/p-XXXXXX/
├── project.json                              ✓  # M-1 项目元数据
├── prd/                                      ✓  # M-3 多页 PRD 站点
│   ├── index.html
│   ├── reading-guide.html
│   ├── product/{background,personas,...}.html
│   ├── feature/feature-tree.html
│   ├── flow/user-flows.html
│   └── prototype/proto-*.html
├── sdd/                                      ✓  # M-4 多页 SDD 站点
│   ├── index.html
│   └── mvcp/{model,view,control,process}.html
├── units.json                                ✓  # M-2 含 l2_rounds / l2_budget 初值
├── integration/spec.json                     ✓  # Architect 写
├── agent-state/                              ✓  # M-10 / M-12 Agent 持久化运行态
│   ├── pm.json · pm-todo.json
│   └── architect.json · architect-todo.json
└── history/                                  ✓  # 全部 rev 归档
    ├── prd-rev-001.html
    └── sdd-rev-001.html

P2 · L1 单 Unit(~1.5 周 / 8 天)

新增文件

server/
├── services/
│   └── unit-registry.js          # ~120 行
└── src/core/
    └── loop-controller.js        # runUnit() 单 unit 循环 + retryWithReflection() 内置,~140 行

system/agents/
├── devloop-coder.md
└── devloop-tester.md
关于反思重试:直接在 loop-controller.js 内写一份 retryWithReflection()。不从 evolution-loop.js 抽公共。原因见 arch-mapping · 为什么 P1~P4 不抽公共 retry 函数。

修改文件

  • server/routes/devloop.js · 加 POST /api/devloop/projects/:pid/run(即 sdd-control · C-3);P2 阶段 handler 临时支持 query ?only=<unitId> 调用 loopController.runUnit(pid, unitId) 让单 unit 可测,P3 改造 runProject() 后即移除 only 参数,与 C-3 完全等价
  • server/services/evolution-loop.js · 不动

验收

跑命令后看到:

  • Unit 状态从 pending → coding → testing → failed → coding → testing → passed
  • coder.log 第二条决策明显引用了第一条的失败原因(说明反思生效)
  • 沙箱越权(试图改其他 unit code)被工具层拒绝

P3 · L1 + L2 联动(~3 周 / 15 天)

新增 / 完善

server/src/core/loop-controller.js   # 完整 runProject() 主循环(去掉 P2 的 ?only= 临时入口)

system/agents/
├── devloop-integrator.md
└── devloop-triager.md

server/services/
├── sse-broker.js                # SSE 订阅管理 + stream.log replay,~80 行
└── bug-tracker.js               # 写 bugs.ndjson + GET /bugs 端点支持,~80 行

server/routes/devloop.js             # 加 C-5 GET /api/devloop/projects/:pid/stream + GET /:pid/bugs

# 同步生成的 append-only 产物(与 data-layout.html 对齐)
projects/{pid}/
├── timeline.ndjson                  # M-13 全流程统一日志(loop-controller / agent-bridge 写)
├── bugs.ndjson                      # M-14 跨 run bug 台账(bug-tracker 写)
├── changelog.ndjson                 # M-15 PRD/SDD/units rev 变更流(DocStore 写)
└── stream.log                       # SSE 客户端视角日志(sse-broker 写,7 天滚动)

验收

P3 必须在 4 类 L2 分支(参见 sdd-process · P-2)下都跑通:

① contract_mismatch · 自动 patch SDD

  1. 需求 = 「一个登录系统:邮箱密码 + token,前端展示」
  2. 在 Architect 生成的 SDD 中故意插入矛盾(auth-be 写 401,auth-fe 假设 403)
  3. L1 全部 passed → L2 集成失败
  4. BugTriager 给出 contract_mismatch,confidence ≥ 0.5
  5. Architect 自动 patch SDD(mode=patch)→ sdd.updated 事件
  6. auth-be + auth-fe reset → 重跑 L1(计 1 个 l2_round)
  7. 第二次 L2 通过 → project.shipped

② impl_bug · 不改 SDD,仅 reset

  • SDD 正确,故意把 auth-be 实现写成 password 字段名打错
  • BugTriager 归因 impl_bug → SDD 不动 → 仅 auth-be reset → 重跑 L1(不烧 l2_round 预算)

③ spec_ambiguous / confidence < 0.5 · 升 L3 等待人类

  • 需求中故意留模糊点(如「token 续期策略」未定)
  • Triager 给出 spec_ambiguous 或 confidence < 0.5
  • SSE 收到 human_intervention_needed(reason=low_confidence_triage)→ LoopController 进入 l2_blocked,不自动 patch

④ infra_flake · 直接重跑

  • 模拟 Integrator 进程超时(kill -9)→ 归因 infra_flake → 直接 runL2() 重跑,不烧预算、不动 Unit

⑤ 可观测性产物校验(4 类分支跑完后统一检查)

  • bugs.ndjson 含上述每次 triage 结果(open → fixing → fixed → verified 状态机轨迹)
  • changelog.ndjson 至少 1 条 sdd-rev 变更(来自分支 ①)
  • timeline.ndjson 含完整事件链路(unit.state / integration.result / triage.result / sdd.updated)
  • SSE GET /api/devloop/projects/:pid/stream 用 Last-Event-ID 重连后能 replay 缺失事件

桥梁:极简 Status Page

P3 末尾顺手做一个 ~100 行的纯静态 HTML status page(不上 Vue 路由,单文件放 server/public/devloop-status.html),轮询 GET /api/devloop/projects/:pid/state 渲染 DAG 与 loop 状态条。作用:

  • 给 P3 后期调试时一个可视化窗口(眼看 unit 状态翻飞比 tail 文件直观)
  • 作为 P4 完整 Dashboard 的功能预演 — 提前发现交互问题
  • ~100 行,不算进 P4 工作量

P4 · L3 + UI(~2 周 / 10 天)

新增

web/src/views/
├── DevLoopDashboard.vue         # ~400 行
└── DevLoopOps.vue                # Ops 容器(4 个 tab:Bugs / Loops / Changelog / Progress)

web/src/components/devloop/         # Dashboard 子组件
├── DashboardHeader.vue
├── LoopStatusBar.vue
├── UnitsDAG.vue                 # 复用 PipelineEditor 渲染层
├── LiveAgentStream.vue
├── PrdDiffPanel.vue
└── FeedbackModal.vue

web/src/components/devloop/ops/     # Ops 子页(与 ops-*.html wireframe 对齐)
├── BuglistView.vue              # 渲染 bugs.ndjson(M-14)
├── LoopLogView.vue              # 按 L1/L2/L3 分组 timeline.ndjson
├── ChangelogView.vue            # 渲染 changelog.ndjson(M-15)
└── ProgressView.vue             # 项目实时进度聚合

web/src/router/index.js              # 加 /devloop/:pid 主路由 + /devloop/:pid/ops/{bugs,loops,changelog,progress} 4 个子路由

server/routes/devloop.js             # 加 C-6 POST /:pid/sign-off + C-7 POST /:pid/abandon(参见 sdd-control)

验收

  • 打开 http://localhost:5173/devloop/p-XXXXXX 看到 wireframe 描述的全部 4 个区域
  • 点 「+ NEW REQUIREMENT」发新需求 → PRD diff 区出现新 section(触发 PM incremental 模式)
  • Live 流实时滚动 Agent 输出(断网 5s 后自动重连,用 Last-Event-ID replay)
  • DAG 节点点击展开抽屉,看 unit 的最近 3 次 run
  • 4 个 Ops 子页都能打开:/ops/bugs · /ops/loops · /ops/changelog · /ops/progress
  • 项目交付后点 「Sign Off」按钮 → POST /api/devloop/projects/:pid/sign-off → 状态变 shipped-final,前端拒绝再发新反馈
  • 异常项目点 「Abandon」按钮 → POST /api/devloop/projects/:pid/abandon → 状态变 abandoned,SSE 发 close 帧

成本估算

类型文件数预估行数难度
新增 JS(后端)6 (doc-store · devloop route · unit-registry · loop-controller · sse-broker · bug-tracker)~800中
新增 Agent 模板6 (PM · Architect · Coder · Tester · Integrator · Triager)~900中(参考 agents-pm / agents-architect,单模板 ~150 行 + 多个 few-shot 例子)
新增 Vue 组件12 (Dashboard 1 + Ops 容器 1 + dashboard 子组件 6 + ops 子页 4)~1650中
修改既有3 (server/index.js 挂路由 · _registry.json 加 6 条 · web/src/router/index.js 加 5 条路由)~50低
新增包依赖1 (cheerio)——
合计27~3400 行—

较早前版本(20 文件 / ~1580 行)低估了:① Agent 模板单文件实际 prompt 长度(PM/Architect 当前 PRD 已揭示需 200-300 行 prompt + 数个 few-shot);② Dashboard 子组件粒度(DAG / 抽屉 / diff 渲染单组件就 100+ 行);③ Ops 4 个子页此前未计入。

时间预算

单人 Claude Code 协同开发:P0(17 天) → P1(5 天)→ P2(8 天)→ P3(18 天)→ P4(15 天)= 约 10.5 周。每阶段末 1 天用于演示 + 写迭代 PR 描述。

  • P0(17 天):P0.0 服务层 7 件套(4.5 天,第一个写)+ 工具 + Mock Claude + ACP 桥接 + 提示提取 + GitVault 集成 + 验证脚本。详见上方 P0 表 + tool-registry + acp-bridge + git-versioning
  • P3 +3 天:增加 4 类 L2 分支演示(contract_mismatch / impl_bug / spec_ambiguous / infra_flake)+ 可观测性产物(bugs/changelog/timeline.ndjson)
  • P4 +5 天:Ops 4 个子页(Bugs / Loops / Changelog / Progress)+ sign-off / abandon 端点联调

原估 4 周 → 6 周 → 7 周 → 9.5 周 → 10 周 → 10.5 周(含 P0.0 服务层 + Mock 模式)。每次都是补缺,不是膨胀。参考 成本预算。

「自举」乐趣

P4 完成后,你可以让 LemonBoss DevLoop 系统去开发 LemonBoss 自己的下一个 feature。换句话说:用 v1 的 DevLoop 写 v1.1 的代码。这是验证三层 Loop 是否真的「能自我迭代」的最朴素方式。