使用方式:把下方「交接 prompt 本體」整段貼到新 session 即可接手。 前置狀態:A1 BE+FE shipped(含 3 輪 UX polish);可選下一階段。
我要接手 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 完整收口。後續:
| 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 |
| Commit | 主題 |
|---|---|
e0ff8f1 |
T6 FE 兩個下載點 + dialog 元件 |
00b6662 |
T6 fix-1 Dialog 框架名跑版 改 stack |