diff --git a/src/repo_manager/commands/registrar_reconcile.py b/src/repo_manager/commands/registrar_reconcile.py index 5e22d5e..0c596e4 100644 --- a/src/repo_manager/commands/registrar_reconcile.py +++ b/src/repo_manager/commands/registrar_reconcile.py @@ -180,6 +180,22 @@ def _run_statehub(command: list[str], *, env: dict[str, str]) -> subprocess.Comp ) +def _restore_generated_brief(repo: Path, paths: list[str]) -> tuple[list[str], str | None]: + """Restore the generated brief after a projection-only repair child.""" + if not paths: + return [], None + if paths != [".custodian-brief.md"]: + return [], "projection repair changed files other than the generated Custodian brief" + original = _git(repo, "show", "HEAD:.custodian-brief.md") + if original.returncode != 0: + return [], original.stderr.strip() or "could not read the committed Custodian brief" + (repo / ".custodian-brief.md").write_text(original.stdout, encoding="utf-8") + remaining = _git(repo, "status", "--porcelain") + if remaining.returncode != 0 or remaining.stdout.strip(): + return [], remaining.stderr.strip() or "generated brief restoration left a dirty worktree" + return paths, None + + def registrar_reconcile( path: Path, *, @@ -308,6 +324,17 @@ def registrar_reconcile( changed = _git(repo, "status", "--porcelain") paths = [line[3:] for line in changed.stdout.splitlines() if len(line) > 3] + if repair_verified and paths: + restored, restore_error = _restore_generated_brief(repo, paths) + evidence["restored_generated_paths"] = restored + if restore_error: + return RegistrarResult( + "failed", + evidence, + {"code": "projection_repair_file_change", "message": restore_error}, + cid, + ) + paths = [] if paths: try: evidence["git_sha"] = commit_paths( diff --git a/tests/test_registrar_reconcile.py b/tests/test_registrar_reconcile.py index 549935c..afc3612 100644 --- a/tests/test_registrar_reconcile.py +++ b/tests/test_registrar_reconcile.py @@ -149,6 +149,8 @@ def test_repairs_an_already_identified_workplan_projection(tmp_path: Path, monke 'priority: high\nstate_hub_task_id: "22222222-2222-4222-8222-222222222222"\n```', ) workplan.write_text(text, encoding="utf-8") + brief = repo / ".custodian-brief.md" + brief.write_text("authoritative local brief\n", encoding="utf-8") _git(repo, "add", ".") _git(repo, "commit", "-m", "add authoritative identifiers") _git(repo, "push") @@ -166,6 +168,7 @@ def test_repairs_an_already_identified_workplan_projection(tmp_path: Path, monke def fake_run(command, *, env): assert env["STATEHUB_REGISTRAR"] == "1" + brief.write_text("generated from partial projection\n", encoding="utf-8") return subprocess.CompletedProcess(command, 1, "legacy stale references remain", "") monkeypatch.setattr(rr, "_run_statehub", fake_run) @@ -180,3 +183,5 @@ def test_repairs_an_already_identified_workplan_projection(tmp_path: Path, monke assert result.status == "applied" assert result.evidence["repair_projection_verified"] is True assert result.evidence["repair_projection_id"] == "11111111-1111-4111-8111-111111111111" + assert result.evidence["restored_generated_paths"] == [".custodian-brief.md"] + assert brief.read_text(encoding="utf-8") == "authoritative local brief\n"