a9a47b7c37
備考 haiku 真考時自查發現的兩個斷點——**若不補,考試必掛,且掛的是我自己的教材**。
形狀=步驟1 那個「世代脫節」的翻版:能力做好了,但教 AI 的地方還停在舊世代。
斷點①:三處教材主動說「沒有條件分支」,還教了正好造成腹語術的替代法
- mcp/src/mcp-handler.ts:44「**沒有** ON_TRUE/ON_FALSE——引擎目前不支援條件分支」
- registry/skills/write_intent_workflow.md:39「不要寫 ON_TRUE/ON_FALSE…
需要判斷時**寫成一個獨立節點**再接 ON_SUCCESS」← 這正是「判斷退回 code」的入口
- registry/skills/INDEX.md:44「已知的坑:引擎沒有條件分支」
⇒ 三處全部更新成現況(三顆零件都輸出 data.branch、引擎依標籤選路、
查零件回應附 branch_hint 照著接即可),並保留「不要寫 ON_FAILURE」(那個真的沒有)。
斷點②(更隱蔽,靜默失效):`graph-builder` 只認得 `對每個 X` 的參數化 label,
`ON_BRANCH(branch_active)` 帶括號會落到 toEdgeType 預設值 **PIPE**
⇒ 我在 skill 教的寫法,編圖收不到,而且**不報錯**——AI 以為分支了、實際全走同一條。
「教了語法但引擎不收」比沒做更糟,故與文件同批補上:比照 FOREACH 抽 iterator 的作法
抽 branch 標籤(半形/全形括號都收),寫進 edge.branch。
新增 tests/intent-branch-syntax.test.ts(7 項綠):守「文件教的寫法,編圖真的收得到」
——ON_TRUE/ON_FALSE 不退化成 PIPE、中文「成立時/否則」、ON_BRANCH(標籤) 抽得出 branch、
全形括號、try/catch 標籤;零變化:ON_SUCCESS 仍是 ON_SUCCESS、對每個 X 的 iterator 不受干擾。
全套 234 passed(前 227 +7),失敗數維持既有 9 筆;tsc 綠。
SDD: workflow-discovery 3.11|CP: arcrun-usable 步驟 5
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
172 lines
6.8 KiB
Markdown
172 lines
6.8 KiB
Markdown
# Skill: Write Intent Workflow(寫意圖工作流)
|
||
|
||
## 何時用這個 skill
|
||
|
||
**用戶說「幫我用 Arcrun 做 X」時,第一個讀這支。** 其他 skill 都是它的下游。
|
||
|
||
- 「幫我用 Arcrun 寫一個…」
|
||
- 「用 Arcrun 做 X」
|
||
- 你要在 Arcrun 上做任何事,但不知道有哪些零件可用
|
||
|
||
> **你不需要知道有哪些零件。** 先把意圖寫出來丟去查,系統會告訴你哪些存在、哪些不存在。
|
||
|
||
## 核心 pattern
|
||
|
||
```
|
||
input >> ON_SUCCESS >> <第一步> >> ... → 丟 /cypher/search → 系統回哪些零件存在
|
||
```
|
||
|
||
---
|
||
|
||
## 1. 意圖工作流的語法
|
||
|
||
一串「誰接誰」,每行一個關係:
|
||
|
||
```
|
||
<節點A> >> <邊> >> <節點B>
|
||
```
|
||
|
||
- **節點**=一個步驟。用你想得到的名字(中文可以),**不必是真實零件名**
|
||
- **邊**=什麼情況下往下走
|
||
|
||
## 2. 邊有這些
|
||
|
||
| 邊 | 意思 | 真例 |
|
||
|---|---|---|
|
||
| `ON_SUCCESS` | 上一步成功就往下 | `input >> ON_SUCCESS >> prep` |
|
||
| `對每個 <變數>` | 上一步產出清單,逐項處理(FOREACH)| `parse_card >> 對每個 block >> post_block` |
|
||
| `ON_TRUE` / `ON_FALSE` | 條件成立/不成立各走一條(配 `if_control`)| `判斷有沒有新資料 >> ON_TRUE >> 傳到 telegram` |
|
||
| `ON_BRANCH`+`branch:` | 依標籤選路(配 `switch` 每個 case、`try_catch` 的 try/catch)| `my_switch >> ON_BRANCH(branch_active) >> 處理啟用` |
|
||
|
||
### 2.1 條件分支怎麼寫(2026-08-01 起引擎支援)
|
||
|
||
**需要判斷時,用分支邊,不要寫 `code` 判斷。**
|
||
三顆流程控制零件都輸出 `data.branch` 標籤,引擎依標籤選路:
|
||
|
||
| 零件 | 輸出的標籤 | 接法 |
|
||
|---|---|---|
|
||
| `if_control` | `"true"` / `"false"` | `ON_TRUE`/`ON_FALSE` 各一條 |
|
||
| `switch` | 你在 `cases[].branch` 取的名字(沒中則 `default_branch`)| 每條路一條 `ON_BRANCH`,邊上標 `branch` |
|
||
| `try_catch` | `"try"`(沒錯)/`"catch"`(有錯)| 兩條 `ON_BRANCH`,標 `try` 與 `catch` |
|
||
|
||
```
|
||
判斷有沒有新資料 >> ON_TRUE >> 傳到 telegram
|
||
判斷有沒有新資料 >> ON_FALSE >> 結束
|
||
```
|
||
中文語意詞亦可:「成立時」=`ON_TRUE`、「否則」=`ON_FALSE`。
|
||
|
||
💡 **不必背**:查零件時回應會附 `branch_hint`(有哪些標籤、用哪些邊型、可照抄的範例),
|
||
照著接就對了。
|
||
|
||
⚠️ 仍然**不要寫 `ON_FAILURE`**(沒有這種邊;要處理失敗用 `try_catch` + `ON_BRANCH(catch)`)。
|
||
|
||
## 3. 第一個節點固定是 `input`
|
||
|
||
所有真範本都以 `input` 起頭——那是「觸發時帶進來的資料」。
|
||
|
||
---
|
||
|
||
## 4. 真範本(照抄結構、改內容)
|
||
|
||
> 以下四份**全部是實際部署且 `verdict=success` 的 workflow**,不是簡化示範。
|
||
> 用 `arcrun_get_workflow(<name>)` 可以拿完整定義。
|
||
|
||
### A. 最短:取資料 → 處理 (`graph_neighbors`)
|
||
```
|
||
input >> ON_SUCCESS >> fetch_triplets
|
||
fetch_triplets >> ON_SUCCESS >> bfs_neighbors
|
||
```
|
||
|
||
### B. 長鏈:多次查詢 → 組裝 → 問 AI → 收尾 (`rag_chat`)
|
||
```
|
||
input >> ON_SUCCESS >> prep
|
||
prep >> ON_SUCCESS >> kw_search
|
||
kw_search >> ON_SUCCESS >> sem_search
|
||
sem_search >> ON_SUCCESS >> fetch_triplets
|
||
fetch_triplets >> ON_SUCCESS >> fetch_blocks_a
|
||
fetch_blocks_a >> ON_SUCCESS >> assemble
|
||
assemble >> ON_SUCCESS >> ask_llm
|
||
ask_llm >> ON_SUCCESS >> finalize
|
||
```
|
||
`prep` 前處理/`assemble` 組 prompt/`finalize` 收拾回應——三個常見的整形節點。
|
||
|
||
### C. 一節點分岔兩條 FOREACH (`rag_ingest_card`)
|
||
```
|
||
input >> ON_SUCCESS >> parse_card
|
||
parse_card >> 對每個 block >> post_block
|
||
parse_card >> 對每個 rel >> post_triplet
|
||
```
|
||
同一節點可有多條出邊,各自處理不同清單。
|
||
|
||
### D. 混合:直線 + 兩段 FOREACH (`rag_takedown_direct`)
|
||
```
|
||
input >> ON_SUCCESS >> prep
|
||
prep >> ON_SUCCESS >> list_dead_blocks
|
||
list_dead_blocks >> ON_SUCCESS >> build_deprecations
|
||
build_deprecations >> 對每個 dead_entry >> deprecate_entry
|
||
build_deprecations >> ON_SUCCESS >> list_triplets
|
||
list_triplets >> ON_SUCCESS >> pick_dead_triplets
|
||
pick_dead_triplets >> 對每個 dead_record >> deprecate_triplet
|
||
```
|
||
`build_deprecations` 同時有 FOREACH 出邊與 `ON_SUCCESS` 出邊——
|
||
前者處理清單、後者繼續主線。
|
||
|
||
---
|
||
|
||
## 5. 節點怎麼命名(照真範本的模式,查詢較容易媒合)
|
||
|
||
| 意圖 | 模式 | 真例 |
|
||
|---|---|---|
|
||
| 前處理/正規化 | `prep` | `rag_chat.prep` |
|
||
| 取一批資料 | `fetch_*`/`list_*` | `fetch_triplets`/`list_dead_blocks` |
|
||
| 搜尋 | `*_search` | `kw_search`/`sem_search` |
|
||
| 解析/切塊 | `parse_*` | `parse_card` |
|
||
| 寫入 | `post_*` | `post_block`/`post_triplet` |
|
||
| 組裝 | `assemble`/`build_*` | `assemble`/`build_deprecations` |
|
||
| 問 AI | `ask_llm` | `rag_chat.ask_llm` |
|
||
| 收尾整形 | `finalize` | `rag_chat.finalize` |
|
||
|
||
---
|
||
|
||
## 6. 寫完一定要查(**不要直接部署**)
|
||
|
||
```bash
|
||
curl -s -X POST https://arcrun-cypher-executor.<subdomain>.workers.dev/cypher/search \
|
||
-H 'content-type: application/json' -H 'X-Arcrun-API-Key: <namespace>' \
|
||
-d '{"triplets":["input >> ON_SUCCESS >> fetch_data","fetch_data >> ON_SUCCESS >> notify"]}'
|
||
```
|
||
|
||
回應的每個節點會有:
|
||
|
||
| status | 意思 | 你該做什麼 |
|
||
|---|---|---|
|
||
| `found` | 有這個節點。`source: component` 附 `input_schema`(怎麼填 payload)與 `success_rate`;`source: recipe` 附 description/endpoint | **只填 payload** |
|
||
| `not_found` | **兩庫(零件 registry+recipe 庫)都查過,確定沒有** | 照 `suggestion` 欄走:缺 API → 寫 recipe(skill `write_recipe`);缺計算能力 → 投稿零件 PR(skill `add_new_wasm_component`)。`similar_components`/`similar_recipes` 是相近候選——先看有沒有現成的能直接用 |
|
||
| `unknown` | 查不到 registry | **不代表不存在**,別據此改寫成 code |
|
||
|
||
> 註(2026-07-31):`/cypher/search` 曾對任何節點名都回假 `found`,已修為真查兩庫。
|
||
> 舊實例(未更新部署)仍可能假 found——status 可信度以該實例部署版本為準。
|
||
|
||
---
|
||
|
||
## 7. 常犯的錯
|
||
|
||
1. **用不存在的邊**(`ON_FAILURE`/`ON_TRUE`)→ 只有 `ON_SUCCESS` 與 `對每個 X`
|
||
2. **第一個節點不是 `input`**
|
||
3. **把 recipe 當零件寫**——`telegram_send`/`gmail`/`kbdb_get` 是 **recipe** 不是零件
|
||
→ 寫成 `http_request` + 該 recipe
|
||
4. 🔴 **查詢回 `not_found` 就改寫成 `code` 節點**
|
||
→ 那叫「腹語術」(表面用 Arcrun、實際全寫 JS)。正解:缺 API 寫 recipe、缺能力投稿零件。
|
||
`code` 只用在**局部整形**(例:剝掉 LLM 回應的雜訊),不用來取代零件與流程控制。
|
||
|
||
---
|
||
|
||
## 8. 相關
|
||
|
||
- 完整版指引與十題考卷(含 haiku 實測 10/10):
|
||
頂層 repo `system-dev/docs/3-specs/arcrun-usable/`
|
||
- 下一步該讀哪支 skill:`arcrun_list_skills()`
|
||
- 定期掃資料 → `build_watcher_workflow`
|
||
- RAG 檢索問答 → `rag_with_arcrun`
|
||
- workflow 卡住不動 → `debug_paused_workflow`
|