diff --git a/tests/test_anchor_prg.py b/tests/test_anchor_prg.py index 7129974..cc6bdbf 100644 --- a/tests/test_anchor_prg.py +++ b/tests/test_anchor_prg.py @@ -311,6 +311,11 @@ def test_phi_prg_rejects_non_int_dim_h(): def test_module_exports_version_string(): assert PHI_PRG_VERSION == "phi-prg-v1-hmac-sha512" + # versioned-default discipline (calculator-test-patterns.md §2): + # "v1" substring present so future major-version rotations + # (v2-blake3-expansion etc.) are detectable at the call site + # without string-comparing module paths. + assert "v1" in PHI_PRG_VERSION def test_placeholder_seed_is_32_bytes(): diff --git a/tests/test_phi_alignment_probe.py b/tests/test_phi_alignment_probe.py index b0b54d3..9853b62 100644 --- a/tests/test_phi_alignment_probe.py +++ b/tests/test_phi_alignment_probe.py @@ -180,6 +180,11 @@ def test_alignment_report_round_trips_via_asdict(): def test_module_exports_thresholds_and_version(): assert PROBE_VERSION == "phi-alignment-v1-lanczos" + # versioned-default discipline (calculator-test-patterns.md §2): + # "v1" substring present so future major-version rotations are + # detectable at the call site without string-comparing module + # paths. + assert "v1" in PROBE_VERSION assert STRUCTURAL_ALIGNMENT_RATIO_FLOOR == 1.5 assert ANTI_ALIGNED_RATIO_CEILING == 0.7 assert DEFAULT_K_TOP == 100 diff --git a/tests/test_v8_fork_score.py b/tests/test_substrate_fork_score.py similarity index 89% rename from tests/test_v8_fork_score.py rename to tests/test_substrate_fork_score.py index 92d7032..0aa5805 100644 --- a/tests/test_v8_fork_score.py +++ b/tests/test_substrate_fork_score.py @@ -14,6 +14,8 @@ Covers: from __future__ import annotations import json +import subprocess +import sys from pathlib import Path import pytest @@ -505,3 +507,56 @@ def test_score_is_dict_serializable(): encoded = json.dumps(sf.to_dict(), default=str) decoded = json.loads(encoded) assert decoded["verdict"] == sf.verdict + + +# --------------------------------------------------------------------- +# Real subprocess-mode CLI test (calculator-test-patterns.md §6). +# The in-process build_parser() tests above catch argparse-shape drift +# but NOT entry-point / module-loading / sys.argv drift. fox's +# test_cli_baseline_runs_clean in test_t3_bound_calculator.py is the +# exemplar; this test mirrors that pattern for `arborist substrate score`. +# --------------------------------------------------------------------- + + +def test_cli_substrate_score_subprocess_invocation(tmp_path): + """Real subprocess-mode invocation of `arborist substrate score`. + + Catches drift at the entry-point + module-loading layer that the + in-process build_parser() tests would miss — e.g. a refactor that + breaks the console-script in pyproject.toml, or that introduces a + sys.argv-handling bug. + + Pattern: docs/calculator-test-patterns.md §6 + the substrate + rename's three-defect lesson (85be5eb fork_score.py import, + 209d670 Makefile bench-fork-score, b320e27 .gitlab-ci.yml job). + """ + parent_path = tmp_path / "parent.json" + child_path = tmp_path / "child.json" + out_path = tmp_path / "report.json" + _write_bench_result(parent_path, { + "5s": {"syntax": {"parse_pass_rate": 0.80}}, + "5t": {}, "5f": {}, + }) + _write_bench_result(child_path, { + "5s": {"syntax": {"parse_pass_rate": 0.85}}, + "5t": {}, "5f": {}, + }) + + cmd = [ + sys.executable, "-m", "arborist.cli", + "substrate", "score", + "--parent", str(parent_path), + "--child", str(child_path), + "--out", str(out_path), + ] + out = subprocess.run( + cmd, capture_output=True, text=True, check=True, + cwd="/home/fox/git/arborist", + ) + # Exit code 0 = ACCEPT or MARGINAL per ScoredFork verdict + # discipline. Subprocess.run(check=True) already asserts it. + assert out_path.exists(), "expected --out artifact written" + artifact = json.loads(out_path.read_text()) + assert "score" in artifact + assert "verdict" in artifact + assert artifact["verdict"] in {"ACCEPT", "MARGINAL", "REJECT"}