feat(rate-of-closure, #4103): port the flight integrator (the last blocking symbol) - #4542
Merged
Conversation
The last and hardest of the ten symbols blocking the React migration. flight.ts gains AngularFlightPoint, FlightSimulationOptions and simulateFlightWithOptions; FlightResult.trajectory widens to AngularFlightPoint[]; and the in-file RK4 loop moves into a new flightIntegrator.ts that both entry points delegate to, so there is one integrator rather than two that can drift. This was deferred twice because main's loop carries #4518's ground-crossing guard and a naive swap would revert it. It does not: the integrator's contact test requires currentGap > 0 strictly, so a launch starting at ground level yields a gap of zero and never records a crossing -- structurally the same protection && t > dt provides. That is not argued from the code alone. All 1,420 tests on main pass unchanged with the integrator swapped in, including wind.test.ts and the ball_flight_metrics_golden_v1 and inverse_flight_solver_golden_v1 Python-parity fixtures. The integrator adds an upfront MAX_FLIGHT_INTEGRATION_STEPS = 50_000 bound keeping synchronous UI-thread RK4 work finite; the default 10s at a 1ms step is 10,000 steps, so no existing caller changes behaviour. Unlocks flightGroundTransfer and simulationTypes, which need the angular state at landing; their 15 tests land with them. Verified: tsc clean, eslint clean, 1,435 tests across 176 files, production build succeeds. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
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.
The last and hardest of the ten symbols that gated the React migration. I deferred this twice — in #4533 and #4541 — because
main's in-file RK4 loop carries #4518's ground-crossing guard, and a naive swap would revert it.What changes
flight.tsgainsAngularFlightPoint,FlightSimulationOptions,simulateFlightWithOptionsFlightResult.trajectorywidens fromFlightPoint[]toAngularFlightPoint[]flightIntegrator.ts; both entry points delegate to it, so there is one integrator rather than two that can driftflight.tsWhy the swap does not revert #4518
main's guard:The
&& t > dtwas added because a descending launch starts below zero,tGroundcan land before zero, and a negative-time trajectory point makes the metric contract raiseRangeError— surfacing a bad launch as an error rather than the nonconverged result it is.The integrator's contact test:
with
terminalGapMdefaulting toposition[2]. It requirescurrentGap > 0strictly, so a launch starting at ground level yields a gap of zero and never records a crossing. That is structurally the same protection, expressed as a state condition rather than a time check.This is not argued from the code alone. All 1,420 tests on
mainpass unchanged with the integrator swapped in — includingwind.test.ts(the Python/TS parity tolerance from #4513) and theball_flight_metrics_golden_v1andinverse_flight_solver_golden_v1Python-parity fixtures. Those goldens are the strongest available evidence that trajectory output is unchanged.One new bound, no behaviour change
The integrator checks
Math.ceil(maxTime / step) > MAX_FLIGHT_INTEGRATION_STEPS(50,000) upfront, keeping synchronous UI-thread RK4 work finite. The default 10 s at a 1 ms step is 10,000 steps, so no existing caller is affected.What it unlocks
flightGroundTransfer(+260) andsimulationTypes(+83) both need the angular state at landing thatAngularFlightPointcarries. Their 15 tests land with them.Two main-owned tests restored (again)
TorqueProfilePanel.test.tsxandPrimaryViewTabs.test.tsxare reverted tomain's versions. Both are purely additive by line count yet fail againstmain's unchanged components — the recurring trap in this migration, and the reason the prune script now refuses to delete files present onorigin/main.Verification
tsc --noEmit— cleaneslint .— cleanvitest run— 1,435 passed across 176 files, 0 failednpm run build— production Vite build succeeds1.17.36)🤖 Generated with Claude Code