← PROTOTYPES

The earnings tape

EVENTS now opens on a timeline you drag sideways: one bar per trading day, as tall as the number of your names reporting that day, history to the left and what is coming to the right. MONTH, WEEK and DAY are all still there, one tap away, unchanged. Nothing is deployed: branch hub/earnings-timeline-20260923, built from Hub production 8927dc4.

“Maybe something that's more like a timeline scrolling left to right that shows counts — September 2 has more than September 1 — and it's a scrollable way of going to the history too. Like a chart of the tick of the earnings tape… I feel like an oscillator is better of some type, a scrollable oscillator left to right.”

1 · What the tape shows

Every bar is one trading day. Its height is how many of the names the Hub tracks report that day. Its colour is that same number, on the load law the MONTH view already uses: cyan under 12, orange from 12, red from 25. Today is marked with a cyan day-number and a line. The biggest name reporting rides the top of the tall bars. The months are written underneath.

The one thing that moves, and the one thing that never does. The height is scaled to the busiest day actually on screen, and it is re-scaled as you drag — that is the answer to “I'm seeing a lot of empty calendar days… the view should auto-adjust in some way”. A quiet fortnight fills the track with its own shape instead of lying flat. The colour is never re-scaled: red always means 25 or more reports, in season and out of it, so the two can never be confused. When the whole stretch on screen is quiet, the tape says so in words and gives the real number.

As it opens — today, out of season

the earnings tape as it opens
1680 px · today is 23 September. Bars of 6, 9, 8, 6, 4, 2, 1 through late September and October, the count written on top of each bar, SEP and OCT labelled underneath, today's 23 in a cyan chip with a vertical line. The right-hand rail is the existing UPCOMING list.

Dragged into the season — November

the tape scrolled to November
1680 px · the same tape dragged right. Wednesday 4 November stands at 38 in red with GOOGL riding it; 28 and 29 October are 33 and 33, also red, carrying GOOGL and AAPL; 19, 12, 23, 24 are orange; the small December days are cyan. This is the shape of the season.

Dragged into history — the spring reporting season

the tape scrolled back to April and May
1680 px · dragged left to late March, April and May: 28, 34 and 31 in red (AAPL and AMD on the tallest), a run of orange 22, 18, 22, 21, 24, and the quiet stretches between them still showing their own shape. This is the “scrollable way of going to the history”.

On the phone

the tape on a phone, November
390 px · the season, with narrower days and a shorter track so a whole month is still under the thumb.
the tape on a phone, history
390 px · dragged back into history; the day panel stays open underneath.

A bar, tapped open

a day opened under the tape, with a company card
1680 px · Thursday 3 September tapped: 4 REPORTING, grouped “after the close”, with AVGO +3.4%, DELL +44.3%, ZS +9.2%, PATH +1.0%. Clicking AVGO opens the same card the WEEK view draws — EPS 3.21 → 3.32 (+3.4%), revenue $29.2B → $29.6B (+1.2%) — with Release, Transcript and Summary. The tape does not move when a day opens, and the open day's column is lit.

The tape lands with the next day that actually has reports already open underneath it, so entering EVENTS shows the working list straight away. Closing it keeps it closed.

2 · Where each number comes from

What you seeWhere it comes from
The height and the number on a barA count of rows in earnings_events for that date, filtered to the names in cohorts and then scoped by the cohort strip at the top, exactly like the rest of the room. Nothing is estimated.
The name on a tall barThe biggest by market value among that day's reporters, using the market caps the board has already read. If the board has not loaded yet, the note says so and the names are alphabetical for the moment.
The day panel and its cardsThe same functions the WEEK view uses — the same chips, the same grouping, the same card — so a day here and the same day there can never disagree.
“before the open / after the close”earnings_events.report_time. Where it is empty the panel says time not announced. It is never guessed.
The window180 days back and 120 days forward of the anchor, read in two requests so a busy season cannot silently lose its far end. The arrows move the window three months; TODAY brings it back.

Measured in the browser on this branch: 215 trading days drawn, 128 of them carrying reports, 1,009 reports in the window on the ALL scope, busiest day 2026-11-04 with 38. No page errors at either size.

3 · Report times — why Costco, Micron and ASML said “time unknown”

Because the stored calendar carries no time for them. This is an upcoming problem only: rows that have already reported nearly all carry one.

Measured 23 Sep, your tracked namesRowsWith a report time
The next 30 days812  (2.5%)
The 30 days behind4239  (93%)

The source I chose: Nasdaq's own earnings calendar. It is public, needs no key, and states the time as “time-pre-market”, “time-after-hours” or “time-not-supplied”. I measured all 23 weekdays of the next 30 days against our rows.

Report time on the next 30 daysBeforeAfter the backfill
Rows with a stated time237
Coverage2.5%45.7%
Costco · 24 Sep—AMC (after the close)
Micron · 30 Sep—AMC (after the close)
ASML · 14 Oct—BMO (before the open)

Why it is not 100%, and why that is the honest answer. Of the 81 rows: 35 get a time; 31 are rows Nasdaq lists but marks “time not supplied” — nobody has announced one yet; 13 are not in Nasdaq's calendar for that day at all; 2 already had a time. Those 44 keep saying time not announced. Across Nasdaq's whole window, only 128 of 543 rows carry a stated time, so this is the state of the world rather than a gap in the read.

The other candidates. FMP's calendar and Finnhub's hour field both need an API key, and there is no key on this machine or in the Hub (the Hub deliberately never calls FMP from the browser), so I could not measure either and do not claim a number for them. Nasdaq needs no key and can be called from the backend the same way. The issuers' own IR pages are the most authoritative for the biggest names and are the natural third step, one name at a time.

A finding I did not act on: for 9 rows our stored date and Nasdaq's disagree — NKE, DAL, WFC, PGR, CSX, ELV, PLD, PM, PG. The backfill matches on ticker and date, so it writes nothing for these: a different date is a different event. A wrong date puts a name on the wrong bar, so this is worth its own pass.

What is written, and by whom

4 · Transcripts — the button already opens the real thing

I checked the store directly. earnings_call_transcripts holds 1,405 rows. Every one carries the call's full text. Not one carries a URL. earnings_events.transcript_url is empty across the entire table, and 171 calls carry an AI summary. The newest call stored is 11 September.

So the answer to “why does no transcript row have a URL” is that the job that writes them never receives one: it is given the transcript's text by its provider, stores the text, and leaves url null. The column was never filled and nothing syncs anything back to earnings_events. That job does not live in the Hub repository and is not on this Mac, so I am naming what the data proves rather than quoting its code.

What the Hub does today, verified in the browser, not read off the page: the ◹ Transcript control appears only when a stored call sits within three days of that card's date, and it opens the stored text — I opened AVGO's 3 September card and got 39,621 characters of the real Broadcom Q3 FY2026 call, beginning “Operator: Welcome to Broadcom Inc.'s Third Quarter Fiscal Year 2026 Financial Results Conference Call”. No card links to the dead column. Where a summarised call exists, the card offers ▤ Summary or ▤ Call summary, and says which of the two it is.

the transcript window open over the tape
1680 px · the stored Broadcom call, opened from the card on the tape.

One real defect found and fixed. Measured at 1680 × 1000: the transcript window came out 1,103 px tall inside a 1,000 px screen, so its own header — and its ✕ Close — sat 35 px above the top edge and could not be clicked (only the dimmed background could close it). The window is now held inside the screen it opens in: measured again, 946 px tall, close button visible.

5 · What could be wrong

6 · What I did not do

Tests: 446 in tests/, 442 pass, 2 fail — the same two that already fail on production (“every place this surface prints an age uses the one function” and xfeed-publish). 19 of the passing tests are new here: 11 for the tape, 5 for the report-time rules, 3 for the transcript control.