diff --git a/scripts/consistency_check.py b/scripts/consistency_check.py index a5c6a07..3ffb92d 100644 --- a/scripts/consistency_check.py +++ b/scripts/consistency_check.py @@ -1131,7 +1131,16 @@ def _generate_work_record_index(repo_dir: Path, repo_slug: str) -> str | None: return None rows.sort(key=lambda r: (_WORK_RECORD_INDEX_KIND_ORDER.get(r[0], 99), r[4], r[1])) + return _work_record_index_document(repo_slug, rows) + +def _work_record_index_document( + repo_slug: str, rows: list[tuple[str, str, str, str, str]] +) -> str: + """Render WORK-RECORDS.md. An empty row list still produces the header + and table so a leftover index can be rewritten after every live record + is archived or removed. + """ lines = [ f"# Work Records — {repo_slug}", "", @@ -1144,7 +1153,10 @@ def _generate_work_record_index(repo_dir: Path, repo_slug: str) -> str | None: "| Kind | ID | Status | Lane | Source |", "| --- | --- | --- | --- | --- |", ] - lines.extend(f"| {kind} | {rid} | {status} | {lane} | {source} |" for kind, rid, status, lane, source in rows) + lines.extend( + f"| {kind} | {rid} | {status} | {lane} | {source} |" + for kind, rid, status, lane, source in rows + ) lines.append("") return "\n".join(lines) @@ -1155,11 +1167,16 @@ def _check_work_record_index_freshness( """C-33: WORK-RECORDS.md missing or stale relative to the current file-derived work-record set.""" content = _generate_work_record_index(repo_dir, repo_slug) - if content is None: - return index_file = repo_dir / _WORK_RECORD_INDEX_NAME existing = index_file.read_text(encoding="utf-8") if index_file.is_file() else None - if existing == content: + if content is None: + if existing is None: + return + empty = _work_record_index_document(repo_slug, []) + if existing == empty: + return + content = empty + elif existing == content: return report.add( severity="WARN", check_id="C-33", diff --git a/tests/test_work_record_index.py b/tests/test_work_record_index.py index 2f1febf..b91e2ab 100644 --- a/tests/test_work_record_index.py +++ b/tests/test_work_record_index.py @@ -17,6 +17,7 @@ from consistency_check import ( # noqa: E402 ConsistencyReport, _check_work_record_index_freshness, _generate_work_record_index, + _work_record_index_document, ) REGISTRY_YAML = textwrap.dedent( @@ -185,3 +186,36 @@ class TestCheckWorkRecordIndexFreshness: ctx = report.issues[0]._fix_context assert ctx["index_file"] == tmp_path / "WORK-RECORDS.md" assert "AWQ-001" in ctx["content"] + + def test_flags_stale_index_when_only_archived_workplans_remain( + self, tmp_path, registry_file + ): + wp_dir = tmp_path / "workplans" / "archived" + wp_dir.mkdir(parents=True) + (wp_dir / "260101-CUST-WP-0000-old.md").write_text( + "---\nid: CUST-WP-0000\nstatus: finished\n---\n", encoding="utf-8" + ) + (tmp_path / "WORK-RECORDS.md").write_text( + "| workplan | CUST-WP-0000 | active | — | workplans/CUST-WP-0000-old.md |\n", + encoding="utf-8", + ) + report = self._report(tmp_path) + assert len(report.issues) == 1 + assert report.issues[0].check_id == "C-33" + content = report.issues[0]._fix_context["content"] + assert "CUST-WP-0000" not in content + assert "| Kind | ID | Status | Lane | Source |" in content + + def test_no_issue_when_empty_index_matches_archived_only_repo( + self, tmp_path, registry_file + ): + wp_dir = tmp_path / "workplans" / "archived" + wp_dir.mkdir(parents=True) + (wp_dir / "260101-CUST-WP-0000-old.md").write_text( + "---\nid: CUST-WP-0000\nstatus: finished\n---\n", encoding="utf-8" + ) + (tmp_path / "WORK-RECORDS.md").write_text( + _work_record_index_document("testrepo", []), encoding="utf-8" + ) + report = self._report(tmp_path) + assert report.issues == []