Repository navigation
Known lane: gate publishes on the loci's geometry, not on receiver sites - #671
Merged
Merged
Conversation
#663 withheld every known-lane solve whose receivers shared a site. That reads the wrong variable. A node's delay puts the aircraft on a curve whose normal is the sum of the unit vectors from its transmitter and from its receiver, so two nodes on one roof cross at half the angle their TRANSMITTERS subtend at the aircraft: a good pair with towers either side of it, none with towers on one farm, and which of the two changes from one aircraft to the next. Receivers far apart are no fix either when the aircraft is distant enough that every focus lies one way, and the site rule published those. On test, 2026-10-02, the one real n=2 pair (receivers co-sited, towers 18 km apart, 981 solves in 26 min) was 3% ghosts where a microsecond of delay error is under 2 km of position, 8% from 2 to 3, 33% from 3 to 4 and 61% over 8. The site rule withheld all of them alike. - services/solve_geometry.delay_dop_km_per_us: the dilution of precision of the delay loci at a pinned altitude, sqrt(trace((sum g g^T)^-1)) over the nodes' horizontal bistatic-range gradients, in km per microsecond. It is the crossing angle's generalisation to any node count, so three or four receivers on one roof are judged by the same number as two. None when a node's geometry is unknown, which never demotes a solve. - Binding publish gate "weak_geometry" (KNOWN_PUBLISH_MAX_DELAY_DOP_KM_PER_US, 3.0, 0 disables; counter known_lane_publish_weak_geometry) in place of "single_site", evaluated at the transponder's position rather than the solve's. Checked before the rms gate. Measurement, label and sample are unchanged. - History records and accuracy samples carry delay_dop_km_per_us in place of n_sites. node_sites.count_sites had no other caller and goes. - Ghosts from a geometry the gate would withhold never re-anchor; a co-sited pair on separate towers now can. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Claude finished @jehanazad's task in 4m 36s —— View job Code review
No issues found. Checked for bugs and CLAUDE.md compliance. Notes from the review (not issues, just what I checked):
CLAUDE.md items (contract regen, uv.lock, |
jehanazad
added a commit
that referenced
this pull request
Oct 18, 2026
Shadow was the measuring stage for the known lane: it claimed, calibrated and solved but published nothing. The measurements are in. On production, 2026-10-01, the single-node arcs the map draws instead sat a median 1.49 km (p95 31.5 km) from the aircraft, while the lane's withheld truth_match solves measured 0.49 km (p95 1.72 km); since #671 a solve whose loci barely cross is withheld as well. Staging mirrors production's real nodes, so binding there first shows what app.retina.fm will show before production's own overlay moves. The parity check gets a staging-scoped allowance for KNOWN_LANE_MODE alone, marked temporary: the change that binds production removes it, and the fallback flag stays compared throughout. Binding is lane-wide, so claims the adsb-service fallback makes for nodes that send no ADS-B of their own are drawn at the service's fix. Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
#663 withheld every known-lane solve whose receivers shared a site. That reads the wrong variable: two nodes on one roof cross at half the angle their transmitters subtend at the aircraft, so the same pair is a good fix for one aircraft and none for the next. This replaces the site count with a per-solve geometry figure, the dilution of precision of the delay loci, which holds at any node count, so three or four receivers on one roof are judged by the same number as two.
Why
Each node's delay puts the aircraft on a curve whose normal is the sum of the unit vectors from its transmitter and from its receiver. Co-sited receivers share the receiver term, which leaves the towers to decide the crossing. Sharing a tower with receivers apart is the mirror case, and receivers far apart are no fix either when the aircraft is distant enough that every focus lies one way.
On test, 2026-10-02, the one real n=2 pair (receivers co-sited, towers 18 km apart, 981 known-lane solves in 26 min):
The site rule withheld every row alike. Median error over median figure is 0.28 µs in each row from 2 to 8, so the error is the geometry. At the 3.0 default the gate keeps 59% of this pair's truth_match solves, with a 5% ghost rate among the attempts it passes.
Changes
services/solve_geometry.py(new):delay_dop_km_per_us,sqrt(trace((Σ g gᵀ)⁻¹))over the nodes' horizontal bistatic-range gradients at a pinned altitude, in km per µs. At n=2 it is the crossing angle in another unit.Nonewhen a node's geometry is unknown,inffor parallel loci.weak_geometryin place ofsingle_site,KNOWN_PUBLISH_MAX_DELAY_DOP_KM_PER_US(3.0, 0 disables), counterknown_lane_publish_weak_geometry. Evaluated at the transponder's position, not the solve's. Checked before the rms gate. Binding only; label, accuracy sample and history outcome are unchanged.delay_dop_km_per_usin place ofn_sites. solver-stats reportspublish_weak_geometryin place ofpublish_single_site.node_sites.count_sitesand its tests, which had no other caller.docs/solverflow.mdgains the gate in the 3c flowchart, prose and constants table;backend/.env.examplegains the key.Test coverage
tests/test_solve_geometry.py(new, 19 tests): the n=2 closed form, the half-angle rule for co-sited receivers, the shared-tower mirror case, three and four receivers on one roof (towers spread, one tower farm, two farms), altitude handling, and the unknown cases.tests/test_known_lane.py:TestSingleSiteGatebecomesTestGeometryGate. Co-sited on separate towers publishes; co-sited on one farm is withheld at n=2 and n=3; three co-sited on spread towers publish; three separate sites seen from 200 km are withheld; gate precedence, the env ceiling, zero-disables, unknown config, shadow mode, no-converge records and re-anchoring.tests/test_deploy_scripts.py, which this change does not touch; they fail on the droplet's own environment (an extra line in the rendered.env).solve_multinodefor 2, 3 and 4 receivers on one roof. Median error tracks the figure at every node count, and under 3 km/µs at most 2% of solves in any set land over 2 km.Greenville replay (2026-10-06)
The four co-sited Greenville nodes are the live case. Three afternoon hours of their detections from prod's public archive, replayed through the real solver as every subset, with the two untagged nodes' detections claimed offline against the ADS-B truth the two tagging nodes carry (receiver position self-surveyed from the tags; the two surveys agree to 68 m):
Two-node solves by the figure: ghosts 0% under 1, 1% at 1–2, 0% at 2–3, 6% at 3–5, 17% at 5–10, 48% over 10. The site-count rule would have withheld every row of this table. The quad never formed: the 195 MHz node claimed 37 aircraft detections in three hours against 937 for the 183 MHz node on the same tower, so the four-receiver case rests on the solver Monte Carlo above.
Review notes
publish_single_siteorn_sitesfrom solver-stats or history needs the new names. Nothing in the dashboard does.🤖 Generated with Claude Code