• 只做了这一件事,没有跟着做「dream 改成 org/work graph 来跑」——两者被
    单独评估过:org/work graph 是单公司作用域(org graph=公司级 workflow,
    work graph=公司内某任务的节点图),dream 却是跨公司扫描,套进去要么破坏
    作用域假设要么得新开图类型;且 graph 引擎自带的验收机制(goal-contract
    benchmark/test-script)判的是「产物过没过验收脚本」,对「经验提炼得对
    不对」这种自由文本判断没有对应机制——不管套不套 graph 都得单独设计
    rubric,是同一件事。用户明确只要 REST/控制台这一半。
    
    ## REST(server/routes/dream.js,挂 /api/dream)
    
    路由本身没有新业务逻辑,全部委托给已测过的 dream-service.js:
    GET /agents(总览)、GET /agents/:id(详情,含定义文件可写性 + 经验
    审计)、POST /agents/:id/run(手动跑一次,dryRun 只看有没有新原料不
    起 LLM)、POST /sweep + GET /sweep/status(全量扫描后台跑 + 轮询,内存
    态并发锁防止连点两下)。
    
    ## 控制台(web/src/views/DreamConsole.vue,路由 /dream)
    
    一个表格 + 两个弹窗:本体列表(详情/跑一次/dry-run)+ 全量扫描按钮
    (15 秒轮询状态)。导航栏加 🌙 Dream 入口。
    
    ## 验证
    
    server/tests/unit/dream-routes.test.js 4 例,monkeypatch 掉
    dream-service 导出对象上的六个函数(不走真文件系统,不误扫真仓库
    76 个本体),只验路由层自己的逻辑:端点接线、sweep 并发锁状态机。
    
    真起服务器打了真数据:GET /agents/innovator-evolver 正确报
    SKILL.md 因没进 git 历史而不可写、经验审计吐出上次真跑沉淀的 4 条
    经验及原文;dry-run 正确报 no-new-material,没多花一次 LLM 调用。
    浏览器里走了一遍列表→详情→dry-run,与直接打 API 结果一致。
    
    955 个单测全绿。
    
    文档:29-dream-design.md §5.7 记录实现与「为什么不做 graph 化」的
    理由;28-followups.md / docs/README.md 同步更新 dream 现状。
    
    Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
    yibo authored
     
    Browse File »

  • ## 定时:每日一次,挂在 DISABLE_BACKGROUND_AGENTS 早退之后
    
    dreamSweep 串行扫所有本体,**不并发**:每轮可能起两次 LLM 调用,
    几十个本体并发 = 同时拉起几十个 claude 子进程 —— 这个代价本仓库付过
    (2h43m 漏出 82 个进程 / 17.5 GB,28-followups §五 第五条)。慢一点没有代价。
    
    空转保护在 dreamOnce 里,所以「76 个本体全扫一遍」的实际成本是 76 次目录读。
    定时器 unref —— 少了它,短命进程会被 24 小时的 timer 吊住不退出。
    只挂定时**不立刻跑一轮**:启动那刻跑没有额外收益,反而让每次重启都烧一遍。
    
    一个本体抛异常不拖垮整轮,但**必须留下是谁抛的**,否则现场只看到「今天没沉淀」,
    查不出是没原料还是一直在抛。
    
    ## 定义文件:受管区块 + 三道闸门
    
    形状是一对 `<!-- dream:begin/end -->` 之间的**受管区块**,区块外一个字节不碰。
    自由追加会让「哪些是人写的、哪些是 dream 写的」几轮之后再也分不开,
    而分不开就没法分别回滚。区块整体重写还顺带**幂等** —— 同一批经验重复跑不会越写越长。
    
    三道闸门,缺一不写:
    ① definition-write-gate:当前内容必须已在 git 历史里(你定的前置条件);
    ② **agent.md 的前 2000 字符必须仍然自足** —— 规划 agent 只看这一段
       (graph-engine.js:915 的「角色定义摘录」),改了等于悄悄换掉它读到的画像;
    ③ 写完复核毕业闸门,不过就**立刻还原** —— agent.md 写坏会让本体雇不进任何公司。
    
    任何一道不过:不写,并把原因逐个文件返回(`definitions[]`)。**不写不该是静默的。**
    
    ## 测试上又纠了自己一次
    
    三条新用例第一版是「在测试里比对形状」而不是真调 —— 和上一轮同一个毛病。
    改成对**真被 git 跟踪且干净**的本体(dream-screener)走真路径:
    真写、验区块外字节不变 / 幂等 / 毕业闸门仍过,finally 还原并断言还原干净。
    agent.md 那条同理真调,验「不写 + 理由点名前 2000 字符 + 一个字节都没动」。
    
    dreamSweep 加 agents 参数,让错误隔离那条能真调而不是真扫 76 个本体。
    
    全量:144 文件 / 1330 测试全绿,仓库干净。
    
    Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
    yibo authored
     
    Browse File »

  • 起因是「全量测试偶发挂一条」。查下来既不是回归、也不是那 45 个孤儿进程(它们 CPU 早归零、
    不再写任何东西),而是**还活着的心跳在测试扫描 system/agents/ 的同时往里建目录**:
    
        locator.taskDir() 的落点是 system/agents/<agent>/<companyId>/<taskId>,
        运行态目录落在本体目录里属既定设计;但心跳每 5 分钟建一个新的
        (cto/_global/ 已 263 个子项且在涨),于是扫描 system/agents/ 的守卫测试
        (no-dead-path-references 那一类)会撞上瞬时竞态:列到了目录名,进去时那一层还没写完。
    
    症状是偶发假失败、重跑就好 —— 这类最费人,因为第一反应总是去怀疑自己刚改的代码。
    
    改法:server/index.js 启动的那个 setTimeout 块里,恰好装着全部「会自己起 agent 的东西」
    (两处中断恢复 + 任务队列扫描 + 两路心跳),所以一条早退就够,不必在五个地方各加一个判断。
    
        DISABLE_BACKGROUND_AGENTS=1 bash start.sh
    
    实测:127 文件 / 1226 用例全绿,跑前跑后 cto/_global 子项数都是 263。
    
    **验证它生效不能只看日志里的 ⏸** —— 那只证明代码走到了早退。硬判据是目录数前后相等,
    也就是真的没有东西在写。文档 §七 把这条写成了可粘的三行。
    
    排掉的两个坑,都记在文档和 .env.example 里:
    
    1. `.env` 里不能给这个键赋空值。start.sh 是 `set -a; source .env` 加载的,.env 里只要
       存在同名键(哪怕空的)就会盖掉命令行传进来的 =1,而且不报错。所以 .env.example 里
       它只以注释形式出现 —— 一个「示例文件顺手写全」的习惯会直接让开关失效。
    
    2. 开关生效后 `[TaskQueue] 🚀 已启动` 仍会打印,那是另一个模块:services/task-queue.js
       (ArenaSK 时代 /api/claude-chat 的队列,routes/claude-chat.js 模块加载时起),
       和批 3 的 services/task-scheduler.js 同名不同物。它的心跳只扫内存里的 this.tasks,
       不碰 system/agents/,不是干扰源。名字撞车,容易误判成开关没生效。
    
    文档同步:
      - docs/done/claude-cli-session-leak.md §七 重写(原文写的是「得让测试隔离,或跑前停心跳」,
        现在后者已实现,改成开关的用法 + 硬判据 + 上面两个坑);原第 2 条降为 §七之二
      - CLAUDE.md 测试命令块加一行(这是找「怎么跑测试」的人真正会看的地方)
      - docs/README.md 索引行补上开关
    
    Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
    yibo authored
     
    Browse File »
  • 队列与调度(§五.1):
    - 下达任务不再因「公司已有 active root run」吃 409,改为建 queued run + queued task
      排队;出队走 updateRunStatus 的 CAS + BEGIN IMMEDIATE 准入事务,触发挂在
      transitionRun 这个唯一漏斗上,60s sweep 兜底。
    - 依赖已不可能满足的排队任务就地推导成 blocked,且每次 tick 重算不落死,上游重跑
      成功后能原路解开。
    
    恢复路径(批 3 复核 F1/F2):三条恢复转换的 from 全在活跃集之外,撞坑满时退回队列而不是
    永远躺在 blocked;退不回去的裸 run 干净拒绝,不留半截状态。
    
    控制台三处可见性修复 —— 症状全是纯视觉、不报错、git status 干净:
    1. 顶栏墙钟恒 `now - started_at`,没有终点。一条昨晚就 blocked 的 run 第二天还在涨到
       「16h 58min」,而那是页面上唯一的时间信号 —— 「已经停了等人处置」被显示成了
       「还在跑再等等」,这两件事需要的动作相反。终点改取 run.updated_at,并标「已停」。
    2. 越界日志只报「留下 N 处改动」,文件清单躺在 timeline.ndjson 里翻不到。判罚就是按
       这份清单下的,而人要判断「这真是 agent 写的吗」唯一的依据就是路径(并行的开发会话
       改宿主仓库会被算到当时在跑的节点头上,那是误判,看一眼就知道)。改为列出 entries。
    3. run 收敛成 blocked 时只把 task 写成 blocked、不写原因,任务列表那一行只剩一个橙色
       的「挂起」,必须逐层点进 org 图 → work 图 → 节点详情才知道发生了什么。改为把
       「卡在哪个节点 + 什么 fail_reason + 判词摘要」写进 tasks.blocked_reason。
       原因绝不带 UPSTREAM_BLOCK_PREFIX —— 带了会被调度器当成依赖推导出的 blocked 自动
       推回 queued,而这类 blocked 本来就等着人处置(守卫在 task-blocked-reason.test.js)。
    
    测试:126 文件 / 1201 用例全绿。
    
    Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
    yibo authored
     
    Browse File »

  • goal 从「人写一句话」变成「agent 拆成一张 task DAG、人确认后下达」,
    收敛时由 org-validator 在 goal 层再验一次。
    
    ## 交付
    - task-planning 本体(毕业判据实测通过:agent.md + soul.md 一次写完、
      不带 _base 哨兵、路径按 cwd 深度 3 实算核对)
    - 拆分链路:3 轮 errors 原样回喂 → 不过就降级成 1 条同描述 task,
      goal 绝不卡在 planning;token 记 goals.planning_tokens
    - goal 级 org-validator 验收:≥2 条 task 全 completed 才调,单 task 跳过,
      有 failed 直接 failed 不调(省一次真花钱的调用)
    - 控制台四栏 + GoalTaskPane 两级树 + 两步表单(拆分中给逃生口)
    - 中断恢复:启动时补跑验收与汇报
    
    ## 三条跨进程竞态,全部用真探针实跑复现后才判定修好
    1. runGoalSplit 无条件把 goal 写回 draft,抹掉逃生口刚下达的 active ——
       而触发它的正是表单自己推荐的那个逃生口。后果是一个正在烧钱的 goal
       显示成「草稿」,且从此永不收敛(OKR 不写、上级不唤醒、无日志)
    2. CAS 把最终态提前写进库,验收窗口内重启即丢,且 verdict=NULL 与
       「单 task 合法跳过」形态相同,查不出来 → 占位判词 + 启动重推
    3. 认领语句 SET verdict=RESUMING WHERE verdict IN (PENDING, RESUMING)
       —— 写进去的值就在 WHERE 里,changes 恒为 1。而函数注释白纸黑字
       写着「认领写的是另一个占位值」。注释是对的,代码没兑现。
       实测:org-validator 调 2 次 / OKR 写 2 条 / token 双记
       → claim 带唯一 token + 时间戳租约,回写条件更新决胜,主路径同闸门
    
    ## 与设计正文的偏离(已记进文档 §十四)
    拆分后 goal 落 draft 而非 active(active 的语义已被 markGoalDispatched
    钉死为「已下达」);mode 三级继承对显式 tasks[] 同样生效;占位判词不出
    API;新增 planning_error / reported_at 两列,后者迁移带回填(否则升级后
    第一次启动会把历史终态 goal 全部重报一遍)。
    
    ## 过程
    四轮 26 个 agent,复核报出 22 条缺陷,其中 6 条是修复自己引入的。
    第四轮修完挂了 3 条测试,全是测试在钉住缺陷本身 —— 其中一条的注释
    写着「模拟进程死后重启」,构造的却是新鲜占位值:注释描述 A 场景、
    代码构造 B 场景、断言按 A 场景写。
    
    全量:118 文件 / 1112 测试全绿,web:build 通过。
    
    Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
    yibo authored
     
    Browse File »
  • 把「人类提的一个需求」与「机器执行的一件活」拆成两级。这不是新概念:
    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>
    yibo authored
     
    Browse File »
  • 设计见 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>
    yibo authored
     
    Browse File »

  • 测试 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>
    yibo authored
     
    Browse File »
  • 按 27-p3-p4-work-graph-console.md v0.3 实现,三轮开发+校验后测试全绿
    (693/693,P2 26/26、DevLoop 230/230 未被打破,web:build 干净)。
    
    服务层
    - work-graph-db.js  定义层(work_graph_*) + 运行时层(graph_runs/graph_run_nodes/
      graph_run_loop_records) 五张表;状态转换表照 unit-registry 模式;
      复用 org-graph-service 四项校验 + 新增第五项 fail-fallback-edge
    - graph-engine.js   advanceOne 幂等原语;agent_call / subgraph 两种 executor;
      手动与自动共用同一原语;双层熔断(单边 loop_count + 按 root_run_id 共池的
      backward_count);任务级预算挂 root run;三层暂停/停止级联;
      重试按 contract_hash unchanged 判据
    - graph-run-sse.js  按 run_id 广播,状态转换+timeline+SSE 三者原子化
    - goal-contract.js  验收契约格式与执行器(R-15.6 验收先行)
    
    引擎泛化(R-15.4):org graph 与 work graph 走同一套 advanceOne,
    定义层两套、运行时层一套,三层下钻用 parent_run_id 链。
    
    R-16 失败归因:validator-reflection 专职归因节点;fail_reason 多边路由
    (精确匹配→兜底边→死路);子 run 收敛透传 success/fail + fail_reason +
    remediation_note 三值;infra_flake 不烧任何计数。
    
    路由 / 前端 / 模板
    - routes/graph-run.js 八个端点;company.js 任务入口
    - WorkGraphCanvas.vue 扩展 UnitsDAG(subgraph 角标、backward 虚线曲线、
      N/3 循环徽标、异常流程视觉降权);GraphConsole.vue 三栏 + 四 tab 详情
    - 五个新 agent 模板:validator-reflection / org-validator / planner-validator /
      coder-validator / workgraph-planning
    
    命名统一(R-15.3 + NAMING §三):org 节点改为 org-{职能},
    三个 org-graph 模板末节点收敛到 org-validator;org_graph_edges 加 fail_reason
    列并把唯一索引补上该列(避免精确边与兜底边互相吞掉)。
    
    三轮校验修掉的主要缺陷:subgraph 重跑不起新子 run 导致永久死锁;
    SSE/timeline 零调用方;org 侧 fail_reason 写入被丢弃;fail-fallback-edge
    只做了一层;backward_count 跨 run 树重置架空熔断外层;
    seedEntryNodes 误点亮只有 fail 入边的节点。
    
    已知缺口见后续提交:remediation_note 仅在 backward 边落库、
    total_tokens 预算维度无生产方。
    
    Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
    yibo authored
     
    Browse File »

  • 代码层:
    - 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>
    yibo authored
     
    Browse File »

  • 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>
    yibo authored
     
    Browse File »
  • 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>
    yibo authored
     
    Browse File »

  • - Add TaskTimeline.vue: two-pane dashboard with task list + message timeline
    - Add task-service.js: aggregate cross-agent conversations into task tree
      - 4-strategy parent-child inference (explicit meta, time-overlap, conv→tpl, master→T)
      - Read messages.log for full tool call details (not just history.json)
    - Add tasks.js API routes: GET /api/tasks, GET /api/tasks/:taskId/timeline
    - Mount /api/tasks in agent-server.js
    - Add 'Task Logs' nav entry in AppNav.vue after Templates
    - Support taskId in URL (/tasks/:taskId?) for sharing/bookmarking
    - Add --parent flag to CLI task dispatch for explicit parentTaskId
    - Auto-detect parentTaskId in task/dispatch from sender's active task
    - Add --instructions flag to template train CLI command
    - Update master tools.md with new parameters
    yibo authored
     
    Browse File »


  • - CompanyHeartbeatService: company-level heartbeat with timer registration
    - Auto-trigger: cron-based pipeline scheduling (intervalHours)
    - Active run driving: dispatch tasks to agents, timeout detection
    - CEO heartbeat: periodic company status check
    - Pipeline cron field support in definitions
    - Registered in server startup alongside agent heartbeat
    - E2E test: 113/113 passed (all phases + autonomous loop)
    yibo authored
     
    Browse File »
  • - CompanyService: CRUD (create/get/list/update/shutdown)
    - Agent Hiring Pipeline: template lookup → copy → context injection
    - Template registry (_registry.json) with CEO and qa-judge initial templates
    - resolveAgentDir(companyId, agentId) unified agent directory resolution
    - Company REST API routes (/api/company/*)
    - E2E test: 46/46 passed
    yibo authored
     
    Browse File »
  • - Extracted HeartbeatService to periodically wake up agents flagged with 'heartbeat.enabled'
    - Sends a silent [SYSTEM HEARTBEAT] message to trigger self-checks (e.g. OKR state validation)
    - Automatically integrated service dispatch hook in server startup sequence
    - Configured qa-judge to run autonomous heartbeat every 10 min
    yibo authored
     
    Browse File »

  • - 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
    yibo authored
     
    Browse File »

  • - 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
    yibo authored
     
    Browse File »