Skip to content

Commit a47327d

Browse files
committed
fix(governance): harden ADR audit boundaries
1 parent 4da6ae2 commit a47327d

3 files changed

Lines changed: 35 additions & 6 deletions

File tree

.agents/skills/docs-governance/scripts/audit-docs.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -344,8 +344,9 @@ def check_status_resurrection(
344344
resurrected: list[str] = []
345345
if match:
346346
for value in CODE_PATH_RE.findall(match.group("body")):
347-
if plausible_deletion_path(value):
348-
resolved = resolve_within_root(root, root, value)
347+
normalized = value.replace("\\", "/")
348+
if plausible_deletion_path(normalized):
349+
resolved = resolve_within_root(root, root, normalized)
349350
if resolved is not None and resolved.exists():
350351
resurrected.append(value)
351352
if resurrected:
@@ -435,7 +436,7 @@ def check_log(
435436

436437
def parse_adr_status(text: str) -> str | None:
437438
patterns = (
438-
r"(?im)^(?:[-*]\s+)?(?:\*\*(?:status|\u72b6\u6001)\*\*|(?:status|\u72b6\u6001))\s*[:\uFF1A]\s*`?([a-z]+)`?(?:\s+by\s+ADR-\d+)?\s*$",
439+
r"(?im)^(?:[-*]\s+)?(?:\*\*(?:status|\u72b6\u6001)\*\*|(?:status|\u72b6\u6001))\s*[:\uFF1A]\s*`?([a-z]+)`?(?:\s+by\s+ADR-\d{3,4})?\s*$",
439440
r"(?im)^##\s+(?:status|\u72b6\u6001)\s*\n+\s*`?([a-z]+)`?\s*$",
440441
)
441442
for pattern in patterns:

skills/docs-governance/scripts/audit-docs.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -344,8 +344,9 @@ def check_status_resurrection(
344344
resurrected: list[str] = []
345345
if match:
346346
for value in CODE_PATH_RE.findall(match.group("body")):
347-
if plausible_deletion_path(value):
348-
resolved = resolve_within_root(root, root, value)
347+
normalized = value.replace("\\", "/")
348+
if plausible_deletion_path(normalized):
349+
resolved = resolve_within_root(root, root, normalized)
349350
if resolved is not None and resolved.exists():
350351
resurrected.append(value)
351352
if resurrected:
@@ -435,7 +436,7 @@ def check_log(
435436

436437
def parse_adr_status(text: str) -> str | None:
437438
patterns = (
438-
r"(?im)^(?:[-*]\s+)?(?:\*\*(?:status|\u72b6\u6001)\*\*|(?:status|\u72b6\u6001))\s*[:\uFF1A]\s*`?([a-z]+)`?(?:\s+by\s+ADR-\d+)?\s*$",
439+
r"(?im)^(?:[-*]\s+)?(?:\*\*(?:status|\u72b6\u6001)\*\*|(?:status|\u72b6\u6001))\s*[:\uFF1A]\s*`?([a-z]+)`?(?:\s+by\s+ADR-\d{3,4})?\s*$",
439440
r"(?im)^##\s+(?:status|\u72b6\u6001)\s*\n+\s*`?([a-z]+)`?\s*$",
440441
)
441442
for pattern in patterns:

tests/test_docs_governance_audit.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,20 @@ def test_adr_scope_rejects_missing_inline_superseded_successor(project: Path) ->
400400
assert "ADR inline successor does not exist" in result.stdout
401401

402402

403+
def test_adr_scope_rejects_short_inline_superseded_successor(project: Path) -> None:
404+
adr_dir = project / "docs" / "adr"
405+
adr_dir.mkdir(parents=True)
406+
(adr_dir / "README.md").write_text(
407+
"[decision](0001-storage.md)\n", encoding="utf-8"
408+
)
409+
(adr_dir / "0001-storage.md").write_text(
410+
"# ADR-0001\n\n**Status**: superseded by ADR-42\n", encoding="utf-8"
411+
)
412+
result = run_audit(project, "adr")
413+
assert result.returncode == 1
414+
assert "ADR has no parseable status" in result.stdout
415+
416+
403417
def test_adr_scope_audits_common_adr_prefixed_filenames(project: Path) -> None:
404418
adr_dir = project / "docs" / "adr"
405419
adr_dir.mkdir(parents=True)
@@ -567,6 +581,19 @@ def test_spine_scope_detects_recreated_root_level_deletion_zone_file(
567581
assert "Deletion-zone target has been recreated" in result.stdout
568582

569583

584+
def test_spine_scope_detects_windows_path_deletion_zone_file(project: Path) -> None:
585+
target = project / "subdir" / "legacy.py"
586+
target.parent.mkdir()
587+
target.write_text("# recreated\n", encoding="utf-8")
588+
(project / "PROJECT_STATUS.md").write_text(
589+
"# Status\n\n## Deletion Zone\n\n- `subdir\\\\legacy.py`\n",
590+
encoding="utf-8",
591+
)
592+
result = run_audit(project, "spine")
593+
assert result.returncode == 1
594+
assert "Deletion-zone target has been recreated" in result.stdout
595+
596+
570597
@pytest.mark.parametrize(
571598
"value",
572599
(

0 commit comments

Comments
 (0)