diff --git a/docs/install.md b/docs/install.md index a5888cd5..0aa5017d 100644 --- a/docs/install.md +++ b/docs/install.md @@ -121,8 +121,8 @@ instead — same call everywhere else. Full walkthrough: [quickstart](quickstart-skill.md). !!! tip "Inspect a port with `--dry-run`" - All nineteen print their configuration and return **with no model call and - no API key**. The eight benchmark-faithful ones return before touching data + All 20 algorithm ports print their configuration and return **with no model call + and no API key**. The eight benchmark-faithful ones return before touching data as well; the eleven `MethodPolicy` ports build their policy first, so one on a real benchmark downloads and caches its split during a dry run and says so. diff --git a/docs/testing-the-plugins.md b/docs/testing-the-plugins.md index e3a0ebff..e156c6f3 100644 --- a/docs/testing-the-plugins.md +++ b/docs/testing-the-plugins.md @@ -192,8 +192,9 @@ async def main(): asyncio.run(main()) ``` -Expected: the eight tools (`apply cancel doctor plan resume show start status`) -and a doctor report. +Expected tools: `apply cancel doctor plan resume show start status audit_drift +audit_pending audit_recompute audit_rescan audit_resolve audit_scorecard audit_status` +and a doctor report (15 total: eight run-lifecycle tools and seven audit tools). ## 6. The web panel diff --git a/tests/test_install_port_count.py b/tests/test_install_port_count.py new file mode 100644 index 00000000..2b36d271 --- /dev/null +++ b/tests/test_install_port_count.py @@ -0,0 +1,34 @@ +"""Keep the install guide's dry-run claim in sync with the port catalogue.""" + +from pathlib import Path +import re + + +ROOT = Path(__file__).resolve().parents[1] + + +def _algorithm_rows(section: str) -> int: + """Count named algorithm rows in one catalogue section.""" + return sum(line.startswith("| **") for line in section.splitlines()) + + +def test_install_guide_names_the_current_number_of_dry_run_ports(): + catalogue = (ROOT / "docs" / "self-evolution-examples.md").read_text() + install = (ROOT / "docs" / "install.md").read_text() + + headings = ( + "### The eight benchmark-faithful ports", + "### The eleven microports and analogues", + "### The twentieth: Genesis, at the standard seams", + ) + sections = [] + for heading in headings: + start = catalogue.index(heading) + following = re.search(r"^### ", catalogue[start + len(heading):], re.MULTILINE) + end = start + len(heading) + following.start() if following else len(catalogue) + sections.append(catalogue[start:end]) + + total = sum(_algorithm_rows(section) for section in sections) + assert total == 20 + assert f"All {total} algorithm ports print" in install + assert "All nineteen" not in install diff --git a/tests/test_mcp.py b/tests/test_mcp.py index decc0c10..9e7c2b0a 100644 --- a/tests/test_mcp.py +++ b/tests/test_mcp.py @@ -2,7 +2,9 @@ import json import os +import re import time +from pathlib import Path import pytest @@ -98,6 +100,17 @@ def test_resources_are_json(store, tmp_path): assert "error" in json.loads(t.rounds_resource("nope")) +def test_standalone_mcp_guide_lists_every_registered_tool(): + guide = ( + Path(__file__).resolve().parents[1] / "docs" / "testing-the-plugins.md" + ).read_text() + expected = re.search(r"Expected tools: `([^`]+)`", guide) + assert expected is not None + documented = set(expected.group(1).split()) + assert documented == set(TOOL_DESCRIPTIONS) + assert len(documented) == 15 + + def test_every_tool_has_a_description_written_for_the_model(): for name, text in TOOL_DESCRIPTIONS.items(): assert len(text) > 60, name