• 44 号:writesArtifacts 节点产出闸门永远打不过
    - goal-benchmark 按设计把产物写进 root run 共享 artifacts/ 目录(三个节点合成同一份
      acceptance.json,天然不可能落在某节点私有目录),但 unsatisfiedRequiredProduces 的
      R-19 逃生口 readDeclaredProduces 的 allowedRoots 只认节点私有目录 + 项目根,够不到
      共享区——这条契约在当前实现下无论 agent 表现多好都无法通过。
    - 修法(44 号文档方案 1,改动面最小):allowedRoots 加入 runRootDir(run)/artifacts/;
      goal-benchmark 的 agent.md/tools.md 补上"写完共享产物后在自己节点私有目录声明一份
      contract.json"这一步。
    - 回归:graph-files-index.test.js 新增用例 ⑭。
    
    41 号:routeFailure 的 infra_flake 分支完全无视 target_node
    - 30 号文档记录过一次真实死循环:节点自称 infra_flake 并点名 target_node,引擎原来
      一律原地重跑该节点自己,从不看 target_node。
    - 修法(最保守方案,用户确认):新增 infraFlakeTargetEdge——target_node 只有在图上
      真有一条从本节点出发的 backward fail 边指向那个节点时才生效,命中就改走正常的
      backward 边路由(计入 backward_count/双层熔断),不再享受"原地重跑、只受
      infra_flake_count 约束"的免账本待遇;没命中维持原有行为。
    - 重要澄清:这条修复堵不住 30 号文档那次真实事故——事故里点名的目标是下游节点,
      而 org-graph-service.js 规则 4(backward-labeled)从图结构上就不允许 backward 边
      指向非祖先,那次事故本来就不是"有边不认",是"诊断内容在打图结构不允许表达的
      主意",已经靠 INFRA_FLAKE_HARD_CAP 熔断收敛,不在这条修复范围内。
    - 回归:graph-engine.test.js 的 infra_flake describe 块新增两条用例。
    
    44 号文档移入 done/,41 号清单项相应更新,43 号文档的交叉引用一并修正。
    
    Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01CwGcvMfUcgCcweN5vjhTkn
    yibo authored
     
    Browse File »

  • 核心修复:indexNodeOutputs() 此前只扫节点私有目录,不扫项目根——但引擎自己的写入边界
    明确允许交付物写项目根,导致内容型交付物节点(产出写进项目根时)永远进不了 R-19 产物
    索引,下游 needs 声明永远查不到实例。新增 readDeclaredProduces():agent 可在
    contract.json 里显式声明 produces:{kind: 绝对路径},校验(绝对路径/落在项目根或私有目录内/
    文件真实存在)通过才登记,不满足就整个 kind 判「没产出」,不静默放过。全局提示词
    (describeArtifactContract)同步更新,所有 org/work 节点自动学到这个新字段。
    
    新增 org-hunt / org-digest / org-evolve 三个 graph 原生 agent(方法论抄
    innovator-hunt/digest/evolver,协议原生兼容 graph 引擎),配套新增 work-graph-templates
    的 deliverable.json(内容型交付物骨架,不引入验证 agent)。11 轮真实试跑挖出并修复 5 个
    独立缺陷(详见 41 号文档问题 7):建公司自动规划与手写图的竞态、work-graph 模板库缺内容型
    交付物骨架、验收节点任务描述范围溢出、两个规划 agent(orggraph-planning/workgraph-planning)
    的路径口径写错、以及上述 R-19 索引缺口。最终产出与原生 FDE 对比:内容骨架可迁移、质量不
    打折,但可靠性差距悬殊。
    
    补充说明:system/agents/{ceo,innovator-evolver,master,org-innovator}/{agent,soul}.md 是
    本会话开始前已存在的 dream 自编辑改动,随本次提交一并收进去,不属于本次改动范围。
    
    Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
    yibo authored
     
    Browse File »

  • org-coder-validator 在真实回归任务里被 missing_required_input 反复误判 blocked:
    executor.json/executor-fanout.json 的 test/integration→validator 边声明
    produces:["log"](required 默认 true),但 test 类节点从不写出能被 indexNodeOutputs
    认作 kind=log 的文件(coder.log 实际属于 impl,test 自己的 _plan.md/_research.md
    认不出 kind 也没有一对一无歧义可猜),这个 kind 因此永远不会被索引到,
    requiredInputsMissing 每次都判缺失——不是时序问题,是结构性、每次重试都复现的硬伤。
    
    改成 { kind: 'log', required: false },对齐 validator.json 已有的写法(它的
    needs:artifact 早就标了 required:false)。真正必需的 needs:artifact 不变,
    仍受硬闸门保护。
    
    中途走了一段弯路:最初以为该改 inboundContracts() 按 role 过滤只留 needs,
    改完单测炸了 9 个用例——大多数边只声明 produces(无配对 needs),这条链路
    正是 T-mt25ecbd 产出闸门依赖的数据源,按 role 过滤会静默削弱那次修复。
    已撤回(work-graph-db.js 这次只加注释,没有逻辑改动),细节记在 33 号文档。
    
    新增回归用例 graph-files-index.test.js ⑪:produces required:false 且该 kind
    从未被索引到时不拦下游成功,同边 needs:artifact(required:true) 依旧受保护。
    全量单测 998/998 通过。
    
    Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
    yibo authored
     
    Browse File »

  • planner 骨架(brd→prd→sdd→goal-benchmark→validator)复现:三个 planning 节点
    声明了 produces 却没真落盘,executor 没抛异常就被引擎判 success;goal-benchmark
    的入边 needs:[brd,prd,sdd] 只用来拼提示词里的 ⚠️ 提示,agent 视而不见照样产出
    合法 acceptance。下游 validator 永远读不到三份文档,backward 重试撞循环硬顶后
    只能人工兜底。
    
    settleNode 判 success 之前新增两道闸门(均只对 agent_call 节点生效,subgraph/org
    节点的契约由子 work run 自己的节点过闸):
    - unsatisfiedRequiredProduces:声明的 required produces 一个候选文件都没落盘 →
      fail_reason=produces_missing,不再放行
    - requiredInputsMissing:声明的 required needs 在 graph_files 里查不到实例 →
      fail_reason=missing_required_input,不采信 agent 自报的 success
    
    两者都只判「有没有」,不判「分类对不对」——ambiguous 归类留给下游 ⚠️ 提示词处理,
    避免把「写了东西但引擎猜不出对应哪个 kind」误判成没执行。
    
    包含此前已完成但未提交的 27-P4 T3(graph_runs.max_concurrency 落库)及配套
    advance-batch 测试。
    
    Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
    yibo authored
     
    Browse File »

  • 28-followups §3.1。**审计结论与那条待办原来的写法不一样,两列要分开处理。**
    
    ## source_kind:删
    
    与 origin 一一映射(global_agent↔builtin / company_hired↔created),
    实查生产库 76 行零例外。全仓唯一读侧是 migrate() 里那条 origin 回填,
    而那是给「origin 列出现之前写下的行」用的一次性迁移。
    
    顺序:**先回填、再删列**,两步都用 hasColumn 守着(幂等)。反过来做不报错 ——
    库能开、测试能过,只是那几行 origin 悄悄是错的。守卫
    source-kind-drop-migration.test.js 走存量库重启那条路,专门钉这个顺序,
    反向验过:弄反立刻红。
    
    写侧散在 3 处生产 INSERT + 35 个测试文件。批量改的时候正则误伤了 4 处
    (吃掉了 JS 默认参数、位置占位符、ON CONFLICT 的赋值行),逐个修回并复查了 diff ——
    **这种跨几十个文件的机械改动,靠「全量跑一遍」兜底比靠正则写得对更可靠**。
    
    ## legacy_path:不能删,它还没死
    
    原待办说「所有读取点都已改成从 id 推导」——那半句对新行成立,对存量行不成立:
    · 新行 legacy_path 恒等于 system/agents/{id}(确实冗余);
    · **存量行里存着批次 4 之前的公司侧路径**,而 graph-seed-service 判「悬空行 / 孤儿行」
      靠的正是这个路径指向的目录还在不在。从 id 推导出来的路径永远指向 system/agents/,
      那条判据会整个失效。
    
    实查生产库:76 行里还有 2 行是老路径(org-planner / org-coder 指着已不存在的
    data/companies/mycompany/agents/)—— 正是这条判据要认出来的那种行。
    
    退出条件写进了 graph-db.js 的建表注释(不只留在文档里):
    库里不再有 legacy_path <> 'system/agents/' || id 的行。
    
    ## 顺带记一条:getDb() 会就地迁移生产库
    
    删列那次,生产库的列是被一条**查状态用的**一行 node -e 删掉的 ——
    服务当时没重启,人也没打算迁移。结果是对的(幂等;与备份逐行核对 76 行一致、
    origin 全部按映射回填正确),但「读一下状态」不该顺手改 schema 这件事值得知道。
    闸门只挡测试进程,故意不挡普通脚本(挡了服务自己也起不来)。
    注释里给了只读的正确姿势。
    
    全量:140 文件 / 1299 测试全绿。
    
    Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
    yibo authored
     
    Browse File »

  • 第六次真 CLI 冒烟 gapClosed=true:org 层契约落库 4 行(此前恒 0),
    且那段文字真的进了 workgraph-planning 收到的提示词(52677 字节,第 746 行起)。
    
    ## workflow 四路并行的产出
    
    - **org 层两半一起接**(关键顺序):先接读回方 buildPlanningPrompt 的 ③bis 段
      (org 边入边 → 上游绝对路径;出边 produces → 「你规划的子图必须有节点产出这些」),
      再接声明方 orggraph-planning 模板。只补模板的话就是又一次「声明了没人读」——
      org 图节点全是 subgraph,而 describeInputs 对 subgraph 直接返回空。
      resolveInboundLines 从 describeInputs 抽出共用,两侧口径物理上不可能漂移。
    - **清掉 404 死路径**:模板三处教的 POST /api/company/:id/work-graphs 从未注册。
      真跑复验:agent 侧零调用,改为按新 Step 7 写项目根绝对路径,还自己 require
      validateWorkGraph 预检了一遍才交回,round=1 一次过。
    - **四张骨架补 produces/needs**:从「靠模板文字施压」变成结构保证,每张过规则 6。
      真跑里 agent 照抄了 planner.json 并跟着任务删掉 sdd 节点——是改编不是复制。
    - **graph-seed 顺序依赖**:靠生产代码里已有的 GRAPH_SEED_ROOT 缝隙指向冻结快照。
      不是「跑几次都绿」结案:构造了原先必红的 churn,修前 12 次 3 红、修后 15 次 0 红。
    
    ## 我自己收的 4 条 major + 1 条 minor(都在 graph-engine.js)
    
    复验挖出「引擎自己拼的提示词在教 agent 做模板明令禁止的事」,同一条提示词里对立:
    1. 「已自行落库成功时回一行 workGraphId: wg_xxx」vs 模板「你永远拿不到真的 wg_ id,
       永远别写」。agent 没有任何受支持的落库途径,写出来必是编的,而 extractPlannedGraph
       优先匹配那个形状、查库查不到就整轮作废。删掉邀请,保留引擎解析真实 wg_ 的能力。
    2. 内联图示例的边一个 produces 都没有——agent 唯一见过的「边长什么样」是零声明的。
    3. 「端点尚未上线」暗示将来会上线,于是它还想去试一次。改成「不存在、也不会上线」。
    4. indexNodeOutputs 收集 declared 不按 role 过滤,把出边的 needs 当成本节点的产出。
       Chrome 走查实测:产品需求文档.md 落成 artifact,下游 prd 输入变 ⚠️。
       更坏的一面是错标(brd_notes.md 命中中继 needs[brd] → 归因给错的产出方)。
       1ea9efa 加的 role 列,这里正是它存在的理由。
    5. (minor) contract.prev.json(retryNode 的契约快照)被索引成 artifact 噪声。
    
    新增 guard:引擎提示词不许与模板对立(静态读源码,剔掉注释行——
    第一版把「解释为什么不许说某句话」的注释也扫进去了,量错了对象)。
    
    测试 850 全绿(83 文件),既有断言未改。5 处变异精确变红后逐字还原。
    Chrome 走查确认控制台正常分支(此前只验过降级分支):契约药丸、绝对路径、
    needs 中继说明、tab 上的 ⚠️ 计数全部渲染,零 console 报错。
    
    Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
    yibo authored
     
    Browse File »
  • 第五次真 CLI 冒烟(gapClosed=true)暴露的两条,都是「这轮成立是侥幸」型。
    
    1) indexNodeOutputs 靠文件名定 kind
       真跑成立纯属 brd 节点恰好把文件命名成 `brd.md`。换写 `业务需求文档.md`
       就落成 kind=artifact → 下游入边声明的 brd 查不到实例 → 提示词退化成
       「⚠️ 索引里查不到实例」,即刚关掉的断点换个形式重现。agent 给产物起中文名
       是完全正常的行为,不该由它决定索引对不对。
       改成两遍:先按文件名认领,再在**一对一无歧义**时(还差一个 kind 没人产、
       正好还剩一个认不出的文件)按声明认领。有歧义不猜 —— 猜错比留 artifact 更坏,
       错的 kind 让下游读到一份不是它要的文件,artifact 只是查不到、会如实报 ⚠️。
    
    2) describeInputs 任务级共享不去重
       真跑里 brd 与 prd 两个节点各写了一份 contract.json,都是 kind=contract,
       于是往后每个节点的提示词里「contract(任务级共享)」逐个累加。节点一多是噪声,
       且给 agent 两个同类路径等于把一个我们自己都没定的选择推给它。
       按 kind 保留最新那份,与沿边那一半的 byKind.set 同口径。
       ponytail 标了根因(节点私有目录的文件也会按文件名落成 task-shared 的 kind)
       与真正的修法(任务级产物只认 tasks/{taskId}/),后者要动 R-9.3 现有语义,
       归到那条线一起定。
    
    测试 829 全绿(+3),既有断言未改。4 处变异精确变红后逐字还原。
    含 verify agent 回填的 §4.6「第五次真 CLI 冒烟」小节。
    
    Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
    yibo authored
     
    Browse File »
  • R-19.A 把 declareEdgeContract 的调用方补上之后,inboundContracts 终于非空,
    「沿边传递」这类数据流在真跑里生效了(真实规划 agent 自己在边上写出了
    produces/needs 声明)。本次收掉它留下的三个缺口。
    
    1) role 落库(第 14 次「四环漏一环」)
       normalizeContracts 产出 role,declareEdgeContract 入参没有它、表也没这列 ——
       产生 → 传递(丢) → 落库 → 读回。后果不止是控制台不精确:规则 6(data-contract)
       靠「有人 needs 但没人 produces」判错,只存 kind 就没法从库里重算,而
       patchGraph 第 5 步的重新校验读的正是库 —— 增量 PATCH 又恰恰是
       「此前满足的 needs 失去产出方」的唯一发生地,校验偏偏在最该生效的通道上失效。
       - graph_edge_contracts 加 role 列(CHECK + 老库 ALTER 后回填 produces:
         NULL 在规则 6 里既不算产出也不算需求,会误拒一张合法的图;闸门宁可漏判不可错拦)
       - 两层调用点透传 role;readGraph 把 contracts 读回来并递进 validateGraph
    
    2) 控制台三字段(前端在、后端没喂)
       GET /api/graph-runs/:id 补 edges[].contracts / companyRoot / taskFiles,
       否则 R19-C 那三块界面整块降级:声明和索引都在库里,界面上看不见。
       contracts 只在非空时出现,与 failReason 同一个约定。
    
    3) 收拢 companyRootDir/taskDirRel 镜像
       goal-contract.js 里那份镜像靠注释约定「与 graph-engine 逐字同构」维持,
       控制台路由成为第三个调用方时这个约定就不成立了。抽到 company-paths.js,
       GRAPH_RUNS_DIR 改为调用时读(原先两个模块各自在加载时快照,
       加载顺序不同会算出不同的根)。goal-contract 那条「镜像漂了就报警」的用例
       按其自身预告改成比函数返回值。
    
    测试 826 全绿(+11:role 8 / 路由 3),既有断言未改。
    11 处变异逐一验证精确变红后逐字还原;其中一条断言初版在 fixture 上永远自洽
    (图里没有无声明的边),补了一条无声明的边才真正有判别力。
    
    Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
    yibo authored
     
    Browse File »