f3d80b4628
Auto Release / auto-release (push) Failing after 1s
CI / lint (push) Failing after 0s
CI / screenshot-quality (push) Failing after 3s
CI / pr-policy (push) Has been skipped
CI / test (3.11) (push) Failing after 0s
CI / test (3.12) (push) Failing after 0s
CI / test (3.13) (push) Failing after 3s
CI / coverage (push) Failing after 1s
Legibility / legibility (push) Failing after 3s
228 lines
6.7 KiB
Python
228 lines
6.7 KiB
Python
#!/usr/bin/env python3
|
|
"""Unit tests for scripts/check_legibility.py."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import datetime as dt
|
|
import importlib.util
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
SCRIPT_PATH = Path(__file__).resolve().parent.parent / "scripts" / "check_legibility.py"
|
|
MODULE_NAME = "check_legibility"
|
|
AGENT_DOCS = Path(".agents") / "docs"
|
|
|
|
|
|
def _load_module():
|
|
spec = importlib.util.spec_from_file_location(MODULE_NAME, SCRIPT_PATH)
|
|
assert spec is not None
|
|
module = importlib.util.module_from_spec(spec)
|
|
assert spec.loader is not None
|
|
sys.modules[MODULE_NAME] = module
|
|
spec.loader.exec_module(module)
|
|
return module
|
|
|
|
|
|
def _write(path: Path, text: str) -> None:
|
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
path.write_text(text, encoding="utf-8")
|
|
|
|
|
|
def _base_repo(tmp_path: Path, *, last_reviewed: str = "2026-03-01", plan_status: str = "active") -> Path:
|
|
_write(
|
|
tmp_path / AGENT_DOCS / "standards" / "policy.md",
|
|
(f"---\nowner: docs-team\nlast_reviewed: {last_reviewed}\nsource_of_truth: AGENTS.md\n---\n\n# Policy\n"),
|
|
)
|
|
_write(
|
|
tmp_path / AGENT_DOCS / "architecture" / "manifest.yaml",
|
|
"expected_paths:\n - .agents/docs/standards/policy.md\n - .agents/docs/plans/plan.md\n",
|
|
)
|
|
_write(
|
|
tmp_path / AGENT_DOCS / "plans" / "plan.md",
|
|
f"---\nstatus: {plan_status}\n---\n\n# Plan\n\nNo TODO items.\n",
|
|
)
|
|
return tmp_path
|
|
|
|
|
|
def test_run_checks_happy_path(tmp_path: Path) -> None:
|
|
module = _load_module()
|
|
repo_root = _base_repo(tmp_path)
|
|
|
|
result = module.run_checks(
|
|
repo_root,
|
|
freshness_days=60,
|
|
strict_freshness=False,
|
|
today=dt.date(2026, 3, 3),
|
|
)
|
|
|
|
assert result.failures == []
|
|
assert result.warnings == []
|
|
|
|
|
|
def test_stale_standards_is_warning_in_mvp_mode(tmp_path: Path) -> None:
|
|
module = _load_module()
|
|
repo_root = _base_repo(tmp_path, last_reviewed="2025-01-01")
|
|
|
|
result = module.run_checks(
|
|
repo_root,
|
|
freshness_days=60,
|
|
strict_freshness=False,
|
|
today=dt.date(2026, 3, 3),
|
|
)
|
|
|
|
assert result.failures == []
|
|
assert any("stale" in warning for warning in result.warnings)
|
|
|
|
|
|
def test_stale_standards_fails_in_strict_mode(tmp_path: Path) -> None:
|
|
module = _load_module()
|
|
repo_root = _base_repo(tmp_path, last_reviewed="2025-01-01")
|
|
|
|
result = module.run_checks(
|
|
repo_root,
|
|
freshness_days=60,
|
|
strict_freshness=True,
|
|
today=dt.date(2026, 3, 3),
|
|
)
|
|
|
|
assert result.warnings == []
|
|
assert any("stale" in failure for failure in result.failures)
|
|
|
|
|
|
def test_missing_manifest_path_fails(tmp_path: Path) -> None:
|
|
module = _load_module()
|
|
repo_root = _base_repo(tmp_path)
|
|
_write(
|
|
repo_root / AGENT_DOCS / "architecture" / "manifest.yaml",
|
|
"expected_paths:\n - .agents/docs/standards/policy.md\n - docs/does-not-exist.md\n",
|
|
)
|
|
|
|
result = module.run_checks(
|
|
repo_root,
|
|
freshness_days=60,
|
|
strict_freshness=False,
|
|
today=dt.date(2026, 3, 3),
|
|
)
|
|
|
|
assert any("expected path missing" in failure for failure in result.failures)
|
|
|
|
|
|
def test_manifest_rejects_absolute_expected_path(tmp_path: Path) -> None:
|
|
module = _load_module()
|
|
repo_root = _base_repo(tmp_path)
|
|
_write(
|
|
repo_root / AGENT_DOCS / "architecture" / "manifest.yaml",
|
|
"expected_paths:\n - /tmp/not-allowed.md\n",
|
|
)
|
|
|
|
result = module.run_checks(
|
|
repo_root,
|
|
freshness_days=60,
|
|
strict_freshness=False,
|
|
today=dt.date(2026, 3, 3),
|
|
)
|
|
|
|
assert any("must be relative" in failure for failure in result.failures)
|
|
|
|
|
|
def test_manifest_rejects_expected_path_outside_repo_root(tmp_path: Path) -> None:
|
|
module = _load_module()
|
|
repo_root = _base_repo(tmp_path)
|
|
_write(
|
|
repo_root / AGENT_DOCS / "architecture" / "manifest.yaml",
|
|
"expected_paths:\n - ../escape.md\n",
|
|
)
|
|
|
|
result = module.run_checks(
|
|
repo_root,
|
|
freshness_days=60,
|
|
strict_freshness=False,
|
|
today=dt.date(2026, 3, 3),
|
|
)
|
|
|
|
assert any("outside repo root" in failure for failure in result.failures)
|
|
|
|
|
|
def test_completed_plan_with_unchecked_todo_fails(tmp_path: Path) -> None:
|
|
module = _load_module()
|
|
repo_root = _base_repo(tmp_path, plan_status="completed")
|
|
_write(
|
|
repo_root / AGENT_DOCS / "plans" / "plan.md",
|
|
"---\nstatus: completed\n---\n\n# Plan\n\n- [ ] unresolved item\n",
|
|
)
|
|
|
|
result = module.run_checks(
|
|
repo_root,
|
|
freshness_days=60,
|
|
strict_freshness=False,
|
|
today=dt.date(2026, 3, 3),
|
|
)
|
|
|
|
assert any("unchecked TODO" in failure for failure in result.failures)
|
|
|
|
|
|
def test_completed_plan_ignores_unchecked_todo_in_fenced_code(tmp_path: Path) -> None:
|
|
module = _load_module()
|
|
repo_root = _base_repo(tmp_path, plan_status="completed")
|
|
_write(
|
|
repo_root / AGENT_DOCS / "plans" / "plan.md",
|
|
("---\nstatus: completed\n---\n\n# Plan\n\n```markdown\n- [ ] example only\n```\n\nAll work done.\n"),
|
|
)
|
|
|
|
result = module.run_checks(
|
|
repo_root,
|
|
freshness_days=60,
|
|
strict_freshness=False,
|
|
today=dt.date(2026, 3, 3),
|
|
)
|
|
|
|
assert not any("unchecked TODO" in failure for failure in result.failures)
|
|
|
|
|
|
def test_public_docs_bilingual_pairs_pass(tmp_path: Path) -> None:
|
|
module = _load_module()
|
|
repo_root = _base_repo(tmp_path)
|
|
_write(repo_root / "README.md", "# English\n")
|
|
_write(repo_root / "README_zh.md", "# 中文\n")
|
|
_write(repo_root / "docs" / "guides" / "feature.md", "# Feature\n")
|
|
_write(repo_root / "docs" / "guides" / "feature.zh.md", "# 功能\n")
|
|
|
|
result = module.run_checks(
|
|
repo_root,
|
|
freshness_days=60,
|
|
strict_freshness=False,
|
|
today=dt.date(2026, 3, 3),
|
|
)
|
|
|
|
assert result.failures == []
|
|
|
|
|
|
def test_public_docs_missing_chinese_counterpart_fails(tmp_path: Path) -> None:
|
|
module = _load_module()
|
|
repo_root = _base_repo(tmp_path)
|
|
_write(repo_root / "docs" / "guides" / "feature.md", "# Feature\n")
|
|
|
|
result = module.run_checks(
|
|
repo_root,
|
|
freshness_days=60,
|
|
strict_freshness=False,
|
|
today=dt.date(2026, 3, 3),
|
|
)
|
|
|
|
assert any("missing Simplified Chinese counterpart" in failure for failure in result.failures)
|
|
|
|
|
|
def test_public_docs_missing_english_counterpart_fails(tmp_path: Path) -> None:
|
|
module = _load_module()
|
|
repo_root = _base_repo(tmp_path)
|
|
_write(repo_root / "docs" / "guides" / "feature.zh.md", "# 功能\n")
|
|
|
|
result = module.run_checks(
|
|
repo_root,
|
|
freshness_days=60,
|
|
strict_freshness=False,
|
|
today=dt.date(2026, 3, 3),
|
|
)
|
|
|
|
assert any("missing English counterpart" in failure for failure in result.failures)
|