"""Durable admission representation: persist before dispatch (T05).""" from __future__ import annotations from datetime import UTC, datetime from pathlib import Path import pytest from wf_api.run_lifecycle import ( load_stored_run, materialize_admitted_view, persist_admission, ) from wf_artifacts import ( PinnedRunEnvironment, StoredRunStatus, WorkflowArtifact, WorkflowDeployment, ) from wf_artifacts.runs.store import FileRunStore def _env() -> PinnedRunEnvironment: deployment = WorkflowDeployment( id="dep-1", artifact_id="wf-1", artifact_version=1, bindings=[{"logical_source": "demo", "concrete_source": "demo.personal"}], ) artifact = WorkflowArtifact( id="wf-1", version=1, title="Wf-1", input_schema={"type": "object", "properties": {}}, output_schema={"type": "object", "properties": {}}, outcomes=("ok",), plan={"name": "wf-1", "nodes": [], "edges": []}, ) return PinnedRunEnvironment( deployment=deployment, root_artifact=artifact, child_artifacts=[] ) def test_admission_persists_authority_before_view(tmp_path: Path) -> None: store = FileRunStore(tmp_path) run_id = store.allocate_run_id() at = datetime(2026, 9, 8, 13, 0, tzinfo=UTC) admission = persist_admission( store=store, run_id=run_id, environment=_env(), resolved_input={"team": "eng"}, max_steps=100, scheduled_at=at, schedule_id="sched-1", schedule_revision=2, ) assert admission.id == run_id assert admission.scheduled_at == at # Admission record exists before any run view or checkpoint. assert store.get_admission(run_id).id == run_id with pytest.raises(KeyError): store.get_run(run_id) record = materialize_admitted_view(store=store, admission=admission) assert record.status is StoredRunStatus.ADMITTED assert record.latest_checkpoint_id is None # Inspection distinguishes admitted (no checkpoint) from stopped. with pytest.raises(KeyError, match="no checkpoints"): store.get_latest_checkpoint(run_id) def test_admission_view_round_trips_real_serialization(tmp_path: Path) -> None: store = FileRunStore(tmp_path) run_id = store.allocate_run_id() admission = persist_admission( store=store, run_id=run_id, environment=_env(), resolved_input={"a": [1, None, "x"]}, max_steps=None, scheduled_at=None, schedule_id=None, schedule_revision=None, ) record = materialize_admitted_view(store=store, admission=admission) reloaded = store.get_run(run_id) assert reloaded.id == record.id assert reloaded.status is StoredRunStatus.ADMITTED reloaded_admission = store.get_admission(run_id) assert reloaded_admission.resolved_input == {"a": [1, None, "x"]} assert reloaded_admission.environment.deployment.id == "dep-1" def test_run_ids_are_store_backed_across_restart(tmp_path: Path) -> None: first = FileRunStore(tmp_path).allocate_run_id() second = FileRunStore(tmp_path).allocate_run_id() assert first != second # Reopening the store never reuses identities. third = FileRunStore(tmp_path).allocate_run_id() assert third not in {first, second} def test_fault_before_admission_persists_nothing(tmp_path: Path, monkeypatch) -> None: from wf_artifacts.runs import store as store_module store = FileRunStore(tmp_path) run_id = store.allocate_run_id() def _boom(path: Path, payload: object) -> None: raise OSError("injected write failure") monkeypatch.setattr(store, "_write_json", _boom) with pytest.raises(OSError, match="injected"): persist_admission( store=store, run_id=run_id, environment=_env(), resolved_input={}, max_steps=None, scheduled_at=None, schedule_id=None, schedule_revision=None, ) assert store_module.FileRunStore(tmp_path).list_admissions() == [] with pytest.raises(KeyError): store.get_admission(run_id) def test_fault_between_admission_and_view_recovers_without_dispatch( tmp_path: Path, monkeypatch ) -> None: store = FileRunStore(tmp_path) run_id = store.allocate_run_id() admission = persist_admission( store=store, run_id=run_id, environment=_env(), resolved_input={"team": "eng"}, max_steps=None, scheduled_at=None, schedule_id=None, schedule_revision=None, ) assert admission.id == run_id # Crash before the view is materialized: admission exists, view missing. with pytest.raises(KeyError): store.get_run(run_id) # Recovery materializes the missing view but never executes work. from wf_api.run_lifecycle import recover_admission_view record = recover_admission_view(store=store, run_id=run_id) assert record.status is StoredRunStatus.ADMITTED assert store.get_run(run_id).id == run_id # Idempotent: second recovery returns the same view. again = recover_admission_view(store=store, run_id=run_id) assert again.id == run_id def test_admitted_run_has_no_fabricated_checkpoint_or_output( tmp_path: Path, ) -> None: store = FileRunStore(tmp_path) run_id = store.allocate_run_id() admission = persist_admission( store=store, run_id=run_id, environment=_env(), resolved_input={}, max_steps=None, scheduled_at=None, schedule_id=None, schedule_revision=None, ) record = materialize_admitted_view(store=store, admission=admission) assert record.latest_checkpoint_id is None assert store.list_checkpoints(run_id) == [] # Loading a stopped run from an admitted view must fail closed, not # fabricate trace/output/step counts. with pytest.raises(ValueError, match="admitted"): load_stored_run(store, run_id)