Scheduler handoff — current authoritative requirements

Scope
- Target project: scheduler only.
- Only scheduler updates are authoritative. Ignore all archived projects.
- Updates 1–5 have been applied below; superseded choices are discarded.
- No implementation or test results are provided. The next update and later questions are not yet available.

Current configuration
{
  "timezone": "America/New_York",
  "cutoff_hour": 17,
  "cutoff_inclusive": true,
  "lead_minutes": 30,
  "adjacency_allowed": true,
  "duration_max": 120,
  "duplicate_policy": "first",
  "cancelled_blocks": true,
  "capacity": 1,
  "report_order": "id",
  "blackout_day": "2026-11-02",
  "priority_high_first": false
}

Fixed interface
- Implement evaluate(payload) -> {"selected": [id], "blocked": [id], "rejected": [id]}.
- payload contains now (offset-aware ISO datetime) and appointments.
- Each appointment has id, start (offset-aware ISO datetime), duration in minutes, integer priority, and boolean cancelled.
- Do not mutate the input.
- Use zoneinfo or equivalent timezone conversion.

Deduplication and processing
- Deduplicate by id, keeping the FIRST row/value.
- Preserve each id's first insertion position.
- The retained row's original index is its actual index in the original appointments array.
- Process priority ASCENDING; ties use retained original index.
- Discarded duplicate rows are not independently scheduled or reported; classify each deduplicated id using its retained row.

Validation and time rules
- Duration must be > 0 and <= 120 minutes.
- Start must be >= now + 30 elapsed minutes.
- Perform start/end arithmetic in UTC elapsed minutes, not local wall minutes.
- Convert start to America/New_York.
- Reject if start's local calendar date is 2026-11-02.
- Construct cutoff at 17:00 America/New_York on start's local calendar day.
- End must be <= that cutoff; equality is allowed.
- Compare instants correctly across offsets and DST.

Cancellation and capacity
- Cancelled appointments may reserve capacity because cancelled_blocks=true.
- An accepted cancelled appointment goes to blocked, not selected.
- Cancelled appointments still must satisfy all validation and capacity rules; otherwise they go to rejected.
- Capacity is 1: accept only if fewer than 1 already accepted intervals overlap the candidate.
- Both selected and blocked appointments count as accepted intervals.
- adjacency_allowed=true: intervals sharing only an endpoint do NOT overlap.
- Capacity counts intersecting accepted intervals, not peak concurrency.
- Invalid or conflicting deduplicated ids go to rejected.

Reporting
- Sort selected, blocked, and rejected separately by id.
- Output order is not processing order or retained input order.

Unresolved / not specified
- No configuration choices remain unresolved.
- Exact behavior for malformed payloads, missing fields/ids, invalid now, unhashable or mixed-type ids, and id sorting across incomparable types is not specified.
- Do not invent policies for these cases without clarification.