Spaces:
Running on Zero
Running on Zero
| from figment.focused_repair import ( | |
| RepairScope, | |
| build_focused_repair_prompt, | |
| build_focused_repair_prompts, | |
| classify_validation_failures, | |
| mandatory_source_card_ids_for_scope, | |
| missing_mandatory_source_cards, | |
| ) | |
| def test_classifies_validator_failures_into_focused_scopes_and_fields() -> None: | |
| failures = [ | |
| "handoff_note_sbar is missing: assessment_observations_only, handoff_request", | |
| "missing_info_to_collect does not reference required observations for CHEST-PAIN-ESCALATION-v1", | |
| "source_cards not in allowed/retrieved card IDs: WOUND-INFECTION-ESCALATION-v1", | |
| "candidate pathway CHEST-PAIN-ESCALATION-v1 is not cited in source_cards", | |
| "forbidden clinical language: prescribe", | |
| "protocol_urgency routine is below deterministic floor emergency", | |
| ] | |
| scopes = classify_validation_failures(failures) | |
| assert [(scope.name, scope.fields) for scope in scopes] == [ | |
| ("handoff_note_sbar", ("handoff_note_sbar",)), | |
| ("missing_observations", ("missing_info_to_collect", "next_observations_to_collect")), | |
| ("citations_and_pathways", ("source_cards", "candidate_protocol_pathways")), | |
| ( | |
| "forbidden_clinical_language", | |
| ( | |
| "red_flags", | |
| "intake_facts", | |
| "candidate_protocol_pathways", | |
| "missing_info_to_collect", | |
| "next_observations_to_collect", | |
| "conflicts_or_uncertainties", | |
| "responder_checklist", | |
| "do_not_do", | |
| "handoff_note_sbar", | |
| "responder_plain_language_script", | |
| "safety_boundary", | |
| ), | |
| ), | |
| ("protocol_urgency", ("protocol_urgency",)), | |
| ] | |
| assert scopes[2].failures == ( | |
| "source_cards not in allowed/retrieved card IDs: WOUND-INFECTION-ESCALATION-v1", | |
| "candidate pathway CHEST-PAIN-ESCALATION-v1 is not cited in source_cards", | |
| ) | |
| def test_schema_failures_extract_missing_and_type_invalid_fields() -> None: | |
| scopes = classify_validation_failures( | |
| [ | |
| "missing required schema keys: red_flags, intake_facts, safety_boundary", | |
| "responder_plain_language_script must be a string", | |
| "next_observations_to_collect must be a list", | |
| ] | |
| ) | |
| assert scopes == ( | |
| RepairScope( | |
| name="schema", | |
| fields=( | |
| "red_flags", | |
| "intake_facts", | |
| "next_observations_to_collect", | |
| "responder_plain_language_script", | |
| "safety_boundary", | |
| ), | |
| failures=( | |
| "missing required schema keys: red_flags, intake_facts, safety_boundary", | |
| "responder_plain_language_script must be a string", | |
| "next_observations_to_collect must be a list", | |
| ), | |
| ), | |
| ) | |
| def test_build_focused_repair_prompt_limits_model_to_selected_fields() -> None: | |
| scope = RepairScope( | |
| name="missing_observations", | |
| fields=("missing_info_to_collect", "next_observations_to_collect"), | |
| failures=( | |
| "missing_info_to_collect does not reference required observations for CHEST-PAIN-ESCALATION-v1", | |
| ), | |
| ) | |
| previous_output = { | |
| "protocol_urgency": "emergency", | |
| "source_cards": ["CHEST-PAIN-ESCALATION-v1"], | |
| "missing_info_to_collect": ["ask anything else that seems relevant"], | |
| "next_observations_to_collect": ["keep monitoring"], | |
| } | |
| prompt = build_focused_repair_prompt( | |
| original_prompt="BASE NAVIGATOR PROMPT", | |
| previous_output=previous_output, | |
| repair_scope=scope, | |
| urgency_floor="emergency", | |
| required_observation_targets=[ | |
| { | |
| "id": "CHEST-PAIN-ESCALATION-v1::required_observation::1", | |
| "card_id": "CHEST-PAIN-ESCALATION-v1", | |
| "display_text": "chest pain description", | |
| "cue_tokens": ["chest", "pain", "description"], | |
| } | |
| ], | |
| ) | |
| assert "BASE NAVIGATOR PROMPT" in prompt | |
| assert "Do not return the whole navigator output" in prompt | |
| assert "exactly these top-level keys: missing_info_to_collect, next_observations_to_collect" in prompt | |
| assert "protocol_urgency" not in prompt.split("PREVIOUS_VALUES_FOR_ALLOWED_FIELDS:", 1)[1] | |
| assert "required observations" in prompt | |
| assert "CHEST-PAIN-ESCALATION-v1" in prompt | |
| assert "CHEST-PAIN-ESCALATION-v1::required_observation::1" in prompt | |
| assert "chest pain description" in prompt | |
| assert "required_display_text_must_copy_exactly" in prompt | |
| assert "Copy every display_text" in prompt | |
| def test_citation_repair_prompt_names_mandatory_source_cards() -> None: | |
| scope = classify_validation_failures( | |
| [ | |
| "fired rule card STROKE-SIGNS-v1 is not cited in source_cards", | |
| "candidate pathway STROKE-SIGNS-v1 is not cited in source_cards", | |
| ] | |
| )[0] | |
| prompt = build_focused_repair_prompt( | |
| original_prompt="BASE NAVIGATOR PROMPT", | |
| previous_output={ | |
| "source_cards": ["SAFETY-BOUNDARIES-v1"], | |
| "candidate_protocol_pathways": [ | |
| { | |
| "card_id": "SAFETY-BOUNDARIES-v1", | |
| "reason_relevant": "Existing pathway.", | |
| } | |
| ], | |
| }, | |
| repair_scope=scope, | |
| urgency_floor="emergency", | |
| ) | |
| assert scope.name == "citations_and_pathways" | |
| assert scope.fields == ("source_cards", "candidate_protocol_pathways") | |
| assert mandatory_source_card_ids_for_scope(scope) == ("STROKE-SIGNS-v1",) | |
| assert "Mandatory source cards: STROKE-SIGNS-v1" in prompt | |
| assert "Do not remove any mandatory source card" in prompt | |
| assert "exactly these top-level keys: source_cards, candidate_protocol_pathways" in prompt | |
| def test_citation_repair_rejects_output_that_omits_mandatory_source_card() -> None: | |
| scope = classify_validation_failures( | |
| ["fired rule card PREG-DANGER-SIGNS-v1 is not cited in source_cards"] | |
| )[0] | |
| assert missing_mandatory_source_cards( | |
| scope, | |
| { | |
| "source_cards": ["REFERRAL-SBAR-v1", "SAFETY-BOUNDARIES-v1"], | |
| "candidate_protocol_pathways": [ | |
| { | |
| "card_id": "REFERRAL-SBAR-v1", | |
| "reason_relevant": "SBAR handoff.", | |
| } | |
| ], | |
| }, | |
| ) == ("PREG-DANGER-SIGNS-v1",) | |
| assert missing_mandatory_source_cards( | |
| scope, | |
| { | |
| "source_cards": ["PREG-DANGER-SIGNS-v1", "REFERRAL-SBAR-v1"], | |
| "candidate_protocol_pathways": [ | |
| { | |
| "card_id": "PREG-DANGER-SIGNS-v1", | |
| "reason_relevant": "Pregnancy danger sign fired deterministically.", | |
| } | |
| ], | |
| }, | |
| ) == () | |
| def test_forbidden_language_prompt_keeps_safety_boundaries_explicit() -> None: | |
| scope = classify_validation_failures(["forbidden clinical language: discharge home"])[0] | |
| prompt = build_focused_repair_prompt( | |
| original_prompt="BASE NAVIGATOR PROMPT", | |
| previous_output={"responder_checklist": ["Discharge home if symptoms improve."]}, | |
| repair_scope=scope, | |
| urgency_floor="urgent", | |
| ) | |
| assert scope.name == "forbidden_clinical_language" | |
| assert "remove or rewrite unsafe clinical language" in prompt | |
| assert "diagnose, prescribe, dose, discharge, or override" in prompt | |
| assert "urgency_floor" in prompt | |
| assert "urgent" in prompt | |
| def test_build_focused_repair_prompts_groups_failures_with_scope_metadata() -> None: | |
| prompts = build_focused_repair_prompts( | |
| original_prompt="BASE NAVIGATOR PROMPT", | |
| previous_output={"handoff_note_sbar": {"situation": "Chest pain"}}, | |
| failures=[ | |
| "handoff_note_sbar background is not grounded in confirmed intake or rules", | |
| "handoff_note_sbar assessment_observations_only has unsupported high-risk handoff facts: skull", | |
| ], | |
| urgency_floor="emergency", | |
| ) | |
| assert len(prompts) == 1 | |
| assert prompts[0].scope == RepairScope( | |
| name="handoff_note_sbar", | |
| fields=("handoff_note_sbar",), | |
| failures=( | |
| "handoff_note_sbar background is not grounded in confirmed intake or rules", | |
| "handoff_note_sbar assessment_observations_only has unsupported high-risk handoff facts: skull", | |
| ), | |
| ) | |
| assert "ground handoff_note_sbar only in confirmed intake and deterministic rules" in prompts[0].prompt | |