Commit 54470be3a4d5a8d78a303cf30b42a3ce74c3ee43
1 parent
dea683eb
test(p3b): 验收 4 进零注入链路;2/8 由真跑验掉,9 的准确状态写清楚
## 验收 4:从「静态成立」变成真的跑过一次
原状态是 🟡「静态成立,未真跑」—— 人读代码把
fixture verdict → FAILING_VERDICTS → readNodeProduct → callAgentNode 判 fail
这条链读通了,但没有任何一次真跑或真链路证据。
现在 graph-real-chain-smoke ⑥ 走完整条:fixture 产出 verdict="attributed"
→ 节点 fail、fail_reason=input_underspecified、沿 fail 边点亮下游、
判词落在**下游节点**行上(判词的载体是「点亮它的那次状态转换」,不是失败节点自己)。
反向验过:verdict 改成 passed 立刻红。
写 fixture 时踩到一条值得记的:fail_reason 是封闭域 ATTRIBUTION_REASONS,
第一版编了个 contract_invalid,被**按设计降级成 null** 并留一条 timeline ——
引擎不认识的归因一律不信。判据没错,是 fixture 错。
## 验收 2 / 8:由 2026-08-20 那次真跑验掉(§六ter)
· 2 —— 19 次真 agent 调用之后 `git status --porcelain` 完全为空,交付物都在项目根内。
这正是 §六bis「后半被并行 agent 打破」那条的干净环境重验。
· 8 —— 判据取「它引用了只可能来自提示词的内部 id」:triager 判词原文写着
「org-coder-impl 私有目录 rn_96a8cd696dcc 下只有 _research.md」,
rn_96a8cd696dcc 是 graph_run_nodes.id,agent 没有别的途径知道它。
## 验收 9:产出端通了,消费端没等到那个形状
真跑里 triager **确实产出了两半地址**(orgNode + workNode)——
这一条本身有分量:27-P3/P4 §八.22 第 13 处记的正是「引擎四环全通,
但产出方 agent.md 里根本没有这个键」,那半条现在通了。
紧接着「忽略跨层地址」那条**不是缺陷,是判据在正常工作**:这次回退发生在
work 层内部,edge.to 本身就是 agent_call 节点,已是最细粒度,没有跨层可言。
缺的是**那个形状**:一次 org 层回退边、且目标是 subgraph 节点。
别把「机制没验」和「机制没有」混为一谈 —— 定点重置的逻辑侧有
graph-cross-layer-address.test.js 三例注入式覆盖,缺的只是真跑里发生过一次。
## 顺带
· template-verdicts 的样本非空那条补 ENOENT 容忍。它扫**活目录**,
而 graph-real-chain-smoke 会在 system/agents/{aid}/{cid}/ 下建了又清运行态 ——
文件在「列出名字」和「读它」之间消失是正常的。walk() 与 violations() 早就容忍了,
只有这一处漏了,实测偶发红过一次。**扫活目录的守卫,每一处读都要容忍 ENOENT。**
· 真跑 timeline 里发现一条未修的:每个节点的产物索引写入都撞
UNIQUE idx_graph_files_path 失败并被降级成日志(重试时同路径再写一次)。
后果是 files.json 产物索引在有重试的 run 上静默不全 —— 归 P4 一起处理,记在 §六ter。
全量:139 文件 / 1297 测试全绿。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Showing
5 changed files
with
143 additions
and
2 deletions
docs/README.md
| @@ -42,7 +42,7 @@ Graph Agent 架构重构(27 系列)。**已完成的阶段文档已移入 `d | @@ -42,7 +42,7 @@ Graph Agent 架构重构(27 系列)。**已完成的阶段文档已移入 `d | ||
| 42 | | [27-e2e-task-execution-flow.md](./todo/system-design/27-e2e-task-execution-flow.md) | 端到端流程总览:建公司 → 下达任务 → org graph 逐节点执行 → work graph 规划与循环 → 验收收敛。含与 DevLoop 既有实现的对应关系分析 | | 42 | | [27-e2e-task-execution-flow.md](./todo/system-design/27-e2e-task-execution-flow.md) | 端到端流程总览:建公司 → 下达任务 → org graph 逐节点执行 → work graph 规划与循环 → 验收收敛。含与 DevLoop 既有实现的对应关系分析 | |
| 43 | | [27-example-dev-company-walkthrough.md](./todo/system-design/27-example-dev-company-walkthrough.md) | 参考场景走查(虚构的「配图工厂」),把架构跑一遍具体的数:各阶段 JSON 形态、成本估算、断点清单 | | 43 | | [27-example-dev-company-walkthrough.md](./todo/system-design/27-example-dev-company-walkthrough.md) | 参考场景走查(虚构的「配图工厂」),把架构跑一遍具体的数:各阶段 JSON 形态、成本估算、断点清单 | |
| 44 | | [27-p3-p4-work-graph-console.md](./todo/system-design/27-p3-p4-work-graph-console.md) | P3+P4(原 P4 回退+Loop-Validator 已并入)图执行引擎与执行控制台 — ✅ 已实现(`c3abf4a`)。**仍留 todo 的原因**:§十 末「四条硬规矩」第 2 条那笔欠账**已还大半** —— `graph-real-chain-smoke.test.js`(零注入、只换掉真 CLI 子进程)已进 CI,`agent_call` 与 `subgraph` 两支都覆盖。剩下的是真 LLM(进不了 CI)、多节点 / 回退边 / 熔断的形状、以及按需 hire 那一段 | | 44 | | [27-p3-p4-work-graph-console.md](./todo/system-design/27-p3-p4-work-graph-console.md) | P3+P4(原 P4 回退+Loop-Validator 已并入)图执行引擎与执行控制台 — ✅ 已实现(`c3abf4a`)。**仍留 todo 的原因**:§十 末「四条硬规矩」第 2 条那笔欠账**已还大半** —— `graph-real-chain-smoke.test.js`(零注入、只换掉真 CLI 子进程)已进 CI,`agent_call` 与 `subgraph` 两支都覆盖。剩下的是真 LLM(进不了 CI)、多节点 / 回退边 / 熔断的形状、以及按需 hire 那一段 | |
| 45 | -| [27-p3b-real-run-runway.md](./todo/system-design/27-p3b-real-run-runway.md) | P3 收尾之真跑跑道(从 mock 走到真 Claude CLI)— 📝 **仍在推进**。验收 7(work 层本体混进 org graph)✅ 已修;缺陷② 的根因(边界守卫误判并行会话)2026-08-20 修掉。**剩下的是 2/4/8/9 —— 都不是「没修」,是「没在干净环境重验」**。⚠️ 这份文档里 ⛔/🟡 的段落多为**当时的现场记录**,读之前先看头部状态行 | | 45 | +| [27-p3b-real-run-runway.md](./todo/system-design/27-p3b-real-run-runway.md) | P3 收尾之真跑跑道(从 mock 走到真 Claude CLI)— 📝 **只剩验收 9**。2026-08-20 第四次真跑(§六ter)验掉 2 与 8,验收 4 由零注入链路验掉,7 早已修好。验收 9 的准确状态是「产出端通了、消费端没等到那个形状」—— 需要一次 **org 层回退边指向 subgraph 节点**。⚠️ 这份文档里 ⛔/🟡 的段落多为**当时的现场记录**,读之前先看头部状态行 | |
| 46 | | [27-goal-contract-format.md](./todo/system-design/27-goal-contract-format.md) | 验收契约格式(`goal-benchmark` / `goal-test-data` / `goal-test-script` 的产物形态与跨节点传递) | | 46 | | [27-goal-contract-format.md](./todo/system-design/27-goal-contract-format.md) | 验收契约格式(`goal-benchmark` / `goal-test-data` / `goal-test-script` 的产物形态与跨节点传递) | |
| 47 | | [27-p4-parallel-and-artifacts.md](./todo/system-design/27-p4-parallel-and-artifacts.md) | **P4(回收编号)并行执行与产物索引** — 📝 设计中,未实现。fan-out 真并发 + 同 agent 多实例隔离 + `files.json` 产物索引。三个 Phase,C 可插队 | | 47 | | [27-p4-parallel-and-artifacts.md](./todo/system-design/27-p4-parallel-and-artifacts.md) | **P4(回收编号)并行执行与产物索引** — 📝 设计中,未实现。fan-out 真并发 + 同 agent 多实例隔离 + `files.json` 产物索引。三个 Phase,C 可插队 | |
| 48 | | [28-followups.md](./todo/system-design/28-followups.md) | 28 号(Agent 注册表统一)的遗留清单 — 主文档已在 `done/`,这份装没做完的:dream 机制(只有口述、无设计)、任务态清理(源码树无限增长)、`source_kind`/`legacy_path` 删列、三项「已实施未验证」。§五 是**已立起来的守卫清单**(别重复造,也别删) | | 48 | | [28-followups.md](./todo/system-design/28-followups.md) | 28 号(Agent 注册表统一)的遗留清单 — 主文档已在 `done/`,这份装没做完的:dream 机制(只有口述、无设计)、任务态清理(源码树无限增长)、`source_kind`/`legacy_path` 删列、三项「已实施未验证」。§五 是**已立起来的守卫清单**(别重复造,也别删) | |
docs/todo/system-design/27-p3b-real-run-runway.md
| @@ -8,7 +8,8 @@ | @@ -8,7 +8,8 @@ | ||
| 8 | > **状态**(2026-08-20 校准): 📝 **仍在推进**。第一批验收 1/3 已验、2 的后半与 4 未在干净环境重验; | 8 | > **状态**(2026-08-20 校准): 📝 **仍在推进**。第一批验收 1/3 已验、2 的后半与 4 未在干净环境重验; |
| 9 | > 第二批验收 7 ✅ **已修**(`58a2865`「W7 零边图」,守卫 `company-hire-org-layer.test.js` 的 | 9 | > 第二批验收 7 ✅ **已修**(`58a2865`「W7 零边图」,守卫 `company-hire-org-layer.test.js` 的 |
| 10 | > `CO_ZEROEDGE` + `W7-fix`)—— 下面 §六bis 缺陷③ 那段是**当时的现场记录**,不是当前状态; | 10 | > `CO_ZEROEDGE` + `W7-fix`)—— 下面 §六bis 缺陷③ 那段是**当时的现场记录**,不是当前状态; |
| 11 | -> 第三批 8/9 真 CLI 未验。 | 11 | +> 验收 2 ✅、验收 8 ✅ 由 2026-08-20 的真跑验掉,验收 4 ✅ 由零注入链路验掉, |
| 12 | +> **验收 9 仍开**(产出端已通、消费端没等到那个形状)—— 逐条证据见 §六ter。 | ||
| 12 | > §六bis 缺陷② 的**根因**(边界守卫误判并行会话的改动)已于 2026-08-20 修掉, | 13 | > §六bis 缺陷② 的**根因**(边界守卫误判并行会话的改动)已于 2026-08-20 修掉, |
| 13 | > 见 [27-P3C §17.2](../../done/system-design/27-p3c-goal-task-model.md) —— 但**根因修了不等于验收点验了**,那几条仍要重跑一遍。 | 14 | > 见 [27-P3C §17.2](../../done/system-design/27-p3c-goal-task-model.md) —— 但**根因修了不等于验收点验了**,那几条仍要重跑一遍。 |
| 14 | 15 | ||
| @@ -935,3 +936,65 @@ failingVerdict = verdict === null ? raw !== null : !PASSING_VERDICTS.has(verdict | @@ -935,3 +936,65 @@ failingVerdict = verdict === null ? raw !== null : !PASSING_VERDICTS.has(verdict | ||
| 935 | (「找不到 FAILING_VERDICTS——取值域防线失去依据,不要让它静默空跑」)。 | 936 | (「找不到 FAILING_VERDICTS——取值域防线失去依据,不要让它静默空跑」)。 |
| 936 | 真去反转的话,把该测试里 `engineSet('FAILING_VERDICTS')` 换成 `engineSet('PASSING_VERDICTS')` | 937 | 真去反转的话,把该测试里 `engineSet('FAILING_VERDICTS')` 换成 `engineSet('PASSING_VERDICTS')` |
| 937 | 并把 `VERDICT_DOMAIN` 的组成对应改一行即可;**不要**把断言删掉了事。 | 938 | 并把 `VERDICT_DOMAIN` 的组成对应改一行即可;**不要**把断言删掉了事。 |
| 939 | + | ||
| 940 | +--- | ||
| 941 | + | ||
| 942 | +## 六ter、第四次真跑复验(2026-08-20) | ||
| 943 | + | ||
| 944 | +**跑法**:主仓库、真 Claude CLI、工作区干净(`git status` 空)。公司 `e2e-demo`, | ||
| 945 | +把 2026-08-18 卡住的那条 run(`run_9168bd24f46c`,做 lemonai 官网)解开后逐节点 `/next` 推到收敛。 | ||
| 946 | +19 次真 agent 调用、177,462 tokens,全树 `completed`,goal → `done`。 | ||
| 947 | +过程记在 [27-P3C §17.5](../../done/system-design/27-p3c-goal-task-model.md)。 | ||
| 948 | + | ||
| 949 | +### 逐条结果 | ||
| 950 | + | ||
| 951 | +| 验收 | 结果 | 证据 | | ||
| 952 | +|---|---|---| | ||
| 953 | +| **2** 产出落在项目根内、宿主仓库 `git status` 无新增/修改 | ✅ **成立** | 19 次真 agent 调用之后 `git status --porcelain` **完全为空**;交付物(`index.html` / `styles.css` / `app.js` / `assets/img/` / `DELIVERY.md`)都在 `data/companies/e2e-demo/projects/p-bkhylu/` 内。这是 §六bis「后半被并行 agent 打破」那一条的干净环境重验 | | ||
| 954 | +| **3** 越界被守卫拒绝并留痕 | ✅ 早已成立;误判那一半 2026-08-20 修掉 | 见 [27-P3C §17.2](../../done/system-design/27-p3c-goal-task-model.md) | | ||
| 955 | +| **4** 非法契约 → validator 判失败且引擎按失败处理 | ✅ **成立**,但**不是真 CLI 验的** | `graph-real-chain-smoke.test.js` ⑥(零注入链路,只换掉 CLI 子进程):fixture 产出 `verdict: "attributed"` → 节点 `fail`、`fail_reason=input_underspecified`、沿 fail 边点亮下游、判词落在下游节点行上。反向验过:verdict 改成 `passed` 立刻红 | | ||
| 956 | +| **7** work 层本体不混进 org graph | ✅ 已修(`58a2865`) | `CO_ZEROEDGE` / `W7-fix` | | ||
| 957 | +| **8** validator-triager 的提示词里有「哪个节点失败、第几 attempt、失败摘要」 | ✅ **成立(真 CLI)** | 判据是**它引用了只可能来自提示词的内部 id**:triager 的判词原文写着「`org-coder-impl` 私有目录 `rn_96a8cd696dcc` 下只有 `_research.md`」—— `rn_96a8cd696dcc` 是 `graph_run_nodes.id`,agent 没有任何别的途径知道它,只能来自 `describeFailureContext` 注入的那一段 | | ||
| 958 | +| **9** 一次真实的跨层回退,两半地址齐全、只重置被点名的节点 | 🟡 **产出端通了,消费端没等到那个形状** | 见下 | | ||
| 959 | + | ||
| 960 | +### 验收 9 的准确状态 | ||
| 961 | + | ||
| 962 | +真跑里 triager **确实产出了两半地址**: | ||
| 963 | + | ||
| 964 | +``` | ||
| 965 | +node.triage | 归因 verdict=attributed fail_reason=impl_bug → {"orgNode":"org-coder","workNode":"org-coder-impl"} | ||
| 966 | +``` | ||
| 967 | + | ||
| 968 | +这一条本身有分量:[27-P3/P4](./27-p3-p4-work-graph-console.md) §八.22 的**第 13 处**记的正是 | ||
| 969 | +「引擎四环全通,但产出方 `validator-triager` 的 agent.md 里根本没有这个键」—— | ||
| 970 | +**那半条现在通了**,真实 agent 真的写出了 `orgNode` + `workNode`。 | ||
| 971 | + | ||
| 972 | +但紧接着的一条: | ||
| 973 | + | ||
| 974 | +``` | ||
| 975 | +node.triage | 归因点名了 org-coder-impl,但回退目标 org-coder-impl 不是 subgraph 节点,忽略跨层地址 | ||
| 976 | +``` | ||
| 977 | + | ||
| 978 | +**这不是缺陷,是判据在正常工作**:这次回退发生在 **work 层内部** | ||
| 979 | +(`org-coder-validator` → `org-coder-impl`),`edge.to` 本身就是 `agent_call` 节点, | ||
| 980 | +已经是最细粒度,没有「跨层」可言 —— `resolveCrossLayerTarget` 第 ② 关就是拦这个的。 | ||
| 981 | + | ||
| 982 | +所以验收 9 缺的是**那个形状本身**:需要一次 **org 层的回退边、且目标是 subgraph 节点**。 | ||
| 983 | +今天这条 run 的三个 org 节点重试后一次过,没有 org 层失败。 | ||
| 984 | + | ||
| 985 | +> **别把「机制没验」和「机制没有」混为一谈**:定点重置的逻辑侧有 | ||
| 986 | +> `graph-cross-layer-address.test.js` 三例注入式覆盖(只写 `target_node` / 只写 | ||
| 987 | +> `target_org_node` / 模板键名逐字对齐)。缺的只是「真跑里发生过一次」。 | ||
| 988 | + | ||
| 989 | +### 顺带发现的一条缺陷(未修) | ||
| 990 | + | ||
| 991 | +真跑的 timeline 里,**每个节点的产物索引写入都失败了**,且被降级成一条日志: | ||
| 992 | + | ||
| 993 | +``` | ||
| 994 | +node.output | 产物索引写入失败 contract.json: UNIQUE constraint failed: index 'idx_graph_files_path' | ||
| 995 | +node.output | 产物索引写入失败 sdd.md: UNIQUE constraint failed: index 'idx_graph_files_path' | ||
| 996 | +``` | ||
| 997 | + | ||
| 998 | +形态是重试时同一条产物路径被再写一次撞唯一索引。后果不是崩溃 —— | ||
| 999 | +**是 `files.json` 产物索引在有重试的 run 上静默不全**,而那正是 | ||
| 1000 | +[27-P4](./27-p4-parallel-and-artifacts.md) 要建的东西。归到 P4 一起处理。 |
fixtures/devloop-mock/benchmark-validator.json
0 → 100644
| 1 | +{ | ||
| 2 | + "_doc": "P3 mock fixture · 判失败的验收节点(27-P3B §六 验收 4)。attempt-{attempt}.json 里 verdict=attributed 落在 graph-engine.FAILING_VERDICTS 里 → readNodeProduct 置 failingVerdict → 节点判 fail。这份 fixture 的**全部意义**就是让「validator 说失败 → 引擎真的按失败处理」这条判据在 CI 里跑得出来:在这之前它只是「静态成立」(人读代码读通了链路),没有任何一次真跑或真链路证据。改 verdict 的取值前先看 graph-engine 的 FAILING_VERDICTS。 fail_reason 必须取自 graph-engine.ATTRIBUTION_REASONS 这个封闭域(impl_bug / input_underspecified / skill_defect / infra_flake)—— 自创的词会被**按设计降级成 null** 并留一条 timeline,不是崩溃,但节点行上就没有归因了。第一版这里写了 contract_invalid,实测就是这个下场。", | ||
| 3 | + "chunks": [ | ||
| 4 | + "[mock] benchmark-validator 读取被测产物与验收契约。\n", | ||
| 5 | + "契约形状非法:acceptance.json 缺 test_script 段。\n" | ||
| 6 | + ], | ||
| 7 | + "result": "mock-fail benchmark-validator:契约非法,判失败。", | ||
| 8 | + "files": [ | ||
| 9 | + { | ||
| 10 | + "path": "attempt-{attempt}.json", | ||
| 11 | + "content": "{\n \"schema\": \"validator-triager/v1\",\n \"verdict\": \"attributed\",\n \"fail_reason\": \"input_underspecified\",\n \"remediation_note\": \"acceptance.json 缺 test_script 段,补齐后重跑\"\n}\n" | ||
| 12 | + } | ||
| 13 | + ], | ||
| 14 | + "usage": { | ||
| 15 | + "input": 400, | ||
| 16 | + "output": 120 | ||
| 17 | + } | ||
| 18 | +} |
server/tests/unit/graph-real-chain-smoke.test.js
| @@ -195,6 +195,66 @@ describe('蝗セ謇ァ陦檎悄螳樣得霍ッ smoke磯峺豕ィ蜈・悟宵謐「謗臥悄 CLI 蟄占ソ帷ィ具シ | @@ -195,6 +195,66 @@ describe('蝗セ謇ァ陦檎悄螳樣得霍ッ smoke磯峺豕ィ蜈・悟宵謐「謗臥悄 CLI 蟄占ソ帷ィ具シ | ||
| 195 | expect(spent.tokens).toBe(1060); // fixture 謚・ 800 + 260 | 195 | expect(spent.tokens).toBe(1060); // fixture 謚・ 800 + 260 |
| 196 | }, 60_000); | 196 | }, 60_000); |
| 197 | 197 | ||
| 198 | + it('竭・ validator 蛻、螟ア雍・譌カ蠑墓梼逵溽噪謖牙、ア雍・螟炊27-P3B ツァ蜈ュ 鬪梧噺 4梧ュ、蜑榊宵譏ッ縲碁撕諤∵遶九搾シ', async () => { | ||
| 199 | + // 蜴滄ェ梧噺譬壹碁荳莉ス髱樊ウ募・醍コヲ霍 benchmark-validator壼愛蜀ウ荳コ螟ア雍・荳泌シ墓梼謖牙、ア雍・螟炊 | ||
| 200 | + // **荳肴弍** success峨阪13B 蠖捺慮逧サ楢ョコ譏ッ 泯縲碁撕諤∵遶具シ梧悴逵溯キ代坂披 莠コ隸サ莉」遐∵滑 | ||
| 201 | + // fixture verdict 竊 FAILING_VERDICTS 竊 readNodeProduct 竊 callAgentNode 蛻、 fail | ||
| 202 | + // 霑呎擅體セ隸サ騾壻コシ御スイ。譛我ササ菴穂ク谺。逵溯キ第逵滄得霍ッ隸∵紺縲 | ||
| 203 | + // | ||
| 204 | + // 縲瑚ッサ騾壻コ榊柱縲瑚キ鷹壻コ堺ケ矩龍髫皮捩逧ュ」譏ッ霑呎擅 smoke 隕∬。・逧ク懆・ソ壻コァ迚ゥ隕∫悄逧誠逶倥 | ||
| 205 | + // 隕∫悄逧「ォ readNodeProduct 隸サ蛻ー縲」erdict 隕∫悄逧「ォ隶、蜃コ譚・縲ゆササ菴穂ク邇ッ譁ュ莠シ | ||
| 206 | + // 闃らせ驛ス莨壻サ・ success 謾カ蝨コ 窶披 閠**蛻、髞呎 success 逧サ」莉キ譏ッ荳榊粋譬シ莠ァ迚ゥ逶エ謗・謾セ陦鯉シ | ||
| 207 | + // 荳比ク咲蕗逞戊ソケ**3B ツァ蜈ォ 驍」谿オ縲御ク、遘埼漠莉」莉キ荳榊ッケ遘ー縲崎ッエ逧ーア譏ッ霑吩クェ譁ケ蜷托シ峨 | ||
| 208 | + const VALIDATOR = 'benchmark-validator'; | ||
| 209 | + // 蜿ヲ蠑荳螳カ蜈ャ蜿ク壻ク螳カ蜈ャ蜿ク蜷梧慮蜿ェ蜈∬ョク荳譚。豢サ霍 root rundx_graph_runs_one_active_root会シ | ||
| 210 | + // 荳企擇蜃譚。逡吩ク狗噪 run 霑伜惠豢サ霍寔驥鯉シ悟逕ィ蜈ャ蜿ク莨壽寵 RunSlotBusyError 窶披 驍」譏ッ郤ヲ譚溷惠豁」蟶ク蟾・菴懶シ | ||
| 211 | + // 荳肴弍霑呎擅逕ィ萓玖ヲェ檎噪荳懆・ソ縲 | ||
| 212 | + const CO = `${COMPANY}-v4`; | ||
| 213 | + const db = wdb.getDb(); | ||
| 214 | + const now = new Date().toISOString(); | ||
| 215 | + db.prepare(`INSERT OR IGNORE INTO system_agents | ||
| 216 | + (id, name, scope, owner_company_id, source_kind, legacy_path, status, created_at, updated_at) | ||
| 217 | + VALUES (?, ?, 'public', NULL, 'global_agent', ?, 'active', ?, ?)`) | ||
| 218 | + .run(VALIDATOR, VALIDATOR, `system/agents/${VALIDATOR}`, now, now); | ||
| 219 | + | ||
| 220 | + const g = wdb.createWorkGraph({ | ||
| 221 | + companyId: CO, | ||
| 222 | + // 蟶ヲ荳譚。 fail 蜈懷コ戊セケ壽イ。譛牙霎ケ譌カ螟ア雍・闃らせ謾カ蝨ィ `blocked`域撃襍キ遲我ココ蟾・会シ | ||
| 223 | + // 驍」荵滓弍縲梧潔螟ア雍・螟炊縲搾シ御ス恚荳榊**霍ッ逕ア**譛画イ。譛芽オー騾壹ょ刈荳願セケ悟愛謐ョ謇榊ョ梧紛 | ||
| 224 | + // 螟ア雍・ 竊 闃らせ fail 竊 豐ソ fail 霎ケ轤ケ莠ョ荳区クク縲 | ||
| 225 | + nodes: [ | ||
| 226 | + { nodeName: VALIDATOR, systemAgentId: VALIDATOR }, | ||
| 227 | + { nodeName: AGENT, systemAgentId: AGENT }, | ||
| 228 | + ], | ||
| 229 | + edges: [{ from: VALIDATOR, to: AGENT, condition: 'fail' }], | ||
| 230 | + }); | ||
| 231 | + expect(g.errors || []).toEqual([]); | ||
| 232 | + const run = wdb.createRun({ graphKind: 'work', graphId: g.id, companyId: CO, executionMode: 'manual' }); | ||
| 233 | + engine.markRunReady(run.id); | ||
| 234 | + engine.startRun(run.id); | ||
| 235 | + | ||
| 236 | + const out = await engine.nextStep(run.id, { task: '逵溷ョ樣得霍ッ smoke夐ェ御ク莉ス髱樊ウ募・醍コヲ' }); | ||
| 237 | + if (!out.ok) throw new Error(`validator 豐。謗ィ蜉ィ${JSON.stringify(out)}`); | ||
| 238 | + // 霑吩ク、陦悟ーア譏ッ鬪梧噺 4 逧驛ィ**荳肴弍 success**御ク泌ス貞屏關ス莠コ | ||
| 239 | + expect(out.node.status).toBe('fail'); | ||
| 240 | + // fail_reason 蜿冶蟆溜蝓 ATTRIBUTION_REASONS 窶披 fixture 驥悟荳ェ閾ェ蛻帷噪隸堺シ夊「ォ | ||
| 241 | + // 謖芽ョセ隶。髯咲コァ謌 null亥シ墓梼荳崎ョ、隸噪蠖貞屏荳蠕倶ク堺ソ。会シ檎ャャ荳迚亥ーア譏ッ霑吩ケ育コ「逧 | ||
| 242 | + expect(out.node.failReason).toBe('input_underspecified'); | ||
| 243 | + // 霍ッ逕ア荵溯ヲ∬オー騾夲シ壼、ア雍・逧ク倶ク豁・譏ッ豐ソ fail 霎ケ轤ケ莠ョ荳区クク御ク肴弍蜴溷慍荳榊勘 | ||
| 244 | + expect((out.activated || []).map((a) => a.name)).toContain(AGENT); | ||
| 245 | + | ||
| 246 | + // 蛻、隸堺ケ溯ヲ∝クヲ荳句悉 窶披 豐。譛牙ョシ御ク倶ク霓ョ agent 荳咲衍驕楢ヲ∽ソョ莉荵茨シ按ァ蜈ォ.14 驍」譚。蝗帷識蜈ィ騾夂噪體セ霍ッ峨 | ||
| 247 | + // 豕ィ諢丞愛隸崎誠蝨ィ**陲ォ轤ケ莠ョ逧ク区クク闃らせ**驍」荳陦鯉シ御ク肴弍螟ア雍・闃らせ閾ェ蟾ア驍」荳陦鯉シ | ||
| 248 | + // 縲悟愛隸咲噪霓ス菴 = 轤ケ莠ョ螳噪驍」谺。迥カ諤∬スャ謐「縲搾シ瑚ソ呎キ螟壽擅蝗樣霎ケ蟷カ蟄俶慮螟ゥ辟カ荳堺クイ蜿ー縲 | ||
| 249 | + const downstream = wdb.getDb() | ||
| 250 | + .prepare(`SELECT remediation_note FROM graph_run_nodes | ||
| 251 | + WHERE run_id = ? AND def_node_id = (SELECT id FROM work_graph_nodes WHERE work_graph_id = ? AND node_name = ?)`) | ||
| 252 | + .get(run.id, g.id, AGENT); | ||
| 253 | + expect(downstream.remediation_note).toContain('test_script'); | ||
| 254 | + | ||
| 255 | + fs.rmSync(path.join(__dirname, '../../../system/agents', VALIDATOR, CO), { recursive: true, force: true }); | ||
| 256 | + }, 60_000); | ||
| 257 | + | ||
| 198 | it('竭「 霎ケ逡悟ョ亥梱蝨ィ霑呎擅霍ッ蠕ク頑弍**蠑逹**逧シ域ウィ蜈・蛛 executor 譌カ螳£荳コ蛛シ碁ぅ譚。蛻髪髮カ隕尠', () => { | 258 | it('竭「 霎ケ逡悟ョ亥梱蝨ィ霑呎擅霍ッ蠕ク頑弍**蠑逹**逧シ域ウィ蜈・蛛 executor 譌カ螳£荳コ蛛シ碁ぅ譚。蛻髪髮カ隕尠', () => { |
| 199 | // 蛻、謐ョ蜿冶蠑墓梼閾ェ蟾ア逧シ蜈ウ蜃ス謨ー瑚御ク肴弍蜴サ謨ー timeline 莠倶サカ | 259 | // 蛻、謐ョ蜿冶蠑墓梼閾ェ蟾ア逧シ蜈ウ蜃ス謨ー瑚御ク肴弍蜴サ謨ー timeline 莠倶サカ |
| 200 | // 螳亥梱蝨ィ螳ソ荳サ莉灘コ灘ケイ蜃譌カ譛ャ譚・蟆ア荳堺コァ逕滉コ倶サカ梧響縲梧イ。譛我コ倶サカ縲榊ス薙梧イ。蠑縲堺シ壼渚霑擂蛻、髞吶 | 260 | // 螳亥梱蝨ィ螳ソ荳サ莉灘コ灘ケイ蜃譌カ譛ャ譚・蟆ア荳堺コァ逕滉コ倶サカ梧響縲梧イ。譛我コ倶サカ縲榊ス薙梧イ。蠑縲堺シ壼渚霑擂蛻、髞吶 |
server/tests/unit/template-verdicts.test.js
No preview for this file type