"""R3 — immutable event log acceptance checks. Acceptance predicate (roadmap R3): replaying a fixture circuit produces a schema-valid JSONL whose SHA-256 matches the manifest; the file is append-only (no in-place edits). This is also instrument-validation gate item 6. """ import hashlib import json import pytest from cmd_chat.sor.events import ( EVENT_TYPES, EventLog, replay_and_seal, replay_fixture_circuit, validate_record, ) from cmd_chat.sor.provenance import Node, RunManifest KNOWN_PUB_B64 = "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=" def _manifest(root, run_id="20260719T010203Z", seed=123456789): return RunManifest( run_id=run_id, sor_seed=seed, topology="1-house", selector="static", churn_schedule_id="fixture-churn-0", nodes=[Node(role="host", persona_pub_b64=KNOWN_PUB_B64, engine="docker")], engine_kind="docker", worktree_root=root, ) def _read_lines(path): return [json.loads(l) for l in path.read_text().splitlines() if l.strip()] def test_replay_schema_valid_and_hash_matches_manifest(tmp_path): run_dir = tmp_path / "run" sealed = replay_and_seal(run_dir, _manifest(tmp_path), pool=5, hops=3, rebuilds=2) events_path = run_dir / "events.jsonl" assert events_path.is_file() # Every line schema-valid, uses a known event type, and carries the seed. records = _read_lines(events_path) assert len(records) > 0 for rec in records: validate_record(rec) assert rec["event"] in EVENT_TYPES assert rec["seed"] == 123456789 # SHA-256 of the closed file matches what was sealed into the manifest. disk_sha = hashlib.sha256(events_path.read_bytes()).hexdigest() assert sealed["events"]["sha256"] == disk_sha manifest_doc = json.loads((run_dir / "manifest.json").read_text()) assert manifest_doc["events"]["sha256"] == disk_sha assert manifest_doc["timestamps"]["stop_utc"] is not None def test_replay_is_deterministic_modulo_timestamps(tmp_path): # Same seed -> identical circuit-build sequence -> identical event bodies # (drop the wall-clock ts). Two independent runs must match field-for-field. a_dir = tmp_path / "a" b_dir = tmp_path / "b" replay_fixture_circuit(a_dir, "runA", 42, pool=6, hops=3, rebuilds=3) replay_fixture_circuit(b_dir, "runB", 42, pool=6, hops=3, rebuilds=3) def _strip(path, run_id): out = [] for r in _read_lines(path): r = dict(r) r.pop("ts") r["run_id"] = "X" # normalize the only other per-run field out.append(r) return out assert _strip(a_dir / "events.jsonl", "runA") == _strip(b_dir / "events.jsonl", "runB") def test_append_only_no_in_place_edits(tmp_path): run_dir = tmp_path / "run" log = EventLog(run_dir, "runX", 7) log.emit("circuit_build", circuit_id="c0", hop_index=0) first_bytes = (run_dir / "events.jsonl").read_bytes() first_len = len(first_bytes) log.emit("hop_add", node_fp="00000001", circuit_id="c0", hop_index=0, bytes_=10, latency_ms=1.0) log.close() after = (run_dir / "events.jsonl").read_bytes() # The file only grew; the original prefix is byte-identical (append-only). assert len(after) > first_len assert after[:first_len] == first_bytes def test_seal_is_once_only(tmp_path): run_dir = tmp_path / "run" replay_and_seal(run_dir, _manifest(tmp_path), rebuilds=1) # A second seal attempt on the same manifest is refused (immutability). from cmd_chat.sor.provenance import seal_manifest with pytest.raises(ValueError): seal_manifest(run_dir, "0" * 64) def test_unknown_event_rejected(tmp_path): log = EventLog(tmp_path / "run", "runX", 1) with pytest.raises(ValueError): log.emit("not_a_real_event") log.close() def test_closed_log_refuses_emit(tmp_path): log = EventLog(tmp_path / "run", "runX", 1) log.emit("circuit_build", circuit_id="c0") log.close() with pytest.raises(RuntimeError): log.emit("circuit_build", circuit_id="c1")