ACTIVITY-WP-0044: disabled repo-manager-bounded-freshness draft (RMGR-WP-0020-T03)
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Build and Publish Container Image / build-and-push (push) Successful in 1m56s

Register bounded operation repo_manager_freshness (single attempt, 300 s,
code-fixed 'rmgr freshness run --limit N --max-seconds S [--dry-run]') and add
the disabled cron definition (40 */2 * * * UTC, limit 6, max_seconds 240).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 692292@bnt-lap001
Assistant-Session: 89c7d8e8-e1b3-47eb-9411-a0ab227fca2f
This commit is contained in:
tegwick 2026-10-04 13:11:54 +02:00
parent c6df768ef0
commit ba4ef00128
9 changed files with 449 additions and 2 deletions

View file

@ -0,0 +1,63 @@
"""Repo Manager bounded freshness invocation (RMGR-WP-0020-T03, ACTIVITY-WP-0044).
Invokes the Repo Manager CLI ``rmgr freshness run --limit N --max-seconds S
[--dry-run]`` (RMGR-WP-0020-T02 interface). The argv is code-fixed: a
definition supplies only the validated ``limit``, ``max_seconds`` and ``apply``
values. The executable is ``rmgr`` on PATH unless the worker sets
``ACTIVITY_CORE_RMGR_BIN``; definitions cannot choose it. Stdout is expected to
be a JSON object carrying ``receipts`` (``repo-manager.freshness-receipt.v1``);
only the counted projection in ``bounded_operations`` is persisted.
"""
from __future__ import annotations
import json
import os
import subprocess
from typing import Any
# Grace on top of the CLI's own --max-seconds budget for start-up/teardown.
_TIMEOUT_GRACE_SECONDS = 30
def build_freshness_argv(params: dict[str, Any]) -> list[str]:
limit = int(params["limit"])
max_seconds = int(params["max_seconds"])
argv = [
os.environ.get("ACTIVITY_CORE_RMGR_BIN", "rmgr"),
"freshness",
"run",
"--limit",
str(limit),
"--max-seconds",
str(max_seconds),
]
if params.get("apply") is not True:
argv.append("--dry-run")
return argv
def repo_manager_freshness(params: dict[str, Any]) -> dict[str, Any]:
"""Run one bounded freshness pass and return its JSON summary."""
argv = build_freshness_argv(params)
timeout = int(params["max_seconds"]) + _TIMEOUT_GRACE_SECONDS
completed = subprocess.run(
argv, capture_output=True, text=True, timeout=timeout, check=False
)
stdout = (completed.stdout or "").strip()
if completed.returncode != 0 and not stdout:
raise RuntimeError(
f"repo_manager_freshness failed (exit {completed.returncode}): "
f"{(completed.stderr or '').strip()[:300]}"
)
try:
summary = json.loads(stdout)
except json.JSONDecodeError as exc:
raise RuntimeError(f"repo_manager_freshness returned invalid JSON: {exc}") from exc
if not isinstance(summary, dict):
raise RuntimeError("repo_manager_freshness output must be a JSON object")
summary.setdefault("apply", params.get("apply") is True)
summary.setdefault("limit", int(params["limit"]))
summary.setdefault("max_seconds", int(params["max_seconds"]))
summary["exit_code"] = completed.returncode
return summary