# Pending Changes（規格變更緩衝區）

> 規則來源：`SDD-LIFECYCLE.md` 第 3、4 條。
> 規格層變更（核心設計/方向改變）**只有這一條路**：CC 把 change proposal 寫進「待裁決」——
> 變更摘要與觸發原因＋影響分析（現行 SDD 哪些任務作廢/修改/不受影響/尚未完成）——然後**停止**，
> 等使用者明說「confirm」才依第 4 條開新 SDD；沒 confirm 就繼續依現行 SDD 工作。
> 多個 proposal 可並存，由人一次裁決。本檔不是 SDD，不掛 status。

## 待裁決

### P-2026-07-21：registry 寫入端＋搜尋端修復（leo 親自交辦，最高優先）

> 提案人：總管交辦之 arcrun subagent。
> 觸發：leo 2026-07-21 —「一旦推進一個零件，就自動進 registry；recipe、workflow、app 都應該可以 registry，
> 不然搜不到。一邊是寫進去，另一邊是搜到，當然要有。」
> 判準：「Arcrun ＝ 讓 AI 輕易建立程式碼」「AI 要覺得 Arcrun 比 Python 還簡單，絕不可迷路」。
> **依 D35：本任務找不到對應的 active SDD（現行 active＝portal-auth，與本題無關），
> 故不動 code、不自建 SDD，寫本 proposal 後停止等 leo confirm。**

#### 一句話

registry 的寫入機制**存在且可用**，但它唯一的自動觸發點長在 GitHub Actions 上；
Actions 因防 flag 鐵律被整個刪除後（commit `037cf9b`），**寫入端失去觸發者、庫從此是空的**。
這不是「沒有機制」，是「機制的手被砍掉、沒補上替代觸發點」。

#### 根因（file:line 級）

| 事實 | 證據 |
|---|---|
| 寫入端點存在 | `registry/src/routes/components.ts:112` `POST /components/index-only`（metadata-only 索引，冪等） |
| 寫入實作存在 | `registry/src/actions/indexOnlyComponent.ts:44` 寫 `comp:{hash}:{ver}` + `idx:{canonical_id}` 兩個 KV key |
| 批次灌注腳本存在 | `registry/scripts/backfill-index.mjs`（掃 22 個 contract.yaml → POST index-only） |
| 單顆註冊腳本存在 | `registry/scripts/register-component.sh`（註解自稱「本地+CI 共用 SSOT」） |
| **唯一自動觸發點已不存在** | `git show 037cf9b^:.github/workflows/deploy.yml` 第 269-275 行有 `Register component in registry` step 呼叫上述 sh；`037cf9b` 刪除整個 `.github/workflows/`，**該 step 隨之消失，無替代品** |
| 從未跑過的實證 | 對 leo21c 跑 `REGISTRY_URL=... node scripts/backfill-index.mjs --dry-run` → 22 顆待灌；線上 `/components/search?q=http` 回 `count:0` |

→ **答案：是「有機制但從沒跑過」**（且失去觸發者），不是「沒有寫入機制」。
→ 附帶事實：`registry/wrangler.toml:26` 的 `[[routes]]` 寫死 `registry.arcrun.dev`，
  self-hosted（leo21c）只能靠 workers.dev URL，backfill 腳本預設 `REGISTRY_URL` 也是官方域 —— 需帶環境變數才會打到自己的庫。

#### 重要更正：leo 要的東西**有一半已經存在，只是不在 registry 上**

`acr search <term>`（`cli/src/commands/search.ts`）已經是 leo 描述的「意圖驅動、跨類一次搜」——
它 fan-out 四個來源（component 靜態清單 / `/recipes` / `/auth-recipes` / `/webhooks/named`）。
**實測（2026-07-21，leo21c，真實輸出見交辦回報）**：
- `acr search http` → 命中零件 `http_request`（驗收劇本 1 ✅）
- `acr search notify` → 命中 recipe `line_notify_send` + auth-recipe `line_notify`（劇本 2 部分達成）
- `acr search github` → 命中 auth-recipe `github`（驗收劇本 3 ✅）
- `acr search telegram` → 命中 recipe `telegram_send` + auth-recipe `telegram`

→ **能力在 CLI 有、在 registry/MCP 沒有**。這正是薄殼原則（rule 07）被違反的典型：
  同一個「跨類搜尋」能力長在介面層（CLI）而非 API，於是另一個薄殼（MCP）享受不到。
  **修法的方向不是在 registry 重造一套搜尋，而是把 `acr search` 的 fan-out 能力下沉成 API 端點，CLI/MCP 同吃。**

#### 提案內容（四件，全部需 confirm 後才動）

**A. 寫入端：補回失去的觸發點（不復活 Actions）**
- A1. `acr push` / `acr deploy` 成功後自動呼叫 `POST /components/index-only`（本機發起、低頻、單 repo，守 D20 讀寫界線與防 flag 鐵律）。
- A2. `acr init` / `acr update` 部署完 22 顆零件後跑一次 backfill（讓新裝的人開箱即有索引）。
- A3. **recipe / workflow 不需要新的 registry 寫入路徑**——它們本來就活在 store（KV），
  `acr recipe push` / `acr push` 當下就已「寫進去」。缺的只是**搜尋端讀得到**（見 B）。
  → leo 說的「recipe、workflow、app 都應該可以 registry」，正解是**統一搜尋面**，不是把它們搬進 registry KV 再存一份（那會製造第二份真相源）。
- A4. `app`（bundle）已有 P-2026-07-19 artifact-sharing 卷涵蓋，本卷不重複立案，只在搜尋面預留類別。

**B. 搜尋端：能力下沉 + 語意**
- B1. 在 **cypher-executor** 開 `GET /search?q=`（不是 registry——因為 recipe/workflow 的真相源在 cypher 的 KV），
  server 端做 `acr search` 現有的四類 fan-out，回統一結果（含 `type` 欄位）。
- B2. `acr search` 與 MCP 新 tool `arcrun_search`（或改造 `arcrun_search_components`）雙雙改為呼叫 B1，介面層不再自行 fan-out（回歸薄殼）。
- B3. 語意搜尋：KBDB 那條路已驗證可用（Vectorize），把四類的 description 灌進去，讓「我要打一個 HTTP API」這種自然語言句命中 `http_request`。
  現行 `registry/src/actions/queryComponents.ts:104` 明載「這是 Phase 0 的純文字比對版本，Phase 2 接入 Vectorize」——本項即補完該 Phase 2。
- B4. 搜不到時的文案改為「導向 recipe / 既有 workflow」，**移除「可以用 arcrun_publish_component 提交新零件」的建議**（見 C）。

**C. 斷掉「推人去寫零件」的路**
- C1. `mcp/src/tools/arcrun_search_components.ts:50` 搜不到時明文建議 `arcrun_publish_component` —— 違反 leo 既定規矩（零件走 PR、專業等級）。改為導向 recipe/workflow。
- C2. `arcrun_get_component_guide`（回 TinyGo 寫 WASM 教學）與 `arcrun_publish_component` 對一般使用者是誤導 → 建議降級為「專業模式」才暴露（預設不掛載），或在描述首句明寫「99% 情況你不需要這個，先用 recipe」。
- C3. **查證結果：零件相關「已拆到另一個 repo」未獲證實**——`registry/components/` 22 顆零件仍在本 repo，
  wiki 與 git 均查無拆分紀錄。leo 的印象可能來自 `.github-public/` 對外鏡像（`GitHub mirror 發佈模型`）。**此點需 leo 確認**。

**D. 過時項**
- D1. MCP 仍要求已廢的 `api_key` 參數者共 **15 處**：`arcrun_introspection.ts`（4）、`arcrun_recipe.ts`（6）、`arcrun_workflow_crud.ts`（5）。
  2026-07-20 已改 namespace 明碼 → 這些應改為由 server 端 namespace 推導，不再要 AI 傳。
- D2. **1042 的真正解法已確認並已落地**（本項無需修 code，只需更正記載）：
  `global_fetch_strictly_public` compatibility flag，已實裝於 `cypher-executor/wrangler.toml:13`
  與 `.component-builds/http_request/wrangler.toml:8`。
  leo 說的「開了一個什麼，把所有呼叫都視為外部」＝**這個 flag**（讓 same-zone fetch 走公網前門）。
  wiki 已有正確記載：`system-dev/wiki/cards/decisions/same-zone-1042用flag解不用binding.md`、
  `mistakes.md:101`、`decisions-summary.md:84`。
  → 「graph_neighbors 改用 recipe 繞過」的過時說法**在本 repo wiki 查無此記載**（status.md:50-52 只寫 MCP tool PR），
    該過時記載可能在頂層 InkStoneCo wiki 或 MEMORY.md，需由總管在該層更正。

#### 影響分析（D35 第 3 條要求）

- **現行 active SDD（portal-auth）**：完全不受影響，本提案不碰其任務。
- **`component-registry-canon`（status: paused，2026-05-07 建）**：**本題其實早有此卷**，
  其 §1.2 診斷的根因與今日實測完全一致（「registry 活著但 index 空的，AI 找不到零件就會繞回 Python」），
  尚有 **29 個未完成任務**。→ **建議：不新開 SDD，改為把此卷 resume 成 active**（並把 A/B/C/D 的新項增補進其 tasks），
  這比另立新卷更符合 D35 第 4 條「先搬移未完成任務」的精神，也避免第二份重疊規格。
  ⚠️ 但這需要先把 portal-auth 收尾或轉 paused（單一活性鐵律），**此為 leo 的排序決策，不是 CC 能裁的**。
- **`workflow-discovery`（paused）／`library-map`（draft）**：與 B1 統一搜尋面高度重疊，resume 時應一併檢視是否合併。

#### 待 leo 拍板的四點

1. **排序**：要不要把 `portal-auth` 讓位、resume `component-registry-canon` 來做這件事？（單一活性鐵律強制二選一）
2. **C2**：`get_component_guide` / `publish_component` 要「預設不掛載」還是「留著但改描述」？（品味/方向）
3. **C3**：零件是否真的已拆到另一個 repo？（leo 記憶待證實）
4. **B3 語意搜尋**：四類描述灌進 Vectorize 會產生 embedding 呼叫成本，確認可行？（花錢）

## 已裁決

### P-2026-07-19：artifact-sharing 增補「App（bundle）＋實例譜系＋訂閱更新＋多源分享」

> 狀態：**confirmed 2026-07-19**（leo「好的可走」）。四個拍板點總管採建議值（leo 可翻案）：①排序＝Phase 1.5 緊接 Phase 1、在 KV 退休（#16/#17）前後皆可並行 ②訂閱預設 policy＝notify ③側載標記第一波＝列表標記即可 ④P6 第一波＝官方源＋直連一個外源，org 私區留第二波。tasks 增補見 artifact-sharing/tasks.md「Phase 1.5」段。

> 提案人：雲端總管（leo 2026-07-19 對話三輪收斂後令「寫」）。
> 目標 SDD：`Leo/Arcrun` `system-dev/docs/3-specs/arcrun/artifact-sharing/`（#27＋#31）。
> 依 D35：本檔為規格層 proposal，**寫入 pending-changes.md 後停下等 leo confirm**，confirm 前不動 tasks、不寫 code。

## 一句話

workflow/recipe/template 的實體在平台（CF/KBDB），不在 YAML——YAML 是隨叫隨到的視圖（搖桿）。
因此版本控制、譜系、更新通知必須是**平台內建能力**，git 降級為：引擎程式碼的家＋人審 diff 面＋災備快照。
本提案把 #27 公庫從「單品發布/拉取」補全成「App 商店＋訂閱更新＋實例譜系」。

## 背景（為什麼現在）

- 實證痛點：arcrun-rag（企業）與 Mira（個人）跑同族管線的兩份變體（rag_ingest v2 vs km_wiki_ingest），
  「哪邊同步了沒」靠人腦；claude.ai 07-19 實測抓到的三個引擎缺口再證「修一次、兩實例都該自動受益」的通道不存在。
- T-pack-v2「repo 即真相源」是**過渡義肢**：因為平台缺版本層（KV 讀不回、無版本、無譜系），才用 git 代位。
  義肢照 D15 前例：平台長出器官後拆。
- 地端版（workerd）將成第三個實例形態——在複雜度上升前把「App×實例×版本」模型立好。

## 提案內容（五件）

### P1. bundle 第四型（App）
- `public_artifact` 新增 `type=bundle`。portable_body＝成員清單：
  `[{type: workflow|recipe|template, canonical_id, uuid(鎖版) 或 version_policy(track-latest)}]`
  ＋`install_params_schema`（安裝參數：多人開關、Gitea 端點、LLM provider…）＋`conformance`（見 P5）。
- 「裝一個 App」＝pull 一個 bundle，成員經既有 dependency_manifest 機制解析；
  個人版與企業版＝**同一個 bundle、不同 install params**。
- arcrun-rag 為第一個 bundle（現行 install.sh 即其手寫前身，落地時翻譯成 manifest）。

### P2. 訂閱與更新通知（可拒、可 pin）
- install/pull 時建立訂閱關係：新 entry `artifact_subscription`
  （subscriber namespace、canonical_id、目前安裝 uuid、policy: notify|auto|pin）。
  （`artifact_pull_event` 保持純事件帳本不改；訂閱是關係、事件是史料，分開存。）
- 新版 submit-p 後，訂閱者「得知」的通道**查詢式優先**：
  `GET /subscriptions/updates`（實例/AI/console 隨時問「我有沒有落後」）；
  推播（notify workflow）為選配、且**禁止因發布事件自動 fan-out 到多實例**（D4 紅線——通知生成可以批次/排程，不掛事件觸發鏈）。
- 更新永遠是訂閱端的**顯式動作**：可更、可拒、可 pin 死版本。

### P3. installed_from 譜系＋側載標記（隱形工作流可見化）
- 實例內每個 materialized artifact（workflow/recipe/template）落籍記
  `{installed_from_uuid, installed_at, content_hash}`（entry metadata，不建表）。
- 平台即可回答四態：`up_to_date / behind / diverged（本地改過）/ sideloaded（無譜系，API 直建）`。
- list/console/MCP 的 workflow 列表帶狀態標記。**側載不禁止、只標記**（Android sideload 哲學）；
  「沒有 YAML 就不准」的 policy 不採納——對 AI 是降頻，可見性由本條提供。
- 既有 git 外掛式 drift 稽核（guard 對 hash）為過渡措施，本條落地後退役。

### P4. 更新與分岔語意
- update＝拉新版重新 materialize（installed_from 換新 uuid）。
- `diverged` 者不自動覆蓋：提示二選一——fork（submit-p 推回公庫成自己的作者版本，derived_from 記溯源）或捨棄本地改動收新版。
- 對應 leo 模型：「Mira 和 Arcrun RAG 都 clone 了 rag app，都可以推回去存成新版本，收到更新通知但自己決定要不要更」。

### P5. conformance self-check 隨 bundle（驗收矩陣自動化）
- bundle 附驗收清單：介面×能力的機械檢查（例：portal 登入 200、MCP tools/list 含 kbdb_*＋graph、
  keyword/semantic/graph 三模式各一題 golden question 命中）。
- install/update 完自動跑、產報告；解「企業 GUI 驗了但企業 MCP／個人 GUI／個人 MCP 不知道、檢查到沒完沒了」——
  可用性從人肉巡邏變安裝產物。地端（workerd）實例＝同一張體檢單多跑一列。

### P6. registry＝源（source）非地方：多源與點對點分享（leo 2026-07-19 追加）
- 公庫端點長在 cypher-executor＝**每個實例都內建 registry 能力**；官方公開市場只是「預設源」。
- 實例可加多個源：公開市場／org 內部源／**另一個實例直連**（A 做了 App，B 把 A 加為源直接拉，CF-to-CF，不經公開市場——Homebrew tap 模式）。
- artifact 加 `visibility: public | org | unlisted`；外源拉取走既有 token 認證（portal-auth／MCP OAuth 機制，A 發「可拉取」token 給 B）。
- P3 落籍擴充：`installed_from` 記「源＋uuid」；P2 訂閱跨源成立（B 訂閱「A 源上的 canonical_id」）。
- **信譽記分邊界**：私下/org 內分享的 pull 事件留在該源帳本，**不進公開信譽**；日後同 canonical 發布公開市場，溯源保留、私史不折算。
- 信任判斷仍在 import 端（#27 原則）：來源是誰，列表標記說清楚。

### P6 鐵律：拉取＝落地複本，runtime 零外部依賴（leo 2026-07-19 Drive 之問定形）
- pull/install＝把 artifact（含 dependency_manifest 解析出的全部依賴，跨源亦然）**materialize 進本實例 KBDB**——複本式分發（npm/App Store），非引用式分享（Google Drive）。
- 源斷線/停止分享＝只失去更新，**已裝的照跑**；狀態標 `source_lost`。互相參照在安裝時全落地，runtime 永不回頭找源；只有「查更新」動作碰源。
- 多源不亂的機制：裝完面對的是一張本地清單（每項帶源＋五態標記）；同 canonical_id 跨源衝突＝安裝時顯式選源，不靜默合併；bundle 鎖版 uuid＝lockfile 對應物。

### 排序定調：分享先行、投稿後行（leo 2026-07-19 收斂）
- **官方的本質＝第一個策展人**（leo 定調）：官方源不是特權角色，就是「把很多資源收集起來分享給大家的人」；公開市場＝分享機制＋官方獎勵制度（信譽層）疊上去，作為分享落地後的下一件事。
- **先做**：P6 最小版（官方源＋直連外源）＋P1＋P3 → 這就是產品自己的部署通道（leo 官方源→客戶實例拉 arcrun-rag bundle；第一組 A/B＝leo 與第一個客戶、以及 Mira）；再 P2 訂閱更新。
- **後開**：公開投稿＋信譽榜——空市場掛榜＝鬼城，等 self-hosted 用戶密度夠再開（社群玩法）。
- **零代價保證**：#31「事件是真相、統計是視圖」——pull/submission 事件 day-one append，信譽晚開也能從頭算，先分享不欠投稿任何債。

### 附：獎勵/信譽（確認既有設計，非新增）
- 「貢獻 recipe 得 reputation」＝#31 作者信譽經濟已設計（作者頁/聚合信譽/選版複合分/獎勵層預留、author 綁認證身份）；事件 day-one append 保證信譽可事後計算。
- 本提案只補一句：**bundle（App）作者同樣累積信譽**——組裝 App 與寫 recipe 同屬貢獻。

## 影響分析

- **不建表**：全部走 entry_type＋metadata_json（D6 鐵律）；`artifact_subscription`／落籍 metadata 皆 template/slot 層。
- **與 Phase 1 關係**：不改既有 1.1–1.6 任務；本提案為 Phase 1.5（bundle/lineage/subscription 建在單品公庫之上）。
  1.5 的 recipe KV 過渡（#16）不受影響。
- **與 D4 flag 鐵律**：通知採查詢式優先、禁事件 fan-out（見 P2），無 GitHub 流量、無 Actions。
- **與現行 installer**：過渡期 install.sh 續用；第一步可先讓 installer **代寫 installed_from 落籍**（義肢幫器官接生），
  公庫端點好了再切換 pull 路徑——遷移平滑、無一次性大爆改。
- **受益者**：Mira 跟上企業版＝「訂閱同一個 bundle 按更新」；未來 N 個客戶實例同此通道；地端版=第三個實例非第三套系統。
- **風險**：scope 擴張（#27 尚未動工就加型）——緩解：P1/P3 是最小核（bundle 形狀＋落籍欄位），
  P2 通知與 P5 self-check 可各自獨立分批落地；全部 compute-on-read 起步，物化快照沿用 #31 判準。

## 待 leo 拍板點

1. Phase 1.5 排序：在 Portal（#24/#25 已收官）之後、KV 退休（#16/#17）之前或之後？
2. 訂閱 policy 預設值：notify（通知不動手）？
3. 側載標記的呈現強度：只列表標記，或 console 加「無譜系 workflow」提醒區塊？
4. P6 多源第一波範圍：只做「官方源＋直連一個外源」？org 私區（visibility=org）是否留第二波？


