Skip to content

feat: post-flight reconciliation review (R2) - #122

Merged
fetzu merged 1 commit into
feat/flight-event-detection-v2from
feat/flight-reconciliation
Aug 2, 2026
Merged

feat: post-flight reconciliation review (R2)#122
fetzu merged 1 commit into
feat/flight-event-detection-v2from
feat/flight-reconciliation

Conversation

@fetzu

@fetzu fetzu commented Aug 2, 2026

Copy link
Copy Markdown
Owner

Post-flight reconciliation (R2 — the "almost-perfect" lever)

Stacked on #121 (flight-event detection v2). Implements recommendation R2 of the 53-flight analysis under decision D2: review diff, never silently change confirmed events.

Why

Live detection has a ceiling that no detector fixes: confirmation prompts auto-dismiss after 20 s while the pilot is hand-flying the circuit, and single-pilot ops will always miss some. The corpus shows the damage — whole circuit sessions with 2 of 7 landings confirmed, flights whose only landing was lost to an early recording stop, and 19 of 53 flights with no block-off because the engine checklist was never tapped.

What

FlightReconciliation (engine): at END FLIGHT, re-runs the v2 detector core over the whole saved track offline (clock pinned to each sample, end-of-flight flush included — the same code path pinned by the corpus fixtures), then builds a diff against the confirmed events:

  • Detected and recorded events within 120 s are one physical event — same type ⇒ agreement, different type ⇒ a type-mismatch row (the <15 ft ambiguity band's human-resolution point).
  • Detected events nobody confirmed ⇒ detected-only rows (the missed-prompt case).
  • Recorded events the track can't see stay confirmed — the pilot's word beats the track — unless they duplicate another landing within 60 s (physically impossible; the corpus's double-taps are 7–35 s apart), which reconciliation refuses.
  • Track-derived block times (the exact first-move / final-stillness rules validated against the club's entries) back-fill flights missing them. Back-fill is additive — a recorded value is never overwritten.

FlightReconciliationView (review sheet, presented over Home right after END FLIGHT, only when the diff would change events):

  • One tap Apply to logbook accepts the track's reading.
  • Every row's type can be overridden (TG ↔ GA ↔ FS) via an inline menu; detected-only rows can be excluded.
  • Keep as recorded leaves the logbook exactly as confirmed — block times still back-fill, since that adds only what was missing. Interactive (swipe) dismissal is disabled: the choice is explicit, and the binding's dismiss path defaults to keep-as-recorded as defense in depth.
  • No diff ⇒ no sheet; block-time back-fill alone happens without ceremony.

AppState: pendingReconciliation + applyReconciliation / keepRecordedReconciliation / backfillBlockTimes — apply rewrites the saved flight's event arrays/counts and landingTime (last full stop), recomputes summary stats, persists and re-syncs.

Tests

FlightReconciliationTests drives the engine with a real corpus fixture (the 7-landing strong-wind circuit session) plus synthetic tracks:

  • 2-of-7 confirmed ⇒ 5 detected-only rows, apply reaches the track's 7, landingTime = last FS.
  • Full agreement ⇒ no diff, no sheet.
  • Confirmed GA on a detected touch ⇒ exactly one type-mismatch row, starting at the track's reading.
  • Recorded double-tap 30 s after a landing ⇒ refused.
  • Block times back-filled only when missing; recorded values never overwritten; the first-move / final-stillness rules pinned on a synthetic track.

Full suite green; EN/FR strings included.

Notes

  • The analysis runs synchronously in the END FLIGHT handler (sub-second for typical tracks at the 5 s recording interval). If a 1 s-interval multi-hour track ever makes this visible, moving it off-main is a contained follow-up.
  • The engine reuses the shipping FlightEventDetector — there is deliberately no second detector implementation to drift out of sync.

🤖 Generated with Claude Code

Live detection has a ceiling: prompts auto-dismiss after 20 s while the pilot
is hand-flying the circuit — the corpus shows sessions with 2 of 7 landings
confirmed. At END FLIGHT the saved track is re-segmented offline through the
SAME v2 detector core (clock pinned per sample, end-of-flight flush included;
no second implementation to drift) and diffed against the confirmed events:

- detected + recorded within 120 s = one physical event (same type → agreement,
  different type → a type-mismatch row: the <15 ft ambiguity band's human
  resolution point);
- detected-only rows = the missed-prompt case;
- recorded events the track can't see stay confirmed — the pilot's word beats
  the track — unless they duplicate another landing within 60 s (physically
  impossible; the corpus's double-taps are 7–35 s apart), which is refused.

The review sheet (FlightReconciliationView, over Home, only when events would
change) applies the track's reading in one tap, lets every row's type be
overridden (TG↔GA↔FS) and detected-only rows be excluded; "keep as recorded"
leaves the logbook untouched. Confirmed events are never changed silently.

Track-derived block times (the first-move / final-stillness rules validated
against the club's entries) back-fill flights whose engine checklist was never
tapped — 19 of 53 corpus flights had no block off. Back-fill is additive and
happens without ceremony when there is no event diff.

Tests drive the engine with the 7-landing strong-wind circuit fixture plus
synthetic tracks: missed-events diff + apply, full-agreement no-diff,
type-mismatch single row, double-tap refusal, back-fill only-when-missing,
block-time rules. EN/FR strings included.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@fetzu

fetzu commented Aug 2, 2026

Copy link
Copy Markdown
Owner Author

Verification summary:

  • All 6 FlightReconciliationTests green on first run (driven by the 7-landing strong-wind circuit fixture + synthetic tracks); full suite 491 tests green.
  • Simulator: END FLIGHT exercises the new path live — offline re-segmentation runs, the no-diff case correctly shows no sheet, the flight saves and the app returns to Home. The unresolved-checklist speed fallback from feat: flight-event detection v2 + barometer (validated on 53 real flights) #121 was also confirmed live (Configured v2: Vso=38 Vr=45 where the pre-guard build logged Vso=0 Vr=0).
  • The review-sheet UI itself is covered by the engine tests (row construction, type-mismatch, include/exclude semantics live in FlightReconciliation, not the view); seeing the sheet on-device needs a real flight with missed prompts — worth a device pass alongside the feat: flight-event detection v2 + barometer (validated on 53 real flights) #121 TestFlight run.

@fetzu fetzu self-assigned this Aug 2, 2026
@fetzu fetzu added the enhancement New feature or request label Aug 2, 2026
@fetzu fetzu added this to the v4.4.0 milestone Aug 2, 2026
@fetzu
fetzu merged commit 76336a5 into main Aug 2, 2026
@fetzu
fetzu deleted the feat/flight-reconciliation branch August 2, 2026 17:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant