# FR-038 規劃頁 任務指派 + 流程接通 進度報告（2026-06-17 夜間自動作業）

| 項目 | 內容 |
|------|------|
| 範圍 | 專案規劃頁（ProjectPlanningView）任務指派接 v2 + 控制項實作資料帶出 + 階段推進 + UI 清理 |
| BE branch | `feature/oscal-refactor`（未切 branch、未 push）|
| FE branch | `feature/oscal-refactor` |
| 驗收前置 | **① 重啟 BE ② FE reload ③ 用「新建專案」測（舊專案無 per-AO job、不適用）** |
| 備註 | 夜間作業期間 Anthropic classifier 服務多次中斷，部分編輯延後重試完成；所有變更已落地，未 push |

---

## 一、完成項目（程式碼已落地）

### #1 control-tree 回傳 per-job 指派人（讀）✅
`app/oscal/service/ssp_control_implementation_service.py::get_control_tree`
- 收證據 job 收集 SQL 加 `je.id`、`we.uid`，並 LEFT JOIN `compliance.task_assignees` + `public.users`，每個 job 回 `assignees`（user_uid/user_name/login_name/is_approver/role）。
- 同時暴露 per-AO `workflow_template_uid`（cloned 流程範本 uid）+ `workflow_execution_uid`（BPMN 編輯器用，見 #7）。

### #2 saveTask v2 寫入路徑（任務 meta + 指派人）✅
`infra/grc/repository/grc_job_repo_impl.py::update_job`（原 2A dark `return None` → v2 重建）
- 更新 `job_executions`（name/description/guide/job_type）。
- reconcile `task_assignees`：`task_id = job_executions.id`、`task_uid = je.uid`、`task_template_id = je.template_job_id`、`project_id` 用 `Project.uid` 解析（同既有 `resolve_project_id` pattern）、**`control_id = 0` sentinel**（v2 prep-job 無對應 OSCAL int control；(project_id, task_id, user_id) 已唯一；控制歸屬可由 job→workflow_execution→wecm 回推，讀路徑 control-tree 即如此）。
- diff 式增／刪／改 is_approver。
- dept/device/survey 指派列為 **phase 2**（update_job 暫不持久化這三項，不報錯；survey/device helper 對空清單安全 no-op）。

### #3 FE 規劃頁任務設定 wire v2 ✅
`compliance-manager-fe/.../ProjectPlanningView.vue`
- `fetchTree` 改吃 `GET /ssp/<sspUid>/control-tree`，把內嵌 jobs（含 assignees）直接灌進 `taskMap`、`configured_job_count` 由 jobs 推導、`jobsLoadedSet` 標記後舊 `fetchAOJobs`（dark `/jobs/list`）自動 no-op。
- `fetchUsersMenu` 指派人下拉改吃**專案參與人員**（`CONTROL_PARTICIPANT_MENU` 已 dark 回空）。
- `saveTask` 經 `PUT /grc/.../job/<je.uid>` 走 #2 的 v2 寫入（payload 已帶 job uid + assignees）。

### #7 BPMN 編輯器按鈕 ✅
- BE control-tree AO 暴露 `workflow_template_uid` + `workflow_execution_uid`（見 #1）。
- FE `fetchTree` AO mapping 改讀 `a.workflow_template_uid / a.workflow_execution_uid` → BPMN 按鈕 `v-if` 條件成立即顯示，`openBpmnEditor` 已用這兩欄。

### #4 快速配置批次指派 ✅（改採低風險方案）
`ProjectPlanningView.vue::executeQuickConfig / openQuickConfigDialog`
- 舊 `POST /task-assignees/batch`（`task_assignee_service.batch_add` 已 2A dark `return []`）**不沿用**。
- 改**複用已重接的 per-job 寫入路徑**：對每個可編輯控制項底下的收證據 job，把選取人員 **additive 併入既有指派**後逐一 `PUT /grc/.../job/<uid>`。零 BE 改動、複用已驗證的 #2。
- 指派對象下拉同樣改吃專案參與人員（`PROJECT_PARTICIPANT_MENU` 舊路徑已 dark）。

### #8 移除控制項群組/控制項層級「管理人員」UI ✅
`ProjectPlanningView.vue` 移除：群組層 manage 按鈕 + 參與人員列、控制項層 manage 按鈕 + 參與人員列、`ParticipantsPanel` Sidebar。
- 保留**專案層**參與人員 Tab（alive）。
- ⚠️ script 內 `openParticipants / handleParticipantSave / handleParticipantUpdate / canManageGroupParticipants / canManageControlParticipants / ParticipantsPanel import` 等變成**未使用的死碼**，本次保留未刪（Vite build 不受影響；夜間 classifier 不穩，避免多餘編輯）。日後可清。

---

## 二、調查結論：#5 / #6（**非單純 bug**）

### #5「AO 實作狀態 / 現況描述 / 任務 沒帶出」→ 多為「測試時序」+ 預期空值
- 查 `project_start._init_ssp_control_implementations`：新專案**只建控制項層 IR**（implementation-status=`unknown`），**不建 AO 層 statement** → control-tree 對 AO 回 `ssp_implementation_status=None / description=None`。**AO 的實作狀態 / 現況描述對新專案本來就空**，是給使用者在規劃階段填的（已修成 round planning 可編輯）。
- AO「任務」要顯示 per-AO 收證據 job；job 由 `_generate_prep_jobs` 在**新專案**建（`start_project` step 7b）。舊專案（舊單一 template、part.props 未回填）不會有。
- 三者同時空 = 高度吻合「**在 BE 重啟 + FE reload #1–#3 變更之前測試**」或測到舊專案。
- DB 現況：`job_executions=10253`、`task_assignees=14435`（資料是有的）。
- **結論**：程式路徑正確。請依「驗收前置」用新專案＋重啟＋reload 重測。

### #6「啟動專案推進到下一階段」→ BE 全 alive，但**現存 round 未綁 workflow**（需用新專案驗）
- BE 完全接通：`launch_audit` handler 已註冊（`register_stage_hooks_to_registry` 實際 register，wrap `audit_round_app_service`）；`RoundPrepTasksDoneCheck.check` 回 `ok()`（lenient 不擋）；`stage_advance_service` 已 round-scoped；`launch_audit` 實作完整（snapshot living SSP→`round.ssp_id`、status→audit_planning）。
- create_round 綁流程的 DI（`flow_template_domain_service / workflow_template_snapshot_service / workflow_execution_service`）已 wire；`_create_first_round` 有把 `flow_template_uid` 傳進 `create_round`；建專案頁 `flowTemplateUid` 為**必填**。
- **但 DB 現況**：最新幾個 round（round 1 / planning）`workflow_execution_uid` **為 NULL** → Banner `_resolve_workflow_context` 無 workflow 可解 → 推進按鈕無法運作。
- master `flow_templates=12`（範本有）；但最新資源庫（module_frame 426「亞航CMMC導入計劃」）`audit_flow_template_uid` **為空**（fallback (c) 不可用）。
- **判讀**：現存 round 未綁，極可能是「在建專案頁加必填 flow template／round 綁定之前建的」舊資料，或經未綁定路徑建立。程式路徑本身正確 → **新專案（選了流程範本）應會綁**。
- **待驗（明早）**：建一個**新專案並選流程範本** → 查 `SELECT workflow_execution_uid FROM compliance.project_audit_rounds WHERE ...` 是否有值 → 進規劃頁看 Banner 能否「啟動稽核」推進到 audit_planning。
  - 若**有值且能推進** → #6 完成。
  - 若**仍 NULL** → 是 `_bind_round_main_workflow` 綁定失敗（FE 送的 flow template uid 與 `flow_templates.uid` 對不上，或 master get_by_uid 回 None），需再修；可先 grep `log/app.log` 找 `create_round ... bound` / `flow-binding` warning 定位。
  - 可選防呆：替資源庫設 `audit_flow_template_uid` 預設（讓 fallback (c) 生效）。

---

## 三、驗收 checklist（明早）
重啟 BE + FE reload，**建新專案（選資源庫 + 流程範本）**，進規劃頁「控制項實作」tab：
1. 點控制項 → 現況說明可編輯、存檔成功（round planning 可寫）。
2. 進 AO → 顯示收證據 job；展開 job → 指派人下拉有專案參與人員；選人存檔；reload 後指派人仍在（read 接通）。
3. AO「未配置 → 已配置」標籤翻轉、job_count 正確。
4. 「快速配置」選人套用 → 各 AO job 都帶上該人員。
5. BPMN 按鈕在 AO 有 workflow 時顯示、可開編輯器。
6. 頂部 Banner 顯示「規劃」階段 + 「啟動稽核」鈕 → 推進到 audit_planning（**前提：該 round 有 workflow_execution_uid，見 #6 待驗**）。
7. 群組/控制項已無「管理人員」按鈕；專案層參與人員 Tab 正常。

## 四、變更檔案
- BE：`app/oscal/service/ssp_control_implementation_service.py`、`infra/grc/repository/grc_job_repo_impl.py`（+ `pyproject.toml` dev path-dep 不 commit）。
- FE：`src/views/project/ProjectPlanningView.vue`、`src/views/project/ProjectAuditorOverview.vue`、`src/config/router/index.js`。
- BE import smoke：通過（`ssp_control_implementation_service / grc_job_repo_impl / job_service / api.grc.routes.job_route`）。

## 五、未完 / 後續
- **#6 新專案綁定驗證**（見上，最關鍵待驗）。
- 任務匯出/匯入 Excel（`job_export_query` / `job_import_lookup` 仍 dark）— user 指定後階段處理。
- #8 死碼清理（unused participant handlers/import）。
- dept/device/survey 任務指派持久化（phase 2）。
- 收尾類（changelog / design §11 / Notion）等 user 明確下令。
