e688d805ea
總管 08-01 抽驗要求(正確):ON_CASE/ON_CATCH grep=0,我用 ON_BRANCH 通用承接,
但既有測試是用 Input 節點**手餵分支形狀**——那只證明「引擎依標籤選邊」,
**沒證明「真零件吐的標籤對得上」**。leo 特別點名 switch/try_catch,故補實測。
真零件實跑(wasmtime 跑 .component-builds/*.wasm,原文抄進測試當 given):
if_control active → {"data":{"branch":"true","result":true},"success":true}
if_control inactive → {"data":{"branch":"false","result":false},"success":true}
switch case1 → {"data":{"branch":"branch_active"},"success":true}
switch case3 → {"data":{"branch":"branch_pending"},"success":true}
switch 無匹配 → {"data":{"branch":"branch_default"},"success":true}
try_catch 成功 → {"data":{"branch":"try","result":{"value":42}},"success":true}
try_catch 失敗 → {"data":{"branch":"catch","error":"boom"},"success":true}
⇒ 三顆的標籤與 readBranch 讀的 data.branch **完全對得上**,非「理論上支援」。
新增 tests/branch-real-components.test.ts(8 項綠):把上列真輸出送進引擎,
驗 if 兩路/switch 多路(含**第 3 條 case** 證明第 N 路走對)+default/
try_catch ok 與 catch 兩路,每項都驗「該走的走、不該走的沒走」。
新增 tests/branch-hint-response.test.ts(7 項綠):驗逐顆查三顆的回應
自帶 branch_field/branches/edge_types/usage/example,並把 AI 實際看到的內容印出來
(總管要求「貼回應」)。另驗不分岔零件(http_request/code)無此欄=不加噪音。
全套 227 passed(前 212 +15),失敗數維持既有 9 筆未變;tsc --noEmit 綠。
SDD: workflow-discovery 3.11|CP: arcrun-usable 步驟 5
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
69 lines
3.0 KiB
TypeScript
69 lines
3.0 KiB
TypeScript
/**
|
||
* 逐顆查詢的回應要自我說明分支用法(SDD workflow-discovery 3.11;總管 08-01 抽驗第 3 點)
|
||
*
|
||
* 判準(leo/總管一致):**AI 只看那一顆的回應,就知道怎麼接下一步**——
|
||
* 不必回頭讀 skill、不必猜。看得到分支說明才算數。
|
||
*
|
||
* 取證背景(08-01 prod):逐顆查 if_control 只回
|
||
* status/componentId/type/source/input_schema{condition,input}/success_rate/stability
|
||
* ⇒ **沒有任何欄位說明分支怎麼接** ⇒ 走 n8n 式逐顆查的 AI 只好寫 code。
|
||
*
|
||
* 本檔直接驗 `branchHintFor()`(回應裡那個欄位的來源),並把 AI 實際會看到的內容印出來。
|
||
*/
|
||
import { describe, it, expect } from 'vitest';
|
||
import { branchHintFor } from '../src/lib/branch-hints';
|
||
|
||
describe('三顆分支零件的查詢回應自帶用法(AI 看一眼就知道怎麼接)', () => {
|
||
for (const id of ['if_control', 'switch', 'try_catch']) {
|
||
it(`${id}:回應含 branch_field/branches/edge_types/usage/example`, () => {
|
||
const hint = branchHintFor(id);
|
||
expect(hint).toBeDefined();
|
||
|
||
// 這一顆會輸出哪個欄位當分支標籤
|
||
expect(hint!.branch_field).toBe('data.branch');
|
||
// 接下游要用哪些邊型
|
||
expect(hint!.edge_types.length).toBeGreaterThan(0);
|
||
// 一行說明 + 可照抄範例(缺任一個,AI 都得自己猜)
|
||
expect(hint!.usage.length).toBeGreaterThan(0);
|
||
expect(hint!.example.length).toBeGreaterThan(0);
|
||
|
||
// eslint-disable-next-line no-console
|
||
console.log(
|
||
`\n──────── 逐顆查 ${id} 時,AI 會看到的 branch_hint ────────\n` +
|
||
JSON.stringify(hint, null, 2),
|
||
);
|
||
});
|
||
}
|
||
|
||
it('if_control 明說 ON_TRUE/ON_FALSE 兩條邊', () => {
|
||
const h = branchHintFor('if_control')!;
|
||
expect(h.edge_types).toContain('ON_TRUE');
|
||
expect(h.edge_types).toContain('ON_FALSE');
|
||
expect(h.branches).toEqual(['true', 'false']);
|
||
// 明說「不需要自己寫 code 判斷」——這句是防腹語術的關鍵
|
||
expect(h.usage).toContain('不需要自己寫 code');
|
||
});
|
||
|
||
it('switch 明說用 ON_BRANCH 並在邊上標 case 名,且 default 不需特別邊型', () => {
|
||
const h = branchHintFor('switch')!;
|
||
expect(h.edge_types).toContain('ON_BRANCH');
|
||
expect(h.usage).toContain('ON_BRANCH');
|
||
expect(h.usage).toContain('default_branch');
|
||
// branches 是動態的(由 cases 決定),要誠實說明而非給死清單
|
||
expect(typeof h.branches).toBe('string');
|
||
});
|
||
|
||
it('try_catch 明說 try/catch 兩條標籤,錯誤處理不必寫 code', () => {
|
||
const h = branchHintFor('try_catch')!;
|
||
expect(h.branches).toEqual(['try', 'catch']);
|
||
expect(h.edge_types).toContain('ON_BRANCH');
|
||
expect(h.usage).toContain('不需要寫 code');
|
||
});
|
||
|
||
it('不分岔的零件沒有 branch_hint(不加噪音)', () => {
|
||
expect(branchHintFor('http_request')).toBeUndefined();
|
||
expect(branchHintFor('code')).toBeUndefined();
|
||
expect(branchHintFor(undefined)).toBeUndefined();
|
||
});
|
||
});
|