Spaces:
Running on Zero
Running on Zero
File size: 8,611 Bytes
5dcfc5c 2d63573 5dcfc5c 2d63573 5dcfc5c 2d63573 5dcfc5c | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 | 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
|