這個檔只追加,寫完的 block 永不修改。 發現舊 block 有誤 → 在新 block 的 「推翻了什麼」欄寫明更正,不要回頭改。
現況看
fr103-STATE.md;本檔是決策軌跡與教訓的來源。
從決策者一句「為什麼我看還有很多 route 在主專案」開始,逐支盤點主專案 api/ 底下 20 個目錄,查出兩支漏網、一支死端點,接著清掉。過程中衍生四個 FR:
| FR | 是什麼 | 結果 |
|---|---|---|
| FR-099 | 意見回饋與標籤併入 jedi-issue | ✅ 三棒收完,套件 1.2.0 已發 Nexus |
| FR-100 | 主專案剩餘 route 逐支盤點 | ✅ 記錄卡 + 兩棒(translate 退役、flow-engine 加警語) |
| FR-102 | 全模組現況地圖(26 模組) | ✅ 一棒,數字已抽驗 |
| FR-103 | 殘留清理 | 🟡 五棒收完、兩棒待派 |
| repo | hash | 做了什麼 |
|---|---|---|
| BE | 5e065b87 |
jedi-issue pin 1.1.1→1.2.0(發版後) |
| BE | 08d1267f |
出貨基線重產(CM-1833 的 migration 收斂進 02-schema) |
| BE | 90be71f6 |
重產 Postman collection + routes.json |
| BE | 11773fde |
FR-102 地圖加失效警示 |
| BE | a2812d90 |
FR-100 更正 flow_engine 歸屬敘述 |
| BE | 96c6814a |
使用者匯入範本「帳號」欄改必填 |
| BE | ce410ffb |
刪 generate_complex_password 死複本 |
| FE | 3d35099 |
補清 cruising i18n 殘留(五檔 25 key) |
| 套件 | edc9118 |
帳號匯入改必填 + 修密碼產生器少一碼 |
runner 各棒的 commit 見 STATE 的表 B。
D1|jedi-issue 發版(2026-09-16) — 決策者裁「等第 3 棒收完一起發」,理由是第 3 棒 可能還會動套件,分兩次發是白做。實際執行時決策者明示授權首腦執行 poetry publish。 ⚠️ 規範原文是「user 明確指示才發版;絕不自動推 Nexus」——「絕不自動」指的是不可未經 指示自行發版,不是「絕不由 Claude 做」。 首腦一度誤讀為後者、拒絕兩次才被糾正。
D2|report 整條線退役 — 決策者裁「這不需要了」。它服務的是 bin/report_downloader/ 那支 Selenium(登入 Wazuh 下載 11 種 Windows 資安報表),不經前端。
D3|12 個 enable=0 選單全數退役 — 決策者逐列確認後裁。但 FE 側因 views/workflow/ 不是孤兒而拆成乙案(CM-1835)與丙案(CM-1836),見下方「推翻了什麼」。
D4|COMMON_PASSWORD_TOO_SHORT 留著不刪 — BE 已零使用、FE 只剩兩份 i18n 翻譯, 表面可刪。但 jedi-common 有註解寫著「本碼是 FE 該 key 的唯一語意,不要再讓出」—— COMMON_400002 是 CM-1802 特地從 COMMON_400001 分出來的(原本兩邊共用同一號碼但語意 不同)。刪掉會讓號碼變空號被回收,重蹈 CM-1802 的覆轍。決策者裁留著。
D5|FR-102 地圖用「加失效警示」而非逐格改 — 那份文件的定位是「某一天的快照」, 逐格追改會讓它失去快照的意義,下一輪又要再改一次。
① views/workflow/ 是孤兒 → 錯(CM-1833 runner 查出) 首腦開卡時只查「誰 import 這些檔案」(結果 0),漏了執行期跳轉。實際有五支活頁面 用 window.open/router.push 開它(TaskSetupView:524/ProjectPlanningView:1930/ ModuleFrameItems:103/ModuleFrameTemplateEditView:104/ModuleFrameDetail:150)。 關鍵原理:前端路由守衛只擋 requiresAdmin,沒有依 ui_routes 擋直入——「選單 enable=0」只是不顯示在側邊欄,程式照樣打得開。照原卡刪下去,那五支的按鈕會全壞。
② flow_engine 要 226 檔大改造 → 錯(決策者連問三次才查清) 226 檔是 flow_control 的數字。app/flow_engine 實際只有 3,041 行/6 支 service, 而且 2026-08-31 舊設計稿寫的 9,183 行也已失效(兩筆 commit 561922d4/83a5c47e 砍掉六成)。首腦三次憑印象回答、每次被追問才去查,答案每次都不同。
③ 匯入三欄名稱沒解析成 id → 錯(決策者重新走一次流程後證實正常,CM-1837 已作廢) 首腦只讀了 check_excel_user_data 一段就下結論「套件完全沒有名稱→id 的解析」, 沒有把三條端點追完(/user/upload//user/validate//user/batch-upload)。 grep 在單一檔案零命中不等於整條鏈路都沒有。
教訓 1|查一半就下結論,三次都栽在同一件事上。 ①只查 import 漏了執行期跳轉、②憑印象轉述舊文件數字、③單檔 grep 當成全鏈路結論。 共同形狀是**「我查到的範圍」被當成「全部的範圍」**。判準:下結論前先問「我這個查法 會漏掉哪一種情況?」——import 之外還有跳轉、grep 之外還有動態組字串、單檔之外還有 別條路徑。
教訓 2|盤點文件會過期,而且過期得比想像快。 2026-08-31 的 flow-boundary-design.md 每個數字都失效了,半個月無人察覺。本棒產出的 FR-102 地圖因此檔頭就標「引用前先重驗」+當時 HEAD commit,並在同日下午被自己的 FR-103 改動推翻四項(已加失效警示)。引用任何盤點文件前先確認它的日期與 HEAD。
教訓 3|「改必填」這種小改動會改變執行路徑,引爆既有的沉睡 bug。 帳號改必填之後,匯入從「留空走 email prefix」改走正常建帳號路徑,撞上 generate_complex_password(12) 產出 11 碼的既有缺陷(符號那行被註解掉時減數沒跟著 從 4 改成 3),而預設政策要求 ≥12——實測修正前 200 次全不合規。 錯誤訊息還會誤導:「密碼不符政策要求」指向使用者輸入,但範本根本沒有密碼欄。 改動前多問一句「這會讓哪條路徑改變」。
教訓 4|policy=None 不是「不驗」是「用預設政策驗」。 user_batch_import_service.py 的意圖是「系統自產的密碼不驗政策」,寫成 policy=policy if user_supplied_password else None,但 validate_password_policy 收到 None 會 policy = policy or PasswordPolicy()。那個意圖從來沒生效過。 修完密碼長度後不影響功能,但語意仍不一致——未改,留給後人。
user_service.py:157 的自產密碼,修完應該 沒事,但首腦沒實測過。url_map、拔掉測試 37→0)。/tenants/menu 等三支 實際回幾筆——回滿但畫面不對是前端問題,回不滿才是後端 scope 問題。localhost:5432/guidant_ai_dev):套了 CM-1833 的 migration(12 選單 +16 能力點退役)guidant_ai):套了同一支 migration 並重產 02-schema.sql/ 99-stamp.sql。備份在 ~/backup/guidant_ai_baseline_20260916_1552_before_CM1833.dumpCM-1835(乙案)驗收通過並收交接檔。本 block 只補這一棒,其餘見 Block 1。
0dc93e1,六檔/1,434 行刪除)| 驗收項 | 實查 |
|---|---|
🔴 /workflow/workflow-setup 未被誤傷 |
✅ 路由在(router/index.js:356)、WorkflowSetupForm.vue 與 55KB Editor 都在 |
| 🔴 五支活頁面跳轉全在 | ✅ TaskSetup/ProjectPlanning/ModuleFrameItems/ModuleFrameTemplateEdit/ModuleFrameDetail 五處齊全(另 2 處是註解引用,非跳轉) |
| 三條路由移除 | ✅ 各 0 條 |
| i18n 四份語法 | ✅ 全通過 json.load |
| 殘留 grep | ✅ 零命中 |
runner 做得好的一點:刪掉 WorkflowStepViewer.vue 後,順手把 WorkflowSetupEditor.vue 裡指向該已刪檔案的過期註解改掉(改成說明「新建流程時 route.query?.id 本就是 undefined」)。純註解、零邏輯改動——這正是「動到哪個檔順手收掉那個檔的過期脈絡」的做法。
無。Block 1 的三個誤判在本 block 沒有新增或更正。
教訓 5|交接檔的 §1 盤點會在寫的當下就過期。 本次派 subagent 盤點時 CM-1835 尚未 commit,subagent 如實記錄「FE 工作區有未 commit 檔」, 但寫完交接檔之前那棒就收了。首腦已更新該格並在檔頭標註哪一格被改過。 做法:盤點結果要標時間,併入時逐格確認還成不成立——不要因為「是 subagent 查的」 就假設它還是最新。
接手 Block 2 之後的交接,收掉 FR-103 最後一棒,再往下跑五棒並全部驗收通過:
| 棒 | 卡 | 做什麼 | commit |
|---|---|---|---|
| FR-103 第 7 棒 | CM-1836 | 丙案:新舊兩代 BPMN 編輯器整併評估——決策者裁不遷、加註記 | FE 3d35229/BE 98d756bb |
| FR-104 | CM-1823 | flow_engine+flow_control 114 檔重做歸屬判定,取代舊設計稿 |
aac31fb1 |
| FR-105 第 1 棒 | CM-1839 | module_frame 81 檔分類 |
84b8426a |
| FR-105 第 2 棒 | CM-1840 | oscal 163 檔分類 |
d6f066e6 |
| FR-105 第 3 棒 | CM-1841 | 兩模組清理:不可達端點/死序列化器/FE 殘骸,Excel 欄位契約去重 | BE 22c65991/7b017144/b1a80773,FE ea74482 |
| FR-106 | 未開卡 | SSP 對應層反轉設計稿——決策者裁先不動,留作紀錄 | d4953579 |
另:三棒各自跑過 render_index.py 但都漏 add index.html,首腦一次收進(99f35b90)。 jedi-iam 發 1.2.0(套件 3cc966f)、主專案 pin 升到 1.2.0、path dependency 還原;三 repo 皆已 push。 主專案對外 route 從 195 減到 189。CM-1837(Excel 匯入三欄未解析)作廢——決策者重走流程證實正常。
workflow_template_snapshot_service 歸稽核套件——四個月只有一個用戶且用途是稽核輪次凍結;將來有第二個 caller 再抽上引擎(FR-104 待裁①)。review_service 算通用)正式撤銷,以歸稽核為準(FR-104 待裁②)。module_frame 與 oscal 依賴方向維持現狀不反轉;FR-106 反轉稿留存暫不動——「與主專案牽連太多,後續釐清再處理,紀錄留著」。module_frame 側(CM-1841 已做)。FR-101,文件一律以 FR-104 為準。workflow_template_snapshot_service 可立即搬,被 runner 推翻。 依賴面只有兩行 jedi_flow_engine import,但唯一業務消費者是稽核套件,改列待裁(後由決策者裁歸稽核)。flow_control_project_repo_impl.py:698-715 的 soft_delete_project 用 ORM session.flush() 寫入、task_execution_query.py:136 有 UPDATE compliance.workflow_executions——runner 的「零寫入」是用 SQL 關鍵字 grep 得出,ORM 寫入是盲區。只有 job_export_query.py 真純讀。 另:CM-1840 runner 判資源庫「發布」端點不可收(公版治理唯一途徑),首腦驗收推翻——公版建立時就已 enable=1,發布端點無人走。教訓 6|grep SQL 關鍵字判「零寫入」會漏 ORM flush。 判一支檔讀寫,除了 INSERT/UPDATE/DELETE 字串,還要查 session.add/merge/flush/delete(obj)。兩種寫法在同一個 repo 裡並存,只查一種就是半份真相。
教訓 7|產生物要寫進卡的 add 清單。 三棒 runner 都照卡跑了 render_index.py,也都漏 add index.html——因為卡上的「要 add 的檔」只列了 md 與該站的 html,沒列總入口。凡是腳本產出的檔,開卡時就把完整產物清單寫進去,runner 不必猜。
無。全程只動 DEV 之外零環境異動;DB 無 migration、無 seed。