# FR-170 交接日誌（LOG）

> **append-only**：每棒追加一個 block，既有 block 不改。發現舊 block 有誤，在新 block 的「推翻了什麼」寫明。現況看 `FR-170-STATE.md`。

---

## 第 1 棒｜2026-10-29｜首腦：分析、四條裁決、開卡、無人值守重檢

**角色**：首腦（分析決策），決策者雷門。Fable 5.1。

**commits（BE `feature/FR-139`，未 push）**
- `79eff2496` analysis、design、README、架構圖、cards.py／gen 腳本；開母卡 CM-3232＋八張子卡 CM-3233～3240。
- `5396eb110` architecture.html 從提案草圖改成定案版（四條裁決、檔案歸屬）。
- `981e2f635` 全案重檢：文件、建卡腳本、九張 Notion 卡對齊「等 166／166.1／169 收完才開」；首次 build FR-170 站與登記表。
- `4f1f4b27c` P0 改成無人值守可跑完：十張卡八批、套件單卡發 beta、系統身分改每請求裝；重寫九張 Notion 卡、新開 CM-3288／3289。

**決策**
- 定位改判：Agent 當獨立產品，模組在外層在內；排除照抄主系統四層、排除換 Postgres、排除維持現狀靠 reviewer。
- 四條裁決全採建議；命名 `guidant-agent`；DB 通用範圍定 Postgres＋SQLite。
- 等 FR-166／166.1／169 收完才開（當晚三案收完，立即派）。
- 無人值守：開發卡發 beta、結案卡轉正式、決策者按結案批即確認套件清單；單卡要人裁的事停下回寫、狀態留 In progress。
- jedi-remote-agent `1c1cdcd5`（事件碼 6230～6236）不單獨發版，等 FR-167 結案卡帶。

**推翻了什麼（本棒自己的前稿）**
- 1-2「啟動時裝一次系統身分」是錯的：jedi-common 身分是 ContextVar，Flask 每請求每執行緒各一份；改 `before_request`＋背景入口裝飾器。且 0.0.31 的 DTO 沒有 `is_system_context` 欄位。
- 1-1 要改主系統 `pyproject.toml` 一行：違反一卡一 repo，且主系統自己列了 psycopg，拔掉。
- 2-1 守衛與 2-2 宿主殼同批：2-2 搬走 `core/local_db`，2-1 凍結清單立刻過期；改 2-2 先。2-3／2-4 都改 bootstrap.py，拆開。
- 2-3 手測 `sudo ifconfig down`：跳密碼、demo 模式不起心跳；改測試模擬＋SIGTERM 子行程。
- 1-3 排練 `docker exec guidant-agent`：188 容器名是隨機 `zen_sutherland`，agent.db 是 WAL；改 `docker ps` 查名、`.backup` 抓。
- 1-3 釘 jedi-file-upload 1.3.8：Nexus 現行 1.5.0，差異只選填掛點；改釘 1.5.0。

**教訓**
- 重檢時每條假設都開檔核到底，花了一小時，決策者點名太慢。該先列「哪些沒驗會讓半夜停掉」只查那幾條，十五分鐘內回報，其餘寫進卡上「開工先確認」。
- 完成宣告只 grep 三個詞被退：「整個重新檢視」要逐檔逐卡讀，含 Notion 實際內文。
- 工作坊帳號 ccy（`~/.claude`）沒信任過 evidence-agent 主資料夾，bg session 開不起來（`Workspace not trusted`）；信任看 git 主資料夾不看 worktree，決策者在主資料夾接受一次即解。之前 Agent 卡都用 ccy3 跑所以沒踩過。
- Notion 大量 wipe＋rewrite 會 429；`notion_case.notion_request` 遇 HTTP 錯誤是 `sys.exit(1)`，包裝時要接 `SystemExit` 並 patch 模組全域。
- 母卡批次行用 `[:34]` 硬截會把標題切成「jedi-fi」；改以分號切第一段。

**環境實況（當時）**
- Agent HEAD `d2fe93f`；jedi-common 0.0.31／jedi-file-upload 0.0.22；1,655 測試綠。
- Nexus 26 支套件版號全在；jedi-remote-agent 1.10.0b1（FR-167）已發。
- 工作坊 28 已派批 1：CM-3233 In progress（23:38）、CM-3234 In progress（23:40，第三次開成）。

**交給下一棒**：首腦驗收，見 STATE §4。

---

## 第 2 棒｜2026-10-30 早｜首腦：一夜結果盤點與交接

**角色**：同第 1 棒 session 續接，首腦。決策者要求「交接首腦工作」。

**一夜結果（工作坊 28，無人值守）**
- 批 1（CM-3233、3234）與批 2（CM-3235、3236）四張全部做完，工作坊首腦 session 第 1 輪就驗過，狀態 `驗收通過待確認`。沒有一張停下來要人裁。
- Nexus 上三個 beta 都在：jedi-common 1.3.7b1、jedi-password 0.1.0b1、jedi-iam 1.11.0b1。
- 卡上「無人值守」改法生效：沒有 sudo、沒有等人確認發版、沒有 188 容器名寫死的問題。

**卡住的地方（要決策者動手）**
- CM-3236 合回失敗：工作坊把未追蹤的 `jedi-password/poetry.lock` 當成「改到一半的檔」拒合。卡設計時沒想到工作坊的髒檔判定連 untracked 也算。
- CM-3235 工作坊 log 沒有合回紀錄，`ws-CM-3232` 停在 3234 合回那一筆。批 3 依賴它。

**工作坊首腦抓到的**
- jedi-iam 測試 4 支舊紅燈（1.10.0 就有），base 同樣紅，不是本案弄壞；建議批 7 前開小卡修。

**教訓**
- 工作坊合回的髒檔判定含 untracked 檔。套件卡若會產生 `poetry.lock`（新套件第一次 `poetry install`），卡上要寫「lock 加進 .gitignore 或刪掉再回寫」，否則合不回。**下次開套件新套件卡要補這句。**
- 卡上寫「首腦照這個驗」時，工作坊會自己開一個首腦 session 照卡驗；本 session 的角色退成抽查與裁示，不要重驗一遍。

**commits**：本棒只改 STATE／LOG。

**交給下一棒**：STATE §4。

## 第 3 棒｜2026-10-30 下午～傍晚｜首腦：P0 合回主線、兩張補卡、Agent 資安規範、決策者裁暫停

**角色**：新 session 冷接首腦（決策者「照 §0 讀序與 §6 pre-flight 盤點完回報，等我發令」）。

**做了什麼（時序）**
1. 盤點時查出 STATE 寫的「CM-3235 沒合回」其實是被 CM-3236 擋在合回隊列後面（工作坊依驗收時間逐張合、一張失敗整隊停）；3236 的髒檔 `poetry.lock` 盤點當下已不在，按繼續派工就全過。決策者按下後 10:02 兩張同秒合回、批 3 開派。
2. 工作坊 28 當天跑完 P0 十張＋補卡 3290／3291／3292／3304／3305（共 15 張）。
3. 決策者要求比兩版差異。用合併演練（暫存 worktree 把主線合進重構線、跑全量）：無衝突、1781 綠／50 紅——45 紅是本機磁碟剩不到 1GB（主線同紅），**5 紅是主線 FR-167 平行加的 `core/update_sync.py`、`core/agent_tree_verify.py` 違反 P0 守衛**。決策者裁「先合、開卡修」。
4. 合回：jedi `88ab3b05`、Agent `8585e99`（commit message 寫明 5 支守衛紅）。開 CM-3314（修守衛）、CM-3315（主系統改釘五支）掛母卡，開卡前查過 FR-170 全部子卡與 FR-167 Agent 側兩張無重複。
5. CM-3314 小弟做到跨模組 import 停下問（卡上寫白名單只能變短，它沒自己加，正確）；原 session `failed` 等不到回答，首腦回寫裁示到卡、按 resume 讓工作坊重派新小弟接著做。裁示：`is_container` 就地兩行；`→ running_tasks`、`→ task_executor._get_stream` 與 vulndb_sync／profile_sync 同形，進白名單、P1 上移 port 時一起刪。
6. 兩張做完、工作坊首腦驗過、決策者按 Done。首腦抽查後發現只合到 `ws-CM-3232` 沒進主線，而 3315 小弟已把 BE 主資料夾 venv 裝成新版、pyproject 卻還是舊 pin；合回主線 Agent `9044d95`、BE `36d6d5972`，重啟本機 Agent。
7. 順手修的 FE bug（決策者測到「下載沒反應」）：FR-169 CM-3230 把主控台下載改走 `useProtectedDownload` 後，三處呼叫端 `download: () => consoleApi.downloadFile(uid)` 多包一層箭頭函式，密碼確認後拿到函式不是回應、靜默結束；Agent log 只見查開關的 `/api/me` 無下載請求是判斷依據。主線同壞，與重構無關。同 commit 把登入頁「AD」統一成「AD／LDAP」、範例換 `EXAMPLE\amy.chen`。FE `bec490d5`，已 push。
8. 寫 Agent 自己的六支資安規則 `.claude/rules/security/`（按 Agent 威脅面改寫、不是 BE 複本，每條指向既有 canonical 函式）＋覆蓋守衛；CLAUDE.md 加段；BE 總覽表與守衛加 Agent。Agent `a6fdf7e`、BE `7962f93ea`。
9. 給 FR-167 首腦的通知 prompt（Agent 結構已換、新規則、CM-3314 撞檔警告）已交決策者轉。
10. 決策者問「後面還有多少」「現在能 work 嗎」「為什麼看起來還是舊架構」：答 P1～P3 規模與三選項、三層行為不變證據（42 條路由相同／1839 綠／本機實測）、P0 刻意不搬業務模組。**決策者裁：先發版測 FR-167 線上更新，FR-170 暫停。**

**教訓**
- 工作坊「合回被拒」會卡住整個合回隊列，後面的卡看起來像「沒合回」其實是在排隊；盤點時先看隊列順序再判。
- 決策者按 Done 的卡只代表合進工作坊線，**不代表進主線**；首腦抽查要多看一步 `ws-<母卡> vs feature/FR-139`。本棒就是這樣抓到 BE venv 與 pyproject 對不上。
- 主 repo 的卡（Repo 欄空）小弟直接在主資料夾的 venv 裝套件，會影響決策者正在跑的 BE；開主 repo 的套件卡要在卡上寫「裝完提醒 BE 重啟」，本棒卡上有寫。
- 比兩版差異用合併演練＋全量測試＋路由 diff，一次收齊；決策者點名前一天逐檔讀太慢。
- 平行 FR 在主線加的新檔會撞新立的守衛，合回前要跑一次守衛預知紅燈數，不要等合完才發現。
- 守衛新 paths 預留未來目錄（`guidant_agent/<模組>/`）時，覆蓋守衛要放行空命中，不然 P1 前一直紅。

**commits**：BE `7962f93ea`、`36d6d5972`、本棒交接；Agent `8585e99`、`a6fdf7e`、`9044d95`；jedi `88ab3b05`；FE `bec490d5`（已 push）。其餘未 push。

**交給下一棒**：STATE §4。

## 第 4 棒｜2026-10-30 晚～10-31 下午｜首腦：P1～P3 設計開卡、無人值守跑完、總驗收、合回主線

**角色**：同第 3 棒 session 續接，首腦。

**時序**
1. 決策者裁「先設計 P1」→ AST 掃 49 支 core 檔的跨模組邊，identity／sync 真正要抽 port 的只有三種（`audit()`、`LOCAL_ADMIN_SUB`、對主系統 HTTP 通道），其餘搬到對的位置即消失。P1 五張卡四批（CM-3319～3323）。決策者「照建議、先不放行」。
2. 母卡掛法反覆：先掛 CM-3232 → 擋了 P0 結案（結案要求子卡全 Done）→ 另開 CM-3324 → P2（CM-3325）／P3（CM-3331）各自母卡 → 決策者「合併到 P1 卡下面半夜跑完」→ 14 張全掛 CM-3324，兩張空母卡標 Done 作廢。
3. 決策者「很多決策其實沒那麼重要，都可以往下跑」→ 掃 14 張卡裡會讓小弟停的句子，append「無人值守決策表」蓋過 P0 時期的「要人決定就停下、首腦早上裁」。
4. 工作坊 29 從 10-30 19:48 跑到 10-31 10:55，批 12～22 十五張全部驗收通過（含工作坊首腦半夜依規則加開的 CM-3345），沒有一張停下等人。
5. 總驗收（決策者「不要檢查的太繁瑣，以基本測試為主」）：全量 1992 綠（補 venv 的 jedi-password 後）、路由 49＝49、demo 起服務、真機基本功能；派 `ddd-compliance-reviewer`（opus）掃 310 檔 diff。兩條阻斷首腦自己修（`8a807dc`）、九項警告開 CM-3357 清理卡（兩條要裁的首腦預設：domain 准用純算法庫＝改規則；單鎖類別＝真收進 DI；決策者「照建議」）。CM-3357 做完驗過：九項全過、新守衛突變有牙齒、1997 綠。
6. 決策者問 P4（心跳瘦身、改雙向直推、socket）→ 分析後裁「要改主系統，先暫緩等重構完成」。
7. FR-167 側調整完 → 合回：先把主線（多 15 個 commit：P8-5／P9-4、1.4.6、工具升版、SeaweedFS 加密）合進 ws，三支文字衝突取 ws 版，`update_notify` 改由 `sync.register()` 掛、import 改新路徑，兩支測試 patch 目標改新路徑；全量 2014 綠。再合回 `feature/FR-139`（Agent `3ab1253`、jedi `fc67330e`），本機 Agent 切回主資料夾。
8. push 卡帳密（session 無 TTY）→ 設 `glab auth git-credential` 為 helper → 三 repo 推上 origin。
9. 給 FR-167 首腦 prompt：主線已是新架構、FR-167 修正全在、出包前要在 188 真跑 Nuitka、188 不 pull 也可以停在 `58793ac` 出純 FR-167 包。

**P4 分析（決策者問「等心跳太偷懶，能不能都改雙向」）**
- 現況兩條路不對等：Agent→主系統只有 60 秒心跳；主系統→Agent 有 8443 直推（mTLS＋綁指紋 JWT）但只開 9 個端點，其餘全塞心跳回應。
- 心跳回應 24 鍵分三類：**指令類**（`pending`／`restart`／`update`／取消，等 60 秒是純延遲，該改直推）、**設定同步類**（清冊、CIDR、profile、漏洞庫、操作者名單等，要的是最終一致，留心跳但改帶版本號有變才送）、**對帳類**（`accepted`／`rejected`／ack，不動）。真正要改的約 4 鍵、三張卡。
- WebSocket 不做：落地版主系統與 Agent 同內網、8443 一定通；WebSocket 認證只在握手做一次、之後靠「連線還在」當信任，比每請求驗 JWT 差，要補每則訊息簽章／重認證／斷線重連；穿 proxy 常被切又要長出一套保活；BE 現有 SocketIO 8002 是給瀏覽器用的使用者身分，不能直接接機器。只在 SaaS 客戶不開 8443 時才有價值（design §3.x 第二期）。
- 建議另開 FR（改對外契約，不是重構），順序在 FR-170 全部合回之後。

**教訓**
- 母卡掛法要先看工作坊結案條件：子卡全 Done 才能結案，分期掛同一張就擋前一期；但決策者要「單一工作坊跑完」時又該合併。開卡前先問「要不要分工作坊」。
- 「首腦早上裁」在無人值守下等於停工到天亮；要人裁的事列成表寫進卡，預設答案給好，真的要停的縮到三種。
- Done ≠ 進主線；工作坊線與主線平行長時，合回前把主線先合進 ws 在工作樹上解，別在主資料夾解。
- 卡工作區跑守衛會因 `.worktrees` 排除寫法假紅；驗收數字要在哪個樹跑清楚標。
- pip 沒帶 Nexus index 裝不到 jedi 套件、poetry install 會挑另一顆 venv：驗收前先 `pip show` 確認 venv 裝了卡上新加的 pin。
- 決策者兩度點名驗證方式：合併演練＋全量＋路由集合 diff＋demo＋真機基本功能，一輪做完；不逐檔讀、不設計複雜情境。

**commits**：BE `803a6e498`（P3-5 spec）、本棒交接；Agent `d7bc4e6`、`8a807dc`、`092efd4`、`3ab1253`（合回）；jedi `fc67330e`（合回）。三 repo 已推 origin。

**交給下一棒**：STATE §4。
