@reicek/neataptic-ts 0.1.21 → 0.1.22

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 (223) hide show
  1. package/.github/agents/boundary-mapper.agent.md +29 -0
  2. package/.github/agents/docs-scout.agent.md +29 -0
  3. package/.github/agents/plan-scout.agent.md +29 -0
  4. package/.github/agents/solid-split.agent.md +138 -0
  5. package/.github/copilot-instructions.md +103 -0
  6. package/package.json +6 -3
  7. package/plans/ES2023 migration +13 -8
  8. package/plans/Evolution_Training_Interoperability_Contracts.md +1 -1
  9. package/plans/Interactive_Examples_and_Learning_Path.md +10 -2
  10. package/plans/Memory_Optimization.md +3 -3
  11. package/plans/README.md +63 -0
  12. package/plans/Roadmap.md +15 -3
  13. package/plans/asciiMaze_SOLID_split.done.md +130 -0
  14. package/plans/flappy_bird_SOLID_split.done.md +67 -0
  15. package/scripts/assets/theme.css +221 -34
  16. package/scripts/copy-examples.mjs +9 -5
  17. package/scripts/export-onnx.mjs +3 -3
  18. package/scripts/generate-bench-tables.mjs +10 -10
  19. package/scripts/generate-bench-tables.ts +10 -10
  20. package/scripts/generate-docs.ts +1415 -449
  21. package/scripts/render-docs-html.ts +15 -8
  22. package/src/README.md +101 -223
  23. package/src/architecture/README.md +57 -185
  24. package/src/architecture/layer/README.md +38 -38
  25. package/src/architecture/network/README.md +33 -31
  26. package/src/architecture/network/activate/README.md +77 -77
  27. package/src/architecture/network/connect/README.md +15 -13
  28. package/src/architecture/network/deterministic/README.md +7 -7
  29. package/src/architecture/network/evolve/README.md +44 -44
  30. package/src/architecture/network/gating/README.md +20 -20
  31. package/src/architecture/network/genetic/README.md +51 -51
  32. package/src/architecture/network/mutate/README.md +97 -97
  33. package/src/architecture/network/onnx/README.md +264 -264
  34. package/src/architecture/network/prune/README.md +39 -39
  35. package/src/architecture/network/remove/README.md +26 -26
  36. package/src/architecture/network/serialize/README.md +56 -56
  37. package/src/architecture/network/slab/README.md +61 -61
  38. package/src/architecture/network/standalone/README.md +24 -24
  39. package/src/architecture/network/stats/README.md +9 -9
  40. package/src/architecture/network/topology/README.md +46 -46
  41. package/src/architecture/network/training/README.md +21 -21
  42. package/src/methods/README.md +9 -87
  43. package/src/multithreading/README.md +8 -77
  44. package/src/multithreading/workers/README.md +2 -2
  45. package/src/multithreading/workers/browser/README.md +0 -6
  46. package/src/multithreading/workers/node/README.md +0 -3
  47. package/src/neat/README.md +562 -568
  48. package/src/utils/README.md +18 -18
  49. package/test/examples/asciiMaze/README.md +59 -59
  50. package/test/examples/asciiMaze/asciiMaze.e2e.test.ts +14 -9
  51. package/test/examples/asciiMaze/browser-entry/README.md +196 -0
  52. package/test/examples/asciiMaze/browser-entry/browser-entry.abort.services.ts +95 -0
  53. package/test/examples/asciiMaze/browser-entry/browser-entry.constants.ts +23 -0
  54. package/test/examples/asciiMaze/browser-entry/browser-entry.curriculum.services.ts +115 -0
  55. package/test/examples/asciiMaze/browser-entry/browser-entry.globals.services.ts +106 -0
  56. package/test/examples/asciiMaze/browser-entry/browser-entry.host.services.ts +157 -0
  57. package/test/examples/asciiMaze/browser-entry/browser-entry.services.ts +14 -0
  58. package/test/examples/asciiMaze/browser-entry/browser-entry.ts +129 -0
  59. package/test/examples/asciiMaze/browser-entry/browser-entry.types.ts +120 -0
  60. package/test/examples/asciiMaze/browser-entry/browser-entry.utils.ts +98 -0
  61. package/test/examples/asciiMaze/browser-entry.ts +10 -576
  62. package/test/examples/asciiMaze/dashboardManager/README.md +276 -0
  63. package/test/examples/asciiMaze/dashboardManager/archive/README.md +16 -0
  64. package/test/examples/asciiMaze/dashboardManager/archive/dashboardManager.archive.services.ts +267 -0
  65. package/test/examples/asciiMaze/dashboardManager/dashboardManager.constants.ts +35 -0
  66. package/test/examples/asciiMaze/dashboardManager/dashboardManager.services.ts +103 -0
  67. package/test/examples/asciiMaze/dashboardManager/dashboardManager.ts +181 -0
  68. package/test/examples/asciiMaze/dashboardManager/dashboardManager.types.ts +267 -0
  69. package/test/examples/asciiMaze/dashboardManager/dashboardManager.utils.ts +254 -0
  70. package/test/examples/asciiMaze/dashboardManager/live/README.md +14 -0
  71. package/test/examples/asciiMaze/dashboardManager/live/dashboardManager.live.services.ts +264 -0
  72. package/test/examples/asciiMaze/dashboardManager/telemetry/README.md +47 -0
  73. package/test/examples/asciiMaze/dashboardManager/telemetry/dashboardManager.telemetry.services.ts +513 -0
  74. package/test/examples/asciiMaze/dashboardManager.ts +13 -2335
  75. package/test/examples/asciiMaze/evolutionEngine/README.md +1058 -0
  76. package/test/examples/asciiMaze/evolutionEngine/curriculumPhase.ts +90 -0
  77. package/test/examples/asciiMaze/evolutionEngine/engineState.constants.ts +36 -0
  78. package/test/examples/asciiMaze/evolutionEngine/engineState.ts +58 -513
  79. package/test/examples/asciiMaze/evolutionEngine/engineState.types.ts +212 -0
  80. package/test/examples/asciiMaze/evolutionEngine/engineState.utils.ts +301 -0
  81. package/test/examples/asciiMaze/evolutionEngine/evolutionEngine.types.ts +445 -0
  82. package/test/examples/asciiMaze/evolutionEngine/evolutionLoop.ts +81 -50
  83. package/test/examples/asciiMaze/evolutionEngine/optionsAndSetup.ts +2 -4
  84. package/test/examples/asciiMaze/evolutionEngine/populationDynamics.ts +17 -33
  85. package/test/examples/asciiMaze/evolutionEngine/populationPruning.ts +1 -1
  86. package/test/examples/asciiMaze/evolutionEngine/rngAndTiming.ts +1 -2
  87. package/test/examples/asciiMaze/evolutionEngine/sampling.ts +1 -1
  88. package/test/examples/asciiMaze/evolutionEngine/scratchPools.ts +2 -5
  89. package/test/examples/asciiMaze/evolutionEngine/setupHelpers.ts +30 -37
  90. package/test/examples/asciiMaze/evolutionEngine/telemetryMetrics.ts +16 -58
  91. package/test/examples/asciiMaze/evolutionEngine/trainingWarmStart.ts +2 -2
  92. package/test/examples/asciiMaze/evolutionEngine.ts +55 -55
  93. package/test/examples/asciiMaze/fitness.ts +2 -2
  94. package/test/examples/asciiMaze/fitness.types.ts +65 -0
  95. package/test/examples/asciiMaze/interfaces.ts +64 -1352
  96. package/test/examples/asciiMaze/mazeMovement/README.md +356 -0
  97. package/test/examples/asciiMaze/mazeMovement/finalization/README.md +49 -0
  98. package/test/examples/asciiMaze/mazeMovement/finalization/mazeMovement.finalization.ts +138 -0
  99. package/test/examples/asciiMaze/mazeMovement/mazeMovement.constants.ts +101 -0
  100. package/test/examples/asciiMaze/mazeMovement/mazeMovement.services.ts +230 -0
  101. package/test/examples/asciiMaze/mazeMovement/mazeMovement.ts +299 -0
  102. package/test/examples/asciiMaze/mazeMovement/mazeMovement.types.ts +185 -0
  103. package/test/examples/asciiMaze/mazeMovement/mazeMovement.utils.ts +153 -0
  104. package/test/examples/asciiMaze/mazeMovement/policy/README.md +91 -0
  105. package/test/examples/asciiMaze/mazeMovement/policy/mazeMovement.policy.ts +467 -0
  106. package/test/examples/asciiMaze/mazeMovement/runtime/README.md +95 -0
  107. package/test/examples/asciiMaze/mazeMovement/runtime/mazeMovement.runtime.ts +354 -0
  108. package/test/examples/asciiMaze/mazeMovement/shaping/README.md +124 -0
  109. package/test/examples/asciiMaze/mazeMovement/shaping/mazeMovement.shaping.ts +459 -0
  110. package/test/examples/asciiMaze/mazeMovement.ts +12 -2978
  111. package/test/examples/flappy_bird/Trace-20260309T191949.json +24124 -0
  112. package/test/examples/flappy_bird/browser-entry/README.md +1129 -0
  113. package/test/examples/flappy_bird/browser-entry/browser-entry.host.utils.ts +4 -324
  114. package/test/examples/flappy_bird/browser-entry/browser-entry.network-view.utils.ts +6 -399
  115. package/test/examples/flappy_bird/browser-entry/browser-entry.playback.utils.ts +1 -717
  116. package/test/examples/flappy_bird/browser-entry/browser-entry.spawn.utils.ts +11 -31
  117. package/test/examples/flappy_bird/browser-entry/browser-entry.visualization.utils.ts +15 -893
  118. package/test/examples/flappy_bird/browser-entry/host/README.md +307 -0
  119. package/test/examples/flappy_bird/browser-entry/host/host.resize.service.ts +1 -295
  120. package/test/examples/flappy_bird/browser-entry/host/host.ts +562 -6
  121. package/test/examples/flappy_bird/browser-entry/host/resize/README.md +274 -0
  122. package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.constants.ts +31 -0
  123. package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.services.ts +360 -0
  124. package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.ts +117 -0
  125. package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.types.ts +63 -0
  126. package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.utils.ts +250 -0
  127. package/test/examples/flappy_bird/browser-entry/network-view/README.md +399 -0
  128. package/test/examples/flappy_bird/browser-entry/network-view/network-view.topology.utils.ts +255 -0
  129. package/test/examples/flappy_bird/browser-entry/network-view/network-view.ts +802 -7
  130. package/test/examples/flappy_bird/browser-entry/playback/README.md +684 -0
  131. package/test/examples/flappy_bird/browser-entry/playback/background/README.md +277 -0
  132. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/README.md +770 -0
  133. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.cache.services.ts +178 -0
  134. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.constants.ts +107 -0
  135. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.geometry.utils.ts +518 -0
  136. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.math.utils.ts +117 -0
  137. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.pulse.utils.ts +233 -0
  138. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.services.ts +211 -0
  139. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.ts +48 -0
  140. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.types.ts +212 -0
  141. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.utils.ts +81 -0
  142. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.cache.services.ts +96 -0
  143. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.constants.ts +62 -0
  144. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.services.ts +244 -0
  145. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.ts +53 -0
  146. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.types.ts +68 -0
  147. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.utils.ts +100 -0
  148. package/test/examples/flappy_bird/browser-entry/playback/frame-render/README.md +310 -0
  149. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.service.ts +92 -0
  150. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.services.ts +272 -0
  151. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.types.ts +39 -0
  152. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.utils.ts +493 -0
  153. package/test/examples/flappy_bird/browser-entry/playback/playback.constants.ts +1 -1
  154. package/test/examples/flappy_bird/browser-entry/playback/playback.frame-render.service.ts +4 -0
  155. package/test/examples/flappy_bird/browser-entry/playback/playback.snapshot.utils.ts +44 -0
  156. package/test/examples/flappy_bird/browser-entry/playback/playback.starfield.service.ts +39 -122
  157. package/test/examples/flappy_bird/browser-entry/playback/playback.starfield.services.ts +272 -0
  158. package/test/examples/flappy_bird/browser-entry/playback/playback.starfield.types.ts +62 -0
  159. package/test/examples/flappy_bird/browser-entry/playback/playback.starfield.utils.ts +11 -4
  160. package/test/examples/flappy_bird/browser-entry/playback/playback.ts +409 -8
  161. package/test/examples/flappy_bird/browser-entry/playback/playback.types.ts +4 -12
  162. package/test/examples/flappy_bird/browser-entry/runtime/README.md +235 -0
  163. package/test/examples/flappy_bird/browser-entry/runtime/runtime.evolution-launch.service.ts +45 -0
  164. package/test/examples/flappy_bird/browser-entry/runtime/runtime.lifecycle.service.ts +81 -0
  165. package/test/examples/flappy_bird/browser-entry/runtime/runtime.startup.service.ts +74 -0
  166. package/test/examples/flappy_bird/browser-entry/runtime/runtime.ts +31 -121
  167. package/test/examples/flappy_bird/browser-entry/runtime/runtime.types.ts +36 -0
  168. package/test/examples/flappy_bird/browser-entry/visualization/README.md +557 -0
  169. package/test/examples/flappy_bird/browser-entry/visualization/visualization.constants.ts +110 -0
  170. package/test/examples/flappy_bird/browser-entry/visualization/visualization.draw.service.ts +957 -19
  171. package/test/examples/flappy_bird/browser-entry/visualization/visualization.legend.utils.ts +138 -3
  172. package/test/examples/flappy_bird/browser-entry/visualization/visualization.topology.utils.ts +3 -27
  173. package/test/examples/flappy_bird/browser-entry/visualization/visualization.ts +1 -23
  174. package/test/examples/flappy_bird/browser-entry/worker-channel/README.md +156 -0
  175. package/test/examples/flappy_bird/constants/README.md +1179 -0
  176. package/test/examples/flappy_bird/constants/constants.network-view.ts +24 -0
  177. package/test/examples/flappy_bird/constants/constants.palette.ts +7 -0
  178. package/test/examples/flappy_bird/constants/constants.starfield.ts +78 -3
  179. package/test/examples/flappy_bird/environment/README.md +143 -0
  180. package/test/examples/flappy_bird/environment/environment.observation.utils.ts +1 -19
  181. package/test/examples/flappy_bird/environment/environment.step.service.ts +3 -66
  182. package/test/examples/flappy_bird/evaluation/README.md +130 -0
  183. package/test/examples/flappy_bird/evaluation/evaluation.fitness.utils.ts +1 -1
  184. package/test/examples/flappy_bird/evaluation/evaluation.rollout.service.ts +5 -375
  185. package/test/examples/flappy_bird/evaluation/rollout/README.md +291 -0
  186. package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.constants.ts +30 -0
  187. package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.service.ts +58 -0
  188. package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.services.ts +310 -0
  189. package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.types.ts +56 -0
  190. package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.utils.ts +368 -0
  191. package/test/examples/flappy_bird/flappy-evolution-worker/README.md +618 -0
  192. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.playback.service.ts +7 -7
  193. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.simulation.frame.service.ts +364 -0
  194. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.simulation.types.ts +14 -0
  195. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.simulation.utils.ts +4 -201
  196. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.ts +184 -345
  197. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.warm-start.service.ts +291 -0
  198. package/test/examples/flappy_bird/flappy.simulation.shared.utils.ts +5 -0
  199. package/test/examples/flappy_bird/simulation-shared/README.md +417 -0
  200. package/test/examples/flappy_bird/simulation-shared/observation/README.md +183 -0
  201. package/test/examples/flappy_bird/simulation-shared/observation/observation.features.utils.ts +301 -0
  202. package/test/examples/flappy_bird/simulation-shared/observation/observation.ts +9 -0
  203. package/test/examples/flappy_bird/simulation-shared/observation/observation.vector.utils.ts +59 -0
  204. package/test/examples/flappy_bird/simulation-shared/simulation-shared.observation.utils.ts +5 -403
  205. package/test/examples/flappy_bird/simulation-shared/simulation-shared.spawn.utils.ts +20 -6
  206. package/test/examples/flappy_bird/{evaluation/evaluation.statistics.utils.ts → simulation-shared/simulation-shared.statistics.utils.ts} +23 -8
  207. package/test/examples/flappy_bird/trainer/README.md +563 -0
  208. package/test/examples/flappy_bird/trainer/evaluation/README.md +199 -0
  209. package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.constants.ts +9 -0
  210. package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.services.ts +73 -0
  211. package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.ts +165 -0
  212. package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.types.ts +25 -0
  213. package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.utils.ts +161 -0
  214. package/test/examples/flappy_bird/trainer/trainer.evaluation.service.ts +13 -0
  215. package/test/examples/flappy_bird/trainer/trainer.report.service.services.ts +181 -0
  216. package/test/examples/flappy_bird/trainer/trainer.report.service.ts +126 -0
  217. package/test/examples/flappy_bird/trainer/trainer.selection.utils.ts +89 -0
  218. package/test/examples/flappy_bird/trainer/trainer.ts +11 -553
  219. package/test/examples/flappy_bird/browser-entry/browser-entry.utils.ts +0 -12
  220. package/test/examples/flappy_bird/environment/environment.ts +0 -7
  221. package/test/examples/flappy_bird/evaluation/evaluation.ts +0 -7
  222. package/test/examples/flappy_bird/simulation-shared/simulation-shared.ts +0 -15
  223. package/test/examples/flappy_bird/trainer/trainer.statistics.utils.ts +0 -78
@@ -0,0 +1,445 @@
1
+ import type Network from '../../../../src/architecture/network';
2
+ import type { FitnessEvaluatorFn } from '../fitness.types';
3
+ import type {
4
+ IDashboardManager,
5
+ IMazeRunResult,
6
+ INetwork,
7
+ } from '../interfaces';
8
+
9
+ /** Maze configuration used by the ASCII Maze evolution helpers. */
10
+ export interface IMazeConfig {
11
+ /** The maze layout, each element is a row string. Rows should be equal length. */
12
+ maze: string[];
13
+ }
14
+
15
+ /** Agent simulation configuration. */
16
+ export interface IAgentSimulationConfig {
17
+ /** Maximum number of steps the agent can take in a single episode. */
18
+ maxSteps: number;
19
+ }
20
+
21
+ /** Configuration options for the evolutionary algorithm used in the ASCII Maze demos. */
22
+ export interface IEvolutionAlgorithmConfig {
23
+ allowRecurrent?: boolean;
24
+ popSize?: number;
25
+ maxStagnantGenerations?: number;
26
+ minProgressToPass?: number;
27
+ maxGenerations?: number;
28
+ stopOnlyOnSolve?: boolean;
29
+ autoPauseOnSolve?: boolean;
30
+ randomSeed?: number;
31
+ initialPopulation?: INetwork[];
32
+ initialBestNetwork?: INetwork | Network;
33
+ lamarckianIterations?: number;
34
+ lamarckianSampleSize?: number;
35
+ plateauGenerations?: number;
36
+ plateauImprovementThreshold?: number;
37
+ simplifyDuration?: number;
38
+ simplifyPruneFraction?: number;
39
+ simplifyStrategy?: 'weakWeight' | 'weakRecurrentPreferred';
40
+ persistEvery?: number;
41
+ persistDir?: string;
42
+ persistTopK?: number;
43
+ dynamicPopEnabled?: boolean;
44
+ dynamicPopMax?: number;
45
+ dynamicPopExpandInterval?: number;
46
+ dynamicPopExpandFactor?: number;
47
+ dynamicPopPlateauSlack?: number;
48
+ deterministic?: boolean;
49
+ memoryCompactionInterval?: number;
50
+ telemetryReduceStats?: boolean;
51
+ telemetryMinimal?: boolean;
52
+ disableBaldwinianRefinement?: boolean;
53
+ }
54
+
55
+ /** Canonical stop reasons reported by the engine to host adapters. */
56
+ export type EvolutionStopReason =
57
+ | 'solved'
58
+ | 'stagnation'
59
+ | 'maxGenerations'
60
+ | 'cancelled'
61
+ | 'aborted';
62
+
63
+ /**
64
+ * Host-facing stop event emitted by the engine when a run finishes for a concrete reason.
65
+ *
66
+ * @remarks
67
+ * The engine uses this narrow payload so browser or terminal hosts can react to
68
+ * solve, stop, and pause-adjacent lifecycle events without the engine depending
69
+ * on browser globals or DOM APIs.
70
+ */
71
+ export interface EvolutionHostStopEvent {
72
+ /** Canonical reason that caused the run to stop. */
73
+ reason: EvolutionStopReason;
74
+ /** Maze layout associated with the stopping run. */
75
+ maze: string[];
76
+ /** Number of generations completed before the stop reason fired. */
77
+ completedGenerations: number;
78
+ /** Latest best result available at stop time, when one exists. */
79
+ result?: IMazeRunResult;
80
+ /** Convenience progress mirror from the latest result. */
81
+ progress?: number;
82
+ /** Whether the host should cooperatively enter a paused state. */
83
+ requestHostPause?: boolean;
84
+ }
85
+
86
+ /**
87
+ * Narrow host adapter used by the engine for pause polling and stop notifications.
88
+ *
89
+ * @remarks
90
+ * Browser-entry and other host boundaries should implement this contract when
91
+ * they need host-specific pause control or solve/stop side effects.
92
+ *
93
+ * @example
94
+ * ```ts
95
+ * const hostAdapter: EvolutionHostAdapter = {
96
+ * isPauseRequested: () => window.asciiMazePaused === true,
97
+ * handleStop: ({ reason }) => console.log('maze run stopped because', reason),
98
+ * };
99
+ * ```
100
+ */
101
+ export interface EvolutionHostAdapter {
102
+ /** Return true while the host wants cooperative frame flushing to stay paused. */
103
+ isPauseRequested?: () => boolean;
104
+ /** React to a solved, aborted, or otherwise stopped run. */
105
+ handleStop?: (event: EvolutionHostStopEvent) => void | Promise<void>;
106
+ }
107
+
108
+ /** Reporting configuration used to control logging, dashboard updates and UI pacing. */
109
+ export interface IReportingConfig {
110
+ /** How frequently, in generations, to emit logs or telemetry updates. */
111
+ logEvery?: number;
112
+ /** Dashboard manager instance responsible for receiving per-generation updates. */
113
+ dashboardManager: IDashboardManager;
114
+ /** Optional human-readable label identifying this run. */
115
+ label?: string;
116
+ /** When true, yield to the host after each generation. */
117
+ paceEveryGeneration?: boolean;
118
+ /** Optional host adapter that owns pause polling and stop side effects. */
119
+ hostAdapter?: EvolutionHostAdapter;
120
+ }
121
+
122
+ /** Main options for running a single maze-evolution experiment. */
123
+ export interface IRunMazeEvolutionOptions {
124
+ mazeConfig: IMazeConfig;
125
+ agentSimConfig: IAgentSimulationConfig;
126
+ evolutionAlgorithmConfig: IEvolutionAlgorithmConfig;
127
+ reportingConfig: IReportingConfig;
128
+ fitnessEvaluator?: FitnessEvaluatorFn;
129
+ cancellation?: { isCancelled: () => boolean };
130
+ signal?: AbortSignal;
131
+ }
132
+
133
+ /**
134
+ * Stable result returned by `EvolutionEngine.runMazeEvolution()`.
135
+ *
136
+ * @remarks
137
+ * Browser curriculum code, terminal demos, and tooling should depend on this
138
+ * shared engine-owned contract instead of recreating local runtime result
139
+ * adapters just to read winner carry-over or solve progress.
140
+ */
141
+ export interface MazeEvolutionRunResult {
142
+ /** Highest-scoring evolved network available at the end of the run. */
143
+ bestNetwork: NetworkInstance | null;
144
+ /** Best simulation result captured during the run, when one exists. */
145
+ bestResult: IMazeRunResult | undefined;
146
+ /** Final NEAT instance after all completed generations. */
147
+ neat: NeatInstance;
148
+ /** Canonical or compatibility exit reason describing why the run ended. */
149
+ exitReason: string;
150
+ }
151
+
152
+ /**
153
+ * Shared curriculum-facing summary derived from one completed evolution phase.
154
+ *
155
+ * @remarks
156
+ * Browser curriculum code and curriculum-style tests should depend on this
157
+ * engine-owned contract so host boundaries do not recreate local refinement or
158
+ * result-interpretation shims when carrying winners across phases.
159
+ */
160
+ export interface MazeEvolutionCurriculumPhaseOutcome {
161
+ /** Original engine result for callers that still need the underlying run details. */
162
+ result: MazeEvolutionRunResult;
163
+ /** Convenience mirror of the best-run progress percentage for logging or gating. */
164
+ progress: number | undefined;
165
+ /** Whether the phase met the caller's curriculum advancement threshold. */
166
+ solved: boolean;
167
+ /** Refined winner to seed into the next curriculum phase, when one is available. */
168
+ nextBestNetwork: INetwork | undefined;
169
+ }
170
+
171
+ /** Type for Neat class instance from the neataptic library. */
172
+ export type NeatInstance = import('../../../../src/neat').default;
173
+
174
+ /** Type for Network class instance from the neataptic library. */
175
+ export type NetworkInstance =
176
+ import('../../../../src/architecture/network').default;
177
+
178
+ /**
179
+ * Network instance annotated with telemetry fields during a generation.
180
+ *
181
+ * @remarks
182
+ * This keeps telemetry post-processing and dashboard reporting aligned on one
183
+ * engine-owned contract instead of file-local runtime casts.
184
+ */
185
+ export interface TrackedNetworkInstance extends NetworkInstance {
186
+ _lastStepOutputs?: Float32Array[];
187
+ _saturationFraction?: number;
188
+ _actionEntropy?: number;
189
+ }
190
+
191
+ /**
192
+ * Loose genome shape shared by engine telemetry and population-dynamics helpers.
193
+ *
194
+ * @remarks
195
+ * The NEAT runtime exposes additional mutable fields during evolution, so the
196
+ * engine centralizes those optional members here rather than duplicating local
197
+ * runtime helper interfaces across multiple files.
198
+ */
199
+ export interface EvolutionGenomeLike {
200
+ nodes?: NetworkNode[];
201
+ connections?: NetworkConnection[];
202
+ score?: number;
203
+ species?: number | null;
204
+ clone?: () => EvolutionGenomeLike;
205
+ mutate?: (method: unknown) => void;
206
+ _lastStepOutputs?: unknown[];
207
+ _id?: number;
208
+ _parentId?: number;
209
+ [key: string]: unknown;
210
+ }
211
+
212
+ /** NEAT runtime shape needed by telemetry helpers that inspect the population. */
213
+ export interface TelemetryNeatLike {
214
+ population?: EvolutionGenomeLike[];
215
+ getTelemetry?: () => unknown;
216
+ [key: string]: unknown;
217
+ }
218
+
219
+ /** Mutation-operation surface read from the NEAT driver at runtime. */
220
+ export interface MutationOperationLike {
221
+ length?: number;
222
+ [key: string]: unknown;
223
+ }
224
+
225
+ /** Static host used to read optional species-history state from the engine facade. */
226
+ export interface SpeciesHistoryHost {
227
+ _speciesHistory?: unknown[];
228
+ [key: string]: unknown;
229
+ }
230
+
231
+ /** Encoded maze representation with cell values. */
232
+ export interface EncodedMaze {
233
+ width: number;
234
+ height: number;
235
+ cells: number[];
236
+ maze: string[];
237
+ }
238
+
239
+ /** 2D position in maze coordinates. */
240
+ export interface Position {
241
+ x: number;
242
+ y: number;
243
+ }
244
+
245
+ /** Distance map for maze navigation. */
246
+ export interface DistanceMap {
247
+ width: number;
248
+ height: number;
249
+ distances: number[];
250
+ }
251
+
252
+ /** Options object passed to evolution functions. */
253
+ export interface EvolutionOptions {
254
+ cancellation?: {
255
+ isCancelled?: () => boolean;
256
+ isCancellationRequested?: () => boolean;
257
+ reason?: string;
258
+ };
259
+ signal?: AbortSignal;
260
+ maxGenerations?: number;
261
+ maxStagnantGenerations?: number;
262
+ minProgressToPass?: number;
263
+ logEvery?: number;
264
+ enableProfiling?: boolean;
265
+ persistDir?: string;
266
+ persistTopK?: number;
267
+ persistEvery?: number;
268
+ flushToFrame?: () => Promise<void>;
269
+ reportingConfig?: {
270
+ dashboardManager?: IDashboardManager;
271
+ logEvery?: number;
272
+ paceEveryGeneration?: boolean;
273
+ hostAdapter?: EvolutionHostAdapter;
274
+ [key: string]: unknown;
275
+ };
276
+ mazeConfig: {
277
+ maze: string[];
278
+ [key: string]: unknown;
279
+ };
280
+ agentSimConfig?: {
281
+ maxSteps: number;
282
+ [key: string]: unknown;
283
+ };
284
+ lamarckianIterations?: number;
285
+ lamarckianSampleSize?: number;
286
+ dynamicPopEnabled?: boolean;
287
+ dynamicPopMax?: number;
288
+ plateauGenerations?: number;
289
+ dynamicPopExpandInterval?: number;
290
+ dynamicPopExpandFactor?: number;
291
+ dynamicPopPlateauSlack?: number;
292
+ plateauImprovementThreshold?: number;
293
+ simplifyDuration?: number;
294
+ simplifyStrategy?: 'weakWeight' | 'weakRecurrentPreferred';
295
+ simplifyPruneFraction?: number;
296
+ memoryCompactionInterval?: number;
297
+ autoPauseOnSolve?: boolean;
298
+ stopOnlyOnSolve?: boolean;
299
+ initialBestNetwork?: unknown;
300
+ [key: string]: unknown;
301
+ }
302
+
303
+ /** Helper functions object passed to evolution loop orchestration. */
304
+ export interface EvolutionHelpers {
305
+ write: (msg: string) => void;
306
+ isProfilingDetailsEnabled: (state: unknown) => boolean;
307
+ getProfilingAccumulators: (state: unknown) => ProfilingAccumulators;
308
+ }
309
+
310
+ /** Profiling accumulator structure. */
311
+ export interface ProfilingAccumulators {
312
+ totalEvolveMs?: number;
313
+ totalLamarckMs?: number;
314
+ totalSimMs?: number;
315
+ mutate?: number;
316
+ crossover?: number;
317
+ select?: number;
318
+ snapshot?: number;
319
+ telemetry?: number;
320
+ simplify?: number;
321
+ prune?: number;
322
+ [key: string]: number | undefined;
323
+ }
324
+
325
+ /** Node.js fs module type for file operations. */
326
+ export interface FileSystem {
327
+ writeFileSync: (path: string, data: string) => void;
328
+ readFileSync: (path: string, encoding: string) => string;
329
+ existsSync: (path: string) => boolean;
330
+ mkdirSync: (path: string, options?: { recursive?: boolean }) => void;
331
+ }
332
+
333
+ /** Node.js path module type. */
334
+ export interface PathModule {
335
+ join: (...paths: string[]) => string;
336
+ resolve: (...paths: string[]) => string;
337
+ dirname: (path: string) => string;
338
+ }
339
+
340
+ /** Loop helpers returned by prepareLoopHelpers. */
341
+ export interface LoopHelpers {
342
+ flushToFrame: () => Promise<void>;
343
+ fs: unknown;
344
+ path: unknown;
345
+ safeWrite: (msg: string) => void;
346
+ }
347
+
348
+ /** Scratch bundle containing reusable buffers. */
349
+ export interface ScratchBundle {
350
+ samplePool?: unknown[];
351
+ profilingScratch?: Float64Array;
352
+ exps?: Float64Array;
353
+ [key: string]: unknown;
354
+ }
355
+
356
+ /** Snapshot entry for persistence. */
357
+ export interface SnapshotEntry {
358
+ idx?: number;
359
+ json?: string;
360
+ score?: number;
361
+ nodes?: number;
362
+ connections?: number;
363
+ [key: string]: unknown;
364
+ }
365
+
366
+ /** Training constants used by Lamarckian warm-start and refinement helpers. */
367
+ export interface TrainingConstants {
368
+ DEFAULT_TRAIN_ERROR: number;
369
+ DEFAULT_TRAIN_RATE: number;
370
+ DEFAULT_TRAIN_MOMENTUM: number;
371
+ DEFAULT_TRAIN_BATCH_SMALL: number;
372
+ DEFAULT_STD_SMALL: number;
373
+ DEFAULT_STD_ADJUST_MULT: number;
374
+ }
375
+
376
+ /** Helper functions for evolution. */
377
+ export interface EvolutionLoopHelpers {
378
+ getNodeIndicesByType: (nodes: NetworkNode[], type: string) => number;
379
+ collectHiddenToOutputConns: (
380
+ hiddenNode: NetworkNode,
381
+ nodes: NetworkNode[],
382
+ outputCount: number,
383
+ ) => NetworkConnection[];
384
+ }
385
+
386
+ /** Network node representation used by engine-side runtime adaptation helpers. */
387
+ export interface NetworkNode {
388
+ type?: string;
389
+ bias?: number;
390
+ squash?:
391
+ | string
392
+ | { name?: string }
393
+ | ((x: number, derivate?: boolean) => number);
394
+ connections?: {
395
+ in?: NetworkConnection[];
396
+ out?: NetworkConnection[];
397
+ };
398
+ [key: string]: unknown;
399
+ }
400
+
401
+ /** Network connection representation used by engine-side runtime adaptation helpers. */
402
+ export interface NetworkConnection {
403
+ from?: NetworkNode;
404
+ to?: NetworkNode;
405
+ weight?: number;
406
+ gain?: number;
407
+ enabled?: boolean;
408
+ [key: string]: unknown;
409
+ }
410
+
411
+ /** Encoded maze for simulation. */
412
+ export interface EncodedMazeData {
413
+ width: number;
414
+ height: number;
415
+ cells: number[];
416
+ maze?: string[];
417
+ [key: string]: unknown;
418
+ }
419
+
420
+ /** Position in maze. */
421
+ export interface MazePosition {
422
+ x: number;
423
+ y: number;
424
+ }
425
+
426
+ /** Distance map for pathfinding. */
427
+ export interface MazeDistanceMap {
428
+ width: number;
429
+ height: number;
430
+ distances: number[];
431
+ }
432
+
433
+ /** Ring state for logits tracking. */
434
+ export interface LogitsRingState {
435
+ logitsRingCap: number;
436
+ logitsRingShared: boolean;
437
+ scratchLogitsRingW: number;
438
+ }
439
+
440
+ /** Simulation result returned by generation evaluation helpers. */
441
+ export interface SimulationResult {
442
+ generationResult: IMazeRunResult;
443
+ simTime: number;
444
+ updatedRingState: LogitsRingState;
445
+ }
@@ -22,11 +22,6 @@
22
22
  * @module evolutionEngine/evolutionLoop
23
23
  */
24
24
 
25
- /** Extended Window interface for maze-specific global state */
26
- interface MazeWindow extends Window {
27
- asciiMazePaused?: boolean;
28
- }
29
-
30
25
  /** Mutable result object with exitReason field */
31
26
  interface MutableMazeResult extends IMazeRunResult {
32
27
  exitReason?: string;
@@ -66,13 +61,6 @@ interface EvolutionLoopResult {
66
61
  };
67
62
  }
68
63
 
69
- /** Network with dynamic runtime properties */
70
- interface RuntimeNetworkInstance extends NetworkInstance {
71
- _lastStepOutputs?: Float32Array[];
72
- _saturationFraction?: number;
73
- _actionEntropy?: number;
74
- }
75
-
76
64
  /** Simulation result with step outputs */
77
65
  interface SimResultWithOutputs extends IMazeRunResult {
78
66
  stepOutputs?: number[][];
@@ -113,20 +101,25 @@ import {
113
101
  } from './rngAndTiming';
114
102
  import type { EngineState } from './engineState';
115
103
  import type {
116
- EvolutionOptions,
117
- IMazeRunResult,
118
- INetwork,
104
+ EvolutionHostAdapter,
105
+ EvolutionStopReason,
106
+ LoopHelpers,
107
+ NetworkConnection,
119
108
  NetworkInstance,
109
+ NetworkNode,
120
110
  NeatInstance,
121
- IDashboardManager,
122
- LoopHelpers,
111
+ ProfilingAccumulators,
123
112
  ScratchBundle,
113
+ SimulationResult,
124
114
  SnapshotEntry,
125
- ProfilingAccumulators,
115
+ TrackedNetworkInstance,
126
116
  TrainingConstants,
127
- NetworkNode,
128
- NetworkConnection,
129
- SimulationResult,
117
+ EvolutionOptions,
118
+ } from './evolutionEngine.types';
119
+ import type {
120
+ IDashboardManager,
121
+ IMazeRunResult,
122
+ INetwork,
130
123
  } from '../interfaces';
131
124
 
132
125
  /**
@@ -235,7 +228,7 @@ export const prepareLoopHelpers = (
235
228
  scratchBundle: ScratchBundle,
236
229
  ): LoopHelpers => {
237
230
  // Step 1: Create the lightweight host-yield helper first.
238
- const flushToFrame = makeFlushToFrame();
231
+ const flushToFrame = makeFlushToFrame(opts?.reportingConfig?.hostAdapter);
239
232
 
240
233
  // Step 2: Initialise persistence handles (best-effort; may be null in browsers).
241
234
  const { fs, path } = initPersistence(opts?.persistDir);
@@ -284,8 +277,7 @@ export const prepareLoopHelpers = (
284
277
  * Side Effects (Best-Effort):
285
278
  * - Updates dashboard manager when stopping
286
279
  * - Awaits flushToFrame to yield to host
287
- * - Sets `window.asciiMazePaused` flag on solve (if autoPauseOnSolve)
288
- * - Dispatches 'asciiMazeSolved' CustomEvent on solve
280
+ * - Reports stop events through the optional host adapter
289
281
  * - Annotates `bestResult.exitReason` with canonical reason string
290
282
  *
291
283
  * Parameters:
@@ -296,8 +288,9 @@ export const prepareLoopHelpers = (
296
288
  * @param neat - NEAT driver instance (passed to dashboard update)
297
289
  * @param dashboardManager - Optional manager exposing `update(maze, result, network, gen, neat)`
298
290
  * @param flushToFrame - Async function to yield to host renderer (e.g. requestAnimationFrame)
291
+ * @param hostAdapter - Optional host adapter that owns host-side stop behavior
299
292
  * @param minProgressToPass - Numeric threshold to consider a run 'solved'
300
- * @param autoPauseOnSolve - When truthy set cooperative pause flag and emit event on solve
293
+ * @param autoPauseOnSolve - When truthy request host-side pause handling on solve
301
294
  * @param stopOnlyOnSolve - When true ignore stagnation/maxGenerations as stop reasons
302
295
  * @param stagnantGenerations - Current count of stagnant generations observed
303
296
  * @param maxStagnantGenerations - Max allowed stagnant generations before stopping
@@ -324,6 +317,7 @@ export const checkStopConditions = async (
324
317
  neat: NeatInstance,
325
318
  dashboardManager: IDashboardManager | undefined,
326
319
  flushToFrame: () => Promise<void>,
320
+ hostAdapter: EvolutionHostAdapter | undefined,
327
321
  minProgressToPass: number,
328
322
  autoPauseOnSolve: boolean,
329
323
  stopOnlyOnSolve: boolean,
@@ -356,29 +350,14 @@ export const checkStopConditions = async (
356
350
  // Swallow frame flush errors
357
351
  }
358
352
 
359
- // Optionally set a cooperative pause and emit a small event for UIs to react to.
360
- if (autoPauseOnSolve) {
361
- try {
362
- if (typeof window !== 'undefined') {
363
- (window as MazeWindow).asciiMazePaused = true;
364
- try {
365
- window.dispatchEvent(
366
- new CustomEvent('asciiMazeSolved', {
367
- detail: {
368
- maze,
369
- generations: completedGenerations,
370
- progress: bestResult?.progress,
371
- },
372
- }),
373
- );
374
- } catch {
375
- // Swallow event dispatch errors
376
- }
377
- }
378
- } catch {
379
- // Swallow window access errors
380
- }
381
- }
353
+ await notifyHostAboutStop(hostAdapter, {
354
+ reason: 'solved',
355
+ maze,
356
+ completedGenerations,
357
+ result: bestResult,
358
+ progress: bestResult?.progress,
359
+ requestHostPause: autoPauseOnSolve,
360
+ });
382
361
 
383
362
  if (hasBest) (bestResult as MutableMazeResult).exitReason = 'solved';
384
363
  return 'solved';
@@ -406,6 +385,14 @@ export const checkStopConditions = async (
406
385
  } catch {
407
386
  // Swallow frame flush errors
408
387
  }
388
+ await notifyHostAboutStop(hostAdapter, {
389
+ reason: 'stagnation',
390
+ maze,
391
+ completedGenerations,
392
+ result: bestResult,
393
+ progress: bestResult?.progress,
394
+ requestHostPause: false,
395
+ });
409
396
  if (hasBest) (bestResult as MutableMazeResult).exitReason = 'stagnation';
410
397
  return 'stagnation';
411
398
  }
@@ -416,6 +403,14 @@ export const checkStopConditions = async (
416
403
  isFinite(maxGenerations) &&
417
404
  completedGenerations >= maxGenerations
418
405
  ) {
406
+ await notifyHostAboutStop(hostAdapter, {
407
+ reason: 'maxGenerations',
408
+ maze,
409
+ completedGenerations,
410
+ result: bestResult,
411
+ progress: bestResult?.progress,
412
+ requestHostPause: false,
413
+ });
419
414
  if (hasBest)
420
415
  (bestResult as MutableMazeResult).exitReason = 'maxGenerations';
421
416
  return 'maxGenerations';
@@ -425,6 +420,31 @@ export const checkStopConditions = async (
425
420
  return undefined;
426
421
  };
427
422
 
423
+ /**
424
+ * Report a concrete stop event through the optional host adapter.
425
+ *
426
+ * @param hostAdapter - Optional host adapter supplied by the embedding host.
427
+ * @param event - Canonical stop event payload.
428
+ * @returns Nothing.
429
+ */
430
+ const notifyHostAboutStop = async (
431
+ hostAdapter: EvolutionHostAdapter | undefined,
432
+ event: {
433
+ reason: EvolutionStopReason;
434
+ maze: string[];
435
+ completedGenerations: number;
436
+ result?: IMazeRunResult;
437
+ progress?: number;
438
+ requestHostPause?: boolean;
439
+ },
440
+ ): Promise<void> => {
441
+ try {
442
+ await hostAdapter?.handleStop?.(event);
443
+ } catch {
444
+ // Host-side effects must never break the engine loop.
445
+ }
446
+ };
447
+
428
448
  /**
429
449
  * Persist a population snapshot to disk at the configured interval.
430
450
  *
@@ -1196,7 +1216,7 @@ export const simulateAndPostprocess = (
1196
1216
  );
1197
1217
 
1198
1218
  // Best-effort: attach legacy buffer refs and compact telemetry onto the genome.
1199
- const runtimeFittest = fittest as RuntimeNetworkInstance;
1219
+ const runtimeFittest = fittest as TrackedNetworkInstance;
1200
1220
  try {
1201
1221
  if (!runtimeFittest._lastStepOutputs) {
1202
1222
  runtimeFittest._lastStepOutputs = scratchLogitsRing;
@@ -1475,7 +1495,17 @@ export const runEvolutionLoop = async (
1475
1495
  while (true) {
1476
1496
  // Step 1: cooperative cancellation check (non-allocating, safe)
1477
1497
  const cancelReason = checkCancellation(opts, bestRunResult);
1478
- if (cancelReason) break;
1498
+ if (cancelReason) {
1499
+ await notifyHostAboutStop(opts.reportingConfig?.hostAdapter, {
1500
+ reason: cancelReason as EvolutionStopReason,
1501
+ maze: opts.mazeConfig.maze,
1502
+ completedGenerations,
1503
+ result: bestRunResult,
1504
+ progress: bestRunResult?.progress,
1505
+ requestHostPause: false,
1506
+ });
1507
+ break;
1508
+ }
1479
1509
 
1480
1510
  // Step 2: perform one generation and collect per-stage timings when enabled
1481
1511
  const generationOutcome = await runGeneration(
@@ -1678,6 +1708,7 @@ export const runEvolutionLoop = async (
1678
1708
  neat,
1679
1709
  opts.reportingConfig?.dashboardManager,
1680
1710
  flushToFrame,
1711
+ opts.reportingConfig?.hostAdapter,
1681
1712
  opts.minProgressToPass ?? 0,
1682
1713
  opts.autoPauseOnSolve ?? false,
1683
1714
  opts.stopOnlyOnSolve ?? false,
@@ -24,10 +24,8 @@
24
24
  import { Network } from '../../../../src/neataptic';
25
25
  import { MazeUtils } from '../mazeUtils';
26
26
  import { FitnessEvaluator } from '../fitness';
27
- import {
28
- IFitnessEvaluationContext,
29
- IRunMazeEvolutionOptions,
30
- } from '../interfaces';
27
+ import type { IFitnessEvaluationContext } from '../fitness.types';
28
+ import type { IRunMazeEvolutionOptions } from './evolutionEngine.types';
31
29
  import { createNeat, seedInitialPopulation } from './neatConfiguration';
32
30
 
33
31
  /**