diff --git a/core/cli_test.py b/core/cli_test.py index 4e7aeaff..1e207bf1 100644 --- a/core/cli_test.py +++ b/core/cli_test.py @@ -26,6 +26,16 @@ TEST_SUITES: dict[str, tuple[str, ...]] = { "tests/test_runtime_config.py", "tests/test_cognitive_turn_pipeline.py", "tests/test_architectural_invariants.py", + # Audio sensorium lane — part of the smoke.yml PR gate (compiler, + # CRDT merge, eval gates, pack manifest, mount, teachers; ~3s). + # Listed explicitly so the local-first pre-push gate (AGENTS.md + # protocol) equals the CI gate rather than silently narrowing it. + "tests/test_audio_compiler.py", + "tests/test_audio_crdt_merge.py", + "tests/test_audio_eval_gates.py", + "tests/test_audio_pack_manifest.py", + "tests/test_audio_sensorium_mount.py", + "tests/test_audio_teachers.py", # ADR-0043 — identity falsifiability: ratified identity packs must # produce distinct, directionally-correct articulations, with a # pack-invariant grounding/refusal floor and zero fabrication. Lives diff --git a/tests/test_cli_test_suites.py b/tests/test_cli_test_suites.py index 5800519a..71147c7e 100644 --- a/tests/test_cli_test_suites.py +++ b/tests/test_cli_test_suites.py @@ -46,6 +46,39 @@ def test_core_test_lists_curated_suites(capsys) -> None: assert "full" in captured.out.splitlines() +def test_cli_smoke_suite_covers_ci_smoke_gate() -> None: + """Local-first parity pin: the CLI ``smoke`` suite must cover every test + path the CI smoke gate (.github/workflows/smoke.yml) runs. + + AGENTS.md makes ``core test --suite smoke`` the mandatory pre-push gate; + if the CI yaml gains a path the CLI tuple lacks, the local gate silently + narrows and regressions clear it — this pin makes that divergence loud. + """ + from core.cli_test import TEST_SUITES + + root = Path(__file__).resolve().parents[1] + workflow = (root / ".github/workflows/smoke.yml").read_text(encoding="utf-8") + + ci_paths: set[str] = set() + for token in workflow.split(): + token = token.strip("\\\"'") + if not token.startswith("tests/"): + continue + if "*" in token: + matches = sorted(root.glob(token)) + assert matches, f"CI smoke glob {token!r} matches no files" + ci_paths.update(str(m.relative_to(root)) for m in matches) + else: + ci_paths.add(token) + + assert ci_paths, "no tests/ paths parsed from smoke.yml — pin needs updating" + missing = ci_paths - set(TEST_SUITES["smoke"]) + assert not missing, ( + "CLI smoke suite is narrower than the CI smoke gate; add to " + f"core/cli_test.py TEST_SUITES['smoke']: {sorted(missing)}" + ) + + def test_core_test_suite_expands_to_expected_pytest_paths(monkeypatch) -> None: calls: list[tuple[str, ...]] = []