From 188bdf2d6a7daa7dcfaab60af904a41fdada50d8 Mon Sep 17 00:00:00 2001 From: Seekers2001 Date: Wed, 9 Sep 2026 17:35:35 +0800 Subject: [PATCH] fix(governance): validate shortcut references before colons --- .../skills/docs-governance/scripts/markdown_links.py | 10 ++++++++-- skills/docs-governance/scripts/markdown_links.py | 10 ++++++++-- tests/test_docs_governance_audit.py | 11 +++++++++++ 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/.agents/skills/docs-governance/scripts/markdown_links.py b/.agents/skills/docs-governance/scripts/markdown_links.py index a7b9ed63e..2c1d3c741 100644 --- a/.agents/skills/docs-governance/scripts/markdown_links.py +++ b/.agents/skills/docs-governance/scripts/markdown_links.py @@ -139,14 +139,20 @@ def normalize_reference_label(label: str) -> str: def reference_link_targets(text: str) -> list[str]: + definition_matches = list(REFERENCE_DEFINITION_RE.finditer(text)) definitions = { normalize_reference_label(match.group("label")): match.group("target") - for match in REFERENCE_DEFINITION_RE.finditer(text) + for match in definition_matches } targets: list[str] = [] for match in REFERENCE_USAGE_RE.finditer(text): + if any( + definition.start() <= match.start() < definition.end() + for definition in definition_matches + ): + continue following = text[match.end() : match.end() + 1] - if following in {"(", ":"}: + if following == "(": continue label = match.group("label") key = normalize_reference_label(label or match.group("text")) diff --git a/skills/docs-governance/scripts/markdown_links.py b/skills/docs-governance/scripts/markdown_links.py index a7b9ed63e..2c1d3c741 100644 --- a/skills/docs-governance/scripts/markdown_links.py +++ b/skills/docs-governance/scripts/markdown_links.py @@ -139,14 +139,20 @@ def normalize_reference_label(label: str) -> str: def reference_link_targets(text: str) -> list[str]: + definition_matches = list(REFERENCE_DEFINITION_RE.finditer(text)) definitions = { normalize_reference_label(match.group("label")): match.group("target") - for match in REFERENCE_DEFINITION_RE.finditer(text) + for match in definition_matches } targets: list[str] = [] for match in REFERENCE_USAGE_RE.finditer(text): + if any( + definition.start() <= match.start() < definition.end() + for definition in definition_matches + ): + continue following = text[match.end() : match.end() + 1] - if following in {"(", ":"}: + if following == "(": continue label = match.group("label") key = normalize_reference_label(label or match.group("text")) diff --git a/tests/test_docs_governance_audit.py b/tests/test_docs_governance_audit.py index dfdf4587d..f3b067ad3 100644 --- a/tests/test_docs_governance_audit.py +++ b/tests/test_docs_governance_audit.py @@ -309,6 +309,17 @@ def test_artifact_scope_checks_reference_style_markdown_links( assert "missing-guide.md" in result.stdout +def test_artifact_scope_checks_shortcut_reference_followed_by_colon( + project: Path, +) -> None: + (project / "index.md").write_text( + "See [docs]: details\n\n[docs]: missing-guide.md\n", encoding="utf-8" + ) + result = run_audit(project, "artifacts") + assert result.returncode == 1 + assert "Broken Markdown link: 'index.md' -> 'missing-guide.md'" in result.stdout + + @pytest.mark.parametrize("target_line", (" missing-guide.md", "missing-guide.md")) def test_artifact_scope_checks_continuation_line_reference_target( project: Path, target_line: str