Listening for events…

Atmospheric Entry Eventdex — Scope + Frozen Settings

Status: rule FROZEN 2026-06-14 (Mike) · Owner: Mike + Claude (engine room) Parent: docs/event-spine-framework.md (the Eventdex framework; this is kind #6 after tc, gst, eq, tor, and vol)

This document scopes the atmospheric-entry kind of the event storehouse: anything that enters Earth's atmosphere and burns up, natural and artificial, recorded as far back as the catalogs reach. It is the first multi-source kind, the first kind to mix natural and human-made events, and the deepest-history kind yet (an observed meteorite fall is dated to 860 AD).

Two properties make it different from every prior kind:

  1. Multiple authoritative spines, not one. Four independent catalogs feed one slot space (GMN fireballs, CelesTrak SATCAT reentries, CNEOS bolides, observed meteorite falls). Each carries its own native fields and its own inclusion rule; slot IDs are source-prefixed so they never collide.
  2. It is catalog-first, sweep-light. Unlike volcano/tornado, the sensor sweep almost never bites here (see The sweep). The value is the spine itself: a complete browsable record of objects that fell from the sky, each with its origin (orbit + parent shower for natural, launch + last tracked orbit for artificial). Most slots are index-only by construction.

All counts below were verified 2026-06-14 (GMN bulk files, CelesTrak SATCAT, PG16).

The theme

Everything that falls into the atmosphere and ablates. Natural: meteors/fireballs (the streak), the rare bolide (CNEOS), and the survivors that reach the ground (meteorite falls). Artificial: satellites, rocket bodies, and debris that decay out of orbit and burn on reentry. One kind, one timeline, from a 9th-century recovered stone to last week's Starlink deorbit.

The spine (four sources)

Source Population Floor (FROZEN) Slots History Status
GMN fireballs camera-triangulated meteors Peak AbsMag <= -4 (fireball-class) ~8,400 2018+ LIVE (gmn_meteors)
CelesTrak SATCAT satellite/rocket-body/debris reentries OBJECT_TYPE in (R/B, PAY) 11,857 1957+ LIVE (celestrak_satcat)
CNEOS bolides US-Gov-sensor bright bolides full curated catalog 1,063 1988+ LIVE (cneos_fireballs)
Meteorite falls observed ("Fell") recovered meteorites all observed falls 1,107 860 AD+ LIVE (meteorite_falls)

~22,000 slots total, comparable to the earthquake kind (13,839) and well under tornado (73,618). Some GMN x CNEOS overlap (a bright bolide both networks saw) is deduplicated at backfill, CNEOS canonical for the bright tail it covers better.

Slot ID — source-prefixed (FROZEN)

Each catalog has its own stable identifier; the kind prefixes them so the slot space is globally unique:

  • gmn:<unique_trajectory_identifier> (e.g. gmn:20260612184153_sW35G) — verified unique, stable YYYYMMDDHHMMSS_xxxx format, zero duplication in the live copy.
  • sat:<norad_cat_id> (e.g. sat:25544) — the NORAD catalog number, globally unique and stable.
  • cneos:<peak_brightness_datetime> — CNEOS assigns no persistent ID; keyed on the peak- brightness timestamp (its de-facto primary key), location as tiebreak.
  • met:<meteoritical_name> (e.g. met:Allende) — the Meteoritical Society name, unique per fall.

The live edge

  • Reentries are the strongest live edge: CelesTrak SATCAT logs new decays almost daily now (the 2020s already hold 10,328 of all 35,229 catalogued decays, Starlink deorbits dominating and accelerating). The live sweep runs on SATCAT newcomers carrying a fresh DECAY_DATE.
  • GMN fireballs stream live (already ingested as gmn_meteors).
  • CNEOS updates within weeks of a bright bolide; meteorite falls are rare (a few/year) and slow to confirm. Both poll on a relaxed cadence.

The floors — decided 2026-06-14 (Mike, FROZEN)

Both floors track the same principle: include what visibly burns up, exclude what doesn't.

  • Natural (GMN): Peak AbsMag <= -4 — the textbook fireball (brighter than Venus). From a clean 32,209-meteor 2025 sample: AbsMag <= -4 is 0.27% of all GMN trajectories, ~8,400 of the ~3.1M-meteor full catalog. GMN saturates around AbsMag -6.5 (the very brightest bolides are CNEOS's domain), so -4 is the practical sweet spot; stricter than -5 leaves almost nothing.
  • Artificial (SATCAT): OBJECT_TYPE in (R/B, PAY) — rocket bodies + payloads, the objects large enough to streak. 11,857 of 35,229 catalogued decays. Drops the ~23,264 sub-meter DEB fragments that ablate invisibly (and would otherwise let 2020s Starlink debris swamp the kind).
  • CNEOS: full catalog — every CNEOS entry is already a vetted bright bolide; no further floor.
  • Meteorite falls: all observed "Fell" — every recovered, dated fall is significant; the Meteoritical Society's own "Fell" vs "Found" flag is the floor.

The sweep (per-kind settings, FROZEN)

  • Geometry: fixed point. Per source: GMN end point (latend/lonend, the terminal/lowest point of the visible track); CNEOS event lat/lon; meteorite recovery lat/lon. Reentries: see the measured-reality rule below, most carry only a decay date + an orbit (not a ground point) and are therefore index-only.
  • Radius: 100 km flat (matches volcano).
  • Window: [event - 2 h, event + 2 h]. A fireball/reentry is a sub-second event with no precursor (the opposite of volcano's 21-day onset window), so the window is just wide enough to catch any lightning/weather context around the instant.
  • Sweep layers (same stack as volcano/tornado): blitzortung_lightning (the only layer at all likely to fire, ambient storms under the track), goes18_glm_flashes, goes19_glm_flashes, usgs_earthquake, nws_alerts, igra_soundings (profile). Included for the rare bright tail and future-proofing, not as expected-hit layers.
  • Sweep-eligible = the slot has a ground point AND a timestamp precise to at least the hour AND falls in a sensor era. Everything else is index-only (a full slot with an empty sensor section, never a lesser slot).

Honest expectation (FROZEN, do not re-litigate at Brick D): the sweep is almost entirely index-only. A -4 GMN fireball is gram-scale, millions of times below GLM's kiloton bolide threshold and far below any seismic/infrasound detection, so GLM/USGS effectively never fire at this floor; those events are Chelyabinsk-class (-28 mag), not -4. The sweep earns occasional hits only for 2026+ natural events over instrumented regions (Blitzortung context, mostly). All reentries, all meteorite falls, all CNEOS, and everything pre-2026 are spine-only records. This is expected and fine, the spine is the product.

Measured-reality rule — reentries (FROZEN)

The fact and date an object decayed is measured reality (radar tracking stopped). The precise reentry time and impact point is usually a Tracking-and-Impact-Prediction model output. Per the platform bright line ([[feedback_measured_reality_only]]):

  • IN: observed DECAY_DATE, last tracked orbit (apogee/perigee/inclination), object identity and launch provenance.
  • OUT: TIP-predicted reentry time, predicted impact latitude/longitude, any decay forecast.

Consequence: a reentry whose only timestamp is a date (no observed time) is index-only (no fictitious anchor), exactly like volcano year-only precision.

Dossier shape

Heterogeneous per source, with a common header. Common fields: event_id (source-prefixed), when (+ precision flag), kind_subtype (natural-meteor / natural-bolide / meteorite-fall / reentry), where (point if available, else null), origin block. Source-native extras:

  • GMN/CNEOS: velocity, peak abs magnitude, mass, full orbital elements, parent shower.
  • Meteorite falls: classification (type), recovered mass, fall circumstances.
  • Reentries: object name, international designator, owner, launch date/site, last tracked orbit.

Same per-sensor-aggregate + hits-parquet pattern as eq/tor/vol for the rare swept slots. Kind directory: data/event_storehouse/entry/.

Data-source notes / gotchas (recorded for the reload bricks)

  • GMN — use the static bulk files, NOT the Datasette API. The Datasette meteor table endpoint hangs (TLS connects, request sent, zero bytes returned, server-side) on the ~3.1M-row table; only the static root is fast. Reload from the yearly bulk files at https://globalmeteornetwork.org/data/traj_summary_data/traj_summary_yearly_YYYY.txt (2018-2026, ~2.9 GB total), ;-delimited fixed-width with a header block. Peak AbsMag is field index -10 in the ;-split (equivalently positive index 76 of 86 columns). Capture it to the value column at unit magnitude, matching the live gmn_meteors rows (the live fetcher already lands AbsMag in value correctly, 100% populated; an earlier note here wrongly called it a null field-name miss, which was a mis-check of extra_json only). Stream/filter each year, keep only AbsMag <= -4. Keyset/stream by unique_id.
  • SATCAThttps://celestrak.org/pub/satcat.csv (~6.6 MB, ~69k objects, no auth). Filter DECAY_DATE non-empty; columns OBJECT_TYPE, RCS (numeric m^2), LAUNCH_DATE, INTL_DES/OBJECT_ID, owner, orbit params. Our live celestrak source pulls only gp.php orbital elements, NOT SATCAT, so this is a net-new fetcher.
  • CNEOS — JPL fireball API https://ssd-api.jpl.nasa.gov/fireball.api (no auth), used in prior workspaces (cneos-fireball-2026-surge); keyed on peak-brightness datetime.
  • Meteorite falls — Meteoritical Society / NASA "Meteorite Landings" dataset; filter fall == "Fell"; dates back to 860 AD, many year-only (index-only by the precision rule).

Build bricks

  • Brick A — freeze. DONE 2026-06-14: theme, four spine sources, both floors (GMN AbsMag <= -4; SATCAT R/B+PAY), source-prefixed slot IDs, sweep settings, and the measured-reality reentry rule frozen above.
  • Brick B1 — GMN spine reload. DONE 2026-06-14: scripts/reload_gmn_fireball_spine.py streamed all yearly bulk files 2018-2026 (~2.9 GB) and filtered to AbsMag <= -4, replacing the capped 8,000-row live sample with **11,481 fireballs** (all distinct IDs, 2019-05-30 -> 2026-06-13; by year 16/296/989/1907/1634/2548/3319/772). End point = ground anchor. Geography now properly global (NZ bias gone). Shower associations sanity-check out (top = IAU 7 Perseids, 2,075). Data-quality catch (audit): GMN's peak photometry is unreliable in the bright tail (raw min AbsMag -45.57, physically impossible; the extreme tail clusters on a few miscalibrated stations US0009 / BE000B / BE000C). Per Mike, the re-run captures GMN's trajectory-quality fields (convergence_angle_deg, fit_error_arcsec) and flags photometry_reliable = AbsMag >= -12 (brighter than the full moon = saturation/miscalibration). 215 of 11,481 (1.9%) flagged unreliable; events kept (real multi-station triangulated meteors) with raw value preserved. Finding: Qc does NOT separate the bad-brightness tail (mean Qc 48.8 deg unreliable vs 51.7 deg reliable) -- the defect is photometric (station calibration), independent of triangulation geometry, so a Qc gate would not have caught it; the physical -12 bound is the right flag. Brightest reliable fireball = AbsMag -12.0 (Belgium 2022-12-13, Qc 84 deg). Live fetcher patched to the -4 floor + end-point anchor (normalize_gmn_meteors); live capture of the quality fields + flag deferred to Brick C (the Datasette query API is hanging, live edge stalled since 06-12).
  • Brick B2 — reentry spine. DONE 2026-06-14: scripts/reload_reentry_spine.py loaded the full SATCAT reentry catalog from satcat.csv (DECAY_DATE non-empty AND OBJECT_TYPE in (R/B, PAY)): 11,857 reentries (4,447 R/B + 7,410 PAY), 1957-12-01 (Sputnik 1's R/B) -> 2026-06-12, decade curve 15/1053/1560/1759/1117/832/1049/4472 (the 2020s Starlink-deorbit surge, as the scope predicted). Counts match the frozen floor exactly (35,229 total decays; 23,264 DEB + 108 UNK dropped). New celestrak_satcat source + fetcher + normalizer (metric satellite_reentry, value = RCS m^2 sparse ~36%, unit m2); registered in seed/scheduler/NORMALIZERS, every 6h. Measured-reality: all DECAY_DATE are date-only (verified 100% YYYY-MM-DD, zero with a time), so every reentry is index-only — timestamp anchored 00:00 UTC + when_precision="day", location NULL (TIP impact point is model output, OUT); last tracked orbit (period/inclination/apogee/perigee, 97% populated) kept in extra. Scope catch (flag, don't drop, mirroring B1's photometry flag): 114 of the 11,857 R/B+PAY decays have a non-Earth orbit center (Luna 2 = first Moon impact, the Rangers, Venus/Mars impactors) — real fell-out-of-orbit events but NOT Earth atmospheric entries. The frozen floor is OBJECT_TYPE only, so they are kept and flagged earth_reentry = (orbit_center == "EA"); 11,743 true Earth reentries. Live edge safe from day one: each reentry is a one-time date-only event the 48h loader dedup can never match, so the fetcher emits only NORAD ids not already stored (fetch-level newcomer skip); the sweep-trigger on new decays is Brick C. UTC-session note: psql ::date shows the 00:00-UTC anchors a day early in a local-TZ session (stored values verified correct under SET TIME ZONE 'UTC').
  • Brick B3 — CNEOS bolide spine. DONE 2026-06-14: scripts/reload_cneos_spine.py loaded the full JPL fireball-API catalog (req-loc=false = ALL events incl. un-located), 1,063 bolides, 1988-04-15 -> 2026-05-30, top event Chelyabinsk 2013-02-15 03:20:26, 441 kt, 54.8N 61.1E (catalog sanity ✓). New dedicated cneos_fireballs source + fetcher + normalizer (metric cneos_bolide, value = total impact energy kt 100% populated, unit kt), seed/scheduler (daily)/NORMALIZERS registered. Verify-before-claiming catch: CNEOS bolides were ALREADY partly ingested via nasa_neo (metric neo_fireball), but only a thin recent window-duplicated slice (359 distinct events, 1998+ only, 3,016 dup rows); the dedicated spine is the clean full catalog and is kept SEPARATE (different source + metric cneos_bolide) so it never collides with the nasa_neo close-approach feed (274k rows — do NOT wholesale-delete that source). The redundant nasa_neo fireball emission is a later-cleanup thread, not touched here. Timestamp- precise (JPL date carries a real time, unlike SATCAT): 877 located events are sweep-eligible, 186 un-located are index-only (NULL point, no fabrication). Signed lat/lon from N/S/E/W dir. Slot key = peak-brightness datetime (cneos:<date>). Live edge newcomer-skip on peak datetime. GMN x CNEOS dedup deferred to Brick D backfill (CNEOS canonical for the bright tail it covers).
  • Brick B4 — meteorite-fall spine. DONE 2026-06-14: scripts/reload_meteorite_spine.py loaded NASA Meteorite Landings filtered to fall=="Fell": 1,107 observed falls, 860 -> 2013 AD, oldest = Nogata (860 AD, L6 chondrite, 472 g), heaviest = Sikhote-Alin (23 t, 1947) — both textbook-correct. New meteorite_falls source + fetcher + normalizer (metric meteorite_fall, value = recovered mass g, unit g), seed/scheduler (weekly)/NORMALIZERS. Year-only precision -> every fall is index-only (Jan 1 00:00 UTC anchor + when_precision= "year"); recovery point stored for the dossier/map (1,096 located, (0,0) null-island sentinel -> NULL) but never swept. Slot key = Meteoritical Society name (met:<name>). Source-freeze honesty: the NASA legacy CSV is a FROZEN 2013 snapshot, so the live edge is effectively dormant after the spine load (newcomer-skip on name keeps it idempotent/uniform); truly-live post-2013 falls would need the Meteoritical Bulletin Database (a later thread). 860 AD stores cleanly (no year-0/BCE trap; positive year).
  • Brick B complete: all four spines loaded — GMN 11,481 + SATCAT 11,857 + CNEOS 1,063 + meteorite 1,107 = 25,508 entry slots (vs the ~22,000 estimate; GMN + SATCAT both came in fuller than the frozen guess). Next: Brick C (kind registration + live sweep).
  • Brick C — kind registration + live sweep. DONE 2026-06-14: src/terrapulse/monitor/entry_sweep.py registers the first multi-source kind — four spines into one source-prefixed slot space via a SOURCES table + generic spine query + uniform event dicts. ENTRY_CONFIG KindConfig (100 km, ±2 h, layers blitzortung/goes18+19 GLM/usgs_earthquake/nws_alerts/igra). Scheduler job entry_sweep every 30 min; per-source newcomer probe (newest-N-per-source missing a dossier, lag-proof). Sweep-eligibility (frozen rule operationalized): ground point AND ≥hour precision. No hard atmospheric-era cutoff — every located+precise entry is 1988+ (already in the seismic/sounding era); a pre-2017 bolide sweeps an empty GLM/Blitzortung but still reaches usgs_earthquake (Chelyabinsk 2013 registered seismically; the frozen scope names exactly that Chelyabinsk-class tail as where hits are earned — a hard cutoff would have hidden it). So only GMN (located, sub-second) + located CNEOS are swept; all SATCAT (date), meteorites (year), and un-located CNEOS are index-only full slots. Live tick verified end-to-end (2,000 newest dossiers, 166 s, 984 swept / 1,016 index-only): 28 real sensor hits, headline a CNEOS 1.1 kt bolide (2026-05-30) co-located with 9 GOES-19 GLM flashes at 0 km — a genuine bright-tail GLM bolide co-detection, exactly the predicted rare hit (±2 h window is wide, so single-flash GMN matches may be ambient; raw hits preserved per dossier). Also: GMN live normalizer now lands photometry_reliable (the B1 −12 flag) on the live path; Qc/fit-err live capture still deferred — the GMN Datasette query API has been hanging since 06-12 (even a 1-row probe returns empty), so the live column names can't be verified yet. 6 unit tests added (198 total green).
  • Brick D — dossier backfill. DONE 2026-06-14: scripts/backfill_entry_dossiers.py built one slot per cataloged entry via entry_sweep.backfill_and_store, year-windowed (one deep [800, 1950) pre-satellite batch then yearly 1950 -> present). 25,508 dossiers in 878s, reconciling exactly with the spine: reentry 11,857 + natural-meteor 11,481 + natural-bolide 1,063
    • meteorite-fall 1,107. Swept 12,358 (all GMN, located + sub-second, + 877 located CNEOS) / index-only 13,150 (11,857 date-only SATCAT + 186 un-located CNEOS + 1,107 year-only meteorites). 56 dossiers carry real sensor hits; top card is the CNEOS 1.1 kt bolide of 2026-05-30 with 14 hits (the GLM bright-tail co-detection). GMN x CNEOS dedup: 0 collapses — verified at backfill (and pre-calibrated: across the 2019+ overlap the nearest-in-time GMN to any CNEOS bolide is >1,600 km away; GMN's gram-scale -4 floor is millions x below CNEOS's kiloton bolides and GMN camera nets are regional, so no physical event lands in both catalogs). The dedup pass stays in (±10 min / 500 km, CNEOS canonical) so the storehouse self-heals if a future bright GMN event ever coincides. Storehouse index now holds all six kinds; total census 138,755. The atmospheric-entry kind is COMPLETE (A+B+C+D).
  • First report: deferred. Engine room, not paper mode.
Live Feed