# 三个新组件 > 整套改造的核心只有三个新对象:**LoopController**、**DocStore**、**UnitRegistry**。它们是新增 1500 行代码的主要载体。 ## ① LoopController 路径:`server/src/core/loop-controller.js` · ~180 行 编排 L1 / L2 / L3 三层状态机。所有 Agent 调用统一从这里出。它本身无状态,所有状态从 UnitRegistry / DocStore 读。 ### 关键方法 | 方法 | 调用时机 | 返回 | | --- | --- | --- | | `runProject(pid)` | 启动 / 续跑项目 | `'shipped' | 'blocked' | 'l2_exhausted'` | | `runUnit(unit)` | L1 内部 | UnitResult | | `onHumanFeedback(pid, req)` | L3 入口(HTTP) | void · 异步触发 runProject | | `onL2Failure(pid, runId)` | Integrator 返回 fail 后 | void | | `getState(pid)` | Dashboard 轮询 | ProjectState 快照 | ### 主循环骨架 ```js async function runProject(pid) { while (true) { // L1: pending → coding → testing → passed const waves = scheduler.getExecutionGroups(unitRegistry.pending(pid)); for (const w of waves) await Promise.all(w.map(runUnit)); if (unitRegistry.anyBlocked(pid)) return 'blocked'; // L2 gate if (!l2GateOpen(pid)) continue; const r = await agentManager.callAgent('integrator', { pid }); if (r.ok) return 'shipped'; // L2 failed → triage → patch SDD → reset units const tri = await agentManager.callAgent('bug-triager', r.failure); if (tri.confidence < 0.5) { sse.emit(pid, 'human_intervention_needed', tri); return 'l2_blocked'; } await agentManager.callAgent('architect', { mode: 'patch', patch: tri.proposed_sdd_patch }); unitRegistry.reset(pid, tri.affected_units); if (project.l2Rounds++ >= 3) return 'l2_exhausted'; } } ``` ## ② DocStore 路径:`server/services/doc-store.js` · ~140 行 负责 prd.html / sdd.html / units.json / integration/spec.json 的读写、归档、校验。所有写操作走它,没有 Agent 能直接 Write 这些文件。 ### API 面 ```js module.exports = { // 读 readPRD(pid), readSDD(pid), readUnits(pid), readIntegrationSpec(pid), // 写(自动归档旧版) writePRD(pid, html), writeSDD(pid, html), writeUnits(pid, json), writeIntegrationSpec(pid, json), // 校验 validateHTML(html), // 用 cheerio + 必含 section validateUnitsSchema(json), // 用 typebox // diff / 归档 diffPRD(pid, fromRev, toRev), archive(pid, kind, oldHtml), // → history/{kind}-rev-N.html }; ``` ### HTML 校验规则 | 文档 | 必含元素 | 校验工具 | | --- | --- | --- | | prd.html | 顶级 ` `,至少 1 ` ` | cheerio | | sdd.html | 每 ` ` 含 ` ### ` + ` ` | cheerio | | units.json | schema 校验 + DAG 无环 | typebox + 拓扑排序 | | integration/spec.json | 每 case 的 involves 都在 units.json 中存在 | 自写 | ## ③ UnitRegistry
路径:`server/services/unit-registry.js` · ~120 行 Unit 状态机的 source of truth。状态转换都走它,不允许 Agent 自己改 units.json 的 status 字段。