Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a023c0-a0a3-7c03-b395-5a0d2757214d
150 lines
4.4 KiB
Python
150 lines
4.4 KiB
Python
"""Dual-run flags, config file, meter, and hardened task status command."""
|
|
|
|
from __future__ import annotations
|
|
|
|
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
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def _clear_dual_run_cache():
|
|
dual_run.reload_config()
|
|
yield
|
|
dual_run.reload_config()
|
|
|
|
|
|
def test_flags_and_pilot(tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
|
|
monkeypatch.delenv("RM_WRITEBACK", raising=False)
|
|
monkeypatch.delenv("RM_RECONCILE", raising=False)
|
|
monkeypatch.delenv("RM_PILOT_REPOS", raising=False)
|
|
monkeypatch.setenv("RM_DUAL_RUN_CONFIG", str(tmp_path / "missing-dual-run.yaml"))
|
|
dual_run.reload_config()
|
|
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_config_file(tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
|
|
cfg = tmp_path / "dual-run.yaml"
|
|
cfg.write_text(
|
|
"writeback: true\nreconcile: true\nwriteback_push: true\n"
|
|
"pilot_repos:\n - repo-manager\n",
|
|
encoding="utf-8",
|
|
)
|
|
monkeypatch.delenv("RM_WRITEBACK", raising=False)
|
|
monkeypatch.delenv("RM_RECONCILE", raising=False)
|
|
monkeypatch.delenv("RM_WRITEBACK_PUSH", raising=False)
|
|
monkeypatch.delenv("RM_PILOT_REPOS", raising=False)
|
|
monkeypatch.setenv("RM_DUAL_RUN_CONFIG", str(cfg))
|
|
dual_run.reload_config()
|
|
assert dual_run.writeback_enabled() is True
|
|
assert dual_run.reconcile_enabled() is True
|
|
assert dual_run.writeback_push_enabled() is True
|
|
assert dual_run.writeback_for_repo("repo-manager") is True
|
|
assert dual_run.writeback_for_repo("other") is False
|
|
|
|
# env overrides file
|
|
monkeypatch.setenv("RM_WRITEBACK", "0")
|
|
dual_run.reload_config()
|
|
assert dual_run.writeback_enabled() is False
|
|
|
|
|
|
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")
|
|
|
|
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"
|