Skip to main content
Full narrative: Event clock writeup (ENG-580). One-page map: Event clock problem canvas. Active Events by writer interval: Event clock active intervals. Locked availability / accept contract: Availability and engagement clock semantics. Target storage after this migration: naive call clocks are UTC Instants. Date-key columns stay calendar dates. created_at only names a writer era when the row was never saved again. A later header save re-encodes call times. Time-bounded means one explicit permutation per writer window. Each window is rewrite, no-op (already Instant or already a calendar date), or leftover pending a zone. 20260817180000_event_clock_alignment does the whole cutover: Flex metadata IANA, Flex Instant calendar days, Flex #1328 / #1387 restore-from-quote, Event wall-clock Instant-ize, noon date_trunc, availability nullable clocks + required IANA + all-day null, offer / request / availability evening Instant-ize (including hour-0 prefixes), offer/request expires_at and RoS clocks, overnight exact 00:00 ends → null open bound and inverted :01–:59 as next morning, and org TZ copy onto leftover null Event labels. RoS clocks Instant-ize through Event IANA when present (prod dump has 0 clocks). 20260819160000_flex_quote_instant_restore repeats the Flex restore after origin’s 20260818140000 Instant→wall.

What the migration rewrites

20260817180000_event_clock_alignment uses writer-era bounds on created_at / createdAt to name cohorts; Event wall-clock Formula B for hours 0–9 additionally gates on updatedAt in the fake-Z writer windows (see table below). Offer / availability / RoS Formula B gates on updated_at / updatedAt with floor #1012 and upper bound < 2026-08-20 23:19:32 UTC (frozen from prod-postgres-20260820-2319-pm.dump; those tables stamp updatedAt after every convert on the row so replay cannot shift again). Schedule-item Formula B lives in a separate file, 20260819170000_event_schedule_item_formula_b (same frozen ceiling on updatedAt; no #1012 floor; Event IANA then org then Chicago; convert dump-proved ids in convert_schedule_wall, 1046 walls — exact match on this dump; hours 0–23; skip Event-equal clocks; two Flex quote-equal ids in skip_schedule_instant). Neither Formula B file is applied in prod yet. timezone('UTC', ts) is not used. Wall → Instant is ((ts AT TIME ZONE iana) AT TIME ZONE 'UTC'). Calendar-day projection from a quote Instant is ((instant AT TIME ZONE 'UTC') AT TIME ZONE iana). Writer-era provenance (Event Formula B hour 0–9): soundcheck-web EventForm fake-Z shipped in cb1e7663 (#262, 2025-08-08 22:02 CDT) through 6ae2e73a (#501, 2025-11-20). Migration uses half-open updatedAt window [2025-08-09, 2025-11-22). Monorepo #1022 fake-Z floor is 2026-07-16 20:13:31. Offer / availability / RoS Formula B uses the #1012 floor 2026-07-15 00:00:19 with the same updated_at / updatedAt upper bound < 2026-08-20 23:19:32.

What it cannot rewrite

Time bounds identify these rows. They do not recover the typed clock. Do not wall→UTC every row in a window. Flex Instant rows in the same dates still equal show_start_at (22:00). Treating that as 10pm Chicago writes 03:00 the next UTC day.

Fresh dump leftovers (2026-08-19 pm — classify only)

Dump prod-postgres-20260819-pm.dump (920 Events; taken 2026-08-19 22:29 UTC). Instant writers are not in production; 0 rows were post-ceiling on the prior 2026-08-20 bound. Record these counts for a later wave — do not convert in this pass: MIG-02/03/04 are empty on this dump — add cheap fixtures later. Candidate convert sets (evening-shaped; Instant writers not live): 36 Event Formula-B starts (13 Flex-linked); 46 schedule rewrites; 54 in-window offer hour 10–23. At Instant-writer deploy: freeze the ceiling to that deploy instant, dump, and Formula-B only rows with updatedAt in (prior_ceiling, freeze]. This pass (branch only, not deployed): MOBILE-01, NOTIFY-01, CAL-03, CLIENT-01, CAL-02, WEB-02, MOBILE-02, CONTRACT-01 — see writeup Instant readers table.

Fresh dump leftovers (2026-08-20 verify — classify only)

Dump prod-postgres-20260820-verify.dump (921 Events; raw restore, clock migrations not applied). Dest already has 20260818140000 Flex Instant→wall and 20260817160000 ledger midnight. Instant writers are not in production. Do not convert from this table; it settles git-history unknowns. Candidate convert sets: Event evenings 180 after simulated zone (was 35 with Event IANA only). Schedule allowlist was 0 at this census — a later pass filled it (see below).

Git + dump proof (2026-08-20)

Web Timeline (formatTimeToTimestampUsingDateSelection) has been fake-Z since soundcheck-web #262 / timeline #501. Mobile schedule on origin/dev is bare-local wall digits — the same naive TIMESTAMP as fake-Z. UEF ingest can INSERT Instant EventScheduleItem rows but this dump has 0 ingestion_batches and 0 schedule-on-ingest. This pass filled convert_schedule_wall from prod-postgres-20260820-verify.dump (1046 walls: every non-null start and/or end except the two Flex quote-equal Instant ids) and expanded 20260819170000 — no #1012 floor, hours 0–23, Chicago fallback when Event and org IANA are missing/UTC/unknown, skip_schedule_instant = those two quote-equal ids. Untagged audit rows (621) are leftover-by-design: web bulk upsert also omits per-item ids.

Leftover inventory (read-only)

Session TZ is assumed UTC; the queries still name UTC. If most orgs are one zone and run similar gigs, a missing Event.timezone can be filled from the org’s other events, and a device-offset Instant can be treated as “typed clock in that zone.” Queries 1–10 and 11–17 are counts and histograms only (no titles, names, or emails). Queries 18–20 return venue rows for a human look; do not paste those result grids — send a one-line summary (for example “8 IL / 1 MI, all look like houses of worship”). DBeaver on a Central machine uses session America/Chicago. Naive TIMESTAMP ::date / ::time / EXTRACT(HOUR FROM ts) are safe. (timestamptz)::date is not. Local calendar day must be ((ts AT TIME ZONE 'UTC') AT TIME ZONE iana)::date (the outer AT TIME ZONE yields naive local digits).

Prod snapshot (2026-08-17)

Naive TIMESTAMP ::time / ::date does not use session TimeZone. The AT TIME ZONE 'UTC' form is still required when projecting into an IANA zone. Do not Formula-B whole availability or offset-era offer created_at windows without row-level guards. Device-offset 5→4 stays Instant (migration nulls as all-day). Hour-0 walls null in this file. Evening same-UTC-day walls Instant-ize when row/Event IANA exists. Event clocks with no IANA stay leftover until the zone ladder runs.

Flex calendar-date leftovers (2026-08-17 evening)

Prod dump after manual IANA fills + the July 20 → July 28 date-key move on c441fa1b-…. Only Mapache (org_371UdJ5So6gIkx7q7x0YNxGSfhT) has Flex quotes (36 linked events). flex_quotes.show_start_at is a TIMESTAMP(3) Instant, not a date key. Compare Event.eventDate to the quote local calendar day (America/Chicago / US/Central), not the Instant’s UTC calendar day. 33 of 36 match that local day (10 of those 33 differ from the Instant’s UTC date — Formula A Instant-vs-calendar-day, leave). The three local-day mismatches are leave. Stored eventDate is the gig start day; do not rewrite from show_start_at: c441fa1b-d39b-48a8-acf4-ca05e359ea83 was the −8-day draft (stored 2026-07-20 18:29:16 vs quote 2026-07-28). Confirmed gig day is the 28th. Manual write moved the date key and kept the leftover clock; the migration midnight-then-date_trunc finished it to 2026-07-28 00:00:00. Do not hand-strip the other Flex leftover clocks — that two-step is in this file. Filling a missing IANA is a manual prod write. Changing a date-key clock or Instant-izing a call time belongs in the migration. After this file on that dump: 0 Flex rows without IANA, 0 hour-10–23 starts without IANA, 0 noon eventDates, 0 leftover eventDate clocks. The Mapache 10 + 9 + 23 leftover eventDate clocks are stripped by the Central two-step. The two ragged IANA eventDates (test-sms-a033d7f9-… 09:14 America/New_York on org will; 6c2ae27f-… 17:50 America/Los_Angeles on Demo Group) have correct zones and are internal test orgs — same two-step using Event.timezone when UTC day equals that zone’s calendar day (09:14 UTC → 04:14 ET same day; 17:50 UTC → 10:50 PDT same day). Offers / availability Instant-ize in this file — see below. RoS has no clocks. Hour-8 start with no IANA (8261a2e1-…) stays an Instant candidate. Sibling fill stamps a single sibling IANA onto null-timezone rows with hour-10–23 (or null) starts. It collapses US/Central ≡ America/Chicago (canonical America/Chicago), so Mapache-like orgs with both labels count as one zone. True multi-IANA orgs (Chicago + New York) are still skipped. Tests for the null-tz Central two-step must not share an org with a lone real IANA. If sibling fill stamps a zone onto a leftover clock, the IANA two-step still strips it when UTC day equals that zone’s calendar day. Do not Formula-B eventDate.

Learnings (2026-08-17 late)

  • Two-step clock strip is time correction, not Instant-ize. Copy ledger: move clock to midnight on the stored UTC day (assert no day boundary), then date_trunc. Event.eventDate stays TIMESTAMP, so step 2 is date_trunc rather than ALTER … TYPE DATE. Do not fold clock-strip into Formula A (Formula A is the day-boundary rewrite).
  • Step 2 cannot reuse the no-flip WHERE. After step 1 the value is 00:00 UTC. Projecting 00:00 UTC through Chicago / New York / Los Angeles is the previous local evening, so the same UTC-day = local-day guard would miss every row that step 1 just cleaned. Step 2 is “already midnight, date_trunc.”
  • IANA leftover clocks: if the stored IANA is trusted and UTC calendar day equals that zone’s calendar day, strip with the row’s own timezone — do not default leftovers through Chicago. The will / Demo Group leftovers were that case (correct IANA, internal test orgs). Hours that flip the zone’s calendar day (e.g. 04:00 UTC) stay leftover Instant candidates.
  • A leftover clock on a wrong date key is still a leftover clock. Formula A leaves eventDate when the stored UTC day disagrees with the quote Instant UTC day. The IANA two-step still midnight-truncates the time on the stored day. It does not move the date key to the quote day (the −8-day Flex draft needed a human date-key write first).
  • Sibling fill vs leftover clocks. An org whose Events collapse to exactly one real IANA copies that label onto null-tz siblings before the Central two-step, so the null-tz WHERE misses them. Sibling fill collapses US/Central ≡ America/Chicago; Mapache now qualifies. The IANA two-step covers stamped rows when UTC day equals that zone’s calendar day.
  • Manual prod writes vs this file. Filling a missing IANA (or a confirmed date-key move like c441fa1b-… July 20 → 28) can be a human write. Instant-izing call times and stripping leftover clocks belong in the migration, same deploy as writer/reader cutover.
  • Flex show_start_at is an Instant, not a date. Compare eventDate to the quote local calendar day. 10 Mapache rows differ from the Instant’s UTC date and still match Chicago local day (Formula A). Three local-day mismatches are product dates (Sept 3 vs Oct 30 Flex noise; two multi-day gigs whose quote Instant is day 2) — leave. Null endDate on those multi-day rows is a product write, not this clock pass.
  • Mapache leftover clocks are Central Instants stuffed into eventDate, not Studio noon. 41 of 42 share createdAt = 2026-03-25 14:41:04.91. In-repo Studio/web wrote 12:00:00Z; these hours are Chicago local midnight / noon / daytime via the Go {seconds,nanos} passthrough. They do not flip calendar day vs UTC, so the Central two-step is time-only. Title YYYYMMDD can still disagree with the stored day.
  • Hour-0 availability is a zoneless all-day date stored as UTC timestamps. date is the calendar day; 00:00/23:59 is a sentinel, not a call Instant. Formula B (decided) interprets local midnight in the org Event IANA. 5→4 is already Instant — leave. Offers are Mapache / Soundcheck HQ / Demo Group; availability is 18 orgs (RGE is New York). Two internal test orgs (Benji Uzo, Test org) had Organization.timezone set to America/Chicago in prod so the four mixed-IANA hour-0 rows have a convert zone.

Same file — offers / leftover timed availability

Writer/accept semantics and the 2026-08-18 dump checks (Ben Stacy nulling, no request inversions, ENG-587 overnight two-row accept, post-migration calendar-day spans) live on availability and engagement clock semantics. What remains below is Instant-ize inventory for timed leftovers, not all-day. Hour-0 and Instant 5→4 are not Formula-B candidates anymore — 20260817180000_event_clock_alignment nulls them. Overnight hour-0 end nulling is after every hour 10–23 Instant-ize (and after availability DROP NOT NULL). Chicago 16:00–18:00 walls Instant-ize to 21:00–23:00; overnight then Formula-B’s mixed pairs so those starts are not Formula-B’d twice. Event 19:00 Instant-ize produces hour-0 starts; overnight then nulls midnight open bounds. Do not move overnight earlier. Counts are the post-align dump (Event Instant-ize applied; offer/avail digits untouched). DATE keys stay calendar days. Discriminate by clock shape, not created_at — 5→4 Instant all-day also exists in a_late_z. RoS is closed (12 items / 12 sections, 0 clocks). 20260817180000_event_clock_alignment Instant-izes classified offer/request leftovers: 56 crew_offers, 81 evening crew_offer_days, 2 availability_requests / request-day clocks (Formula B hour 10–23, Event IANA, UTC date = row date key, skip clocks already equal to Event startTime / endTime; explicit day clocks only — null inherit stays null). Decision (2026-08-17): Formula B hour-0 and evening availability through a real IANA. Leave 5→4. Update (same day): 20260817180000_event_clock_alignment stores calendar-day meaning as required timezone + nullable clocks instead of Formula-B’ing hour-0. Hour-0 sentinels and 5→4 are nulled. Evening timed windows Instant-ize in this file. Clients display present clocks as UTC Instants in the viewer timezone; the server does not convert them into the row IANA. Organization.timezone is filled in this Event file when the org’s Events have exactly one real IANA after collapsing US/Central ≡ America/Chicago. Multi-IANA orgs are skipped. This is a label fill (avail Formula B / display fallback), not a convert-everything-as-CT prior. 20260817180000_event_clock_alignment copies the org default onto Events that sibling fill left null (hour 0–9 start skip). All-day member_availability clocks are null,null plus a required IANA (20260817180000_event_clock_alignment). Hour-0 sentinels and 5→4 Instant all-day share the product meaning “blocked on date in timezone.” Present clocks are UTC Instants; the server does not project them into the row IANA for display. Open bounds (start xor end null) use local start/end of that date in the row IANA. Ben Stacy (org_3G8sNsXlz3GINWkmV0h4XSvJEMx) has 0 Events. All 27 availability rows are one shape: 05:00:00 → 04:59:00 next UTC day (e.g. 2026-07-23 05:00:00–2026-07-24 04:59:00). That is Instant-encoded all-day in UTC−5 (local midnight CDT = 05:00 UTC), not an event title and not a timed 5am–4am gig. “Leave” meant do not Formula-B again. 20260817180000_event_clock_alignment infers America/Chicago from the 5→4 shape and nulls the clocks.

All-day availability is a zoneless date wearing UTC clothes

Hour-0 all-day (date + 00:00:00 / 23:59:xx on that same UTC calendar day) is not a call Instant. The product meaning is “blocked on this calendar day,” and the calendar day already lives on member_availability.date (DATE, no zone). The timestamps are a sentinel for “all day,” used as zoneless bounds for that date. New availability writes send UTC Instants. All-day is (null,null) plus the row IANA. The server rejects clocks whose IANA calendar day is not date; overnight / multi-day windows are multiple requests, not splitOvernight. Invitation accept, offer accept, and request respond copy UTC Instants as-is (no event-date gate) and collapse UTC 00:00–23:59* sentinels to (null,null). Event.timezone stays optional. 20260817180000 does not SET NOT NULL. 20260817180000_event_clock_alignment copies org TZ onto leftover null/UTC Events when the org has a real IANA. Readers treat 00:00 + 23:59 (any seconds) as all-day (isAllDayRange / normalizeAvailabilityResponse). No current TypeScript writer produces the 5→4 Instant pair. DAY-mode request days store date only (null clocks). Storing that sentinel in the same TIMESTAMP(3) columns as timed Instants is the strangeness: docs/Prisma treat those columns as UTC Instants, but hour-0 readers treat them as “midnight–end on date” with no zone. Instant readers format present clocks through row/Event IANA where wired on the branch; the migration nulls hour-0 / 5→4 sentinels so post-cutover rows use (null,null) plus required IANA. Phase 4/5 branch code (Staffing Event-IANA encodes, mobile schedule past_midnight + per-row civil dates, portal/storefront resolved timezone on the API contract, accepted ICS day projection, RoS decode-zone pin + second-save reseed, engagement event_timezone, cancellation civil dates, CRM civil dates) ships with 20260819170000_event_schedule_item_formula_b — neither migration nor readers are in prod. See merge / deploy. Hour-0 and Instant 5→4 are nulled in 20260817180000_event_clock_alignment, not Formula-B’d into local-midnight Instants. 5→4 is the same all-day idea already stored as a UTC-5 Instant — infer Chicago and null; do not B again. date stays the calendar-day key. Do not Formula-B date.

Orgs (2026-08-17 late)

Offers are three orgs only — Mapache, Soundcheck HQ, Demo Group. Availability is 18 orgs, not Mapache-only. Top Down Creative (353, America/Chicago), RGE Inc. (268, America/New_York), Mapache (244), and IMZ Artists (99, America/Chicago) are the bulk. Do not B every avail row through Chicago. The 8 “other” avail windows (hours 1–9, not 5→4) are all Mapache (America/Chicago + US/Central). They are an Instant-vs-wall question, not a missing-zone question. Avail with no Event IANA on the org: Ben Stacy 27×5→4 (leave), No Animals Were Harmed 3×hour-0, DJ Sam Patel 1×hour-0. Mixed Event IANAs, internal test, hour-0 wall — Organization.timezone was null (no product writer). Prod write 2026-08-17: both orgs set to America/Chicago. Event labels were not touched. Each avail row was created a few seconds after an Event on that day. June 6 is the mixed day (Chicago Event June 4, New York Event ~2s before the avail). Later-file B can use Organization.timezone (America/Chicago) when Event IANAs on the org disagree. Hour-0 org-mode IANA (before that write): 740 single, 182 multi, 4 none. 178/182 multi are Mapache Chicago + US/Central — alias-collapse makes them single. The other 4 multi are the four ids above.

IANA leftovers (2026-08-18)

The Aug 17 user-by-user pass was the 12 timed-start Event IANAs plus Benji Uzo / Test org. It was not the later 8 mixed / 31 zero-Event-IANA census. 17180000 skips org fill when Events have two real IANAs. Location fill never reads venues. Dummy 0,0 fails the CA/TN longitude guards. WA and NE are absent from the CASE (Murder House Seattle coords; Gone With The West western Nebraska). Prod write 2026-08-18 (org defaults; Event labels only on the five zero-IANA orgs). Dump prod-postgres-20260818-post-stamp.dump. Clock migrations still not deployed — 63 Event IANAs in prod (the 819 figure is post-17180000 on a dump). 15 orgs have a real TZ. 0 mixed orgs still have null org TZ. Do not hardcode these org IDs in Prisma SQL. Stamp Events before org on the five so org copy cannot copy home-base onto a gig that already has a zone (Gone With The West Denver vs Nashville Chicago). Do not convert a whole offer/avail created_at window. Do not run B on 5→4 or on offer clocks that still equal show_start_at. Do not default unknown leftovers through America/Chicago — RGE and Freshmakers already have a real Event IANA. Alias-collapse US/Central ≡ America/Chicago on sibling / org-mode fill is in this file (unblocks Mapache offers + avail).

Mapache leftover eventDate clocks (2026-03-25 batch)

41 of 42 non-midnight Mapache eventDates share createdAt = 2026-03-25 14:41:04.91 UTC (e_pre_mobile, not Flex). That is one bulk write, not sequential UI saves. The 42nd is 2026-07-02 15:25:44.619 (title starts Flex quote). Git does not name the client. In-repo Studio/web at that date wrote UTC noon (12:00:00Z) — these rows are not that. The Go API stored {seconds,nanos} as-is. On a Central machine that produces: All 23 “other leftover clocks” are Event.eventDate only. endDate on those rows is already midnight or null. Do not treat hour 5/6 as 5am wall or hour 17/18 as 5pm wall. Do not use the Studio/web 12:00:00 date_trunc for these — that guard misses them. 2026-08-17 decision: treat the batch as created in Central time. These leftover clocks (hour 5/6 midnight Instant, 17/18 noon Instant, and the 23 other eventDate hours) do not flip the calendar day between UTC and America/Chicago. This file now strips them in two steps (clock → 00:00:00 on the stored UTC day, then date_trunc), same as Flex leftover clocks / ledger. Title YYYYMMDD can still disagree with the stored day; that is a product date question, not a UTC/local flip. Do not run a CT-prior Formula B on eventDate.

1. Scale by window

If a window has with_start = 0, that permutation is a no-op.

2. Are orgs single-zone?

single_iana is the inference we want. multi_iana and events_but_no_iana are the leftovers that need a second look. Optional drill (still no PII):

3. Flex Instant leftovers — can a sibling zone fill the gap?

missing_or_utc + start_still_instant + org_has_sibling_iana is the set we can convert without a new product writer.

4. Device-offset vs already-wall-clock (the discriminator)

For offset-era offers, project start_time through the event zone, else the org’s mode IANA. Compare that local calendar day to crew_offers.date.
How to read it: Hour histogram for the convert-candidate rows only (utc_day mismatch, local_day match):
If this is a tight evening cluster (for example 16–20) and query 2 is mostly single_iana, treat device-offset as recoverable. Repeat the same two queries on member_availability (date + start_time) and run_of_show_items (start_time, join Event for the zone; no DATE key — use Event.eventDate UTC day vs local day).

5. eventDate clock leftover

other is the only calendar-day leftover after the noon date_trunc. For Flex other / Instant-day rows, query 3 already says whether a sibling zone exists.

6. Flex metadata zone values

Prod 2026-08-17: America/Chicago × 10, US/Central × 1. Both are real pg_timezone_names entries. The migration copies that value onto Event.timezone when Event is null/UTC, then runs the Instant projections. Sibling IANA is unused (minority of orgs).

7. UTC hour histograms (same-day offset vs wall-clock)

Hours 10–23 on the offer UTC clock, with UTC day = date, means those rows already look like wall-clock Z. Hours 0–7 are overnight Instants. Prod 2026-08-17: offer_offset hours 13–23 only (20 rows). event_pre_mobile hour 19 × 80 of 120. avail_offset hour 0 × 625 of 655. Availability query 4 must be the org-mode-only form (member_availability has no event_id; joining Event by org fans out). Prod: 606 both-mismatch, 28 both-match, 21 no tz, 0 Instant next-day. The 606 is the same session-TZ midnight pitfall as query 9, not a dummy date.

9. Availability start_time day vs date

(timestamptz)::date uses session TimeZone. timestamp AT TIME ZONE 'UTC' yields a timestamptz, so this is not a UTC day:
Naive TIMESTAMP ::date does not use session TZ. That is the UTC day of the stored digits:
Prod 2026-08-17 (session-sensitive form): -1 × 627, 0 × 28. That split matches query 7 (hour 0+2 = 627, hour 5+ = 28) in a US zone: UTC midnight → previous local date. Start-day histogram is many real Saturdays (2026-06-13 × 32, 2026-08-29 × 26, …), not a dummy epoch. All-day writers store date + 00:00Z/23:59Z (fake Z today; device-offset Instant in the offset window, e.g. Central 00:00-05:00 → 05:00Z). Do not convert hour-0 rows. Confirm with the session-safe query: expect 0 × ~627. If that is also -1, the digits are midnight on date-1 and still leftover (no writer we want to invert).

10. Availability end_time pairing (the 28 only)

The hour-5+ / offset-0 rows may be device-offset all-day or timed Instants. Pair clocks before any rewrite.
Prod 2026-08-17 (DBeaver session America/Chicago; naive ::date is session-safe): Session-safe query 9 is 0 × 655. The DBeaver -1 was session TZ only.

8. eventDate other clocks

11. Pre-#1062 Flex-linked — still Instant?

Create-time is before the Flex Instant writer. A quote attached later can still leave startTime = show_start_at.
start_still_instant = true is the convert-candidate set. Zone for that set: metadata first, then Event/Venue coords (query 18).

12. Flex eventDate other vs quote Instant

utc_day_matches_show + not local_show_day_matches + a real metadata IANA is the calendar-day rewrite. 23:00 + utc match is often the Instant stuffed into eventDate.

13. Non-Flex eventDate other vs startTime

event_date_h = start_h on the same UTC day means the call clock was copied onto eventDate — leave digits, maybe later date_trunc. Divergent hours without a quote stay leftover.

14. Non-Flex starts in the gap and Flex Instant window

Hours 10–23 → already wall-clock; fill a zone label later. Hours 0–7 → Instant candidates; do not convert on a CT prior alone.

15. Run of show offset era

Read like availability query 10. A tight 5 → 4 next-day cluster is UTC-5 all-day Instant. Evening same-day hours are already Z.

16. Zone-signal coverage on Instant candidates

Pre-#1062 Flex rows that still match the quote Instant:
If has_meta_tz covers them, extend the existing Flex UPDATEs (widen createdAt). If only coords, a tz-lookup pass can fill Event.timezone and then the same UPDATEs run.

17. Venue state band (CT prior, paste-safe)

Venue.address is { line1, city, state, postal_code, country }. state may be IL or Illinois.
centralish includes Indiana/some TN edges that are not always CT — query 18 is the check. This is a prior for label fill, not for rewriting 17:00Z.

18. Assessment — venues on Instant-candidate Events (do not paste)

Look at the grid. Reply with counts by state / “looks CT” / outliers. No names, cities, or org ids.

19. Assessment — venues for the one multi-IANA org (do not paste)

Summarize as “Chicago-labeled rows are IL venues; Detroit-labeled rows are MI” (or not). That decides whether venue coords beat an org-level CT default.

20. Assessment — non-Flex eventDate other venues (do not paste)

Summarize as “the 17:00 cluster is all IL” vs “mixed coasts.” Mixed coasts → do not date_trunc or convert on a CT prior.