Scope freeze — nuforc Eventdex kind
Frozen 2026-06-26. One slot = one UFO sighting report from the National UFO Reporting Center (NUFORC). A report-log Eventdex, the sighting analogue of the FEMA administrative-record kind.
The slot
- One slot = one sighting report. Slot id is a deterministic content hash,
{YYYYMMDDTHHMM}_{hash10}, over the report's time, place, shape, duration, and description (NUFORC carries no native report id). Re-running is idempotent and the byte-identical duplicate filings collapse to one slot. - Roster: 80,324 slots (from 80,332 PG observations; 8 exact-duplicate filings collapse). Span 1906-11-11 .. 2014-05-08.
- Real ground point: unlike FEMA (an area), every NUFORC report has a geocoded lat/lon, so the slot keeps the point. 80,324 / 80,324 carry coords.
Measured reality
NUFORC is a report log: the measured fact is that a human filed a sighting
report at a given time and place, the same footing as the FEMA disaster
declarations (a record that a declaration was made). It is eyewitness testimony
as data, not an instrument reading and not a model. TerraPulse already treats it
this way: the published earthquake-lights paper (/articles, 2026-05-30) used
NUFORC sightings cross-matched against USGS quakes. It clears the bright line as
a catalog of human reports; it is never presented as a measurement of a physical
field. The slot records what was reported, verbatim, without endorsing it.
Source
nuforc datasource (already normalized in PG, metric ufo_sighting,
80,332 observations). A static historical archive that ended in 2014, so the
build is a one-shot PG read with no live edge (nothing new arrives). Each
observation already carries the shape, duration (seconds + free text),
description, posting date, and city/state/country in extra_json.
Slot contents (spine columns)
slot_id, kind, origin_utc (UTC), lat, lon, shape (the subtype),
duration_seconds + duration_text, city / state / country,
date_posted, description, year.
Storage — spine parquet first (the severe-wx rule)
Follows the locked severe-wx ruling (docs/scope-severe-wx-eventdex.md,
2026-06-17): a big Eventdex kind is written spine-parquet first, not
file-per-slot, so the shared storehouse_index.json (~101 MB / 297k slots) does
not absorb another 80k files and slow every kind's rebuild_index_from_disk().
data/event_storehouse/nuforc/nuforc_spine.parquet (one row per sighting)
Per-slot JSON dossiers + the terrestrial cross-match are Brick D, deferred
behind the scalable per-kind index, same as the 15 severe-wx kinds. Flagged in
docs/dex-triage-surfaced.md, not silently dropped.
Builder
scripts/build_nuforc_spine.py (pure PG read; importable slot_id / _row /
load_rows / build). Tests: tests/test_monitor/test_nuforc_spine.py
(6, slot-id determinism + dup-collapse + row mapping).
Frozen vs deferred
- Frozen (this brick): the 80,324-slot spine parquet (one row per report, with ground point + record fields).
- Deferred (Brick D): per-slot JSON dossiers; the terrestrial cross-match read-across (does a sighting line up in time and place with a quake, a launch, a fireball reentry); any enrichment of the free-text description.