FR-141 STATE

FR-141 交接現況(STATE)

這份是 living 檔:每棒就地 Edit,只描述「此刻」。歷史脈絡看同資料夾的 fr141-LOG.md。

項目 值
最後更新 2026-10-16 22:00(決策者裁示當全部驗過;三 repo 已 push;母卡+全部子卡 Done;套件未發版、主專案未進版)
branch BE/FE/套件都在 feature/FR-139(主工作樹)。feature/FR-141 三 repo 皆保留,已全數併入,不要再在它上面開發
合併 commit BE 75d3af54d、FE c4b0a359、套件 e3be08aa;已 push 到 origin/feature/FR-139(BE 30b0f8363、FE ba0aa033、套件 3b94ad67,套件分支已設追蹤)
母案卡 CM-2799 https://app.notion.com/p/FR-141-Excel-3fa346da4cd081dc86f3fd725ee2707f (Done,2026-10-16)
子卡 雛形 CM-2800;實作 CM-2802~2810、CM-2814,全部 Done
下一棒 無。收口待辦(§3)等 FR-140 收口後與套件發版一起做
Notion 回寫規範 docs/claude/notion-issue-tracker.md

🧭 原始需求 / WHY

決策者原話(2026-10-15):「稽核計畫的功能需要整個重新調整……需要再多一塊稽核計畫的文字表單,內容如下面文件內 1-6 大點……這份儲存後要可以匯出類似範例搞格式的 docx or pdf」「目前的稽核計畫很難填寫,而且也不能 by ao 去寫是 by 控制項,需要改成可以 by AO 去填寫,要可以提供 Excel 匯出匯入」「畫面不要用舊的,舊的真的很難用」「一份 Excel 不同 Sheet 分兩頁……這樣就不用分兩種匯入」。

做出來長什麼樣:稽核計畫頁整個換掉,兩個頁籤——

  • 計畫概要:亞航報告稿 1~6 段(依據、目的、稽核單位〔單行,只填公司名〕、稽核日期起迄、稽核範圍、稽核方法論)+稽核人員。
  • 查核項目規劃(原名「評估目標」,2026-10-16 改名):左樹右表單(同 SSP 控制項編輯版型),逐條評估目標(AO)填「查核方法+指引」(不限組數)、受評人員(可當場新增,存本計畫名單)、受評元件/資產、稽核人員(預帶概要名單可覆寫)。
  • Excel 一份四頁(填寫說明、計畫概要、評估目標、可選清單),匯出就是匯入範本;一格多值(方法與指引一行一組「方法:指引」,人名換行或分號);匯回在原畫面「預覽模式」標黃底與原值,打錯的方法詞或人名就地對應,對應完才能確認。
  • 匯出三選一:亞航格式報告稿 docx/pdf、Excel、打包 zip。
  • 內外稽核不混:FR-140 之後每一次稽核各自一份計畫,頁首麵包屑標「第 N 次內部/外部」,可切同輪已結束的那次唯讀看。
  • 第 2 次內稽/覆核輪:上一次「不合格」與「沒判定」的評估目標所屬整條控制項帶過去,只有明確「合格」才不帶;帶過去的連同填好的內容一起承襲,標「承襲自第 N 次」。

資料存法:照 OSCAL 評估計畫標準欄位——六段文字進新表 oscal.ap_terms_and_conditions;一條 AO 一個 activity(control-objective-selections 帶 part_id);受評對象進 task 的 associated_activities[].subjects;本計畫新增的受評人員存 AP metadata party、角色 assessed。

不在本案:評估結果(AR)改逐 AO 判定與 Excel 的「佐證、結果」兩欄 → 已另開 FR-142(CM-2818)。

§0 接手讀序

0.1 🔒 先懂需求 gate

  1. 本檔 🧭 WHY 節
  2. docs/features/FR-141-2610-audit-plan-ao-worksheet-and-report-export/design.md「分工概述」「決策定案」兩節全讀
  3. python3 scripts/notion_case.py get CM-2799 讀母卡最後一段「合併前現況」與「合併後決策者複測清單」

0.2 現況

  1. 本檔 §1~§4
  2. fr141-LOG.md 最後 2 個 block

0.3 需要才開

  • 各子卡的 runner 回寫與首腦復核(每張卡最後兩段)
  • 雛形 prototype/index.html(假資料,實作後新增的 B4 選單名、B5 受評人員新增不在雛形裡)

0.4 ✅ 冷接自檢

  1. 為什麼要重做稽核計畫?(舊頁以行程為單位、只到控制項、填不動、不能匯出報告稿)
  2. 兩個頁籤各放什麼?Excel 幾頁、多值怎麼寫?
  3. 第 2 次內稽帶哪些控制項?跟 FR-140 的什麼共用?
  4. 受評人員當場新增存在哪?為什麼不存 SSP?

§1 當前狀態

項目 狀態
程式 在 feature/FR-139,三 repo 已 push(BE 14c7c5d75 起、FE ba0aa033、套件 3b94ad67);新端點 overview/objectives/export/xlsx-imports、report-title、assessed-people;舊 PUT /ap/<uid>/tasks 已移除
worktree 三個 repo 的 FR-141 worktree 都已移除;8001、5181 已停;worker(RUN_MODE=worker)沒動
測試 守衛+FR-141 相關 149 passed;FE npm run build:DEV 過
manifest 衝突兩邊列都留,check_migration_manifest.sh 通過
DB(DEV 共用) 已套:2026-10-16-fr141-ap-terms-and-conditions.sql(主線)、2026-10-16-fr141-audit-method-examine-label.sql(seed,「檢視」→「檢視/現場觀察」)
Notion 母卡 CM-2799 與子卡 CM-2800、2802~2810、2814、2835 全部 Done
文件 SPEC〈稽核計畫填寫頁〉docs/spec-site/current/audit-execution/ap-authoring.md、使用手冊 docs/user-manual/audit-plan-guide.md、design.md「實作後改判」節、README 均已更新
卡 做什麼 狀態
CM-2802 A1 計畫概要存得起來(terms 新表+overview API) ✅ Done
CM-2803 A2 新頁殼+計畫概要頁籤+稽核次麵包屑 ✅ Done
CM-2804 A3 報告稿 docx/pdf 匯出 ✅ Done
CM-2805 A4 docx 匯入寫進計畫概要 ✅ Done
CM-2810 A5 docx 匯入不再改寫行程(修 A4×B1 衝突) ✅ Done
CM-2806 B1 逐 AO 存+AR 讀方法逐 AO ✅ Done
CM-2807 B2 評估目標頁籤+刪舊頁與舊 /tasks ✅ Done
CM-2808 B3 Excel 匯出匯入+同畫面預覽 ✅ Done
CM-2809 B4 第 2 次內稽/覆核輪範圍含未判定+承襲+「檢視/現場觀察」 ✅ Done
CM-2814 B5 受評人員當場新增(存本計畫名單) ✅ Done

§2 已定裁示(不要重新討論)

  • D1 Excel 一格多值(換行或分號),附填寫說明+可選清單;不用固定格數下拉、不用巨集。(2026-10-16 改判)
  • D2 稽核人員概要預設、AO 可覆寫;D3 受評對象拆人員與元件/資產兩欄;D4 未知方法詞或人名在預覽就地對應。(2026-10-15)
  • 頁籤名「計畫概要」;稽核單位單行只填公司名稱;方法組不限數量。(2026-10-16)
  • Excel 匯入對不到的稽核人員可當場新增(下拉「新增『名字』為稽核人員」),確認時 AP 有同名非受評人員就沿用、沒有才建;元件/資產不開放。對不到的受評人員與稽核人員預設就是新增,橫幅標「將新增 N 位人員」。匯入預覽進場篩選固定「全部」。(2026-10-16 晚)
  • 查核項目規劃沒有控制項層:「控制項預設」區塊已拿掉(它只是不存檔的一鍵複製,會讓人誤以為能設定控制項層);Excel、總覽、預覽、Word 都只有逐條評估目標。曾做過的 Excel 控制項列已 revert。(2026-10-16 晚,決策者裁示)
  • 第二個頁籤改名「查核項目規劃」(en「Assessment Item Planning」),Excel 第三頁同名;舊檔頁名「評估目標」仍可匯入。指 AO 本身的「評估目標」字樣不改。(2026-10-16 晚)
  • P1 第 2 次內稽與覆核輪:只有明確 satisfied 才不帶,pending 與沒判定都帶,整條控制項帶過去。(2026-10-16)
  • P2 報告稿附件表多印受評對象、稽核人員兩欄,匯出可關。P3「現場觀察」併入「檢視」改名「檢視/現場觀察」,不新增選項。(2026-10-16)
  • A4×B1 衝突走甲案:docx 匯入只寫計畫概要與稽核人員、不碰行程。(2026-10-16)
  • 受評人員當場新增存 AP 自己 metadata party(role=assessed),不加進 SSP。(2026-10-16)
  • AR 逐 AO 另案 → FR-142。

§3 下一步

現況:決策者 2026-10-16 晚裁示「當我都驗過」,母卡與子卡已 Done,三 repo 已 push。決策者裁示先不發套件、不進版。

剩下的收口待辦(等決策者下令,FR-140 收口後一起):

  1. 四支套件同批發版(jedi-compliance-audit、jedi-flow-engine、jedi-task-platform+jedi-oscal-v2),主專案四支一起還原 pin。
  2. 主專案進版(release note、BE/FE 版號、spec 快照、重生 99-stamp)——要等套件發版、pin 還原後才能做。
  3. 出貨基線重產(A1 那支主線 migration)。
  4. 小收尾三項(見 §4)。
  5. 文件:design.md 已補「實作後改判」節(115c8e3e1);SPEC 頁 ap-authoring.md 改寫、新寫使用手冊「稽核計畫使用指南」、README 與需求站 HTML 更新 → ✅ CM-2835 完成(54a600127),首腦復核過、Done;新使用手冊 docs/user-manual/audit-plan-guide.md。
  6. e2e 另開一棒;ddd-compliance-reviewer 掃整個 FR-141 diff;碰到的超標檔至少拆一支。

⚠️ 這節是建議清單,不是執行授權。接手方讀完盤點完即停,等決策者發令。

§4 待辦與風險

  • ✅ 稽核計畫書預覽壞掉——已修(FE a927edd4),待決策者畫面複測。原因:fetchPdfUrl 沒帶 meta.withHeaders,攔截器直接回 Blob,程式卻解構 { data } 拿到 undefined,包成內容「undefined」的假 PDF。以下為原始紀錄::匯出對話框按「預覽」→ 前端 useApExportDownload.fetchPdfUrl 打 GET /ap/<uid>/export?format=pdf,拿 blob 包成 application/pdf 放進 ApReportExportDialog.vue 的 iframe。後端 log 那次 export 沒有任何錯誤(log/app.log 約 71796 行,req-fc89d098),所以問題在瀏覽器端。待查假設(都未驗):① axios 攔截器在 responseType: blob 時把回應包成信封,blob 不是 PDF;② meta: { withHeaders: true } 沒帶,回的是 data 而非 blob(下載用的 download() 有帶);③ 前門 CSP 擋 blob: 的 frame-src;④ LibreOffice 轉檔慢、對話框沒 loading。先開瀏覽器看 console 與 network,本棒瀏覽器工具整晚不可用所以沒查。
  • ✅ Word 附件表「稽核人員」欄空白——已修(BE 70be6a8cc),登入狀態實打 docx 7/7 有值、PDF 正常。以下為原始紀錄::app/flow_control/service/ap_report_export_service.py 約 213 行,附件表每列稽核人員取 o.get("auditors"),只有該 AO 個別覆寫時才有值;沿用計畫概要名單時 auditors 為 null,格子就空白。修法:null 時改用計畫概要的稽核人員名單(畫面的 effectiveAuditors 同一規則)。修完匯出 Word 與 PDF 都要開檔確認,Excel 匯出要檢查是否同樣規則(Excel 空白=沿用是刻意設計,不要跟著改)。
  • 🔴 驗證教訓:本棒 299a69b0d 新端點 return_response 少帶 status,一打就 500,決策者打開頁面才發現;只驗了未登入 401。之後新端點必須用登入狀態實打一次(瀏覽器或 test client)才算驗過。
  • 🔴 主 pyproject.toml 仍 pin jedi-oscal-v2==2.6.0:主 venv 目前是 editable 指主套件目錄(.venv/lib/python3.11/site-packages/jedi_oscal_v2.pth),所以 8000 吃得到新碼;有人在主工作樹跑 poetry install/update 就會換回 Nexus 2.6.0,計畫概要(terms)與逐 AO 會 500。驗證:.venv/bin/python -c "import jedi_oscal_v2,os;print(os.path.dirname(jedi_oscal_v2.__file__))" 應指 jedi-python-package/jedi-oscal-v2/...。
  • 🔴 B4 改了 FR-140 共用的縮範圍規則:合併後 FR-140 的第 2 次內稽與覆核輪會多帶 pending 與未判定的控制項(P1 預期);合併前測過的舊資料範圍會跟現在不同。
  • 合併前就紅、屬 FR-140:test_fr132_t42_route_capability_mounts.py::...[api/flow_engine/routes/flow_engine_route.py]——FR-140.14(c496961a2)在 flow_engine_route 加了 route 沒登記附錄 A。已轉告 FR-140 首腦。
  • 舊債紅燈:test_error_code_mirror_parity(主專案錯誤碼比 jedi_compliance_audit 鏡像多;FR-141 前就紅),發套件時補鏡像。
  • 小收尾(不影響功能):ap_overview_app_service.py 與 assessment_plan_app_service.py 直接 PartyRepoImpl() 未經 DI;套件兩處過期註解(audit_round_app_service.py、audit_round_pass_app_service.py 提到已刪的 set_tasks/_backfill_scope_from_tasks);list_ap_parties 不分角色,docx 匯入比對稽核單位用全量名單 → 改只比 organization。
  • DEV 測試資料:已軟刪的 1409 AP 留了幾筆 runner 測試資料(受評人員「B5測試受訪者」「B5匯入新人」)。

§5 Pre-flight(測試棒開工先跑)

cd ~/Projects/Billows/Audit-Manager/compliance-manager-be
git branch --show-current                          # feature/FR-139
git log --oneline -1 75d3af54d                     # FR-141 合併 commit 存在
.venv/bin/python -c "import jedi_oscal_v2,os;print(os.path.dirname(jedi_oscal_v2.__file__))"   # 要指主套件目錄
lsof -iTCP:8000 -sTCP:LISTEN -t                    # 8000 在跑
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8000/api/1.0/ap/x/overview      # 401=路由在
curl -s -o /dev/null -w "%{http_code}\n" -X PUT http://localhost:8000/api/1.0/ap/x/tasks  # 404=舊路徑已移除

§6 環境座標

  • BE 8000(主工作樹,python main.py);worker 另一支行程(RUN_MODE=worker);log log/app.log。
  • FE 主工作樹 dev server(.env.development.local 指 8000)。
  • DB:DEV 本機 localhost:5432,連線看 .env(DB_HOST/DB_PORT/DB_NAME/DB_PASSWORD),帳號 cmmgr。
  • FR-141 測試資料:專案 1548「CMMC 內外稽流程測試專案」(輪次 1199、AP 7cd12add-286d-4283-9e52-cdf3f5d2b450,決策者 10/16 晚新開)。1547 已軟刪。1321 為覆核輪範例。
  • 範例檔:決策者桌面 00_Compliance Manager/01_稽核文件/AirAsia實際稽核檔案/AP稽核計畫匯入測試檔案/(報告稿 docx、稽核紀錄 xlsx)。

§7 行為規範提醒

  • 只動 DEV;STG/POC 一律不碰。push 等令。不切 branch。
  • 主工作樹多 session 共用:只 git add 自己的檔;不要跑會改整棵工作樹的 git 指令。
  • 主 pyproject.toml 有 FR-140 三支套件 path 設定未 commit(刻意),不要 stage、不要還原。
  • 改 BE service 後重啟 8000;BE 出錯先看 log/app.log。
  • 自做突變測試後清 __pycache__(見 closing-and-handoff skill)。

§8 不在本期 scope

  • AR 畫面與判定改逐 AO、Excel 的「佐證資料」「稽核結果」欄 → FR-142。
  • AP 的 OSCAL JSON 匯出。
  • docx 匯入擴充其他格式 adapter。

§9 給 fresh session 的短 prompt

接手 FR-141(稽核計畫重做)測試棒。先讀 docs/features/FR-141-2610-audit-plan-ao-worksheet-and-report-export/handoff/fr141-STATE.md(🧭 WHY、§0 讀序、§1~§4),再讀同資料夾 fr141-LOG.md 最後 2 個 block,並 python3 scripts/notion_case.py get CM-2799 看母卡「合併後決策者複測清單」。
回答 §0.4 冷接自檢 4 題,跑 §5 pre-flight 唯讀盤點。
讀取與盤點完成後不做任何事——不派工、不跑測試、不改檔,回報現況後等我下指令才開始作業。