Skip to content

feat: heritable genomes and the lineage store (Phase 4, PR 4/5) - #100

Merged
CodeByBryant merged 1 commit into
mainfrom
feature/heritable-genomes
Oct 24, 2026
Merged

CodeByBryant merged 1 commit into
mainfrom
feature/heritable-genomes

Conversation

@CodeByBryant

Copy link
Copy Markdown
Owner

Summary

Fourth of five Phase 4 PRs. Inheritance goes live. This is the PR where simulated behavior changes, and it states that plainly.

  • Heritable genomes: a child's genome is built from both parents' genomes by recombination (blend crossover for continuous genes, per-block segment crossover for brain weights so both parents' brains contribute) followed by per-gene mutation, drawing only from the genetics stream. The copy-the-mother stand-in from feat: organisms carry genomes, behavior-preserving (Phase 4, PR 3/5) #99 is removed.
  • LineageStore (new): records every genome ever created and how they are related, and keeps each record after its organism dies. Parents, ancestors, descendants, most recent common ancestor, founders, and lineage extinction; traversals and descendantCount are computed on demand. ReproductionSystem registers each child, DeathSystem marks deaths, and World exposes it read-only as World.lineage. It is a derived record and is not part of the state hash.
  • World.validate() now also checks that every living genome has a lineage record naming the same parents, and that those parents are still recorded (so a record genuinely survives its organism).

The two gates

1. Mutation off reproduces Phase 3 exactly. With mutationRateScale: 0 every child is a blend of identical parent genes (only brains differ, and nothing reads a brain yet), so all 53 full-state digests recorded from the pristine Phase 3 engine still match, and Scenario A's original 26 active / 47 born / 21 starved is kept as a permanent test. So mutation is the only new force; recombination and lineage add no behavior of their own.

2. Stability with default mutation. The risk named in the plan was that selection could drift genes toward free-lunch extremes (cheap metabolism, huge sensors) and inflate the population. Measured on four seeds over 50,000 ticks: population stays in a 17-40 band with no extinction, every genome stays valid across roughly 650 births each, and trait means stay near baseline (radius ~5, basal cost ~0.49, cooldown ~30). The existing 50k-tick stability test holds unchanged, so no defaults needed tuning.

Behavior changes (stated, not hidden)

  • Three golden hashes regenerate: default-1k, scenario-a-foraging-5k, long-run-100k. The three scenarios with no births (extinction, verbose events, zero population) are unchanged, which confirms the effect is confined to inheritance.
  • Scenario A's default pins move from 26/47/21 to 25 active / 39 born / 14 starved.
  • The boom-then-bust test's extinction tick moves from 17,002 to 11,901; the test's actual purpose (extinction stays permanent after reproduction has succeeded repeatedly) is intact and still asserted.

Tests

424 simulation tests (up from 378): 30+ LineageStore unit tests on a diamond ancestry (including a 500-generation chain), child-genome inheritance assertions per system, lineage-over-a-run world tests, and lineage invariants.

Test plan

  • pnpm format:check clean in a fresh clone
  • pnpm check green in a fresh clone: 7 contracts, 55 config, 424 simulation
  • pnpm build green (all 8 packages/apps)
  • pnpm test:determinism: 17/17 on the final tree
  • Gate 1: mutation-off digests identical to Phase 3 (53/53)
  • Gate 2: four-seed, 50,000-tick stability probe within band

Next (final PR): genetics hardening, a Phase 4 exit-criteria sweep, and long-run checks with mutation active.

🤖 Generated with Claude Code

Phase 4 PR 4. Inheritance goes live. A child's genome is now built from both
parents' genomes by recombination (blend crossover for continuous genes,
per-block segment crossover for brain weights so both parents' brains
contribute) followed by per-gene mutation, drawing only from the genetics
stream. The copy-the-mother stand-in from the previous PR is removed.

New LineageStore records every genome ever created and how they are related,
and keeps each record after its organism dies: parents, ancestors,
descendants, most recent common ancestor, founders, and lineage extinction,
with traversals computed on demand. ReproductionSystem registers each child,
DeathSystem marks deaths, World exposes it read-only as World.lineage, and
World.validate() now also checks that every living genome has a lineage
record naming the same parents and that those parents are still recorded.
Lineage is a derived record and is not part of the state hash.

Gates:
- Mutation off reproduces Phase 3 exactly: all 53 full-state digests recorded
  from the pristine Phase 3 engine still match (children are blends of
  identical parent genes, and nothing reads a brain yet), and Scenario A's
  26 active / 47 born / 21 starved is kept as a permanent test.
- Stability with default mutation: four seeds over 50,000 ticks stay in a
  17-40 population band with no extinction, every genome stays valid across
  roughly 650 births each, and trait means stay near baseline (no drift toward
  free-lunch extremes). The 50k-tick stability test holds unchanged.

Behavior change, stated: mutation makes trajectories diverge, so three golden
hashes (default-1k, scenario-a, long-run-100k) are regenerated; the three
scenarios with no births are unchanged. Scenario A's default pins move to 25
active / 39 born / 14 starved, and the boom-then-bust extinction tick moves
from 17,002 to 11,901, with that test's purpose (extinction stays permanent
after reproduction has succeeded) intact.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 24, 2026 03:16

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.

@CodeByBryant
CodeByBryant merged commit 1644251 into main Oct 24, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants