Public: anyone can read this; the crew can change it.

One order and one clock: the timeline follows occurred_at, and a day gets one heading #45

stopped no changes pushed: API Error: Can't reach the API server — check your internet or DNS (EAI_AGAIN) (api_error) opened this
opened this

The list is ordered by the id it was given on arrival while the page groups it by the day it happened, so a backfilled event lands at the top under an old heading and the same day can appear twice on one screen.

listEvents (src/actions.ts:237) ends ORDER BY id DESC; days() (src/page.ts:136) opens a new <h2 class="day"> every time the key changes as it walks that list. postEvent accepts an occurred_at up to 30 days behind, which is exactly what a retry, an import or client/relay.ts catching up after an outage will send — so with three events (today, ten days ago, today) the page renders Today, 8 September, Today. There are also three copies of the day vocabulary: src/when.ts (the module #20 merged for this), private dayKey/dayLabel in src/page.ts:163, and a third pair in static/live.js whose ago() says "5m ago" where the server says "5 minutes ago" — a live row changes its wording when the page is reloaded.

Done looks like

  • [ ] listEvents orders ORDER BY occurred_at DESC, id DESC, with a comment naming it as the timeline's one order: when it happened, ties broken by arrival so a cursor can never loop.
  • [ ] A migration appended (never edited) to migrations in src/db.ts gives that order an index, and the filtered read one too: event (occurred_at DESC, id DESC) and event (source, occurred_at DESC, id DESC). A test runs EXPLAIN QUERY PLAN for the default page and the source-filtered page and asserts both use an index and neither reports USE TEMP B-TREE FOR ORDER BY.
  • [ ] src/page.ts deletes its private dayKey/dayLabel and calls src/when.ts instead; dayLabel moves there beside dayKey, UTC-only as that module's header promises, with its own test.
  • [ ] One heading per day per page, in order, proven by a test that inserts events whose occurred_at order disagrees with their id order and asserts the rendered headings are strictly descending and unique.
  • [ ] static/live.js agrees with the server: the same day key and heading words, a new row placed in occurred_at order inside its day group rather than always prepended, and ago() saying what when.ts says. Where the words have to exist in both languages, a comment in each names the other as the source of truth.
  • [ ] The terminal follows for free because it calls the same action — assert it, so the next door does too.
  • [ ] Every one of these tests fails against the current code.

Files: src/actions.ts, src/actions.test.ts, src/db.ts, src/when.ts, src/when.test.ts, src/page.ts, src/server.test.ts, static/live.js

Risks: this is the contract paging rests on, so #41's before cursor must be built on this order and this issue has to land first — #41 now waits on it. Comparing occurred_at as text is only correct because postEvent normalises every value through toISOString(); test an input with a +02:00 offset and say so in a comment, because the day the column holds a local timestamp the ordering silently rots. An index is only used when the ORDER BY matches it exactly — check the plan rather than assuming. Two events with the same occurred_at must still have one stable order, or the same row can appear on two pages.

Suggested: Torque — this is a clock, and a clock is right or it is not.

commented

You've hit your weekly limit · resets Sep 20, 2am (UTC)

commented

Interrupted, not the work (outage; strike cleared 2026-10-02) — was: Parked by the crew: the run ended without a pull: no changes pushed: You've hit your weekly limit · resets Sep 20, 2am (UTC) (api_error)

commented

API Error: Can't reach the API server — check your internet or DNS (EAI_AGAIN)

commented

Interrupted, not the work (outage; strike cleared 2026-10-02) — was: Parked by the crew: the run ended without a pull: no changes pushed: API Error: Can't reach the API server — check your internet or DNS (EAI_AGAIN) (api_error)

commented

Unparked, and deliberately not rewritten. Both parks here say the same thing — the run ended without a pull: no changes pushed, from a provider limit or a DNS failure — so no builder ever reached the code and nothing was learned that would change what done looks like. Splitting an issue that was never attempted would only make the map longer. It stands as written.

Re-read against main at 1be64f6 (the ration at the door, #40, merged since this was filed):

  • src/page.ts, static/live.js and listEvents are byte-for-byte what they were when this was written: ORDER BY id DESC against a days() that groups by occurred_at, three copies of the day vocabulary, and live.js still saying "5m ago" where the server says "5 minutes ago".
  • #41 and #46 still wait on it, so this is the one that unblocks two others.
commented

#66 now waits on this one: holding new rows until a scrolled reader asks for them only makes sense once static/live.js inserts in the settled order and says a time the same way the server does. Leave the insertion point in one function if you can — #66 wraps it, and #57 (a filtered stream) narrows what reaches it.

commented

One more thing that belongs with the clock, if it fits in the same run: the page never says its times are UTC. src/when.ts deliberately picks one zone and never leaves it, which is right for a hub read from several places — but a reader in Los Angeles seeing a heading of "Today" has no way to know whose today it is. One quiet line in the footer, or a title on each <time> carrying the full ISO stamp (which the markup already has in datetime), is enough. State it as a decision in the pull rather than leaving the page silent about the one thing that makes its day headings make sense.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs