@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,39 +1,82 @@
|
|
|
1
1
|
# neat/adaptive/core
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Reading map and stable index for the adaptive shared-vocabulary chapter.
|
|
4
|
+
|
|
5
|
+
The other adaptive folders explain concrete feedback loops: acceptance
|
|
6
|
+
rewrites scores, complexity rewrites structural budgets, mutation rewrites
|
|
7
|
+
per-genome pressure, and lineage rewrites future diversity pressure. This
|
|
8
|
+
folder exists for the question underneath all of them: what shared language
|
|
9
|
+
lets those controllers stay narrow without each one inventing its own host
|
|
10
|
+
contract, option slice, scratch-field names, and fallback constants?
|
|
11
|
+
|
|
12
|
+
That is why `adaptive/core/` should be read as a glossary with ownership,
|
|
13
|
+
not as a bag of types. `adaptive.core.types.ts` defines what adaptive
|
|
14
|
+
helpers are allowed to read and rewrite. `adaptive.core.constants.ts`
|
|
15
|
+
defines the shared defaults, mode names, and numeric guard rails that keep
|
|
16
|
+
those helpers speaking the same policy dialect. This file is the stable
|
|
17
|
+
import surface that points later helpers at both shelves without making them
|
|
18
|
+
depend on file-by-file internals.
|
|
19
|
+
|
|
20
|
+
A useful mental model is to treat the chapter as the protocol layer between
|
|
21
|
+
adaptive controllers. Complexity, acceptance, mutation, and lineage each own
|
|
22
|
+
a different control loop, but they still have to agree on the shape of the
|
|
23
|
+
host, the option slices they may inspect, and the small amount of adaptive
|
|
24
|
+
state they may persist across generations.
|
|
4
25
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
26
|
+
```mermaid
|
|
27
|
+
flowchart TD
|
|
28
|
+
Core[adaptive core index] --> Types[types<br/>host contract and working shapes]
|
|
29
|
+
Core --> Constants[constants<br/>defaults modes and guard rails]
|
|
30
|
+
Types --> Acceptance[acceptance helpers]
|
|
31
|
+
Types --> Complexity[complexity helpers]
|
|
32
|
+
Types --> Mutation[mutation helpers]
|
|
33
|
+
Types --> Lineage[lineage helpers]
|
|
34
|
+
Constants --> Acceptance
|
|
35
|
+
Constants --> Complexity
|
|
36
|
+
Constants --> Mutation
|
|
37
|
+
Constants --> Lineage
|
|
38
|
+
```
|
|
9
39
|
|
|
10
|
-
Read the
|
|
40
|
+
Read the chapter in three passes:
|
|
41
|
+
|
|
42
|
+
1. start with `adaptive.core.types.ts` when the missing question is what an
|
|
43
|
+
adaptive helper may legally read or rewrite,
|
|
44
|
+
2. continue through the re-exported aliases in this file when you want the
|
|
45
|
+
shortest stable import path for that vocabulary,
|
|
46
|
+
3. finish with `adaptive.core.constants.ts` when the missing question is
|
|
47
|
+
which defaults, phase labels, thresholds, and clamps keep the adaptive
|
|
48
|
+
loops aligned.
|
|
49
|
+
|
|
50
|
+
Example: type a new adaptive helper against the shared host contract instead
|
|
51
|
+
of a broader `Neat` runtime surface.
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
import type {
|
|
55
|
+
NeatLikeWithAdaptive,
|
|
56
|
+
ComplexityBudgetConfig,
|
|
57
|
+
} from './adaptive.core';
|
|
58
|
+
|
|
59
|
+
function previewBudget(
|
|
60
|
+
engine: NeatLikeWithAdaptive,
|
|
61
|
+
config: ComplexityBudgetConfig,
|
|
62
|
+
) {
|
|
63
|
+
return { generation: engine.generation, enabled: config.enabled ?? false };
|
|
64
|
+
}
|
|
65
|
+
```
|
|
11
66
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
- continue with the exported `*Config` aliases to see how complexity,
|
|
15
|
-
acceptance, mutation, operator adaptation, and lineage feedback each slice
|
|
16
|
-
the broader options object,
|
|
17
|
-
- finish with `Genome`, `MutationSettings`, `MutationPartitions`, and
|
|
18
|
-
`MutationOutcome` when you want the normalized working shapes used inside
|
|
19
|
-
adaptive mutation helpers.
|
|
67
|
+
Example: keep constants and contracts on one import path when an extracted
|
|
68
|
+
helper needs both a typed option slice and a shared mode label.
|
|
20
69
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
70
|
+
```ts
|
|
71
|
+
import type { PhasedComplexityConfig } from './adaptive.core';
|
|
72
|
+
import { PHASE_COMPLEXIFY } from './adaptive.core.constants';
|
|
24
73
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
Host --> Population[Population runtime state]
|
|
29
|
-
Host --> Scratch[Adaptive scratch fields and telemetry]
|
|
30
|
-
Options --> Complexity[Complexity and phased schedules]
|
|
31
|
-
Options --> Acceptance[Acceptance and minimal criterion]
|
|
32
|
-
Options --> Mutation[Mutation and operator adaptation]
|
|
33
|
-
Options --> Lineage[Ancestor uniqueness and lineage pressure]
|
|
74
|
+
function isComplexifyPhase(config: PhasedComplexityConfig) {
|
|
75
|
+
return (config.initialPhase ?? PHASE_COMPLEXIFY) === PHASE_COMPLEXIFY;
|
|
76
|
+
}
|
|
34
77
|
```
|
|
35
78
|
|
|
36
|
-
## neat/adaptive/core/adaptive.core.
|
|
79
|
+
## neat/adaptive/core/adaptive.core.ts
|
|
37
80
|
|
|
38
81
|
### AdaptiveMutationConfig
|
|
39
82
|
|
|
@@ -155,26 +198,40 @@ This isolates the alternating complexify/simplify schedule from the broader
|
|
|
155
198
|
adaptive options object so phase-oriented helpers can stay narrow and think
|
|
156
199
|
in terms of mode transitions instead of the entire adaptive policy surface.
|
|
157
200
|
|
|
158
|
-
## neat/adaptive/core/adaptive.core.ts
|
|
201
|
+
## neat/adaptive/core/adaptive.core.types.ts
|
|
159
202
|
|
|
160
|
-
|
|
203
|
+
Contract map for the adaptive helper boundary.
|
|
161
204
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
205
|
+
The adaptive subtree works because each policy chapter can stay focused on a
|
|
206
|
+
single feedback loop while still sharing one precise agreement about what it
|
|
207
|
+
may read, what it may rewrite, and which option family owns each tuning
|
|
208
|
+
decision. This file is that agreement.
|
|
165
209
|
|
|
166
|
-
Read
|
|
210
|
+
Read the contracts in three passes:
|
|
167
211
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
212
|
+
- start with `NeatLikeWithAdaptive` to see the runtime host surface and the
|
|
213
|
+
scratch fields adaptive controllers are allowed to maintain,
|
|
214
|
+
- continue with the exported `*Config` aliases to see how complexity,
|
|
215
|
+
acceptance, mutation, operator adaptation, and lineage feedback each slice
|
|
216
|
+
the broader options object,
|
|
217
|
+
- finish with `Genome`, `MutationSettings`, `MutationPartitions`, and
|
|
218
|
+
`MutationOutcome` when you want the normalized working shapes used inside
|
|
219
|
+
adaptive mutation helpers.
|
|
220
|
+
|
|
221
|
+
The matching defaults and mode labels live in `adaptive.core.constants.ts`.
|
|
222
|
+
This file stays focused on contracts so the generated chapter reads as a
|
|
223
|
+
bounded vocabulary map rather than a second controller implementation.
|
|
174
224
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
225
|
+
```mermaid
|
|
226
|
+
flowchart TD
|
|
227
|
+
Host[NeatLikeWithAdaptive host] --> Options[Adaptive option families]
|
|
228
|
+
Host --> Population[Population runtime state]
|
|
229
|
+
Host --> Scratch[Adaptive scratch fields and telemetry]
|
|
230
|
+
Options --> Complexity[Complexity and phased schedules]
|
|
231
|
+
Options --> Acceptance[Acceptance and minimal criterion]
|
|
232
|
+
Options --> Mutation[Mutation and operator adaptation]
|
|
233
|
+
Options --> Lineage[Ancestor uniqueness and lineage pressure]
|
|
234
|
+
```
|
|
178
235
|
|
|
179
236
|
### AdaptiveMutationConfig
|
|
180
237
|
|
|
@@ -1,22 +1,79 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Reading map and stable index for the adaptive shared-vocabulary chapter.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* The other adaptive folders explain concrete feedback loops: acceptance
|
|
5
|
+
* rewrites scores, complexity rewrites structural budgets, mutation rewrites
|
|
6
|
+
* per-genome pressure, and lineage rewrites future diversity pressure. This
|
|
7
|
+
* folder exists for the question underneath all of them: what shared language
|
|
8
|
+
* lets those controllers stay narrow without each one inventing its own host
|
|
9
|
+
* contract, option slice, scratch-field names, and fallback constants?
|
|
7
10
|
*
|
|
8
|
-
*
|
|
11
|
+
* That is why `adaptive/core/` should be read as a glossary with ownership,
|
|
12
|
+
* not as a bag of types. `adaptive.core.types.ts` defines what adaptive
|
|
13
|
+
* helpers are allowed to read and rewrite. `adaptive.core.constants.ts`
|
|
14
|
+
* defines the shared defaults, mode names, and numeric guard rails that keep
|
|
15
|
+
* those helpers speaking the same policy dialect. This file is the stable
|
|
16
|
+
* import surface that points later helpers at both shelves without making them
|
|
17
|
+
* depend on file-by-file internals.
|
|
9
18
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* guard rails that keep those adaptive loops speaking one vocabulary.
|
|
19
|
+
* A useful mental model is to treat the chapter as the protocol layer between
|
|
20
|
+
* adaptive controllers. Complexity, acceptance, mutation, and lineage each own
|
|
21
|
+
* a different control loop, but they still have to agree on the shape of the
|
|
22
|
+
* host, the option slices they may inspect, and the small amount of adaptive
|
|
23
|
+
* state they may persist across generations.
|
|
16
24
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
25
|
+
* ```mermaid
|
|
26
|
+
* flowchart TD
|
|
27
|
+
* Core[adaptive core index] --> Types[types<br/>host contract and working shapes]
|
|
28
|
+
* Core --> Constants[constants<br/>defaults modes and guard rails]
|
|
29
|
+
* Types --> Acceptance[acceptance helpers]
|
|
30
|
+
* Types --> Complexity[complexity helpers]
|
|
31
|
+
* Types --> Mutation[mutation helpers]
|
|
32
|
+
* Types --> Lineage[lineage helpers]
|
|
33
|
+
* Constants --> Acceptance
|
|
34
|
+
* Constants --> Complexity
|
|
35
|
+
* Constants --> Mutation
|
|
36
|
+
* Constants --> Lineage
|
|
37
|
+
* ```
|
|
38
|
+
*
|
|
39
|
+
* Read the chapter in three passes:
|
|
40
|
+
*
|
|
41
|
+
* 1. start with `adaptive.core.types.ts` when the missing question is what an
|
|
42
|
+
* adaptive helper may legally read or rewrite,
|
|
43
|
+
* 2. continue through the re-exported aliases in this file when you want the
|
|
44
|
+
* shortest stable import path for that vocabulary,
|
|
45
|
+
* 3. finish with `adaptive.core.constants.ts` when the missing question is
|
|
46
|
+
* which defaults, phase labels, thresholds, and clamps keep the adaptive
|
|
47
|
+
* loops aligned.
|
|
48
|
+
*
|
|
49
|
+
* Example: type a new adaptive helper against the shared host contract instead
|
|
50
|
+
* of a broader `Neat` runtime surface.
|
|
51
|
+
*
|
|
52
|
+
* ```ts
|
|
53
|
+
* import type {
|
|
54
|
+
* NeatLikeWithAdaptive,
|
|
55
|
+
* ComplexityBudgetConfig,
|
|
56
|
+
* } from './adaptive.core';
|
|
57
|
+
*
|
|
58
|
+
* function previewBudget(
|
|
59
|
+
* engine: NeatLikeWithAdaptive,
|
|
60
|
+
* config: ComplexityBudgetConfig,
|
|
61
|
+
* ) {
|
|
62
|
+
* return { generation: engine.generation, enabled: config.enabled ?? false };
|
|
63
|
+
* }
|
|
64
|
+
* ```
|
|
65
|
+
*
|
|
66
|
+
* Example: keep constants and contracts on one import path when an extracted
|
|
67
|
+
* helper needs both a typed option slice and a shared mode label.
|
|
68
|
+
*
|
|
69
|
+
* ```ts
|
|
70
|
+
* import type { PhasedComplexityConfig } from './adaptive.core';
|
|
71
|
+
* import { PHASE_COMPLEXIFY } from './adaptive.core.constants';
|
|
72
|
+
*
|
|
73
|
+
* function isComplexifyPhase(config: PhasedComplexityConfig) {
|
|
74
|
+
* return (config.initialPhase ?? PHASE_COMPLEXIFY) === PHASE_COMPLEXIFY;
|
|
75
|
+
* }
|
|
76
|
+
* ```
|
|
20
77
|
*/
|
|
21
78
|
export type {
|
|
22
79
|
AdaptiveMutationConfig,
|
|
@@ -9,33 +9,135 @@ telemetry, diagnostics, or adaptive policy need to detect whether a run is
|
|
|
9
9
|
still exploring multiple lineages or quietly collapsing onto descendants of a
|
|
10
10
|
small ancestor set.
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
12
|
+
In evolutionary systems, structural variety can be misleading on its own.
|
|
13
|
+
Two genomes can look different because they drifted locally through weight
|
|
14
|
+
updates or a few recent mutations while still descending from the same narrow
|
|
15
|
+
branch. Lineage reads add the missing genealogical context. They let the
|
|
16
|
+
controller ask whether today's population still contains multiple recent
|
|
17
|
+
family stories or whether most of the search budget is now being spent on one
|
|
18
|
+
ancestor neighborhood wearing several slightly different topologies.
|
|
19
|
+
|
|
20
|
+
That distinction is useful because NEAT already has several other lenses on
|
|
21
|
+
search health. Compatibility distance explains structural disagreement.
|
|
22
|
+
Novelty explains behavioral difference. Score trends explain whether the
|
|
23
|
+
current search path is paying off. Lineage contributes a separate clue: how
|
|
24
|
+
much of the population's recent history is shared. If compatibility says
|
|
25
|
+
genomes are spread out but lineage says they still share recent parents, the
|
|
26
|
+
run may be exploring one branch in detail rather than keeping multiple
|
|
27
|
+
evolutionary bets alive.
|
|
28
|
+
|
|
29
|
+
The core algorithmic idea is intentionally simple. `buildAnc()` performs a
|
|
30
|
+
bounded breadth-first walk over parent ids so it can recover a shallow family
|
|
31
|
+
neighborhood for one genome. `computeAncestorUniqueness()` then samples genome
|
|
32
|
+
pairs and compares those shallow ancestor sets with a Jaccard-style distance.
|
|
33
|
+
The result is not a full phylogenetic tree or a museum-grade genealogy. It is
|
|
34
|
+
a lightweight controller signal designed to stay cheap enough for runtime
|
|
35
|
+
telemetry while still capturing whether the population's recent ancestry is
|
|
36
|
+
broad or collapsing.
|
|
37
|
+
|
|
38
|
+
Read this chapter with two silent reader questions in mind. First: what kind
|
|
39
|
+
of historical evidence is lineage actually measuring? Second: why stop at a
|
|
40
|
+
shallow ancestry window instead of walking every parent back to the origin?
|
|
41
|
+
The answer to the first is recent overlap in parentage, not lifetime
|
|
42
|
+
similarity. The answer to the second is that controller telemetry needs the
|
|
43
|
+
ancestry evidence that is most actionable now. Shallow ancestry is usually a
|
|
44
|
+
better indicator of current branch collapse, takeover, or recent divergence
|
|
45
|
+
than an unbounded tree that keeps every distant common ancestor equally loud.
|
|
46
|
+
|
|
47
|
+
One useful mental model is to treat lineage as the population's memory of
|
|
48
|
+
"who recently came from whom." It does not replace structural or behavioral
|
|
49
|
+
metrics. It complements them. A run with strong scores and low lineage
|
|
50
|
+
uniqueness may be exploiting aggressively around one family. A run with high
|
|
51
|
+
lineage uniqueness and weak scores may still be exploring many recent
|
|
52
|
+
branches without yet consolidating progress. Seeing those regimes explicitly
|
|
53
|
+
helps the rest of the telemetry and adaptation stack read less like a pile of
|
|
54
|
+
unrelated numbers.
|
|
25
55
|
|
|
26
56
|
```mermaid
|
|
27
57
|
flowchart TD
|
|
58
|
+
classDef base fill:#08131f,stroke:#1ea7ff,color:#dff6ff,stroke-width:1px;
|
|
59
|
+
classDef accent fill:#0f2233,stroke:#ffd166,color:#fff4cc,stroke-width:1.5px;
|
|
60
|
+
|
|
28
61
|
Genome[Genome with parent ids] --> Ancestors[Shallow ancestor set]
|
|
29
62
|
Population[Population genomes] --> Pairs[Sample genome pairs]
|
|
30
63
|
Ancestors --> Distance[Compare ancestor overlap]
|
|
31
64
|
Pairs --> Distance
|
|
32
65
|
Distance --> Uniqueness[Ancestor uniqueness summary]
|
|
33
66
|
Uniqueness --> Consumers[Telemetry diagnostics and adaptive lineage policy]
|
|
67
|
+
|
|
68
|
+
class Genome,Ancestors,Population,Pairs,Distance,Consumers base;
|
|
69
|
+
class Uniqueness accent;
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
A second view places lineage beside the other common NEAT health signals so
|
|
73
|
+
a first-time reader can see what question each metric family is really
|
|
74
|
+
answering.
|
|
75
|
+
|
|
76
|
+
```mermaid
|
|
77
|
+
flowchart LR
|
|
78
|
+
classDef base fill:#08131f,stroke:#1ea7ff,color:#dff6ff,stroke-width:1px;
|
|
79
|
+
classDef accent fill:#0f2233,stroke:#ffd166,color:#fff4cc,stroke-width:1.5px;
|
|
80
|
+
|
|
81
|
+
Population[Current population]:::base --> Compat[Compatibility distance<br/>How structurally different?]:::base
|
|
82
|
+
Population --> Novelty[Behavioral novelty<br/>How behaviorally different?]:::base
|
|
83
|
+
Population --> Fitness[Fitness trend<br/>How well is the run scoring?]:::base
|
|
84
|
+
Population --> Lineage[Lineage uniqueness<br/>How many recent families remain?]:::accent
|
|
34
85
|
```
|
|
35
86
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
87
|
+
A third view explains why the implementation stops after a bounded ancestry
|
|
88
|
+
window instead of treating lineage as a full archive query.
|
|
89
|
+
|
|
90
|
+
```mermaid
|
|
91
|
+
flowchart TD
|
|
92
|
+
classDef base fill:#08131f,stroke:#1ea7ff,color:#dff6ff,stroke-width:1px;
|
|
93
|
+
classDef accent fill:#0f2233,stroke:#ffd166,color:#fff4cc,stroke-width:1.5px;
|
|
94
|
+
|
|
95
|
+
FullTree[Walk every ancestor forever]:::base --> Expensive[Expensive and historically noisy]:::base
|
|
96
|
+
Window[Walk only a shallow recent window]:::accent --> Actionable[Cheaper and better aligned to current takeover risk]:::base
|
|
97
|
+
Expensive --> Telemetry[Harder to reuse inside runtime telemetry]:::base
|
|
98
|
+
Actionable --> Telemetry
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
The root chapter therefore stays small in API surface but rich in meaning.
|
|
102
|
+
`core/` owns the queue mechanics, sampled pair generation, and distance
|
|
103
|
+
aggregation so this file can stay focused on what the ancestry reads mean at
|
|
104
|
+
the controller surface. That separation is deliberate: the public question is
|
|
105
|
+
not "how does the queue advance?" but "what kind of evidence does lineage add
|
|
106
|
+
that the rest of the controller does not already have?"
|
|
107
|
+
|
|
108
|
+
For background reading, the most relevant mathematical and traversal ideas
|
|
109
|
+
are the breadth-first search used for the shallow family walk and the Jaccard
|
|
110
|
+
index used to compare ancestor-set overlap. See Wikipedia contributors,
|
|
111
|
+
[Breadth-first search](https://en.wikipedia.org/wiki/Breadth-first_search),
|
|
112
|
+
and Wikipedia contributors,
|
|
113
|
+
[Jaccard index](https://en.wikipedia.org/wiki/Jaccard_index), for compact
|
|
114
|
+
background on the two ideas this chapter adapts into a runtime NEAT signal.
|
|
115
|
+
|
|
116
|
+
Example: inspect the recent family neighborhood behind one genome.
|
|
117
|
+
|
|
118
|
+
```ts
|
|
119
|
+
const ancestorIds = neat.buildAnc(neat.population[0]);
|
|
120
|
+
|
|
121
|
+
console.log([...ancestorIds].toSorted((leftId, rightId) => leftId - rightId));
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Example: watch whether the run is collapsing onto a narrow recent lineage.
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
const ancestorUniqueness = neat.computeAncestorUniqueness();
|
|
128
|
+
|
|
129
|
+
if (ancestorUniqueness < 0.2) {
|
|
130
|
+
console.log('Recent ancestry is collapsing into a narrow family band.');
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Practical reading order:
|
|
135
|
+
|
|
136
|
+
1. Start with `buildAnc()` if you want direct evidence for one genome.
|
|
137
|
+
2. Continue to `computeAncestorUniqueness()` if you want the controller-level
|
|
138
|
+
summary that can feed telemetry or adaptive policy.
|
|
139
|
+
3. Finish in `core/` if you want the exact traversal, pair sampling, and set
|
|
140
|
+
distance mechanics.
|
|
39
141
|
|
|
40
142
|
## neat/lineage/lineage.ts
|
|
41
143
|
|
|
@@ -25,33 +25,135 @@ export type { GenomeLike, NeatLineageContext } from './core/lineage.types';
|
|
|
25
25
|
* still exploring multiple lineages or quietly collapsing onto descendants of a
|
|
26
26
|
* small ancestor set.
|
|
27
27
|
*
|
|
28
|
-
*
|
|
28
|
+
* In evolutionary systems, structural variety can be misleading on its own.
|
|
29
|
+
* Two genomes can look different because they drifted locally through weight
|
|
30
|
+
* updates or a few recent mutations while still descending from the same narrow
|
|
31
|
+
* branch. Lineage reads add the missing genealogical context. They let the
|
|
32
|
+
* controller ask whether today's population still contains multiple recent
|
|
33
|
+
* family stories or whether most of the search budget is now being spent on one
|
|
34
|
+
* ancestor neighborhood wearing several slightly different topologies.
|
|
29
35
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
36
|
+
* That distinction is useful because NEAT already has several other lenses on
|
|
37
|
+
* search health. Compatibility distance explains structural disagreement.
|
|
38
|
+
* Novelty explains behavioral difference. Score trends explain whether the
|
|
39
|
+
* current search path is paying off. Lineage contributes a separate clue: how
|
|
40
|
+
* much of the population's recent history is shared. If compatibility says
|
|
41
|
+
* genomes are spread out but lineage says they still share recent parents, the
|
|
42
|
+
* run may be exploring one branch in detail rather than keeping multiple
|
|
43
|
+
* evolutionary bets alive.
|
|
33
44
|
*
|
|
34
|
-
*
|
|
45
|
+
* The core algorithmic idea is intentionally simple. `buildAnc()` performs a
|
|
46
|
+
* bounded breadth-first walk over parent ids so it can recover a shallow family
|
|
47
|
+
* neighborhood for one genome. `computeAncestorUniqueness()` then samples genome
|
|
48
|
+
* pairs and compares those shallow ancestor sets with a Jaccard-style distance.
|
|
49
|
+
* The result is not a full phylogenetic tree or a museum-grade genealogy. It is
|
|
50
|
+
* a lightweight controller signal designed to stay cheap enough for runtime
|
|
51
|
+
* telemetry while still capturing whether the population's recent ancestry is
|
|
52
|
+
* broad or collapsing.
|
|
35
53
|
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
54
|
+
* Read this chapter with two silent reader questions in mind. First: what kind
|
|
55
|
+
* of historical evidence is lineage actually measuring? Second: why stop at a
|
|
56
|
+
* shallow ancestry window instead of walking every parent back to the origin?
|
|
57
|
+
* The answer to the first is recent overlap in parentage, not lifetime
|
|
58
|
+
* similarity. The answer to the second is that controller telemetry needs the
|
|
59
|
+
* ancestry evidence that is most actionable now. Shallow ancestry is usually a
|
|
60
|
+
* better indicator of current branch collapse, takeover, or recent divergence
|
|
61
|
+
* than an unbounded tree that keeps every distant common ancestor equally loud.
|
|
62
|
+
*
|
|
63
|
+
* One useful mental model is to treat lineage as the population's memory of
|
|
64
|
+
* "who recently came from whom." It does not replace structural or behavioral
|
|
65
|
+
* metrics. It complements them. A run with strong scores and low lineage
|
|
66
|
+
* uniqueness may be exploiting aggressively around one family. A run with high
|
|
67
|
+
* lineage uniqueness and weak scores may still be exploring many recent
|
|
68
|
+
* branches without yet consolidating progress. Seeing those regimes explicitly
|
|
69
|
+
* helps the rest of the telemetry and adaptation stack read less like a pile of
|
|
70
|
+
* unrelated numbers.
|
|
41
71
|
*
|
|
42
72
|
* ```mermaid
|
|
43
73
|
* flowchart TD
|
|
74
|
+
* classDef base fill:#08131f,stroke:#1ea7ff,color:#dff6ff,stroke-width:1px;
|
|
75
|
+
* classDef accent fill:#0f2233,stroke:#ffd166,color:#fff4cc,stroke-width:1.5px;
|
|
76
|
+
*
|
|
44
77
|
* Genome[Genome with parent ids] --> Ancestors[Shallow ancestor set]
|
|
45
78
|
* Population[Population genomes] --> Pairs[Sample genome pairs]
|
|
46
79
|
* Ancestors --> Distance[Compare ancestor overlap]
|
|
47
80
|
* Pairs --> Distance
|
|
48
81
|
* Distance --> Uniqueness[Ancestor uniqueness summary]
|
|
49
82
|
* Uniqueness --> Consumers[Telemetry diagnostics and adaptive lineage policy]
|
|
83
|
+
*
|
|
84
|
+
* class Genome,Ancestors,Population,Pairs,Distance,Consumers base;
|
|
85
|
+
* class Uniqueness accent;
|
|
86
|
+
* ```
|
|
87
|
+
*
|
|
88
|
+
* A second view places lineage beside the other common NEAT health signals so
|
|
89
|
+
* a first-time reader can see what question each metric family is really
|
|
90
|
+
* answering.
|
|
91
|
+
*
|
|
92
|
+
* ```mermaid
|
|
93
|
+
* flowchart LR
|
|
94
|
+
* classDef base fill:#08131f,stroke:#1ea7ff,color:#dff6ff,stroke-width:1px;
|
|
95
|
+
* classDef accent fill:#0f2233,stroke:#ffd166,color:#fff4cc,stroke-width:1.5px;
|
|
96
|
+
*
|
|
97
|
+
* Population[Current population]:::base --> Compat[Compatibility distance<br/>How structurally different?]:::base
|
|
98
|
+
* Population --> Novelty[Behavioral novelty<br/>How behaviorally different?]:::base
|
|
99
|
+
* Population --> Fitness[Fitness trend<br/>How well is the run scoring?]:::base
|
|
100
|
+
* Population --> Lineage[Lineage uniqueness<br/>How many recent families remain?]:::accent
|
|
101
|
+
* ```
|
|
102
|
+
*
|
|
103
|
+
* A third view explains why the implementation stops after a bounded ancestry
|
|
104
|
+
* window instead of treating lineage as a full archive query.
|
|
105
|
+
*
|
|
106
|
+
* ```mermaid
|
|
107
|
+
* flowchart TD
|
|
108
|
+
* classDef base fill:#08131f,stroke:#1ea7ff,color:#dff6ff,stroke-width:1px;
|
|
109
|
+
* classDef accent fill:#0f2233,stroke:#ffd166,color:#fff4cc,stroke-width:1.5px;
|
|
110
|
+
*
|
|
111
|
+
* FullTree[Walk every ancestor forever]:::base --> Expensive[Expensive and historically noisy]:::base
|
|
112
|
+
* Window[Walk only a shallow recent window]:::accent --> Actionable[Cheaper and better aligned to current takeover risk]:::base
|
|
113
|
+
* Expensive --> Telemetry[Harder to reuse inside runtime telemetry]:::base
|
|
114
|
+
* Actionable --> Telemetry
|
|
115
|
+
* ```
|
|
116
|
+
*
|
|
117
|
+
* The root chapter therefore stays small in API surface but rich in meaning.
|
|
118
|
+
* `core/` owns the queue mechanics, sampled pair generation, and distance
|
|
119
|
+
* aggregation so this file can stay focused on what the ancestry reads mean at
|
|
120
|
+
* the controller surface. That separation is deliberate: the public question is
|
|
121
|
+
* not "how does the queue advance?" but "what kind of evidence does lineage add
|
|
122
|
+
* that the rest of the controller does not already have?"
|
|
123
|
+
*
|
|
124
|
+
* For background reading, the most relevant mathematical and traversal ideas
|
|
125
|
+
* are the breadth-first search used for the shallow family walk and the Jaccard
|
|
126
|
+
* index used to compare ancestor-set overlap. See Wikipedia contributors,
|
|
127
|
+
* [Breadth-first search](https://en.wikipedia.org/wiki/Breadth-first_search),
|
|
128
|
+
* and Wikipedia contributors,
|
|
129
|
+
* [Jaccard index](https://en.wikipedia.org/wiki/Jaccard_index), for compact
|
|
130
|
+
* background on the two ideas this chapter adapts into a runtime NEAT signal.
|
|
131
|
+
*
|
|
132
|
+
* Example: inspect the recent family neighborhood behind one genome.
|
|
133
|
+
*
|
|
134
|
+
* ```ts
|
|
135
|
+
* const ancestorIds = neat.buildAnc(neat.population[0]);
|
|
136
|
+
*
|
|
137
|
+
* console.log([...ancestorIds].toSorted((leftId, rightId) => leftId - rightId));
|
|
138
|
+
* ```
|
|
139
|
+
*
|
|
140
|
+
* Example: watch whether the run is collapsing onto a narrow recent lineage.
|
|
141
|
+
*
|
|
142
|
+
* ```ts
|
|
143
|
+
* const ancestorUniqueness = neat.computeAncestorUniqueness();
|
|
144
|
+
*
|
|
145
|
+
* if (ancestorUniqueness < 0.2) {
|
|
146
|
+
* console.log('Recent ancestry is collapsing into a narrow family band.');
|
|
147
|
+
* }
|
|
50
148
|
* ```
|
|
51
149
|
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
150
|
+
* Practical reading order:
|
|
151
|
+
*
|
|
152
|
+
* 1. Start with `buildAnc()` if you want direct evidence for one genome.
|
|
153
|
+
* 2. Continue to `computeAncestorUniqueness()` if you want the controller-level
|
|
154
|
+
* summary that can feed telemetry or adaptive policy.
|
|
155
|
+
* 3. Finish in `core/` if you want the exact traversal, pair sampling, and set
|
|
156
|
+
* distance mechanics.
|
|
55
157
|
*/
|
|
56
158
|
|
|
57
159
|
/**
|