---
title: 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 現況
4. 本檔 §1～§4
5. `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（測試棒開工先跑）

```bash
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 唯讀盤點。
讀取與盤點完成後不做任何事——不派工、不跑測試、不改檔，回報現況後等我下指令才開始作業。
```
