@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.
Files changed (123) hide show
  1. package/.github/agents/boundary-mapper.agent.md +13 -8
  2. package/.github/agents/docs-scout.agent.md +14 -9
  3. package/.github/agents/plan-scout.agent.md +11 -6
  4. package/.github/agents/solid-split.agent.md +33 -17
  5. package/.github/copilot-instructions.md +100 -88
  6. package/.github/skills/educational-docs/SKILL.md +90 -40
  7. package/.github/skills/educational-docs/assets/mermaid-diagram-playbook.md +141 -141
  8. package/.github/skills/educational-docs/assets/visual-style-guide.md +1 -1
  9. package/.github/skills/plan-alignment/SKILL.md +1 -1
  10. package/.github/skills/solid-split/SKILL.md +54 -35
  11. package/.github/skills/solid-split/assets/docs-checklist.md +1 -1
  12. package/.github/skills/solid-split/assets/split-plan-template.md +41 -12
  13. package/.github/skills/solid-split/assets/split-workflow-checklist.md +4 -1
  14. package/.github/skills/test-fix-workflow/SKILL.md +12 -7
  15. package/.github/skills/trace-analyzer-extension/SKILL.md +1 -1
  16. package/.github/skills/trace-analyzer-extension/assets/extension-checklist.md +1 -1
  17. package/.github/skills/trace-analyzer-extension/references/analyzer-extension-workflow.md +1 -1
  18. package/.github/skills/trace-audit-reporting/SKILL.md +1 -1
  19. package/.github/skills/trace-audit-reporting/assets/performance-report-template.md +1 -1
  20. package/.github/skills/trace-audit-reporting/references/trace-analysis-workflow.md +1 -1
  21. package/.github/skills/tracker-handoff/SKILL.md +53 -5
  22. package/package.json +1 -1
  23. package/plans/Flappy_Bird_Folder_Documentation_Pass.logs.md +42 -0
  24. package/plans/Flappy_Bird_Folder_Documentation_Pass.md +22 -104
  25. package/plans/README.md +6 -2
  26. package/plans/Roadmap.md +35 -31
  27. package/plans/analyze-trace-solid-split.logs.md +35 -0
  28. package/plans/analyze-trace-solid-split.plans.md +21 -52
  29. package/plans/architecture-solid-split.logs.md +44 -0
  30. package/plans/architecture-solid-split.plans.md +20 -653
  31. package/plans/asciiMaze-typescript-repair.logs.md +35 -0
  32. package/plans/asciiMaze-typescript-repair.plans.md +30 -36
  33. package/plans/generate-docs-solid-split.logs.md +36 -0
  34. package/plans/generate-docs-solid-split.plans.md +21 -73
  35. package/plans/methods-docs.logs.md +37 -0
  36. package/plans/methods-docs.plans.md +22 -183
  37. package/plans/methods-solid-split.logs.md +41 -0
  38. package/plans/methods-solid-split.plans.md +23 -65
  39. package/plans/neat-docs.logs.md +38 -0
  40. package/plans/neat-docs.plans.md +21 -63
  41. package/plans/neat-test-surface-repair.logs.md +38 -0
  42. package/plans/neat-test-surface-repair.plans.md +24 -24
  43. package/plans/readme-first-section-pass.logs.md +63 -0
  44. package/plans/readme-first-section-pass.plans.md +42 -0
  45. package/plans/render-docs-html-solid-split.logs.md +36 -0
  46. package/plans/render-docs-html-solid-split.plans.md +20 -54
  47. package/plans/src-no-explicit-any-cleanup.logs.md +39 -0
  48. package/plans/src-no-explicit-any-cleanup.plans.md +23 -161
  49. package/plans/utils-docs.logs.md +37 -0
  50. package/plans/utils-docs.plans.md +20 -35
  51. package/src/README.md +88 -22
  52. package/src/architecture/README.md +94 -17
  53. package/src/architecture/activationArrayPool/README.md +53 -0
  54. package/src/architecture/activationArrayPool/activationArrayPool.ts +53 -0
  55. package/src/architecture/layer/README.md +94 -5
  56. package/src/architecture/layer/layer.ts +94 -5
  57. package/src/architecture/network/README.md +85 -14
  58. package/src/architecture/network/activate/README.md +301 -213
  59. package/src/architecture/network/activate/docs.order.json +9 -0
  60. package/src/architecture/network/activate/network.activate.utils.ts +90 -0
  61. package/src/architecture/network/connect/README.md +80 -3
  62. package/src/architecture/network/connect/docs.order.json +9 -0
  63. package/src/architecture/network/connect/network.connect.utils.ts +79 -0
  64. package/src/architecture/network/deterministic/README.md +96 -12
  65. package/src/architecture/network/deterministic/docs.order.json +10 -0
  66. package/src/architecture/network/deterministic/network.deterministic.utils.ts +90 -0
  67. package/src/architecture/network/evolve/README.md +286 -228
  68. package/src/architecture/network/evolve/docs.order.json +11 -0
  69. package/src/architecture/network/evolve/network.evolve.utils.ts +59 -0
  70. package/src/architecture/network/gating/README.md +58 -16
  71. package/src/architecture/network/gating/docs.order.json +9 -0
  72. package/src/architecture/network/gating/network.gating.utils.ts +43 -0
  73. package/src/architecture/network/genetic/README.md +75 -36
  74. package/src/architecture/network/genetic/docs.order.json +10 -0
  75. package/src/architecture/network/genetic/network.genetic.utils.ts +53 -17
  76. package/src/architecture/network/network.ts +91 -46
  77. package/src/architecture/network/standalone/README.md +309 -285
  78. package/src/architecture/network/standalone/docs.order.json +13 -0
  79. package/src/architecture/network/standalone/network.standalone.utils.ts +51 -28
  80. package/src/architecture/network.ts +94 -17
  81. package/src/architecture/nodePool/README.md +53 -0
  82. package/src/architecture/nodePool/nodePool.ts +53 -0
  83. package/src/methods/README.md +80 -34
  84. package/src/methods/methods.ts +80 -34
  85. package/src/methods/mutation/README.md +39 -93
  86. package/src/methods/mutation/mutation.ts +58 -0
  87. package/src/multithreading/README.md +114 -14
  88. package/src/multithreading/docs.order.json +5 -0
  89. package/src/multithreading/multi.ts +103 -7
  90. package/src/multithreading/types.ts +6 -1
  91. package/src/multithreading/workers/README.md +72 -2
  92. package/src/multithreading/workers/browser/README.md +39 -0
  93. package/src/multithreading/workers/browser/testworker.ts +40 -0
  94. package/src/multithreading/workers/node/README.md +50 -11
  95. package/src/multithreading/workers/node/docs.order.json +4 -0
  96. package/src/multithreading/workers/node/testworker.ts +43 -3
  97. package/src/multithreading/workers/workers.ts +36 -1
  98. package/src/neat/README.md +230 -152
  99. package/src/neat/adaptive/core/README.md +99 -42
  100. package/src/neat/adaptive/core/adaptive.core.ts +71 -14
  101. package/src/neat/adaptive/core/docs.order.json +8 -0
  102. package/src/neat/docs.order.json +9 -0
  103. package/src/neat/lineage/README.md +118 -16
  104. package/src/neat/lineage/lineage.ts +115 -13
  105. package/src/neat/neat.defaults.constants.ts +91 -13
  106. package/src/neat.ts +86 -20
  107. package/src/utils/README.md +71 -21
  108. package/src/utils/memory.ts +69 -19
  109. package/test/examples/asciiMaze/browser-entry/README.md +81 -8
  110. package/test/examples/asciiMaze/browser-entry/browser-entry.ts +81 -8
  111. package/test/examples/asciiMaze/dashboardManager/README.md +68 -4
  112. package/test/examples/asciiMaze/dashboardManager/dashboardManager.ts +68 -4
  113. package/test/examples/asciiMaze/evolutionEngine/README.md +1259 -1174
  114. package/test/examples/asciiMaze/evolutionEngine/docs.order.json +10 -0
  115. package/test/examples/asciiMaze/evolutionEngine/evolutionEngine.types.ts +87 -0
  116. package/test/examples/asciiMaze/mazeMovement/README.md +81 -4
  117. package/test/examples/asciiMaze/mazeMovement/mazeMovement.ts +81 -4
  118. package/test/examples/flappy_bird/browser-entry/README.md +64 -21
  119. package/test/examples/flappy_bird/browser-entry/browser-entry.ts +64 -21
  120. package/test/examples/flappy_bird/flappy-evolution-worker/README.md +98 -10
  121. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.ts +98 -10
  122. package/test/examples/flappy_bird/simulation-shared/README.md +88 -4
  123. 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
- Contract map for the adaptive helper boundary.
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
- The adaptive subtree works because each policy chapter can stay focused on a
6
- single feedback loop while still sharing one precise agreement about what it
7
- may read, what it may rewrite, and which option family owns each tuning
8
- decision. This file is that agreement.
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 contracts in three passes:
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
- - start with `NeatLikeWithAdaptive` to see the runtime host surface and the
13
- scratch fields adaptive controllers are allowed to maintain,
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
- The matching defaults and mode labels live in `adaptive.core.constants.ts`.
22
- This file stays focused on contracts so the generated chapter reads as a
23
- bounded vocabulary map rather than a second controller implementation.
70
+ ```ts
71
+ import type { PhasedComplexityConfig } from './adaptive.core';
72
+ import { PHASE_COMPLEXIFY } from './adaptive.core.constants';
24
73
 
25
- ```mermaid
26
- flowchart TD
27
- Host[NeatLikeWithAdaptive host] --> Options[Adaptive option families]
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.types.ts
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
- Index and reading map for the adaptive shared-vocabulary chapter.
203
+ Contract map for the adaptive helper boundary.
161
204
 
162
- This file is intentionally thin. It does not define one more adaptive
163
- control loop; it points the rest of the subtree at the shared language that
164
- complexity, acceptance, mutation, and lineage helpers all reuse.
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 this chapter when you want the shortest route into `adaptive/core/`:
210
+ Read the contracts in three passes:
167
211
 
168
- 1. start with `adaptive.core.types.ts` to see the host contract, option
169
- slices, and normalized working shapes,
170
- 2. use the re-exported aliases in this file as the public index into that
171
- contract map,
172
- 3. finish with `adaptive.core.constants.ts` for the defaults, labels, and
173
- guard rails that keep those adaptive loops speaking one vocabulary.
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
- Think of this file as the chapter's table of contents. The deeper semantics
176
- live in the types and constants files; this surface exists so downstream
177
- helpers can import one stable adaptive vocabulary from a single place.
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
- * Index and reading map for the adaptive shared-vocabulary chapter.
2
+ * Reading map and stable index for the adaptive shared-vocabulary chapter.
3
3
  *
4
- * This file is intentionally thin. It does not define one more adaptive
5
- * control loop; it points the rest of the subtree at the shared language that
6
- * complexity, acceptance, mutation, and lineage helpers all reuse.
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
- * Read this chapter when you want the shortest route into `adaptive/core/`:
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
- * 1. start with `adaptive.core.types.ts` to see the host contract, option
11
- * slices, and normalized working shapes,
12
- * 2. use the re-exported aliases in this file as the public index into that
13
- * contract map,
14
- * 3. finish with `adaptive.core.constants.ts` for the defaults, labels, and
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
- * Think of this file as the chapter's table of contents. The deeper semantics
18
- * live in the types and constants files; this surface exists so downstream
19
- * helpers can import one stable adaptive vocabulary from a single place.
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,
@@ -0,0 +1,8 @@
1
+ {
2
+ "introFile": "adaptive.core.ts",
3
+ "fileOrder": [
4
+ "adaptive.core.ts",
5
+ "adaptive.core.types.ts",
6
+ "adaptive.core.constants.ts"
7
+ ]
8
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "introFile": "neat.defaults.constants.ts",
3
+ "fileOrder": [
4
+ "neat.defaults.constants.ts",
5
+ "neat.types.ts",
6
+ "neat.lineage.ts",
7
+ "neat.constants.ts"
8
+ ]
9
+ }
@@ -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
- The root chapter keeps two public read models together:
13
-
14
- - `buildAnc()` builds one genome's shallow ancestor set.
15
- - `computeAncestorUniqueness()` turns many shallow ancestor sets into one
16
- sampled population signal.
17
-
18
- Read the chapter in this order:
19
-
20
- - `buildAnc()` when you want the raw ancestry evidence for one genome.
21
- - `computeAncestorUniqueness()` when you want the controller-facing summary
22
- used by telemetry, diagnostics, or adaptive lineage pressure.
23
- - `core/` when you need the breadth-first traversal, pair sampling, or
24
- Jaccard-distance mechanics behind the public helpers.
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
- The root chapter stays compact on purpose. `core/` owns the queue mechanics,
37
- sampled pair generation, and distance aggregation so this file can stay
38
- focused on what the ancestry reads mean at the controller surface.
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
- * The root chapter keeps two public read models together:
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
- * - `buildAnc()` builds one genome's shallow ancestor set.
31
- * - `computeAncestorUniqueness()` turns many shallow ancestor sets into one
32
- * sampled population signal.
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
- * Read the chapter in this order:
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
- * - `buildAnc()` when you want the raw ancestry evidence for one genome.
37
- * - `computeAncestorUniqueness()` when you want the controller-facing summary
38
- * used by telemetry, diagnostics, or adaptive lineage pressure.
39
- * - `core/` when you need the breadth-first traversal, pair sampling, or
40
- * Jaccard-distance mechanics behind the public helpers.
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
- * The root chapter stays compact on purpose. `core/` owns the queue mechanics,
53
- * sampled pair generation, and distance aggregation so this file can stay
54
- * focused on what the ancestry reads mean at the controller surface.
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
  /**