From 4b5f8ea5375e68ebb9e597b8e5ba88a05e1a2431 Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 1 Jul 2026 12:50:53 +0800 Subject: [PATCH] fix(agent): prioritize harbor ai loop blocker --- .../awoooi_priority_work_order_readback.py | 19 +++++++--- ...awoooi_priority_work_order_readback_api.py | 35 +++++++++++++++++++ docs/LOGBOOK.md | 14 ++++++++ 3 files changed, 63 insertions(+), 5 deletions(-) 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 9b520ef96..43f55f88a 100644 --- a/apps/api/src/services/awoooi_priority_work_order_readback.py +++ b/apps/api/src/services/awoooi_priority_work_order_readback.py @@ -503,11 +503,6 @@ def apply_ai_loop_current_blocker_execution_queue( executor_readback: dict[str, Any], ) -> None: """Overlay the AI Loop current blocker queue onto the ordered work board.""" - if payload.get("status") != ( - "p0_006_blocked_harbor_registry_controlled_recovery_preflight" - ): - return - context = _dict(executor_readback.get("agent_consumption_context")) queue = list(_list(context.get("current_blocker_execution_queue"))) if not queue: @@ -515,6 +510,12 @@ def apply_ai_loop_current_blocker_execution_queue( first_item = _dict(queue[0]) blocker_id = str(first_item.get("blocker_id") or "") + if not _ai_loop_current_blocker_can_override( + status=str(payload.get("status") or ""), + blocker_id=blocker_id, + ): + return + controlled_recovery_package = str( first_item.get("controlled_recovery_package") or "" ) @@ -801,6 +802,14 @@ def apply_ai_loop_current_blocker_execution_queue( ) +def _ai_loop_current_blocker_can_override(*, status: str, blocker_id: str) -> bool: + if status == "p0_006_blocked_harbor_registry_controlled_recovery_preflight": + return True + if status == "p0_006_blocked_stockplatform_public_api_runtime_drift": + return blocker_id.startswith("harbor_110_") + return False + + def _harbor_registry_next_state(*, status: str, candidate_packaged: bool) -> str: if candidate_packaged and "upstream_502" in status: return ( 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 56bcdef74..c11806811 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 @@ -491,6 +491,41 @@ def test_awoooi_priority_work_order_readback_overlays_live_stockplatform_drift() ) +def test_awoooi_priority_work_order_ai_loop_overrides_stockplatform_drift_for_harbor_110_blocker(): + payload = load_latest_awoooi_priority_work_order_readback() + executor = load_latest_ai_agent_log_controlled_writeback_executor_readback() + + apply_stockplatform_public_api_runtime_readback( + payload, + _stockplatform_runtime_blocked(), + ) + apply_ai_loop_current_blocker_execution_queue(payload, executor) + + state = payload["mainline_execution_state"] + assert payload["status"] == ( + "p0_006_blocked_ai_loop_current_blocker_execution_queue" + ) + assert state["active_p0_state"] == ( + "blocked_ai_loop_current_blocker_execution_queue" + ) + assert state["next_executable_mainline_workplan_id"] == ( + "P0-006-AI-LOOP-CURRENT-BLOCKER-EXECUTION-QUEUE" + ) + assert state["stockplatform_public_api_live_readback_state"] == "blocked" + assert state["ai_loop_current_blocker_id"] == ( + "harbor_110_remote_ssh_publickey_auth_stalled" + ) + assert state["ai_loop_current_blocker_control_path_blocker"] == ( + "remote_ssh_server_accepts_key_then_session_timeout" + ) + assert payload["summary"]["ai_loop_current_blocker_id"] == ( + "harbor_110_remote_ssh_publickey_auth_stalled" + ) + assert payload["next_execution_order"][0].startswith( + "P0-006-AI-LOOP-CURRENT-BLOCKER-EXECUTION-QUEUE" + ) + + def test_awoooi_priority_work_order_readback_overlays_controlled_recovery_preflight(): payload = load_latest_awoooi_priority_work_order_readback() runtime = _stockplatform_runtime_blocked() diff --git a/docs/LOGBOOK.md b/docs/LOGBOOK.md index 8a0c1b38d..fe062dfde 100644 --- a/docs/LOGBOOK.md +++ b/docs/LOGBOOK.md @@ -1,3 +1,17 @@ +## 2026-07-01 — 12:50 Priority work order AI Loop blocker 優先權修正 + +**照主線修正的問題**: +- Production `/api/v1/agents/awoooi-priority-work-order-readback` 仍把 `p0_006_blocked_stockplatform_public_api_runtime_drift` 當第一訊號,`ai_loop_current_blocker_id=null`;但目前 main/CD 的實際阻塞是 Harbor deploy marker 被 110 SSH / Harbor registry blocker 擋住。 +- `apply_ai_loop_current_blocker_execution_queue` 原本只在 `p0_006_blocked_harbor_registry_controlled_recovery_preflight` 之後才 overlay;若 StockPlatform live drift 先寫入 status,AI Loop current blocker queue 就不會上到第一訊號。 +- 本次改成:當 status 是 `p0_006_blocked_stockplatform_public_api_runtime_drift` 且 AI Loop blocker 以 `harbor_110_` 開頭時,允許 AI Loop current blocker 覆蓋 priority board 的第一訊號;StockPlatform evidence 仍保留,但不再蓋住 Harbor/110 deploy blocker。 +- 新增測試固定此行為:先套 StockPlatform drift,再套 AI Loop executor,最後 status 必須是 `p0_006_blocked_ai_loop_current_blocker_execution_queue`,next execution order 必須從 AI Loop current blocker 開始。 + +**驗證**: +- `DATABASE_URL=... python3.11 -m pytest apps/api/tests/test_awoooi_priority_work_order_readback_api.py apps/api/tests/test_ai_agent_autonomous_runtime_control.py apps/api/tests/test_ai_agent_log_controlled_writeback_executor_readback_api.py -q`:`23 passed`。 +- `git diff --check`:通過。 + +**邊界**:只改 priority work order overlay 排序邏輯、測試與 LOGBOOK;未讀 secret / token / `.env` / raw sessions / SQLite / auth;未讀 authorized_keys 內容或 `.runner` 內容;未使用 GitHub / `gh` / GitHub API;未 workflow_dispatch;未重啟主機、未 restart Docker / Nginx / K3s / DB / firewall;未執行 runtime apply。 + ## 2026-07-01 — 12:38 110 SSH local metadata receipt 擴充 **照主線修正的問題**: