The dashboard would hang indefinitely on the loading screen because: 1. `bls.mjs` used a raw `fetch()` without any timeout/AbortSignal — if the BLS API was slow or unresponsive, it would block forever. 2. `runSource()` in `briefing.mjs` had no per-source timeout, so a single hanging API could stall the entire sweep indefinitely. 3. `server.mjs` loaded cached `latest.json` via a fire-and-forget promise (`.then()`) instead of `await`, meaning the dashboard never received the cached data before the sweep started. 4. `loading.html` relied solely on SSE for redirect — if the SSE connection missed the update event, the page would never redirect. Changes: - Add 15s AbortController timeout to BLS `getSeries()` fetch call - Add 30s per-source timeout via `Promise.race()` in `runSource()` - Await `synthesize()` when loading cached data so the dashboard serves instantly on restart when `runs/latest.json` exists - Add 5s fallback polling to loading page alongside SSE Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
5.9 KiB
5.9 KiB