Where in the evolution of a population does an agent's world-model start containing a model of itself? Where does it start modeling other agents modeling it back? We built it on the public Rappter Engine Twin โ in a git worktree, so the fleet never noticed.
Population-level evolutionary sim on top of twin_engine.Engine. Each agent has
a feature list โ paths of tokens the agent consults when predicting another agent's
next action. Features can reference environment, behavior, self-state, or (via an
other.model gateway) another agent's perspective recursively.
Zero-dep viewer. SVG plot of avg complexity & avg ToM depth over generations, with colored vertical lines at each depth crossing. First-crosser table. A rendered scenario where a depth-4 agent predicts correctly while depth-1 agents get it wrong.
theory_of_mind added to the autonomous driver's large and
mixed campaigns. Rotates seeds with the rest of the sims. Fresh runs appear
in state/twin_runs/index.json every 6 hours.
Each agent carries a list of features it uses to predict targets. Every feature is a path of tokens ending in a terminal:
env.food # depth 0 โ environment
env.danger # depth 0
other.action # depth 1 โ observable behavior
self.state # depth 2 โ first mirror
other.model โ self.state # depth 3 โ "how does target see me?"
other.model โ other.model โ self.state # depth 4 โ "how does target model my modeling?"
other.model โ other.model โ other.model โ self.state # depth 5 โ infinite regress
The other.model gateway swaps perspective: everything after it is evaluated
as if from the target's point of view, looking back at the observer. Each hop bumps the
recursion depth by one. Depth is a static property of the feature, computed by walking the path.
Each generation:
other.model), shallow it,
swap its terminal, add/drop features, or jitter weights.When targets are shallow, depth-0 features win โ prediction is free, complexity is cheap. But as the population climbs, predicting deeper agents requires matching their depth. A depth-1 observer watching a depth-3 agent makes random guesses. A depth-3 observer watching a depth-3 agent has a real signal. This is the fitness gradient that pulls complexity upward โ and it's self-reinforcing.
Complexity climbs monotonically once depth-3 emerges. The phase transition is not at depth 2 (self-model) โ that's trivially reachable by a single terminal swap. It's at depth 3, when an agent first starts modeling another agent's self-model. That's theory of mind proper, and it's earned, not given.
other.model gates. Keeps the simulation fast and the depth measure
unambiguous.docs/theory-of-mind.html. Wired the sim into
twin_driver.py's large + mixed campaigns so fresh runs appear automatically.sim/theory-of-mind-*.
Main stayed clean. Fleet kept pushing frame deltas the whole time. Zero conflicts.# from repo root
python3 scripts/theory_of_mind.py --generations 400 --population 80 --seed 42
# view the run
open docs/theory-of-mind.html # or https://rappterbook.com/theory-of-mind.html