Repository navigation
fix(ui): make gate capture ask for the gates a circuit actually has, and say why a save was refused - #232
Open
PurpleSentinel wants to merge 1 commit into
Open
fix(ui): make gate capture ask for the gates a circuit actually has, and say why a save was refused#232PurpleSentinel wants to merge 1 commit into
PurpleSentinel wants to merge 1 commit into
Conversation
…and say why a save was refused Gate capture was made reachable on the device in #205, which left #204 open on its field criteria. Two things in the way of meeting them, both found by reading the screen as somebody standing at a circuit would. Removing pit entry and exit (#227) took a circuit from four gates to two. The controller followed - two gates, four endpoints, save unlocking at four - and the text it hands the screen did not. The device went on instructing the driver to capture 8 endpoints across FOUR GATES, and the selection line counted toward an 8 it could never reach, while save had already unlocked. The counts now come from kGateCaptureEndpointCount or the gates are named rather than counted, and the host test asserts the instructions against that stated shape instead of a number typed into the test. A save refused by validation said GATE GEOMETRY FAILED SAFETY VALIDATION, which names none of the three things that can go wrong. A line whose ends are under a metre apart, a line outside the circuit's geofence, and a line too long or within ten degrees of the direction of travel share nothing but the refusal and have three different remedies - and the difference between them, at a circuit, is the difference between walking ten metres and giving up on the session. serialize_track_definition already round-trips its candidate through load_track_definition, which is what keeps invalid geometry off the card, so the report it was discarding is now passed back through an optional out-parameter. The panel and the log both name it. Where one result covers several checks, all of them are listed rather than one being picked and presented as the cause. Refs #204 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This was referenced Oct 21, 2026
Open
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.
Refs #204. Does not close it — see the last section.
#204 was wired in #205
#205made capture reachable (SETUP → CAPTURE GATES, operating on the loaded circuit) and said so honestly: "Not verified: an actual capture on hardware." Checking the acceptance criteria against the code now, the wiring is all there — open, six actions routed,update_fixfed every tick, catalogue rebuilt and the circuit re-applied after a save, outcome logged.Two things were still between that and a capture succeeding at a circuit, and both are about what the screen tells you.
It asked for eight endpoints that no longer exist
Removing pit entry and exit (#227) took a circuit from four gates to two. The controller followed —
kGateNames{"START","FINISH"},captured_of 4, save unlocking at 4. The text it hands the screen did not:ENDPOINT CAPTURED - CONTINUE UNTIL ALL 8 ARE COMPLETESAVE BLOCKED - CAPTURE BOTH ENDS OF ALL FOUR GATESSAVED AND RELOADED - FOUR-GATE DEFINITION IS READYSTART | LEFT | 2/8/4capture: ... %u of 8 endpoints(log)So a driver following the screen captures four endpoints, is told to continue to eight, and never reaches a state the screen calls finished — while
SAVEhas been enabled since the fourth. That is the acceptance criterion "all gates and both endpoints of each can be captured and saved" failing on instructions rather than on logic.Counts now come from
kGateCaptureEndpointCount, or the gates are named rather than counted —CAPTURE BOTH ENDS OF THE START AND FINISH LINESis both un-staleable and the clearer instruction at the line. The host test asserts the text against that stated shape, so the next change to the shape of a circuit cannot pass with stale instructions:A refused save named none of its three causes
SAVE BLOCKED - GATE GEOMETRY FAILED SAFETY VALIDATION, to somebody parked at a circuit with the engine off. The three ways a captured line is refused have three different remedies:LINE TOO SHORT: THE TWO ENDS MUST BE AT LEAST 1 M APARTAN ENDPOINT IS OUTSIDE THIS CIRCUIT'S GEOFENCEgates.start REFUSED. CHECK ITS LENGTH, ITS ANGLE TO THE DIRECTION OF TRAVEL, AND THAT IT IS AT THIS CIRCUITserialize_track_definitionalready round-trips its candidate throughload_track_definition— that round trip is what keeps invalid geometry off the card — and was discarding the report. It now takes an optionalTrackLoadReport*, so no existing caller changes, and both the panel and a newESP_LOGWname the reason.Three causes share
invalid_valuefor a gate — projection failure, over a kilometre long, within ten degrees of the direction of travel — and from the controller there is no telling which. All three are listed rather than one being picked and presented as the cause.Verification
make check→CHECK_RC=0; simulator 78/78; firmware builds, 32% of the app partition freeSAVE→ refused withAN ENDPOINT IS OUTSIDE THIS CIRCUIT'S GEOFENCE, nothing written. The new host test pins exactly that, shifting both lines 5.5 km north and assertinggeometry_outside_geofencerather than a degenerate lineWhy this does not close #204
Its criteria are "all gates captured and saved" and "after saving, the circuit reads
device_capturedand timing arms". Those can only be met at a circuit, parked at the physical ends of a line with a fix. Nothing in this PR or #205 can prove them from a desk — the geofence check means a successful save is impossible anywhere but the circuit itself, by design.Two things worth deciding separately, both left alone:
COPY START TO FINISHaction would fix it and is a new feature, not wiring.GateCaptureScreen::update()rewrites all six labels unconditionally at the display cadence — the same unconditional repaint fix(ui): make Race's running-screen rule testable and drop the delta it never drew #231 just gated on the Race screen. Untouched here: it is A single LVGL repaint costs 40 ms against a 25 ms service period, on the task that also polls the receiver #213's territory and this screen is used parked.🤖 Generated with Claude Code