{"files": {"main.py": "from core import run\nfrom policy import POLICY\ndef evaluate(payload):\n    return run(payload, POLICY)\n", "core.py": "from datetime import datetime, timedelta, timezone\nfrom zoneinfo import ZoneInfo\nfrom helpers import parse_aware, overlaps, extract_duration\n\ndef run(payload, policy):\n    selected = []\n    blocked = []\n    rejected = []\n    if not isinstance(payload, dict):\n        return {'selected': [], 'blocked': [], 'rejected': []}\n    appointments = payload.get('appointments')\n    if not isinstance(appointments, list):\n        appointments = []\n    duplicate_policy = policy.get('duplicate_policy', 'first')\n    retained_by_key = {}\n    order_keys = []\n    for idx, row in enumerate(appointments):\n        if not isinstance(row, dict):\n            continue\n        if 'id' not in row:\n            continue\n        rid = row.get('id')\n        try:\n            hash(rid)\n            key = ('id', rid)\n        except Exception:\n            key = ('repr', repr(rid))\n        if key not in retained_by_key:\n            retained_by_key[key] = (idx, row)\n            order_keys.append(key)\n        elif duplicate_policy == 'last':\n            retained_by_key[key] = (idx, row)\n    retained = [retained_by_key[k] for k in order_keys]\n    def sort_output(items):\n        if policy.get('report_order') == 'id':\n            try:\n                return [rid for rid, _ in sorted(items, key=lambda x: x[0])]\n            except Exception:\n                return [rid for rid, _ in sorted(items, key=lambda x: str(x[0]))]\n        return [rid for rid, _ in sorted(items, key=lambda x: x[1])]\n    try:\n        now = parse_aware(payload.get('now'))\n        if now is None:\n            raise ValueError('invalid now')\n        now_utc = now.astimezone(timezone.utc)\n    except Exception:\n        for idx, row in retained:\n            rejected.append((row.get('id'), idx))\n        return {'selected': [], 'blocked': [], 'rejected': sort_output(rejected)}\n    try:\n        tz = ZoneInfo(policy.get('timezone', 'UTC'))\n    except Exception:\n        for idx, row in retained:\n            rejected.append((row.get('id'), idx))\n        return {'selected': [], 'blocked': [], 'rejected': sort_output(rejected)}\n    lead = policy.get('lead_minutes', 0)\n    duration_max = policy.get('duration_max')\n    cutoff_hour = policy.get('cutoff_hour', 18)\n    cutoff_inclusive = policy.get('cutoff_inclusive', False)\n    blackout_day = policy.get('blackout_day')\n    cancelled_blocks = policy.get('cancelled_blocks', False)\n    capacity = policy.get('capacity', 1)\n    adjacency_allowed = policy.get('adjacency_allowed', True)\n    priority_high_first = policy.get('priority_high_first', True)\n    try:\n        earliest = now_utc + timedelta(minutes=lead)\n    except Exception:\n        earliest = now_utc\n    candidates = []\n    for idx, row in retained:\n        rid = row.get('id')\n        valid = True\n        start_utc = None\n        end_utc = None\n        duration = None\n        priority = None\n        cancelled = False\n        try:\n            start = parse_aware(row.get('start'))\n            if start is None:\n                valid = False\n            else:\n                start_utc = start.astimezone(timezone.utc)\n        except Exception:\n            valid = False\n        if valid:\n            duration = extract_duration(row)\n            if isinstance(duration, bool) or duration is None:\n                valid = False\n            elif isinstance(duration, float) and duration.is_integer():\n                duration = int(duration)\n            elif not isinstance(duration, int):\n                valid = False\n            else:\n                if duration <= 0:\n                    valid = False\n                elif duration_max is not None and duration > duration_max:\n                    valid = False\n        if valid:\n            priority = row.get('priority')\n            if isinstance(priority, bool) or not isinstance(priority, int):\n                valid = False\n        if valid:\n            if 'cancelled' in row:\n                if not isinstance(row.get('cancelled'), bool):\n                    valid = False\n                else:\n                    cancelled = row.get('cancelled')\n            else:\n                cancelled = False\n        if valid:\n            if start_utc < earliest:\n                valid = False\n        if valid:\n            try:\n                local_start = start_utc.astimezone(tz)\n                if blackout_day is not None and local_start.date().isoformat() == str(blackout_day):\n                    valid = False\n            except Exception:\n                valid = False\n        if valid:\n            try:\n                end_utc = start_utc + timedelta(minutes=duration)\n                local_start = start_utc.astimezone(tz)\n                cutoff = datetime(local_start.year, local_start.month, local_start.day, int(cutoff_hour), 0, tzinfo=tz)\n                if cutoff_inclusive:\n                    if end_utc > cutoff.astimezone(timezone.utc):\n                        valid = False\n                else:\n                    if end_utc >= cutoff.astimezone(timezone.utc):\n                        valid = False\n            except Exception:\n                valid = False\n        if valid and cancelled and not cancelled_blocks:\n            valid = False\n        if not valid:\n            rejected.append((rid, idx))\n        else:\n            candidates.append({'id': rid, 'index': idx, 'start': start_utc, 'end': end_utc, 'priority': priority, 'cancelled': cancelled})\n    if priority_high_first:\n        candidates.sort(key=lambda c: (-c['priority'], c['index']))\n    else:\n        candidates.sort(key=lambda c: (c['priority'], c['index']))\n    accepted = []\n    for cand in candidates:\n        count = 0\n        for a_start, a_end in accepted:\n            if overlaps(cand['start'], cand['end'], a_start, a_end, adjacency_allowed):\n                count += 1\n        if count < capacity:\n            accepted.append((cand['start'], cand['end']))\n            if cand['cancelled']:\n                blocked.append((cand['id'], cand['index']))\n            else:\n                selected.append((cand['id'], cand['index']))\n        else:\n            rejected.append((cand['id'], cand['index']))\n    return {'selected': sort_output(selected), 'blocked': sort_output(blocked), 'rejected': sort_output(rejected)}\n", "policy.py": "POLICY = {\n    \"adjacency_allowed\": False,\n    \"blackout_day\": \"2026-11-02\",\n    \"cancelled_blocks\": False,\n    \"capacity\": 2,\n    \"cutoff_hour\": 18,\n    \"cutoff_inclusive\": False,\n    \"duplicate_policy\": \"last\",\n    \"duration_max\": 90,\n    \"lead_minutes\": 60,\n    \"priority_high_first\": False,\n    \"report_order\": \"input\",\n    \"timezone\": \"UTC\",\n}\n", "helpers.py": "from datetime import datetime\n\ndef parse_aware(value):\n    if isinstance(value, datetime):\n        dt = value\n    elif isinstance(value, str):\n        text = value.strip()\n        if text.endswith('Z') or text.endswith('z'):\n            text = text[:-1] + '+00:00'\n        dt = datetime.fromisoformat(text)\n    else:\n        return None\n    if dt.tzinfo is None or dt.utcoffset() is None:\n        return None\n    return dt\n\ndef overlaps(start, end, other_start, other_end, adjacency_allowed):\n    if adjacency_allowed:\n        return start < other_end and other_start < end\n    return start <= other_end and other_start <= end\n\ndef extract_duration(row):\n    for key in ('duration', 'duration_minutes', 'minutes', 'duration_min', 'duration_mins'):\n        if key in row:\n            return row.get(key)\n    return None\n"}}