# FR-063 Nuitka 落地版打包 — LOG（append-only，每棒追加一 block）

---

## Block 1 — 2026-08-14 首腦 session（設計棒）

**角色**：分析決策首腦（協調者）。實作零行，文件產出外包。

**產出軌跡（時序）**：
1. 三路探脈（動態 import／`__file__` 路徑／外部依賴）→ 盤點 15 項風險（🔴2／🟠4／🟡5／🟣4）
2. 討論稿（discussion.md/html）產出 → user 審 → D1–D11 逐項定案（D7–D10 由原 Q1–Q4 待確認項升格）
3. design.md 定稿 → commit `b053c765`（未 push）
4. 開卡：三母案 CM-1187（FR-063）/CM-1188（FR-064 防竄改）/CM-1189（FR-065 Installer）＋ FR-063 子卡樹 14 張 CM-1190~1203 一次建齊（Case No 連號）
5. 第 1 波派工 prompt 產出（.1a/.1b/.1f 三棒平行），等 user 發令

**關鍵決策脈絡（供回顧）**：
- **Nuitka 取代 .pyc 方案**：Python 3.11 反編譯工具鏈已斷（uncompyle6/decompyle3 停在 3.8 前後），純 .pyc 其實已有基礎保護力，但 user 拍板要最高保護等級 → Nuitka standalone，對齊 Go binary 陣營交付形態。
- **夜間實測炸 dependency-injector**（2026-08-13 STG 機實測：冷 build 1h27m／產物 808MB／pymupdf 單檔 34 分）：import 期 `SystemError: dynamic module 'dependency_injector.providers' not initialized properly from def`——官方 wheel 走 Limited API（abi3）強制 PEP 489 多相初始化，與 Nuitka 靜態嵌入不相容 → **D2 私房 wheel rebuild 納入管線前置步驟**（版本感知快取＋sdist 留檔）。
- **D9 統一入口是 user 提議**：原方案兩支入口各自編譯（build ×2、產物 ×2），user 反把兩次 build 變一次——單 binary `RUN_MODE` 切 api/socketio 兩模式，三支舊入口全退役，順帶解 scheduler 雙跑＋socketio 進程瘦身。
- **D11 config 三層重整源自 user 主動提問**（binary 化後「改 config＝重編譯交付」，設定放錯層代價放大）→ 六套環境 class 塌一套／Secret 拆 JSON 包裝＋config_loader 集中驗證（向後相容舊 .env）／營運參數遷 DB system_config，加開子任務 .1g（CM-1200）。
- **盤查大發現（列 follow-up memory）**：`SQLALCHEMY_*` 四支 ×7 份全無消費者（未裝 flask_sqlalchemy、app_factory 自組 URI）——**讀寫分離從未實際生效**（`DB_READ_HOST` 設了沒人用）；**Swagger 從未啟用**（`docs.init_app` 被註解，`APISPEC_*` 是死項）。兩者皆不進本案，Swagger 補齊列 follow-up。

**教訓／備忘**：
- `.env.bak`（user 自留備份）差點被 `git add` 掃進——**不在 .gitignore**（現行規則只有 `.env`）；當場攔下，`.gitignore` 補 `.env.*` 留給 .1g 一併做。
- `ENV` 環境變數降級為純顯示標籤時**不退變數本身**——避免破壞現有部署腳本（三環境 .env / systemd / compose 都還在傳它）。

**產出物**：discussion.md/html、design.md/html（含 D1–D11 決策表、§5 詳細設計、§6 拆分表）、commit `b053c765`、Notion 3 母案 + 14 子卡、第 1 波派工 prompt ×3、本 STATE/LOG 雙檔。

**下一步（給下一任首腦）**：依 STATE「派工順序表」發令——第 1 波 .1a/.1b/.1f 三棒平行；build 機一到位插隊 .2b 驗炸點。

---

## Block 2 — 2026-08-14 晚 首腦 session（第二任，第 1 波驗收）

**角色**：接手首腦（分析決策/協調）。本棒動作：.1a / .1f 驗收。

**驗收結果（皆親手實跑，不信 runner 自報）**：
- **.1a CM-1194**（commit `18ef3142`）✅ 通過：
  - `gen_di_modules_static.py` 實跑產 138 模組、`--check` 綠
  - 兩軌等價：`CM_DI_MODULES_MODE=static/dynamic` 取清單 list equal
  - 突變測試：親手在靜態清單插 `app.fake.module_xyz` → `--check` exit 1 並指名多餘項
  - 缺檔 fail-fast：移走靜態清單 → static 模式 RuntimeError（非靜默退回動態掃）
  - code 抽查：`--check` 走 AST parse 不 import（避開 import 快取），設計正確
- **.1f CM-1199**（jedi repo commit `57e8a41`）✅ 通過：
  - env override：設 `LIBREOFFICE_CMD=/fake/path/soffice` → resolve 回傳該值
  - fallback：清 env → 回 PATH 的 `soffice`
  - grep 兩 adapter 確認舊 `LibreOffice.app`/platform 硬編已清零，共用 helper
  - path override（pyproject.toml `M`）確認為開發態，未 commit，符合 jedi-* 規範

**教訓／備忘**：無新教訓；runner 自報與實況一致（含突變測試都有做）。

**下一步**：.1b（CM-1195）進行中等回寫；.1b 過驗後派第 2 波 .1g（CM-1200）。卡收 Done 等 user 令。

---

## Block 3 — 2026-08-14 晚 首腦 session 續（.1b 驗收、白話化、.1g 派工與事故復原）

**本棒動作**：.1b 驗收 → Notion 15 卡白話化 → 派 .1g → .1g 事故裁決與交接檔復原。

**.1b CM-1195 驗收 ✅ 通過**（commit `78937428`）：
- 四讀取點親測解析：TRANSLATIONS_DIR isdir、SSP docx 範本 exists、`load_canon('cmmc-l1')` 63 條、`build_catalog('cmmc-l1')` 6 domains
- `resources/download/` 5 支範本檔實在；GLOBAL_DOWNLOAD_DIR 絕對路徑
- 範本下載端點 401 非 404（route 註冊活；完整下載留 user 手測——login 有 Cloudflare captcha 擋 curl）
- 核心測試 26 passed；test/ 9 個 ai_dashboard collection error **查證為既存**（前一 commit 就缺模組）
- 備忘：`version_route.py:17` `__file__` 讀 pyproject.toml 打包後 fallback 'unknown'——歸 .1e version bake，派 .1e 時寫進 prompt

**Notion 15 卡白話化**：subagent 全數重寫（PM 受眾＋文末「技術細節（工程用）」段，事實零流失），抽查 CM-1194 確認。

**🔴 .1g 事故（checkout-index 誤抹）**：.1g runner 用 stash 驗「測試 error 是否既存」，pop 後改動進 index、工作樹回 HEAD，再跑 `git checkout-index -f -a` 把 index 沒有的檔案（STATE/LOG 的未 commit 更新、pyproject path override）覆寫回 HEAD 版。runner 自己的 .1g 改動無損。**復原**：STATE/LOG 由首腦逐字還原（皆本棒親筆，context 有原文）；pyproject override 由首腦改回。**教訓**：runner 派工 prompt 應明令「驗既存問題用 `git stash` 後恢復只准 `stash pop`，禁 checkout-index / checkout -- / restore 整樹操作」；交接檔未 commit 就跨棒是風險放大器——首腦寫完 STATE/LOG 應盡快 commit。

**下一步**：.1g runner 續跑驗收⑤（module_frame 6 支 collection error 已由其驗證為既存）→ 回寫卡等驗收。

---

## Block 4 — 2026-08-14 夜 首腦 session 續（.1g 驗收）

**.1g CM-1200 驗收 ✅ 通過**（commit `5acedd9b`）：
- 驗收③ 親驗：隔離 env 跑 `validate_required_env()` → ConfigError 一次列全 5 缺項（含新舊兩種填法提示）
- 驗收④ 親驗（DEV DB 突變）：UPDATE LOGIN_MAX_LOCK_COUNT 3→9 → `init_db(uri)` 後讀到 9；DELETE 該列 → 回內建預設 3；re-seed migration 冪等還原 7 列
- 六套環境 class 已刪（grep class Development/Staging/Production = 0）；SQLALCHEMY_*/APISPEC_*/TOKEN_TTL/WEBSITE_URL 已清
- schema_migrations 有登記 `2026-08-14-fr063-1g-runtime-config-seed.sql`
- HEAD 起服務 200、log 印 `Config loaded (ENV label=DEVELOP_PREMISE, DEBUG=True)`
- 既有測試抽跑 16 passed；tests/ 整合套件全紅為既存（runner 用改版前程式碼驗證同紅）

**驗收方法備忘**：`runtime_config` reader 走 `db.SessionLocal`，裸 script 未 init 引擎時 fail-open 回預設（設計如此）——獨立驗證要先 `init_db(uri)`；`create_app()` 二次呼叫會炸 dependency-injector NonCopyableArgumentError（既存行為，服務路徑不受影響）。

**Runner 留下的注意事項（首腦查證）**：
1. `MANUAL_FILENAME`（login_route.py:127 手冊下載端點讀取）config 從未定義——**既存問題**，該端點一直是壞的；不在 .1g 清單，留待裁決是否開卡
2. STG/POC CORS 目前全放行（既存，因 ENV 一直填 DEVELOP）——上版時補實際站台網址，已列 config-migration-mapping.md
3. JWT 效期改 DB 後需重啟才生效（框架啟動期讀 app.config），登入政策/MFA 即時生效——已寫進對照表
4. tests/ 測試 DB 缺 schema 全紅、6 支 module_frame collection error——皆既存，另行處理

**下一步**：第 3 波 .1c+.1d 併一棒待派；四張卡收 Done 等 user 令。

---

## Block 5 — 2026-08-14 夜 首腦 session 續（.1c+.1d 驗收、.env 整理、CM-1204 開卡）

**.1c+.1d CM-1196/CM-1197 驗收 ✅ 通過**（commit `b40a5710`）：
- 新入口 `main.py`＋新平鋪 .env 起服務：version 200、DI 138、menu 401（@inject 活）
- socketio 模式：8002 `/healthz` 200（mode=socketio）、`/api/1.0/version` 404（REST 未載）
- scheduler：`init_scheduler` 獨立驗證 4 jobs 掛齊（drive_sync_worker 5s／webhook_channel_renewer 6h／framework_parse_job_cleanup 1am／license_expiry_state_machine 2am）；socketio 模式 log 印 disabled
- grep 舊入口引用：僅剩註解與歷史文件，程式/腳本/Dockerfile 全改
- 備忘：`main.py` 與舊入口一樣**不自帶 load_dotenv**（PyCharm/dotenv wrapper 慣例），CLI 起服務用 wrapper：`python3 -c "from dotenv import load_dotenv; load_dotenv(); import runpy; runpy.run_path('main.py', run_name='__main__')"`

**.env 整理（user 直接交辦首腦做，非 runner）**：
- 本機 .env 遷平鋪格式＋全檔分區註解（備份 `.env.bak-20260814-pre1g`）
- 逐 key 審計 49 項（主專案＋jedi 全樹）：清 6 死項——REDIS_DB（程式硬寫 0）、通知四項（SEND_NOTIFY_MODULES/TELEGRAM_BOT_TOKEN/TELEGRAM_CHAT_ID/DISCORD_WEBHOOK_URL，通知已全走 DB NOTIFY_CONFIG）、DRIVE_WEBHOOK_PUBLIC_BASE_URL（config 有定義零讀者，Phase 3 未實作）
- 差點誤殺後留下的：SCHEDULE_REPORT_DIR（api 層在讀）、ENABLE_MULTI_TENANT／AUTH_CHANGE_SECRET_COOLING_HOURS／TURNSTILE_SECRET_KEY（jedi 套件在讀）——**審 env 死活必須連 jedi 套件一起 grep**
- .env.sample 同步：清通知四項＋修 TURNSTILE 格式錯誤（範本裸值→JSON，jedi-captcha json.loads 它）

**CM-1204 開卡**（subagent）：MANUAL_FILENAME 手冊下載端點——查證升級為「死碼端點」（route 從未註冊、FE 無呼叫、config 無定義、檔案不存在三缺一殼）；獨立 bugfix 不掛 FR-063。另 config-migration-mapping.md §6 補 STG/POC 上版 13 項 checklist（commit `cb830d09`）。

**下一步**：.1e（CM-1198）＋.1 收口 gate——派工 prompt 要帶：version bake 接點含 version_route.py:17、config.py:200 死定義清除、.env.sample working tree 變更一併收。

---

## Block 6 — 2026-08-14 深夜 首腦 session 續（.1e 驗收＝FR-063.1 子需求收口）

**.1e CM-1198 驗收 ✅ 通過**（commits `aa760c50` + `8a83fa98`）：
- version 端點親打：回 `{version: 1.14.0, commit: 5766...}` 兩欄位
- bake 突變親演：gen → 改 9.9.9-ARBITER → 讀到突變值（真讀檔非快取）→ 刪 bake → fallback pyproject 1.14.0
- fail-fast 突變親演：REGISTERED_APPS 塞假模組 → RuntimeError [FATAL] 指名模組
- 意外收穫查證：`resource` 模組確為死項（api/ 無此目錄、FE api.js 無呼叫）——fail-fast 上線即抓到 19 次靜默 warning 的陳年漏拔
- 收口 gate 八項 runner 自報全過，抽驗①②③⑥⑧一致；⑧ PyCharm 真實 debug 體驗留 user 本人驗
- test_api_version_route 2 passed

**FR-063.1「程式整理」子需求 7 卡全數過驗**（a/b/c/d/e/f/g）。剩：.2 build 線（等 build 機）→ .3 → .4。

**啟動方式變更（user 已確認知悉）**：`python main.py`＝API 服務（8000，日常唯一指令）；`RUN_MODE=socketio python main.py`＝通知服務（8002）。main_app.py/main_socketio.py 已刪除退役。

---

## Block 7 — 2026-08-14 深夜 首腦 session 續（FR-063.1 收 Done）

user 本機複測通過（登入/範本下載/SSP 匯出/i18n/雙模式），下令收卡：
- 七工作卡 CM-1194/1195/1196/1197/1198/1199/1200 → Done
- 子需求卡 CM-1190 → Done＋收口註記（commits 清單/gate 結果/新啟動指令）
- 母案 CM-1187 續留（全案結案才收）

**下一階段 = FR-063.2 Build 管線**：.2a（build 機環境建置）→ .2b（wheel rebuild，到機最優先驗 dependency-injector 炸點）→ .2c（Nuitka build script）。卡點＝user 的 24core/32GB build 機；**.2c script 撰寫依 design §5.4 可先行**（不需 build 機，只是沒法實跑）。

---

## Block 8 — 2026-08-14 深夜 首腦 session 續（.2a+.2b 驗收＝D2 炸點排除）

**.2a+.2b CM-1201/CM-1202 驗收 ✅ 通過**（commit `d510ed79`）：
- 🔴 **D2 炸點親驗排除**：build 機親跑兩份探針產物——官方 wheel 版炸 `SystemError: dynamic module 'dependency_injector.containers' not initialized properly from def`（重現 8/13）；私房 cp311 wheel 版 `RESULT=PASS`。全案最底層風險解除，且走候選①（setup.py 預設重編）即成功
- rebuild script 快取親測 0.047 秒命中；abi3 守門突變測試 runner 已做
- abi3 觀察名單 3 套件：cryptography／gevent／nacl（4 個 .so），.2c 整包編譯見真章
- build 機環境全項達標（Nuitka 4.1.3／ccache 46% hit／二次編譯 55s→8.9s）

**兩阻塞事項處置**（user 當場裁示）：
- `/opt/guidant_ai` 權限：user 給 sudo，首腦 chown jedi:jedi＋清 8/13 舊產物 4.8GB（磁碟回 198G）
- Nexus 憑證：user 本人在 build 機設 pip extra-index-url（憑證處置不經 Claude，紀律正確）；首腦驗證 `pip download jedi-common` 成功拉到

**runner 誠實澄清**：pyproject path override 只在 Mac working tree 未 commit，build 機 checkout 是 pin 版——派工單預想的處置不需要。

**下一步**：.2c Nuitka build script（整包編譯）——jedi-* 19 支可裝了、工作區權限已解，無阻塞可派。

---

## Block 9 — 2026-08-15 01:03 首腦夜間檢查（user 授權自主驗收）：.2c 通過

**.2c CM-1203 驗收 ✅ 通過**（commit `8a697d85`）——夜間第 1 檢查點即完成回寫，直接進驗收：
- **產物親驗（build 機實跑，非抄自報）**：
  - `/opt/guidant_ai/.build/dist/guidant-ai-1.14.0/`（832MB）：`.py` 檔數 **0**（保護未破）、`.mo` ×2、SSP docx 範本在位、resources/download 5 支在位
  - 親起 `./guidant-ai` binary → `/api/1.0/version` 回 `{version: 1.14.0, commit: 8a83fa98...}`（與 bake 一致）、`/users/menu` 401（DI wire 活）——**.1 全部機制（DI 靜態清單/resource_path/version bake/binary 旁 .env 載入）在真產物內首次驗證通過**
  - 驗完 pkill 清進程，無殘留
- runner 自報數據：首編 56m42s（勝 8/13 的 1h27m）、二次 18m36s（快取證實）、六項健檢全過（含 gunicorn 雙 worker）、防呆突變測試有做
- **兩個真問題 runner 已修**：①gunicorn 動態載入模組 Nuitka 追不到→顯式 include＋升級為健檢項（開發環境看不出、只有正式承載會死的陰險型）②編譯參數誤收 metadata 目錄
- 觀察名單三套件（cryptography/gevent/nacl）整包編譯**未觸發**——不需重編，繼續觀察
- 待 .3 的遺留：七項全套探針（PDF 中文/上傳/socketio 實際收發）、production Dockerfile

**FR-063.2 三卡全數過驗**（.2a/.2b/.2c），收 Done 等 user 令。下一波 **.3（CM-1192 production image）→ .4（CM-1193）**，全案剩最後兩棒。

---

## Block 10 — 2026-08-15 上午 首腦 session 續（發版收官、.4 回歸裁決、.2d 開卡）

**jedi 發版收官**：file-upload 0.0.21＋captcha 0.0.14 推 Nexus、pin 還原、BE/jedi 雙 repo user 親推齊（BE 至 `02146e9d`）。**poetry.lock 自此入版控**（歷史誤排除移除；當日實測教訓：build 機因 lock 不同步 poetry 拒跑，scp 急救後拍板正規化）。TURNSTILE 平鋪化（captcha 三段式解析）＋ENV 四值新慣例（DEV/STG/POC/PRD，本機與 sample 已改）同日落地。

**.4 發現真回歸（runner 調查）**：.1c 模式裁剪把 socketio namespace 註冊（藏在 create_module() 內）一起裁掉——兩模式都沒有可用 namespace，即時功能整組失效。**首腦裁決選項 2**：namespace 註冊抽離至集中清單 config/socketio_namespaces.py（比照 REGISTERED_APPS），app_factory 於 init_app＋DI wiring 後統一註冊。首腦全 repo 掃定 namespace 封閉集合＝2 個（notification／fill-survey）。派工 prompt 已出（含端到端 client 探針要求——本回歸正是 healthz 級探針測不到的層，驗收探針深度教訓）。獨立發現：nginx http2 擋 WebSocket（環境異動待裁示；.3 範例設定需避開）。**順序改為 .4 → .2d → .3**（.3 包最終修正後 binary）。

**.2d 開卡 CM-1205（編譯加速）**：首腦研究＋user 拍板「公開套件不需編譯保護」——pymupdf（31 分地板）等公開大套件 --nofollow 排除原樣附帶、測試依賴（pytest 系 4 支誤放正式清單）搬 dev group。預估冷 build 砍半。jedi-*＋業務碼照舊全編譯。

**在飛**：user 的熱 rebuild 計時（監看中）、.4 runner、（.2d 待 .4 完成後派）。

---

## Block 11 — 2026-08-15 下午 首腦 session 續（.2d 驗收＋.4 產物層驗證）

**.2d CM-1205 驗收 ✅ 核心通過**（commits `381acf76`→`f449f939` 共 5 筆）：
- 親打 STG 成品（user 授權起於 188）：8000 version 200＋commit `36708b35` 身分正確、menu 401、8002 healthz 200、REST 隔離 404
- 產物抽驗：業務碼 .py=0、jedi 目錄 0（全編入 binary）、排除套件抽樣 5/5 在位
- **成果數字**：冷編 56m42s→穩態 **12m11s（省 78%）**；三個靜默複製 bug 全修＋三道自動把關（完整性斷言/功能探針 9 項/dry-run 預檢）
- **.4 產物層同場驗證**：runner 確認兩 namespace（notification/fill-survey）在編譯成品內註冊成功——.4 的修正在產物層活著
- runner 名言收錄：「拿最慢的迴圈去測最快能測的東西」——驗證順序金字塔已寫進腳本檔頭

**首腦自踩事故（記錄）**：驗收時在 188 跑 `--dry-run`，但 188 停在 `36708b35`（**f449f939 的 dry-run 功能未 push**），舊版無參數解析、`--dry-run` 被無視直接進真編譯——誤觸兩輪、已 pkill 清除，STG 驗證服務無波及。教訓：**跑新功能前先驗目標機的 code 版本**（與 runner 的「服務有回應≠你要的版本在跑」同型——它 09:58 也撞過 root 舊進程佔 8002）。
**runner 留的環境警示**：188 .env 今早被異動時漏了一支 Drive 金鑰導致成品一度起不來（已補）——其他環境同批異動需檢查。

**待收尾**：188 push 齊後親跑一次真 dry-run＋腳本端到端輪（runner 的「需讓腳本完整跑一次」）；.4 尚欠 client 級 socketio 收發探針；兩卡收 Done 等 user 複測令。

---

## Block 12 — 2026-08-15 下午 第二任首腦交棒（中繼 handoff）

**交棒時刻的狀態**：.1 七卡＋.2 四卡（.2a/b/c/d）全 Done（user 皆複測過）；.4（CM-1193）修正待驗證——產物層 namespace 驗證已過，user 實測中發現**新的 socket bug，正在另開卡**（等 .4 runner 回報，新卡號待補）；.3（CM-1192）未派。

**給下一任首腦的待辦（依序）**：
1. **等 .4 runner 回報＋user 的新 socket bug 卡**——驗收 .4 時注意：產物層 namespace 註冊已驗過（STG 上 36708b35 成品），欠 client 級收發探針（scripts/build/socketio_probe.py 是現成工具）；新 bug 卡按 user 指示處理（可能併 .4 修或獨立棒）
2. **.3（CM-1192 production image）派工**——包含：Dockerfile（非 root uid/entrypoint chdir+chown/apt 清單/fc-match 斷言）、七項探針全套（design §5.6）、nginx 範例避開 http2（LOG Block 10 的發現）、volume 佈局（design §5.5）；產物用最終修正後的那顆
3. .3/.4 全收後：母案 CM-1187 收 Done 等令、全套收尾（SUMMARY 由 LOG 濃縮／spec／手冊／analysis——.2d「公開套件不需編譯保護」的推理已答應 user 寫 analysis）

**組織記憶（這兩天最值錢的教訓，皆已實證）**：
- 「服務有回應≠你要的版本在跑」——commit bake 的版本端點是唯一身分證（runner 撞 root 舊進程、首腦撞舊版 script 誤觸真編譯，同日兩例）
- 靜默失效是本案主敵：三個複製 bug 全部「回報成功但成品是壞的」；防線=把人工清點做進腳本斷言＋功能級探針（不只 import 級）
- 驗證順序金字塔：bash -n 0.01s → dry-run 0.3s → 小探針 10s → 全量 19m，先快後慢
- Nuitka 常數表連坐：模組集合一變全量重編；排除清單越大連坐圈越小（12m11s 的由來）
- env 管理三坑同日爆：sample 歷史欠帳 18 支／188 設定在 .bashrc 隱形／LICENSE_ACTIVATION 隱式預設剛好能動——單一真相來源＋顯式化是解

**在途物**：STG 188 上兩服務（8000/8002，36708b35 成品）供 user 驗證中，驗完由 user 決定去留；.env.bak-20260814-pre1g 留在 repo 根（user 自留）；jedi repo 與 BE 均已 push 齊。

---

## Block 13 — 2026-08-15 傍晚 首腦 session 續（.4 驗收＝eventlet 命題閉環）

**.4 CM-1193 驗收 ✅ 通過**（commits `78debb6c`/`e8104ef6`）：
- 首腦親跑產物 socketio 探針（STG 8002，36708b35 成品）：**4/4 PASS**——兩 namespace connect、join 回應、多人 join 走到 @inject service（DI 注入實證）
- runner 全套驗證：產物雙模式（8002 healthz 200/REST 404/scheduler 0；8000 REST 200/socket.io 404/scheduler 4）、突變測試（關 namespace 註冊→探針 0/2）、既有測試 37 passed
- **eventlet × Nuitka 命題閉環：編譯產物下 monkey_patch + socketio.run 正常，D1 保底方案（換 gevent）不需啟用**——本卡最初存在的目的達成
- Flask-SocketIO 5.3.6→5.6.1 升版根治（user 裁示，取代 manage_session workaround）；app_factory 留「不可退版至 5.3.6 以下」警語＋症狀特徵
- user 實測：加入/離開通知、在線頭像正常；**自動存檔問題確認為既存獨立 bug（2026-07-07 起）→ CM-1206**（socket 路徑無 auth context，patch_task_survey_answer AttributeError）——先前被「連不上」蓋住現形，不擋 .4
- 排程雙跑老問題實錄確認解除（api 1 份 scheduler、socketio 0 份）

**全案盤點至此**：.1 七卡＋.2 四卡＋兩母卡（CM-1190/1191）Done；.4 修正待驗證（等 user 收卡令）；剩 **.3（CM-1192 production image）未派**＋母案 CM-1187。CM-1206 獨立 bug 待排程（不掛 FR-063）。nginx http2 待裁示。

---

## Block 14 — 2026-08-15 傍晚 更正（推翻了什麼）

**🔴 更正：nginx http2 不是問題，不需要任何處置**——user 裁定並實證。先前 .4 runner（Block 10/13 引用）記「http2 擋 WebSocket、修法拿掉 http2 或升 nginx」是**誤診**：當時 400 的真因是 **socket endpoint 沒建置好**（namespace 未註冊，即 .1c 回歸本身），不是 HTTP/2 協定問題。user 已把 http2 開回、實測 h2 200 正常。**後續一律不再把「避開 http2」寫進 .3 nginx 範例或任何文件**；Block 10/11/13 中相關句子視為作廢。教訓：runner 的「獨立問題發現」也要驗證因果——當時兩個問題（namespace 缺席＋http2 假設）疊在一起，修好前者後就該回頭重測後者再下結論。

---

## Block 15 — 2026-08-15 晚 第二任首腦最終交棒（兩棒派出、.4 收 Done）

**收卡**：.4（CM-1193）＋.2a/b/c（CM-1201/1202/1203）＋CM-1191 全收 Done——**FR-063 主線 11 工作卡＋兩子需求卡全數完結**。

**兩棒同時派出（平行，零檔案重疊）**：
- **CM-1206**（socket 共編存檔修復，app 層＋可能跨 FE）：修法方向已定＝connect 驗 JWT 建 auth context、FR-048 守門不降級、錯誤不再靜默（handler emit 錯誤事件＋log）；驗收五項含突變測試
- **.3 CM-1192**（production image，docker 層）：Dockerfile.production（非 root uid1000／entrypoint／apt＋fc-match 斷言／volume §5.5）＋七項探針 §5.6；先用 36708b35 產物跑通、合流時重打

**更正沿革注意**（接手必知）：nginx http2 誤診已在 Block 14 作廢——.3 的派工 prompt 發出時仍含「避開 http2」字樣（發出在更正之前），**驗收 .3 時若 runner 照做了要把該部分退回**：nginx 不需任何 http2 特殊處置。

**交棒交割**：STATE 已定稿（當前狀態／待辦地圖四項＋場外／遺留待辦）；交接 prompt 已交 user（讀 STATE→LOG→盤點→停）。本任首腦 context 滿載退場，接手者從驗收兩棒開始。

---

## Block 16 — 2026-08-15 晚 第三任首腦（合流執行＋全案收口）

**角色**：接手首腦。本棒與前兩任不同：user 直接令首腦本體執行合流（原 runner session 已失能），故本 block 含執行紀錄。

**驗收**：
- CM-1206 ✅（commit `6de7ffd8`＋FE `967e67b`）：code 抽查（fail-closed 全路徑、UserContextDTO 組裝抽單一實作與 HTTP 等價、DI fixed_modules 有補）＋DI --check 綠＋guard 測試 6 passed＋本機 8002 活體負向探針拒連 PASS
- .3 CM-1192 ✅（commits `29c4013f`→`cc7714d2` 共 3 筆）：Dockerfile/entrypoint 實讀（glibc 對齊理由、chown-then-setpriv 設計、fc-match 斷言）＋188 image 內實跑 fc-match 解析 NotoSansCJK、業務 .py=0、uid1000；**http2 檢查：全部產出 grep 零命中，runner 未踩已作廢誤診**

**合流執行（皆 188）**：
- 插曲：前 session 遺留一份 build 與新起的互撞 → linker crash（`undefined reference to module_code_anthropic$_exceptions`，判定為共用 nuitka-out 汙染非 code 問題）→ 全清重跑單 build 一次過
- rebuild 產物 bake `cc7714d2`；**摘要報告範本本輪由腳本自動收**（上輪手動 cp 欠帳閉環，斷言 OK）
- build_image（`0dcabc8d`）→ push Harbor `guidant-ai/guidant-ai-be:1.14.0`＋`latest`（digest `bba0449d…`）；Harbor API 端複驗在位。探針最終輪依 user 指示跳過
- 發現修正：**188 gitlab SSH 金鑰實測可用**（runner「無金鑰」為誤判）；user 同日立 memory「部署機程式碼一律走 git pull、禁 rsync」

**收尾補強**：build script i18n 加 `--statistics`＋註明 .mo 現場重編語意（`f921ed39`；查證 Step 2 本就重編、「忘 compile」本就進不了產物，原提案的 staleness 檢查不需要）；--statistics 首輪即抓到 zh_Hant_TW 65/66 → 查證為死條目 `non_existent_key`（jedi-system-config 測試 fixture 被 extract 誤收）清除，兩 locale 回 100%（`2834cf4c`）。188 工作樹清乾淨（proxy.csr/key＝8/13 nginx 實驗遺留 → 搬 `~/certs/`；messages.pot 還原）。

**收卡**：CM-1192/CM-1206 user 複測後親收 Done；母案 **CM-1187 收 Done**（末段 append 全案收口摘要）——FR-063 全案完結。

**新戰線決策（user 拍板）**：①FE image＋產品 compose **不提早做**，劃入 FR-065（compose 形狀由 installer 決定；FE 靜態產物無保護議題）②**DB 初始化基線獨立開卡 CM-1207**（FR-065.0：帳號/schema 基線/GRANT 逐表/seed 三分類/初始 admin，一卡五事互相咬合）③順序＝FR-064（user 親做）→ CM-1207 實作 → FR-065；**盤點棒唯讀可先行**，prompt 已交 user
- 依賴關係：FR-064（binary/image 側）與 DB 初始化（資料側）零依賴可平行；兩者皆為 FR-065 前置

**教訓**：
- 起遠端長任務前先 `pgrep` 查同類進程——兩份 build 互撞的 crash 症狀（linker undefined reference)像 code 問題，實為 artifact 汙染
- runner 的「環境不可行」結論（無金鑰）也要親驗——一條 `ssh -T git@gitlab.com` 就能戳破，誤信就多養一條 rsync 歧路
- 覆蓋率統計是便宜的守門：--statistics 一行參數，首輪即抓到潛伏死條目

**下一步（給接手者）**：FR-064 期間首腦待命；CM-1207 盤點棒回報後驗收（重點：待裁決清單品質、有無越界寫入）；FR-063 文件收尾等 user 令。

---

## Block 17 — 2026-08-15 晚 文件收尾完結（第三任首腦，user 下令後執行）

user 令「收尾直接派 subagent」。兩支平行：
- **SUMMARY**（`handoff/2026-08-15-FR-063-SUMMARY.md`，commit `0e7368a0`）：八段式，由 LOG 16 blocks 濃縮；抽查過——commits 清單/交付物座標正確，http2 僅以「誤診更正」教訓形式出現（無「避開」指示）
- **analysis 兩篇**（commit `feccea4e`）：`2026-08-15-nuitka-public-package-exclusion.md`（公開套件不需編譯保護推理，含反悔條件）＋`2026-08-15-nuitka-build-verification-pyramid.md`（常數表連坐＋驗證金字塔＋靜默失效防線）；抽查過——皆含選項/取捨/反悔條件四段，數字與 LOG 一致
- memory：新增 feedback「起遠端 build 前先 pgrep 查同類進程」；MEMORY.md 瘦身至 140 行內（含 FR-063 收案座標、BE 入口 main.py 修正）

**範圍裁定**：spec／使用手冊不觸發——FR-063 是 build/打包基建，無終端使用者操作變更（啟動方式屬部署文件範疇，已在 deployment-env.md）。

FR-063 至此**全案含文件完結**。剩餘：本機 4 筆 docs commits 待 user push；CM-1207 盤點棒等 user 派。
