@inventure71/paddockjs 4.1.0 → 4.3.0

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 (257) hide show
  1. package/CHANGELOG.md +76 -0
  2. package/INSTALL_AND_UPDATE.md +31 -5
  3. package/README.md +34 -3
  4. package/docs/advanced_ai_pace.md +131 -0
  5. package/docs/advanced_physics_rebuild.md +166 -0
  6. package/docs/architecture.md +111 -30
  7. package/docs/cleanup_coverage.md +284 -0
  8. package/docs/component_inventory.md +32 -16
  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/getting-started.md +3 -0
  16. package/docs/grid_walk.md +80 -0
  17. package/docs/index.md +5 -2
  18. package/docs/keyboard_driving_fix.md +118 -0
  19. package/docs/limit_driving_2026-10-14.md +88 -0
  20. package/docs/loading.md +141 -0
  21. package/docs/maintainability_audit_2026-09-08.md +146 -0
  22. package/docs/racing_ai_improvements.md +145 -0
  23. package/docs/rules.md +43 -13
  24. package/docs/sense_contract.md +4 -1
  25. package/docs/system_specs.md +40 -12
  26. package/docs/testing-reliability-guide.md +67 -0
  27. package/docs/v11_improvements.md +108 -0
  28. package/package.json +23 -15
  29. package/src/api/MountedSimulatorComponents.js +101 -0
  30. package/src/api/PaddockSimulatorController.js +56 -81
  31. package/src/app/BrowserExpertAdapter.js +0 -6
  32. package/src/app/BrowserExpertExternalRenderer.js +72 -50
  33. package/src/app/ExternalTrackSnapshot.js +50 -0
  34. package/src/app/F1SimulatorApp.js +242 -297
  35. package/src/app/HostLifecycleEmitter.js +93 -0
  36. package/src/app/banners/raceDataBannerController.js +9 -4
  37. package/src/app/camera/cameraConstants.js +1 -1
  38. package/src/app/camera/cameraController.js +10 -13
  39. package/src/app/camera/cameraGeometry.js +1 -1
  40. package/src/app/controls/SimulatorViewControls.js +45 -0
  41. package/src/app/controls/workbenchBindings.js +64 -0
  42. package/src/app/controls/workbenchDisclosure.js +41 -0
  43. package/src/app/domBindings.js +21 -13
  44. package/src/app/gridWalk/GridWalkController.js +180 -0
  45. package/src/app/gridWalk/gridWalkCamera.js +88 -0
  46. package/src/app/gridWalk/gridWalkControls.js +24 -0
  47. package/src/app/gridWalk/gridWalkCrew.js +246 -0
  48. package/src/app/gridWalk/gridWalkLabels.js +104 -0
  49. package/src/app/gridWalk/gridWalkLayout.js +46 -0
  50. package/src/app/gridWalk/gridWalkNavigation.js +99 -0
  51. package/src/app/gridWalk/gridWalkProjectBanner.js +43 -0
  52. package/src/app/gridWalk/gridWalkSession.js +50 -0
  53. package/src/app/layoutSupport.js +2 -0
  54. package/src/app/raceOverlayClearanceSupport.js +21 -7
  55. package/src/app/readouts/carOverviewRenderer.js +9 -4
  56. package/src/app/readouts/readoutFormatters.js +1 -8
  57. package/src/app/readouts/telemetryRenderer.js +1 -3
  58. package/src/app/readouts/timingTowerRenderer.js +48 -50
  59. package/src/app/rendering/appAssets.js +8 -10
  60. package/src/app/rendering/carRenderer.js +27 -79
  61. package/src/app/rendering/displayUtils.js +0 -6
  62. package/src/app/rendering/expertSensorRenderer.js +1 -1
  63. package/src/app/rendering/replayGhostRenderer.js +4 -1
  64. package/src/app/rendering/trackRenderer.js +2 -2
  65. package/src/app/runtime/frameLoop.js +18 -17
  66. package/src/app/runtime/pixiStartupLifecycle.js +94 -0
  67. package/src/app/runtime/runtimeTiming.js +4 -1
  68. package/src/app/runtime/runtimeVisibility.js +7 -2
  69. package/src/config/cssValues.js +1 -1
  70. package/src/config/defaultOptions.js +12 -173
  71. package/src/config/restartOptions.js +1 -0
  72. package/src/config/runtimeSeed.js +10 -0
  73. package/src/config/simulatorDefaults.js +106 -0
  74. package/src/config/telemetryModules.js +20 -0
  75. package/src/config/theme/cssTokens.js +85 -0
  76. package/src/config/theme/themeCss.js +72 -0
  77. package/src/config/theme/themeInputs.js +155 -0
  78. package/src/config/theme/themeResolver.js +172 -0
  79. package/src/config/theme/themeSelectors.js +69 -0
  80. package/src/config/theme/themeTokens.js +257 -0
  81. package/src/config/theme/themeUtils.js +15 -0
  82. package/src/config/themeOptions.js +14 -830
  83. package/src/config/timingGapMode.js +0 -2
  84. package/src/config/uiOptions.js +53 -0
  85. package/src/data/championship.js +16 -158
  86. package/src/data/championshipDefaults.js +87 -0
  87. package/src/data/driverData.js +10 -20
  88. package/src/data/entryIdentity.js +67 -0
  89. package/src/data/entryPresentation.js +23 -0
  90. package/src/data/entryTypes.d.ts +160 -0
  91. package/src/data/index.d.ts +12 -195
  92. package/src/data/ratingScale.js +14 -0
  93. package/src/data/teamTypes.d.ts +23 -0
  94. package/src/data/trackTypes.d.ts +101 -0
  95. package/src/data/vehicleData.js +12 -23
  96. package/src/environment/actions.js +3 -2
  97. package/src/environment/controllerLoop.js +57 -44
  98. package/src/environment/controllerScheduler.js +30 -0
  99. package/src/environment/driverObservations.js +260 -0
  100. package/src/environment/driverReset.js +51 -0
  101. package/src/environment/episode.js +0 -1
  102. package/src/environment/evaluation.js +6 -90
  103. package/src/environment/evaluationTracker.js +100 -0
  104. package/src/environment/events.js +23 -0
  105. package/src/environment/index.d.ts +35 -91
  106. package/src/environment/metrics.js +3 -17
  107. package/src/environment/observationSchema.js +104 -0
  108. package/src/environment/observationVector.js +16 -115
  109. package/src/environment/observations.js +16 -316
  110. package/src/environment/options.js +5 -24
  111. package/src/environment/renderFrames.js +21 -0
  112. package/src/environment/resetOptions.js +41 -0
  113. package/src/environment/results.js +125 -0
  114. package/src/environment/rewards.js +10 -16
  115. package/src/environment/runtime.js +17 -300
  116. package/src/environment/scenarioOptions.js +90 -0
  117. package/src/environment/scenarioPlacements.js +70 -0
  118. package/src/environment/scenarioPresets.js +78 -0
  119. package/src/environment/scenarios.js +5 -236
  120. package/src/environment/scratch.js +18 -0
  121. package/src/environment/sensorOptions.js +20 -0
  122. package/src/environment/sensors/index.js +2 -556
  123. package/src/environment/sensors/indexedRayBands.js +0 -18
  124. package/src/environment/sensors/nearbyCars.js +18 -15
  125. package/src/environment/sensors/opponentRadar.js +3 -2
  126. package/src/environment/sensors/pitConnectorProximity.js +20 -0
  127. package/src/environment/sensors/rayBandTrace.js +1 -37
  128. package/src/environment/sensors/rayBatch.js +81 -0
  129. package/src/environment/sensors/rayConfig.js +26 -0
  130. package/src/environment/sensors/rayGeometry.js +0 -8
  131. package/src/environment/sensors/rayGuards.js +0 -6
  132. package/src/environment/sensors/rayOutputs.js +75 -0
  133. package/src/environment/sensors/rayQuery.js +110 -0
  134. package/src/environment/sensors/rayScratch.js +146 -0
  135. package/src/environment/sensors/sensorTargets.js +12 -4
  136. package/src/environment/sensors/surfaceRays.js +6 -61
  137. package/src/environment/sensors/trackRays.js +7 -80
  138. package/src/environment/simulationSetup.js +30 -0
  139. package/src/environment/specs.js +15 -109
  140. package/src/index.d.ts +43 -202
  141. package/src/index.js +28 -6
  142. package/src/placeholder/index.js +1 -8
  143. package/src/rendering/displayLifecycle.js +6 -0
  144. package/src/rendering/proceduralTrackAsset.js +1 -1
  145. package/src/rendering/renderSnapshot.js +3 -0
  146. package/src/rendering/track/finishLineRenderer.js +1 -1
  147. package/src/rendering/track/gridRenderer.js +1 -1
  148. package/src/rendering/track/offsetStrokeSafety.js +2 -2
  149. package/src/rendering/track/pitLaneRenderer.js +1 -1
  150. package/src/rendering/track/trackMaterialRenderer.js +4 -4
  151. package/src/rendering/track/trackRenderConstants.js +0 -1
  152. package/src/rendering/track/trackRenderGeometry.js +1 -7
  153. package/src/simulation/collisionGeometry.js +12 -20
  154. package/src/simulation/driver/advancedPathControls.js +53 -0
  155. package/src/simulation/driver/advancedRacePace.js +112 -0
  156. package/src/simulation/driver/advancedRacingControls.js +61 -0
  157. package/src/simulation/driver/advancedRacingEnvelope.js +255 -0
  158. package/src/simulation/driver/advancedRacingSteering.js +76 -0
  159. package/src/simulation/driver/advancedRacingTiming.js +16 -0
  160. package/src/simulation/driver/arcadeRacePace.js +83 -0
  161. package/src/simulation/driver/arcadeRacingControls.js +111 -0
  162. package/src/simulation/driver/arcadeRacingEnvelope.js +63 -0
  163. package/src/simulation/driver/driverControlConstants.js +0 -2
  164. package/src/simulation/driver/driverController.js +16 -5
  165. package/src/simulation/driver/edgeRecovery.js +2 -3
  166. package/src/simulation/driver/racingControls.js +10 -396
  167. package/src/simulation/driver/racingDriverProfile.js +48 -0
  168. package/src/simulation/driver/racingLinePlan.js +54 -20
  169. package/src/simulation/driver/rejoinControls.js +59 -112
  170. package/src/simulation/driver/safetyCarControls.js +12 -0
  171. package/src/simulation/driver/trafficScan.js +136 -27
  172. package/src/simulation/participants/participantInteractions.js +24 -15
  173. package/src/simulation/pit/pitCarPlacement.js +29 -0
  174. package/src/simulation/pit/pitFlow.js +8 -30
  175. package/src/simulation/pit/pitIntent.js +4 -3
  176. package/src/simulation/pit/pitOccupancy.js +2 -2
  177. package/src/simulation/pit/pitQueue.js +2 -18
  178. package/src/simulation/pit/pitRouteMovement.js +1 -36
  179. package/src/simulation/pit/pitRouting.js +5 -81
  180. package/src/simulation/pit/pitService.js +3 -32
  181. package/src/simulation/pit/pitServiceConstants.js +1 -0
  182. package/src/simulation/pit/pitServiceProgress.js +34 -0
  183. package/src/simulation/pit/pitSnapshots.js +8 -4
  184. package/src/simulation/pit/pitState.js +1 -5
  185. package/src/simulation/race/classification.js +1 -8
  186. package/src/simulation/race/raceFinish.js +3 -8
  187. package/src/simulation/race/raceOrder.js +2 -13
  188. package/src/simulation/race/raceProgress.js +6 -20
  189. package/src/simulation/race/raceSetup.js +1 -1
  190. package/src/simulation/race/raceStep.js +20 -11
  191. package/src/simulation/race/redFlag.js +2 -4
  192. package/src/simulation/race/safetyCar.js +5 -9
  193. package/src/simulation/race/stalledDnf.js +2 -4
  194. package/src/simulation/raceSimulation.js +6 -38
  195. package/src/simulation/replay/replayGhosts.js +44 -32
  196. package/src/simulation/rules/collisionSteward.js +0 -14
  197. package/src/simulation/rules/penaltyActions.js +37 -0
  198. package/src/simulation/rules/penaltyLedger.js +8 -1
  199. package/src/simulation/rules/pitLaneSpeedingSteward.js +1 -1
  200. package/src/simulation/rules/rulesReview.js +20 -16
  201. package/src/simulation/rules/trackLimitsSteward.js +2 -2
  202. package/src/simulation/simMath.js +4 -0
  203. package/src/simulation/snapshots/raceSnapshots.js +30 -11
  204. package/src/simulation/timing/drsState.js +8 -0
  205. package/src/simulation/timing/drsTiming.js +2 -4
  206. package/src/simulation/timing/lapTelemetry.js +7 -4
  207. package/src/simulation/timing/sectorPerformance.js +14 -6
  208. package/src/simulation/timing/timingLines.js +12 -6
  209. package/src/simulation/track/pitLaneAccess.js +2 -2
  210. package/src/simulation/track/pitLaneLayout.js +4 -135
  211. package/src/simulation/track/pitLaneModel.js +70 -0
  212. package/src/simulation/track/pitLaneState.js +0 -1
  213. package/src/simulation/track/pitServiceLayout.js +121 -0
  214. package/src/simulation/track/proceduralTrack.js +77 -0
  215. package/src/simulation/track/spatialQueries.js +76 -31
  216. package/src/simulation/track/trackBuilder.js +54 -0
  217. package/src/simulation/track/trackConstants.js +0 -22
  218. package/src/simulation/track/trackMath.js +4 -29
  219. package/src/simulation/track/trackModel.js +12 -240
  220. package/src/simulation/track/trackModelCache.js +105 -0
  221. package/src/simulation/track/trackNearestQueries.js +1218 -0
  222. package/src/simulation/track/trackQueryConstants.js +3 -0
  223. package/src/simulation/track/trackQueryConstruction.js +368 -0
  224. package/src/simulation/track/trackQueryIndex.js +12 -1933
  225. package/src/simulation/track/trackQuerySegments.js +174 -0
  226. package/src/simulation/track/trackQueryStats.js +12 -0
  227. package/src/simulation/track/trackRayQueries.js +165 -0
  228. package/src/simulation/vehicle/advancedContactResponse.js +89 -0
  229. package/src/simulation/vehicle/advancedTireForces.js +92 -0
  230. package/src/simulation/vehicle/advancedVehicleModel.js +65 -0
  231. package/src/simulation/vehicle/advancedVehiclePhysics.js +127 -0
  232. package/src/simulation/vehicle/contactResolution.js +23 -9
  233. package/src/simulation/vehicle/mainTrackWheelSurface.js +2 -13
  234. package/src/simulation/vehicle/pitWheelSurface.js +0 -12
  235. package/src/simulation/vehicle/runoffResponse.js +2 -4
  236. package/src/simulation/vehicle/sampledWheelSurface.js +266 -0
  237. package/src/simulation/vehicle/vehicleGeometry.js +85 -103
  238. package/src/simulation/vehicle/vehicleKinematics.js +10 -0
  239. package/src/simulation/vehicle/vehiclePhysics.js +42 -196
  240. package/src/simulation/vehicle/vehicleSnapshots.js +18 -6
  241. package/src/simulation/vehicle/vehicleState.js +5 -3
  242. package/src/simulation/vehicle/wheelSurface.js +13 -432
  243. package/src/simulation/vehicle/wheelSurfaceCache.js +55 -0
  244. package/src/simulation/vehicle/wheelSurfaceSummary.js +101 -0
  245. package/src/styles.css +173 -19
  246. package/src/ui/bannerTemplates.js +4 -2
  247. package/src/ui/cameraControlsTemplate.js +4 -2
  248. package/src/ui/gridWalkTemplate.js +29 -0
  249. package/src/ui/htmlEscaping.js +8 -0
  250. package/src/ui/raceCanvasTemplate.js +3 -2
  251. package/src/ui/shellTemplate.js +3 -0
  252. package/src/ui/telemetryDrawerTemplate.js +4 -2
  253. package/src/ui/telemetryTemplates.js +3 -22
  254. package/src/ui/templateUtils.js +2 -8
  255. package/src/ui/viewControlsTemplate.js +21 -0
  256. package/examples/train-basic-policy.mjs +0 -276
  257. package/examples/trainingData.mjs +0 -133
@@ -0,0 +1,284 @@
1
+ # Repository cleanup coverage
2
+
3
+ This continues the initial [maintainability audit](maintainability_audit_2026-09-08.md) across the repository. The stopping condition is coverage of every repository area, resolution of verified actionable cleanup findings, preserved supported behavior, and passing package/release gates. It is not a promise that software contains no undiscovered defects, and it does not mean discarding or committing the existing working tree.
4
+
5
+ ## Plan and constraints
6
+
7
+ - [x] Recheck `v11` / `fedff4e` and preserve all 380 current tracked/untracked files in a second baseline outside Git.
8
+ - [x] Run three unchanged standard runtime benchmark baselines; retain the prior passing package/release gates as the verified starting state.
9
+ - [x] Restore Linear logging and record completed work plus this continuation in the PaddockJS project.
10
+ - [x] Review simulation, environment, browser/API/rendering/UI, data/configuration, tests, scripts, demo/showcase, docs, assets, and package/workflow configuration.
11
+ - [x] Check compiler-assisted unused-local/missing-name hypotheses and static/dynamic/type/consumer references; retain intentional compile-time assertion bindings.
12
+ - [x] Remove proven dead paths and consolidate identical feature rules with explicit owners.
13
+ - [x] Fix verified snapshot isolation, cached geometry ownership, and default-path defects with regression tests.
14
+ - [x] Update authoritative docs and reconcile every earlier deferred concern with evidence.
15
+ - [x] Review integrated changes, run `npm run check` and `npm run check:release`, compare deterministic outputs and repeated benchmarks against the saved source.
16
+ - [x] Record final coverage, changed files, measurement limits, preservation checks, read-only Git status, and Linear results.
17
+
18
+ No dependency upgrades, product redesign, speculative optimization, or Git/GitHub mutation is part of this work. Existing timing-board proportions, model-facing sensor precision, deterministic arithmetic/random order, public exports/types, and intentional asset/callback recovery remain acceptance constraints.
19
+
20
+ ## Ownership before implementation
21
+
22
+ - **Simulation:** remove definition-only internals after checking barrels and consumers. `raceDistance` owns wrapped progress arithmetic; `penaltyStats` owns penalty totals; pit geometry constants belong to existing pit routing/state owners. Snapshot serializers own copies of supported mutable nested data; race orchestration selects snapshots. Cached track grid topology is static and must be frozen without freezing per-runtime query scratch.
23
+ - **Environment:** `events` owns shared driver-ID extraction/deduplication; metrics retains contact filtering/counting and observations retain distribution/order, each with separate scratch. Sensor modules retain the indexed/analytic/sampled hierarchy but lose mathematically unreachable branches and producerless internal encoding paths. Public sensor precision and output ownership are verified with existing independent oracles and differential runs.
24
+ - **Browser:** the radio feature owns scheduling transitions while the app retains radio state, driver data, and seeded RNG. Renderer modules own sprite transforms and geometry; unreachable disabled raw-renderer paths do not need replacement. Pure HTML escaping has a dependency-free UI owner, shared by templates, readouts, and the standalone placeholder. Asset recovery remains intact. Track-stroke defaults must import their existing constant owner.
25
+ - **Data/configuration:** a focused rating-scale module owns common bounds, coercion/clamping, and linear conversion; driver/vehicle classes retain stat definitions, output selection, direction policy, and exact domain-specific errors. Telemetry-module normalization belongs in config and must serve both normalized app options and raw template callers. Boundary-specific normalization with different semantics stays separate.
26
+ - **Tooling/tests/docs:** remove unused private harness paths without deleting behavior coverage. Keep intentional type-only assertions and independent numerical test oracles. Inspect showcase/demo lifecycle and use their existing smoke tests; do not replace host-specific orchestration with package internals. Historical plans remain historical, while authoritative docs are corrected alongside implementation.
27
+
28
+ ## Coverage and results
29
+
30
+ The inventory contains 391 tracked/untracked files, including all existing work. Every area received reference/contract screening; depth and executable coverage are recorded separately below. Ignored local training/checkpoint/output content and generated dependency/build directories were excluded; this covers repository product and verification files, not arbitrary local artifacts. Evidence is under `/tmp/paddockjs-audit-20260908/phase2/`.
31
+
32
+ | Area | Review and disposition |
33
+ | --- | --- |
34
+ | Simulation: 108 modules | Import/export/unused-local screening throughout; feature ownership review of race/driver/vehicle/pit/rules/timing/track/replay/warmup groups. Dead adapters removed; shared rules and snapshot ownership corrected. Numerical kernels remain covered by characterization and differential checks. |
35
+ | Environment: 38 files after cleanup | Every implementation module read; action/reset/observation/vector/spec/event/metric/controller/transport boundaries checked. Shared schema and event rules consolidated; direct/rich channel ordering corrected. |
36
+ | Browser/API/rendering/UI/placeholder | All 55 original JS modules read with declarations, dynamic consumers, DOM bindings and lifecycle tests. Dead rendering and forwarding paths removed; radio and escaping have single owners. Timing-board CSS/proportions are unchanged. |
37
+ | Data/config: 19 files after cleanup | Public exports/types/defaults/assets and every implementation screened. Shared rating and telemetry normalization consolidated without changing stat definitions or coercion/error contracts. |
38
+ | Demo: 17 existing files | Five runtime lifecycle/state defects fixed with real public controller-shaped stubs and deferred mounts. Product layout, feature catalogue, host/package boundary and styles retained. |
39
+ | Engineering showcase: 26 files | Routes, Policy Runner transport, sensor display, fixtures and package imports inspected. Removed one unused placement parameter and made Vite's ESM root explicit. Distinct policy fallback semantics retained. |
40
+ | Tests: 56 files after cleanup | Compiler/import and source-coupling screen across all files; affected suites reviewed in detail. Independent numerical oracles, type assertions, slow fixtures, and boundary checks retained. Added focused behavior/failure suites; replaced radio method spies with seeded observable schedule assertions. |
41
+ | Scripts/smoke: 13 files | Gate/pack/consumer/benchmark/build ownership and cleanup inspected. Removed an uncalled preview helper and needless single-item chunking; slow tests still execute in isolated per-file batches. Existing benchmark workloads/settings retained. |
42
+ | Docs/root guidance | Authoritative docs checked against affected implementation and package contracts; ownership and stale precision statements corrected. Historical design notes, root `Q&A.md`, and the first-pass report explicitly remain historical. Link/spec checker runs in both gates. |
43
+ | Assets/dependencies/packaging/workflows | All six bundled assets have default mappings. Pixi, Vitest, TypeScript, Playwright and Changesets each have active consumers. Public exports and package file list checked against types and packed builds. No dependency upgrades or workflow changes. |
44
+ | Python example: 3 files | Transport, extension hooks, README and declared dependencies inspected. Server hooks and preview disconnect isolation are intentional example boundaries; no implementation change or external server execution claimed. |
45
+
46
+ ### Verified findings and smallest coherent fixes
47
+
48
+ Package paths in the finding table are relative to `src/`; demo/tooling paths are relative to the repository root. Locations below identify functions in the saved phase-two baseline where code was removed, and current owners where code remains. The first-pass F1–F8 evidence remains in the linked historical report.
49
+
50
+ | Finding and exact evidence | Unnecessary cost and fix | Compatibility risk and verification |
51
+ | --- | --- | --- |
52
+ | `simulation/rules/penaltyLedger.js:50` spread-copied a penalty but shared nested consequences; changing returned seconds from 5 to 99 changed later live pit service. `pit/pitSnapshots.js:38` and `vehicle/vehicleSnapshots.js` shared declared crew objects. | Public result edits could mutate the state owner. Serializers now copy only supported nested arrays/records, preserving optional fields and the documented live-track exception. | Intentional contract repair; tests exercise actual normalized entries and live pit penalty service, plus two-way snapshot isolation. |
53
+ | `simulation/track/trackModel.js:212-261` froze only Map cells and carried a Map proxy, but current grids use arrays. | Obsolete representation branch left shared cells mutable across simulations. Freeze existing arrays/buckets and remove unused proxy. Keep per-runtime query scratch/stats separate. | No query math change. Test attempted mutation through shared geometry, unaffected second simulation, separate scratch/stats; repeated query/runtime benchmarks. |
54
+ | `environment/specs.js` and `observationVector.js` separately declared names/order/units/scales. Compact ray writing in `sensors/index.js` followed configured surface order while rich vectors/specs used canonical order. | New senses required duplicate metadata edits; reversed channel arrays silently mislabeled compact values. `observationSchema.js` owns metadata and canonical surface order; numeric encoding stays explicit. | Contract repair for reversed `illegalSurface`/`kerb` options. Thirty full/compact/schema/array/Float32/per-driver cases, including three reproduced failures, plus independent sense oracles. |
55
+ | `environment/observations.js` and `metrics.js` duplicated participant ID extraction/deduplication. | Changes to event ID shapes had two owners. `events.js:writeEventDriverIds` writes IDs into caller-owned scratch. Distribution and contact filtering remain distinct. | Ordering and one-contact-per-driver semantics tested through environment results; no shared mutable scratch introduced. |
56
+ | `environment/observationVector.js:96` consumed `source.rayVectorValues`, but no producer existed. `sensors/trackRays.js`, `surfaceRays.js:229,253`, `rayBandTrace.js` carried unreachable/redundant checks and sampled branches. `rayGeometry.js`, `rayGuards.js`, `indexedRayBands.js` contained unreferenced exports. | Removed producerless encoding and proven dead helpers/branches; retain active indexed, analytic and bounded sampled recovery paths. | All exports, types, tests, dynamic references and consumers checked. 82 before/after nominal cases are byte-identical; driver/debug and road/curve/pit/recovery oracles retained. No precision shortcut. |
57
+ | `app/F1SimulatorApp.js:1034 updateRadioSchedule` duplicated `app/banners/raceDataBannerController.js:updateRadioSchedule`. | Two copies of deadline/catch-up state transitions could drift. App supplies narrow state/time/drivers/enabled/RNG inputs to the existing feature owner. | Seeded random-call order, normal deadlines, long pauses, boundary times and muted behavior asserted without method spies. |
58
+ | `app/rendering/carRenderer.js:8,98` had constant-false `TEMP_RENDER_RAW_CAR_GEOMETRY`, an unreachable renderer and repeated conditions. `F1SimulatorApp.js` had uncalled render/camera/steward forwards and write-only banner state; `domBindings.js` collected unused arrays. | Removed dead code/state/dependencies with no replacement abstraction. Active sprite geometry and useful facade delegation remain. | Dynamic references, tests, types and root controller checked; renderer/component tests and Chromium flows exercise retained paths. |
59
+ | `ui/templateUtils.js`, `app/readouts/readoutFormatters.js`, `placeholder/index.js` duplicated identical escaping. | Three copies of a presentation rule. Dependency-free `ui/htmlEscaping.js` owns the exact existing mapping and coercion. | Existing escaping tests plus packed root/placeholder/data/environment boundary checks; no browser dependency enters placeholder. |
60
+ | `rendering/track/offsetStrokeSafety.js:89 traceSegmentedOffsetStroke` used an unimported `SEGMENTED_STROKE_STEP` default. | Default invocation threw before drawing. Import its existing constant owner. | Omitted-default reproduction failed before; real-track omitted versus explicit default test now passes. No material/proportion change. |
61
+ | `data/driverData.js:3-25` and `vehicleData.js:3-27` repeated rating bounds/conversion; `config/defaultOptions.js` and `ui/telemetryTemplates.js` repeated module defaults/normalization. | Focused `ratingScale.js` and `telemetryModules.js` own shared rules. Classes retain definitions/direction/error labels; templates consume resolved policy. | Eighteen normalization cases cover coercion, clamp limits, inverse vehicle direction, errors and public markup. Existing data/type/consumer suites remain. |
62
+ | `simulation/rules/rulesReview.js:21` duplicated wrapped progress; `race/classification.js` duplicated penalty-stat defaults; pit intent/state/routing repeated approach limits. | Use existing `raceDistance`, `penaltyStats`, and `pitServiceConstants` owners. No generic utility/service added. | Preserve arithmetic order, defaults and constants; race, pit, collision characterization and deterministic comparisons. |
63
+ | Definition-only `race/raceOrder.js:222 buildDrsReferenceByCarId`, `rules/collisionSteward.js:3 calculateCollisionPenalties`, `track/spatialQueries.js:131 nearestSampleGlobal`, `track/trackConstants.js:37 NEAREST_HINT_WINDOW_SAMPLES`, `vehicle/vehicleGeometry.js:241,458,463` geometry adapters and private collision/track/wheel helpers. | Remove unused adapters, old constants/templates, unused imports/locals and private parameters. Keep actively imported compatibility barrels and canonical algorithms. | Checked package exports, declarations, direct/dynamic/test/benchmark consumers before removal; all simulation tests and packed consumers verify retained surfaces. |
64
+ | `demo/src/runtime/presetShowcase.js:12,23,32 mount` allowed concurrent mounts on one root; generation checks ran too late. | Serialize root ownership, skip superseded requests, invalidate pending results on disposal. | Deferred real-shaped mount tests reproduce root collisions and late disposal; Chromium rapidly selects three presets and verifies the final ready route. |
65
+ | `demo/src/runtime/mainShowcase.js:37,45,72`, `expertLab.js:50,104,115`, `headlessLab.js:50,109` released resources only after successful initialization/run. | Owner cleans up on failure; expert disposal invalidates late mounts and failed launches allow retry. | Regressions cover failed hero start, headless step, expert loop start, retry and pending disposal. No package lifecycle API changes. |
66
+ | `demo/src/runtime/controlDeck.js:2-5,69` maintained duplicate safety/red-flag/pit/theme booleans and read nonexistent `raceControl.totalLaps`. | Read public state getters and `snapshot.totalLaps`; remove listeners on cleanup. | Reproduced Lap 2/5 with a three-lap race. Tests verify actual state-derived controls, including deployment legitimately rejected during pre-start/red flag; Chromium waits for observable green, toggles embedded controls and checks host synchronization. |
67
+ | `smoke/browser-smoke.mjs:startPreviewController` was uncalled; `scripts/run-vitest.mjs:chunk` always used size 1; two tests had unused setup/imports. | Remove private dead harness code and iterate slow files directly; no assertion or slow isolation removed. `local-preview/vite.config.js` uses explicit ESM file URL resolution. | Both gates, slow per-file batches, existing showcase build reuse and updated browser/demo smoke. Benchmark callback signatures and positional compatibility parameters remain intentional. |
68
+ | Stale tire-care/custom-field docs (first pass), current ownership prose, sampled-only driver-precision wording, historical Linear blocker. | Correct authoritative docs with source; retain invariant/numerical explanations and explicitly mark historical reports. | Docs checker and source/contract review; final Linear log contains both passes. |
69
+
70
+ ### Complexity deliberately retained
71
+
72
+ - Active root track/vehicle/driver/timing/sensor/UI compatibility exports and legacy public aliases have consumers. Removing them would not simplify supported use.
73
+ - Physics-mode profiles, narrow numerical helpers, public/controller forwarding and frame/pit orchestration represent actual boundaries. Moving methods into helpers receiving the entire owner would merely relocate coupling.
74
+ - Timing rings, indexed geometry, bounded ray recovery, wheel/ray scratch, render/full/training snapshot distinctions, visibility pacing and keyed DOM rows have benchmark or behavior evidence. No new cache, pool, precision tradeoff or hot-path algorithm was introduced.
75
+ - Asset load **and texture-configuration** failures intentionally recover per asset to the white texture. Tests now characterize both; changing the failure policy would violate the requested behavior preservation. Host callback containment, optional warmup, controller cancellation and external-renderer error isolation remain intentional.
76
+ - Reward/legal-surface rules, DNF race-order versus interaction participation, driver versus ray heading normalization, and Policy Runner model math have different semantics despite similar code. They remain separate.
77
+ - Unused positional callback parameters and type-only assertion bindings are intentional. Large files, cohesive benchmark fixtures, slow characterization setup and source-level module-boundary assertions were not removed merely for size or line-count targets.
78
+ - Cached private typed index buffers remain shared and immutable by convention; arbitrary mutation of private internal buffers is unsupported. Public nested snapshots are isolated, while the documented in-memory track reference remains live.
79
+
80
+ ### Verification and measurements
81
+
82
+ Both final gates passed end to end. Initial `npm run check` had no failures: 846 fast tests passed with 78 intentional slow skips. The first pass ended with 878 fast / 956 exhaustive tests passing. The final results are:
83
+
84
+ | Verification | Result |
85
+ | --- | --- |
86
+ | `npm run check` | Passed: 947 tests across 53 files, 78 intentional slow skips; docs, public types, dry pack, packed-consumer install/build, subpath bundle boundaries, showcase/demo builds, quick Chromium and demo smoke. |
87
+ | `npm run check:release` | Passed: all 1,025 tests across 53 isolated files, no skips; all packaging/build gates and full Chromium matrix plus demo smoke. |
88
+ | Browser workloads | Desktop, 464px narrow, 390px/320px mobile, tablet, short-wide, timing breakpoints, loading, components, customization, API, playable expert, Policy Runner, race behavior, stewarding, collision lab; demo rapid presets, embedded-control synchronization, expert/headless/search/mobile. |
89
+ | Packed boundaries | Root 1,033.5 kB JS; placeholder 2.0 kB JS, no assets; data 99.1 kB JS, no CSS/assets; environment 353.9 kB JS, no CSS/assets. All existing budgets passed. |
90
+ | Deterministic differential | Original baseline versus final: exact serialized full/vector/object reset, 60 steps per mode, and getState with seeds 71/2097 and frameSkip 4. SHA-256 `4ea290b6504cfe3b4903de58baab9e2eb32ff979255a393628e00ee28eb4b06d`. |
91
+ | Sensor differential | 82 nominal before/after driver/debug, normal/batch, road/curve/pit/recovery cases byte-identical. Reversed channel ordering is separately verified as an intentional contract correction. |
92
+ | Independent integration review | No actionable issue found in schema/event/rating/telemetry changes; 51 focused tests passed. |
93
+ | Static and preservation checks | Missing-name scan clean; remaining unused diagnostic bindings are intentional positional callbacks/type assertions. Diff whitespace check passed. No original file deleted; manifests, locks, public entry files/declarations, package CSS and benchmark harness unchanged. |
94
+
95
+ Raw gate logs are `final-check.log` and `final-release.log` in the phase-two evidence directory. The initially failing smoke and its correction are preserved in `check-before-smoke-correction.log`. Python example syntax was checked without running a policy server. No portfolio integration files were changed, so no portfolio install/update gate was needed.
96
+
97
+ ### Performance results, separate from structural cleanup
98
+
99
+ The unchanged standard runtime harness ran three initial baselines before edits, followed by six paired baseline/final repetitions across all 22 workloads. Pairs 1–3 ran baseline then final; pairs 4–6 reversed the order because initial sub-millisecond results were noisy. All runs used the same existing seeds, operation counts, profile/settings, Node v24.13.0, darwin arm64 / Darwin 27.0.0, Apple M4 Pro, and installed dependencies. Package gates and browser workloads were stopped before measurement. Saved baseline source was loaded through a dependency symlink; no Git worktree or checkout was created.
100
+
101
+ All benchmark verification invariants passed. Every before/after range overlaps across the six pairs. Some medians move in either direction, but these measurements do not establish a general speedup or justify additional hot-path complexity. No new optimization, cache, pool, or sensor precision change was introduced. Browser workloads establish behavior and layout; no browser FPS or latency improvement is claimed.
102
+
103
+ | Workload | Before median [min, max] ms/op | After median [min, max] ms/op |
104
+ | --- | ---: | ---: |
105
+ | simulation.step advanced field | 0.032801 [0.031272, 0.033599] | 0.032442 [0.031833, 0.033704] |
106
+ | simulation phase profile | 0.357059 [0.349806, 0.370971] | 0.355280 [0.349018, 0.358573] |
107
+ | timing history and line maintenance | 0.000127 [0.000122, 0.000135] | 0.000126 [0.000119, 0.000170] |
108
+ | timing-line gap without stored crossings | 0.000054 [0.000052, 0.000055] | 0.000054 [0.000052, 0.000072] |
109
+ | lap telemetry in-progress sync | 0.000145 [0.000144, 0.000154] | 0.000148 [0.000143, 0.000163] |
110
+ | pit route transition geometry | 0.000588 [0.000580, 0.000596] | 0.000605 [0.000569, 0.000623] |
111
+ | collision candidate and narrowphase | 0.014253 [0.013958, 0.014692] | 0.014490 [0.014137, 0.016212] |
112
+ | nearest track query index | 0.002214 [0.002175, 0.002272] | 0.002259 [0.002206, 0.002336] |
113
+ | sensor ray road and surface channels | 0.032233 [0.030728, 0.032894] | 0.032314 [0.030969, 0.034062] |
114
+ | batch-training sensor surface channels | 0.016790 [0.014976, 0.017522] | 0.016528 [0.015295, 0.017793] |
115
+ | sensor ray barrier illegal-surface validation | 0.044455 [0.041261, 0.045982] | 0.039740 [0.038388, 0.044068] |
116
+ | sensor ray barrier off-track recovery | 0.057815 [0.054281, 0.065055] | 0.057022 [0.053003, 0.061740] |
117
+ | sensor ray pit-lane direct boundary | 0.014588 [0.013090, 0.019442] | 0.015052 [0.013519, 0.018638] |
118
+ | wheel surface near pit connector | 0.013048 [0.012234, 0.014348] | 0.012633 [0.011986, 0.015194] |
119
+ | wheel surface connector local-refresh path | 0.003137 [0.002559, 0.003902] | 0.003449 [0.002298, 0.004560] |
120
+ | wheel surface main-track analytic | 0.001910 [0.001775, 0.002772] | 0.002159 [0.001801, 0.002632] |
121
+ | headless environment vector step | 0.052542 [0.050919, 0.055145] | 0.051610 [0.051316, 0.052461] |
122
+ | snapshot construction | 0.018148 [0.017784, 0.021723] | 0.018441 [0.018166, 0.019232] |
123
+ | snapshot JSON serialization | 0.236370 [0.232869, 0.248784] | 0.236371 [0.231430, 0.240804] |
124
+ | policy server compact JSON transport | 0.055986 [0.054528, 0.061248] | 0.056397 [0.054168, 0.060892] |
125
+ | render snapshot interpolation | 0.000588 [0.000564, 0.000697] | 0.000636 [0.000575, 0.000672] |
126
+ | timing tower row markup | 0.003828 [0.003767, 0.004122] | 0.003908 [0.003659, 0.004013] |
127
+
128
+ Raw results are `paired-before-1.json` through `paired-before-6.json` and their `paired-after-*` counterparts. The first-pass measurements remain in the historical audit report.
129
+
130
+
131
+
132
+ Linear work log: [2026-09-08 repository cleanup audit](https://linear.app/mgiorgetti/document/2026-09-08-repository-cleanup-audit-14d678a1a82c).
133
+
134
+ ### Pre-existing findings outside the cleanup changes
135
+
136
+ The original package gate had no failures. Vite's existing large-chunk warnings remain; bundle-boundary budgets pass and chunk-size warnings alone do not justify a redesign. A read-only npm dependency audit found five root advisories (four high, one moderate), two high advisories each in demo/showcase dependency trees, and one moderate production-only advisory (`@xmldom/xmldom`). The root high advisories name `js-yaml`, `nanoid`, `postcss`, and `vite`; demo/showcase name `nanoid` and `postcss`. All three manifests and lockfiles are byte-identical to the user's original tree. No `npm audit fix` or dependency upgrade was run, as unrelated upgrades were explicitly excluded. Remediation should be a separate focused dependency change with its own verification; the repository is not being claimed dependency-advisory-free.
137
+
138
+ The first integrated demo smoke failure was diagnosed during cleanup: its old assertion assumed safety-car deployment during pre-start, while the simulator intentionally rejects that command. The old shadow boolean concealed rejection. The smoke now waits for the actual green readout; real-simulation tests preserve rejected-command behavior. No production assertion or race rule was weakened.
139
+
140
+ ### Cumulative changed-file inventory
141
+
142
+ Compared with the saved original user tree (not with HEAD):
143
+
144
+ **Existing files edited**
145
+
146
+ - `Q&A.md`
147
+ - `demo/src/runtime/controlDeck.js`
148
+ - `demo/src/runtime/expertLab.js`
149
+ - `demo/src/runtime/headlessLab.js`
150
+ - `demo/src/runtime/mainShowcase.js`
151
+ - `demo/src/runtime/presetShowcase.js`
152
+ - `docs/architecture.md`
153
+ - `docs/data_contract.md`
154
+ - `docs/data_model.md`
155
+ - `docs/rules.md`
156
+ - `docs/sense_contract.md`
157
+ - `local-preview/src/main.js`
158
+ - `local-preview/vite.config.js`
159
+ - `scripts/run-vitest.mjs`
160
+ - `smoke/browser-smoke.mjs`
161
+ - `smoke/demo-smoke.mjs`
162
+ - `src/__tests__/championship.test.js`
163
+ - `src/__tests__/componentApi.test.js`
164
+ - `src/__tests__/proceduralTrackAsset.test.js`
165
+ - `src/__tests__/raceSimulation.test.js`
166
+ - `src/__tests__/timingHistory.test.js`
167
+ - `src/app/BrowserExpertAdapter.js`
168
+ - `src/app/F1SimulatorApp.js`
169
+ - `src/app/camera/cameraController.js`
170
+ - `src/app/domBindings.js`
171
+ - `src/app/readouts/readoutFormatters.js`
172
+ - `src/app/readouts/telemetryRenderer.js`
173
+ - `src/app/rendering/appAssets.js`
174
+ - `src/app/rendering/carRenderer.js`
175
+ - `src/config/defaultOptions.js`
176
+ - `src/config/themeOptions.js`
177
+ - `src/config/timingGapMode.js`
178
+ - `src/data/championship.js`
179
+ - `src/data/driverData.js`
180
+ - `src/data/vehicleData.js`
181
+ - `src/environment/actions.js`
182
+ - `src/environment/events.js`
183
+ - `src/environment/metrics.js`
184
+ - `src/environment/observationVector.js`
185
+ - `src/environment/observations.js`
186
+ - `src/environment/options.js`
187
+ - `src/environment/runtime.js`
188
+ - `src/environment/sensors/index.js`
189
+ - `src/environment/sensors/indexedRayBands.js`
190
+ - `src/environment/sensors/rayBandTrace.js`
191
+ - `src/environment/sensors/rayGeometry.js`
192
+ - `src/environment/sensors/rayGuards.js`
193
+ - `src/environment/sensors/surfaceRays.js`
194
+ - `src/environment/sensors/trackRays.js`
195
+ - `src/environment/specs.js`
196
+ - `src/placeholder/index.js`
197
+ - `src/rendering/track/offsetStrokeSafety.js`
198
+ - `src/rendering/track/trackMaterialRenderer.js`
199
+ - `src/rendering/track/trackRenderConstants.js`
200
+ - `src/simulation/collisionGeometry.js`
201
+ - `src/simulation/driver/edgeRecovery.js`
202
+ - `src/simulation/driver/racingControls.js`
203
+ - `src/simulation/driver/racingLinePlan.js`
204
+ - `src/simulation/driver/rejoinControls.js`
205
+ - `src/simulation/driver/trafficScan.js`
206
+ - `src/simulation/pit/pitFlow.js`
207
+ - `src/simulation/pit/pitIntent.js`
208
+ - `src/simulation/pit/pitOccupancy.js`
209
+ - `src/simulation/pit/pitRouting.js`
210
+ - `src/simulation/pit/pitServiceConstants.js`
211
+ - `src/simulation/pit/pitSnapshots.js`
212
+ - `src/simulation/pit/pitState.js`
213
+ - `src/simulation/race/classification.js`
214
+ - `src/simulation/race/raceOrder.js`
215
+ - `src/simulation/raceSimulation.js`
216
+ - `src/simulation/rules/collisionSteward.js`
217
+ - `src/simulation/rules/penaltyLedger.js`
218
+ - `src/simulation/rules/rulesReview.js`
219
+ - `src/simulation/snapshots/raceSnapshots.js`
220
+ - `src/simulation/track/pitLaneAccess.js`
221
+ - `src/simulation/track/pitLaneState.js`
222
+ - `src/simulation/track/spatialQueries.js`
223
+ - `src/simulation/track/trackConstants.js`
224
+ - `src/simulation/track/trackMath.js`
225
+ - `src/simulation/track/trackModel.js`
226
+ - `src/simulation/vehicle/mainTrackWheelSurface.js`
227
+ - `src/simulation/vehicle/pitWheelSurface.js`
228
+ - `src/simulation/vehicle/vehicleGeometry.js`
229
+ - `src/simulation/vehicle/vehiclePhysics.js`
230
+ - `src/simulation/vehicle/vehicleSnapshots.js`
231
+ - `src/simulation/vehicle/wheelSurface.js`
232
+ - `src/ui/telemetryTemplates.js`
233
+ - `src/ui/templateUtils.js`
234
+
235
+ **New files added**
236
+
237
+ - `docs/cleanup_coverage.md`
238
+ - `docs/maintainability_audit_2026-09-08.md`
239
+ - `src/__tests__/appAssets.test.js`
240
+ - `src/__tests__/configurationNormalization.test.js`
241
+ - `src/__tests__/demoLifecycle.test.js`
242
+ - `src/__tests__/environmentEventOwnership.test.js`
243
+ - `src/__tests__/environmentObservationSchema.test.js`
244
+ - `src/__tests__/environmentParticipants.test.js`
245
+ - `src/__tests__/environmentPitActions.test.js`
246
+ - `src/__tests__/pitSnapshots.test.js`
247
+ - `src/__tests__/simulationSnapshotOwnership.test.js`
248
+ - `src/config/telemetryModules.js`
249
+ - `src/data/ratingScale.js`
250
+ - `src/environment/observationSchema.js`
251
+ - `src/ui/htmlEscaping.js`
252
+
253
+ ### Final preservation and Git handoff
254
+
255
+ The original tree contained 376 files with substantial ongoing work. Across both passes, 288 original files remain byte-identical, 88 existing files have intentional cleanup edits, 15 files were added, and no original file was removed. The external original and phase-two baselines, manifests and cumulative `audit-only.patch` preserve review evidence independently of Git. This comparison separates this task from pre-existing edits; it does not claim those earlier edits were committed.
256
+
257
+ Current read-only Git state: branch `v11`, HEAD `fedff4e`, tracking the locally recorded `origin/v11` with 0 ahead / 0 behind. Remote freshness is unknown because no fetch was authorized or run. The index is empty. There are 116 modified tracked paths and 26 untracked status entries (directories count as one status entry). The working tree remains dirty intentionally, including all original ongoing work. No Git or GitHub mutation was performed.
258
+
259
+ Proposed next steps are to review the cumulative audit-only diff and select the exact cleanup hunks to carry forward. Any staging, branch creation, commit, fetch, push or PR action remains subject to AGENTS.md's exact command/target/risk approval gate. No such action is being executed as part of cleanup completion.
260
+
261
+ ## Follow-up: demo physics configuration
262
+
263
+ After the cleanup, manual use exposed excessive automatic-demo retirements. All six exact demo configurations forced advanced physics. At 180 simulated seconds, five races had 10/10 DNFs and the sixth 5/10, all `stalled-off-track` under the five-second cutoff. Their checkpoint snapshots matched the original pre-cleanup source exactly. With arcade and otherwise identical settings, every field had zero DNFs over that interval. Earlier single-car advanced survival tests and short browser smoke did not establish healthy full-field demo races.
264
+
265
+ The user confirmed arcade should remain the general default and advanced should be a separate section for later rework. Shared automatic-demo options and the neutral headless example now select arcade. The existing expert chapter/anchor is retained and labeled Advanced physics; its keyboard/sensor runtime remains an explicit, lazy advanced opt-in with a visible limitation note. No package physics, AI tuning, mode normalization or public API was changed. New regressions exercise actual demo settings and six ten-car fields for 180 simulated seconds; this is bounded survival coverage, not a guarantee of zero incidents over every complete race.
266
+
267
+
268
+ ### Mode-correction verification status
269
+
270
+ The targeted demo physics and lifecycle suite passed 23/23 tests, including six 180-second full-field cases. Documentation validation, public types, demo feature coverage (54 records / 78 API symbols / seven chapters), and the rebuilt demo also passed. These checks establish the requested mode selection and bounded simulation behavior; they do not establish a fully passing browser session.
271
+
272
+ The subsequent `npm run check` was interrupted after existing tests became unusually slow and reported failures; it did not complete. `npm run check:release` passed the new demo cases again, then stopped on two existing environment test timeouts: the generated no-pit profile exceeded 20 seconds and canonical indexed-ray determinism exceeded 60 seconds. The host reported memory pressure level 2 and roughly 10 GB of swap use. An isolated unchanged physics-mode suite passed on retry. Resource pressure is a likely contributor, but these results must not be presented as a green full gate.
273
+
274
+ The rebuilt demo responds at the running local preview, with arcade and Advanced physics copy in place. Its standalone browser smoke timed out waiting for the race to reach green. Diagnostic browser runs showed very low page animation throughput, while a blank page animated normally; no application exception was reported. The source review did not establish a ticker or lifecycle regression. Browser playback verification remains open. Test assertions, production timing and physics/AI parameters were not weakened to bypass these failures.
275
+
276
+ No performance optimization was made in this follow-up. The 55/60 advanced versus 0/60 arcade retirement comparison is behavior diagnosis under fixed simulation settings, not a performance benchmark. Remaining work is to obtain passing full gates and browser playback verification, then address advanced physics and AI recovery in the separately requested future rework.
277
+
278
+
279
+ Packed-consumer installation/build, subpath bundle-boundary verification, and dry-pack verification passed independently after the full-gate failure. A diagnostic browser-only replacement restoring the old advanced demo mode also remained at pre-start with no FPS reading before the diagnostic deadline; the browser stall is not specific to the arcade selection. This does not resolve its underlying cause.
280
+
281
+ At mode-correction handoff, read-only Git inspection still shows `v11` at `fedff4e`, empty index, 116 modified tracked paths and 27 untracked status entries. The locally recorded upstream comparison is 0 ahead / 0 behind; no fetch was performed. Preserve the ongoing dirty work and review the bounded demo changes before proposing any exact, separately approved Git/GitHub action.
282
+
283
+
284
+ Files changed for the mode correction: `demo/src/data/demoOptions.js`, `demo/src/runtime/headlessLab.js`, `demo/src/runtime/expertLab.js`, `demo/src/data/featureCatalog.js`, `demo/index.html`, `demo/README.md`, `smoke/demo-smoke.mjs`, `src/__tests__/demoLifecycle.test.js`, `src/__tests__/demoPhysics.test.js` (new), `docs/architecture.md`, `docs/system_specs.md`, and this report.
@@ -19,7 +19,8 @@ This inventory maps package-owned UI surfaces to their shared bases, owner modul
19
19
  | All-in-one shell | `mountF1Simulator()` | `src/ui/shellTemplate.js` | Composes race controls, optional external camera controls, timing tower, race canvas, telemetry stack, shell unsupported overlay | `F1SimulatorApp` | Owns `data-f1-simulator-shell`, workspace/grid classes, layout preset classes, and the package root styling scope. Not individually mounted by composable hosts. |
20
20
  | Race controls | `mountRaceControls()` and all-in-one shell | `src/ui/raceControlsTemplate.js` | Component surface frame helper, `createSafetyCarControlMarkup({ compact: true })`, loading overlay, unsupported overlay | `controlStateRenderer.js` plus `F1SimulatorApp.bindControls()` | Includes title, kicker, safe backlink, safety-car button, and restart. The compact safety button has no standalone component wrapper. |
21
21
  | Safety-car control | `mountSafetyCarControl()` and drawer/race-controls compact embed | `src/ui/raceControlsTemplate.js` | Component surface frame helper for standalone, loading overlay, unsupported overlay, same `data-safety-car` button and control-state renderer | `controlStateRenderer.js` plus `F1SimulatorApp.bindControls()` | Standalone variant gets `data-paddock-component="safety-car-control"`. Compact variants are plain subcontrols inside race controls or drawer toolbar. |
22
- | Camera controls | `mountCameraControls()`, all-in-one external controls, embedded race-canvas controls, drawer toolbar | `src/ui/cameraControlsTemplate.js` | Component surface frame helper, shared `data-camera-mode`, zoom, banner mute, optional speed button, loading overlay, unsupported overlay | `controlStateRenderer.js`, `CameraController`, `F1SimulatorApp.bindControls()` | External variant adds `camera-controls--external`; embedded variant omits that class. Driver camera and simulation-speed buttons are option gated. |
22
+ | Camera controls | `mountCameraControls()`, all-in-one external controls, embedded race-canvas controls, drawer toolbar | `src/ui/cameraControlsTemplate.js` | Component surface frame helper, shared `data-camera-mode`, zoom, banner mute, optional speed button, loading overlay, unsupported overlay | `controlStateRenderer.js`, `CameraController`, `F1SimulatorApp.bindControls()` | External variant adds `camera-controls--external`; embedded variant omits that class. Driver camera and simulation-speed buttons are option gated. Zoom actions form one wrapping group; drawer camera-control rows fill available width. |
23
+ | View controls | `mountViewControls()`, all-in-one shell, drawer toolbar | `src/ui/viewControlsTemplate.js` | Component surface frame helper, camera-control styling, loading and unsupported overlays | `SimulatorViewControls`, `GridWalkController` | Separate from the canvas and centered entry selector. `ui.viewControls` chooses the default two-button switch or one Start race / Stop race action; both share the existing runtime view and focus handling, including after restart; disabled until startup and hidden while Grid Walk is disabled. Built-in compositions retain the hidden surface so enabling Grid Walk on restart can activate it. |
23
24
  | Timing tower | `mountTimingTower()`, all-in-one shell, embedded race canvas, drawer race canvas | `src/ui/timingTowerTemplate.js` | Component surface frame helper, race-control status banner, loading overlay, unsupported overlay, shared timing gap controls | `timingTowerRenderer.js`, `raceStatusRenderer.js`, `controlStateRenderer.js`, `F1SimulatorApp.observeLayoutResize()` | Embedded variants receive generated instance ids for `aria-controls`. `domBindings.js` exposes plural timing lists/header/status nodes and focused renderers fan out rows, lap counters, status banners, gap controls, and resize observation across every mounted tower owned by the same simulator. Header gap toggle may be hidden while controller APIs remain active. Width/proportions are package-owned and must not be tuned by host CSS. |
24
25
  | Race-control status banner | Timing tower internal component | `src/ui/raceControlStatusBanner.js` | Timing tower status slot | `raceStatusRenderer.js` | Internal only. It has no public mount because it is a timing-tower status affordance, not a standalone component. |
25
26
  | Race canvas | `mountRaceCanvas()` and shell/drawer templates | `src/ui/raceCanvasTemplate.js` | Component surface frame helper, steward message, optional embedded camera controls, optional race-data panel, optional sector banner, loading overlay, unsupported overlay | `F1SimulatorApp`, `CameraController`, Pixi renderers, `raceStatusRenderer.js`, `stewardMessageController.js`, `raceDataBannerController.js` | Base canvas can be canvas-only; options add timing tower, race-data lower-third, sector banner, FPS, physics indicator, and responsive narrow timing reveal. Race canvas is required before runtime start. |
@@ -34,25 +35,40 @@ This inventory maps package-owned UI surfaces to their shared bases, owner modul
34
35
  | Telemetry sector times | `mountTelemetrySectorTimes()` and telemetry stack | `src/ui/telemetryTemplates.js` | Telemetry module class helper, loading overlay, unsupported overlay | `telemetryRenderer.js` | Last/best sector table only. |
35
36
  | Car/driver overview | `mountCarDriverOverview()` and optional telemetry stack embed | `src/ui/carOverviewTemplate.js` | Component surface frame helper, overview field slots, loading overlay, unsupported overlay | `domBindings.js` cached field bindings, `carOverviewRenderer.js` | Standalone and stack-embedded variants share identical markup. Runtime toggles vehicle vs driver fields without remounting and updates cached label/value bindings instead of querying each field during render. |
36
37
  | Race telemetry drawer | `mountRaceTelemetryDrawer()` and complete preview template | `src/ui/telemetryDrawerTemplate.js` | Component surface frame helper, loading overlay, camera controls, compact safety-car control, race canvas with timing/data panel, telemetry stack, unsupported overlay | `F1SimulatorApp.setTelemetryDrawerOpen()`, `controlStateRenderer.js`, normal race/telemetry renderers | Higher-level mixed template. It intentionally owns toolbar placement, drawer ids, open/closed inert state, and responsive narrow drawer behavior. |
37
- | Loading overlay | All public startup-capable mounted surfaces, including all-in-one shell children and composable roots | `src/ui/templateUtils.js` | `createLoadingMarkup(label)` | `F1SimulatorApp.completeComponentLoading()` | Removed after startup after the initial frame. Component labels remain surface-specific for accessibility. Pre-JS placeholders are host-owned, not package-owned. |
38
+ | Loading overlay | All public startup-capable mounted surfaces, including all-in-one shell children and composable roots | `src/ui/templateUtils.js` | `createLoadingMarkup(label)` | `F1SimulatorApp.completeComponentLoading()` | Removed after startup after the initial frame. Component labels remain surface-specific for accessibility. Pre-JS placeholders are rendered by the host before package runtime starts, not by `F1SimulatorApp`. |
38
39
  | Pre-JS startup placeholder | `@inventure71/paddockjs/placeholder` and `@inventure71/paddockjs/placeholder.css` | `src/placeholder/index.js`, `src/placeholder.css` | Escaped inert HTML helper, optional tiny CSS start-light animation | Host page before root simulator import | Covers the network/import gap before the root package can render. It must stay independent of PixiJS, simulator assets, root runtime CSS, and app modules. |
39
40
  | Unsupported-size overlay | Public mount roots, shell, drawer, race/data/telemetry surfaces | `src/ui/templateUtils.js` | `createUnsupportedSizeMarkup(label)` | `installLayoutSupport()` | Display is driven by measured support state. Minimum size thresholds remain centralized in `layoutSupport.js`. |
40
41
 
41
- ## Local Preview Variants
42
+ ## Product Demo Chapters
42
43
 
43
- | Route or section | Package surfaces exercised | Owner in preview | Intentional difference |
44
+ The `site/` consumer is the product tour, not a second implementation of package UI. Its host layout and explanatory content stay outside `src/`; every simulator surface below comes from a public package entrypoint.
45
+
46
+ | Chapter | Public surfaces exercised | Demo owner | Purpose |
47
+ | --- | --- | --- | --- |
48
+ | Grid Walk and live race | `createPaddockSimulator()` plus `mountRaceTelemetryDrawer()` | `site/src/demo/runtime/mainShowcase.js` | Starts in Grid Walk, then resumes the same race in the complete broadcast workbench. Controller API controls and lifecycle callbacks remain live. |
49
+ | Compose | Every public composable mount on one shared controller | `site/src/demo/runtime/mainShowcase.js` | Shows each package-owned surface in a readable atlas without duplicating its generated markup. |
50
+ | Presets | `mountF1Simulator()` with dashboard, timing overlay, compact race, and full dashboard | `site/src/demo/runtime/presetShowcase.js` | Destroys and remounts each real all-in-one shell while keeping preset selection deep-linkable. |
51
+ | Race systems | Public rules options and live race state | `site/src/demo/ui/featureInventory.js` | Explains race flow, physics, strategy, stewarding, consequences, and classification without claiming unsupported systems. |
52
+ | Browser expert | `mountF1Simulator({ expert })` and `createPaddockDriverControllerLoop()` | `site/src/demo/runtime/expertLab.js` | Loads on demand and drives the same public action/observation contract with keyboard-owned host input and package sensor visualization. |
53
+ | Headless | `@inventure71/paddockjs/environment` | `site/src/demo/runtime/headlessLab.js` | Runs reset/step, observations, rewards, recorder, transition, evaluation, renderer hook, and worker protocol only when requested. |
54
+ | Feature inventory | Root, `/environment`, `/data`, and `/placeholder` declarations | `site/src/demo/data/featureCatalog.js` | Searchable catalogue whose public API coverage is enforced during the demo build. |
55
+
56
+ ## Guide And Labs Variants
57
+
58
+ | Route or section | Package surfaces exercised | Website owner | Intentional difference |
44
59
  | --- | --- | --- | --- |
45
- | Templates complete broadcast | `createPaddockSimulator()` plus `mountRaceTelemetryDrawer()` | `local-preview/src/main.js`, `local-preview/src/showcaseCatalog.js` | Demonstrates the highest-level mixed workbench with race, timing, lower-third, top controls, and drawer in one package-owned template. |
46
- | Templates dashboard, timing overlay, compact race, full dashboard | `mountF1Simulator()` with presets | `local-preview/src/main.js` | Demonstrates all-in-one shell presets and preset-first option override behavior. |
47
- | Templates banner option | `mountRaceCanvas()` plus external `mountCameraControls()` | `local-preview/src/main.js` | Demonstrates a composable race window that owns timing tower and race-data lower-third while camera controls remain separate. |
48
- | Components embedded window | `mountRaceCanvas()` with timing tower, data panel, sector banner plus external camera controls | `local-preview/src/main.js` | Exercises optional race-canvas embeds without the drawer wrapper. |
49
- | Components separate pieces | Every public composable mount | `local-preview/src/main.js` `COMPONENT_PIECE_MOUNTS` | Proves separate host roots still receive package CSS variables, loading state, layout support, and shared runtime updates. The preview inventory table is the single owner of the separate-piece root id to mount-helper mapping; the telemetry drawer remains separate because it is a mixed higher-level template with its own simulator. |
50
- | Customization route | Race canvas, overview, race-data panel, controls, timing tower, telemetry core | `local-preview/src/main.js` | Exercises theme packages, selected-team component theming, component overrides, and standalone vs embedded component theming. |
51
- | API route | Race telemetry drawer | `local-preview/src/main.js` | Exercises controller methods and snapshot readout beside the package-owned workbench. |
52
- | Behavior route | Multiple race-canvas variants | `local-preview/src/main.js` | Exercises timing expand/scroll, embedded camera controls, sector banner, finish panel, and deterministic behavior fixtures. |
53
- | Stewarding route | Race canvas with race-data panel and penalty UI options | `local-preview/src/main.js` | Exercises steward message, timing penalty badges, and penalty controller APIs. |
54
- | Playable route | Race telemetry drawer in browser expert mode | `local-preview/src/main.js`, `local-preview/src/playableKeyboardController.js` | Host-owned keyboard controller drives package-owned expert runtime; package UI remains the same drawer/canvas/timing/telemetry surfaces. |
55
- | Policy Runner route | All-in-one browser expert mount | `local-preview/src/main.js`, `local-preview/src/policyRunner/*` | Host-owned model/controller panel drives package expert APIs and model-sense visualization without changing package component markup. |
60
+ | Grid Walk | `createPaddockSimulator()` with `mountViewControls()` + `mountRaceCanvas()`, and an all-in-one shell fixture | `site/src/showcase/gridWalk.js` | Uses the same starting grid, project banner and simulator through wide/tall/container resizing, themes and mode transitions. |
61
+ | Templates complete broadcast | `createPaddockSimulator()` plus `mountRaceTelemetryDrawer()` | `site/src/showcase/main.js`, `site/src/showcase/showcaseCatalog.js` | Demonstrates the highest-level mixed workbench with race, timing, lower-third, top controls, and drawer in one package-owned template. |
62
+ | Templates dashboard, timing overlay, compact race, full dashboard | `mountF1Simulator()` with presets | `site/src/showcase/main.js` | Demonstrates all-in-one shell presets and preset-first option override behavior. |
63
+ | Templates banner option | `mountRaceCanvas()` plus external `mountCameraControls()` | `site/src/showcase/main.js` | Demonstrates a composable race window that owns timing tower and race-data lower-third while camera controls remain separate. |
64
+ | Components embedded window | `mountRaceCanvas()` with timing tower, data panel, sector banner plus external camera controls | `site/src/showcase/main.js` | Exercises optional race-canvas embeds without the drawer wrapper. |
65
+ | Components separate pieces | Every public composable mount | `site/src/showcase/main.js` `COMPONENT_PIECE_MOUNTS` | Proves separate host roots still receive package CSS variables, loading state, layout support, and shared runtime updates. The preview inventory table is the single owner of the separate-piece root id to mount-helper mapping; the telemetry drawer remains separate because it is a mixed higher-level template with its own simulator. |
66
+ | Customization route | Race canvas, overview, race-data panel, controls, timing tower, telemetry core | `site/src/showcase/main.js` | Exercises theme packages, selected-team component theming, component overrides, and standalone vs embedded component theming. |
67
+ | API route | Race telemetry drawer | `site/src/showcase/main.js` | Exercises controller methods and snapshot readout beside the package-owned workbench. |
68
+ | Behavior route | Multiple race-canvas variants | `site/src/showcase/main.js` | Exercises timing expand/scroll, embedded camera controls, sector banner, finish panel, and deterministic behavior fixtures. |
69
+ | Stewarding route | Race canvas with race-data panel and penalty UI options | `site/src/showcase/main.js` | Exercises steward message, timing penalty badges, and penalty controller APIs. |
70
+ | Playable route | Race telemetry drawer in browser expert mode | `site/src/showcase/main.js`, `site/src/showcase/playableKeyboardController.js` | Host-owned keyboard controller drives only while the game root is focused, visible and running; page keyboard scrolling and browser shortcuts remain available elsewhere. Click the track or focus its root to drive. Package UI remains the same drawer/canvas/timing/telemetry surfaces. |
71
+ | Policy Runner route | All-in-one browser expert mount | `site/src/showcase/main.js`, `site/src/showcase/policyRunner/*` | Host-owned model/controller panel drives package expert APIs and model-sense visualization without changing package component markup. |
56
72
 
57
73
  ## Duplication Map
58
74
 
@@ -70,4 +86,4 @@ This inventory maps package-owned UI surfaces to their shared bases, owner modul
70
86
  | Race-data lower-third and standalone panel | `bannerTemplates.js`, `domBindings.js`, and `raceDataBannerController.js` | Standalone adds one class and canvas embeds rely on placement | Intentional public placement difference with shared markup. Runtime state, open/dismiss controls, project mode, radio mode, and hide behavior fan out through grouped panel bindings so embedded and standalone panels do not drift. |
71
87
  | Timing tower standalone vs embedded | `timingTowerTemplate.js`, `raceCanvasTemplate.js`, `timingTowerRenderer.js`, `raceStatusRenderer.js` | Embedded adds reveal button/id and narrow classes in race canvas | Intentional because disclosure state belongs to the parent race canvas, not the tower. Runtime rows, lap counters, race-control status, and gap labels are shared across standalone and embedded towers through plural DOM bindings and focused readout renderers. |
72
88
  | Drawer and race-canvas responsive logic | `telemetryDrawerTemplate.js`, `raceCanvasTemplate.js`, `layoutSupport.js`, `raceOverlayClearanceSupport.js`, `layoutScheduler.js` | Drawer toolbar and race-canvas narrow reveal have distinct CSS classes | Intentional because they solve different container constraints while sharing component children. RAF scheduling/cancellation for layout measurement is shared so support checks and overlay clearance do not drift. |
73
- | Local preview route setup | `local-preview/src/main.js` | Route-specific controllers, timers, readouts, and the components-page `COMPONENT_PIECE_MOUNTS` table remain local | Intentional host-owned demo behavior. Package component logic must not move into preview. The components-page table centralizes preview wiring of public mount helpers without changing package contracts. |
89
+ | Guide/Labs route setup | `site/src/showcase/main.js` | Route-specific controllers, timers, readouts, and the components-page `COMPONENT_PIECE_MOUNTS` table remain local | Intentional host-owned demo behavior. Package component logic must not move into preview. The components-page table centralizes preview wiring of public mount helpers without changing package contracts. |
@@ -77,3 +77,5 @@ Browser expert mode changes are not a casual restart setting. Expert mode change
77
77
  Each mounted root receives PaddockJS component scope classes and package CSS variables. Hosts may size the outer roots, but timing-board width, broadcast proportions, camera safe area, drawer behavior, lower-thirds, focus styles, and touch targets remain package-owned.
78
78
 
79
79
  Use `includeTimingTower: true` when the race canvas should own the timing tower placement. Use `timingTowerVerticalFit: 'scroll'` to keep a fixed race height with a scrolling timing list, or `'expand-race-view'` when the race window may grow to fit the tower.
80
+
81
+ For a height-constrained standalone telemetry panel, give its host root a definite height (for example `height: 640px`). The stack owns internal scrolling. A host with only `max-height` can leave percentage sizing unresolved and let the stack overflow neighboring content.
package/docs/concepts.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Concepts
2
2
 
3
+ **Grid Walk** is the optional starting-grid discovery presentation. It uses the same world and cars with a responsive camera, labels, preparing crew and inspector. A **view switch** pauses/resumes playback and retains progress; an explicit **restart** creates a new race. Returning to Grid Walk presents original display poses without rewinding simulation state. See [Grid Walk](grid_walk.md).
4
+
3
5
  ## Host
4
6
 
5
7
  The host is the website or app that installs PaddockJS. The host provides data and chooses what happens when a driver/project is opened.
@@ -100,7 +102,7 @@ Driver ratings are `0-100` values converted into behavior inputs:
100
102
  - `patience`
101
103
  - `consistency`
102
104
 
103
- `50` is neutral.
105
+ `50` is neutral. Built-in racing separates ability (`pace` and `racecraft`), repeatability (`consistency`), and willingness to use smaller margins (`riskTolerance` and `aggression`). Strong cautious drivers retain precise control with more reserve; strong aggressive drivers exploit more of the same car. A less consistent driver has bounded continuous judgement variation, without scripted crashes or extra grip.
104
106
 
105
107
  ## Vehicle Ratings
106
108
 
@@ -135,6 +137,8 @@ Progress is the wrapped distance around the current lap.
135
137
 
136
138
  Race distance is cumulative and can increase beyond one lap. Ranking uses race distance, not wrapped progress.
137
139
 
140
+ Built-in driver traffic uses a separate physical gap: the local signed distance between wrapped track positions. Its passing/following target may be a lapped car or a car across the start line, while timing-board intervals and race ranking retain cumulative-distance semantics. Traffic lateral spacing uses chassis centers in the main-track frame; pit-local offsets and outer-wheel surface offsets are not interchangeable with that spacing.
141
+
138
142
  ## Sectors
139
143
 
140
144
  Every built track is divided into three equal sectors, published as `track.sectors`. Sector timing is derived from cumulative race distance crossing those sector boundaries, not from UI state.
@@ -201,3 +205,10 @@ PaddockJS bundles default simulator assets:
201
205
  - Asphalt texture.
202
206
 
203
207
  Hosts can override assets, but they should not need to provide them.
208
+
209
+
210
+ ## Advanced vehicle dynamics
211
+
212
+ Advanced mode resolves forces at four tire contact patches. A tire's normal load is its share of weight and aerodynamic load after longitudinal/lateral transfer. Combined grip means acceleration or braking uses some of the same adhesion needed for cornering. Tire load sensitivity means transferring load between two tires reduces their summed grip. Yaw inertia resists changes in body rotation; yaw arises from contact moments rather than a commanded turn rate. Body slip is velocity direction relative to heading, distinct from each tire's local slip angle. These are planar approximations; vertical suspension and individual wheel rotation are not simulated.
213
+
214
+ A driver policy force budget is a prediction, not delivered tire utilization. Advanced `gripUsage` reports requested force demand before longitudinal clamping and the nonlinear lateral brush response; values above one do not mean that much force was delivered. The limit-driving benchmark separately measures actual tire force divided by actual contact capacity. Arcade has a lateral-acceleration/yaw limit and no combined contact-force model; the benchmark reports that mode’s own delivered lateral utilization.
@@ -243,7 +243,7 @@ When external renderer mode is attached:
243
243
 
244
244
  - local expert `step()` is blocked
245
245
  - local expert `resetDrivers()` is blocked
246
- - local expert `reset()` is blocked in strict mode
246
+ - local expert `reset()` is blocked
247
247
 
248
248
  Detach before returning to browser-owned stepping:
249
249