fix(registrar): contain projection repair writeback

Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a023c0-a0a3-7c03-b395-5a0d2757214d
This commit is contained in:
tegwick 2026-08-22 10:05:33 +02:00
parent f8b914a52a
commit 8eff8d3239
2 changed files with 32 additions and 0 deletions

View file

@ -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(

View file

@ -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"