Explorer: event detail timeline (#139) #172

Merged
claude-bot merged 2 commits from feat/explorer-event into main 2026-08-01 05:25:01 +00:00
Contributor

Closes #139. The Explorer's centerpiece, stacked on the day view (#138/PR #171, merged).

What this adds

GET /explorer/event/{event_id} — the full reconstruction of one correlated event:

  • Timeline across all members, chronological: one entry per nws_alert_snapshots update with the full official text (description + instruction, collapsed <details>); an honest fallback entry from the dashboard SentAlert when a lifecycle predates capture ("full text not captured"); all-clear entries from cleared_at; lightning-episode spans; context members (watches) visually distinct from cores.
  • Delivered-notification rail from notification_deliveries, including failures with attempts + last_error — "we tried and it failed" is part of the historical record, per the issue.
  • AI summaries inline (the #23 coordination point). Notable finding while wiring this: summaries are only ever generated for nws_watch/nws_advisory product families — warning-severity products have no summary path by design (gated behind backlog #24), so the section is naturally absent for warnings.
  • Radar stills: the first-fire snapshot plus the captured alert_radar_frames strip (chronological); the #140 loop player slots in where marked.
  • Source links to public alert pages where one exists for a member lifecycle.
  • Per the issue: the existing /p/{token} timeline CSS is generalized into a shared .wb-timeline class (alias selector — the public template needed zero changes), not forked.

404 deliberately doesn't distinguish unknown-event from invisible-location (no existence leak). Archived locations render with the badge; visibility checked before any data loads. Every section is one bounded query keyed off the event's member ids — no per-member loops. MCD members render nothing yet (no lifecycle-keyed source rows exist; documented — they arrive with future SPC association work).

Review fix

One test-data bug: the delivery-rail test inserted delivered + failed rows under the same (sent_alert, channel, kind), which the schema's UNIQUE constraint correctly rejects — surfaced by the real test infrastructure, fixed by giving the failed delivery its own channel.

Verification

Full bulk suite on the dev server: 954 passed (12 new event-page tests: snapshot ordering + full text, no-snapshot fallback, all-clear entries, context-member styling, delivery rail delivered/failed, AI summary present/absent, archived badge, 404s, radar snapshot URL). ruff clean. No migrations, no new JS.

🤖 Generated with Claude Code

Closes #139. The Explorer's centerpiece, stacked on the day view (#138/PR #171, merged). ## What this adds `GET /explorer/event/{event_id}` — the full reconstruction of one correlated event: - **Timeline** across all members, chronological: one entry per `nws_alert_snapshots` update with the **full official text** (description + instruction, collapsed `<details>`); an honest fallback entry from the dashboard `SentAlert` when a lifecycle predates capture ("full text not captured"); all-clear entries from `cleared_at`; lightning-episode spans; context members (watches) visually distinct from cores. - **Delivered-notification rail** from `notification_deliveries`, including **failures** with attempts + `last_error` — "we tried and it failed" is part of the historical record, per the issue. - **AI summaries inline** (the #23 coordination point). Notable finding while wiring this: summaries are only ever generated for `nws_watch`/`nws_advisory` product families — warning-severity products have no summary path by design (gated behind backlog #24), so the section is naturally absent for warnings. - **Radar stills**: the first-fire snapshot plus the captured `alert_radar_frames` strip (chronological); the #140 loop player slots in where marked. - **Source links** to public alert pages where one exists for a member lifecycle. - Per the issue: the existing `/p/{token}` timeline CSS is **generalized into a shared `.wb-timeline` class** (alias selector — the public template needed zero changes), not forked. 404 deliberately doesn't distinguish unknown-event from invisible-location (no existence leak). Archived locations render with the badge; visibility checked before any data loads. Every section is one bounded query keyed off the event's member ids — no per-member loops. MCD members render nothing yet (no lifecycle-keyed source rows exist; documented — they arrive with future SPC association work). ## Review fix One test-data bug: the delivery-rail test inserted delivered + failed rows under the same `(sent_alert, channel, kind)`, which the schema's UNIQUE constraint correctly rejects — surfaced by the real test infrastructure, fixed by giving the failed delivery its own channel. ## Verification Full bulk suite on the dev server: **954 passed** (12 new event-page tests: snapshot ordering + full text, no-snapshot fallback, all-clear entries, context-member styling, delivery rail delivered/failed, AI summary present/absent, archived badge, 404s, radar snapshot URL). `ruff` clean. No migrations, no new JS. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
New GET /explorer/event/{event_id} page: chronological timeline across all
of a WeatherEvent's members (NWSAlertSnapshot-backed entries with full
official text, a pre-#129 fallback for lifecycles with no captured
snapshot, all-clear entries, and lightning-episode windows), plus a
delivered-notifications rail, matching AI summaries, alert-time/periodic
radar stills, and source links to any public alert pages. Generalizes
.public-alert-timeline into a shared .wb-timeline class in app.css (alias
kept so public_alert.html needs no template change) and reuses it here.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Fix delivery-rail test data: unique (sent_alert, channel, kind) constraint
All checks were successful
CI / test (pull_request) Successful in 3m44s
08f3288fd2
The test inserted a delivered and a failed delivery under the same
channel, which the schema's UNIQUE constraint correctly rejects; the
failed row now uses its own channel.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
rbrooks/WeatherBot!172
No description provided.