-
把「人类提的一个需求」与「机器执行的一件活」拆成两级。这不是新概念: 27-NAMING §四 早就定义了 goal 1 : task N,graph_runs.goal_id / task_id 两列从 P3 起就一直在写,却没有任何表接得住 —— 本次补上那两张缺席的表。 ## 交付 - goals / tasks 两张表 + CRUD + depends_on 环检测 + ID 生成器 T-{base36}-{4hex}:原格式同毫秒必撞,而 tasks.id 是主键, 「一个 goal 拆 N 条 task」是循环建行,撞了就是 500 - goal / task 全套端点;POST /:cid/tasks 向后兼容(不带 goal_id 自动 建 goal);退役 /api/goals 与 /:cid/goals 两个 OKR 别名(零调用方) - 终态回写 + goal 收敛 + OKR 写一次:钩子挂在唯一漏斗 graph-run-sse.transitionRun 上,而不是枚举路径 —— stopRun 与 「预算耗尽 → blocked」两条最常见的释放路径都不走 settleRun, 枚举一次漏一次。goal 收敛用 CAS 闸门,并行完成的 N 个 task 只有 一个赢家做不可重放的副作用(写 OKR / 唤醒上级) - blocked 在 task/goal 两层都不是终态:它是「挂起等人介入」, 与 completed/failed/cancelled 不同类。否则预算耗尽后加预算恢复、 跑完,两次条件更新静默命中 0 行,最终 run=completed 而 task=blocked/goal=failed/OKR=failed 永久对不上(实跑复现过) - goal 级是唯一汇报出口:删掉 run 级 reportRunOutcome(零其它调用方), 1 goal:1 task 形态下它会把上级 agent 就同一件事唤醒两次 - dispatch 挑第一条可跑的 draft,而不是恒取 seq 最小那条 —— 否则「第 1 条依赖第 2 条」这种合法输入会让 goal 永远下达不了 - 路径缺陷:writeTaskGoalArtifact 不认 GRAPH_RUNS_DIR 而读侧认, 设了 env 就写进 A 处、从 B 处读,describeTask 拿到 null 后静默退回 兜底文案「执行图节点任务」;三处模块加载时快照改为调用时读 - 存量回填脚本(幂等 + --dry-run):不做的话批 1 反而让历史任务 更看不见 —— 正是本批要修的问题的反向放大 ## 过程 三轮多 agent 编排 + 每轮对抗复核,共报出 19 条缺陷(10 条首轮实现的、 4 条第二轮修复引入的、5 条判定为非问题)。全部已修并有用例覆盖。 新增测试 4 个文件,含不变式测试 runs-root-single-holder(凡是声明了 GRAPH_RUNS_DIR 覆盖的模块,该覆盖必须真的被用到)。 全量:116 文件 / 1057 测试全绿。 ## 未做(属批 2-5) task-planning 与 goal 级 org-validator 验收(批 2)、调度器与 run_status='queued'(批 3)、并行(批 4)、两套任务体系统一(批 5)。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> -
system/templates/ 已随 28 号改造整体并入 system/agents/,目录在磁盘和 git 里都已不存在。 但引用还散在各处,其中几处是 agent 运行时真会照着读写的: 本体提示词(读不到就静默降级,不报错) workgraph-planning/agent.md system/templates/base/ ×3、模板库路径 ×1 orggraph-planning/agent.md 同上 ×1 orggraph-planning/tools.md ×1 org-innovator/agent.md 四条产出落点 system/templates/weibo-scraper/train/* skill 代码里的硬编码目标 evolver-youtube-crawler 的 refactor.js / mock_setup.js / evolve.js 共 4 处 innovator-hunt/collect_seed.js —— 这处是真 bug 且已发作过: 写的是裸相对路径 'system/templates/…',相对 cwd 解析,于是在 agent 自己目录下 造出一棵野生嵌套树 system/agents/innovator-hunt/system/templates/… 现在改成由 __dirname 推导,不再依赖 cwd(cwd 已经是深度 3 的任务态目录) 图模板契约(work-graph-templates / org-graph-templates 的 README) CI 防线的三条规则写的还是「在 system/templates/ 下必须有目录」「在 system/templates/_registry.json 里必须有条目」,与实际执行的检查已经对不上 DevLoop PRD(13 份 HTML + 重新生成的 52 份 _spec + build-manifest + search-index) 写的是 system/templates/devloop-pm.md(扁平 .md)。根和形状都错: loop-controller.js:166 实际读的是 system/agents/{agentName}/prompt.md。 按真实形状改,然后跑 spec:extract / extract-manifest / build-search-index 重新生成。 顺带订正两处早于本次改造就已过期的内容: - 「避开 6 个命名冲突 id」这条约束列的 digester / evolver / hunter / innovator 四个 id 根本不存在(早已改名),而它的理由(两个目录下各有一份、内容不同步) 也已随合并消失。约束保留(元 agent 本来就不该进执行流),理由与清单按实际本体重写。 - orggraph-planning/agent.md 里「真相源是 company.json.agents[]」—— 28 号起真相源是 company_agents 表,company.json.agents[] 仅作兼容保留。 刻意不动的三类(改了是净损失): 历史说明 server/ 下解释「原来指向 X、批次 1 并进了 Y」的注释、docs/done/、tasks/ 完成证明 server/tests/ 里断言该目录已不存在的守卫 运行态记录 未跟踪的 workspace/ conversations/ 与 train/ 下的历次训练报告 新增 server/tests/unit/no-stale-templates-path.test.js 守住活定义这一档: 扫 system/ 与 fixtures/ 下被 git 跟踪的文件(跟踪=人工维护的定义, 未跟踪=运行态产物),零例外。带「样本非空」前置断言防 git 失灵时退化成永远通过。 改坏一处实测能精确点名到文件行号。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> -
28 号把本体根从 system/templates/ 搬到 system/agents/,agent-locator 就是 为了当这个路径的唯一持有者而建的。但搬完之后仓库里仍有 13 处自己拼这个路径, 等于 locator 只是多了一份副本、没有真正收敛: server/routes/company.js 9 处(6 个 TEMPLATES_DIR + 3 个 DATA_DIR, 同一文件里只有 1 处用了 locator) server/services/task-service.js 1 处 server/src/core/skill-config-loader.js 1 处 server/src/core/devloop/loop-controller.js 1 处 scripts/extract-agent-prompts.js 1 处 危害不是「不好看」,而是下一次再搬时改 12 处、漏 1 处:漏掉的那处指向一个 不存在的目录,而本仓库读这类路径几乎都包在 fs.existsSync() 守卫里 —— 目录没了不报错,只是静默跳过。这个形状刚在 scripts/demo-harness-company.js 上实测过(base 本体没挂上,demo 跑出来的 agent 没有四段式骨架,脚本照常打印成功)。 局部变量名保留不动(TEMPLATES_DIR / DATA_DIR / SYSTEM_AGENTS_DIR / agentsRoot / OUT_DIR),只把取值改成 locator.AGENTS_ROOT —— 名字是局部别名,无害; 「路径这个事实」则收敛成一处,下次再搬只改 agent-locator.js。 新增 server/tests/unit/agents-root-single-holder.test.js 锁住这条不变式: 扫 server/ packages/ scripts/ 下所有源码,禁止 path.resolve/join 自己拼 「以 ../ 开头、以 system/agents 结尾」的字面量。带「样本非空」前置断言, 防止扫描路径写错时退化成永远通过。改坏一处实测能精确点名到文件行号。 线索来自并行会话(它在准备改 company.js 时发现同一文件里 7 份定义)。 实际比它看到的更多:它只查了 TEMPLATES_DIR,同文件另有 3 个 DATA_DIR、 另外 3 个文件各 1 处。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> -
设计见 docs/done/system-design/28-agent-registry-unification.md。 改造前 Agent 本体散在三处(system/agents/ 11 个、system/templates/ 50 个、 data/companies/{id}/agents/ 17 个),同一个 AgentScaffold 被三个 baseDir 实例化。 后果是同一角色在 N 家公司下有 N 份互不相干的副本,模板更新不会同步; org-coder / org-planner 这类走 hireFromBaseMetaAgent 造出来的本体 legacy_path 指回自己公司目录,永远无法被第二家公司复用。 本次: - G1 单一注册表:system/templates/ 整体并入 system/agents/,base → _base。 7 个同名 id 逐个裁决,被丢弃的一份归档到 docs/_archive/ 而非删除。 source_kind(template/global_agent/company_hired) → origin(builtin/created)。 - G2 运行态下沉:CLI 的 cwd 从本体根改为 system/agents/{aid}/{cid}/{taskId}/。 memory / conversations 落公司态 {aid}/{cid}/,按公司隔离不串。 sessionPool 的 key 含 (companyId, taskId),两家公司调同一 agent 不复用会话。 - G2b 产物不下沉:交付物仍落 data/companies/{cid}/,system/agents/ 只留运行痕迹。 写入边界按链路分叉——graph 节点走节点私有目录(被 indexNodeOutputs 索引), chat 走公司 workspace,同一提示词里不再出现两条互斥指令。 - G3 公司只存引用:data/companies/{id}/agents/ 删除,新增 company_agents 关联表。 不复用 org_graph_nodes——后者是执行流图,work 层本体被雇时不写它,天生覆盖不全。 - G4 缺则创建:本体缺失时从 _base 复制骨架进 system/agents/{id}/, agent-creator 填 agent.md/soul.md 后才从 draft 转 active(哨兵判据, 骨架未填时哨兵仍在,不许被 hire)。产物即刻是全系统可复用的本体。 新增 server/services/agent-locator.js 收编原先散在 6 处的寻址逻辑。 边界守卫(graph-engine)的豁免从「本体根上五个文件名」放宽为整棵 system/agents/: 新本体的骨架本来就要进 git,gitignore 挡不住 ?? system/agents/{newId}/, 旧判据会把一个真正成功的招聘节点判成 boundary_escape fail。 存量迁移见 scripts/migrate-agent-registry.js(幂等,备份到 data/_migration-backup-*)。 真 Claude CLI E2E 已验证:新建公司 → orggraph-planning 自动规划 → 自动招聘 org-planner/org-coder/org-validator 三节点流水线; data/companies/{cid}/agents/ 不存在,company_agents 4 行, system_agents 56→56(零新建私有本体,纯复用),git status 零增量。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> -
用户授权清理 system/templates/ 的过期引用。全仓库核了 34 处, 结论与预期相反:没有该删的死代码,但有两处正在静默失效。 真正坏掉的(demo-harness-company.js): path.join(ROOT, 'system/templates/base/agent.md') → system/agents/_base/ path.join(ROOT, 'system/templates/base/config.json') → system/agents/_base/ 两处都包在 fs.existsSync() 里,所以目录消失后**不报错**,只是 静默跳过 base 本体的挂载 —— demo 跑出来的 agent 没有四段式骨架, 但脚本照常打印成功。又一个静默降级。 顺带:real-pm-smoke.js 的提示文案、migrate-agent-naming.js 里 已失效的遍历项、docs/README.md 的 qa-judge 落点。 CLAUDE.md 目录速查表原来只有 `system/templates/devloop-*/` 一行, 连 system/agents/ 都没列。换成两行并写清三个容易踩的点:目录才是 数据源头(seedAgents 直接扫目录)、_registry.json 只补 benchmark_score、_ 前缀是保留 id 会被跳过。 **刻意不动的**:server/tests/ 下 30 处引用。它们分两类,都得留 —— ① 记录迁移过程的注释;② 断言目录已不存在的守卫 (`expect(git(['ls-files','--','system/templates'])).toBe('')`、 `expect(fs.existsSync(...)).toBe(false)`)。删掉后者等于删掉 「迁移已完成」的证明。legacy_path 那几个测试夹具同理,是历史数据形态。 验证:三个脚本 node --check 通过;改后的四个路径实测存在。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
-
控制台原先只能看引擎的事件轨(stream.log / timeline.ndjson),里面是结构化事件、 自由文本还被截断到 600 字;引擎更是根本不消费流式 chunk(onAcpEvent 只取 session/result 的 usage)。所以 LLM 的逐字输出从来不在它的轨道上。 新端点 GET /api/graph-runs/:id/nodes/:nodeRunId/transcript **惰性读** Claude CLI 自己的会话文件:不进 SSE、不进节点行、不落第二份库 —— 那正是引擎当初决定不存全文的 三条理由要避免的(输出无上限而 getRunState 每次轮询 SELECT * 全量回传 / 产物已有 output_ref 这个唯一真相源 / fail_reason 是选边匹配键不能掺自由文本)。 这里没有推翻那个设计,只是多开一个读取入口。 目录推导与条目规范化抽到 server/services/agent-transcript.js, scripts/tail-agent.js 改为复用它 —— 一份实现两个入口。今天已经修过三次 「两份必须保持一致的实现漂了」,不想制造第四次。 ## 界面上明说的三个前提(不藏) 1. transcript 按 (公司, 角色) 分、**不按节点分**,只能用节点 started_at/completed_at 截时间窗口 —— 近似而非精确对齐,窗口边界原样显示。 2. <env_status>(harness 每轮注入的环境块,几 KB 机器噪音)服务端剥掉, 但**剥了几处如实显示**。静默删内容比留噪音更坏。 3. 默认只看 agent 说的话;喂进去的内容(提示词全文、工具返回)要勾选才出来 —— 提示词里有写入边界与公司上下文,不默认摊开,但可以看。 subgraph 节点不给这个 tab(它自己不调 agent,活在子图里)—— 给了就是个空 tab, 而空 tab 会被读成「没记录」。正在跑的节点靠「刷新」取最新,**不轮询** (整份会话几百 KB,跟着 run 状态轮询太贵)。 ## 三处「看着对、实际错」都有用例钉住 ① listRoles 的目录前缀差一个 '-':path.join 丢掉空的最后一段,切出来的角色名 全带前导 '-'(实测 '-sdd-planning')。我是靠肉眼看输出发现的,所以补回归测试。 ② 路由取本体取错层:本体绑在定义层节点上,graph_run_nodes 只有 def_node_id, 第一版直接读运行时行 → SqliteError: no such column。 ③ 找不到文件时回 ok:false + 期望目录,不回空列表 —— 空列表会被读成「这个 agent 没说过话」,而真相是「我们没找到文件」。 另外测试当场抓到我自己那个诚实机制的漏洞:整条正文都是 env_status 的条目会被剥空, normalize 早返回 null 导致它剥掉的那一处**没计入总数** —— 号称如实回报却少报。 改成 parts 空但剥过东西时仍返回,由 readEntries 先记账再决定入不入列表。 ## 验证 880 全绿(88 文件)。3 处变异精确变红后逐字还原。 运行中的实例上走查过:org-planner-sdd 的原文逐条带时间戳显示, 第一条就是它去读上游 prd.md / contract.json —— R-19 那条链路被 agent 真的用上了。 subgraph 节点(org-planner)确认没有这个 tab。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
-
控制台「运行日志」看不到 LLM 逐字输出,不是坏了,是引擎按设计不存: 1. **引擎根本不消费流式 chunk**:defaultAgentExecutor 的 onAcpEvent 只处理 session/result(累 usage)与 mock/files,文本 chunk 一个字都不接。 2. **事件里的自由文本截断到 600 字**(EVENT_TEXT_MAX),graph-engine.js 那段注释 写了三条理由:完整输出无上限而 getRunState 每次轮询 SELECT * 全量回传; 完整产物已有地址(output_ref)不该有第二个真相源;fail_reason 是选边的匹配键 不能掺自由文本。 所以 stream.log / timeline.ndjson 里只有结构化事件 + 短摘要。 但 Claude CLI 自己把完整会话写在 ~/.claude/projects/<cwd 路径的 / 换成 ->/<sessionId>.jsonl 而 agent 的 cwd 就是 data/companies/<公司>/agents/<角色>,目录名可推。 这个脚本把那份 jsonl 渲染成可读的实时流: node scripts/tail-agent.js <公司> 列出哪些角色有 transcript node scripts/tail-agent.js <公司> <角色> 跟看(增量轮询,Ctrl+C 退出) node scripts/tail-agent.js <公司> <角色> --last 40 只看最后 40 条 只渲染 assistant 的 text 当「LLM 输出」:user 侧的 text 是喂进去的东西(提示词全文、 每轮注入的 <env_status>),跟看时纯噪音 —— 第一版没滤,实测满屏 env_status。 user 侧只留 tool_result(agent 到底读到了什么,这个有用)。 在运行中的实例上验过:mycompany/sdd-planning 正在跑时列表、--last、跟看三种都对, 角色名写错时明确报「目录不存在 + 先跑列表看有哪些」,不静默空跑。 ponytail: projects 目录名按 CLI 现行的「/ → -」规则推导,规则变了会找不到目录 (会明说,不会假装没输出)。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
-
测试 736/736 全绿(68 文件,起点 719/66,净增 17 条,未改任何既有断言)。 W1 · seed 接进启动流程 + 悬空行回收 - server/index.js 与 agent-server.js 均在 listen() 前调 runStartupSeedSafely() (幂等、失败降级记日志、不挡服务启动) - seedTemplates() 此前**没有任何运行时调用方**,只有测试与手动脚本引用, 于是 system/templates/ 新增本体永远进不了 system_agents,而 work_graph_nodes.system_agent_id 是指向该表的外键 - 占位 id 回收:legacy_path 已失效的 company_hired 行改为可被 template 就地转正, 保留行 id 以保外键。此前 seedTemplates 遇占用即 skip,导致污染不可逆: lookupSharedAgentMd 恒 null → hire 静默退回全量拷贝 → 模板改动对已雇公司不生效 - 生产库实查:company_hired 0 行(原 10 条悬空全清)、template 45、 verifyCounts().ok=true、foreign_key_check 空 W2 · 项目根分配(四环闭合) - ensureProjectRoot 复用 path-resolver.allocateProjectRoot(sandbox 模式) - 分配 → 进 agent_call 与 planning 两处提示词 + callAgent metadata → 落 artifacts/project-root.json(wx 独占)→ readProjectRootRecord 读回 - 子 run 经 createRun 继承 root_run_id,跨层共享同一项目根 - 核实 data/companies/ 在 .gitignore 内,故项目根内的合法写入不会被 W3 守卫误报 W3 · 产出边界守卫(部分,文档如实标注) - 真 CLI 是子进程直接写盘,引擎拦不住,守卫只能拒收结果、不能回滚 - 7 条「拦不住」的情形逐条列明;文档自述「在 cwd 隔离做掉之前, 真跑仍应在可丢弃的工作副本里做」 W4 · 修验收 fail-open(性质严重) - benchmark-validator / testdata-validator 的 Step 表教 agent 写 verdict:"fail", 而引擎 FAILING_VERDICTS={attributed,inconclusive} 不含它 → 契约非法的产物 被判 success 放行。失效方向是放行不是拦截 - org-validator 的审计字段 verdict → audit_verdict:它与 work 层判词写同一路径 (nodes/<nodeRunId>/attempt-<n>.json),此前只靠「该节点恰好是 subgraph」 才没被 readNodeProduct 当判词读,属隐患藏在巧合里 - 新增防线 template-verdicts.test.js,从 graph-engine.js 源码取 FAILING_VERDICTS / ATTRIBUTION_REASONS 扫全部模板;经三次变异验证有效 (改回 "fail" / 改回 verdict / 造 "ok" 均变红并报精确行号) 真 CLI 冒烟未执行,两条理由(终验 agent 自行判断,符合任务给的门槛): ① W3 按其自身文档明确「不是沙箱」且要求真跑在可丢弃副本里做,而当前是主仓库、 持有未提交交付物、且有并行 agent 在写,W3 自述的误判项必然触发; ② 断点已零成本静态证明:getAgentConfig 解析裸名只查 system/agents/、 从不查 system/templates/,resolveAgentName 不做按需 hire,实测 prd-planning / sdd-planning / benchmark-validator / testdata-validator / validator-triager / org-validator 全部 throw「Agent not found」。花 $3-8 复现已知断点无意义。 故「做完这四件就能真跑」不成立,真跑挪到 W5/W6 之后。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> -
界面走查(真 server + HTTP + 真 AgentManager,底层 mock 协议)已把 manual 模式全流程点通:org 节点起子图 → 下钻 work graph → 单步 → 第 3 步触发回退(徽标 0/3→1/3、run 级 1/5 双层计数同时可见)→ 归因记录与 remediation_note 完整送达 → 收敛后父节点结算、左栏前移。 mock 侧补两处缺失接线(都是「四环漏一环」,非新功能) - ClaudeCliProtocol._sendMockPrompt 按 agent 类型查 fixture:图执行侧的 agent 名带公司前缀(resolveAgentName 返回 {cid}:{id}),fixture 不该 按公司复制一份。DevLoop 侧名字不含冒号,行为不变 - graph-engine.defaultAgentExecutor 接住 mock/files 事件:此前只有 DevLoop 的 loop-controller 接,图执行侧没接,于是 mock 下 readNodeProduct 永远找不到 attempt-{n}.json,validator 系节点恒 blocked。 写入限制在节点产物目录内,越界丢弃并留痕 新增 5 份 P3 fixture(workgraph-planning / prd-planning / sdd-planning / coder-validator / validator-triager),coder-validator 用 sequence 演示 一次回退。图必须放 chunks 不能只放 result——callAgent 的 output 来自 流式 chunks,session/result 的文本不进 output。 控制台入口:CompanyDashboard 加「🕸️ 执行控制台」按钮(路由早已注册, 此前无任何入口,只能手敲 URL)。 scripts/p3-demo-setup.js:手工测试准备脚本(雇人+写图+起 run),头部 写明它是两个已知缺口的绕行,缺口修好后第 1 步即可删。 _registry.json 补齐 6 条本体登记(brd/prd/sdd-planning、goal-benchmark、 benchmark/testdata-validator)——同轮新增的 template-refs 防线测试正是 因为缺这 6 条而变红,防线抓到了「交付与报告不符」。 文档 - 27-REQ R-18:招聘归 workgraph-planning(方案 a)、停用 mock 改真 CLI - 27-P3B 真实运行前置(新增):11 个工作项分三批,含现状核实 10 条证据 (seedTemplates 无运行时调用方、10 条悬空 company_hired 行、 FAILING_VERDICTS 不含 "fail" 导致验收假放行等) 测试 719/719 全绿(66 文件)。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> -
命名轴是「节点在哪一层图里」,把散落的老 agent 归到它实际所处的层级: innovator → org-innovator type='cxo',是 org graph 层的节点 hunter → innovator-hunt innovator work graph 第 1 阶段 digester → innovator-digest 第 2 阶段(输入是 hunt 产出) evolver → innovator-evolver 第 3 阶段 依据:retrain-pipeline.js 的 stepConfigs 就是按 hunter → digester → evolver 顺序 跑的,行 231 明写 steps: ['re_hunt','re_digest','evolve'] —— 这三个本来就是 innovator 的 work graph 三阶段,只是名字没体现出来。 ■ 迁移(scripts/migrate-agent-naming.js,--dry-run + 幂等可重跑) - 8 个目录(system/agents/ + system/templates/),用 git mv 保留历史 - system_agents 表 4 行的 id 与 legacy_path - 公司实例目录与 company.json.agents[](本次无公司雇过这四个,实际 0 条) ■ 代码引用点(5 处,手工改) - retrain-pipeline.js: stepConfigs 的 agent 字段 ×3、agentToStep 映射的 key ×3、 call_sub_agent 的 evolver 判断 - agent-chat.js: agent 列表过滤里的 innovator - company.js: 模板训练触发的 agentId ■ 刻意不动的三类同形异义(改了会坏) 1. skill 内部子目录名 {skillDir}/hunter/knowhow.md —— 那是 hunt/digest/evolve 三阶段的产物目录约定,与 agent 名同形但不同义。涉及 open-api.js:402、 retrain-pipeline.js:148/374、evolution-loop.js:178、sync-skills.js 的 INTERNAL_DIRS 2. skill 命名空间白名单 —— skill-dir-manager.js 的 CORE_SKILLS、 migrate-trained-skills.js 的 SYSTEM_SKILLS,那里的 'innovator' 指同名 skill 3. conversations/ 与 system/tasklog/ 下的历史记录 —— 运行态数据,不改写历史 evolver-youtube-crawler 按 §3.4 列为待定,迁移脚本按精确目录名匹配,未误伤。 这四个重命名顺带解决了 27 号文档 §七 挂了很久的 6 个命名冲突 id —— 重命名后 system/agents/ 与 system/templates/ 下不再有同名目录(只剩 agent-creator 与 evolver-youtube-crawler 两个,前者是基础设施角色按规则不改名)。 验证:npm run test:unit 693 全绿(64 files);test-company-e2e 114/114; 迁移脚本二次执行 dirs=0 dbRows=0 skipped=8(幂等)。 未触碰另一进程正在进行的 P3 文件(graph-engine.js / graph-run-sse.js / work-graph-db.js / 27-p3-p4-work-graph-console.md / 27-requirement.md)。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
-
代码层: - server/services/goals.js → okr-service.js;GoalsService → OkrService · this.goalsDir → okrDir,目录 goals/ → okr/ · ID 前缀 G- → O-;落盘文件 goal.json → objective.json · updateGoal → updateObjective,_nextGoalId/_saveGoal 等同步改名 · parseNodeId 层级名 ['Goal','Objective','KeyResult','SubTask'] → ['Objective','KeyResult','SubTask','SubTask'](OKR 无 Goal 这一层) - server/routes/goals.js → okr.js;:goalId → :objectiveId - 7 处调用点同步:index.js / agent-server.js / agent-chat.js / company.js / company-heartbeat-service.js / prompt-builder.js / test-company-e2e.js - 前端 OkrDashboard.vue / CompanyDashboard.vue 切到 /api/okr(前后端命名终于一致) - bin/lemon.js 新增 okr create/add-node/list/status 向后兼容(不破坏任何现有调用方): - /api/goals/* 与 /api/company/:cid/goals/* 全部保留为别名,与新路径同时挂载 - task dispatch/report 同时接受 objectiveId(新) 与 goalId(旧),写入时两字段都留 - bin/lemon.js 保留 goal * 命令别名 迁移脚本 scripts/migrate-goals-to-okr.js(npm run okr:migrate): - 目录 data/{,companies/*/}goals/ → okr/;条目 G-xxx → O-xxx - 改写 objective.json 的 id / nodes 的 key / children 数组、_index.json、 progress.json 的 goalId、history.log 文本、system/tasklog/*.json 的 goalId+nodeId - --dry-run 预演;幂等;迁移前自动备份为 *.bak-goals(已加入 .gitignore) - 处理一个反直觉边界:OkrService 构造函数会自动 mkdir 目标目录,"okr/ 已存在" 不等于"已迁移过"——只要服务被 require 过一次就留下空壳。用 isEmptyOkrDir() 区分空壳与真实数据,空壳移除后继续迁移。这个 bug 是在 fixture 上验证时发现的。 - 同样在 fixture 上发现并修掉:nodeId 的值漏改写、tasklog 迁移不幂等 验证:新增 server/tests/unit/okr-service.test.js(7 例,覆盖新命名工作正常 + 迁移纯函数的 ID 改写);全量 npm run test:unit 652 例全绿。 范围说明:NAMING §五 的 benchmark 三分(skill-/agent-/goal-)本轮未动代码—— 该节自身的建议就是存量保持现状、只对新增代码强制前缀,因为 benchmark_runs 等表 服务于线上 Arena 排行榜,改表名/路由是另一次独立迁移。 §二-四 的新 agent id 尚不存在实体,待 P2/P3 实现时按规范创建。 已知遗留(非本次引入):server/scripts/test-company-e2e.js 早已失效——它按 data/{id}/ 找公司,而 company-service 用的是 data/companies/{id}/,在 HEAD 版本 同样全部断言失败。本次只同步了其中的 OKR 命名,未修这个路径问题。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> -
# Conflicts: # system/agents/master/.claude/scheduled_tasks.json
-
Adds server/services/graph-db.js (new data/graph.sqlite: system_agents, org_graph_nodes, org_graph_edges) and graph-seed-service.js, which scans system/agents/, system/templates/, and data/companies/*/company.json into seed rows without touching company-service.js's existing hire/copy path. Real repo data diverged from the design doc's original estimates (8 not 10 global agents; 39 not 34 template dirs; system/agents/ and system/templates/ turn out to share 6 ids describing the "same" agent from two different files) — documented in docs/todo/system-design/27-graph-agent-architecture.md section 7 for P1/P2 to resolve. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
-
First successful real-CLI agent invocation. After REAL.1 (system-prompt injection) + REAL.2 (mtime-diff file detection) wired, the only remaining gate was Claude auth. Once CLAUDE_CODE_OAUTH_TOKEN was added to the project .env, scripts/real-pm-smoke.js completed cleanly: Wire-up status: ✓ process spawn ✓ stream chunks (3) ✓ result text (Claude returned "DONE") ✓ files written (6: prd/index, feature-tree, user-flows, product/overview, assets/shell.{css,js}) ✓ git commit (8cb0493) 5/5 checks passed · elapsed 163s PM output quality (real Claude, not mock): - valid <article data-doc="prd" data-rev="1"> + <section data-rev="1"> structure per system prompt - nav links use correct relative paths across 4 chapters - pid (p-7gwlbl) embedded in HTML metadata - 中文 prose in the requested 克制 voice Spec-deviation confirmed (no MCP tool gateway yet — Claude only has built-in Read/Write/Bash): - ✗ agent-state/pm.json (no update_runtime_state tool) - ✗ agent-state/pm-todo.json (no write_todolist tool) - ✗ history/prd-rev-001.html (no archive_doc tool) - ✗ timeline.ndjson 'prd_drafted' event (no timeline_append tool) - ✓ core PRD site IS produced — sufficient to prove pipeline ──── code ──── - scripts/real-pm-smoke.js — loads root .env via dotenv resolved from server/node_modules (script dir has no node_modules of its own). ──── ambient ──── Files modified by user/linter while real-CLI work was in flight; merged without revert: - server/routes/devloop.js — new GET /:pid/requirements endpoint - server/services/devloop/path-resolver.js — listProjects() includes archived flag + helpers; supports project archive lifecycle - server/services/devloop/git-vault.js — commit() now accepts files[] to scope which paths the commit covers (avoids dragging linked-existing user's unstaged files into chore commits) - server/src/core/devloop/loop-controller.js — createProject uses explicit files:['project.json','timeline.ndjson'] for first chore commit (avoids same issue) - server/tests/devloop/path-resolver.test.js — coverage for archive/ patch/hardDelete helpers - web/src/components/devloop/RequirementListSection.vue (new) - web/src/views/DevLoopNewRequirement.vue (new) - web/src/views/DevLoopDashboard.vue — mounts RequirementListSection - web/src/views/DevLoopProjects.vue — list page polish - web/src/router/index.js — adds /devloop/:pid/requirements/new route - web/src/components/devloop/DashboardHeader.vue — back link tweak Test results: 233/233 vitest pass (was 230 → +3 path-resolver cases). ──── ⚠ SECURITY NOTE ──── .env is currently TRACKED in git (committed in b1a348b) even though .gitignore lists it. Existing committed contents include credentials for DOUBAO / FEISHU / GITHUB / GOOGLE / JWT. The CLAUDE_CODE_OAUTH_TOKEN + AZURE_OPENAI_API_KEY I just added to .env are NOT in this commit — they stay in your working tree only. Recommended follow-up (separate commit): git rm --cached .env git commit -m "chore: stop tracking .env (already gitignored)" And rotate every key that was in the previous committed .env. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> -
Two parallel pieces of plumbing — neither has been exercised end-to-end yet (real CLI gated on `claude /login`; Projects list view served alongside existing pages): ──── real-CLI wire-up (REAL.1 + REAL.2) ──── LemonBoss now has a clean toggle between mock & real Claude CLI: - packages/acp-core/protocol/ClaudeCliProtocol.js * `options.systemPrompt` → `--append-system-prompt <prompt>` so each devloop agent receives its role-specific prompt.md without losing Claude's default tool-use conventions. * `options.maxBudgetUsd` → `--max-budget-usd` (note: only effective in `--print` mode; documented inline). - server/src/core/devloop/loop-controller.js * callAgent now branches on `opts.mock`: - mock (P1-P5 path, untouched): fixture sequence + `mock/files` event - real: read system/templates/{agent}/prompt.md, pass as systemPrompt, snapshot project file mtimes pre-call, diff post-call to compute `files_written` — no fixture, no mock/files needed. * `_snapshotMtimes(root)` helper walks the project tree (skipping .git / node_modules / .cache / .tmp) and returns Map<relPath,mtime>. * timeline event payload now carries `real: true` flag. - scripts/real-pm-smoke.js — minimal real-CLI sanity: spawns claude, injects PM prompt, prints which files were written + git commit sha. Hard timeout 5min. Single agent → expected spend $0.10-0.30 per run when authenticated. Current status: process spawn + system-prompt injection + stream-json flow all verified up to the `Not logged in · Please run /login` gate. Auth is the only remaining blocker for executing the real smoke. ──── project CRUD routes ──── server/routes/devloop.js + server/services/devloop/path-resolver.js add the lifecycle pieces the Projects list view needs: - GET /projects?include_archived=true list w/ archive filter - PATCH /projects/:pid edit name + idea_summary - DELETE /projects/:pid soft delete (archive) - DELETE /projects/:pid?hard=true hard delete (rm -rf sandbox; unregister linked) - POST /projects/:pid/restore un-archive path-resolver exposes matching helpers: listProjects({includeArchived}), patchProjectMeta(pid,patch), hardDeleteProject(pid). ──── UI ──── - web/src/views/DevLoopProjects.vue (320 lines, new) — Projects list - web/src/router/index.js — adds `/devloop` → DevLoopProjects - web/src/components/devloop/DashboardHeader.vue — back-link now points to `/devloop` (project list) instead of `/company`. ──── housekeeping ──── - CLAUDE.md / start.sh — start.sh now boots server/index.js (full route surface incl. /api/devloop) instead of the historical agent-server.js; docs updated to reflect this. ──── tests (+12) ──── - server/tests/devloop/routes-crud.test.js — 12 cases: PATCH validation (4) · soft DELETE + list filter (4) · POST /restore (1) · hard DELETE (2) · GET /projects default behavior (1). Results: - phase0-verify .. phase5-verify: 8+7+7+6+9+9+7 all pass - vitest devloop+acp-core: 230/230 (was 218 → +12) Specs: - docs/prd/newfunction/_spec/arch-acp-bridge.md · Mock Mode - docs/prd/newfunction/_spec/plan-migration.md · "自举乐趣" (real path prep) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> -
Self-bootstrap demo: hits the same HTTP API a human would, asking DevLoop to add a /restart endpoint to itself. End-to-end: 1. POST /projects (PM + Architect scaffold) 2. GET /state 3. POST /run (L1 + L2 → ship) 4. GET /{bugs,timeline,changelog,units/todo-be} 5. POST /feedback (PM incremental → PRD rev 1→2) 6. POST /run (re-ship) 7. POST /sign-off (→ shipped-final) 8. POST /feedback (→ 400 InvalidProjectStatusTransition) Run: node scripts/self-bootstrap.js (artifacts retained for inspection) Output proves the three-layer Loop survives a real curl-equivalent session: 12 git commits auto-generated, 20 timeline events emitted, prd_rev bumped, sdd_rev unchanged (happy path), bugs.ndjson empty (no integration failures), .git contains full agent provenance. For production: drop LEMONBOSS_CLAUDE_MODE=mock — the protocol layer will route to real Claude CLI without any code change in LoopController / routes. Specs: docs/prd/newfunction/_spec/plan-migration.md · "自举乐趣" Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> -
…b-pages + UI endpoints) Completes the §P4 acceptance UI scope that was deferred in commit 0594b1d. Adds the full Vue Dashboard + Ops sub-pages with live SSE stream + auto-reconnect, unit DAG with detail drawer, PRD/SDD diff panel, feedback modal, and 4 ops views (Bugs / Loops / Changelog / Progress). Vue surface (≈1480 lines): - web/src/views/DevLoopDashboard.vue (~110 lines) * 4-region grid: status header / loop bar / units DAG / live stream / PRD diff. Polls /state every 2.5s; opens feedback modal & unit drawer; mounts Sign Off / Abandon controls. - web/src/views/DevLoopOps.vue (~50 lines) — tab container. - web/src/components/devloop/DashboardHeader.vue * Status badge (7 states color-coded), NEW REQUIREMENT button, Sign Off / Abandon buttons (disabled per FSM), Ops nav link. - web/src/components/devloop/LoopStatusBar.vue * 4-phase pipeline (Docs → L1 → L2 → Ship), highlights active phase. - web/src/components/devloop/UnitsDAG.vue * SVG DAG rendered from topological waves; per-unit status color; click → emits select → opens UnitDrawer. - web/src/components/devloop/UnitDrawer.vue * Slide-in panel showing unit metadata + last 3 runs + result summary + coder.log tail (last 1KB). - web/src/components/devloop/LiveAgentStream.vue * EventSource subscriber listening to project.status, unit.state, integration.result, triage.result, sdd.updated, prd.updated, human_intervention_needed, etc. Manual 5s reconnect on disconnect (browser's built-in Last-Event-ID is honored). - web/src/components/devloop/PrdDiffPanel.vue * Reads changelog.ndjson, renders prd_rev / sdd_rev entries with trigger labels. - web/src/components/devloop/FeedbackModal.vue * POSTs /feedback with PM incremental — shows rev bump on success. - web/src/components/devloop/ops/BuglistView.vue * Filterable bug table; status badges; severity / category columns. - web/src/components/devloop/ops/LoopLogView.vue * Timeline grouped by L1 (unit.*) / L2 (integration/triage/sdd/l2_*) / L3 (project.status/shipped/prd.updated/human_intervention) / System (rest). Free-text substring filter. - web/src/components/devloop/ops/ChangelogView.vue * Tabular prd_rev/sdd_rev entries with by/trigger/summary columns. - web/src/components/devloop/ops/ProgressView.vue * 6 metric cards (status, PRD rev, SDD rev, units passed bar, L2 rounds bar, open bugs) + per-unit breakdown table. Router: - web/src/router/index.js — adds: * /devloop/:pid → DevLoopDashboard * /devloop/:pid/ops/:tab(bugs|loops|changelog|progress) → DevLoopOps Backend UI-supporting endpoints (server/routes/devloop.js): - GET /api/devloop/projects/:pid/timeline?limit=N Reads timeline.ndjson, returns last N events reversed. - GET /api/devloop/projects/:pid/changelog Returns full changelog.ndjson entries reversed. - GET /api/devloop/projects/:pid/units/:unitId Returns { unit, runs (last 3 result.json), coder_log_tail }. 404 on unknown unit. Tests (+5 cases): - server/tests/devloop/routes.test.js — new P5 UI endpoints block: * timeline / changelog / units happy-paths * 404 on unknown unit and unknown pid Acceptance: - scripts/phase5-verify.js — 7 steps: ① Vue build artifacts (DevLoopDashboard.js + DevLoopOps.js chunks) ② POST /projects → state returns status + units ③ GET /timeline returns events ④ GET /changelog returns entries ⑤ GET /units/todo-be returns unit + runs ⑥ GET /bugs returns bug list ⑦ SSE /stream delivers ≥1 event after a triggering feedback POST Vue build: - npm run web:build → DevLoopDashboard chunk 15.63 kB, DevLoopOps chunk 9.09 kB, both with co-loaded CSS bundles. Results — all 7 phase gates green: - phase0-verify: 8/8 - phase0-test-call: 7/7 - phase1-verify: 7/7 - phase2-verify: 6/6 - phase3-verify: 9/9 - phase4-verify: 9/9 - phase5-verify: 7/7 - vitest devloop+acp-core: 218/218 (was 213 → +5) Specs: docs/prd/newfunction/_spec/plan-migration.md · P4 L3 + UI Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
-
Implements the §P4 acceptance gate from plan-migration.md, with one scope adjustment confirmed up-front: full Vue Dashboard (~1650 lines) deferred to a future UI phase, replaced by extending the existing P3 static status page with Sign Off / Abandon / Feedback controls. All P4 backend acceptance criteria are scripted (phase4-verify.js). Project status FSM (project.json.status): - server/src/core/devloop/loop-controller.js * draft → running → shipped → shipped-final | abandoned ↓ ↓ l2_blocked (feedback flips back to running) l2_exhausted * `_setProjectStatus` validates transitions via STATUS_TRANSITIONS, emits SSE `project.status`, writes timeline event. * createProject seeds status=draft; runDocsPhase end → running; runProject(shipped) → shipped; all dead-end branches (l2_blocked, l2_exhausted) also propagate to status via _safeSetStatus. L3 helpers: - signOff(pid, opts) — requires status=shipped → shipped-final; commits a `chore: sign-off` git entry; rejects other source states with InvalidProjectStatusTransition. - abandon(pid, opts) — any non-terminal → abandoned; commits + calls sseBroker.close(pid) to send SSE close frame to subscribers. - submitFeedback(pid, text, opts) — rejects in shipped-final/abandoned; invokes PM in incremental mode; on prd_rev bump writes changelog.ndjson prd_rev entry + emits prd.updated SSE; if prior status was shipped, flips back to running so next runProject can rebuild. PM incremental mock fixture: - fixtures/devloop-mock/devloop-pm.json — converted to sequence form: * sequence[0] (init) — original P1 fixture (PRD rev=1, 14 files). * sequence[1] (incremental) — appends a new section to prd/feature/feature-tree.html, bumps article data-rev to 2, writes history/prd-rev-002.html. Baseline happy-path Integrator: - fixtures/devloop-mock/devloop-integrator.json — single-shot pass. Makes vanilla runProject ship without a scenario override. P4 happy-path scenario: - fixtures/devloop-mock-scenarios/happy_path/devloop-architect.json — single-unit (todo-be only) Architect so end-to-end ship works with the baseline Coder/Tester (which only know todo-be paths). Routes: - server/routes/devloop.js: * POST /projects/:pid/sign-off — 400 InvalidProjectStatusTransition when status != 'shipped'; 200 returns { status }. * POST /projects/:pid/abandon — body { by?, reason?, note? }; 400 on terminal state; 200 returns { status: 'abandoned' }. * POST /projects/:pid/feedback — body { text (req), by?, mockFixtureDir? }; 400 on missing text or shipped-final/abandoned; 200 returns { prd_rev_before, prd_rev_after, status }. * POST /projects: now accepts optional `mockFixtureDir` so the same fixture dir threads through both the create call and later feedback (keeps mock-sequence counters aligned). Static status page (replaces full Vue Dashboard for P4): - server/public/devloop-status.html — adds: * Status badge in header (color-coded per status). * Sign Off / Abandon control buttons (disabled per current state). * Feedback textarea + Submit button → POST /feedback. * Buttons reflect FSM (signoff only when shipped; abandon/feedback locked at terminal states). Acceptance: - scripts/phase4-verify.js — 9 steps, full HTTP path: ① POST /projects → running ② POST /run → shipped ③ POST /feedback → PRD rev 1→2 + running (+ changelog entry) ④ POST /run again → shipped ⑤ POST /sign-off → shipped-final ⑥ POST /feedback (after sign-off) → 400 ⑦ POST /sign-off (after sign-off) → 400 ⑧ second project: POST /abandon → abandoned ⑨ POST /abandon (after abandon) → 400 Tests (+19 cases): - server/tests/devloop/p4-l3-feedback.test.js * 14 FSM cases covering happy path + abandon path + signOff pre-conditions + empty feedback rejection. * 5 route cases via fetch on ephemeral express app. Results: - phase0-verify: 8/8 - phase0-test-call: 7/7 - phase1-verify: 7/7 - phase2-verify: 6/6 - phase3-verify: 9/9 - phase4-verify: 9/9 - vitest devloop+acp-core: 213/213 (was 194 → +19) Spec deviations explicit: - Full Vue DevLoopDashboard.vue + Ops 4 sub-pages NOT implemented; static status page handles the demoable surface area instead. - All backend endpoints from §P4 (sign-off, abandon, feedback) are complete and tested. Specs: docs/prd/newfunction/_spec/plan-migration.md · P4 L3 + UI Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> -
Implements the §P3 acceptance gate from plan-migration.md: a single POST /api/devloop/projects/:pid/run drives the full project from L1 through L2 with 4 distinct BugTriager branches, observability via SSE stream + bugs.ndjson + changelog.ndjson, and a tiny static status page. Mock protocol — fallback dir: - packages/acp-core/protocol/ClaudeCliProtocol.js * New options.mockFallbackDir: when scenario dir lacks a per-agent fixture, fall back to the baseline fixtures/devloop-mock/. Enables scenario dirs to override only the agents that differ (Integrator + Triager + sometimes Architect). Scenario fixtures — 4 L2 branches: - fixtures/devloop-mock-scenarios/contract_mismatch/ * Architect: sequence[init, patch] — patch bumps sdd_rev → 2, units.json l2_rounds → 1, marks todo-be back to pending. * Integrator: sequence[fail (500 vs 201), pass]. * Triager: contract_mismatch confidence 0.85 with proposed_sdd_patch. - fixtures/devloop-mock-scenarios/impl_bug/ * Integrator: sequence[fail (ReferenceError), pass]. * Triager: impl_bug confidence 0.78 affected=[todo-be], proposed=null. - fixtures/devloop-mock-scenarios/spec_ambiguous/ * Triager: confidence 0.4 → LoopController emits human_intervention. - fixtures/devloop-mock-scenarios/infra_flake/ * Integrator: sequence[crashed (EADDRINUSE), pass]. * Triager: infra_flake confidence 0.95 affected=[]. - Each scenario also includes a 1-unit (todo-be) Architect.init fixture so baseline Coder/Tester (todo-be) can drive L1. LoopController: - server/src/core/devloop/loop-controller.js — adds: * runProject(pid, opts) — wave-scheduled L1 via _groupUnitsByWave, runIntegrator (devloop-integrator), runTriager (devloop-triager), then branch dispatch: - contract_mismatch+conf≥0.5 → Architect(patch) writes new units.json (already pending, l2_rounds++); emits sdd.updated + changelog sdd_rev entry; loop back to L1. - impl_bug+conf≥0.5 → unitRegistry.reset(affected); loop, no budget burn. - spec_ambiguous OR conf<0.5 → emit human_intervention_needed SSE, exit l2_blocked. - infra_flake → loop directly (no reset, no budget burn). * runDocsPhase + runUnit + callAgent all thread opts.mockFixtureDir through to the protocol. * Auto-attaches sseBroker to unit-registry and bug-tracker on module load — every FSM transition + bug op fires an SSE event. * bug_open at integration failure, bug_transition → fixed when subsequent L2 round passes. Routes: - server/routes/devloop.js: * POST /projects/:pid/run now defaults to full runProject; ?only=<id> still drills into single-unit runUnit (P2 compatibility). * GET /projects/:pid/stream — SSE with Last-Event-ID replay. * GET /projects/:pid/bugs?status=&unit_id=&severity= — bug list. - server/index.js + agent-server.js mount /public for static assets. Static status page: - server/public/devloop-status.html (~100 lines) — pure HTML, polls GET /state every 2s, renders unit DAG with status pills + timeline tail. URL ?pid= or input box. Acceptance: - scripts/phase3-verify.js — 9 steps across 4 scenarios + observability: ① contract_mismatch ships at sdd_rev=2 l2_rounds=1, sdd.updated SSE, changelog sdd_rev entry, bug open → fixed. ② impl_bug ships, sdd_rev=1, l2_rounds=0 (no budget burn). ③ spec_ambiguous → l2_blocked + human_intervention_needed SSE. ④ infra_flake ships, rerun_integrator action, l2_rounds=0. ⑤ Observability: timeline/bugs/changelog/stream.log present. ⑥ SSE replay from Last-Event-ID returns ≥2 historical events. Tests (+13 cases): - server/tests/devloop/run-project.test.js (11) — 4 scenarios end to end + SSE event capture. - server/tests/devloop/routes.test.js (+2) — full-project mode + bugs 404. Updated P2 ?only stub test → full-project 404 on unknown pid. Results: - phase0-verify: 8/8 - phase0-test-call: 7/7 - phase1-verify: 7/7 - phase2-verify: 6/6 - phase3-verify: 9/9 - vitest devloop+acp-core: 194/194 (was 181 → +13) Specs: - docs/prd/newfunction/_spec/plan-migration.md · P3 验收 - docs/prd/newfunction/_spec/loops-l2.md (failure attribution + budget) - docs/prd/newfunction/_spec/agents-integrator.md - docs/prd/newfunction/_spec/agents-triager.md Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> -
Implements the §P2 acceptance gate from plan-migration.md: a single POST /api/devloop/projects/:pid/run?only=todo-be drives the L1 inner loop (Coder → Tester → fail → Coder → Tester → pass), with the second Coder pass demonstrably reflecting on the first failure. Mock protocol — stateful sequences: - packages/acp-core/protocol/ClaudeCliProtocol.js * Mock fixtures now support `sequence: [{chunks,result,files}, ...]`. Each protocol.connect() + sendPrompt() consumes the next variant; sticks on the last entry after exhausted. * Static `ClaudeCliProtocol.resetMockState()` clears counters between test runs. Fixtures: - fixtures/devloop-mock/devloop-architect.json — units.json now has status:pending + retries:0 + retry_budget per unit, plus units/{todo-be,todo-db,todo-fe}/spec.json so Tester has acceptance criteria to read. - fixtures/devloop-mock/devloop-coder.json — sequence: implement (with intentional missing 400 branch) → retry (reflective fix, coder.log attempt:2 has last_failure/last_cause/this_fix/rationale). - fixtures/devloop-mock/devloop-tester.json — sequence: fail (1/3 failure with hint pointing at missing body validation) → pass (3/3). LoopController: - server/src/core/devloop/loop-controller.js — adds: * runUnit(pid, unitId, opts) — drives the L1 loop via unit-registry FSM (pending → coding → testing → failed → coding → testing → passed/blocked). Calls Coder then Tester per attempt; on failure, builds a retry context summarizing prior coder.log + tester failures and feeds it into the next Coder prompt. * _buildRetryContext + _findLatestTesterResult helpers. * callAgent now rewrites units.json.project_id to the real pid after mock writes (so unit-registry validation passes). Route: - server/routes/devloop.js — adds POST /projects/:pid/run?only=<unitId>. Without ?only, returns 501 (full project run lands in P3). Acceptance: - scripts/phase2-verify.js — 6 steps: 1. POST /projects (PM + Architect) 2. POST /run?only=todo-be returns ok=true, attempts=2, final=passed 3. FSM trail matches expected 6-step transition sequence 4. coder.log second entry has all 4 reflection fields 5. runs/ has ≥2 result.json with first.ok=false, last.ok=true 6. sandbox cross-unit + prd writes blocked by ToolSandboxError Tests (5 new cases): - server/tests/devloop/run-unit.test.js (4) — FSM trail, coder.log reflection, runs/ result chain, sandbox enforcement. - server/tests/devloop/routes.test.js (+3) — POST /run validation, full P2 loop, 404 on unknown unit. Results: - phase0-verify: 8/8 - phase0-test-call: 7/7 - phase1-verify: 7/7 - phase2-verify: 6/6 - vitest devloop+acp-core: 181/181 (was 174 → +7) Specs: - docs/prd/newfunction/_spec/plan-migration.md · P2 验收 - docs/prd/newfunction/_spec/loops-l1.md (retryWithReflection) - docs/prd/newfunction/_spec/agents-coder.md - docs/prd/newfunction/_spec/agents-tester.md Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> -
Implements the §P1 acceptance gate from plan-migration.md: a single POST /api/devloop/projects produces a runnable todo-demo project with multi-page PRD/SDD sites, units.json, integration spec, agent-state, and history snapshots — all via mock agents (no real Claude CLI cost). Code additions: - packages/acp-core/protocol/ClaudeCliProtocol.js * mock mode now emits an extra `mock/files` acp_event when the fixture contains a files[] array. LoopController applies it to the project root, letting mock agents produce real outputs. - server/src/core/devloop/loop-controller.js (now ~280 lines) * callAgent(pid, agentName, prompt, opts) — single-agent invocation: reads system/templates/{agent}/prompt.md, runs mock protocol, applies fixture files[], timeline-logs, auto-commits. * runDocsPhase(pid, requirement) — orchestrates PM → Architect with `docs.complete` timeline marker. * getProjectState(pid) — returns project.json + units + prd_rev/sdd_rev + timeline tail for the GET /state endpoint. - server/routes/devloop.js (new) * POST /api/devloop/projects — createProject + runDocsPhase * GET /api/devloop/projects * GET /api/devloop/projects/:pid/state - server/index.js / server/agent-server.js — mount /api/devloop. Mock fixtures (drive the full acceptance file tree): - fixtures/devloop-mock/devloop-pm.json * 14 files: prd/{index,reading-guide,product/*,feature/*,flow/*,prototype/*}.html, prd/assets/{shell.css,shell.js,search-index.json}, agent-state/{pm.json,pm-todo.json}, history/prd-rev-001.html. - fixtures/devloop-mock/devloop-architect.json * 13 files: sdd/{index,mvcp/*}.html, sdd/assets/*, units.json (3 units, DAG), integration/spec.json, agent-state/{architect.json,architect-todo.json}, history/sdd-rev-001.html. Acceptance: - scripts/phase1-verify.js — spins ephemeral express app, POSTs the todo-demo project, asserts 23 expected paths exist + 3 units with l2_rounds/l2_budget + git ≥4 commits + timeline events. Tests (12 new cases): - server/tests/devloop/loop-controller.test.js (7) — callAgent + runDocsPhase + state. - server/tests/devloop/routes.test.js (5) — POST validation, full POST, GET state, 404 on unknown pid. Results: - phase0-verify: 8/8 - phase0-test-call: 7/7 - phase1-verify: 7/7 - vitest devloop+acp-core: 174/174 (was 162 → +12) Specs: docs/prd/newfunction/_spec/plan-migration.md · P1 Docs MVP Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> -
Final P0 deliverables to make the system bootable in mock mode and pass `scripts/phase0-verify.js` + `scripts/phase0-test-call.js` end-to-end. ClaudeCliProtocol (mock mode): - LEMONBOSS_CLAUDE_MODE=mock or { mock: true } in constructor enables mock mode. connect() becomes a no-op; sendPrompt reads fixtures from fixtures/devloop-mock/{agentName}.json and emits scripted session_update chunks + session/result(mock=true). Falls back to default.json. Agent registry: - 6 entries added to system/templates/_registry.json (devloop-pm, devloop-architect, devloop-coder, devloop-tester, devloop-integrator, devloop-triager). - Per-agent dirs system/templates/devloop-{role}/ with: * prompt.md — auto-extracted from agents-{role}.html §2.2 * config.json — cli.toolPolicy.allowedTools + sandbox.writeAllowList Tooling: - scripts/extract-agent-prompts.js — regex-extracts §2.2 system prompts from 6 agent HTML pages to system/templates/devloop-{role}/prompt.md. - server/src/tools/devloop/index.js — central export (tools Map, bashHooks, dispatch). - server/src/core/devloop/loop-controller.js (P0 skeleton) — exposes createProject (sandbox alloc + git init + first commit + timeline) and commitAfterAgent (per-agent kind-routed git commit + timeline event). Mock fixtures: - fixtures/devloop-mock/default.json + devloop-pm.json Acceptance scripts: - scripts/phase0-verify.js — 8 static checks (35 tools loadable, 6 agents registered, prompt+config wired, bash guard exported, services require, fixtures present, git-vault interface, loop-controller). - scripts/phase0-test-call.js — 7 end-to-end steps under mock mode (createProject → CLI connect → sendPrompt chunks → no-op commit returns null → real write commits → git log ≥2 → timeline has both events). vitest.config.js: include packages/**/*.test.js so the mock smoke test runs in the suite. Results: - 162/162 devloop + acp-core tests pass (up from 159). - phase0-verify: 8/8. - phase0-test-call: 7/7. Specs: docs/prd/newfunction/_spec/plan-migration.md · Quick-Start step 7 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> -
The 50-page PRD HTML totals ~520KB; loading it all costs Claude ~222K tokens just for context. This adds a token-efficient sibling layer: - scripts/extract-spec.js → npm run spec:extract / spec:check Walks docs/prd/newfunction/*.html and produces stripped MD into _spec/. Strategy varies per page (full-extract for SDD/process/data, shell-strip for agents to keep long system prompts intact). Result: 327.9KB MD (~84K tokens) — 38% of full load, saves ~138K tokens for every Agent invocation that reads the spec. - scripts/git-hooks/pre-commit + scripts/install-hooks.sh Pre-commit guard: when any docs/prd/newfunction/*.html changes, the hook checks the corresponding _spec/*.md is up to date; fails commit if stale, telling user to `npm run spec:extract`. Auto-installed via package.json `prepare` script on `npm install`. - docs/prd/newfunction/_spec/ (51 .md files + CONVENTIONS.md) Machine-readable mirror of HTML. Used by: - Coder/Architect/Tester agents when reading spec at runtime - External Claude Code sessions doing reproducibility - CI checks (npm run spec:check) NOT hand-edited; regenerated from HTML by extract-spec.js. - CLAUDE.md: 1-line note directing future agents to read _spec/*.md preferentially, fall back to *.html only for wireframes/SVG/full human-readable context. This is the user's pre-existing scaffolding that the previous commits hadn't pulled in yet. Now tracked + enforced by hook. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
-
DevLoop: a 3-layer Loop (L1 Unit / L2 Integration / L3 Human) auto-development system that takes a one-line human requirement and produces multi-page HTML PRD + SDD + units.json + full backend/frontend code via 6 specialized agents. This commit adds the complete documentation set: 50 HTML pages organized in 8 sections (3-level menu + global search): - 01 Overview · 02 PRD · 03 Design (loops + 6 agents) - 04 SDD (MVCP × 4) · 05 Prototype · 06 Architecture - 07 API · 08 Ops · 09 Plan Key specs: - 6 agent skills (PM/Architect/Coder/Tester/Integrator/BugTriager), each with full system prompt, 13-17 tool signatures, 3 E2E samples, helper source code - 52 MVCP definitions, 100% machine-extractable via data-* anchors - 79 tool signatures with implementation guidance (arch-tool-registry) - ACP bridge spec (arch-acp-bridge): how LoopController calls into LemonBoss agent-manager without breaking existing Master/Innovator flows - 5-phase plan P0→P4 (~9.5 weeks): P0 bootstrap (tool impl + ACP bridge), P1 docs MVP, P2 single unit L1, P3 L1+L2 loop, P4 L3 feedback + UI - Persistence layer: AgentState (M-10), Memory (M-11), Todolist (M-12), Timeline (M-13), Bugs (M-14), Changelog (M-15) + crash recovery (P-8) - Cost & concurrency budgets (plan-cost-concurrency) - Code lifecycle: stay-in-sandbox v1 + export API + future GitHub PR (v2) Plus supporting scripts (zero deps, regex-based): - scripts/extract-manifest.js: extracts MVCP defs to build-manifest.json, used to verify all definitions have path + shape (currently 100%) - scripts/build-search-index.js: builds assets/search-index.json (183KB), enables Ctrl+K global search across all 50 pages The PRD itself is meta-executable: a future Claude Code session reading plan-reproducibility.html can rebuild the entire DevLoop runtime from the docs alone. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
-
- Moved data/system/ → system/ (agents, templates, skills, data, workspace) - Updated all server route/service path references - Updated all script path references - Updated all documentation references - Restructured .gitignore for cleaner system/ vs data/ boundary system/ = platform-shared assets (system agents, template library) data/ = tenant-specific company instance data
-
scripts/demo-harness-company.js creates a company, hires a Base Agent worker, and simulates the full RPEV lifecycle with real API calls: - Company creation (skipBootstrap) - Agent hiring with base template - meta-research initial skill mount - 3 transition API calls (plan → execute → verify) - Hot Swap verification at each stage - Artifact production validation
-
scripts/test-harness.js covers: - Meta-Skill file existence & content - Base Agent template completeness - Hot Swap simulation - Context Flush simulation - _lessons.md injection - billing.log format - GoalsService new statuses - CLI registration - Transition API route verification - Optional --online mode for live API tests
-
- Implement OKR GoalsService with hierarchical node tracking - Add /api/goals routes and integrate with dispatch/report APIs - Create Innovator agent with Hunt→Digest→Evolving pipeline - Create Hunter (l3-hunt), Digester (l2-digest), Evolver (evolving) meta agents - Copy L1/L2 dependency skills into each agent's .claude/skills/ - Fix buildSystemPrompt to scan ALL skill subdirectories (critical) - Fix agent list sorting: master pinned top, rest by lastActiveAt - Rename master-001→master, innovator-001→innovator - Establish meta agent output convention: write to target agent dir - Add CXO agent base class for management agents - Update CEO agent with delegation-first management model
-
- Agent as Micro-Container: each agent lives in data/agents/{id}/ with full encapsulation - Persona vs Capability split: agent.md (identity) + .claude/skills/main_skill/SKILL.md (workflow) - Conversations co-located: data/agents/{id}/conversations/ replaces global dir - Meta Skills renamed: meta_hunt, meta_digest, meta_creator, meta_evolving, meta_benchmark, meta_research - Dynamic Hot-Reload: AgentManager.getAgentConfig() falls back to filesystem scan - Parallel Sub-Agent orchestration via Promise.all with multi-terminal UI - Removed SQLite dependency, global skills/ directory, and legacy conversations/ - Full architecture docs: 18-local-filesystem-first-agent-encapsulation.md