-
released this
2026-08-01 19:51:28 +00:00 | 21 commits to main since this releaseRelease candidate for the v2.0.0 Historical Weather Event Explorer (#22) — for dev rehearsal before the final cut. Image:
git.rhoving.com/rbrooks/weatherbot:2.0.0-rc1. Deploy: bump dev'sweatherbot_imageoverride in iac-repo and run the play againstdocker-test.Pick any day in the last 13 months and see what happened: reconstructed per-location events (correlation layer #135/#136), a month calendar (#137), day detail with SPC risk bands (#138), the full event timeline — official product text, delivery record including failures, inline AI summaries (#139/#23) — radar loop replay (#140), and JSON export (#142). Location deletion now archives instead of destroying history (#134);
/statsis range-bounded with five benchmark-justified indexes behind it (#141).Upgrade notes: migrations 0034–0036 apply at first boot (new derived tables + indexes, no existing-data changes); the correlation job backfills
weather_eventsfrom retained history within 30 minutes of startup.Full details in the CHANGELOG.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
-
Source code (ZIP)
-
v1.8.1
Stablereleased this
2026-08-01 02:51:24 +00:00 | 48 commits to main since this releaseFix release for the dashboard-accuracy bugs surfaced by post-migration verification during the 2026-08-01 severe-weather event, plus a CI reliability fix. Image:
git.rhoving.com/rbrooks/weatherbot:1.8.1. Deploy: bumpweatherbot_imagein iac-repo and run the play.Fixed
- Permanent "data freshness" warning (#161) — days 4–8 SPC outlook text now fetches the real combined
SWOD48product under one freshness key; migration 0033 deletes the five deadSWODY4–8rows (~26k accumulated failures) that pinned the degraded-data banner. - Nowcast false "no precip in the area" (#162) — sampling now reads a ~±1 km pixel neighborhood instead of one exact pixel, and honestly reports "(no forecast frames available)" when RainViewer's forward feed is out (
nowcast_availableflag added to the API result). - Concurrent CI runs killed each other's Postgres (#165) — per-run container name + ephemeral published port in
ci.yml.
Migration 0033 runs automatically at first boot of this image (a pure row deletion — no schema change). Bulk suite 856/857 green on dev; all three PRs (#163, #164, #166) passed CI individually.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- Permanent "data freshness" warning (#161) — days 4–8 SPC outlook text now fetches the real combined
-
v1.8.0
Stablereleased this
2026-08-01 00:22:45 +00:00 | 59 commits to main since this releaseFirst release published as a container image: this tag builds and pushes
git.rhoving.com/rbrooks/weatherbot:1.8.0viarelease.yml. Production deploys are operator-run fromiac-repo(bumpweatherbot_image, run theweatherbotplay) — deliberately not from CI, so no production credentials live in Actions secrets (#154).Added
- Alert history capture, ungated (#129) — snapshots for all monitored locations, independent of public-page settings; groundwork for the Historical Weather Event Explorer (#22)
- Periodic radar frame capture for active alerts (#130)
- Media storage abstraction (#131)
- ENTLN lightning cluster archive (#132)
Changed
- Unified 13-month retention horizon (#133)
cd.ymlrenamed "CD (dev only)" (#154) — production tracks release tags, notmain
Fixed
Alert-correctness fixes in the all-clear path: supersession false all-clears (#145), incomplete-feed guards (#146, #147), unbounded all-clear retry (#148), all-clear image URL encoding (#152).
Chores
Consolidated dependency refresh (#126) plus FastAPI/Python/Actions bumps; retired drift-prone planning docs (#39).
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
-
v1.7.0
Stablereleased this
2026-07-22 17:15:15 +00:00 | 94 commits to main since this releaseAdded
- Expanded radar products — one shared set drives the dashboard modal and the public pages: NOAA Base/Composite Reflectivity, Echo Tops, Precip Type; IEM NEXRAD reflectivity mosaic; MRMS precipitation accumulation (1-hour / 24-hour / storm-total); RainViewer satellite (IR) + nowcast (best-effort). Single-select, lazily built.
- Public location pages now render a full interactive Leaflet radar map (base map + product switcher), replacing the flat radar image. The map centers on a coarsened (~11 km) area with no pinpoint marker — precise coordinates never reach the public page.
Notes
- Velocity (BV/SRV) and derived rotation/hail products (NROT, MESH, VIL) are not included: no free web-tile source exists, and premium data is desktop GRLevelX format — web rendering would need a dedicated radar pipeline. Tracked as future work.
All radar sources are free/public HTTPS. No migration. Bulk suite 779 passed.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
-
v1.6.2
Stablereleased this
2026-07-22 16:06:26 +00:00 | 96 commits to main since this releaseFixed
- Blank radar on public location pages (#123) — the public page embedded the authenticated
/api/locations/{id}/radarendpoint, so unauthenticated visitors were redirected to login and the radar rendered blank. Added apublic_enabled-gatedGET /api/locations/{id}/public/radarroute (disk-cached, no auth) and repointed the page at it.
No migration. Bulk suite 778 passed.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- Blank radar on public location pages (#123) — the public page embedded the authenticated
-
v1.6.1
Stablereleased this
2026-07-22 15:44:14 +00:00 | 98 commits to main since this releaseFollow-ups to v1.6.0.
Changed
- Lightning proximity alerts are now edge-triggered (#87) — fires once when lightning moves into a location's radius, stays silent while it persists, and re-arms only after the area is clear for
LIGHTNING_ALERT_CLEAR_MINUTES(default 10), instead of re-firing on a fixed 30-minute cooldown. Migration 0030 addsLocation.lightning_last_seen_at.LIGHTNING_ALERT_COOLDOWN_MINUTESis deprecated/unused.
Added
- Open/copy button for public location pages — a public-enabled location now shows a "Public page ↗" link and a "Copy link" button on the Locations page (the page was already served at
/api/locations/{id}/publicbut had no UI entry point).
Testing
Bulk suite 776 passed; migration 0030 verified through the full chain on a restored copy of the real prod DB.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- Lightning proximity alerts are now edge-triggered (#87) — fires once when lightning moves into a location's radius, stays silent while it persists, and re-arms only after the area is clear for
-
v1.6.0
Stablereleased this
2026-07-22 02:31:16 +00:00 | 102 commits to main since this releaseLightning support (#87), unblocked by a Weather Pulse (AllisonHouse) ENTLN placefile data source. Authenticated/personal by default; no breaking changes; a no-op until the feed is configured.
Added
- Lightning overlay on the dashboard radar map — a ⚡ toggle plots recent ENTLN clusters as age-colored markers, refreshing on pan and on an interval. Fed by a subscriber placefile URL (
LIGHTNING_PLACEFILE_URL, a secret); the toggle is disabled when no feed is configured, so the commercial feed is never fetched unsolicited.services/lightning.pyparses the placefile fail-soft + cached;GET /api/lightning/strikesis authenticated. (Verified live against the real feed — parsed all 55 clusters the feed contained.) - Lightning proximity alerts — set
lightning_alert_radius_mion a location and apoll_lightningjob notifies channels with the per-subscription "Lightning proximity alerts" toggle when recent clusters fall within that radius. "Lightning Nearby" is advisory-severity (respects quiet hours — a heads-up, not a life-safety warning), cooldown-limited, snooze-aware, and dispatched through the existing per-notifier path. Migration 0029.
Config
New optional
.env:LIGHTNING_PLACEFILE_URL(secret — enables lightning),LIGHTNING_ON_PUBLIC_PAGES(default false; reserved — public-page display not built yet),LIGHTNING_POLL_INTERVAL_MINUTES,LIGHTNING_ALERT_COOLDOWN_MINUTES,LIGHTNING_ALERT_MAX_AGE_MINUTES. Per-location radius + per-subscription toggle set in the UI.Notes
- ENTLN data is licensed to the subscriber, so lightning is authenticated/personal by default; showing it on the unauthenticated public pages stays behind
LIGHTNING_ON_PUBLIC_PAGES(off) — a deliberate, documented opt-in.
Testing
Bulk suite 775 passed; migration 0029 verified on a restored copy of the real dev DB. PRs: #119 (overlay), #120 (proximity), #121 (changelog).
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- Lightning overlay on the dashboard radar map — a ⚡ toggle plots recent ENTLN clusters as age-colored markers, refreshing on pan and on an interval. Fed by a subscriber placefile URL (
-
v1.5.0
Stablereleased this
2026-07-19 16:47:18 +00:00 | 108 commits to main since this releaseFeature-enhancement release building on the stabilised core (audit ideas I-02, I-05, I-06, I-13, I-14, I-15, I-18). No breaking changes; new runtime behaviors are opt-in or degrade to nothing when their upstream is unavailable.
Notifications
- ntfy channel (#72) — self-hosted push with full web-form config, Transient/Permanent delivery classification, and severity→priority mapping. (Web Push remains a separate future effort.)
- Outbreak digest mode (#76, opt-in) — per-subscription
digest_threshold; over-threshold advisory/watch alerts batch into a periodic digest. Warning-class alerts are never batched — they always send immediately. Off by default. - Lead-time / time-to-impact (#84) — "arrives in ~40 min" on dashboard cards and in all notifications when an alert's
onsetis in the future.
Situational awareness
- Precipitation nowcast (#88) — a per-location "rain starting in ~X min" dashboard indicator sampled from RainViewer nowcast frames (lazy, cached, fail-soft). A heads-up, not a forecast — NWS alerts remain authoritative.
- Per-location alert feeds (#75) —
GET /p/{location_id}.json | .rss | .icsfor homelab automations (Home Assistant, etc.). - Alert activity / statistics view (#83) —
GET /stats("Activity"): counts by location, event type, and month. A down-payment on the v2.0.0 Historical Explorer. - Radar-at-alert-time snapshot (#85, opt-in) —
ALERT_RADAR_SNAPSHOT_ENABLEDcaptures the radar image when an alert fires; shown on the public alert page. Front-loads history for the Explorer.
Config
New optional
.env:PRECIP_NOWCAST_ENABLED,ALERT_RADAR_SNAPSHOT_ENABLED,DIGEST_FLUSH_MINUTES,DIGEST_WINDOW_MINUTES. ntfy config + per-subscriptiondigest_thresholdare set in the UI.Notes
- #71 (storm polygon matching) was found already implemented — the alert path already matches the warned polygon and falls back to zones — closed without changes.
- #87 (lightning overlay / proximity alert) is deferred to the backlog: no free lightning tile source exists (NLDN is commercial; RainViewer/IEM don't offer one), so it awaits a data-source decision.
Testing
Migrations 0025–0028 verified against restored copies of the real dev DB. Bulk suite 746 passed, Postgres tier 4. PRs #112 (ntfy + feeds), #113 (lead-time), #114 (radar snapshot + stats), #115 (nowcast), #116 (digest), #117 (changelog).
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
-
v1.4.0
Stablereleased this
2026-07-19 04:36:59 +00:00 | 122 commits to main since this releaseTech-debt and structure work from the 2026-07-17 audit (F-18, F-19, F-24, F-30). No breaking changes; one user-visible feature addition.
Added
- SPC fire-weather Day 2 (#63) — fire-weather outlook coverage now includes Day 2 (categorical ELEV/CRIT/EXTR), matching the Day 1-3 convective coverage. Previously only Day-1 fire geometry was fetched while the Day-2 text was fetched every poll and discarded.
Changed — structure
- Dashboard assembly extracted from
main.py(#58) — the/route is now auth + abuild_dashboard_context()service call + render (~10 lines, from ~318). The 13-request live SPC fan-out on every page load is gone; the dashboard reads SPC outlooks from the recordspoll_spc_dashboardalready maintains, so a load makes zero direct SPC upstream requests. - Consolidated the two drifted SPC match-context builders into one shared implementation (#58).
Fixed
- ORM ↔ DB index metadata drift (#57) — models now reproduce the live schema exactly, so
alembic revision --autogenerateyields an empty diff. Also restored the missingalembic/script.py.mako(absent since init —alembic revisionfailed on a fresh clone without it). - Dashboard-dedup NULL gap (#57) — a partial unique index (
nws_alert_id, location_id WHERE channel_id IS NULL) now enforces uniqueness that Postgres NULL semantics left unprotected. The migration de-duplicates existing rows first (this had accumulated to 18 groups / up to 147 copies on the dev DB), and the racingpoll_spc/poll_spc_dashboarddashboard inserts are now savepoint-guarded (#109). - UI consistency pass (#69) —
✕→✕encoding fix,confirm()parity, double-submit guards, inline error surfacing (replacingalert()),aria-labels on icon-only buttons, a defined--color-accent, and removal of a dead unreachableafterSwapJSON block.
Testing
ruff clean; bulk suite 670 passed; Postgres tier 4 passed. Migration verified against a restored copy of the real dev DB (de-dup to zero, index created). PRs: #107 (Phase 1), #108 (Phase 2), #109 (deploy hotfix), #110 (Phase 3), #111 (changelog).
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
-
v1.3.0
Stablereleased this
2026-07-19 01:16:13 +00:00 | 134 commits to main since this releaseAI summarization expansion milestone (all 7 issues: #16–#21, #61). No breaking changes; all runtime-affecting additions are off by default except two intended always-on summarizer fixes.
AI context enrichment
- Feed staleness in context (#61) — a distinct
stalestatus (with age) when a feed has no failures but its last success is past its category threshold, instead of reporting a silently-stalled feed as fresh. Reaches local + cloud prompts. - SPS/SVS excerpts (#17, opt-in) — bounded, verbatim-labeled statement snippets via
AI_CONTEXT_INCLUDE_SEVERE_STATEMENTS(local providers only). - Radar/precip freshness (#18) — a factual "radar imagery last updated N minutes ago" field (DB-only, no imagery).
- Local-time normalization in the AI context (#20) — no raw
Z/UTC strings reach the model.
Summarizer behavior (opt-in)
- Quiet-hours AI mode (#19) —
QUIET_HOURS_AI_MODE(defaultreplace): non-critical products in quiet hours have the verbose raw alert replaced by the concise AI summary, orsupplementto send both. Warning-class alerts always send in full. - Guardrailed timing/impact follow-ups (#21) —
AI_TIMING_IMPACT_FOLLOWUPS_ENABLED(defaultfalse): a bounded, source-grounded onset/duration/impact clause that preserves uncertainty. Ships dark.
Summarizer hygiene (F-33, always-on)
- Prompt delimiter neutralization (feed content can't break out of the prompt blocks; stored DB text untouched).
- Output-URL validator (rejects a summary URL absent from the source text).
- Token-budget fix (
_output_tokens_for_charswas a no-op returning 4096; now scales with the character budget, floor 4096 / cap 8192).
Config
New optional
.envsettings:AI_CONTEXT_INCLUDE_SEVERE_STATEMENTS,QUIET_HOURS_AI_MODE,AI_TIMING_IMPACT_FOLLOWUPS_ENABLED. See.env.example.Notes
- The real-world Qwen quality-tracking part of #16 is an ongoing operational activity, not a code deliverable; the deterministic-validator/hygiene work shipped here.
Full test suite green (658 passed). PRs: #104 (Phase A context enrichment), #105 (Phase B summarizer), #106 (changelog).
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- Feed staleness in context (#61) — a distinct