Skip to content

Gate capture cannot be opened on the device, so no circuit can be promoted out of provisional #204

Open

Description

@PurpleSentinel

Objective

Make gate capture reachable on the device. It is built, host-tested, wired into the
simulator, and there is no way to open it on the hardware.

This is the last thing between the device and a timed lap

The chain is complete except for one link:

  1. No circuit can arm timing, because every one in the UK pack is provisional (No circuit in the UK pack can arm timing: all 24 are provisional #139)
  2. A provisional circuit is promoted by capturing its geometry on the device (Define a Test Circuit: a fixed road loop for end-to-end timing, GNSS and logging tests #184)
  3. The capture screen exists and cannot be opened on the device

So no lap has ever been timed, and the whole timing chain - engine, lap state machine,
crossing validation, interpolation, logger - remains unproven against reality. All of it is
host-tested. None of it has seen a real crossing.

What is already there

firmware/components/ui/gate_capture.cpp          GateCaptureController, 13 states
firmware/components/ui/gate_capture_screen.cpp   GateCaptureScreen, 6 actions
tests/cpp/test_gate_capture.cpp                  host tests
simulator/src/application_screen.cpp             31 references, fully wired
firmware/main/                                   0 references

The two ends that matter are already correct, which is worth stating because they are what
make this worth doing rather than rebuilding:

  • gate_capture.cpp:172 sets geometry_status = device_captured on save, so a captured
    circuit is promoted out of provisional and will arm timing.
  • SdTrackStore::write_atomic writes into the device-captured pack rather than over the
    distributed one, so a capture can never be confused with shipped data and wiping a
    downloaded pack cannot delete your own work.

Nothing in the capture logic needs changing. This is wiring.

Scope

  • A way in. Recommended: a new SETUP entry, CAPTURE GATES, operating on the circuit
    currently loaded. The simulator enters from its track-selection screen through
    TrackSelectionAction::capture_information, but the device's track list is a
    carousel with no equivalent action, and "load the circuit, then capture its gates" is
    the clearer mental model anyway
  • A screen root and a GateCaptureScreen, as the other full-panel screens are built
  • Route the six GateCaptureActions - previous gate, next gate, toggle endpoint,
    capture, save, cancel
  • Feed update_fix() from the GNSS pipeline, so accuracy, fix age and the captured
    coordinate are live
  • Hand it the existing track_store_ and the session-active flag, so capture is
    refused while a session runs and while moving
  • Reload the catalogue and re-apply the track after a successful save, so the newly
    captured circuit arms without a restart
  • Log the outcome. A capture that silently did not save is the failure most likely to be
    discovered at the circuit rather than in the paddock

The button question, and the recommendation

GateCaptureScreen is a button panel - button_for(), add_buttons_to_group() - from
the UI generation before #128 reworked everything into press-and-hold carousels. Every
other full-panel screen on the device is gesture-driven.

Two options:

  1. Wire it as it is. Fast, and it works. Inconsistent with the rest of the device.
  2. Rebuild it in the carousel idiom first. Consistent, and considerably more work before
    anything can be captured.

Recommendation: (1), and say so in the issue that follows. This screen is used stationary,
in a paddock, with the car switched off - which is the one place on this device where a
button panel is not a liability. Getting a circuit captured is worth more right now than
getting it captured consistently, and the consistency work is easier to judge once somebody
has actually used the screen in the field.

Acceptance criteria

  • A user can open gate capture on the device, with no rebuild
  • All four gates and both endpoints of each can be captured and saved
  • Capture is visibly refused while a session is active or the car is moving
  • An invalid or partial capture never replaces a valid definition
  • After saving, the circuit reads as device_captured and timing arms
  • make check and the simulator suite pass

This also reopens the question #108 was closed on

#108 "Capture and persist four circuit gates safely on device" was closed in August with the
acceptance criterion "a user can capture, validate, save, reload, and select all four lines
without rebuilding firmware"
. That criterion is not met and never was on the device - the
same shape of premature close as #18, where the work was built and host-tested and nothing
called it.

Worth deciding whether #108 reopens or stays closed with this issue carrying the remainder.

Not in scope

  • Rebuilding the capture screen in the carousel idiom
  • Changing any capture, validation or persistence logic. It is written, tested, and its two
    critical behaviours - promoting provenance and writing to a separate pack - are already
    right
  • Capturing while moving. Deliberately refused

Activity

  1. added
    enhancementNew feature or request
    priority:highRequired for the current milestone or a correctness/reliability risk
    area:tracksTrack definitions, loading, selection, and tooling
    on Oct 16, 2026
  2. PurpleSentinel commented on Oct 21, 2026

    @PurpleSentinel
    ContributorAuthor

    Decision on #108

    #108 stays closed. This issue carries the remainder.

    Reopening it would split one piece of work across two issues: #108's criterion ("a user can capture, validate, save, reload, and select all four lines without rebuilding firmware") and this issue's criteria are the same criterion, and it is this issue that has the wiring, the counts and the refusal reporting attached to it. A closed issue that was closed early is a matter of record; two open issues describing the same unverified capture would be a matter of confusion at the circuit.

    What #108 got wrong is worth keeping as the lesson rather than as an open ticket: it was closed on work that was built and host-tested and called by nothing. Same shape as #18, #204, #214, #219 and #222. The remedy is the acceptance criteria on this issue staying unticked until a capture happens on hardware — which is also why #232 refs this issue rather than closing it.

    State of this issue after #232

    Done:

    Still open, and only provable at a circuit:

    • All gates and both endpoints of each captured and saved
    • After saving, the circuit reads device_captured and timing arms

    Everything short of a valid save is now checkable on the bench: capture four endpoints anywhere, press SAVE, and the refusal reads AN ENDPOINT IS OUTSIDE THIS CIRCUIT'S GEOFENCE with nothing written to the card. A successful save is impossible away from the circuit by design, which is the whole reason this issue cannot be closed from a desk.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:tracksTrack definitions, loading, selection, and toolingenhancementNew feature or requestpriority:highRequired for the current milestone or a correctness/reliability risk

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions