#!/usr/bin/env python3 """Keep entry documentation, skill packaging, and the CLI surface aligned.""" from __future__ import annotations import importlib.machinery import importlib.util from pathlib import Path import subprocess import sys import unittest ROOT = Path(__file__).resolve().parents[1] class DocumentationContract(unittest.TestCase): def test_required_document_map_and_jj_policy(self) -> None: readme = (ROOT / "README.md").read_text(encoding="utf-8") claude = (ROOT / "CLAUDE.md").read_text(encoding="utf-8") agents = (ROOT / "AGENTS.md").read_text(encoding="utf-8") design = (ROOT / "DESIGN.md").read_text(encoding="utf-8") self.assertIn("[`CLAUDE.md`](CLAUDE.md)", readme) self.assertIn("[`DESIGN.md`](DESIGN.md)", readme) self.assertIn("[`CLAUDE.md`](CLAUDE.md)", agents) self.assertIn("Jujutsu (`jj`)", claude) self.assertIn("Jujutsu (`jj`)", agents) self.assertIn("Status: implemented", design) def test_readme_names_every_public_top_level_command(self) -> None: loader = importlib.machinery.SourceFileLoader("coord_docs_test", str(ROOT / "coord")) spec = importlib.util.spec_from_loader(loader.name, loader) assert spec is not None module = importlib.util.module_from_spec(spec) sys.modules[spec.name] = module loader.exec_module(module) parser = module.build_parser() choices: set[str] = set() for action in parser._actions: if hasattr(action, "choices") and isinstance(action.choices, dict): choices.update(action.choices) readme = (ROOT / "README.md").read_text(encoding="utf-8") missing = sorted(name for name in choices if f"coord {name}" not in readme) self.assertEqual(missing, [], f"README omits public commands: {missing}") def test_help_entrypoints_are_live(self) -> None: for command in ( [str(ROOT / "coord"), "--help"], [str(ROOT / "coord"), "work", "--help"], [str(ROOT / "install"), "--help"], ): result = subprocess.run( command, cwd=ROOT, text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) self.assertEqual(result.returncode, 0, result.stderr) self.assertIn("usage:", result.stdout) def test_skill_is_concise_and_has_no_placeholders(self) -> None: skill = (ROOT / "skills/coord/SKILL.md").read_text(encoding="utf-8") self.assertNotIn("TODO", skill) self.assertLess(len(skill.splitlines()), 120) for operation in ("claim", "send", "work create", "work close", "work gc"): self.assertIn(operation, skill) if __name__ == "__main__": unittest.main(verbosity=2)