@reicek/neataptic-ts 0.1.21 → 0.1.23

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 (361) hide show
  1. package/.github/agents/boundary-mapper.agent.md +31 -0
  2. package/.github/agents/docs-scout.agent.md +29 -0
  3. package/.github/agents/plan-scout.agent.md +31 -0
  4. package/.github/agents/solid-split.agent.md +143 -0
  5. package/.github/copilot-instructions.md +119 -0
  6. package/.github/skills/solid-split-playbook/SKILL.md +220 -0
  7. package/.github/skills/solid-split-playbook/assets/docs-checklist.md +34 -0
  8. package/.github/skills/solid-split-playbook/assets/split-plan-template.md +48 -0
  9. package/.github/skills/solid-split-playbook/assets/split-workflow-checklist.md +51 -0
  10. package/.github/skills/trace-analyzer-extension/SKILL.md +63 -0
  11. package/.github/skills/trace-analyzer-extension/assets/extension-checklist.md +24 -0
  12. package/.github/skills/trace-analyzer-extension/references/analyzer-extension-workflow.md +101 -0
  13. package/.github/skills/trace-audit-reporting/SKILL.md +96 -0
  14. package/.github/skills/trace-audit-reporting/assets/performance-report-template.md +123 -0
  15. package/.github/skills/trace-audit-reporting/references/trace-analysis-workflow.md +132 -0
  16. package/package.json +7 -3
  17. package/plans/ES2023 migration +13 -8
  18. package/plans/Evolution_Training_Interoperability_Contracts.md +1 -1
  19. package/plans/Flappy_Bird_Folder_Documentation_Pass.md +53 -0
  20. package/plans/Flappy_Evolution_Worker_Documentation_Pass.md +58 -0
  21. package/plans/Interactive_Examples_and_Learning_Path.md +10 -2
  22. package/plans/Memory_Optimization.md +3 -3
  23. package/plans/README.md +63 -0
  24. package/plans/Roadmap.md +15 -3
  25. package/plans/asciiMaze_SOLID_split.done.md +130 -0
  26. package/plans/flappy_bird_SOLID_split.done.md +67 -0
  27. package/scripts/analyze-trace.ts +590 -0
  28. package/scripts/assets/theme.css +221 -34
  29. package/scripts/copy-examples.mjs +9 -5
  30. package/scripts/export-onnx.mjs +3 -3
  31. package/scripts/generate-bench-tables.mjs +10 -10
  32. package/scripts/generate-bench-tables.ts +10 -10
  33. package/scripts/generate-docs.ts +1415 -449
  34. package/scripts/render-docs-html.ts +15 -8
  35. package/src/README.md +127 -222
  36. package/src/architecture/README.md +117 -184
  37. package/src/architecture/architect.ts +6 -0
  38. package/src/architecture/layer/README.md +38 -38
  39. package/src/architecture/network/README.md +49 -31
  40. package/src/architecture/network/activate/README.md +77 -77
  41. package/src/architecture/network/connect/README.md +15 -13
  42. package/src/architecture/network/deterministic/README.md +7 -7
  43. package/src/architecture/network/evolve/README.md +44 -44
  44. package/src/architecture/network/gating/README.md +20 -20
  45. package/src/architecture/network/genetic/README.md +51 -51
  46. package/src/architecture/network/mutate/README.md +97 -97
  47. package/src/architecture/network/network.types.ts +39 -0
  48. package/src/architecture/network/onnx/README.md +264 -264
  49. package/src/architecture/network/prune/README.md +39 -39
  50. package/src/architecture/network/remove/README.md +26 -26
  51. package/src/architecture/network/serialize/README.md +56 -56
  52. package/src/architecture/network/serialize/network.serialize.json.utils.ts +1 -0
  53. package/src/architecture/network/serialize/network.serialize.utils.ts +6 -1
  54. package/src/architecture/network/serialize/network.serialize.utils.types.ts +1 -1
  55. package/src/architecture/network/slab/README.md +61 -61
  56. package/src/architecture/network/standalone/README.md +24 -24
  57. package/src/architecture/network/stats/README.md +9 -9
  58. package/src/architecture/network/topology/README.md +46 -46
  59. package/src/architecture/network/training/README.md +21 -21
  60. package/src/architecture/network.ts +114 -10
  61. package/src/methods/README.md +9 -87
  62. package/src/multithreading/README.md +8 -77
  63. package/src/multithreading/workers/README.md +2 -2
  64. package/src/multithreading/workers/browser/README.md +0 -6
  65. package/src/multithreading/workers/node/README.md +0 -3
  66. package/src/neat/README.md +623 -568
  67. package/src/neat/neat.evolve.population.utils.ts +29 -5
  68. package/src/neat/neat.helpers.ts +16 -0
  69. package/src/neat/neat.topology-intent.utils.ts +160 -0
  70. package/src/utils/README.md +18 -18
  71. package/test/examples/asciiMaze/README.md +59 -59
  72. package/test/examples/asciiMaze/asciiMaze.e2e.test.ts +14 -9
  73. package/test/examples/asciiMaze/browser-entry/README.md +196 -0
  74. package/test/examples/asciiMaze/browser-entry/browser-entry.abort.services.ts +95 -0
  75. package/test/examples/asciiMaze/browser-entry/browser-entry.constants.ts +23 -0
  76. package/test/examples/asciiMaze/browser-entry/browser-entry.curriculum.services.ts +115 -0
  77. package/test/examples/asciiMaze/browser-entry/browser-entry.globals.services.ts +106 -0
  78. package/test/examples/asciiMaze/browser-entry/browser-entry.host.services.ts +157 -0
  79. package/test/examples/asciiMaze/browser-entry/browser-entry.services.ts +14 -0
  80. package/test/examples/asciiMaze/browser-entry/browser-entry.ts +129 -0
  81. package/test/examples/asciiMaze/browser-entry/browser-entry.types.ts +120 -0
  82. package/test/examples/asciiMaze/browser-entry/browser-entry.utils.ts +98 -0
  83. package/test/examples/asciiMaze/browser-entry.ts +10 -576
  84. package/test/examples/asciiMaze/dashboardManager/README.md +276 -0
  85. package/test/examples/asciiMaze/dashboardManager/archive/README.md +16 -0
  86. package/test/examples/asciiMaze/dashboardManager/archive/dashboardManager.archive.services.ts +267 -0
  87. package/test/examples/asciiMaze/dashboardManager/dashboardManager.constants.ts +35 -0
  88. package/test/examples/asciiMaze/dashboardManager/dashboardManager.services.ts +103 -0
  89. package/test/examples/asciiMaze/dashboardManager/dashboardManager.ts +181 -0
  90. package/test/examples/asciiMaze/dashboardManager/dashboardManager.types.ts +267 -0
  91. package/test/examples/asciiMaze/dashboardManager/dashboardManager.utils.ts +254 -0
  92. package/test/examples/asciiMaze/dashboardManager/live/README.md +14 -0
  93. package/test/examples/asciiMaze/dashboardManager/live/dashboardManager.live.services.ts +264 -0
  94. package/test/examples/asciiMaze/dashboardManager/telemetry/README.md +47 -0
  95. package/test/examples/asciiMaze/dashboardManager/telemetry/dashboardManager.telemetry.services.ts +513 -0
  96. package/test/examples/asciiMaze/dashboardManager.ts +13 -2335
  97. package/test/examples/asciiMaze/evolutionEngine/README.md +1058 -0
  98. package/test/examples/asciiMaze/evolutionEngine/curriculumPhase.ts +90 -0
  99. package/test/examples/asciiMaze/evolutionEngine/engineState.constants.ts +36 -0
  100. package/test/examples/asciiMaze/evolutionEngine/engineState.ts +58 -513
  101. package/test/examples/asciiMaze/evolutionEngine/engineState.types.ts +212 -0
  102. package/test/examples/asciiMaze/evolutionEngine/engineState.utils.ts +301 -0
  103. package/test/examples/asciiMaze/evolutionEngine/evolutionEngine.types.ts +445 -0
  104. package/test/examples/asciiMaze/evolutionEngine/evolutionLoop.ts +81 -50
  105. package/test/examples/asciiMaze/evolutionEngine/optionsAndSetup.ts +2 -4
  106. package/test/examples/asciiMaze/evolutionEngine/populationDynamics.ts +17 -33
  107. package/test/examples/asciiMaze/evolutionEngine/populationPruning.ts +1 -1
  108. package/test/examples/asciiMaze/evolutionEngine/rngAndTiming.ts +1 -2
  109. package/test/examples/asciiMaze/evolutionEngine/sampling.ts +1 -1
  110. package/test/examples/asciiMaze/evolutionEngine/scratchPools.ts +2 -5
  111. package/test/examples/asciiMaze/evolutionEngine/setupHelpers.ts +30 -37
  112. package/test/examples/asciiMaze/evolutionEngine/telemetryMetrics.ts +16 -58
  113. package/test/examples/asciiMaze/evolutionEngine/trainingWarmStart.ts +2 -2
  114. package/test/examples/asciiMaze/evolutionEngine.ts +55 -55
  115. package/test/examples/asciiMaze/fitness.ts +2 -2
  116. package/test/examples/asciiMaze/fitness.types.ts +65 -0
  117. package/test/examples/asciiMaze/interfaces.ts +64 -1352
  118. package/test/examples/asciiMaze/mazeMovement/README.md +356 -0
  119. package/test/examples/asciiMaze/mazeMovement/finalization/README.md +49 -0
  120. package/test/examples/asciiMaze/mazeMovement/finalization/mazeMovement.finalization.ts +138 -0
  121. package/test/examples/asciiMaze/mazeMovement/mazeMovement.constants.ts +101 -0
  122. package/test/examples/asciiMaze/mazeMovement/mazeMovement.services.ts +230 -0
  123. package/test/examples/asciiMaze/mazeMovement/mazeMovement.ts +299 -0
  124. package/test/examples/asciiMaze/mazeMovement/mazeMovement.types.ts +185 -0
  125. package/test/examples/asciiMaze/mazeMovement/mazeMovement.utils.ts +153 -0
  126. package/test/examples/asciiMaze/mazeMovement/policy/README.md +91 -0
  127. package/test/examples/asciiMaze/mazeMovement/policy/mazeMovement.policy.ts +467 -0
  128. package/test/examples/asciiMaze/mazeMovement/runtime/README.md +95 -0
  129. package/test/examples/asciiMaze/mazeMovement/runtime/mazeMovement.runtime.ts +354 -0
  130. package/test/examples/asciiMaze/mazeMovement/shaping/README.md +124 -0
  131. package/test/examples/asciiMaze/mazeMovement/shaping/mazeMovement.shaping.ts +459 -0
  132. package/test/examples/asciiMaze/mazeMovement.ts +12 -2978
  133. package/test/examples/flappy_bird/README.md +193 -88
  134. package/test/examples/flappy_bird/browser-entry/README.md +1441 -0
  135. package/test/examples/flappy_bird/browser-entry/browser-entry.host.utils.ts +4 -324
  136. package/test/examples/flappy_bird/browser-entry/browser-entry.network-view.utils.ts +9 -396
  137. package/test/examples/flappy_bird/browser-entry/browser-entry.playback.utils.ts +6 -714
  138. package/test/examples/flappy_bird/browser-entry/browser-entry.render.types.ts +26 -3
  139. package/test/examples/flappy_bird/browser-entry/browser-entry.runtime.types.ts +16 -1
  140. package/test/examples/flappy_bird/browser-entry/browser-entry.simulation.types.ts +39 -5
  141. package/test/examples/flappy_bird/browser-entry/browser-entry.spawn.utils.ts +11 -31
  142. package/test/examples/flappy_bird/browser-entry/browser-entry.stats.types.ts +32 -4
  143. package/test/examples/flappy_bird/browser-entry/browser-entry.ts +11 -0
  144. package/test/examples/flappy_bird/browser-entry/browser-entry.types.ts +8 -0
  145. package/test/examples/flappy_bird/browser-entry/browser-entry.visualization.types.ts +50 -7
  146. package/test/examples/flappy_bird/browser-entry/browser-entry.visualization.utils.ts +21 -893
  147. package/test/examples/flappy_bird/browser-entry/browser-entry.worker.types.ts +91 -10
  148. package/test/examples/flappy_bird/browser-entry/host/README.md +318 -0
  149. package/test/examples/flappy_bird/browser-entry/host/host.canvas.service.ts +16 -0
  150. package/test/examples/flappy_bird/browser-entry/host/host.constants.ts +20 -0
  151. package/test/examples/flappy_bird/browser-entry/host/host.dom.service.ts +10 -0
  152. package/test/examples/flappy_bird/browser-entry/host/host.resize.service.ts +1 -295
  153. package/test/examples/flappy_bird/browser-entry/host/host.stats.service.ts +14 -0
  154. package/test/examples/flappy_bird/browser-entry/host/host.ts +592 -6
  155. package/test/examples/flappy_bird/browser-entry/host/host.types.ts +13 -0
  156. package/test/examples/flappy_bird/browser-entry/host/resize/README.md +309 -0
  157. package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.constants.ts +47 -0
  158. package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.services.ts +392 -0
  159. package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.ts +132 -0
  160. package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.types.ts +92 -0
  161. package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.utils.ts +272 -0
  162. package/test/examples/flappy_bird/browser-entry/network-view/README.md +389 -0
  163. package/test/examples/flappy_bird/browser-entry/network-view/network-view.draw.service.ts +13 -0
  164. package/test/examples/flappy_bird/browser-entry/network-view/network-view.labels.utils.ts +12 -0
  165. package/test/examples/flappy_bird/browser-entry/network-view/network-view.layout.utils.ts +14 -0
  166. package/test/examples/flappy_bird/browser-entry/network-view/network-view.topology.utils.ts +267 -0
  167. package/test/examples/flappy_bird/browser-entry/network-view/network-view.ts +823 -7
  168. package/test/examples/flappy_bird/browser-entry/network-view/network-view.types.ts +11 -0
  169. package/test/examples/flappy_bird/browser-entry/playback/README.md +845 -0
  170. package/test/examples/flappy_bird/browser-entry/playback/background/README.md +355 -0
  171. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/README.md +1068 -0
  172. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.batch.services.ts +64 -0
  173. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.cache.services.ts +207 -0
  174. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.constants.ts +197 -0
  175. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.geometry.batch.utils.ts +114 -0
  176. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.geometry.layout.utils.test.ts +96 -0
  177. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.geometry.layout.utils.ts +204 -0
  178. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.geometry.services.ts +49 -0
  179. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.geometry.utils.ts +313 -0
  180. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.layer.services.ts +81 -0
  181. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.math.utils.test.ts +33 -0
  182. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.math.utils.ts +201 -0
  183. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.pulse.selection.utils.ts +171 -0
  184. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.pulse.timing.utils.ts +124 -0
  185. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.pulse.utils.test.ts +279 -0
  186. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.pulse.utils.ts +132 -0
  187. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.scene.services.ts +26 -0
  188. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.services.ts +65 -0
  189. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.ts +48 -0
  190. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.types.ts +342 -0
  191. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.utils.ts +10 -0
  192. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.cache.services.ts +96 -0
  193. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.constants.ts +127 -0
  194. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.draw.services.ts +184 -0
  195. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.scene.services.ts +64 -0
  196. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.services.ts +6 -0
  197. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.ts +53 -0
  198. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.types.ts +105 -0
  199. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.utils.ts +100 -0
  200. package/test/examples/flappy_bird/browser-entry/playback/frame-render/README.md +541 -0
  201. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.bird.utils.ts +180 -0
  202. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.canvas.services.ts +77 -0
  203. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.entity.services.ts +167 -0
  204. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.scene.services.ts +57 -0
  205. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.service.test.ts +176 -0
  206. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.service.ts +113 -0
  207. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.services.ts +35 -0
  208. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.trail.utils.ts +248 -0
  209. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.types.ts +103 -0
  210. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.utils.ts +11 -0
  211. package/test/examples/flappy_bird/browser-entry/playback/playback.constants.ts +1 -1
  212. package/test/examples/flappy_bird/browser-entry/playback/playback.frame-render.service.ts +10 -0
  213. package/test/examples/flappy_bird/browser-entry/playback/playback.iteration.services.ts +192 -0
  214. package/test/examples/flappy_bird/browser-entry/playback/playback.loop.service.ts +12 -0
  215. package/test/examples/flappy_bird/browser-entry/playback/playback.orchestration.types.ts +78 -0
  216. package/test/examples/flappy_bird/browser-entry/playback/playback.render.pipe-outline.service.ts +128 -0
  217. package/test/examples/flappy_bird/browser-entry/playback/playback.render.service.ts +1 -116
  218. package/test/examples/flappy_bird/browser-entry/playback/playback.session.services.ts +184 -0
  219. package/test/examples/flappy_bird/browser-entry/playback/playback.snapshot.utils.test.ts +121 -0
  220. package/test/examples/flappy_bird/browser-entry/playback/playback.snapshot.utils.ts +8 -0
  221. package/test/examples/flappy_bird/browser-entry/playback/playback.starfield.layer.services.ts +36 -0
  222. package/test/examples/flappy_bird/browser-entry/playback/playback.starfield.service.ts +11 -128
  223. package/test/examples/flappy_bird/browser-entry/playback/playback.starfield.services.ts +268 -0
  224. package/test/examples/flappy_bird/browser-entry/playback/playback.starfield.types.ts +91 -0
  225. package/test/examples/flappy_bird/browser-entry/playback/playback.starfield.utils.ts +11 -4
  226. package/test/examples/flappy_bird/browser-entry/playback/playback.trail.utils.ts +9 -86
  227. package/test/examples/flappy_bird/browser-entry/playback/playback.ts +75 -7
  228. package/test/examples/flappy_bird/browser-entry/playback/playback.types.ts +12 -9
  229. package/test/examples/flappy_bird/browser-entry/playback/playback.worker-channel.utils.ts +11 -123
  230. package/test/examples/flappy_bird/browser-entry/playback/snapshot/README.md +55 -0
  231. package/test/examples/flappy_bird/browser-entry/playback/snapshot/playback.snapshot.services.ts +103 -0
  232. package/test/examples/flappy_bird/browser-entry/playback/snapshot/playback.snapshot.summary.utils.test.ts +45 -0
  233. package/test/examples/flappy_bird/browser-entry/playback/snapshot/playback.snapshot.summary.utils.ts +28 -0
  234. package/test/examples/flappy_bird/browser-entry/playback/trail/README.md +95 -0
  235. package/test/examples/flappy_bird/browser-entry/playback/trail/playback.trail.history.services.test.ts +35 -0
  236. package/test/examples/flappy_bird/browser-entry/playback/trail/playback.trail.history.services.ts +64 -0
  237. package/test/examples/flappy_bird/browser-entry/playback/trail/playback.trail.opacity.utils.test.ts +37 -0
  238. package/test/examples/flappy_bird/browser-entry/playback/trail/playback.trail.opacity.utils.ts +74 -0
  239. package/test/examples/flappy_bird/browser-entry/playback/worker-channel/README.md +71 -0
  240. package/test/examples/flappy_bird/browser-entry/playback/worker-channel/playback.worker-channel.request.services.ts +45 -0
  241. package/test/examples/flappy_bird/browser-entry/playback/worker-channel/playback.worker-channel.summary.services.ts +74 -0
  242. package/test/examples/flappy_bird/browser-entry/playback/worker-channel/playback.worker-channel.types.ts +53 -0
  243. package/test/examples/flappy_bird/browser-entry/runtime/README.md +304 -0
  244. package/test/examples/flappy_bird/browser-entry/runtime/runtime.browser-globals.service.ts +15 -0
  245. package/test/examples/flappy_bird/browser-entry/runtime/runtime.errors.ts +17 -0
  246. package/test/examples/flappy_bird/browser-entry/runtime/runtime.evolution-launch.service.ts +56 -0
  247. package/test/examples/flappy_bird/browser-entry/runtime/runtime.evolution-loop.service.ts +19 -0
  248. package/test/examples/flappy_bird/browser-entry/runtime/runtime.lifecycle.service.ts +96 -0
  249. package/test/examples/flappy_bird/browser-entry/runtime/runtime.startup.service.ts +92 -0
  250. package/test/examples/flappy_bird/browser-entry/runtime/runtime.telemetry.service.ts +24 -0
  251. package/test/examples/flappy_bird/browser-entry/runtime/runtime.ts +31 -121
  252. package/test/examples/flappy_bird/browser-entry/runtime/runtime.types.ts +65 -0
  253. package/test/examples/flappy_bird/browser-entry/visualization/README.md +568 -0
  254. package/test/examples/flappy_bird/browser-entry/visualization/visualization.colors.utils.ts +26 -0
  255. package/test/examples/flappy_bird/browser-entry/visualization/visualization.constants.ts +110 -0
  256. package/test/examples/flappy_bird/browser-entry/visualization/visualization.draw.service.ts +979 -19
  257. package/test/examples/flappy_bird/browser-entry/visualization/visualization.legend.utils.ts +157 -3
  258. package/test/examples/flappy_bird/browser-entry/visualization/visualization.topology.utils.ts +13 -27
  259. package/test/examples/flappy_bird/browser-entry/visualization/visualization.ts +7 -20
  260. package/test/examples/flappy_bird/browser-entry/visualization/visualization.types.ts +14 -0
  261. package/test/examples/flappy_bird/browser-entry/worker-channel/README.md +238 -0
  262. package/test/examples/flappy_bird/browser-entry/worker-channel/worker-channel.errors.ts +11 -0
  263. package/test/examples/flappy_bird/browser-entry/worker-channel/worker-channel.generation.service.ts +12 -0
  264. package/test/examples/flappy_bird/browser-entry/worker-channel/worker-channel.playback.service.test.ts +143 -0
  265. package/test/examples/flappy_bird/browser-entry/worker-channel/worker-channel.playback.service.ts +140 -14
  266. package/test/examples/flappy_bird/browser-entry/worker-channel/worker-channel.request.service.ts +27 -0
  267. package/test/examples/flappy_bird/browser-entry/worker-channel/worker-channel.ts +8 -0
  268. package/test/examples/flappy_bird/browser-entry/worker-channel/worker-channel.types.ts +23 -0
  269. package/test/examples/flappy_bird/browser-entry/worker-channel/worker-channel.url.service.ts +5 -0
  270. package/test/examples/flappy_bird/constants/README.md +1163 -0
  271. package/test/examples/flappy_bird/constants/constants.birds.ts +16 -38
  272. package/test/examples/flappy_bird/constants/constants.difficulty.ts +21 -0
  273. package/test/examples/flappy_bird/constants/constants.network-view.ts +24 -0
  274. package/test/examples/flappy_bird/constants/constants.network.ts +1 -1
  275. package/test/examples/flappy_bird/constants/constants.observation.ts +7 -0
  276. package/test/examples/flappy_bird/constants/constants.palette.ts +9 -2
  277. package/test/examples/flappy_bird/constants/constants.physics.ts +9 -0
  278. package/test/examples/flappy_bird/constants/constants.pipe-render.ts +3 -0
  279. package/test/examples/flappy_bird/constants/constants.pipes.ts +22 -3
  280. package/test/examples/flappy_bird/constants/constants.runtime.ts +28 -4
  281. package/test/examples/flappy_bird/constants/constants.starfield.ts +78 -3
  282. package/test/examples/flappy_bird/constants/constants.ts +6 -0
  283. package/test/examples/flappy_bird/environment/README.md +182 -0
  284. package/test/examples/flappy_bird/environment/environment.collision.utils.ts +7 -0
  285. package/test/examples/flappy_bird/environment/environment.constants.ts +16 -3
  286. package/test/examples/flappy_bird/environment/environment.observation.utils.ts +12 -19
  287. package/test/examples/flappy_bird/environment/environment.state.service.ts +10 -0
  288. package/test/examples/flappy_bird/environment/environment.step.service.ts +15 -66
  289. package/test/examples/flappy_bird/environment/environment.types.ts +14 -0
  290. package/test/examples/flappy_bird/evaluation/README.md +155 -0
  291. package/test/examples/flappy_bird/evaluation/evaluation.constants.ts +23 -4
  292. package/test/examples/flappy_bird/evaluation/evaluation.fitness.utils.ts +16 -1
  293. package/test/examples/flappy_bird/evaluation/evaluation.rollout.service.ts +7 -374
  294. package/test/examples/flappy_bird/evaluation/evaluation.seed.utils.ts +4 -0
  295. package/test/examples/flappy_bird/evaluation/evaluation.types.ts +18 -2
  296. package/test/examples/flappy_bird/evaluation/rollout/README.md +355 -0
  297. package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.constants.ts +38 -0
  298. package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.service.ts +71 -0
  299. package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.services.ts +338 -0
  300. package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.types.ts +69 -0
  301. package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.utils.ts +399 -0
  302. package/test/examples/flappy_bird/flappy-evolution-worker/README.md +845 -0
  303. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.constants.ts +49 -7
  304. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.errors.ts +34 -3
  305. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.evolution.service.ts +22 -0
  306. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.playback.service.ts +62 -26
  307. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.protocol.service.ts +27 -1
  308. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.runtime.service.ts +23 -0
  309. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.simulation.frame.service.ts +378 -0
  310. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.simulation.types.ts +22 -0
  311. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.simulation.utils.ts +20 -203
  312. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.snapshot.utils.test.ts +94 -0
  313. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.snapshot.utils.ts +78 -13
  314. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.ts +235 -344
  315. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.types.ts +170 -22
  316. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.warm-start.service.ts +314 -0
  317. package/test/examples/flappy_bird/flappy.simulation.shared.utils.ts +17 -0
  318. package/test/examples/flappy_bird/flappyEnvironment.ts +21 -0
  319. package/test/examples/flappy_bird/flappyEvaluation.ts +12 -0
  320. package/test/examples/flappy_bird/flappyEvolution.worker.ts +7 -0
  321. package/test/examples/flappy_bird/index.ts +8 -2
  322. package/test/examples/flappy_bird/rng.ts +10 -0
  323. package/test/examples/flappy_bird/simulation-shared/README.md +518 -0
  324. package/test/examples/flappy_bird/simulation-shared/observation/README.md +255 -0
  325. package/test/examples/flappy_bird/simulation-shared/observation/observation.features.utils.ts +339 -0
  326. package/test/examples/flappy_bird/simulation-shared/observation/observation.ts +19 -0
  327. package/test/examples/flappy_bird/simulation-shared/observation/observation.vector.utils.ts +81 -0
  328. package/test/examples/flappy_bird/simulation-shared/simulation-shared.constants.ts +3 -0
  329. package/test/examples/flappy_bird/simulation-shared/simulation-shared.control.utils.ts +6 -0
  330. package/test/examples/flappy_bird/simulation-shared/simulation-shared.difficulty.utils.ts +9 -0
  331. package/test/examples/flappy_bird/simulation-shared/simulation-shared.errors.ts +10 -1
  332. package/test/examples/flappy_bird/simulation-shared/simulation-shared.memory.utils.ts +18 -0
  333. package/test/examples/flappy_bird/simulation-shared/simulation-shared.observation.utils.ts +7 -402
  334. package/test/examples/flappy_bird/simulation-shared/simulation-shared.spawn.utils.ts +36 -6
  335. package/test/examples/flappy_bird/{evaluation/evaluation.statistics.utils.ts → simulation-shared/simulation-shared.statistics.utils.ts} +30 -9
  336. package/test/examples/flappy_bird/simulation-shared/simulation-shared.types.ts +38 -5
  337. package/test/examples/flappy_bird/trainFlappyBird.ts +13 -0
  338. package/test/examples/flappy_bird/trainer/README.md +676 -0
  339. package/test/examples/flappy_bird/trainer/evaluation/README.md +253 -0
  340. package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.constants.ts +15 -0
  341. package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.services.ts +86 -0
  342. package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.ts +187 -0
  343. package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.types.ts +32 -0
  344. package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.utils.ts +182 -0
  345. package/test/examples/flappy_bird/trainer/trainer.evaluation.service.ts +13 -0
  346. package/test/examples/flappy_bird/trainer/trainer.fitness.service.ts +23 -1
  347. package/test/examples/flappy_bird/trainer/trainer.loop.service.ts +17 -1
  348. package/test/examples/flappy_bird/trainer/trainer.report.service.services.ts +181 -0
  349. package/test/examples/flappy_bird/trainer/trainer.report.service.ts +136 -0
  350. package/test/examples/flappy_bird/trainer/trainer.selection.utils.ts +89 -0
  351. package/test/examples/flappy_bird/trainer/trainer.setup.service.ts +22 -0
  352. package/test/examples/flappy_bird/trainer/trainer.signals.service.ts +8 -0
  353. package/test/examples/flappy_bird/trainer/trainer.ts +38 -553
  354. package/test/examples/flappy_bird/trainer/trainer.types.ts +44 -7
  355. package/test/neat/neat.topology-intent.test.ts +129 -0
  356. package/test/network/network.topology-intent.test.ts +44 -0
  357. package/test/examples/flappy_bird/browser-entry/browser-entry.utils.ts +0 -12
  358. package/test/examples/flappy_bird/environment/environment.ts +0 -7
  359. package/test/examples/flappy_bird/evaluation/evaluation.ts +0 -7
  360. package/test/examples/flappy_bird/simulation-shared/simulation-shared.ts +0 -15
  361. package/test/examples/flappy_bird/trainer/trainer.statistics.utils.ts +0 -78
@@ -3,50 +3,16 @@
3
3
  import { Neat } from '../../../../src/neataptic';
4
4
  import Network from '../../../../src/architecture/network';
5
5
  import { createXorshift32 } from '../rng';
6
- import {
7
- commitObservationMemoryStep,
8
- resolveFlapDecision,
9
- resolveObservationVector,
10
- } from '../browser-entry/browser-entry.observation.utils';
11
- import {
12
- createBirdColor,
13
- resolveDifficultyProfile,
14
- sampleGapCenterY,
15
- } from '../browser-entry/browser-entry.spawn.utils';
16
6
  import type {
17
- WorkerHeuristicObservationFeatures,
18
7
  WorkerInitMessage,
19
- WorkerPlaybackFrameSnapshot,
20
- WorkerPopulationPipe,
21
8
  WorkerPlaybackState,
22
9
  WorkerRequestMessage,
23
10
  WorkerRequestPlaybackStepMessage,
24
11
  WorkerResponseMessage,
12
+ WorkerStartPlaybackMessage,
25
13
  } from './flappy-evolution-worker.types';
26
14
  import { createInitializedWorkerRuntime } from './flappy-evolution-worker.runtime.service';
27
- import { FLAPPY_BIRD_VIEWPORT_X_RATIO } from '../constants/constants';
28
- import {
29
- FLAPPY_BIRD_RADIUS_PX,
30
- FLAPPY_BIRD_X_PX,
31
- FLAPPY_PIPE_COLLISION_ENTRANCE_EXPAND_PX,
32
- FLAPPY_PIPE_COLLISION_SIDE_EXPAND_PX,
33
- FLAPPY_CONTROL_SUBSTEPS_PER_FRAME,
34
- FLAPPY_ENABLE_RUNTIME_INSTRUMENTATION,
35
- FLAPPY_FLAP_VELOCITY_PX_PER_FRAME,
36
- FLAPPY_GRAVITY_PX_PER_FRAME2,
37
- FLAPPY_MAX_FALL_SPEED_PX_PER_FRAME,
38
- FLAPPY_PIPE_WIDTH_PX,
39
- FLAPPY_WORLD_HEIGHT_PX,
40
- } from '../constants/constants';
41
- import {
42
- FLAPPY_WORKER_GEN0_PRETRAIN_BATCH_SIZE,
43
- FLAPPY_WORKER_GEN0_PRETRAIN_BIAS_NOISE_STDDEV,
44
- FLAPPY_WORKER_GEN0_PRETRAIN_ITERATIONS,
45
- FLAPPY_WORKER_GEN0_PRETRAIN_RATE,
46
- FLAPPY_WORKER_GEN0_PRETRAIN_SAMPLE_COUNT,
47
- FLAPPY_WORKER_GEN0_PRETRAIN_VISIBLE_WORLD_WIDTH_PX,
48
- FLAPPY_WORKER_GEN0_PRETRAIN_WEIGHT_NOISE_STDDEV,
49
- } from './flappy-evolution-worker.constants';
15
+ import { FLAPPY_ENABLE_RUNTIME_INSTRUMENTATION } from '../constants/constants';
50
16
  import {
51
17
  createWorkerErrorMessage,
52
18
  createWorkerErrorMessageFromUnknown,
@@ -58,22 +24,30 @@ import {
58
24
  beginWorkerPlaybackSession,
59
25
  processWorkerPlaybackStep,
60
26
  } from './flappy-evolution-worker.playback.service';
61
- import { createWorkerPlaybackSnapshot } from './flappy-evolution-worker.snapshot.utils';
62
- import { createSharedObservationMemoryState } from '../flappy.simulation.shared.utils';
63
27
  import {
64
- createWorkerPopulationRenderState,
65
- stepWorkerPopulationFrame,
66
- } from './flappy-evolution-worker.simulation.utils';
28
+ createWorkerPlaybackSnapshot,
29
+ resolveWorkerPlaybackSnapshotTransferList,
30
+ } from './flappy-evolution-worker.snapshot.utils';
31
+ import { createWorkerPopulationRenderState } from './flappy-evolution-worker.simulation.utils';
32
+ import { stepWorkerPopulationFrame } from './flappy-evolution-worker.simulation.frame.service';
33
+ import { warmStartWorkerGenerationZeroIfNeeded } from './flappy-evolution-worker.warm-start.service';
34
+
35
+ const FLAPPY_WORKER_INITIAL_SEED = 0;
36
+ const FLAPPY_WORKER_INITIAL_WINNER_INDEX = -1;
37
+
38
+ type WorkerMutableRuntimeState = {
39
+ stopped: boolean;
40
+ neatRuntime: Neat | undefined;
41
+ currentPopulation: Network[];
42
+ currentPlaybackState: WorkerPlaybackState | undefined;
43
+ currentPlaybackRng: ReturnType<typeof createXorshift32> | undefined;
44
+ playbackWinnerIndex: number;
45
+ initializationPromise: Promise<void> | undefined;
46
+ workerInitSeed: number;
47
+ generationZeroWarmStartApplied: boolean;
48
+ };
67
49
 
68
- let stopped = false;
69
- let neatRuntime: Neat | undefined;
70
- let currentPopulation: Network[] = [];
71
- let currentPlaybackState: WorkerPlaybackState | undefined;
72
- let currentPlaybackRng: ReturnType<typeof createXorshift32> | undefined;
73
- let playbackWinnerIndex = -1;
74
- let initializationPromise: Promise<void> | undefined;
75
- let workerInitSeed = 0;
76
- let generationZeroWarmStartApplied = false;
50
+ const workerMutableRuntimeState = createWorkerMutableRuntimeState();
77
51
 
78
52
  /**
79
53
  * Main worker message router.
@@ -83,6 +57,10 @@ let generationZeroWarmStartApplied = false;
83
57
  * the host posts typed messages, and the worker folds those messages into state.
84
58
  * This keeps rendering and heavy simulation/evolution work decoupled.
85
59
  *
60
+ * If you want background reading, the MDN article on Web Workers is the most
61
+ * practical reference for understanding why this example moves evolution and
62
+ * playback simulation off the main thread.
63
+ *
86
64
  * Routing policy in this worker:
87
65
  * - `init`: create NEAT runtime and seed deterministic RNG state.
88
66
  * - `request-generation`: run one evolution cycle and publish summary payload.
@@ -90,50 +68,102 @@ let generationZeroWarmStartApplied = false;
90
68
  * - `request-playback-step`: advance playback and stream telemetry snapshots.
91
69
  * - `stop`: mark worker as stopped (future generation requests fail fast).
92
70
  */
93
- self.onmessage = (event: MessageEvent<WorkerRequestMessage>) => {
94
- // Step 1: Decode the incoming discriminated-union message.
95
- const workerMessage = event.data;
71
+ self.onmessage = createWorkerMessageHandler(workerMutableRuntimeState);
72
+
73
+ /**
74
+ * Creates the mutable worker runtime state container.
75
+ *
76
+ * Educational note:
77
+ * The worker keeps one small mutable state bag instead of scattering globals.
78
+ * That makes the protocol flow easier to explain and lets the entrypoint pass a
79
+ * single dependency object through the orchestration helpers.
80
+ *
81
+ * @returns Mutable worker runtime state.
82
+ */
83
+ function createWorkerMutableRuntimeState(): WorkerMutableRuntimeState {
84
+ // Step 1: Initialize the worker state with empty runtime and playback fields.
85
+ return {
86
+ stopped: false,
87
+ neatRuntime: undefined,
88
+ currentPopulation: [],
89
+ currentPlaybackState: undefined,
90
+ currentPlaybackRng: undefined,
91
+ playbackWinnerIndex: FLAPPY_WORKER_INITIAL_WINNER_INDEX,
92
+ initializationPromise: undefined,
93
+ workerInitSeed: FLAPPY_WORKER_INITIAL_SEED,
94
+ generationZeroWarmStartApplied: false,
95
+ };
96
+ }
97
+
98
+ /**
99
+ * Creates the top-level worker message handler.
100
+ *
101
+ * The returned function is intentionally thin. All protocol decisions are
102
+ * delegated to the router service so the worker entrypoint stays readable as a
103
+ * high-level orchestration module.
104
+ *
105
+ * @example
106
+ * ```ts
107
+ * self.onmessage = createWorkerMessageHandler(workerMutableRuntimeState);
108
+ * ```
109
+ *
110
+ * @param workerMutableRuntimeState - Mutable worker runtime state.
111
+ * @returns Worker message handler.
112
+ */
113
+ function createWorkerMessageHandler(
114
+ workerMutableRuntimeState: WorkerMutableRuntimeState,
115
+ ): (event: MessageEvent<WorkerRequestMessage>) => void {
116
+ // Step 1: Capture the protocol handlers so each message reuses the same stateful callbacks.
117
+ const workerProtocolHandlers = createWorkerProtocolHandlers(
118
+ workerMutableRuntimeState,
119
+ );
120
+
121
+ // Step 2: Return the thin orchestration handler used by `self.onmessage`.
122
+ return (event: MessageEvent<WorkerRequestMessage>): void => {
123
+ const workerMessage = event.data;
124
+ routeWorkerProtocolMessage(workerMessage, workerProtocolHandlers);
125
+ };
126
+ }
96
127
 
97
- // Step 2: Route inbound protocol message to worker lifecycle handlers.
98
- routeWorkerProtocolMessage(workerMessage, {
99
- markStopped: () => {
100
- stopped = true;
128
+ /**
129
+ * Creates protocol handlers bound to the mutable worker runtime state.
130
+ *
131
+ * This helper is the bridge between the pure protocol router and the impure
132
+ * worker runtime. Each callback closes over the same mutable state bag so the
133
+ * protocol layer can remain small and declarative.
134
+ *
135
+ * @param workerMutableRuntimeState - Mutable worker runtime state.
136
+ * @returns Protocol handler bundle.
137
+ */
138
+ function createWorkerProtocolHandlers(
139
+ workerMutableRuntimeState: WorkerMutableRuntimeState,
140
+ ) {
141
+ // Step 1: Bind each protocol operation to the shared mutable runtime state.
142
+ return {
143
+ markStopped: (): void => {
144
+ workerMutableRuntimeState.stopped = true;
145
+ },
146
+ beginInitialization: (payload: WorkerInitMessage['payload']): void => {
147
+ beginWorkerInitialization(workerMutableRuntimeState, payload);
101
148
  },
102
- beginInitialization: (payload) => {
103
- initializationPromise = initializeRuntime(payload).catch(
104
- (error: unknown) => {
105
- postWorkerMessage(createWorkerErrorMessageFromUnknown(error));
106
- throw error;
107
- },
108
- );
109
- void initializationPromise.catch(() => {
110
- postWorkerMessage(
111
- createWorkerErrorMessage(FLAPPY_WORKER_INIT_FAILED_ERROR_MESSAGE),
112
- );
113
- });
149
+ beginGenerationRequest: (): void => {
150
+ beginWorkerGenerationRequest(workerMutableRuntimeState);
114
151
  },
115
- beginGenerationRequest: () => {
116
- void evolveAndPublishGeneration().catch((error: unknown) => {
117
- postWorkerMessage(createWorkerErrorMessageFromUnknown(error));
118
- });
152
+ hasPopulation: (): boolean =>
153
+ workerMutableRuntimeState.currentPopulation.length > 0,
154
+ startPlayback: (payload: WorkerStartPlaybackMessage['payload']): void => {
155
+ beginWorkerPlayback(workerMutableRuntimeState, payload);
119
156
  },
120
- hasPopulation: () =>
121
- Array.isArray(currentPopulation) && currentPopulation.length > 0,
122
- startPlayback: (payload) => {
123
- const nextPlaybackSessionState = beginWorkerPlaybackSession({
124
- currentPopulation,
125
- payload,
126
- createPopulationRenderState: createWorkerPopulationRenderState,
127
- });
128
- currentPlaybackState = nextPlaybackSessionState.currentPlaybackState;
129
- currentPlaybackRng = nextPlaybackSessionState.currentPlaybackRng;
130
- playbackWinnerIndex = nextPlaybackSessionState.playbackWinnerIndex;
157
+ hasPlaybackState: (): boolean =>
158
+ workerMutableRuntimeState.currentPlaybackState != null,
159
+ processPlaybackStep: (
160
+ payload: WorkerRequestPlaybackStepMessage['payload'],
161
+ ): void => {
162
+ processWorkerPlaybackStepRequest(workerMutableRuntimeState, payload);
131
163
  },
132
- hasPlaybackState: () => currentPlaybackState != null,
133
- processPlaybackStep,
134
164
  postWorkerMessage,
135
- });
136
- };
165
+ };
166
+ }
137
167
 
138
168
  /**
139
169
  * Initializes the worker-local NEAT runtime used by browser evolution playback.
@@ -143,17 +173,23 @@ self.onmessage = (event: MessageEvent<WorkerRequestMessage>) => {
143
173
  * early-termination fitness rollout. Keeping this setup centralized helps ensure
144
174
  * reproducibility between runs and keeps host<->worker contracts simple.
145
175
  *
176
+ * This function only prepares the evolutionary controller. It does not start
177
+ * playback and it does not evolve a generation yet; those remain separate
178
+ * protocol steps so the host can control them explicitly.
179
+ *
146
180
  * @param initPayload - Initialization values from the browser host.
147
181
  * @returns Promise resolved when runtime setup is complete.
148
182
  */
149
183
  async function initializeRuntime(
184
+ workerMutableRuntimeState: WorkerMutableRuntimeState,
150
185
  initPayload: WorkerInitMessage['payload'],
151
186
  ): Promise<void> {
152
187
  // Step 1: Persist the worker seed so warm-start logic can reuse it deterministically.
153
- workerInitSeed = initPayload.rngSeed;
188
+ workerMutableRuntimeState.workerInitSeed = initPayload.rngSeed;
154
189
 
155
190
  // Step 2: Build and configure the NEAT runtime controller.
156
- neatRuntime = createInitializedWorkerRuntime(initPayload);
191
+ workerMutableRuntimeState.neatRuntime =
192
+ createInitializedWorkerRuntime(initPayload);
157
193
  }
158
194
 
159
195
  /**
@@ -166,14 +202,23 @@ async function initializeRuntime(
166
202
  *
167
203
  * @returns Promise resolved after generation payload is posted.
168
204
  */
169
- async function evolveAndPublishGeneration(): Promise<void> {
205
+ async function evolveAndPublishGeneration(
206
+ workerMutableRuntimeState: WorkerMutableRuntimeState,
207
+ ): Promise<void> {
170
208
  const generationPayload = await evolveAndBuildGenerationReadyMessage({
171
- initializationPromise,
172
- neatRuntime,
173
- isStopped: () => stopped,
174
- warmStartGenerationZeroIfNeeded,
209
+ initializationPromise: workerMutableRuntimeState.initializationPromise,
210
+ neatRuntime: workerMutableRuntimeState.neatRuntime,
211
+ isStopped: () => workerMutableRuntimeState.stopped,
212
+ warmStartGenerationZeroIfNeeded: (neatController) =>
213
+ warmStartWorkerGenerationZeroIfNeeded(neatController, {
214
+ workerInitSeed: workerMutableRuntimeState.workerInitSeed,
215
+ generationZeroWarmStartApplied:
216
+ workerMutableRuntimeState.generationZeroWarmStartApplied,
217
+ }).then(() => {
218
+ workerMutableRuntimeState.generationZeroWarmStartApplied = true;
219
+ }),
175
220
  setCurrentPopulation: (nextPopulation) => {
176
- currentPopulation = nextPopulation;
221
+ workerMutableRuntimeState.currentPopulation = nextPopulation;
177
222
  },
178
223
  });
179
224
 
@@ -181,263 +226,86 @@ async function evolveAndPublishGeneration(): Promise<void> {
181
226
  }
182
227
 
183
228
  /**
184
- * Applies a one-time generation-0 warm-start to improve initial demo quality.
185
- *
186
- * Educational note:
187
- * NEAT in this setup starts from cloned copies of one seed architecture.
188
- * A short supervised warm-up can reduce the "all-random" first-generation
189
- * behavior while preserving evolutionary search in later generations.
190
- *
191
- * Strategy:
192
- * 1) Build heuristic-labeled synthetic observations.
193
- * 2) Train one template network quickly.
194
- * 3) Copy template parameters to each genome with small Gaussian noise.
195
- *
196
- * @param neatController - Initialized NEAT runtime.
197
- * @returns Promise resolved when warm-start decision completes.
198
- */
199
- async function warmStartGenerationZeroIfNeeded(
200
- neatController: Neat,
201
- ): Promise<void> {
202
- // Step 1: Exit fast when warm-start is already processed.
203
- if (generationZeroWarmStartApplied) return;
204
-
205
- // Step 2: Warm-start only generation 0 to avoid skewing later evolution.
206
- if (neatController.generation !== 0) {
207
- generationZeroWarmStartApplied = true;
208
- return;
209
- }
210
-
211
- // Step 3: Validate population availability.
212
- const population = neatController.population;
213
- if (!Array.isArray(population) || population.length === 0) {
214
- generationZeroWarmStartApplied = true;
215
- return;
216
- }
217
-
218
- // Step 1: Build a small synthetic dataset labeled by a simple heuristic.
219
- // The goal is NOT to solve Flappy here, only to avoid a totally random first generation.
220
- const warmStartRng = createXorshift32(workerInitSeed ^ 0x9e37_79b9);
221
- const trainingSet = buildHeuristicPretrainSet(
222
- warmStartRng,
223
- FLAPPY_WORKER_GEN0_PRETRAIN_SAMPLE_COUNT,
224
- );
225
-
226
- // Step 2: Train a single template network (fast), then seed the whole population from it.
227
- const templateNetwork = population[0]?.clone();
228
- if (!templateNetwork) {
229
- generationZeroWarmStartApplied = true;
230
- return;
231
- }
232
-
233
- try {
234
- templateNetwork.train(trainingSet, {
235
- iterations: FLAPPY_WORKER_GEN0_PRETRAIN_ITERATIONS,
236
- rate: FLAPPY_WORKER_GEN0_PRETRAIN_RATE,
237
- batchSize: FLAPPY_WORKER_GEN0_PRETRAIN_BATCH_SIZE,
238
- optimizer: 'adam',
239
- // Keep the training loop simple and deterministic.
240
- mixedPrecision: false,
241
- });
242
- } catch {
243
- // If training fails for any reason (e.g., incompatible topology), fall back to pure noise seeding.
244
- }
245
-
246
- // Step 3: Copy trained weights/biases into each genome with small noise for diversity.
247
- for (const genome of population) {
248
- applyTemplateWeightsWithNoise(genome, templateNetwork, warmStartRng, {
249
- weightStdDev: FLAPPY_WORKER_GEN0_PRETRAIN_WEIGHT_NOISE_STDDEV,
250
- biasStdDev: FLAPPY_WORKER_GEN0_PRETRAIN_BIAS_NOISE_STDDEV,
251
- });
252
- (genome as unknown as { score?: number }).score = undefined;
253
- }
254
-
255
- generationZeroWarmStartApplied = true;
256
- }
257
-
258
- /**
259
- * Builds synthetic supervised samples for generation-0 behavior cloning.
229
+ * Begins worker initialization and captures asynchronous failures.
260
230
  *
261
- * Educational note:
262
- * Samples are generated from plausible Flappy states and passed through the
263
- * exact observation encoder used during runtime. This keeps feature semantics
264
- * aligned between pretraining and live simulation.
231
+ * The worker retains the initialization promise so later generation requests can
232
+ * await setup completion instead of racing against it.
265
233
  *
266
- * @param rng - Deterministic random source.
267
- * @param sampleCount - Requested number of synthetic samples.
268
- * @returns Supervised dataset of { input, output } pairs.
234
+ * @param workerMutableRuntimeState - Mutable worker runtime state.
235
+ * @param initPayload - Initialization payload.
236
+ * @returns Nothing.
269
237
  */
270
- function buildHeuristicPretrainSet(
271
- rng: ReturnType<typeof createXorshift32>,
272
- sampleCount: number,
273
- ): Array<{ input: number[]; output: number[] }> {
274
- // Step 1: Resolve bounded sample count and a baseline difficulty profile.
275
- const clampedSampleCount = Math.max(8, Math.trunc(sampleCount));
276
- const difficultyProfile = resolveDifficultyProfile(0);
277
- const trainingSet: Array<{ input: number[]; output: number[] }> = [];
278
-
279
- // Step 2: Sample state tuples, encode observations, and attach heuristic labels.
280
- for (let sampleIndex = 0; sampleIndex < clampedSampleCount; sampleIndex++) {
281
- const pipeGapPx = difficultyProfile.pipeGapPx;
282
- const gapHalfPx = pipeGapPx * 0.5;
283
-
284
- const birdYPx = rng.nextFloat01() * FLAPPY_WORLD_HEIGHT_PX;
285
- const velocityYPxPerFrame =
286
- (rng.nextFloat01() * 2 - 1) * FLAPPY_MAX_FALL_SPEED_PX_PER_FRAME;
287
-
288
- const pipeXMinPx = FLAPPY_BIRD_X_PX + 40;
289
- const pipeXMaxPx =
290
- FLAPPY_BIRD_X_PX +
291
- FLAPPY_WORKER_GEN0_PRETRAIN_VISIBLE_WORLD_WIDTH_PX * 0.92;
292
- const pipeXSamplePx =
293
- pipeXMinPx + rng.nextFloat01() * Math.max(1, pipeXMaxPx - pipeXMinPx);
294
-
295
- const minGapCenterYPx = gapHalfPx;
296
- const maxGapCenterYPx = Math.max(
297
- minGapCenterYPx,
298
- FLAPPY_WORLD_HEIGHT_PX - gapHalfPx,
299
- );
300
- const gapCenterYPx =
301
- minGapCenterYPx + rng.nextFloat01() * (maxGapCenterYPx - minGapCenterYPx);
302
-
303
- const pipes: WorkerPopulationPipe[] = [
304
- {
305
- id: 1,
306
- xPx: pipeXSamplePx,
307
- gapCenterYPx,
308
- gapSizePx: pipeGapPx,
309
- },
310
- ];
311
-
312
- const observationMemoryState = createSharedObservationMemoryState();
313
- const observation = resolveObservationVector(
314
- birdYPx,
315
- velocityYPxPerFrame,
316
- pipes,
317
- FLAPPY_WORKER_GEN0_PRETRAIN_VISIBLE_WORLD_WIDTH_PX,
318
- FLAPPY_WORLD_HEIGHT_PX,
319
- difficultyProfile,
320
- difficultyProfile.pipeSpawnIntervalFrames,
321
- observationMemoryState,
322
- );
238
+ function beginWorkerInitialization(
239
+ workerMutableRuntimeState: WorkerMutableRuntimeState,
240
+ initPayload: WorkerInitMessage['payload'],
241
+ ): void {
242
+ // Step 1: Start initialization and retain the promise for later generation requests.
243
+ workerMutableRuntimeState.initializationPromise = initializeRuntime(
244
+ workerMutableRuntimeState,
245
+ initPayload,
246
+ ).catch((error: unknown) => {
247
+ postWorkerMessage(createWorkerErrorMessageFromUnknown(error));
248
+ throw error;
249
+ });
323
250
 
324
- const shouldFlap = resolveHeuristicTeacherFlapDecision(
325
- observation.observationFeatures,
251
+ // Step 2: Emit a stable init-failed error if the initialization promise rejects.
252
+ void workerMutableRuntimeState.initializationPromise.catch(() => {
253
+ postWorkerMessage(
254
+ createWorkerErrorMessage(FLAPPY_WORKER_INIT_FAILED_ERROR_MESSAGE),
326
255
  );
327
- trainingSet.push({
328
- input: observation.observationVector,
329
- output: shouldFlap ? [0, 1] : [1, 0],
330
- });
331
- }
332
-
333
- // Step 3: Return immutable training pairs consumed by `Network.train`.
334
- return trainingSet;
335
- }
336
-
337
- /**
338
- * Heuristic teacher policy used to label synthetic pretraining samples.
339
- *
340
- * Educational note:
341
- * The teacher is intentionally simple and interpretable, acting as a rough
342
- * "stay near next gap center" controller. The objective is biasing the initial
343
- * policy away from chaotic behavior, not producing expert trajectories.
344
- *
345
- * @param features - Structured observation features for one synthetic state.
346
- * @returns True when the teacher says "flap".
347
- */
348
- function resolveHeuristicTeacherFlapDecision(
349
- features: WorkerHeuristicObservationFeatures,
350
- ): boolean {
351
- // Heuristic intent:
352
- // - If the bird is below the upcoming gap center, flap to correct upward.
353
- // - Avoid spamming flap when already moving upward quickly.
354
- // - Prefer corrections closer to the pipe (or when urgency is high).
355
- const isBelowNextGapCenter = features.normalizedDeltaToNextGap > 0.035;
356
- const isNotAlreadyRisingFast = features.normalizedVelocity > -0.25;
357
- const isNearGapEntry = features.normalizedFramesToGapEntry < 0.8;
358
- const isUrgent = features.normalizedEntryUrgency > 0.18;
359
-
360
- return (
361
- isBelowNextGapCenter &&
362
- isNotAlreadyRisingFast &&
363
- (isNearGapEntry || isUrgent)
364
- );
256
+ });
365
257
  }
366
258
 
367
259
  /**
368
- * Copies template parameters into a genome and injects small Gaussian noise.
260
+ * Begins one asynchronous generation request and captures failures.
369
261
  *
370
- * Educational note:
371
- * Copying one trained template without noise would collapse diversity. Adding
372
- * mild deterministic jitter keeps the population near a useful baseline while
373
- * preserving variation for selection and mutation.
262
+ * This is intentionally fire-and-forget from the protocol perspective. The
263
+ * actual completion signal is the later `generation-ready` or `error` message
264
+ * posted back to the host.
374
265
  *
375
- * @param genome - Target genome to mutate in-place.
376
- * @param template - Trained template source network.
377
- * @param rng - Deterministic random source for noise sampling.
378
- * @param noise - Standard deviations for weight and bias perturbations.
266
+ * @param workerMutableRuntimeState - Mutable worker runtime state.
379
267
  * @returns Nothing.
380
268
  */
381
- function applyTemplateWeightsWithNoise(
382
- genome: Network,
383
- template: Network,
384
- rng: ReturnType<typeof createXorshift32>,
385
- noise: { weightStdDev: number; biasStdDev: number },
269
+ function beginWorkerGenerationRequest(
270
+ workerMutableRuntimeState: WorkerMutableRuntimeState,
386
271
  ): void {
387
- // Step 1: Clamp noise scales to valid non-negative values.
388
- const weightStdDev = Math.max(0, noise.weightStdDev);
389
- const biasStdDev = Math.max(0, noise.biasStdDev);
390
-
391
- // Step 2: Copy node biases with additive Gaussian noise.
392
- const genomeNodes = genome.nodes;
393
- const templateNodes = template.nodes;
394
- const nodeCopyCount = Math.min(genomeNodes.length, templateNodes.length);
395
- for (let nodeIndex = 0; nodeIndex < nodeCopyCount; nodeIndex++) {
396
- const templateBias = templateNodes[nodeIndex]?.bias ?? 0;
397
- genomeNodes[nodeIndex].bias =
398
- templateBias + sampleGaussian(rng) * biasStdDev;
399
- }
400
-
401
- // Step 3: Copy connection weights with additive Gaussian noise.
402
- const genomeConnections = genome.connections;
403
- const templateConnections = template.connections;
404
- const connectionCopyCount = Math.min(
405
- genomeConnections.length,
406
- templateConnections.length,
272
+ // Step 1: Run the generation pipeline and publish worker errors on failure.
273
+ void evolveAndPublishGeneration(workerMutableRuntimeState).catch(
274
+ (error: unknown) => {
275
+ postWorkerMessage(createWorkerErrorMessageFromUnknown(error));
276
+ },
407
277
  );
408
- for (
409
- let connectionIndex = 0;
410
- connectionIndex < connectionCopyCount;
411
- connectionIndex++
412
- ) {
413
- const templateWeight = templateConnections[connectionIndex]?.weight ?? 0;
414
- genomeConnections[connectionIndex].weight =
415
- templateWeight + sampleGaussian(rng) * weightStdDev;
416
- }
417
278
  }
418
279
 
419
280
  /**
420
- * Samples one standard-normal value using the Box–Muller transform.
281
+ * Begins a new playback session from the current evolved population.
421
282
  *
422
- * Educational note:
423
- * Uniform RNG is easy to produce, but Gaussian noise is usually a better fit
424
- * for small parameter perturbations because it concentrates probability around
425
- * zero while still occasionally exploring larger offsets.
283
+ * A playback session is a deterministic simulation snapshot seeded from the
284
+ * current population. Each new session resets playback RNG and world state so
285
+ * the host can replay generations cleanly.
426
286
  *
427
- * @param rng - Deterministic random source.
428
- * @returns One approximately standard-normal random value.
287
+ * @param workerMutableRuntimeState - Mutable worker runtime state.
288
+ * @param payload - Playback start payload.
289
+ * @returns Nothing.
429
290
  */
430
- function sampleGaussian(rng: ReturnType<typeof createXorshift32>): number {
431
- // Box–Muller transform (deterministic given rng).
432
- // Step 1: Avoid `log(0)` by flooring uniforms away from zero.
433
- const epsilon = 1e-12;
434
- const uniformA = Math.max(epsilon, rng.nextFloat01());
435
- const uniformB = Math.max(epsilon, rng.nextFloat01());
291
+ function beginWorkerPlayback(
292
+ workerMutableRuntimeState: WorkerMutableRuntimeState,
293
+ payload: { visibleWorldWidthPx: number; visibleWorldHeightPx: number },
294
+ ): void {
295
+ // Step 1: Create the next playback session from the current population snapshot.
296
+ const nextPlaybackSessionState = beginWorkerPlaybackSession({
297
+ currentPopulation: workerMutableRuntimeState.currentPopulation,
298
+ payload,
299
+ createPopulationRenderState: createWorkerPopulationRenderState,
300
+ });
436
301
 
437
- // Step 2: Convert two uniforms into one normal sample.
438
- const magnitude = Math.sqrt(-2 * Math.log(uniformA));
439
- const angle = 2 * Math.PI * uniformB;
440
- return magnitude * Math.cos(angle);
302
+ // Step 2: Persist the next playback state, RNG, and winner index.
303
+ workerMutableRuntimeState.currentPlaybackState =
304
+ nextPlaybackSessionState.currentPlaybackState;
305
+ workerMutableRuntimeState.currentPlaybackRng =
306
+ nextPlaybackSessionState.currentPlaybackRng;
307
+ workerMutableRuntimeState.playbackWinnerIndex =
308
+ nextPlaybackSessionState.playbackWinnerIndex;
441
309
  }
442
310
 
443
311
  /**
@@ -448,41 +316,64 @@ function sampleGaussian(rng: ReturnType<typeof createXorshift32>): number {
448
316
  * smoothness against throughput. This function keeps that loop deterministic and
449
317
  * emits one compact snapshot payload per request.
450
318
  *
319
+ * Importantly, the worker remains authoritative for deciding when the run is
320
+ * over and which bird should be treated as the playback winner.
321
+ *
451
322
  * @param playbackStepPayload - Host-selected simulation-step budget and viewport.
452
323
  * @returns Nothing.
453
324
  */
454
- function processPlaybackStep(
325
+ function processWorkerPlaybackStepRequest(
326
+ workerMutableRuntimeState: WorkerMutableRuntimeState,
455
327
  playbackStepPayload: WorkerRequestPlaybackStepMessage['payload'],
456
328
  ): void {
457
- if (!currentPlaybackState || !currentPlaybackRng) {
329
+ // Step 1: Guard against playback-step requests before playback state exists.
330
+ if (
331
+ !workerMutableRuntimeState.currentPlaybackState ||
332
+ !workerMutableRuntimeState.currentPlaybackRng
333
+ ) {
458
334
  throw new Error(
459
335
  'Playback random source is unavailable. Start playback first.',
460
336
  );
461
337
  }
462
338
 
339
+ // Step 2: Advance playback and build the next compact snapshot payload.
463
340
  const nextPlaybackStepState = processWorkerPlaybackStep({
464
341
  playbackStepPayload,
465
- currentPlaybackState,
466
- currentPlaybackRng,
467
- currentPopulation,
468
- neatRuntime,
342
+ currentPlaybackState: workerMutableRuntimeState.currentPlaybackState,
343
+ currentPlaybackRng: workerMutableRuntimeState.currentPlaybackRng,
344
+ currentPopulation: workerMutableRuntimeState.currentPopulation,
345
+ neatRuntime: workerMutableRuntimeState.neatRuntime,
469
346
  stepPopulationFrame: stepWorkerPopulationFrame,
470
347
  createPlaybackSnapshot: createWorkerPlaybackSnapshot,
348
+ resolvePlaybackSnapshotTransferList:
349
+ resolveWorkerPlaybackSnapshotTransferList,
471
350
  postWorkerMessage,
472
351
  });
473
352
 
474
- currentPlaybackState = nextPlaybackStepState.currentPlaybackState;
475
- currentPlaybackRng = nextPlaybackStepState.currentPlaybackRng;
476
- currentPopulation = nextPlaybackStepState.currentPopulation;
477
- playbackWinnerIndex = nextPlaybackStepState.playbackWinnerIndex;
353
+ // Step 3: Persist the advanced playback state for the next host request.
354
+ workerMutableRuntimeState.currentPlaybackState =
355
+ nextPlaybackStepState.currentPlaybackState;
356
+ workerMutableRuntimeState.currentPlaybackRng =
357
+ nextPlaybackStepState.currentPlaybackRng;
358
+ workerMutableRuntimeState.currentPopulation =
359
+ nextPlaybackStepState.currentPopulation;
360
+ workerMutableRuntimeState.playbackWinnerIndex =
361
+ nextPlaybackStepState.playbackWinnerIndex;
478
362
  }
479
363
 
480
364
  /**
481
365
  * Posts a typed message from worker to host.
482
366
  *
367
+ * This is the narrowest possible transport helper: all message construction is
368
+ * done elsewhere so the README can point to one stable worker-to-host boundary.
369
+ *
483
370
  * @param workerMessage - Outbound worker response payload.
371
+ * @param transferList - Optional transferable buffers moved with the payload.
484
372
  * @returns Nothing.
485
373
  */
486
- function postWorkerMessage(workerMessage: WorkerResponseMessage): void {
487
- self.postMessage(workerMessage);
374
+ function postWorkerMessage(
375
+ workerMessage: WorkerResponseMessage,
376
+ transferList?: Transferable[],
377
+ ): void {
378
+ self.postMessage(workerMessage, transferList ?? []);
488
379
  }