chore: D22 落地——docs/SDD/wiki/CLAUDE.md 進 repo(Gitea private 預設全 push)
頂層 D22 決策(leo 2026-07-03 拍板):推什麼由開發環境歸屬決定, Gitea private=除機敏值/build 產物/.github 外全 push。 解 T1.5 卡點:雲端工人 clone 拿得到 credential-store-migration.md,可就地改寫 SDD。 機敏掃描兩輪通過(新增 189 檔約 2.1MB,node_modules/dist/wasm 照舊排除)。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
# 部署慣例(CI/CD)
|
||||
|
||||
> **核心原則:新增 Worker = 新目錄 + `wrangler.toml`,不用改 workflow。**
|
||||
|
||||
`.github/workflows/deploy.yml` 是**通用掃描式** workflow,不該為每個 Worker 手寫 job。
|
||||
|
||||
---
|
||||
|
||||
## Workflow 如何找到要部署的 Worker?
|
||||
|
||||
```
|
||||
find . -name 'wrangler.toml' -not -path '*/node_modules/*' -not -name 'wrangler.test.toml'
|
||||
```
|
||||
|
||||
每一個命中的目錄 = 一個部署單位。無論是:
|
||||
|
||||
- `cypher-executor/` (orchestration Worker)
|
||||
- `registry/` (合約管理 Worker)
|
||||
- `.component-builds/{name}/` (零件 Worker,25+ 個)
|
||||
- 未來新增的任何 Worker
|
||||
|
||||
**無需改 workflow,只要符合掃描規則就會自動部署**。
|
||||
|
||||
---
|
||||
|
||||
## 觸發邏輯
|
||||
|
||||
| 觸發 | 部署範圍 |
|
||||
|------|---------|
|
||||
| `push` 到 main | diff 涉及的 Worker 目錄才部署 |
|
||||
| `push` 到 main + 改 `registry/components/{name}/` | 連動 rebuild `.component-builds/{name}/component.wasm` 再 deploy |
|
||||
| `workflow_dispatch` + `force_all=true` | 全部 Worker |
|
||||
| `workflow_dispatch` + `only=a,b,c` | 只部署指定清單 |
|
||||
| `push` 但 base sha 不可及(首次) | 全部 Worker |
|
||||
|
||||
---
|
||||
|
||||
## 新增 Worker 的步驟
|
||||
|
||||
### 如果是新 WASM 零件 Worker
|
||||
|
||||
1. 在 `registry/components/{new_name}/` 建 `main.go` + `component.contract.yaml`
|
||||
2. 在 `.component-builds/{new_name}/` 建 Worker 模板:
|
||||
- `wrangler.toml`(name/routes/bindings)
|
||||
- `package.json`(hono + workers-types + wrangler 即可,參考 `auth_static_key/package.json`)
|
||||
- `tsconfig.json`(可直接複製)
|
||||
- `src/index.ts`(WASI shim,方案 A:import `../../cypher-executor/src/lib/wasi-shim`)
|
||||
3. 本地跑 `pnpm install` 產 `pnpm-lock.yaml`
|
||||
4. 本地跑 `tinygo build -target=wasi -o {new_name}.wasm main.go` 先驗證 build 通過
|
||||
5. Commit push → CI 自動 rebuild WASM + deploy
|
||||
|
||||
### 如果是新 orchestration/service Worker
|
||||
|
||||
1. 在 repo 根建新目錄(類似 `cypher-executor/`)
|
||||
2. `wrangler.toml` + `package.json` + `pnpm-lock.yaml` + `src/index.ts` + `tsconfig.json`
|
||||
3. Push → CI 自動部署
|
||||
|
||||
---
|
||||
|
||||
## Runtime Secret 管理
|
||||
|
||||
**CI 只提供 Cloudflare 驗證,不碰 runtime secret**。
|
||||
|
||||
- GH Actions secrets:`CLOUDFLARE_API_TOKEN`、`CLOUDFLARE_ACCOUNT_ID`(一次性設好)
|
||||
- Runtime secret(例:`ENCRYPTION_KEY`、`OPENAI_KEY`、`GOOGLE_API_KEY`):
|
||||
- **由 richblack 一次性手動** `wrangler secret put <KEY>` 設進各 Worker
|
||||
- 不進 CI,不進 `wrangler.toml` `[vars]`
|
||||
- 需要的 Worker:`auth_static_key`、`auth_service_account`(兩個都要 `ENCRYPTION_KEY`)
|
||||
|
||||
---
|
||||
|
||||
## Lockfile 規範
|
||||
|
||||
- **統一使用 pnpm**。新增 Worker 只放 `pnpm-lock.yaml`,不要 `package-lock.json`
|
||||
- 若新建 Worker 時用 `npm install` 產出 `package-lock.json`,**刪掉它**,改跑 `pnpm install`
|
||||
- `cypher-executor/` 和 `registry/` 的 `package-lock.json` 已於 2026-04-20 刪除
|
||||
|
||||
**現存例外**(歷史遺產,混合期不強制遷移):
|
||||
- `.component-builds/{if_control, switch, ... 16 個舊邏輯零件}/` 仍是 `package-lock.json`,workflow 有 fallback 分支(`pnpm install --no-frozen-lockfile`)可跑
|
||||
- `builtins/`、`landing/` 同上
|
||||
|
||||
**新增 Worker 一律 pnpm,不要製造新的混合情況**。
|
||||
|
||||
---
|
||||
|
||||
## WASM 來源
|
||||
|
||||
> **⚠️ 慣例變更(richblack 2026-06-02,self-hosted 開源策略)**:
|
||||
> 原慣例「`.component-builds/{name}/component.wasm` 不 commit 進 repo」**已推翻**。
|
||||
> 現在 **commit `.component-builds/*/component.wasm` 進 repo**,因為 self-host 用戶 / `acr init --self-hosted`
|
||||
> 從 GitHub(codeload tarball)直接拿這份 wasm 部署到自己的 CF——repo 必須自帶可部署的 wasm。
|
||||
> 決策依據:`docs/3-specs/arcrun/sdk-and-website/self-hosted-init.md §6`。
|
||||
|
||||
### 現行規則(2026-06-02 起)
|
||||
|
||||
- **`.component-builds/*/component.wasm` → commit 進 repo**(部署來源)。`.gitignore` 用否定規則放行:
|
||||
```
|
||||
*.wasm # 預設排除
|
||||
!.component-builds/**/component.wasm # 例外放行部署物
|
||||
```
|
||||
- **`registry/components/*.wasm` → 仍不 commit**(build 中間產物,部署不直接用,`.gitignore` 仍排除)。
|
||||
- 本地開發 build:`cd registry/components/{name} && tinygo build -target=wasi -o {name}.wasm main.go && cp {name}.wasm ../../../.component-builds/{name}/component.wasm`,**然後 commit `.component-builds/{name}/component.wasm`**。
|
||||
- CI(deploy.yml):仍在 deploy 前自動 rebuild + copy(部署 prod 用最新 source;與 repo 內 commit 的 wasm 不衝突——前者給 CI deploy prod,後者給 self-host 用戶當部署來源)。
|
||||
|
||||
### 誠實 trade-off(mindset §7)
|
||||
|
||||
commit wasm 進 repo → 每次 rebuild 在 git 歷史累積二進位,**repo 長期會膨脹**。
|
||||
可接受(self-host 體驗優先),未來若膨脹過劇再考慮 git-lfs / 按需安裝(self-hosted-init.md §6.6)。
|
||||
|
||||
---
|
||||
|
||||
## 並行度
|
||||
|
||||
`max-parallel: 5` — 避免觸發 Cloudflare Workers API rate limit。
|
||||
|
||||
Worker 數量 > 5 時,deploy 會分批跑。25 個 Worker 大約 5 輪 × ~30 秒 = 2-3 分鐘可完成全部。
|
||||
|
||||
---
|
||||
|
||||
## 禁止事項
|
||||
|
||||
1. **禁止**為新 Worker 手動加 deploy job 到 `deploy.yml`。通用掃描會自動處理,手加就是重複工作。
|
||||
2. **禁止**把 runtime secret(API key / encryption key / credential)放進 GH Actions secrets 或 `wrangler.toml` `[vars]`,只能用 `wrangler secret put`。
|
||||
3. **禁止**在 CI 裡跑不必要的測試阻擋 deploy。測試在 PR / 本地跑,`main` 推上去就 deploy(trunk-based)。若要測試關,開新 workflow 檔,不要污染 deploy workflow。
|
||||
4. **禁止**跳過 TinyGo rebuild 直接 deploy 舊 `.wasm`。CI 的 rebuild 步驟是確保部署的是最新 source。
|
||||
|
||||
---
|
||||
|
||||
## 驗證指令
|
||||
|
||||
本地模擬 CI 的掃描結果:
|
||||
|
||||
```bash
|
||||
find . -name 'wrangler.toml' -not -path '*/node_modules/*' -not -name 'wrangler.test.toml' \
|
||||
| xargs -n1 dirname | sort -u
|
||||
```
|
||||
|
||||
應列出 ~25 個目錄。任何「我新增了 Worker 但沒被 deploy」的問題,先跑這條確認目錄被掃到。
|
||||
@@ -0,0 +1,312 @@
|
||||
# Arcrun for AI Agents
|
||||
|
||||
> 給 AI 操盤手(Claude Code、Cursor、Codex、自製 agent)的 onboarding。
|
||||
> 載入這份就能用 arcrun,不需要讀 SDD 內部架構、不需要 grep codebase、不需要問人。
|
||||
>
|
||||
> 對應 SDD:`docs/3-specs/llm-interface/`(v0.1,2026-05-16)
|
||||
|
||||
---
|
||||
|
||||
## 1. Arcrun 是什麼(30 秒)
|
||||
|
||||
Arcrun = 用 YAML 把 WASM 零件串成可重複執行 workflow 的平台。**用戶寫 YAML,平台跑**。
|
||||
|
||||
- 每個零件是 TinyGo / AssemblyScript 編譯的 `.wasm`,stdin/stdout JSON I/O
|
||||
- 每個 workflow 是一份 cypher binding YAML,描述「節點 + 邊」的圖
|
||||
- 觸發機制:HTTP webhook、cron、callback resume
|
||||
- 部署完成回 `webhook_url`,用戶或下游服務 POST 即可執行
|
||||
|
||||
n8n 從手寫程式碼開始,arcrun 從 AI 描述開始:你跟用戶聊出他想要什麼自動化,**你(AI)寫 YAML 部署,之後不需要 AI 也能跑**。
|
||||
|
||||
---
|
||||
|
||||
## 2. 連線(一步搞定)
|
||||
|
||||
加到你的 MCP config(Claude Desktop / Cursor / 任何支援 MCP 的 client):
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"arcrun": {
|
||||
"type": "http",
|
||||
"url": "https://mcp.arcrun.dev/mcp",
|
||||
"headers": {
|
||||
"Authorization": "Bearer ak_YOUR_API_KEY"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> **暫時**:M5 完成前 URL 仍是 `https://mcp.finally.click/mcp`,預計 2026-06 切。
|
||||
> Tool 命名暫時仍是 `u6u_*` prefix,M5 一次改 `arcrun_*`。
|
||||
> 本 doc 描述目標狀態,實際用 `list_*` tool 取得當前可用名單。
|
||||
|
||||
取得 ak_ 金鑰:到 https://arcrun.dev/me(OAuth Google / GitHub 登入),右下角複製。
|
||||
|
||||
---
|
||||
|
||||
## 3. 五個核心概念
|
||||
|
||||
| 概念 | 一句話 |
|
||||
|---|---|
|
||||
| **Component(零件)** | WASM Worker,獨立部署成 `arcrun-{kebab}.{user}.workers.dev`。用 `list_components` 看可用清單 |
|
||||
| **Cypher binding** | YAML 三元組 `A >> 關係 >> B`,定義 workflow 圖。常用關係:`ON_SUCCESS` / `對每個 X` / `IF` |
|
||||
| **FOREACH** | `>> 對每個 item >> next_node` 迭代陣列。`item` 變數自動可用 |
|
||||
| **Paused-resume** | claude_api 等需等外部 callback 的零件會「paused」,cypher-executor 透過 `/workflows/resume` 接續 |
|
||||
| **api_key (ak_xxx)** | 所有 call 必帶(MCP header 或 workflow `{{api_key}}`),同時當 partition key |
|
||||
|
||||
---
|
||||
|
||||
## 4. 你的第一個 workflow(5 分鐘 e2e)
|
||||
|
||||
### Step 1:看有什麼零件可用
|
||||
```
|
||||
arcrun_list_components() # 全部零件名單
|
||||
# 或
|
||||
arcrun_search_examples('rag') # 範例庫搜尋(從 use case 找範本)
|
||||
arcrun_list_skills() # 看 playbook 清單
|
||||
arcrun_get_skill('build_watcher_workflow') # 拿特定 playbook 細節
|
||||
```
|
||||
常用零件:`http_request`、`claude_api`、`kbdb_get`、`kbdb_create_block`、`telegram`、`gmail`、`cron`、`filter`、`trigger_workflow`。
|
||||
|
||||
### Step 2:寫 minimal YAML(從範例改 > 從零寫)
|
||||
|
||||
```yaml
|
||||
name: hello_world
|
||||
description: 接 webhook,回個 hi
|
||||
|
||||
flow:
|
||||
- "input >> ON_SUCCESS >> say_hi"
|
||||
|
||||
config:
|
||||
say_hi:
|
||||
component: http_request
|
||||
url: "https://httpbin.org/post"
|
||||
method: POST
|
||||
body_json:
|
||||
hello: "{{input.name}}"
|
||||
```
|
||||
|
||||
### Step 3:dry-run 校驗
|
||||
```
|
||||
arcrun_validate_yaml(api_key, graph)
|
||||
```
|
||||
|
||||
### Step 4:部署
|
||||
```
|
||||
arcrun_push_workflow(api_key, yaml_content)
|
||||
```
|
||||
回 `{name, webhook_url: 'https://cypher.arcrun.dev/webhooks/named/hello_world/trigger'}`。
|
||||
|
||||
### Step 5:觸發測試
|
||||
```
|
||||
arcrun_run_workflow(api_key, name='hello_world', input={name: 'leo'})
|
||||
```
|
||||
|
||||
### Step 6:看結果 / debug
|
||||
```
|
||||
arcrun_list_recent_executions(api_key, workflow_name='hello_world')
|
||||
# 若 paused:
|
||||
arcrun_list_paused_executions(api_key)
|
||||
arcrun_get_execution_trace(api_key, task_id='task_XXX')
|
||||
```
|
||||
|
||||
### Step 7:回報(**必做**,見 §8)
|
||||
```
|
||||
arcrun_report_feedback(api_key, issue_type='success_story', description='...')
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. URL 慣例(很重要,搞錯會撞 522)
|
||||
|
||||
| URL pattern | 用途 |
|
||||
|---|---|
|
||||
| `cypher.arcrun.dev` | Orchestration API(你的 workflow CRUD + trigger 走這) |
|
||||
| `arcrun-{kebab}.{user}.workers.dev` | 零件 worker(cypher-executor 走 workers.dev 對內 URL,避 CF 同 zone 自循環死鎖) |
|
||||
| `{kebab}.arcrun.dev` | 零件 worker 對外公開 URL(用戶 / 直接 curl 用,cypher-executor 不要走這) |
|
||||
| `kbdb-*.arcrun.dev` | KBDB 操作(資料層) |
|
||||
| `mcp.arcrun.dev` | MCP server(**你**用這個) |
|
||||
| `mcp.finally.click` | MCP server 舊網址(過渡) |
|
||||
|
||||
**踩坑警示**:cypher-executor 自打 `cypher.arcrun.dev` 或自打 `arcrun-cypher-executor.*.workers.dev` 都會撞 CF self-fetch 防護回 1042/522。要 in-process 觸發另一個 workflow,**用內建零件 `trigger_workflow`**(不是 `http_request` 自打)。
|
||||
|
||||
---
|
||||
|
||||
## 6. 常見錯誤 + 怎麼讀
|
||||
|
||||
| error_code | 含義 | 你該做什麼 |
|
||||
|---|---|---|
|
||||
| `auth_missing` / `auth_invalid` | ak_ 沒帶 / 錯了 | 去 https://arcrun.dev/me 重拿,更新 MCP config |
|
||||
| `component_not_found` | 零件名打錯 | call `list_components()` 看正確名 |
|
||||
| `component_not_in_whitelist` | 零件存在但 cypher-executor 不認 | 告訴用戶聯絡平台維護者(這是平台 bug) |
|
||||
| `validation_failed` | YAML / schema 不過 | 看 response 的 `next_actions` 陣列,照著修 |
|
||||
| `running_async` (status field) | workflow 已接受,在背景跑等 callback(claude_api 等) | **正常**,wait 或 call `get_execution_trace` 看狀態。舊名 `paused_awaiting_resume` 2026-05-16 改 |
|
||||
| `dependency_unavailable` | 下游 API(Claude / Gmail / KBDB)掛 | retry,仍掛 → 公告型 issue |
|
||||
|
||||
---
|
||||
|
||||
## 7. 不確定的時候,按這個順序
|
||||
|
||||
1. **不知道有什麼零件可用** → `arcrun_list_components()` / `arcrun_get_component_contract(id)`
|
||||
2. **不知道用戶有什麼 workflow** → `arcrun_list_workflows(api_key)`
|
||||
3. **想看零件 input/output schema** → `arcrun_get_component_contract('xxx')`
|
||||
4. **要不要 dry-run** → 預設 yes,永遠先 `arcrun_validate_yaml` 再 `arcrun_push_workflow`
|
||||
5. **觸發後不知道結果** → `arcrun_list_recent_executions(api_key, name)` / `arcrun_get_execution_trace(api_key, task_id)`,paused 不算錯
|
||||
6. **有沒有現成範例可參考** → `arcrun_search_examples('rag llm chain')`(範例庫 10+ 個 workflow)
|
||||
7. **有沒有 playbook** → `arcrun_list_skills() / arcrun_get_skill(slug)`(5 個 playbook:watcher / paused-debug / migrate-trigger / rag / new-component)
|
||||
8. **不知道下一步** → 看任何 error response 的 `next_actions` 陣列
|
||||
|
||||
### 過渡期 tool 命名注意
|
||||
|
||||
LI 開發中(2026-05-16~)。目前 arcrun-mcp 同時提供:
|
||||
- **`arcrun_*`**(新規範,**主用這套**):報 feedback / 工作流 CRUD / 執行 trace
|
||||
- **`u6u_*`**(舊規範,等 M5 一次切):component 操作、tag 操作、GUI context
|
||||
|
||||
舊 `u6u_*` 仍可用。其中 `u6u_deploy_workflow` 是壞的(呼叫不存在的 endpoint),用 `arcrun_push_workflow` 取代。
|
||||
|
||||
---
|
||||
|
||||
## 8. 回報機制(**必做**)
|
||||
|
||||
平台用回饋資料 self-improve。**每次部署 workflow / 卡住 / 解掉問題後**,call:
|
||||
|
||||
```typescript
|
||||
report_feedback({
|
||||
workflow_name: "hello_world", // 你剛做的 workflow
|
||||
issue_type:
|
||||
| "success_story" // 順利完成,值得記錄這個 pattern
|
||||
| "doc_unclear" // AGENTS.md / skill / contract 講不清楚
|
||||
| "tool_missing" // 該有的 MCP tool 沒有
|
||||
| "error_unhelpful" // 錯誤訊息看不懂下一步
|
||||
| "unexpected_behavior" // 跟我預期的不一樣
|
||||
| "feature_request", // 我想要 X 功能
|
||||
description: "...",
|
||||
retry_count: 2, // 你試了幾次才搞定
|
||||
blocked: false, // 完全擋住嗎
|
||||
suggested_fix: "..." // optional,你建議的修補
|
||||
})
|
||||
```
|
||||
|
||||
「success_story」也要報,**那是告訴平台「這個 pattern 已經 work,可以推廣」**。
|
||||
|
||||
不需要怕回報太多 — 你不報,平台拿 implicit telemetry(每個 deploy / run 平台自己 log)也會看到問題,但 explicit feedback 質感高很多。
|
||||
|
||||
---
|
||||
|
||||
## 9. KBDB(資料儲存)速覽
|
||||
|
||||
arcrun 的「資料庫」是 KBDB(Cloudflare D1)。萬物皆 block:note / wiki-page / chat / triplet / template / skill / feedback / 等,靠 `type` 區分。
|
||||
|
||||
工具:
|
||||
- `kbdb_get(type, block_id?, page_name?, ...)` — 讀
|
||||
- `kbdb_create_block(type, content, ...)` — 建
|
||||
- `kbdb_patch_block(block_id, content?, tags?, ...)` — 改
|
||||
- `kbdb_upsert_block(page_name, content, ...)` — page_name 當 idempotency key
|
||||
|
||||
寫 workflow 要 RAG / KM / 用戶資料持久化時,直接用這幾個 component(在 YAML `component: kbdb_get` 等)。
|
||||
|
||||
完整 KBDB API 將有獨立 SDD(`kbdb-llm-interface`),目前看 `https://kbdb.finally.click/ui`(Swagger)。
|
||||
|
||||
---
|
||||
|
||||
## 10. 範例:寫一個 cron watcher(最常見 pattern)
|
||||
|
||||
```yaml
|
||||
name: my_watcher
|
||||
description: 每 5 分鐘掃未處理資料 → 觸發 wiki_synthesis
|
||||
|
||||
flow:
|
||||
- "watch_cron >> ON_SUCCESS >> list_unprocessed"
|
||||
- "list_unprocessed >> ON_SUCCESS >> filter_new"
|
||||
- "filter_new >> 對每個 item >> trigger_synthesis"
|
||||
|
||||
config:
|
||||
watch_cron:
|
||||
component: cron
|
||||
cron_expr: "*/5 * * * *"
|
||||
|
||||
list_unprocessed:
|
||||
component: kbdb_get
|
||||
api_key: "{{api_key}}"
|
||||
type: "note"
|
||||
source: "user-input"
|
||||
limit: 20
|
||||
|
||||
filter_new:
|
||||
component: filter
|
||||
items: "{{list_unprocessed.blocks}}"
|
||||
condition:
|
||||
key: "tags_json"
|
||||
op: "eq"
|
||||
value: "[]"
|
||||
|
||||
trigger_synthesis:
|
||||
component: trigger_workflow # 不要用 http_request 自打 — 會撞 CF self-fetch
|
||||
workflow_name: "wiki_synthesis"
|
||||
api_key: "{{api_key}}"
|
||||
input:
|
||||
api_key: "{{api_key}}"
|
||||
raw_block_id: "{{item.id}}"
|
||||
```
|
||||
|
||||
部署完每 5 分鐘自動跑。
|
||||
|
||||
---
|
||||
|
||||
## 10.5 內建 magic vars(`_` prefix reserved)
|
||||
|
||||
YAML 內可直接用以下變數,cypher-executor 自動展開為當下時間(UTC):
|
||||
|
||||
| 變數 | 範例 | 用途 |
|
||||
|---|---|---|
|
||||
| `{{_today}}` | `2026-05-16` | 日 log / page_name |
|
||||
| `{{_yesterday}}` | `2026-05-15` | digest 取昨日 |
|
||||
| `{{_now}}` | `2026-05-16T09:30:00.123Z` | ISO 8601 |
|
||||
| `{{_now_unix}}` | `1778937000123` | unix ms |
|
||||
| `{{_now_unix_s}}` | `1778937000` | unix sec |
|
||||
| `{{_iso_week}}` | `2026-W20` | weekly archive (本 doc 推薦) |
|
||||
| `{{_iso_week_num}}` / `{{_iso_year}}` | `20` / `2026` | 拆開用 |
|
||||
| `{{_yyyymm}}` / `{{_yyyymmdd}}` | `202605` / `20260516` | 緊湊路徑 |
|
||||
| `{{_year}}` / `{{_month}}` / `{{_day}}` / `{{_hour}}` / `{{_minute}}` | 各別 zero-padded | 自己拼路徑 |
|
||||
| `{{_weekday}}` | `0`-`6`(0=日)| if-control |
|
||||
| `{{_iso_weekday}}` | `1`-`7`(1=一)| ISO 風格 |
|
||||
|
||||
**rule**:`_` prefix reserved for system,**用戶自己 ctx 變數不要用 `_` 開頭**。
|
||||
|
||||
**範例**:weekly archive
|
||||
```yaml
|
||||
publish_roadmap_archive:
|
||||
component: kbdb_upsert_block
|
||||
page_name: "roadmap-{{_iso_week}}" # roadmap-2026-W20
|
||||
tags_json: '["weekly", "week:{{_iso_week}}"]'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 11. 給寫 LI 的 AI 自己的 meta-規範
|
||||
|
||||
你(AI)在寫 arcrun workflow 時,**遵守以下習慣**會少踩坑:
|
||||
|
||||
1. **永遠先 list → validate → push → run → trace**:5 步流程,缺一個都會多繞路
|
||||
2. **error 一定讀 `next_actions`**:不是讀 `human_message` 然後猜
|
||||
3. **paused 不是錯**:claude_api、外部 OAuth flow 都會 paused,正常
|
||||
4. **`{{api_key}}` 是 trigger context 帶進來的**:手動觸發要在 body 帶;cron 觸發 cypher-executor 自動塞
|
||||
5. **新增零件不在 list_components 出來的清單裡** → 平台沒部署該零件,告訴用戶「我們需要先做 component」,不是你寫 workflow 的鍋
|
||||
6. **完成後 call `report_feedback`**:哪怕 success_story,也回報。AI 用得順不順不能靠人類事後回顧
|
||||
|
||||
---
|
||||
|
||||
## 12. 進階參考
|
||||
|
||||
- 完整 SDD:`docs/3-specs/llm-interface/`
|
||||
- 平台架構(rules):`matrix/arcrun/.claude/rules/`
|
||||
- 零件開發指南:call `get_component_guide()` MCP tool
|
||||
- KBDB Swagger:https://kbdb.finally.click/ui
|
||||
- 範例庫(M3 完成後):`registry/examples/`
|
||||
- 平台週報(M4 完成後):KBDB block `type=arcrun-roadmap`
|
||||
|
||||
---
|
||||
|
||||
> 本 doc 是 source of truth。每次更新後 GH Actions 自動同步 KBDB block (`type=agent-onboarding`),AI 可透過 `get_onboarding` MCP tool 拿最新版(M1 完成)。
|
||||
@@ -0,0 +1,34 @@
|
||||
# 4. Guides — 操作手冊 + 教程
|
||||
|
||||
> 「怎樣做」:部署、開發、CLI 用法、壓測、工作流例子。
|
||||
|
||||
## 核心操作
|
||||
|
||||
| 檔案 | 用途 |
|
||||
|------|------|
|
||||
| **05-deploy-convention.md** | 部署流程、掃描式 workflow、lockfile、WASM 來源 |
|
||||
| **RELEASE-CHECKLIST.md** | 發佈檢查清單 |
|
||||
|
||||
## 工具使用
|
||||
|
||||
| 檔案 | 用途 |
|
||||
|------|------|
|
||||
| **AGENTS.md** | Agent 工具 / MCP 工具描述 |
|
||||
| **mcp-setup.md** | MCP 安裝 + 配置(搬來中) |
|
||||
| **mcp-development.md** | MCP 開發指南(搬來中) |
|
||||
|
||||
## 開發
|
||||
|
||||
| 目錄 | 內容 |
|
||||
|------|------|
|
||||
| **examples/** | workflow 範例(搬來中) |
|
||||
| **skills/** | registry skills 文檔(搬來中) |
|
||||
| **components/** | 零件開發指南(搬來中) |
|
||||
|
||||
## 壓測 + 驗收
|
||||
|
||||
測試文件統一移至 `5-records/test-reports/`。
|
||||
|
||||
---
|
||||
|
||||
更新時間:2026-06-08
|
||||
@@ -0,0 +1,61 @@
|
||||
# RELEASE-CHECKLIST — 出貨清單(沒有 GitHub Actions,每個 target 分開推,照順序不漏)
|
||||
|
||||
> 為什麼要這份:沒有 CI,deploy 是「一個個分開」的動作(git / CF workers / npm CLI)。
|
||||
> 漏任一步就會「有些新有些舊」——壓測踩過兩次:
|
||||
> - 第一次:CLI 改了但 npm 沒發 → 用戶 npm 裝到舊 CLI。
|
||||
> - 第二次(階段 6):cypher 改了但**沒推 main** → `acr init` 從 origin/main codeload 抓到**舊 worker** → 薄殼打不存在的 API(seed 404)。
|
||||
>
|
||||
> 核心鐵則:**self-hosted `acr init` 從 `origin/main` 抓 worker 源。所以「git push main」必須在「部署」之前。**
|
||||
> 順序錯了 = deploy 出去的 prod 是新的,但 self-hosted 用戶裝到的是舊的。
|
||||
|
||||
---
|
||||
|
||||
## 正確順序(照做不會忘)
|
||||
|
||||
### 0. 改完 code,先驗證
|
||||
- [ ] 三端 typecheck 綠:`cd cli && npx tsc --noEmit`、`cd cypher-executor && npx tsc --noEmit`、`cd mcp && npx tsc --noEmit`
|
||||
- [ ] 動到的 .sh:`bash -n scripts/<檔>.sh`
|
||||
|
||||
### 1. ⬆️ 先 git commit + push(**必須在 deploy 之前**)
|
||||
- [ ] `git add -A`(確認 `.env` / secret 沒被加:`git diff --cached --name-only | grep -iE '\.env|secret|token'` 應空)
|
||||
- [ ] `git commit -m "..."`
|
||||
- [ ] `git push origin main`
|
||||
- 理由:self-hosted 從 `origin/main` codeload 抓 worker。沒先 push → 用戶抓到舊碼。
|
||||
|
||||
### 2. ✅ 跑出貨前檢查(會擋住「git 沒同步」)
|
||||
- [ ] `bash scripts/check-release.sh` → 必須全綠(含「0. Git 同步」段)。
|
||||
- 紅燈「領先 origin/main N commit 未 push」= 回步驟 1。
|
||||
- 此腳本 git 未同步會 `exit 1`,是 deploy 的前置閘。
|
||||
|
||||
### 3. 🚀 deploy(worker + CLI npm)
|
||||
- [ ] Node ≥ 20(本機若預設舊版:`export PATH="$HOME/.nvm/versions/node/v22.21.0/bin:$PATH"`)
|
||||
- [ ] `bash scripts/local-deploy.sh --all`(或不帶 `--all` 只 deploy diff)
|
||||
- 此腳本**會先自動跑步驟 2 的 git 閘**;未過直接拒絕 deploy(要強推設 `SKIP_GIT_CHECK=true`,自負風險)。
|
||||
- worker 走 `wrangler deploy`;CLI 走 `npm publish`(版本未 bump 會自動 patch +1 + 寫 CHANGELOG)。
|
||||
- npm publish 需 `npm login` 或 `.env` 的 `NPM_API_TOKEN`(authToken)。
|
||||
|
||||
### 4. 🔁 deploy 後線上驗證(確認新碼真的上去了)
|
||||
- [ ] `curl https://cypher.arcrun.dev/health` → 200
|
||||
- [ ] 改了 cypher 路由時,**實際打那條新路由**確認存在(例:`curl -X POST https://cypher.arcrun.dev/init/seed`、`curl https://cypher.arcrun.dev/recipes` 應非空)。
|
||||
← 這步就是階段 6 的教訓:別只看「部署成功」,要打新端點確認。
|
||||
- [ ] 改了 CLI:`npm view arcrun version` == `cli/package.json` version。
|
||||
- [ ] landing 有改:確認 arcrun.dev 更新。
|
||||
|
||||
### 5. 📣 通知 / 收尾
|
||||
- [ ] 若是回應壓測:到壓測報告加「開發者回覆」+ 請壓測者重跑。
|
||||
|
||||
---
|
||||
|
||||
## 一眼對照表:每個 target 怎麼推、誰依賴它
|
||||
|
||||
| Target | 推法 | 誰依賴「它在 origin/main」 |
|
||||
|---|---|---|
|
||||
| **git origin/main** | `git push origin main` | **self-hosted `acr init` codeload 抓這裡的 worker 源** → 必須最先 |
|
||||
| CF workers(26 個含 mcp) | `local-deploy.sh`(wrangler deploy) | 平台 prod;self-hosted 自己 deploy |
|
||||
| CLI(npm `arcrun`) | `local-deploy.sh` 第 6 段 / `cd cli && npm publish` | 用戶 `npm i -g arcrun` |
|
||||
| landing(arcrun.dev) | `cd landing && wrangler pages deploy` | 訪客 |
|
||||
|
||||
## 常見漏失(自我檢查)
|
||||
- ❌ 「我 deploy 了 prod cypher 但忘了 push main」→ self-hosted 用戶 init 抓舊碼。**先 push 再 deploy。**
|
||||
- ❌ 「改了 CLI 但版本沒 bump」→ npm publish 跳過(同版)。`local-deploy.sh` 會自動 bump,但手動 publish 時要記得。
|
||||
- ❌ 「改了 cypher 路由只看到『部署成功』就收工」→ 要實際 curl 新路由確認(步驟 4)。
|
||||
@@ -0,0 +1,47 @@
|
||||
# CLI / MCP 能力對照清單(薄殼防漂移)
|
||||
|
||||
> **來源**:thin-shell-alignment SDD(issue #11)R4 防複發機制層 1。
|
||||
> **用途**:每新增一個薄殼能力(CLI 命令 / MCP 工具)**必填一行**,PR review 對照。
|
||||
> **治什麼**:① 打不存在的 server 端點(死端點假綠)② CLI/MCP 同能力不同源(漂移)。
|
||||
> **配套**:`scripts/thin-shell-smoke.sh`(層 2,對真端點打、斷言非 404)。
|
||||
> **建立**:2026-06-27
|
||||
>
|
||||
> **填寫規則**:
|
||||
> 1. 「server 端點」必須在 cypher-executor route 清單裡**存在**(用 `grep -rE "Router\.(post|get)\('/xxx'" cypher-executor/src/routes/` 驗)。
|
||||
> 2. 「同源?」= CLI 與 MCP 是否打**同一個** server 端點。不同源 = 漂移(除非刻意單邊,記明原因)。
|
||||
> 3. 標 ⚠️ 的是已知債/待收斂項,連到 SDD 對應段。
|
||||
|
||||
---
|
||||
|
||||
## 對照表
|
||||
|
||||
| 能力 | CLI | MCP | server 端點 | route 存在? | 同源? | 備註 |
|
||||
|------|-----|-----|------------|:---:|:---:|------|
|
||||
| 部署 workflow | `acr push` | `u6u_deploy_workflow` | `POST /webhooks/named` | ✅ | ⚠️ | MCP 現打死端點 `/workflows/deploy`(404)→ 待 #8 ①-a + #10 編排下沉。CLI 走 4 步介面層編排(#10 待下沉)|
|
||||
| 執行 workflow(已部署)| `acr run <name>` | `u6u_execute_workflow` | `POST /webhooks/named/:name/trigger` | ✅ | ✅ | **#11 P0 已修**:CLI 原打死端點 `/webhooks/<name>` → 改打 trigger 真端點 |
|
||||
| 執行 workflow(本機 YAML)| `acr run <file>` | — | `POST /cypher/execute` | ✅ | — | CLI 本機 YAML 直跑;MCP `u6u_execute_workflow` 同打 /cypher/execute |
|
||||
| list workflow | `acr list` | `u6u_list_workflows` | `GET /webhooks/named` | ✅ | ✅ | **#11 P1 已修**:兩邊原不同源(CLI 直連 KV `workflow:` 前綴對不上 / MCP 讀 KBDB record)→ 收斂到 `GET /webhooks/named`(KV 源)|
|
||||
| get workflow | — | `u6u_get_workflow` | (KBDB record / KV)| — | — | MCP only;CLI 無對應(次要,可不補)|
|
||||
| search workflow | (次階段 `acr workflow search`)| `u6u_search_workflows` | `GET /workflows/search` | ✅ | — | **#8 新增**;CLI 對稱補列次階段(R3.3)|
|
||||
| 驗證 YAML | `acr validate`(本機)| `arcrun_validate_yaml`(server /validate)| `POST /validate` | ✅ | ⚠️ | **真漂移,依賴 #10**:CLI 本機驗 YAML、MCP 傳 graph 打 /validate,輸入不同層。乾淨收斂依賴 #10 編排下沉(SDD §4 表 + tasks 3.1)|
|
||||
| 搜尋零件 | `acr parts` | `u6u_search_components` | `GET /components/search`(registry)| ✅ | ✅ | 同打 registry search(註:目前是 KV substring 非真語意,registry Phase 2 另案)|
|
||||
| recipe(6 能力)| `acr recipe *` | `arcrun_recipe_*` | `/recipes/*` `/public-recipes/*` | ✅ | ✅ | 已對齊 |
|
||||
| credential 上傳 | `acr creds push` | — | `POST /credentials` | ✅ | — | **刻意單邊**(非疏漏):含 client 端加密 + 本機檔路徑,AI 不代傳 credential(mindset §6/§7)|
|
||||
| KBDB 資料層(template/record/query/search)| `acr kbdb *` | `kbdb_*`(6 工具)| `/kbdb/*` | ✅ | ✅ | 已對齊(#8 前批)|
|
||||
| tag(create/list/delete/tag/untag)| — | `u6u_*_tag` / `u6u_tag_resource` | (KBDB resource_tag)| — | — | MCP only。⚠️ tag resource_id 語意債(UUID vs name),待方向①收斂(SDD §4.1)|
|
||||
| whoami | `acr whoami` | `arcrun_whoami` | `GET /me` | ✅ | ✅ | 已對齊 |
|
||||
|
||||
---
|
||||
|
||||
## 已知債(連 SDD)
|
||||
|
||||
- ⚠️ **MCP deploy 死端點**:`/workflows/deploy` 不存在 → #8 ①-a(先擋)+ #10(編排下沉)。
|
||||
- ⚠️ **validate 漂移**:依賴 #10 編排下沉後才能統一吃 YAML。
|
||||
- ⚠️ **tag resource_id 語意**:UUID vs name 不明確,待方向①收斂統一為 name。
|
||||
|
||||
## 防複發檢查點(新增能力時)
|
||||
|
||||
1. 新 CLI 命令 / MCP 工具 → **本表加一行**。
|
||||
2. 填「server 端點」前,`grep` 確認該 route 在 cypher-executor 裡**存在**(否則就是死端點)。
|
||||
3. 同能力兩介面 → 確認「同源」打同一端點;刻意單邊 → 備註記明原因。
|
||||
4. 宣稱「對齊/完成」前 → 跑 `scripts/thin-shell-smoke.sh`(對真端點斷言非 404)。
|
||||
@@ -0,0 +1,79 @@
|
||||
# self-hosted KBDB 能力清單(查詢能力對照)
|
||||
|
||||
> 來源:issue #5(普世框架視角——任何 self-hosted 用戶都該知道自架 `arcrun-kbdb` 提供哪些查詢能力)。
|
||||
> 範圍:**base tier(D1-only,免費不綁卡)**。optional 模組(embed/triplet)另標。
|
||||
> 鐵律:API-as-Wall(只經 HTTP API,不直連 D1)/零建表/零 SQL 暴露給用戶。
|
||||
|
||||
---
|
||||
|
||||
## 兩條存取路徑
|
||||
|
||||
| 路徑 | 對象 | 入口 | 隔離 |
|
||||
|------|------|------|------|
|
||||
| **cypher proxy `/kbdb/*`** | app 前端 / CLI(`acr kbdb`) | `cypher.arcrun.dev/kbdb/*`(self-hosted 指自己的 cypher) | X-Arcrun-API-Key → owner_id,自動租戶隔離 |
|
||||
| **raw worker** | 內部 / MCP service binding | `arcrun-kbdb.<sub>.workers.dev` | 無 auth(內網),owner_id 由 caller 帶 |
|
||||
|
||||
> **前端存取準則**:app(如自架的任何 Next.js 前端)**走 cypher proxy `/kbdb/*`**,不直連 raw worker——proxy 才有 owner_id 租戶隔離。CLI/MCP 是薄殼(thin-shell §0),底層同一條 proxy。
|
||||
|
||||
---
|
||||
|
||||
## base 查詢能力(現有)
|
||||
|
||||
### entries(原子資料 / 樹節點)
|
||||
|
||||
| 能力 | 端點 | filter / 參數 |
|
||||
|------|------|------|
|
||||
| 建 | `POST /entries` | `entry_type`(必), content, owner_id, parent_id, page_name, metadata_json… |
|
||||
| 列 + 過濾 | `GET /entries` | `entry_type` / `owner_id` / `parent_id` / `page_name` / **`source`**(#5.1) / `limit` / `offset` |
|
||||
| 取單筆 | `GET /entries/:id` | — |
|
||||
| 改 | `PATCH /entries/:id` | 任意可改欄位(proxy 會剝 owner_id 防認領) |
|
||||
| 刪 | `DELETE /entries/:id` | ⚠️ **raw 有;cypher proxy 暫未開**(見下「擱置」) |
|
||||
| **關鍵字搜尋** | `GET /entries/search?q=` | D1 `LIKE`,回 `mode:'keyword'`。owner_id 限本租戶 |
|
||||
|
||||
- **`source` 過濾(#5.1,2026-06-26)**:按 ingest 來源篩(envelope `source.uri`)。實作走 SQLite
|
||||
`json_extract(metadata_json,'$.source')`——**source 埋在 metadata_json,零建表**即可查。
|
||||
例:`GET /kbdb/entries?source=logseq://vault/foo.md`。
|
||||
|
||||
### templates(虛擬表定義=替代建表)
|
||||
|
||||
| 能力 | 端點 |
|
||||
|------|------|
|
||||
| 建 / 列 / 取 / 改 slots | `POST /templates`、`GET /templates`、`GET /templates/:idOrName`、`PATCH /templates/:id` |
|
||||
|
||||
> 鐵律:template = 萬用表的 slot 定義,**不是建真表**。AI/用戶只能「建 template(name+slots) + 填 record」,無 CREATE TABLE / SQL。
|
||||
|
||||
### records(template 實例=填 slot)
|
||||
|
||||
| 能力 | 端點 |
|
||||
|------|------|
|
||||
| 建 | `POST /records`(template + values) |
|
||||
| 列某 template 下 | `GET /records/by-template/:template`(owner_id 限本租戶) |
|
||||
| 取單筆 | `GET /records/:recordId` |
|
||||
| **改 slot 值** | `PATCH /records/:recordId`(#6,翻 slot 值=改底層 entries.content,三表 append-only 不破) |
|
||||
|
||||
### recipe-stats(市場成功率)
|
||||
|
||||
| 能力 | 端點 |
|
||||
|------|------|
|
||||
| 記一次成功/失敗 | `POST /recipe-stats/record` |
|
||||
| 查某 recipe 統計 | `GET /recipe-stats/:canonical_id` |
|
||||
|
||||
---
|
||||
|
||||
## 語義搜尋(optional embed 模組)
|
||||
|
||||
- **base 不含語義搜尋**——關鍵字 `GET /entries/search` 是 `LIKE`(`mode:'keyword'`)。
|
||||
- 開 **embed 模組**(CF Vectorize binding,自付費)後升級語義(`mode:'semantic'`)。是 base 的 optional 模組,
|
||||
不裝保持輕(free-tier 友善)。開法 + 行為見 issue #7 / kbdb-base SDD T2.4。
|
||||
|
||||
---
|
||||
|
||||
## 擱置 / 不做(誠實標明,避免用戶誤以為有)
|
||||
|
||||
| 項 | 狀態 | 原因 |
|
||||
|----|------|------|
|
||||
| cypher proxy `DELETE /kbdb/entries/:id` | ⏸ **暫擱置** | 依賴頂層「死資料自動刪除原則」(mira-dissolve T8 未定)。raw worker 有 DELETE,但裸 delete-by-id 無 owner 檢查,經 proxy 暴露=跨租戶刪除風險 → 補時要先驗 owner_id 才放行。 |
|
||||
| documents 聚合(GROUP BY page_name → block_count) | ❌ **不做** | 「跨 vault 的圖」走 **graph MCP**(traverse/neighbors),不靠 KBDB 出 SQL 聚合端點。普世用戶不需要。 |
|
||||
|
||||
> 這份**不列**「documents / process-page 待移植」——那是舊 SaaS KBDB(kbdb.finally.click)/ 舊河道頁視角,
|
||||
> 新架構不移植。self-hosted base 的能力以本清單為準。
|
||||
Reference in New Issue
Block a user