Handoff Prompt — A5 Session A → B(design + plan ship → BE 實作開工)

使用方式:把下方「交接 prompt 本體」整段貼到新 session 即可接手。 前置狀態:A5 Session A docs shipped (5d979bf);working tree 乾淨(除 pre-existing pyproject.toml dev-path + 2 個 zip + 2 個刪除)。 A5 BE 範圍:T1-T8 共 8 個 task;預估 ~1.5d;交付 1 個主要 feat changelog + 7-8 個 BE commit。


§1

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

我要進 SSP 匯入匯出 Phase 2 / A5 Session B — BE 實作(confirm schema 定稿 + inline_creates handling + DELETE endpoint + content_overrides + pytest)。

A5 是「中型」phase(design 段落 + plan,不獨立 brainstorm);Session A 已 ship design + plan。

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

A5 Session B 只做 BE 工作,不動 FE。共 8 個 task,沿 plan §1 順序執行:

1. **T0 pre-flight verify** (6 個 verify 項;落地偏差進 design §10)
2. **T1 Confirm Request Schema 定稿** (api/oscal/serializers/ssp/ssp_excel_import.py)
   - 新增 InlineCreateSchema (row_idx / entity_type / payload)
   - 新增 DecisionSchema (sheet / row_idx / action / matched_id_override / inline_create_row_idx)
   - 改 SspExcelImportConfirmRequestSchema 含 3 個結構化欄位
3. **T2 _apply_inline_creates helper + 4 domain service DI** (app + di_containers)
   - 注入 device / information_system / org_unit (jedi-auth) / user (jedi-auth) 4 個 domain service
   - 寫 _apply_inline_creates(inline_creates, user_context, tenant_id) -> dict[row_idx, ...]
4. **T3 _apply_decisions + _apply_content_overrides** (沿 A4 _iter_paired by-key pattern)
5. **T4 confirm_import 整合 + transaction 保證** (整段 @transaction,rollback safety)
6. **T5 DELETE /ssp-excel-import/<parse_uid> endpoint** (沿 docx discard_parse pattern)
7. **T6 Error code 新增** (依 T0.5 verify 結果定序號)
8. **T7 BE Pytest 補齊** (~44 個新 a5 test)
9. **T8 Session B 收尾** (changelog feat + handoff B→C)

ship 後 BE 可獨立 smoke test (curl / postman),Session C (FE) 才是 user-facing 完整。

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

Branch: feature/ssp-import-export-phase2 (BE)

A5 Session A docs shipped:
- 5d979bf docs(ssp-import-export-phase2): A5 Session A design + plan
  ├── design-A5.md (~340 行, 12 段含 mental walkthrough §5 / BE AC §6.1 / T0 verify §9)
  └── implementation-plan-A5.md (~400 行, 15 task / 3 session)

A4 前置狀態 (Session F 已 ship):
- 6f6b663 docs(ssp-import-export-phase2): A4 Session F / T11 收尾 - SUMMARY + tracker + T9 changelog
- 600f50a test(oscal): A4 T9 unit + integration tests 補齊 boundary case
- a3+a4+a2 ssp_excel 累計 282 test 全綠
- jedi-oscal 仍 path-dep;pyproject.toml dev-path 改動未 commit (沿 A4 慣例)

User 拍板的 3 個關鍵決策 (Session A 期間,已寫入 design §12.1):
1. Inline 新建時機: Confirm 階段 BE 一次處理 (原子性最強)
2. Fuzzy match UI: 預設 auto-accept + badge + user override
3. FE 路由: 新建 /module-frame/import-excel 獨立頁面

開工 SOP
========

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

1. 本 handoff prompt(你正在看)
2. docs/features/FR-011.2-2605-ssp-import-export-phase2/design-A5.md
   - §2 Scope (in/out + 4 follow-up + 3 明確排除)
   - §3.3 BE App service 內部結構 (confirm_import 新 flow 7 step)
   - §4 Data Structures (3 個 Schema + import_summary 擴張 + FE localStorage shape)
   - §5 User Mental Walkthrough (理解 BE return 給 FE 用的 contract)
   - §6.1 BE 10 個 Acceptance Criteria
   - §9 Pre-flight Verification (6 項;T0 必驗)
   - §10 Reconciliation 預留段 (落地偏差進這)
3. docs/features/FR-011.2-2605-ssp-import-export-phase2/implementation-plan-A5.md
   - §0 T0 pre-flight (6 verify 項,每項 grep 指令給好了)
   - §1 Session B 8 task 完整細則
   - §3 CLAUDE.md 規範對應 Checklist
   - §4 Risk / Rollback
   - §5 Migration 順序
4. docs/features/FR-011.2-2605-ssp-import-export-phase2/handoff/2026-05-20-a4-SUMMARY.md
   - 看 A4 ship 的 19 個 dep 注入結構 (A5 要再加 4 個 → 23 個)
   - 看 A4 _write_all_data 8-step pipeline (A5 confirm_import 在 step 4 call it)
   - 看 _iter_paired by-key 對齊 helper (A5 _apply_decisions 沿用)
5. docs/changelog/2026-05-20-feat-ssp-excel-import-phase2-a4-write-pipeline.md
   - A4 Session E ship 紀錄;看 7 條 §11.1 偏差 pattern (Session B 偏差會寫類似)
6. api/oscal/serializers/ssp/ssp_excel_import.py (既有 schema 看 line 47-65)
7. api/oscal/serializers/ssp/ssp_docx_import.py (對齊 docx ConfirmRequestSchema pattern;A5 schema 沿用 use_kwargs)
8. api/oscal/routes/ssp/ssp_docx_import_route.py (對齊 DELETE 端點 + discard_parse pattern)
9. app/oscal/service/ssp_excel_import_app_service.py
   - 看 A4 ship 後 confirm_import 簽章 + _write_all_data + 既有 _update_parsed_result_with_reconcile (T3 套類似 by-key pattern)
10. di_containers/oscal/oscal_containers.py
    - 看 A4 ship 的 19 個 dep wiring (line 250+ 區段;A5 加 4 個 domain service)

讀完後給「我看完了,準備 T0 pre-flight」確認。

第二步:T0 pre-flight Verification (~30-45 min)

跑 plan §0 的 6 個 verify 指令並把結果摘要記下;如有偏差直接補進
design §10.1 (Session A 已預留段落):

T0.1 既有 confirm test 盤點:
  grep -rn "SspExcelImportConfirmRequestSchema\|decisions.*overrides" api/oscal/ app/oscal/ tests/

T0.2 4 個 domain service .add() 簽章:
  - DeviceDomainService.add: domain/device/service/
  - InformationSystemDomainService.add: domain/compliance/...
  - OrgUnitDomainService.add: ~/Projects/Jedicogy/.../jedi-auth/
  - UserDomainService.add + send_invite flow

T0.3 content_overrides overlay timing:
  - A4 _dict_to_* helper 在 _write_all_data step 3 跑
  - A5 _apply_content_overrides 必須在 step 3 之前蓋掉 parsed_result

T0.4 DELETE pattern:
  grep -A 20 "def discard_parse" app/oscal/service/ssp_docx_import_app_service.py

T0.5 Error code 序號 (400 / 409 / 412):
  grep -E "GRC_(400|409|412)" common/code/grc_error_code.py | sort -t_ -k2 -n
  記下最大序號,A5 從下一個開始

T0.6 FE 不在 Session B 範圍 — skip (Session C 才驗)

T0 結束給 user 一份偏差摘要,user 拍板後才進 T1。

第三步:T1-T8 順序執行 (~1.5d)

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

T1: feat(oscal): A5 T1 confirm request schema 定稿
T2: feat(oscal): A5 T2 inline_creates handling + 4 domain service DI
T3: feat(oscal): A5 T3 _apply_decisions + _apply_content_overrides
T4: feat(oscal): A5 T4 confirm_import 整合 + atomicity 保證
T5: feat(oscal): A5 T5 DELETE /ssp-excel-import discard endpoint
T6: 併 T2/T5 commit (error code 小範圍)
T7: test(oscal): A5 T7 unit + integration tests (~44 個 a5 test)
T8: docs(ssp-import-export-phase2): A5 Session B 收尾 - changelog + handoff B→C

每個 task 完成跑相關 test (不一定全套,T7 才全套);T7 完成跑:
  poetry run pytest tests/test_a*_*.py tests/test_ssp_excel_import_app_service.py -q

驗收 a2+a3+a4+a5 全綠 (預期 ~326 個)。

第四步:Session B 收尾 (T8)

按 CLAUDE.md「做 summary 觸發完整收尾」段:
1. 跑全套 BE pytest 確認 0 regression
2. 寫 BE changelog: docs/changelog/2026-05-21-feat-ssp-excel-import-phase2-a5-be.md
   (type=feat,含 commit chain + 行為差異 + T0 偏差段)
3. design §10 reconciliation 補 Session B 落地偏差 (T0 + 實作期)
4. tracker README A5 row 補 BE shipped 狀態 (FE 留空等 Session C)
5. 寫 Session B → C handoff prompt:
   docs/features/FR-011.2-2605-ssp-import-export-phase2/handoff/2026-05-21-a5-b-to-c.md
   (新 session 接 FE 工作)
6. commit Session B 收尾 docs

第五步:交接 Session C

Session C 是 FE 實作 + A5 task arc 收口 SUMMARY (不在 Session B 範圍)。
給 user 選 partial smoke (BE only) 或 直接交接 Session C。

鐵律 (沿 A0.1 + A1 + A2 + A3 + A4 全部)
==========================================

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 重啟必 lsof -ti:8000 | xargs kill -9 (T0-T7 補 test 不需重啟;T7 跑 pytest 不接 BE process)
5. 改 BE service code 後必提醒 user 重啟 — BE 沒 hot reload
6. DDD 嚴格分層 — Route 不碰 DB,App Service @transaction,Repo 用 BaseRepoImpl
7. 不寫 docstring / 註解除非真有 non-obvious 的 why
8. Test 用 mock 包 logger 避開 jedi DBLogHandler 撞 SessionLocal=None
   patch path: `app.oscal.service.ssp_excel_import_app_service.logger`
9. T0 / T1-T8 期間若發現新偏差 → 補 design §10.1
10. 重大決策 → docs/analysis/YYYY-MM-DD-<topic>.md
11. 重型 bug / 跨域問題 → docs/issues/pending/YYYY-MM-DD-<title>.md
12. Handoff 文件統一放 docs/features/<feature>/handoff/
13. 階段性 commit 不用問 (子 task / milestone / changelog / issue 完成後 commit 直接做)
14. Subagent dispatch prompt 必加「git add 顯式檔名,禁用 -am」(本 Session 不需 subagent — 8 task 順做)
15. 套件異動需 user 拍板 — A5 design §2.3 已明確排除,不會動套件
16. Confirm endpoint 整段 @transaction — inline_create + write_all_data 必須 atomic
17. 4 個 inline create domain service .add() 必須驗簽章可接 @transaction scope (T0.2)

Session B 預估規模
==================

- T0: ~30-45 min (6 verify 項;偏差摘要)
- T1: ~30 min (schema 結構化)
- T2: ~1h (4 domain service DI 加 + helper 寫)
- T3: ~45 min (2 個 helper;沿 A4 by-key pattern)
- T4: ~1h (confirm_import 串 + atomicity test)
- T5: ~30 min (DELETE endpoint + discard_parse method)
- T6: ~15 min (error code,併 T2/T5)
- T7: ~2h (~44 個 pytest)
- T8: ~30 min (收尾 docs + handoff B→C)

總計:~1.5d / 5-6 個 BE commit + 1 個 docs 收尾 commit

不在 Session B 範圍
====================

- T9-T14 FE 工作 (Session C:路由 + Vue 元件 + Pinia + i18n + manual smoke)
- T15 A5 task arc 收口 SUMMARY (Session C 末尾才做)
- FE smoke test (BE smoke 用 curl 即可)
- A5 cucumber (拍板跳過 — F-A5-cucumber follow-up)
- 任何 jedi-* 套件改動
- A4 ship 的 reconciler / WriteStrategy / pipeline 行為改動 (design §2.3 明確排除)

謝謝。

§2

收口清單(A5 A → B 端)

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

  1. 讀 10 個必讀文件(handoff + design-A5 + plan-A5 + A4 SUMMARY + A4 changelog + 6 個 source code reference)
  2. T0 pre-flight verify 6 項(落地偏差進 design §10.1)
  3. T1-T8 順序執行 BE 實作(5-6 個 feat/test commit + 1 個 docs 收尾 commit)
  4. Session B 收尾 → 產 B → C handoff(交接 FE 工作)

接下來 user 可以選:

  • 直接 /clear 後新 session 貼上交接 prompt
  • 暫停評估其他 priorities,A5 BE 之後再開