-
第五次真 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> -
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>