Files
boshu2__agentops/tests/python/test_check_t0_evidence.py

471 lines
21 KiB
Python

from __future__ import annotations
import copy
import hashlib
import importlib.util
import json
from pathlib import Path
import shutil
import subprocess
import sys
import tempfile
import unittest
ROOT = Path(__file__).resolve().parents[2]
CHECKER = ROOT / "scripts" / "check-t0-evidence.py"
EVIDENCE = ROOT / "docs" / "evidence" / "proof-epochs" / "epoch-0"
SPEC = importlib.util.spec_from_file_location("agentops_check_t0_evidence", CHECKER)
assert SPEC is not None and SPEC.loader is not None
CHECK_MODULE = importlib.util.module_from_spec(SPEC)
SPEC.loader.exec_module(CHECK_MODULE)
class T0EvidenceCheckTest(unittest.TestCase):
def run_checker(
self, repository: Path, evidence: Path
) -> subprocess.CompletedProcess[str]:
return subprocess.run(
[
sys.executable,
str(CHECKER),
"--repository",
str(repository),
"--evidence-root",
str(evidence),
],
text=True,
capture_output=True,
check=False,
)
def test_live_t0_ledgers_are_coherent(self) -> None:
result = self.run_checker(ROOT, EVIDENCE)
self.assertEqual(result.returncode, 0, result.stderr)
self.assertEqual(json.loads(result.stdout)["skill_count"], 49)
def test_seeded_skill_digest_mutation_is_detected(self) -> None:
with tempfile.TemporaryDirectory() as temporary:
evidence = Path(temporary) / "evidence"
shutil.copytree(EVIDENCE, evidence)
ledger = json.loads((evidence / "t0-skill-ledger.json").read_text())
ledger["skills"][0]["sha256"] = "0" * 64
(evidence / "t0-skill-ledger.json").write_text(json.dumps(ledger))
result = self.run_checker(ROOT, evidence)
self.assertNotEqual(result.returncode, 0)
self.assertIn("T0 skill ledger bytes changed", result.stderr)
def test_seeded_routing_summary_mismatch_is_detected(self) -> None:
with tempfile.TemporaryDirectory() as temporary:
evidence = Path(temporary)
shutil.copytree(EVIDENCE, evidence, dirs_exist_ok=True)
routing_path = evidence / "routing-baseline.json"
routing = json.loads(routing_path.read_text())
routing["observation"]["summary"]["acceptable"] += 1
routing_path.write_text(json.dumps(routing))
result = self.run_checker(ROOT, evidence)
self.assertNotEqual(result.returncode, 0)
self.assertIn("routing assessment summary", result.stderr)
def test_pause_lineage_removal_is_detected_despite_pass_result(self) -> None:
with tempfile.TemporaryDirectory() as temporary:
evidence = Path(temporary)
shutil.copytree(EVIDENCE, evidence, dirs_exist_ok=True)
pause_path = evidence / "t0-pause-drill.json"
pause = json.loads(pause_path.read_text())
pause["lineage"] = {}
pause_path.write_text(json.dumps(pause))
result = self.run_checker(ROOT, evidence)
self.assertNotEqual(result.returncode, 0)
self.assertIn("pause drill lineage", result.stderr)
def test_pause_rejected_proof_authority_is_detected(self) -> None:
with tempfile.TemporaryDirectory() as temporary:
evidence = Path(temporary)
shutil.copytree(EVIDENCE, evidence, dirs_exist_ok=True)
pause_path = evidence / "t0-pause-drill.json"
pause = json.loads(pause_path.read_text())
pause["authority"]["proof_contract_ref"] = (
"docs/contracts/proof-contracts/epoch-0/descriptor.json"
)
pause_path.write_text(json.dumps(pause))
result = self.run_checker(ROOT, evidence)
self.assertNotEqual(result.returncode, 0)
self.assertIn("pause drill authority", result.stderr)
def test_pause_false_t1_completion_is_detected(self) -> None:
with tempfile.TemporaryDirectory() as temporary:
evidence = Path(temporary)
shutil.copytree(EVIDENCE, evidence, dirs_exist_ok=True)
pause_path = evidence / "t0-pause-drill.json"
pause = json.loads(pause_path.read_text())
pause["progress"]["states"]["T1"] = "COMPLETE"
pause_path.write_text(json.dumps(pause))
result = self.run_checker(ROOT, evidence)
self.assertNotEqual(result.returncode, 0)
self.assertIn("pause drill typed progress", result.stderr)
def test_pause_semantic_completion_in_safe_stop_claim_is_detected(self) -> None:
with tempfile.TemporaryDirectory() as temporary:
evidence = Path(temporary)
shutil.copytree(EVIDENCE, evidence, dirs_exist_ok=True)
pause_path = evidence / "t0-pause-drill.json"
pause = json.loads(pause_path.read_text())
pause["safe_stop_claim"] += " T1 is complete and epoch 1 is active."
pause_path.write_text(json.dumps(pause))
result = self.run_checker(ROOT, evidence)
self.assertNotEqual(result.returncode, 0)
self.assertIn("safe-stop claim", result.stderr)
def test_pause_semantic_completion_in_extra_gap_is_detected(self) -> None:
with tempfile.TemporaryDirectory() as temporary:
evidence = Path(temporary)
shutil.copytree(EVIDENCE, evidence, dirs_exist_ok=True)
pause_path = evidence / "t0-pause-drill.json"
pause = json.loads(pause_path.read_text())
pause["known_gaps"].append("T1 has completed")
pause_path.write_text(json.dumps(pause))
result = self.run_checker(ROOT, evidence)
self.assertNotEqual(result.returncode, 0)
self.assertIn("known gaps", result.stderr)
def test_future_active_pointer_must_bind_transition_candidate(self) -> None:
with tempfile.TemporaryDirectory() as temporary:
repository = Path(temporary) / "repo"
evidence = repository / "docs/evidence/proof-epochs/epoch-0"
epoch0b = repository / "docs/evidence/proof-epochs/epoch-0b"
shutil.copytree(EVIDENCE, evidence)
shutil.copytree(
ROOT / "docs/evidence/proof-epochs/epoch-0b",
epoch0b,
)
descriptor = repository / CHECK_MODULE.PAUSE_PROOF_REF
descriptor.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(ROOT / CHECK_MODULE.PAUSE_PROOF_REF, descriptor)
for reference in (
CHECK_MODULE.ACTIVE_SCHEMA_REF,
CHECK_MODULE.TRANSITION_SCHEMA_REF,
CHECK_MODULE.PROOF_SCHEMA_REF,
CHECK_MODULE.SUBJECT_SCHEMA_REF,
CHECK_MODULE.VERDICT_SCHEMA_REF,
"scripts/bootstrap-proof-transition.py",
):
target = repository / reference
target.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(ROOT / reference, target)
corpus_ref = "tests/fixtures/t0-epoch1-corpus"
corpus = repository / corpus_ref
corpus.mkdir(parents=True)
(corpus / "case.json").write_text('{"case":"pass"}\n')
bootstrap = CHECK_MODULE.load_bootstrap_module(repository)
corpus_digest = bootstrap.tree_digest(corpus)
components = []
for role in [
"validator-contract",
"validator-implementation",
"verdict-schema",
"rpi-report-schema",
"subject-manifest-schema",
]:
reference = f"components/{role}"
path = repository / reference
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(f"{role}\n")
path.chmod(0o644)
components.append(
{
"role": role,
"ref": reference,
"digest": hashlib.sha256(path.read_bytes()).hexdigest(),
"mode": "0644",
}
)
recorder_ref = "scripts/future-transition.py"
recorder_path = repository / recorder_ref
recorder_path.write_text("#!/usr/bin/env python3\n")
recorder_path.chmod(0o755)
recorder = {
"ref": recorder_ref,
"digest": hashlib.sha256(recorder_path.read_bytes()).hexdigest(),
"mode": "0755",
}
frozen_items = components + [recorder]
subject_ref = "docs/evidence/proof-epochs/epoch-1/subject.json"
subject_path = repository / subject_ref
subject_path.parent.mkdir(parents=True, exist_ok=True)
subject = {
"schema_version": "subject-manifest.v1",
"declared_roots": [item["ref"] for item in frozen_items],
"exclusions": [],
"entries": [
{
"path": item["ref"],
"kind": "file",
"executable": item["mode"] == "0755",
"digest": item["digest"],
}
for item in frozen_items
],
}
subject["canonical_manifest_digest"] = CHECK_MODULE.canonical_digest(
subject
)
subject_path.write_text(json.dumps(subject, sort_keys=True))
verdict_ref_prefix = "docs/evidence/proof-epochs/epoch-1/verdicts"
verdict = {
"schema_version": "verdict.v2",
"acceptance_digest": "b" * 64,
"subject_manifest_digest": subject["canonical_manifest_digest"],
"author_context_id": "author",
"validator_context_id": "validator",
"freshness_attestation": {
"source": "runtime",
"attester_identity": "validator",
},
"verdict": "PASS",
"criteria": [
{
"id": "Q-1",
"result": "PASS",
"evidence_refs": ["fixture"],
}
],
"findings": [],
"evidence_refs": ["fixture"],
"checked": ["fixture"],
"not_checked": [],
"validated_at": "2026-07-24T20:00:00Z",
}
verdict["artifact_digest"] = CHECK_MODULE.canonical_digest(verdict)
verdict_ref = (
f"{verdict_ref_prefix}/{verdict['artifact_digest']}.json"
)
verdict_path = repository / verdict_ref
verdict_path.parent.mkdir(parents=True, exist_ok=True)
verdict_path.write_text(json.dumps(verdict, sort_keys=True))
candidate_ref = "docs/contracts/proof-contracts/epoch-1/descriptor.json"
candidate = repository / candidate_ref
candidate.parent.mkdir(parents=True, exist_ok=True)
candidate_value = {
"schema_version": "proof-contract.v1",
"epoch": 1,
"components": components,
"qualification_corpus": {
"algorithm": "sha256-tree-v1",
"ref": corpus_ref,
"digest": corpus_digest,
},
"qualification_subject_manifest_digest": subject[
"canonical_manifest_digest"
],
"transition_recorder": recorder,
"known_gaps": [],
}
candidate.write_text(json.dumps(candidate_value, sort_keys=True))
candidate_digest = hashlib.sha256(candidate.read_bytes()).hexdigest()
transition = {
"schema_version": "proof-contract-transition.v1",
"prior": {
"epoch": 0,
"contract_ref": CHECK_MODULE.PAUSE_PROOF_REF,
"contract_digest": CHECK_MODULE.PAUSE_PROOF_DIGEST,
"activation_transition_digest": None,
},
"candidate": {
"epoch": 1,
"contract_ref": candidate_ref,
"contract_digest": candidate_digest,
"subject_manifest_ref": subject_ref,
"subject_manifest_digest": subject[
"canonical_manifest_digest"
],
"qualification_corpus_ref": corpus_ref,
"qualification_corpus_digest": corpus_digest,
},
"qualification_verdict": {
"ref": verdict_ref,
"digest": verdict["artifact_digest"],
},
"validator_identity": "validator",
"activated_at": "2026-07-24T20:01:00Z",
}
transition_payload = (
json.dumps(transition, sort_keys=True, separators=(",", ":")) + "\n"
).encode()
transition_digest = hashlib.sha256(transition_payload).hexdigest()
transition_ref = (
f"docs/contracts/proof-contracts/transitions/{transition_digest}.json"
)
transition_path = repository / transition_ref
transition_path.parent.mkdir(parents=True, exist_ok=True)
transition_path.write_bytes(transition_payload)
active_path = repository / "docs/contracts/proof-contracts/active.json"
active_path.write_text(
json.dumps(
{
"schema_version": "proof-contract-active.v1",
"epoch": 1,
"contract_ref": "docs/contracts/proof-contracts/epoch-1/fabricated.json",
"contract_digest": "f" * 64,
"activation_transition_ref": transition_ref,
"activation_transition_digest": transition_digest,
}
)
)
pause = json.loads((evidence / "t0-pause-drill.json").read_text())
with self.assertRaisesRegex(
CHECK_MODULE.EvidenceError,
"not bound to the transition candidate",
):
CHECK_MODULE.check_pause_state(repository, evidence, pause)
active_path.write_text(
json.dumps(
{
"schema_version": "proof-contract-active.v1",
"epoch": 1,
"contract_ref": candidate_ref,
"contract_digest": candidate_digest,
"activation_transition_ref": transition_ref,
"activation_transition_digest": transition_digest,
}
)
)
CHECK_MODULE.check_pause_state(repository, evidence, pause)
malformed_cases: list[tuple[str, dict[str, object]]] = []
extra_transition = copy.deepcopy(transition)
extra_transition["unexpected"] = True
malformed_cases.append(("extra transition field", extra_transition))
extra_candidate = copy.deepcopy(transition)
extra_candidate["candidate"]["unexpected"] = True
malformed_cases.append(("extra candidate field", extra_candidate))
escaping_verdict = copy.deepcopy(transition)
escaping_verdict["qualification_verdict"]["ref"] = "../escape.json"
malformed_cases.append(("escaping qualification ref", escaping_verdict))
boolean_epoch = copy.deepcopy(transition)
boolean_epoch["candidate"]["epoch"] = True
malformed_cases.append(("boolean candidate epoch", boolean_epoch))
malformed_time = copy.deepcopy(transition)
malformed_time["activated_at"] = "not-a-time"
malformed_cases.append(("malformed activation time", malformed_time))
for label, malformed_case in malformed_cases:
with self.subTest(label=label):
with self.assertRaisesRegex(
CHECK_MODULE.EvidenceError,
"active transition violates its schema",
):
CHECK_MODULE.validate_schema_instance(
repository,
schema_ref=CHECK_MODULE.TRANSITION_SCHEMA_REF,
schema_digest=CHECK_MODULE.TRANSITION_SCHEMA_DIGEST,
instance=malformed_case,
label="active transition",
)
malformed = dict(transition)
malformed.pop("qualification_verdict")
malformed_payload = (
json.dumps(malformed, sort_keys=True, separators=(",", ":")) + "\n"
).encode()
malformed_digest = hashlib.sha256(malformed_payload).hexdigest()
malformed_ref = (
f"docs/contracts/proof-contracts/transitions/{malformed_digest}.json"
)
malformed_path = repository / malformed_ref
malformed_path.write_bytes(malformed_payload)
active_path.write_text(
json.dumps(
{
"schema_version": "proof-contract-active.v1",
"epoch": 1,
"contract_ref": candidate_ref,
"contract_digest": candidate_digest,
"activation_transition_ref": malformed_ref,
"activation_transition_digest": malformed_digest,
}
)
)
with self.assertRaisesRegex(
CHECK_MODULE.EvidenceError,
"active transition violates its schema",
):
CHECK_MODULE.check_pause_state(repository, evidence, pause)
duplicate_path = repository / "duplicate.json"
duplicate_path.write_text('{"epoch":1,"epoch":1}\n')
with self.assertRaisesRegex(
CHECK_MODULE.EvidenceError,
"duplicate JSON key",
):
CHECK_MODULE.load(duplicate_path)
alias_parent = repository / "component-alias"
alias_parent.symlink_to(repository / "components", target_is_directory=True)
with self.assertRaisesRegex(
CHECK_MODULE.EvidenceError,
"uses a symlinked path component",
):
CHECK_MODULE.resolve_repository_ref(
repository,
"component-alias/validator-contract",
"aliased component",
)
direct_alias = repository / "direct-alias"
direct_alias.symlink_to(repository / "components/validator-contract")
with self.assertRaisesRegex(
CHECK_MODULE.EvidenceError,
"uses a symlinked path component",
):
CHECK_MODULE.resolve_repository_ref(
repository,
"direct-alias",
"direct alias",
)
outside = Path(temporary) / "outside"
outside.write_text("outside\n")
outside_alias = repository / "outside-alias"
outside_alias.symlink_to(outside)
with self.assertRaisesRegex(
CHECK_MODULE.EvidenceError,
"uses a symlinked path component",
):
CHECK_MODULE.resolve_repository_ref(
repository,
"outside-alias",
"outside alias",
)
for reference in (
"/absolute",
"../parent",
"a/../parent",
"a/./dot",
"a//empty",
"a\\windows",
"trailing/",
):
with self.subTest(reference=reference):
with self.assertRaises(CHECK_MODULE.EvidenceError):
CHECK_MODULE.resolve_repository_ref(
repository,
reference,
"invalid reference",
)
def test_rejected_verdict_byte_mutation_is_detected(self) -> None:
with tempfile.TemporaryDirectory() as temporary:
evidence = Path(temporary)
shutil.copytree(EVIDENCE, evidence, dirs_exist_ok=True)
verdict = next((evidence / "verdicts").glob("*.json"))
verdict.write_bytes(verdict.read_bytes() + b" ")
result = self.run_checker(ROOT, evidence)
self.assertNotEqual(result.returncode, 0)
self.assertIn("failed verdict bytes changed", result.stderr)
if __name__ == "__main__":
unittest.main()