STATE-WP-0069: schedule weekly legacy-meter review monitoring
All checks were successful
CI Smoke / host-smoke (push) Successful in 1s
CI Smoke / container-smoke (push) Successful in 3s
Build and Publish Container Image / build-and-push (push) Successful in 36s

Add legacy_meter_weekly_review state-hub resolver query, weekly activity
definition (Mon 08:30 Berlin), Railiance runtime projection, and progress
sink posting for STATE-WP-0069 retirement gating.
This commit is contained in:
tegwick 2026-07-08 20:55:06 +02:00
parent bad91099e8
commit efa361541b
8 changed files with 267 additions and 1 deletions

View file

@ -170,7 +170,12 @@ def progress_event_types(args: argparse.Namespace) -> list[str | None]:
raw = args.progress_event_type
if raw is None:
env_value = os.environ.get("AUTOMATION_STATUS_PROGRESS_EVENT_TYPES")
raw = env_value.split(",") if env_value else ["daily_triage", "schedule_miss", "ops_inventory_probe"]
raw = env_value.split(",") if env_value else [
"daily_triage",
"schedule_miss",
"ops_inventory_probe",
"legacy_meter_weekly_review",
]
values = [item.strip() for item in raw if item and item.strip()]
return [None if item == "all" else item for item in values]

View file

@ -16,6 +16,7 @@ Supported queries:
- recently_on_scope_hourly: POST {STATE_HUB_URL}/recently-on-scope/hourly
- consistency_sweep_remote_all: POST {STATE_HUB_URL}/consistency/sweep/remote-all
- phase5_stabilization_check: hub-visible Phase 5 stabilization gates
- legacy_meter_weekly_review: GET {STATE_HUB_URL}/legacy-meter/weekly-review
No caching state hub data is live operational state and must not be stale
within a single workflow run.
@ -149,6 +150,8 @@ class StateHubContextResolver(ContextResolver):
return _validate_consistency_sweep_remote_all(result)
if query == "phase5_stabilization_check":
return _phase5_stabilization_check(params)
if query == "legacy_meter_weekly_review":
return _legacy_meter_weekly_review(params)
return {}
@ -169,6 +172,42 @@ def _utc_now() -> datetime:
return datetime.now(timezone.utc)
def _legacy_meter_weekly_review(params: dict[str, Any]) -> dict[str, Any]:
"""Fetch State Hub legacy-meter weekly review for activity-core scheduling."""
query_params = {
key: params[key]
for key in ("days", "window_start", "window_end")
if key in params
}
raw = _fetch_json("/legacy-meter/weekly-review", query_params or None)
interfaces = raw.get("interfaces") or []
candidates = raw.get("retirement_candidates") or []
window_calls = sum(int((item.get("window") or {}).get("calls") or 0) for item in interfaces)
return {
"kind": "legacy_meter_weekly_review",
"generated_at": raw.get("generated_at"),
"window_start": raw.get("window_start"),
"window_end": raw.get("window_end"),
"activity_core_handoff": raw.get("activity_core_handoff"),
"interface_count": len(interfaces),
"retirement_candidate_count": len(candidates),
"window_legacy_calls": window_calls,
"retirement_candidates": [
{
"interface_key": (item.get("interface") or {}).get("interface_key"),
"interface_kind": (item.get("interface") or {}).get("interface_kind"),
"replacement_ref": (item.get("interface") or {}).get("replacement_ref"),
"retirement_reason": item.get("retirement_reason"),
}
for item in candidates[:25]
],
"checks": {
"has_retirement_candidates": bool(candidates),
},
"overall_pass": True,
}
def _phase5_stabilization_check(params: dict[str, Any]) -> dict[str, Any]:
closeout = bool(params.get("closeout"))
now = _utc_now()

View file

@ -127,6 +127,10 @@ def _post_state_hub_progress(
compact = probe_result
summary = _core_hub_stabilization_summary_text(probe_result)
source_type = "core-hub"
elif probe_result.get("kind") == "legacy_meter_weekly_review":
compact = probe_result
summary = _legacy_meter_summary_text(probe_result)
source_type = "state-hub"
elif probe_result.get("checks") is not None:
compact = probe_result
summary = _phase5_summary_text(probe_result)
@ -518,6 +522,16 @@ def _core_hub_stabilization_summary_text(result: dict[str, Any]) -> str:
)
def _legacy_meter_summary_text(result: dict[str, Any]) -> str:
candidates = result.get("retirement_candidate_count", 0)
calls = result.get("window_legacy_calls", 0)
interfaces = result.get("interface_count", 0)
return (
f"Legacy-meter weekly review: {candidates} retirement candidate(s) of "
f"{interfaces} registered interface(s); {calls} legacy call(s) in window"
)
def _phase5_summary_text(result: dict[str, Any]) -> str:
checks = result.get("checks") or {}
totals = checks.get("totals") or {}