From 69adfff48d3bd2a02d060d5900dee50d2d9572b9 Mon Sep 17 00:00:00 2001 From: tegwick Date: Sat, 22 Aug 2026 12:57:59 +0200 Subject: [PATCH] fix(registrar): register newly closed workplans Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a023c0-a0a3-7c03-b395-5a0d2757214d --- .../commands/registrar_reconcile.py | 17 +++++++++++++---- tests/test_registrar_reconcile.py | 19 ++++++++++++++++++- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/repo_manager/commands/registrar_reconcile.py b/src/repo_manager/commands/registrar_reconcile.py index 21d2e91..c39860b 100644 --- a/src/repo_manager/commands/registrar_reconcile.py +++ b/src/repo_manager/commands/registrar_reconcile.py @@ -67,12 +67,21 @@ def _missing_identifiers(repo: Path) -> dict[str, list[str]]: parsed = parse_workplan_file(path, repo_root=repo) if parsed.frontmatter.get("type") != "workplan" or not parsed.id: continue - # Closed records are frozen provenance under ADR-007. State Hub also - # deliberately refuses to create missing task rows for them. - if (parsed.status or "").strip().lower() in {"finished", "archived"}: - continue if not parsed.state_hub_workstream_id: workplans.append(parsed.id) + # C-06 creates a newly discovered workplan and its tasks as one + # registration unit, including closed file-backed provenance. + # Include those task gaps so post-verification cannot report a + # false success after creating only the parent. + for task in parsed.tasks: + if task.id and not task.state_hub_task_id: + tasks.append(task.id) + continue + # Once a closed workplan is linked, missing task identifiers are + # frozen historical artefacts. State Hub's C-11 fixer deliberately + # refuses to create them. + if (parsed.status or "").strip().lower() in {"finished", "archived"}: + continue for task in parsed.tasks: if task.id and not task.state_hub_task_id: tasks.append(task.id) diff --git a/tests/test_registrar_reconcile.py b/tests/test_registrar_reconcile.py index 3edd89b..cfa52f6 100644 --- a/tests/test_registrar_reconcile.py +++ b/tests/test_registrar_reconcile.py @@ -51,13 +51,30 @@ def test_requires_explicit_primary_confirmation(tmp_path: Path) -> None: assert result.error and result.error["code"] == "confirmation_required" -def test_closed_records_are_not_registrar_work(tmp_path: Path) -> None: +def test_unlinked_closed_workplan_is_registrar_work(tmp_path: Path) -> None: repo = _fixture(tmp_path) workplan = repo / "workplans" / "DEMO-WP-0001.md" workplan.write_text( workplan.read_text(encoding="utf-8").replace("status: active", "status: finished"), encoding="utf-8", ) + assert rr._missing_identifiers(repo) == { + "workplans": ["DEMO-WP-0001"], + "tasks": ["DEMO-WP-0001-T01"], + "intakes": [], + "decisions": [], + } + + +def test_linked_closed_workplan_does_not_reopen_historical_task_gaps(tmp_path: Path) -> None: + repo = _fixture(tmp_path) + workplan = repo / "workplans" / "DEMO-WP-0001.md" + text = workplan.read_text(encoding="utf-8") + text = text.replace( + "status: active\n---", + 'status: finished\nstate_hub_workstream_id: "11111111-1111-4111-8111-111111111111"\n---', + ) + workplan.write_text(text, encoding="utf-8") assert rr._missing_identifiers(repo) == { "workplans": [], "tasks": [],