@reicek/neataptic-ts 0.1.24 → 0.1.26

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 (215) hide show
  1. package/.github/copilot-instructions.md +11 -0
  2. package/.github/skills/trace-analyzer-extension/SKILL.md +3 -3
  3. package/.github/skills/trace-analyzer-extension/assets/extension-checklist.md +1 -1
  4. package/.github/skills/trace-analyzer-extension/references/analyzer-extension-workflow.md +1 -1
  5. package/.github/skills/trace-audit-reporting/SKILL.md +3 -3
  6. package/.github/skills/trace-audit-reporting/references/trace-analysis-workflow.md +1 -1
  7. package/.github/workflows/ci.yml +3 -3
  8. package/.github/workflows/deploy-pages.yml +6 -6
  9. package/.github/workflows/manual_release_pipeline.yml +3 -3
  10. package/.github/workflows/publish.yml +18 -19
  11. package/.github/workflows/release_dispatch.yml +3 -3
  12. package/package.json +26 -20
  13. package/plans/Flappy_Bird_Folder_Documentation_Pass.md +4 -4
  14. package/plans/README.md +24 -0
  15. package/plans/Roadmap.md +62 -40
  16. package/plans/analyze-trace-solid-split.plans.md +66 -0
  17. package/plans/architecture-solid-split.plans.md +9 -15
  18. package/plans/asciiMaze-typescript-repair.plans.md +1 -1
  19. package/plans/generate-docs-solid-split.plans.md +87 -0
  20. package/plans/methods-docs.plans.md +25 -1
  21. package/plans/methods-solid-split.plans.md +14 -14
  22. package/plans/neat-docs.plans.md +9 -1
  23. package/plans/neat-test-surface-repair.plans.md +1 -1
  24. package/plans/render-docs-html-solid-split.plans.md +68 -0
  25. package/plans/src-no-explicit-any-cleanup.plans.md +1 -1
  26. package/plans/utils-docs.plans.md +6 -1
  27. package/scripts/analyze-trace/analyze-trace.analysis.ts +479 -0
  28. package/scripts/analyze-trace/analyze-trace.constants.ts +35 -0
  29. package/scripts/analyze-trace/analyze-trace.io.ts +69 -0
  30. package/scripts/analyze-trace/analyze-trace.report.ts +100 -0
  31. package/scripts/analyze-trace/analyze-trace.shared.ts +116 -0
  32. package/scripts/analyze-trace/analyze-trace.ts +45 -0
  33. package/scripts/analyze-trace/analyze-trace.types.ts +72 -0
  34. package/scripts/assets/theme.css +80 -23
  35. package/scripts/copy-examples.ts +239 -0
  36. package/scripts/export-onnx.ts +223 -0
  37. package/scripts/generate-bench-tables.ts +378 -37
  38. package/scripts/generate-docs/generate-docs.constants.ts +107 -0
  39. package/scripts/generate-docs/generate-docs.order.ts +355 -0
  40. package/scripts/generate-docs/generate-docs.state.ts +31 -0
  41. package/scripts/generate-docs/generate-docs.targets.ts +165 -0
  42. package/scripts/generate-docs/generate-docs.ts +63 -0
  43. package/scripts/generate-docs/generate-docs.types.ts +112 -0
  44. package/scripts/generate-docs/output/generate-docs.output.folder-index.utils.ts +167 -0
  45. package/scripts/generate-docs/output/generate-docs.output.ordering.utils.ts +353 -0
  46. package/scripts/generate-docs/output/generate-docs.output.readme.utils.ts +420 -0
  47. package/scripts/generate-docs/output/generate-docs.output.ts +123 -0
  48. package/scripts/generate-docs/output/generate-docs.output.warnings.utils.ts +219 -0
  49. package/scripts/generate-docs/symbols/generate-docs.symbols.collection.utils.ts +365 -0
  50. package/scripts/generate-docs/symbols/generate-docs.symbols.jsdoc.utils.ts +373 -0
  51. package/scripts/generate-docs/symbols/generate-docs.symbols.normalize.utils.ts +155 -0
  52. package/scripts/generate-docs/symbols/generate-docs.symbols.render.utils.ts +149 -0
  53. package/scripts/generate-docs/symbols/generate-docs.symbols.signature.utils.ts +289 -0
  54. package/scripts/generate-docs/symbols/generate-docs.symbols.ts +11 -0
  55. package/scripts/mermaid-cli.mjs +102 -22
  56. package/scripts/mermaid-cli.ts +736 -0
  57. package/scripts/render-docs-html/render-docs-html.assets.ts +54 -0
  58. package/scripts/render-docs-html/render-docs-html.mermaid.ts +245 -0
  59. package/scripts/{render-docs-html.sidebar.ts → render-docs-html/render-docs-html.navigation.ts} +141 -144
  60. package/scripts/render-docs-html/render-docs-html.pages.ts +333 -0
  61. package/scripts/render-docs-html/render-docs-html.shared.ts +333 -0
  62. package/scripts/render-docs-html/render-docs-html.types.ts +42 -0
  63. package/scripts/render-docs-html.ts +23 -587
  64. package/scripts/run-docs.ts +238 -0
  65. package/scripts/write-dist-docs-pkg.ts +40 -0
  66. package/src/README.md +75 -75
  67. package/src/architecture/connection/README.md +5 -5
  68. package/src/architecture/layer/README.md +508 -508
  69. package/src/architecture/network/README.md +1458 -1458
  70. package/src/architecture/network/activate/README.md +694 -694
  71. package/src/architecture/network/bootstrap/README.md +77 -77
  72. package/src/architecture/network/connect/README.md +74 -74
  73. package/src/architecture/network/deterministic/README.md +135 -135
  74. package/src/architecture/network/evolve/README.md +364 -364
  75. package/src/architecture/network/gating/README.md +130 -130
  76. package/src/architecture/network/genetic/README.md +399 -399
  77. package/src/architecture/network/mutate/README.md +897 -897
  78. package/src/architecture/network/onnx/README.md +720 -720
  79. package/src/architecture/network/onnx/export/README.md +728 -728
  80. package/src/architecture/network/onnx/export/layers/README.md +450 -450
  81. package/src/architecture/network/onnx/import/README.md +618 -618
  82. package/src/architecture/network/onnx/schema/README.md +32 -32
  83. package/src/architecture/network/prune/README.md +245 -245
  84. package/src/architecture/network/remove/README.md +135 -135
  85. package/src/architecture/network/runtime/README.md +106 -106
  86. package/src/architecture/network/serialize/README.md +542 -542
  87. package/src/architecture/network/slab/README.md +608 -608
  88. package/src/architecture/network/standalone/README.md +212 -212
  89. package/src/architecture/network/stats/README.md +84 -84
  90. package/src/architecture/network/topology/README.md +465 -465
  91. package/src/architecture/network/training/README.md +200 -200
  92. package/src/architecture/node/README.md +5 -5
  93. package/src/architecture/nodePool/README.md +14 -14
  94. package/src/methods/README.md +99 -99
  95. package/src/methods/activation/README.md +189 -189
  96. package/src/methods/cost/README.md +131 -131
  97. package/src/methods/rate/README.md +86 -86
  98. package/src/multithreading/README.md +77 -77
  99. package/src/multithreading/workers/browser/README.md +8 -8
  100. package/src/multithreading/workers/node/README.md +8 -8
  101. package/src/neat/README.md +148 -148
  102. package/src/neat/adaptive/README.md +120 -120
  103. package/src/neat/adaptive/acceptance/README.md +40 -40
  104. package/src/neat/adaptive/complexity/README.md +137 -137
  105. package/src/neat/adaptive/core/README.md +197 -197
  106. package/src/neat/adaptive/lineage/README.md +90 -90
  107. package/src/neat/adaptive/mutation/README.md +284 -284
  108. package/src/neat/compat/README.md +43 -43
  109. package/src/neat/compat/core/README.md +90 -90
  110. package/src/neat/diversity/README.md +35 -35
  111. package/src/neat/diversity/core/README.md +88 -88
  112. package/src/neat/evaluate/README.md +85 -85
  113. package/src/neat/evaluate/auto-distance/README.md +75 -75
  114. package/src/neat/evaluate/entropy-compat/README.md +37 -37
  115. package/src/neat/evaluate/entropy-sharing/README.md +43 -43
  116. package/src/neat/evaluate/fitness/README.md +23 -23
  117. package/src/neat/evaluate/novelty/README.md +120 -120
  118. package/src/neat/evaluate/objectives/README.md +17 -17
  119. package/src/neat/evaluate/shared/README.md +94 -94
  120. package/src/neat/evolve/README.md +96 -96
  121. package/src/neat/evolve/adaptive/README.md +60 -60
  122. package/src/neat/evolve/objectives/README.md +63 -63
  123. package/src/neat/evolve/offspring/README.md +56 -56
  124. package/src/neat/evolve/population/README.md +171 -171
  125. package/src/neat/evolve/runtime/README.md +79 -79
  126. package/src/neat/evolve/speciation/README.md +74 -74
  127. package/src/neat/evolve/warnings/README.md +10 -10
  128. package/src/neat/export/README.md +114 -114
  129. package/src/neat/helpers/README.md +50 -50
  130. package/src/neat/init/README.md +9 -9
  131. package/src/neat/lineage/core/README.md +101 -101
  132. package/src/neat/multiobjective/category/README.md +74 -74
  133. package/src/neat/multiobjective/crowding/README.md +272 -272
  134. package/src/neat/multiobjective/dominance/README.md +171 -171
  135. package/src/neat/multiobjective/fronts/README.md +68 -68
  136. package/src/neat/multiobjective/metrics/README.md +43 -43
  137. package/src/neat/multiobjective/objectives/README.md +31 -31
  138. package/src/neat/multiobjective/shared/README.md +27 -27
  139. package/src/neat/mutation/README.md +97 -97
  140. package/src/neat/mutation/add-conn/README.md +115 -115
  141. package/src/neat/mutation/add-node/README.md +126 -126
  142. package/src/neat/mutation/flow/README.md +149 -149
  143. package/src/neat/mutation/repair/README.md +185 -185
  144. package/src/neat/mutation/select/README.md +117 -117
  145. package/src/neat/mutation/shared/README.md +32 -32
  146. package/src/neat/objectives/README.md +25 -25
  147. package/src/neat/objectives/core/README.md +67 -67
  148. package/src/neat/pruning/README.md +40 -40
  149. package/src/neat/pruning/core/README.md +171 -171
  150. package/src/neat/pruning/facade/README.md +32 -32
  151. package/src/neat/rng/README.md +104 -104
  152. package/src/neat/rng/core/README.md +137 -137
  153. package/src/neat/rng/facade/README.md +50 -50
  154. package/src/neat/selection/README.md +111 -111
  155. package/src/neat/selection/core/README.md +227 -227
  156. package/src/neat/selection/facade/README.md +61 -61
  157. package/src/neat/shared/README.md +163 -163
  158. package/src/neat/speciation/README.md +31 -31
  159. package/src/neat/speciation/threshold/README.md +35 -35
  160. package/src/neat/species/README.md +25 -25
  161. package/src/neat/species/core/README.md +20 -20
  162. package/src/neat/species/core/shared/README.md +18 -18
  163. package/src/neat/species/history/context/README.md +22 -22
  164. package/src/neat/telemetry/accessors/README.md +58 -58
  165. package/src/neat/telemetry/exports/README.md +233 -233
  166. package/src/neat/telemetry/facade/README.md +252 -252
  167. package/src/neat/telemetry/facade/archive/README.md +57 -57
  168. package/src/neat/telemetry/facade/buffer/README.md +43 -43
  169. package/src/neat/telemetry/facade/lineage/README.md +12 -12
  170. package/src/neat/telemetry/facade/objectives/README.md +44 -44
  171. package/src/neat/telemetry/facade/runtime/README.md +26 -26
  172. package/src/neat/telemetry/facade/species/README.md +27 -27
  173. package/src/neat/telemetry/metrics/README.md +696 -696
  174. package/src/neat/telemetry/recorder/README.md +57 -57
  175. package/src/neat/telemetry/types/README.md +32 -32
  176. package/src/neat/topology-intent/README.md +75 -75
  177. package/src/utils/README.md +193 -193
  178. package/test/examples/asciiMaze/browser-entry/README.md +92 -92
  179. package/test/examples/asciiMaze/dashboardManager/README.md +109 -109
  180. package/test/examples/asciiMaze/dashboardManager/telemetry/README.md +28 -28
  181. package/test/examples/asciiMaze/evolutionEngine/README.md +1527 -1527
  182. package/test/examples/asciiMaze/mazeMovement/README.md +105 -105
  183. package/test/examples/asciiMaze/mazeMovement/finalization/README.md +16 -16
  184. package/test/examples/asciiMaze/mazeMovement/policy/README.md +57 -57
  185. package/test/examples/asciiMaze/mazeMovement/runtime/README.md +52 -52
  186. package/test/examples/asciiMaze/mazeMovement/shaping/README.md +46 -46
  187. package/test/examples/flappy_bird/browser-entry/README.md +508 -508
  188. package/test/examples/flappy_bird/browser-entry/host/README.md +101 -101
  189. package/test/examples/flappy_bird/browser-entry/host/resize/README.md +144 -144
  190. package/test/examples/flappy_bird/browser-entry/network-view/README.md +194 -194
  191. package/test/examples/flappy_bird/browser-entry/playback/README.md +278 -278
  192. package/test/examples/flappy_bird/browser-entry/playback/background/README.md +129 -129
  193. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/README.md +502 -502
  194. package/test/examples/flappy_bird/browser-entry/playback/frame-render/README.md +139 -139
  195. package/test/examples/flappy_bird/browser-entry/playback/snapshot/README.md +10 -10
  196. package/test/examples/flappy_bird/browser-entry/playback/trail/README.md +43 -43
  197. package/test/examples/flappy_bird/browser-entry/playback/worker-channel/README.md +30 -30
  198. package/test/examples/flappy_bird/browser-entry/runtime/README.md +59 -59
  199. package/test/examples/flappy_bird/browser-entry/visualization/README.md +276 -276
  200. package/test/examples/flappy_bird/browser-entry/worker-channel/README.md +16 -16
  201. package/test/examples/flappy_bird/constants/README.md +1070 -1070
  202. package/test/examples/flappy_bird/environment/README.md +22 -22
  203. package/test/examples/flappy_bird/evaluation/README.md +32 -32
  204. package/test/examples/flappy_bird/evaluation/rollout/README.md +141 -141
  205. package/test/examples/flappy_bird/flappy-evolution-worker/README.md +425 -425
  206. package/test/examples/flappy_bird/simulation-shared/README.md +170 -170
  207. package/test/examples/flappy_bird/simulation-shared/observation/README.md +109 -109
  208. package/test/examples/flappy_bird/trainer/README.md +325 -325
  209. package/test/examples/flappy_bird/trainer/evaluation/README.md +74 -74
  210. package/scripts/analyze-trace.ts +0 -590
  211. package/scripts/copy-examples.mjs +0 -114
  212. package/scripts/export-onnx.mjs +0 -86
  213. package/scripts/generate-bench-tables.mjs +0 -182
  214. package/scripts/generate-docs.ts +0 -2900
  215. package/scripts/write-dist-docs-pkg.mjs +0 -16
@@ -14,6 +14,10 @@ arrays and counters through every hot-path helper.
14
14
 
15
15
  ## evolutionEngine/engineState.types.ts
16
16
 
17
+ ### EngineProfilingState
18
+
19
+ Aggregated profiling configuration and accumulators shared across the evolution run.
20
+
17
21
  ### EngineScratchState
18
22
 
19
23
  Centralised shared state for the ASCII maze evolution façade.
@@ -26,33 +30,29 @@ Responsibilities:
26
30
 
27
31
  Callers mutate the returned scratch instances in place to avoid per-generation allocations; higher-level modules should treat the helpers as the sole entry point for sizing or resetting shared buffers.
28
32
 
29
- ### EngineToggleState
30
-
31
- Runtime switches that adjust telemetry verbosity and optional training phases.
32
-
33
- ### EngineProfilingState
34
-
35
- Aggregated profiling configuration and accumulators shared across the evolution run.
36
-
37
33
  ### EngineState
38
34
 
39
35
  Shared engine state instance combining pooled scratch buffers with toggle flags.
40
36
 
41
- ### TelemetryScratchRequest
37
+ ### EngineToggleState
42
38
 
43
- Configuration describing which telemetry scratch buffers require capacity guarantees.
39
+ Runtime switches that adjust telemetry verbosity and optional training phases.
44
40
 
45
- ### TelemetryScratchHandles
41
+ ### RngCacheHandles
46
42
 
47
- Collection of scratch buffers handed back after initialisation for convenience.
43
+ Handles returned after ensuring the RNG cache is ready for consumption.
48
44
 
49
45
  ### RngCacheParameters
50
46
 
51
47
  Parameters controlling the RNG cache refill process.
52
48
 
53
- ### RngCacheHandles
49
+ ### TelemetryScratchHandles
54
50
 
55
- Handles returned after ensuring the RNG cache is ready for consumption.
51
+ Collection of scratch buffers handed back after initialisation for convenience.
52
+
53
+ ### TelemetryScratchRequest
54
+
55
+ Configuration describing which telemetry scratch buffers require capacity guarantees.
56
56
 
57
57
  ### VisitedHashScratchHandles
58
58
 
@@ -60,25 +60,34 @@ Handles exposed after ensuring the visited-coordinate hash table capacity.
60
60
 
61
61
  ## evolutionEngine/evolutionEngine.types.ts
62
62
 
63
- ### IMazeConfig
63
+ ### DistanceMap
64
64
 
65
- Maze configuration used by the ASCII Maze evolution helpers.
65
+ Distance map for maze navigation.
66
66
 
67
- ### IAgentSimulationConfig
67
+ ### EncodedMaze
68
68
 
69
- Agent simulation configuration.
69
+ Encoded maze representation with cell values.
70
70
 
71
- ### IEvolutionAlgorithmConfig
71
+ ### EncodedMazeData
72
72
 
73
- Configuration options for the evolutionary algorithm used in the ASCII Maze demos.
73
+ Encoded maze for simulation.
74
74
 
75
- ### EvolutionStopReason
75
+ ### EvolutionEngineFacadeRuntimeState
76
76
 
77
- Canonical stop reasons reported by the engine to host adapters.
77
+ Mutable runtime state owned by the public EvolutionEngine facade.
78
78
 
79
- ### EvolutionHostStopEvent
79
+ The extracted engine modules already share pooled buffers through
80
+ `engineState`. This narrower state exists only for the facade-specific
81
+ logits-ring bookkeeping that must survive across runs while keeping the
82
+ class boundary orchestration-first.
80
83
 
81
- Host-facing stop event emitted by the engine when a run finishes for a concrete reason.
84
+ ### EvolutionGenomeLike
85
+
86
+ Loose genome shape shared by engine telemetry and population-dynamics helpers.
87
+
88
+ ### EvolutionHelpers
89
+
90
+ Helper functions object passed to evolution loop orchestration.
82
91
 
83
92
  ### EvolutionHostAdapter
84
93
 
@@ -93,167 +102,158 @@ const hostAdapter: EvolutionHostAdapter = {
93
102
  };
94
103
  ```
95
104
 
96
- ### IReportingConfig
97
-
98
- Reporting configuration used to control logging, dashboard updates and UI pacing.
99
-
100
- ### IRunMazeEvolutionOptions
101
-
102
- Main options for running a single maze-evolution experiment.
105
+ ### EvolutionHostStopEvent
103
106
 
104
- ### MazeEvolutionRunResult
107
+ Host-facing stop event emitted by the engine when a run finishes for a concrete reason.
105
108
 
106
- Stable result returned by `EvolutionEngine.runMazeEvolution()`.
109
+ ### EvolutionLoopHelpers
107
110
 
108
- ### MazeEvolutionCurriculumPhaseOutcome
111
+ Helper functions for evolution.
109
112
 
110
- Shared curriculum-facing summary derived from one completed evolution phase.
113
+ ### EvolutionLoopRuntimeContext
111
114
 
112
- ### NeatInstance
115
+ Shared runtime buffers and limits consumed by the evolution loop hot path.
113
116
 
114
- Type for Neat class instance from the neataptic library.
117
+ This context keeps the loop and simulation helpers from passing a long list
118
+ of pooled ring buffers, scratch arrays, and capacity limits positionally.
115
119
 
116
- ### NetworkInstance
120
+ ### EvolutionLoopSupportContext
117
121
 
118
- Type for Network class instance from the neataptic library.
122
+ Shared scratch buffers and helper callbacks used across evolution-loop stages.
119
123
 
120
- ### TrackedNetworkInstance
124
+ This context groups the scratch arrays and analysis helpers that travel
125
+ together through generation, simulation, and snapshot paths.
121
126
 
122
- Network instance annotated with telemetry fields during a generation.
127
+ ### EvolutionLoopTelemetryContext
123
128
 
124
- ### EvolutionGenomeLike
129
+ Shared telemetry thresholds consumed by the evolution loop simulation pass.
125
130
 
126
- Loose genome shape shared by engine telemetry and population-dynamics helpers.
131
+ The loop owns these switches conceptually, but grouping them as one context
132
+ keeps telemetry policy changes from widening hot-path function signatures.
127
133
 
128
- ### TelemetryNeatLike
134
+ ### EvolutionOptions
129
135
 
130
- NEAT runtime shape needed by telemetry helpers that inspect the population.
136
+ Options object passed to evolution functions.
131
137
 
132
- The telemetry helpers intentionally ask for very little here: access to the
133
- population plus optional telemetry export. That keeps them portable across the
134
- engine's internal helpers without binding them to the full driver surface.
138
+ ### EvolutionStopReason
135
139
 
136
- ### MutationOperationLike
140
+ Canonical stop reasons reported by the engine to host adapters.
137
141
 
138
- Mutation-operation surface read from the NEAT driver at runtime.
142
+ ### FileSystem
139
143
 
140
- The engine treats mutation operations as opaque descriptors because the
141
- concrete driver owns how those operations are interpreted. The helpers only
142
- need enough structure to cache, count, and hand them back into `mutate(...)`.
144
+ Node.js fs module type for file operations.
143
145
 
144
- ### SpeciesHistoryHost
146
+ ### IAgentSimulationConfig
145
147
 
146
- Static host used to read optional species-history state from the engine facade.
148
+ Agent simulation configuration.
147
149
 
148
- ### EncodedMaze
150
+ ### IEvolutionAlgorithmConfig
149
151
 
150
- Encoded maze representation with cell values.
152
+ Configuration options for the evolutionary algorithm used in the ASCII Maze demos.
151
153
 
152
- ### Position
154
+ ### IMazeConfig
153
155
 
154
- 2D position in maze coordinates.
156
+ Maze configuration used by the ASCII Maze evolution helpers.
155
157
 
156
- ### DistanceMap
158
+ ### IReportingConfig
157
159
 
158
- Distance map for maze navigation.
160
+ Reporting configuration used to control logging, dashboard updates and UI pacing.
159
161
 
160
- ### EvolutionOptions
162
+ ### IRunMazeEvolutionOptions
161
163
 
162
- Options object passed to evolution functions.
164
+ Main options for running a single maze-evolution experiment.
163
165
 
164
- ### EvolutionHelpers
166
+ ### LogitsRingState
165
167
 
166
- Helper functions object passed to evolution loop orchestration.
168
+ Ring state for logits tracking.
167
169
 
168
- ### ProfilingAccumulators
170
+ ### LoopHelpers
169
171
 
170
- Profiling accumulator structure.
172
+ Loop helpers returned by prepareLoopHelpers.
171
173
 
172
- ### FileSystem
174
+ ### MazeDistanceMap
173
175
 
174
- Node.js fs module type for file operations.
176
+ Distance map for pathfinding.
175
177
 
176
- ### PathModule
178
+ ### MazeEvolutionCurriculumPhaseOutcome
177
179
 
178
- Node.js path module type.
180
+ Shared curriculum-facing summary derived from one completed evolution phase.
179
181
 
180
- ### LoopHelpers
182
+ ### MazeEvolutionRunResult
181
183
 
182
- Loop helpers returned by prepareLoopHelpers.
184
+ Stable result returned by `EvolutionEngine.runMazeEvolution()`.
183
185
 
184
- ### ScratchBundle
186
+ ### MazePosition
185
187
 
186
- Scratch bundle containing reusable buffers.
188
+ Position in maze.
187
189
 
188
- ### SnapshotEntry
190
+ ### MutationOperationLike
189
191
 
190
- Snapshot entry for persistence.
192
+ Mutation-operation surface read from the NEAT driver at runtime.
191
193
 
192
- ### TrainingConstants
194
+ The engine treats mutation operations as opaque descriptors because the
195
+ concrete driver owns how those operations are interpreted. The helpers only
196
+ need enough structure to cache, count, and hand them back into `mutate(...)`.
193
197
 
194
- Training constants used by Lamarckian warm-start and refinement helpers.
198
+ ### NeatInstance
195
199
 
196
- ### EvolutionLoopHelpers
200
+ Type for Neat class instance from the neataptic library.
197
201
 
198
- Helper functions for evolution.
202
+ ### NetworkConnection
199
203
 
200
- ### EvolutionLoopRuntimeContext
204
+ Network connection representation used by engine-side runtime adaptation helpers.
201
205
 
202
- Shared runtime buffers and limits consumed by the evolution loop hot path.
206
+ ### NetworkInstance
203
207
 
204
- This context keeps the loop and simulation helpers from passing a long list
205
- of pooled ring buffers, scratch arrays, and capacity limits positionally.
208
+ Type for Network class instance from the neataptic library.
206
209
 
207
- ### EvolutionLoopTelemetryContext
210
+ ### NetworkNode
208
211
 
209
- Shared telemetry thresholds consumed by the evolution loop simulation pass.
212
+ Network node representation used by engine-side runtime adaptation helpers.
210
213
 
211
- The loop owns these switches conceptually, but grouping them as one context
212
- keeps telemetry policy changes from widening hot-path function signatures.
214
+ ### PathModule
213
215
 
214
- ### EvolutionLoopSupportContext
216
+ Node.js path module type.
215
217
 
216
- Shared scratch buffers and helper callbacks used across evolution-loop stages.
218
+ ### Position
217
219
 
218
- This context groups the scratch arrays and analysis helpers that travel
219
- together through generation, simulation, and snapshot paths.
220
+ 2D position in maze coordinates.
220
221
 
221
- ### NetworkNode
222
+ ### ProfilingAccumulators
222
223
 
223
- Network node representation used by engine-side runtime adaptation helpers.
224
+ Profiling accumulator structure.
224
225
 
225
- ### NetworkConnection
226
+ ### ScratchBundle
226
227
 
227
- Network connection representation used by engine-side runtime adaptation helpers.
228
+ Scratch bundle containing reusable buffers.
228
229
 
229
- ### EncodedMazeData
230
+ ### SimulationResult
230
231
 
231
- Encoded maze for simulation.
232
+ Simulation result returned by generation evaluation helpers.
232
233
 
233
- ### MazePosition
234
+ ### SnapshotEntry
234
235
 
235
- Position in maze.
236
+ Snapshot entry for persistence.
236
237
 
237
- ### MazeDistanceMap
238
+ ### SpeciesHistoryHost
238
239
 
239
- Distance map for pathfinding.
240
+ Static host used to read optional species-history state from the engine facade.
240
241
 
241
- ### LogitsRingState
242
+ ### TelemetryNeatLike
242
243
 
243
- Ring state for logits tracking.
244
+ NEAT runtime shape needed by telemetry helpers that inspect the population.
244
245
 
245
- ### EvolutionEngineFacadeRuntimeState
246
+ The telemetry helpers intentionally ask for very little here: access to the
247
+ population plus optional telemetry export. That keeps them portable across the
248
+ engine's internal helpers without binding them to the full driver surface.
246
249
 
247
- Mutable runtime state owned by the public EvolutionEngine facade.
250
+ ### TrackedNetworkInstance
248
251
 
249
- The extracted engine modules already share pooled buffers through
250
- `engineState`. This narrower state exists only for the facade-specific
251
- logits-ring bookkeeping that must survive across runs while keeping the
252
- class boundary orchestration-first.
252
+ Network instance annotated with telemetry fields during a generation.
253
253
 
254
- ### SimulationResult
254
+ ### TrainingConstants
255
255
 
256
- Simulation result returned by generation evaluation helpers.
256
+ Training constants used by Lamarckian warm-start and refinement helpers.
257
257
 
258
258
  ## evolutionEngine/sampling.ts
259
259
 
@@ -268,38 +268,89 @@ These helpers look small, but they sit under several hot paths. The main job
268
268
  is not "random choice" in the abstract; it is random choice without quietly
269
269
  reintroducing per-generation array churn into long-running experiments.
270
270
 
271
- ### sampleArray
271
+ ### getTail
272
272
 
273
273
  ```ts
274
- sampleArray(
274
+ getTail(
275
275
  state: EngineState,
276
- source: T[],
277
- sampleCount: number,
276
+ source: T[] | undefined,
277
+ count: number,
278
278
  ): T[]
279
279
  ```
280
280
 
281
- Sample `sampleCount` items (with replacement) from `source` into the pooled scratch buffer.
282
-
283
- This helper is for callers that want an ephemeral array view immediately. The
284
- returned array reuses shared scratch storage, so callers should copy it first
285
- if they need the contents to survive another helper call.
281
+ Extract the last `count` items from `source` into the shared tail buffer.
286
282
 
287
283
  Steps:
288
- 1. Validate the input array and normalise `sampleCount` to an integer.
289
- 2. Grow the shared `sampleResultBuffer` to the next power of two when capacity is insufficient.
290
- 3. Fill the pooled buffer using the shared fast RNG and truncate the logical length to `sampleCount`.
284
+ 1. Validate the source array and clamp the requested tail length.
285
+ 2. Grow the pooled tail buffer to the next power of two when necessary.
286
+ 3. Copy the suffix into the pooled buffer and trim its logical length.
291
287
 
292
288
  Parameters:
293
- - `state` - Shared engine state providing pooled scratch buffers.
294
- - `source` - Source array to sample from.
295
- - `sampleCount` - Number of samples to draw (with replacement).
289
+ - `state` - Shared engine state providing the tail history buffer.
290
+ - `source` - Source array reference.
291
+ - `count` - Number of trailing items requested.
296
292
 
297
- Returns: Pooled ephemeral array containing the sampled elements.
293
+ Returns: Pooled array containing the requested tail slice.
298
294
 
299
295
  Example:
300
296
 
301
- const picks = sampleArray(sharedState, population, 16);
302
- const safeCopy = [...picks];
297
+ const recent = getTail(sharedState, telemetryLog, 40);
298
+
299
+ ### pushHistory
300
+
301
+ ```ts
302
+ pushHistory(
303
+ buffer: T[] | undefined,
304
+ value: T,
305
+ maxLength: number,
306
+ ): T[]
307
+ ```
308
+
309
+ Proxy to {@link MazeUtils.pushHistory} for consistency with the façade API.
310
+
311
+ Parameters:
312
+ - `buffer` - Existing history buffer (may be undefined).
313
+ - `value` - Value to append to the buffer.
314
+ - `maxLength` - Maximum allowed buffer length.
315
+
316
+ Returns: Updated history buffer with `value` appended and trimmed to `maxLength`.
317
+
318
+ Example:
319
+
320
+ const history = pushHistory(existingHistory, snapshot, 20);
321
+
322
+ ### sampleArray
323
+
324
+ ```ts
325
+ sampleArray(
326
+ state: EngineState,
327
+ source: T[],
328
+ sampleCount: number,
329
+ ): T[]
330
+ ```
331
+
332
+ Sample `sampleCount` items (with replacement) from `source` into the pooled scratch buffer.
333
+
334
+ This helper is for callers that want an ephemeral array view immediately. The
335
+ returned array reuses shared scratch storage, so callers should copy it first
336
+ if they need the contents to survive another helper call.
337
+
338
+ Steps:
339
+ 1. Validate the input array and normalise `sampleCount` to an integer.
340
+ 2. Grow the shared `sampleResultBuffer` to the next power of two when capacity is insufficient.
341
+ 3. Fill the pooled buffer using the shared fast RNG and truncate the logical length to `sampleCount`.
342
+
343
+ Parameters:
344
+ - `state` - Shared engine state providing pooled scratch buffers.
345
+ - `source` - Source array to sample from.
346
+ - `sampleCount` - Number of samples to draw (with replacement).
347
+
348
+ Returns: Pooled ephemeral array containing the sampled elements.
349
+
350
+ Example:
351
+
352
+ const picks = sampleArray(sharedState, population, 16);
353
+ const safeCopy = [...picks];
303
354
 
304
355
  ### sampleIntoScratch
305
356
 
@@ -370,57 +421,6 @@ Example:
370
421
  const written = sampleSegmentIntoScratch(sharedState, population, elitismCount, 12);
371
422
  const genome = sharedState.scratch.samplePool[0];
372
423
 
373
- ### getTail
374
-
375
- ```ts
376
- getTail(
377
- state: EngineState,
378
- source: T[] | undefined,
379
- count: number,
380
- ): T[]
381
- ```
382
-
383
- Extract the last `count` items from `source` into the shared tail buffer.
384
-
385
- Steps:
386
- 1. Validate the source array and clamp the requested tail length.
387
- 2. Grow the pooled tail buffer to the next power of two when necessary.
388
- 3. Copy the suffix into the pooled buffer and trim its logical length.
389
-
390
- Parameters:
391
- - `state` - Shared engine state providing the tail history buffer.
392
- - `source` - Source array reference.
393
- - `count` - Number of trailing items requested.
394
-
395
- Returns: Pooled array containing the requested tail slice.
396
-
397
- Example:
398
-
399
- const recent = getTail(sharedState, telemetryLog, 40);
400
-
401
- ### pushHistory
402
-
403
- ```ts
404
- pushHistory(
405
- buffer: T[] | undefined,
406
- value: T,
407
- maxLength: number,
408
- ): T[]
409
- ```
410
-
411
- Proxy to {@link MazeUtils.pushHistory} for consistency with the façade API.
412
-
413
- Parameters:
414
- - `buffer` - Existing history buffer (may be undefined).
415
- - `value` - Value to append to the buffer.
416
- - `maxLength` - Maximum allowed buffer length.
417
-
418
- Returns: Updated history buffer with `value` appended and trimmed to `maxLength`.
419
-
420
- Example:
421
-
422
- const history = pushHistory(existingHistory, snapshot, 20);
423
-
424
424
  ## evolutionEngine/engineState.ts
425
425
 
426
426
  Centralised shared state for the ASCII maze evolution façade.
@@ -433,57 +433,30 @@ Responsibilities:
433
433
 
434
434
  Callers mutate the returned scratch instances in place to avoid per-generation allocations; higher-level modules should treat the helpers as the sole entry point for sizing or resetting shared buffers.
435
435
 
436
- ### EngineProfilingState
437
-
438
- Aggregated profiling configuration and accumulators shared across the evolution run.
439
-
440
- ### EngineScratchState
441
-
442
- Centralised shared state for the ASCII maze evolution façade.
443
-
444
- Responsibilities:
445
- 1. Define the scratch-buffer schema consumed by telemetry, population, and inspection helpers.
446
- 2. Expose runtime toggle state (`EngineToggleState`) that drives optional phases and telemetry density.
447
- 3. Provide factory and maintenance helpers (`createEngineState`, `initialiseTelemetryScratch`, `ensureVisitedHashCapacity`, `ensureRngCacheBatch`, `reseedRngState`) that size buffers and keep deterministic RNG state in sync.
448
- 4. Export the project-wide singleton `engineState` so extracted modules can share the façade’s pooled resources while still accepting injected state for testing.
449
-
450
- Callers mutate the returned scratch instances in place to avoid per-generation allocations; higher-level modules should treat the helpers as the sole entry point for sizing or resetting shared buffers.
451
-
452
- ### EngineState
453
-
454
- Shared engine state instance combining pooled scratch buffers with toggle flags.
455
-
456
- ### EngineToggleState
457
-
458
- Runtime switches that adjust telemetry verbosity and optional training phases.
459
-
460
- ### RngCacheHandles
461
-
462
- Handles returned after ensuring the RNG cache is ready for consumption.
463
-
464
- ### RngCacheParameters
465
-
466
- Parameters controlling the RNG cache refill process.
467
-
468
- ### TelemetryScratchHandles
436
+ ### createEngineState
469
437
 
470
- Collection of scratch buffers handed back after initialisation for convenience.
438
+ ```ts
439
+ createEngineState(): EngineState
440
+ ```
471
441
 
472
- ### TelemetryScratchRequest
442
+ Fabricates a new {@link EngineState} with pre-sized scratch buffers and default toggle values.
473
443
 
474
- Configuration describing which telemetry scratch buffers require capacity guarantees.
444
+ Returns: Initialized engine state used by the maze evolution façade.
475
445
 
476
- ### VisitedHashScratchHandles
446
+ ### createProfilingState
477
447
 
478
- Handles exposed after ensuring the visited-coordinate hash table capacity.
448
+ ```ts
449
+ createProfilingState(): EngineProfilingState
450
+ ```
479
451
 
480
- ### DEFAULT_RNG_CACHE_BATCH_SIZE
452
+ Fabricates the profiling state bundle consumed by timing helpers.
481
453
 
482
- Default RNG cache batch size mirroring the façade constant.
454
+ Returns: Profiling configuration and accumulator state.
483
455
 
484
- ### DEFAULT_VISITED_HASH_LOAD_FACTOR
456
+ Example:
485
457
 
486
- Default load factor target for the visited coordinate hash table.
458
+ const profiling = createProfilingState();
459
+ console.log(profiling.detailsEnabled); // false unless env flag set
487
460
 
488
461
  ### createScratchState
489
462
 
@@ -515,30 +488,54 @@ Example:
515
488
  const toggles = createToggleState();
516
489
  console.log(toggles.reducedTelemetry); // false
517
490
 
518
- ### createProfilingState
491
+ ### DEFAULT_RNG_CACHE_BATCH_SIZE
519
492
 
520
- ```ts
521
- createProfilingState(): EngineProfilingState
522
- ```
493
+ Default RNG cache batch size mirroring the façade constant.
523
494
 
524
- Fabricates the profiling state bundle consumed by timing helpers.
495
+ ### DEFAULT_VISITED_HASH_LOAD_FACTOR
525
496
 
526
- Returns: Profiling configuration and accumulator state.
497
+ Default load factor target for the visited coordinate hash table.
527
498
 
528
- Example:
499
+ ### EngineProfilingState
529
500
 
530
- const profiling = createProfilingState();
531
- console.log(profiling.detailsEnabled); // false unless env flag set
501
+ Aggregated profiling configuration and accumulators shared across the evolution run.
532
502
 
533
- ### createEngineState
503
+ ### EngineScratchState
504
+
505
+ Centralised shared state for the ASCII maze evolution façade.
506
+
507
+ Responsibilities:
508
+ 1. Define the scratch-buffer schema consumed by telemetry, population, and inspection helpers.
509
+ 2. Expose runtime toggle state (`EngineToggleState`) that drives optional phases and telemetry density.
510
+ 3. Provide factory and maintenance helpers (`createEngineState`, `initialiseTelemetryScratch`, `ensureVisitedHashCapacity`, `ensureRngCacheBatch`, `reseedRngState`) that size buffers and keep deterministic RNG state in sync.
511
+ 4. Export the project-wide singleton `engineState` so extracted modules can share the façade’s pooled resources while still accepting injected state for testing.
512
+
513
+ Callers mutate the returned scratch instances in place to avoid per-generation allocations; higher-level modules should treat the helpers as the sole entry point for sizing or resetting shared buffers.
514
+
515
+ ### EngineState
516
+
517
+ Shared engine state instance combining pooled scratch buffers with toggle flags.
518
+
519
+ ### EngineToggleState
520
+
521
+ Runtime switches that adjust telemetry verbosity and optional training phases.
522
+
523
+ ### ensureRngCacheBatch
534
524
 
535
525
  ```ts
536
- createEngineState(): EngineState
526
+ ensureRngCacheBatch(
527
+ parameters: RngCacheParameters,
528
+ state: EngineState,
529
+ ): RngCacheHandles
537
530
  ```
538
531
 
539
- Fabricates a new {@link EngineState} with pre-sized scratch buffers and default toggle values.
532
+ Ensure the RNG cache contains fresh samples before consumption.
540
533
 
541
- Returns: Initialized engine state used by the maze evolution façade.
534
+ Parameters:
535
+ - `parameters` - Congruential generator parameters and cache batch size.
536
+ - `state` - Optional engine state container (defaults to the shared singleton).
537
+
538
+ Returns: Handles exposing the cache and its batch size.
542
539
 
543
540
  ### ensureVisitedHashCapacity
544
541
 
@@ -589,23 +586,6 @@ Parameters:
589
586
 
590
587
  Returns: Handles referencing the ensured scratch buffers for immediate use.
591
588
 
592
- ### ensureRngCacheBatch
593
-
594
- ```ts
595
- ensureRngCacheBatch(
596
- parameters: RngCacheParameters,
597
- state: EngineState,
598
- ): RngCacheHandles
599
- ```
600
-
601
- Ensure the RNG cache contains fresh samples before consumption.
602
-
603
- Parameters:
604
- - `parameters` - Congruential generator parameters and cache batch size.
605
- - `state` - Optional engine state container (defaults to the shared singleton).
606
-
607
- Returns: Handles exposing the cache and its batch size.
608
-
609
589
  ### reseedRngState
610
590
 
611
591
  ```ts
@@ -623,6 +603,27 @@ Parameters:
623
603
 
624
604
  Returns: Unsigned seed stored in scratch state for diagnostics.
625
605
 
606
+ ### RngCacheHandles
607
+
608
+ Handles returned after ensuring the RNG cache is ready for consumption.
609
+
610
+ ### RngCacheParameters
611
+
612
+ Parameters controlling the RNG cache refill process.
613
+
614
+ ### setBaldwinPhaseDisabledFlag
615
+
616
+ ```ts
617
+ setBaldwinPhaseDisabledFlag(
618
+ isDisabled: boolean,
619
+ ): void
620
+ ```
621
+
622
+ Enable or disable the Baldwin-phase warm-start pipeline.
623
+
624
+ Parameters:
625
+ - `isDisabled` - When true, skips the Lamarckian training stage.
626
+
626
627
  ### setReducedTelemetryFlag
627
628
 
628
629
  ```ts
@@ -649,60 +650,21 @@ Toggle the minimal telemetry mode for JSON output.
649
650
  Parameters:
650
651
  - `isMinimal` - When true, disables verbose telemetry capture.
651
652
 
652
- ### setBaldwinPhaseDisabledFlag
653
+ ### TelemetryScratchHandles
653
654
 
654
- ```ts
655
- setBaldwinPhaseDisabledFlag(
656
- isDisabled: boolean,
657
- ): void
658
- ```
659
-
660
- Enable or disable the Baldwin-phase warm-start pipeline.
661
-
662
- Parameters:
663
- - `isDisabled` - When true, skips the Lamarckian training stage.
664
-
665
- ## evolutionEngine/rngAndTiming.ts
666
-
667
- RNG and timing helpers extracted from the evolution façade.
668
-
669
- ### readHighResolutionTime
670
-
671
- ```ts
672
- readHighResolutionTime(): number
673
- ```
674
-
675
- Obtain a monotonic-ish timestamp suitable for profiling.
676
-
677
- Returns: Timestamp in milliseconds, preferring `performance.now` when available.
678
-
679
- Example:
680
-
681
- const timestamp = readHighResolutionTime();
682
-
683
- ### profilingStartTimestamp
684
-
685
- ```ts
686
- profilingStartTimestamp(): number
687
- ```
688
-
689
- Return a profiling start timestamp that mirrors the historic `#PROFILE_T0` helper.
690
-
691
- Returns: Millisecond timestamp representing the profiling start time.
655
+ Collection of scratch buffers handed back after initialisation for convenience.
692
656
 
693
- ### resolveRngParameters
657
+ ### TelemetryScratchRequest
694
658
 
695
- ```ts
696
- resolveRngParameters(): RngCacheParameters
697
- ```
659
+ Configuration describing which telemetry scratch buffers require capacity guarantees.
698
660
 
699
- Provide cached congruential parameters used by the shared fast RNG helper.
661
+ ### VisitedHashScratchHandles
700
662
 
701
- Returns: Immutable {@link RngCacheParameters} reference reused across draws.
663
+ Handles exposed after ensuring the visited-coordinate hash table capacity.
702
664
 
703
- Example:
665
+ ## evolutionEngine/rngAndTiming.ts
704
666
 
705
- const parameters = resolveRngParameters();
667
+ RNG and timing helpers extracted from the evolution façade.
706
668
 
707
669
  ### accumulateProfilingDuration
708
670
 
@@ -723,6 +685,21 @@ Parameters:
723
685
 
724
686
  Returns: void.
725
687
 
688
+ ### clearDeterministicMode
689
+
690
+ ```ts
691
+ clearDeterministicMode(
692
+ state: EngineState,
693
+ ): void
694
+ ```
695
+
696
+ Disable deterministic RNG mode.
697
+
698
+ Parameters:
699
+ - `state` - Shared engine state where the deterministic flag is stored.
700
+
701
+ Returns: void.
702
+
726
703
  ### drawFastRandom
727
704
 
728
705
  ```ts
@@ -744,37 +721,20 @@ Example:
744
721
 
745
722
  const sample = drawFastRandom(sharedState, rngParameters);
746
723
 
747
- ### setDeterministicMode
748
-
749
- ```ts
750
- setDeterministicMode(
751
- state: EngineState,
752
- seed: number | undefined,
753
- ): void
754
- ```
755
-
756
- Enable deterministic RNG mode and optionally reseed the shared RNG state.
757
-
758
- Parameters:
759
- - `state` - Shared engine state where the deterministic flag is stored.
760
- - `seed` - Optional deterministic seed. Finite numeric inputs are normalised to u32.
761
-
762
- Returns: void.
763
-
764
- ### clearDeterministicMode
724
+ ### getProfilingAccumulators
765
725
 
766
726
  ```ts
767
- clearDeterministicMode(
727
+ getProfilingAccumulators(
768
728
  state: EngineState,
769
- ): void
729
+ ): Record<string, number>
770
730
  ```
771
731
 
772
- Disable deterministic RNG mode.
732
+ Provide direct access to the profiling accumulator map.
773
733
 
774
734
  Parameters:
775
- - `state` - Shared engine state where the deterministic flag is stored.
735
+ - `state` - Shared engine state containing the profiling accumulators.
776
736
 
777
- Returns: void.
737
+ Returns: Mutable record of profiling accumulators keyed by category name.
778
738
 
779
739
  ### isDeterministicModeEnabled
780
740
 
@@ -806,72 +766,68 @@ Parameters:
806
766
 
807
767
  Returns: True when detail profiling is enabled.
808
768
 
809
- ### getProfilingAccumulators
769
+ ### profilingStartTimestamp
810
770
 
811
771
  ```ts
812
- getProfilingAccumulators(
813
- state: EngineState,
814
- ): Record<string, number>
772
+ profilingStartTimestamp(): number
815
773
  ```
816
774
 
817
- Provide direct access to the profiling accumulator map.
818
-
819
- Parameters:
820
- - `state` - Shared engine state containing the profiling accumulators.
821
-
822
- Returns: Mutable record of profiling accumulators keyed by category name.
775
+ Return a profiling start timestamp that mirrors the historic `#PROFILE_T0` helper.
823
776
 
824
- ## evolutionEngine/scratchPools.ts
777
+ Returns: Millisecond timestamp representing the profiling start time.
825
778
 
826
- Scratch pool management helpers extracted from the maze evolution façade.
779
+ ### readHighResolutionTime
827
780
 
828
- These utilities centralise the logic that grows and shrinks pooled buffers attached to the
829
- shared {@link EngineState}. They keep the façade lean by encapsulating heuristics for logits
830
- ring sizing, telemetry scratch sizing, and connection flag pooling.
781
+ ```ts
782
+ readHighResolutionTime(): number
783
+ ```
831
784
 
832
- ### LogitsRingCapacityOptions
785
+ Obtain a monotonic-ish timestamp suitable for profiling.
833
786
 
834
- Shape describing the parameters used when ensuring the logits ring capacity.
787
+ Returns: Timestamp in milliseconds, preferring `performance.now` when available.
835
788
 
836
- ### LogitsRingCapacityResult
789
+ Example:
837
790
 
838
- Result returned after resizing the logits ring.
791
+ const timestamp = readHighResolutionTime();
839
792
 
840
- ### ensureLogitsRingCapacity
793
+ ### resolveRngParameters
841
794
 
842
795
  ```ts
843
- ensureLogitsRingCapacity(
844
- capacityRequest: LogitsRingCapacityOptions,
845
- ): LogitsRingCapacityResult
796
+ resolveRngParameters(): RngCacheParameters
846
797
  ```
847
798
 
848
- Grow or shrink the logits ring to accomodate the requested recent-step budget.
849
-
850
- Parameters:
851
- - `capacityRequest` - Parameters describing the requested resize.
799
+ Provide cached congruential parameters used by the shared fast RNG helper.
852
800
 
853
- Returns: The resulting capacity and whether shared-array mode stayed enabled.
801
+ Returns: Immutable {@link RngCacheParameters} reference reused across draws.
854
802
 
855
- ### SharedLogitsConfig
803
+ Example:
856
804
 
857
- Parameters passed when attempting to initialise the shared logits ring buffers.
805
+ const parameters = resolveRngParameters();
858
806
 
859
- ### initialiseSharedLogitsRing
807
+ ### setDeterministicMode
860
808
 
861
809
  ```ts
862
- initialiseSharedLogitsRing(
810
+ setDeterministicMode(
863
811
  state: EngineState,
864
- config: SharedLogitsConfig,
865
- ): boolean
812
+ seed: number | undefined,
813
+ ): void
866
814
  ```
867
815
 
868
- Attempt to allocate SharedArrayBuffer-backed logits ring storage.
816
+ Enable deterministic RNG mode and optionally reseed the shared RNG state.
869
817
 
870
818
  Parameters:
871
- - `state` - Shared engine state containing the logits buffers.
872
- - `config` - Shared ring configuration (capacity and action dimension).
819
+ - `state` - Shared engine state where the deterministic flag is stored.
820
+ - `seed` - Optional deterministic seed. Finite numeric inputs are normalised to u32.
873
821
 
874
- Returns: true when shared mode was activated successfully.
822
+ Returns: void.
823
+
824
+ ## evolutionEngine/scratchPools.ts
825
+
826
+ Scratch pool management helpers extracted from the maze evolution façade.
827
+
828
+ These utilities centralise the logic that grows and shrinks pooled buffers attached to the
829
+ shared {@link EngineState}. They keep the façade lean by encapsulating heuristics for logits
830
+ ring sizing, telemetry scratch sizing, and connection flag pooling.
875
831
 
876
832
  ### allocateLogitsRing
877
833
 
@@ -890,9 +846,37 @@ Parameters:
890
846
 
891
847
  Returns: Array of typed rows representing the ring buffer.
892
848
 
893
- ### ScratchCapacityRequest
849
+ ### ensureConnFlagsCapacity
894
850
 
895
- Parameters describing the scratch sizing requirements for ensureScratchCapacity.
851
+ ```ts
852
+ ensureConnFlagsCapacity(
853
+ state: EngineState,
854
+ minimumCapacity: number,
855
+ ): Int8Array<ArrayBufferLike> | null
856
+ ```
857
+
858
+ Ensure the recurrent/gated detection bitmap has sufficient capacity.
859
+
860
+ Parameters:
861
+ - `state` - Shared engine state containing the pooled bitmap.
862
+ - `minimumCapacity` - Minimum number of entries required by the caller.
863
+
864
+ Returns: Int8Array bitmap or null when allocation failed.
865
+
866
+ ### ensureLogitsRingCapacity
867
+
868
+ ```ts
869
+ ensureLogitsRingCapacity(
870
+ capacityRequest: LogitsRingCapacityOptions,
871
+ ): LogitsRingCapacityResult
872
+ ```
873
+
874
+ Grow or shrink the logits ring to accomodate the requested recent-step budget.
875
+
876
+ Parameters:
877
+ - `capacityRequest` - Parameters describing the requested resize.
878
+
879
+ Returns: The resulting capacity and whether shared-array mode stayed enabled.
896
880
 
897
881
  ### ensureScratchCapacity
898
882
 
@@ -909,6 +893,31 @@ Parameters:
909
893
  - `state` - Shared engine state exposing scratch buffers.
910
894
  - `request` - Sizing request describing the evolution workload.
911
895
 
896
+ ### initialiseSharedLogitsRing
897
+
898
+ ```ts
899
+ initialiseSharedLogitsRing(
900
+ state: EngineState,
901
+ config: SharedLogitsConfig,
902
+ ): boolean
903
+ ```
904
+
905
+ Attempt to allocate SharedArrayBuffer-backed logits ring storage.
906
+
907
+ Parameters:
908
+ - `state` - Shared engine state containing the logits buffers.
909
+ - `config` - Shared ring configuration (capacity and action dimension).
910
+
911
+ Returns: true when shared mode was activated successfully.
912
+
913
+ ### LogitsRingCapacityOptions
914
+
915
+ Shape describing the parameters used when ensuring the logits ring capacity.
916
+
917
+ ### LogitsRingCapacityResult
918
+
919
+ Result returned after resizing the logits ring.
920
+
912
921
  ### maybeShrinkScratch
913
922
 
914
923
  ```ts
@@ -924,22 +933,13 @@ Parameters:
924
933
  - `state` - Shared engine state exposing scratch buffers.
925
934
  - `populationSize` - Current population size used to derive shrink heuristics.
926
935
 
927
- ### ensureConnFlagsCapacity
928
-
929
- ```ts
930
- ensureConnFlagsCapacity(
931
- state: EngineState,
932
- minimumCapacity: number,
933
- ): Int8Array<ArrayBufferLike> | null
934
- ```
936
+ ### ScratchCapacityRequest
935
937
 
936
- Ensure the recurrent/gated detection bitmap has sufficient capacity.
938
+ Parameters describing the scratch sizing requirements for ensureScratchCapacity.
937
939
 
938
- Parameters:
939
- - `state` - Shared engine state containing the pooled bitmap.
940
- - `minimumCapacity` - Minimum number of entries required by the caller.
940
+ ### SharedLogitsConfig
941
941
 
942
- Returns: Int8Array bitmap or null when allocation failed.
942
+ Parameters passed when attempting to initialise the shared logits ring buffers.
943
943
 
944
944
  ## evolutionEngine/setupHelpers.ts
945
945
 
@@ -950,50 +950,15 @@ Responsibilities:
950
950
  - Initialize Node.js persistence helpers when available.
951
951
  - Build resilient logging writers with dashboard and console fallbacks.
952
952
 
953
- ### FilesystemModule
954
-
955
- Minimal filesystem module shape for type safety (Node.js fs module subset).
956
-
957
- ### PathModule
958
-
959
- Minimal path module shape for type safety (Node.js path module subset).
960
-
961
953
  ### DashboardManagerLike
962
954
 
963
955
  Dashboard manager shape for logging (optional log function).
964
956
 
965
- ### makeFlushToFrame
966
-
967
- ```ts
968
- makeFlushToFrame(
969
- hostAdapter: EvolutionHostAdapter | undefined,
970
- ): () => Promise<void>
971
- ```
972
-
973
- Create a cooperative frame-yielding function used by the evolution loop.
974
-
975
- Behaviour:
976
- - Prefers `requestAnimationFrame` when available (browser hosts)
977
- - Falls back to `setImmediate` when available (Node) or `setTimeout(...,0)` otherwise
978
- - Respects an optional host adapter pause callback by polling between ticks without busy-waiting
979
- - Resolves once a single new frame or tick is available and the host is not paused
980
-
981
- Steps:
982
- 1. Choose the preferred tick function based on the host runtime
983
- 2. When called, await the preferred tick; if the host adapter reports pause, poll again after the tick
984
- 3. Resolve once a tick passed while not paused
985
-
986
- Parameters:
987
- - `hostAdapter` - - Optional host adapter that owns cooperative pause state.
988
-
989
- Returns: A function that yields cooperatively to the next animation frame / tick.
990
-
991
- Example:
992
-
993
- const flushToFrame = makeFlushToFrame();
994
- await flushToFrame(); // yields to next frame/tick
995
-
996
- ### initPersistence
957
+ ### FilesystemModule
958
+
959
+ Minimal filesystem module shape for type safety (Node.js fs module subset).
960
+
961
+ ### initPersistence
997
962
 
998
963
  ```ts
999
964
  initPersistence(
@@ -1027,6 +992,52 @@ if (fs && path) {
1027
992
  fs.writeFileSync(path.join(dir, 'snapshot.json'), data);
1028
993
  }
1029
994
 
995
+ ### isPauseRequested
996
+
997
+ ```ts
998
+ isPauseRequested(
999
+ hostAdapter: EvolutionHostAdapter | undefined,
1000
+ ): boolean
1001
+ ```
1002
+
1003
+ Read host-controlled pause state without letting host errors break the engine.
1004
+
1005
+ Parameters:
1006
+ - `hostAdapter` - - Optional host adapter implementing pause polling.
1007
+
1008
+ Returns: True when the host asks the engine to remain paused.
1009
+
1010
+ ### makeFlushToFrame
1011
+
1012
+ ```ts
1013
+ makeFlushToFrame(
1014
+ hostAdapter: EvolutionHostAdapter | undefined,
1015
+ ): () => Promise<void>
1016
+ ```
1017
+
1018
+ Create a cooperative frame-yielding function used by the evolution loop.
1019
+
1020
+ Behaviour:
1021
+ - Prefers `requestAnimationFrame` when available (browser hosts)
1022
+ - Falls back to `setImmediate` when available (Node) or `setTimeout(...,0)` otherwise
1023
+ - Respects an optional host adapter pause callback by polling between ticks without busy-waiting
1024
+ - Resolves once a single new frame or tick is available and the host is not paused
1025
+
1026
+ Steps:
1027
+ 1. Choose the preferred tick function based on the host runtime
1028
+ 2. When called, await the preferred tick; if the host adapter reports pause, poll again after the tick
1029
+ 3. Resolve once a tick passed while not paused
1030
+
1031
+ Parameters:
1032
+ - `hostAdapter` - - Optional host adapter that owns cooperative pause state.
1033
+
1034
+ Returns: A function that yields cooperatively to the next animation frame / tick.
1035
+
1036
+ Example:
1037
+
1038
+ const flushToFrame = makeFlushToFrame();
1039
+ await flushToFrame(); // yields to next frame/tick
1040
+
1030
1041
  ### makeSafeWriter
1031
1042
 
1032
1043
  ```ts
@@ -1058,20 +1069,9 @@ Example:
1058
1069
  const safeWrite = makeSafeWriter(dashboardManager);
1059
1070
  safeWrite('[INFO] Generation 42 complete\n');
1060
1071
 
1061
- ### isPauseRequested
1062
-
1063
- ```ts
1064
- isPauseRequested(
1065
- hostAdapter: EvolutionHostAdapter | undefined,
1066
- ): boolean
1067
- ```
1068
-
1069
- Read host-controlled pause state without letting host errors break the engine.
1070
-
1071
- Parameters:
1072
- - `hostAdapter` - - Optional host adapter implementing pause polling.
1072
+ ### PathModule
1073
1073
 
1074
- Returns: True when the host asks the engine to remain paused.
1074
+ Minimal path module shape for type safety (Node.js path module subset).
1075
1075
 
1076
1076
  ## evolutionEngine/evolutionLoop.ts
1077
1077
 
@@ -1141,53 +1141,6 @@ if (checkCancellation(opts)) {
1141
1141
  break;
1142
1142
  }
1143
1143
 
1144
- ### prepareLoopHelpers
1145
-
1146
- ```ts
1147
- prepareLoopHelpers(
1148
- opts: EvolutionOptions,
1149
- scratchBundle: ScratchBundle,
1150
- ): LoopHelpers
1151
- ```
1152
-
1153
- Build lightweight helpers used inside the evolution loop.
1154
-
1155
- This function assembles the helper utilities needed by the main evolution loop:
1156
- - Frame flushing for cooperative yielding
1157
- - Persistence handles for snapshot saving (Node.js only)
1158
- - Safe logging writer with fallback chain
1159
- - Scratch buffer warm-up (best-effort)
1160
-
1161
- Design Rationale:
1162
- - All initialization is best-effort (failures swallowed)
1163
- - Warms up common scratch buffers to reduce first-use allocation spikes
1164
- - Returns simple POJO with utilities (no class coupling)
1165
- - Side effects isolated to scratch bundle parameter
1166
-
1167
- Scratch Buffer Warm-Up:
1168
- - samplePool: Array for population sampling
1169
- - profilingScratch: Float64Array(4) for timing accumulation
1170
- - exps: Float64Array(64) for exponential computations
1171
-
1172
- Parameters:
1173
-
1174
- Parameters:
1175
- - `opts` - - Normalized run options (contains persistDir and dashboardManager)
1176
- - `scratchBundle` - - Engine scratch state for optional buffer warm-up
1177
-
1178
- Returns: Object containing:
1179
- - flushToFrame: Async function for cooperative yielding
1180
- - fs: Node.js fs module (null in browsers)
1181
- - path: Node.js path module (null in browsers)
1182
- - safeWrite: Resilient logging function with fallback chain
1183
-
1184
- Example:
1185
-
1186
- // Prepare loop helpers with scratch buffer warm-up
1187
- const { flushToFrame, fs, path, safeWrite } = prepareLoopHelpers(opts, engineState.scratch);
1188
- safeWrite('Starting evolution...\n');
1189
- await flushToFrame(); // Yield to host
1190
-
1191
1144
  ### checkStopConditions
1192
1145
 
1193
1146
  ```ts
@@ -1261,6 +1214,73 @@ if (reason) {
1261
1214
  break;
1262
1215
  }
1263
1216
 
1217
+ ### emitProfileSummary
1218
+
1219
+ ```ts
1220
+ emitProfileSummary(
1221
+ engineState: EngineState,
1222
+ safeWrite: (msg: string) => void,
1223
+ completedGenerations: number,
1224
+ totalEvolveMs: number,
1225
+ totalLamarckMs: number,
1226
+ totalSimMs: number,
1227
+ isProfilingDetailsEnabledFn: (state: EngineState) => boolean,
1228
+ getProfilingAccumulatorsFn: (state: EngineState) => ProfilingAccumulators,
1229
+ ): void
1230
+ ```
1231
+
1232
+ Emit a formatted profiling summary showing average per-generation timings.
1233
+
1234
+ This function prints a compact profiling summary with average millisecond timings
1235
+ for the main evolution phases (evolve, Lamarckian training, simulation). If detailed
1236
+ profiling is enabled, it also prints averages for telemetry, simplify, snapshot, and
1237
+ prune operations.
1238
+
1239
+ Design Rationale:
1240
+ - Allocation-free (reuses pooled Float64Array for intermediate calculations)
1241
+ - Best-effort error handling (swallow all exceptions)
1242
+ - Defensive numeric validation with divide-by-zero guards
1243
+ - Conditional detailed profiling output
1244
+
1245
+ Calculation Steps:
1246
+ 1. Validate and normalize generation count (guard divide-by-zero)
1247
+ 2. Store totals in pooled scratch buffer (4-slot Float64Array)
1248
+ 3. Compute per-generation averages by dividing totals by generation count
1249
+ 4. Format numbers with 2 decimal places and print compact summary
1250
+ 5. If detailed profiling enabled, print averaged detail line
1251
+
1252
+ Parameters:
1253
+
1254
+ Parameters:
1255
+ - `engineState` - - Shared engine state with scratch buffers and profiling accumulators
1256
+ - `safeWrite` - - Safe logging function (best-effort, never throws)
1257
+ - `completedGenerations` - - Number of completed generations (must be > 0)
1258
+ - `totalEvolveMs` - - Total milliseconds spent in NEAT evolve() calls
1259
+ - `totalLamarckMs` - - Total milliseconds spent in Lamarckian training
1260
+ - `totalSimMs` - - Total milliseconds spent in simulation
1261
+ - `isProfilingDetailsEnabledFn` - - Function to check if detailed profiling is enabled
1262
+ - `getProfilingAccumulatorsFn` - - Function to get detailed profiling accumulators
1263
+
1264
+ Example:
1265
+
1266
+ // Print averages after a run that completed 100 generations
1267
+ emitProfileSummary(
1268
+ state, console.log, 100, 12000, 3000, 4500,
1269
+ isProfilingDetailsEnabled, getProfilingAccumulators
1270
+ );
1271
+
1272
+ ### EvolutionLoopResult
1273
+
1274
+ Evolution loop result
1275
+
1276
+ ### GenerationOutcome
1277
+
1278
+ Generation outcome with profiling timings
1279
+
1280
+ ### MutableMazeResult
1281
+
1282
+ Mutable result object with exitReason field
1283
+
1264
1284
  ### persistSnapshotIfNeeded
1265
1285
 
1266
1286
  ```ts
@@ -1342,170 +1362,109 @@ persistSnapshotIfNeeded(
1342
1362
  scratchObj, scratchTop, collectTail, getSorted, isProfilingEnabled, profileStart, profileAccum
1343
1363
  );
1344
1364
 
1345
- ### updateDashboardAndMaybeFlush
1365
+ ### prepareLoopHelpers
1346
1366
 
1347
1367
  ```ts
1348
- updateDashboardAndMaybeFlush(
1349
- maze: string[],
1350
- result: IMazeRunResult | undefined,
1351
- network: default | null,
1352
- completedGenerations: number,
1353
- neat: default,
1354
- dashboardManager: IDashboardManager | undefined,
1355
- flushToFrame: (() => Promise<void>) | undefined,
1356
- ): Promise<void>
1368
+ prepareLoopHelpers(
1369
+ opts: EvolutionOptions,
1370
+ scratchBundle: ScratchBundle,
1371
+ ): LoopHelpers
1357
1372
  ```
1358
1373
 
1359
- Safely update a UI dashboard with the latest run state and optionally yield to the
1360
- host/frame via an awaited flush function.
1374
+ Build lightweight helpers used inside the evolution loop.
1361
1375
 
1362
- Behaviour (best-effort):
1363
- 1) If `dashboardManager.update` exists and is callable, call it with the stable
1364
- argument order (maze, result, network, completedGenerations, neat). Any exception
1365
- raised by the dashboard is swallowed to avoid interrupting the evolution loop.
1366
- 2) If `flushToFrame` is supplied as an async function, await it to yield control to
1367
- the event loop or renderer (for example `() => new Promise(r => requestAnimationFrame(r))`).
1368
- 3) The helper avoids heap allocations and relies on existing pooled scratch buffers in
1369
- the engine for heavy telemetry elsewhere; this method intentionally performs only
1370
- short-lived control flow and minimal work.
1376
+ This function assembles the helper utilities needed by the main evolution loop:
1377
+ - Frame flushing for cooperative yielding
1378
+ - Persistence handles for snapshot saving (Node.js only)
1379
+ - Safe logging writer with fallback chain
1380
+ - Scratch buffer warm-up (best-effort)
1371
1381
 
1372
1382
  Design Rationale:
1373
- - Allocation-free (no ephemeral objects or arrays created)
1374
- - Best-effort error handling (swallow all dashboard/flush errors)
1375
- - Stable argument order for dashboard implementations
1376
- - Async support for cooperative yielding to host scheduler
1383
+ - All initialization is best-effort (failures swallowed)
1384
+ - Warms up common scratch buffers to reduce first-use allocation spikes
1385
+ - Returns simple POJO with utilities (no class coupling)
1386
+ - Side effects isolated to scratch bundle parameter
1387
+
1388
+ Scratch Buffer Warm-Up:
1389
+ - samplePool: Array for population sampling
1390
+ - profilingScratch: Float64Array(4) for timing accumulation
1391
+ - exps: Float64Array(64) for exponential computations
1377
1392
 
1378
1393
  Parameters:
1379
1394
 
1380
1395
  Parameters:
1381
- - `maze` - - Maze instance or descriptor used by dashboard rendering.
1382
- - `result` - - Per-run result object (path, progress, telemetry, etc.).
1383
- - `network` - - Network or genome object that should be visualised.
1384
- - `completedGenerations` - - Integer index of the completed generation.
1385
- - `neat` - - NEAT manager instance (context passed to the dashboard update).
1386
- - `dashboardManager` - - Optional manager exposing `update(maze, result, network, gen, neat)`.
1387
- - `flushToFrame` - - Optional async function used to yield to the host/frame scheduler; may be omitted.
1388
-
1389
- Example:
1390
-
1391
- // Yield to the browser's next repaint after dashboard update:
1392
- await updateDashboardAndMaybeFlush(
1393
- maze, genResult, fittestNetwork, gen, neatInstance, dashboard, () => new Promise(r => requestAnimationFrame(r))
1394
- );
1395
-
1396
- ### updateDashboardPeriodic
1397
-
1398
- ```ts
1399
- updateDashboardPeriodic(
1400
- maze: string[],
1401
- bestResult: IMazeRunResult | undefined,
1402
- bestNetwork: default | null,
1403
- completedGenerations: number,
1404
- neat: default,
1405
- dashboardManager: IDashboardManager | undefined,
1406
- flushToFrame: (() => Promise<void>) | undefined,
1407
- ): Promise<void>
1408
- ```
1409
-
1410
- Periodic dashboard update used when the engine wants to refresh a non-primary
1411
- dashboard view (for example background or periodic reporting). This helper is
1412
- intentionally small, allocation-light and best-effort: dashboard errors are
1413
- swallowed so the evolution loop cannot be interrupted by UI issues.
1414
-
1415
- Behavioural contract:
1416
- 1) If `dashboardManager.update` is present and callable the method invokes it with
1417
- the stable argument order: (maze, bestResult, bestNetwork, completedGenerations, neat).
1418
- 2) If `flushToFrame` is supplied the helper awaits it after the update to yield to
1419
- the host renderer (eg. requestAnimationFrame). Any exceptions raised by the
1420
- flush are swallowed.
1421
- 3) The helper avoids creating ephemeral arrays/objects and therefore does not use
1422
- typed-array scratch buffers here — there is no hot numerical work to pool. Other
1423
- engine helpers already reuse class-level scratch buffers where appropriate.
1424
-
1425
- Design Rationale:
1426
- - Fast-guard early when update cannot be performed
1427
- - Best-effort error handling (swallow all exceptions)
1428
- - Preserves dashboard `this` binding with `.call()`
1429
- - Minimal allocations (no scratch buffers needed)
1430
-
1431
- Steps / inline intent:
1432
- 1. Fast-guard when an update cannot be performed (missing manager, update method,
1433
- or missing content to visualise).
1434
- 2. Call the dashboard update in a try/catch to preserve best-effort semantics.
1435
- 3. Optionally await the provided `flushToFrame` function to yield to the host.
1436
-
1437
- Parameters:
1396
+ - `opts` - - Normalized run options (contains persistDir and dashboardManager)
1397
+ - `scratchBundle` - - Engine scratch state for optional buffer warm-up
1438
1398
 
1439
- Parameters:
1440
- - `maze` - - Maze descriptor passed to the dashboard renderer.
1441
- - `bestResult` - - Best-run result object used for display (may be falsy when not present).
1442
- - `bestNetwork` - - Network or genome object to visualise (may be falsy when not present).
1443
- - `completedGenerations` - - Completed generation index (number).
1444
- - `neat` - - NEAT manager instance (passed through to dashboard update).
1445
- - `dashboardManager` - - Optional manager exposing `update(maze, result, network, gen, neat)`.
1446
- - `flushToFrame` - - Optional async function used to yield to the host/frame scheduler
1447
- (for example: `() => new Promise(r => requestAnimationFrame(r))`).
1399
+ Returns: Object containing:
1400
+ - flushToFrame: Async function for cooperative yielding
1401
+ - fs: Node.js fs module (null in browsers)
1402
+ - path: Node.js path module (null in browsers)
1403
+ - safeWrite: Resilient logging function with fallback chain
1448
1404
 
1449
1405
  Example:
1450
1406
 
1451
- // Safe periodic update and yield to next frame
1452
- await updateDashboardPeriodic(
1453
- maze, result, network, gen, neatInstance, dashboard, () => new Promise(r => requestAnimationFrame(r))
1454
- );
1407
+ // Prepare loop helpers with scratch buffer warm-up
1408
+ const { flushToFrame, fs, path, safeWrite } = prepareLoopHelpers(opts, engineState.scratch);
1409
+ safeWrite('Starting evolution...\n');
1410
+ await flushToFrame(); // Yield to host
1455
1411
 
1456
- ### emitProfileSummary
1412
+ ### runEvolutionLoop
1457
1413
 
1458
1414
  ```ts
1459
- emitProfileSummary(
1415
+ runEvolutionLoop(
1460
1416
  engineState: EngineState,
1461
- safeWrite: (msg: string) => void,
1462
- completedGenerations: number,
1463
- totalEvolveMs: number,
1464
- totalLamarckMs: number,
1465
- totalSimMs: number,
1466
- isProfilingDetailsEnabledFn: (state: EngineState) => boolean,
1467
- getProfilingAccumulatorsFn: (state: EngineState) => ProfilingAccumulators,
1468
- ): void
1417
+ neat: default,
1418
+ opts: EvolutionOptions,
1419
+ lamarckianTrainingSet: { input: number[]; output: number[]; }[],
1420
+ encodedMaze: number[][],
1421
+ startPosition: readonly [number, number],
1422
+ exitPosition: readonly [number, number],
1423
+ distanceMap: number[][],
1424
+ helpers: LoopHelpers,
1425
+ doProfile: boolean,
1426
+ runtimeContext: EvolutionLoopRuntimeContext,
1427
+ initialRingState: LogitsRingState,
1428
+ telemetryContext: EvolutionLoopTelemetryContext,
1429
+ supportContext: EvolutionLoopSupportContext,
1430
+ constants: TrainingConstants & { DEFAULT_TRAIN_BATCH_LARGE: number; FITTEST_TRAIN_ITERATIONS: number; TELEMETRY_MINIMAL: boolean; SATURATION_PRUNE_THRESHOLD: number; RECENT_WINDOW: number; REDUCED_TELEMETRY: boolean; DISABLE_BALDWIN: boolean; },
1431
+ ): Promise<EvolutionLoopResult>
1469
1432
  ```
1470
1433
 
1471
- Emit a formatted profiling summary showing average per-generation timings.
1472
-
1473
- This function prints a compact profiling summary with average millisecond timings
1474
- for the main evolution phases (evolve, Lamarckian training, simulation). If detailed
1475
- profiling is enabled, it also prints averages for telemetry, simplify, snapshot, and
1476
- prune operations.
1477
-
1478
- Design Rationale:
1479
- - Allocation-free (reuses pooled Float64Array for intermediate calculations)
1480
- - Best-effort error handling (swallow all exceptions)
1481
- - Defensive numeric validation with divide-by-zero guards
1482
- - Conditional detailed profiling output
1434
+ Internal evolution loop that executes generations until a stop condition or cancellation.
1483
1435
 
1484
- Calculation Steps:
1485
- 1. Validate and normalize generation count (guard divide-by-zero)
1486
- 2. Store totals in pooled scratch buffer (4-slot Float64Array)
1487
- 3. Compute per-generation averages by dividing totals by generation count
1488
- 4. Format numbers with 2 decimal places and print compact summary
1489
- 5. If detailed profiling enabled, print averaged detail line
1436
+ Behaviour & contract:
1437
+ - Runs generations in a resilient, best-effort manner; internal errors are swallowed
1438
+ so a single failure cannot abort the whole run.
1439
+ - When `doProfile` is truthy the loop accumulates timing into a pooled Float64Array
1440
+ to avoid per-iteration allocations. The pooled buffer is reused across calls.
1441
+ - The helper performs side-effects (dashboard updates, persistence) in a non-fatal
1442
+ fashion and yields to the host when requested via `helpers.flushToFrame`.
1490
1443
 
1491
1444
  Parameters:
1445
+ - `engineState` - - Shared engine state with scratch buffers and configuration
1446
+ - `neat` - - NEAT driver instance used to perform evolution and mutation operations
1447
+ - `opts` - - Normalised run options (produced by normalizeRunOptions)
1448
+ - `lamarckianTrainingSet` - - Optional supervised training cases used for Lamarckian warm-start
1449
+ - `encodedMaze` - - Encoded maze representation consumed by simulators
1450
+ - `startPosition` - - Start coordinates for the simulated agent
1451
+ - `exitPosition` - - Exit coordinates for the simulated agent
1452
+ - `distanceMap` - - Optional precomputed distance map to speed simulation
1453
+ - `helpers` - - Helper utilities: { flushToFrame, fs, path, safeWrite }
1454
+ - `doProfile` - - When truthy collect and return millisecond timings in the result
1455
+ - `runtimeContext` - - Shared pooled ring buffers and limits for the hot path.
1456
+ - `initialRingState` - - Current mutable ring state for this run.
1457
+ - `telemetryContext` - - Telemetry thresholds and verbosity switches used during simulation.
1458
+ - `supportContext` - - Shared scratch buffers and helper callbacks used by the loop.
1459
+ - `constants` - - Object containing all engine constants (DEFAULT_TRAIN_ERROR, etc.)
1492
1460
 
1493
- Parameters:
1494
- - `engineState` - - Shared engine state with scratch buffers and profiling accumulators
1495
- - `safeWrite` - - Safe logging function (best-effort, never throws)
1496
- - `completedGenerations` - - Number of completed generations (must be > 0)
1497
- - `totalEvolveMs` - - Total milliseconds spent in NEAT evolve() calls
1498
- - `totalLamarckMs` - - Total milliseconds spent in Lamarckian training
1499
- - `totalSimMs` - - Total milliseconds spent in simulation
1500
- - `isProfilingDetailsEnabledFn` - - Function to check if detailed profiling is enabled
1501
- - `getProfilingAccumulatorsFn` - - Function to get detailed profiling accumulators
1461
+ Returns: Promise resolving to an object:
1462
+ { bestNetwork, bestResult, neat, completedGenerations, totalEvolveMs, totalLamarckMs, totalSimMs, updatedRingState }
1502
1463
 
1503
1464
  Example:
1504
1465
 
1505
- // Print averages after a run that completed 100 generations
1506
- emitProfileSummary(
1507
- state, console.log, 100, 12000, 3000, 4500,
1508
- isProfilingDetailsEnabled, getProfilingAccumulators
1466
+ const runSummary = await runEvolutionLoop(
1467
+ state, neat, opts, trainingSet, maze, start, exit, distMap, helpers, true, ...
1509
1468
  );
1510
1469
 
1511
1470
  ### runGeneration
@@ -1606,6 +1565,10 @@ const { fittest, tEvolve, tLamarck } = await runGeneration(
1606
1565
  { DEFAULT_TRAIN_ERROR: 0.01, ... }
1607
1566
  );
1608
1567
 
1568
+ ### SimResultWithOutputs
1569
+
1570
+ Simulation result with step outputs
1571
+
1609
1572
  ### simulateAndPostprocess
1610
1573
 
1611
1574
  ```ts
@@ -1679,113 +1642,122 @@ const { generationResult, simTime, updatedRingState } = simulateAndPostprocess(
1679
1642
  state, bestGenome, maze, start, exit, distMap, 1000, true, console.log, 10, genIdx, neat, ...
1680
1643
  );
1681
1644
 
1682
- ### runEvolutionLoop
1645
+ ### SimulationOutcome
1646
+
1647
+ Simulation result with profiling and ring state
1648
+
1649
+ ### updateDashboardAndMaybeFlush
1683
1650
 
1684
1651
  ```ts
1685
- runEvolutionLoop(
1686
- engineState: EngineState,
1652
+ updateDashboardAndMaybeFlush(
1653
+ maze: string[],
1654
+ result: IMazeRunResult | undefined,
1655
+ network: default | null,
1656
+ completedGenerations: number,
1687
1657
  neat: default,
1688
- opts: EvolutionOptions,
1689
- lamarckianTrainingSet: { input: number[]; output: number[]; }[],
1690
- encodedMaze: number[][],
1691
- startPosition: readonly [number, number],
1692
- exitPosition: readonly [number, number],
1693
- distanceMap: number[][],
1694
- helpers: LoopHelpers,
1695
- doProfile: boolean,
1696
- runtimeContext: EvolutionLoopRuntimeContext,
1697
- initialRingState: LogitsRingState,
1698
- telemetryContext: EvolutionLoopTelemetryContext,
1699
- supportContext: EvolutionLoopSupportContext,
1700
- constants: TrainingConstants & { DEFAULT_TRAIN_BATCH_LARGE: number; FITTEST_TRAIN_ITERATIONS: number; TELEMETRY_MINIMAL: boolean; SATURATION_PRUNE_THRESHOLD: number; RECENT_WINDOW: number; REDUCED_TELEMETRY: boolean; DISABLE_BALDWIN: boolean; },
1701
- ): Promise<EvolutionLoopResult>
1658
+ dashboardManager: IDashboardManager | undefined,
1659
+ flushToFrame: (() => Promise<void>) | undefined,
1660
+ ): Promise<void>
1702
1661
  ```
1703
1662
 
1704
- Internal evolution loop that executes generations until a stop condition or cancellation.
1663
+ Safely update a UI dashboard with the latest run state and optionally yield to the
1664
+ host/frame via an awaited flush function.
1705
1665
 
1706
- Behaviour & contract:
1707
- - Runs generations in a resilient, best-effort manner; internal errors are swallowed
1708
- so a single failure cannot abort the whole run.
1709
- - When `doProfile` is truthy the loop accumulates timing into a pooled Float64Array
1710
- to avoid per-iteration allocations. The pooled buffer is reused across calls.
1711
- - The helper performs side-effects (dashboard updates, persistence) in a non-fatal
1712
- fashion and yields to the host when requested via `helpers.flushToFrame`.
1666
+ Behaviour (best-effort):
1667
+ 1) If `dashboardManager.update` exists and is callable, call it with the stable
1668
+ argument order (maze, result, network, completedGenerations, neat). Any exception
1669
+ raised by the dashboard is swallowed to avoid interrupting the evolution loop.
1670
+ 2) If `flushToFrame` is supplied as an async function, await it to yield control to
1671
+ the event loop or renderer (for example `() => new Promise(r => requestAnimationFrame(r))`).
1672
+ 3) The helper avoids heap allocations and relies on existing pooled scratch buffers in
1673
+ the engine for heavy telemetry elsewhere; this method intentionally performs only
1674
+ short-lived control flow and minimal work.
1675
+
1676
+ Design Rationale:
1677
+ - Allocation-free (no ephemeral objects or arrays created)
1678
+ - Best-effort error handling (swallow all dashboard/flush errors)
1679
+ - Stable argument order for dashboard implementations
1680
+ - Async support for cooperative yielding to host scheduler
1713
1681
 
1714
1682
  Parameters:
1715
- - `engineState` - - Shared engine state with scratch buffers and configuration
1716
- - `neat` - - NEAT driver instance used to perform evolution and mutation operations
1717
- - `opts` - - Normalised run options (produced by normalizeRunOptions)
1718
- - `lamarckianTrainingSet` - - Optional supervised training cases used for Lamarckian warm-start
1719
- - `encodedMaze` - - Encoded maze representation consumed by simulators
1720
- - `startPosition` - - Start coordinates for the simulated agent
1721
- - `exitPosition` - - Exit coordinates for the simulated agent
1722
- - `distanceMap` - - Optional precomputed distance map to speed simulation
1723
- - `helpers` - - Helper utilities: { flushToFrame, fs, path, safeWrite }
1724
- - `doProfile` - - When truthy collect and return millisecond timings in the result
1725
- - `runtimeContext` - - Shared pooled ring buffers and limits for the hot path.
1726
- - `initialRingState` - - Current mutable ring state for this run.
1727
- - `telemetryContext` - - Telemetry thresholds and verbosity switches used during simulation.
1728
- - `supportContext` - - Shared scratch buffers and helper callbacks used by the loop.
1729
- - `constants` - - Object containing all engine constants (DEFAULT_TRAIN_ERROR, etc.)
1730
1683
 
1731
- Returns: Promise resolving to an object:
1732
- { bestNetwork, bestResult, neat, completedGenerations, totalEvolveMs, totalLamarckMs, totalSimMs, updatedRingState }
1684
+ Parameters:
1685
+ - `maze` - - Maze instance or descriptor used by dashboard rendering.
1686
+ - `result` - - Per-run result object (path, progress, telemetry, etc.).
1687
+ - `network` - - Network or genome object that should be visualised.
1688
+ - `completedGenerations` - - Integer index of the completed generation.
1689
+ - `neat` - - NEAT manager instance (context passed to the dashboard update).
1690
+ - `dashboardManager` - - Optional manager exposing `update(maze, result, network, gen, neat)`.
1691
+ - `flushToFrame` - - Optional async function used to yield to the host/frame scheduler; may be omitted.
1733
1692
 
1734
1693
  Example:
1735
1694
 
1736
- const runSummary = await runEvolutionLoop(
1737
- state, neat, opts, trainingSet, maze, start, exit, distMap, helpers, true, ...
1695
+ // Yield to the browser's next repaint after dashboard update:
1696
+ await updateDashboardAndMaybeFlush(
1697
+ maze, genResult, fittestNetwork, gen, neatInstance, dashboard, () => new Promise(r => requestAnimationFrame(r))
1738
1698
  );
1739
1699
 
1740
- ### MutableMazeResult
1741
-
1742
- Mutable result object with exitReason field
1743
-
1744
- ### GenerationOutcome
1700
+ ### updateDashboardPeriodic
1745
1701
 
1746
- Generation outcome with profiling timings
1747
-
1748
- ### SimulationOutcome
1749
-
1750
- Simulation result with profiling and ring state
1751
-
1752
- ### EvolutionLoopResult
1753
-
1754
- Evolution loop result
1755
-
1756
- ### SimResultWithOutputs
1757
-
1758
- Simulation result with step outputs
1702
+ ```ts
1703
+ updateDashboardPeriodic(
1704
+ maze: string[],
1705
+ bestResult: IMazeRunResult | undefined,
1706
+ bestNetwork: default | null,
1707
+ completedGenerations: number,
1708
+ neat: default,
1709
+ dashboardManager: IDashboardManager | undefined,
1710
+ flushToFrame: (() => Promise<void>) | undefined,
1711
+ ): Promise<void>
1712
+ ```
1759
1713
 
1760
- ## evolutionEngine/curriculumPhase.ts
1714
+ Periodic dashboard update used when the engine wants to refresh a non-primary
1715
+ dashboard view (for example background or periodic reporting). This helper is
1716
+ intentionally small, allocation-light and best-effort: dashboard errors are
1717
+ swallowed so the evolution loop cannot be interrupted by UI issues.
1761
1718
 
1762
- ### resolveMazeEvolutionPhaseOutcome
1719
+ Behavioural contract:
1720
+ 1) If `dashboardManager.update` is present and callable the method invokes it with
1721
+ the stable argument order: (maze, bestResult, bestNetwork, completedGenerations, neat).
1722
+ 2) If `flushToFrame` is supplied the helper awaits it after the update to yield to
1723
+ the host renderer (eg. requestAnimationFrame). Any exceptions raised by the
1724
+ flush are swallowed.
1725
+ 3) The helper avoids creating ephemeral arrays/objects and therefore does not use
1726
+ typed-array scratch buffers here — there is no hot numerical work to pool. Other
1727
+ engine helpers already reuse class-level scratch buffers where appropriate.
1763
1728
 
1764
- ```ts
1765
- resolveMazeEvolutionPhaseOutcome(
1766
- evolutionResult: MazeEvolutionRunResult,
1767
- previousBestNetwork: INetwork | undefined,
1768
- minProgressToPass: number,
1769
- ): MazeEvolutionCurriculumPhaseOutcome
1770
- ```
1729
+ Design Rationale:
1730
+ - Fast-guard early when update cannot be performed
1731
+ - Best-effort error handling (swallow all exceptions)
1732
+ - Preserves dashboard `this` binding with `.call()`
1733
+ - Minimal allocations (no scratch buffers needed)
1771
1734
 
1772
- Resolve the stable curriculum-facing outcome of one maze evolution phase.
1735
+ Steps / inline intent:
1736
+ 1. Fast-guard when an update cannot be performed (missing manager, update method,
1737
+ or missing content to visualise).
1738
+ 2. Call the dashboard update in a try/catch to preserve best-effort semantics.
1739
+ 3. Optionally await the provided `flushToFrame` function to yield to the host.
1773
1740
 
1774
1741
  Parameters:
1775
- - `evolutionResult` - - Stable engine result returned by `EvolutionEngine.runMazeEvolution()`.
1776
- - `previousBestNetwork` - - Previously carried winner used when the latest phase has no replacement.
1777
- - `minProgressToPass` - - Progress threshold required before curriculum should advance.
1778
1742
 
1779
- Returns: Shared curriculum outcome describing progress, solve state, and next carry-over seed.
1743
+ Parameters:
1744
+ - `maze` - - Maze descriptor passed to the dashboard renderer.
1745
+ - `bestResult` - - Best-run result object used for display (may be falsy when not present).
1746
+ - `bestNetwork` - - Network or genome object to visualise (may be falsy when not present).
1747
+ - `completedGenerations` - - Completed generation index (number).
1748
+ - `neat` - - NEAT manager instance (passed through to dashboard update).
1749
+ - `dashboardManager` - - Optional manager exposing `update(maze, result, network, gen, neat)`.
1750
+ - `flushToFrame` - - Optional async function used to yield to the host/frame scheduler
1751
+ (for example: `() => new Promise(r => requestAnimationFrame(r))`).
1780
1752
 
1781
1753
  Example:
1782
1754
 
1783
- ```ts
1784
- const phaseOutcome = resolveMazeEvolutionPhaseOutcome(result, previousBest, 95);
1785
- if (phaseOutcome.solved) {
1786
- previousBest = phaseOutcome.nextBestNetwork;
1787
- }
1788
- ```
1755
+ // Safe periodic update and yield to next frame
1756
+ await updateDashboardPeriodic(
1757
+ maze, result, network, gen, neatInstance, dashboard, () => new Promise(r => requestAnimationFrame(r))
1758
+ );
1759
+
1760
+ ## evolutionEngine/curriculumPhase.ts
1789
1761
 
1790
1762
  ### hasMazeEvolutionReachedCurriculumThreshold
1791
1763
 
@@ -1821,6 +1793,34 @@ Parameters:
1821
1793
 
1822
1794
  Returns: Refined winner or the best available carry-over network.
1823
1795
 
1796
+ ### resolveMazeEvolutionPhaseOutcome
1797
+
1798
+ ```ts
1799
+ resolveMazeEvolutionPhaseOutcome(
1800
+ evolutionResult: MazeEvolutionRunResult,
1801
+ previousBestNetwork: INetwork | undefined,
1802
+ minProgressToPass: number,
1803
+ ): MazeEvolutionCurriculumPhaseOutcome
1804
+ ```
1805
+
1806
+ Resolve the stable curriculum-facing outcome of one maze evolution phase.
1807
+
1808
+ Parameters:
1809
+ - `evolutionResult` - - Stable engine result returned by `EvolutionEngine.runMazeEvolution()`.
1810
+ - `previousBestNetwork` - - Previously carried winner used when the latest phase has no replacement.
1811
+ - `minProgressToPass` - - Progress threshold required before curriculum should advance.
1812
+
1813
+ Returns: Shared curriculum outcome describing progress, solve state, and next carry-over seed.
1814
+
1815
+ Example:
1816
+
1817
+ ```ts
1818
+ const phaseOutcome = resolveMazeEvolutionPhaseOutcome(result, previousBest, 95);
1819
+ if (phaseOutcome.solved) {
1820
+ previousBest = phaseOutcome.nextBestNetwork;
1821
+ }
1822
+ ```
1823
+
1824
1824
  ## evolutionEngine/optionsAndSetup.ts
1825
1825
 
1826
1826
  Options and Setup Module
@@ -1842,6 +1842,65 @@ ES2023 Policy:
1842
1842
  - Optional chaining `?.` for safe property access
1843
1843
  - Spread operator for object composition
1844
1844
 
1845
+ ### createAndSeedNeat
1846
+
1847
+ ```ts
1848
+ createAndSeedNeat(
1849
+ opts: NormalizedRunOptions,
1850
+ inputSize: number,
1851
+ outputSize: number,
1852
+ fitnessContext: IFitnessEvaluationContext,
1853
+ scratchPopClone: default[],
1854
+ scratchSample: unknown[],
1855
+ ): CreateAndSeedNeatResult
1856
+ ```
1857
+
1858
+ Create and seed a NEAT driver with normalized configuration and optional initial population.
1859
+
1860
+ This function orchestrates the complete NEAT setup workflow:
1861
+ 1) Build a fitness callback bound to the fitness context
1862
+ 2) Instantiate the NEAT driver with normalized options
1863
+ 3) Seed the driver's population from optional initial networks
1864
+ 4) Warm up pooled scratch buffers to reduce first-use allocation spikes
1865
+
1866
+ Design Rationale:
1867
+ - Single orchestration point for NEAT creation + seeding
1868
+ - Delegates heavy lifting to createNeat and seedInitialPopulation
1869
+ - Best-effort buffer warm-up (failures swallowed)
1870
+ - Returns updated scratch buffers for caller to persist
1871
+
1872
+ Buffer Management:
1873
+ - Accepts and returns scratchPopClone buffer (grown if needed)
1874
+ - Accepts and returns scratchSample buffer (grown if needed)
1875
+ - Caller should persist returned buffers for reuse across runs
1876
+
1877
+ Parameters:
1878
+
1879
+ Parameters:
1880
+ - `opts` - - Normalized run options (produced by normalizeRunOptions)
1881
+ - `inputSize` - - Network input count
1882
+ - `outputSize` - - Network output count
1883
+ - `fitnessContext` - - Compact fitness evaluation context
1884
+ - `scratchPopClone` - - Pooled clone buffer (will be grown if needed)
1885
+ - `scratchSample` - - Pooled sample buffer (will be grown if needed)
1886
+
1887
+ Returns: Object containing:
1888
+ - neat: Configured and seeded NEAT driver instance
1889
+ - scratchPopClone: Updated clone buffer (may be new array if grown)
1890
+ - scratchSample: Updated sample buffer (may be new array if grown)
1891
+
1892
+ Example:
1893
+
1894
+ // Create and seed NEAT with optional initial population
1895
+ const { neat, scratchPopClone, scratchSample } = createAndSeedNeat(
1896
+ normalizedOpts,
1897
+ 6,
1898
+ 4,
1899
+ fitnessContext,
1900
+ scratchPopCloneBuffer,
1901
+ scratchSampleBuffer
1902
+ );
1903
+
1845
1904
  ### normalizeRunOptions
1846
1905
 
1847
1906
  ```ts
@@ -1964,72 +2023,41 @@ Example:
1964
2023
  const env = prepareEnvironmentForRun(normalizedOpts, engineState.scratch);
1965
2024
  const neat = createAndSeedNeat(normalizedOpts, env.inputSize, env.outputSize, env.fitnessContext);
1966
2025
 
1967
- ### createAndSeedNeat
1968
-
1969
- ```ts
1970
- createAndSeedNeat(
1971
- opts: NormalizedRunOptions,
1972
- inputSize: number,
1973
- outputSize: number,
1974
- fitnessContext: IFitnessEvaluationContext,
1975
- scratchPopClone: default[],
1976
- scratchSample: unknown[],
1977
- ): CreateAndSeedNeatResult
1978
- ```
1979
-
1980
- Create and seed a NEAT driver with normalized configuration and optional initial population.
2026
+ ## evolutionEngine/telemetryMetrics.ts
1981
2027
 
1982
- This function orchestrates the complete NEAT setup workflow:
1983
- 1) Build a fitness callback bound to the fitness context
1984
- 2) Instantiate the NEAT driver with normalized options
1985
- 3) Seed the driver's population from optional initial networks
1986
- 4) Warm up pooled scratch buffers to reduce first-use allocation spikes
2028
+ Telemetry logging and metric computation helpers extracted from the ASCII maze evolution engine.
1987
2029
 
1988
- Design Rationale:
1989
- - Single orchestration point for NEAT creation + seeding
1990
- - Delegates heavy lifting to createNeat and seedInitialPopulation
1991
- - Best-effort buffer warm-up (failures swallowed)
1992
- - Returns updated scratch buffers for caller to persist
2030
+ The helpers in this module operate on the shared {@link EngineState} scratch buffers to avoid
2031
+ per-call allocations while keeping the main façade lighter. All telemetry is best-effort: any
2032
+ internal error is swallowed so that logging never impacts the evolution loop.
1993
2033
 
1994
- Buffer Management:
1995
- - Accepts and returns scratchPopClone buffer (grown if needed)
1996
- - Accepts and returns scratchSample buffer (grown if needed)
1997
- - Caller should persist returned buffers for reuse across runs
2034
+ ### ActionEntropyStats
1998
2035
 
1999
- Parameters:
2036
+ Structure describing the result of action-entropy computation.
2000
2037
 
2001
- Parameters:
2002
- - `opts` - - Normalized run options (produced by normalizeRunOptions)
2003
- - `inputSize` - - Network input count
2004
- - `outputSize` - - Network output count
2005
- - `fitnessContext` - - Compact fitness evaluation context
2006
- - `scratchPopClone` - - Pooled clone buffer (will be grown if needed)
2007
- - `scratchSample` - - Pooled sample buffer (will be grown if needed)
2038
+ ### collectTelemetryTail
2008
2039
 
2009
- Returns: Object containing:
2010
- - neat: Configured and seeded NEAT driver instance
2011
- - scratchPopClone: Updated clone buffer (may be new array if grown)
2012
- - scratchSample: Updated sample buffer (may be new array if grown)
2040
+ ```ts
2041
+ collectTelemetryTail(
2042
+ state: EngineState,
2043
+ neat: unknown,
2044
+ tailLength: number,
2045
+ ): unknown
2046
+ ```
2013
2047
 
2014
- Example:
2048
+ Collect a short telemetry tail from a NEAT instance when available.
2015
2049
 
2016
- // Create and seed NEAT with optional initial population
2017
- const { neat, scratchPopClone, scratchSample } = createAndSeedNeat(
2018
- normalizedOpts,
2019
- 6,
2020
- 4,
2021
- fitnessContext,
2022
- scratchPopCloneBuffer,
2023
- scratchSampleBuffer
2024
- );
2050
+ Parameters:
2051
+ - `state` - Shared engine state (provides pooled scratch buffers for `getTail`).
2052
+ - `neat` - NEAT instance that may expose a `getTelemetry` function.
2053
+ - `tailLength` - Desired tail length (floored to an integer >= 0). Defaults to 10.
2025
2054
 
2026
- ## evolutionEngine/telemetryMetrics.ts
2055
+ Returns: Tail array, raw telemetry value or `undefined` on missing API/errors.
2027
2056
 
2028
- Telemetry logging and metric computation helpers extracted from the ASCII maze evolution engine.
2057
+ ### GenerationResult
2029
2058
 
2030
- The helpers in this module operate on the shared {@link EngineState} scratch buffers to avoid
2031
- per-call allocations while keeping the main façade lighter. All telemetry is best-effort: any
2032
- internal error is swallowed so that logging never impacts the evolution loop.
2059
+ Minimal structure representing a generation evolution result.
2060
+ Expected to have a path property containing the movement history.
2033
2061
 
2034
2062
  ### LOG_TAG_ACTION_ENTROPY
2035
2063
 
@@ -2039,14 +2067,6 @@ Example:
2039
2067
 
2040
2068
  safeWrite(`${LOG_TAG_ACTION_ENTROPY} gen=1 entropyNorm=0.500 uniqueMoves=4 pathLen=32\n`);
2041
2069
 
2042
- ### LOG_TAG_OUTPUT_BIAS
2043
-
2044
- Telemetry tag emitted when logging bias statistics for output nodes.
2045
-
2046
- Example:
2047
-
2048
- safeWrite(`${LOG_TAG_OUTPUT_BIAS} gen=2 mean=0.001 std=0.010 biases=0.01,-0.02,0.03,-0.01\n`);
2049
-
2050
2070
  ### LOG_TAG_LOGITS
2051
2071
 
2052
2072
  Telemetry tag emitted when logging logits statistics and collapse diagnostics.
@@ -2055,9 +2075,13 @@ Example:
2055
2075
 
2056
2076
  safeWrite(`${LOG_TAG_LOGITS} gen=3 means=0.001,0.002,-0.001,-0.002 stds=0.01,0.02,0.03,0.04 kurt=0,0,0,0 entMean=0.500 stability=0.750 steps=32\n`);
2057
2077
 
2058
- ### LogActionEntropyParams
2078
+ ### LOG_TAG_OUTPUT_BIAS
2059
2079
 
2060
- Parameters required to emit action-entropy telemetry.
2080
+ Telemetry tag emitted when logging bias statistics for output nodes.
2081
+
2082
+ Example:
2083
+
2084
+ safeWrite(`${LOG_TAG_OUTPUT_BIAS} gen=2 mean=0.001 std=0.010 biases=0.01,-0.02,0.03,-0.01\n`);
2061
2085
 
2062
2086
  ### logActionEntropy
2063
2087
 
@@ -2074,47 +2098,28 @@ Parameters:
2074
2098
 
2075
2099
  Returns: void
2076
2100
 
2077
- ### LogOutputBiasParams
2078
-
2079
- Parameters required to emit output-bias telemetry.
2080
-
2081
- ### logOutputBiasStats
2082
-
2083
- ```ts
2084
- logOutputBiasStats(
2085
- __0: LogOutputBiasParams,
2086
- ): void
2087
- ```
2088
-
2089
- Emit bias statistics for the fittest network's output nodes.
2090
-
2091
- Parameters:
2092
- - `params` - Shared state, subject network and writer callback.
2093
-
2094
- Returns: void
2095
-
2096
- ### LogLogitsParams
2101
+ ### LogActionEntropyParams
2097
2102
 
2098
- Parameters required to emit logits statistics, perform collapse detection and trigger recovery.
2103
+ Parameters required to emit action-entropy telemetry.
2099
2104
 
2100
- ### logLogitsAndCollapse
2105
+ ### logDiversity
2101
2106
 
2102
2107
  ```ts
2103
- logLogitsAndCollapse(
2104
- __0: LogLogitsParams,
2108
+ logDiversity(
2109
+ __0: LogDiversityParams,
2105
2110
  ): void
2106
2111
  ```
2107
2112
 
2108
- Emit logits-level telemetry, detect collapse streaks and trigger anti-collapse recovery when needed.
2113
+ Emit diversity telemetry including species count, Simpson index and weight standard deviation.
2109
2114
 
2110
2115
  Parameters:
2111
- - `params` - Shared state, subject genomes and telemetry configuration.
2116
+ - `params` - Shared state, NEAT population reference and logger callback.
2112
2117
 
2113
2118
  Returns: void
2114
2119
 
2115
- ### LogExplorationParams
2120
+ ### LogDiversityParams
2116
2121
 
2117
- Parameters required to emit exploration telemetry.
2122
+ Parameters required to emit population diversity telemetry.
2118
2123
 
2119
2124
  ### logExploration
2120
2125
 
@@ -2131,43 +2136,9 @@ Parameters:
2131
2136
 
2132
2137
  Returns: void
2133
2138
 
2134
- ### LogDiversityParams
2135
-
2136
- Parameters required to emit population diversity telemetry.
2137
-
2138
- ### logDiversity
2139
-
2140
- ```ts
2141
- logDiversity(
2142
- __0: LogDiversityParams,
2143
- ): void
2144
- ```
2145
-
2146
- Emit diversity telemetry including species count, Simpson index and weight standard deviation.
2147
-
2148
- Parameters:
2149
- - `params` - Shared state, NEAT population reference and logger callback.
2150
-
2151
- Returns: void
2152
-
2153
- ### collectTelemetryTail
2154
-
2155
- ```ts
2156
- collectTelemetryTail(
2157
- state: EngineState,
2158
- neat: unknown,
2159
- tailLength: number,
2160
- ): unknown
2161
- ```
2162
-
2163
- Collect a short telemetry tail from a NEAT instance when available.
2164
-
2165
- Parameters:
2166
- - `state` - Shared engine state (provides pooled scratch buffers for `getTail`).
2167
- - `neat` - NEAT instance that may expose a `getTelemetry` function.
2168
- - `tailLength` - Desired tail length (floored to an integer >= 0). Defaults to 10.
2139
+ ### LogExplorationParams
2169
2140
 
2170
- Returns: Tail array, raw telemetry value or `undefined` on missing API/errors.
2141
+ Parameters required to emit exploration telemetry.
2171
2142
 
2172
2143
  ### logGenerationTelemetry
2173
2144
 
@@ -2238,36 +2209,65 @@ logGenerationTelemetry(
2238
2209
  isProfilingDetailsEnabled, profilingStartTimestamp, accumulateProfilingDuration
2239
2210
  );
2240
2211
 
2241
- ### TelemetryWriter
2212
+ ### LogitStatsParams
2213
+
2214
+ Input parameters for computing logit statistics.
2215
+
2216
+ ### LogitStatsResult
2217
+
2218
+ Structure describing aggregated logit statistics.
2219
+
2220
+ ### logLogitsAndCollapse
2242
2221
 
2243
2222
  ```ts
2244
- TelemetryWriter(
2245
- message: string,
2223
+ logLogitsAndCollapse(
2224
+ __0: LogLogitsParams,
2246
2225
  ): void
2247
2226
  ```
2248
2227
 
2249
- Writer signature reused across telemetry helpers.
2228
+ Emit logits-level telemetry, detect collapse streaks and trigger anti-collapse recovery when needed.
2250
2229
 
2251
- ### GenerationResult
2230
+ Parameters:
2231
+ - `params` - Shared state, subject genomes and telemetry configuration.
2252
2232
 
2253
- Minimal structure representing a generation evolution result.
2254
- Expected to have a path property containing the movement history.
2233
+ Returns: void
2255
2234
 
2256
- ### TelemetryBaseParams
2235
+ ### LogLogitsParams
2257
2236
 
2258
- Parameters shared by telemetry helpers that require access to the shared state and writer.
2237
+ Parameters required to emit logits statistics, perform collapse detection and trigger recovery.
2259
2238
 
2260
- ### ActionEntropyStats
2239
+ ### LogOutputBiasParams
2261
2240
 
2262
- Structure describing the result of action-entropy computation.
2241
+ Parameters required to emit output-bias telemetry.
2263
2242
 
2264
- ### LogitStatsParams
2243
+ ### logOutputBiasStats
2265
2244
 
2266
- Input parameters for computing logit statistics.
2245
+ ```ts
2246
+ logOutputBiasStats(
2247
+ __0: LogOutputBiasParams,
2248
+ ): void
2249
+ ```
2267
2250
 
2268
- ### LogitStatsResult
2251
+ Emit bias statistics for the fittest network's output nodes.
2269
2252
 
2270
- Structure describing aggregated logit statistics.
2253
+ Parameters:
2254
+ - `params` - Shared state, subject network and writer callback.
2255
+
2256
+ Returns: void
2257
+
2258
+ ### TelemetryBaseParams
2259
+
2260
+ Parameters shared by telemetry helpers that require access to the shared state and writer.
2261
+
2262
+ ### TelemetryWriter
2263
+
2264
+ ```ts
2265
+ TelemetryWriter(
2266
+ message: string,
2267
+ ): void
2268
+ ```
2269
+
2270
+ Writer signature reused across telemetry helpers.
2271
2271
 
2272
2272
  ## evolutionEngine/neatConfiguration.ts
2273
2273
 
@@ -2290,10 +2290,6 @@ ES2023 Policy:
2290
2290
  - Optional chaining `?.` for safe property access
2291
2291
  - Spread operator for array/object operations
2292
2292
 
2293
- ### NeatConfig
2294
-
2295
- NEAT configuration object shape for type safety.
2296
-
2297
2293
  ### createNeat
2298
2294
 
2299
2295
  ```ts
@@ -2356,6 +2352,10 @@ const neat = createNeat(10, 4, fitnessFn, { popSize: 200, lineageTracking: false
2356
2352
  // Create with default configuration
2357
2353
  const neat = createNeat(10, 4, fitnessFn);
2358
2354
 
2355
+ ### NeatConfig
2356
+
2357
+ NEAT configuration object shape for type safety.
2358
+
2359
2359
  ### seedInitialPopulation
2360
2360
 
2361
2361
  ```ts
@@ -2433,36 +2433,6 @@ ES2023 Policy:
2433
2433
  - Pooled scratch buffers to avoid allocations
2434
2434
  - Best-effort error handling (swallow non-fatal errors)
2435
2435
 
2436
- ### swallowError
2437
-
2438
- ```ts
2439
- swallowError(
2440
- error: unknown,
2441
- ): void
2442
- ```
2443
-
2444
- Utility to explicitly mark swallowed errors for lint compliance.
2445
-
2446
- This function is used to explicitly void error objects in catch blocks
2447
- to satisfy linters that flag unused catch binding variables. It has no
2448
- runtime effect beyond the void operation.
2449
-
2450
- Design Rationale:
2451
- - Explicit intent signaling for best-effort error handling
2452
- - Lint-compliant alternative to catch binding suppression
2453
- - Zero runtime overhead (optimized away by JIT)
2454
-
2455
- Parameters:
2456
- - `error` - - The error object to void (can be any type)
2457
-
2458
- Example:
2459
-
2460
- try {
2461
- riskyOperation();
2462
- } catch (error) {
2463
- swallowError(error); // Explicit void for lint compliance
2464
- }
2465
-
2466
2436
  ### printNetworkStructure
2467
2437
 
2468
2438
  ```ts
@@ -2493,6 +2463,36 @@ Example:
2493
2463
 
2494
2464
  printNetworkStructure(state, bestNetwork);
2495
2465
 
2466
+ ### swallowError
2467
+
2468
+ ```ts
2469
+ swallowError(
2470
+ error: unknown,
2471
+ ): void
2472
+ ```
2473
+
2474
+ Utility to explicitly mark swallowed errors for lint compliance.
2475
+
2476
+ This function is used to explicitly void error objects in catch blocks
2477
+ to satisfy linters that flag unused catch binding variables. It has no
2478
+ runtime effect beyond the void operation.
2479
+
2480
+ Design Rationale:
2481
+ - Explicit intent signaling for best-effort error handling
2482
+ - Lint-compliant alternative to catch binding suppression
2483
+ - Zero runtime overhead (optimized away by JIT)
2484
+
2485
+ Parameters:
2486
+ - `error` - - The error object to void (can be any type)
2487
+
2488
+ Example:
2489
+
2490
+ try {
2491
+ riskyOperation();
2492
+ } catch (error) {
2493
+ swallowError(error); // Explicit void for lint compliance
2494
+ }
2495
+
2496
2496
  ## evolutionEngine/populationPruning.ts
2497
2497
 
2498
2498
  Population pruning and network warm-start helpers for the ASCII maze evolution engine.
@@ -2510,6 +2510,35 @@ Responsibilities:
2510
2510
 
2511
2511
  All functions are best-effort: internal errors are swallowed to avoid destabilizing the evolution loop.
2512
2512
 
2513
+ ### applyCompassWarmStart
2514
+
2515
+ ```ts
2516
+ applyCompassWarmStart(
2517
+ __0: ApplyCompassWarmStartParams,
2518
+ ): void
2519
+ ```
2520
+
2521
+ Warm-start wiring for compass and directional openness inputs.
2522
+
2523
+ Steps:
2524
+ 1. Validate network structure and extract node/connection arrays.
2525
+ 2. Collect input and output node indices using the shared helper.
2526
+ 3. For each of the 4 compass directions, ensure an input→output connection exists with light initialization.
2527
+ 4. Connect the special 'compass' input (index 0) to all outputs with deterministic base weights.
2528
+
2529
+ Parameters:
2530
+ - `params` - Shared state and network reference.
2531
+
2532
+ Returns: void
2533
+
2534
+ Example:
2535
+
2536
+ applyCompassWarmStart({ state: sharedState, network: trainedNetwork });
2537
+
2538
+ ### ApplyCompassWarmStartParams
2539
+
2540
+ Parameters for warm-starting compass wiring.
2541
+
2513
2542
  ### ApplySimplifyPruningParams
2514
2543
 
2515
2544
  Parameters for applying simplify pruning to a population.
@@ -2542,48 +2571,15 @@ applySimplifyPruningToPopulation({
2542
2571
  simplifyPruneFraction: 0.15,
2543
2572
  });
2544
2573
 
2545
- ### ApplyCompassWarmStartParams
2546
-
2547
- Parameters for warm-starting compass wiring.
2548
-
2549
- ### applyCompassWarmStart
2574
+ ### centerOutputBiases
2550
2575
 
2551
2576
  ```ts
2552
- applyCompassWarmStart(
2553
- __0: ApplyCompassWarmStartParams,
2577
+ centerOutputBiases(
2578
+ __0: CenterOutputBiasesParams,
2554
2579
  ): void
2555
2580
  ```
2556
2581
 
2557
- Warm-start wiring for compass and directional openness inputs.
2558
-
2559
- Steps:
2560
- 1. Validate network structure and extract node/connection arrays.
2561
- 2. Collect input and output node indices using the shared helper.
2562
- 3. For each of the 4 compass directions, ensure an input→output connection exists with light initialization.
2563
- 4. Connect the special 'compass' input (index 0) to all outputs with deterministic base weights.
2564
-
2565
- Parameters:
2566
- - `params` - Shared state and network reference.
2567
-
2568
- Returns: void
2569
-
2570
- Example:
2571
-
2572
- applyCompassWarmStart({ state: sharedState, network: trainedNetwork });
2573
-
2574
- ### CenterOutputBiasesParams
2575
-
2576
- Parameters for re-centering output biases.
2577
-
2578
- ### centerOutputBiases
2579
-
2580
- ```ts
2581
- centerOutputBiases(
2582
- __0: CenterOutputBiasesParams,
2583
- ): void
2584
- ```
2585
-
2586
- Re-center and clamp output node biases to prevent drift.
2582
+ Re-center and clamp output node biases to prevent drift.
2587
2583
 
2588
2584
  Steps:
2589
2585
  1. Collect output node indices using the shared helper.
@@ -2600,6 +2596,10 @@ Example:
2600
2596
 
2601
2597
  centerOutputBiases({ state: sharedState, network: trainedNetwork });
2602
2598
 
2599
+ ### CenterOutputBiasesParams
2600
+
2601
+ Parameters for re-centering output biases.
2602
+
2603
2603
  ## evolutionEngine/trainingWarmStart.ts
2604
2604
 
2605
2605
  trainingWarmStart.ts
@@ -2622,43 +2622,6 @@ solve the maze with backprop. They are trying to give evolution a better
2622
2622
  first draft while preserving the example's core identity as an evolutionary
2623
2623
  system.
2624
2624
 
2625
- ### buildLamarckianTrainingSet
2626
-
2627
- ```ts
2628
- buildLamarckianTrainingSet(
2629
- state: EngineState,
2630
- constants: { TRAIN_OUT_PROB_HIGH: number; TRAIN_OUT_PROB_LOW: number; PROGRESS_MEDIUM: number; PROGRESS_STRONG: number; PROGRESS_JUNCTION: number; PROGRESS_FOURWAY: number; PROGRESS_REGRESS: number; PROGRESS_MIN_SIGNAL: number; PROGRESS_MILD_REGRESS: number; DEFAULT_JITTER_PROB: number; AUGMENT_JITTER_BASE: number; AUGMENT_JITTER_RANGE: number; AUGMENT_PROGRESS_JITTER_PROB: number; AUGMENT_PROGRESS_DELTA_RANGE: number; AUGMENT_PROGRESS_DELTA_HALF: number; RNG_PARAMETERS: RngCacheParameters; },
2631
- ): { input: number[]; output: number[]; }[]
2632
- ```
2633
-
2634
- Build the supervised training set used for Lamarckian warm-start training.
2635
-
2636
- Generates a small curated dataset of canonical navigation scenarios combining:
2637
- - Single-path corridors with varying progress signals
2638
- - Two-way junctions with directional bias
2639
- - Four-way intersections with full openness variety
2640
- - Regression cases (backtracking or stalled progress)
2641
- - Mild data augmentation via random jitter on openness and progress values
2642
-
2643
- Each training case maps a 6-dimensional input to a soft one-hot output:
2644
- - Input: [compassScalar, openN, openE, openS, openW, progressDelta]
2645
- - Output: [pN, pE, pS, pW] with probabilities (high for target, low for others)
2646
-
2647
- Parameters:
2648
- - `state` - - Shared engine state (used for RNG when applying jitter augmentation).
2649
- - `constants` - - Training hyperparameters and signal constants.
2650
-
2651
- Returns: Array of training cases `{ input: number[], output: number[] }`.
2652
-
2653
- Example:
2654
-
2655
- const trainingSet = buildLamarckianTrainingSet(engineState, {
2656
- TRAIN_OUT_PROB_HIGH: 0.9,
2657
- TRAIN_OUT_PROB_LOW: 0.033,
2658
- PROGRESS_MEDIUM: 0.5,
2659
- // ... other constants
2660
- });
2661
-
2662
2625
  ### adjustOutputBiasesAfterTraining
2663
2626
 
2664
2627
  ```ts
@@ -2702,52 +2665,6 @@ adjustOutputBiasesAfterTraining(
2702
2665
  getNodeIndicesByType
2703
2666
  );
2704
2667
 
2705
- ### pretrainPopulationWarmStart
2706
-
2707
- ```ts
2708
- pretrainPopulationWarmStart(
2709
- neat: default,
2710
- lamarckianTrainingSet: LamarckianTrainingCase[],
2711
- constants: { PRETRAIN_MAX_ITER: number; PRETRAIN_BASE_ITER: number; DEFAULT_TRAIN_ERROR: number; DEFAULT_PRETRAIN_RATE: number; DEFAULT_PRETRAIN_MOMENTUM: number; DEFAULT_TRAIN_BATCH_SMALL: number; },
2712
- applyCompassWarmStart: WarmStartNetworkCallback,
2713
- centerOutputBiases: WarmStartNetworkCallback,
2714
- ): void
2715
- ```
2716
-
2717
- Pretrain the population using a small supervised dataset and apply warm-start heuristics.
2718
-
2719
- Behaviour & contract:
2720
- - Runs a short supervised training pass on each network in `neat.population`
2721
- - Treats the training set as a biasing hint, not as a replacement for later evolution
2722
- - Applies lightweight warm-start heuristics after training: compass wiring
2723
- and output-bias centering
2724
- - Isolates failures per network so one bad trainer state does not abort the
2725
- rest of the population
2726
- - Stays allocation-light so warm-start remains cheap enough to use as a
2727
- tactical assist instead of a second training regime
2728
-
2729
- Steps:
2730
- 1. Validate inputs and obtain `population` (fast-exit on empty populations)
2731
- 2. For each network: guard missing `train` method, compute conservative iteration budget, then call `train`
2732
- 3. Apply warm-start heuristics (compass wiring + bias centering). Swallow any per-network exceptions.
2733
-
2734
- Parameters:
2735
- - `neat` - - NEAT instance exposing a `population` array of networks.
2736
- - `lamarckianTrainingSet` - - Array of `{input:number[], output:number[]}` training cases.
2737
- - `constants` - - Training hyperparameters (iteration limits, learning rates, etc.).
2738
- - `applyCompassWarmStart` - - Helper function for compass wiring adjustment.
2739
- - `centerOutputBiases` - - Helper function for output bias centering.
2740
-
2741
- Example:
2742
-
2743
- pretrainPopulationWarmStart(
2744
- neatInstance,
2745
- trainingDataset,
2746
- { PRETRAIN_MAX_ITER: 10, PRETRAIN_BASE_ITER: 3, ... },
2747
- applyCompassWarmStart,
2748
- centerOutputBiases
2749
- );
2750
-
2751
2668
  ### applyLamarckianTraining
2752
2669
 
2753
2670
  ```ts
@@ -2812,63 +2729,47 @@ const elapsed = applyLamarckianTraining(
2812
2729
  adjustOutputBiasesAfterTraining
2813
2730
  );
2814
2731
 
2815
- ### warmStartPopulationIfNeeded
2732
+ ### buildLamarckianTrainingSet
2816
2733
 
2817
2734
  ```ts
2818
- warmStartPopulationIfNeeded(
2819
- neat: default,
2820
- trainingSet: LamarckianTrainingCase[],
2735
+ buildLamarckianTrainingSet(
2821
2736
  state: EngineState,
2822
- pretrainPopulation: PretrainPopulationCallback,
2823
- ): void
2737
+ constants: { TRAIN_OUT_PROB_HIGH: number; TRAIN_OUT_PROB_LOW: number; PROGRESS_MEDIUM: number; PROGRESS_STRONG: number; PROGRESS_JUNCTION: number; PROGRESS_FOURWAY: number; PROGRESS_REGRESS: number; PROGRESS_MIN_SIGNAL: number; PROGRESS_MILD_REGRESS: number; DEFAULT_JITTER_PROB: number; AUGMENT_JITTER_BASE: number; AUGMENT_JITTER_RANGE: number; AUGMENT_PROGRESS_JITTER_PROB: number; AUGMENT_PROGRESS_DELTA_RANGE: number; AUGMENT_PROGRESS_DELTA_HALF: number; RNG_PARAMETERS: RngCacheParameters; },
2738
+ ): { input: number[]; output: number[]; }[]
2824
2739
  ```
2825
2740
 
2826
- Conditionally warm-start / pretrain the population using a provided training set.
2741
+ Build the supervised training set used for Lamarckian warm-start training.
2827
2742
 
2828
- Behaviour & contract:
2829
- - If a non-empty `trainingSet` is provided this method will attempt a best-effort
2830
- invocation of `pretrainPopulationWarmStart(neat, trainingSet)`
2831
- - To reduce first-use allocation spikes the helper will also attempt to ensure
2832
- engine-level pooled buffers exist and have a reasonable capacity before
2833
- pretraining begins (plain Array for sampling and Float64Array for numeric work)
2834
- - All operations are non-throwing; any internal error is swallowed to keep the
2835
- evolution loop resilient
2743
+ Generates a small curated dataset of canonical navigation scenarios combining:
2744
+ - Single-path corridors with varying progress signals
2745
+ - Two-way junctions with directional bias
2746
+ - Four-way intersections with full openness variety
2747
+ - Regression cases (backtracking or stalled progress)
2748
+ - Mild data augmentation via random jitter on openness and progress values
2836
2749
 
2837
- Steps:
2838
- 1. Fast-guard invalid inputs nothing to do when no data or driver
2839
- 2. Best-effort ensure pooled buffers exist and have capacity
2840
- 3. Invoke the pretrain helper (best-effort). This may mutate the NEAT driver
2750
+ Each training case maps a 6-dimensional input to a soft one-hot output:
2751
+ - Input: [compassScalar, openN, openE, openS, openW, progressDelta]
2752
+ - Output: [pN, pE, pS, pW] with probabilities (high for target, low for others)
2841
2753
 
2842
2754
  Parameters:
2843
- - `neat` - - NEAT driver instance which will be pre-trained (may be `null`/`undefined`).
2844
- - `trainingSet` - - Array of supervised training cases used for warm-start; ignored when empty.
2845
- - `state` - - Shared engine state (provides scratch buffer pools).
2846
- - `pretrainPopulation` - - Helper function for population pretraining.
2755
+ - `state` - - Shared engine state (used for RNG when applying jitter augmentation).
2756
+ - `constants` - - Training hyperparameters and signal constants.
2757
+
2758
+ Returns: Array of training cases `{ input: number[], output: number[] }`.
2847
2759
 
2848
2760
  Example:
2849
2761
 
2850
- warmStartPopulationIfNeeded(
2851
- neatDriver,
2852
- trainingCasesArray,
2853
- engineState,
2854
- pretrainPopulationWarmStart
2855
- );
2762
+ const trainingSet = buildLamarckianTrainingSet(engineState, {
2763
+ TRAIN_OUT_PROB_HIGH: 0.9,
2764
+ TRAIN_OUT_PROB_LOW: 0.033,
2765
+ PROGRESS_MEDIUM: 0.5,
2766
+ // ... other constants
2767
+ });
2856
2768
 
2857
2769
  ### LamarckianTrainingCase
2858
2770
 
2859
2771
  Small supervised case used during Lamarckian warm-start.
2860
2772
 
2861
- ### TrainableNetwork
2862
-
2863
- The warm-start path trains ordinary runtime networks; this alias keeps intent explicit.
2864
-
2865
- ### WarmStartNeatLike
2866
-
2867
- Narrow NEAT view used by the warm-start helpers.
2868
-
2869
- These helpers only need population access and a couple of option fields, so
2870
- they avoid depending on the entire engine-facing driver surface.
2871
-
2872
2773
  ### NodeIndexCollector
2873
2774
 
2874
2775
  ```ts
@@ -2880,256 +2781,286 @@ NodeIndexCollector(
2880
2781
 
2881
2782
  Callback used when a helper needs to write node indices of a specific role into scratch.
2882
2783
 
2883
- ### WarmStartNetworkCallback
2784
+ ### PretrainPopulationCallback
2884
2785
 
2885
2786
  ```ts
2886
- WarmStartNetworkCallback(
2887
- network: default,
2787
+ PretrainPopulationCallback(
2788
+ neat: default,
2789
+ trainingSet: LamarckianTrainingCase[],
2888
2790
  ): void
2889
2791
  ```
2890
2792
 
2891
- Best-effort post-training hook applied to one network at a time.
2793
+ Population-wide warm-start hook used by the public orchestration helper.
2892
2794
 
2893
- ### PretrainPopulationCallback
2795
+ ### pretrainPopulationWarmStart
2894
2796
 
2895
2797
  ```ts
2896
- PretrainPopulationCallback(
2798
+ pretrainPopulationWarmStart(
2897
2799
  neat: default,
2898
- trainingSet: LamarckianTrainingCase[],
2800
+ lamarckianTrainingSet: LamarckianTrainingCase[],
2801
+ constants: { PRETRAIN_MAX_ITER: number; PRETRAIN_BASE_ITER: number; DEFAULT_TRAIN_ERROR: number; DEFAULT_PRETRAIN_RATE: number; DEFAULT_PRETRAIN_MOMENTUM: number; DEFAULT_TRAIN_BATCH_SMALL: number; },
2802
+ applyCompassWarmStart: WarmStartNetworkCallback,
2803
+ centerOutputBiases: WarmStartNetworkCallback,
2899
2804
  ): void
2900
2805
  ```
2901
2806
 
2902
- Population-wide warm-start hook used by the public orchestration helper.
2807
+ Pretrain the population using a small supervised dataset and apply warm-start heuristics.
2903
2808
 
2904
- ## evolutionEngine/populationDynamics.ts
2809
+ Behaviour & contract:
2810
+ - Runs a short supervised training pass on each network in `neat.population`
2811
+ - Treats the training set as a biasing hint, not as a replacement for later evolution
2812
+ - Applies lightweight warm-start heuristics after training: compass wiring
2813
+ and output-bias centering
2814
+ - Isolates failures per network so one bad trainer state does not abort the
2815
+ rest of the population
2816
+ - Stays allocation-light so warm-start remains cheap enough to use as a
2817
+ tactical assist instead of a second training regime
2905
2818
 
2906
- populationDynamics.ts
2819
+ Steps:
2820
+ 1. Validate inputs and obtain `population` (fast-exit on empty populations)
2821
+ 2. For each network: guard missing `train` method, compute conservative iteration budget, then call `train`
2822
+ 3. Apply warm-start heuristics (compass wiring + bias centering). Swallow any per-network exceptions.
2907
2823
 
2908
- Population-level dynamics for the ASCII Maze evolution loop.
2824
+ Parameters:
2825
+ - `neat` - - NEAT instance exposing a `population` array of networks.
2826
+ - `lamarckianTrainingSet` - - Array of `{input:number[], output:number[]}` training cases.
2827
+ - `constants` - - Training hyperparameters (iteration limits, learning rates, etc.).
2828
+ - `applyCompassWarmStart` - - Helper function for compass wiring adjustment.
2829
+ - `centerOutputBiases` - - Helper function for output bias centering.
2909
2830
 
2910
- This module owns the parts of the run that only make sense once the engine
2911
- stops thinking about one genome at a time and starts thinking about the
2912
- population as a living search process: plateau detection, simplify phases,
2913
- parent selection, child creation, collapse recovery, and bulk connection
2914
- cleanup.
2831
+ Example:
2915
2832
 
2916
- Responsibilities:
2917
- - Decide when search appears stuck and whether to enter a simplify phase
2918
- - Expand the population by sampling from the current top performers
2919
- - Sort genomes by fitness without allocating fresh arrays every generation
2920
- - Track species diversity so collapse is visible instead of silent
2921
- - Recover from pathological convergence by perturbing outputs and weights
2922
- - Compact disabled connections once pruning has made them dead weight
2833
+ pretrainPopulationWarmStart(
2834
+ neatInstance,
2835
+ trainingDataset,
2836
+ { PRETRAIN_MAX_ITER: 10, PRETRAIN_BASE_ITER: 3, ... },
2837
+ applyCompassWarmStart,
2838
+ centerOutputBiases
2839
+ );
2923
2840
 
2924
- The helpers here are intentionally allocation-light because they sit on the
2925
- hot path of long runs. They lean on `EngineState` scratch buffers and accept
2926
- slightly loose runtime surfaces so the public loop can stay orchestration-
2927
- first while these internals adapt to the real Neat and Network instances.
2841
+ ### TrainableNetwork
2928
2842
 
2929
- ### updatePlateauState
2843
+ The warm-start path trains ordinary runtime networks; this alias keeps intent explicit.
2930
2844
 
2931
- ```ts
2932
- updatePlateauState(
2933
- fitness: number,
2934
- lastBestFitnessForPlateau: number,
2935
- plateauCounter: number,
2936
- plateauImprovementThreshold: number,
2937
- ): { plateauCounter: number; lastBestFitnessForPlateau: number; }
2938
- ```
2845
+ ### WarmStartNeatLike
2939
2846
 
2940
- Update plateau state based on current fitness vs baseline.
2847
+ Narrow NEAT view used by the warm-start helpers.
2941
2848
 
2942
- Behaviour:
2943
- - Compares `fitness` against `lastBestFitnessForPlateau + threshold`.
2944
- - If improved, resets plateau counter to 0 and updates baseline.
2945
- - Otherwise, increments plateau counter (capped at a safe maximum).
2849
+ These helpers only need population access and a couple of option fields, so
2850
+ they avoid depending on the entire engine-facing driver surface.
2946
2851
 
2947
- Parameters:
2948
- - `fitness` - - Current best fitness (must be finite).
2949
- - `lastBestFitnessForPlateau` - - Previous baseline fitness.
2950
- - `plateauCounter` - - Current consecutive plateau generations.
2951
- - `plateauImprovementThreshold` - - Minimum improvement to reset plateau.
2852
+ ### WarmStartNetworkCallback
2952
2853
 
2953
- Returns: Updated `{ plateauCounter, lastBestFitnessForPlateau }`.
2854
+ ```ts
2855
+ WarmStartNetworkCallback(
2856
+ network: default,
2857
+ ): void
2858
+ ```
2859
+
2860
+ Best-effort post-training hook applied to one network at a time.
2861
+
2862
+ ### warmStartPopulationIfNeeded
2863
+
2864
+ ```ts
2865
+ warmStartPopulationIfNeeded(
2866
+ neat: default,
2867
+ trainingSet: LamarckianTrainingCase[],
2868
+ state: EngineState,
2869
+ pretrainPopulation: PretrainPopulationCallback,
2870
+ ): void
2871
+ ```
2872
+
2873
+ Conditionally warm-start / pretrain the population using a provided training set.
2874
+
2875
+ Behaviour & contract:
2876
+ - If a non-empty `trainingSet` is provided this method will attempt a best-effort
2877
+ invocation of `pretrainPopulationWarmStart(neat, trainingSet)`
2878
+ - To reduce first-use allocation spikes the helper will also attempt to ensure
2879
+ engine-level pooled buffers exist and have a reasonable capacity before
2880
+ pretraining begins (plain Array for sampling and Float64Array for numeric work)
2881
+ - All operations are non-throwing; any internal error is swallowed to keep the
2882
+ evolution loop resilient
2883
+
2884
+ Steps:
2885
+ 1. Fast-guard invalid inputs – nothing to do when no data or driver
2886
+ 2. Best-effort ensure pooled buffers exist and have capacity
2887
+ 3. Invoke the pretrain helper (best-effort). This may mutate the NEAT driver
2888
+
2889
+ Parameters:
2890
+ - `neat` - - NEAT driver instance which will be pre-trained (may be `null`/`undefined`).
2891
+ - `trainingSet` - - Array of supervised training cases used for warm-start; ignored when empty.
2892
+ - `state` - - Shared engine state (provides scratch buffer pools).
2893
+ - `pretrainPopulation` - - Helper function for population pretraining.
2954
2894
 
2955
2895
  Example:
2956
2896
 
2957
- const state = updatePlateauState(1.23, 1.1, 3, 0.05);
2958
- // state => { plateauCounter: 0, lastBestFitnessForPlateau: 1.23 }
2897
+ warmStartPopulationIfNeeded(
2898
+ neatDriver,
2899
+ trainingCasesArray,
2900
+ engineState,
2901
+ pretrainPopulationWarmStart
2902
+ );
2959
2903
 
2960
- ### maybeStartSimplify
2904
+ ## evolutionEngine/populationDynamics.ts
2905
+
2906
+ populationDynamics.ts
2907
+
2908
+ Population-level dynamics for the ASCII Maze evolution loop.
2909
+
2910
+ This module owns the parts of the run that only make sense once the engine
2911
+ stops thinking about one genome at a time and starts thinking about the
2912
+ population as a living search process: plateau detection, simplify phases,
2913
+ parent selection, child creation, collapse recovery, and bulk connection
2914
+ cleanup.
2915
+
2916
+ Responsibilities:
2917
+ - Decide when search appears stuck and whether to enter a simplify phase
2918
+ - Expand the population by sampling from the current top performers
2919
+ - Sort genomes by fitness without allocating fresh arrays every generation
2920
+ - Track species diversity so collapse is visible instead of silent
2921
+ - Recover from pathological convergence by perturbing outputs and weights
2922
+ - Compact disabled connections once pruning has made them dead weight
2923
+
2924
+ The helpers here are intentionally allocation-light because they sit on the
2925
+ hot path of long runs. They lean on `EngineState` scratch buffers and accept
2926
+ slightly loose runtime surfaces so the public loop can stay orchestration-
2927
+ first while these internals adapt to the real Neat and Network instances.
2928
+
2929
+ ### antiCollapseRecovery
2961
2930
 
2962
2931
  ```ts
2963
- maybeStartSimplify(
2964
- plateauCounter: number,
2965
- plateauGenerations: number,
2966
- simplifyDuration: number,
2967
- ): number
2932
+ antiCollapseRecovery(
2933
+ state: EngineState,
2934
+ neat: PopulationDynamicsNeatLike,
2935
+ completedGenerations: number,
2936
+ safeWrite: (msg: string) => void,
2937
+ sampleSegmentIntoScratchFn: (state: EngineState, array: PopulationDynamicsGenome[], startIdx: number, count: number) => number,
2938
+ ): void
2968
2939
  ```
2969
2940
 
2970
- Decide whether to start a simplify phase based on plateau duration.
2941
+ Reinitialize output biases and weights for anti-collapse recovery.
2971
2942
 
2972
2943
  Behaviour:
2973
- - Returns requested simplify duration if plateau threshold is reached.
2974
- - Skips simplify in browser environments (presence of `window` global).
2944
+ - Selects a fraction (up to 30%) of non-elite genomes.
2945
+ - Samples from non-elite segment using pooled sample buffer.
2946
+ - Reinitializes each sampled genome's outputs via `reinitializeGenomeOutputsAndWeights`.
2947
+ - Emits diagnostic summary.
2975
2948
 
2976
2949
  Parameters:
2977
- - `plateauCounter` - - Observed consecutive plateau generations.
2978
- - `plateauGenerations` - - Threshold to trigger simplify.
2979
- - `simplifyDuration` - - Requested simplify phase length.
2980
-
2981
- Returns: Number of generations to run simplify (0 means "do not start").
2950
+ - `state` - - Shared engine state.
2951
+ - `neat` - - NEAT driver with `population` and `options.elitism`.
2952
+ - `completedGenerations` - - Current generation for logging.
2953
+ - `safeWrite` - - Logging callback.
2954
+ - `sampleSegmentIntoScratchFn` - - Sampling helper function.
2982
2955
 
2983
2956
  Example:
2984
2957
 
2985
- const duration = maybeStartSimplify(plateauCount, 10, 5);
2986
- if (duration > 0) {
2987
- // Begin simplify for `duration` generations
2988
- }
2958
+ antiCollapseRecovery(state, neat, genIndex, console.log, sampleSegmentIntoScratch);
2989
2959
 
2990
- ### runSimplifyCycle
2960
+ ### applyMutationsToClone
2991
2961
 
2992
2962
  ```ts
2993
- runSimplifyCycle(
2963
+ applyMutationsToClone(
2994
2964
  state: EngineState,
2965
+ clone: PopulationDynamicsGenome,
2995
2966
  neat: PopulationDynamicsNeatLike,
2996
- simplifyRemaining: number,
2997
- simplifyStrategy: string,
2998
- simplifyPruneFraction: number,
2999
- ): number
2967
+ mutateCount: number,
2968
+ ): void
3000
2969
  ```
3001
2970
 
3002
- Run a single simplify/pruning generation if conditions permit.
3003
-
3004
- Conceptually, simplify mode is the engine saying: "stop growing for a moment
3005
- and remove weak structure so the current population has to justify what it
3006
- keeps." That is useful after a long plateau, but only in non-browser hosts
3007
- where the extra pruning work is acceptable.
2971
+ Apply up to `mutateCount` distinct mutation operations to `clone`.
3008
2972
 
3009
- Steps:
3010
- 1. Normalize inputs and perform fast exits for zero remaining or invalid population.
3011
- 2. Environment gate: skip pruning in browser-like hosts.
3012
- 3. Record profiling start time when enabled.
3013
- 4. Execute pruning across the population (best-effort per-genome).
3014
- 5. Record profiling delta and return remaining generations decremented.
2973
+ Behaviour:
2974
+ 1. Uses cached mutation operation array from `getMutationOps`.
2975
+ 2. Selects up to `mutateCount` unique operations via partial Fisher–Yates shuffle.
2976
+ 3. For small `mutateCount` values, uses unrolled fast path.
3015
2977
 
3016
2978
  Parameters:
3017
- - `state` - - Shared engine state for RNG and profiling.
3018
- - `neat` - - NEAT instance with `population` array.
3019
- - `simplifyRemaining` - - Remaining simplify generations.
3020
- - `simplifyStrategy` - - Strategy identifier for pruning.
3021
- - `simplifyPruneFraction` - - Fraction in [0,1] controlling pruning aggressiveness.
3022
-
3023
- Returns: Remaining simplify generations after executing one cycle (0 means done).
2979
+ - `state` - - Shared engine state for RNG and scratch buffers.
2980
+ - `clone` - - Genome-like object with `mutate(op)` method.
2981
+ - `neat` - - NEAT driver for resolving mutation ops.
2982
+ - `mutateCount` - - Desired number of distinct mutation ops.
3024
2983
 
3025
2984
  Example:
3026
2985
 
3027
- const remaining = runSimplifyCycle(state, neat, 5, 'pruneWeak', 0.2);
2986
+ applyMutationsToClone(state, someClone, neat, 2);
3028
2987
 
3029
- ### handleSimplifyState
2988
+ ### compactGenomeConnections
3030
2989
 
3031
2990
  ```ts
3032
- handleSimplifyState(
3033
- state: EngineState,
3034
- neat: PopulationDynamicsNeatLike,
3035
- plateauCounter: number,
3036
- plateauGenerations: number,
3037
- simplifyDuration: number,
3038
- simplifyMode: boolean,
3039
- simplifyRemaining: number,
3040
- simplifyStrategy: string,
3041
- simplifyPruneFraction: number,
3042
- ): { simplifyMode: boolean; simplifyRemaining: number; plateauCounter: number; }
2991
+ compactGenomeConnections(
2992
+ genome: PopulationDynamicsGenome,
2993
+ ): number
3043
2994
  ```
3044
2995
 
3045
- Handle simplify entry and per-generation advance.
2996
+ Compact a single genome's connection list by removing disabled connections.
3046
2997
 
3047
2998
  Behaviour:
3048
- - Decides when to enter a simplification phase and runs one simplify cycle
3049
- per generation.
3050
- - Resets the plateau counter when simplify starts so the engine does not
3051
- immediately re-enter simplify after leaving it.
3052
- - Delegates the "should we start?" question to `maybeStartSimplify` and the
3053
- actual pruning work to `runSimplifyCycle`.
2999
+ - Performs in-place stable compaction of `genome.connections`.
3000
+ - Preserves relative order of enabled connections.
3001
+ - Two-pointer write/read technique.
3054
3002
 
3055
3003
  Parameters:
3056
- - `state` - - Shared engine state.
3057
- - `neat` - - NEAT driver instance.
3058
- - `plateauCounter` - - Current plateau counter.
3059
- - `plateauGenerations` - - Window size for plateau decision.
3060
- - `simplifyDuration` - - Requested simplify duration.
3061
- - `simplifyMode` - - Current simplify active flag.
3062
- - `simplifyRemaining` - - Remaining simplify generations.
3063
- - `simplifyStrategy` - - Strategy identifier.
3064
- - `simplifyPruneFraction` - - Pruning fraction.
3004
+ - `genome` - - Mutable genome with `connections` array.
3065
3005
 
3066
- Returns: Updated `{ simplifyMode, simplifyRemaining, plateauCounter }`.
3006
+ Returns: Number of removed (disabled) connections.
3067
3007
 
3068
3008
  Example:
3069
3009
 
3070
- const state = handleSimplifyState(engineState, neat, 3, 10, 5, false, 0, 'aggressive', 0.2);
3010
+ const removed = compactGenomeConnections(genome);
3071
3011
 
3072
- ### expandPopulation
3012
+ ### compactPopulation
3073
3013
 
3074
3014
  ```ts
3075
- expandPopulation(
3015
+ compactPopulation(
3076
3016
  state: EngineState,
3077
3017
  neat: PopulationDynamicsNeatLike,
3078
- targetAdd: number,
3079
- safeWrite: (msg: string) => void,
3080
- completedGenerations: number,
3081
- ): void
3018
+ ): number
3082
3019
  ```
3083
3020
 
3084
- Expand the population by creating children from top-performing parents.
3085
-
3086
- This is the engine's controlled answer to stagnation before full collapse
3087
- recovery becomes necessary: widen the search, but bias that widening toward
3088
- the current best-performing slice of the population instead of sampling from
3089
- everyone equally.
3021
+ Compact entire population by removing disabled connections from each genome.
3090
3022
 
3091
- Steps:
3092
- 1. Prepare working sets (population reference, sorted parent indices, parent pool size).
3093
- 2. Sample parents uniformly from the top parent pool.
3094
- 3. Create children via `createChildFromParent` (per-child failures ignored).
3095
- 4. Update `neat.options.popsize` and emit status line.
3023
+ Behaviour:
3024
+ - Uses pooled sample buffer as scratch counts array.
3025
+ - Compacts each genome via `compactGenomeConnections`.
3026
+ - Returns total removed connections.
3096
3027
 
3097
3028
  Parameters:
3098
- - `state` - - Shared engine state for RNG.
3099
- - `neat` - - NEAT driver with `population` and `options`.
3100
- - `targetAdd` - - Desired number of new genomes.
3101
- - `safeWrite` - - Logging callback.
3102
- - `completedGenerations` - - Generation counter for telemetry.
3029
+ - `state` - - Shared engine state.
3030
+ - `neat` - - NEAT driver with `population`.
3031
+
3032
+ Returns: Total removed disabled connections.
3103
3033
 
3104
3034
  Example:
3105
3035
 
3106
- expandPopulation(state, neat, 10, msg => process.stdout.write(msg), currentGen);
3036
+ const totalRemoved = compactPopulation(state, neat);
3107
3037
 
3108
- ### prepareExpansion
3038
+ ### createChildFromParent
3109
3039
 
3110
3040
  ```ts
3111
- prepareExpansion(
3041
+ createChildFromParent(
3112
3042
  state: EngineState,
3113
3043
  neat: PopulationDynamicsNeatLike,
3114
- ): { populationRef: PopulationDynamicsGenome[]; sortedIdx: number[]; parentPoolSize: number; }
3044
+ parent: PopulationDynamicsGenome,
3045
+ ): PopulationDynamicsGenome | undefined
3115
3046
  ```
3116
3047
 
3117
- Prepare working sets for population expansion.
3048
+ Create a child genome from a parent via cloning and mutation.
3118
3049
 
3119
- The key idea is to sort once, derive a parent pool from the best quarter of
3120
- the population, and then let child creation sample uniformly from that pool.
3121
- That gives expansion a clear bias toward current evidence without hard-coding
3122
- elitist cloning only.
3050
+ Behaviour:
3051
+ 1. Clone the parent genome (with or without ID tracking).
3052
+ 2. Determine mutation count (1 or 2).
3053
+ 3. Apply mutations to the clone.
3054
+ 4. Register the clone with the NEAT driver.
3123
3055
 
3124
3056
  Parameters:
3125
3057
  - `state` - - Shared engine state.
3126
- - `neat` - - NEAT driver with `population`.
3127
-
3128
- Returns: Object with `populationRef`, `sortedIdx`, `parentPoolSize`.
3058
+ - `neat` - - NEAT driver instance.
3059
+ - `parent` - - Parent genome object.
3129
3060
 
3130
3061
  Example:
3131
3062
 
3132
- const { populationRef, sortedIdx, parentPoolSize } = prepareExpansion(state, neat);
3063
+ createChildFromParent(state, neat, someParentGenome);
3133
3064
 
3134
3065
  ### determineMutateCount
3135
3066
 
@@ -3146,81 +3077,63 @@ Parameters:
3146
3077
 
3147
3078
  Returns: 1 or 2 based on random sample.
3148
3079
 
3149
- ### applyMutationsToClone
3080
+ ### ensureOutputIdentity
3150
3081
 
3151
3082
  ```ts
3152
- applyMutationsToClone(
3153
- state: EngineState,
3154
- clone: PopulationDynamicsGenome,
3083
+ ensureOutputIdentity(
3155
3084
  neat: PopulationDynamicsNeatLike,
3156
- mutateCount: number,
3157
3085
  ): void
3158
3086
  ```
3159
3087
 
3160
- Apply up to `mutateCount` distinct mutation operations to `clone`.
3088
+ Ensure all output nodes use identity activation.
3161
3089
 
3162
3090
  Behaviour:
3163
- 1. Uses cached mutation operation array from `getMutationOps`.
3164
- 2. Selects up to `mutateCount` unique operations via partial Fisher–Yates shuffle.
3165
- 3. For small `mutateCount` values, uses unrolled fast path.
3091
+ - Iterates population genomes.
3092
+ - Sets `node.squash = methods.Activation.identity` for output nodes.
3093
+ - Best-effort: swallows errors.
3166
3094
 
3167
3095
  Parameters:
3168
- - `state` - - Shared engine state for RNG and scratch buffers.
3169
- - `clone` - - Genome-like object with `mutate(op)` method.
3170
- - `neat` - - NEAT driver for resolving mutation ops.
3171
- - `mutateCount` - - Desired number of distinct mutation ops.
3096
+ - `neat` - - NEAT driver with `population` array.
3172
3097
 
3173
3098
  Example:
3174
3099
 
3175
- applyMutationsToClone(state, someClone, neat, 2);
3100
+ ensureOutputIdentity(neat);
3176
3101
 
3177
- ### registerClone
3102
+ ### expandPopulation
3178
3103
 
3179
3104
  ```ts
3180
- registerClone(
3105
+ expandPopulation(
3106
+ state: EngineState,
3181
3107
  neat: PopulationDynamicsNeatLike,
3182
- clone: PopulationDynamicsGenome,
3183
- parentId: PopulationDynamicsParentId | undefined,
3108
+ targetAdd: number,
3109
+ safeWrite: (msg: string) => void,
3110
+ completedGenerations: number,
3184
3111
  ): void
3185
3112
  ```
3186
3113
 
3187
- Register a cloned genome with the NEAT driver's bookkeeping.
3188
-
3189
- Parameters:
3190
- - `neat` - - NEAT driver instance.
3191
- - `clone` - - Cloned genome object.
3192
- - `parentId` - - Optional parent ID for lineage tracking.
3193
-
3194
- Example:
3195
-
3196
- registerClone(neat, genomeClone, parentId);
3197
-
3198
- ### createChildFromParent
3199
-
3200
- ```ts
3201
- createChildFromParent(
3202
- state: EngineState,
3203
- neat: PopulationDynamicsNeatLike,
3204
- parent: PopulationDynamicsGenome,
3205
- ): PopulationDynamicsGenome | undefined
3206
- ```
3114
+ Expand the population by creating children from top-performing parents.
3207
3115
 
3208
- Create a child genome from a parent via cloning and mutation.
3116
+ This is the engine's controlled answer to stagnation before full collapse
3117
+ recovery becomes necessary: widen the search, but bias that widening toward
3118
+ the current best-performing slice of the population instead of sampling from
3119
+ everyone equally.
3209
3120
 
3210
- Behaviour:
3211
- 1. Clone the parent genome (with or without ID tracking).
3212
- 2. Determine mutation count (1 or 2).
3213
- 3. Apply mutations to the clone.
3214
- 4. Register the clone with the NEAT driver.
3121
+ Steps:
3122
+ 1. Prepare working sets (population reference, sorted parent indices, parent pool size).
3123
+ 2. Sample parents uniformly from the top parent pool.
3124
+ 3. Create children via `createChildFromParent` (per-child failures ignored).
3125
+ 4. Update `neat.options.popsize` and emit status line.
3215
3126
 
3216
3127
  Parameters:
3217
- - `state` - - Shared engine state.
3218
- - `neat` - - NEAT driver instance.
3219
- - `parent` - - Parent genome object.
3128
+ - `state` - - Shared engine state for RNG.
3129
+ - `neat` - - NEAT driver with `population` and `options`.
3130
+ - `targetAdd` - - Desired number of new genomes.
3131
+ - `safeWrite` - - Logging callback.
3132
+ - `completedGenerations` - - Generation counter for telemetry.
3220
3133
 
3221
3134
  Example:
3222
3135
 
3223
- createChildFromParent(state, neat, someParentGenome);
3136
+ expandPopulation(state, neat, 10, msg => process.stdout.write(msg), currentGen);
3224
3137
 
3225
3138
  ### getSortedIndicesByScore
3226
3139
 
@@ -3249,27 +3162,48 @@ Example:
3249
3162
 
3250
3163
  const indices = getSortedIndicesByScore(state, population);
3251
3164
 
3252
- ### ensureOutputIdentity
3165
+ ### handleSimplifyState
3253
3166
 
3254
3167
  ```ts
3255
- ensureOutputIdentity(
3168
+ handleSimplifyState(
3169
+ state: EngineState,
3256
3170
  neat: PopulationDynamicsNeatLike,
3257
- ): void
3171
+ plateauCounter: number,
3172
+ plateauGenerations: number,
3173
+ simplifyDuration: number,
3174
+ simplifyMode: boolean,
3175
+ simplifyRemaining: number,
3176
+ simplifyStrategy: string,
3177
+ simplifyPruneFraction: number,
3178
+ ): { simplifyMode: boolean; simplifyRemaining: number; plateauCounter: number; }
3258
3179
  ```
3259
3180
 
3260
- Ensure all output nodes use identity activation.
3181
+ Handle simplify entry and per-generation advance.
3261
3182
 
3262
3183
  Behaviour:
3263
- - Iterates population genomes.
3264
- - Sets `node.squash = methods.Activation.identity` for output nodes.
3265
- - Best-effort: swallows errors.
3184
+ - Decides when to enter a simplification phase and runs one simplify cycle
3185
+ per generation.
3186
+ - Resets the plateau counter when simplify starts so the engine does not
3187
+ immediately re-enter simplify after leaving it.
3188
+ - Delegates the "should we start?" question to `maybeStartSimplify` and the
3189
+ actual pruning work to `runSimplifyCycle`.
3266
3190
 
3267
3191
  Parameters:
3268
- - `neat` - - NEAT driver with `population` array.
3192
+ - `state` - - Shared engine state.
3193
+ - `neat` - - NEAT driver instance.
3194
+ - `plateauCounter` - - Current plateau counter.
3195
+ - `plateauGenerations` - - Window size for plateau decision.
3196
+ - `simplifyDuration` - - Requested simplify duration.
3197
+ - `simplifyMode` - - Current simplify active flag.
3198
+ - `simplifyRemaining` - - Remaining simplify generations.
3199
+ - `simplifyStrategy` - - Strategy identifier.
3200
+ - `simplifyPruneFraction` - - Pruning fraction.
3201
+
3202
+ Returns: Updated `{ simplifyMode, simplifyRemaining, plateauCounter }`.
3269
3203
 
3270
3204
  Example:
3271
3205
 
3272
- ensureOutputIdentity(neat);
3206
+ const state = handleSimplifyState(engineState, neat, 3, 10, 5, false, 0, 'aggressive', 0.2);
3273
3207
 
3274
3208
  ### handleSpeciesHistory
3275
3209
 
@@ -3289,58 +3223,155 @@ Behaviour:
3289
3223
  - Inspects recent window for collapse (consecutive single-species).
3290
3224
  - When collapsed, escalates mutation/novelty parameters.
3291
3225
 
3292
- Parameters:
3293
- - `state` - - Shared engine state.
3294
- - `neat` - - NEAT driver with `population`.
3295
- - `speciesHistory` - - Global species history array (mutated).
3226
+ Parameters:
3227
+ - `state` - - Shared engine state.
3228
+ - `neat` - - NEAT driver with `population`.
3229
+ - `speciesHistory` - - Global species history array (mutated).
3230
+
3231
+ Returns: `true` when collapse detected; `false` otherwise.
3232
+
3233
+ Example:
3234
+
3235
+ const collapsed = handleSpeciesHistory(state, neat, historyArray);
3236
+
3237
+ ### IndexBuffer
3238
+
3239
+ Typed or array-based index buffer for sorting
3240
+
3241
+ ### maybeExpandPopulation
3242
+
3243
+ ```ts
3244
+ maybeExpandPopulation(
3245
+ state: EngineState,
3246
+ neat: PopulationDynamicsNeatLike,
3247
+ dynamicPopEnabled: boolean,
3248
+ completedGenerations: number,
3249
+ dynamicPopMax: number,
3250
+ plateauGenerations: number,
3251
+ plateauCounter: number,
3252
+ dynamicPopExpandInterval: number,
3253
+ dynamicPopExpandFactor: number,
3254
+ dynamicPopPlateauSlack: number,
3255
+ safeWrite: (msg: string) => void,
3256
+ ): void
3257
+ ```
3258
+
3259
+ Attempt population expansion when conditions permit.
3260
+
3261
+ Behaviour:
3262
+ - Checks if dynamic expansion is enabled and interval/plateau conditions met.
3263
+ - Computes target addition count based on current size and factor.
3264
+ - Delegates to `expandPopulation` when there is room to grow.
3265
+
3266
+ Parameters:
3267
+ - `state` - - Shared engine state.
3268
+ - `neat` - - NEAT driver.
3269
+ - `dynamicPopEnabled` - - Flag to enable dynamic expansion.
3270
+ - `completedGenerations` - - Current generation index.
3271
+ - `dynamicPopMax` - - Maximum allowed population size.
3272
+ - `plateauGenerations` - - Plateau window size.
3273
+ - `plateauCounter` - - Current plateau counter.
3274
+ - `dynamicPopExpandInterval` - - Generations between expansion attempts.
3275
+ - `dynamicPopExpandFactor` - - Fraction of current size to add.
3276
+ - `dynamicPopPlateauSlack` - - Minimum plateau ratio to trigger.
3277
+ - `safeWrite` - - Logging callback.
3278
+
3279
+ Example:
3280
+
3281
+ maybeExpandPopulation(state, neat, true, 100, 500, 10, 8, 5, 0.1, 0.75, console.log);
3282
+
3283
+ ### maybeStartSimplify
3284
+
3285
+ ```ts
3286
+ maybeStartSimplify(
3287
+ plateauCounter: number,
3288
+ plateauGenerations: number,
3289
+ simplifyDuration: number,
3290
+ ): number
3291
+ ```
3292
+
3293
+ Decide whether to start a simplify phase based on plateau duration.
3294
+
3295
+ Behaviour:
3296
+ - Returns requested simplify duration if plateau threshold is reached.
3297
+ - Skips simplify in browser environments (presence of `window` global).
3298
+
3299
+ Parameters:
3300
+ - `plateauCounter` - - Observed consecutive plateau generations.
3301
+ - `plateauGenerations` - - Threshold to trigger simplify.
3302
+ - `simplifyDuration` - - Requested simplify phase length.
3303
+
3304
+ Returns: Number of generations to run simplify (0 means "do not start").
3305
+
3306
+ Example:
3307
+
3308
+ const duration = maybeStartSimplify(plateauCount, 10, 5);
3309
+ if (duration > 0) {
3310
+ // Begin simplify for `duration` generations
3311
+ }
3312
+
3313
+ ### PopulationDynamicsConnection
3314
+
3315
+ Connection surface used when population helpers inspect network edges.
3316
+
3317
+ ### PopulationDynamicsGenome
3318
+
3319
+ Narrow genome view used by this module.
3320
+
3321
+ The real runtime objects are `Network` instances with a few extra evolution-
3322
+ time fields such as `score`, `species`, and lineage markers. Capturing that
3323
+ shape locally keeps the rest of the helper signatures readable without
3324
+ claiming that the entire engine only ever works with plain `Network` values.
3325
+
3326
+ ### PopulationDynamicsNeatLike
3327
+
3328
+ Narrow NEAT driver view used by this module.
3329
+
3330
+ The population-dynamics helpers care about population access, a handful of
3331
+ options, and mutation operator discovery. Everything else remains owned by
3332
+ the concrete `Neat` implementation.
3333
+
3334
+ ### PopulationDynamicsNode
3335
+
3336
+ Node surface used when population helpers inspect network topology.
3337
+
3338
+ ### PopulationDynamicsNoveltyConfig
3296
3339
 
3297
- Returns: `true` when collapse detected; `false` otherwise.
3340
+ Minimal novelty configuration surface used during anti-collapse escalation.
3298
3341
 
3299
- Example:
3342
+ ### PopulationDynamicsOptions
3300
3343
 
3301
- const collapsed = handleSpeciesHistory(state, neat, historyArray);
3344
+ Minimal NEAT options surface used by population-dynamics helpers.
3302
3345
 
3303
- ### maybeExpandPopulation
3346
+ ### PopulationDynamicsParentId
3347
+
3348
+ Runtime parent identifier carried through clone lineage tracking.
3349
+
3350
+ ### prepareExpansion
3304
3351
 
3305
3352
  ```ts
3306
- maybeExpandPopulation(
3353
+ prepareExpansion(
3307
3354
  state: EngineState,
3308
3355
  neat: PopulationDynamicsNeatLike,
3309
- dynamicPopEnabled: boolean,
3310
- completedGenerations: number,
3311
- dynamicPopMax: number,
3312
- plateauGenerations: number,
3313
- plateauCounter: number,
3314
- dynamicPopExpandInterval: number,
3315
- dynamicPopExpandFactor: number,
3316
- dynamicPopPlateauSlack: number,
3317
- safeWrite: (msg: string) => void,
3318
- ): void
3356
+ ): { populationRef: PopulationDynamicsGenome[]; sortedIdx: number[]; parentPoolSize: number; }
3319
3357
  ```
3320
3358
 
3321
- Attempt population expansion when conditions permit.
3359
+ Prepare working sets for population expansion.
3322
3360
 
3323
- Behaviour:
3324
- - Checks if dynamic expansion is enabled and interval/plateau conditions met.
3325
- - Computes target addition count based on current size and factor.
3326
- - Delegates to `expandPopulation` when there is room to grow.
3361
+ The key idea is to sort once, derive a parent pool from the best quarter of
3362
+ the population, and then let child creation sample uniformly from that pool.
3363
+ That gives expansion a clear bias toward current evidence without hard-coding
3364
+ elitist cloning only.
3327
3365
 
3328
3366
  Parameters:
3329
3367
  - `state` - - Shared engine state.
3330
- - `neat` - - NEAT driver.
3331
- - `dynamicPopEnabled` - - Flag to enable dynamic expansion.
3332
- - `completedGenerations` - - Current generation index.
3333
- - `dynamicPopMax` - - Maximum allowed population size.
3334
- - `plateauGenerations` - - Plateau window size.
3335
- - `plateauCounter` - - Current plateau counter.
3336
- - `dynamicPopExpandInterval` - - Generations between expansion attempts.
3337
- - `dynamicPopExpandFactor` - - Fraction of current size to add.
3338
- - `dynamicPopPlateauSlack` - - Minimum plateau ratio to trigger.
3339
- - `safeWrite` - - Logging callback.
3368
+ - `neat` - - NEAT driver with `population`.
3369
+
3370
+ Returns: Object with `populationRef`, `sortedIdx`, `parentPoolSize`.
3340
3371
 
3341
3372
  Example:
3342
3373
 
3343
- maybeExpandPopulation(state, neat, true, 100, 500, 10, 8, 5, 0.1, 0.75, console.log);
3374
+ const { populationRef, sortedIdx, parentPoolSize } = prepareExpansion(state, neat);
3344
3375
 
3345
3376
  ### pruneSaturatedHiddenOutputs
3346
3377
 
@@ -3370,36 +3401,26 @@ Example:
3370
3401
 
3371
3402
  pruneSaturatedHiddenOutputs(state, genome, getNodeIndicesByTypeFn, collectHiddenToOutputConnsFn);
3372
3403
 
3373
- ### antiCollapseRecovery
3404
+ ### registerClone
3374
3405
 
3375
3406
  ```ts
3376
- antiCollapseRecovery(
3377
- state: EngineState,
3407
+ registerClone(
3378
3408
  neat: PopulationDynamicsNeatLike,
3379
- completedGenerations: number,
3380
- safeWrite: (msg: string) => void,
3381
- sampleSegmentIntoScratchFn: (state: EngineState, array: PopulationDynamicsGenome[], startIdx: number, count: number) => number,
3409
+ clone: PopulationDynamicsGenome,
3410
+ parentId: PopulationDynamicsParentId | undefined,
3382
3411
  ): void
3383
3412
  ```
3384
3413
 
3385
- Reinitialize output biases and weights for anti-collapse recovery.
3386
-
3387
- Behaviour:
3388
- - Selects a fraction (up to 30%) of non-elite genomes.
3389
- - Samples from non-elite segment using pooled sample buffer.
3390
- - Reinitializes each sampled genome's outputs via `reinitializeGenomeOutputsAndWeights`.
3391
- - Emits diagnostic summary.
3414
+ Register a cloned genome with the NEAT driver's bookkeeping.
3392
3415
 
3393
3416
  Parameters:
3394
- - `state` - - Shared engine state.
3395
- - `neat` - - NEAT driver with `population` and `options.elitism`.
3396
- - `completedGenerations` - - Current generation for logging.
3397
- - `safeWrite` - - Logging callback.
3398
- - `sampleSegmentIntoScratchFn` - - Sampling helper function.
3417
+ - `neat` - - NEAT driver instance.
3418
+ - `clone` - - Cloned genome object.
3419
+ - `parentId` - - Optional parent ID for lineage tracking.
3399
3420
 
3400
3421
  Example:
3401
3422
 
3402
- antiCollapseRecovery(state, neat, genIndex, console.log, sampleSegmentIntoScratch);
3423
+ registerClone(neat, genomeClone, parentId);
3403
3424
 
3404
3425
  ### reinitializeGenomeOutputsAndWeights
3405
3426
 
@@ -3427,129 +3448,84 @@ Example:
3427
3448
 
3428
3449
  const deltas = reinitializeGenomeOutputsAndWeights(state, genome);
3429
3450
 
3430
- ### compactGenomeConnections
3451
+ ### runSimplifyCycle
3431
3452
 
3432
3453
  ```ts
3433
- compactGenomeConnections(
3434
- genome: PopulationDynamicsGenome,
3454
+ runSimplifyCycle(
3455
+ state: EngineState,
3456
+ neat: PopulationDynamicsNeatLike,
3457
+ simplifyRemaining: number,
3458
+ simplifyStrategy: string,
3459
+ simplifyPruneFraction: number,
3435
3460
  ): number
3436
3461
  ```
3437
3462
 
3438
- Compact a single genome's connection list by removing disabled connections.
3463
+ Run a single simplify/pruning generation if conditions permit.
3439
3464
 
3440
- Behaviour:
3441
- - Performs in-place stable compaction of `genome.connections`.
3442
- - Preserves relative order of enabled connections.
3443
- - Two-pointer write/read technique.
3465
+ Conceptually, simplify mode is the engine saying: "stop growing for a moment
3466
+ and remove weak structure so the current population has to justify what it
3467
+ keeps." That is useful after a long plateau, but only in non-browser hosts
3468
+ where the extra pruning work is acceptable.
3469
+
3470
+ Steps:
3471
+ 1. Normalize inputs and perform fast exits for zero remaining or invalid population.
3472
+ 2. Environment gate: skip pruning in browser-like hosts.
3473
+ 3. Record profiling start time when enabled.
3474
+ 4. Execute pruning across the population (best-effort per-genome).
3475
+ 5. Record profiling delta and return remaining generations decremented.
3444
3476
 
3445
3477
  Parameters:
3446
- - `genome` - - Mutable genome with `connections` array.
3478
+ - `state` - - Shared engine state for RNG and profiling.
3479
+ - `neat` - - NEAT instance with `population` array.
3480
+ - `simplifyRemaining` - - Remaining simplify generations.
3481
+ - `simplifyStrategy` - - Strategy identifier for pruning.
3482
+ - `simplifyPruneFraction` - - Fraction in [0,1] controlling pruning aggressiveness.
3447
3483
 
3448
- Returns: Number of removed (disabled) connections.
3484
+ Returns: Remaining simplify generations after executing one cycle (0 means done).
3449
3485
 
3450
3486
  Example:
3451
3487
 
3452
- const removed = compactGenomeConnections(genome);
3488
+ const remaining = runSimplifyCycle(state, neat, 5, 'pruneWeak', 0.2);
3453
3489
 
3454
- ### compactPopulation
3490
+ ### updatePlateauState
3455
3491
 
3456
3492
  ```ts
3457
- compactPopulation(
3458
- state: EngineState,
3459
- neat: PopulationDynamicsNeatLike,
3460
- ): number
3493
+ updatePlateauState(
3494
+ fitness: number,
3495
+ lastBestFitnessForPlateau: number,
3496
+ plateauCounter: number,
3497
+ plateauImprovementThreshold: number,
3498
+ ): { plateauCounter: number; lastBestFitnessForPlateau: number; }
3461
3499
  ```
3462
3500
 
3463
- Compact entire population by removing disabled connections from each genome.
3501
+ Update plateau state based on current fitness vs baseline.
3464
3502
 
3465
3503
  Behaviour:
3466
- - Uses pooled sample buffer as scratch counts array.
3467
- - Compacts each genome via `compactGenomeConnections`.
3468
- - Returns total removed connections.
3504
+ - Compares `fitness` against `lastBestFitnessForPlateau + threshold`.
3505
+ - If improved, resets plateau counter to 0 and updates baseline.
3506
+ - Otherwise, increments plateau counter (capped at a safe maximum).
3469
3507
 
3470
3508
  Parameters:
3471
- - `state` - - Shared engine state.
3472
- - `neat` - - NEAT driver with `population`.
3509
+ - `fitness` - - Current best fitness (must be finite).
3510
+ - `lastBestFitnessForPlateau` - - Previous baseline fitness.
3511
+ - `plateauCounter` - - Current consecutive plateau generations.
3512
+ - `plateauImprovementThreshold` - - Minimum improvement to reset plateau.
3473
3513
 
3474
- Returns: Total removed disabled connections.
3514
+ Returns: Updated `{ plateauCounter, lastBestFitnessForPlateau }`.
3475
3515
 
3476
3516
  Example:
3477
3517
 
3478
- const totalRemoved = compactPopulation(state, neat);
3479
-
3480
- ### IndexBuffer
3481
-
3482
- Typed or array-based index buffer for sorting
3483
-
3484
- ### PopulationDynamicsParentId
3485
-
3486
- Runtime parent identifier carried through clone lineage tracking.
3487
-
3488
- ### PopulationDynamicsGenome
3489
-
3490
- Narrow genome view used by this module.
3491
-
3492
- The real runtime objects are `Network` instances with a few extra evolution-
3493
- time fields such as `score`, `species`, and lineage markers. Capturing that
3494
- shape locally keeps the rest of the helper signatures readable without
3495
- claiming that the entire engine only ever works with plain `Network` values.
3496
-
3497
- ### PopulationDynamicsNode
3498
-
3499
- Node surface used when population helpers inspect network topology.
3500
-
3501
- ### PopulationDynamicsConnection
3502
-
3503
- Connection surface used when population helpers inspect network edges.
3504
-
3505
- ### PopulationDynamicsNoveltyConfig
3506
-
3507
- Minimal novelty configuration surface used during anti-collapse escalation.
3508
-
3509
- ### PopulationDynamicsOptions
3510
-
3511
- Minimal NEAT options surface used by population-dynamics helpers.
3512
-
3513
- ### PopulationDynamicsNeatLike
3514
-
3515
- Narrow NEAT driver view used by this module.
3516
-
3517
- The population-dynamics helpers care about population access, a handful of
3518
- options, and mutation operator discovery. Everything else remains owned by
3519
- the concrete `Neat` implementation.
3518
+ const state = updatePlateauState(1.23, 1.1, 3, 0.05);
3519
+ // state => { plateauCounter: 0, lastBestFitnessForPlateau: 1.23 }
3520
3520
 
3521
3521
  ## evolutionEngine/engineState.constants.ts
3522
3522
 
3523
3523
  Constant values shared by the ASCII maze engine-state facade and its helper utilities.
3524
3524
 
3525
- ### DEFAULT_LOGITS_RING_CAPACITY
3526
-
3527
- Default logits ring length used when allocating pooled softmax buffers.
3528
-
3529
3525
  ### ACTION_OUTPUT_DIMENSION
3530
3526
 
3531
3527
  Number of action outputs (N, E, S, W) represented in each logits row.
3532
3528
 
3533
- ### DEFAULT_VISITED_HASH_LOAD_FACTOR
3534
-
3535
- Default load factor target for the visited coordinate hash table.
3536
-
3537
- ### MIN_VISITED_HASH_LOAD_FACTOR
3538
-
3539
- Minimum safe load factor applied when normalising visited-hash configuration.
3540
-
3541
- ### MAX_VISITED_HASH_LOAD_FACTOR
3542
-
3543
- Maximum safe load factor applied when normalising visited-hash configuration.
3544
-
3545
- ### DEFAULT_RNG_CACHE_BATCH_SIZE
3546
-
3547
- Default RNG cache batch size mirroring the façade constant.
3548
-
3549
- ### DEFAULT_SPECIES_SCRATCH_CAPACITY
3550
-
3551
- Default capacity reserved for species identifier scratch arrays.
3552
-
3553
3529
  ### DEFAULT_CONNECTION_FLAG_CAPACITY
3554
3530
 
3555
3531
  Default capacity reserved for connection flag buffers.
@@ -3558,58 +3534,59 @@ Default capacity reserved for connection flag buffers.
3558
3534
 
3559
3535
  Default capacity reused by history and sampling scratch arrays.
3560
3536
 
3561
- ### DEFAULT_SORTED_INDEX_CAPACITY
3537
+ ### DEFAULT_LOGITS_RING_CAPACITY
3562
3538
 
3563
- Default capacity reserved for sorted index scratch arrays.
3539
+ Default logits ring length used when allocating pooled softmax buffers.
3540
+
3541
+ ### DEFAULT_NODE_INDEX_BUFFER_CAPACITY
3542
+
3543
+ Default capacity for the node index buffer used during inspection.
3564
3544
 
3565
3545
  ### DEFAULT_QUICKSORT_STACK_CAPACITY
3566
3546
 
3567
3547
  Default stack depth reserved for quicksort range storage.
3568
3548
 
3569
- ### DEFAULT_SAMPLE_POOL_SIZE
3549
+ ### DEFAULT_RNG_CACHE_BATCH_SIZE
3570
3550
 
3571
- Default pool size for telemetry sampling helpers.
3551
+ Default RNG cache batch size mirroring the façade constant.
3572
3552
 
3573
- ### DEFAULT_STRING_BUFFER_CAPACITY
3553
+ ### DEFAULT_SAMPLE_POOL_SIZE
3574
3554
 
3575
- Default capacity for telemetry string assembly buffers.
3555
+ Default pool size for telemetry sampling helpers.
3576
3556
 
3577
3557
  ### DEFAULT_SMALL_EXPLORE_TABLE_CAPACITY
3578
3558
 
3579
3559
  Default capacity for the small exploration table scratch.
3580
3560
 
3581
- ### DEFAULT_NODE_INDEX_BUFFER_CAPACITY
3561
+ ### DEFAULT_SORTED_INDEX_CAPACITY
3582
3562
 
3583
- Default capacity for the node index buffer used during inspection.
3563
+ Default capacity reserved for sorted index scratch arrays.
3584
3564
 
3585
- ### RNG_GOLDEN_RATIO_SEED
3565
+ ### DEFAULT_SPECIES_SCRATCH_CAPACITY
3586
3566
 
3587
- Knuth-derived 32-bit constant used when seeding the RNG state.
3567
+ Default capacity reserved for species identifier scratch arrays.
3588
3568
 
3589
- ## evolutionEngine/evolutionEngine.services.ts
3569
+ ### DEFAULT_STRING_BUFFER_CAPACITY
3590
3570
 
3591
- ### getEvolutionEngineSharedState
3571
+ Default capacity for telemetry string assembly buffers.
3592
3572
 
3593
- ```ts
3594
- getEvolutionEngineSharedState(): EngineState
3595
- ```
3573
+ ### DEFAULT_VISITED_HASH_LOAD_FACTOR
3596
3574
 
3597
- Return the shared engine singleton used by extracted engine modules.
3575
+ Default load factor target for the visited coordinate hash table.
3598
3576
 
3599
- The public facade now depends on the same owner as the rest of the engine
3600
- boundary instead of creating a private duplicate singleton.
3577
+ ### MAX_VISITED_HASH_LOAD_FACTOR
3601
3578
 
3602
- Returns: Shared engine state singleton.
3579
+ Maximum safe load factor applied when normalising visited-hash configuration.
3580
+
3581
+ ### MIN_VISITED_HASH_LOAD_FACTOR
3603
3582
 
3604
- ### getEvolutionEngineFacadeRuntimeState
3583
+ Minimum safe load factor applied when normalising visited-hash configuration.
3605
3584
 
3606
- ```ts
3607
- getEvolutionEngineFacadeRuntimeState(): LogitsRingState
3608
- ```
3585
+ ### RNG_GOLDEN_RATIO_SEED
3609
3586
 
3610
- Read the mutable facade-owned logits-ring runtime state.
3587
+ Knuth-derived 32-bit constant used when seeding the RNG state.
3611
3588
 
3612
- Returns: Current ring-capacity, shared-mode, and write-cursor state.
3589
+ ## evolutionEngine/evolutionEngine.services.ts
3613
3590
 
3614
3591
  ### applyEvolutionEngineRingState
3615
3592
 
@@ -3624,13 +3601,32 @@ Apply the latest logits-ring runtime values returned by the evolution loop.
3624
3601
  Parameters:
3625
3602
  - `updatedRingState` - - New ring-capacity, shared-mode, and write-cursor values.
3626
3603
 
3627
- ### resetEvolutionEngineRingState
3604
+ ### configureEvolutionEngineToggles
3628
3605
 
3629
3606
  ```ts
3630
- resetEvolutionEngineRingState(): void
3607
+ configureEvolutionEngineToggles(
3608
+ reducedTelemetry: boolean,
3609
+ telemetryMinimal: boolean,
3610
+ disableBaldwinPhase: boolean,
3611
+ ): void
3631
3612
  ```
3632
3613
 
3633
- Reset the facade-owned logits-ring runtime state to its baseline defaults.
3614
+ Apply telemetry and Baldwin-phase toggles derived from one normalized run request.
3615
+
3616
+ Parameters:
3617
+ - `reducedTelemetry` - - When true, keep only the essential telemetry metrics.
3618
+ - `telemetryMinimal` - - When true, disable verbose telemetry capture.
3619
+ - `disableBaldwinPhase` - - When true, skip the Baldwin refinement stage.
3620
+
3621
+ ### getEvolutionEngineFacadeRuntimeState
3622
+
3623
+ ```ts
3624
+ getEvolutionEngineFacadeRuntimeState(): LogitsRingState
3625
+ ```
3626
+
3627
+ Read the mutable facade-owned logits-ring runtime state.
3628
+
3629
+ Returns: Current ring-capacity, shared-mode, and write-cursor state.
3634
3630
 
3635
3631
  ### getEvolutionEngineMaxLogitsRingCapacity
3636
3632
 
@@ -3642,22 +3638,26 @@ Read the hard maximum ring capacity used by the public facade.
3642
3638
 
3643
3639
  Returns: Maximum ring capacity allowed for logits telemetry.
3644
3640
 
3645
- ### configureEvolutionEngineToggles
3641
+ ### getEvolutionEngineSharedState
3646
3642
 
3647
3643
  ```ts
3648
- configureEvolutionEngineToggles(
3649
- reducedTelemetry: boolean,
3650
- telemetryMinimal: boolean,
3651
- disableBaldwinPhase: boolean,
3652
- ): void
3644
+ getEvolutionEngineSharedState(): EngineState
3653
3645
  ```
3654
3646
 
3655
- Apply telemetry and Baldwin-phase toggles derived from one normalized run request.
3647
+ Return the shared engine singleton used by extracted engine modules.
3656
3648
 
3657
- Parameters:
3658
- - `reducedTelemetry` - - When true, keep only the essential telemetry metrics.
3659
- - `telemetryMinimal` - - When true, disable verbose telemetry capture.
3660
- - `disableBaldwinPhase` - - When true, skip the Baldwin refinement stage.
3649
+ The public facade now depends on the same owner as the rest of the engine
3650
+ boundary instead of creating a private duplicate singleton.
3651
+
3652
+ Returns: Shared engine state singleton.
3653
+
3654
+ ### resetEvolutionEngineRingState
3655
+
3656
+ ```ts
3657
+ resetEvolutionEngineRingState(): void
3658
+ ```
3659
+
3660
+ Reset the facade-owned logits-ring runtime state to its baseline defaults.
3661
3661
 
3662
3662
  ## evolutionEngine/evolutionEngine.constants.ts
3663
3663
 
@@ -3667,21 +3667,21 @@ The public EvolutionEngine class should read as orchestration-first code.
3667
3667
  These constants live in a dedicated module so warm-start tuning, loop
3668
3668
  thresholds, and shared fallback arrays do not crowd the facade itself.
3669
3669
 
3670
- ### EVOLUTION_ENGINE_EMPTY_VECTOR
3670
+ ### EVOLUTION_ENGINE_ACTION_DIMENSION
3671
3671
 
3672
- Shared empty vector reused when engine helpers need a stable array fallback.
3672
+ Number of action outputs emitted by the ASCII maze policy network.
3673
3673
 
3674
3674
  Example:
3675
3675
 
3676
- const outgoing = node.connections?.out ?? EVOLUTION_ENGINE_EMPTY_VECTOR;
3676
+ console.log(EVOLUTION_ENGINE_ACTION_DIMENSION); // 4
3677
3677
 
3678
- ### EVOLUTION_ENGINE_ACTION_DIMENSION
3678
+ ### EVOLUTION_ENGINE_EMPTY_VECTOR
3679
3679
 
3680
- Number of action outputs emitted by the ASCII maze policy network.
3680
+ Shared empty vector reused when engine helpers need a stable array fallback.
3681
3681
 
3682
3682
  Example:
3683
3683
 
3684
- console.log(EVOLUTION_ENGINE_ACTION_DIMENSION); // 4
3684
+ const outgoing = node.connections?.out ?? EVOLUTION_ENGINE_EMPTY_VECTOR;
3685
3685
 
3686
3686
  ### EVOLUTION_ENGINE_INITIAL_LOGITS_RING_CAPACITY
3687
3687
 
@@ -3690,17 +3690,16 @@ Initial ring-buffer capacity used for logits telemetry.
3690
3690
  The ring may grow at runtime, but the facade starts from this size so the
3691
3691
  first generations stay allocation-light.
3692
3692
 
3693
- ### EVOLUTION_ENGINE_MAX_LOGITS_RING_CAPACITY
3693
+ ### EVOLUTION_ENGINE_LOOP_CONSTANTS
3694
3694
 
3695
- Hard safety limit for the logits telemetry ring-buffer capacity.
3695
+ Main-loop tuning values passed into the extracted evolution-loop helpers.
3696
3696
 
3697
- ### EVOLUTION_ENGINE_WARM_START_CONSTANTS
3697
+ This table keeps the public facade declarative while preserving the same
3698
+ runtime thresholds and training behaviour.
3698
3699
 
3699
- Warm-start curriculum samples used to bias early supervised guidance.
3700
+ ### EVOLUTION_ENGINE_MAX_LOGITS_RING_CAPACITY
3700
3701
 
3701
- These values shape the synthetic targets used before the main NEAT loop
3702
- takes over, so they are grouped here instead of being scattered across the
3703
- facade method body.
3702
+ Hard safety limit for the logits telemetry ring-buffer capacity.
3704
3703
 
3705
3704
  ### EVOLUTION_ENGINE_PRETRAIN_CONSTANTS
3706
3705
 
@@ -3710,36 +3709,42 @@ Example:
3710
3709
 
3711
3710
  const iterations = EVOLUTION_ENGINE_PRETRAIN_CONSTANTS.PRETRAIN_MAX_ITER;
3712
3711
 
3713
- ### EVOLUTION_ENGINE_LOOP_CONSTANTS
3712
+ ### EVOLUTION_ENGINE_WARM_START_CONSTANTS
3714
3713
 
3715
- Main-loop tuning values passed into the extracted evolution-loop helpers.
3714
+ Warm-start curriculum samples used to bias early supervised guidance.
3716
3715
 
3717
- This table keeps the public facade declarative while preserving the same
3718
- runtime thresholds and training behaviour.
3716
+ These values shape the synthetic targets used before the main NEAT loop
3717
+ takes over, so they are grouped here instead of being scattered across the
3718
+ facade method body.
3719
3719
 
3720
3720
  ## evolutionEngine/engineState.utils.ts
3721
3721
 
3722
3722
  Pure utility helpers shared by the ASCII maze engine-state facade.
3723
3723
 
3724
- ### createLogitsRing
3724
+ ### buildTelemetryHandles
3725
3725
 
3726
3726
  ```ts
3727
- createLogitsRing(): Float32Array<ArrayBufferLike>[]
3727
+ buildTelemetryHandles(
3728
+ scratch: EngineScratchState,
3729
+ ): TelemetryScratchHandles
3728
3730
  ```
3729
3731
 
3730
- Build a logits ring sized to the requested default capacity.
3732
+ Build typed handles referencing the ensured telemetry scratch buffers.
3731
3733
 
3732
- Returns: Array of Float32Array rows sized to the action dimension.
3734
+ Parameters:
3735
+ - `scratch` - Scratch state containing the prepared buffers.
3733
3736
 
3734
- ### resolveProfilingEnabled
3737
+ Returns: Structured handles consumed by telemetry helpers.
3738
+
3739
+ ### createLogitsRing
3735
3740
 
3736
3741
  ```ts
3737
- resolveProfilingEnabled(): boolean
3742
+ createLogitsRing(): Float32Array<ArrayBufferLike>[]
3738
3743
  ```
3739
3744
 
3740
- Compute whether detailed profiling is enabled via the environment flag.
3745
+ Build a logits ring sized to the requested default capacity.
3741
3746
 
3742
- Returns: True when the profiling environment flag is set.
3747
+ Returns: Array of Float32Array rows sized to the action dimension.
3743
3748
 
3744
3749
  ### createProfilingAccumulators
3745
3750
 
@@ -3761,21 +3766,6 @@ Build the reusable snapshot metadata payload consumed by persistence helpers.
3761
3766
 
3762
3767
  Returns: Snapshot placeholder populated with neutral defaults.
3763
3768
 
3764
- ### normaliseTelemetryCapacityHints
3765
-
3766
- ```ts
3767
- normaliseTelemetryCapacityHints(
3768
- request: TelemetryScratchRequest,
3769
- ): TelemetryCapacityHints
3770
- ```
3771
-
3772
- Derive normalised capacity hints from the raw telemetry scratch request.
3773
-
3774
- Parameters:
3775
- - `request` - Raw capacity request supplied by callers.
3776
-
3777
- Returns: Sanitised capacity values used during buffer initialisation.
3778
-
3779
3769
  ### ensureTelemetryFloatPools
3780
3770
 
3781
3771
  ```ts
@@ -3810,21 +3800,6 @@ Parameters:
3810
3800
 
3811
3801
  Returns: Original buffer when large enough, otherwise a grown copy.
3812
3802
 
3813
- ### buildTelemetryHandles
3814
-
3815
- ```ts
3816
- buildTelemetryHandles(
3817
- scratch: EngineScratchState,
3818
- ): TelemetryScratchHandles
3819
- ```
3820
-
3821
- Build typed handles referencing the ensured telemetry scratch buffers.
3822
-
3823
- Parameters:
3824
- - `scratch` - Scratch state containing the prepared buffers.
3825
-
3826
- Returns: Structured handles consumed by telemetry helpers.
3827
-
3828
3803
  ### nextPowerOfTwo
3829
3804
 
3830
3805
  ```ts
@@ -3840,93 +3815,92 @@ Parameters:
3840
3815
 
3841
3816
  Returns: Smallest power-of-two greater than or equal to the candidate.
3842
3817
 
3843
- ### normaliseVisitedHashEntries
3818
+ ### normaliseRngBatchSize
3844
3819
 
3845
3820
  ```ts
3846
- normaliseVisitedHashEntries(
3847
- requestedEntries: number,
3821
+ normaliseRngBatchSize(
3822
+ requestedBatchSize: number,
3848
3823
  ): number
3849
3824
  ```
3850
3825
 
3851
- Clamp the requested target entry count to a non-negative integer.
3826
+ Clamp the RNG cache batch size to a positive integer.
3852
3827
 
3853
3828
  Parameters:
3854
- - `requestedEntries` - Raw target entry count supplied by callers.
3829
+ - `requestedBatchSize` - Raw batch size requested by callers.
3855
3830
 
3856
- Returns: Sanitised entry count used for capacity planning.
3831
+ Returns: Valid batch size.
3857
3832
 
3858
- ### normaliseVisitedHashLoad
3833
+ ### normaliseRngSeed
3859
3834
 
3860
3835
  ```ts
3861
- normaliseVisitedHashLoad(
3862
- requestedLoadFactor: number,
3836
+ normaliseRngSeed(
3837
+ rawSeed: number,
3863
3838
  ): number
3864
3839
  ```
3865
3840
 
3866
- Ensure the visited hash load factor falls within a sensible range.
3841
+ Normalise a raw numeric seed into an unsigned 32-bit value.
3867
3842
 
3868
3843
  Parameters:
3869
- - `requestedLoadFactor` - Proposed load factor from configuration or state.
3844
+ - `rawSeed` - Raw seed provided by the caller.
3870
3845
 
3871
- Returns: Clamped load factor with a fallback to the project default.
3846
+ Returns: Unsigned 32-bit seed suitable for the congruential generator.
3872
3847
 
3873
- ### normaliseRngBatchSize
3848
+ ### normaliseTelemetryCapacityHints
3874
3849
 
3875
3850
  ```ts
3876
- normaliseRngBatchSize(
3877
- requestedBatchSize: number,
3878
- ): number
3851
+ normaliseTelemetryCapacityHints(
3852
+ request: TelemetryScratchRequest,
3853
+ ): TelemetryCapacityHints
3879
3854
  ```
3880
3855
 
3881
- Clamp the RNG cache batch size to a positive integer.
3856
+ Derive normalised capacity hints from the raw telemetry scratch request.
3882
3857
 
3883
3858
  Parameters:
3884
- - `requestedBatchSize` - Raw batch size requested by callers.
3859
+ - `request` - Raw capacity request supplied by callers.
3885
3860
 
3886
- Returns: Valid batch size.
3861
+ Returns: Sanitised capacity values used during buffer initialisation.
3887
3862
 
3888
- ### normaliseRngSeed
3863
+ ### normaliseVisitedHashEntries
3889
3864
 
3890
3865
  ```ts
3891
- normaliseRngSeed(
3892
- rawSeed: number,
3866
+ normaliseVisitedHashEntries(
3867
+ requestedEntries: number,
3893
3868
  ): number
3894
3869
  ```
3895
3870
 
3896
- Normalise a raw numeric seed into an unsigned 32-bit value.
3871
+ Clamp the requested target entry count to a non-negative integer.
3897
3872
 
3898
3873
  Parameters:
3899
- - `rawSeed` - Raw seed provided by the caller.
3900
-
3901
- Returns: Unsigned 32-bit seed suitable for the congruential generator.
3874
+ - `requestedEntries` - Raw target entry count supplied by callers.
3902
3875
 
3903
- ## evolutionEngine/evolutionEngine.utils.ts
3876
+ Returns: Sanitised entry count used for capacity planning.
3904
3877
 
3905
- ### collectEvolutionEngineNodeIndicesByType
3878
+ ### normaliseVisitedHashLoad
3906
3879
 
3907
3880
  ```ts
3908
- collectEvolutionEngineNodeIndicesByType(
3909
- state: EngineState,
3910
- nodes: NetworkNode[] | undefined,
3911
- type: string,
3881
+ normaliseVisitedHashLoad(
3882
+ requestedLoadFactor: number,
3912
3883
  ): number
3913
3884
  ```
3914
3885
 
3915
- Collect node indices of one requested type into the shared engine scratch buffer.
3916
-
3917
- This helper keeps the facade free of buffer-growth details while preserving
3918
- the existing allocation-light behaviour used by the evolution loop.
3886
+ Ensure the visited hash load factor falls within a sensible range.
3919
3887
 
3920
3888
  Parameters:
3921
- - `state` - - Shared engine state that owns the reusable node-index buffer.
3922
- - `nodes` - - Candidate nodes to scan.
3923
- - `type` - - Node type to collect, such as `input`, `hidden`, or `output`.
3889
+ - `requestedLoadFactor` - Proposed load factor from configuration or state.
3924
3890
 
3925
- Returns: Number of matching indices written into the shared scratch buffer.
3891
+ Returns: Clamped load factor with a fallback to the project default.
3926
3892
 
3927
- Example:
3893
+ ### resolveProfilingEnabled
3928
3894
 
3929
- const outputCount = collectEvolutionEngineNodeIndicesByType(state, nodes, 'output');
3895
+ ```ts
3896
+ resolveProfilingEnabled(): boolean
3897
+ ```
3898
+
3899
+ Compute whether detailed profiling is enabled via the environment flag.
3900
+
3901
+ Returns: True when the profiling environment flag is set.
3902
+
3903
+ ## evolutionEngine/evolutionEngine.utils.ts
3930
3904
 
3931
3905
  ### collectEvolutionEngineHiddenToOutputConnections
3932
3906
 
@@ -3960,3 +3934,29 @@ const connections = collectEvolutionEngineHiddenToOutputConnections(
3960
3934
  nodes,
3961
3935
  outputCount,
3962
3936
  );
3937
+
3938
+ ### collectEvolutionEngineNodeIndicesByType
3939
+
3940
+ ```ts
3941
+ collectEvolutionEngineNodeIndicesByType(
3942
+ state: EngineState,
3943
+ nodes: NetworkNode[] | undefined,
3944
+ type: string,
3945
+ ): number
3946
+ ```
3947
+
3948
+ Collect node indices of one requested type into the shared engine scratch buffer.
3949
+
3950
+ This helper keeps the facade free of buffer-growth details while preserving
3951
+ the existing allocation-light behaviour used by the evolution loop.
3952
+
3953
+ Parameters:
3954
+ - `state` - - Shared engine state that owns the reusable node-index buffer.
3955
+ - `nodes` - - Candidate nodes to scan.
3956
+ - `type` - - Node type to collect, such as `input`, `hidden`, or `output`.
3957
+
3958
+ Returns: Number of matching indices written into the shared scratch buffer.
3959
+
3960
+ Example:
3961
+
3962
+ const outputCount = collectEvolutionEngineNodeIndicesByType(state, nodes, 'output');