Listening for events…

Scope freeze — neo CelestialObjectDex kind

Frozen 2026-06-26. The pilot kind of the CelestialObjectDex family (docs/celestialdex-framework.md). The slot is one near-Earth object (an asteroid), carrying its identity, intrinsic properties, and an array of its close approaches to Earth.

The slot

  • One slot = one asteroid (slot ID = the CNEOS designation, e.g. 99942 for Apophis, 2026LX). Its many close approaches are an array inside the slot, not separate event slots. Apophis is one slot holding both its 2029 pass (38,011 km, 0.099 lunar distances) and its 2051 pass.
  • Roster: 18,749 objects (6,147 with more than one approach), from 30,362 close approaches.
  • No ground point: an approach happens in space near Earth, so geographic lat/lon are NULL; the "position" is the miss-distance.

Source and the data-gap fix

cneos_cad (new spine source, scripts/reload_neo_spine.py) — NASA/JPL CNEOS Close Approach Data API (ssd-api.jpl.nasa.gov/cad.api), keyless. Scope: Earth approaches within 0.05 au (the standard close-approach threshold, ~7.5M km), 2000-01-01 through 2100 — modern well-observed era on the past side, future kept (see Measured reality). 20,318 past + 10,044 future approaches.

The existing live sources nasa_neo / jpl_sbdb captured close approaches without the approach DATE (fetch-time stamps only), so they cannot date events; this dedicated spine fills that gap with the real CAD records, per feedback_no_spiking_global (fill gaps with real measurement, never spike).

Slot contents

  • Identity: designation, name, orbit id.
  • Intrinsic properties: absolute magnitude H; estimated diameter (derived from H assuming albedo 0.14, flagged as an estimate, not a measurement).
  • Approach array (time-ordered), each with: UTC, miss-distance (km, lunar distances, au), the uncertainty range dist_min_au/dist_max_au, relative and infinity velocities, the CAD time-uncertainty, and a past/future flag.
  • Object summary: approach count (past/future split), closest approach (distance + date), first/last approach span.
  • Provisional flag: an object with no measured H (uncharacterized) is flagged.

Measured reality (the celestial-mechanics refinement)

A close approach is admissible under the bright line's celestial-mechanics refinement (feedback_measured_reality_only, Mike 2026-06-26): it is the deterministic consequence of real telescope/radar observations (the orbital mechanics that lands spacecraft), not a chaotic weather/climate forecast. So:

  • IN: computed close approaches, past AND future, of telescope-discovered objects. Future passes are forward propagation of a measured orbit, the same deterministic mechanics as backward, and are the impact-relevant ones.
  • Caveat is precision, not category: short observation arcs and deep extrapolation carry real uncertainty. The slot preserves the dist_min/dist_max range and the time uncertainty rather than hiding them. The modern-era (2000+) past-side floor avoids pre-discovery retrodictions where uncertainty is largest.

Storage

  • Source cneos_cad (registry, active=False; reloaded by the spine module).
  • Slots in data/celestial_storehouse/neo/, the CelestialObjectDex storehouse sibling, so the index rebuild scans only the ~19k object files.

Live edge (auto-update)

Self-updating via the CelestialObjectDex live-edge contract (docs/celestialdex-framework.md): neo_celestialdex.refresh_and_store() re-pulls the CNEOS CAD catalog into the cneos_cad spine (TTL-guarded, default 6 days) and rebuilds every asteroid slot, so newly discovered NEOs and refined approaches flow in. The scheduler runs it weekly (Mon 08:00 UTC, neo_refresh job); the import path is terrapulse.monitor.neo_spine.reload() for the spine and neo_celestialdex.refresh_and_store() for the combined step. New scheduler jobs activate on the next terrapulse service restart. The manual force-reload remains python scripts/reload_neo_spine.py.

Gotchas (reuse-critical)

  • Spine ≠ slot granularity. The spine has one row per approach; the sweep groups by designation into one slot per object. Never count spine rows as objects.
  • DuckDB bulk insert, not executemany. 30k row-by-row executemany inserts hang for minutes (columnar append anti-pattern); the reload uses a single INSERT ... SELECT FROM df (a DataFrame replacement scan). ~11s end to end.
  • cd parses as %Y-%b-%d %H:%M, UTC (e.g. 2029-Apr-13 21:46).
  • extra_json is TEXT — cast ::jsonb for SQL on designation/fields.
  • Estimated diameter assumes albedo 0.14 — a derived estimate (Apophis reads 540 m vs ~370 m actual because its albedo is higher); H is the measured datum.

Frozen vs deferred-v2

  • Frozen (this brick): 18,749-object roster as CelestialObjectDex slots, each with its close-approach array + intrinsic properties; own storehouse + index.
  • Deferred-v2: comet / transient / satellite members of the family; full orbital elements per object from SBDB; named-object enrichment (Apophis, Bennu); a live edge folding newly-discovered objects in.
Live Feed