Skip to content

D-A3-1: The sandwich has two independent halves

Status: Accepted, implemented (graph/nodes/post_flight.py, Phase 5).

Context

A guardrail that only screens the incoming question cannot catch a case where the question is benign but the retrieved evidence is dangerous — canonical case 4, a patient asking a plain lab-education question over a potassium of 6.9 mmol/L. Most healthcare AI demos put a disclaimer in the system prompt and call it safety; that pattern cannot produce this escalation at all, because nothing re-examines the evidence or the draft after the pre-flight decision is made.

Decision

Policy runs before the model (resolve_policy) and after it (post_flight), and the second half does not replay the first. It assesses the retrieved evidence and the drafted answer on its own authority, through three checks in cost order — critical_value (pure code), citation_coverage (pure code), scope_judge (one model call) — and its override_action is always more_restrictive(pre_flight_action, implied) (schemas/preflight.py::more_restrictive): post-flight may escalate a run pre-flight allowed, but it can never relax a restriction pre-flight already imposed.

tests/graph/test_post_flight.py::test_post_flight_never_relaxes_a_restriction and tests/graph/test_post_flight_graph.py::test_benign_question_over_critical_value_escalates assert both halves of the property directly: the monotonic guarantee, and case 4 escalating a run pre-flight was happy to allow.

Consequences

  • The published answer's safety property depends on two independently testable stages, not one system prompt's discipline.
  • A retrieved value can override a benign question's disposition, which is the entire reason case 4 is one of the three credibility cases named in docs/evidence/evaluation.md.
  • Post-flight cannot be bypassed by phrasing the question carefully, since it never re-reads the question — it reads the evidence and the draft.