FR-154 feature/FR-139 合回 main 收尾 — LOG(append-only,每棒一 block)

§1

2026-10-21 首腦第 1 棒(原為 FR-151 首腦第 6 棒,本 FR 自其 STATE §5.0 拆出)

  • 決策者宣告準備合回 main。首腦唯讀盤點整條 feature/FR-139(merge-base 24cc72972,BE 694 commits)寫成總清單;先做 1~3(套件發版 jedi 56a2f0de+bdd5b90c、還原 pin BE 7bc35752c、基線重產 BE 8f7cc9bc5)。乾淨庫重演抓到三個坑並修:04 產生器漏 is_menu、FR-144 與 FR-148 seed 斷言寫死中間態。
  • 教訓:重產基線的「驗」不能只看 diff 與 stamp gate,乾淨庫 init+migrate 實跑才抓得到「出貨 seed 已是最終態」的順序坑。
  • 教訓:總驗收 STATE 停在 10-17 只管 FR-139~147,之後的 FR 沒人彙總收尾——長 branch 收口要以 git(merge-base、manifest、lock、套件 version-bump commit)重新盤點,不能拼各 FR 的 STATE。
  • FR-149.3 派出並驗收(CM-2903 → BE b6e835785)。派前先確認「需求仍成立」(範本三段亞航字仍在、母卡無改判),不只確認「沒人做」。
  • 四題全裁(照首腦建議):風險 Excel 三欄且可匯入、風險等級只改名;FK 索引這版補;FR-147 空格語意不統一只寫明;#69 併進版、#71 下版。
  • 開十張子卡 CM-2965~2974,起初散掛六張 FR 母卡並自創需求編號 MERGE-2610;決策者兩度點出(「不是要開母卡?」「為什麼不當一個新 FR?」)→ 補母卡 CM-2975,再升格為 FR-154,需求編號改 FR-154 與 FR-154.1~.10,STATE 自 FR-151 STATE §5.0 搬出。
  • 教訓:「不是功能」不是不編 FR 的理由——FR 編號管的是「會跨 session 的工作 arc」,自評(FR-138)、官網(FR-152)都編了;先例 acceptance-2610-fr139-147 用非 FR 命名,結果就是沒人接、不在登記表。
  • 教訓:工作坊是「選母卡派」,一批要一起派的卡就要同一張母卡。
  • 教訓:用 agent-workshop 的 notion_create_case.py 會建到工作坊自己的任務庫;先建錯十張已 archive,改用其 spec 格式配 BE notion_case.py 的 DATASOURCE_ID 重建。
  • 教訓:開十張跨六個 FR 的卡探脈佔大半時間,決策者問「開這麼久」;下次先回報「要查 N 處、預估多久」或分批出。
§2

2026-10-21 首腦第 2 棒(工作坊 session「CM-2975-首腦」:Stage 1 驗收)

  • 決策者在工作坊派七張(CM-2965~2971 扣 2972、加 2973),全部一輪通過 → 驗收通過待確認。每張實際核對:開 commit 看檔、BE 測試自己重跑(2965 三支 159 綠;2967 守衛 2 紅 1 紅與小弟一致)、DEV/STG/POC/188 基線唯讀查索引(2966 只 DEV 有)、整站 mkdocs build --strict exit 0/0 warning、SPEC 頁 grep 沿革句型與 border-left 皆 0、手冊「我的稽核任務」0 筆。
  • CM-2967 守衛紅燈逐條開 FE 檔判定:2 處真落差(MfControlsToolbar 批次設定負責部門掛 resource-library.update 但後端守 raci.manage;JobExecutionDrawer 外層 read 蓋子元件寫鈕)、4 處沒洞但違規範(三顆寫入鈕無 v-can、TaskDueDateRow 散寫 hasCap)、1 處掃描器盲區(risks/import/${mode} 動態路徑)。守衛紅著不合 main → 開 CM-2976(FR-154.11,Stage 1,sonnet/medium)。
  • CM-2971 小弟指出「兩端空格語意不同」前提已被 4d bfda2fe8a 收掉(兩端皆空白=不變動);首腦開該 commit 與 ao_task_guidance_service.py:189 確認屬實。決策者 §2.3 裁定無事可裁;FR-147-STATE 第 50、58 行劃掉並寫明。
  • 教訓:派工卡引用 STATE「待裁」段前要對 git log 驗前提——FR-147-STATE 10-17 之後沒更新,4d commit message 明寫「順帶收掉 4a/4b 不一致」卻沒人回頭劃;首腦開卡時照抄,決策者多裁了一題。
  • 教訓:同批文件卡用 git commit -- <檔> 整檔提交 mkdocs.yml,先 commit 的會夾帶後 commit 的 nav 行(CM-2970 帶進 CM-2969 三行),build 短暫紅到對方頁落地。內容無損,但下次同批改同一 yml 的卡要在 prompt 註明「build 因別人 nav 紅不算你的」(本棒已這樣寫,小弟照報)。
  • 教訓:五張 SPEC 卡對 site/ 建置產物處置不一(四張不 commit、一張只 commit 自己頁),工作樹留 190 檔。卡上該明寫 site/ 歸收尾棒統一 build,不要各自決定。
  • 教訓:zsh 迴圈 for p in "a b"; do set -- $p 不會拆字($2 空),用明確配對或 read -r a b <<< "$p"。
  • 本棒工具:建卡用 BE scripts/notion_create_case.py(建到 CM 庫)+ PATCH /pages/<id> 補四欄(母卡 relation/Stage number/Model select/Effort select);腳本本身仍不支援四欄,STATE §5 的待補項未動。
  • (同棒續)CM-2972 通過(8afcd67f5);整站 strict build 0 warning,Stage 1 六張 SPEC 卡全部落地。CM-2976 第 1 輪退回:小弟把外層 v-can 搬到 <template> 讓守衛綠,但 Vue 只在 <template> 當下帶 v-if/v-for/v-slot 時才視為結構節點,v-can 到 transform 階段才改 v-if、已成一般元素,編譯出真 <template> 標籤被瀏覽器藏起來——首腦用 @vue/compiler-dom+vCanTransform 編譯再 SSR 渲染證實(輸出 <div><template><span>…)。守衛只掃字串不渲染所以綠。
  • 教訓:v-can 守衛綠 ≠ 畫面對;凡改動 v-can 掛點位置(不只是加減),驗收要編譯該 template 看輸出,不能只跑 vitest/三向守衛。<template v-can> 是陷阱,全 FE 原本 0 處使用,退回後應回到 0 並在 vCanTransform.js 檔頭補一行陷阱註解。
  • 教訓:派工卡寫「②先查守衛怎麼收功能點再動」是對的方向,但沒把「fe_vcan_scan.py 第 9 行:掛在子元件標籤=整支子元件 API 算這顆」這條規則直接貼進卡,小弟自己找到規則卻選了錯的繞法。規則本身能貼就貼,少一次猜。
  • (同棒續)CM-2976 第 2 輪通過(FE 0eb060f5、BE 223bd7738):A 方案,read 守門掛子元件根 div;首腦用 @vue/compiler-sfc 編譯三 SFC 確認 createElementBlock("template" 為 0、$can 14/6/5;守衛 FE 6/6、BE 12/12。Stage 1 十張全數驗收通過待確認,CM-2974 arc-review 可派。
  • 教訓:小弟第 1 輪回寫老實寫了「沒實際渲染驗證」,首腦正是循那句去編譯才抓到。打折處是驗收的路標,不是免責聲明——驗收先讀打折處再決定補什麼驗。
§3

2026-10-22 首腦第 3 棒(排程 04:03 自動觸發:CM-2974 arc-review 驗收)

  • 決策者 10-21 晚交代「兩點派、四點驗」,首腦以 CronCreate 一次性排程 04:03 自驗。小弟 02:34 落報告(afa7f52de,372 行),九支 agent(opus 7/sonnet 2)全帶 model。
  • 八條阻斷級逐條開檔到行:B1 _template_readable 對綁專案範本只驗讀權;B2 _require_participant docstring 自承不升 manager、DELETE 只擋 legacy;B3 rk.description = desc or rem 讓 has_risk 成立;B4 AllPoamClosedCheck.check 一律 ok、FE 五處 Banner 只兩處帶 intercept;B5 store_issued → plan → _app.build:101 與預覽同一支吞錯 builder;B6 三語 0 筆;B7 2,595→2,632;B8 801→808 且 CLAUDE.md 例外清單無 DI 檔。八條全真、無誤報 → 通過。
  • 重要級 1 推翻首腦昨天的判斷:CM-2976 ① 我把「批次設定負責部門」鈕改掛 GRC_RACI_MANAGE,依據是守衛訊息「打的 API 後端守 raci.manage」;實際那顆鈕打 control-org-units/batch(守 oscal.ssp.update),守衛把同檔另一支 RACI 呼叫算進來了。昨天給決策者的 (a)「管理員勾 raci.manage 給顧問」作廢。
  • 教訓:守衛訊息列的「打的寫入 API」是該檔所有呼叫的聯集,不是那顆鈕的;判一顆鈕該掛什麼,要開 dialog 檔找它實際 put/post 的路徑,再對後端 route 的 require_capability。昨天少開一個檔就下了結論。
  • 教訓:排程驗收可行——卡狀態+報告檔存在+commit 三重判定「做完了」才驗,避免驗半成品;Notion 連續 append 會 429,重送前先 get 確認卡尾沒落半截。
  • 待決策者:圈阻斷級修正範圖(STATE §3.1 給了 A~D 四張卡的切法與 model)、裁 B8 規範、裁重要 19/20 與 ISO PDF 授權。
  • (同棒續,決策者醒後裁定)阻斷 8 條全修、重要級修 12 條、其餘下版;B1 採「不帶處理人」;B8 豁免 DI 檔;FR-150 D7 改合併知情只改文件;ISO PDF 改官網連結(英文)。首腦查 ISO 官網與版權頁:27001/27002 無免費官方全文或介紹 PDF,版權條款明寫不得放內網/共享平台,「找官方 PDF 放上去」不可行 → 改 reference_url+說明卡+自行上傳。
  • 開七張修正卡 CM-3002~3008(FR-154.12~.18),四欄已補,spec notion-cards-review-fixes.json。建卡後再 PATCH 四欄,Notion 連續 PATCH 要 sleep 並接 429。
  • 教訓:決策者問「連結語言是什麼」——我寫「ISO 連結語言」時沒想到他看不出這是「英文頁 vs 法文頁」這種不必問的小事。不必決策者選的事不要列成選項;列了就要一句講明是什麼。
  • (同棒續)七張修正卡全部一輪通過。驗法:九個 commit 逐檔開 diff;BE 守衛全套+七張新測試 667 過 4 紅——4 紅用唯讀 worktree 在 fd84e5943 重跑證實動手前就紅(平行 session 殘留),寫進 STATE §3.2 要另收;FE v-can-guards 6/6、vite build exit 0、ProjectPlanningView 2,632→2,591;docx 用 zipfile 重數客戶字串 0;DEV 實查 019 新版已套(file_uid 空、reference_url 填、upload_files 刪)、稽核員 export 權已補。
  • 發現:CM-3002 卡上我寫「DELETE 只放行 legacy」是寫反(legacy 本來就唯讀),小弟兩邊都擋沒放寬、還老實問了——卡寫錯時小弟照現況判斷並回問,是對的行為。
  • 🔴 待決策者:jedi-oscal-v2 2.7.1 發版推 Nexus(pin 已指 2.7.1,不發版 build 機會壞);守衛 4 紅另開卡;基線重產;重要 3 寫入端裁示。
  • 教訓:Notion 連續 get/append 七張會 429,要每張間隔 ≥6 秒並接 retry_after;驗收多張時先把 commit diff 全看完再抓回寫,不要一開始就打七次 API。
  • 教訓:zsh for p in "a b"; do set -- $p 已踩第二次,改用 ${p%%:*}/${p##*:} 拆字串。
  • (同棒續,決策者裁三件後執行)①jedi-oscal-v2 2.7.1 推 Nexus:build 後先 unzip -l 確認 wheel 內無 ISO PDF(只剩 CMMC×2+CRA)才 publish;poetry 這版 publish 不收檔名,把 dist 舊版 mv 到 dist-old 再推;BE poetry update 切回 Nexus 來源 00d90a396,realpath 指 site-packages 無 symlink。②基線重產:先 dry-run gen_schema 確認 02 與基線庫同步(只 \restrict 雜訊)→ 容器內 pg_dump 備份 → 基線庫套 CM-2966 → 發現 CM-3006 手改 04 會被 gen 沖掉(04 由 gen_shipped_roles_sql.py 從 shipped-roles.json 產),改源頭 json → 三支 gen → 02 零刪除只多兩索引、04 排序後只差日期、99 gate (a) 綠 → 834d2f811。③重要 3:FR-147 D2 本來就寫明不要求 manager,arc-review 沒對到;補一句 a2c5eac6c。
  • CM-3009 通過:守衛 576 綠 0 紅;路由三支登記 PENDING 不豁免、解析點八點分類正確、Redis 六前綴皆非 key、jedi 鏡像綠。帶出一題待裁:review-step-templates GET 無 read 能力點,建議改附錄 C 列 JWT_ONLY。
  • 教訓:04-seed 是 gen 產物,手改必被沖掉——CM-3006 卡上我寫「04-seed-core.sql:710 加一行」是錯的指引,正確是改 resources/roles/shipped-roles.json;README 第 29 行早寫了「不要手改 04」。開卡時指定路徑前要先看該檔是不是產物(記憶 feedback_card_check_capability_index_before_prescribing_path 的同型)。
  • 教訓:rm -rf dist/* 被安全檢查擋是對的——publish 不需要刪舊檔,mv 到旁邊就好;順手刪不是必要動作就不要寫進指令。
  • 教訓:arc-review 的「重要級」要先對 design 決策表再列——重要 3 其實是 D2 已定案的本意,reviewer 沒對到;首腦當時也沒對,多讓決策者裁了一題。
  • 決策者裁「先 push 一版、bump 之後再做、安裝包先等」並放行 push:三 repo feature/FR-139 推 origin(BE 18 commits ee88d5e6d、FE 15 7ba85915、jedi 7 223cc823),不碰 main、不 force。BE 工作樹 190 檔 site/ 產物與 CLAUDE.md/FR-144/151 HTML 未提交改動不是本棒的,未動。發版時移開的 dist-old 已移回 dist/。