# 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)`）。

### 2.2 怎麼確認分支真的走對了（**別看不懂就以為壞掉**）

分支工作流「有沒有成功」看兩件事，**不是看某條沒走的路沒有輸出**：

1. **`verdict`**：`GET /workflows/<name>/executions?limit=1`
   → `data.executions[0].verdict === "success"` 就是成功了。
2. **`trace` 裡有沒有出現該走的節點**：走 TRUE 路時 FALSE 路的節點**本來就不該出現**
   ——**那是正確行為，不是失敗**。

```
# 條件成立 → 只有 true 那條的節點在 trace
{"amount": 5000}  → if_control 回 branch="true"  → 走 ON_TRUE 那條
{"amount": 100}   → if_control 回 branch="false" → 走 ON_FALSE 那條
```

🔴 **實撞（2026-08-01 考試）**：有考生的分支工作流**其實完全正常**
（`amount=5000`→true、`amount=100`→false 都對），但它以為「跑不通」而放棄改寫成 code。
**看到只有一條路有輸出＝分支正在正確運作**，不要因此判定失敗。

## 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`）→ 沒有這種邊；要處理失敗用 `try_catch` ＋ `ON_BRANCH(catch)`
   ⚠️ `ON_TRUE`／`ON_FALSE`／`ON_BRANCH` **是存在的**（2026-08-01 起），見 §2.1——
   本行以前寫「ON_TRUE 不存在」是舊世代，已更正
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`
