-
Notifications
You must be signed in to change notification settings - Fork 0
Gate bounce is its own rule: a tunable per-timer same_pass_window, classified in the fold (#517) - #520
Merged
Merged
Conversation
...red" section `src-tauri/README.md` said Windows packaging was deferred and "no Windows artifact is produced here". That has not been true since the release workflow grew its `windows-latest` leg: it builds `gridfpv-desktop.exe`, smoke-tests that it starts, and uploads it as `gridfpv-windows-portable`. The same README's own build section already listed the `.exe` output path, so the file contradicted itself. Replaced with what actually happens, and — since the question comes up every time someone looks at building locally — WHY no cross-compile is attempted: building the exe from Linux is feasible, but it cannot *launch* the result, and the startup smoke-test is the point (#58 is done when the binary launches on all three OSes, not when it compiles for them). Same note for the macOS leg, which stays on Apple hardware for licensing reasons. Also drops the "(deferred — not yet built)" qualifier from the Windows row of the data-dir table, which was stale for the same reason. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011XCMrqJjroyaZ7M2gF6JhU
...ss_window (#517) A bouncy gate put a removal row between every pair of real laps in Marshaling: ∅ crossing at 1:02.4s — under min lap, auto-removed [Restore] three or four of them per pass, so the laps an RD came to marshal were the minority of the list. The cause was that ONE concept had TWO owners and neither was the fold: the console suppressed reflection tones with a hardcoded 1s constant the server knew nothing about (#503), while the fold lumped every too-close crossing under `UnderMinLap` — conflating a competition rule ("too soon to count as a lap") with a hardware fact ("that did not happen twice"). Because they were the same disposition on the wire, the console could not collapse a reflection burst without also hiding a genuinely short lap. So the fold now decides, once, and both consumers read it. * `Timer::same_pass_window_micros` — timer-level, because bounce is a property of the GATE (antenna, RSSI thresholds, placement), identical across every round run on it. `RoundDef::min_lap_secs` stays where it is; that one is a racing rule. Default 1s, hard-capped at 2s: no lap is that short, so the setting can only ever collapse repeat detections of one physical pass. * `VoidReason::SamePassBounce` / `CrossingDisposition::RejectedSamePass` — checked BEFORE the floor (it is the narrower claim), measured from the last SURVIVING pass so a burst collapses against one anchor instead of ratcheting forward off its own echoes, and honouring the same marshal exemption. * Marshaling collapses a burst to one muted line, expanding to the ordinary rows with per-crossing Restore. No bulk restore — restoring a whole burst is never wanted and one misclick would add that many phantom laps. * `CROSSING_TONE_COOLDOWN_MICROS` is deleted, not aliased. `useCrossingTones` reads the disposition instead. Behaviour is unchanged: the fold measures from the last surviving pass exactly as the cooldown measured from the last sounded tone, and a suppressed crossing extends neither. ## Pinned at the arm, so a timer edit cannot re-judge a finished race `min_lap_secs` freezes once a round has raced, precisely so results cannot shift under it. Timers have no such freeze — they are edited freely — so a timer-level fold input read live would re-score every past race on that timer. `Event::HeatDetectionPinned` records the window in force when the heat arms, and the fold reads it from the log. Same shape as `HeatStarting` / `HeatFinalizing` / `RaceExpired`: the runtime resolves a value once, at emission time, and logs it as a fact. `(Staged, Start) -> Armed` is the only arm in the heat FSM, so every run pins exactly once and a re-arm re-pins. Verified live: with a race finished, turning the timer's window off left the lap list byte-identical. The general rule is #518. The pin is included in the heat and class windows BY TAG and un-gated — it is appended at the arm and `current_run_start` opens the window at Running, so a gated scan would drop it and the live view would then disagree with the lap list about a suppressed pass. That is the D26 failure of #409; `live_crossings.rs` now asserts it cannot recur. `docker/rotorhazard/race_day.py` gains a `bouncy` scenario — echo bursts per pass plus one genuine sub-floor crossing — which is the fixture this needs. Verified against dockerized RH: 11 RejectedSamePass, 1 RejectedTooShort, 8 counted laps, and the two sitting side by side in one pilot's list. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011XCMrqJjroyaZ7M2gF6JhU
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.
Closes #517.
A bouncy gate put a removal row between every pair of real laps in Marshaling — three or four per pass — so the laps an RD came to marshal were the minority of the list.
The cause was that one concept had two owners, and neither was the fold: the console suppressed reflection tones with a hardcoded 1 s constant the server knew nothing about (#503), while the fold lumped every too-close crossing under
UnderMinLap— conflating a competition rule ("too soon to count as a lap") with a hardware fact ("that did not happen twice"). Same disposition on the wire, so the console could not collapse a reflection burst without also hiding a genuinely short lap.What changed
Timer::same_pass_window_micros— timer-level, because bounce is a property of the gate.RoundDef::min_lap_secsstays put; that one is a racing rule. Default 1 s, hard-capped at 2 s.VoidReason::SamePassBounce/CrossingDisposition::RejectedSamePass— checked before the floor, measured from the last surviving pass, honouring the marshal exemption.CROSSING_TONE_COOLDOWN_MICROSdeleted —useCrossingTonesreads the disposition. Behaviour-preserving: the fold measures from the last surviving pass exactly as the cooldown measured from the last sounded tone.Pinned at the arm
min_lap_secsfreezes once a round has raced so results cannot shift under it. Timers have no such freeze, so a timer-level fold input read live would re-score every past race on that timer.Event::HeatDetectionPinnedrecords the window in force at the arm and the fold reads it from the log — the same shape asHeatStarting/HeatFinalizing/RaceExpired. The general rule is #518.current_run_startopens the window atRunning, so a gated scan drops it and the live view then disagrees with the lap list about a suppressed pass — the D26 failure of #409. I hit exactly that mid-build;live_crossings.rsnow asserts it cannot recur.Verification
cargo xtask ci(1636 passed) · frontend build/check/lint/test (1248) · contract (141) ·cargo xtask e2e(46/46).Also driven end-to-end against dockerized RotorHazard, via a new
bouncyrace-day scenario (echo bursts per pass plus one genuine sub-floor crossing):One pilot's list shows both cases side by side — 2 collapsed bounces and a real 3 s crossing that keeps its full row, its Restore and its tone. And with the race finished, setting the timer's window to
0left the lap list byte-identical; a live read would have flipped all 15 bounces toUnderMinLap.Also here
A second commit corrects
src-tauri/README.md, which claimed Windows packaging was deferred and no Windows artifact was produced — untrue since the release workflow grew itswindows-latestleg, and contradicted by the same file's own build section.🤖 Generated with Claude Code
https://claude.ai/code/session_011XCMrqJjroyaZ7M2gF6JhU