import os, sys, json, tempfile, pytest sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", "src")) from pgar.state import StateStore from pgar.contracts import RunManifest def mk(): d = tempfile.mkdtemp(); return StateStore(os.path.join(d, "s.sqlite")) def test_create_and_idempotent(): s = mk(); m = RunManifest("RD0001", "F2-smoke-01", "development", "A", 0) s.create_run(m) with pytest.raises(ValueError): s.create_run(m) assert s.get_run("RD0001")["status"] == "not_started" def test_transitions_validated(): s = mk(); s.create_run(RunManifest("RD0002", "t", "development", "B", 0)) with pytest.raises(ValueError): s.transition("RD0002", "completed") # not_started -> completed illegal s.transition("RD0002", "prepared"); s.transition("RD0002", "running"); s.transition("RD0002", "completed") with pytest.raises(ValueError): s.transition("RD0002", "evaluated") # invariant: no receipt s.transition("RD0002", "evaluated", evaluation_receipt="x.json") with pytest.raises(ValueError): s.transition("RD0002", "running") # terminal def test_freeze_blocks_updates(): s = mk(); s.create_run(RunManifest("RD0003", "t", "confirmatory", "C", 0)) s.transition("RD0003", "prepared"); s.transition("RD0003", "running"); s.transition("RD0003", "completed"); s.transition("RD0003", "evaluated", evaluation_receipt="r") assert s.freeze_split("confirmatory") == 1 with pytest.raises(PermissionError): s.update_manifest("RD0003", notes="x") def test_job_ledger_idempotent(): s = mk(); assert s.log_job("k1", "RD", "execute") is True; assert s.log_job("k1", "RD", "execute") is False