交接 Prompt — A1 完整 shipped,準備進下一階段(A2 / B1 / T7)

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


§1

交接 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

謝謝。

§2

收口清單

本 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)
§3

速查: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