# FR-122 交接紀錄（LOG，append-only）

> 每棒收工 append 一個 block，寫完永不改。發現舊 block 有誤 → 在新 block「推翻了什麼」欄更正。

## 第 1 棒 — 2026-09-28 — 首腦（需求討論→討論稿→design.md→開卡→派棒 1、2）

**commits**（BE `feature/ai-guard`，皆未 push）：`f942667fb` 討論稿定稿／`31d4c2266` 討論稿輪子版／`f5d56065c` design.md／`e1fd8bffc` 開卡檔／`d27dd1c09` spec branch 改回／本 block 與 STATE 的 commit 見 git log
**Notion**：CM-2293 母卡＋CM-2294～2299 子需求＋CM-2300～2320 子任務，28 張一次建完連號；全 `Not started`。棒 1（CM-2294）、棒 2（CM-2295）決策者已各開 runner 派出。
**派出**：棒 1、棒 2（平行）。**未派**：棒 3～6。

**做了什麼**
- 實查三支 AI 功能程式碼（主專案 `core/plugins/` 三支接線＋三支 jedi 套件＋分類容器），列 16 項資安問題，對照 OWASP LLM Top 10 2025／EU AI Act 第 50 條／2026 事件（康乃狄克法院白字注入案、Snyk PDF 信評繞過、OWASP Q1 GrafanaGhost、LiteLLM 供應鏈、Netskope 影子 AI）
- 查 2026 開源生態：LLM Guard 已 archived、Bifrost 開源版無 guardrail／稽核、Langfuse／Opik／Helicone 定位是開發觀測非產品稽核
- 討論稿兩版（自寫版→輪子版）、design.md、28 張卡，皆派 subagent 產出，本體抽查
- 派棒 1（worker 最小版）、棒 2（gateway 套件骨架）prompt 給決策者

**決策**（決策者 2026-09-28 全部拍板）
- 決定三角色架構 gateway（library）／sandbox（容器）／worker。理由：守門要一份且功能不知道守門存在；解析不可信檔案的箱子不該握金鑰；長工作要有家。被排除：① 各功能自己接守門（三份會漂移）；② `jedi-ai-guard` 純守門套件（仍是三處各接，設定步驟多）；③ 全搬回 BE 不留容器（政府／金融客戶不接受 BE 行程直接解析惡意檔）；④ 容器內 pip install gateway 頂著（金鑰仍在容器、gateway 兩份）
- 決定採開源輪子：LiteLLM library／Presidio／Prompt Guard 2（ONNX）／pydantic，Langfuse 只 DEV。理由：通用偵測與供應商差異不自造。被排除：LLM Guard（archived）、Bifrost（guardrail 與可查稽核皆企業版、guardrail 轉接雲端）、NeMo（太重）、Guardrails AI（pydantic 夠）、Helicone（維護模式）、Phoenix（ELv2）、ProtectAI DeBERTa（準確度略低，Llama 授權對商用無礙）、LiteLLM proxy（多容器＋部分企業授權）、PyTorch（image ＋1GB）
- 決定四級處置「放行／遮罩後送／標記後送／擋下」，原則「能遮就遮、拿不準就標、明確危險才擋」；分類的檔案內容不遮（IP／帳號是判斷線索）改標記＋人審。被排除：一律拒答（消費者聊天產品做法，企業工具不該懷疑付費使用者）
- 決定稽核落自家 `ai_call_log`（人事時地物全欄位，D5 分級存原文），不用 Langfuse 進出貨。被排除：Langfuse／Opik 進正式環境（＋5 容器、不認識租戶、稽核在另一套 DB）
- 決定成本三題：點數計量／原廠鑰試用額度／硬上限只擋 AI 呼叫
- 決定本 arc branch `feature/ai-guard`

**教訓**
- **討論任何 FR 前必查開源輪子**——本案討論稿自寫版定稿、design.md 派出去後決策者才問「有沒有現成的」，整份詳細設計重做。已存 memory `feedback_fr_design_must_survey_open_source_first` 並入 MEMORY.md
- **判定 branch 一律當下 `git branch --show-current`**——首腦憑 session 開頭 git 快照（`feature/review`）判定建卡 subagent 寫的 `feature/ai-guard` 是錯的，改了 22 張卡 33 處；實際決策者已為本 arc 切到 `feature/ai-guard`，subagent 是對的。來回改兩次＋刪 20 個誤追加 block
- **Notion CLI 只能 append 不能改既有 block**——要原地修正得直接打 Notion API（`PATCH /blocks/{id}`），本棒已寫過一次可抄（見對話，未入 scripts）
- 派 subagent 寫文件時，撰寫者會自補討論稿沒定的數值並自標——這是好行為，首腦要把「自補項」列進 STATE §4 給驗收方

**推翻了什麼**
- `e1fd8bffc` commit message 寫「subagent 誤寫 branch 為 feature/ai-guard，已改正為 feature/review」——**錯的是首腦**，`d27dd1c09` 已改回。Notion 22 張卡已改回並刪掉誤追加的更正段（複驗 0 殘留）
- 首腦早期回覆說 Netskope「資料量一年六倍」——原報告指提示數不是資料量，討論稿已修正

**留給下一棒**：等棒 1、2 回寫 `修正待驗證` 逐卡驗收；棒 2 過了派棒 3、4；棒 3 完成是第一次請決策者親手測的節點。

---
## 第 5 棒（前段）— 2026-09-29 — runner（CM-2298／CM-2313，context 滿中繼交接，未寫程式）

**派工**：user 直接貼派工 prompt（CM-2313→2314→2315→2316→2317 依序做，含 CM-2316 末段首腦追加三件）。

**做了什麼**
- 讀 CM-2298 全文＋CM-2313～2317 五張子卡全文
- 讀 CM-2294／CM-2295 兩張已完成子需求卡末段的「首腦驗收」「首腦裁決」，確認棒 1、2 已過、閘道套件形狀（`domain/ports.py`＋`plugin/` 四檔）與 layer 定案、HF_TOKEN／套件發版時機等既定裁示
- 讀 CM-2322（棒 2 收尾追加卡）確認 Prompt Guard 2 int8 量化版（513MB）與 spaCy 只用規則類已定案
- 讀 design.md §5.1／§5.2／§5.9／§5.10／§5.11／§5.12／§5.13／§5.17，拆分表 §6.1「FR-122.5」整段
- 讀套件 `jedi-ai-gateway` 全部原始碼（`domain/`、`app/`、`infra/guard/`、`infra/extract/sandbox_client.py`、`plugin/`）——確認 `GatewayService.complete()` 七步管線、`SandboxClient`（remote／inprocess）都已由棒 2 做好且可用
- 讀套件 `jedi-evidence-classification/docker/` 四支要動的檔（`container_entrypoint.py` 813 行、`classifier_service.py`、`llm_clients.py`、`prompt_guard.py`）與對應單元測試，確認卡片指定的「保留／刪除」函式清單與程式碼現況一致
- 讀主專案 `core/plugins/evidence_classification.py`（697 行）、`_evidence_classification_job_queue.py`、`_evidence_classification_runner.py`、`app/background_job/*.py`（handler_registry／worker_loop／worker_runner）、`evidence_batch_service.py` 分類流程（`classify()` → `dispatch_batch_classify()` → `_run_batch_body()`），確認現有分類流程的完整呼叫鏈
- 讀 `main.py` RUN_MODE=worker 段、`scripts/build/build_classifier_image.sh`、`scripts/build/build_prompt_guard_onnx.sh`，確認 build 側現況
- 開工當下把 CM-2298、CM-2313 標成 `In progress`（照 runner 側紀律）
- **context 滿，做中繼 handoff：未寫任何程式碼、未改任何檔案**

**做了什麼判斷／決定**：無設計決策，純讀碼盤點。

**教訓**
- 五張卡＋母卡＋兩張已完成子需求卡的驗收段＋整份 design.md 相關節，份量遠超過一次讀完就能開始寫的量——這種「先通讀全案再動手」的 runner 任務，讀碼階段本身就該預估會吃掉一大截 context，下一棒可以直接用本 block 與 STATE §3.1 的盤點結果起步，不必重讀全部原始碼

**推翻了什麼**：無。

**留給下一棒**：直接看 STATE §3／§3.1，兩節已把「要改哪些檔、怎麼改、既有座標」寫清楚，可以省掉重新探索的步驟。CM-2298、CM-2313 的 `In progress` 狀態與實際「零程式碼」不一致，接手時先跟決策者說明這個落差（是讀碼被打斷，不是做一半）。

---
## 第 2 棒 — 2026-09-28～29 — 首腦（驗收棒 1～5、派棒 3～6、拆 CM-2313、開 CM-2321～2328）

**派工**：首腦接手第 1 棒，逐卡驗收棒 1、2 後派棒 3、4（平行）、棒 5、棒 6；CM-2313 兩棒 runner 爆 context 後拆卡重派；開文件卡 CM-2321、補強卡 CM-2322、前端修正卡 CM-2323、拆卡 CM-2324～2326、註解收斂卡 CM-2327、新功能卡 CM-2328。

**commits**（皆未 push）
- BE `feature/ai-guard` 自 `abc33954b` 後：`57ffa3738` `6a35e2cf3` `d5d20f135` `742e69892`（棒 1）、`6a7a37f1d` `29e2ea908`（CM-2321）、`bd2da4d69` `41c3acefc` `97da10a1e`（棒 2）、`2d367c4bd`（CM-2322）、`6028d3f42` `701770fdc`（棒 3）、`f8dfb4530`（棒 4）、`28a24e61e`（棒 5 前段交接）、`7cfc36085`（CM-2320）、`d1bde3f3c` `feae9bd3f` `352874d9d` `ff606e27d` `d7e54bf1b` `5af285baa`（棒 5＋CM-2327）
- jedi `feature/ai-guard` 自 `18b52e50` 後：`486c1d9e`（CM-2303）、`76dde3f9` `fc2777b1` `5eb892ca`（棒 2）、`2ac98195`（CM-2322）、`6dfe496a` `3f7aeb43` `c4602bb7`（棒 3）、`8f85e3b6` `89422153`（棒 4）、`bd281942` `ff680b73` `b9207dbd`（CM-2324～2326）、`d1109b9e` `23e35a14` `bcbc77d1`（CM-2314～2315）
- FE `feature/ai-guard` 自 `50bda00` 後：`a385017`（CM-2310 相容）、`4db5b98`（CM-2320）、`279554e`（CM-2318）、`479fd3c`（CM-2323）
- BE 工作區 path dependency（四支 jedi 套件）刻意不 commit，arc 收尾還原 pin 一起 commit

**做了什麼**
- 驗收通過：棒 1（CM-2294／2300～2303）、棒 2（CM-2295／2304～2308）＋CM-2322、棒 3（CM-2296／2309～2310，決策者親測五件事通過）、棒 4（CM-2297／2311～2312）、棒 5（CM-2298：CM-2324～2326＋CM-2314～2317）、文件卡 CM-2321
- 棒 6（CM-2299）：CM-2320／2318／2323 回寫待驗，CM-2319 進行中；CM-2327 回寫待驗；CM-2328 進行中（皆 2026-09-29 派出或回寫）
- DEV 已套 `2026-09-28-fr122-background-jobs.sql`、`2026-09-28-fr122-ai-call-log.sql`；STG／POC 未動

**決策**（決策者裁）
- 補強卡 CM-2322：Prompt Guard 2 只量化詞彙表（513MB），Presidio 只用規則類、不做人名地名
- `jedi-common` 從閘道核心相依移到 `[gateway]` extra（jedi `d1109b9e`）
- socketio 推分類進度不做，記 followup（memory `followup_classify_progress_socketio_push_not_done.md`）
- installer 未在乾淨 VM 實跑，留到上 STG 前在 188 用 `install.sh --upgrade` 實跑
- 安裝包 513MB 沒差；記憶體靠 gunicorn `preload_app`＋installer worker 上限 8→4
- 新開 CM-2328 AI 呼叫紀錄頁（租戶管理員 capability `ai-call-log.read`、唯讀列表＋detail、四個明文欄位 schema 不宣告、掛系統設定區、`AI_CALL_LOG_RETENTION_DAYS` 整筆保留天數清理 ROOT 預設 365）

**教訓**
- **派工 prompt 只給卡號不夠**：大檔多的棒（CM-2313 要開 813＋270＋314 行三支檔＋design 三節）兩棒都在讀檔階段把 context 吃光。修法：卡上直接給座標與「已 grep 過無呼叫者」的結論、每張標「只 Read 這幾個檔、超過 10 次讀檔停下」、一張卡揉三件事就拆三張。拆後三張（CM-2324～2326）一個 session 做完沒爆
- **首腦用 sonnet 派文件 subagent 在本 repo 爆 context**（CM-2321 第一次），改 opus
- **量化不能只看單句**：Prompt Guard 2 全量化 int8 單句分數不變，但前面帶 20 句正常內文的注入句從 0.998 掉到 0.04；runner 沒照卡上「<400MB」硬做，停在只量化詞彙表 513MB 並加帶內文回歸測試
- **兩棒撞同一列文件**：CM-2321 文件棒判斷 `AI_GATEWAY_*` 三變數「程式碼不存在」刪掉那列，實際是棒 2 CM-2308 同時段才 commit；首腦當時也誤判
- **記憶體比 design 大四倍**：閘道常駐實測 1.5GB（design 寫 400MB）；gunicorn `preload_app` 實測 4 worker 從各 530MB 降到 42～268MB。落地版規格建議改最低 16GB／建議 24GB

**推翻了什麼**
- 第 5 棒（前段）block 與舊 STATE 寫模型檔「538MB，int8 量化版」——實為只量化詞彙表版 513MB（全量化 int8 帶內文時注入分數崩掉，未採用）
- 第 5 棒（前段）block 規劃 CM-2313 一張卡做完——實際拆為 CM-2324～2326 三張；舊 STATE §3.1 棒 5 讀碼盤點已刪（棒 5 已收，內容過期）
- design 記憶體估 400MB——實測 1.5GB

**留給下一棒**：看 STATE §3 六點。先驗 CM-2318／2320／2323／2327，再等 CM-2319、CM-2328 回寫驗收；之後決策者親手做 design §7.1 十一條端到端驗收，過了才裁上 STG。

---
## 第 3 棒 — 2026-09-29 下午 — 首腦（驗 .6＋CM-2328～2331、決策者實測揪誤判、開 CM-2329～2334）

**派工**：決策者以首腦 prompt 接手；中途改口令「驗一下 .6」「幫我重啟」「你直接幫我做」「監控一下」，全程邊驗邊開卡。

**commits**（皆未 push）
- BE：`ce49c234e`（CM-2331 runner）；本棒首腦只動 STATE／LOG（本 commit）
- jedi：`d8eeb1e2`（CM-2329）、`0d10ca4e`（CM-2330）、`9bc618b0`（CM-2332 未完）
- FE：`7c53710`（CM-2328）、`3e6d401`（CM-2329）、`efc3e58`（CM-2332）
- 決策者自己平行 commit：BE `9cbf9113b` `63473ddb3` `c8d2232dd`、jedi `709e7404`、FE `46dbb6a` `531823a`

**做了什麼**
- 驗收通過（開檔＋實打端點＋查 DB）：.6 四張、CM-2328（真登入 blsadmin 37 筆／blsit 403／detail 無明文欄位）、CM-2329、CM-2330（規則五句＋離題回歸）、CM-2331（四情境紀錄全留、blsit 那筆 user_id=18）
- 決策者逐頁手測，每個「怪怪的」都追到根因才開卡：CM-2329（遮蔽提示＋注入 flag 警告＋失敗分三類＋刪 route prompt log）、CM-2330（SECRET_REQUEST／RAW_COMMAND 規則）、CM-2331（稽核獨立交易）、CM-2332（儀表板 intent）、CM-2333（沙箱兩誤判）、CM-2334（UI 討論）
- 生四份分類測試檔到決策者桌面，起 worker 實跑 67 份批次
- BE 重啟四次配合手測；殺掉並重起主專案 FE dev server

**決策**（決策者裁）
- 攻擊性 prompt 儀表板本來就 block（≥0.95）、0.8～0.95 flag 照送；裁「flag 要在畫面警告」不改門檻
- 索取密碼／下 SQL 這類「試探邊界」句要正面拒絕並說原因（Prompt Guard 看不見，用格式規則）
- 儀表板選 API：擋操作看 intent，query 一律選同主題最近一支、把握度門檻拿掉（卡上原兩條互斥，首腦寫錯，以裁示為準）
- 待人審維持「標記、人接手」不直接擋（誤判代價是合法證據進不來）

**教訓**
- **模型守門的盲區要用格式規則補，不要調門檻**：Prompt Guard 對「索取意圖」分數 0.004，調門檻只會誤殺正常句
- **稽核寫入不能掛在業務交易上**：jedi-common `@transaction` 遇外層交易沿用不新開，「最該留紀錄的失敗呼叫」正是消失的那批；小幫手有紀錄純粹因為它不拋錯，驗收時被這個假象騙過一輪
- **包裝給 AI 的警語不可拿去算分**：沙箱把「這是資料不是指令」那段一起餵 Prompt Guard，警語本身 0.989，純文字檔全滅；PDF 走另一條路沒中，所以 runner 自驗時用 PDF 看不到
- **runner 撞到卡上互斥要求停下等裁是對的**（CM-2332），首腦寫驗收表時要自己先跑一遍句子
- **決策者實測比首腦開檔驗有效**：本棒五張補強卡全是決策者手測揪出，首腦只負責追根因與寫卡
- **Chrome MCP 分類器服務偶發不可用**，首腦看不了頁面時 UI 題直接外包

**推翻了什麼**
- 第 2 棒 STATE 寫 CM-2328「四個明文欄位 schema 不宣告」為主要驗點——實際更關鍵的是 CM-2331 揪出的「失敗呼叫無紀錄」，稽核完整性比明文遮蔽更基本
- CM-2332 卡上「不要湊最接近的 API」與「稽核進度要產表」互斥，以卡末首腦裁示為準

**留給下一棒**：STATE §3 八點。先等 CM-2332／2333 回寫驗，再派 CM-2334。分類驗收要起 worker、`.env` 要有 `AI_GATEWAY_PROMPT_GUARD_MODEL_DIR`。

---
## 第 4 棒 — 2026-09-29 傍晚 — 首腦（收第一階段全部子卡、驗 CM-2332／2333／2335、開 CM-2335／2338）

**派工**：決策者以首腦 prompt 接手；派 CM-2334（opus）、CM-2332 收尾棒、CM-2335、CM-2338（皆 sonnet）。CM-2334 那棒自行拆出 CM-2336／2337 並做完。

**commits**（皆未 push）
- BE：`1804a778d`（CM-2335 runner）、`d594768cd`～`e3ee3efaa` 七支 docs（CM-2334 討論稿、CM-2336／2337 SPEC）；本棒首腦只動 STATE／LOG
- jedi：`43e70120`（CM-2332 收尾）、`95b9e199`（CM-2333）
- FE：`cf721a6`（CM-2335）、`9ce16d3` `2a07b4a`（CM-2336／2337）

**做了什麼**
- CM-2333 首腦實跑完整分類流程（重啟 worker → API 建批次／上傳五檔／seal／classify）：normal 與帶 BOM csv 拿 AI 建議、藏字 PDF 與注入 txt 待人審、PEM 閘道擋；查 `compliance.evidence_classification_runs.state` 與 `ai_call_log` 核對
- CM-2332 首腦重啟 API 實打五句（稽核進度／控制項完成率產表、重開機／天氣擋 400006 帶具體原因）後才請 runner 收尾
- CM-2335 實測匯出 xlsx 表頭
- 批次收 31 張子卡＋6 張子需求母卡 Done；CM-2327 開檔驗字眼歸零後收
- 向決策者解釋「需人工審閱」＝閘道 flag 級（0.8～0.95 照送＋旗子），與分類「待人審」（藏字／高分不送 AI）是兩件事

**決策**（決策者裁）
- CM-2333 Done；紀錄頁「需人工審閱」欄拿掉（「沒意義 user 會誤會」）→ CM-2335
- CM-2334 只做審閱頁不擴到全流程
- 第二階段等第一階段出貨後再開；下一棒先談成本

**教訓**
- **runner 回寫「未跑完整流程」要首腦自己補跑**：CM-2333 runner 只驗到 extract 層，worker 舊碼還在跑；重啟後走完整條才敢收
- **runner 卡在裁示等待時工作區會留半成品**：CM-2332 程式已改好但沒 commit 沒回寫，狀態看起來像沒動；先 `git diff` 看工作區再判斷「做到哪」
- **決策者一句「看不懂」值得整段重講**：「需人工審閱」名字讓人以為要去打勾，其實只是事後旗子；名詞會誤導就直接拿掉欄位

**推翻了什麼**
- 第 3 棒 STATE 寫 CM-2334 裁完「再拆實作卡（1～2 張 FE）」由首腦拆——實際該棒 runner 自己拆 CM-2336／2337 並做完，首腦事後核對
- 第 3 棒建議「處置欄補標記黃徽章」——實查處置欄本來就有，CM-2335 只剩刪欄

**留給下一棒**：STATE §3 五點，第 1 點成本討論是主題；未裁清單五條在 §3 末段。

---
## 第 5 棒 — 2026-09-29 晚 — 成本首腦（第三階段從討論到結案：CM-2339～2350、CM-2353）

**派工**：決策者以首腦 prompt 接手，主題「成本討論」；後半段決策者裁「你只管成本部分」，與主線首腦（第二階段 .8／.9）平行。

**commits**（皆未 push）
- BE：`60241a257`（討論稿）、`34b179818`（design 落地＋開卡）、`d4158de59`（2345）、`c269d2c41`（2349）、`b782c0f8d`（2346）、`7f161b5ab`（2347）、`a5932f070`（2348 凍結表）、`ebc8a3ad2`（2350）、`ddfb39df1`（2353）；本棒首腦只動 STATE／LOG
- jedi：`2be00daf`（2344）、`7c3db8b5`（2346）
- FE：`60d2afb`（2346）、`a8f448c`（2347）、`6a34031`（2350）、`5f8fdf1`（2348）、`70046bd`（2353）

**做了什麼**
- 討論起手用 DEV `ai_call_log` 實測數據（小幫手 0.0015／儀表板 0.034／分類 0.016 USD 每次）＋查 LiteLLM／Bifrost 業界做法，決策者當場推翻點數制改美金制；設定放金鑰頁→手測後再裁拆成獨立頁＋自有能力點
- 三波派工：第 1 波 2344＋2345 同棒（本體 subagent，事後決策者糾正）；第 3 波 2346／2347／2349 三線平行（決策者自派）；FE 2348／2350 平行；補 2353 重做頁
- 每張卡開檔核 commit 檔案清單（查平行夾帶）、查 DB 證據（blocked 筆數、seed 列）、抽查 DDD；最後決策者手測全過收 13 張 Done

**決策**（決策者裁）：見 STATE §2 09-29 那列

**教訓**
- **「派工」＝給決策者 prompt 自己開 session，不是本體開 Agent**：本棒前三支（討論稿／design 落地／2344＋2345）都用 subagent 跑，決策者反問「不是給我 prompt 我去派嗎？」——memory 已補
- **新增系統設定頁必登記授權豁免清單**（CM-2353 runner 踩到）：沒登記時租戶管理員整頁被 license 過濾、平台管理員看不出來，驗收要用租戶管理員登
- **平行 runner 改同一支 repo 檔**：CM-2346 把共用小函式插在 CM-2349 剛加的方法前面，worker 起不來——插入位置要避開別人 hunk
- **STATE 記的 PID 會過期**：8000 那支早被別棒換過，照 STATE kill 錯人；一律 `lsof -iTCP:8000` 查當下
- **runner 自標「驗收打折處」很有用**：三棒都主動寫了「在自起埠驗、8000 沒重啟」，首腦才知道要重啟再給手測

**推翻了什麼**
- 09-28「點數計量」與「配額寫進 license limits」兩條裁示
- 第 4 棒 STATE §3 第 1 點「未定四題」——全部裁定並落地

**留給主線**：出貨基線待重產（現在共三支 FR-122 migration＋兩支新能力點未進 seed）；用量頁 `key_source` 篩選小卡未開；DEV 手動修的孤兒綁定不必進 migration（STG 沒有）。

---
## 第 4 棒（續）— 2026-09-29 晚～深夜 — 首腦（第二階段 .8／.9 三卡、出貨基線重產、文件對齊）

**派工**：CM-2351／2352（sonnet 平行）→ 收口卡 CM-2354（opus，中途裁「拿掉 presidio-anonymizer」續做）→ CM-2338（sonnet）＋ CM-2355（opus，決策者放行 188 基線庫寫入）平行，首腦 Monitor 盯 Notion 狀態。

**commits**（皆未 push）
- BE：`9001b0681`（2351）、`b864497a8`（2352）、`5f5571b82`（2354）、`e1e79dd5d` `1382fa225`（2355）、`f7821c893`（2338）；首腦 STATE／LOG
- jedi：`42ccdbc3`（2352）、`8a7ad38d` `e9bac936` `315866cc`（2354）

**做了什麼**
- 2351 首腦親跑 STAGING worker 拔金鑰＋模型目錄 → exit 1 一次列兩項
- 2352 核釘版與 venv 一致、sha256 重算相符；發現 strict_model_checksum 預設 False 沒開 → 併進 2354
- 2354 卡在 presidio-anonymizer 釘 cryptography<49；首腦 grep 發現閘道從未呼叫 AnonymizerEngine → 裁拿掉而非白名單；驗 audit 0 項、重啟 API 到 cryptography 50 小幫手正常
- 2355 唯讀先查 188 基線庫：真缺的只有 FR-122 五支（後兩支 manifest 未登記），STATE 寫的 FR-114 疑未進是虛驚；放行後 runner 做，首腦逐項核 DB／diff／守衛
- 2338 核 14 條 id、沿革字眼零命中；殘留三處 presidio-anonymizer 字樣（2354 晚於開卡）

**決策**（決策者裁）
- 第二階段只做 .8＋.9；.7／.10／.11 劃掉不記 followup
- CM-2354 三件都做；presidio-anonymizer 拿掉、不白名單
- 基線重產放行、派 runner 做（首腦建議）

**教訓**
- **設計時「成對」寫進的相依要在實作後回頭清**：presidio analyzer＋anonymizer 成對進 pyproject，實作只用一半，那一半反而是卡升版的兇手；釘版卡（.9）順手 grep「宣告了但沒 import」很值
- **pip-audit 不給嚴重度**：閘門只能「有就擋」，白名單靠人判；先查「我們的程式碼碰不碰那支 API」再裁
- **STATE 的「疑未進基線」要先唯讀查再開卡**：一句「疑十餘支」差點讓重產卡範圍失控，實查只有五支
- **`poetry update X` 對 path 套件不重讀 pyproject**：要連套件名一起列（runner 踩到）
- **Monitor 盯 Notion 狀態比等人喊有效**：兩張平行卡回寫首腦立刻驗，決策者離席也能收

**推翻了什麼**
- 第 4 棒 STATE §4「FR-114 十餘支＋FR-121 疑未進基線」——實查為虛驚
- CM-2352 卡上「pip-audit HIGH 以上才擋」——工具不給嚴重度，改「有就擋」

**留給下一棒**：收 CM-2355／2338／2299 → 上 STG（188 HF_TOKEN、build 含沙箱 image、`install.sh --upgrade`、§7.1 8／9／10）→ 收 CM-2293 → arc 收尾（pin 還原、六支套件發版、SPEC、記憶體規格文件、memory）。design.md 三處 presidio-anonymizer 殘留併收尾。

---
## 第 4 棒（收尾）— 2026-09-30 — 首腦（第二階段收口、守門現場可調、六支套件發版、1.22.0 進版）

**派工**：CM-2356（DB 總覽文件）、CM-2357（小幫手角色 prompt，本體 subagent）、CM-2358（ai-quota.update 授予規則，本體 subagent）、CM-2360（prompt 外置＋規則目錄出貨＋維護手冊）、CM-2359（六支發版＋pin 還原）、CM-2361（spec 五頁＋記憶體 16GB＋memory）、CM-2362（version-bump 1.22.0＋快照）。

**commits**（皆未 push）
- BE：`b495fca7c`（2356）、`0cb673091`（2358）、`fa09ba4f9`（2360）、`9637559a2` `da5e2db00`（README／手冊進站，首腦）、`354ba4039`（2359 pin）、`924c5eefb`（2362 進版）、`4a0a9a60c` `0cf4ff5aa` `db195b0d9` `1a4390897`（2361）、`e0e05fa8e`（2362 快照）
- jedi：`d73a9d21` `2d78e264`（2357）、`a00affb1`（2360）、`dd4a5b14`（2359 六支 bump）
- FE：`55d8422`（2362 版號）

**做了什麼**
- 決策者手測揪出：CMMC 被角色 prompt 推掉（改「合規稽核助理」＋ISO 預設 2022）、「調整額度」連結權限（機制對、預設名單錯：IT執行人員也拿到 update → 改只給 is_admin，既有資料不動）、prompt 改一句要重出 image → CM-2360 把三段 prompt 外置到 `prompts.yaml`，並發現 design §5.5.3「規則目錄隨 image 出貨可覆寫」根本沒落地（Dockerfile／compose／installer 全沒接），一併補齊＋寫客戶維護手冊
- 發版：presidio-anonymizer 拿掉後 cryptography 升 50；六支發 Nexus；BE 還原 pin，六支 realpath 指 site-packages、守衛 114 綠、audit 0 項
- 手冊搬進 FR-122 站可讀 HTML（決策者：站上連 md 不能讀），user-manual 留 symlink
- 三階段 42＋張卡全 Done，只剩母卡 CM-2293 等 STG 三條

**決策**（決策者裁）
- 第二階段只做 .8／.9；.7／.10／.11 劃掉不記 followup
- 守門「要可維護、要寫文件」→ CM-2360；schema 歸屬先不整理；額度預設先不動
- e2e 要補但不擋合 main；快照肥大先 build 版後面討論

**教訓**
- **設計寫「可覆寫」不等於落地**：§5.5.3 的規則目錄出貨機制從棒 2 到收尾沒人接 Dockerfile／compose，靠決策者問「以後怎麼調」才暴露。收尾前要對 design 每條「運維可調」逐一查出貨鏈
- **prompt 跟規則同等級**：措辭一天改兩次，寫死在 .py 就是每次重出 image；一開始就該跟 YAML 一起外置
- **平行 runner 夾帶又踩**：CM-2362 帶走 CM-2361 的 `install.sh` hunk（內容對，但回寫還說「沒 add」）；驗收必對 stat
- **runner 回「額度用完沒實打」是機制在跑的證據**，不是驗收失敗；查清是哪層設定（租戶自設 0.04）再判
- **快照機制指數成長**：`legacy/` 巢狀放每版整個 site，前例本身有雷，照前例做的 runner 沒錯；切版前要看 commit 檔數
- **決策者「看不懂」要整段重講，不要補細節**：「需人工審閱」→ 講清楚它只是事後旗子、沒人消費 → 裁拿掉

**推翻了什麼**
- design §5.5.3「規則檔隨 image 放 /opt/guidant/ai-gateway-rules/」——CM-2360 前為假；現已真
- design §5.6 Presidio「analyzer＋anonymizer」——實作只用 analyzer，anonymizer 已從相依移除
- STATE §4「FR-114 十餘支疑未進基線」——虛驚

**留給下一棒**：STATE §3 五點——決策者合 main／push → 188 出包（沙箱 image 要重 build）→ STG 驗 §7.1 8／9／10 收 CM-2293 → e2e 另棒 → 快照肥大另案。

---
## 第 4 棒（出包段，中繼交接）— 2026-09-30 下午 — 首腦（合 main 後出包撞三擋點，決策者判首腦已疲乏、換棒）

**派工**：CM-2363 出包卡（sonnet），兩輪回寫皆卡住。

**commits**（已 push main）：`13da8b714`（push 授權 memory）、`f6e3d8a7a`（lock 同步＋pip-audit 進 dev＋requires-python<3.15）

**做了什麼**
- 確認三 repo 已在 origin/main；補推首腦最後兩支文件 commit
- 解 CM-2363 兩個擋點；第三個（STG DB 落後）裁不套、改 smoke 連基線庫，寫進卡末

**決策**（決策者裁）：授權首腦本 arc 內 push；出包不套 STG DB

**教訓**
- **🔴 `poetry.lock` 在本 repo 入版控**：memory `feedback_jedi_package_batch_release_execution` 寫「lock 是 gitignored」是舊事實，首腦照它在 CM-2359 卡上寫「lock 不 add」→ 188 `poetry install` 直接擋。寫卡前 `git check-ignore` 一秒的事沒做。該 memory 要改
- **加進 build 流程的工具要同時進相依**：CM-2352 讓 `audit_deps.sh` 進 build，但 pip-audit 只在首腦本機有；驗收「本機跑過」≠「build 機跑得過」
- **出包 SOP 的 DB 斷言每版都會撞**：smoke 預設連 STG stack，而 STG DB 在出包前永遠落後本版 migration（鐵律不准先套）——這是 SOP 與鐵律的結構性矛盾，不是這棒的錯；長期解法是 smoke 預設連基線庫或 build 機自帶一顆 throwaway DB，記 followup
- **首腦疲乏訊號**：同一件事問兩次（push 授權）、看錯 branch 狀態、卡上寫錯事實——決策者「你已經爆掉了」是對的，這種時候該主動提交接而不是硬撐

**推翻了什麼**：memory「poetry.lock 是 gitignored」（錯，入版控）；CM-2359 卡「lock 不 add」（錯）

**留給下一棒**：等 CM-2363 回寫 → 自己 ssh 188 核開包驗至少兩項 → 收卡 → 開部署卡（`install.sh --upgrade` 上 STG，這步要決策者放行）→ 驗 §7.1 8／9／10 → 收 CM-2293 → e2e 另棒、快照肥大另案、smoke DB 結構性問題另案。

---
## 第 6 棒 — 2026-09-30 晚 — 執行者（1.22.0 出包九輪、190 全新安裝驗過）

**角色**：決策者改派「執行者」，自己在 188 出包不派卡。

**commits**（皆 push main）
- BE：`e86601eb9`（litellm 不編譯）、`e2de14ea6`（google.api_core，後被 e6109ff14 取代）、`03b664980` `0dc0b6fbd`（stdlib 自動推導）、`c196f61d1` `c9775e84a` `3e678856b`（smoke AI 設定＋閘道 YAML 資料檔）、`e6109ff14`（nofollow 擴到封閉集合、presidio／spaCy 附帶、en_core_web_sm 鎖進 pyproject）、`d805f19f3`（cffi 全 import 名扣除）、`964d8a6fe`（沙箱 wheel 用 venv 3.11）、`5b8706b56`（netrc secret）、`088d2351d`（compose 沙箱設定三 BE 容器共用）
- jedi：`e877456c`（stage_context PYTHON）、`4b3c8f7f`（Dockerfile netrc secret）、`017d12cb`（requirements 剔 0.0.1 pin）

**做了什麼**
- 出貨前盤點揪出兩題先問決策者：smoke 目標庫（README 說連 STG stack，1.21.0 實際是建臨時庫）、monorepo 在別 branch。裁：從 STG 唯讀 dump 建 `guidant_ai_smoke_1220`、切 main
- build 九輪才過（16:19～19:39）；封包 `--skip-prod-key-check`；四項開包驗 188 實做
- 決策者中途令：190 uninstall → 全新安裝。首裝發現 socketio 無限重啟（installer 報綠）→ 修 compose、同版號重出、再裝一次，8 服務全綠、§7.1 8／10 驗過
- CM-2363 回寫 #3、修正待驗證

**決策**（決策者裁）：建臨時 smoke 庫；monorepo 切 main；stage_context 改 PYTHON（動套件）；封包 skip PROD 鑰；「不要一直 rebuild，先停下分析」→ 第六輪起改為先整份對照再動手；bundle 從 188 直接 scp 到 190

**教訓**
- 🔴 **上游 import 消失會讓一整串隱性相依掉出 Nuitka 編譯圖**：1.21.0 儀表板直接 import Google SDK 順路帶進 google.api_core／unittest／csv／email，1.22.0 改走閘道全掉。每輪 smoke 只暴露一個，前四輪就是這樣逐個補。正確做法是第五輪的：把「該在產物的」與「實際在產物的」整份 diff 一次列完
- 🔴 **nofollow 只下清單、複製卻整包封閉集合＝套件被拆一半**：40 支套件一半編進二進位一半在磁碟，Nuitka 只認二進位那半。1.21.0 沒事純屬碰巧。nofollow 與複製範圍必須同一組
- **build 機 venv 會壞**：8/28 pip 中斷留 42 個 `~` 殘骸，poetry 看 lock 以為 attrs 裝著。`pip check` 一行就看得到，出包前置盤點該加這條
- **installer 健康檢查對 socketio／worker 只看「執行中」**：socketio 無限重啟 install.sh 照報綠。驗收要看 `RestartCount` 與 log，不能信安裝總結
- **決策者「不要一直 rebuild」是對的**：每輪 20 分鐘只換一條線索，第五輪停下來整份對照後一次修四個坑，比前四輪加起來快
- 卡上「guidant.env sample 有 AI_GATEWAY_RULES_DIR」是錯的驗收條件（installer 刻意不寫），寫卡時要對照實作

**推翻了什麼**
- README「smoke 連 STG stack 的 guidant-db」——與「出包前不准套 STG」結構性矛盾，前幾版都靠臨時庫繞，沒人寫回 README（待補）
- d7e54bf1b「api 不碰沙箱所以不給 token」——api 啟動心跳掃描會建 runner，要 token
- 首腦 LOG「smoke 改連基線庫 188:25432 guidant_ai」——基線庫沒跑過套件輪、69 支套件 migration 只登記 1 支，DB 斷言必紅，走不通

**續（21:00～21:35）**：決策者手測後令三件——藏 Azure OpenAI／Ollama 卡（FE `0413b6e`，重出 FE image＋同版號重封包 sha `e266d94e…`）；188 清舊包／beta image／agent 舊 image／build cache（7.5GB→35GB）；**STG 升 1.22.0**（先停 api／socketio 再 `--upgrade`，6 支 migration、舊 classifier 容器由 installer 換成 sandbox，8 服務健康零 Traceback，§7.1 8／10 驗過）。「租戶用不到 AI」查 `ai_call_log` 是金鑰當時設錯，非 bug。

**續（21:40～22:45）**：決策者手測抓到「第二次儲存把上一次金鑰洗掉」——BE 合併只走 payload 有的供應商＋整格覆寫、FE 沒改的那家不送，兩邊湊成缺席＝刪除。BE `62a864e62`（以既有列為底＋六條測試）、FE `3826339`（每家一律送）。重出 BE／FE／init，沙箱沿用（源碼無變、重建卡 deb.debian.org 20 分鐘 kill 掉），封包 sha `0f788947…`；STG 與 190 先停 api 再 `--upgrade --force`，兩台 commit 62a864e62、全綠。

**教訓**：「空值＝沿用」的合併規則若只走 payload 的鍵，前端一個「不送沒改的」最佳化就把它變成刪除——沿用要以既有列為底，刪除只認顯式旗標。`docker builder prune -af` 清 cache 後沙箱 image 要重抓 apt，Debian 鏡像慢時等於卡死；源碼沒變就不必重建。

**留給下一棒**：STATE §3——手測金鑰沿用＋§7.1-9 後收 CM-2293；190 license／Agent 重接；189 POC 等放行；README 補 smoke 臨時庫 SOP；PROD 鑰；`guidant_ai_smoke_1220` 留刪待裁

**續（22:55）**：決策者放行 POC——189 先停 api／socketio 再 `--upgrade`（Agent 心跳中，不停必 deadlock），主線 5 支、全綠、62a864e62。三環境同包。

**中繼交接（23:00）**：context 滿換棒。續棒 prompt 在 STATE §9「執行者續棒」。本棒 commits 全 push；CM-2363 修正待驗證（回報 #3～#5）。

---
## 第 7 棒 — 2026-09-30 深夜 — 執行者（收口：三環境盤點、CM-2363／CM-2293 Done、SUMMARY、橫向文件）

**派工**：接執行者續棒 prompt，pre-flight 盤點完決策者令「122 應該差不多了，可以做收尾，授權 push」。

**commits**：本 block 所在 commit（SUMMARY／analysis／README SOP／design §7.1／memory 三條新增＋四條更新）；已 push main。

**做了什麼**
- 唯讀盤點：三 repo 乾淨等 origin/main（BE e62c3afcb／FE 3826339／jedi 017d12cb）；188／189／190 五個 guidant 容器 1.22.0 健康、`RestartCount` 全 0、`/version` 三台皆 62a864e62；沙箱 image 三台同一顆（58cb0cf61b25）；bundle sha 0f788947 相符；190 Agent 401 迴圈（enroll token 已換）、license 未重匯
- 收尾六步：SUMMARY 由 LOG 七 block 濃縮；analysis 寫出包鏈根因；`scripts/build/README.md` 補臨時庫 SOP；design §7.1 第 8／10 改 ✅、第 9 標未驗；FR README／features README 狀態改已出貨；memory 三條新增（Nuitka 隱性相依／installer 健康檢查盲區／缺席＝沿用合併）＋ push 授權失效＋ lock 入版控更正
- Notion：CM-2363 append 收口段改 Done；CM-2293 母卡 append 五段改 Done

**決策**（決策者裁）：收尾；§7.1-9 未驗接受打折；push 授權本次用畢即失效

**教訓**
- 「差不多了」的收尾令要把**打折處逐條寫進 SUMMARY**（§7.1-9 未驗、PROD 鑰缺、190 license 未重匯），不能只寫「已出貨」——下一個讀 README 的人看到 ✅ 會以為可交付客戶
- 收口 pre-flight 多查一行 `RestartCount` 與沙箱 image ID 三台比對，比只看 `docker ps` 的 healthy 可靠（本棒查到三台沙箱同一顆，才敢寫「同包」）

**推翻了什麼**：memory `feedback_jedi_package_batch_release_execution`「poetry.lock 是 gitignored」（第 4 棒已指出，本棒改檔）；FR README「待上 STG 驗 8／9／10」→ 8／10 已驗、9 接受未驗

**留給下一棒**：無下一棒。後續各自開卡：PROD 鑰、190 license／Agent、e2e、arc-review、快照肥大、臨時庫清理。

---
