Files
uncle6me-web 7bd7b4b26a SDD 生命週期鐵律遷移:單一活性制度上線(portal-auth=active,其餘 paused/draft)
- 鋪檔(自 system-dev-template v1.15.0):SDD-LIFECYCLE.md+pending-changes.md
  +sdd-guard.sh(覆蓋舊版,加單一活性檢查)+sdd-check.md+sdd-active-check.sh
- settings.json PreToolUse(Write|Edit|MultiEdit)掛上 sdd-guard.sh
- 全部 SDD design.md 掛 frontmatter:portal-auth=active(現行 portal 線,
  #61 demo 四件套剛 merge);artifact-sharing=draft(零任務動工);
  其餘 16 份=paused(皆有未完成任務,無明顯死件,不硬 close)
- CLAUDE.md 加「SDD 生命週期鐵律」段(指向 SDD-LIFECYCLE.md+濃縮五條)
  +SDD 速查表改以 frontmatter status: active 為現行判準
- 驗證:sdd-active-check exit 0(恰 1 份 active);guard pipe-test code 檔
  exit 0 帶現行 SDD 提示;反向測試(造 2 份 active)guard exit 2/check exit 1 全擋

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 17:03:16 +08:00

118 lines
7.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
status: paused
superseded_by: ""
---
# thin-shell-alignment — Design
> **狀態**:草案,待確認。對應 `requirements.md`。
> **建立**2026-06-27issue #11
---
## 1. 設計總綱
四塊,全守 rule 07(能力落 API、薄殼只暴露、讀同一源):
1. **R1 P0**CLI run 改打真 trigger 端點(一行修,但要端到端驗)。
2. **R2 P1**CLI list 改走 `GET /webhooks/named`KV 源),停止直連 CF KV。
3. **R3 P2**:單邊能力逐項判「補對稱 / 刻意單邊」。
4. **R4 防複發**(治本核心):能力對照清單 + 本機 smoke test,讓假綠當場現形。
---
## 2. R1CLI run 死端點(P0
`cli/run.ts:102` 現打 `${executorUrl}/webhooks/${name}` → 改 `${executorUrl}/webhooks/named/${name}/trigger`
- 對齊真端點 `webhooks-named.ts:279``POST /webhooks/named/:name/trigger`X-Arcrun-API-Key header)。
- 注意:trigger 端點吃 header api_key + body trigger contextrun.ts 現已帶 headers + inputContext,只差路徑)。
- **驗收**leo21c 部署一個 workflow → `acr run <name>`(本機無該 YAML,走「玩法二」)→ 真的觸發執行(200),非 404。
---
## 3. R2list 來源統一(P1
### 3.1 收斂到 `GET /webhooks/named`
- CLI `list.ts` 停止 `CfKvClient` 直連 KV,改 `fetch(${executorUrl}/webhooks/named)`X-Arcrun-API-Key header)。
- MCP `u6u_list_workflows` 從讀 KBDB record 改讀 `GET /webhooks/named`(經 CYPHER_EXECUTOR binding)。
- 兩者同一端點 → 同源、同欄位(#8 1.3b 已補 `GET /webhooks/named` 回 description/created_at/cron_expr)。
### 3.2 為何 list 讀 KV 而非 KBDB entry(職責分)
- **list = 精確列舉「我有哪些 workflow」** → 讀 KV(部署寫入處,權威)。
- **search = 語意找「做某事的 workflow」** → 讀 KBDB entry#8 雙寫的 search-entry)。
- 兩者不同職責、不同源頭,本就該分。KBDB entry 是 search 投影,不是 list 真相(避免 list 受 embed 模組開關影響)。
### 3.3 順手修 CLI list 的 key 前綴 bug(核實補充①)
- CLI 直連 KV 讀 `workflow:` 前綴,但部署寫 `{apiKey}:wf:{name}` → 現狀 CLI list 列不到。改走 `GET /webhooks/named` 後此 bug 自然消失(端點內部用正確前綴 `${apiKey}:wf:`)。
---
## 4. R3P2 單邊能力決策
| 能力 | 現況 | 判定 | 理由 |
|------|------|------|------|
| 驗證 YAML | CLI `acr validate` **純本機**validate.ts:44loadWorkflowYaml+parseTriplets+validateRelations,不打端點);MCP `arcrun_validate_yaml` 打 server `/validate`introspection.ts:34| **隱藏漂移,需收斂**(總管 2026-06-27 核實)| 同「驗證 YAML」能力,CLI 走本機、MCP 走 server = 又一個不同源(同 list 病)。收斂:驗證邏輯落 API(/validate)為單一真相,CLI 改打它;或明確記「本機快驗 vs server 權威驗」兩層定位——但**別讓兩邊邏輯漂移**。實作時定,記進對照清單 |
| `acr creds push`/credentials| CLI only | **刻意單邊**(記明)| credential 上傳含 client 端加密 + 本機檔案路徑,是 CLI 慣例;AI 不該代傳 credentialmindset §6/§7)。記明非疏漏 |
| `u6u_search_workflows`/workflows/search| MCP only | **補 CLI 對稱**(次階段)| 對齊 #8 Phase 5`acr workflow search`),同端點 |
| recipe 6 能力 / execute | 已對齊 ✅ | — | — |
> 判準:消費者是 AI → MCP 必有;含人類互動/本機檔/敏感操作 → 可刻意單邊但記明。**不強求 1:1**。
### 4.1 實作期發現:tag resource_id 語意債(Phase 2.2,需總管確認)
MCP list 改讀 `GET /webhooks/named`(KV 源,主鍵=name)後,tag 過濾(`resource_tag` record 的 `resource_id`)出現語意不一致:
-`u6u_deploy_workflow``workflow_metadata``workflow_id` `result.workflow_id ?? randomUUID()`**可能是 UUID**)。
- `u6u_tag_resource``resource_id` 由用戶傳入(語意不明確,可能 name 也可能 id)。
- 原 list 用 `w.workflow_id` 比對 tag 集合;改讀 KV 源後只有 `name`KV 無 UUID 概念)。
**過渡處理**list tag 過濾改用 `name` 比對(KV 源唯一鍵)。舊用 UUID 的 tag 會在 re-tag 後對齊。
**待總管確認**:方向①收斂到 KV(主鍵=name)後,tag `resource_id` 應統一為 **name**;是否要 backfill 舊 UUID tagtag 系統不在 #11 明確範圍,但 list 收斂碰到它 → 標記待決,不擅自改 tag 寫入語意。
---
## 5. R4 ⭐:防複發機制(治本核心)
> 根因是假綠(宣稱對齊但端點不存在)。機制目標:**讓「打了不存在的端點」無法悄悄混過**。
### 5.1 推薦:雙層(對照清單 + 本機 smoke test),互補
**層 1:能力對照清單(靜態,文檔 + review 防線)**
- 一張表 `docs/4-guides/cli-mcp-capability-matrix.md``能力 | CLI 端點 | MCP 端點 | server route 存在? | 同源?`
- 新增任何薄殼能力**必填一行**,PR review 對照。
- 治「忘了對齊」+「打不存在端點」的**意識層**。
**層 2:本機 smoke test(動態,端點存在性的客觀證據)** ⭐治本
- 一個**本機手動跑**的 script`scripts/thin-shell-smoke.sh``acr selftest`):對每個薄殼能力打一次真實端點,斷言「非 404」(不要求 200——有些需 auth/資料,但**404 = 端點不存在 = 死端點當場現形**)。
- **守 flag 紅線(C2/R4.2**:本機/手動觸發,**非 CI、非 cron、非輪詢**。對齊「執行鏈路不依賴 CI」「部署走 local script」既有鐵律。
- 治「假綠」的**客觀層**:宣稱對齊前先跑它,死端點無所遁形。這正是當初 MCP `/workflows/deploy` 會被攔下的機制。
**層 3(輕量,PR 時)**:新薄殼工具 PR 描述附「打的端點在 server route 清單裡」的一行證據(grep route 即可)。低成本、補 review。
### 5.2 為何不單靠 CI smoke
- CI 高頻輪詢真實端點 = 違 flag 紅線(rule 05 §3、避免被 flag 鐵律 §3)。
- smoke 是「宣布完成前手動跑一次」的閘,不是每 push 自動跑。對齊 arcrun「執行鏈路不依賴 CI、稀有驗證才 CI」分層。
### 5.3 機制自驗(R4.3
- 驗收:故意把某 CLI 工具的端點改成不存在的路徑 → 跑 smoke → **當場報該能力 404 死端點**。證明機制能攔。
---
## 6. 影響面(框架級,C1
- **改 CLI**`run.ts`trigger 路徑)、`list.ts`(改走 cypher proxy 停直連 KV)、可能補 `acr workflow search`
- **改 MCP**`u6u_list_workflows`(改讀 GET /webhooks/named)、可能補 validate 對稱。
- **改 cypher**:可能無(複用既有 `GET /webhooks/named`);確認它回的欄位夠 list 用(#8 1.3b 已補)。
- **新增**:能力對照清單文檔、smoke test script。
- **不改**deploy 那條(#8/#10);recipe/execute(已對齊)。
---
## 7. 拍板結果(leo 2026-06-27 issue #114 點全定)
1. **Q1 R4 = 雙層(對照清單 + 本機 smoke test)✅** 含 §5.3 機制自驗。守 flag 紅線(本機手動跑非 CI/cron)。
2. **Q2 CLI list = 複用 `GET /webhooks/named`✅**(不新建 proxyCLI/MCP 同源)。
3. **Q3 P2 判定全照 SDD✅**validate 補對稱(**但總管核實揭 validate 是隱藏漂移:CLI 純本機、MCP 打 server /validate,需收斂**,見 §4 表)/creds push 刻意單邊記明/search 補 CLI 次階段。
4. **Q4 smoke test = `scripts/thin-shell-smoke.sh` 本機跑 ✅**
> **狀態:4 點拍定,已點頭實作。** 順序 P0→P1→P2→R4。完成標準=leo21c 端到端(CLI/MCP 真打通 200 非 404、smoke 能攔故意死端點),非 tsc 綠。