# FR-038 子弧 SUMMARY — 證據蒐集任務執行 + 規劃頁/總覽 v2 修復

> 日期：2026-06-17　branch：`feature/oscal-refactor`
> 範圍：FR-038 規劃頁 v2 遷移衍生的一連串缺口修復。下階段 = **ap_authoring（稽核計畫填寫）**。

## 弧脈絡（為何做）

規劃頁整合證據蒐集後，「待辦任務 / 任務佇列」恆空。追下去發現一連串 FR-038 **Wave 2A「2B 重建」沒做的 stub** —— 證據蒐集任務執行整條斷、總覽多個面板/進度 dark。本弧逐一補齊 BE+FE。

## 已 commit

| commit | 內容 |
|--------|------|
| `b99e8067` | **證據蒐集任務執行 BE** — `start_task_execution`（PM 批次轉 PROCESSING + 通知）+ `get_prep_job_progress`（軟 gate 進度）+ route/DI/測試（5 綠）。設計記錄 `evidence-task-execution-design.md`。 |

## 未 commit（working tree，與 ap_authoring WIP 混檔，待人工分離後 commit）

### BE 修復

| 主題 | 檔案 | 改動 / 根因 |
|------|------|------------|
| **完成/退回死表 fix** | `app/flow_engine/service/workflow_execution_service.py` | `complete_job` / `revert_job` / `notify_user_todo_job` 開頭無條件查已 DROP 的 v1 表 `oscal.assessment_plan_task_workflow_execution_mapping` → 任務一完成就 500（PG transaction 毒化）。讓該 v1 路徑退場（ap_mapping=None + guard 下游 reviewer 通知 / 專案狀態更新）。 |
| **退回 flag** | `infra/grc/repository/grc_job_repo_impl.py` | `get_job` 寫死 `can_revert_job=False` → 退回鈕永不出現。改實際算 `_compute_can_revert_job`。 |
| **問卷型任務還原** | `infra/grc/repository/grc_job_repo_impl.py` | 6 個 survey 方法（`get_job_survey_evidences`/`add_survey_evidence`/`get_job_ids`/…）2A 被過度 stub（只查 job_evidences+survey 表、不碰死 OSCAL 表）→ 從 git 撈回原始實作；`get_job` 補載入 surveys + 真實 job_type。設問卷任務 → 抽屜顯示填寫卡片。 |
| **Dashboard 重建** | `infra/grc/repository/grc_project_repo_impl.py` + `domain/grc/service/grc_project_domain_service.py` + `app/grc/service/project_service.py` + `api/grc/routes/assessment_plan_route.py` | `get_ap_dashboard` 原 `return {}` → 用 per-AO prep-job 經 catalog 鏈統計（任務數/完成率/狀態分布/控制項數）。串 `project_uid` 進 route→app→domain→repo。 |
| **受評範圍 + resolver fix** | `app/grc/service/project_service.py` + `di_containers/grc/grc_containers.py` | `components=[]` 寫死 → 改查專案 living SSP 的 `ssp_inventory_items`（props `ref-type`：device→設備、information_system→稽核系統）。**根因**：`SspProjectResolver.resolve_current_ssp` 內部呼叫 `SspService` 不存在的 `get_ssp_by_id` → 自 2A 起永遠回 None；繞過它直接取 `project_extension.living_ssp_id`。注入 `ssp_service`。 |
| **受評標的 DTO** | `app/grc/dto/project_dto.py` + `api/grc/serializers/project.py` + `app/grc/service/project_service.py` | 新 `AssessmentTargetDto`（範圍名稱/識別碼/安全分類/類型/負責人，從 SSP system characteristic + owner-uid 解析 nickname）。 |

### FE 修復（compliance-manager-fe）

| 主題 | 檔案 | 改動 |
|------|------|------|
| **開始執行任務按鈕** | `ProjectPlanningView.vue` + `ProjectAuditorOverview.vue` + `api.js` + `project-planning.json`(zh/en) | 規劃頁(header+進度條) + 總覽(自動分類證據旁) 各加 PM「開始執行任務」鈕（規劃階段才出現）+ **confirm 對話框**（確認發批次通知 + 進執行階段）。 |
| **批次完成原因回顯** | `MyTasksView.vue` | 批次完成結果畫面補顯示輸入的原因（原本沒顯示）。 |
| **受評標的 + 資產面板** | `ProjectAuditorOverview.vue` + `auditor-overview.json`(zh/en) | 「稽核系統」面板 → **受評標的**（SSP system characteristic）；「設備」面板 → **資產**（設備+系統整併、帶類型標籤）。icon `pi-bullseye`(不存在)→`pi-compass`。 |
| **控制項進度** | `ProjectAuditorOverview.vue` | 左側群組/控制項 % 原讀 BE 沒算的 `completion_rate`(恆 0) → 加 `ctrlProgress`/`groupProgress` 從 AO jobs 算。 |
| **規劃 banner 文案** | `auditor-overview.json`(zh/en) | 拿掉「啟動專案」重寫。 |

## 行為差異（user 可見）

- 任務可完成/退回（原一完成就 500）；問卷任務可填；批次完成顯示原因。
- 總覽：任務數/完成率正確、受評標的 + 資產面板有資料、控制項進度反映任務完成度。
- PM 可在規劃頁/總覽一鍵「開始執行任務」（批次轉 PROCESSING + 通知）。

## 已知 follow-up

- **AO/控制項審閱 v2 全壞（2A stub）** — Notion 已開：`AO/控制項審閱在 v2 全壞（review resolver 2A stub + control-tree is_reviewed 寫死 False）`（Not started）。`_resolve_control_ids`/`_resolve_ao_id` 回 None + control-tree `is_reviewed` 寫死 False。待決：審閱屬規劃還是稽核(AR)階段。
- **commit 分離**：未 commit 的 BE 修復與 ap_authoring WIP 混檔（`workflow_execution_service.py` 等也含 WIP），需人工分離後顯式 git add。
- **驗證**：user 已手測「都改好了」；BE `start_task_execution` 5 單元測試綠；其餘修復以 DB 實證 + py_compile 驗證，未補自動化測試。

## 部署 handover

- BE 改 service 層 → 需重啟（無 hot reload）。
- 無 schema migration（全用既有表）。
- FE 純前端 + i18n，HMR。
