ACTIVITY-WP-0044-T02: read freshness-run.v1 results[] from rmgr
The repo-manager runner reports per-repository rows under results[], not receipts[]; the projection counted nothing against the real output. 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:
parent
d6eb788578
commit
b2c6c56132
3 changed files with 29 additions and 10 deletions
|
|
@ -156,11 +156,13 @@ def normalize_operation_result(operation_id: str, raw: Any) -> dict[str, Any]:
|
|||
"script_exit_code": exit_code,
|
||||
}
|
||||
if operation_id == "repo_manager_freshness":
|
||||
receipts = result.get("receipts")
|
||||
# repo-manager.freshness-run.v1 reports one row per attempted repository
|
||||
# under "results"; dry-run rows carry only a planned action, no outcome.
|
||||
results = result.get("results")
|
||||
outcomes = {name: 0 for name in REPO_MANAGER_FRESHNESS_OUTCOMES}
|
||||
if isinstance(receipts, list):
|
||||
for receipt in receipts:
|
||||
outcome = receipt.get("outcome") if isinstance(receipt, dict) else None
|
||||
if isinstance(results, list):
|
||||
for row in results:
|
||||
outcome = row.get("outcome") if isinstance(row, dict) else None
|
||||
if outcome in outcomes:
|
||||
outcomes[outcome] += 1
|
||||
exit_code = result.get("exit_code", 0)
|
||||
|
|
@ -171,7 +173,7 @@ def normalize_operation_result(operation_id: str, raw: Any) -> dict[str, Any]:
|
|||
"apply": bool(result.get("apply")),
|
||||
"limit": _safe_count(result.get("limit")),
|
||||
"max_seconds": _safe_count(result.get("max_seconds")),
|
||||
"receipt_count": len(receipts) if isinstance(receipts, list) else 0,
|
||||
"result_count": len(results) if isinstance(results, list) else 0,
|
||||
"outcomes": outcomes,
|
||||
"exit_code": exit_code,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ def test_invocation_projects_counts_only(monkeypatch):
|
|||
|
||||
def fake_run(argv, **kwargs):
|
||||
calls.append((argv, kwargs["timeout"]))
|
||||
out = {"receipts": [
|
||||
out = {"schema": "repo-manager.freshness-run.v1", "results": [
|
||||
{"repo": "a", "outcome": "applied", "detail": "must not persist"},
|
||||
{"repo": "b", "outcome": "noop"},
|
||||
{"repo": "c", "outcome": "refused"},
|
||||
|
|
@ -106,7 +106,7 @@ def test_invocation_projects_counts_only(monkeypatch):
|
|||
raw = repo_manager.repo_manager_freshness({"limit": 6, "max_seconds": 240, "apply": True})
|
||||
projected = normalize_operation_result("repo_manager_freshness", raw)
|
||||
assert calls[0][1] == 240 + repo_manager._TIMEOUT_GRACE_SECONDS
|
||||
assert projected["receipt_count"] == 4
|
||||
assert projected["result_count"] == 4
|
||||
assert projected["outcomes"]["applied"] == 1
|
||||
assert projected["outcomes"]["noop"] == 1
|
||||
assert projected["outcomes"]["refused"] == 1
|
||||
|
|
@ -114,6 +114,16 @@ def test_invocation_projects_counts_only(monkeypatch):
|
|||
assert "must not persist" not in json.dumps(projected)
|
||||
|
||||
|
||||
def test_dry_run_rows_without_outcome_count_nothing():
|
||||
raw = {"schema": "repo-manager.freshness-run.v1", "dry_run": True,
|
||||
"results": [{"slug": "a", "action": "reconcile"},
|
||||
{"slug": "b", "action": "skip_noop"}],
|
||||
"apply": False, "limit": 2, "max_seconds": 60, "exit_code": 0}
|
||||
projected = normalize_operation_result("repo_manager_freshness", raw)
|
||||
assert projected["result_count"] == 2
|
||||
assert sum(projected["outcomes"].values()) == 0
|
||||
|
||||
|
||||
def test_invocation_fails_on_non_json(monkeypatch):
|
||||
monkeypatch.setattr(
|
||||
repo_manager.subprocess, "run",
|
||||
|
|
@ -127,7 +137,7 @@ def test_invocation_fails_on_non_json(monkeypatch):
|
|||
async def test_execute_bounded_operation_dispatches_to_repo_manager(monkeypatch):
|
||||
monkeypatch.setattr(
|
||||
repo_manager, "repo_manager_freshness",
|
||||
lambda params: {"receipts": [], "apply": False, "limit": 1, "max_seconds": 10},
|
||||
lambda params: {"results": [], "apply": False, "limit": 1, "max_seconds": 10},
|
||||
)
|
||||
patch = await activities.execute_bounded_operation({"source": _source(apply=False)})
|
||||
assert patch["freshness"]["kind"] == "repo_manager_freshness"
|
||||
|
|
|
|||
|
|
@ -47,10 +47,9 @@ state_hub_task_id: "0cbbadc8-d217-55a3-bc2a-da81e19ec2a8"
|
|||
|
||||
```task
|
||||
id: ACTIVITY-WP-0044-T02
|
||||
status: wait
|
||||
status: progress
|
||||
priority: medium
|
||||
needs_human: false
|
||||
blocking_reason: "rmgr freshness run is being built in RMGR-WP-0020-T02; JSON output (receipts[].outcome) assumed from the T01 receipt contract"
|
||||
depends_on: [RMGR-WP-0020-T01, RMGR-WP-0020-T02]
|
||||
state_hub_task_id: "e4517812-aec2-57e9-9677-de4a89f3f48f"
|
||||
```
|
||||
|
|
@ -60,6 +59,14 @@ JSON object with `receipts[]` carrying `repo-manager.freshness-receipt.v1`
|
|||
outcomes; adjust `normalize_operation_result` if the shape differs. Decide the
|
||||
worker image/packaging of `rmgr` (no deployment in this workplan).
|
||||
|
||||
2026-10-04: RMGR-WP-0020-T01/T02 landed (repo-manager ad1ee3e). Flags match
|
||||
(`--limit`, `--max-seconds` required, `--dry-run`). The run summary is
|
||||
`repo-manager.freshness-run.v1` with per-repository rows under `results[]`
|
||||
(not `receipts[]`); dry-run rows carry only a planned `action`. The projection
|
||||
now reads `results[].outcome` and reports `result_count`; 35 focused tests pass.
|
||||
Exit 1 with JSON (a failed attempt) still projects; exit 3/4 without JSON raise.
|
||||
Remaining: decide how `rmgr` is packaged onto the worker.
|
||||
|
||||
## Founder-reviewed activation
|
||||
|
||||
```task
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue