@inventure71/paddockjs 4.2.0 → 4.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (249) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/INSTALL_AND_UPDATE.md +24 -4
  3. package/README.md +31 -2
  4. package/docs/advanced_ai_pace.md +131 -0
  5. package/docs/advanced_physics_rebuild.md +166 -0
  6. package/docs/architecture.md +109 -30
  7. package/docs/cleanup_coverage.md +284 -0
  8. package/docs/component_inventory.md +31 -15
  9. package/docs/composable-layouts.md +2 -0
  10. package/docs/concepts.md +12 -1
  11. package/docs/custom_model_controller.md +1 -1
  12. package/docs/data_contract.md +33 -10
  13. package/docs/data_model.md +4 -2
  14. package/docs/efficiency_cleanup_2026-10-13.md +80 -0
  15. package/docs/grid_walk.md +84 -0
  16. package/docs/index.md +1 -0
  17. package/docs/keyboard_driving_fix.md +118 -0
  18. package/docs/limit_driving_2026-10-14.md +88 -0
  19. package/docs/maintainability_audit_2026-09-08.md +146 -0
  20. package/docs/racing_ai_improvements.md +145 -0
  21. package/docs/rules.md +43 -13
  22. package/docs/sense_contract.md +4 -1
  23. package/docs/system_specs.md +38 -11
  24. package/docs/testing-reliability-guide.md +5 -0
  25. package/docs/v11_improvements.md +108 -0
  26. package/package.json +24 -13
  27. package/src/api/MountedSimulatorComponents.js +101 -0
  28. package/src/api/PaddockSimulatorController.js +56 -81
  29. package/src/app/BrowserExpertAdapter.js +0 -6
  30. package/src/app/BrowserExpertExternalRenderer.js +72 -50
  31. package/src/app/ExternalTrackSnapshot.js +50 -0
  32. package/src/app/F1SimulatorApp.js +242 -297
  33. package/src/app/HostLifecycleEmitter.js +93 -0
  34. package/src/app/banners/raceDataBannerController.js +9 -4
  35. package/src/app/camera/cameraConstants.js +1 -1
  36. package/src/app/camera/cameraController.js +10 -13
  37. package/src/app/camera/cameraGeometry.js +1 -1
  38. package/src/app/controls/SimulatorViewControls.js +45 -0
  39. package/src/app/controls/workbenchBindings.js +64 -0
  40. package/src/app/controls/workbenchDisclosure.js +41 -0
  41. package/src/app/domBindings.js +21 -13
  42. package/src/app/gridWalk/GridWalkController.js +180 -0
  43. package/src/app/gridWalk/gridWalkCamera.js +88 -0
  44. package/src/app/gridWalk/gridWalkControls.js +24 -0
  45. package/src/app/gridWalk/gridWalkCrew.js +246 -0
  46. package/src/app/gridWalk/gridWalkLabels.js +104 -0
  47. package/src/app/gridWalk/gridWalkLayout.js +46 -0
  48. package/src/app/gridWalk/gridWalkNavigation.js +106 -0
  49. package/src/app/gridWalk/gridWalkProjectBanner.js +43 -0
  50. package/src/app/gridWalk/gridWalkSession.js +50 -0
  51. package/src/app/layoutSupport.js +2 -0
  52. package/src/app/raceOverlayClearanceSupport.js +21 -7
  53. package/src/app/readouts/carOverviewRenderer.js +9 -4
  54. package/src/app/readouts/readoutFormatters.js +1 -8
  55. package/src/app/readouts/telemetryRenderer.js +1 -3
  56. package/src/app/readouts/timingTowerRenderer.js +48 -50
  57. package/src/app/rendering/appAssets.js +8 -10
  58. package/src/app/rendering/carRenderer.js +27 -79
  59. package/src/app/rendering/displayUtils.js +0 -6
  60. package/src/app/rendering/expertSensorRenderer.js +1 -1
  61. package/src/app/rendering/replayGhostRenderer.js +4 -1
  62. package/src/app/rendering/trackRenderer.js +2 -2
  63. package/src/app/runtime/frameLoop.js +18 -17
  64. package/src/app/runtime/pixiStartupLifecycle.js +94 -0
  65. package/src/app/runtime/runtimeTiming.js +4 -1
  66. package/src/app/runtime/runtimeVisibility.js +7 -2
  67. package/src/config/cssValues.js +1 -1
  68. package/src/config/defaultOptions.js +12 -173
  69. package/src/config/restartOptions.js +1 -0
  70. package/src/config/runtimeSeed.js +10 -0
  71. package/src/config/simulatorDefaults.js +106 -0
  72. package/src/config/telemetryModules.js +20 -0
  73. package/src/config/theme/cssTokens.js +85 -0
  74. package/src/config/theme/themeCss.js +72 -0
  75. package/src/config/theme/themeInputs.js +155 -0
  76. package/src/config/theme/themeResolver.js +172 -0
  77. package/src/config/theme/themeSelectors.js +69 -0
  78. package/src/config/theme/themeTokens.js +257 -0
  79. package/src/config/theme/themeUtils.js +15 -0
  80. package/src/config/themeOptions.js +14 -830
  81. package/src/config/timingGapMode.js +0 -2
  82. package/src/config/uiOptions.js +53 -0
  83. package/src/data/championship.js +16 -158
  84. package/src/data/championshipDefaults.js +87 -0
  85. package/src/data/driverData.js +10 -20
  86. package/src/data/entryIdentity.js +67 -0
  87. package/src/data/entryPresentation.js +23 -0
  88. package/src/data/entryTypes.d.ts +160 -0
  89. package/src/data/index.d.ts +13 -259
  90. package/src/data/ratingScale.js +14 -0
  91. package/src/data/teamTypes.d.ts +23 -0
  92. package/src/data/trackTypes.d.ts +101 -0
  93. package/src/data/vehicleData.js +12 -23
  94. package/src/environment/actions.js +3 -2
  95. package/src/environment/controllerLoop.js +57 -44
  96. package/src/environment/controllerScheduler.js +30 -0
  97. package/src/environment/driverObservations.js +260 -0
  98. package/src/environment/driverReset.js +51 -0
  99. package/src/environment/episode.js +0 -1
  100. package/src/environment/evaluation.js +6 -90
  101. package/src/environment/evaluationTracker.js +100 -0
  102. package/src/environment/events.js +23 -0
  103. package/src/environment/index.d.ts +21 -140
  104. package/src/environment/metrics.js +3 -17
  105. package/src/environment/observationSchema.js +104 -0
  106. package/src/environment/observationVector.js +16 -115
  107. package/src/environment/observations.js +16 -316
  108. package/src/environment/options.js +5 -24
  109. package/src/environment/renderFrames.js +21 -0
  110. package/src/environment/resetOptions.js +41 -0
  111. package/src/environment/results.js +125 -0
  112. package/src/environment/rewards.js +10 -16
  113. package/src/environment/runtime.js +17 -300
  114. package/src/environment/scenarioOptions.js +90 -0
  115. package/src/environment/scenarioPlacements.js +70 -0
  116. package/src/environment/scenarioPresets.js +78 -0
  117. package/src/environment/scenarios.js +5 -236
  118. package/src/environment/scratch.js +18 -0
  119. package/src/environment/sensorOptions.js +20 -0
  120. package/src/environment/sensors/index.js +2 -556
  121. package/src/environment/sensors/indexedRayBands.js +0 -18
  122. package/src/environment/sensors/nearbyCars.js +18 -15
  123. package/src/environment/sensors/opponentRadar.js +3 -2
  124. package/src/environment/sensors/pitConnectorProximity.js +20 -0
  125. package/src/environment/sensors/rayBandTrace.js +1 -37
  126. package/src/environment/sensors/rayBatch.js +81 -0
  127. package/src/environment/sensors/rayConfig.js +26 -0
  128. package/src/environment/sensors/rayGeometry.js +0 -8
  129. package/src/environment/sensors/rayGuards.js +0 -6
  130. package/src/environment/sensors/rayOutputs.js +75 -0
  131. package/src/environment/sensors/rayQuery.js +110 -0
  132. package/src/environment/sensors/rayScratch.js +146 -0
  133. package/src/environment/sensors/sensorTargets.js +12 -4
  134. package/src/environment/sensors/surfaceRays.js +6 -61
  135. package/src/environment/sensors/trackRays.js +7 -80
  136. package/src/environment/simulationSetup.js +30 -0
  137. package/src/environment/specs.js +15 -109
  138. package/src/index.d.ts +34 -259
  139. package/src/index.js +28 -6
  140. package/src/placeholder/index.js +1 -8
  141. package/src/rendering/displayLifecycle.js +6 -0
  142. package/src/rendering/proceduralTrackAsset.js +1 -1
  143. package/src/rendering/renderSnapshot.js +3 -0
  144. package/src/rendering/track/finishLineRenderer.js +1 -1
  145. package/src/rendering/track/gridRenderer.js +1 -1
  146. package/src/rendering/track/offsetStrokeSafety.js +2 -2
  147. package/src/rendering/track/pitLaneRenderer.js +1 -1
  148. package/src/rendering/track/trackMaterialRenderer.js +4 -4
  149. package/src/rendering/track/trackRenderConstants.js +0 -1
  150. package/src/rendering/track/trackRenderGeometry.js +1 -7
  151. package/src/simulation/collisionGeometry.js +5 -11
  152. package/src/simulation/driver/advancedPathControls.js +53 -0
  153. package/src/simulation/driver/advancedRacePace.js +112 -0
  154. package/src/simulation/driver/advancedRacingControls.js +61 -0
  155. package/src/simulation/driver/advancedRacingEnvelope.js +255 -0
  156. package/src/simulation/driver/advancedRacingSteering.js +76 -0
  157. package/src/simulation/driver/advancedRacingTiming.js +16 -0
  158. package/src/simulation/driver/arcadeRacePace.js +83 -0
  159. package/src/simulation/driver/arcadeRacingControls.js +111 -0
  160. package/src/simulation/driver/arcadeRacingEnvelope.js +63 -0
  161. package/src/simulation/driver/driverControlConstants.js +0 -2
  162. package/src/simulation/driver/driverController.js +14 -3
  163. package/src/simulation/driver/edgeRecovery.js +0 -1
  164. package/src/simulation/driver/racingControls.js +10 -406
  165. package/src/simulation/driver/racingDriverProfile.js +48 -0
  166. package/src/simulation/driver/racingLinePlan.js +48 -15
  167. package/src/simulation/driver/rejoinControls.js +58 -111
  168. package/src/simulation/driver/safetyCarControls.js +12 -0
  169. package/src/simulation/driver/trafficScan.js +89 -6
  170. package/src/simulation/pit/pitCarPlacement.js +29 -0
  171. package/src/simulation/pit/pitFlow.js +8 -30
  172. package/src/simulation/pit/pitIntent.js +4 -3
  173. package/src/simulation/pit/pitOccupancy.js +2 -2
  174. package/src/simulation/pit/pitQueue.js +2 -18
  175. package/src/simulation/pit/pitRouteMovement.js +1 -36
  176. package/src/simulation/pit/pitRouting.js +5 -81
  177. package/src/simulation/pit/pitService.js +3 -32
  178. package/src/simulation/pit/pitServiceConstants.js +1 -0
  179. package/src/simulation/pit/pitServiceProgress.js +34 -0
  180. package/src/simulation/pit/pitSnapshots.js +8 -4
  181. package/src/simulation/pit/pitState.js +1 -5
  182. package/src/simulation/race/classification.js +1 -8
  183. package/src/simulation/race/raceFinish.js +3 -8
  184. package/src/simulation/race/raceOrder.js +2 -13
  185. package/src/simulation/race/raceProgress.js +6 -20
  186. package/src/simulation/race/raceSetup.js +1 -1
  187. package/src/simulation/race/raceStep.js +1 -1
  188. package/src/simulation/race/redFlag.js +2 -4
  189. package/src/simulation/race/safetyCar.js +3 -8
  190. package/src/simulation/race/stalledDnf.js +2 -4
  191. package/src/simulation/raceSimulation.js +6 -38
  192. package/src/simulation/replay/replayGhosts.js +44 -32
  193. package/src/simulation/rules/collisionSteward.js +0 -14
  194. package/src/simulation/rules/penaltyActions.js +37 -0
  195. package/src/simulation/rules/penaltyLedger.js +8 -1
  196. package/src/simulation/rules/rulesReview.js +1 -7
  197. package/src/simulation/simMath.js +4 -0
  198. package/src/simulation/snapshots/raceSnapshots.js +30 -11
  199. package/src/simulation/timing/drsState.js +8 -0
  200. package/src/simulation/timing/drsTiming.js +2 -4
  201. package/src/simulation/timing/lapTelemetry.js +7 -4
  202. package/src/simulation/timing/sectorPerformance.js +3 -3
  203. package/src/simulation/timing/timingLines.js +12 -6
  204. package/src/simulation/track/pitLaneAccess.js +2 -2
  205. package/src/simulation/track/pitLaneLayout.js +4 -135
  206. package/src/simulation/track/pitLaneModel.js +70 -0
  207. package/src/simulation/track/pitLaneState.js +0 -1
  208. package/src/simulation/track/pitServiceLayout.js +121 -0
  209. package/src/simulation/track/proceduralTrack.js +77 -0
  210. package/src/simulation/track/spatialQueries.js +1 -25
  211. package/src/simulation/track/trackBuilder.js +54 -0
  212. package/src/simulation/track/trackConstants.js +0 -22
  213. package/src/simulation/track/trackMath.js +4 -29
  214. package/src/simulation/track/trackModel.js +4 -241
  215. package/src/simulation/track/trackModelCache.js +105 -0
  216. package/src/simulation/track/trackNearestQueries.js +1218 -0
  217. package/src/simulation/track/trackQueryConstants.js +3 -0
  218. package/src/simulation/track/trackQueryConstruction.js +368 -0
  219. package/src/simulation/track/trackQueryIndex.js +12 -1933
  220. package/src/simulation/track/trackQuerySegments.js +174 -0
  221. package/src/simulation/track/trackQueryStats.js +12 -0
  222. package/src/simulation/track/trackRayQueries.js +165 -0
  223. package/src/simulation/vehicle/advancedContactResponse.js +89 -0
  224. package/src/simulation/vehicle/advancedTireForces.js +92 -0
  225. package/src/simulation/vehicle/advancedVehicleModel.js +65 -0
  226. package/src/simulation/vehicle/advancedVehiclePhysics.js +127 -0
  227. package/src/simulation/vehicle/contactResolution.js +20 -6
  228. package/src/simulation/vehicle/mainTrackWheelSurface.js +2 -13
  229. package/src/simulation/vehicle/pitWheelSurface.js +0 -12
  230. package/src/simulation/vehicle/runoffResponse.js +2 -4
  231. package/src/simulation/vehicle/sampledWheelSurface.js +266 -0
  232. package/src/simulation/vehicle/vehicleGeometry.js +0 -56
  233. package/src/simulation/vehicle/vehicleKinematics.js +10 -0
  234. package/src/simulation/vehicle/vehiclePhysics.js +35 -194
  235. package/src/simulation/vehicle/vehicleSnapshots.js +13 -4
  236. package/src/simulation/vehicle/vehicleState.js +2 -1
  237. package/src/simulation/vehicle/wheelSurface.js +13 -432
  238. package/src/simulation/vehicle/wheelSurfaceCache.js +55 -0
  239. package/src/simulation/vehicle/wheelSurfaceSummary.js +101 -0
  240. package/src/styles.css +173 -19
  241. package/src/ui/bannerTemplates.js +4 -2
  242. package/src/ui/cameraControlsTemplate.js +4 -2
  243. package/src/ui/gridWalkTemplate.js +29 -0
  244. package/src/ui/htmlEscaping.js +8 -0
  245. package/src/ui/shellTemplate.js +3 -0
  246. package/src/ui/telemetryDrawerTemplate.js +4 -2
  247. package/src/ui/telemetryTemplates.js +3 -22
  248. package/src/ui/templateUtils.js +2 -8
  249. package/src/ui/viewControlsTemplate.js +21 -0
@@ -0,0 +1,88 @@
1
+ # Skill-dependent limit driving — 2026-10-14
2
+
3
+ Work is isolated in `PaddockJS-v11-improvements`, branch `v11-improvements`, from approved v11 commit `5bd587528a1b95cd78dd77768129e71a2b09a0e6`. Original v11 remains untouched. This report follows the completed efficiency/cleanup pass; it does not replace that pass’s measured resource limitations.
4
+
5
+ ## Goal and boundaries
6
+
7
+ Built-in racers should exploit their actual vehicle’s speed, braking and handling capabilities. Ability and consistency determine control precision; risk tolerance and aggression determine willingness to use smaller margins. Strong cautious and strong aggressive drivers both exist. Risk is not skill, and incidents are not deliberately scheduled.
8
+
9
+ Vehicle force/integration equations, setup coefficients, action limits, deterministic seed ordering, model observation precision and the 330 km/h ceiling are preserved. Only racing policy, additive physical prediction/inverse helpers, normalized consistency retention, and timing-line boundary correctness change. Recovery, safety-car and pit routing retain their ownership. No host-specific behavior or new public options are introduced. Existing legacy vehicle fallbacks remain: when explicit vehicle coefficients are omitted, car creation derives power from pace and grip partly from racecraft. Use explicit vehicle entries for comparisons that must hold the car identical across skills.
10
+
11
+ ## Implementation
12
+
13
+ - `racingDriverProfile`: existing pace/racecraft → ability; consistency → bounded continuous distance-based judgement variation; aggression/risk tolerance → smaller chosen margins. No RNG calls, new per-car controller history, extra power or grip.
14
+ - `advancedRacingEnvelope`: transferred four-contact capacities, yaw-balanced limiting axle, equal rear drive and 57/43 brake allocation. Safeguarded root solving finds nonzero feasible braking windows near front-axle saturation.
15
+ - `advancedRacingSteering`: velocity-oriented pursuit and inverse nonlinear brush slip, including current-pedal front force projection. Steering remains a normal rate-limited physical wheel-angle request.
16
+ - `advancedRacingTiming` / pace: shared pursuit/yaw response; contiguous curvature preview. The braking recurrence counts only distance outside its pursuit, response, driver anticipation and one-sample reserve.
17
+ - Arcade: actual model corner and longitudinal limits plus racing-only 8–35 m smooth pursuit horizon. Arcade has no fictitious combined friction circle.
18
+ - Timing: exact forward half-open line boundaries replace a tolerance dead zone that could permanently omit a lap timestamp.
19
+
20
+ ## Verification evidence
21
+
22
+ The final source hash is `8f7349f261feda96cceb40647e645636ba270b1fb7d3ef6d151707964007c5c0`; envelope harness hash is `9d8d1d433086c97fa4c8742a4b3ed72b83b6a16ff633c97857ebe8262deeb564`. Across both modes, five profiles × six development/held-out tracks × two repeats produce **120 full three-lap solo runs: all finished, no off-road time or DNFs, all 60 repeat pairs exact**. Profiles are novice, expert, skilled-cautious, expert-risky and skilled-risky. The cautious/expert-risky pair has identical ability, consistency and vehicle coefficients; only personality changes. The less consistent skilled-risky profile is slower despite greater risk willingness.
23
+
24
+ Same-car advanced expert flying-lap means on tracks 12 / 7110 / 7203 are **138.59 → 122.11 s**, **167.50 → 147.39 s**, **103.00 → 92.49 s** (about 10–12% faster). Final novice means are 134.96 / 164.32 / 100.59 s. Cautious experts average 122.64 / 148.13 / 92.81 s; aggressive experts 121.93 / 147.15 / 92.37 s. Risk influences pace modestly and does not manufacture ability.
25
+
26
+ The six actual worn/pitting demo fields run twice in each mode: **24 final executions, all 240 car results finished without DNF, all 12 repeat pairs exact**, compared against 24 baseline executions. First-repeat results below count every field interval; off-road time uses wheel-derived `onTrack=false` outside pit routing, which differs from all-four-wheels white-line stewarding. Contacts are physical event counts, not penalty consequences.
27
+
28
+ | Mode / field | Field finish seconds, baseline → final | Off-road seconds | Contacts | Final finishers |
29
+ | --- | --- | --- | --- | --- |
30
+ | advanced / hero | 879.13 → 780.93 | 0.000 → 0.000 | 2 → 1 | 10/10 |
31
+ | advanced / components | 596.77 → 544.07 | 0.050 → 0.083 | 0 → 2 | 10/10 |
32
+ | advanced / dashboard | 524.13 → 479.13 | 0.000 → 0.100 | 0 → 1 | 10/10 |
33
+ | advanced / timing-overlay | 601.02 → 551.95 | 0.000 → 0.000 | 0 → 0 | 10/10 |
34
+ | advanced / compact-race | 483.50 → 445.15 | 0.000 → 0.117 | 1 → 2 | 10/10 |
35
+ | advanced / full-dashboard | 354.67 → 340.07 | 0.000 → 1.983 | 4 → 5 | 10/10 |
36
+ | arcade / hero | 716.78 → 658.53 | 0.050 → 0.000 | 6 → 10 | 10/10 |
37
+ | arcade / components | 500.45 → 461.40 | 2.350 → 0.000 | 8 → 12 | 10/10 |
38
+ | arcade / dashboard | 448.35 → 406.95 | 0.450 → 0.000 | 7 → 8 | 10/10 |
39
+ | arcade / timing-overlay | 493.62 → 465.40 | 0.000 → 0.000 | 5 → 12 | 10/10 |
40
+ | arcade / compact-race | 407.85 → 368.57 | 0.333 → 0.000 | 7 → 5 | 10/10 |
41
+ | arcade / full-dashboard | 313.92 → 289.62 | 1.017 → 0.533 | 6 → 3 | 10/10 |
42
+
43
+ All fields finish faster. Advanced aggregate first-repeat off-road time rises 0.050 → 2.283 s and contacts 7 → 11; arcade off-road time falls 4.200 → 0.533 s while contacts rise 39 → 50. These regressions in contacts are retained as a tradeoff; this is not a claim of universally cleaner racing. There are no scheduled accidents or forced contact effects.
44
+
45
+ A read-only advanced integrator hook observes every one of four contacts in every substep. On minimum supported Node 20.19, observed/unobserved final expert runs have identical trajectory, event and behavior hashes across three complete tracks and two repeats. Contact counts equal exactly 16 per active fixed frame. Final force equations match the prior accepted implementation exactly across 288 contact cases and 2,400 integrated car frames (hash `c42a9690aba8b69920558544f166c36fadc52fbe3f802ffbb9ec826fea8509a8`).
46
+
47
+ Phase-specific delivered forces, pedal occupancy, speed-ceiling fractions, slips and denominators are in the JSONL records. Advanced expert corner delivered combined utilization is 0.681 / 0.676 / 0.701; steady corner utilization 0.789 / 0.752 / 0.727, with short steady windows. Actual-integrator circle tests additionally verify both turn directions at 93% of physical corner speed, track within half a car width and deliver at least 90% of actual-speed turning demand. These are bounded measurements, not a global optimal-lap certificate.
48
+
49
+ ## Resource cost
50
+
51
+ Invocation-local input reuse refreshes surfaces, nominal loads, drag and rolling characteristics on every public helper call, then reuses them inside its transfer/bracket passes. Surface scans drop 60 → 4 straight, 156 → 4 mixed, 28 → 4 brake preview, and 20 → 4 corner estimation. One thousand helper cases and three tracks × 1,800 frames × four cars retain exact outputs, including immediate DRS, tire and surface changes. All 120 final solo records also have identical trajectory/event/behavior/metric hashes to the uncached candidate.
52
+
53
+ Five alternating fresh-process pairs share identical serialized real 20-car states and 2,000 production driver decisions. Median policy CPU is **124.376 → 113.352 ms** after reuse (8.86% less); wall time **89.813 → 76.958 ms** (14.31% less), with identical control hashes. The old pre-limit policy uses **43.521 ms**: the optimized advanced policy still costs **2.60×** the old policy in this fixture. These are policy-only CPU measurements, not whole browser/physics CPU or frame rate.
54
+
55
+ ## Hardware frame measurements
56
+
57
+ An isolated headed Chrome uses `ANGLE Metal Renderer: Apple M4 Pro`, fixed 1,280 × 800 viewport, DPR/renderer density 2 and identical 2,450 × 1,210 pixel canvases. Each 30-second sample uses ten cars, the complete broadcast host, same seeds/setup, a 10-second fixed-step warmup, leader camera and settled visible runtime. The initial paths differ because the driving policy changes; this is not a claim of identical post-warmup poses. No tests/field benchmarks run during frame sampling; typed-array instrumentation and CDP metrics are restored afterward.
58
+
59
+ | Mode | FPS, baseline → final | Draw p95 ms | Draw p99 ms | Mean update work ms | Draw gaps >50 ms |
60
+ | --- | --- | --- | --- | --- | --- |
61
+ | arcade1 | 58.53 → 58.49 | 23.1 → 23.6 | 25.5 → 26.1 | 0.998 → 0.911 | 0 → 0 |
62
+ | advanced1 | 58.54 → 58.60 | 23.6 → 23.4 | 25.7 → 26.1 | 0.851 → 1.379 | 0 → 0 |
63
+ | advanced10 | 58.59 → 58.59 | 20.4 → 25.8 | 26.5 → 27.9 | 2.034 → 5.150 | 0 → 0 |
64
+
65
+ FPS is maintained in the measured hardware configuration. Advanced update work rises and 10× draw tail times worsen, despite no >50 ms gaps or long tasks. No browser CPU/FPS improvement is claimed; slower devices and larger fields can expose this added controller cost. Arcade’s single paired callback decrease is not a general performance claim. The collaborative preview reports SwiftShader and is excluded from hardware timing. An off-screen probe correctly paused with zero draw frames and is excluded; the first cold baseline is retained separately, with the settled repeat used above.
66
+
67
+ ## Package and interaction gates
68
+
69
+ `npm run check` passes 81 fast files / 1,254 tests, with 93 intentional slow skips, public types, dry pack, fresh packed consumer/build, bundle boundaries, both builds, quick Chromium showcase smoke and complete demo smoke. Minimum Node20.19 passes the 74 focused new/affected tests and full observed/unobserved advanced characterization. The final standard runtime benchmark validates all 23 cases. `npm run check:release` passes all 81 exhaustive test batches / 1,347 tests, four dependency audits with zero vulnerabilities, public types, dry pack, fresh packed consumer/build, bundle boundaries, both builds, the full Chromium showcase matrix and complete demo smoke.
70
+
71
+ Native interaction verifies telemetry open/close, timing reveal, Budget Buddy selection, interval→leader gap switching and Overview camera at 390 × 844. Document width remains 390 px with all ten rows. An open telemetry drawer intentionally overlays timing controls; the interaction closes the drawer before selecting/toggling the board. Package-owned sizing is untouched. Raw successful readback is `native-interaction-verified.txt`.
72
+
73
+ All source changes precede the final gates. Subsequent edits only record evidence; final documentation and whitespace checks are rerun. Original v11 remains clean at the approved starting commit; candidate changes remain uncommitted with no upstream. No remote fetch, commit or publication occurs. Raw frozen-source experiments and final measurements are under `/tmp/paddock-v11-limit-driving-20261014/`; observational harnesses under `scripts/` are excluded from package runtime.
74
+
75
+ The release gate’s old natural-kerb assertion was found to depend on overshoot: the baseline chassis moved 2.45 m beyond its requested line before touching a kerb. The shorter pursuit follows its intended line more closely. The 90-second legal-surface and >180 kph mean-pace requirements remain; both-side public-state placement tests now directly verify two outer wheels on legal kerb, real AI/physics motion, bounded controls, speed and return to asphalt. No apex change was made solely to recreate overshoot.
76
+
77
+
78
+ ## Rejected approaches and limits
79
+
80
+ Raising the old static grip multiplier alone caused excursions/retirements. Front slip feedforward alone also failed. A shifted preview origin could skip nearby bends and accelerate into a corner; extra constant anticipation hid that defect in some solo races but did not pass full fields. The accepted preview keeps near-field constraints contiguous and reserves response distance. A tighter reserve was quicker solo but worse in traffic; an adaptive brush-slope predictor added cost and conservatism without superior field evidence.
81
+
82
+ Higher raw `gripUsage` is not proof of better delivered force. The nonlinear brush model can report demand above one before actual lateral force reaches contact capacity. Delivered utilization is measured independently from the integrator. Phase-specific steady tight-corner windows can be sparse; no claim of continuous 100% grip use or globally optimal racing lines is made. Top-speed, engine and traffic constraints also prevent a meaningful 100% grip expectation on every bend.
83
+
84
+ Arcade pursuit validation against its preceding candidate reduced six-field aggregate off-road time 46.517 → 0.533 s, all 60 cars finished, and contacts 51 → 50; combined finish times increased 2.09% and pit stops changed 19 → 22. Faster isolated laps do not automatically imply faster worn/pitting races.
85
+
86
+ No Git staging, commit, fetch, push, merge or publication has been authorized or performed. Release publishing and lock synchronization follow-ups remain separately approval-gated.
87
+
88
+ The [PaddockJS Linear project document](https://linear.app/mgiorgetti/document/v11-improvement-pass-racecraft-render-cost-and-lifecycle-reliability-b6c4a20b8501) is updated with task, solution, verification and tradeoffs; readback preserves previous content and verifies the new section. Temporary profiling servers and the isolated native QA browser are closed. The rebuilt demo stays available at `http://127.0.0.1:4181/`. Native painted-track capture: `output/playwright/limit-final-track-narrow.png`.
@@ -0,0 +1,146 @@
1
+ # Maintainability audit — 2026-09-08
2
+
3
+ This records the initial pass and its original evidence. The subsequent repository-wide review, resolved follow-ups, final verification, and current Linear status are in [cleanup coverage](cleanup_coverage.md). Counts, locations, and deferred decisions below describe that earlier baseline.
4
+
5
+ ## Scope and baseline
6
+
7
+ This is a bounded audit of package entry points, data/configuration, environment input boundaries, pit and vehicle snapshot assembly, runtime/readout loops, sensor infrastructure, selected tests, and documentation. It is not a claim that every module is clean. Existing product behavior, supported exports, sensor precision, snapshot ownership, deterministic stepping, lifecycle recovery, and timing-board sizing must remain unchanged.
8
+
9
+ Initial checkout: `v11` at `fedff4e`, tracking the locally recorded `origin/v11` at the same commit. No fetch was performed. There were 55 modified tracked files and 11 untracked top-level status entries, including substantial ongoing runtime, sensor, API, test, documentation, and demo work. The initial contents of 376 tracked/untracked files, their SHA-256 hashes, status, and binary Git diff were saved outside the repository in `/tmp/paddockjs-audit-20260908/` before any edits. Changes described here are relative to that working-tree baseline, not relative to HEAD.
10
+
11
+ Baseline `npm run check`: **passed**, including 44 fast test files, 846 passing tests and 78 intentionally skipped tests, public types, dry pack, packed consumer install/build and subpath bundle boundaries, showcase/demo builds, quick Chromium smoke, and desktop/mobile demo smoke. Existing build warnings about large chunks were present; no baseline gate failure was observed. Baseline log: `/tmp/paddockjs-audit-20260908/baseline-check.log`.
12
+
13
+ ## Checkable plan
14
+
15
+ - [x] Preserve the initial file contents and inspect read-only Git state.
16
+ - [x] Read supported exports, architecture, contracts, and verification commands; run the baseline gate.
17
+ - [x] Audit candidate defects and check internal, dynamic, type, documentation, and local portfolio consumer references.
18
+ - [x] Define bounded fixes and ownership before implementation (below).
19
+ - [x] Collect three standard runtime benchmark runs before implementation.
20
+ - [x] Apply dead-code and stale-documentation cleanup first.
21
+ - [x] Consolidate pit-intent policy, pit snapshot ownership, and participant validation.
22
+ - [x] Add meaningful boundary and snapshot ownership characterization; keep existing assertions.
23
+ - [x] Run final `npm run check` and `npm run check:release`.
24
+ - [x] Repeat the same standard runtime benchmark three times and report noise separately from cleanup; additionally alternate three baseline/current pairs to control for observed timing drift.
25
+ - [x] Log task, solution, verification, and remaining concerns in the PaddockJS Linear project (completed during the continuation).
26
+ - [x] Compare final files against the saved baseline and report read-only Git status.
27
+
28
+ ## Verified findings selected for cleanup
29
+
30
+ Locations in this section refer to the saved pre-edit baseline. Each finding was checked as a hypothesis before selection.
31
+
32
+ | ID | Exact evidence and unnecessary cost | Smallest coherent fix | Compatibility risk and verification |
33
+ | --- | --- | --- | --- |
34
+ | F1 | `src/config/themeOptions.js:370-383`: `deriveDarkColor`, `deriveLightColor`, and `resolveModePair` forward fixed primary-token arguments to existing implementations. No code, dynamic import, type, supported export, documentation, or local portfolio source consumer references them. Three unused internal exports suggest alternate theme APIs without providing a boundary. | Remove the three wrappers; retain active token derivation and every supported theme alias. | Unsupported source imports outside the audited workspace cannot be disproved. Public types, theme tests, packed consumers, and browser checks cover supported usage. |
35
+ | F2 | `src/data/championship.js:243` builds `CHAMPIONSHIP_PROJECT_DRIVERS` eagerly; only `src/__tests__/championship.test.js:5,16-29,89` reads it. Package exports and declarations do not expose it. Production import initialization owns a fixture it never uses. | Construct the default grid in the test file and remove the internal fixture export. Keep the default builder and entry data unchanged. | Preserve all existing championship assertions and verify data subpath consumers. This removes unused initialization; no startup speed claim is made. |
36
+ | F3 | `src/simulation/raceSimulation.js:392-394` exposes `vehicleSnapshotDependencies()` with no callers. Actual snapshot functions call their factory directly. Neither the class nor this method is a supported export. | Remove the unused facade method and its otherwise unused factory import. | Check all snapshot variants and packed consumers. Do not remove the factory used by snapshot assembly. |
37
+ | F4 | `src/simulation/pit/pitFlow.js:4` imports `normalizePitIntent` without reading it. | Remove that binding only. | No changed execution; package gate verifies module loading. |
38
+ | F5 | `src/environment/actions.js:56-60` duplicates the exact numeric conversion and integer range `0..2` from `src/simulation/pit/pitIntent.js:16-20`. Two owners can drift. | Use the canonical pit normalizer and test for `!= null`, retaining valid zero. | Preserve coercion, omitted-field handling, compound validation, strict/report errors, and their ordering. Exercise accepted/coerced/rejected inputs through `resolveActionMap`. |
39
+ | F6 | `src/simulation/pit/pitSnapshots.js:16,50` requests a normalizer and default constant as injected arguments; its only callers at `src/simulation/snapshots/raceSnapshots.js:41-46` always pass identical pit-owned values through closures. The assembly layer must know and repeat pit policy. | Import the existing policy in pit snapshots and pass the serializers directly from race assembly. | Preserve full/observation/render/training shapes, null/nonfinite defaults, and copied mutable arrays/profile objects. Verify through real simulation snapshots. |
40
+ | F7 | `src/environment/options.js:62-68` creates a second participant ID set and checks membership already proved by `resolveScenario` at `132-136`. `all` and `controlled-only` include already validated controlled IDs by construction at `145-148`. | Remove the second set and loop; retain the earlier validation owner. | Test all participant modes, duplicate IDs, unknown IDs, missing controlled IDs, and error precedence. No stricter input rules or changed defaults. |
41
+ | F8 | `docs/data_model.md:97` calls `tireCare` reserved, but both vehicle integrators divide wear by it at `src/simulation/vehicle/vehiclePhysics.js:196-197,375-377`. Constructor-output examples at `53-66,99-113` omit current `customFields`. | Correct the active behavior description and output examples. | Documentation only; compare with implementations and run the docs checker. |
42
+
43
+ ## Ownership and data flow before refactoring
44
+
45
+ F1–F4 remove paths without a runtime owner or caller; no replacement abstraction is needed. Championship tests own their fixture, while the public builder continues to own normalization.
46
+
47
+ For F5, `pitIntent.js` owns numeric pit intent values and coercion. `actions.js` owns external action presence, driver identity, required controls, compound shape, and strict/report error handling. Input is an optional action field; output is a normalized intent or the existing error. Simulation receives the same numeric value or intent/compound object. Invalid integer range and nonfinite inputs remain failures; coercible zero remains valid. No simulation or app object crosses this boundary.
48
+
49
+ For F6, pit snapshot serializers own pit field selection, fallback values, and copies of mutable pit state. Their sole input is a pit-stop state object; their output is the requested public pit snapshot variant. They depend on the existing pit normalizer/default and finite-number serializer. Race snapshot assembly owns selecting cars and constructing the overall snapshot, and vehicle serializers continue selecting the pit snapshot variant. Existing broader vehicle dependency injection is retained in this bounded change; no new dependency cycle or generic service is introduced. Missing pit state remains `null`; nonfinite service values remain `null`; returned penalty ID arrays and top-level profile objects must not alias live pit state. Existing nested pit-crew metadata is shared; this cleanup does not change that ownership.
50
+
51
+ For F7, the environment option boundary validates controlled driver IDs first, then scenario membership/placements, then filters normalized drivers. `resolveScenario` is the only owner of explicit participant-list membership validation. The return shape and validation order remain unchanged. Default participant modes require no second validation because their construction proves membership.
52
+
53
+ ## Findings retained or deferred
54
+
55
+ - **Dependencies:** all declared dependencies have identifiable runtime, verification, or release consumers. No unused dependency was established; no upgrades are proposed.
56
+ - **Compatibility paths:** track, vehicle, driver, sensor, and UI barrels still have active imports. Their small size is not evidence of a defect. Supported legacy theme aliases remain contracts.
57
+ - **Shared rating conversion:** `src/data/driverData.js:3-25` and `src/data/vehicleData.js:3-27` duplicate rating limits and conversion. A focused rating-scale owner is plausible, but vehicle direction and domain-specific error strings must remain distinct. Maintenance cost is modest, so defer instead of expanding this change. Verify coercion, clamping, defaults, nonfinite input, and inverse direction before consolidation.
58
+ - **Asset error scope:** `src/app/rendering/appAssets.js:3-10` catches both asset loading and texture configuration failures. Returning `Texture.WHITE` intentionally recovers from missing assets, but also hides configuration faults. Separating those failure modes would change initialization behavior; characterize both and obtain a behavior decision before changing it.
59
+ - **Intentional error containment:** environment external-renderer callbacks, host lifecycle callbacks, controller-loop scheduling, and external-renderer state reporting provide deliberate failure boundaries. Their catches are not removed. Warmup is best effort and its failure path preserves normal execution.
60
+ - **Nested snapshot ownership:** `src/simulation/pit/pitSnapshots.js:37` shallow-copies `serviceProfile`, while `src/simulation/pit/pitServiceProfile.js:20` includes a nested `pitCrew` object. The snapshot therefore retains that nested reference. Tests exercise a real generated service profile and verify top-level isolation only. Clarify the intended nested ownership contract before adding deeper cloning; no snapshot ownership change is bundled here.
61
+ - **Whole-runtime dependencies:** `src/app/runtime/frameLoop.js:12` and pit orchestration consume broad mutable owners. Moving their methods into helpers with the same app/simulation object would not reduce coupling. The pit snapshot adapters are a smaller demonstrated ownership problem that can be corrected now.
62
+ - **Tests:** `src/__tests__/componentApi.test.js:1611-1617,1864-1870,2059-2068` includes source-text assertions coupled to spelling, but they guard documented module boundaries. Replacing them requires equivalent import-graph or behavior checks; deleting them would remove coverage. Large test files alone do not justify splitting.
63
+ - **Documentation:** architecture and sensor contract passages repeat detailed hot-path information, but distinguish ownership from externally observable precision. No broad prose rewrite is justified without checking every corresponding claim. Historical design plans are not authoritative runtime contracts.
64
+
65
+ ## Performance audit and measurement protocol
66
+
67
+ Inspect existing runtime benchmarks across simulation phases, pit routing, collision, track queries, road/surface/recovery rays, wheel surfaces, environment stepping, snapshots/JSON, policy JSON, render interpolation, and DOM readouts. Run `node scripts/benchmark-runtime-efficiency.mjs --profile=standard --verify --json` three times before and three times after, sequentially without concurrent package gates. Keep the existing benchmark code, seeds, settings, and operation counts identical. Record raw JSON under `/tmp/paddockjs-audit-20260908/{before,after}-{1,2,3}.json`.
68
+
69
+ Environment: Node `v24.13.0`, arm64 macOS `27.0` build `26A5421a`. Wall-clock timings include normal local-machine noise and fixture setup. Compare per-operation medians and ranges; retain deterministic counters/checks. These runs characterize structural cleanup, not a controlled claim about a specific optimization.
70
+
71
+ Representative browser workloads are the existing quick/full showcase smoke matrix and product demo smoke, covering mounted/composable lifecycle, expert/headless flows, readouts, presets, and desktop/mobile sizing. They verify behavior rather than establish browser latency gains. The benchmark DOM workload uses a test DOM, so do not describe its timings as real-browser rendering performance.
72
+
73
+ Hot-path decisions: retain frame pacing, throttled DOM updates, separate render/full snapshots, sensor scratch reuse, track query indexing, precision-aware ray fallback, and timing-row reconciliation. The frame loop at `src/app/runtime/frameLoop.js:43-68` already avoids most full snapshots; `src/app/readouts/timingTowerRenderer.js` reuses row DOM. Repeated overview key construction in `src/app/readouts/carOverviewRenderer.js:61-84` is a candidate only if a real-browser profile identifies it as material. No new cache, pooling, precision change, or algorithmic optimization is planned.
74
+
75
+ ## Results and work log
76
+
77
+ F1–F8 are implemented. The audit added 32 characterization tests for action coercion/errors, participant modes/error precedence, and real simulation snapshot fields/copy ownership. They pass against the original implementation and the cleanup; the real generated-service-profile fixture was also checked independently against both trees. Existing championship assertions remain intact. Independent review of the input/pit/snapshot delta found no actionable issue.
78
+
79
+ Verification:
80
+
81
+ - Baseline `npm run check`: passed (846 tests; 78 intentionally skipped).
82
+ - Final `npm run check`: passed (878 tests; 78 intentionally skipped).
83
+ - `npm run check:release`: passed (956 tests across 47 test batches, public types, dry pack, packed consumer build/subpath boundaries, showcase/demo builds, full Chromium showcase matrix and demo smoke).
84
+ - Full browser matrix: loading overlays, desktop/mobile/tablet and timing breakpoints, composable components, customization, API, playable, Policy Runner, behavior, stewarding, and collision lab passed. Demo desktop/mobile runtime, public surfaces, presets, expert/headless, and search passed.
85
+ - Exact serialized environment output matches between the saved baseline and current source for seed `71`, track seed `2097`, full/vector/object observation modes, reset, 60 steps per mode with frame skip 4, and final state. Combined SHA-256: `4ea290b6504cfe3b4903de58baab9e2eb32ff979255a393628e00ee28eb4b06d`.
86
+ - `git diff --check`: passed. No pre-existing gate failures were found. Existing chunk-size build warnings remain.
87
+
88
+ Logs and comparison scripts are in `/tmp/paddockjs-audit-20260908/`; these are local temporary evidence, not published assets. `audit-only.patch` isolates this task from the larger uncommitted tree. The exhaustive gate was run because the cleanup crosses environment and simulation snapshot boundaries; no portfolio integration source was changed.
89
+
90
+ ### Measurement result
91
+
92
+ The first consecutive before/after groups suggested a roughly one-third speedup even in untouched algorithms. That was not credible evidence of a cleanup benefit. The measurement plan was revised to alternate the preserved baseline and current source in fresh Node processes, using the same installed dependencies without creating a Git worktree or changing either benchmark harness. Three pairs ran after the gates finished. Simulation uses seed `71` and the benchmark's explicit canonical `TRACK`; environment settings and operation counts are unchanged.
93
+
94
+ All 22 workload identities, operation counts, and non-timing checks match across the six paired runs. Before/after ranges overlap for every workload. No material performance gain is established, and no hot-path optimization was introduced. The table reports milliseconds per benchmark-defined operation; the DOM workload is synthetic, not browser paint latency. Browser smoke supplies behavior evidence only.
95
+
96
+ | Workload | Before median [min, max] ms/op | After median [min, max] ms/op |
97
+ | --- | ---: | ---: |
98
+ | simulation.step advanced field | 0.032442 [0.031945, 0.034029] | 0.031913 [0.031660, 0.033126] |
99
+ | simulation phase profile | 0.355519 [0.351087, 0.357263] | 0.350887 [0.348334, 0.355748] |
100
+ | timing history and line maintenance | 0.000122 [0.000121, 0.000128] | 0.000122 [0.000117, 0.000129] |
101
+ | timing-line gap without stored crossings | 0.000054 [0.000054, 0.000055] | 0.000057 [0.000054, 0.000061] |
102
+ | lap telemetry in-progress sync | 0.000153 [0.000148, 0.000164] | 0.000154 [0.000154, 0.000155] |
103
+ | pit route transition geometry | 0.000600 [0.000590, 0.000645] | 0.000613 [0.000612, 0.000621] |
104
+ | collision candidate and narrowphase | 0.014346 [0.014100, 0.014780] | 0.014325 [0.014252, 0.014630] |
105
+ | nearest track query index | 0.002226 [0.002203, 0.002256] | 0.002278 [0.002214, 0.002325] |
106
+ | sensor ray road and surface channels | 0.032712 [0.032159, 0.033753] | 0.032801 [0.032604, 0.035977] |
107
+ | batch-training sensor surface channels | 0.016548 [0.016198, 0.017499] | 0.016499 [0.015432, 0.022635] |
108
+ | sensor ray barrier illegal-surface validation | 0.042978 [0.042229, 0.044926] | 0.040824 [0.040024, 0.042457] |
109
+ | sensor ray barrier off-track recovery | 0.056817 [0.054710, 0.057457] | 0.053189 [0.052965, 0.059095] |
110
+ | sensor ray pit-lane direct boundary | 0.014867 [0.013823, 0.018707] | 0.014279 [0.013579, 0.015012] |
111
+ | wheel surface near pit connector | 0.012874 [0.012743, 0.013432] | 0.012937 [0.012330, 0.014278] |
112
+ | wheel surface connector local-refresh path | 0.003203 [0.002642, 0.003578] | 0.002867 [0.002862, 0.003264] |
113
+ | wheel surface main-track analytic | 0.002045 [0.001932, 0.002120] | 0.002089 [0.001967, 0.002196] |
114
+ | headless environment vector step | 0.051907 [0.050513, 0.087385] | 0.050693 [0.050625, 0.051605] |
115
+ | snapshot construction | 0.018195 [0.017968, 0.018811] | 0.018014 [0.017356, 0.018649] |
116
+ | snapshot JSON serialization | 0.231152 [0.230037, 0.235442] | 0.234313 [0.231366, 0.235079] |
117
+ | policy server compact JSON transport | 0.056871 [0.056494, 0.059002] | 0.057974 [0.054731, 0.058445] |
118
+ | render snapshot interpolation | 0.000570 [0.000563, 0.000624] | 0.000626 [0.000610, 0.000678] |
119
+ | timing tower row markup | 0.003913 [0.003845, 0.004045] | 0.003741 [0.003425, 0.004084] |
120
+
121
+ Raw paired results: `/tmp/paddockjs-audit-20260908/paired-{before,after}-{1,2,3}.json`. The initial six results are retained separately as `before-*.json` and `after-*.json` so the timing drift is auditable.
122
+
123
+ ### Changed file inventory
124
+
125
+ This task changed 11 existing files:
126
+
127
+ - `src/config/themeOptions.js`: remove unused internal theme wrappers.
128
+ - `src/data/championship.js`, `src/__tests__/championship.test.js`: relocate the test-only default grid fixture.
129
+ - `src/environment/actions.js`: consume canonical pit-intent normalization.
130
+ - `src/environment/options.js`: remove redundant participant validation.
131
+ - `src/simulation/pit/pitFlow.js`: remove unused import.
132
+ - `src/simulation/pit/pitSnapshots.js`, `src/simulation/snapshots/raceSnapshots.js`: put pit serialization policy in the pit module and remove fixed adapters.
133
+ - `src/simulation/raceSimulation.js`: remove unused snapshot dependency facade method.
134
+ - `docs/architecture.md`, `docs/data_model.md`: document actual ownership and data behavior.
135
+
136
+ Four files were added: this report and `src/__tests__/environmentPitActions.test.js`, `src/__tests__/environmentParticipants.test.js`, and `src/__tests__/pitSnapshots.test.js`.
137
+
138
+ Preservation check: 365 of the 376 baseline files remain byte-identical. The other 11 were reviewed against the saved contents; existing edits in the three overlapping dirty files (`themeOptions.js`, `options.js`, and `architecture.md`) were preserved. Initial untracked work, package exports/types, dependency versions, benchmark harnesses, and browser implementation remain unchanged by this task.
139
+
140
+ Read-only final Git state: branch `v11`, HEAD `fedff4e`, locally recorded upstream `origin/v11`, ahead/behind `0/0` without fetching. There are 63 modified tracked files, 15 untracked status entries (including pre-existing directory entries), and no staged changes. No Git/GitHub mutation was performed. Proposed next step is review of the audit-only diff; any later staging, commit, branch, or push requires separate approval of exact commands and targets.
141
+
142
+ ### Initial Linear logging blocker (resolved)
143
+
144
+ The required Linear work log could not be posted. The official connector returned `UNAUTHORIZED` / reauthentication required; the prescribed `mcp-remote` route opened authorization and waited for sign-in before timing out. A reauthentication request was sent to the user during local work. The task summary, implementation rationale, verification, and remaining concerns are preserved here and in `/tmp/paddockjs-audit-20260908/linear-work-log.md`, ready to log in the PaddockJS project once authentication is restored. No Linear write is claimed.
145
+
146
+ Authentication was restored during the continuation. Both passes are logged in the [PaddockJS audit document](https://linear.app/mgiorgetti/document/2026-09-08-repository-cleanup-audit-14d678a1a82c). Shared ratings and nested snapshot ownership were resolved, asset recovery was characterized and retained, and repository-wide dispositions are recorded in the current coverage report.
@@ -0,0 +1,145 @@
1
+ # Racing-driver AI improvements: arcade and advanced
2
+
3
+ ## Goal and acceptance
4
+
5
+ Improve both built-in drivers relative to the September 9 advanced-AI closeout. Measure braking, corner exit and traffic decisions under unchanged physics. Preserve arcade defaults, public actions/observations, deterministic stepping, recovery, pits and package layout. Faster solo driving is insufficient if representative full fields become substantially less reliable. No claim of globally optimal driving.
6
+
7
+ ## Checkable plan
8
+
9
+ - [x] Preserve a source snapshot and inspect current dirty Git state and driver ownership.
10
+ - [x] Complete baseline package gate and matched solo/full-field measurements for both modes.
11
+ - [x] Diagnose concrete pace losses; compare bounded independent candidates in isolated source copies.
12
+ - [x] Select changes on lap times, contacts, off-road time and finish rate; reject fragile gains.
13
+ - [x] Integrate feature-owned controls, meaningful production regressions and authoritative docs.
14
+ - [x] Repeat accepted races, compare unchanged raw physics, measure CPU cost with paired existing benchmarks.
15
+ - [x] Pass package/release/browser/packed-consumer gates; update Linear and report read-only Git status.
16
+
17
+ ## Ownership and design gate
18
+
19
+ `driver/racingControls.js` dispatches modes and preserves its existing internal exports. Arcade `arcadeRacingControls.js` owns target-line composition, geometric steering, edge guarding and pedals; `arcadeRacePace.js` owns preview and corner-line planning. `driverController.js` owns the backward-facing recovery transition. Advanced `advancedRacingControls.js` composes geometric steering, existing traffic planning and `advancedRacePace.js` speed envelopes; `advancedPathControls.js` also serves recovery/safety driving, which must remain stable. `racingLinePlan.js` owns shared overtaking intentions. Vehicle modules exclusively own physical forces/integration and the analytic arcade tarmac corner-capacity estimate; physical laws and constants are not tuning targets.
20
+
21
+ Inputs are track geometry, vehicle capability/state, existing traffic and racing intentions. Outputs remain bounded steering/throttle/brake. Candidate logic must have a narrow feature owner, no whole-app helper or hidden persistent state. The racing-driver hypotheses are braking too early or too late, unnecessary coasting, failing to unwind steering on exit, and confusing overtaking intention with available space. Each must be supported by simulation traces before adoption.
22
+
23
+ Risks: corner-entry understeer, exit oversteer, oscillatory controls, unsafe passing, tire wear, pit-coordinate mismatches and procedural-track overfitting. Evaluate development and held-out tracks, complete ten-car races with wear/pits, recovery regressions and deterministic repeats. Any structural or behavior change requires evidence and matching documentation.
24
+
25
+ ## Baseline and artifacts
26
+
27
+ Baseline source: `/tmp/paddockjs-racing-ai-20260909/baseline`. Earlier ongoing work, including the first advanced AI improvement, is preserved. No Git/GitHub mutations are authorized or performed.
28
+
29
+ ## Verified findings and candidate decisions
30
+
31
+ - Arcade speed preview (`driver/racingControls.js`): the sharpest future curvature became the current corner target, ignoring braking distance. In track 20260427, the car slowed from 283 km/h at 239 m to 151 km/h at 432 m while the road was still straight; the first bend began around 540 m. A distance-aware envelope avoids unnecessary early braking while retaining conservative reaction distance.
32
+ - Arcade steering combined target-point angle, future-heading feedforward and lateral correction. On track 7110 at 1319 m, the target required negative steering, but the combined controller commanded positive steering before any tire saturation. Pure pursuit inverted through arcade's own bicycle yaw relation points toward the intended path and compensates tire condition, avoiding contradictory corrections.
33
+ - Arcade corner targets barely responded to tire wear. Its physical lateral capacity scales static grip with tire factor squared and downforce with tire factor. Worn tires therefore require much lower corner speeds than the old 96 km/h corner floor. The driver must respect a physical ceiling after intentional pace floors and DRS bonuses.
34
+ - Baseline arcade full fields finished 44/60: all 16 retirements were stalled off track. Worn-tire gravel drive capacity can be lower than rolling resistance even at maximum drive, so simply raising recovery throttle cannot fix these departures. The accepted direction prevents avoidable departures instead of altering physics.
35
+ - Advanced: tighter/longer geometric pursuit and a corner-profile offset did not give useful repeatable gains. Aggressively later braking was faster alone but slower and less clean in traffic. These variants are rejected. The accepted advanced change restrains lateral lane movement under corner load, releasing it on exit. Combined with a modest braking-preview reserve change from 50% to 55%, it improves solo pace and field reliability; the 60% corner reserve, steering model and recovery controls remain unchanged.
36
+
37
+ Baseline `npm run check` passed with 1043 fast tests and 88 slow skips, plus types, packing, consumer/build and browser gates. There were no pre-existing gate failures. Both modes completed all 16 wear-disabled solo stints. Arcade accumulated 273.733 seconds off road; advanced had zero. Advanced baseline full fields finished 60/60.
38
+
39
+ ## Accepted implementation and limits
40
+
41
+ Arcade uses inverse bicycle-model pursuit with tire-condition compensation, a 12 m sampled speed preview and conservative braking/reaction distance. Existing rating, aggression, DRS, edge and traffic inputs remain, but they cannot exceed the worn-tire corner ceiling. The old generic control profile and discarded additive steering calculations were removed. Recovery handles backward-facing placements; it does not alter the physical ability to escape a surface.
42
+
43
+ Advanced keeps the existing pursuit model and following-distance safety. Its selected lane target interpolates from the actual chassis center toward the planned lane according to unused cornering budget, preventing abrupt lateral moves while heavily loaded. The braking preview uses 55% of estimated available capacity after lateral demand, still below the longitudinal control limit. The shared 60% racing corner reserve remains unchanged. There are no persistent new state owners, caches, added grip, position corrections or public API changes.
44
+
45
+ Both controllers remain deterministic heuristic drivers. Results do not establish global optimality or guarantee clean racing on every procedural track, setup or user placement. Nonzero contacts and brief field excursions remain. Arcade's physical worn-tire gravel stall limitation is unchanged.
46
+
47
+ ## Driving measurements
48
+
49
+ Same Node v24.13.0, Darwin arm64, fixed 1/60 s step, seeds, tracks, drivers, entries and rules before/after. Solo tests use race seed 100, one bundled driver, three laps, no standing-start sequence and tire wear disabled. Flying time is the mean of laps two and three. The first eight tracks are development cases; the remaining eight are held-out cases. All 32 final solo runs finish without off-road time or DNFs.
50
+
51
+ | Track seed | Arcade before (s) | Arcade after (s) | Quicker | Advanced before (s) | Advanced after (s) | Quicker |
52
+ | --- | ---: | ---: | ---: | ---: | ---: | ---: |
53
+ | 7109 | 137.150 | 123.317 | 10.09% | 144.167 | 143.550 | 0.43% |
54
+ | 7110 | 173.533 | 138.183 | 20.37% | 168.150 | 167.050 | 0.65% |
55
+ | 7200 | 149.911 | 129.508 | 13.61% | 150.284 | 149.227 | 0.70% |
56
+ | 7201 | 161.142 | 136.633 | 15.21% | 169.517 | 168.683 | 0.49% |
57
+ | 12 | 138.833 | 122.031 | 12.10% | 139.349 | 138.300 | 0.75% |
58
+ | 26 | 131.171 | 107.467 | 18.07% | 123.000 | 122.083 | 0.75% |
59
+ | 61 | 178.065 | 148.900 | 16.38% | 179.783 | 178.733 | 0.58% |
60
+ | 20260427 | 151.693 | 132.901 | 12.39% | 155.567 | 154.983 | 0.37% |
61
+ | 28 | 167.533 | 140.450 | 16.17% | 176.150 | 174.817 | 0.76% |
62
+ | 62 | 161.783 | 136.908 | 15.38% | 161.267 | 160.250 | 0.63% |
63
+ | 69 | 147.695 | 131.817 | 10.75% | 158.598 | 157.742 | 0.54% |
64
+ | 7202 | 141.001 | 117.417 | 16.73% | 138.433 | 137.667 | 0.55% |
65
+ | 7203 | 104.985 | 96.867 | 7.73% | 104.033 | 102.988 | 1.00% |
66
+ | 101 | 134.817 | 118.967 | 11.76% | 136.767 | 136.267 | 0.37% |
67
+ | 9099 | 182.923 | 156.383 | 14.51% | 199.017 | 198.400 | 0.31% |
68
+ | 12345 | 153.847 | 127.745 | 16.97% | 149.667 | 148.783 | 0.59% |
69
+
70
+ Full fields use the six actual demo configurations with ten driver/entry pairs, normal tire wear, pits and interactions. Hero runs five laps; others run three. **Arcade baseline retires 16 cars, so its field-duration differences are not equal-completion race comparisons.** Finish counts, incidents and clean solo pace must be considered together.
71
+
72
+ ### Arcade full fields
73
+
74
+ | Field | Finishers before → after | Last finish before → after (s) | Mean finish before → after (s) | Contacts | Off-road (car-seconds) |
75
+ | --- | ---: | ---: | ---: | ---: | ---: |
76
+ | hero | 8 → 10 | 796.733 → 724.667 | 776.554 → 701.100 | 82 → 50 | 279.933 → 0.000 |
77
+ | components | 7 → 10 | 627.967 → 501.733 | 584.274 → 482.592 | 73 → 65 | 542.517 → 2.467 |
78
+ | dashboard | 5 → 10 | 530.417 → 445.800 | 503.560 → 433.562 | 70 → 43 | 371.350 → 0.000 |
79
+ | timing-overlay | 6 → 10 | 618.467 → 497.467 | 568.528 → 479.483 | 82 → 52 | 381.100 → 0.000 |
80
+ | compact-race | 8 → 10 | 509.283 → 407.633 | 478.856 → 393.245 | 75 → 57 | 228.617 → 0.167 |
81
+ | full-dashboard | 10 → 10 | 350.583 → 329.283 | 336.478 → 311.360 | 57 → 38 | 79.733 → 1.067 |
82
+
83
+ Total finishers: 44/60 → 60/60. Contacts: 439 → 305. Aggregate off-road time: 1883.250 → 3.700 car-seconds.
84
+
85
+ ### Advanced full fields
86
+
87
+ | Field | Finishers before → after | Last finish before → after (s) | Mean finish before → after (s) | Contacts | Off-road (car-seconds) |
88
+ | --- | ---: | ---: | ---: | ---: | ---: |
89
+ | hero | 10 → 10 | 864.083 → 887.817 | 846.897 → 839.533 | 10 → 12 | 5.650 → 0.000 |
90
+ | components | 10 → 10 | 601.567 → 597.350 | 590.820 → 586.737 | 7 → 3 | 0.100 → 0.300 |
91
+ | dashboard | 10 → 10 | 532.883 → 528.933 | 520.068 → 516.378 | 5 → 1 | 0.000 → 0.467 |
92
+ | timing-overlay | 10 → 10 | 609.700 → 604.583 | 595.245 → 591.433 | 6 → 3 | 0.100 → 0.767 |
93
+ | compact-race | 10 → 10 | 491.167 → 486.567 | 478.878 → 475.007 | 7 → 3 | 0.000 → 0.433 |
94
+ | full-dashboard | 10 → 10 | 370.817 → 356.183 | 353.282 → 345.350 | 9 → 6 | 3.917 → 0.000 |
95
+
96
+ Total finishers: 60/60 → 60/60. Contacts: 44 → 28. Aggregate off-road time: 9.767 → 1.967 car-seconds.
97
+
98
+ Advanced mean finishing times improve in every field, but hero's last-car completion is 2.75% slower (864.083 → 887.817 s). This is an explicit tradeoff, not a universal race-duration improvement. Five other fields finish sooner. The tight full-dashboard field improves from 370.817 to 356.183 s. Arcade's baseline means include only its surviving finishers; they are shown for context rather than treated as a matched population speed claim.
99
+
100
+ ## Measurement integrity
101
+
102
+ The two existing AI harnesses now accept validated `--physics-mode arcade|advanced`; advanced remains the default for existing invocations. Solo records include source fingerprints. Field benchmark v2 derives lap intervals from canonical timing-line crossings, because pit movement can advance completed-lap counters before `lastLapTime` updates. Each finished car's lap intervals reconcile with its finish time within one fixed step. Completed pit exits are read from `pitStop.stopsCompleted` and checked against pit-exit events; pit service completion is a separate event. This corrects reporting only and leaves trajectory/event hashes unchanged.
103
+
104
+ All final solo trajectories match the accepted isolated candidates exactly. Both modes' six full fields are repeated twice with exact deterministic result hashes. Source fingerprint for the final simulation/data tree: `29c71119c480dfca686dc479545ad4b7e4098af9738c63e85100067ba83a6998`.
105
+
106
+ ## Verification and runtime cost
107
+
108
+ - Baseline package gate passed without pre-existing failures.
109
+ - Focused AI suite: 44 passed, including worn-tire/DRS/braking/steering/wrong-way cases, loaded-corner lane restraint, clean stints and complete fields. Existing advanced full-field assertions were strengthened.
110
+ - An initial release run failed the old assertion that a particular 30-second approach must reach over 7 m lateral offset. The new faster line reaches 6.181 m there, but reaches 8.085 m on the tight demo circuit with legal kerb use. The original pace fixture and all its speed/off-road thresholds remain; the unchanged 7 m threshold now has a dedicated 90-second tight-circuit test, additionally requiring actual kerb contact, legal surfaces and average speed above 180 km/h. All 10 driver-controller tests passed after this coverage separation; no runtime change or relaxed numeric threshold was used to pass it.
111
+ - Raw physics: 216 combinations across both modes, three surfaces, three tire states, three speeds and four control patterns, each integrated for 120 steps. Complete vehicle states match baseline exactly.
112
+ - Package `npm run check` passed on the final runtime source: 1051 fast tests, 92 slow skips, docs, public types, dry pack, packed-consumer install/build and bundle checks, showcase/demo builds, quick Chromium and demo smoke. Final `npm run check:release` passed with all 1144 tests across 62 files, public types, pack/consumer/build checks, the full Chromium matrix and demo smoke (desktop runtime, public surfaces, presets, expert, headless, search and mobile layout).
113
+ - Twelve paired runs (two batches of six, alternating before/after order) of all 23 standard runtime workloads passed `--verify`. Same Apple M4 Pro host, Node v24.13.0 and settings; our test/benchmark processes were otherwise stopped. The unchanged local-preview source dependency was copied into the frozen baseline to run the common harness. The measured field workloads include setup, instrumentation and 180 steps for 16 cars; these are not browser frame timings.
114
+
115
+ | CPU workload | Before median (ms) | After median (ms) | Before range (ms) | After range (ms) |
116
+ | --- | ---: | ---: | ---: | ---: |
117
+ | Arcade field | 46.916 | 52.846 | 45.239–69.124 | 50.845–154.979 |
118
+ | Advanced field | 174.944 | 163.604 | 167.632–250.340 | 159.241–400.565 |
119
+ | Headless vector | 140.565 | 134.068 | 132.149–163.235 | 127.945–275.706 |
120
+
121
+ Arcade has a consistent planning cost: the two batch median comparisons are +13.26% and +13.11%; the pooled comparison is +12.64% (about 5.93 ms per whole field workload). Advanced's batch signs disagree (+17.38% versus −7.17%), with overlapping ranges/outliers; the pooled −6.48% median is **not a reliable throughput improvement claim**. The headless-vector batches likewise disagree. No CPU speedup is claimed or speculative cache introduced. All raw runs and per-workload comparisons remain in the task artifacts.
122
+
123
+ ## Changed files and closeout
124
+
125
+ Runtime: `src/simulation/driver/racingControls.js`, new `arcadeRacingControls.js` and `arcadeRacePace.js`, `driverController.js`, `advancedRacingControls.js`, `advancedRacePace.js`, and `src/simulation/vehicle/vehiclePhysics.js` (analytic planning helper only). Tests: new `src/__tests__/arcadeAIRacing.test.js`, updated `advancedAIRacing.test.js`, and a separated kerb-use characterization in `driverController.test.js`. Measurement: `scripts/benchmark-advanced-ai.mjs`, `benchmark-advanced-ai-fields.mjs`, `runtimeEfficiencyBenchmarks.mjs`. Documentation: `docs/rules.md`, `architecture.md`, a historical follow-up link in `advanced_ai_pace.md`, and this report.
126
+
127
+ Artifacts: `/tmp/paddockjs-racing-ai-20260909/`, including frozen baseline, accepted/rejected source copies, JSONL measurements, physics comparison and gate logs. Reproduce:
128
+
129
+ ```sh
130
+ node scripts/benchmark-advanced-ai.mjs . 7109,7110,7200,7201,12,26,61,20260427,28,62,69,7202,7203,101,9099,12345 --physics-mode arcade
131
+ node scripts/benchmark-advanced-ai.mjs . 7109,7110,7200,7201,12,26,61,20260427,28,62,69,7202,7203,101,9099,12345 --physics-mode advanced
132
+ node scripts/benchmark-advanced-ai-fields.mjs . --physics-mode arcade --repeats 2
133
+ node scripts/benchmark-advanced-ai-fields.mjs . --physics-mode advanced --repeats 2
134
+ node scripts/benchmark-runtime-efficiency.mjs --profile=standard --json --verify
135
+ npm run check
136
+ npm run check:release
137
+ ```
138
+
139
+ Git remains approval-gated. Existing dirty work is preserved; this task does not establish repository-wide cleanliness. Review the bounded changes against the task snapshot and the combined working diff before proposing exact staging/commit actions. No Git/GitHub mutation is authorized or performed.
140
+
141
+ Work log: [Racing-driver AI improvements: arcade and advanced](https://linear.app/mgiorgetti/document/racing-driver-ai-improvements-arcade-and-advanced-9dac1149e8ab).
142
+
143
+ Current read-only Git inspection: branch `v11`, HEAD `fedff4e`, recorded `origin/v11` at 0 ahead/0 behind without fetching; index empty, 123 modified tracked paths and 50 untracked entries. Earlier work is preserved.
144
+
145
+ Subsequent skill-dependent physical-envelope tuning, timing-line boundary repair and measured limitations are documented in [limit driving, 2026-10-14](limit_driving_2026-10-14.md). Earlier results above describe their recorded candidate.