feat(RMGR-WP-0002): dual-run writeback, flags, meter, SH facade
Add dual-run flags/meter, harden task-status (idempotency, UUID, head, push), State Hub adapter for PATCH /tasks and C-15/reconcile proxy, pilot evidence, and finish RMGR-WP-0002.
This commit is contained in:
parent
bb1d030257
commit
310b43079d
14 changed files with 679 additions and 50 deletions
118
tests/test_dual_run.py
Normal file
118
tests/test_dual_run.py
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
"""Dual-run flags, meter, and hardened task status command."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from repo_manager import dual_run
|
||||
from repo_manager.commands.task_status import update_task_status
|
||||
|
||||
|
||||
def _git(repo: Path, *args: str) -> None:
|
||||
subprocess.run(["git", *args], cwd=repo, check=True, capture_output=True)
|
||||
|
||||
|
||||
def _fixture(tmp_path: Path) -> Path:
|
||||
repo = tmp_path / "pilot"
|
||||
repo.mkdir()
|
||||
_git(repo, "init")
|
||||
_git(repo, "config", "user.email", "t@example.com")
|
||||
_git(repo, "config", "user.name", "T")
|
||||
(repo / "workplans").mkdir()
|
||||
(repo / "workplans" / "P-WP-0001.md").write_text(
|
||||
"""---
|
||||
id: P-WP-0001
|
||||
type: workplan
|
||||
title: Pilot
|
||||
status: active
|
||||
---
|
||||
|
||||
## T
|
||||
|
||||
```task
|
||||
id: P-WP-0001-T01
|
||||
status: todo
|
||||
state_hub_task_id: "11111111-1111-4111-8111-111111111111"
|
||||
```
|
||||
|
||||
x
|
||||
""",
|
||||
encoding="utf-8",
|
||||
)
|
||||
_git(repo, "add", ".")
|
||||
_git(repo, "commit", "-m", "seed")
|
||||
return repo
|
||||
|
||||
|
||||
def test_flags_and_pilot(monkeypatch: pytest.MonkeyPatch):
|
||||
monkeypatch.delenv("RM_WRITEBACK", raising=False)
|
||||
monkeypatch.delenv("RM_RECONCILE", raising=False)
|
||||
monkeypatch.delenv("RM_PILOT_REPOS", raising=False)
|
||||
assert dual_run.writeback_enabled() is False
|
||||
|
||||
monkeypatch.setenv("RM_WRITEBACK", "1")
|
||||
monkeypatch.setenv("RM_PILOT_REPOS", "repo-manager,other")
|
||||
assert dual_run.writeback_for_repo("repo-manager") is True
|
||||
assert dual_run.writeback_for_repo("nope") is False
|
||||
|
||||
monkeypatch.delenv("RM_PILOT_REPOS", raising=False)
|
||||
assert dual_run.writeback_for_repo("any") is True
|
||||
|
||||
|
||||
def test_meter(tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
|
||||
meter = tmp_path / "meter.jsonl"
|
||||
monkeypatch.setenv("RM_METER_PATH", str(meter))
|
||||
dual_run.record_mutation(
|
||||
source="repo-manager",
|
||||
kind="test",
|
||||
repo_slug="x",
|
||||
detail={"a": 1},
|
||||
)
|
||||
dual_run.record_mutation(source="state-hub", kind="test", repo_slug="x")
|
||||
summary = dual_run.meter_summary(meter)
|
||||
assert summary["repo-manager"] == 1
|
||||
assert summary["state-hub"] == 1
|
||||
assert summary["total"] == 2
|
||||
|
||||
|
||||
def test_update_by_uuid_and_idempotency(tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
|
||||
repo = _fixture(tmp_path)
|
||||
monkeypatch.setenv("RM_METER_PATH", str(tmp_path / "m.jsonl"))
|
||||
monkeypatch.setenv("RM_IDEMPOTENCY_PATH", str(tmp_path / "idemp.json"))
|
||||
|
||||
r1 = update_task_status(
|
||||
repo,
|
||||
"11111111-1111-4111-8111-111111111111",
|
||||
"progress",
|
||||
idempotency_key="k1",
|
||||
repo_slug="pilot",
|
||||
)
|
||||
assert r1.status == "applied"
|
||||
assert r1.evidence.get("git_sha")
|
||||
text = (repo / "workplans" / "P-WP-0001.md").read_text(encoding="utf-8")
|
||||
assert "status: progress" in text
|
||||
|
||||
r2 = update_task_status(
|
||||
repo,
|
||||
"11111111-1111-4111-8111-111111111111",
|
||||
"progress",
|
||||
idempotency_key="k1",
|
||||
repo_slug="pilot",
|
||||
)
|
||||
assert r2.status == "applied"
|
||||
assert r2.evidence.get("git_sha") == r1.evidence.get("git_sha")
|
||||
|
||||
# Different payload same key → conflict
|
||||
r3 = update_task_status(
|
||||
repo,
|
||||
"11111111-1111-4111-8111-111111111111",
|
||||
"done",
|
||||
idempotency_key="k1",
|
||||
repo_slug="pilot",
|
||||
)
|
||||
assert r3.status == "rejected"
|
||||
assert r3.error and r3.error.get("code") == "conflict"
|
||||
Loading…
Add table
Add a link
Reference in a new issue