SSP OSCAL Alignment — Phase 1 + Phase 2 FINAL SUMMARY — 2026-05-25

項目 內容
Phase Phase 1 + Phase 2 COMPLETE
日期區間 2026-05-24(Phase 1 全日 + Phase 2 開工) ~ 2026-05-25(Phase 2 完工 + 收尾)
Branch(兩 repo 一致) feature/ssp-oscal-alignment
Phase 1 完成 Tasks 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 14(11 / 14)— 跳 Task 10 E2E / Task 13 套件進版
Phase 2 完成 Tasks 1, 2, 3, 4, 5A, 5B, 5C, 6, 7, 8, 9, 11A, 11B(13 / 12 — Task 11 拆兩段執行)
主專案 local commits 30(Phase 1: 14 + Phase 2: 14 + 收尾 hotfix: 2;全 local,未 push)
jedi-oscal local commits 18(Phase 1 全;Phase 2 + 收尾 hotfix 全在主專案)
主專案 working tree M pyproject.toml(Phase 1 Task 1 dev-only path dep,永遠不 stage;Task 12 Part 2 套件進版時才還原)
jedi-oscal working tree clean
Dev DB 4 新 OSCAL 表 + RLS (delimiter 修好) + 12 LA + 341 components + 0 inv_items;Docx import path 通;Excel import 走 legacy 412(見 §6.2)
下一步 Phase 3 / Phase 4(user 拍板「衝一下 3, 4」)— 詳見 2026-05-25-phase3-4-handoff.md;Task 12 Part 2 (jedi-oscal bump + push) 仍待 user 拍板

TL;DR — Phase 1 + Phase 2 達成

Phase 1(Foundation) — OLD 單一 SspSystemImplementationItemEntity 拆成 OSCAL-correct 3 entity(LeveragedAuthorization / Component / InventoryItem + M2M join),落地到 DB + jedi-oscal 套件 + 主專案 BE 全層。12 LA + 341 components migrate verified。18 主專案 callers refactor 完成,舊表 + 舊 M2M 全 DROP。

Phase 2(Import Pipeline 對接) — Import pipeline 拆出獨立 module domain/oscal/import_pipeline/(warnings collector / normalizer / bundle_restore / confirm_service 四檔);3 個 v3 write strategy(LeveragedWriteStrategy / ComponentWriteStrategy / InventoryItemWriteStrategy)落地;orchestrator 採 Minimal scope(只保留 leveraged reconcile);Docx adapter 加 adapt_to_bundle() 輸出 v3;Docx app service 走新 pipeline 全通;Task 11 cleanup 刪 5 src + 4 test 共 1057 LOC dead code。

⚠️ Excel parser gap(§6.2 / design.md §11.13) — Excel app service dispatch 落地但 parser 還沒輸出 v2-bundle dict shape,目前 Excel import 走 legacy path → 412。Phase 3 §3.X 接手

✅ Subagent-driven mode 跑通(13 個 Phase 2 task),review-after-implementer pattern 多次截到 spec drift(如 Task 11B reviewer 加 SourceTable enum)。


1. Phase 1 + Phase 2 Tasks 最終狀態

Phase 1(14 tasks)

# Task Status
1 主專案 pyproject.toml path dep ✅ 落地(dev-only, M pyproject.toml)
2-4 jedi-oscal PR-1/2/3(LA / Component / Inventory) ✅ SHIPPED
5 ParsedExcelEntityBundle restructure ✅ SHIPPED
6 DI container wire 3 services ✅ SHIPPED
7-9 DB Step 1-3(建表 / migrate / verify) ✅ SHIPPED
10 E2E 測試 SKIPPED(Phase 2 重設計,throwaway)
11A/B jedi-oscal cleanup + 主專案 refactor ✅ SHIPPED
12 DROP 舊表 + 舊 M2M ✅ SHIPPED
13 jedi-oscal bump + 推 Nexus + 主專案 pin 還原 DEFERRED to Task 12 Part 2
14 Mini-handoff ✅ SHIPPED (2026-05-24-phase1-COMPLETE-SUMMARY.md)

Phase 2(13 tasks)

# Task Status Commit
1 Pre-flight — parsed_result shape reference ✅ SHIPPED 6b577a55
2 ImportWarnings collector module ✅ SHIPPED aee0e991
3 ParsedBundleNormalizer + warnings emission ✅ SHIPPED ec9d3b20
4 SspImportConfirmService + bundle_restore ✅ SHIPPED f6069f83 + 901d3460
5A LeveragedWriteStrategy v3 ✅ SHIPPED dfdc6d98
5B ComponentWriteStrategy v3 ✅ SHIPPED d8c9a19d
5C InventoryItemWriteStrategy v3(含 M2M) ✅ SHIPPED d547f314
6 Orchestrator + leveraged_reconciler v3(Minimal scope ✅ SHIPPED 56f35d83
7 Excel app service wire ConfirmService ✅ SHIPPED(dispatch 落地 / parser gap 見 §6.2) f4cb9b10
8 CmmcSspAdapter.adapt_to_bundle 輸出 v3 ✅ SHIPPED e6bc9ede
9 Docx app service wire ConfirmService ✅ SHIPPED c681e3a8
11A 刪 v2 strategies + dataclasses + helpers + reconcilers ✅ SHIPPED 9165b866
11B Reviewer minor follow-ups(SourceTable enum / _strip_nulls DRY 等 7 點) ✅ SHIPPED 1e3abaee
12 Part 1 Changelog + Final SUMMARY + design §11 update + conversation extract ✅ SHIPPED(本文件)
12 Part 2 jedi-oscal 進版 + Nexus push + 主專案 pin 還原 PENDING user 拍板

Note:Plan 寫 Task 10 是 E2E pre-flight smoke,Phase 2 期間 user 拍板「重設計後寫」延到 Phase 3+ 一起做。Plan 也沒列 Task 11B(reviewer follow-up),實際是 Phase 2 review checkpoint 後自然產出的 minor cleanup。


2. 兩 repo commits 全清單

jedi-oscal(18 commits,baseline 6f04da7;Phase 1 期間 ship,Phase 2 全 0 commit)

Commit 摘要
ebadfe8 refactor(oscal): remove deprecated SspSystemImplementationItem (Task 11A)
ac1d860 fix(oscal): harden InventoryItem M2M contract (PR-3 follow-up)
2162af2 feat(oscal): add InventoryItemDomainService (PR-3 part 6)
646cc38 feat(oscal): add InventoryItem repo + M2M write path (PR-3 part 5)
1b22843 feat(oscal): add InventoryItemMapper + tests (PR-3 part 4)
c358d8e feat(oscal): add OscalInventoryImplementedComponent M2M ORM (PR-3 part 3)
9d0db75 feat(oscal): add OscalInventoryItem ORM (PR-3 part 2)
1281121 feat(oscal): add InventoryItemEntity + QueryEntity (PR-3 part 1)
29b3bf0 feat(oscal): add ComponentDomainService (PR-2 part 5)
f498af1 feat(oscal): add Component repo + impl (PR-2 part 4)
697a460 feat(oscal): add ComponentMapper + tests (PR-2 part 3)
fdfd317 feat(oscal): add OscalComponent ORM with partial index (PR-2 part 2)
157d2bc feat(oscal): add ComponentEntity + QueryEntity + enums (PR-2 part 1)
a748205 feat(oscal): add LeveragedAuthorizationDomainService (PR-1 part 5)
fed9970 feat(oscal): add LeveragedAuthorization repo + impl (PR-1 part 4)
773c5eb feat(oscal): add LeveragedAuthorizationMapper (PR-1 part 3)
bf12dc9 feat(oscal): add OscalLeveragedAuthorization ORM (PR-1 part 2)
ab66af0 feat(oscal): add LeveragedAuthorizationEntity + QueryEntity (PR-1 part 1)

主專案(28 commits,baseline d6fab20

Phase 1(14 commits)

Commit 摘要
dfefab08 docs(ssp-oscal-alignment): Phase 1 COMPLETE mini-handoff
af3b0952 SQL migration step 4 — DROP 舊表 + 舊 M2M(Task 12)
f9e6de75 chore — update stale comment after Task 11A provider removal
2776d151 Task 11A — remove deprecated system_implementation_item DI providers
94891eb3 Task 11B-3 — remove 3 backward-compat shims + migrate 11 tests
176c977b Task 11B-2 follow-up — migrate 3 context services props JSONB
7d1d0a76 Task 11B-2 — migrate app services + project layer
5eaee305 Task 11B-1 review — tighten LeveragedWriteStrategy except scope
8a81c221 Task 11B-1 — migrate write strategies from SspSystemImplementationItem
af0ea339 docs — Phase 1 Tasks 2-9 SHIPPED handoff
1f944e2a docs — design.md v1.1 → v1.2 §11 reconciliation
c5b43fbd Task 9 — SQL verification
567efe73 Task 8 — SQL migrate data
a9712a12 Task 7 — SQL create tables + RLS
2e6849fb Task 6 — DI wire 3 services
95e9efd2 Task 5 — ParsedExcelEntityBundle restructure

Phase 2(14 commits)

Commit 摘要
1e3abaee Task 11B — Phase 2.A/B reviewer minor follow-ups(7 點 cleanup)
9165b866 Task 11A — remove v2 strategies + dataclasses + helpers + reconcilers
c681e3a8 Task 9 — wire Docx app service through SspImportConfirmService
e6bc9ede Task 8 — CmmcSspAdapter.adapt_to_bundle outputs v3 bundle
f4cb9b10 Task 7 — wire Excel app service through SspImportConfirmService
56f35d83 Task 6 — orchestrator + leveraged_reconciler v3(Minimal scope
d547f314 Task 5C — InventoryItemWriteStrategy v3(M2M write)
d8c9a19d Task 5B — ComponentWriteStrategy v3(consume ParsedComponent, resolve LA ref)
dfdc6d98 Task 5A — LeveragedWriteStrategy v3
901d3460 Phase 2.A review — bundle_restore preserves reconciler fields + log orchestrator failures
f6069f83 Task 4 — SspImportConfirmService + bundle_restore
6b577a55 Task 1 — parsed_result shape reference
ec9d3b20 Task 3 — ParsedBundleNormalizer + warnings emission
aee0e991 Task 2 — ImportWarnings collector module

3. Dev DB 最終狀態(cmmgr@192.168.50.188:25432/guidant_ai_dev — 密碼請查 .env

oscal.ssp_leveraged_authorizations           rowsecurity=t   12 rows
oscal.ssp_components                          rowsecurity=t  341 rows  (164 hw + 165 system + 12 service)
oscal.ssp_inventory_items                     rowsecurity=t    0 rows  (Phase 3 Excel parser fix 後 Phase 2 confirm 流程才會寫入)
oscal.ssp_inventory_implemented_components    rowsecurity=t    0 rows  (M2M join)

舊表狀態(Phase 1 Task 12 DROP):

  • oscal.ssp_system_implementation_items → DROPPED
  • oscal.ssp_inventory_item_components (OLD M2M) → DROPPED

FK linkage:12/12 service components 全綁回 leveraged_authorizations.uid(Phase 1 migration 期)。

Note:Phase 2 完工但 ssp_inventory_items 仍 0 rows 是因 Phase 2 期間沒新 import;新 import 經 Docx flow 應能寫入,Excel flow 待 Phase 3 §3.X parser 對齊。


4. 行為差異對使用者影響

4.1 Docx import — 完整 v3 path 通

POST /api/1.0/ssp-docx-imports/parse + POST /api/1.0/ssp-docx-imports/<uid>/confirm

  • Parse phase 同時 emit ParsedSsp overlay(Stage 1 docx-import-parity caller 仍依賴)+ v2-bundle ParsedExcelEntityBundle(merged into parsed_result with schema_version="v2-bundle")。
  • Confirm phase:controls / parties write 維持既有 path;LA → Component → InventoryItem 走新 SspImportConfirmService.confirm()(bundle_restore → normalize → orchestrator → 3 write strategies)。
  • Bundle 失敗非 fatal — log warning + 422 fallback 不會 silent drop LA/Component data。

4.2 Excel import — 走 legacy path 拋 412(⚠️ Phase 3 §3.X 才能 close)

POST /api/1.0/ssp-excel-imports/.../confirm

  • App service dispatch logic 已落地(Task 7),但 parser 還沒輸出 schema_version="v2-bundle"
  • 結果:parsed_result.get("schema_version", "v1-ssp") == "v1-ssp" → 直接 raise PreconditionFailedError(GRC_DOCX_PARSE_JOB_LEGACY_SHAPE, 412)
  • 對使用者:Excel import flow 從「200 + 寫入舊表」變「412 提示重傳」。
  • Phase 3 §3.X 改 Excel parser 後恢復 200 + 寫入新 OSCAL-correct 表。

4.3 移除的 dead code

Phase 2 Task 11A 刪:

  • 5 個 src 檔(device_write_strategy.py / information_system_write_strategy.py / base.py AbstractSspComponentWriteStrategy / device_reconciler.py / information_system_reconciler.py
  • 4 個 test 檔(test_a4_write_all_data_pipeline.py / test_a4_reconciliation_device.py / test_a4_reconciliation_information_system.py / test_a4_boundary_cases.py
  • 3 個 v2 dataclass(ParsedDevice / ParsedInformationSystem / ParsedLeveraged

未來 caller 若 import 上述 symbol 會 ImportError — Phase 3+ 引用者請 migrate 到 v3 dataclass + ConfirmService。


5. 規範文件齊全度

項目 路徑 狀態
design.md v1.2 + §11 reconciliation(11 + 4 條 = 15 條 deviations) docs/features/FR-028-2605-ssp-oscal-alignment/design.md ✅ Phase 2 加 §11.12~§11.15
implementation-plan-phase1.md + SHIPPED markers docs/features/FR-028-2605-ssp-oscal-alignment/implementation-plan-phase1.md
implementation-plan-phase2.md docs/features/FR-028-2605-ssp-oscal-alignment/implementation-plan-phase2.md ✅(SHIPPED markers 略)
Phase 1 mini-handoff docs/features/FR-028-2605-ssp-oscal-alignment/handoff/2026-05-24-phase1-COMPLETE-SUMMARY.md
Phase 1+2 Final SUMMARY(本文件) docs/features/FR-028-2605-ssp-oscal-alignment/handoff/2026-05-25-phase1-phase2-FINAL-SUMMARY.md
Changelog (batch Phase 1+2) docs/changelog/2026-05-25-feat-ssp-oscal-alignment-phase1-phase2.md
Conversation history JSONL extract docs/conversation-history/2026-05-24/ssp-oscal-alignment-phase2/ ✅(7 個 .md)
Analysis 文件 design.md §11 涵蓋(不另寫)

6. 已知 follow-ups

⚠️ 3 個 Phase 2 收尾留下的 leftover 抽到 §8(L1 / L2 / L3)獨立列,下方是更早期的 follow-up 清單。

6.1 Production / API(Phase 3+ 處理)

  1. Excel parser v1→v2 gap(⭐ 最高優先 — Phase 3 §3.X):domain/oscal/parser/excel/cmmc_excel_parser.py 需輸出 parsed_result["schema_version"] = "v2-bundle" + components / leveraged_authorizations / inventory_items 三 list(mirror Docx Task 8 adapt_to_bundle)。改完 Excel import 從 412 變 200 + 寫入新表。
  2. _parsed_ssp_to_dict_overlay 仍存在於 Docx app service(Stage 1 docx-import-parity 留下的 ParsedSsp overlay logic)— Phase 4 FE preview UI 重設計後可考慮整段刪掉,直接吃 v2-bundle。
  3. 7 個 pre-existing pytest failures(orthogonal,不在 Phase 2 root cause 範圍)— Task 11A commit message 已記錄「pytest tests/ 跟 c681e3a8 HEAD 同 7 個 failures,無新 failure」。下個 maintenance window 處理。
  4. Phase 4 FE preview UI 重設計(design.md §4 / 5d 預估):preview 需顯示 ImportWarning chip(normalizer.py 已 emit warnings)+ LA / Component / InventoryItem 三 sub-panel;template-edit 5-tab 第四 tab 必須改讀新表 — 這是 user-facing demo readiness 的關鍵 phase(見 §9 demo gap)。
  5. OSCAL export endpoint(design.md Phase 5 / 5d 預估):round-trip verification 的最後一塊。

6.2 Phase 1 follow-ups(仍未處理,從 2026-05-24-phase1-COMPLETE-SUMMARY.md 延續)

  1. API contract implementation_type vs component_typeSspImportTemplateAppService._build_info_systems dict key 改了,Phase 3 e2e 要驗 Excel template 下游沒人依賴舊 key。
  2. project_device_route 410-Gone 未實作tests/test_c3_scope_migration.py::test_gone_response_uses_grc_error_code@pytest.mark.skip,獨立任務。
  3. Leveraged delete orphan service-Component:用戶刪 LA 時 linked Component 變 orphan(leveraged_authorization_uid 指向已刪 LA.uid)— Phase 4 FE 重設計時處理。
  4. AbstractSspComponentWriteStrategy.write() sys_impl_main_id dead param — Phase 2 Task 11A 刪 base.py 後此 follow-up 自動結案 ✅。

7. 部署 handover

7.1 Task 12 Part 2 — 套件進版 + 主專案 pin 還原(user 拍板才執行

兩 repo 都還 local,未 push。Push 需 user 明確指示(per CLAUDE.md「push 永遠要 user 明確指示」)。

執行步驟(user 拍板後):

# 1. jedi-oscal bump version
cd ~/Projects/Jedicogy/module/jedi-python-package/jedi-oscal
# 編輯 pyproject.toml: version = "0.0.18" → "0.1.0"
git add pyproject.toml
git commit -m "chore(jedi-oscal): bump 0.0.18 → 0.1.0 (OSCAL Component/LA/Inventory split)"
# push 到 Nexus(依套件 publish flow)

# 2. 主專案 pin 還原
cd ~/Projects/Billows/Audit-Manager/compliance-manager-be
# 編輯 pyproject.toml:
#   - line ~80 jedi-oscal pin: "^0.0.18" → "^0.1.0"
#   - line ~91 path dep 改回註解(dev-only)
poetry update jedi-oscal
# smoke:python main_app.py 8000 listening + DI 122 modules wired
git add pyproject.toml poetry.lock
git commit -m "chore(ssp-oscal-alignment): bump jedi-oscal 0.0.18 → 0.1.0 + restore pin"

# 3. 兩 repo push(user 明確指示後)
git push origin feature/ssp-oscal-alignment
cd ~/Projects/Jedicogy/module/jedi-python-package/jedi-oscal
git push origin feature/ssp-oscal-alignment

7.2 部署順序(兩 repo 同 deploy unit)

  1. jedi-oscal 0.1.0 推 Nexus(先)
  2. 主專案 deploy(pin 0.1.0 後)
  3. DB migration 已在 Phase 1 跑完(dev DB 確認 + staging / prod 上線時補跑 scripts/sql/2026-05-24-ssp-oscal-alignment-*.sql 4 個檔)

7.3 FE 對齊(提醒)

Phase 4 FE preview UI 是 Phase 1+2 ship 後的後續 task — FE repo 路徑 ~/Projects/Billows/Audit-Manager/compliance-manager-fe,建議切到 FE repo 開新 session 由 FE Claude 主導。Phase 1+2 本身沒動 FE,但 Excel import 412 行為差異會被 FE 既有 error toast 抓到。


7.4 收尾 Hotfix(2026-05-24 晚)

Phase 2 Task 12 Part 1 commit (2bd8e7b3) 之後,user 拉 docx import 跑端到端驗證,連續觸發兩個 latent bug:

Hotfix 1 — Bug A:docx confirm 對 module_frame source 沒建 SSP shell(ba0cdd7a

項目 內容
症狀 docx import 成功,但 template-edit「外部利用服務」tab 仍空白
Root cause _run_v2_bundle_confirm 只 handle source_type='project_ssp';module_frame branch ssp_id 留 None → SspImportConfirmService 拿不到 ssp_id 直接 skip LA/Component/Inventory writes
Fix 抽出 domain/oscal/service/ssp_shell_service.py(DDD domain-service 層,無 infra import;含 can_build / create_shell / resolve_existing_shell / ensure_shell);docx app service 新增 kwarg ssp_shell_service,module_frame branch 呼叫 ensure_shell() 取得 ssp_id 後才 delegate confirm_service
範圍 新檔 domain/oscal/service/ssp_shell_service.py;修 app/oscal/service/ssp_docx_import_app_service.py__init__ + _run_v2_bundle_confirm + 新 helper _derive_shell_description);Excel inline logic 不動(32 既有 tests 保留)
教訓 v3 wire-up 必須同時支援 superset / update / module_frame 三種 source_type;v2 → v3 過渡期 Excel/docx 流程 source_type 處理不對稱 → 留後門 latent bug

Hotfix 2 — RLS policy delimiter(d12bd705

項目 內容
症狀 Bug A 修完,docx confirm 第一次從 cm_app 真寫 4 張新表 → DataError: invalid input syntax for type integer: '/1/102/'
Root cause Phase 1 §1.2 spec RLS policy 寫 split by ,;實際 session_scopeapp.allowed_tenant_paths='/1/102/'(slash-delimited path)
Why latent Phase 1 Task 9 verify 用 cmmgr (superuser bypasses RLS) → false-positive ship;Bug A 沒 fix 時 confirm path 從沒實際 evaluate RLS
Fix DROP + recreate 4 policies (ssp_components_rls / ssp_leveraged_authorizations_rls / ssp_inventory_items_rls / ssp_inventory_implemented_components_rls) 改用 string_to_array(trim(both '/' from ...), '/')::integer[]
Migration scripts/sql/2026-05-24-ssp-oscal-alignment-fix-rls-delimiter.sql
教訓 未來新增 RLS policy 一律 cm_app verify(cmmgr superuser 等於沒測);session 變數格式跨套件假設要在 spec 明寫

完整 root-cause 寫在 design.md §11.16(RLS)+ 待補 §11.17(Bug A — 本文件下方第 12 段補入)。


8. 已知 Leftover(必須在 Phase 3/4 收掉)

⚠️ 3 個未收尾項目,Phase 3/4 接手者開工前先掃過

L1 — Task 12 Part 2:jedi-oscal 0.0.18 → 0.1.0 bump + Nexus push + 主專案 pin 還原

項目 內容
範圍 jedi-oscal 套件 pyproject.toml bump、Nexus push、主專案 pyproject.toml path-dep 還原為 pin ^0.1.0poetry update jedi-oscal、兩 repo git push
阻擋 user 拍板才執行 — 違反 CLAUDE.md「絕對禁止:自動執行套件發版」+「push 永遠要 user 明確指示」
時機 建議 Phase 3+4 全 ship 後一次性處理;中間 phase 還會改 jedi-oscal(特別 Phase 5 export)就再 bump 一次成本高
步驟 見 §7.1

L2 — Bug B:docx import 5 parties 全 decision=skip → 0 parties 寫入

項目 內容
症狀 user 用 docx import flow,diff stepper 顯示 5 parties,user 點確認後 0 parties 落到 DB → template-edit「責任單位 / 責任人員」tab 空白
推測 root cause FE diff stepper 預設 decision=skip 而不是 decision=accept;user 沒手動切換就直接送 confirm → BE 全 skip 是正確行為
待釐清 (a) FE 給的預設 decision 是哪個?(b) user 在 UI 上看到的有沒有預先 highlight?(c) BE response 顯示的 decision distribution 跟 user 看到的差異
行動 Phase 4 FE 重設計時 BE/FE 共查;BE 端不主動改行為(accept-by-default 風險:user 沒看 diff 就誤寫資料)

L3 — Bug C:v2-bundle confirm 路徑沒套 content_overrides

項目 內容
症狀 user 在 docx preview UI 改 component 類型 / LA 欄位 → submit 後 DB 仍是 parse 時原值
Root cause ssp_docx_import_app_service._run_v2_bundle_confirm 入口直接 dict_to_bundle(parsed_result["bundle"])沒套 content_overrides。對比 Excel side ssp_excel_import_app_service._apply_content_overrides 有完整 metadata / system_characteristic / sheet rows / controls overrides handling
範圍(fix outline) _run_v2_bundle_confirm 入口加 _apply_content_overrides_to_bundle() helper:拆 overrides 對 bundle.components / bundle.leveraged_authorizations / bundle.inventory_items 三 list 做 row-level update(mirror Excel _apply_content_overrides 的 sheet-row loop logic)
注意 Excel side override 是針對 parsed_result dict path(row_overrides[sheet_key][row_idx]);v2-bundle 已是 dataclass list → 設 idx-based mapping 或 uid-based mapping,需先決定
時機 Phase 4 開工時順手做(FE 改 preview 行為 → BE override path 一起對齊)

9. ⚠️ User-facing demo readiness gap

這段是 Phase 3/4 接手者必讀 — 解釋為何 Phase 1+2 完成 ≠ user 看得到 import 結果。

9.1 Phase 邊界對應 user-facing 問題

Phase 完成後 user 能做什麼 完成後 user 不能做什麼
Phase 1(DDD/DB foundation) 後台資料模型正確;無 user-facing 行為 看不到 component / LA / inventory tab 內容
Phase 2(Import pipeline 對接) docx import 把 LA + Component + InventoryItem 寫進新表;Excel import 412 提示重傳 template-edit 5-tab 還是舊架構,看不到新表內容
Phase 3(Excel/Docx 樣板重設計) Excel import 從 412 變 200 + 寫入新表 template-edit FE 還是舊架構,仍看不到
Phase 4(FE preview UI 重設計) template-edit 改讀新 ssp_components / ssp_leveraged_authorizations / ssp_inventory_items 表,user 看到 import 結果 OSCAL JSON export 還沒
Phase 5(OSCAL Export) ⏸ deferred 2026-05-25 完整 round-trip:import → edit → export OSCAL JSON

9.2 為何 Phase 2 完工 user 還是「空白」(template-edit 截圖驗證)

驗證 case:MF 62c31d47-a90e-40e0-98ae-cb0c164a8acc(SSP id=260)

後端 DB 真實狀態 FE template-edit 顯示
1 LA + 4 Components 寫入新表 「外部利用服務 (1)」(只看到 LA
「設備 (0)」(讀舊 jedi_device 概念表)
「資訊系統 (0)」(讀舊 jedi_information_system 概念表)

Root cause:template-edit 5-tab 仍是 Phase 0 設計(OLD 三族 entity device / information_system / leveraged);新表 ssp_components 沒有對應的 tab → 4 個 components 在 FE「不存在」。

驗證 query(密碼請查 .env):

-- 連 cmmgr@192.168.50.188:25432/guidant_ai_dev
SET app.is_super_admin='t';
-- LA 由 SSP id 查
SELECT id, uid, title FROM oscal.ssp_leveraged_authorizations WHERE ssp_id=260;
-- Components 同上
SELECT id, uid, title, component_type FROM oscal.ssp_components WHERE ssp_id=260;
-- 對比 FE 截圖 → 確認 BE 有資料,差距在 FE 沒讀

9.3 Acceptance criteria 分三層

條件 由哪個 phase 收
(a) BE 寫對 DB 4 新表有正確資料 + RLS 通過 Phase 1+2 ✅(已驗)
(b) UI 可看到 template-edit 改讀新 ssp_components / ssp_leveraged_authorizations / ssp_inventory_items;新 tab「元件 + 授權 + 資產」 Phase 4(最關鍵 demo gap)
(c) 完整 demo 流程 Excel import 也通(不只 docx)+ OSCAL JSON export Phase 3(Excel)+ Phase 5(export)

結論:要做 user-facing demo readiness,先做 Phase 4 收 demo gap;Phase 3 解 Excel import path 但不阻擋 docx demo;Phase 5 是 round-trip 收尾。


10. 開發流程觀察(subagent-driven mode retrospective)

本 task arc 全程採 superpowers:subagent-driven-development mode:

觀察 說明
Reviewer-after-implementer Task 4 / 11B 兩次抓到 spec drift(bundle_restore 漏 reconciler field / SourceTable enum 該加)— review 投資值得
Token budget Phase 2 13 task 全 subagent,主 thread token 用量明顯低於同等 monolithic session
Wall clock Task 5A/B/C 三 task 平行 dispatch(共用 v3 dataclass dep)— 比 sequential 快
Trap Task 6 plan 寫「filter components by type 再 dispatch reconciler」,第一次 dispatch implementer 照寫;review checkpoint 才提「reconciler 已 dead code,跳過更乾淨」→ 採 Minimal scope(§11.12)

Pattern baked into 後續 phase prompt:DB-touching / 大規模 refactor task 開工前,controller 親查 schema + sample data + 看既有 caller 慣例(trust-but-verify pre-flight),再寫 implementer prompt。


11. 給 Phase 3 / Phase 4 接手 session 的 prompt(直接複製貼)

詳細版本(含 Phase 4 優先建議 + Bug B/C 開工前必處理)見 docs/features/FR-028-2605-ssp-oscal-alignment/handoff/2026-05-25-phase3-4-handoff.md。下方為精簡版:

你接手 SSP OSCAL Alignment Phase 3 — Excel/Docx 樣板重設計。Phase 1+2 完整 SHIPPED(28 主專案 commits + 18 jedi-oscal commits,全 local)。請按以下順序讀文件:

1. docs/features/FR-028-2605-ssp-oscal-alignment/handoff/2026-05-25-phase1-phase2-FINAL-SUMMARY.md(本文件 — 5 分鐘)
2. docs/features/FR-028-2605-ssp-oscal-alignment/design.md §11.12~§11.15(Phase 2 reconciliation)— 重點 §11.13 Excel parser gap
3. docs/features/FR-028-2605-ssp-oscal-alignment/design.md §3 Phase 3 段(Excel/Docx 樣板重設計 4d)
4. domain/oscal/import_pipeline/normalizer.py(理解 v2-bundle dict shape)
5. domain/oscal/adapter/cmmc_ssp_adapter.py:adapt_to_bundle()(Docx 端 v3 輸出 reference)

開工前 pre-flight:
1. 兩 repo branch:
   git branch --show-current  # 預期 feature/ssp-oscal-alignment
   git -C ~/Projects/Jedicogy/module/jedi-python-package/jedi-oscal branch --show-current
2. Dev DB 確認 Phase 2 final state(密碼請查 .env):
   psql -h 192.168.50.188 -p 25432 -U cmmgr -d guidant_ai_dev -c "
   SET app.is_super_admin='t';
   SELECT
     (SELECT count(*) FROM oscal.ssp_leveraged_authorizations) AS la,
     (SELECT count(*) FROM oscal.ssp_components) AS comp,
     (SELECT count(*) FROM oscal.ssp_inventory_items) AS inv;"
   預期: la=12, comp=341, inv=0
3. Smoke:tail -50 log/app.log,預期無 Traceback;pytest tests/test_ssp_docx_import_app_service.py 應綠

Phase 3 §3.X 首要任務:改 Excel parser 輸出 v2-bundle dict shape,恢復 Excel import 從 412 變 200。

附錄 A — 路徑速查

用途 路徑
Spec v1.2 + §11 reconciliation 15 條 docs/features/FR-028-2605-ssp-oscal-alignment/design.md
Phase 1 plan docs/features/FR-028-2605-ssp-oscal-alignment/implementation-plan-phase1.md
Phase 2 plan docs/features/FR-028-2605-ssp-oscal-alignment/implementation-plan-phase2.md
Phase 1 mini-handoff docs/features/FR-028-2605-ssp-oscal-alignment/handoff/2026-05-24-phase1-COMPLETE-SUMMARY.md
Phase 1+2 Final SUMMARY(本文件) docs/features/FR-028-2605-ssp-oscal-alignment/handoff/2026-05-25-phase1-phase2-FINAL-SUMMARY.md
Phase 1+2 changelog docs/changelog/2026-05-25-feat-ssp-oscal-alignment-phase1-phase2.md
Conversation history docs/conversation-history/2026-05-24/ssp-oscal-alignment-phase2/
Import pipeline 新 module domain/oscal/import_pipeline/
新 entities(jedi-oscal) ~/Projects/Jedicogy/module/jedi-python-package/jedi-oscal/jedi_oscal/domain/entity/base/oscal_{leveraged_authorization,component,inventory_item}_entity.py
SQL migration 4 檔 scripts/sql/2026-05-24-ssp-oscal-alignment-*.sql