chore(wiki): 本 session capture(薄殼防複發/歷史債卡 + mistakes #19-21 + status)
兩次 /wiki-capture 累積的知識落盤: - cards/decisions/ 新卡:薄殼防複發-能力對照表加smoke、薄殼規則晚於實作-MCP漂移是歷史債 (+ 00-INDEX 編入,決策桶現 15 張) - mistakes #19 死端點假綠(grep route/smoke 驗端點存在) - mistakes #20 gitignored 檔無 git 史(時間靠檔內註記) - mistakes #21 wrangler.toml services=[...] inline 在 [vars] 後被吸成 vars.services(issue #12) - decisions-summary:薄殼防複發機制、workflow description 由操盤 CC 據實生成 - status:本 session #8/#11/#12 進度 + merge 結果 純記憶/文檔,無 code。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
- [[自力救濟階梯-缺能力怎麼補]] — 自家API缺→補API/第三方→workflow補丁/純計算→code-node
|
||||
- [[薄殼原則-能力長在API]] — CLI/MCP/lib 只暴露,齊的單位是「能力」不是「端點」
|
||||
- [[薄殼規則晚於實作-MCP漂移是歷史債]] — 為何 MCP/CLI 不一致:紀律 2026-06-07 才補、補前漂移
|
||||
- [[薄殼防複發-能力對照表加smoke]] — 防死端點假綠:對照清單 + 本機 smoke(非 CI),自驗能攔
|
||||
|
||||
## 串接 / 部署
|
||||
|
||||
|
||||
@@ -34,4 +34,5 @@ MCP 和 CLI 不一致的根因不是「MCP 更早開發所以舊」,而是**
|
||||
- 薄殼原則 >> 修正 >> MCP 漂移
|
||||
### 卡片關係
|
||||
- [[薄殼規則晚於實作-MCP漂移是歷史債]] >> 補充歷史成因於 >> [[薄殼原則-能力長在API]]
|
||||
- [[薄殼規則晚於實作-MCP漂移是歷史債]] >> 被治理於 >> [[薄殼防複發-能力對照表加smoke]]
|
||||
- (相關 memory:`mcp-self-hosted-bug-fixed`、`thin-shell-capability-in-api` — MCP 後端接線與薄殼鐵律)
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
---
|
||||
tags: [薄殼, 平台原則, 架構決策, 機制說明]
|
||||
gloss: 防 CLI/MCP 薄殼漂移(死端點假綠)的雙層機制——靜態能力對照清單 + 本機 smoke test 對真端點斷言非 404。
|
||||
---
|
||||
# 薄殼防複發 — 能力對照表 + 本機 smoke
|
||||
|
||||
← [[decisions/00-INDEX]]
|
||||
|
||||
**來源**:`system-dev/docs/3-specs/thin-shell-alignment/design.md §5`(issue #11)、`docs/4-guides/cli-mcp-capability-matrix.md`、`scripts/thin-shell-smoke.sh`
|
||||
**最後更新**:2026-06-27
|
||||
|
||||
## 摘要
|
||||
治「薄殼打了不存在的 server 端點」(死端點假綠)用雙層:靜態能力對照清單(review 防線)+ 本機 smoke test(對真端點斷言非 404,死端點當場現形)。本機手動跑,非 CI。
|
||||
|
||||
## 重點
|
||||
- **根因是假綠**:MCP deploy 在宣稱「一致性落地」的同一 commit 裡打了不存在的 `/workflows/deploy`(必 404),從未端到端跑過。光靠「宣稱對齊」會再犯。
|
||||
- **層 1 能力對照清單**(`docs/4-guides/cli-mcp-capability-matrix.md`):表「能力 × CLI 端點 × MCP 端點 × route 存在? × 同源?」,新薄殼能力必填一行,填前 grep 確認 route 存在。
|
||||
- **層 2 本機 smoke**(`scripts/thin-shell-smoke.sh`):對每能力打真端點斷言非 404。**本機手動跑非 CI/cron/輪詢**(守 flag 紅線,對齊「執行鏈路不依賴 CI」鐵律)。
|
||||
- **機制自驗**:注入故意死端點 → smoke 當場攔下、exit 1(已驗證能攔)。
|
||||
- **smoke 區分「code 有 route」vs「prod 真部署」**:首跑就揭 #8 search/backfill 在 prod 仍 404(code 已 commit 但未部署)——這正是它要揭的假綠。
|
||||
- **不用 CI 高頻打真端點**(違 flag 紅線);smoke 是「宣布完成前手動跑一次」的閘。
|
||||
|
||||
## 實體
|
||||
- **能力對照清單**(cli-mcp-capability-matrix)— 靜態表列每能力的 CLI/MCP 端點與 route 存在性,review 防線。
|
||||
- **本機 smoke test**(thin-shell-smoke.sh)— 對真端點打、斷言非 404 的腳本,死端點現形,本機手動跑。
|
||||
- **死端點假綠**(dead endpoint)— 薄殼打了 server 不存在的 route(404),卻被宣稱成完成。
|
||||
- **機制自驗**(注入死端點測試)— 故意加不存在端點驗 smoke 能攔,證明機制有效。
|
||||
|
||||
## 關聯
|
||||
### 內文知識關係
|
||||
- 死端點假綠 >> 被攔於 >> 本機 smoke test
|
||||
- 能力對照清單 >> 互補於 >> 本機 smoke test
|
||||
- 機制自驗 >> 證明 >> 本機 smoke test
|
||||
- 本機 smoke test >> 區分 >> 死端點假綠
|
||||
### 卡片關係
|
||||
- [[薄殼防複發-能力對照表加smoke]] >> 治理 >> [[薄殼規則晚於實作-MCP漂移是歷史債]]
|
||||
- [[薄殼防複發-能力對照表加smoke]] >> 落實 >> [[薄殼原則-能力長在API]]
|
||||
@@ -327,6 +327,41 @@ code-node 規則已定、零件實作屬 wishlist C1 另案。**詳見**:DECIS
|
||||
|
||||
---
|
||||
|
||||
## 薄殼防複發機制=對照清單 + 本機 smoke(2026-06-27,issue #11)
|
||||
|
||||
**Q:CLI/MCP 薄殼漂移(死端點假綠)怎麼防複發?**
|
||||
|
||||
**決策**:雙層,非 CI。
|
||||
- **層 1 能力對照清單** `docs/4-guides/cli-mcp-capability-matrix.md`:一張表「能力 × CLI 端點 × MCP 端點 × route 存在? × 同源?」,新增薄殼能力**必填一行**,PR review 對照。
|
||||
- **層 2 本機 smoke test** `scripts/thin-shell-smoke.sh`:對每能力打真端點、**斷言非 404**(死端點當場現形)。**本機手動跑非 CI/cron/輪詢**(守 flag 紅線,對齊「執行鏈路不依賴 CI」)。
|
||||
- **機制自驗**:注入故意死端點 → smoke 當場攔(已驗證能攔,exit 1)。
|
||||
|
||||
**為什麼**:根因是**假綠**——宣稱「一致性落地」但端點不存在,光靠宣稱會再犯。smoke 區分「code 有 route」vs「prod 真部署」(首跑就揭 #8 search/backfill 在 prod 仍 404=未部署)。
|
||||
|
||||
**避坑**:不用 CI 高頻打真端點(違 flag 紅線);smoke 是「宣布完成前手動跑一次」的閘。
|
||||
|
||||
**詳見**:thin-shell-alignment SDD §5、[[薄殼規則晚於實作-MCP漂移是歷史債]] 卡、mistakes #19。
|
||||
|
||||
---
|
||||
|
||||
## workflow description 由操盤 CC 據實生成、用戶可改(2026-06-27,issue #8)
|
||||
|
||||
**Q:強制 workflow 填 description,但 low-code 用戶不知道要填,怎麼辦?**
|
||||
|
||||
**決策**:強制非空落 API(不變);**空時由操盤的 CC 據實寫一句「能做什麼」,用戶可改**——非逼用戶手填、非介面層機械塞佔位。
|
||||
|
||||
**調和關鍵(分清兩種「生成」)**:
|
||||
- ✅ **操盤 CC 據實生成**:CC 剛建這 workflow、最懂它做什麼 → 寫真描述(leo 例「呼叫可 Upsert Google Sheets」)。**真描述非假裝**,不違 mindset §7。
|
||||
- ❌ **介面層機械塞佔位**(從 name 複製、`workflow_xxx`)=假描述,仍禁。
|
||||
|
||||
**為什麼**:low-code 用戶不知道要填 description(逼填違北極星「不增負擔」);但自動機械填=假裝有(違誠實)。北極星「執行力外包給 AI」=AI 據實幫他寫好、他可改。
|
||||
|
||||
**避坑**:description 是一句「能做什麼」供語意搜尋,**非寫文章**。
|
||||
|
||||
**詳見**:workflow-discovery SDD §3.2。
|
||||
|
||||
---
|
||||
|
||||
## 快速決策樹
|
||||
|
||||
```
|
||||
|
||||
@@ -387,6 +387,64 @@ listEntries 加 `source` filter 即可,表結構一個欄位都不動。
|
||||
|
||||
---
|
||||
|
||||
## 19. 薄殼打的端點 server 不一定存在——死端點假綠(2026-06-27,issue #8/#11)
|
||||
|
||||
**錯誤模式**:以為「tsc 綠 + 介面有這個工具」=能力通了。實際 MCP `u6u_deploy_workflow` 打
|
||||
`/workflows/deploy`、CLI `run.ts` 打 `/webhooks/<name>`——**兩個端點 cypher 根本沒有,必 404**,
|
||||
且當初 commit message 還宣稱「部署一致性落地」。**從未端到端跑過**。
|
||||
|
||||
**症狀**:宣稱對齊/完成,但薄殼打的 route 在 server 不存在;tsc 綠掩蓋了端點不存在。
|
||||
|
||||
**正確做法**:
|
||||
1. 宣稱對齊/完成前,**grep server route 清單確認端點存在**
|
||||
(`grep -rE "Router\.(post|get)\('/xxx'" cypher-executor/src/routes/`)。
|
||||
2. 或跑 `scripts/thin-shell-smoke.sh`(對真端點打、斷言非 404,死端點當場現形)。
|
||||
3. **tsc 綠 ≠ 端點存在 ≠ 端到端通**。三者分開驗(mindset §7 完成=客觀證據)。
|
||||
|
||||
**通用教訓**:薄殼漂移(CLI/MCP 各長各的)的根因常是「規則晚於實作 + 假綠」。
|
||||
防複發見 [[薄殼防複發-能力對照表加smoke]] 卡 + `docs/4-guides/cli-mcp-capability-matrix.md`。日期:2026-06-27。
|
||||
|
||||
---
|
||||
|
||||
## 20. gitignored 檔查不到 git 史——別用 git log 推斷時間/狀態(2026-06-27)
|
||||
|
||||
**錯誤模式**:想用 `git log` 查 rule 07 / SDD / wiki 的建立時間 → 全空白,卡住。
|
||||
|
||||
**症狀**:`git log -- .claude/rules/07-thin-shell.md` 等回空,誤以為檔案有問題或 follow 寫錯。
|
||||
|
||||
**正確做法**:先 `git check-ignore <path>` 確認。`.claude/`、`docs/`、部分 `system-dev/docs/`
|
||||
**全 gitignored** → git 無這些檔的歷史。查它們的時序只能靠**檔內日期註記**,且要誠實標
|
||||
「估計非 git 鐵證」。**注**:`system-dev/wiki/` **不是** gitignored(可 commit),只有 `docs/` + `.claude/hooks/` 是。
|
||||
|
||||
**通用教訓**:查歷史前先確認檔在不在 git 追蹤範圍;gitignored 的東西「精確時間」不可考,別假裝有鐵證。日期:2026-06-27。
|
||||
|
||||
---
|
||||
|
||||
## 21. wrangler.toml 的 `services = [...]` inline 放在 `[vars]` 後 → binding 消失(2026-06-27,issue #12)
|
||||
|
||||
**錯誤模式**:以為「toml 裡有 `services = [{ binding="CYPHER_EXECUTOR", ... }]`」= binding 就會生效。
|
||||
實際 self-hosted MCP 報 `CYPHER_EXECUTOR service binding not configured`,binding 像憑空消失。
|
||||
|
||||
**根因(TOML 語法坑)**:`services = [...]` 是 **inline array 形式**,且位置在 `[vars]` table **之後**。
|
||||
TOML 規則:`[vars]` header 後的所有 key(含 `services`)都歸 `vars` table → `services` 被解析成
|
||||
**`vars.services`(一個普通 env var 陣列)而非頂層 service bindings** → wrangler 看不到任何 binding。
|
||||
self-hosted 部署 `injectMultiTenant` 往 `[vars]` 注入 `MULTI_TENANT` 後此問題暴露(官方不注入故沒早爆,
|
||||
且 whoami 不需 binding)。
|
||||
|
||||
**正確做法**:service binding 一律用 **`[[services]]` array-of-tables**(每個 binding 獨立頂層 table,
|
||||
不受 `[vars]` 影響),**不要用 inline `services = [...]`**——尤其檔案有 `[vars]` 時。對齊官方
|
||||
`cypher-executor/wrangler.toml` 慣例(它用 `[[services]]` 故不中招)。
|
||||
|
||||
**驗法(決定性)**:`wrangler deploy --dry-run --outdir /tmp/x` 列 bindings:
|
||||
- 正確 → `env.CYPHER_EXECUTOR (arcrun-cypher-executor) Worker`
|
||||
- 中招 → `env.services ([{"binding":...}]) Environment Variable`(binding 變成一個叫 services 的 env var)。
|
||||
|
||||
**通用教訓**:TOML 頂層 key 必須在任何 `[table]` header 之前;要在 table 後宣告的集合用
|
||||
array-of-tables(`[[x]]`)不用 inline array。改 toml 後用 `wrangler --dry-run` 驗 binding 真的在
|
||||
(別只看「檔裡有寫」)。連帶:這跟 mistakes #17「注入順序」、#11「死端點假綠」同類——**配置寫了 ≠ 生效**,要驗。日期:2026-06-27。
|
||||
|
||||
---
|
||||
|
||||
## 快速檢查清單(做新功能前)
|
||||
|
||||
- [ ] 這是工作流還是零件?問「有必要嗎?」
|
||||
@@ -400,3 +458,6 @@ listEntries 加 `source` filter 即可,表結構一個欄位都不動。
|
||||
- [ ] 碰 KBDB?確認打基本盤現存 route(/entries /templates /records /entries/search),別假設 v3 /blocks /search 還在
|
||||
- [ ] KBDB 要新可查欄位?用 json_extract 查 metadata_json,別加真欄(表不變鐵律,#18)
|
||||
- [ ] 改 deploy.ts toml 注入順序?想「後面還有沒有 pass(如 strip)會動同一段」(#17)
|
||||
- [ ] 新增/改薄殼工具?grep 確認它打的 server route 真的存在,別假綠(#19);宣稱對齊前跑 thin-shell-smoke.sh
|
||||
- [ ] 想用 git log 查某檔歷史?先 git check-ignore——gitignored 檔無 git 史,時間靠檔內註記(#20)
|
||||
- [ ] 改 wrangler.toml service binding?用 [[services]] 不用 inline services=[...]([vars] 後會被吸走);改完 wrangler --dry-run 驗 binding 真在(#21)
|
||||
|
||||
@@ -21,7 +21,10 @@ metadata:
|
||||
> - ✅ **已實作 tsc 全綠**:1.1 `/webhooks/named` 強制 description|2.2+Q4 KBDB base 通用 entry_type filter(改4處:searchEntries/semanticSearch/route/proxy)|2.1 部署雙寫 embeddable entry(注意 KBDB 用 metadata_json 字串)|3.1 cypher `/workflows/search`|3.2 MCP `u6u_search_workflows`|4.1 `/workflows/backfill-search-entries`|1.3b `GET /webhooks/named` 補 description/created_at 欄位。
|
||||
> - ⏸ **卡待總管定**:Phase 1.2/1.3(MCP deploy 改打 /webhooks/named)卡在 ①-a/b/c——實作期發現 /webhooks/named 吃 graph 非 YAML,YAML→graph 編排寫在 CLI push.ts 介面層,MCP 複製=違 rule 07。①-c(先通債另開 issue)我推薦,待總管定。
|
||||
> - **完成標準**:tsc 綠≠完成,框架級待 leo21c 端到端實證(強制填擋空/搜尋命中/租戶隔離/降級 hint/MCP 不再 404)。issue open。
|
||||
> - **未 commit**(待 leo 明示;wiki 骨架與 #8 SDD/code 建議分兩 commit)。署名鐵律:跨 repo comment 開頭 `[arcrun CC]`(#12)。
|
||||
> - **已 merge 進 main**(fast-forward,3 commit:934b926 #4/5/7/8 功能 / 558e80b wiki-init / 5d38b59 #11 薄殼對齊)+ push origin main。repo Actions `enabled:false`(leo 關),merge **未觸發部署**。**merge≠部署**:#5/#7/#8/#11 端到端待 leo21c wrangler 直推(Mira 線)。
|
||||
> - **issue #11 全做**(P0 run 死端點/P1 list 同源/R4 防複發機制:對照清單+smoke+自驗能攔);P2 validate 依賴 #10、tag resource_id 語意債待方向①。
|
||||
> - **issue #12(self-hosted MCP 缺 CYPHER_EXECUTOR binding)✅ 修+merge main(commit 222a382)**:根因非總管假設的 strip 誤清,是 **TOML 坑——mcp toml `services=[...]` inline 在 [vars] 後被吸成 vars.services**(binding 消失);修法 inline→`[[services]]` array-of-tables(對齊官方 cypher)。wrangler --dry-run 雙向驗(修法後 binding 在/舊版變 env.services)。**端到端待 leo21c acr update 重部 MCP**;連帶解鎖 #11 self-hosted MCP + mira #6 門鈴 + acr push。見 mistakes #21。
|
||||
> - 署名鐵律:跨 repo comment 開頭 `[arcrun CC]`(#12 issue 慣例,非本次 bug)。
|
||||
>
|
||||
> **2026-06-26 上個 session(issue #4/#5/#6/#7 一批)**:
|
||||
> - **#6**(base `PATCH /records/:id`):✅ updateRecord + route,三表 append-only 不破。tsc 綠,端到端待 leo21c。issue open。
|
||||
|
||||
Reference in New Issue
Block a user