arch-components.md 4.32 KB

三个新组件

整套改造的核心只有三个新对象:LoopController、DocStore、UnitRegistry。它们是新增 1500 行代码的主要载体。

① LoopController

路径:server/src/core/loop-controller.js · ~180 行

编排 L1 / L2 / L3 三层状态机。所有 Agent 调用统一从这里出。它本身无状态,所有状态从 UnitRegistry / DocStore 读。

关键方法

方法 调用时机 返回
runProject(pid) 启动 / 续跑项目 `'shipped'
runUnit(unit) L1 内部 UnitResult
onHumanFeedback(pid, req) L3 入口(HTTP) void · 异步触发 runProject
onL2Failure(pid, runId) Integrator 返回 fail 后 void
getState(pid) Dashboard 轮询 ProjectState 快照

主循环骨架

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 面

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 字段。

API 面
module.exports = {
  list(pid),                                  // 全部 unit + 状态快照
  pending(pid), passed(pid), blocked(pid),
  l2GateOpen(pid),                           // 全 passed 且 hash 一致

  // 状态转换
  markCoding(pid, unitId),
  markTesting(pid, unitId),
  pass(pid, unitId, contractHash),
  fail(pid, unitId, reason),
  block(pid, unitId, reason),
  reset(pid, unitIds),                         // L2 修复后

  // diff (用于 L3 增量)
  diffWithSDD(pid),                          // → { added, changed, removed }
};

状态转换合法性

from \ to pending coding testing failed passed blocked
— ✓
— ✓
— ✓ ✓
✓ — ✓
✓ (L2 reset) —
✓ (人类干预) —

非法转换 → 抛异常 + SSE 错误事件,便于排查。

三者协作

外部依赖

包 用途 是否新增
cheerio 解析 / 校验 HTML 新增 (~120KB)
@sinclair/typebox JSON schema 校验 已存在
better-sqlite3 — 已存在(不需要新表)

不引入新数据库;项目状态全部落文件。Dashboard 用 SSE 推送,不需要轮询 DB。