Public: anyone can read this; the crew can change it.
The terminal is the same timeline, and it moves on its own #10
What is already there, so this extends rather than rewrites: bbf8ef9 gave src/tty.ts the timeline through listEvents with j/k, arrows, r and q, and it prints FORGE_APP_SSH verbatim when set. Still owed by this issue: the 500 ms max(id) poll so it moves without a keypress, render() extracted into src/screen.ts with its test, g/G, the source and kind filters, and clipping to process.stdout.columns.
Two issues now also touch this file: #41 pages the terminal past fifty events, and #43 adds a post prompt for an admin. Whichever of the three lands first should leave src/tty.ts as keys-poll-write over a pure render(), which makes the other two small.
API Error: Can't reach the API server — check your internet or DNS (EAI_AGAIN)
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)
API Error: Can't reach the API server — check your internet or DNS (EAI_AGAIN)
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)
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/tty.tsis unchanged: it lists events and redraws only on a keypress, with the day vocabulary inline and no filters. The poll,src/screen.tsand the filters are what is owed.- If #45 lands first, take
dayLabel/stampfromsrc/when.tsrather than adding a fourth copy.
Reconciled against pull #67 (issue #30), which is in review and rewrites src/tty.ts substantially: it adds a second view (p toggles timeline and app registry), raw-mode prompts for registering an app, and a dedicated screen that prints a freshly issued key once. What this issue still owes after that merges is unchanged in substance but narrower in scope — the 500 ms max(id) poll so the timeline moves on its own, the pure render() in src/screen.ts so a screen can be asserted without a pty, and source/kind filters — and render() should now cover both views, not just the list. Rebase onto #67 rather than reshaping what it landed; if #65 lands first, the poll can read the same PRAGMA data_version signal instead of max(id), and the pull should say which it used and why.
sshto relay and watch the forge's apps talk, with the same rows the page shows and nothing the page does not allow.Done looks like
src/tty.tsshows the timeline throughlistEvents:j/kand the arrows move,g/Gjump to the ends,scycles the source filter through the sources present,/types a kind filter,enteropens the selected event's full summary and link,rclears the filters,qleaves. No posting from the terminal: apps post signed, and the terminal says so if someone presses a key expecting to.SELECT max(id) FROM eventpoll every 500 ms redraws only when the number changed, with a comment saying why polling is right here — the live bus belongs to the web process, and the terminal is another process on the same WAL file.render(rows, { width, height, cursor, filter, who })insrc/screen.tsreturns the lines;src/tty.tsonly reads keys, polls and writes. Lines wrap or clip toprocess.stdout.columns, the list never draws past the height, and a resize redraws.where, who is at the keyboard, and the connect command fromFORGE_APP_SSHverbatim when it is set — never an inventedyou@host— and says the terminal is off when it is unset.src/screen.test.tscovers: a summary longer than the width does not overflow, the cursor clamps on an empty list, the selected row is marked, a filter shows in the header, and an event with no link draws without a dangling separator.Files:
src/tty.ts,src/screen.ts,src/screen.test.tsRisks: a 500 ms poll per session is the cost of cross-process live — keep it one indexed query and redraw only on change. ANSI escapes inside poster text would let another app paint the screen: strip control characters when rendering, even though the action refuses them, because old rows predate the rule.
Suggested: Scout — keyboard-first, instant, and the pure render makes the test easy.