@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
@@ -0,0 +1,590 @@
1
+ /**
2
+ * analyze-trace.ts
3
+ *
4
+ * Reads a Chrome/Perfetto trace export and prints a compact performance report.
5
+ * The report is intentionally thread-aware so browser-main, renderer-main,
6
+ * worker, compositor, and GPU activity can be inspected separately.
7
+ *
8
+ * Usage:
9
+ * npm run trace:analyze -- test/examples/flappy_bird/Trace-20260309T191949.json
10
+ * npx ts-node scripts/analyze-trace.ts path/to/trace.json --top=20
11
+ */
12
+ import fs from 'fs';
13
+ import path from 'path';
14
+
15
+ type Primitive = string | number | boolean | null | undefined;
16
+
17
+ interface TraceEvent {
18
+ pid?: number;
19
+ tid?: number;
20
+ ts?: number;
21
+ dur?: number;
22
+ tdur?: number;
23
+ ph?: string;
24
+ cat?: string;
25
+ name?: string;
26
+ args?: Record<string, unknown>;
27
+ }
28
+
29
+ interface TraceFile {
30
+ traceEvents?: TraceEvent[];
31
+ }
32
+
33
+ interface ThreadIdentity {
34
+ pid: number;
35
+ tid: number;
36
+ }
37
+
38
+ interface ThreadSummary {
39
+ label: string;
40
+ totalDurationMs: number;
41
+ runTaskDurationMs: number;
42
+ longTaskCount16ms: number;
43
+ longTaskCount50ms: number;
44
+ maxTaskMs: number;
45
+ }
46
+
47
+ interface AggregatedDuration {
48
+ name: string;
49
+ count: number;
50
+ totalMs: number;
51
+ maxMs: number;
52
+ }
53
+
54
+ interface LongEventSummary {
55
+ durationMs: number;
56
+ threadLabel: string;
57
+ eventName: string;
58
+ scriptUrl?: string;
59
+ }
60
+
61
+ const MICROSECONDS_PER_MILLISECOND = 1000;
62
+ const DEFAULT_TOP_COUNT = 12;
63
+ const LONG_TASK_THRESHOLD_MS = 16.7;
64
+ const VERY_LONG_TASK_THRESHOLD_MS = 50;
65
+
66
+ /**
67
+ * CLI entry point.
68
+ *
69
+ * Reads the trace, derives thread metadata, and prints a deterministic textual
70
+ * report that is easy to compare across captures.
71
+ */
72
+ function main(): void {
73
+ const options = resolveCliOptions(process.argv.slice(2));
74
+ const traceFilePath = path.resolve(options.tracePath);
75
+ const trace = loadTrace(traceFilePath);
76
+ const traceEvents = trace.traceEvents ?? [];
77
+
78
+ if (traceEvents.length === 0) {
79
+ throw new Error(`Trace contains no events: ${traceFilePath}`);
80
+ }
81
+
82
+ const processNames = collectMetadataNames(traceEvents, 'process_name');
83
+ const threadNames = collectMetadataNames(traceEvents, 'thread_name');
84
+ const workerThreadLabels = collectWorkerThreadLabels(traceEvents);
85
+ const timeRange = resolveTimeRange(traceEvents);
86
+ const droppedFrameCount = traceEvents.filter(
87
+ (traceEvent) => traceEvent.name === 'DroppedFrame',
88
+ ).length;
89
+ const beginFrameCount = traceEvents.filter(
90
+ (traceEvent) => traceEvent.name === 'BeginFrame',
91
+ ).length;
92
+
93
+ const threadSummaries = buildThreadSummaries({
94
+ traceEvents,
95
+ processNames,
96
+ threadNames,
97
+ workerThreadLabels,
98
+ });
99
+ const hottestEvents = aggregateDurationsByName(traceEvents, options.topCount);
100
+ const hottestFunctionCalls = aggregateFunctionCalls(traceEvents, options.topCount);
101
+ const longestEvents = collectLongestEvents({
102
+ traceEvents,
103
+ processNames,
104
+ threadNames,
105
+ workerThreadLabels,
106
+ topCount: options.topCount,
107
+ });
108
+ const fireAnimationFrameDurations = collectEventDurationsMs(
109
+ traceEvents,
110
+ 'FireAnimationFrame',
111
+ );
112
+ const functionCallDurations = collectEventDurationsMs(traceEvents, 'FunctionCall');
113
+
114
+ printSection('Trace');
115
+ printLine(`File: ${traceFilePath}`);
116
+ printLine(
117
+ `Window: ${formatMs(timeRange.windowMs)} across ${traceEvents.length.toLocaleString()} events`,
118
+ );
119
+ printLine(
120
+ `Frames: ${beginFrameCount.toLocaleString()} begin, ${droppedFrameCount.toLocaleString()} dropped`,
121
+ );
122
+
123
+ printSection('Thread Summary');
124
+ for (const threadSummary of threadSummaries) {
125
+ printLine(
126
+ `${threadSummary.label}: total=${formatMs(threadSummary.totalDurationMs)}, ` +
127
+ `RunTask=${formatMs(threadSummary.runTaskDurationMs)}, ` +
128
+ `>16.7ms=${threadSummary.longTaskCount16ms}, ` +
129
+ `>50ms=${threadSummary.longTaskCount50ms}, ` +
130
+ `max=${formatMs(threadSummary.maxTaskMs)}`,
131
+ );
132
+ }
133
+
134
+ printSection('Animation Frames');
135
+ printLine(`FireAnimationFrame: ${formatDistribution(fireAnimationFrameDurations)}`);
136
+ printLine(`FunctionCall: ${formatDistribution(functionCallDurations)}`);
137
+
138
+ printSection('Longest Events');
139
+ for (const longEvent of longestEvents) {
140
+ printLine(
141
+ `${formatMs(longEvent.durationMs)} | ${longEvent.threadLabel} | ${longEvent.eventName}${
142
+ longEvent.scriptUrl ? ` | ${longEvent.scriptUrl}` : ''
143
+ }`,
144
+ );
145
+ }
146
+
147
+ printSection('Top Events');
148
+ for (const eventSummary of hottestEvents) {
149
+ printLine(
150
+ `${eventSummary.name}: count=${eventSummary.count.toLocaleString()}, total=${formatMs(eventSummary.totalMs)}, max=${formatMs(eventSummary.maxMs)}`,
151
+ );
152
+ }
153
+
154
+ printSection('Top Function Calls');
155
+ for (const functionCallSummary of hottestFunctionCalls) {
156
+ printLine(
157
+ `${functionCallSummary.name}: count=${functionCallSummary.count.toLocaleString()}, total=${formatMs(functionCallSummary.totalMs)}, max=${formatMs(functionCallSummary.maxMs)}`,
158
+ );
159
+ }
160
+ }
161
+
162
+ /**
163
+ * Resolves CLI flags.
164
+ *
165
+ * Supported flags:
166
+ * - positional trace path
167
+ * - `--top=NUMBER`
168
+ */
169
+ function resolveCliOptions(argumentsList: string[]): {
170
+ tracePath: string;
171
+ topCount: number;
172
+ } {
173
+ const pathArgument = argumentsList.find((argument) => !argument.startsWith('--'));
174
+ if (!pathArgument) {
175
+ throw new Error(
176
+ 'Missing trace path. Example: npm run trace:analyze -- test/examples/flappy_bird/Trace.json',
177
+ );
178
+ }
179
+
180
+ const topArgument = argumentsList.find((argument) => argument.startsWith('--top='));
181
+ const requestedTopCount = topArgument
182
+ ? Number.parseInt(topArgument.slice('--top='.length), 10)
183
+ : DEFAULT_TOP_COUNT;
184
+
185
+ return {
186
+ tracePath: pathArgument,
187
+ topCount:
188
+ Number.isFinite(requestedTopCount) && requestedTopCount > 0
189
+ ? requestedTopCount
190
+ : DEFAULT_TOP_COUNT,
191
+ };
192
+ }
193
+
194
+ /** Reads and parses a trace JSON file. */
195
+ function loadTrace(traceFilePath: string): TraceFile {
196
+ const traceFileContents = fs.readFileSync(traceFilePath, 'utf8');
197
+ return JSON.parse(traceFileContents) as TraceFile;
198
+ }
199
+
200
+ /**
201
+ * Collects thread or process metadata labels keyed by `pid:tid`.
202
+ *
203
+ * Chrome emits metadata events (`ph === 'M'`) that attach human-readable names
204
+ * to otherwise numeric process and thread identifiers.
205
+ */
206
+ function collectMetadataNames(
207
+ traceEvents: TraceEvent[],
208
+ metadataName: 'process_name' | 'thread_name',
209
+ ): Map<string, string> {
210
+ const metadataNames = new Map<string, string>();
211
+
212
+ for (const traceEvent of traceEvents) {
213
+ if (traceEvent.ph !== 'M' || traceEvent.name !== metadataName) {
214
+ continue;
215
+ }
216
+
217
+ const resolvedName = readNestedPrimitive(traceEvent.args, ['name']);
218
+ if (typeof resolvedName !== 'string') {
219
+ continue;
220
+ }
221
+
222
+ const metadataKey =
223
+ metadataName === 'process_name'
224
+ ? createProcessKey(traceEvent.pid)
225
+ : createThreadKey(traceEvent.pid, traceEvent.tid);
226
+
227
+ if (metadataKey) {
228
+ metadataNames.set(metadataKey, resolvedName);
229
+ }
230
+ }
231
+
232
+ return metadataNames;
233
+ }
234
+
235
+ /**
236
+ * Resolves worker-thread labels from worker attachment events.
237
+ *
238
+ * This helps map generic `DedicatedWorker thread` labels back to the worker
239
+ * script URL that spawned them.
240
+ */
241
+ function collectWorkerThreadLabels(traceEvents: TraceEvent[]): Map<string, string> {
242
+ const workerThreadLabels = new Map<string, string>();
243
+
244
+ for (const traceEvent of traceEvents) {
245
+ if (traceEvent.name !== 'TracingSessionIdForWorker') {
246
+ continue;
247
+ }
248
+
249
+ const workerThreadId = readNestedPrimitive(traceEvent.args, [
250
+ 'data',
251
+ 'workerThreadId',
252
+ ]);
253
+ const workerUrl = readNestedPrimitive(traceEvent.args, ['data', 'url']);
254
+
255
+ if (typeof workerThreadId !== 'number' || typeof workerUrl !== 'string') {
256
+ continue;
257
+ }
258
+
259
+ const threadKey = createThreadKey(traceEvent.pid, workerThreadId);
260
+ if (!threadKey) {
261
+ continue;
262
+ }
263
+
264
+ workerThreadLabels.set(threadKey, workerUrl);
265
+ }
266
+
267
+ return workerThreadLabels;
268
+ }
269
+
270
+ /** Computes the visible time window spanned by non-zero timestamp events. */
271
+ function resolveTimeRange(traceEvents: TraceEvent[]): { windowMs: number } {
272
+ let minimumTimestamp = Number.POSITIVE_INFINITY;
273
+ let maximumTimestamp = 0;
274
+
275
+ for (const traceEvent of traceEvents) {
276
+ const eventTimestamp = traceEvent.ts;
277
+ if (typeof eventTimestamp === 'number' && eventTimestamp > 0) {
278
+ minimumTimestamp = Math.min(minimumTimestamp, eventTimestamp);
279
+ }
280
+
281
+ const eventDuration = typeof traceEvent.dur === 'number' ? traceEvent.dur : 0;
282
+ maximumTimestamp = Math.max(maximumTimestamp, (eventTimestamp ?? 0) + eventDuration);
283
+ }
284
+
285
+ if (!Number.isFinite(minimumTimestamp)) {
286
+ minimumTimestamp = 0;
287
+ }
288
+
289
+ return {
290
+ windowMs: (maximumTimestamp - minimumTimestamp) / MICROSECONDS_PER_MILLISECOND,
291
+ };
292
+ }
293
+
294
+ /**
295
+ * Builds per-thread rollups for total duration and long-task counts.
296
+ */
297
+ function buildThreadSummaries(options: {
298
+ traceEvents: TraceEvent[];
299
+ processNames: Map<string, string>;
300
+ threadNames: Map<string, string>;
301
+ workerThreadLabels: Map<string, string>;
302
+ }): ThreadSummary[] {
303
+ const {
304
+ traceEvents,
305
+ processNames,
306
+ threadNames,
307
+ workerThreadLabels,
308
+ } = options;
309
+ const durationByThread = new Map<string, ThreadSummary>();
310
+
311
+ for (const traceEvent of traceEvents) {
312
+ if (traceEvent.ph !== 'X' || typeof traceEvent.dur !== 'number') {
313
+ continue;
314
+ }
315
+
316
+ const threadKey = createThreadKey(traceEvent.pid, traceEvent.tid);
317
+ if (!threadKey) {
318
+ continue;
319
+ }
320
+
321
+ const threadSummaryLabel = resolveThreadLabel({
322
+ traceEvent,
323
+ processNames,
324
+ threadNames,
325
+ workerThreadLabels,
326
+ });
327
+ const threadSummary =
328
+ durationByThread.get(threadSummaryLabel) ?? {
329
+ label: threadSummaryLabel,
330
+ totalDurationMs: 0,
331
+ runTaskDurationMs: 0,
332
+ longTaskCount16ms: 0,
333
+ longTaskCount50ms: 0,
334
+ maxTaskMs: 0,
335
+ };
336
+ const eventDurationMs = traceEvent.dur / MICROSECONDS_PER_MILLISECOND;
337
+
338
+ threadSummary.totalDurationMs += eventDurationMs;
339
+ if (traceEvent.name === 'RunTask') {
340
+ threadSummary.runTaskDurationMs += eventDurationMs;
341
+ if (eventDurationMs >= LONG_TASK_THRESHOLD_MS) {
342
+ threadSummary.longTaskCount16ms += 1;
343
+ }
344
+ if (eventDurationMs >= VERY_LONG_TASK_THRESHOLD_MS) {
345
+ threadSummary.longTaskCount50ms += 1;
346
+ }
347
+ threadSummary.maxTaskMs = Math.max(threadSummary.maxTaskMs, eventDurationMs);
348
+ }
349
+
350
+ durationByThread.set(threadSummaryLabel, threadSummary);
351
+ }
352
+
353
+ return Array.from(durationByThread.values()).toSorted(
354
+ (leftSummary, rightSummary) => rightSummary.totalDurationMs - leftSummary.totalDurationMs,
355
+ );
356
+ }
357
+
358
+ /** Resolves a readable process/thread label for one event. */
359
+ function resolveThreadLabel(options: {
360
+ traceEvent: TraceEvent;
361
+ processNames: Map<string, string>;
362
+ threadNames: Map<string, string>;
363
+ workerThreadLabels: Map<string, string>;
364
+ }): string {
365
+ const { traceEvent, processNames, threadNames, workerThreadLabels } = options;
366
+ const processLabel = processNames.get(createProcessKey(traceEvent.pid) ?? '') ?? 'unknown-process';
367
+ const threadKey = createThreadKey(traceEvent.pid, traceEvent.tid) ?? 'unknown-thread';
368
+ const threadLabel = threadNames.get(threadKey) ?? 'unknown-thread';
369
+ const workerLabel = workerThreadLabels.get(threadKey);
370
+ return workerLabel
371
+ ? `${processLabel} / ${threadLabel} / ${workerLabel}`
372
+ : `${processLabel} / ${threadLabel}`;
373
+ }
374
+
375
+ /** Collects the longest complete events in the trace. */
376
+ function collectLongestEvents(options: {
377
+ traceEvents: TraceEvent[];
378
+ processNames: Map<string, string>;
379
+ threadNames: Map<string, string>;
380
+ workerThreadLabels: Map<string, string>;
381
+ topCount: number;
382
+ }): LongEventSummary[] {
383
+ const { traceEvents, processNames, threadNames, workerThreadLabels, topCount } = options;
384
+
385
+ return traceEvents
386
+ .filter(
387
+ (traceEvent) =>
388
+ traceEvent.ph === 'X' &&
389
+ typeof traceEvent.dur === 'number' &&
390
+ typeof traceEvent.name === 'string',
391
+ )
392
+ .map((traceEvent) => ({
393
+ durationMs: traceEvent.dur! / MICROSECONDS_PER_MILLISECOND,
394
+ threadLabel: resolveThreadLabel({
395
+ traceEvent,
396
+ processNames,
397
+ threadNames,
398
+ workerThreadLabels,
399
+ }),
400
+ eventName: traceEvent.name!,
401
+ scriptUrl:
402
+ (readNestedPrimitive(traceEvent.args, ['data', 'url']) as string | undefined) ??
403
+ undefined,
404
+ }))
405
+ .toSorted((leftEvent, rightEvent) => rightEvent.durationMs - leftEvent.durationMs)
406
+ .slice(0, topCount);
407
+ }
408
+
409
+ /**
410
+ * Aggregates complete-event durations by event name.
411
+ *
412
+ * `RunTask` is kept because it is still useful for thread pressure, but the
413
+ * separate function-call rollup below is generally more actionable.
414
+ */
415
+ function aggregateDurationsByName(
416
+ traceEvents: TraceEvent[],
417
+ topCount: number,
418
+ ): AggregatedDuration[] {
419
+ const durationsByName = new Map<string, AggregatedDuration>();
420
+
421
+ for (const traceEvent of traceEvents) {
422
+ if (traceEvent.ph !== 'X' || typeof traceEvent.dur !== 'number' || !traceEvent.name) {
423
+ continue;
424
+ }
425
+
426
+ const eventDurationMs = traceEvent.dur / MICROSECONDS_PER_MILLISECOND;
427
+ const eventSummary = durationsByName.get(traceEvent.name) ?? {
428
+ name: traceEvent.name,
429
+ count: 0,
430
+ totalMs: 0,
431
+ maxMs: 0,
432
+ };
433
+
434
+ eventSummary.count += 1;
435
+ eventSummary.totalMs += eventDurationMs;
436
+ eventSummary.maxMs = Math.max(eventSummary.maxMs, eventDurationMs);
437
+ durationsByName.set(traceEvent.name, eventSummary);
438
+ }
439
+
440
+ return Array.from(durationsByName.values())
441
+ .toSorted((leftSummary, rightSummary) => rightSummary.totalMs - leftSummary.totalMs)
442
+ .slice(0, topCount);
443
+ }
444
+
445
+ /**
446
+ * Aggregates `FunctionCall` events by script URL.
447
+ *
448
+ * This is the most direct way to see which bundle or worker file owns main
449
+ * thread or worker thread execution time in the trace.
450
+ */
451
+ function aggregateFunctionCalls(
452
+ traceEvents: TraceEvent[],
453
+ topCount: number,
454
+ ): AggregatedDuration[] {
455
+ const durationsByFunctionCall = new Map<string, AggregatedDuration>();
456
+
457
+ for (const traceEvent of traceEvents) {
458
+ if (
459
+ traceEvent.ph !== 'X' ||
460
+ traceEvent.name !== 'FunctionCall' ||
461
+ typeof traceEvent.dur !== 'number'
462
+ ) {
463
+ continue;
464
+ }
465
+
466
+ const functionCallName =
467
+ (readNestedPrimitive(traceEvent.args, ['data', 'url']) as string | undefined) ??
468
+ '(unknown-script)';
469
+ const functionCallSummary = durationsByFunctionCall.get(functionCallName) ?? {
470
+ name: functionCallName,
471
+ count: 0,
472
+ totalMs: 0,
473
+ maxMs: 0,
474
+ };
475
+ const eventDurationMs = traceEvent.dur / MICROSECONDS_PER_MILLISECOND;
476
+
477
+ functionCallSummary.count += 1;
478
+ functionCallSummary.totalMs += eventDurationMs;
479
+ functionCallSummary.maxMs = Math.max(functionCallSummary.maxMs, eventDurationMs);
480
+ durationsByFunctionCall.set(functionCallName, functionCallSummary);
481
+ }
482
+
483
+ return Array.from(durationsByFunctionCall.values())
484
+ .toSorted((leftSummary, rightSummary) => rightSummary.totalMs - leftSummary.totalMs)
485
+ .slice(0, topCount);
486
+ }
487
+
488
+ /** Collects all durations for one event name in milliseconds. */
489
+ function collectEventDurationsMs(
490
+ traceEvents: TraceEvent[],
491
+ eventName: string,
492
+ ): number[] {
493
+ return traceEvents
494
+ .filter(
495
+ (traceEvent) =>
496
+ traceEvent.ph === 'X' &&
497
+ traceEvent.name === eventName &&
498
+ typeof traceEvent.dur === 'number',
499
+ )
500
+ .map((traceEvent) => traceEvent.dur! / MICROSECONDS_PER_MILLISECOND)
501
+ .toSorted((leftDuration, rightDuration) => leftDuration - rightDuration);
502
+ }
503
+
504
+ /** Formats a percentile-style summary for one event duration collection. */
505
+ function formatDistribution(durationsMs: number[]): string {
506
+ if (durationsMs.length === 0) {
507
+ return 'count=0';
508
+ }
509
+
510
+ return [
511
+ `count=${durationsMs.length.toLocaleString()}`,
512
+ `p50=${formatMs(percentile(durationsMs, 0.5))}`,
513
+ `p90=${formatMs(percentile(durationsMs, 0.9))}`,
514
+ `p99=${formatMs(percentile(durationsMs, 0.99))}`,
515
+ `max=${formatMs(durationsMs.at(-1) ?? 0)}`,
516
+ ].join(', ');
517
+ }
518
+
519
+ /** Computes a nearest-rank percentile from sorted durations. */
520
+ function percentile(sortedDurations: number[], rank: number): number {
521
+ if (sortedDurations.length === 0) {
522
+ return 0;
523
+ }
524
+
525
+ const clampedRank = Math.max(0, Math.min(1, rank));
526
+ const index = Math.min(
527
+ sortedDurations.length - 1,
528
+ Math.floor(clampedRank * (sortedDurations.length - 1)),
529
+ );
530
+ return sortedDurations[index];
531
+ }
532
+
533
+ /** Safely resolves a nested primitive value from an event args object. */
534
+ function readNestedPrimitive(
535
+ value: unknown,
536
+ pathSegments: string[],
537
+ ): Primitive {
538
+ let currentValue: unknown = value;
539
+
540
+ for (const pathSegment of pathSegments) {
541
+ if (!currentValue || typeof currentValue !== 'object') {
542
+ return undefined;
543
+ }
544
+
545
+ currentValue = (currentValue as Record<string, unknown>)[pathSegment];
546
+ }
547
+
548
+ if (
549
+ currentValue == null ||
550
+ typeof currentValue === 'string' ||
551
+ typeof currentValue === 'number' ||
552
+ typeof currentValue === 'boolean'
553
+ ) {
554
+ return currentValue;
555
+ }
556
+
557
+ return undefined;
558
+ }
559
+
560
+ /** Formats a duration for stable human-readable output. */
561
+ function formatMs(durationMs: number): string {
562
+ return `${durationMs.toFixed(2)}ms`;
563
+ }
564
+
565
+ /** Creates a stable process lookup key. */
566
+ function createProcessKey(pid: number | undefined): string | undefined {
567
+ return typeof pid === 'number' ? `pid:${pid}` : undefined;
568
+ }
569
+
570
+ /** Creates a stable thread lookup key. */
571
+ function createThreadKey(
572
+ pid: number | undefined,
573
+ tid: number | undefined,
574
+ ): string | undefined {
575
+ return typeof pid === 'number' && typeof tid === 'number'
576
+ ? `pid:${pid}:tid:${tid}`
577
+ : undefined;
578
+ }
579
+
580
+ /** Prints a section title. */
581
+ function printSection(title: string): void {
582
+ console.log(`\n[${title}]`);
583
+ }
584
+
585
+ /** Prints one content line. */
586
+ function printLine(value: string): void {
587
+ console.log(value);
588
+ }
589
+
590
+ main();