test_dag_and_gates.py 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. from __future__ import annotations
  2. from supply_infra.pipeline.dag import PIPELINE_STEPS
  3. from supply_infra.pipeline.gates import evaluate_step_gate
  4. def test_pipeline_has_twelve_strictly_ordered_steps() -> None:
  5. assert len(PIPELINE_STEPS) == 12
  6. assert PIPELINE_STEPS[0].key == "global_tree_sync"
  7. assert PIPELINE_STEPS[-1].key == "aigc_write_record"
  8. for previous, current in zip(PIPELINE_STEPS, PIPELINE_STEPS[1:]):
  9. assert current.dependencies == (previous.key,)
  10. assert current.critical is True
  11. def test_aigc_gate_requires_durable_effect_record() -> None:
  12. failed = evaluate_step_gate("aigc_write_record", {"success": True})
  13. assert failed.passed is False
  14. live_ok = evaluate_step_gate(
  15. "aigc_write_record",
  16. {
  17. "success": True,
  18. "effect_recorded": True,
  19. "payload_hash": "abc",
  20. "external_request_made": True,
  21. },
  22. )
  23. assert live_ok.passed is True
  24. def test_aigc_gate_rejects_failed_batches() -> None:
  25. decision = evaluate_step_gate(
  26. "aigc_write_record",
  27. {
  28. "success": True,
  29. "effect_recorded": True,
  30. "payload_hash": "abc",
  31. "failed_batch_count": 2,
  32. },
  33. )
  34. assert decision.passed is False
  35. assert decision.error_code == "aigc_publish_failed"
  36. def test_explicit_step_failure_fails_closed() -> None:
  37. decision = evaluate_step_gate(
  38. "global_tree_sync",
  39. {"success": False, "error": "source missing"},
  40. )
  41. assert decision.passed is False
  42. assert decision.error_code == "step_reported_failure"