"""Regression coverage for explicit legacy PR root migration.""" from __future__ import annotations from contextlib import nullcontext import json from pathlib import Path import sys import yaml from testing.tests.test_hermes_cli_support import HERMES, _load ROOT = Path(__file__).parents[2] sys.path.insert(0, str(HERMES / "scm-common/scripts")) state = _load("supervisor_state") seed = _load("seed_legacy_scm_roots") class NativeKanban: """Minimal native task lookup surface used by the operator seed.""" def __init__(self, task_ids: set[str]) -> None: self.task_ids = task_ids def scoped_current_board(self, _board: str): return nullcontext() def connect(self, *, board: str): return type("Connection", (), {"close": lambda self: None})() def get_task(self, _connection, task_id: str): return {"id": task_id} if task_id in self.task_ids else None def _pull(root, head: str | None = None) -> bytes: """Build only the canonical open PR shape the seed accepts.""" return json.dumps({ "state": "open", "head": {"ref": root.ref, "sha": head or root.head, "repo": {"full_name": f"titan/{root.project}"}}, "base": {"ref": root.base, "repo": {"full_name": f"titan/{root.project}"}}, }).encode() def test_seed_registry_exactly_matches_flux_broker_adoptions(): """The board integrity table and broker ledger share one reviewed scope.""" document = yaml.safe_load( (ROOT / "services/hermes-scm-broker/task-branch-adoptions-configmap.yaml").read_text() ) deployed = json.loads(document["data"]["task-branch-adoptions.json"]) expected = {f"{root.project}/{root.ref}": root.adoption() for root in seed.ROOTS} assert deployed == expected assert "t_cf89a2ec" in {root.root_task_id for root in seed.ROOTS} assert deployed["atlas-iac/feature/hermes-next-hux"]["latest_head"] == ( "98c7c6184f6edfe3cdac228529c2287584db3006" ) def test_seed_requires_native_root_and_matching_live_canonical_pr(tmp_path, monkeypatch): """A stale PR or fabricated root leaves the board-local integrity DB untouched.""" root = seed.ROOTS[1] monkeypatch.setattr(state, "KANBAN_ROOT", tmp_path / "boards") missing = NativeKanban(set()) assert seed.seed_root(missing, root, lambda _path: (_ for _ in ()).throw(AssertionError)) == "missing-task" native = NativeKanban({root.root_task_id}) assert seed.seed_root(native, root, lambda _path: _pull(root, "a" * 40)) == "live-pr-mismatch" assert state.get_root(root.board, root.root_task_id) is None assert seed.seed_root(native, root, lambda _path: _pull(root)) == "seeded" assert state.get_root(root.board, root.root_task_id) == root.lineage assert state.get_live_head(root.board, root.root_task_id) == root.head def test_seed_rerun_preserves_same_owned_newer_state_and_approval(tmp_path, monkeypatch): """A static migration record never rewinds a later verified continuation head.""" root = seed.ROOTS[1] monkeypatch.setattr(state, "KANBAN_ROOT", tmp_path / "boards") native = NativeKanban({root.root_task_id}) assert seed.seed_root(native, root, lambda _path: _pull(root)) == "seeded" newer = "b" * 40 state.record_submission(root.board, root.root_task_id, root.lineage, newer) state.set_ready(root.board, root.root_task_id, newer) assert seed.seed_root(native, root, lambda _path: (_ for _ in ()).throw(AssertionError)) == "already-seeded" assert state.get_live_head(root.board, root.root_task_id) == newer with state._connect(root.board) as connection: assert connection.execute( "SELECT ready_for_human_merge,ready_commit FROM supervisor_roots" ).fetchone() == (1, newer)