salvage(swarm): hourly scanner, event journal, space weather, scan severity - #111
Conversation
…verity Recovers the four capabilities flagged by docs/BRANCH_CLEANUP.md before the swarm branches are deleted, adapted to the post-#108/#109 API on main: - hourly_scanner.py (from feat/neo-hourly-scanner): autonomous hourly scan of CNEOS fireballs, JPL CAD close approaches, and shower calendar. Adapted to close_approach_client (field renames), rank-preserving THREAT_LEVEL_MAP (JPL WATCH/ALERT -> scanner CLOSE/ALERT), timezone-aware UTC. - event_journal.py (from nightwatch/neo-tracking-and-event-journal): SQLite sky-event journal with Hopi-ring classification; timezone-aware UTC. - space_weather.py (from feat/neo-space-weather-hourly-scan): NOAA SWPC Kp, solar wind, alerts; UTC-aware parsing + warning when the feed is partial so outages cannot masquerade as quiet conditions. - scan_severity.py (from feat/hourly-event-scanner): severity classification with tests. - fireball_client.py: CNEOS lat-dir/lon-dir sign fix (coords are unsigned in the API; S/W must negate) from feat/hourly-event-scanner. - lexicon_prayers.py: generate_prayer_of_approach + status prayer NEO count (from the event-journal branch). - __init__.py: eager event_journal/lexicon exports; lazy loaders for hourly scanner, space weather, scan severity. 142 new unit tests, all passing. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 7 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 58c54a0. Configure here.
| self._last_scan = datetime.fromisoformat(state["last_scan"]) | ||
| self._known_event_ids = set(state.get("known_event_ids", [])) | ||
| except (json.JSONDecodeError, KeyError) as e: | ||
| logger.warning(f"Could not load scanner state: {e}") |
There was a problem hiding this comment.
Scanner state never reloads
High Severity
The HourlyEventScanner's _load_state method is never called, so _known_event_ids and _scan_count reset on restart. This causes previously seen fireballs and NEO approaches to be re-alerted.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 58c54a0. Configure here.
| }, | ||
| threat_level="INFO", | ||
| ) | ||
| shower_events.append(shower_event) |
There was a problem hiding this comment.
Shower events repeat every scan
Medium Severity
Meteor shower events (active and upcoming) are not deduplicated against _known_event_ids during each scan. This inflates the events_found count and causes repeated shower entries in the scan history and prayer output.
Reviewed by Cursor Bugbot for commit 58c54a0. Configure here.
| SELECT * FROM sky_events | ||
| WHERE timestamp >= ? AND timestamp < ? | ||
| ORDER BY timestamp | ||
| """, (start.isoformat(), end.isoformat())).fetchall() |
There was a problem hiding this comment.
Journal timestamps compare inconsistently
Medium Severity
EventJournal stores each event’s timestamp.isoformat() as-is while create_hourly_entry, get_recent_events, and default create_daily_summary query with timezone-aware UTC bounds (+00:00). Naive timestamps from CNEOS, CAD, or tests compare as strings against aware bounds and can fall outside ranges—hourly and daily rollups may omit valid events.
Additional Locations (2)
Reviewed by Cursor Bugbot for commit 58c54a0. Configure here.
| fireball: Fireball, | ||
| home_lat: float = 38.9, | ||
| home_lon: float = -117.4, | ||
| bright_threshold: float = -8.0, |
There was a problem hiding this comment.
Default home coords disagree
Medium Severity
New scan_severity helpers default home to 38.9, -117.4, while EventJournal and HourlyEventScanner use Nevada 39.5, -117.0. Callers using defaults get different distance zones and fireball proximity severity than the journal and scanner for the same event.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 58c54a0. Configure here.
| lines = [] | ||
| hour_str = self.hour_start.strftime("%Y-%m-%d %H:00") | ||
| lines.append(f"nightwatch-journal. varek-hour: {hour_str}") | ||
| lines.append(f"home-wit: {self.site_name} ({self.site_lat:.1f}N {abs(self.site_lon):.1f}W)") |
There was a problem hiding this comment.
Prayer output assumes west longitude
Low Severity
HourlyEntry.to_prayer and daily summary text format longitude as {abs(site_lon):.1f}W regardless of sign. A site with eastern longitude is mislabeled west in journal prayers.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 58c54a0. Configure here.
| event.ring = classify_ring( | ||
| self.home_lat, self.home_lon, | ||
| event.latitude, event.longitude | ||
| ) |
There was a problem hiding this comment.
Ring never auto-classified from coords
High Severity
record_event only recomputes ring when event.ring is None, but SkyEvent requires a non-optional EventRing, so typical events keep a placeholder like GLOBAL even when coordinates imply ZENITH or nearer rings. Hourly prayers and ring summaries can mislabel proximity.
Reviewed by Cursor Bugbot for commit 58c54a0. Configure here.
| row = conn.execute( | ||
| "SELECT prayer FROM hourly_entries WHERE hour_start = ?", | ||
| (hour_start.isoformat(),) | ||
| ).fetchone() |
There was a problem hiding this comment.
Hourly prayer query ignores site
Low Severity
get_hourly_prayer selects by hour_start only, while hourly_entries has a unique key on (hour_start, site_name). Multiple sites in one database can return the wrong hour’s prayer for the current journal instance.
Reviewed by Cursor Bugbot for commit 58c54a0. Configure here.
…ry tests (#114) Recovered from the legacy master branch before its deletion: a purely additive spiral search-route generator (Waypoint, SearchRoute, generate_spiral_route, destination_point, initial_bearing) for hopi_circles, plus the comprehensive test suites for hopi_circles and trajectory (the only content of master's 8 unique commits not already superseded by #108/#109/#111). All tests pass against current main. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>


Summary
Recovers the four unmerged capabilities identified by
docs/BRANCH_CLEANUP.mdbefore the 86-branch purge deletes their only copies, adapted to current main (post-#108/#109 NEO client API):feat/neo-hourly-scannerhourly_scanner.pynightwatch/neo-tracking-and-event-journalevent_journal.pyfeat/neo-space-weather-hourly-scanspace_weather.pyfeat/hourly-event-scannerscan_severity.py,fireball_client.pyKey adaptations
neo_clientto main'sclose_approach_client(field renames) with a rank-preserving threat map: JPLWATCH/ALERT(<2 LD, PHA, <1 LD) → scannerCLOSE/ALERT(the alerting tiers).datetime.utcnow()→ timezone-aware UTC (same class of bug fix(neo_feed): missing-distance false ALERT + UTC feed window #109 fixed inneo_feed_client).fireball_client._parse_fireballs: CNEOS returns unsigned lat/lon +lat-dir/lon-dir— southern/western events were previously mislocated; now signed correctly.space_weather._parse_solar_windlogs a warning when the feed is partial so an outage can't silently report a quiet sun.generate_prayer_of_approach+ NEO count in status prayer (additive lexicon salvage).Test plan
Part 1/Step 1 of the v0.1.1 main-only consolidation.
🤖 Generated with Claude Code
Note
Medium Risk
New background scanning, external NASA/NOAA dependencies, and SQLite persistence expand operational surface; the CNEOS coordinate fix materially affects alert geography but is a targeted parser change.
Overview
Salvages four NIGHTWATCH capabilities into
meteor_tracking: an always-on hourly scanner (CNEOS fireballs + JPL close approaches + shower calendar), a SQLite event journal with Hopi-ring classification and hourly/daily Lexicon summaries, a NOAA SWPC space weather client, and scan severity helpers for prioritizing alerts.The package exports journal types and lazy loaders for the scanner, space weather, and severity. Lexicon adds
generate_prayer_of_approachand NEO approach counts on status prayers. The scanner mapsclose_approach_client.ThreatLevelto scanner alert tiers (CLOSE/ALERTdrivehas_alerts) and uses timezone-aware UTC in scan loops.fireball_clientnow applies CNEOSlat-dir/lon-dirso southern/western events get correct signed coordinates (fixes mislocated fireballs).space_weatherwarns when solar-wind feeds are partial so quiet defaults cannot mask an outage.Large unit test coverage is added for journal, scanner, severity, and space weather (~140 tests).
Reviewed by Cursor Bugbot for commit 58c54a0. Bugbot is set up for automated code reviews on this repo. Configure here.