@reicek/neataptic-ts 0.1.26 → 0.1.27
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.
- package/.github/agents/boundary-mapper.agent.md +13 -8
- package/.github/agents/docs-scout.agent.md +14 -9
- package/.github/agents/plan-scout.agent.md +11 -6
- package/.github/agents/solid-split.agent.md +33 -17
- package/.github/copilot-instructions.md +100 -88
- package/.github/skills/educational-docs/SKILL.md +90 -40
- package/.github/skills/educational-docs/assets/mermaid-diagram-playbook.md +141 -141
- package/.github/skills/educational-docs/assets/visual-style-guide.md +1 -1
- package/.github/skills/plan-alignment/SKILL.md +1 -1
- package/.github/skills/solid-split/SKILL.md +54 -35
- package/.github/skills/solid-split/assets/docs-checklist.md +1 -1
- package/.github/skills/solid-split/assets/split-plan-template.md +41 -12
- package/.github/skills/solid-split/assets/split-workflow-checklist.md +4 -1
- package/.github/skills/test-fix-workflow/SKILL.md +12 -7
- package/.github/skills/trace-analyzer-extension/SKILL.md +1 -1
- package/.github/skills/trace-analyzer-extension/assets/extension-checklist.md +1 -1
- package/.github/skills/trace-analyzer-extension/references/analyzer-extension-workflow.md +1 -1
- package/.github/skills/trace-audit-reporting/SKILL.md +1 -1
- package/.github/skills/trace-audit-reporting/assets/performance-report-template.md +1 -1
- package/.github/skills/trace-audit-reporting/references/trace-analysis-workflow.md +1 -1
- package/.github/skills/tracker-handoff/SKILL.md +53 -5
- package/package.json +1 -1
- package/plans/Flappy_Bird_Folder_Documentation_Pass.logs.md +42 -0
- package/plans/Flappy_Bird_Folder_Documentation_Pass.md +22 -104
- package/plans/README.md +6 -2
- package/plans/Roadmap.md +35 -31
- package/plans/analyze-trace-solid-split.logs.md +35 -0
- package/plans/analyze-trace-solid-split.plans.md +21 -52
- package/plans/architecture-solid-split.logs.md +44 -0
- package/plans/architecture-solid-split.plans.md +20 -653
- package/plans/asciiMaze-typescript-repair.logs.md +35 -0
- package/plans/asciiMaze-typescript-repair.plans.md +30 -36
- package/plans/generate-docs-solid-split.logs.md +36 -0
- package/plans/generate-docs-solid-split.plans.md +21 -73
- package/plans/methods-docs.logs.md +37 -0
- package/plans/methods-docs.plans.md +22 -183
- package/plans/methods-solid-split.logs.md +41 -0
- package/plans/methods-solid-split.plans.md +23 -65
- package/plans/neat-docs.logs.md +38 -0
- package/plans/neat-docs.plans.md +21 -63
- package/plans/neat-test-surface-repair.logs.md +38 -0
- package/plans/neat-test-surface-repair.plans.md +24 -24
- package/plans/readme-first-section-pass.logs.md +63 -0
- package/plans/readme-first-section-pass.plans.md +42 -0
- package/plans/render-docs-html-solid-split.logs.md +36 -0
- package/plans/render-docs-html-solid-split.plans.md +20 -54
- package/plans/src-no-explicit-any-cleanup.logs.md +39 -0
- package/plans/src-no-explicit-any-cleanup.plans.md +23 -161
- package/plans/utils-docs.logs.md +37 -0
- package/plans/utils-docs.plans.md +20 -35
- package/src/README.md +88 -22
- package/src/architecture/README.md +94 -17
- package/src/architecture/activationArrayPool/README.md +53 -0
- package/src/architecture/activationArrayPool/activationArrayPool.ts +53 -0
- package/src/architecture/layer/README.md +94 -5
- package/src/architecture/layer/layer.ts +94 -5
- package/src/architecture/network/README.md +85 -14
- package/src/architecture/network/activate/README.md +301 -213
- package/src/architecture/network/activate/docs.order.json +9 -0
- package/src/architecture/network/activate/network.activate.utils.ts +90 -0
- package/src/architecture/network/connect/README.md +80 -3
- package/src/architecture/network/connect/docs.order.json +9 -0
- package/src/architecture/network/connect/network.connect.utils.ts +79 -0
- package/src/architecture/network/deterministic/README.md +96 -12
- package/src/architecture/network/deterministic/docs.order.json +10 -0
- package/src/architecture/network/deterministic/network.deterministic.utils.ts +90 -0
- package/src/architecture/network/evolve/README.md +286 -228
- package/src/architecture/network/evolve/docs.order.json +11 -0
- package/src/architecture/network/evolve/network.evolve.utils.ts +59 -0
- package/src/architecture/network/gating/README.md +58 -16
- package/src/architecture/network/gating/docs.order.json +9 -0
- package/src/architecture/network/gating/network.gating.utils.ts +43 -0
- package/src/architecture/network/genetic/README.md +75 -36
- package/src/architecture/network/genetic/docs.order.json +10 -0
- package/src/architecture/network/genetic/network.genetic.utils.ts +53 -17
- package/src/architecture/network/network.ts +91 -46
- package/src/architecture/network/standalone/README.md +309 -285
- package/src/architecture/network/standalone/docs.order.json +13 -0
- package/src/architecture/network/standalone/network.standalone.utils.ts +51 -28
- package/src/architecture/network.ts +94 -17
- package/src/architecture/nodePool/README.md +53 -0
- package/src/architecture/nodePool/nodePool.ts +53 -0
- package/src/methods/README.md +80 -34
- package/src/methods/methods.ts +80 -34
- package/src/methods/mutation/README.md +39 -93
- package/src/methods/mutation/mutation.ts +58 -0
- package/src/multithreading/README.md +114 -14
- package/src/multithreading/docs.order.json +5 -0
- package/src/multithreading/multi.ts +103 -7
- package/src/multithreading/types.ts +6 -1
- package/src/multithreading/workers/README.md +72 -2
- package/src/multithreading/workers/browser/README.md +39 -0
- package/src/multithreading/workers/browser/testworker.ts +40 -0
- package/src/multithreading/workers/node/README.md +50 -11
- package/src/multithreading/workers/node/docs.order.json +4 -0
- package/src/multithreading/workers/node/testworker.ts +43 -3
- package/src/multithreading/workers/workers.ts +36 -1
- package/src/neat/README.md +230 -152
- package/src/neat/adaptive/core/README.md +99 -42
- package/src/neat/adaptive/core/adaptive.core.ts +71 -14
- package/src/neat/adaptive/core/docs.order.json +8 -0
- package/src/neat/docs.order.json +9 -0
- package/src/neat/lineage/README.md +118 -16
- package/src/neat/lineage/lineage.ts +115 -13
- package/src/neat/neat.defaults.constants.ts +91 -13
- package/src/neat.ts +86 -20
- package/src/utils/README.md +71 -21
- package/src/utils/memory.ts +69 -19
- package/test/examples/asciiMaze/browser-entry/README.md +81 -8
- package/test/examples/asciiMaze/browser-entry/browser-entry.ts +81 -8
- package/test/examples/asciiMaze/dashboardManager/README.md +68 -4
- package/test/examples/asciiMaze/dashboardManager/dashboardManager.ts +68 -4
- package/test/examples/asciiMaze/evolutionEngine/README.md +1259 -1174
- package/test/examples/asciiMaze/evolutionEngine/docs.order.json +10 -0
- package/test/examples/asciiMaze/evolutionEngine/evolutionEngine.types.ts +87 -0
- package/test/examples/asciiMaze/mazeMovement/README.md +81 -4
- package/test/examples/asciiMaze/mazeMovement/mazeMovement.ts +81 -4
- package/test/examples/flappy_bird/browser-entry/README.md +64 -21
- package/test/examples/flappy_bird/browser-entry/browser-entry.ts +64 -21
- package/test/examples/flappy_bird/flappy-evolution-worker/README.md +98 -10
- package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.ts +98 -10
- package/test/examples/flappy_bird/simulation-shared/README.md +88 -4
- package/test/examples/flappy_bird/simulation-shared/simulation-shared.types.ts +88 -4
|
@@ -1,3 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Population-level runtime contracts for the ASCII Maze evolution engine.
|
|
3
|
+
*
|
|
4
|
+
* This folder is where one maze, one fitness story, and one NEAT controller
|
|
5
|
+
* turn into a repeatable training program. The public `EvolutionEngine` facade
|
|
6
|
+
* uses these contracts to normalize options, coordinate host callbacks, keep
|
|
7
|
+
* deterministic state reproducible, and decide when a curriculum phase has
|
|
8
|
+
* produced a winner worth carrying forward.
|
|
9
|
+
*
|
|
10
|
+
* The important distinction is scale. `mazeMovement/` explains one agent run.
|
|
11
|
+
* `fitness.ts` explains how that run is scored. `dashboardManager/` explains
|
|
12
|
+
* how progress is shown to a human. `evolutionEngine/` explains how many runs
|
|
13
|
+
* across many generations become one population-level search loop with stop
|
|
14
|
+
* reasons, telemetry, warm starts, and phase outcomes that the next maze can
|
|
15
|
+
* reuse.
|
|
16
|
+
*
|
|
17
|
+
* This file is the right chapter opening because it names the public nouns of
|
|
18
|
+
* that loop before the reader hits pooled scratch buffers or hot-path helpers.
|
|
19
|
+
* It answers four questions quickly: what a caller can configure, what a host
|
|
20
|
+
* may observe or interrupt, what result the engine returns, and which shared
|
|
21
|
+
* runtime contexts keep the hot path allocation-light.
|
|
22
|
+
*
|
|
23
|
+
* A useful mental model is to treat the engine as a control tower rather than
|
|
24
|
+
* the aircraft itself. The engine does not move the agent through one maze cell
|
|
25
|
+
* at a time. It schedules phases, batches generations, preserves deterministic
|
|
26
|
+
* state, and hands structured outcomes back to browser or terminal hosts.
|
|
27
|
+
*
|
|
28
|
+
* Read the chapter in three passes. Start here for the public contracts and the
|
|
29
|
+
* meaning of a run result. Continue to `engineState.types.ts` when you want the
|
|
30
|
+
* shared scratch and toggle state that keeps the loop cheap. Finish with
|
|
31
|
+
* `evolutionLoop.ts`, `evolutionEngine.services.ts`, and `sampling.ts` when you
|
|
32
|
+
* want the actual orchestration and telemetry mechanics.
|
|
33
|
+
*
|
|
34
|
+
* ```mermaid
|
|
35
|
+
* flowchart LR
|
|
36
|
+
* classDef base fill:#08131f,stroke:#1ea7ff,color:#dff6ff,stroke-width:1px;
|
|
37
|
+
* classDef accent fill:#0f2233,stroke:#ffd166,color:#fff4cc,stroke-width:1.5px;
|
|
38
|
+
*
|
|
39
|
+
* Caller["Caller or host"]:::base --> Options["IRunMazeEvolutionOptions\nrun inputs"]:::base
|
|
40
|
+
* Options --> Engine["EvolutionEngine facade\npopulation-level control"]:::accent
|
|
41
|
+
* Engine --> Loop["generation loop\nevaluate mutate telemetry"]:::base
|
|
42
|
+
* Loop --> Result["MazeEvolutionRunResult\nbest network + exit reason"]:::base
|
|
43
|
+
* Result --> Phase["MazeEvolutionCurriculumPhaseOutcome\ncarry winner forward"]:::base
|
|
44
|
+
* Engine --> Host["EvolutionHostAdapter\npause and stop hooks"]:::base
|
|
45
|
+
* ```
|
|
46
|
+
*
|
|
47
|
+
* ```mermaid
|
|
48
|
+
* flowchart TD
|
|
49
|
+
* classDef base fill:#08131f,stroke:#1ea7ff,color:#dff6ff,stroke-width:1px;
|
|
50
|
+
* classDef accent fill:#0f2233,stroke:#ffd166,color:#fff4cc,stroke-width:1.5px;
|
|
51
|
+
*
|
|
52
|
+
* EngineFolder["evolutionEngine/"]:::accent --> Contracts["evolutionEngine.types.ts\npublic run contracts"]:::base
|
|
53
|
+
* EngineFolder --> Scratch["engineState.types.ts\nshared scratch and toggles"]:::base
|
|
54
|
+
* EngineFolder --> Loop["evolutionLoop.ts\nmain generation orchestration"]:::base
|
|
55
|
+
* EngineFolder --> Services["evolutionEngine.services.ts\nand helpers"]:::base
|
|
56
|
+
* EngineFolder --> Sampling["sampling.ts\nand telemetry support"]:::base
|
|
57
|
+
* ```
|
|
58
|
+
*
|
|
59
|
+
* For background reading on the staged difficulty idea behind the browser and
|
|
60
|
+
* curriculum-style runs, see Wikipedia contributors,
|
|
61
|
+
* [Curriculum learning](https://en.wikipedia.org/wiki/Curriculum_learning),
|
|
62
|
+
* which captures the broader teaching idea of solving easier tasks before
|
|
63
|
+
* harder ones.
|
|
64
|
+
*
|
|
65
|
+
* Example: describe the host adapter and reporting hooks the engine may call.
|
|
66
|
+
*
|
|
67
|
+
* ```ts
|
|
68
|
+
* const hostAdapter: EvolutionHostAdapter = {
|
|
69
|
+
* isPauseRequested: () => window.asciiMazePaused === true,
|
|
70
|
+
* handleStop: ({ reason, completedGenerations }) => {
|
|
71
|
+
* console.log(reason, completedGenerations);
|
|
72
|
+
* },
|
|
73
|
+
* };
|
|
74
|
+
* ```
|
|
75
|
+
*
|
|
76
|
+
* Example: sketch one engine run configuration before execution begins.
|
|
77
|
+
*
|
|
78
|
+
* ```ts
|
|
79
|
+
* const runOptions: IRunMazeEvolutionOptions = {
|
|
80
|
+
* mazeConfig: { maze },
|
|
81
|
+
* agentSimConfig: { maxSteps: 160 },
|
|
82
|
+
* evolutionAlgorithmConfig: { popSize: 120, deterministic: true },
|
|
83
|
+
* reportingConfig: { dashboardManager, logEvery: 5 },
|
|
84
|
+
* };
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
|
|
1
88
|
import type Network from '../../../../src/architecture/network';
|
|
2
89
|
import type { FitnessEvaluatorFn } from '../fitness.types';
|
|
3
90
|
import type {
|
|
@@ -1,10 +1,87 @@
|
|
|
1
1
|
# mazeMovement
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Episode-simulation boundary for one maze-controlled agent.
|
|
4
|
+
|
|
5
|
+
This folder is where a policy stops being abstract logits and starts paying
|
|
6
|
+
for local decisions. One run moves through perception, direction selection,
|
|
7
|
+
collision-aware movement, shaping, and finalization until the agent reaches
|
|
8
|
+
the exit or exhausts its step budget.
|
|
9
|
+
|
|
10
|
+
The boundary exists because single-episode logic needs both honesty and
|
|
11
|
+
inspectability. If movement rules, reward shaping, and stop conditions were
|
|
12
|
+
scattered across fitness or evolution helpers, it would be much harder to
|
|
13
|
+
tell whether poor results came from weak policy, thin observations, harsh
|
|
14
|
+
shaping, or simple runtime edge cases.
|
|
15
|
+
|
|
16
|
+
Read the folder as four cooperating shelves. `runtime/` builds perception,
|
|
17
|
+
visit bookkeeping, and low-level state transitions. `policy/` converts raw
|
|
18
|
+
outputs into concrete directional choices and exploration nudges. `shaping/`
|
|
19
|
+
applies the score semantics that make sparse-goal navigation learnable.
|
|
20
|
+
`finalization/` folds the finished path into one result the engine and
|
|
21
|
+
fitness layers can compare.
|
|
22
|
+
|
|
23
|
+
The public class stays class-based on purpose. Existing imports remain
|
|
24
|
+
stable, but the real teaching value is now inside the split helpers. The
|
|
25
|
+
facade tells the reader what the episode boundary promises; the subfolders
|
|
26
|
+
explain how that promise is kept.
|
|
27
|
+
|
|
28
|
+
Read this chapter in three passes. Start with `simulateAgent(...)` when you
|
|
29
|
+
want the whole episode loop. Continue to `selectDirection(...)` and
|
|
30
|
+
`moveAgent(...)` when you want the policy-to-action seam. Finish in the
|
|
31
|
+
runtime, policy, shaping, and finalization folders when you need the exact
|
|
32
|
+
bookkeeping or reward logic behind one run.
|
|
33
|
+
|
|
34
|
+
```mermaid
|
|
35
|
+
flowchart LR
|
|
36
|
+
classDef base fill:#08131f,stroke:#1ea7ff,color:#dff6ff,stroke-width:1px;
|
|
37
|
+
classDef accent fill:#0f2233,stroke:#ffd166,color:#fff4cc,stroke-width:1.5px;
|
|
38
|
+
|
|
39
|
+
Vision["vision and visit state"]:::base --> Policy["direction selection\nand exploration nudges"]:::accent
|
|
40
|
+
Policy --> Move["collision-aware movement"]:::base
|
|
41
|
+
Move --> Shaping["progress and penalty shaping"]:::base
|
|
42
|
+
Shaping --> Finalize["episode result\nfitness path progress"]:::base
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
```mermaid
|
|
46
|
+
flowchart TD
|
|
47
|
+
classDef base fill:#08131f,stroke:#1ea7ff,color:#dff6ff,stroke-width:1px;
|
|
48
|
+
classDef accent fill:#0f2233,stroke:#ffd166,color:#fff4cc,stroke-width:1.5px;
|
|
49
|
+
|
|
50
|
+
MazeMovement["mazeMovement/"]:::accent --> Facade["mazeMovement.ts\npublic episode facade"]:::base
|
|
51
|
+
MazeMovement --> Runtime["runtime/\nvision and state"]:::base
|
|
52
|
+
MazeMovement --> Policy["policy/\naction choice"]:::base
|
|
53
|
+
MazeMovement --> Shaping["shaping/\nreward and penalties"]:::base
|
|
54
|
+
MazeMovement --> Finalization["finalization/\nresult folding"]:::base
|
|
55
|
+
```
|
|
4
56
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
57
|
+
For background on why direction selection talks about probabilities and
|
|
58
|
+
entropy instead of only the raw logits, see Wikipedia contributors,
|
|
59
|
+
[Softmax function](https://en.wikipedia.org/wiki/Softmax_function), which is
|
|
60
|
+
the probability transform used by the action-diagnostics helper layer.
|
|
61
|
+
|
|
62
|
+
Example: inspect the direction choice implied by one network output vector.
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
const directionStats = MazeMovement.selectDirection([0.4, 1.2, -0.3, 0.1]);
|
|
66
|
+
|
|
67
|
+
console.log(directionStats.selectedDirection);
|
|
68
|
+
console.log(directionStats.entropy);
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Example: simulate one complete maze episode for a candidate network.
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
const result = MazeMovement.simulateAgent(
|
|
75
|
+
network,
|
|
76
|
+
encodedMaze,
|
|
77
|
+
startPos,
|
|
78
|
+
exitPos,
|
|
79
|
+
distanceMap,
|
|
80
|
+
160,
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
console.log(result.fitness, result.reachedExit);
|
|
84
|
+
```
|
|
8
85
|
|
|
9
86
|
## mazeMovement/mazeMovement.types.ts
|
|
10
87
|
|
|
@@ -1,9 +1,86 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Episode-simulation boundary for one maze-controlled agent.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* This folder is where a policy stops being abstract logits and starts paying
|
|
5
|
+
* for local decisions. One run moves through perception, direction selection,
|
|
6
|
+
* collision-aware movement, shaping, and finalization until the agent reaches
|
|
7
|
+
* the exit or exhausts its step budget.
|
|
8
|
+
*
|
|
9
|
+
* The boundary exists because single-episode logic needs both honesty and
|
|
10
|
+
* inspectability. If movement rules, reward shaping, and stop conditions were
|
|
11
|
+
* scattered across fitness or evolution helpers, it would be much harder to
|
|
12
|
+
* tell whether poor results came from weak policy, thin observations, harsh
|
|
13
|
+
* shaping, or simple runtime edge cases.
|
|
14
|
+
*
|
|
15
|
+
* Read the folder as four cooperating shelves. `runtime/` builds perception,
|
|
16
|
+
* visit bookkeeping, and low-level state transitions. `policy/` converts raw
|
|
17
|
+
* outputs into concrete directional choices and exploration nudges. `shaping/`
|
|
18
|
+
* applies the score semantics that make sparse-goal navigation learnable.
|
|
19
|
+
* `finalization/` folds the finished path into one result the engine and
|
|
20
|
+
* fitness layers can compare.
|
|
21
|
+
*
|
|
22
|
+
* The public class stays class-based on purpose. Existing imports remain
|
|
23
|
+
* stable, but the real teaching value is now inside the split helpers. The
|
|
24
|
+
* facade tells the reader what the episode boundary promises; the subfolders
|
|
25
|
+
* explain how that promise is kept.
|
|
26
|
+
*
|
|
27
|
+
* Read this chapter in three passes. Start with `simulateAgent(...)` when you
|
|
28
|
+
* want the whole episode loop. Continue to `selectDirection(...)` and
|
|
29
|
+
* `moveAgent(...)` when you want the policy-to-action seam. Finish in the
|
|
30
|
+
* runtime, policy, shaping, and finalization folders when you need the exact
|
|
31
|
+
* bookkeeping or reward logic behind one run.
|
|
32
|
+
*
|
|
33
|
+
* ```mermaid
|
|
34
|
+
* flowchart LR
|
|
35
|
+
* classDef base fill:#08131f,stroke:#1ea7ff,color:#dff6ff,stroke-width:1px;
|
|
36
|
+
* classDef accent fill:#0f2233,stroke:#ffd166,color:#fff4cc,stroke-width:1.5px;
|
|
37
|
+
*
|
|
38
|
+
* Vision["vision and visit state"]:::base --> Policy["direction selection\nand exploration nudges"]:::accent
|
|
39
|
+
* Policy --> Move["collision-aware movement"]:::base
|
|
40
|
+
* Move --> Shaping["progress and penalty shaping"]:::base
|
|
41
|
+
* Shaping --> Finalize["episode result\nfitness path progress"]:::base
|
|
42
|
+
* ```
|
|
43
|
+
*
|
|
44
|
+
* ```mermaid
|
|
45
|
+
* flowchart TD
|
|
46
|
+
* classDef base fill:#08131f,stroke:#1ea7ff,color:#dff6ff,stroke-width:1px;
|
|
47
|
+
* classDef accent fill:#0f2233,stroke:#ffd166,color:#fff4cc,stroke-width:1.5px;
|
|
48
|
+
*
|
|
49
|
+
* MazeMovement["mazeMovement/"]:::accent --> Facade["mazeMovement.ts\npublic episode facade"]:::base
|
|
50
|
+
* MazeMovement --> Runtime["runtime/\nvision and state"]:::base
|
|
51
|
+
* MazeMovement --> Policy["policy/\naction choice"]:::base
|
|
52
|
+
* MazeMovement --> Shaping["shaping/\nreward and penalties"]:::base
|
|
53
|
+
* MazeMovement --> Finalization["finalization/\nresult folding"]:::base
|
|
54
|
+
* ```
|
|
55
|
+
*
|
|
56
|
+
* For background on why direction selection talks about probabilities and
|
|
57
|
+
* entropy instead of only the raw logits, see Wikipedia contributors,
|
|
58
|
+
* [Softmax function](https://en.wikipedia.org/wiki/Softmax_function), which is
|
|
59
|
+
* the probability transform used by the action-diagnostics helper layer.
|
|
60
|
+
*
|
|
61
|
+
* Example: inspect the direction choice implied by one network output vector.
|
|
62
|
+
*
|
|
63
|
+
* ```ts
|
|
64
|
+
* const directionStats = MazeMovement.selectDirection([0.4, 1.2, -0.3, 0.1]);
|
|
65
|
+
*
|
|
66
|
+
* console.log(directionStats.selectedDirection);
|
|
67
|
+
* console.log(directionStats.entropy);
|
|
68
|
+
* ```
|
|
69
|
+
*
|
|
70
|
+
* Example: simulate one complete maze episode for a candidate network.
|
|
71
|
+
*
|
|
72
|
+
* ```ts
|
|
73
|
+
* const result = MazeMovement.simulateAgent(
|
|
74
|
+
* network,
|
|
75
|
+
* encodedMaze,
|
|
76
|
+
* startPos,
|
|
77
|
+
* exitPos,
|
|
78
|
+
* distanceMap,
|
|
79
|
+
* 160,
|
|
80
|
+
* );
|
|
81
|
+
*
|
|
82
|
+
* console.log(result.fitness, result.reachedExit);
|
|
83
|
+
* ```
|
|
7
84
|
*/
|
|
8
85
|
|
|
9
86
|
import type { INetwork } from '../interfaces';
|
|
@@ -1,37 +1,80 @@
|
|
|
1
1
|
# browser-entry
|
|
2
2
|
|
|
3
|
-
Browser
|
|
3
|
+
Browser teaching surface and lifecycle facade for the Flappy Bird example.
|
|
4
|
+
|
|
5
|
+
This folder is where worker-owned evolution meets human-friendly inspection.
|
|
6
|
+
The browser side owns DOM setup, HUD updates, playback rendering, and network
|
|
7
|
+
visualization. The worker side owns the hot-path simulation and packed frame
|
|
8
|
+
production. `browser-entry/` exists so those responsibilities stay honest
|
|
9
|
+
instead of drifting into one blurry runtime.
|
|
10
|
+
|
|
11
|
+
That split is the main reason this file stays intentionally small. The public
|
|
12
|
+
`start(...)` surface should feel simple to call even though the surrounding
|
|
13
|
+
system is not simple at all. A caller gets one run handle, while the folder
|
|
14
|
+
behind it fans out into runtime bootstrap, host layout, worker messaging,
|
|
15
|
+
playback rendering, and inspection views.
|
|
16
|
+
|
|
17
|
+
Read this boundary as the browser-side answer to one practical question:
|
|
18
|
+
how do you make an evolved controller visible and interactive without moving
|
|
19
|
+
simulation authority back onto the main thread? The answer is a stable entry
|
|
20
|
+
facade plus a strict authority split between browser presentation and worker
|
|
21
|
+
execution.
|
|
22
|
+
|
|
23
|
+
`index.html` is only the local shell that loads the published bundle and then
|
|
24
|
+
reaches this same start boundary through globals. If you want the real
|
|
25
|
+
host/runtime seam, start here rather than with the static shell.
|
|
26
|
+
|
|
27
|
+
Read the folder in three passes. Start with this file for the public
|
|
28
|
+
lifecycle contract. Continue into `runtime/` and `worker-channel/` for the
|
|
29
|
+
bootstrap and protocol story. Finish with `host/`, `playback/`,
|
|
30
|
+
`network-view/`, and `visualization/` for the teaching surface the browser
|
|
31
|
+
renders around the worker-owned simulation.
|
|
4
32
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
33
|
+
```mermaid
|
|
34
|
+
flowchart LR
|
|
35
|
+
classDef base fill:#08131f,stroke:#1ea7ff,color:#dff6ff,stroke-width:1px;
|
|
36
|
+
classDef accent fill:#0f2233,stroke:#ffd166,color:#fff4cc,stroke-width:1.5px;
|
|
9
37
|
|
|
10
|
-
|
|
11
|
-
|
|
38
|
+
Start["start()"]:::accent --> Runtime["runtime/\nbootstrap orchestration"]:::base
|
|
39
|
+
Runtime --> Host["host/\nDOM and canvas shell"]:::base
|
|
40
|
+
Runtime --> Channel["worker-channel/\nworker protocol"]:::base
|
|
41
|
+
Channel --> Playback["playback/\npopulation rendering"]:::base
|
|
42
|
+
Runtime --> Network["network-view + visualization/\nnetwork inspection"]:::base
|
|
43
|
+
```
|
|
12
44
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
45
|
+
```mermaid
|
|
46
|
+
flowchart TD
|
|
47
|
+
classDef base fill:#08131f,stroke:#1ea7ff,color:#dff6ff,stroke-width:1px;
|
|
48
|
+
classDef accent fill:#0f2233,stroke:#ffd166,color:#fff4cc,stroke-width:1.5px;
|
|
49
|
+
|
|
50
|
+
Browser["Main thread browser host"]:::accent --> Ui["canvas HUD and network view"]:::base
|
|
51
|
+
Browser --> Handle["FlappyBirdRunHandle\nstop isRunning done"]:::base
|
|
52
|
+
Browser --> Protocol["worker-channel\nmessage transport"]:::base
|
|
53
|
+
Protocol --> Worker["worker-owned evolution\nand packed playback frames"]:::base
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
For background on why the boundary keeps simulation authority off the main
|
|
57
|
+
thread, see MDN,
|
|
58
|
+
[Using Web Workers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers),
|
|
59
|
+
which captures the browser execution model this example leans on.
|
|
60
|
+
|
|
61
|
+
Example: start the demo and stop it from embedding code later.
|
|
17
62
|
|
|
18
|
-
Minimal browser start example:
|
|
19
63
|
```ts
|
|
20
64
|
import { start } from './browser-entry/browser-entry';
|
|
21
65
|
|
|
22
66
|
const handle = await start('flappy-bird-output');
|
|
23
|
-
|
|
67
|
+
setTimeout(() => handle.stop(), 10_000);
|
|
24
68
|
await handle.done;
|
|
25
69
|
```
|
|
26
70
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
Runtime --> Network["network-view + visualization/\nnetwork inspection"]
|
|
71
|
+
Example: watch the lifecycle handle while the browser host is running.
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
const handle = await start('flappy-bird-output');
|
|
75
|
+
|
|
76
|
+
console.log(handle.isRunning());
|
|
77
|
+
await handle.done;
|
|
35
78
|
```
|
|
36
79
|
|
|
37
80
|
## browser-entry/browser-entry.ts
|
|
@@ -1,36 +1,79 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Browser
|
|
2
|
+
* Browser teaching surface and lifecycle facade for the Flappy Bird example.
|
|
3
3
|
*
|
|
4
|
-
* This
|
|
5
|
-
* browser
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* This folder is where worker-owned evolution meets human-friendly inspection.
|
|
5
|
+
* The browser side owns DOM setup, HUD updates, playback rendering, and network
|
|
6
|
+
* visualization. The worker side owns the hot-path simulation and packed frame
|
|
7
|
+
* production. `browser-entry/` exists so those responsibilities stay honest
|
|
8
|
+
* instead of drifting into one blurry runtime.
|
|
8
9
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
10
|
+
* That split is the main reason this file stays intentionally small. The public
|
|
11
|
+
* `start(...)` surface should feel simple to call even though the surrounding
|
|
12
|
+
* system is not simple at all. A caller gets one run handle, while the folder
|
|
13
|
+
* behind it fans out into runtime bootstrap, host layout, worker messaging,
|
|
14
|
+
* playback rendering, and inspection views.
|
|
11
15
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
+
* Read this boundary as the browser-side answer to one practical question:
|
|
17
|
+
* how do you make an evolved controller visible and interactive without moving
|
|
18
|
+
* simulation authority back onto the main thread? The answer is a stable entry
|
|
19
|
+
* facade plus a strict authority split between browser presentation and worker
|
|
20
|
+
* execution.
|
|
21
|
+
*
|
|
22
|
+
* `index.html` is only the local shell that loads the published bundle and then
|
|
23
|
+
* reaches this same start boundary through globals. If you want the real
|
|
24
|
+
* host/runtime seam, start here rather than with the static shell.
|
|
25
|
+
*
|
|
26
|
+
* Read the folder in three passes. Start with this file for the public
|
|
27
|
+
* lifecycle contract. Continue into `runtime/` and `worker-channel/` for the
|
|
28
|
+
* bootstrap and protocol story. Finish with `host/`, `playback/`,
|
|
29
|
+
* `network-view/`, and `visualization/` for the teaching surface the browser
|
|
30
|
+
* renders around the worker-owned simulation.
|
|
31
|
+
*
|
|
32
|
+
* ```mermaid
|
|
33
|
+
* flowchart LR
|
|
34
|
+
* classDef base fill:#08131f,stroke:#1ea7ff,color:#dff6ff,stroke-width:1px;
|
|
35
|
+
* classDef accent fill:#0f2233,stroke:#ffd166,color:#fff4cc,stroke-width:1.5px;
|
|
36
|
+
*
|
|
37
|
+
* Start["start()"]:::accent --> Runtime["runtime/\nbootstrap orchestration"]:::base
|
|
38
|
+
* Runtime --> Host["host/\nDOM and canvas shell"]:::base
|
|
39
|
+
* Runtime --> Channel["worker-channel/\nworker protocol"]:::base
|
|
40
|
+
* Channel --> Playback["playback/\npopulation rendering"]:::base
|
|
41
|
+
* Runtime --> Network["network-view + visualization/\nnetwork inspection"]:::base
|
|
42
|
+
* ```
|
|
43
|
+
*
|
|
44
|
+
* ```mermaid
|
|
45
|
+
* flowchart TD
|
|
46
|
+
* classDef base fill:#08131f,stroke:#1ea7ff,color:#dff6ff,stroke-width:1px;
|
|
47
|
+
* classDef accent fill:#0f2233,stroke:#ffd166,color:#fff4cc,stroke-width:1.5px;
|
|
48
|
+
*
|
|
49
|
+
* Browser["Main thread browser host"]:::accent --> Ui["canvas HUD and network view"]:::base
|
|
50
|
+
* Browser --> Handle["FlappyBirdRunHandle\nstop isRunning done"]:::base
|
|
51
|
+
* Browser --> Protocol["worker-channel\nmessage transport"]:::base
|
|
52
|
+
* Protocol --> Worker["worker-owned evolution\nand packed playback frames"]:::base
|
|
53
|
+
* ```
|
|
54
|
+
*
|
|
55
|
+
* For background on why the boundary keeps simulation authority off the main
|
|
56
|
+
* thread, see MDN,
|
|
57
|
+
* [Using Web Workers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers),
|
|
58
|
+
* which captures the browser execution model this example leans on.
|
|
59
|
+
*
|
|
60
|
+
* Example: start the demo and stop it from embedding code later.
|
|
16
61
|
*
|
|
17
|
-
* Minimal browser start example:
|
|
18
62
|
* ```ts
|
|
19
63
|
* import { start } from './browser-entry/browser-entry';
|
|
20
64
|
*
|
|
21
65
|
* const handle = await start('flappy-bird-output');
|
|
22
|
-
*
|
|
66
|
+
* setTimeout(() => handle.stop(), 10_000);
|
|
23
67
|
* await handle.done;
|
|
24
68
|
* ```
|
|
25
69
|
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* Runtime --> Network["network-view + visualization/\nnetwork inspection"]
|
|
70
|
+
* Example: watch the lifecycle handle while the browser host is running.
|
|
71
|
+
*
|
|
72
|
+
* ```ts
|
|
73
|
+
* const handle = await start('flappy-bird-output');
|
|
74
|
+
*
|
|
75
|
+
* console.log(handle.isRunning());
|
|
76
|
+
* await handle.done;
|
|
34
77
|
* ```
|
|
35
78
|
*/
|
|
36
79
|
export { start } from './runtime/runtime';
|
|
@@ -7,16 +7,104 @@ explanation, HUD rendering, and network inspection, while the worker owns the
|
|
|
7
7
|
hot path: evolving generations, materializing playback state, advancing the
|
|
8
8
|
simulation, and packaging compact snapshots back to the host.
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
10
|
+
That separation is doing two jobs at once. It protects the browser from
|
|
11
|
+
heavy simulation work, and it turns responsibility into something a reader
|
|
12
|
+
can see directly because every cross-thread handoff must become an explicit
|
|
13
|
+
typed message.
|
|
14
|
+
|
|
15
|
+
Read this folder as the protocol chapter between the browser host and the
|
|
16
|
+
deterministic runtime that actually evolves and replays the flock. The
|
|
17
|
+
important design question is not merely "how do Web Workers run code?" It is
|
|
18
|
+
"which side should own each piece of truth when evolution, playback, and
|
|
19
|
+
inspection all need the same population?"
|
|
20
|
+
|
|
21
|
+
In this example, the answer is deliberate:
|
|
22
|
+
|
|
23
|
+
- the host owns controls, HUD state, and network visualization,
|
|
24
|
+
- the worker owns generation requests, playback stepping, and winner
|
|
25
|
+
selection,
|
|
26
|
+
- packed snapshots are the narrow bridge between those two worlds.
|
|
27
|
+
|
|
28
|
+
## What This Folder Is Trying To Teach
|
|
29
|
+
|
|
30
|
+
The worker chapter is organized around four reader questions:
|
|
31
|
+
|
|
32
|
+
1. How does the browser request evolution work without becoming the
|
|
33
|
+
simulation authority?
|
|
34
|
+
2. How does one evolved population become a replayable playback session?
|
|
35
|
+
3. Why are snapshots packed into typed arrays instead of posted as nested
|
|
36
|
+
render objects?
|
|
37
|
+
4. Where should you read next when the protocol is clear but one runtime step
|
|
38
|
+
still feels opaque?
|
|
39
|
+
|
|
40
|
+
## Core Worker Map
|
|
41
|
+
|
|
42
|
+
```mermaid
|
|
43
|
+
flowchart LR
|
|
44
|
+
Host["browser-entry/\nhost UI and controls"] --> Protocol["protocol service\nlegal message transitions"]
|
|
45
|
+
Protocol --> Runtime["runtime service\nworker-local NEAT controller"]
|
|
46
|
+
Runtime --> Evolution["evolution service\nadvance one generation"]
|
|
47
|
+
Runtime --> Playback["playback service\nmaterialize and step population"]
|
|
48
|
+
Playback --> Snapshot["snapshot utils\npacked typed-array transport"]
|
|
49
|
+
Snapshot --> Host
|
|
50
|
+
|
|
51
|
+
WarmStart["warm-start service\ngeneration zero bootstrap"] -.-> Evolution
|
|
52
|
+
Types["worker types\nmessage and DTO contracts"] -.-> Protocol
|
|
53
|
+
|
|
54
|
+
classDef boundary fill:#001522,stroke:#0fb5ff,color:#9fdcff,stroke-width:2px;
|
|
55
|
+
classDef runtime fill:#03111f,stroke:#00e5ff,color:#d8f6ff,stroke-width:2px;
|
|
56
|
+
classDef highlight fill:#2a1029,stroke:#ff4a8d,color:#ffd7e8,stroke-width:3px;
|
|
57
|
+
|
|
58
|
+
class Host,Protocol,Types boundary;
|
|
59
|
+
class Runtime,Evolution,Playback,Snapshot runtime;
|
|
60
|
+
class Snapshot highlight;
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Read the diagram left to right. The host is allowed to request work, but it
|
|
64
|
+
never takes ownership of the worker's mutable simulation state. The worker
|
|
65
|
+
can then optimize for determinism and throughput while the browser optimizes
|
|
66
|
+
for explanation.
|
|
67
|
+
|
|
68
|
+
## Choose Your Route
|
|
69
|
+
|
|
70
|
+
- Start with `flappy-evolution-worker.ts` if you want the high-level message
|
|
71
|
+
lifecycle.
|
|
72
|
+
- Read `flappy-evolution-worker.protocol.service.ts` next if you want the
|
|
73
|
+
legal sequencing rules.
|
|
74
|
+
- Read `flappy-evolution-worker.runtime.service.ts` if you want the worker's
|
|
75
|
+
NEAT runtime setup.
|
|
76
|
+
- Read `flappy-evolution-worker.playback.service.ts` and
|
|
77
|
+
`flappy-evolution-worker.simulation.frame.service.ts` if you want the hot
|
|
78
|
+
playback path.
|
|
79
|
+
- Read `flappy-evolution-worker.snapshot.utils.ts` if you want the typed-array
|
|
80
|
+
transport story.
|
|
81
|
+
|
|
82
|
+
Minimal host-side sketch:
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
worker.postMessage({
|
|
86
|
+
type: 'init',
|
|
87
|
+
payload: { populationSize: 50, elitismCount: 10, rngSeed: 12345 },
|
|
88
|
+
});
|
|
89
|
+
worker.postMessage({ type: 'request-generation' });
|
|
90
|
+
worker.postMessage({
|
|
91
|
+
type: 'start-playback',
|
|
92
|
+
payload: { visibleWorldWidthPx: 1280, visibleWorldHeightPx: 720 },
|
|
93
|
+
});
|
|
94
|
+
worker.postMessage({
|
|
95
|
+
type: 'request-playback-step',
|
|
96
|
+
payload: {
|
|
97
|
+
requestId: 1,
|
|
98
|
+
simulationSteps: 2,
|
|
99
|
+
visibleWorldWidthPx: 1280,
|
|
100
|
+
visibleWorldHeightPx: 720,
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
If you want background reading before the symbol shelf, the MDN Web Workers
|
|
106
|
+
guide is the fastest practical reference for why this example pushes both
|
|
107
|
+
evolution and playback off the main thread.
|
|
20
108
|
|
|
21
109
|
## flappy-evolution-worker/flappy-evolution-worker.ts
|
|
22
110
|
|