fix(api): normalize priority work order source truth
All checks were successful
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 24s
CD Pipeline / build-and-deploy (push) Successful in 9m37s
CD Pipeline / post-deploy-checks (push) Successful in 1m1s

This commit is contained in:
Your Name
2026-06-30 09:29:54 +08:00
parent a7e6de46aa
commit a4abc00d25
4 changed files with 181 additions and 14 deletions

View File

@@ -8,14 +8,18 @@ external SCM APIs.
from __future__ import annotations from __future__ import annotations
import json import json
import re
from datetime import datetime
from pathlib import Path from pathlib import Path
from typing import Any from typing import Any
from zoneinfo import ZoneInfo
from src.services.snapshot_paths import default_operations_dir from src.services.snapshot_paths import default_operations_dir
_DEFAULT_OPERATIONS_DIR = default_operations_dir(Path(__file__)) _DEFAULT_OPERATIONS_DIR = default_operations_dir(Path(__file__))
_SNAPSHOT_FILE = "awoooi-priority-work-order-readback.snapshot.json" _SNAPSHOT_FILE = "awoooi-priority-work-order-readback.snapshot.json"
_SCHEMA_VERSION = "awoooi_priority_work_order_readback_v1" _SCHEMA_VERSION = "awoooi_priority_work_order_readback_v1"
_SHA_RE = re.compile(r"^[0-9a-f]{40}$")
def load_latest_awoooi_priority_work_order_readback( def load_latest_awoooi_priority_work_order_readback(
@@ -117,26 +121,49 @@ def _enrich_from_current_readbacks(payload: dict[str, Any]) -> None:
runtime_sha = str( runtime_sha = str(
workbench_summary.get("production_deploy_runtime_build_commit_sha") or "" workbench_summary.get("production_deploy_runtime_build_commit_sha") or ""
) ).strip().lower()
runtime_short_sha = str( runtime_short_sha = str(
workbench_summary.get("production_deploy_runtime_build_commit_short_sha") or "" workbench_summary.get("production_deploy_runtime_build_commit_short_sha") or ""
) ).strip().lower()
desired_short_sha = str( desired_short_sha = str(
workbench_summary.get( workbench_summary.get(
"production_deploy_desired_main_api_image_tag_short_sha" "production_deploy_desired_main_api_image_tag_short_sha"
) )
or "" or ""
) ).strip().lower()
current_head = _dict(payload.setdefault("current_head", {})) current_head = _dict(payload.setdefault("current_head", {}))
current_head["latest_verified_worktree_base_sha"] = runtime_short_sha runtime_source_truth_available = _is_sha(runtime_sha)
current_head["latest_successful_deployed_source_sha"] = runtime_sha if runtime_source_truth_available:
current_head["latest_successful_deploy_marker"] = ( runtime_short_sha = runtime_short_sha or runtime_sha[:10]
f"production desired image tag {desired_short_sha}" desired_short_sha = desired_short_sha or runtime_short_sha
production_readback_id = f"production_readback:{desired_short_sha}"
production_subject = f"production desired image tag {desired_short_sha}"
current_head["gitea_main_sha"] = runtime_sha
current_head["latest_fetched_gitea_main_subject"] = production_subject
current_head["latest_source_readiness_cd_run_id"] = production_readback_id
current_head["latest_verified_worktree_base_sha"] = runtime_short_sha
current_head["latest_successful_deployed_source_sha"] = runtime_sha
current_head["latest_successful_deploy_marker"] = production_subject
current_head["latest_source_readiness_cd_run_status"] = (
"production_readback_verified"
)
current_head["latest_source_readiness_commit_sha"] = runtime_sha
state["updated_at"] = _taipei_now_iso()
state["current_main_cd_run_id"] = production_readback_id
state["current_main_cd_run_status"] = "production_readback_verified"
state["current_main_latest_source_sha"] = runtime_sha
state["latest_successful_deployed_source_sha"] = runtime_sha
state["reboot_drill_preflight_source_status"] = "production_endpoint_ready"
state["p0_004_template_copy_apply_gate_source_status"] = (
"production_endpoint_ready"
)
current_head["production_source_truth_available"] = runtime_source_truth_available
current_head["stale_current_head_metadata_normalized"] = (
runtime_source_truth_available
) )
current_head["latest_source_readiness_cd_run_status"] = (
"production_readback_verified"
)
current_head["latest_source_readiness_commit_sha"] = runtime_sha
current_head["no_matching_runner_visible"] = False current_head["no_matching_runner_visible"] = False
current_head["source_readiness_ci_fix_required"] = False current_head["source_readiness_ci_fix_required"] = False
@@ -276,6 +303,74 @@ def _enrich_from_current_readbacks(payload: dict[str, Any]) -> None:
"failed CD runs, and retired GitHub lanes must not reorder closed work." "failed CD runs, and retired GitHub lanes must not reorder closed work."
), ),
] ]
_set_rollups_and_summary(
payload=payload,
current_head=current_head,
state=state,
p0_004_ready=p0_004_ready,
p0_006_event_gated=p0_006_event_gated,
runtime_source_truth_available=runtime_source_truth_available,
runtime_sha=runtime_sha,
)
def _set_rollups_and_summary(
*,
payload: dict[str, Any],
current_head: dict[str, Any],
state: dict[str, Any],
p0_004_ready: bool,
p0_006_event_gated: bool,
runtime_source_truth_available: bool,
runtime_sha: str,
) -> None:
completed = _list(payload.get("completed_in_priority_order"))
in_progress = _list(payload.get("in_progress_or_blocked_in_priority_order"))
latest_source_sha = (
runtime_sha
if runtime_source_truth_available
else str(current_head.get("latest_successful_deployed_source_sha") or "")
)
active_blockers = _strings(state.get("active_p0_live_active_blockers"))
active_gap_count = _int(state.get("active_p0_immediate_apply_gap_count"))
payload["rollups"] = {
"completed_p0_count": len(completed),
"in_progress_or_blocked_count": len(in_progress),
"active_p0_immediate_apply_gap_count": active_gap_count,
"active_p0_event_gated_by_fresh_reboot_window_only": p0_006_event_gated,
"active_p0_live_active_blocker_count": len(active_blockers),
"p0_004_runtime_readback_ready": p0_004_ready,
"reboot_drill_preflight_runtime_readback_ready": (
state.get("reboot_drill_preflight_runtime_readback_state") == "ready"
),
"production_source_truth_available": runtime_source_truth_available,
"stale_current_head_metadata_normalized": runtime_source_truth_available,
"stale_cd_runs_reopen_closed_work": False,
"break_glass_reboot_drill_required": True,
}
payload["summary"] = {
"status": str(payload.get("status") or ""),
"active_p0_workplan_id": str(state.get("active_p0_workplan_id") or ""),
"active_p0_state": str(state.get("active_p0_state") or ""),
"active_p0_readiness_percent": _int(
state.get("active_p0_readiness_percent")
),
"active_p0_live_active_blockers": active_blockers,
"latest_successful_deployed_source_sha": latest_source_sha,
"latest_successful_deployed_source_short_sha": latest_source_sha[:10],
"latest_successful_deploy_marker": str(
current_head.get("latest_successful_deploy_marker") or ""
),
"next_executable_mainline_workplan_id": str(
state.get("next_executable_mainline_workplan_id") or ""
),
"next_executable_mainline_state": str(
state.get("next_executable_mainline_state") or ""
),
"production_source_truth_available": runtime_source_truth_available,
"stale_current_head_metadata_normalized": runtime_source_truth_available,
}
def _require_schema(payload: dict[str, Any], label: str) -> None: def _require_schema(payload: dict[str, Any], label: str) -> None:
@@ -358,3 +453,11 @@ def _int(value: Any) -> int:
def _strings(value: Any) -> list[str]: def _strings(value: Any) -> list[str]:
return [str(item) for item in _list(value)] return [str(item) for item in _list(value)]
def _is_sha(value: str) -> bool:
return bool(_SHA_RE.fullmatch(value))
def _taipei_now_iso() -> str:
return datetime.now(ZoneInfo("Asia/Taipei")).isoformat(timespec="seconds")

View File

@@ -42,12 +42,12 @@ from src.services.gitea_workflow_runner_owner_attestation_request import (
from src.services.p0_cicd_baseline_source_readiness import ( from src.services.p0_cicd_baseline_source_readiness import (
load_latest_p0_cicd_baseline_source_readiness, load_latest_p0_cicd_baseline_source_readiness,
) )
from src.services.reboot_auto_recovery_slo_scorecard import (
load_latest_reboot_auto_recovery_slo_scorecard,
)
from src.services.reboot_auto_recovery_drill_preflight import ( from src.services.reboot_auto_recovery_drill_preflight import (
load_latest_reboot_auto_recovery_drill_preflight, load_latest_reboot_auto_recovery_drill_preflight,
) )
from src.services.reboot_auto_recovery_slo_scorecard import (
load_latest_reboot_auto_recovery_slo_scorecard,
)
from src.services.runtime_surface_inventory import ( from src.services.runtime_surface_inventory import (
load_latest_runtime_surface_inventory, load_latest_runtime_surface_inventory,
) )

View File

@@ -74,6 +74,50 @@ def test_awoooi_priority_work_order_readback_endpoint_returns_snapshot():
assert "do not reboot" in data["next_execution_order"][0] assert "do not reboot" in data["next_execution_order"][0]
def test_awoooi_priority_work_order_readback_normalizes_runtime_source_truth(
monkeypatch: pytest.MonkeyPatch,
):
runtime_sha = "b4dc407ce05c68a3908b993437a61b869d83810f"
runtime_short_sha = runtime_sha[:10]
monkeypatch.setenv("AWOOOI_BUILD_COMMIT_SHA", runtime_sha)
monkeypatch.setenv("AWOOOI_DESIRED_API_IMAGE_TAG", runtime_sha)
payload = load_latest_awoooi_priority_work_order_readback()
current_head = payload["current_head"]
state = payload["mainline_execution_state"]
assert current_head["gitea_main_sha"] == runtime_sha
assert current_head["latest_source_readiness_commit_sha"] == runtime_sha
assert current_head["latest_source_readiness_cd_run_id"] == (
f"production_readback:{runtime_short_sha}"
)
assert current_head["latest_fetched_gitea_main_subject"] == (
f"production desired image tag {runtime_short_sha}"
)
assert current_head["stale_current_head_metadata_normalized"] is True
assert state["current_main_latest_source_sha"] == runtime_sha
assert state["latest_successful_deployed_source_sha"] == runtime_sha
assert state["current_main_cd_run_status"] == "production_readback_verified"
assert state["p0_004_template_copy_apply_gate_source_status"] == (
"production_endpoint_ready"
)
assert state["reboot_drill_preflight_source_status"] == "production_endpoint_ready"
assert payload["rollups"]["stale_current_head_metadata_normalized"] is True
assert payload["summary"]["latest_successful_deployed_source_sha"] == runtime_sha
current_truth = json.dumps(
{
"current_head": current_head,
"mainline_execution_state": state,
},
ensure_ascii=False,
sort_keys=True,
)
assert "3973" not in current_truth
assert "49637ee7" not in current_truth
assert "f426522" not in current_truth
def test_awoooi_priority_work_order_readback_rejects_reordered_active_p0(tmp_path): def test_awoooi_priority_work_order_readback_rejects_reordered_active_p0(tmp_path):
operations_dir = tmp_path / "docs" / "operations" operations_dir = tmp_path / "docs" / "operations"
operations_dir.mkdir(parents=True) operations_dir.mkdir(parents=True)

View File

@@ -50156,3 +50156,23 @@ production browser smoke:
- 沒有讀 secret / token / `.env` / raw sessions / SQLite / auth沒有寫 credential marker。 - 沒有讀 secret / token / `.env` / raw sessions / SQLite / auth沒有寫 credential marker。
- 沒有重啟主機,沒有 restart Docker / Nginx / K3s / DB / firewall。 - 沒有重啟主機,沒有 restart Docker / Nginx / K3s / DB / firewall。
- 沒有使用 GitHub / gh / GitHub API / GitHub Actions。 - 沒有使用 GitHub / gh / GitHub API / GitHub Actions。
## 2026-06-30 — 09:28 P0 priority work-order runtime source truth 正規化
**完成內容**
- 修正 `apps/api/src/services/awoooi_priority_work_order_readback.py`:當 Delivery Workbench 讀到合法 production runtime deploy SHA 時,將 `current_head``mainline_execution_state` 的 current main / CD / deployed source 欄位正規化為 `production_readback:<short_sha>`,不再讓舊 snapshot 的 `#3973``49637ee7``f426522` 混入目前主線進度。
- 新增 `rollups` / `summary`,明確輸出 `production_source_truth_available``stale_current_head_metadata_normalized``stale_cd_runs_reopen_closed_work=false`、P0-006 fresh reboot event gate 與 P0-004 / reboot preflight readiness。
- 補 `apps/api/tests/test_awoooi_priority_work_order_readback_api.py` regression`AWOOOI_BUILD_COMMIT_SHA` / `AWOOOI_DESIRED_API_IMAGE_TAG` 模擬 production env鎖住 priority readback 不再回吐舊 CD/run/source metadata。
**本地驗證結果**
- rebase 到 `a7e6de46a feat(delivery): expose p0 reboot drill readback` 後,`DATABASE_URL=postgresql+asyncpg://test:test@localhost:5432/test PYTHONPATH=apps/api python3.11 -m pytest apps/api/tests/test_awoooi_priority_work_order_readback_api.py apps/api/tests/test_delivery_closure_workbench_api.py ops/runner/test_cd_controlled_runtime_profile.py -q``35 passed`
- `PYTHONPATH=apps/api python3.11 -m py_compile apps/api/src/services/awoooi_priority_work_order_readback.py apps/api/tests/test_awoooi_priority_work_order_readback_api.py apps/api/src/services/delivery_closure_workbench.py apps/api/tests/test_delivery_closure_workbench_api.py`:通過。
- `PYTHONPATH=apps/api python3.11 -m ruff check apps/api/src/services/awoooi_priority_work_order_readback.py apps/api/tests/test_awoooi_priority_work_order_readback_api.py apps/api/src/services/delivery_closure_workbench.py apps/api/tests/test_delivery_closure_workbench_api.py`:通過。
- `python3.11 ops/runner/guard-gitea-runner-pressure.py --root .`:通過,`auto_branch_events_on_110=0``generic_runner_labels=0`
- `node scripts/ci/check-gitea-step-env-secrets.js`:通過。
- `git diff --check`:通過。
**仍維持**
- 沒有讀 secret / token / `.env` / raw sessions / SQLite / auth。
- 沒有使用 GitHub / gh / GitHub API / GitHub Actions。
- 沒有重啟主機,沒有 workflow_dispatch沒有 host / Docker / K8s / DB / firewall runtime 寫入。