scripts/tests/reproduction_cli/test_verify_chain.py
scripts/tests/reproduction_cli/test_verify_chain.pyBrowse 41 files
2,042 tokens
7,605 bytes
Token encoding: o200k_base
Snapshot a9fb1c3
← Back to SKILL.md
1import sys2from pathlib import Path3 4import pytest5 6sys.path.insert(0, str(Path(__file__).resolve().parents[2]))7 8from cli_testlib import _chain, _commit, _git, _write, _write_stub_proof9from mechanical_refactor_proof_generator import generate_range10from mechanical_refactor_reproduction_cli import (11 VERDICT_FAIL,12 VERDICT_HUMAN_REVIEW,13 VERDICT_PASS,14 ChainVerificationError,15 main,16 verify_chain,17)18 19 20def test_chain_of_proved_and_declared_commits_passes(21 repo: Path, tmp_path: Path22) -> None:23 """A proved mechanical commit plus a declared non-mechanical one verifies as PASS."""24 proof = tmp_path / "proof"25 base, shas = _chain(26 repo,27 ["mechanical_provable: move foo", "non_mechanical_provable: rework bar"],28 )29 _write_stub_proof(proof, shas[0])30 31 result = verify_chain(base=base, branch="chain", proof=proof, repo_root=str(repo))32 33 assert [v.verdict for v in result.verdicts] == [VERDICT_PASS, VERDICT_HUMAN_REVIEW]34 assert result.passed35 36 37def test_failing_proof_fails_the_commit_and_the_chain(38 repo: Path, tmp_path: Path39) -> None:40 """A proof that exits non-zero yields FAIL with the output tail in the detail."""41 proof = tmp_path / "proof"42 base, shas = _chain(repo, ["mechanical_provable: move foo"])43 _write_stub_proof(proof, shas[0], passing=False)44 45 result = verify_chain(base=base, branch="chain", proof=proof, repo_root=str(repo))46 47 assert result.verdicts[0].verdict == VERDICT_FAIL48 assert "RESIDUAL" in result.verdicts[0].detail49 assert not result.passed50 51 52def test_proof_exiting_zero_without_a_pass_line_is_a_fail(53 repo: Path, tmp_path: Path54) -> None:55 """PASS needs exit 0 AND the PASS: verdict line, so a residual under exit 0 fails."""56 proof = tmp_path / "proof"57 base, shas = _chain(repo, ["mechanical_provable: move foo"])58 script = _write_stub_proof(proof, shas[0])59 script.write_text('print("RESIDUAL (1 lines):\\n+x")\n')60 61 result = verify_chain(base=base, branch="chain", proof=proof, repo_root=str(repo))62 63 assert result.verdicts[0].verdict == VERDICT_FAIL64 65 66def test_main_exit_codes_reflect_the_chain_verdict(repo: Path, tmp_path: Path) -> None:67 """main returns 0 for a verified chain and 1 once an unverifiable commit appears."""68 proof = tmp_path / "proof"69 base, shas = _chain(repo, ["mechanical_provable: move"])70 _write_stub_proof(proof, shas[0])71 args = [72 "--base",73 base,74 "--branch",75 "chain",76 "--proof",77 str(proof),78 "--repo-root",79 str(repo),80 ]81 82 assert main(args) == 083 84 _git(repo, "commit", "-q", "--allow-empty", "-m", "plain subject with no kind word")85 assert main(args) == 186 87 88def test_unresolvable_refs_and_missing_proof_folder_are_setup_errors(89 repo: Path, tmp_path: Path90) -> None:91 """Bad --base/--branch/--proof inputs raise ChainVerificationError (exit code 2)."""92 proof = tmp_path / "proof"93 proof.mkdir()94 base, _ = _chain(repo, ["mechanical_provable: move"])95 96 with pytest.raises(ChainVerificationError):97 verify_chain(98 base=base, branch="no-such-branch", proof=proof, repo_root=str(repo)99 )100 with pytest.raises(ChainVerificationError):101 verify_chain(102 base=base,103 branch="chain",104 proof=tmp_path / "missing",105 repo_root=str(repo),106 )107 assert (108 main(109 [110 "--base",111 base,112 "--branch",113 "no-such-branch",114 "--proof",115 str(proof),116 "--repo-root",117 str(repo),118 ]119 )120 == 2121 )122 123 124def test_non_ancestor_base_and_empty_range_are_setup_errors(125 repo: Path, tmp_path: Path126) -> None:127 """A base off the branch or an empty base..branch range refuses to verify."""128 proof = tmp_path / "proof"129 proof.mkdir()130 base, shas = _chain(repo, ["mechanical_provable: move"])131 _git(repo, "switch", "-q", "main")132 _write(repo, **{"other.py": "OTHER = 1\n"})133 off_branch = _commit(repo, "unrelated main-side commit")134 135 with pytest.raises(ChainVerificationError):136 verify_chain(base=off_branch, branch="chain", proof=proof, repo_root=str(repo))137 with pytest.raises(ChainVerificationError):138 verify_chain(base=shas[0], branch=shas[0], proof=proof, repo_root=str(repo))139 140 141def test_merge_commit_in_the_chain_is_a_setup_error(repo: Path, tmp_path: Path) -> None:142 """A non-linear chain (contains a merge commit) refuses to verify."""143 proof = tmp_path / "proof"144 proof.mkdir()145 base, _ = _chain(repo, ["mechanical_provable: move"])146 _git(repo, "switch", "-q", "main")147 _write(repo, **{"other.py": "OTHER = 1\n"})148 _commit(repo, "mechanical_provable: main-side")149 _git(repo, "switch", "-q", "chain")150 _git(repo, "merge", "-q", "--no-ff", "-m", "non_mechanical_provable: merge", "main")151 152 with pytest.raises(ChainVerificationError):153 verify_chain(base=base, branch="chain", proof=proof, repo_root=str(repo))154 155 156def test_proofs_run_concurrently_up_to_jobs(repo: Path, tmp_path: Path) -> None:157 """With jobs>=2 a proof that waits on a sibling proof's sentinel still completes."""158 proof = tmp_path / "proof"159 sentinel = tmp_path / "sentinel"160 base, shas = _chain(161 repo, ["mechanical_provable: move a", "mechanical_provable: move b"]162 )163 waiter = _write_stub_proof(proof, shas[0])164 waiter.write_text(165 "import sys, time\n"166 f"deadline = time.monotonic() + 30\n"167 f"while not __import__('pathlib').Path({str(sentinel)!r}).exists():\n"168 " if time.monotonic() > deadline:\n"169 " sys.exit(1)\n"170 " time.sleep(0.05)\n"171 'print("PASS: reproduces the commit byte-for-byte.")\n'172 "sys.exit(0)\n"173 )174 creator = _write_stub_proof(proof, shas[1])175 creator.write_text(176 "import sys\n"177 f"__import__('pathlib').Path({str(sentinel)!r}).write_text('go')\n"178 'print("PASS: reproduces the commit byte-for-byte.")\n'179 "sys.exit(0)\n"180 )181 182 result = verify_chain(183 base=base, branch="chain", proof=proof, repo_root=str(repo), jobs=2184 )185 186 assert [v.verdict for v in result.verdicts] == [VERDICT_PASS, VERDICT_PASS]187 assert [v.sha for v in result.verdicts] == shas188 assert result.passed189 190 191def test_end_to_end_with_a_generated_proof_folder(repo: Path, tmp_path: Path) -> None:192 """A real move commit proved by generate_range verifies through the CLI end-to-end."""193 _write(194 repo,195 **{196 "model.py": "def keep():\n return 0\n\n\ndef resolve(m):\n return m\n",197 "util.py": "import os\n",198 },199 )200 base = _commit(repo, "base")201 _git(repo, "switch", "-q", "-c", "chain")202 # The after-state is the primitives' exact output (this bare repo has no formatter203 # to absorb the cut's leftover blank lines, unlike a pre-commit-clean real repo).204 _write(205 repo,206 **{207 "model.py": "def keep():\n return 0\n\n\n",208 "util.py": "import os\n\ndef resolve(m):\n return m\n",209 },210 )211 move_sha = _commit(repo, "mechanical_provable: move resolve to util")212 213 proof = tmp_path / "proof"214 generate_range(f"{base}..chain", out_dir=str(proof), repo_root=str(repo))215 result = verify_chain(base=base, branch="chain", proof=proof, repo_root=str(repo))216 217 assert result.verdicts[0].sha == move_sha218 assert result.verdicts[0].verdict == VERDICT_PASS219 assert result.passed220