Files
CelerisLab/tests/unit/test_validation_source_provenance.py
T
ClaudeandClaude Opus 5.5 8064834c37 test: tighten historical-pin checks per review of 941eb28b
- test_refined_dfg::test_source_pin runs its mismatch negative controls
  first (now including window mode) so missing history cannot skip them.
- test_re100: renamed to test_manifest_matches_its_pinned_commit, plus an
  explicit record that today's src differs from the pin.
- Structural manifest checks run before any history-dependent check.
- Real tamper test: a flipped digest raises via verify_manifest, and a
  path absent at the commit raises ValueError.
- A blobless clone (tree present, blob missing) is reported as unavailable
  history, not as a missing path.
- All history skips go through history_unavailable(): fatal when
  CELERIS_REQUIRE_HISTORY=1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 18:28:09 +00:00

101 lines
3.8 KiB
Python

"""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"])