---
title: FR-069 LOG — 歷程（append-only）
---

# FR-069 LOG（append-only，每棒追加一 block，不回改）

## 2026-08-29 ～ 2026-08-30｜第一棒（首腦 session，協調＋驗收）

**歷程**：

1. 三棒平行盤點（全模組清單／耦合矩陣／jedi monorepo 格局）→ 拍板 P0–P8 第一階段＋P9–P13 凍結路線圖（後由 D8 解凍）。
2. FR-069 取號、design.md 落地（`7e87c2ca`）、Notion 開卡 9 張（CM-1435 母＋CM-1436～1443 子，連號）。
3. P0（前置清理）與 P1（jedi-ai-bot）平行——P0 含 D5 追加的 grc→flow_control 改名（`6a0aa72c`＋`6f3d02cd`）；P1 定插件契約首例＋extraction-sop.md 七階段（`43bd2ec1`），發版 `cbcff277`。
4. P2（jedi-integrity `d8cca74c`）＋P4（jedi-remote-agent `c9590b3f`）平行；P4 定 migration 隨包五規則（SOP §4.2 首例）。合併發版 `327a5963`。
5. P3（jedi-log-forwarding `3de631da`，含端到端「迷你接收器真的收到 log」實測）＋P5（jedi-license-runtime `7d07d62b`，驗簽引擎逐行比對零改動、執法留宿主）平行。合併發版 `6daa0f67`。
6. P7（jedi-common 擴充）兩批：批一 response_util（`cb85f193`）、批二通用工具與 enum（`0d63684d`）——先加後刪、主專案留 re-export shim、124+ 處消費端零改動。**jedi-common 未發版**（與 jedi-auth 併 P8 後一起，等令）。
7. **base_repository 誤判插曲**：首腦把 jedi-common 頂層 7 行的 `base_repository.py` 誤判為「舊代待汰換」，發了清理棒；子棒查證發現它是 lazy session mixin、`BaseRepositoryImpl` 自己就繼承它、5 個目標檔全屬合法特殊 repo 用法——**按紀律煞車回報，未改任何檔**。結論改為「不汰換，第二階段正名（SessionMixin）＋刪 0 引用的頂層 base_model.py」，入 design.md（`ac9e93f3`）。途中一支基於錯誤前提的記帳文件棒被叫停、半成品編輯已還原。
8. 決策演進：D5 改名（`b497e5c7`）→ D6 插件契約（隨 `6f3d02cd` 入庫）＋四插槽指引（`5e8f711e`）→ D7 harness＋README（`dbaf4bdc`）→ D8 全路線解凍＋四階段＋身分脈絡標準件（`e2a394a4`）。
9. P7 user 手測通過收 Done → P8 發棒（進行中）→ 本交接檔。

**教訓（後棒引以為戒）**：

1. **驗收發現「文件與實況不符」，先比對變更前後的原始碼再下結論**——P7 實測信封鍵是 `status`，CLAUDE.md 寫 `code`；比對搬家前後證明兩版一字不差，是文件債不是搬壞。差點誤判 P7。
2. **「看似殘留的重複」先查繼承鏈再發清理棒**——base_repository 兩檔同名不同角色（session mixin vs 查詢介面），憑檔名與大小差異推斷「新舊兩代」是錯的；同名不同角色的基底類是「假清理」誘因，收斂靠正名不靠強制遷移。執行棒「前提被推翻就停手回報」的紀律救了這次。

---

## 2026-08-30（同棒續）第一階段收官

**P7/P8 收口與驗收要點**：

- **P7（jedi-common 擴充，CM-1442）**：分兩批 commit（`cb85f193` response_util 批一／`0d63684d` 通用工具與 enum 批二），全程「先加後刪」——主專案舊位置全改 re-export shim，124 處消費端零改動、零檔案被碰。jedi-common 內主專案 import 0、自帶測試 153 passed。順帶第一刀 base_repository 清理案被執行棒查證推翻（見上方教訓 2），收斂改走「第二階段正名案」（commit `ac9e93f3`）。
- **P8（authz 主體域併 jedi-auth，CM-1443）**：拆兩半精準——主體域五檔（platform/admin/capability/decorators/signed_token）進 `jedi_auth.authz`、資源域四檔＋license 軸留主專案；126 處消費點零改動（shim）。四個守門 error code 進套件 `AuthzErrorCode` 但**字串值凍結 `GRC_*`**（FE i18n key，實地驗過 8 筆翻譯都靠它）。權限行為實測：admin 200／無 token 401；主專案守衛擴到 47 passed。CLAUDE.md authz 段由 P8 棒同步更新（「改主體域改套件，勿在 shim 補邏輯」）。

**發版第四輪（收官輪）**：jedi-common `0.0.32`＋jedi-auth `0.1.35` 上 Nexus（monorepo 版號 commit `a206cf7`），主專案 pin commit `ac696b02`，poetry.lock 無連帶升版；全域煙測綠（守衛 47／auth／信封／authz decorator 三鏈 200／無 token 401）。**至此七支套件發版全清。**

**身分族兩棒深度分析 → D9 立案**：耦合盤點（login→auth 21 處穿透 infra、五支發版全同批、B 類通用膠水 1,300 行＋C 類重複 320 行、死鏈三條）＋全站漏網掃描（jwt_mw／socketio 驗簽／user_context_builder／安全政策定義等約 930 行主專案側身分程式；四髒：jedi-department 殭屍、root 判定三份、roles.is_admin 殭屍旗標、login 手測腳本）→ **D9：合併為 jedi-identity，插隊 2.5 階段**（commit `ba44d274`）。notification 獨立、agent 機器身分不併。前置確認：jedi-* 僅 Guidant AI 消費。

**疆界盤點案立案（FR-069.9／CM-1446，commit `06266329`）**：第四階段開工門檻——照 D9 方法對 26 支套件＋主專案候選做疆界地圖；五組候選（檔案／問卷／檢測／OSCAL／追蹤）＋兩項退役查證（jedi-log、jedi-oscal v1）；願景 26→12–15 支疆界套件。

**第二階段開卡**：CM-1447（.10 ext 表全庫盤點）／CM-1448（.11 jedi-common 查詢層：JSONB＋身分脈絡包＋基底正名）／CM-1449（.12 收斂實作 auth/user 首批，等前兩張）。**RLS 覆蓋缺口另案 CM-1445**（三張授權關聯表無 RLS，獨立安全債不掛 FR-069）。

**教訓補一條**：

3. **base_repository 誤判事件全程**——首腦憑「兩檔同名＋大小懸殊＋修改日期差一年」推斷新舊兩代並發清理棒；執行棒開工前查繼承鏈發現頂層 7 行是被完整版繼承的 session 底座，**前提錯→停手回報未改一檔**；首腦叫停平行的欠帳記錄棒、還原半成品編輯、撤回對 user 的錯誤說法、改立正名案。完整鏈：誤判→子棒煞車→撤回→正名。派清理棒前先驗「誰繼承誰」，且執行棒的「前提被推翻就停」紀律是最後防線，開棒 prompt 要一直帶著。

---

## 2026-08-30（同棒下半場）第二階段全收＋2.5 開打

**第二階段三棒收口與驗收**：

- **.10 ext 全庫盤點（CM-1447，`b459da74`）**：190 張表掃出 9 張延伸表形態——收回主表 1（project_extensions）／留置 6／待決策 2；**推翻原假設**：全庫沒有任何「純展示型客製欄位」，側掛表是「跨套件邊界」長出來的不是客製需求 → JSONB 容器定位改「預防性建設」（D15）。auth/user 域無可收斂表，.12 首批改打 project_extensions。順手發現三則（users.topt_secret 死欄位／projects RLS 停用但 policy 殘留／孤兒表）。涵蓋性自證：四偵測面 SQL 全附可重跑；subagent 初報 raw SQL JOIN 12 處、自己復驗實為 14 並註明。
- **.11 jedi-common 查詢層擴充（CM-1448，`2394200`）**：三件套全「用加的」——JSONB 查詢（`_ext_`/`_extlike_`/`_extin_`/`_exthas_`/`_extcontains` 前綴＋排序分頁；袋內一律 AND 不混 OR 群組；缺 key 不炸；未宣告袋子的 repo 靜默忽略）；`identity/` 身分脈絡包（三名冊 port 同構）；SessionMixin 正名（舊名 base_repository 留轉發）。jedi-common 測試 215 passed。
- **.12 project_extensions 收斂（CM-1449，主專案 `4c6b90a8`＋review 修 `6f1608e5`、jedi-project `0d3ea71`）**：四欄收回主表（皆帶業務邏輯轉正式欄位非 JSONB）；五步搬遷走到第 4 步「切讀取」，**drop 舊表等令**；14 處 raw SQL JOIN 改完 grep 殘留 0；DEV 實查回填 211 列零不一致；**STG 實查未被套**（環境紅線守住）。讀取端「一手切完」（覆寫 ext repo 的 get_one_by_fields 由主表供值）；雙寫收在 repo 層單一入口；審計欄不互蓋（實查兩表本記不同事）。user 手測一度誤連未套 migration 的庫報 UndefinedColumn——教訓見下。

**Postman 全站 API 設定檔（CM-1454，`38e8734a`）**：交付「產生器即真相」——`scripts/gen_postman_collection.py` 產 collection（637 支/21 資料夾）＋environment＋端點對照表；驗收時首腦重跑產生器 git diff 空＝與路由表零落差；憑證掃描 0。**掃出 62 支裸路徑死端點**（23 個 Resource 雙路徑註冊缺 handler；runner 逐支查 FE 零裸打、線上零影響；初判 84 支、改讀實際 signature 收斂 62——自我修正值得記）→ 裁決「開追蹤卡隨棒順手拔」＝ **CM-1461**（`705d8401`），design.md 第三階段隨棒必做補一行。

**發版第五輪**：jedi-common `0.0.33`＋jedi-project `0.0.9`（monorepo `593334e`、主專案 pin `0f8c1b93`）——九支全正式版、主專案零 path 依賴。**push 委任**：user 明示「push 到分支授權給你做」＝兩 repo feature/FR-069 收口順手推（memory `feedback_fr069_push_delegated_branch_only`；main 仍禁）。

**兩包退役（user 拍板追加 D13）**：jedi-department（四面查證零使用——程式/venv/DB 表不存在/套件依賴全零）＋jedi-resource-store（程式 e2e DB 全零但主專案仍 pin）。退役棒：monorepo 標記 `d765191`、docs `29e124bd`；**pin 拆不開處置**——working tree 的 pyproject 混有 1455 的 path override 同檔拆不開，pin 移除留工作區、docs 先行記錄、託付 .18 收口棒一併入版。

**2.5 階段拆卡六張（CM-1455–1460）**：.13 地基（骨架＋遷入策略 A/B 案查證定案）→ .14 login／.15 mfa+captcha／.17 清理三棒平行 → .16 中介層 → .18 收口。地基棒已發（user 側 session），working tree 已見 jedi-identity 0.1.0＋jedi-auth 轉發殼 0.1.36（疑似 A 案）。

**教訓補兩條**：

4. **平行棒共用 pyproject 時，退役/pin 類改動要嘛排在 path override 清掉之後，要嘛接受「docs 先行、pin 託付後棒」**——同檔混不可入版改動時硬 commit 必夾帶違規，退役棒的處置是正解。
5. **手測報錯先看 log 的 Host 埠與連的庫**——.12 手測「無法顯示專案」實為 .env 連錯庫（未套 migration）；平行棒臨時服務（8010）的錯誤與主線（8000）要用 Host 分辨，別誤判成主線 bug。

---

## 2026-08-31｜第三階段 3.1 首棒（CM-1467，runner session）jedi-iam 完全體

> ⚠️ 本 block 只記 3.1 這一棒（runner 視角）。2.5 階段 .13～.18 與 .H、改名 .G、
> 第三階段拆卡的歷程由首腦 session 記錄，本檔上方 2026-08-30 之後若有空缺以
> STATE 現況清單與各 Notion 卡為準。

**交付**：身分模組從「套件出 service、route 留宿主」升格為**真正隨插即用的插件**。
commit：monorepo `e614c34`（本體）＋`d6b0dfa`（blueprint 改名）／主專案 `e483ba17`
（本體）＋`d1a141c2`（檔名改名），兩 repo 已 push `feature/FR-069`。

**六件工作**：①route 上移（39 條進 `jedi_iam/api/`，主專案 `api/auth/` 26 檔刪除）；
②內部結構重整（頂層 `common/code` 與 `common/enum` 兩套合一、`mfa/common` 併回頂層、
`mfa/domain/entity`→`entities`）；③四殼退役（主專案 80 檔改名＋拔 pin＋死名守衛）；
④D16 port 化（三支認證 adapter 的 10 處自建 RepoImpl 收進 `AuthRepositories`）；
⑤`GoogleAuthAdapter` 缺 `__init__` 的 TypeError 修掉；⑥README 架構節＋README.html。

**設計上的關鍵取捨（後 11 支照抄，全文見 STATE「照抄要點」）**：

- **route 取 service 用 `ctx().service(name)` 而非 `@inject`**——`Provide[Containers.x.y]`
  要在 import 期寫死具體 container 路徑，那是宿主的組裝知識，寫進套件＝套件反依賴主專案。
  改由 `register()` 把 **provider 名冊**放進 `app.extensions`。**存 provider 不存實例**：
  主專案 service 多為每 request 建新的（內含 session-bound repo），存實例是那種平常
  看不出、併發才爆的壞。
- **缺認證接線要拒絕掛載**（`_assert_api_wiring`）——不是「有就用沒有就跳過」。跳過的
  後果是身分端點全變公開，而服務照常起得來、健康檢查照樣綠燈。三個插槽刻意無預設值。
- **切分判準：「換一個產品，這段還會一樣嗎」**——一樣的留套件（流程順序、組樹、欄位
  正規化），不一樣的走 hook 回宿主（商務授權旗標／選單過濾／密碼政策來源／防帳號列舉）。
  四個 hook 都是這樣切出來的。

**驗證**：拔掉測試（`mount_api=False` → 16 支端點全 404、其餘模組無感）；harness
**`POST /login` 走通拿到真 JWT**（不用 DI 框架、不碰主專案一行）；行為表 8 列；
URL／能力點／error code 三組**集合機械比對相等**；突變測試兩發（關掉守門→4 紅、
拼錯一條 URL→1 紅）；套件 357 綠、守衛 53 綠；8000 重啟煙測全 200 log 零 ERROR。

**隨棒**：CM-1461 身分 13 支死路徑照 .18 正解拆 Create Route 類（**500→405，POST
仍活**），已回該卡勾銷；依賴衛生順掃（套件補三個 route 層相依宣告）。

**追加改名**（user 指示「以前叫 identity 的換 iam」）：blueprint `identity`→`iam`
（`.13` 殘留、`.G` 漏改；三 repo 對 `identity.*` endpoint 引用皆 0，對外 URL 零影響）、
`common/identity.py`→`iam_ports.py`、`core/identity_wiring.py`→`iam_wiring.py`。

**教訓（接續上方編號）**：

6. **harness 只證明「掛得上」是不夠的——要實打一支端點走通**。3.1 讓 harness 真的打
   `POST /login`，一路挖出**四道宿主前提**（`init_db`／`PROPAGATE_EXCEPTIONS=True`／
   `JWT_IDENTITY_CLAIM`／`column_property` 用的 6 支 DB 函式），原本 harness 只記兩道。
   其中 `PROPAGATE_EXCEPTIONS` 最陰：flask-restful 的 `Api` 會包掉 `handle_user_exception`
   **自行處理所有例外**，於是 `register_error_handlers` 註冊成功卻完全不生效，
   401/403/404 一律變 500——「註冊成功但不生效」這種病，靜態看程式碼看不出來。
7. **改名要掃「寫死字串前綴」的地方**：blueprint 改名時有兩處寫死 `"identity."`
   （contract 測試與 harness），它們壞掉的方式是**靜默匹配到 0 條**而不是報錯——測試會
   變成「掃了個寂寞卻顯示通過」。已改成從 `plugin.DEFAULT_BLUEPRINT_NAME` 取。
8. **改名前先分辨「舊套件名」與「領域概念」**：codebase 裡 `identity` 兩種意思混用。
   `JWT_IDENTITY_CLAIM`／`user_identity` 欄位／`get_jwt_identity()`／`resolve_identity()`
   ／`Accept-Encoding: identity` 都不能改（對外契約或第三方 API，改 JWT claim 名會讓
   所有既有 token 當場失效）。我一度把 `test_middleware_identity_core.py` 也改了，
   翻開發現它測的正是 `resolve_identity` 就改回去——**檔名要跟著它測的東西走**。
9. **`common/` 不得反向 import 上層是活的守衛**：宿主接線檔初版放 `common/`，被
   `test_common_has_no_reverse_imports` 當場抓到（它要 import `app/` 與 `infra/`）。
   組裝根的正確位置是 `core/`，與 `app_factory.py` 同層。

---

## 2026-08-30 深夜 ～ 2026-08-31｜第二任首腦（協調＋驗收：2.5 全收＋第三階段開打＋形態定調）

**歷程**：

1. 接手驗收 2.5 全部棒次：.13 user 判收、.14（66 檔機械比對零行為差）、.15（MFA 全鏈親打含 redis 真碼）、.16（**抓到真提權洞**——X-Tenant-ID:0 觸發 is_super_admin 繞全 RLS，含 socket 整數 0 falsy 變體，皆修）、.17（root 判定收斂；is_admin 實查非殭屍→裁 (A) 另開 CM-1463）、.H 補搬（D9 缺角三塊；「消滅 raw SQL」照意圖不照字面——elevated_session 保留繞 RLS，root admin 保護是承重牆）、.18 收口（發版清單備妥）、CM-1465（socketio 一行修）。
2. **命名定案 jedi-iam**（PM 推翻 identity——「只涵蓋你是誰半邊，太狹隘」；IAM=類別正名，Keycloak 屬其解決方案）→ CM-1464 改名棒（monorepo git mv 321 檔＋BE 96 處 import＋三支 AST 死名守衛；`jedi_identity` 不留殼直接死名）。
3. **驗證瘦身規則七條**（user 拍板，實測驗證吃 6 成工時；判準「壞了會不會靜默」；同型棒信任遞減；首腦驗收改抽查）——入 STATE，CM-1464 起生效。
4. **發版擱置**（user 裁「先不發版直接進第三」）——五支清單（iam 0.1.0/auth 0.1.36/login 0.0.24/mfa 0.0.15 必發/captcha 0.0.15）與 patch 備妥等令；pyproject 三批託付改動續留 working tree。
5. 第三階段拆卡六張（CM-1467–1472）→ 3.1 首棒收（39 URL 集合比對/api/auth 刪除/**照抄要點 7 條=範本**/authz 命名維持不改的實查裁量）→ 3.2 file-upload（兩輪：API 全過→16 test ERROR 退回→runner 三證推翻首腦歸因「本棒連帶」為既有存量債，接受更正收 Done）→ 3.3 notification 收（「拔掉≠寄信消失」雙用法誠實揭露；README 原是 issue 照抄件重寫）→ **3.4 煞車**（19 條 route 17 條吃主專案 service，「兩個流程範本」同名不同物；裁 (a) 降級輕量＋(c) route 歸屬併第四階段流程疆界三方設計）。
6. **flow_control 拆出升格第四階段議程**（user 指示；確認指涉=稽核業務層 37 支 service 非範本管理；拆法定調「先單純拆出、切分後議」照 jedi-iam 先搬家後裝修先例）。
7. **形態知識大量沉澱**（user 連續追問插件模式的運作細節，全部落檔）：架構手冊常設專區成立（`docs/features/architecture-handbook/`——插件架構指南＋模組化路線圖，自 FR-069 站移出改名）；插件指南擴至九節（使用流程五步/接線 QA 三題/資料關聯三律/查詢實戰 QA 六題＋API 歸屬總表——「各檔口的菜檔口自己賣，套餐才開櫃檯窗口」）。
8. **第四階段前置盤點完成**：D12 查證（CM-1462：77 條 97% 服務層缺能力，建議中間路線）＋**跨疆界聚合 API 盤點**（`docs/analysis/2026-08-31-cross-boundary-aggregation-api-inventory.md`：**最重聚合在 infra 跨 schema raw SQL 非 service 注入**——8 支聚合 query 約 2,000 行、冠軍一句 SQL 19 表七疆界；真聚合端點 25–30 條；三條建議待裁——readmodel 正名/AI registry 自註冊/TaskAssigneeService 切法）。
9. 第四階段議程累積至六件：核心抽取、flow_control＋流程疆界三方、設定 schema 申報制（作用域/fallback 細節已記）、資料關聯三律、聚合層設計（依盤點）、P13 中間路線待裁。

**教訓（後棒引以為戒）**：

10. **開卡前必查 design.md 對該對象的既有標記**——3.4 卡片寫「route 上移」但 design.md §L360 早寫「flow-engine 未做完整判定、建議另立流程疆界棒」，首腦開卡沒引用導致前提錯誤；runner 靠「前提被推翻就停」救回。同型教訓在 is_admin（卡片寫殭屍、實查活線）已發生過一次——**卡片斷言的查證責任在開卡人，煞車紀律是最後防線不是常規**。
11. **首腦誤夾帶平行棒 staged 檔兩次**（.18 的 captcha 刪檔/3.1 的 api/auth 刪檔）——commit 帶 pathspec 顯式列檔可防（`git commit <files> -m`），事後 `reset --soft` 拆開可救；**平行棒在跑期間首腦最好完全不 commit**。
12. **驗收歸因要三證才下結論**——3.2 的 16 ERROR 首腦初判「本棒連帶」，runner 用「參數來源 commit/本棒未觸該檔/父節點同紅」三證推翻。壞在 setup 的測試（ERROR 非 FAIL）會遮住「測不存在方法+斷言與實作相反」的存量債。
13. **runner 未 push 不算違規**——3.3 選擇等令（委任其實涵蓋），下一棒順手補即可；分辨「保守」與「漏做」。

## 2026-08-31 ～ 2026-09-01｜第三任首腦（協調＋驗收：第三階段收官＋發版＋第四階段 17 棒）

**歷程**：

1. 接手驗收 3.5（CM-1471 輕量批七支——守衛須 `python -m pytest` 否則假紅的坑在此發現）→ 3.6（CM-1472 退役四支，monorepo 26→24）→ 發版裁決：user 質疑四殼為何要發，重盤後**裁不發改退役**（.18 清單的前提已被 3.1 拔 pin 推翻）→ CM-1473 發版棒（11 支上 Nexus、pin 入版收三批託付、四殼刪除 24→20、守衛換軌）。
2. **第四階段拆卡九張 CM-1475–1483**（四待裁全拍板：聚合三建議全採/P13 中間路線/flow_control 排 P12 後/首棒 4.A）→ 與 CM-1474（DROP 清債：孤兒表退役＋project_extensions 收尾，P-like 雙路徑驗證，抓到 .12 漏網 view 活依賴）平行跑。
3. **平台化方向拍板**（user 願景討論）：project＝插座不是插頭（被功能套件 register 的平台核心）；flow_control 分家＝流程骨架半供複用＋稽核半自成插件（「分家是複用的前提」）；終局五層包裝。決策頁 project-platform-decision.md＋大架構圖 big-picture.md＋相依圖 dependency-map.md 落架構手冊。
4. 4.A（D17 資料關聯三律/D18 設定申報制入決策表＋分類地圖十族；③readmodel 搬遷因名單衝突煞車→裁「純讀聚合」為準併入 P12 步驟 0）→ 4.B（AI registry 申報制，壞條目 2→4）→ **P12 jedi-participant**（readmodel 櫃檯建置＋40 組參數 md5 比對＋A/B 對打抓到 Containers 類別層真回歸；identity JOIN 債→CM-1484）。
5. **4.2 全鏈**：設計稿（切線 12/22/12＋D-1~D-9）→ user 抓黑話→白話改寫棒（零漂移）→ CM-1485 盤點（camunda 程式死/環境有孤兒容器 189 user 裁不動/「只剩 BPMN 解析」推翻——執行面活著）→ CM-1486 退役 4,351 行（三護欄各突變實證）→ D-1~D-9 全採（D-7 補 port 閥）→ CM-1487 搬遷（runner 煞車推翻「226 檔比照 P12」——16 支依賴未套件化模組，裁 A 拆兩棒，190 檔進 jedi-flow-control）→ CM-1488 分家（平台層零稽核詞機械判準/兩處設計稿判反改判/D-10 材料：DB 四條 CASCADE FK vs import 僅 2 條）→ D-10 裁「償債維持兩包」→ CM-1490 第 3 步（FK 拆軟參照/申報制上線/問卷審核開關「設定不是客製」實證/D-1 job_service 三分）。
6. **CM-1489 detection**：先煞車（首腦裁決「綁定表歸 flow_control」被推翻——用量反向+FK 指向 detection——裁 B 留檢測側）→ 服務化評估裁插件 → 抽出 147 支（裁示④漏項→CM-1491 小卡）。**CM-1481 P10** evidence-classification（五張 port/兩表刻意不加 RLS/突變抓到自家守衛盲點）。
7. **三包定名**（user 註可能再調）：flow-engine 不動（**實查更正首腦誤述**——執行引擎活著在套件內非「BPMN 工具箱」，BPMN generator 2,758 行實住主專案裁歸引擎）/task-platform/compliance-audit（不佔 audit 泛稱）。申報書選配化定調（survey 核心不依賴 task declaration）。CM-1492 打包棒＋CM-1482 P11 兩棒發出（在途）。
8. **族譜節入路線圖**（已完成/退役/進行中/未完成全景）；收官棒待辦累積節立於 STATE（readmodel 四規格+分組/族譜終版/四類清單/SQL 守衛可選）。

**教訓（後棒引以為戒）**：

14. **卡片「比照先例」前必驗前提等價**（CM-1487：P12 能機械搬因 out-degree 8，flow_control 纏五疆界照抄翻車）——已入 memory。
15. **首腦裁決含事實斷言也要附實查**（CM-1489：裁「綁定表歸 flow_control」只憑語意沒跑 grep/pg_constraint，被 runner 用量與 FK 方向推翻）——本任裁決被推翻共 2 次、卡片斷言被推翻共 4 次，煞車紀律全數救回。
16. **平行棒共用 git index 事故**（b74bd564 誤收平行棒 35 檔）：顯式 add 防不了「別人已 staged 的混進來」——**commit 前必 `git diff --cached --stat` 核清單**，已入所有後續 prompt。
17. **驗收抽打前先核 8000 跑的是不是最新碼**（兩次撞到重啟空窗/舊碼——比對進程啟動時間 vs 最後 commit 時間）。
18. **view 與 SQL 字串是守衛盲區**（CM-1474/1486 兩案實證）——已入 memory；D17 補 view 條款。

## 2026-09-01｜CM-1500 問卷共編即時同步修復（runner 兩階段：偵察煞車 → 裁定後收口）

**背景**：CM-1482 問卷疆界合併（P11）搬家後，user 手測抓到 8002 問卷共編整組失效——
進問卷頁跳「即時同步失敗」，join／update 一律回「更新失敗，請稍後再試」。

**歷程**：

1. **第一階段（偵察＋主專案側接線，`97133497`）**：實測複現坐實根因——socket handler
   搬進套件後走 `ctx()` 讀 `app.extensions["jedi_survey"]`，而該鑰匙只在掛 REST
   blueprint 時由 `record_once` 寫入；socketio 模式刻意不載 REST（FR-063.1c 不可倒退），
   於是每個事件呼叫 `ctx()` 就 RuntimeError。連線與身分驗證皆通過（排除 auth／Redis／CORS）；
   不載 REST 的 app 其 extensions 清單實查確認無 `jedi_survey`。notification 的 socket
   handler 不經 `ctx()` 故未中招，對照吻合。
2. **撞到卡片明訂的停止條件**：修法要走的 `register(..., mount_api=False)` **簽名有、
   行為不夠**——該分支只做 `_configure_runtime()` 就返回，不寫 extensions。即
   **「不掛路由」與「拿得到 context」在套件裡是綁死的二選一**，宿主端無論怎麼接線都補不出。
   照卡片邊界停手回報（不繞道、不在 8002 掛 REST、不自行改套件）。為確認「缺的只有這一項」，
   本機**暫時**改 site-packages 驗一輪即還原（md5 比對確認與發版版本逐位元組相同）。
3. **第二階段（user 裁 A 案後收口）**：套件補 4 行（monorepo `28e8be3`，jedi-survey
   **0.1.1** 上 Nexus）＋主專案 pin 跟上（`9312ba3d`）。語意刻意與 `record_once` 一致
   ——**無條件覆寫、最後一次贏**（那邊是 `__setitem__` 不做 already-exists 檢查；
   library 模式若寫成「已存在就跳過」，同一 app 先後接兩份 adapters 會得到相反結果）。
4. **驗證**：複現腳本三輪（修前 RED／本機暫改 GREEN／**正式版 0.1.1 GREEN 且 DB 實查
   答案確實寫入**）；**雙客戶端共編實測**（A 改答案 B 即時收到、在線名單互見、零錯誤）；
   8000 URL 424 條逐字同＋帶 token 打 `/surveys/menu` 回 200；守衛 77 綠（併 iam_wiring 85）；
   兩模式重啟乾淨；DB 零淨異動（探測值與在線名單殘留皆清）。突變兩發：拿掉寫入 → 2 failed、
   改 skip-if-exists → 1 failed。**user 瀏覽器手測通過收 Done**。

**決策**：

5. **裁 A 案——只修 jedi-survey 單獨發 0.1.1**，其餘七支同款缺口（iam／file-upload／
   detection／notification／system-menu／issue／log）**記帳不修**，併 CM-1497 當 D6 契約
   統一補齊。理由：那七支現無 socket 模式使用場景、缺口不發作，而修它們等於重發七支套件；
   一次統一處理比七次 patch 發版乾淨。已 append 至 CM-1497（含修法與參考 commit）。

**教訓（後棒引以為戒）**：

6. **「逃生門存在」不等於「逃生門夠用」**——卡片修法指向 `mount_api=False`，簽名確實有，
   但實際行為缺一半。**契約要看實作不看簽名**；runner 照邊界停手回報，是這次沒被繞成
   「在 socket 模式掛 REST」（會倒退 FR-063.1c）的原因。
7. **套件全量測試的 baseline 要先量再歸因**——jedi-survey `tests/unittest/` 有
   48 failed／42 errors，用 `git stash` 抽掉改動跑同一份指令對照確認**改動前就存在**，
   本次是 +2 passing。不先量 baseline 就會把存量債誤記在自己頭上（同型教訓見第 12 條
   3.2 的 16 ERROR 案）。
8. **契約測試要同時焊「行為成立」與「語意一致」**——只驗「拿得到 ctx()」的話，
   把寫入改成 skip-if-exists 仍會綠；補第二條（重複 register 覆寫語意）才擋得住。
   兩條各以突變實證有牙齒。

**推翻了什麼**：

9. **STATE 的「8000 現跑舊碼／現在重啟必炸」已失效**——CM-1499 發版棒還原 pin 後
   path override 已全清，本棒實測 8000／8002 重啟皆乾淨。連帶：**拉分支不再需要
   `pip install -e` 六支**，`poetry install` 即可（該條交接事項已從 STATE 移除）。

## 2026-09-01（晚）｜第四任首腦（協調＋驗收：收官串——review／修復／文件／補發版）

**歷程**：

1. 接手時第四階段 19 棒收 17，在途 CM-1492 打包棒＋CM-1482 P11。兩棒收後驗收，其間 user 質疑「收 Done 的卡有沒有沒人接的遺留」→ **P4＋P3 共 24 張卡全文重讀盤點**，抓出五件懸案開卡：CM-1493 償債（平台包反向依賴斷根／detection handler 640 行歸位／1482 shim 清理）、CM-1494 查證（殭屍定讞）、CM-1495 孤兒清理、CM-1496 SMTP bug（1469 說「另開卡」從未開）、CM-1497 套件債清理。原卡全部 append 指向，防再漏。
2. **user 手測期間三場環境修復**：①問卷共編失效＝CM-1482 搬家真回歸（socketio 模式不載 REST → survey 插件從未註冊 → ctx() 炸）→ CM-1500 兩階段修（runner 煞車：套件 `mount_api=False` 簽名有行為不夠，補 4 行發 0.1.1）；②檢測「agent 怪怪的」＝DB agent uid 與 agent 自持 uid 漂移（JWT aud 對不上）＋分派表也存舊 uid＋.151 SSH 公鑰遺失，三處修完派工鏈通；③SMTP 測試信＝CM-1496 修（.get() 用錯＋RLS 讀不到 ROOT 設定）。
3. **arc-review 5 agent 平行**（type/silent/comment/spec/code-quality）→ 報告 1 Critical＋10 Important；**主題「綠著的守衛不代表在守」**（守衛掃改名前舊名永遠綠／掃描根縮水／兩處 docstring 宣稱有守衛但不存在）。
4. **CM-1501 全修**（user 裁全修）：13 條處置完畢，突變 15 發；C-1 撞號 `GRC_400105` 一碼兩用修成 `GRC_400121` 三 repo 同步。
5. **CM-1502 文件收官**（第一段）＋**CM-1503 補發版**（四支 patch 上 Nexus，可拉性三層驗證含解包 grep）。
6. **190 dev server 建置**：user 裁「不編譯直跑」→ 後改 nginx 服務 build 產物；補套 26 支 migration（帶舊資料升級實地驗證）；切 on-prem 形態；修好 nginx `/socket.io` 錯指 8000 的既有設定錯誤。

**教訓（接續編號）**：

19. **收 Done 不等於沒有遺留——卡片尾段的「留給後棒」若無人接卡就會靜默消失**。P3/P4 掃卡抓出五件懸案，其中 1469 的 SMTP bug 從發現到開卡隔了兩天、1489↔1490 的 640 行 handler 互踢到兩卡都 Done 還沒人認領。**判準：任何「交後續/另開卡/待議」的字樣，當下就要開卡或明記落點**，否則它只活在那張卡的尾段。
20. **環境漂移的症狀不指向原因**（本任三場修復全屬此型）：agent 身分漂移的表徵是「測試連線失敗」、SSH 公鑰遺失的表徵是「掃描 Authentication failed」、socket 插件未註冊的表徵是「即時同步失敗」——**都要追到最底層才看得到真因**（agent log 的 JWT aud 不符／私鑰直連實測／app.extensions 實查）。
21. **「簽名有 ≠ 行為夠」**（CM-1500）：套件的 `mount_api=False` 逃生門存在但不寫 extensions，宿主端無論怎麼寫都補不出鑰匙。**契約要看實作不看簽名**；runner 照邊界停手回報而非繞道（繞道＝在 socket 模式掛 REST，會倒退 FR-063.1c）。
22. **守衛會靜默失效於改名與搬遷**（arc-review 主題）：四條守衛在改名/搬家後仍是綠的但守不到東西。**修守衛必做突變驗證**；新增守衛時想「這條會不會在下次改名後空轉」。

## 2026-09-01（深夜）～ 2026-09-03｜第五任首腦（協調＋驗收：收整階段 FR-069.5 全程 → 收官 → v1.19.0 正式進版）

**歷程**：

1. 接手時 STATE 說「只剩四件」（FE 未推／收官章／merge／190 去留）。盤點後 user 拍板**「主專案內部重整＋技術債算在本 FR 收尾，不另開 FR」**（理由：這波是本 FR 的大異動，債留下個 FR 絕對忘光）。切 `feature/FR-069.5` 作業（原 FR-069 為已審凍結態），開 CM-1504～1510 七卡＋沿用 1484/1495，拆 A～H 八棒。
2. **十二棒全收**（A 小債清掃含 CM-1461 62 支全清＋tests/ 退役 25,015 行／B 存量紅 94→0 全量 2155／C shim 清退 310 支／D readmodel 分子資料夾／E 孤兒清理 job／F+CM-1512 身分表直連 port 化 13 支／G 四類重佈局——runner 用守衛焊死面實證推翻我的「大搬遷」預設，改小幅歸位／H 收口：九支發版＋pin 還原零 editable＋mini arc-review）。另開 CM-1513（DI deepcopy＋DBLogHandler 雙病根）、1514（三套件紅歸零）、1515（出貨衛生四件）三張技術債卡並收；CM-1511 排程時間 bugfix 平行收。
3. **收官章**（user 令）：母卡 CM-1435 Done、SPEC 補檢測指南、memory 兩條；CM-1516 用 POC 真資料重建 190（migration 升級路徑三處實測）。
4. **beta 出包 `1.19.0b1`**（user 要先測）：188 build 連踩六雷——STG 缺 fr069-12（user 放行套）／Nuitka product-version 不收 b1／BE-FE 版號守門字面比對／修守門時 `\1` 變 \x01／基線產物 stale（user 放行套基線＋regenerate）／FE image tag 雙格式（別名）＋bundle 公鑰死路徑（skip 出）。**四顆入版、兩顆記帳**。
5. **資安修補**：user 錄影時發現 `guidant credentials` 印明文密碼→裁移除。整支拔除＋文件三處＋190 同版 `--upgrade --force` 實驗證。同時 CM-1533 agent heredoc 反引號 cosmetic bug 修＋0.2.32 出；user 延伸提出 Agent 安裝形態缺陷→FR-073 開案（runner 一氣完成，Agent 跳 1.0.0）。
6. **v1.19.0 正式進版**（main 上）：RN／spec 快照（含 CM-1432 的 legacy/ 部署根層，skill 文件未載，照 v1.18.0 實況補）／FE 對齊／兩 repo tag。開 CM-1543 出包部署卡（runner 級）。FR-070（AI/Drive 憑證 DB 化）、FR-071（診斷包）Phase 0 開案。

**決策（user 拍板）**：收整併本 FR／branch FR-069.5 繼續／四類重佈局全套→實證後改小幅歸位／技術債三卡全開＋project_extensions drop（實查已由 1474 做過）／Nexus 舊殼先不動／jedi-issue GL/GH 留／190 e2e 舊庫清／`credentials` 移除、密碼藏法另談／FR-070／071 開案先不做／H 棒 190 走查段刪除改機器驗證為準／beta 只留版號不做 RN。

**教訓（接續編號）**：

23. **收整債要在同一個 FR 收**——user 原話「下個 FR 開始絕對忘光」。安全網（190）、context（誰造的債、修法）、驗證體系（守衛＋D5 diff）三樣只在此刻齊備；「另開 FR」的理由（規模）在有安全網後不成立。
24. **「全套重佈局」前提被 runner 用守衛焊死面推翻**（G 棒）：頂層八 package 名被 5 處守衛迭代、`api/` 目錄名是載入契約——四類是功能分類、DDD 四層是技術分層，正交不競爭。開卡「比照手冊」前該先盤守衛焊死面（同 [[feedback_card_analogy_requires_premise_check]]）。
25. **staging 夾帶是平行棒的常見事故型**：我自己（commit STATE 夾帶 A 棒 101 檔）與 CM-1514 runner（夾帶 1512 三支 pyproject）各撞一次。`git add` 之後 commit 之前要**再** `git status` 一次——add 前確認不夠。
26. **預發版號在 build 鏈是一整族雷**（六顆，四處字面比對）：歷來只出正式版號所以全潛伏。詳 memory `feedback_prerelease_version_two_ecosystems_build_chain`。
27. **交付客戶的 CLI 不得有「印明文密碼」子命令**——設計時的正當理由（保險庫登錄、稽核集中控管）抵不過「客戶端任何 sudo 都看得到全部密碼」。原廠查法走內部文件。詳 memory `feedback_no_cli_that_prints_secrets_to_customer`。
28. **驗收抽查要看「跑的是哪份 code」**：CM-1509 交接說六支 editable、實查另三支有產品碼改動卻指舊 wheel——第一輪綠沒驗到；CM-1533 新目錄首裝撞固定 container_name、fallback 把「舊容器還在跑」判成功、`status` 讀 .env 宣告值非實況。**image tag／`direct_url.json`／`docker ps` 才是真相，宣告值不是。**
29. **runner 誠實揭露的坑價值高於修正本身**：CM-1516「grep 濾掉錯誤→restore 假成功」、CM-1533「換版靜默失敗」、CM-1509「venv 舊副本」——每條都成了下一棒的護欄。派工 prompt 的「踩到什麼坑」欄要保留。

**推翻了什麼**：

30. STATE「只剩四件」的第 1 件（FE `e5595f1` 未推）接手實查已消；第 2～4 件併入收整。「主專案內部重整建議另開 FR」（第四任記帳）被 user 推翻（教訓 23）。
31. CM-1515 卡上「project_extensions drop 四步」——runner 實查 CM-1474 已於 8/31 全部完成，卡片前提過時；卡上「病灶在 jedi-auth/bulletin」——實查那兩支早修好，真來源是 common/oscal-v2/survey。開卡斷言先查（同 [[feedback_card_env_assertions_verify_or_mark_assumption]]）。
32. 「190 直跑功能驗證」段（H 棒）——user 裁刪除：pytest 在本機驗邏輯、190 驗真資料與整合鏈，兩者不重疊；190 由 CM-1516 承擔。
