diff --git a/apps/api/src/services/awoooi_priority_work_order_readback.py b/apps/api/src/services/awoooi_priority_work_order_readback.py index 30e3347e5..1785e38e9 100644 --- a/apps/api/src/services/awoooi_priority_work_order_readback.py +++ b/apps/api/src/services/awoooi_priority_work_order_readback.py @@ -3079,6 +3079,7 @@ def _enrich_from_current_readbacks( or reboot_slo.get("safe_next_step") or "" ) + state["active_p0_projection_source"] = "reboot_auto_recovery_slo_scorecard" state["active_p0_readiness_percent"] = _int( reboot_slo.get("readiness_percent") or workbench_readback.get("current_p0_readiness_percent") @@ -4021,6 +4022,9 @@ def _set_rollups_and_summary( "active_p0_next_safe_action": str( state.get("active_p0_next_safe_action") or "" ), + "active_p0_projection_source": str( + state.get("active_p0_projection_source") or "" + ), "controlled_service_data_backup_readback_present": ( state.get("controlled_service_data_backup_readback_present") is True ), @@ -4143,6 +4147,9 @@ def _set_rollups_and_summary( "active_p0_next_safe_action": str( state.get("active_p0_next_safe_action") or "" ), + "active_p0_projection_source": str( + state.get("active_p0_projection_source") or "" + ), "active_p0_live_active_blockers": active_blockers, "controlled_service_data_backup_readback_present": ( state.get("controlled_service_data_backup_readback_present") is True diff --git a/apps/api/tests/test_awoooi_priority_work_order_readback_api.py b/apps/api/tests/test_awoooi_priority_work_order_readback_api.py index 21ad0b886..bc911ef20 100644 --- a/apps/api/tests/test_awoooi_priority_work_order_readback_api.py +++ b/apps/api/tests/test_awoooi_priority_work_order_readback_api.py @@ -665,6 +665,10 @@ def test_awoooi_priority_work_order_readback_routes_closed_backup_to_host_boot_a assert state["active_p0_next_safe_action"] == ( "rerun_reboot_event_detector_and_host_probe_verify_only_no_reboot" ) + assert ( + state["active_p0_projection_source"] + == "reboot_auto_recovery_slo_scorecard" + ) assert state["next_executable_mainline_state"] == ( "blocked_reboot_slo_scorecard_host_boot_and_windows99_verify_" "collection_not_ready" @@ -683,9 +687,17 @@ def test_awoooi_priority_work_order_readback_routes_closed_backup_to_host_boot_a assert payload["summary"]["active_p0_next_safe_action"] == ( "rerun_reboot_event_detector_and_host_probe_verify_only_no_reboot" ) + assert ( + payload["summary"]["active_p0_projection_source"] + == "reboot_auto_recovery_slo_scorecard" + ) assert payload["rollups"]["active_p0_slo_active_blocker_count"] == len( in_progress["evidence"]["active_blockers"] ) + assert ( + payload["rollups"]["active_p0_projection_source"] + == "reboot_auto_recovery_slo_scorecard" + ) assert payload["summary"]["next_executable_mainline_state"] == ( "blocked_reboot_slo_scorecard_host_boot_and_windows99_verify_" "collection_not_ready" diff --git a/docs/LOGBOOK.md b/docs/LOGBOOK.md index e29d02f2d..e841f14dc 100644 --- a/docs/LOGBOOK.md +++ b/docs/LOGBOOK.md @@ -54159,6 +54159,7 @@ production browser smoke: **完成內容**: - `awoooi-priority-work-order-readback` 已在 source 層補齊 P0-006 active blocker count、primary blocker、current phase、ETA / wait reason 與 next safe action projection;第一次 main push `12af61a58` 已進 Gitea main,但 CD `#4559` 被後續 metadata-only commit 取代,production readback 尚未出現新增欄位。 - 本段以最小 API source touch 固定 `active_p0_live_active_blocker_count` 以 live blocker list 為 canonical,避免 stale top-level count 遮蔽 priority work order 的下一步欄位,並重新觸發 production build/deploy。 +- 第二輪補上 `active_p0_projection_source=reboot_auto_recovery_slo_scorecard`,讓 production readback 可直接證明 active P0 欄位來自 reboot SLO scorecard projection。 **本地驗證結果**: - `DATABASE_URL=postgresql+asyncpg://test:test@localhost/test PYTHONPATH=apps/api python3.11 -m pytest apps/api/tests/test_awoooi_priority_work_order_readback_api.py apps/api/tests/test_reboot_auto_recovery_slo_scorecard_api.py -q -p no:cacheprovider`:`38 passed`。