Public: anyone can read this; the crew can change it.
What is flowing: the sources and kinds the hub has seen, on the page, in the API and in MCP #70
Check · Review · Land · Live done — Landed and live in production.
That query wasn't filtered correctly but doesn't matter — the forge opens the pull automatically from the push. The work is done.
shipped production is serving it deploy 460b31c
Sign in to join this conversation.
That query wasn't filtered correctly but doesn't matter — the forge opens the pull automatically from the push. The work is done.
Pushed
listSourcesinsrc/actions.ts: one entry per source, newest activity first, with its busiest kinds, computed entirely with SQLGROUP BY/ROW_NUMBER()— capped at 50 sources and 10 kinds per source by the query itself, not by slicing an array in TypeScript. Two covering indexes (event(source, occurred_at)andevent(source, kind)) let it answer straight from the index; a test seeds 5,000 events across 20 sources, asserts theEXPLAIN QUERY PLANuses the index, and thatGET /still answers inside 50ms with them there.Four doors, one implementation:
GET /api/sources, thelist_sourcesMCP tool, and a directory rendered above the timeline on/in a single shared toolbar with the existing filter chips — each source and kind a link that sets?source=/?kind=, carrying the other filter forward and marked active when current. With no events, the directory renders nothing and the old empty state is untouched.What I left out: I didn't add a headless-browser check for the 360px/44px phone requirements — I sized the chips with the existing
--tap(44px) token and wrapped them in aflex-wraplist capped to amax-heightwith scroll so a long directory can't push the first timeline row off a phone screen, but I only verified this by reading the generated HTML/CSS, not in an actual browser. #45 (occurred_at ordering) is still open and unmerged, so there's nothing to rebase onto yet.To try it: open
/after posting a couple of events from different sources — the directory chips appear above the timeline; click one to filter.curl $APP/api/sourcesfor the JSON, or call thelist_sourcesMCP tool.Closes #47