| 項目 | 內容 |
|---|---|
| Branch | feature/ssp-oscal-alignment(兩 repo 一致) |
| 起源 handoff | handoff/2026-05-25-bug-b-and-parties-stepper-handoff.md |
| 涵蓋 fix | Bug B 兩段(§11.22 FE store + §11.24 BE adapter)+ Issue 1(§11.23 FE PartyDiffCard 欄位) |
| Verify evidence | mf 368 (5eb137c8) responsible_parties 5 筆(1 org responsible-organization + 4 person system-user) |
| 接續 | Bug D(leveraged services 寫 1/4)→ 開新 handoff 2026-05-25-bug-d-leveraged-services-handoff.md |
Bug B 從 2026-05-20 Phase 1+2 SUMMARY §8 L2 第一次推測,到本次 2026-05-25 收尾,累計兩段 root cause + 一段 cross-source漏修。
症狀:docx confirm 後 BE log decision=skip ×5 → no parties marked use_docx → 0 parties to write。
Root cause:stores/sspDocxImportStore.js:initDefaultDecisions 對 added parties 留 action=null → buildConfirmPayload._safeAction(null)='skip' → 5 parties 全 skip。
Fix(commit FE f31d0cf):新增 _defaultPartyAction helper,per diff_status seed default:
added → use_docx(新 party 預設加入)gone → keep_current(既有 link 預設不動)conflict / changed / unchanged → skip(user 主動確認才覆寫)連帶 §11.23 Issue 1:PartyDiffCard.fields 從 4 欄擴 7 欄(補 title / address / telephone)+ formatValue telephone alias。
症狀:§11.22 fix ship 後 user retry,BE log decision=use_docx ×5 + parties_written=5(看起來成功),但 mf template-edit 仍 0 parties。DB 直查發現 oscal_parties 寫 5 筆但 oscal_responsible_parties link 一筆都沒建。
Root cause:module_frame_write_strategy._upsert_responsible_party:662-663:
if not role_id or not party_uid:
return # ← 空 role_id silent skip,無 raise / logwrite_parties:530 傳 role_id=parsed.role or "",parsed.role 來自 _dict_to_parsed_parties:1104 的 p.get("role")。docx party JSONB 由 _parse_party_table 抓,只 set name / title / address / telephone / email / party_type,沒 role → None → "" → silent skip。
Cross-source 漏修:Excel 端 2026-05-21 已修同一 bug(ssp_excel_import_app_service.py:1956-1968 註解清楚),但 docx 沒套。
Fix(commit BE fef5eecf):mirror Excel pattern,_dict_to_parsed_parties 加 default role:
party_type == "organization" → 'responsible-organization''system-user'write_parties 回傳的計數只算 oscal_parties 寫成功的 row,沒驗 oscal_responsible_parties link 建立。這是 silent-failure 計數,混淆 caller — 兩個 session 都被它誤導,把根因鎖在錯的地方。
下次寫類似 strategy method 時,計數 metric 必須 echo 最終 side-effect(兩張表都驗),不能 stop 在 silent-skip 之前。
| Repo | Commit | 內容 |
|---|---|---|
| BE | ba7885d4 |
docs: design §11.22 + §11.23 reconciliation(Bug B 第一段 + Issue 1) |
| BE | fef5eecf |
fix: _dict_to_parsed_parties default role + design §11.24(Bug B 第二段) |
| BE | 本 commit | docs: 本 SUMMARY + Bug D handoff |
| FE | f31d0cf |
fix: store _defaultPartyAction + PartyDiffCard.fields 擴展 + SspDocxImportPage 過時 comment |
push 狀態:BE 3 commits + FE 1 commit 待 push(等 user 拍板)。
[ssp-confirm] _filter_parties_for_write parties_decisions count=5 map={
'new-1628102bb960bfc8': 'use_docx', ... # 5 筆全 use_docx
}
[ssp-confirm] _filter_parties_for_write resolved 5 parsed parties to write
[ssp-confirm] calling ModuleFrameWriteStrategy.write_parties with 5 parties
to source_type=module_frame source_uid=5eb137c8-84b6-4894-b0dd-a25ae092a8d2
[ssp-confirm] strategy.write_parties returned parties_written=5
SET app.is_super_admin='t')SELECT id || ' role=' || role_id || ' party=' || party_uuid::text
FROM oscal.oscal_responsible_parties
WHERE context_type='module_frame' AND context_id=368;
-- 216 role=responsible-organization party=ecbe22dd-...
-- 217 role=system-user party=5a1c53b0-...
-- 218 role=system-user party=9c2c6408-...
-- 219 role=system-user party=f1d242db-...
-- 220 role=system-user party=9ef01730-...
-- (5 筆 — 1 org + 4 person)mf /template-edit 「責任單位 (1) / 責任人員 (4)」tab 顯示完整 — user 視覺確認 OK。
| 項目 | 處理 |
|---|---|
mf 367 (fc51dd08) 失敗 import 殘留 |
DB 寫了 5 個 oscal_parties (id 1266-1270) 但無 link。_upsert_party idempotent → 不會 duplicate。mf 367 留著無害(user 可手動刪) |
| Bug D — leveraged services 寫 1/4 | 開新 handoff 2026-05-25-bug-d-leveraged-services-handoff.md,下個 session 處理 |
jedi-oscal _upsert_responsible_party silent-skip pattern |
列入 jedi-oscal 進版時的 cleanup — 改 log.warning 比 silent return 安全 |
| Cross-source ParsedParty adapter 共用 helper | docx / Excel / 未來 OSCAL JSON 各自 build ParsedParty,沒共用 → 下次又會漏。列入 future refactor |
| 進版(L8 jedi-oscal Nexus + L9 BE/FE 版號對齊 v1.2.0) | User 拍板才做 |
if not X: return 是危險 silent-skip pattern:caller 100% 沒辦法察覺。jedi-oscal 進版時改 raise 或至少 log.warning。