From f6b2609d60063c89c7c8e6e132884c30f81ae803 Mon Sep 17 00:00:00 2001 From: Artur Shiriev Date: Sat, 19 Sep 2026 13:20:31 +0300 Subject: [PATCH] test: report a bare docs/adr/NNNN citation as unresolved --- tests/test_adr_citations.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/tests/test_adr_citations.py b/tests/test_adr_citations.py index 760f6f1..7f7706c 100644 --- a/tests/test_adr_citations.py +++ b/tests/test_adr_citations.py @@ -7,7 +7,7 @@ _REPO_ROOT: typing.Final = pathlib.Path(__file__).resolve().parent.parent _ADR_DIR: typing.Final = "docs/adr/" -_CITATION: typing.Final = re.compile(r"docs/adr/\d{4}-[a-z0-9-]+\.md") +_CITATION: typing.Final = re.compile(r"docs/adr/\d{4}(?:-[a-z0-9-]+\.md)?") _UNWALKED_DIR: typing.Final = "node_modules" @@ -45,6 +45,8 @@ def test_every_adr_path_cited_from_python_resolves() -> None: offline link gate reads Markdown only, so a path in a docstring, a comment or a guard message is otherwise checked by nothing, and an `INVARIANT:` docstring that names its ADR silently loses the rationale the test depends on. A user who trips a guard is handed a link to follow. + A bare `docs/adr/NNNN` is reported as well: it names no file, so it would survive the same + rename or drop unnoticed and point at whatever record holds that number next. """ unresolved = unresolved_citations(_REPO_ROOT) @@ -64,6 +66,18 @@ def test_a_citation_of_a_missing_adr_is_reported_with_its_citing_file(tmp_path: assert unresolved_citations(tmp_path) == [("pkg/mod.py", f"{_ADR_DIR}9999-missing.md")] +def test_a_short_form_citation_is_reported_even_when_the_adr_exists(tmp_path: pathlib.Path) -> None: + """`docs/adr/NNNN` with no slug names nothing on disk, so a rename or a drop never breaks it.""" + (tmp_path / _ADR_DIR).mkdir(parents=True) + (tmp_path / _ADR_DIR / "0002-kept.md").write_text("# kept\n", encoding="utf-8") + (tmp_path / "pkg").mkdir() + (tmp_path / "pkg" / "mod.py").write_text( + f'"""Argued in {_ADR_DIR}0002 and {_ADR_DIR}0002-kept.md."""\n', encoding="utf-8" + ) + + assert unresolved_citations(tmp_path) == [("pkg/mod.py", f"{_ADR_DIR}0002")] + + def test_a_citation_split_across_adjacent_string_literals_is_found(tmp_path: pathlib.Path) -> None: """Python joins adjacent literals at parse time, which is what the `nack` guard message relies on.""" (tmp_path / "guard.py").write_text(