"""Explicit experimental repin and historical-source provenance contracts.""" import hashlib import json from pathlib import Path import subprocess import sys ROOT = Path(__file__).resolve().parents[2] sys.path.insert(0, str(ROOT / "tests/validation")) import pytest from source_provenance import (HistoryUnavailable, checkout_provenance, historical_sha256, historical_tree, history_unavailable, verify_manifest) import unittest import re100_helpers import run_jet_circle_cv ORIGIN = "47b05bc8abfc957fe876b0c63bdb386e3c6cbaa5" def test_manifests_match_their_recorded_source_and_preserve_origin(): """Historical evidence integrity: each manifest describes the tree of its own commit.""" manifests = [] for group, hashes_key, revision_key in ( ("dfg_re100", "production_sha256", "commit"), ("jet_circle_cv", "files", "revision"), ): manifest = json.loads( ( ROOT / "tests/validation/data" / group / "source_manifest.json" ).read_text() ) # Structural checks need no history and always run. assert manifest[revision_key] == ORIGIN assert manifest["source_origin_commits"][-1] == ORIGIN assert ( manifest["historical_checkpoints"]["production"] == "d79e3f6f0a424f5bcc3a1a6d610313e49daf97a2" ) assert "not inherited from d79" in manifest["experiment"] manifests.append(manifest[hashes_key]) try: names = historical_tree(ROOT, ORIGIN) for digests in manifests: assert set(digests) == set(names) verify_manifest(ROOT, ORIGIN, digests) except HistoryUnavailable as error: history_unavailable(unittest.TestCase(), error) assert re100_helpers.PIN == run_jet_circle_cv.PIN == ORIGIN def test_runtime_checkout_identity_is_separate_from_source_origin(tmp_path): subprocess.run(["git", "init", "-q", str(tmp_path)], check=True) (tmp_path / "test.txt").write_text("tracked\n") subprocess.run(["git", "-C", str(tmp_path), "add", "test.txt"], check=True) subprocess.run( [ "git", "-C", str(tmp_path), "-c", "user.name=Test", "-c", "user.email=test@example.invalid", "commit", "-qm", "fixture", ], check=True, ) expected = subprocess.check_output( ["git", "-C", str(tmp_path), "rev-parse", "HEAD"], text=True ).strip() assert checkout_provenance(tmp_path) == dict( checkout_revision=expected, checkout_dirty=False ) (tmp_path / "test.txt").write_text("changed\n") assert checkout_provenance(tmp_path) == dict( checkout_revision=expected, checkout_dirty=True ) def test_historical_check_rejects_tampering_and_reports_missing_history(tmp_path): with pytest.raises(HistoryUnavailable): historical_sha256(tmp_path, ORIGIN, ["src/x.py"]) # not a repository with pytest.raises(HistoryUnavailable): historical_sha256(ROOT, "0" * 40, ["src/x.py"]) # commit absent manifest = json.loads( (ROOT / "tests/validation/data/dfg_re100/source_manifest.json").read_text()) digests = dict(manifest["production_sha256"]) name = sorted(digests)[0] tampered = dict(digests, **{name: ("0" if digests[name][0] != "0" else "1") + digests[name][1:]}) try: historical_tree(ROOT, ORIGIN) except HistoryUnavailable as error: history_unavailable(unittest.TestCase(), error) with pytest.raises(RuntimeError, match="Historical manifest mismatch"): verify_manifest(ROOT, ORIGIN, tampered) # one flipped digest is caught with pytest.raises(ValueError, match="not part of"): historical_sha256(ROOT, ORIGIN, ["src/CelerisLab/does_not_exist.py"])