# 交接 Prompt — A1 完整 shipped，準備進下一階段（A2 / B1 / T7）

> **使用方式**：把下方「交接 prompt 本體」整段貼到新 session 即可接手。
> **前置狀態**：A1 BE+FE shipped（含 3 輪 UX polish）；可選下一階段。

---

## 交接 prompt 本體（從此貼到新 session）

```
我要接手 SSP 匯入匯出 Phase 2。A1（Excel 樣板下載）BE+FE 完整 shipped
（T0-T6 + 3 輪 UX polish），準備進下一階段。

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

Branch（兩 repo 同名）
- BE: feature/ssp-import-export-phase2（17 commits 未 push）
- FE: feature/ssp-import-export-phase2（2 commits 未 push）

測試: BE 106 unit test 全綠
工具狀態: jedi-oscal 仍 path-dep（Phase 2 整體完工再 bump Nexus）
pyproject.toml dev-path 改動仍在 working tree（不 commit）

A1 已 ship 範圍
- BE endpoint 兩個：
  * GET /api/1.0/module-frame/<uid>/ssp-import-template?mode=blank|filled  (S3)
  * GET /api/1.0/ssp-import-template?framework_version_uid=&mode=blank      (S1 訪談前 superset)
- FE 兩個下載點：列表頁右上 menu + MF template-edit 批次維護 menu
- 9 sheet 結構 + 6 lookup sheets + UX polish 完成
- TEMPLATE_VERSION = v1.1.0

開工 SOP
========

第一步：必讀文件（順序）

1. docs/conversation-history/2026-05-19/ssp-import-export-phase2-A1/SUMMARY-T6-final.md
   ← A1 task arc 完整收尾 SUMMARY（commits / 改動 / behavior / follow-ups）
2. docs/features/FR-011.2-2605-ssp-import-export-phase2/design-A1.md (v1.2)
   ← A1 完整 design，含 §15.1-15.3 reconciliation
   ← 特別看 §15.3 person role 跨域不一致 finding（A2 必看）
3. docs/features/FR-011.2-2605-ssp-import-export-phase2/README.md
   ← Phase 2 整體 tracker — A1 row 標 BE+FE shipped ✅
4. docs/issues/pending/2026-05-19-person-role-cross-domain-inconsistency.md
   ← A2 phase 開工必看 — Excel parser role enum validation 修補計劃 A

讀完後給「我看完了，A1 完整 shipped，建議下一步走 X」的簡短確認。

第二步：決定下一階段
====================

三個方向：

選項 A — A2 Excel Parser + 解析 API（中型，~2-3d）
  依賴 A1 已 ship；做 SSP 匯入流程下半段
  範圍：
  - 上傳 Excel + parse + parse_uid TTL（mirror docx 的 v2 import 流程）
  - 03_參與人員 role 強制 enum validation（issue 修補 A 必做）
  - 區分兩條 import flow：
    * Superset upload（訪談後上傳 framework_version-scoped 樣板）→ 建新 MF + 篩 subset profile
    * MF update upload（既有 MF 下載 filled 後上傳）→ 更新既有 MF
  - 對應 FE 入口（列表頁「從 Excel 建立」+ 批次維護「Excel 匯入更新」）
  - design + plan 要先寫

選項 B — B1 Docx 樣板 + generator 骨架（中型，~2d）
  可平行 A2；依賴 A0.1
  範圍：
  - SSP docx 匯出樣板（python-docx）
  - jedi-docx 整合（若已套件化）
  - 對齊 OSCAL responsible_party / system_implementation_item / control_implementation
  - 跟 A1 Excel 樣板對齊欄位（同樣 9 領域）

選項 C — T7 完整 E2E（小型，~0.5d）
  A1 收尾最後一塊；跨 compliance-manager-test repo
  範圍：
  - cucumber feature 兩 scenario（MF-scoped + FW-version-scoped 下載）
  - Playwright step + page object
  - openpyxl 驗 sheet 結構 / 黃底 / hidden cols / role enum
  - user 端配齊 GitLab env → 跑完整 BE smoke

建議順序
- A2 跟 T7 都依賴 A1 — 可選一個先做
- T7 是 A1 收尾驗收，不複雜；做完 T7 後 A1 才算 100%
- A2 是 Phase 2 主軸推進，工作量較大
- B1 跟 A1/A2 解耦，可平行

問我選哪個，等我說 GO 才開工。

第三步：依選擇走對應 SOP
========================

A2 SOP：
- 先讀 issue/pending/2026-05-19-person-role-cross-domain-inconsistency.md
  確認修補 A 範圍
- 開 phase docs（design-A2.md + implementation-plan-A2.md）
- 規格層面要釐清 superset upload vs MF update upload 兩條 flow 的差異
  - Superset：建 MF + profile（subset 篩選）→ 牽涉 profile 建立邏輯
  - MF update：對齊既有 MF 結構直接 upsert
- jedi-* 套件可能需動（jedi-oscal 加 profile 建立 helper？）— Plan 階段拍板

B1 SOP：
- 開 phase docs (design-B1.md + implementation-plan-B1.md)
- 確認 jedi-docx 套件狀態（已存在 / 待建）
- 對齊 A1 sheet 結構到 docx 段落結構

T7 SOP：
- 主要 repo 切到 ~/Projects/Billows/Audit-Manager/compliance-manager-test/
- BE repo user 端配齊 GitLab env 後做完整 smoke
- 對 BE 端只需把 changelog + tracker 標 T7 完成 + A1 fully shipped

Pre-flight verify（A2 開工前必做）：
- jedi-oscal profile 建立 path（有沒 ProfileService.create？）
- assessment_plan 跟 profile 的依賴關係
- ssp_docx_import_v2 流程結構（A2 mirror 該結構）
- compliance.module_frames + oscal.oscal_profiles 寫入順序

每項用具體 grep / read 命令在 implementation log 內列。

鐵律（沿用 A0.1 + A1 全部）
=============================

1. 顯式 git add <file>，禁 -am / -A — commit 前 git status --short 確認
2. jedi-oscal 維持 path-dep，不 bump 版本不推 Nexus（Phase 2 整體完工才 bump）
3. pyproject.toml dev-path 改動不該 commit
4. BE 重啟必 lsof -ti:8000 | xargs kill -9
5. 改 BE service code 後必提醒 user 重啟 — BE 沒 hot reload
6. DDD 嚴格分層 — Route 不碰 DB，App Service @transaction，Generator 純函式
7. 不寫 docstring / 註解除非真有 non-obvious 的 why
8. Test 用 mock 包 logger 避開 jedi DBLogHandler 撞 SessionLocal=None
9. T0/Pre-flight verify 結果不符 design 假設時主動修 design.md（不照舊硬幹）
10. 跨 repo 切換時提醒 user：FE / test repo 跟 BE 是不同 git repo，commit / branch 分開
11. design.md 加 §11 / §15 Reconciliation 段紀錄實作偏離原始 design 的條目
12. 重大決策 → docs/analysis/YYYY-MM-DD-<topic>.md（trade-off 取捨理由）
13. 重型 bug / 跨域問題 → docs/issues/pending/YYYY-MM-DD-<title>.md（不擠在 changelog）

A1 已知 contracts（A2 必看）
================================

API endpoints
~~~~~~~~~~~~~

MF-scoped (S3 場景)
  GET /api/1.0/module-frame/<uid>/ssp-import-template?mode=blank|filled&locale=
  Response: xlsx binary + Content-Disposition

FW-version-scoped (S1 訪談前 superset)
  GET /api/1.0/ssp-import-template?framework_version_uid=<uid>&mode=blank&locale=
  Response: xlsx binary

A2 需新加（建議）
  POST /api/1.0/ssp-import-template/upload  (上傳 xlsx → parse_uid)
  GET  /api/1.0/ssp-import-template/parse/<uid>  (取解析結果)
  POST /api/1.0/ssp-import-template/parse/<uid>/confirm  (確認匯入)

樣板版本 TEMPLATE_VERSION = v1.1.0
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

A2 parser 讀 00_說明 sheet R1 col B 取版本字串，做相容性判斷。

控制項 sheet 父子 row contract（A2 parser 必看）
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

父 row (control)：statement_id 空 / hidden + control_id + control_name + 灰底 F2F2F2
子 row (AO)：statement_id=AO uid 字串 + control_id 同父 + objective_id (e.g. AC-1_smt.a)

Person role 強制 enum (A2 修補 A)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

03_參與人員 row 的 role 欄位匯入時 enum validation：
  valid = {"manager", "reviewer", "auditor", "viewer"}
  invalid → BadRequestError 或 verify UI 提示 user 修正

寫到 oscal_responsible_parties.role_id 仍是字串，但保證對齊系統 enum。

Hidden columns
~~~~~~~~~~~~~~

A2 parser 仍要解析這些欄位（雖然 user 看不到）：
- 01_基本資料: framework_version_uid (col E), profile_uid (col F)
- 07_控制項與AO: statement_id (col A) — 父子判斷用

VLOOKUP autofill cell（A2 parser 處理）
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

03/04/05 sheet 內 autofill column 在 blank mode 寫公式：
  =IFERROR(INDEX('_lookup_users'!B:B, MATCH($D2, '_lookup_users'!A:A, 0)), "")

A2 parser 用 openpyxl load_workbook(data_only=True) 讀 cached value，
拿到的應是 Excel 計算後純值（不必解析公式）。

已知限制 / risk
================

- BE 完整 boot 撞 jedi-issue GitLab env 問題（A0.1 follow-up #7，非 A1 引入）
- VLOOKUP autofill Excel 開檔可能不自動算（user skip）
- pre-existing test fail: test_write_parties_refreshes_existing_party_in_place（非 A1 引入）
- profile → controls 雙段查詢效能（NIST 800-53 1000+ controls）— 第一版接受

工具預期
========

- A2: 用既有 ssp_docx_import_v2 / module_frame_template_import_service 為 mirror reference
- B1: 用既有 python-docx pattern (mirror docx generation scripts)
- T7: 用既有 cucumber + Playwright + openpyxl pattern

謝謝。
```

---

## 收口清單

本 SUMMARY commit 後 A1 task arc 完整收口。後續：

1. 跨 repo push（BE + FE）+ open PR（user 決定時機）
2. T7 follow-up（跨 test repo）
3. A2 phase 起手（讀本 handoff prompt 進新 session）

## 速查：A1 完整 commit 鏈（17 BE + 2 FE）

### BE (17 commits, oldest → newest)

| Phase | Commit | 主題 |
|-------|--------|------|
| Setup | `b18db55` | A1 phase docs (design + plan) |
| T0 | `f59c4ff` | T0 verify 回填 design.md |
| T1 | `d9d54c2` | skeleton (route + app service + DI) |
| T2 | `f68525f` | generator base (sheet defs + styles + lookup) |
| T3 | `ffd5d63` | blank mode 主邏輯 + 30 tests |
| Mid | `f14a942` | T0-T3 partial summary |
| T4 | `c3de9fa` | filled mode 非控制項 6 領域 + 12 tests |
| T5 | `419907d` | 07_控制項與AO 父子 row + 6 tests |
| Mid | `46b8999` | T7 partial (BE smoke + changelog + tracker) |
| Mid | `c653f05` | BE partial ship 收口 SUMMARY |
| T6 BE | `3171116` | FW-version-scoped endpoint |
| T6 doc | `66d0d13` | Tracker README FE shipped |
| Fix r1 | `fbcf9f2` | UX polish round 1 (hidden / VLOOKUP / required / ref_docs) |
| Fix r2 | `690f25c` | UX polish round 2 (body 黃底 / recalc / role enum) |
| Fix r3a | `faade8d` | 黃底 cell + border |
| Fix r2.5 | `b6b4870` | 跨域 role finding (design + issue) |
| Fix r3b | `2b1e93c` | 黃底範圍限縮 filled rows |
| Final | (本 SUMMARY commit) | T6 final 收口 SUMMARY + round 3 changelog |

### FE (2 commits)

| Commit | 主題 |
|--------|------|
| `e0ff8f1` | T6 FE 兩個下載點 + dialog 元件 |
| `00b6662` | T6 fix-1 Dialog 框架名跑版 改 stack |
