Handoff Prompt — A3 Session B → Session C(implementation T0~T2)

使用方式:把下方「交接 prompt 本體」整段貼到新 session 即可接手。 前置狀態:Session B(writing-plans)完成;implementation-plan-A3.md shipped + 兩輪 plan review approved + user review GO;working tree 乾淨(除 pre-existing pyproject.toml + 既有 conversation-history zip 異動)。 Session C 任務:T0 implementer pre-flight verification + T1 抽 BaseReconciliationService / Person+OrganizationReconciler skeleton / ParsedParty 加欄位 + T2 門面化 + DI wiring → 4 個 commit(T0 併 T1)。


§1

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

我要進 SSP 匯入匯出 Phase 2 / A3 phase Session C — implementation T0+T1+T2。

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

Branch: feature/ssp-import-export-phase2(BE,33 commits 未 push)
- A0 / A0.1 / A1 / A2 都 shipped;A3 design + plan 已 ship(Session A + B)
- Session A + B 累計 3 commits:
  - 8e61def docs(ssp-import-export-phase2): A3 design.md — 共用 matcher 抽取(parties / org-units)
  - 6e0f103 docs(ssp-import-export-phase2): A3 design.md spec review fix — iteration 1
  - 479bc28 docs(ssp-import-export-phase2): A3 implementation-plan.md — 共用 matcher 抽取執行計畫
- 工具狀態:jedi-oscal 仍 path-dep;pyproject.toml dev-path 改動仍未 commit
- Test 基準:BE 既有 213 passed(A1 106 + A2 99 + party 8);A3 新 ~51 case 預計 ship 後達 ~264

A3 Session C 是 5 session 切分中的第 3 站,task:
  T0 implementer pre-flight verification(3 項)— 併入 T1 commit
  T1 抽 BaseReconciliationService + MatchMethod enum + _normalizers + PersonReconciler skeleton + OrganizationReconciler skeleton + ParsedParty 加欄位
  T2 PartyReconciliationService 改門面 + DI wiring + 既有 8 unit test 全綠保住
  預估 ~1d(C session 整段)

開工 SOP
========

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

1. docs/features/FR-011.2-2605-ssp-import-export-phase2/implementation-plan-A3.md
   ← A3 完整 plan(~860 行)— 直接照 T0 → T1 → T2 task 內 bite-sized step 開工
   ← 重點:T0 pre-flight 3 項 verify + T1.1~T1.8 七小段(含完整 code snippet)+ T2.1~T2.4
   ← 每 task 都有「規範遵守清單」+「Acceptance」要逐項勾
2. docs/features/FR-011.2-2605-ssp-import-export-phase2/design-A3.md
   ← A3 design 13 章 — implementer 對齊 §3.2 base class / §3.3 門面 / §4 ParsedParty / §5.3 normalizers / §6.4 DI wiring 用
   ← 開工瞬間若 plan 假設不符(method 改名 / shape 變)→ 主動修 design §11 reconciliation,不照舊硬幹
3. CLAUDE.md
   ← 「行為規範」段全部適用;特別注意 plan T7 收尾規範 + handoff 文件路徑(2026-05-20 新規)
4. domain/oscal/service/party_reconciliation_service.py(既有 97 行)
   ← T2 改門面的對象 — verify 既有 method 簽章與行為作為 T2 acceptance 對照組
5. tests/test_party_reconciliation_service.py(既有 8 case)
   ← T2 必綠 — 0 行測試 code 改動

讀完後給「我看完了,建議下一步 X」的簡短確認。

第二步:執行 T0 + T1 + T2

按 plan 三 task 順序:
  T0 implementer pre-flight verification
    0.1 verify PartyReconciliationService 既有實作未被改動
    0.2 verify A2 _confirm_*_flow 仍未呼叫 reconcile
    0.3 verify ParsedParty dataclass 既有欄位
    → 三項 verify 結果與 design 假設一致 → 進 T1(不需 standalone commit)

  T1 BaseReconciliationService + Reconcilers skeleton + ParsedParty 加欄位
    1.1 建 sub-folder + match_method.py(MatchMethod StrEnum 5 values)
    1.2 寫 _normalizers.py(TDD 13 case:_strip_plus_alias / _normalize_name / _strip_org_suffix)
    1.3 寫 base.py BaseReconciliationService[TParsed, TEntity](TDD 7 case 含 cache 行為)
    1.4 ParsedParty 加 match_method + match_confidence 欄位(既有 213 test 不破壞)
    1.5 寫 PersonReconciler skeleton(exact stage 完整,normalized/fuzzy 留 T4;TDD 4 case)
    1.6 寫 OrganizationReconciler skeleton(同上;TDD 5 case)
    1.7 補 __init__.py export
    1.8 commit T1(顯式 git add 11 個檔,禁 -A / -am)
       Commit message: feat(oscal): A3 T1 base + reconcilers skeleton

  T2 PartyReconciliationService 改門面 + DI wiring
    2.1 改門面(97 → ~30 行,公開 method 簽章不變)→ 既有 8 unit test 全綠
    2.2 DI wiring(Step 1b 必 verify auth_container import 已存在;plan 已標)
    2.3 寫門面 3 個 dispatch test
    2.4 commit T2
       Commit message: feat(oscal): A3 T2 facade + DI wiring

第三步:BE smoke + 提醒 user

T2 結束後 BE 重啟 smoke(plan T2.2 Step 3):
  lsof -ti:8000 | xargs kill -9
  set -a; source .env; set +a
  nohup poetry run python main_app.py > /tmp/a3-be-boot.log 2>&1 &
  sleep 5; tail -50 /tmp/a3-be-boot.log

若撞 jedi-issue GitLab env 問題 → partial smoke 接受(DI container build 不 wire error 即可)。

**T1 / T2 commit 完成都要明確提醒 user:BE 沒 hot reload,下次 manual 測必重啟。**

第四步:跨 session 接續

T2 commit 後產 handoff prompt 給 Session D(A2 串接 + fuzzy 演算法):
  docs/features/FR-011.2-2605-ssp-import-export-phase2/handoff/2026-05-XX-a3-session-C-to-D-implementation.md
然後給 user Session C SUMMARY,等 user GO 換 session D(T3 + T4)。

A3 Session A + B 已產出(參考)
==============================

design-A3.md(13 章)+ implementation-plan-A3.md(~860 行)+ 兩份 handoff
(brainstorm-kickoff / session-A-to-B-writing-plans)+ tracker README A3 row。

8 題 brainstorm 拍板摘要(出自 design §13):
  Q1 A — domain/oscal/service/reconciliation/ sub-folder
  Q2 B — 三態 matched/fuzzy/unmatched + fuzzy 必進 user 確認
  Q3 A — 直接切換,cucumber regression 守
  Q4 B — Normalize + email domain (person) / name prefix (org)
  Q4' A — Client-side filter(拉全 tenant list,A3 不動 jedi-auth)
  Q5 A — 不整併 issue 修補 B(role normalize)
  Q6 A — Strategy Pattern + Generic Base
  Q3' A — A3 順手串 A2 _confirm_*_flow

鐵律(沿用 A0.1 + A1 + A2 + Session A + B 全部)
================================================

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,純函式 helper / matcher 不接 DB
7. 不寫 docstring / 註解除非真有 non-obvious 的 why
   - A3 例外:BaseReconciliationService 4 hook + _get_or_load_candidates exception 行為兩處屬「non-obvious why」
8. Test 用 mock 包 logger 避開 jedi DBLogHandler 撞 SessionLocal=None;@transaction 用 patch_session_scope
9. plan 階段假設不準確時主動修 design.md (§11 reconciliation)
10. 跨 repo 切換時提醒 user:cucumber 在 compliance-manager-test repo,commit / branch 分開
11. 改 docx parser 既有行為 → cucumber regression 必跑 — 是 ship 必要條件(Session E T6 跑)
12. 重大決策 → docs/analysis/YYYY-MM-DD-<topic>.md(trade-off 取捨理由)
13. 重型 bug / 跨域問題 → docs/issues/pending/YYYY-MM-DD-<title>.md(不擠在 changelog)
14. Handoff 文件統一放 docs/features/<feature>/handoff/(CLAUDE.md 2026-05-20 新規)
15. brainstorm dump 留 Session E 收口才一次 dump 到 docs/conversation-history/<date>/ssp-import-export-phase2/
16. 階段性 commit 不用問(子 task 完成直接 commit)
17. Subagent dispatch prompt 必加「git add 顯式檔名,禁用 -am」(避免 sweep CLAUDE.md)

A3 phase 預估規模(剩餘)
========================

| Session | 範圍 | Task | 預估 |
|---------|------|------|------|
| C(self)| Implementation T0+T1+T2 | architecture 抽出 + 門面化 + DI | ~1d |
| D | Implementation T3+T4 | A2 串接 + fuzzy 演算法 | ~0.75d |
| E | Test + cucumber + 收尾 | T5 + T6 + T7 | ~1.25d |

剩餘總計:~3d

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

- 直接照 plan-A3 內 bite-sized step(TDD:write failing test → run FAIL → implement → run PASS → commit)
- T2 結束後 BE smoke + 提醒 user 重啟
- 不需 dispatch subagent — Session C 工作量在主 session 推得動
- 若 T1 / T2 撞 unexpected reality(method shape 改 / DI provider 不存在)→ 修 design-A3 §11 reconciliation

謝謝。

§2

收口清單(Session B 端)

本 handoff prompt + Session B SUMMARY commit 後,新 session 接手即可:

  1. 讀 5 個必讀文件(plan-A3 / design-A3 / CLAUDE.md / party_reconciliation_service.py / test_party_reconciliation_service.py)
  2. 執行 T0 + T1 + T2(plan 內含完整 code snippet)
  3. T2 結束後 BE smoke + 提醒 user 重啟
  4. 產 Session C → D handoff + Session C SUMMARY
§3

Session B 累計 commits(feature/ssp-import-export-phase2)

479bc28  docs(ssp-import-export-phase2): A3 implementation-plan.md — 共用 matcher 抽取執行計畫

外加本 handoff prompt + Session B SUMMARY commit。

§4

Session B 規範遵守