Bug O 已完工。收尾報告 docs/features/FR-028-2605-ssp-oscal-alignment/handoff/2026-05-25-bug-o-FIXED-SUMMARY.md,changelog docs/changelog/2026-05-25-feat-bug-o-diff-stepper-4key-tabview.md,design spec 更新 design.md §11.34(含 5 教訓 + commit clause)。
本檔保留作為「接手前 context handoff」歷史紀錄 — 內容反映開工前的設計假設,實作過程中有偏差(特別是 annotated key 改用 <key>_diff 獨立 suffix,跟原 plan 直接覆寫 raw list 的設計不同),偏差紀錄見 FIXED-SUMMARY + design.md §11.34 教訓段。
下期 follow-up:docs/features/FR-028-2605-ssp-oscal-alignment/handoff/2026-05-25-bug-p-q-r-parties-form-handoff.md(3 個本期 E2E 發現的 parties form bug)。
| 項目 | 內容 |
|---|---|
| 緣由 | User 對既有 mf 重跑 docx import 進 diff stepper,只看到 controls / objectives / parties 3 種 diff,缺:sc / components / leveraged_authorizations / inventory_items 4 key;跳過 diff 後 confirm 會 silently overwrite user 在 template-edit 已手動編輯的內容。並反映 UI stack 過長要改 TabView。 |
| Branch | feature/ssp-oscal-alignment(接續 H-N arc) |
| 主要 file | BE: ssp_docx_diff_service.py + ssp_docx_import_app_service.py confirm decisions 過濾;FE: sspDocxImportStore.js + 4 個新 *DiffSection.vue + DiffResolutionStep.vue TabView refactor |
| 接手前必讀 | 本文件自包含 — 按 §0 順序讀本檔 + design.md §11.34 spec + 既有 PartyDiffCard / ControlDiffCard pattern 即可。前提:H-N batch commit 必須先 push 完,working tree 乾淨才開工 |
| 預估時間 | 6-10 小時(跨 BE + FE,4 新 diff section + TabView refactor + tests) |
docs/features/FR-028-2605-ssp-oscal-alignment/design.md §11.34 — full spec(root cause / scope / 不在 scope / cross-references)docs/features/FR-028-2605-ssp-oscal-alignment/handoff/2026-05-25-bug-h-to-l-FULL-ARC-SUMMARY.md — 前一 session 累積 H-N 9 bugs 完整狀態(特別看「待 commit working tree」段確認 commit 完成)app/oscal/service/ssp_docx_diff_service.py — 既有 BE diff annotation 結構(controls + parties pattern)src/stores/sspDocxImportStore.js — FE diff store decisions 結構src/components/grc/ssp-docx-import-v2/diff/ 全資料夾:
DiffResolutionStep.vue (要 refactor 成 TabView)ControlDiffSection.vue / ControlDiffCard.vue (pattern 抄)PartiesDiffSection.vue / PartyDiffCard.vue (pattern 抄)src/components/grc/ssp/SspComponentsLeveragedInventoryTab.vue — template-edit 端的 3 sub-panel 結構(diff section 視覺對齊用)src/components/grc/ssp/SspBasicSection.vue — 受評標的 template-edit 端 8 欄位結構(SystemCharacteristicDiffSection 對齊)讀完後跑 §6 Pre-flight + §7 Verify H-N close → §3 開工順位。
User 對既有 mf 重 import docx 後進 Step「解決差異」(DiffResolutionStep):
目前看到:
[解決差異 step]
└─ 控制條文:X 已修改 ... (badge)
└─ Parties:Y 新增 ... (badge)
└─ ControlDiffSection(一串 ControlDiffCard)
└─ PartiesDiffSection(一串 PartyDiffCard)
期望看到:
[解決差異 step]
└─ <TabView>
├─ 控制條文 (X)
├─ 評估目標 (Y)
├─ 參與人員與單位 (Z)
├─ 受評標的 (1 if changed)
├─ 系統依賴元件 (W)
├─ 外部正式授權服務 (V)
└─ 資產清冊 (U)
</TabView>
每 tab header 含 changed/added/gone count badge;無 diff 的 tab disable 或隱藏。
# 看現有 BE diff_summary 確認 4 key 缺漏
PGPASSWORD='jedi@123!' psql -h 192.168.50.188 -p 25432 -U cmmgr -d guidant_ai_dev -A -c "
SET app.is_super_admin='t';
SELECT id, jsonb_pretty(parsed_result->'diff_summary') FROM oscal.ssp_docx_parse_jobs WHERE id=(SELECT MAX(id) FROM oscal.ssp_docx_parse_jobs);
"
# 預期看到 diff_summary 只有 controls / objectives / parties 3 key
# 缺 sc / components / leveraged_authorizations / inventory_items跳過 diff stepper(或 stepper 對 4 key 沒 expose 決策)後 confirm,BE write strategy 直接用 docx 端值覆寫既有 SSP — user 在 template-edit 已手動編輯的 leveraged / components / inventory / sc 被 silently overwritten。
try/except: pass silent failure 讓 bug 隱形數週。本 Bug O 寫 BE confirm decision filter 時必加 log.warning 而非默吞。ssp_docx_diff_service — 4 key annotation + summaryssp_docx_import_app_service.confirm_import decisions 過濾sspDocxImportStore decisions schema| 檔案 | 為何 read / 改 |
|---|---|
app/oscal/service/ssp_docx_diff_service.py (line 130+ for parties pattern) |
主改 — 加 4 key annotation + summary。Parties 是現有 pattern reference |
app/oscal/service/ssp_docx_import_app_service.py (confirm_import line 505~, _apply_v2_bundle_overrides line 820~) |
主改 — 接 4 個新 decision payload + filter parsed_result by decision before write |
app/oscal/service/ssp_import_confirm_service.py (if used in confirm path) |
確認 4 key write strategy 已 ship + 怎麼接 decision filter |
tests/test_ssp_docx_diff_service.py |
加 4 key annotation + summary test cases |
| 檔案 | 為何 read / 改 |
|---|---|
src/stores/sspDocxImportStore.js (line 19+ decisions struct) |
主改 — 加 4 sub-map + init + payload build |
src/components/grc/ssp-docx-import-v2/diff/DiffResolutionStep.vue |
主改 — TabView refactor wrap 既有 2 + 新 4 section |
src/components/grc/ssp-docx-import-v2/diff/PartyDiffCard.vue |
Pattern reference — 抄結構建 4 個新 card |
src/components/grc/ssp-docx-import-v2/diff/ControlDiffCard.vue |
同上 |
src/components/grc/ssp-docx-import-v2/diff/DiffSectionShell.vue |
看 section 統一外殼 pattern |
新檔:SystemCharacteristicDiffSection.vue / ComponentsDiffSection.vue / LeveragedAuthorizationsDiffSection.vue / InventoryItemsDiffSection.vue |
主要新增 |
src/components/grc/ssp/SspBasicSection.vue |
受評標的欄位結構參考 (8 fields) |
src/components/grc/ssp/SspComponentsLeveragedInventoryTab.vue |
3 sub-panel 結構參考(component_type 14 enum / LA fields / inventory fields) |
~/Projects/Billows/Audit-Manager/compliance-manager-fe/CLAUDE.md(per memory feedback_cross_repo_read_claude_md_first)— 特別「Add / Create Action Button Style」(per Bug L) + Loading / 等待狀態規範 + PrimeVue 3.53 quirks# 1. 兩 repo branch + working tree
git -C ~/Projects/Billows/Audit-Manager/compliance-manager-be branch --show-current
git -C ~/Projects/Billows/Audit-Manager/compliance-manager-fe branch --show-current
# 預期:兩個都 feature/ssp-oscal-alignment
git -C ~/Projects/Billows/Audit-Manager/compliance-manager-be status --short
# 預期:clean (H-N 已 commit + push);或只有 dev-only path dep pyproject.toml
git -C ~/Projects/Billows/Audit-Manager/compliance-manager-fe status --short
# 預期:clean
# 2. local vs origin
git -C ~/Projects/Billows/Audit-Manager/compliance-manager-be log origin/feature/ssp-oscal-alignment..HEAD --oneline
# 預期 0 commits ahead (H-N pushed)
git -C ~/Projects/Billows/Audit-Manager/compliance-manager-fe log origin/feature/ssp-oscal-alignment..HEAD --oneline
# 預期 0 commits ahead
# 3. BE / FE listener
lsof -t -i:8000 && echo "BE up" || echo "BE down — restart needed"
lsof -t -i:5180 && echo "FE up" || echo "FE down"
# 4. BE pytest smoke (含 Bug H-N 改動 verify still passing)
cd ~/Projects/Billows/Audit-Manager/compliance-manager-be
poetry run pytest tests/test_ssp_docx_import_app_service.py \
tests/test_ssp_docx_diff_service.py \
tests/test_docx_section_extractors.py \
tests/test_cmmc_ssp_adapter_v3_bundle.py \
tests/test_ssp_write_strategy.py \
tests/test_ssp_leveraged_app_service.py \
tests/test_system_characteristic_write_strategy.py -q
# 預期 ~200 passed# 6.1 Bug H-6 cleanup verify — 4 OSCAL 表 org_unit_id 應全 NULL
PGPASSWORD='jedi@123!' psql -h 192.168.50.188 -p 25432 -U cmmgr -d guidant_ai_dev -A -c "
SET app.is_super_admin='t';
SELECT 'parties' AS tbl, count(*) AS bad FROM oscal.oscal_parties WHERE org_unit_id IS NOT NULL
UNION ALL SELECT 'leveraged', count(*) FROM oscal.ssp_leveraged_authorizations WHERE org_unit_id IS NOT NULL
UNION ALL SELECT 'components', count(*) FROM oscal.ssp_components WHERE org_unit_id IS NOT NULL
UNION ALL SELECT 'inventory', count(*) FROM oscal.ssp_inventory_items WHERE org_unit_id IS NOT NULL;
"
# 預期 4 row all bad=0
# 6.2 Bug I verify — mf 372 / 373 應只剩 T6 LA (1 筆 MDR)
PGPASSWORD='jedi@123!' psql -h 192.168.50.188 -p 25432 -U cmmgr -d guidant_ai_dev -A -c "
SET app.is_super_admin='t';
SELECT mf.uid, COUNT(la.id) AS la_count
FROM public.module_frames mf
JOIN oscal.profiles p ON p.uid::text=mf.oscal_profile_uid
JOIN oscal.system_security_plans s ON s.profile_id=p.id
LEFT JOIN oscal.ssp_leveraged_authorizations la ON la.ssp_id=s.id
WHERE mf.uid IN ('2c4ba0b8-52e2-4e90-a8fc-df8dcf481002', 'b006fc6c-28ae-4190-bdab-d930903e6314')
GROUP BY mf.uid;
"
# 預期 2 row la_count=1feedback_no_branch_switch)feedback_stage_commit_no_ask)feedback_cross_repo_read_claude_md_first)feedback_be_restart_after_service_change)— BE diff service 改動需重啟:active-step 不是 :active-indexfeedback_no_chinglish)feedback_plan_vs_reality_verify_first)— BE diff annotation pattern 對 4 key 是否真適用,先實證再 planfeedback_subagent_explicit_git_add)handoff/2026-05-25-bug-o-FIXED-SUMMARY.md 短收尾報告(mirror 2026-05-25-bug-h-to-l-FULL-ARC-SUMMARY.md 樣式)leveraged_services key(已 Bug L 廢棄)template_module_frame_id entity field 沒 wire(Bug K1 留 follow-up)docs/conversation-history/ (H-N session 收尾時觸發)請閱讀交接文件,了解現況,並接手 Bug O 開發。
交接文件路徑:
docs/features/FR-028-2605-ssp-oscal-alignment/handoff/2026-05-25-bug-o-diff-stepper-expansion-handoff.md
按本檔 §0 接手讀序執行 — 必跑 §5 Pre-flight + §6 Verify H-N close →
§3 開工順位。注意 §2 前次教訓 + §7 行為規範。
前次 (Bug H ~ N) 已全 close + commit。本 Bug O 範圍:BE diff service
擴展 4 key annotation + FE store decisions 擴展 + 4 新 diff section 元件
+ DiffResolutionStep TabView refactor + BE confirm 接新 decisions filter。
依 §3 順序,第 2 步 enter plan mode 寫完整 implementation plan 給 user
approve 才開工。
H-N 改動清單(per 2026-05-25-bug-h-to-l-FULL-ARC-SUMMARY.md):
push 建議(per H-N SUMMARY §6):
Bug O 是 H-N 整段 arc 的第 10 個 follow-up,緣由是 user 對既有 mf 重 import docx 時的 diff stepper coverage gap — 跟 H-N 的「single import 完整 chain fix」是同 feature 不同 mode(update vs create)。
H-N arc 把 create mode 的 chain 全打通了(parties / sc / components / leveraged / inventory / cleanup / template SSP endpoint 全通),update mode 的 diff stepper 是另一條路 — diff service 只 cover 2 source(controls / parties)跟 4 種寫入 path(sc + components + leveraged + inventory)不對等。Bug O 補完。
完成後 docx import 整段 user-facing chain(create + update mode)就 complete v1 階段,可開始考慮 Phase 5 OSCAL Export deferred plan。