rules/07 §3.6:自舉例外——能力只實作一次,但不一定要是 HTTP API

代補 PR #111 的 agent 想加但改不動的段落(該檔受保護)。

立這條的原因不是理論:#97 的修法一開始寫在 cli/src/lib/resource-resolver.ts
(能力住在介面層,違反 §0)⇒ 安裝器拿不到它 ⇒ 同一個 bug 只修了一半,
走 acr 的人有保護、走 install.arcrun.dev 的人沒有——而所有真實用戶走後者。

leo 2026-08-12:「根本就不應該在 CLI,我要的是一個大家都可以用到的規則。」

記三件,都是為了不讓下一個人「修正」回去:
① 為什麼不放 cypher API(自舉/輸入是使用者自己的帳號狀態/它是純函式)
② §0 的正確讀法是「只准有一份、不准住在單一介面裡」,放 API 只是常見手段
③ npm 打包例外:cli/ 下的逐位元組副本由 sync --check 機械擋漂移,不是第二份實作

📍 repo:matrix/arcrun(shared/resource-rule/、cli/、.claude/rules/07)
   + products/arcrun-rag(安裝器待接上,已派工)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
uncle6me-web
2026-08-12 23:50:53 +08:00
parent 13155a1d7b
commit fad5da0e17
+32
View File
@@ -99,6 +99,38 @@ CLI / MCP / Python lib / JS lib 全是薄殼:只做「介面轉換 + 暴露」
---
## 3.6 自舉例外:能力該「只實作一次」,但不一定要是 HTTP API2026-08-12 立)
> 立這條的原因:`Arcrun#97`(更新把使用者的工作流與登入弄不見)的修法一開始寫在
> `cli/src/lib/resource-resolver.ts` ——**能力住在介面層,違反 §0**。
> 後果不是理論:**安裝器(arcrun-rag)拿不到它,於是同一個 bug 只修了一半**,
> 走 `acr` 的人有保護、走 `install.arcrun.dev` 的人沒有——**而所有真實用戶走後者**。
> leo 2026-08-12:「**根本就不應該在 CLI,我要的是一個大家都可以用到的規則。**」
修法(PR #111)把它搬到 **`shared/resource-rule/`:一份零依賴 ESM**
`acr` 與安裝器共用。**它刻意不是 cypher 的 API 端點**,三個理由:
| 為什麼不放 API | 說明 |
|---|---|
| **自舉** | 這條規則要在「決定怎麼裝」的當下用得到,而安裝器的工作正是把 cypher 生出來。放進 cypher = 要先有雞才能有蛋。 |
| **輸入是使用者自己的帳號狀態** | 判斷依據是使用者 CF 帳號上的綁定。送去平台託管的 worker 換答案 ⇒ ①「能不能安裝」綁在平台是否活著 ②使用者的帳號拓撲交給第三方。 |
| **它根本不需要是服務** | 這是**純函式**,唯一的 IO 由呼叫端注入。**§0 要求「能力只實作一次」,不是「能力一定要是 HTTP」。** |
🔴 **所以本檔 §0 的正確讀法是**:能力**只准有一份**,且**不准住在任何單一介面裡**。
「放 API」是達成它的**常見手段**,不是唯一手段。
**判準仍然是那句口訣**:「這段邏輯換一個介面要不要重寫?」要 → 它是能力。
📌 **給下一個人**:看到 `shared/` 底下的純函式**不要「修正」成 API 端點**——
先讀 `shared/resource-rule/README.md §2`,那裡記著評估過並否決的其他形態
(共用 npm 套件=自舉問題換位置;做成零件=要用 TinyGo 重寫一次,那才是第二份實作)。
📌 **打包例外**`acr` 是獨立 npm 套件,`npm pack` 打不進套件目錄外的檔案 ⇒
`cli/` 下必須有一份**逐位元組副本**。那不是第二份實作——
`scripts/sync-resource-rule.mjs --check` 一有漂移就 exit 1,且 `build``test` 都會先跑它
(同 `cli/harness/` 的既有慣例)。**手改副本 = build 紅 publish 擋下。**
---
## 4. 統一帳號來源(薄殼共用同一身份)
所有薄殼讀**同一份**身份設定: