20260914 - Give every track its own identity, not the aircraft's - #31
Purple10101 wants to merge 1 commit into
Conversation
Track._generate_id built the id from adsb_hex whenever the aircraft was known, so every pass of that aircraft in a day answered to one identity. That hid the failure we most need to see. live_score.fragmentation counts distinct ids per hex, so an id derived from the hex can only ever yield one: a site splitting an aircraft four ways reported 1.05 where the truth was 4.57. It cost more than a blind metric. TrackEventWriter keeps a per-track high-water mark keyed by id, so two tracks of one aircraft shared it, and whichever emitted first silently suppressed the other's earlier detections. The events file was missing data nobody could see was missing. The id becomes a plain daily counter. The label is not lost: it travels in the event's own adsb_hex field, which is where every consumer already reads it. One assertion in test_adsb_features.py inverts, because it pinned the old behaviour of carrying the hex in the id. This matters now rather than later because fairforest B started producing labelled tracks today, and fragmentation is one of the measures that was blind while its ADS-B feed was misconfigured. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Claude finished @Purple10101's task in 3m 2s —— View job Code Review
The core change is sound: Finding:
|
Track._generate_idbuilt the id out ofadsb_hexwhenever the aircraft was known, so every pass of that aircraft in a day answered to one identity. That hid the failure we most need to see this week.live_score.fragmentationcounts distinct track ids per hex. An id derived from the hex can only ever yield one, so a site splitting an aircraft four ways reported 1.05 where the truth was 4.57. The metric was not wrong, it was structurally incapable of being right.It cost more than a blind metric.
TrackEventWriterkeeps a per-track high-water mark keyed by id, so two tracks of one aircraft shared it, and whichever emitted first silently suppressed the other's earlier detections. The events file was missing data nobody could see was missing.What is in here
_generate_iddrops itsadsb_hexargument and always returns the plain daily counter,YYMMDD-NNNN.tracker.py(promotion, and tracklet initiation) updated to match.tests/test_track_identity.py, new: distinct ids for two tracks of one aircraft, the counter rolling over at the date boundary, and the hex still reaching the event.test_adsb_features.pyinverts, because it pinned the old behaviour of carrying the hex in the id.The label is not lost. It travels in the event's own
adsb_hexfield, which is where every consumer already reads it.Why now
This is Phase 0 of today's tracker plan, and it blocks the rest of it. fairforest B started producing labelled tracks today, now that retina-node #39 has pointed its ADS-B truth feed at the right port, and fragmentation is one of the measures that was blind the whole time that feed was misconfigured. Anything measured against labels before this lands is measured through a metric that cannot move.
Verification
ruff check(E, F, W) clean,ruff format --checkclean, 268 passed / 1 xfailed.Merges cleanly with
20260914-record-filter-innovations, which is the other Phase 0 branch and touches neither call site.🤖 Generated with Claude Code