from __future__ import annotations from pathlib import Path import pytest from repo_manager.identifiers import ( derive_work_record_uuid, plan_identifier_migration, scan_live_identifier_collisions, ) def _workplan(path: Path, identifier: str, status: str, task_status: str = "todo") -> None: path.parent.mkdir(parents=True, exist_ok=True) path.write_text( f"""--- id: {identifier} title: Test status: {status} --- ## Task ```task id: {identifier}-T01 status: {task_status} ``` """, encoding="utf-8", ) def test_uuid_derivation_is_stable_and_namespace_scoped() -> None: first = derive_work_record_uuid("helixforge", "RMGR-WP-0005") assert str(first) == "6dcf854e-9229-569d-90f0-2d9df235a61d" assert derive_work_record_uuid("helixforge", "RMGR-WP-0005") == first assert derive_work_record_uuid("client-a", "RMGR-WP-0005") != first with pytest.raises(ValueError): derive_work_record_uuid("Client A", "RMGR-WP-0005") def test_preflight_blocks_live_collision_but_ignores_archived_history(tmp_path: Path) -> None: one = tmp_path / "one" two = tmp_path / "two" _workplan(one / "workplans" / "one.md", "SHARED-WP-0001", "active") _workplan(two / "workplans" / "two.md", "SHARED-WP-0001", "ready") report = scan_live_identifier_collisions(tmp_path) assert report["ok"] is False assert "SHARED-WP-0001" in report["collisions"] _workplan(two / "workplans" / "two.md", "SHARED-WP-0001", "archived") report = scan_live_identifier_collisions(tmp_path) assert report["ok"] is True def test_migration_plan_preserves_mapping_and_is_atomic_per_repo(tmp_path: Path) -> None: one = tmp_path / "one" two = tmp_path / "two" _workplan(one / "workplans" / "one.md", "ONE-WP-0001", "active") _workplan(two / "workplans" / "two.md", "TWO-WP-0001", "ready", task_status="done") report = plan_identifier_migration(tmp_path, "fleet-a") assert report["ok"] is True assert report["apply_policy"] == "all-or-nothing per repository" assert report["totals"] == { "repositories": 2, "eligible": 2, "skipped": 0, "records": 3, "replace": 0, "assign": 3, "unchanged": 0, } one_plan = next(item for item in report["repositories"] if item["repo"] == "one") assert one_plan["atomic_unit"] is True assert {item["record_id"] for item in one_plan["mappings"]} == { "ONE-WP-0001", "ONE-WP-0001-T01", } assert all(item["current_uuid"] is None for item in one_plan["mappings"]) def test_migration_plan_skips_entire_repo_affected_by_collision(tmp_path: Path) -> None: one = tmp_path / "one" two = tmp_path / "two" _workplan(one / "workplans" / "one.md", "SHARED-WP-0001", "active") _workplan(one / "workplans" / "safe.md", "ONE-WP-0002", "active") _workplan(two / "workplans" / "two.md", "SHARED-WP-0001", "ready") report = plan_identifier_migration(tmp_path, "fleet-a") assert report["ok"] is False assert report["totals"]["skipped"] == 2 one_plan = next(item for item in report["repositories"] if item["repo"] == "one") assert one_plan["eligible"] is False assert any(item["record_id"] == "ONE-WP-0002" for item in one_plan["mappings"]) assert any(item["reason"] == "live identifier collision" for item in one_plan["blockers"])