feat(legacy-meter): schedule 8h capture activity on railiance01
All checks were successful
CI Smoke / host-smoke (push) Successful in 1s
CI Smoke / container-smoke (push) Successful in 49s
Build and Publish Container Image / build-and-push (push) Successful in 2m50s

Add legacy-meter-8h-capture cron (0 */8 * * * UTC), pass hours through the
state-hub resolver, and label progress summaries by window size.
This commit is contained in:
tegwick 2026-07-09 09:29:41 +02:00
parent b59bf92341
commit f41cf14977
5 changed files with 104 additions and 2 deletions

View file

@ -0,0 +1,31 @@
---
id: legacy-meter-8h-capture
name: Legacy-Meter 8h Capture
enabled: true
owner: custodian-agent
governance: custodian
status: active
trigger:
type: cron
cron_expression: "0 */8 * * *"
timezone: UTC
misfire_policy: skip
context_sources:
- type: state-hub
query: legacy_meter_weekly_review
required: true
params:
hours: 8
evidence_sinks:
- type: state-hub-progress
event_type: legacy_meter_8h_capture
author: activity-core
workplan_id: 44e2e123-9934-4b5e-8b50-1bac548c5b70
bind_to: context.legacy_meter_weekly_review
---
# Legacy-Meter 8h Capture
Runs every eight hours UTC. Fetches State Hub `/legacy-meter/weekly-review?hours=8`
and posts `legacy_meter_8h_capture` progress for STATE-WP-0073 / STATE-WP-0070
seven-window retirement gating.

View file

@ -328,6 +328,41 @@ data:
Railiance projection of the Custodian-owned definition in
`activity-definitions/weekly-legacy-meter-review.md`. Posts
`legacy_meter_weekly_review` progress for STATE-WP-0069 retirement gating.
legacy-meter-8h-capture.md: |
---
id: legacy-meter-8h-capture
name: Legacy-Meter 8h Capture
type: activity-definition
version: "1.0"
enabled: true
owner: custodian
governance: custodian
status: active
created: "2026-07-09"
trigger:
type: cron
cron_expression: "0 */8 * * *"
timezone: UTC
misfire_policy: skip
context_sources:
- type: state-hub
query: legacy_meter_weekly_review
required: true
params:
hours: 8
evidence_sinks:
- type: state-hub-progress
event_type: legacy_meter_8h_capture
author: activity-core
workplan_id: 44e2e123-9934-4b5e-8b50-1bac548c5b70
bind_to: context.legacy_meter_weekly_review
---
# ActivityDefinition: Legacy-Meter 8h Capture
Railiance projection of the Custodian-owned definition in
`activity-definitions/legacy-meter-8h-capture.md`. Posts
`legacy_meter_8h_capture` progress every 8h for STATE-WP-0073 retirement gating.
phase5-stabilization-closeout.md: |
---
id: "e7d2b5a8-4c1f-4e9a-b6d3-8f2a1c4e6b09"

View file

@ -178,15 +178,24 @@ 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")
for key in ("days", "hours", "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)
window_hours = params.get("hours")
window_days = params.get("days")
if window_hours is not None:
window_label = f"{window_hours}h"
elif window_days is not None:
window_label = f"{window_days}d"
else:
window_label = "7d"
return {
"kind": "legacy_meter_weekly_review",
"window_label": window_label,
"generated_at": raw.get("generated_at"),
"window_start": raw.get("window_start"),
"window_end": raw.get("window_end"),

View file

@ -538,8 +538,9 @@ 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)
window_label = result.get("window_label", "7d")
return (
f"Legacy-meter weekly review: {candidates} retirement candidate(s) of "
f"Legacy-meter {window_label} review: {candidates} retirement candidate(s) of "
f"{interfaces} registered interface(s); {calls} legacy call(s) in window"
)

View file

@ -768,6 +768,32 @@ def test_legacy_meter_weekly_review_summarises_candidates(monkeypatch) -> None:
assert result["retirement_candidates"][0]["interface_key"] == "mcp:create_workstream"
def test_legacy_meter_weekly_review_passes_hours_param(monkeypatch) -> None:
seen: dict[str, Any] = {}
def fake_get(url: str, **kwargs: Any) -> DummyResponse:
seen["params"] = kwargs.get("params")
return DummyResponse(
{
"generated_at": "2026-07-09T08:00:00+00:00",
"window_start": "2026-07-09T00:00:00+00:00",
"window_end": "2026-07-09T08:00:00+00:00",
"interfaces": [],
"retirement_candidates": [],
}
)
monkeypatch.setenv("STATE_HUB_URL", "http://state-hub.test")
monkeypatch.setattr(httpx, "get", fake_get)
result = StateHubContextResolver().resolve(
"legacy_meter_weekly_review", None, {"hours": 8}
)
assert seen["params"] == {"hours": 8}
assert result["window_label"] == "8h"
def test_phase5_stabilization_check_passes(monkeypatch) -> None:
payloads = {
"/state/health": {"status": "ok", "db": "connected"},