Handoff Prompt — A5 Session B → C(BE ship → FE 實作開工)

使用方式:把下方「交接 prompt 本體」整段貼到新 session 即可接手。 前置狀態:A5 Session B BE shipped (6f926e0);BE 273 a5+a4+a3 test 全綠 0 regression;A5 phase BE 端 OK,FE 仍待開工。 A5 Session C 範圍:T9-T14 共 6 FE task + T15 task arc 收口 SUMMARY;預估 ~2d。


§1

交接 prompt 本體(從此貼到新 session)

我要進 SSP 匯入匯出 Phase 2 / A5 Session C — FE 實作(/module-frame/import-excel
路由 + 9 sheet preview + unmatched 三路徑 UI + InlineCreateDialog + fuzzy
badge + i18n + manual smoke)+ task arc 收口 SUMMARY。

A5 是「中型」phase(design + plan);Session A docs shipped、Session B BE
shipped、Session C FE + 收尾。

範圍簡述
========

A5 Session C 主要在 compliance-manager-fe repo 工作(不在 BE)。共 6 FE task +
1 收尾 task,沿 plan §2 順序:

1. T9 service + Pinia store + router (~1h)
2. T10 上傳頁 + ImportExcelPreview.vue 骨架 (~1h)
3. T11 Sheet preview 元件 × 7 (~4h)
4. T12 UnmatchedRow + InlineCreateDialog + FuzzyBadge 共用元件 (~2h)
5. T13 Confirm flow + 確認 modal (~1h)
6. T14 i18n + UX polish + Manual smoke (~1.5h)
7. T15 A5 task arc 收口 SUMMARY (~1h)

切到 ~/Projects/Billows/Audit-Manager/compliance-manager-fe/ 新建 branch
`feature/ssp-import-export-phase2`(對齊 BE 命名)。

前置狀態
========

BE Branch: feature/ssp-import-export-phase2 (compliance-manager-be)
- A5 Session B 已 ship 5 個 BE commit:
  - 535b931 T1 schema 定稿
  - 5852cca T2 inline_creates + 4 domain service DI (含 T6 error code)
  - 56edd30 T3 _apply_decisions + _apply_content_overrides
  - 7ed9363 T4 confirm_import 整合 + atomicity
  - 6f926e0 T7 BE pytest (54 test)
- BE changelog: docs/changelog/2026-05-21-feat-ssp-excel-import-phase2-a5-be.md
- BE smoke:a2 + a3 + a4 + a5 共 273 test 全綠 0 regression

FE branch: 新建 feature/ssp-import-export-phase2 對齊 BE
- 沿用 compliance-manager-fe 既有 framework(Vue 3 + Vite + Pinia + Vue
  Router + PrimeVue 3.53)
- Service 繼承 BaseService.js
- i18n config/translations/<locale>/

BE API 對齊
============

`POST /ssp-excel-import/<parse_uid>/confirm` Schema 結構化(A5 T1 ship):

  {
    "decisions": [
      {
        "sheet": "devices" | "info_systems" | "leveraged" | "parties" | "controls",
        "row_idx": int,
        "action": "use_matched" | "use_existing" | "use_inline_new" | "skip_as_text",
        "matched_id_override": int | str | null,  // leveraged uses str UUID
        "inline_create_row_idx": int | null
      }
    ],
    "inline_creates": [
      {
        "row_idx": int,
        "entity_type": "device" | "information_system" | "org_unit" | "user",
        "payload": {
          // device: name / ip (必填) + os / device_type / status / purpose / ...
          // information_system: name (必填) + abbreviation / description /
          //   system_status / system_owner (int FK) / ...
          // org_unit: name (必填) + description / parent_id / tenant_id 自動帶
          // user: login_name / nickname / email (必填) + tel / job_title /
          //   tenant_id 自動帶 / org_unit_id / status
        }
      }
    ],
    "content_overrides": {
      "metadata": { "target_mf_name": "<new>", ... },
      "controls": {
        "AC-1": {
          "implementation": "<new control 層 statement>",
          "objectives": { "(a)": "<new>", "(b)": "<new>" }
        }
      }
    }
  }

`DELETE /ssp-excel-import/<parse_uid>` 已 ship (A2 ship;A5 T0.4 偏差確認)。
直接呼叫,回 {"parse_uid": "<uid>", "status": "discarded"}。

import_summary response 新增欄位 (A5 T4 + T7 ship):
- inline_created_devices / info_systems / org_units / users
- decision_applied_count
- skipped_as_text_count

已知限制(design §10.2.1)
==========================

A5 decisions 對 write-time FK 不直接 propagate(_write_all_data Step 7 by-key
對齊覆寫):

- ✅ inline_creates 正確寫入 tenant entity(atomicity 保證)
- ✅ import_summary stats 正確
- ✅ parsed_result mutation 套用後 FE 重讀 GET endpoint 可看到
- ⚠ 但實際 DB 寫入的 SSP item FK 仍由 orchestrator 決定(除非剛好同 ID)

→ Session C FE smoke 觀察是否影響用戶體驗,需 follow-up 評估
F-A5-decision-write-propagation。

開工 SOP
========

第一步:必讀文件(順序)

1. 本 handoff prompt(你正在看)
2. docs/features/FR-011.2-2605-ssp-import-export-phase2/design-A5.md
   - §3.2 FE 改動 file 清單
   - §4.1 Confirm Request Schema (BE 已 ship — FE 對齊 contract)
   - §4.3 FE parsed_result 編輯 state (localStorage)
   - §5 User Mental Walkthrough(FE 流程要對齊這份)
   - §6.2 FE 10 個 Acceptance Criteria
   - §10.1-10.2 偏差紀錄(含 known limitation)
3. docs/features/FR-011.2-2605-ssp-import-export-phase2/implementation-plan-A5.md
   - §0.6 FE base patterns verify (BaseService / Pinia / PrimeVue / i18n)
   - §2 Session C 6 task 完整細則
4. docs/features/FR-011.2-2605-ssp-import-export-phase2/handoff/2026-05-20-a5-a-to-b.md
   - 看 A5 Session A 結尾的 3 個關鍵拍板
5. docs/changelog/2026-05-21-feat-ssp-excel-import-phase2-a5-be.md
   - 看 BE ship 範圍 / API shape / 已知限制
6. ~/Projects/Billows/Audit-Manager/compliance-manager-fe/CLAUDE.md
   - FE 開發規範
7. ~/Projects/Billows/Audit-Manager/compliance-manager-fe/src/service/BaseService.js
   - BaseService extension pattern reference
8. (既有 service 範例) ~/Projects/Billows/Audit-Manager/compliance-manager-fe/src/service/oscal/
9. (既有 store) ~/Projects/Billows/Audit-Manager/compliance-manager-fe/src/store/modules/
10. (既有路由) ~/Projects/Billows/Audit-Manager/compliance-manager-fe/src/router/routes.js

讀完後給「我看完了,準備 T9 service + store」確認。

第二步:T9-T14 順序執行

按 plan §2 順序,每個 task 一個 commit:

T9: feat(fe): A5 T9 SspExcelImportService + Pinia store + router
T10: feat(fe): A5 T10 上傳頁 + ImportExcelPreview.vue 骨架
T11: feat(fe): A5 T11 7 個 sheet preview 元件
T12: feat(fe): A5 T12 UnmatchedRow + InlineCreateDialog + FuzzyBadge
T13: feat(fe): A5 T13 confirm flow + 確認 modal
T14: feat(fe): A5 T14 i18n + UX polish + manual smoke

每個 task 完成跑相關元件 verify + 手動 smoke 局部流程。T14 完成跑:
- 上傳 → 預覽 → 編輯 → unmatched 三路徑 → fuzzy override → confirm → 驗 DB
- 各種錯誤路徑(上傳錯 / parse 過期 / confirm 失敗)

第三步:T15 task arc 收口 SUMMARY

按 CLAUDE.md「做 summary 觸發完整收尾」段:
1. 跑全套 BE pytest 確認 0 regression(最後 sanity check)
2. 規範文件齊全度:BE changelog (Session B ship) + FE changelog 新寫
3. design §10.3 補 Session C FE 偏差
4. tracker README A5 row 改 BE+FE shipped
5. 對話歷史 dump 到 docs/conversation-history/<date>/ssp-import-export-phase2-A5/
6. 產 SUMMARY → docs/features/FR-011.2-2605-ssp-import-export-phase2/handoff/2026-05-XX-a5-SUMMARY.md

鐵律(沿 A0.1 + A1-A4 + A5 Session B 全部)
============================================

1. 顯式 git add <file>,禁 -am / -A — commit 前 git status --short 確認
2. jedi-oscal / jedi-auth 維持原版本(A5 不動套件 — design §2.3)
3. pyproject.toml dev-path 改動不該 commit
4. BE 不需重啟(Session C 是 FE 工作;FE Vite dev server 有 HMR)
5. DDD 嚴格分層(FE 邊界 — service 不直接訊息傳到 component;走 store)
6. 不寫 docstring / 註解除非真有 non-obvious 的 why
7. 開發完成不自動 commit — 等 user 明確指示
8. 重大決策 → docs/analysis/YYYY-MM-DD-<topic>.md
9. 重型 bug / 跨域問題 → docs/issues/pending/YYYY-MM-DD-<title>.md
10. Handoff 文件統一放 docs/features/<feature>/handoff/
11. 階段性 commit 不用問 (子 task / milestone 完成後 commit 直接做)
12. 對話歷史兩層目錄 (date / topic),不二次加工

Session C 預估規模
===================

- T9: ~1h (service + store + router)
- T10: ~1h (上傳頁 + tab shell)
- T11: ~4h (7 個 sheet preview 元件)
- T12: ~2h (3 個共用元件 — 含 InlineCreateDialog form 切換)
- T13: ~1h (confirm flow + modal)
- T14: ~1.5h (i18n + manual smoke)
- T15: ~1h (收尾 docs + SUMMARY + tracker)

總計:~2d / 6 個 FE commit + 1 個 docs 收尾 commit

不在 Session C 範圍
====================

- BE bug fix(除非 manual smoke 撞到 — 此時補 hotfix changelog type=fix)
- A5 cucumber(拍板跳過 — F-A5-cucumber follow-up)
- F-A5-decision-write-propagation 修正(Session C smoke 後評估)
- F-A5-user-invite-on-inline-create(follow-up;不在本 phase)
- A4 ship 的 reconciler / WriteStrategy / pipeline 行為改動(design §2.3 明確排除)

謝謝。

§2

收口清單(A5 B → C 端)

本 handoff prompt commit 後,新 session 接手即可:

  1. 讀 10 個必讀文件(design-A5 + plan-A5 + B→C handoff + BE changelog + 6 個 FE source code reference)
  2. T9-T14 順序執行 FE 實作(6 個 feat commit + 1 個 docs 收尾 commit)
  3. T15 A5 task arc 收口 → 產 A5 final SUMMARY(含 BE + FE 跨 repo)

接下來 user 可以選:

  • 直接 /clear 後新 session 貼上交接 prompt(切到 FE repo)
  • 暫停評估其他 priorities,A5 FE 之後再開