Methods
What we compute, how predictions are graded, and how a third party can
verify that we never edited history. Every metric on this page is read from
the published metrics.json at load time — nothing is typed by hand.
Silence detection
Objects stop being tracked before they stop existing. In the final days of orbital decay, an object's tracking updates become sparse and then stop — sensors lose it as it drops through the densest part of the atmosphere. That quiet has a shape: the interval between catalog updates stretches in a way that is distinguishable from routine tracking gaps, especially when read against the object's own tracking cadence and the cadence of its orbital cohort.
Our silence detector monitors per-object tracking cadence and flags the terminal pattern. When it fires on an object whose orbit is consistent with terminal decay, a dated re-entry prediction is issued the same day and enters the ledger.
We publish the method's description and its full graded record. We do not publish the gating thresholds or sigma floors — the description is open, the tuning is the product.
Window model & conformal calibration
Each prediction carries a window in days: P10, P50 and P90. The windows come from a decay-clock model over the object's perigee history and effective perigee (drag-weighted), calibrated with split-conformal prediction so that the stated coverage is an empirical property, not a modelling assumption. The coverage target is —.
Calibration is graded in public: once enough closed predictions exist,
observed window coverage is published alongside the target in
metrics.json and on the landing page. Current published
coverage: —.
Casualty tiers
Each watchlist row carries a casualty tier — HIGH, MEDIUM or LOW — a coarse index of what the object could do on the way down. It is a mapping from two public catalog properties:
- Object type — rocket bodies and large payloads carry dense components (tanks, casings) that are more likely to survive re-entry than fragmentation debris.
- Radar cross-section class (LARGE / MEDIUM / SMALL) — a proxy for the object's size and therefore its surviving mass.
The tier feeds the exposed-latitude-band column: together they answer "how much could reach the ground, and under which latitudes could it happen." The mapping is publishable and deliberately coarse — it ranks attention, it does not model debris fields.
Receipts: verify it yourself
Every day's issued predictions are written to an append-only emission file and hashed at issue time. The hashes form a chain:
chain[0] = "genesis"
file_sha = SHA-256(file bytes) — hex digest
chain[i] = SHA-256(chain[i-1] + file_sha[i]) — hex string concatenation
The published receipts.json
lists every chained file with its sha256 and running
chain value, and the chain_head — the last chain
value — is displayed on the track record and republished nightly. Editing
any past prediction changes that file's bytes, which changes its
sha256, which changes every downstream chain value including
the head. Anyone holding yesterday's receipts file can catch it.
Worked example you can run in a terminal, using the first entry of the
current receipts file
(2026-07-15/terminal-silence.jsonl):
# 1. hash the emission file (or take entries[0].sha256 from receipts.json)
$ shasum -a 256 2026-07-15/terminal-silence.jsonl
7eb200c50242f93892409c88de9d4b74ec347de4e74dae881651f278f686ca27
# 2. first chain value = SHA-256 of "genesis" + that hex digest
$ printf 'genesis%s' \
7eb200c50242f93892409c88de9d4b74ec347de4e74dae881651f278f686ca27 \
| shasum -a 256
d3bc7548ec98e5050f53c6007808927a12d29b77c811a7f8c04da29f3492837c
# matches entries[0].chain in receipts.json. Repeat the fold over every
# entry; the final value must equal chain_head.
To fold the whole file, feed each entry's sha256 through the
same two-line recipe, carrying the chain value forward. Ten lines of shell
or Python; no DecayGuard code required.
The anchor chain: one line per day, forever
Receipts protect individual prediction files. The
anchor chain
protects whole days: every night, one JSON line records the SHA-256 of
every artifact published that day (metrics, track record, predictions,
the receipts head) plus the previous line's hash. Rewriting any
historical day breaks every line after it. Dated artifact snapshots stay
frozen once anchored — a republish may refresh
latest/, never the dated record.
You do not have to trust us on that: verify_anchors.py (standard library only, no DecayGuard code) re-downloads every anchored day over plain HTTPS, recomputes all hashes, and checks every link:
$ python3 verify_anchors.py # checks https://decayguard.deepfieldlabs.dev/data
anchor 2026-09-06 .. 2026-09-25: 20 days, chain intact, all artifacts match
The first run of this verifier caught our own publisher overwriting an anchored day after a restart (2026-09-10). We fixed the publisher, and the incident is exactly why the verifier exists: honesty you can check beats honesty you are promised.
Grading rules
These rules are fixed in writing in the DFL Prediction Grading Standard v1 (frozen on publication, 2026-10-04). A prediction is a dated claim: "this object re-enters inside this window." Grades:
- hit / confirmed — a Space-Track decay record dates the re-entry inside the claimed window. Lead time is the number of days between issue and re-entry.
- miss — the re-entry is confirmed outside the claimed window. Misses stay in the ledger forever.
- expired — the window closed and no confirmation exists yet.
Space-Track's after-the-fact decay records publish days to weeks late
(median ≈ 6 days, 90th percentile ≈ 26 days in our observed sample),
so a freshly-expired window is usually "evidence not in yet", not
"wrong". Our headline evidence-mature precision therefore judges
a prediction only once a 28-day grace period past its window end has
elapsed — whatever its status. Confirmed, missed and expired
calls from a cohort that has not matured are all pending and
excluded from numerator and denominator alike (the matured and pending
counts are always shown). Expired is never final: evidence arriving
even after the grace period retroactively converts it to a hit or a
miss. The raw no-grace number is published alongside — nothing is
hidden, only labelled.
Correction, 2026-10-07. From launch (2026-10-04) until this date the published figure applied the grace test to expired calls only, while confirmations from the same unmatured cohorts counted at once. That is the survivorship bias the Grading Standard forbids, in the favourable direction: it read 0.955 on launch day, when the cohort-consistent figure was 0.22 on 9 matured calls — too few to claim anything. The standard's text was right; the implementation was not. The code, this page, the dashboard's client-side reproduction and the published metrics were corrected together, and the ledger itself is unchanged — every call, hit and miss is where it was. The current issuance regime (since 2026-08-17) matures from mid-November 2026; until then the headline describes the July–August cohorts. - cohorts — the ledger's first three days (2026-07-15..17)
issued calls against the pre-existing backlog of already-silent
objects, most of which are dead catalog entries whose decay predates
available ground truth. That founding cohort is reported separately
and excluded from the headline (both numbers are in the data files —
the cutoff date ships in
metrics.jsonso you can redo the split yourself). - void — the prediction was invalid at issue (for example, ground truth later shows the object had already decayed before we issued). Voids are shown in the ledger but excluded from precision — they are bookkeeping errors, not calls.
Ground truth is Space-Track Historical decay messages only — never Prediction messages. This is a deliberate integrity rule: Space-Track also distributes predicted decay epochs, and grading our forecasts against someone else's forecast would make "precision" circular. We wait for the after-the-fact record of what actually re-entered, even though it makes our numbers slower to close.
Headline stats on the track record page are recomputed in your browser
from the raw entries and compared against the published
metrics.json — if they ever diverge, the page says so,
loudly.
Claims policy
We publish the silence stream: its precision, lead-time stats, window coverage against target, and per-entry ground-truth links. We also run a burn-cadence stream — manoeuvre-behaviour predictions — internally. It is hash-chained daily like everything else (you can see its files in receipts.json), but its claims are not published and not for sale until the stream sustains better than 60% precision over 30 days of public-grade evaluation.
We think this is the feature. A prediction product that publishes every stream it runs is telling you its confidence bar is zero. Ours is written down, and the receipts chain proves the internal stream existed and was dated long before we started selling it.
Provenance
All inputs are public catalog data — Space-Track general-perturbations
histories and decay messages. Every published artifact carries
generated_at, a schema version and
source_day, and is validated against its schema before
publish; a failing artifact is never published and yesterday's stays live.
Stale-but-true beats fresh-but-wrong, and a visible "data delayed" banner
appears on every page when latest/ is older than 48 hours.