createdAt window those rows sit in, and what the migrations plus Phase 2 + Phase 4/5 branch Instant readers mean for those rows. Migrations are still not deployed on cited dumps; reader code on cursor/eng-580-timebound-clock-alignment-b9d9 is likewise branch-only.
Inventory ran from DBeaver with session
America/Chicago, not the deployed app. Naive TIMESTAMP ::date / ::time / EXTRACT(HOUR) are session-safe. (timestamptz)::date is not.Locked target
NaiveTIMESTAMP(3) call clocks are UTC Instants. Event.timezone is a display IANA. Date-key columns stay calendar dates (UTC midnight of the venue’s calendar day), not venue-midnight Instants.
Two formulas, never mixed:
Do not run B on a row that is already Instant (
startTime = show_start_at, or availability 05:00 → 04:xx next UTC day).
How to read an interval
A writer interval is UTCcreated_at / Event.createdAt, half-open: >= start AND < end. Both ends are named even when a side is indefinite (−∞ or +∞). The right end is the start of the next writer, not the last row of this one.
created_at names a writer only if the row was never saved again. A later header save re-encodes call times. Flex quotes attached after create-time (25 in the gap, 1 in web-Z) are the usual lie.
Calendar-day bounds are midnight UTC. PR / first-row bounds are merge or first-row seconds.
Event intervals
Noon calendar days (
eventDate::time = 12:00:00) are not a writer interval. Both ends are indefinite; the predicate is the clock.
Offer, availability, and RoS intervals
Availability splits inside
a_device_offset by clock shape, not by another created_at bound: hour-0 wall (625), 5→4 Instant pair (15, leave), timed leftovers (15).
Two meanings of active
Display-active is what the gigs list calls Active. A past stored-active gig already shows as Completed. The one
UNARCHIVED row is stored-active but past, so it is in the 880 and not in the 156.
Display-active is a calendar-day filter, not a writer interval. A March create for a September gig is still
e_pre_mobile.
Active Events by createdAt interval
All 880 stored-active and 156 display-active rows, same half-open CASE as query 1.
Display-active with a
startTime: 22. Display-active with a real IANA (timezone not null and not 'UTC'): 17.
Of the 156 display-active:
- 131 are pre-mobile / mobile / gap (47 + 17 + 67). Almost no IANA (0 + 0 + 3).
- 19 are Flex Instant overlap (14 starts, 12 with IANA).
- 4 are web fake Z (2 starts, 0 IANA).
- 2 are after
#1328(1 start, both have IANA).
What this file can rewrite of the 156
20260817180000_event_clock_alignment Instant-izes Event wall hours 10–23 only when a real IANA exists, and skips quote-equal Flex clocks. It also fills Flex metadata IANA and projects Flex Instant calendar days in the #1062 … #1292 window.
It can touch the IANA slice of display-active — mainly Flex Instant overlap (19, 12 zoned) and the 2 after #1328 in that snapshot. Later #1387 Formula A walls restore from the quote Instant (metadata zone first). It cannot Instant-ize the 131 display-active rows in pre-mobile / mobile / gap without a zone ladder first. Mobile #379 display-active is 17 events with 0 starts.
Recommended fix
Same-release cutover. Do not teach every reader “these digits are UTC” until that row is already Instant or a proven IANA exists to Instant-ize it. A global reader flip on the 596 no-zone Events shows UTC hours and recreates Mapache in reverse.- Same deploy: writers store a real Instant and a real IANA; readers format Instant →
Event.timezone(Phase 2 + Phase 4/5 branch code); ship20260817180000_event_clock_alignmentand20260819170000_event_schedule_item_formula_bas written. Schedule Formula B SQL covers hour 10–23, overnight inverted ends, and invalid Event IANA → org, but no schedule rows convert whileconvert_schedule_wallis empty — populate dump-proved ids before prod. Run the:5434integration test before prod. - Transitional read for leftovers: real IANA → Instant;
startTime = show_start_at→ Instant even if the zone was just filled; null /'UTC'and not quote-equal → still wall. - Zone ladder, display-active first. Fill a label, then formula B. Never use a CT prior as the convert zone. Order: real
Event.timezone→ Flexmetadata.timezone(skipUTC) → Event / Venue lat/lng (skip0,0) → sibling Event IANA →Venue.address.state→America/Chicagolabel only after venues agree. Then the 25+1 Flex-linked created before#1062(query 11). Hours 0–9 stay Instant candidates. - The same file Instant-izes offer Formula B (56) +
crew_offer_daysoverrides, and avail same-UTC-day hour 10–23 evening walls (row IANA, fake-Zupdated_atband). Avail hour-0 and5→4are nulled with a required IANA. RoS has 0 clocks. See cohort-alignment leftovers. - Make
Organization.timezonea real writer so new orgs stop landing in the leftover bucket.
created_at window. Do not run B on Flex quote-equal or avail 5→4. Do not default leftovers through America/Chicago. Do not mix LedgerItem.date (ENG-581). Do not edit applied 20260307.