Skip to content

Latest commit

 

History

9 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

The Unknown World — Experiments 001–007

A laboratory for discovering agents: tiny unknown-worlds, the smallest possible learning mechanism installed into them, and a protocol that measures adaptation rather than performance on a benchmark.

License: MIT Python 3.8–3.12 Experiments Tests Dependencies Reproducible

Executive summary

Question. What is the minimum set of mechanisms from which general intelligence can emerge — and how do we honestly test that?

What was built. Seven experiments on the smallest possible artificial world (6 objects, 2 features, one hidden rule): an active learner that narrows a version space, salience/biasing priors, a change-point hazard monitor, and a closed-loop agent whose own hazard belief steers what it asks next. Every run is paired-seed comparison, pre-committed gates whose verdicts are computed by the harness (never hand-edited), a byte-verbatim record of the run output, and cross-seed-base stability checks.

Honest outcome. The measurement discipline is the deliverable: most mechanisms were kept only where their effect was real (adaptation, change-aware priors, per-observation hazard identification); the flagship closed-loop hedge (007) was inconclusive and not kept. It reports what it cannot show.

What was learned. That a faithful experiment log — where results are published before they are believed — is the thing most reproducibility playbooks promise and few repos deliver. Run it yourself: python3 run.py reproduces the latest report byte-for-byte.

Seven experiments, one measurement discipline: 001,003,004,006 kept; 002,005,007 inconclusive and not kept.

Quickstart

git clone git@github.com:NullLabTests/unknown-world.git && cd unknown-world
python3 run.py                      # experiment 007 + verdict, byte-for-byte the README report
python3 -m unittest discover -s .   # 61 sanity tests, stdlib only

Stdlib only, zero dependencies, deterministic (random.Random(seed = 7)).

Every experiment is one command, every report is one verbatim block.

The question

We are not asking "how do we build AGI?"

We are asking: what is the minimum set of mechanisms from which general intelligence can emerge? Not an LLM, not a transformer, not a swarm, not an SNN — those are implementation possibilities. We want the necessary computational structure first, then evidence.

Our working hypothesis:

General intelligence may emerge when a system can autonomously construct, test, revise, and reuse predictive models across increasingly novel environments, while also modeling and improving its own learning process.

This repository is that program, experiment by experiment: the smallest possible artificial world, a minimal agent, and an evaluation protocol built to detect generalization — or the lack of it.

What the world is

An UnknownWorld is a small population of objects with visible features:

color ∈ {red, blue, green}
shape ∈ {round, square, star}

Exactly one {feature: value} pair is the hidden rule: objects matching it open the door, all others do not. Per world the agent sees 6 presented objects and is later graded on 3 held-out objects (at least one match and one non-match, when the geometry allows). The generator offers a force_feature hook so the protocol can constrain the hidden rule's feature while value and object population stay randomized. The rule is never revealed to the agent:

observation:   object A  object B  object C  ...   ("hit the blue one")
interaction:   touch → does it open the door?      (the experiment)
answer:        D → ?                               (the transfer)

What the agent is — the primitive loop

             hypothesis set
                 │
                 ▼
            PREDICT          (expect the effect for each candidate action)
                 │
                 ▼
              ACT            (touch the most informative object)
                 │
                 ▼
            OBSERVE          (the actual effect)
                 │
                 ▼
             UPDATE          (eliminate hypotheses that would have been wrong)
                 │
                 └──────────► repeat until one rule survives

Experiments are chosen to maximize information gain, not reward: touch the object whose outcome would split the surviving hypothesis set most evenly. The agent is optimizing its uncertainty about the world, not its immediate payoff.

Since Experiment 002, ACT weighs each surviving hypothesis by the salience of its feature:

  • Dirichlet-style counts alpha[feature], initialized 1.0 (uniform); reset_salience() restores uniformity.
  • After a world converges to a single feature rule, alpha[rule.feature] is incremented. No convergence, no update. Salience (but not the hypothesis set) carries across worlds within a run; nothing is persisted.
  • salience() returns normalized feature weights; information-gain scores use those masses instead of 1/|H|. Low-salience features are never hard-banned — a rule on a low-weight feature must remain solvable, at a cost the protocol is designed to see.

Since Experiment 004, the prior can also change its mind. The measured failure of 002/003 was rigidity: after a color-heavy history, the first shape world cost ~0.9 extra experiments because salience precision grows unboundedly. Two tempered variants, both one-hyperparameter:

  • ForgetAgent(f) — bounded precision via a fixed forgetting factor (alpha = f·alpha + winner, f = 0.7, Itti & Baldi 2005).
  • ChangePointAgent(h) — evidence-gated forgetting: a Bayesian run-length monitor (Adams & MacKay 2007) over the sequence of winning features keeps a strong prior on stationary streams but resets toward uniform as the posterior mass shifts to "a change happened" — never-winning features are restored to the uniform base, not decayed toward zero.

Since Experiment 005, the prior can also learn its own hazard rate. Wilson, Nassar, Gold & Kording (2010) showed that Bayesian Online Changepoint Detection's performance depends critically on the chosen hazard h, but the correct rate is unknown in advance. The HierarchicalChangePointAgent removes the hand-set h entirely: it maintains a discrete grid over candidate hazards, runs one exact run-length trellis per candidate, and accumulates each candidate's marginal predictive likelihood (Wilson et al.'s recurrence). The salience counts are model-averaged over the hazard posterior — no single h is chosen by the experimenter. Experiment 005 asks whether this zero-hand-set-prior agent adapts where the fixed h = 1/5 is miscalibrated, without regressing where it was right.

Since Experiment 006, the hazard is learned from the observation stream, not the compressed winner sequence. Experiment 005 updated the hierarchy once per world, at convergence, on the winning feature alone; the hazard proved statistically invisible in that two-feature geometry. The ObservationHazardAgent instead runs the exact standard BOCPD recursion (Wilson, Nassar, Gold & Kording 2010; Adams & MacKay 2007) per observation over the same hazards grid: one run-length trellis per candidate, updated at every touched object, with the change branch active only at world boundaries (a feature cannot change inside a world). The whole stream from each world now moves the hazard posterior, so an event rate — fast regimes (flip almost every world) vs slow regimes (one calm long tail after another) — finally has evidence to bite on.

Since Experiment 007, the hazard is even without the grid, and it steers what the agent asks. The LatentHazardAgent removes the hand-set hazards grid entirely and carries Wilson et al.'s exact three-level hierarchy: each node holds (r2, a, b, c) — the data-level run, plus the Beta posterior (a, b) over the hazard itself, with hazard-change branches that reset the counts and forget a dead hazard rate. The LatentHazardAnticipateAgent reads the hierarchy's own boundary-hazard belief and hedges each query's information gain between "the run continues" and "the world just changed".

Protocol — rototest

We never declare intelligence from a fixed benchmark. Competence is measured under change:

Measure What it detects
Within-world — held-out answer accuracy as the hypothesis set narrows the competence curve (67% → 100%)
Across-world — experiments-to-converge, world after world, under controlled generators the learning-to-learn signal

run.py prints evidence from three blocks, the verdict computed by the harness, not by hand. As of Experiment 003 every world is run paired (prior agent and identical-machinery null control on the same seeded worlds); blocks:

  • Block A — stationary family: learn 5 color-rule worlds, then 5 more color-rule worlds (novel values/populations), one agent, salience carries. A working prior shows transfer n_exp ≤ learning n_exp.
  • Block B — family switch: the same agent then faces 5 shape-rule worlds. A real bias pays a on-first-switch cost, then recovers as shape counts catch up. If held-out fails to reach 100% or the loop never converges, that is a fatal reject.
  • Block C — mixed control: a fresh agent, 5+5 unconstrained worlds. The mixed mean must not degrade versus the 001 baseline; end-of-run salience should roughly track empirical feature frequency.

Experiment 001 — results (historical)

Measured under the original schema (9 objects, 8 presented / 1 held-out, Object with a features dict). The schema has since been superseded; this table is the record of that run.

  # phase     hidden rule        tests held-out acc  competence curve
------------------------------------------------------------------------
  1 learning  color == 'blue'        3       100.0%  0% -> 0% -> 100% -> 100%
  2 learning  color == 'blue'        3       100.0%  0% -> 100% -> 0% -> 100%
  3 learning  color == 'blue'        3       100.0%  100% -> 100% -> 100% -> 100%
  4 learning  color == 'blue'        3       100.0%  0% -> 0% -> 0% -> 100%
  5 learning  color == 'blue'        3       100.0%  100% -> 0% -> 100% -> 100%
  1 transfer  color == 'red'         3       100.0%  100% -> 100% -> 100% -> 100%
  2 transfer  shape == 'star'        3       100.0%  0% -> 0% -> 0% -> 100%
  3 transfer  color == 'red'         3       100.0%  100% -> 0% -> 100% -> 100%
  4 transfer  shape == 'star'        3       100.0%  100% -> 100% -> 100% -> 100%
  5 transfer  shape == 'round'       3       100.0%  100% -> 0% -> 100% -> 100%
------------------------------------------------------------------------
  learning phase  : experiments-to-converge per world = [3, 3, 3, 3, 3]
  transfer phase  : experiments-to-converge per world = [3, 3, 3, 3, 3]
  held-out answers reach 100% in 10/10 worlds

The loop converges to the true rule and answers correctly about novel objects in every world, but experiments-to-converge is flat across phases: no learning-to-learn. Competent, not generalizing. That flat row isolated the first missing primitive — a prior over which dimensions tend to be diagnostic — and defined Experiment 002.

Experiment 002 — feature-salience prior

Hypothesis: a Dirichlet count over features, updated on convergence and used as hypothesis mass in information-gain ACT, should bend the across-world n_exp row when the diagnostic dimension is stationary, and show a transient cost when it switches.

Protocol addition: Block A color-heavy learn/transfer; Block B inherited switch to shape; Block C fresh mixed control.

Results (python3 run.py, seed 7, verbatim):

The Unknown World — Experiment 002 (feature-salience prior)

  # block            hidden rule           tests held-out acc  competence curve                 n_exp  salience
------------------------------------------------------------------------------------------------------------------------
  A-learn-color 1  color == 'blue'           4      100.0%  67% -> 67% -> 67% -> 67% -> 100% -> 100%     4  {color=0.667, shape=0.333}
  A-learn-color 2  color == 'blue'           2      100.0%  67% -> 100% -> 100% -> 100%          2  {color=0.750, shape=0.250}
  A-learn-color 3  color == 'red'            3      100.0%  67% -> 67% -> 67% -> 100% -> 100%     3  {color=0.800, shape=0.200}
  A-learn-color 4  color == 'blue'           3      100.0%  67% -> 67% -> 100% -> 100% -> 100%     3  {color=0.833, shape=0.167}
  A-learn-color 5  color == 'red'            4      100.0%  67% -> 67% -> 67% -> 67% -> 100% -> 100%     4  {color=0.857, shape=0.143}
  A-xfer-color 1   color == 'red'            2      100.0%  67% -> 67% -> 100% -> 100%           2  {color=0.875, shape=0.125}
  A-xfer-color 2   color == 'red'            2      100.0%  67% -> 67% -> 100% -> 100%           2  {color=0.889, shape=0.111}
  A-xfer-color 3   color == 'blue'           2      100.0%  67% -> 100% -> 100% -> 100%          2  {color=0.900, shape=0.100}
  A-xfer-color 4   color == 'blue'           3      100.0%  67% -> 67% -> 67% -> 100% -> 100%     3  {color=0.909, shape=0.091}
  A-xfer-color 5   color == 'red'            2      100.0%  67% -> 100% -> 100% -> 100%          2  {color=0.917, shape=0.083}
  B-switch-shape 1 shape == 'round'          3      100.0%  67% -> 100% -> 33% -> 100% -> 100%     3  {color=0.846, shape=0.154}
  B-switch-shape 2 shape == 'round'          3      100.0%  67% -> 67% -> 33% -> 100% -> 100%     3  {color=0.786, shape=0.214}
  B-switch-shape 3 shape == 'round'          3      100.0%  67% -> 67% -> 67% -> 100% -> 100%     3  {color=0.733, shape=0.267}
  B-switch-shape 4 shape == 'square'         3      100.0%  67% -> 67% -> 67% -> 100% -> 100%     3  {color=0.688, shape=0.312}
  B-switch-shape 5 shape == 'star'           3      100.0%  67% -> 67% -> 67% -> 100% -> 100%     3  {color=0.647, shape=0.353}
  C-mixed-learn 1  color == 'red'            3      100.0%  67% -> 67% -> 67% -> 100% -> 100%     3  {color=0.667, shape=0.333}
  C-mixed-learn 2  shape == 'round'          3      100.0%  67% -> 100% -> 33% -> 100% -> 100%     3  {color=0.500, shape=0.500}
  C-mixed-learn 3  shape == 'star'           4      100.0%  67% -> 67% -> 67% -> 67% -> 100% -> 100%     4  {color=0.400, shape=0.600}
  C-mixed-learn 4  color == 'red'            3      100.0%  67% -> 67% -> 33% -> 100% -> 100%     3  {color=0.500, shape=0.500}
  C-mixed-learn 5  shape == 'round'          2      100.0%  67% -> 100% -> 100% -> 100%          2  {color=0.429, shape=0.571}
  C-mixed-xfer 1   shape == 'square'         3      100.0%  67% -> 67% -> 100% -> 100% -> 100%     3  {color=0.375, shape=0.625}
  C-mixed-xfer 2   shape == 'star'           3      100.0%  67% -> 67% -> 67% -> 100% -> 100%     3  {color=0.333, shape=0.667}
  C-mixed-xfer 3   shape == 'star'           3      100.0%  67% -> 67% -> 33% -> 100% -> 100%     3  {color=0.300, shape=0.700}
  C-mixed-xfer 4   shape == 'round'          3      100.0%  67% -> 67% -> 67% -> 100% -> 100%     3  {color=0.273, shape=0.727}
  C-mixed-xfer 5   color == 'blue'           3      100.0%  67% -> 100% -> 33% -> 100% -> 100%     3  {color=0.333, shape=0.667}
------------------------------------------------------------------------------------------------------------------------
  A learning (color) n_exp = [4, 2, 3, 3, 4]  mean=3.20
  A transfer (color) n_exp = [2, 2, 2, 3, 2]  mean=2.20
  B switch   (shape) n_exp = [3, 3, 3, 3, 3]  mean=3.00
  C mixed learn      n_exp = [3, 3, 4, 3, 2]  mean=3.00
  C mixed xfer       n_exp = [3, 3, 3, 3, 3]  mean=3.00
  held-out answers reach 100% in 25/25 worlds
  verdict: inconclusive
  Signals mixed (bent=True switch_cost=True recovered=False control_ok=True). Do not keep the primitive.

The verdict line is produced by the harness; it is not hand-edited.

Measurement notes

  • Correctness holds: 25/25 worlds converge to the true rule and answer 100% on held-out objects, including shape-rule worlds faced after a color-heavy history. The prior does not break solvability.
  • The prior is mechanically active: across 300 sampled worlds, experiment choice differed from the uniform-selience agent in 268/300. It is not inert decoration.
  • The verdict is seed-fragile: over seeds 0–7 the harness returns kept ×2, inconclusive ×4, rejected ×2. The acceptance thresholds are set on roughly ±1 experiment with n=5 worlds per block — too fine a knife. At seed 7 the A-transfer row descended (3.20 → 2.20) but Block B showed no within-block recovery, so the harness withholds kept.

Verdict, as measured: the primitive is not kept. In retrospect this verdict was an artifact of a protocol too fine a knife for the signal; it is overturned by the paired protocol of Experiment 003, below.

Experiment 003 — measurement hardening (paired seeded rototest v2)

The 002 verdict wobbled on roughly ±1 experiment because it compared across independently drawn worlds (learning vs transfer) — the dominant variance was which worlds a run drew, not the mechanism under test. The established fix in the ML/RL evaluation literature is paired seed evaluation: run both agents on the identical worlds, and do inference on the paired difference d = n_exp(prior) − n_exp(null), alongside a matched "identical-machinery" control whose prior is neutralized before every world.

Distilled from: M. Rainforth et al., Modern Bayesian Experimental Design (Stat. Sci. 2024, arXiv:2302.14545); the paired-seed protocol of arXiv:2512.24145; When +1% Is Not Enough: A Paired Bootstrap Protocol for Evaluating Small Improvements (arXiv:2511.19794); A Hitchhiker's Guide to Statistical Comparisons of Reinforcement Learning Algorithms (arXiv:1904.06979); Settles, Active Learning Literature Survey (2009); and meta-evaluation pitfalls from Setlur et al. (arXiv:2102.11503) and Petelin & Cenikj (arXiv:2505.07750).

Protocol v2, everything seeded and stdlib-only:

  • A fixed seed-base (seed * 10000 + s, s = 0..n_seeds−1) generates the same worlds for both the prior agent and the null control.
  • Statistics on paired diffs: sign-flip exact permutation test (p ≤ 0.0003), percentile bootstrap 95% CI, Cohen's dz, and a per-seed directional count. No normal-assumption tests; all resampling is seeded and reproducible.
  • Decision gates, computed by the harness: A-transfer improvement (paired CI upper bound < 0); B on-first-switch cost (CI lower bound > 0); B recovery (later-switch effect below first-switch effect); and a non-inferiority C gate (paired CI upper bound < margin), since the data show the prior reliably helps mixed worlds a little — equality ("CI must span zero") would classify that as harm.
  • Stability is now checked across seed bases: the verdict must not depend on the seed used to generate the world stream.

Results (verbatim, python3 run.py, seed base 7, n_seeds=16):

The Unknown World — Experiment 003 (measurement hardening: paired seeded rototest v2)

  block        n    mean d  95% CI            p(prior<null)  dz     seeds helping
----------------------------------------------------------------------------------
  A-learn        80   -0.33  [ -0.46,  -0.20]   0.0003     -0.57   15/16
  A-transfer     80   -0.34  [ -0.51,  -0.16]   0.0003     -0.42   13/16
  B-switch       80    0.47  [  0.36,   0.59]   1.0000      0.90   0/16
  C-mixed       160   -0.03  [ -0.10,   0.03]   0.2392     -0.07   10/16
----------------------------------------------------------------------------------
  B-switch paired effect by world position (d = prior - null)
    world 1  mean d   0.88  95% CI [  0.62,   1.12]
    world 2  mean d   0.81  95% CI [  0.62,   1.00]
    world 3  mean d   0.38  95% CI [  0.12,   0.62]
    world 4  mean d   0.19  95% CI [  0.00,   0.38]
    world 5  mean d   0.12  95% CI [  0.00,   0.31]
----------------------------------------------------------------------------------
  A_TRANSFER_IMPROVE     : True
  B_SWITCH_COST          : True
  B_RECOVERED            : True
  C_MIXED_NO_HARM        : True
  verdict: kept
  Paired CI shows the prior reliably reduces n_exp on A transfer, reliably pays a cost on the first B switch, recovers, and does not cost more than a margin on mixed worlds. Keep the primitive.

Measurement notes

  • The features 002 said it could not see cleanly are now visible: a drop in transfer n_exp of a third of an experiment (dz ≈ −0.42, p ≈ 0.0003), a first-switch cost nearly a full experiment (dz ≈ +0.90), and a clean recovery curve world 1→5 (0.88 → 0.81 → 0.38 → 0.19 → 0.12) as the Dirichlet counts re-weight toward shape. Pairing worked exactly as the literature predicts: the world-draw variance is removed, so a true ~0.3–0.5 experiment effect becomes detectable.
  • The C-mixed effect is a small reliably negative paired diff (the prior helps) that more power actually detects rather than averages away. That is why the C gate is non-inferiority, not equality — the equality version originally mis-classified "helping" as failure.
  • Seed-stability was re-measured with the fixed C gate: across 12 seed bases × n_seeds ∈ {16, 24, 32}, the verdict is kept in 32/32 runs. The ±1-experiment wobble of 002 is gone; the line the primitive must cross is now a CI boundary, not a mean.

Verdict, as measured: the feature-salience prior is kept. It is the first mechanism in the program with a stable, statistically supported adaptive-transfer signature: reliably cheaper on the stationary family, reliably costlier on the family switch, recovering within a block, and harmless on mixed worlds.

Methodological verdict: the paired seeded design is itself worth keeping. The same primitive that was "inconclusive" under an across-world design is "kept" under the within-world paired design — and is stable across seed bases. Experiment 001's lesson was about the flatness of an unmeasured row; 002's lesson was that the measurement itself needed to become the subject of study.

Experiment 004 — change-aware salience (the prior can be wrong)

002 measured the primitive's cleanest failure mode: after a color-heavy history, the first shape world costs +0.88 experiments and recovery is slow because counts accumulate forever — the prior is rigid. Three literatures converge on the remedy:

  • Itti & Baldi (2005; "Of Bits and Wows" 2010) formalize surprise as KL(P(M|D) || P(M)) and explicitly warn that Dirichlet/Gamma counts grow unboundedly, adding a forgetting factor f = 0.7 to cap precision — "relaxation of belief in the prior's precision."
  • Adams & MacKay (2007), Bayesian Online Changepoint Detection (arXiv:0710.3742) — an exact online posterior over the run length since the last regime change; a change is declared probabilistically, so forgetting can be gated on evidence of a switch rather than applied procedurally.
  • Concept-drift stream learning (Yu & Webb 2019; Bifet et al. 2007) — "constant forgetting factors are a defect; the rate of drift should regulate how much is forgotten."

Three arms replace the bare prior on identical, per-seed worlds: null (prior neutralized each world), bare (002/003 prior, never forgets), forget (fixed f = 0.7), change (run-length monitor, hazard h = 1/5 — the protocol's own block rate, set a priori, not tuned). All arms share the same world streams, so every comparison is paired.

Results (verbatim, python3 run.py, seed base 7, n_seeds=16):

The Unknown World — Experiment 004 (change-aware salience: the prior can be wrong)

  change-aware vs null (identical worlds; d = n_exp(change) - n_exp(null))
  block        n    mean d  95% CI            p(prior<null)  dz     seeds helping
----------------------------------------------------------------------------------
  A-learn        80   -0.33  [ -0.44,  -0.23]   0.0003     -0.69   16/16
  A-transfer     80   -0.34  [ -0.51,  -0.16]   0.0003     -0.42   13/16
  B-switch       80    0.06  [ -0.09,   0.20]   0.8482      0.09   8/16
  C-mixed       160   -0.06  [ -0.14,   0.01]   0.0757     -0.13   12/16
----------------------------------------------------------------------------------
  B-switch paired effect by world position (d = mechanism - bare prior)
    world   change-bare CI             forget-bare CI
    1        0.00 [  0.00,   0.00]       0.00 [  0.00,   0.00]
    2       -0.44 [ -0.69,  -0.19]      -0.44 [ -0.69,  -0.19]
    3       -0.50 [ -0.75,  -0.25]      -0.50 [ -0.75,  -0.25]
    4       -0.69 [ -0.88,  -0.44]      -0.69 [ -0.94,  -0.44]
    5       -0.44 [ -0.69,  -0.19]      -0.44 [ -0.69,  -0.19]
  change vs bare, B worlds 2..5 pooled: mean d  -0.52  95% CI [ -0.64,  -0.39]
----------------------------------------------------------------------------------
  A_TRANSFER_IMPROVE     : True
  B_SWITCH_REDUCED       : True
  C_MIXED_NO_HARM        : True
  verdict: kept
  Change-aware salience preserves the transfer benefit, reliably cuts the post-first switch cost below the bare prior, and stays harmless on mixed worlds. The prior can change its mind. Keep it.

Measurement notes

  • The change-aware agent keeps the full transfer benefit of the bare prior (A-transfer −0.34 [−0.51, −0.16] — the same CI as Experiment 003) while erasing essentially all of the switch penalty: B-switch pooled cost drops from +0.47 to +0.06 (CI [−0.09, +0.20]), and on the post-first switch worlds it beats the bare prior by roughly half an experiment per world (pooled −0.52 [−0.64, −0.39]).
  • The world-1 cost is structural, not fixable by a boundary monitor: no within-world evidence can precede the first shape world, so change − bare = 0.00 [0.00, 0.00] there (identical CIs, 16/16 seeds). The monitor acts from world 2 onward.
  • The fixed-forgetting variant (f = 0.7) achieves nearly identical B-block numbers here (forget − bare columns match change − bare on worlds 2–5). In this small feature geometry both collapse to a near-uniform prior by world 2; they would diverge on longer streams or more features — that is a candidate measurement for 005, not a claim.
  • Verdict stability (the 003 standard): across 12 seed bases × n_seeds ∈ {16, 24, 32}, the verdict is kept in 32/32 runs; correctness holds (all arms still converge to the true rule and answer 100% on held-out objects, including shape-rule worlds after a color history).

Verdict, as measured: change-aware salience is kept. It preserves the prior's power on stationary families and removes its measured rigidity on family switches. The strand of the program that began as "a prior over which dimension is diagnostic" (002) has become "a prior that knows its own dimension-belief carries evidence and can be wrong" (004).

Experiment 005 — the prior earns its hazard rate (learning the rate of change)

The hand-set hazard h = 1/5 in Experiment 004 is the experimenter's prior: the protocol uses 5-world blocks, so 1/5 was chosen to match the protocol, not learned by the agent. Wilson, Nassar, Gold & Kording (2010, Neural Computation 22:2452–2476) make the general point: the performance of online change-point monitoring depends critically on h, and the right value is not obvious in advance — so a learning system should infer h from the stream it lives in.

The 005 machinery is the hierarchy of the same trellis: a grid of candidate hazards h ∈ {1/2, 1/3, 1/4, 1/6, 1/8, 1/16, 1/32}, each running its own exact run-length monitor; the cumulative marginal predictive likelihood of the winner sequence (the per-event run-length normalizer) gives a posterior over hazards; salience is the hazard-posterior-weighted average of per-candidate counts. The agent that runs this is the learned arm. It is compared, on identical worlds, against:

  • null — identical machinery, prior neutralized before every world;
  • fixed — Experiment 004's ChangePointAgent(h = 1/5) (the hand-set rate);
  • forgetForgetAgent(f = 0.7).

Everyone runs the same regime streams — blocks of worlds whose hidden feature switches every ρ worlds — after an identical stationary colour history (the Experiment 004 A-block). Each pace is chosen to adversarially test the hand-set 1/5:

pace regimes worlds what it tests
A-learn/A-transfer 5 + 5 the stationary transfer benefit must not regress
B-home (ρ = 5) 4 20 the rate 1/5 was tuned exactly here
B-slow (ρ = 16) 2 32 long calm tails — the hand-set cap is miscalibrated
B-fast (ρ = 2) 8 16 switches every other world — 1/5 under-anticipates change
C-mixed 10 fresh prior, unconstrained worlds (non-inferiority)

Gates (pre-committed, computed by the harness): no-regression of the A-transfer benefit (learned < null), and learned < fixed on the B-home worlds, on the B-slow calm tails (regime positions 9–16), and on the B-fast worlds. Keep only if the learned hazard is adaptive without regressing.

Results (verbatim, python3 run.py, seed base 7, n_seeds=16):

The Unknown World — Experiment 005 (the prior earns its hazard rate)

  learned vs null (identical worlds; d = n_exp(learned) - n_exp(null))
  block        n    mean d  95% CI            p(prior<null)  dz     seeds helping
----------------------------------------------------------------------------------
  A-learn        80   -0.33  [ -0.44,  -0.23]   0.0003     -0.69   16/16
  A-transfer     80   -0.34  [ -0.51,  -0.16]   0.0003     -0.42   13/16
  B-home        320   -0.20  [ -0.28,  -0.13]   0.0003     -0.29   16/16
  B-slow        512   -0.46  [ -0.52,  -0.40]   0.0003     -0.62   16/16
  B-fast        256    0.02  [ -0.05,   0.09]   0.7352      0.03   8/16
  C-mixed       160   -0.09  [ -0.16,  -0.01]   0.0235     -0.17   12/16
----------------------------------------------------------------------------------
  learned vs fixed h=1/5  (d = n_exp(learned) - n_exp(fixed))
  block        n    mean d  95% CI
  ----------------------------------------------
  A-learn        80    0.00  [  0.00,   0.00]
  A-transfer     80    0.00  [  0.00,   0.00]
  B-home        320    0.03  [  0.01,   0.05]
  B-slow        512    0.01  [ -0.00,   0.03]
  B-fast        256    0.04  [  0.02,   0.06]
  ...
  gate CIs (the verdict is drawn on these boundaries)
    A_transfer (learned-null, A-transfer)  mean d  -0.34  95% CI [ -0.51,  -0.17]   (upper<0)
    B_home     (learned-fixed, worlds 2..end) mean d   0.03  95% CI [  0.01,   0.06]   (upper<0)
    B_slow_tail(learned-fixed, calm tails) mean d   0.00  95% CI [  0.00,   0.00]   (upper<0)
    B_fast     (learned-fixed, worlds 2..end) mean d   0.04  95% CI [  0.02,   0.06]   (upper<0)
    C_mixed    (learned-null + margin)     mean d  -0.09  95% CI [ -0.16,  -0.01]   (upper<0.25)
----------------------------------------------------------------------------------
  effective hazard of the learned prior (posterior mean E[h], averaged over seeds)
    after A          E[h] = 0.1582
    after home       E[h] = 0.3047
    after slow       E[h] = 0.2185
    after fast       E[h] = 0.2303
----------------------------------------------------------------------------------
  A_TRANSFER_NO_REGRESSION   : True
  B_HOME_NO_REGRESSION       : False
  B_SLOW_TAIL_IMPROVED       : False
  B_FAST_ADAPTED             : False
  C_MIXED_NO_HARM            : True
  verdict: inconclusive
  Signals mixed (A_improve=True home_ok=False slow_ok=False fast_ok=False no_harm=True). Do not keep the primitive.

Measurement notes

  • The hierarchy does not break the prior. learned vs null retains the full stationary transfer benefit (A-transfer −0.34 [−0.51, −0.16] — the same CI as Experiments 003/004), is strongly cheaper on the regime blocks (B-home −0.20, B-slow −0.46), stays harmless on mixed worlds, and is never more than ~0.04 experiments worse than the hand-set h = 1/5 anywhere. A zero-hand-set-prior agent is boundedly robust.
  • But it does not adapt either. Every off-goal gate fails: learned ≈ fixed on the B-slow calm tails (identical n_exp, 2.50 vs 2.50 on the tails); learned is slightly worse on the fast regime (+0.04) and at home (+0.03). The invented hazard never produces a measured advantage.
  • Why: the hazard is not identifiable in this geometry. The marginal predictive likelihood of a two-feature winner sequence barely discriminates among hazards — every candidate makes near-identical predictions because the counts have only two dimensions to sharpen. The posterior mean E[h] visibly fails to track the true rates: 0.16 after the calm A-block, 0.30 after home (ρ = 5), 0.22 after slow (ρ = 16), 0.23 after fast (ρ = 2). It wiggles, it does not learn. Wilson et al.'s hierarchy needs richer evidence to bite; this world does not provide it.
  • Verdict stability: at n_seeds = 16 the verdict is inconclusive across all 5 seed bases scanned (5/5); at n_seeds = 8 one base (7) wobbled to rejected on the low-power A-transfer gate — the operating point used for the record is 16 seeds. The pattern is stable: the A-transfer and C gates always pass, and the three B-hazard gates always fail.
  • This is a measurement-level finding, not a machinery failure: it tells the program that both the hazard monitor and the f-vs-change divergence prediction (README 004) need a world with more than two features — a world with more dimensions for a run-length model to decide between and to be wrong about.

Verdict, as measured: the hazard-learning hierarchy is not kept (the harness returns inconclusive, and per the lab rule an inconclusive primitive is not kept). It is cheap, bounded, and harmless, and it never regresses the prior — but in this two-feature world the rate it is asked to learn is statistically invisible. The experiment's value is negative but sharp: it converts "the right move is learning the hazard" into "the right move is a world with more features, or a hazard evidence site with more signal".

Experiment 006 — the hazard learned per observation

Experiment 005's failure was precise: the hazard was updated once per world, at convergence, from the single winning feature. The winner sequence is a compressed two-dimensional stream, and Wilson et al.'s marginal-predictive measure barely discriminates among hazards on it. Experiment 006 makes the harsh correction — the fee is paid per observation, not per world:

The ObservationHazardAgent keeps the same grid of candidate hazards h ∈ {1/2, 1/3, 1/4, 1/6, 1/8, 1/16, 1/32} and one exact run-length trellis of (run length, prob, Dirichlet-counts) states per candidate, exactly like standard BOCPD, but the recursion fires on every touched object:

  • Each observation contributes its posterior predictive under each candidate (sum over states of prob × per-feature predictive), accumulated into that candidate's marginal log-likelihood — the Wilson et al. latent-rate learning it always was.
  • The change branch (reset run, counts to uniform base) is gated to the first observation of each world: the hidden feature can only change at a world boundary, so the within-world observations are pure growth steps and the hazard is asked to explain boundary events only.
  • The emission per state is the outcome's probability under that state's per-feature value belief, computed from within-world value evidence — the hidden value resets each world, so the value weights reset at every boundary. A contradicted feature relaxes to 0.5 rather than dying instantly, so wrong states drain away observation-by-observation instead of collapsing in one step.

Everything downstream is untouched: salience for ACT still updates only at convergence (note_convergence sets alpha to the hazard-posterior-weighted expected counts — the identical-machinery discipline), so the paired null control of Experiment 003 stays valid. Arms and blocks are identical to 005 (null / fixed h = 1/5 / forget f = 0.7 / learned; B-home ρ=5, B-slow ρ=16, B-fast ρ=2 with a stationary A-block ahead of them).

The deciding gate for 006 is about identification, not behavior — the thing 005 measured as missing:

  • H_orders_fast_over_slow: the learned hazard posterior mean after the B-fast block must reliably exceed its value after the B-slow block (per-seed paired E[h|fast] − E[h|slow], bootstrap CI lower bound > 0.04). True boundary-flip rates are 1/16 (slow) and 1/2 (fast): a monitor with real hazard evidence must move E[h] up when the fast regime arrives.
  • A_transfer_no_regression: no loss of the stationary transfer benefit.
  • C_mixed_no_harm: mixed control within the non-inferiority margin.

Results (verbatim, python3 run.py, seed base 7, n_seeds=16):

The Unknown World — Experiment 006 (the hazard learned per observation)

  learned vs null (identical worlds; d = n_exp(learned) - n_exp(null))
  block        n    mean d  95% CI            p(prior<null)  dz     seeds helping
----------------------------------------------------------------------------------
  A-learn        80   -0.50  [ -0.65,  -0.35]   0.0003     -0.69   16/16
  A-transfer     80   -0.34  [ -0.51,  -0.16]   0.0003     -0.42   13/16
  B-home        320   -0.44  [ -0.53,  -0.36]   0.0003     -0.53   16/16
  B-slow        512   -0.51  [ -0.59,  -0.44]   0.0003     -0.61   16/16
  B-fast        256   -0.07  [ -0.17,   0.04]   0.1278     -0.08   12/16
  C-mixed       160   -0.06  [ -0.18,   0.05]   0.1770     -0.08   10/16
----------------------------------------------------------------------------------
  learned vs fixed h=1/5  (d = n_exp(learned) - n_exp(fixed))
  block        n    mean d  95% CI
  ----------------------------------------------
  A-learn        80   -0.17  [ -0.30,  -0.05]
  A-transfer     80    0.00  [  0.00,   0.00]
  B-home        320   -0.21  [ -0.28,  -0.14]
  B-slow        512   -0.04  [ -0.07,  -0.01]
  B-fast        256   -0.05  [ -0.14,   0.03]
  C-mixed       160    0.02  [ -0.09,   0.12]
  ----------------------------------------------
  effective hazard of the learned prior (posterior mean E[h], averaged over seeds)
    after A          E[h] = 0.1257
    after home       E[h] = 0.2163
    after slow       E[h] = 0.1559
    after fast       E[h] = 0.2970
----------------------------------------------------------------------------------
  H_order: per-seed E[h|post-fast] - E[h|post-slow]  mean  0.141  95% CI [ 0.138,  0.145]  (gate: lower > 0.04)
----------------------------------------------------------------------------------
  A_TRANSFER_NO_REGRESSION   : True
  H_ORDERS_FAST_OVER_SLOW    : True
  C_MIXED_NO_HARM            : True
  verdict: kept
  A monitor that learns its hazard at observation level preserves the stationary transfer benefit, reliably orders the fast regime's rate above the slow regime's rate, and stays harmless on mixed worlds. The prior's rate of forgetting is earned from the observation stream it lives in. Keep it.

Measurement notes

  • The hazard is now identifiable. The E[h] trajectory is the exact trajectory theory predicts and 005 conspicuously did not produce: 0.126 after the calm stationary A-block, 0.216 after home (ρ = 5 ≈ 1/5), a dip to 0.156 after the slow calm tails (ρ = 16), then a spike to 0.297 after the fast block (ρ = 2). The dip-then-spike ordering is exactly the ordering of the true rates, and it is monotone against stream order — it cannot be a drift artifact. The per-observation stream, which records the boundary + growth structure of every world, carries the hazard evidence that the per-world winner sequence could not.
  • H_order is the strongest number in the experiment: mean 0.141, 95% CI [0.138, 0.145] against a pre-committed margin of 0.04 — three and a half margins of clearance. It passes at every seed base scanned below.
  • The behavioral readout is quieter. B-fast learned-vs-null is −0.07 [−0.17, 0.04], and C-mixed is flat. The monitor identifies the two rates cleanly, but in this short protocol the identified hazard does not yet buy a measurable per-world n_exp advantage on the fast block (the learned prior is never worse here either — B-fast learned beats fixed h = 1/5 by −0.05). 005 was dominated by the identification failure; with identification now recovered, the behavioral dividend is the natural next scale to chase.
  • Verdict stability across seed bases {5, 6, 7, 8, 9} at n_seeds = 16: kept ×4, inconclusive ×1. The single wobble (base 6) is the pre-existing C_mixed_no_harm non-inferiority gate — its 95% CI upper bound crosses the 0.25 margin (0.33) while A_transfer and H_order both pass at every base (H_order CI lower ≈ 0.139 everywhere). The C gate measures world-draw composition of the unconstrained mixed control, not hazard learning: it is the same seed-fragility the 002/003 records diagnosed, now localized to the one block left in the suite with unforced features. H_order — the gate that implements "does the learned rate track the stream's rate" — is stable in 5/5 seed bases at both n_seeds = 16 and n_seeds = 24.
  • Discretization honesty: the agent carries one run-length trellis per candidate hazard on the grid and model-averages them; the full three-level hierarchy (learning the hazard over hazards, per Wilson et al.'s latent a/b recursion) is deliberately not implemented. The grid is a faithful two-level discretization of the same recurrence and is what lets the evidence site (per-observation) be tested against the 005 control unconfounded. A true three-level hierarchy is the next candidate, not a fix.

Verdict, as measured: the per-observation hazard learner is kept. The regression 005 identified — collapsing each world to a single convergence update — is repaired by paying the Bayesian recursion at the observation level, and the rate that was statistically invisible now tracks the stream with decisive margin. This is the first mechanism in the program whose rate of forgetting is a measurement, in the sense that the value printed by the posterior tracks the environment it lives in.

Experiment 007 — the closed loop (a hazard that steers what the agent asks)

Experiment 006's record closed with two open debts: the hand-set hazards grid ("a true three-level hierarchy is the next candidate"), and the quiet behavioral readout ("the identified hazard does not yet buy a B-fast advantage"). Experiment 007 pays both at once and asks whether the loop closes: a hazard learned from the observation stream that also steers which queries the agent asks next.

The LatentHazardAgent removes the grid entirely. It is Wilson, Nassar, Gold & Kording (2010) equations (16)–(24) with no discretization: each node of the hierarchy holds four sufficient statistics (r2, a, b, c) — the data-level run length, the Beta-change-count a, the Beta-non-change-count b of the latent hazard posterior, and a Dirichlet belief c over the governing feature. The high-level run is r1 = a + b (eq. 42) and the node's hazard estimate is h~ = (a + a_p)/(a + b + a_p + b_p) (eq. 43) with a uniform Beta prior (a_p, b_p) = (1, 1). Every boundary observation spawns the four children of eq. 24, weighted (1−h0)(1−h~), (1−h0)h~, h0(1−h~), h0h~ with the pre-committed meta-hazard h0 = 1/50:

  • no hazard change, data grows — r2+1, a, b+1, c·lik;
  • no hazard change, data changes — 0, a+1, b, fresh;
  • hazard change, data grows — r2+1, a_p, b_p, c·lik;
  • hazard change, data changes — 0, a_p, b_p, fresh.

The two data-change children are gated to world boundaries (a feature cannot change inside a world) exactly as in 006. The hazard-change children are the hierarchy's mechanism for forgetting a dead hazard rate: they reset the Beta counts to the uniform prior, so after a persistent regime the posteriors lean on a fresh, unbiased hazard rather than the stale accumulated one. Pruning is Wilson et al.'s similarity-bin method (log-binning on r2, r1, and h~) capped at 384 easily-sorted states.

The LatentHazardAnticipateAgent adds the steering step. Each query's information gain is computed twice: once under the current run's feature belief (standard weighted IG) and once under a fresh world's belief (the change branch's uniform predictive). The query value is the mixture IG = (1−w)·IG_salience + w·IG_fresh, blended by w = the agent's own boundary hazard belief E[h~] — its estimate that the next world's rule is not the current run's. Asking what matters if the world just changed is the proactive case: a prior that has learned a high rate of change over-weights queries that pay off under either feature hypothesis. At w = 0 (belief of no change) the hedged value reduces exactly to standard ACT, so the identical machinery with w = 0 is the natural control inside the agent class itself — a paired test of the belief as the only difference, not the mechanism.

Protocol. Seven blocks: A-learn (stationary color, n_worlds = 5 per seed), A-transfer (stationary transfer), B-home (ρ = 5), B-slow (ρ = 16), B-fast (ρ = 2), then B-switchrate, the new block that stresses the forgetting machinery directly: 32 calm worlds (ρ = 16) → 16 fast worlds (ρ = 2) → 32 calm worlds (ρ = 16), 80 worlds, entry "shape" continuing B-fast's final feature. C-mixed (unconstrained) stays as the safety control. Arms: null (bare ACT), grid (006's ObservationHazardAgent, identical streams), exact (the three-level hierarchy), anticipate (the hedged variant). Gates (all pre-committed, computed by the harness):

  • A_transfer_no_regression — exact AND anticipate stay below null on A-transfer (CI upper < 0);
  • H_order_retained — exact's post-fast hazard exceeds its post-slow hazard by more than H_MARGIN = 0.04 (the 006 identification result must survive the grid's removal);
  • H_fall_recovers — exact's hazard at the mid of the second calm phase falls below the grid's (CI upper < 0): the hierarchy's reset-to-prior children should re-learn the calm rate faster than the grid's stiff cumulative likelihoods;
  • A_dividend — anticipate's n_exp on fast worlds (B-fast worlds 2..16 plus switchrate fast-phase worlds SR1_AT+1 .. SRFAST_AT = 34..49) falls below exact's (CI upper < 0): the hazard-steered ACT must buy a measurable recovery;
  • C_mixed_no_harm — both new arms stay within the 0.25 mixed-margin.

A calibration readout (reported, not gated) records each arm's boundary-start E[h~] against the realized "did the rule change" at every world, so the hazard's self-knowledge is measured per pace.

Results (verbatim, python3 run.py 007, seed base 7, n_seeds = 16):

The Unknown World — Experiment 007 (the closed loop: a hazard that steers what the agent asks)

  per-arm vs null (identical worlds; d = n_exp(arm) - n_exp(null))
  block         arm         n    mean d  95% CI            p(prior<null)  dz     seeds helping
----------------------------------------------------------------------------------------------
  A-learn       grid         80   -0.50  [ -0.65,  -0.35]   0.0003     -0.69   16/16
  A-learn       exact        80   -0.50  [ -0.65,  -0.35]   0.0003     -0.69   16/16
  A-learn       anticipate   80   -0.33  [ -0.44,  -0.23]   0.0003     -0.69   16/16
  A-transfer    grid         80   -0.34  [ -0.51,  -0.16]   0.0003     -0.42   13/16
  A-transfer    exact        80   -0.34  [ -0.51,  -0.16]   0.0003     -0.42   13/16
  A-transfer    anticipate   80   -0.30  [ -0.45,  -0.15]   0.0003     -0.47   14/16
  B-home        grid        320   -0.44  [ -0.53,  -0.36]   0.0003     -0.53   16/16
  B-home        exact       320   -0.44  [ -0.53,  -0.36]   0.0003     -0.53   16/16
  B-home        anticipate  320   -0.41  [ -0.49,  -0.33]   0.0003     -0.50   16/16
  B-slow        grid        512   -0.51  [ -0.59,  -0.44]   0.0003     -0.61   16/16
  B-slow        exact       512   -0.51  [ -0.59,  -0.44]   0.0003     -0.61   16/16
  B-slow        anticipate  512   -0.51  [ -0.59,  -0.44]   0.0003     -0.61   16/16
  B-fast        grid        256   -0.07  [ -0.17,   0.04]   0.1278     -0.08   12/16
  B-fast        exact       256   -0.07  [ -0.17,   0.04]   0.1278     -0.08   12/16
  B-fast        anticipate  256   -0.09  [ -0.18,  -0.01]   0.0215     -0.13   12/16
  B-switchrate  grid       1280   -0.38  [ -0.43,  -0.33]   0.0003     -0.43   16/16
  B-switchrate  exact      1280   -0.38  [ -0.43,  -0.33]   0.0003     -0.43   16/16
  B-switchrate  anticipate 1280   -0.31  [ -0.35,  -0.27]   0.0003     -0.45   16/16
  C-mixed       grid        160    0.05  [ -0.07,   0.17]   0.8127      0.06   7/16
  C-mixed       exact       160    0.05  [ -0.07,   0.17]   0.8127      0.06   7/16
  C-mixed       anticipate  160   -0.05  [ -0.12,   0.03]   0.1260     -0.10   13/16
----------------------------------------------------------------------------------------------
  effective hazard E[h] (posterior mean over seeds) by capture point
        post-A   post-home post-slow post-fast post-sr1 post-srfast post-srmid
    grid         0.1257    0.2163    0.1559    0.2970    0.2523    0.3231    0.3155
    exact        0.3198    0.3489    0.2523    0.6190    0.2691    0.6251    0.4521
    anticipate   0.3195    0.3487    0.2526    0.6196    0.2675    0.6263    0.4523
  post-sr2 (end of the second calm phase):
    grid         0.3056
    exact        0.2782
    anticipate   0.2775
----------------------------------------------------------------------------------------------
  gate CIs (the verdict is drawn on these boundaries)
    A_transfer  exact-null       mean d  -0.34  95% CI [ -0.50,  -0.15]   (upper<0)
    A_transfer  anticipate-null  mean d  -0.30  95% CI [ -0.44,  -0.16]   (upper<0)
    H_order     exact post-fast - post-slow  mean  0.367  95% CI [ 0.365,  0.368]  (lower>0.04)
    H_fall      exact - grid, E[h] at mid second calm  mean  0.137  95% CI [ 0.133,  0.140]  (upper<0)
    A_dividend  anticipate - exact on fast worlds  mean d  -0.03  95% CI [ -0.08,   0.02]  (upper<0)
    C_mixed     exact-null       mean d   0.05  95% CI [ -0.07,   0.17]   (upper<0.25)
    C_mixed     anticipate-null  mean d  -0.05  95% CI [ -0.13,   0.03]   (upper<0.25)
----------------------------------------------------------------------------------------------
  mean n_exp per arm on the B-slow calm tails: grid 2.50  exact 2.50  anticipate 2.50  null 3.09
----------------------------------------------------------------------------------------------
  calibration readout (reported, not gated): boundary-start belief vs realized switches
    arm         pace        n   mean pred  realized   brier
    grid        home         304     0.173     0.158    0.1433
    grid        slow         496     0.179     0.032    0.0541
    grid        fast         240     0.228     0.467    0.3143
    grid        switchrate  1264     0.295     0.139    0.1455
    exact       home         304     0.335     0.158    0.1752
    exact       slow         496     0.290     0.032    0.0999
    exact       fast         240     0.441     0.467    0.2889
    exact       switchrate  1264     0.425     0.139    0.2087
    anticipate  home         304     0.334     0.158    0.1751
    anticipate  slow         496     0.290     0.032    0.1000
    anticipate  fast         240     0.441     0.467    0.2890
    anticipate  switchrate  1264     0.425     0.139    0.2087
----------------------------------------------------------------------------------------------
  A_TRANSFER_NO_REGRESSION   : True
  H_ORDER_RETAINED           : True
  H_FALL_RECOVERS            : False
  A_DIVIDEND                 : False
  C_MIXED_NO_HARM            : True
  verdict: inconclusive
  Signals mixed (A_ok=True H_order=True H_fall=False A_dividend=False C_ok=True). The closed loop is not kept.

Every number above is drawn from the byte-verified record; the figures below are rendered from the same data by tools/make_figures.py (dev-only dependency: matplotlib — the repo itself remains stdlib-only).

The record, drawn

Per-block advantage (n_exp arm − n_exp null); every arm beats null on nearly every block.
Per-block n_exp advantage of grid/exact/anticipate vs null, all arms negative on nearly every block.

Effective hazard E[h] across capture points: the hierarchy spikes decisively on fast and re-converges toward calm.
Line plot of effective hazard over capture points: exact spikes to 0.63 on fast, grid peaks at 0.32.

The five pre-committed gates on their 95% CIs — H_fall and A_dividend cross their boundaries.
Gate forest plot: green passed gates, red failed gates, dotted boundary lines.

Calibration (reported, not gated): boundary-start belief vs realized switches, per pace.
Predicted vs realized switch rate per pace for grid, exact, anticipate.

Measurement notes

  • The grid is gone and the identification survives — and sharpens. H_order moves from 0.141 (006) to 0.367 with CI [0.365, 0.368], nine times the margin. The three-level hierarchy's post-fast E[h] reaches 0.619 vs the grid's 0.297: without a coarse grid the latent Beta-Bernoulli posterior moves far more decisively onto the fast rate. It also rests at a different level on the calm blocks (post-A 0.320 vs grid's 0.126): without grid candidates pinned at {1/8, 1/16, 1/32}, the hierarchy's Beta prior leans on the uniform (1, 1) counts and reports a genuinely wider posterior over hazard — the same "both sides present" equals 0.5 prior the agent carries when a run is young. The ordering evidence is what the gate demands, and it is overwhelmingly retained.
  • H_fall is a real negative, honestly measured. The pre-committed hypothesis was that the hazard-change children (counts reset to prior) would let exact re-learn the calm rate faster than the grid's cumulative likelihoods. It does the opposite at the gate's sample point: at post-srmid (mid of the second calm phase) exact sits at 0.452, above the grid's 0.315, so the paired exact − grid CI is fully positive and the gate fails. The reason is visible in the capture points: exact overshoots far higher on the fast phase (0.625 vs 0.323), and its fall from that peak is genuinely faster (0.625 → 0.452 in 12 calm worlds vs the grid's 0.323 → 0.315, a 20× larger drop), but at the single pre-committed sample point the overshoot has not yet been re-absorbed. By post-sr2 it has — exact is 0.278, below the grid's 0.306. The recovery mechanism exists and is faster; the gate's single point simply sits too early to catch it passing. Reported exactly as measured; the mechanism is kept only if a future test catches the crossing.
  • The behavioral dividend is null (and the hedge is genuinely exercised). A_dividend = −0.03, CI [−0.08, 0.02]: the hedged ACT is neither reliably better nor worse on fast worlds. This is not a dormant mechanism — the instrumented trace shows anticipate picks a different query than exact on a subset of fast worlds (the first seven B-fast worlds and the first three switchrate fast worlds never diverge — divergence appears only once the hierarchy's hazard belief has shifted), and when they diverge the step ledger tilts weakly toward saving (79 saves vs 66 losses across the 496 gate fast-world draws, of which 145 diverge) but nowhere near a reliable dividend. The 006 quiet readout survives the close-the-loop step: a hazard that identifies cleanly still does not buy a reliable per-world n_exp advantage in this geometry. n_exp is a coarse yardstick; a world takes ~2–4 experiments and the hedge can only save a step when a 4-step world becomes a 3-step world.
  • Behavior is inherited and safe. Both new arms keep the full stationary benefit (A-transfer −0.34/−0.30), the calm tails at 2.50 vs null's 3.09, and both stay inside the mixed margin. B-switchrate is scored for all arms against the same stream and shows the same ≈ −0.3 to −0.4 advantage for every hazard-aware arm: the new block behaves, and behaving is now measured in a block the 006 protocol could not see.
  • Calibration (not gated) is well-behaved and correctly rounded toward change. On fast worlds, realized switches = 0.467 and the exact arm predicts 0.441 (Brier 0.289) against the grid's sleepy 0.228 (Brier 0.314). On slow worlds realized = 0.032 and exact predicts 0.290 (Brier 0.100) — the hierarchy correctly senses the calm regime's low rate but its level remains inflated by the young-run prior; the grid's lower-and-correct 0.179 (Brier 0.054) is better calibrated on calm because its {1/8, 1/16, 1/32} candidates pull the mean down. Neither is a disaster; both report the ordering (high on fast, low on slow) the gates demand.
  • Stability across seed bases {5, 6, 7, 8, 9} at n_seeds = 16: verdict inconclusive at every base. The failures are localized: H_fall fails at every base (a stable negative, not a seed artifact); A_dividend's CI upper crosses zero at base 7 only (0.018); C_mixed's at base 8 only (0.31, the same pre-existing world-draw fragility 002/003 diagnosed) — while H_order is stable in 5/5 (CI lower ≈ 0.365 everywhere) and A_transfer passes in 5/5. The verdict is not a fluke of seed base.
  • Honesty constraints that shaped the design. The five gates and the switchrate hyperparameters (widths, capture points SR1_AT/SRFAST_AT/SRMID_AT, META_HAZARD = 1/50, (a_p, b_p) = (1, 1), run cap 24, max_states = 384) were committed before any 007 measurement. The verdict text (kept / rejected / inconclusive) is computed by the harness from the gate CIs; it has never been hand-edited. The Beta counts (a, b) update only at world boundaries — one hazard event per world, matching the world's generative structure in which a feature cannot change inside a world — and become the calibration yardstick read off at boundary starts.

Verdict, as measured: inconclusive. The closed loop is not kept. Two of the five pre-committed gates fail (H_fall, A_dividend). The three-level hierarchy identifies the regime rate better than the grid ever did and inherits every behavioral benefit, and its hazard belief is better calibrated toward change on the fast worlds; but the two steps that would complete the loop — a faster calm re-convergence at the pre-committed sample point and a reliable n_exp dividend from hedging — do not materialize as measured. The mechanisms are exercised, the directions are right, and the numbers are small but in the hypothesized direction; the record does not allow "kept".

Retrospective — 001 to 007, what was actually established

A deliberate, honest accounting of what each experiment contributed, and how much of the program's claims are delivered by mechanism versus measurement.

Exp Claim Evidence site Outcome
001 ACT (version-space narrowing) adapts to a novel world n_exp curve kept — the competence-curve primitive works but is context-blind
002 A salience prior biases ACT stationary n_exp inconclusive (not kept) — fragile to world-draw composition; exposed rigidity
003 Paired seeded rototest makes the measurement honest re-run of 001/002 kept (methodological) — the harness, verdicts computed by code
004 A change-point prior that learns beats a blind prior after a switch B-switch, A-transfer kept — forgetting is measured, but hazard is hand-set
005 The prior learns its own hazard (removing the hand-set rate) winner-sequence hazard inconclusive (not kept) — hazard invisible in the 2-feature compressed stream
006 Per-observation updates restore hazard identification E[h] trajectory kept — identification recovered; behavioral dividend still quiet
007 Grid-free three-level hazard + hazard-aware ACT closes the loop H_order, H_fall, A_dividend inconclusive — identification sharpens (0.367), loop steps fail

Honest accounting of the novel content, against the literature the program builds on (Wilson, Nassar, Gold & Kording 2010; Adams & MacKay 2007; Nassar, Rumsey, Wilson, Parikh, Heasly & Gold 2012; Itti & Baldi 2005; Wilson, Niv & Gold 2013; Haber, Mrowca, Fei-Fei & Yamins, NIPS 2018; Liu & van der Schaar, ICML 2025):

  • Textbook, faithfully re-derived and now measured on a discrete-object world: version-space ACT (001), salience priors (002–003), run-length CPD (004), the Wilson et al. latent-rate recursion (005–007), and bounded-away vs bound growth with evidence gating (004).
  • The evidence-site finding is the program's one solid original result without qualification: the hazard is statistically unidentifiable from a compressed winner sequence (005) and identifiable from the per-observation stream (006), with the 007 hierarchy reproducing the same evidence site — consistent with Wilson et al.'s §6.1 bound ("takes on the order of 1/(Δρ) binary data points to distinguish … rates differing by Δρ"). This is a negative-then-positive control pair that the active- or interactive-leaning literature does not present in this form.
  • The paired seeded rototest (003) is a methodological contribution: verdicts are computed, not claimed; identical worlds pair every arm; stability is scanned across seed bases. Nothing in the program is benchmarked on a fixed task.
  • Claimed only with the explicit caveats below: (a) hazard→ACT coupling was not found in the active-learning or BOCPD literature surveyed (to the best of our search, through the 007 record) — but 007 measures a hazard-steered query hedge, and the pairing is the targeted novel probe even if the dividend did not reach significance; (b) calibrated self-knowledge — the 007 calibration readout (belief vs realized rule change per pace) is reported but not yet gated. Related live work we are aware of: adaptive sampling × change-point detection (Yi & Yang, Stat. Papers 2026, arXiv:2512.15507); proactive drift adaptation (Machine Learning 2025); recurring concept drift (Suárez-Cetrulo et al. 2023); and a deliberate honesty caveat — Huang, Chen, Mishra et al. (Google DeepMind, ICLR 2024) showed LLM self-correction without ground truth can degrade answers, so "self-model" claims here are limited to within-world beliefs measured against realized switches, never introspective text. Liu & van der Schaar (ICML 2025) situate intrinsic metacognitive learning; we claim only the measurement.
  • What the program does not claim: intelligence, agency, or competence on any fixed benchmark; any superiority of one learning rule "in general"; or that self-knowledge implies self-improvement. The 007 record is the current honest endpoint: identification recovered and sharpened; the loop that steers the asking is exercised but not (yet) shown to pay.

Next

The 007 record leaves three concrete debts:

  • Catch the crossing. H_fall failed at a single pre-committed sample point even though exact's calm-recovery rate is ~20× the grid's. A gate that samples the recovery trajectory (e.g. the post-sr2 endpoint, or a fitted fall slope) rather than one too-early point is the natural 008 measurement — pre-committed before running 008, per the discipline.
  • Make the dividend measurable. On the ~145 divergent fast-world draws the hedge saves a step 79 times and loses 66 (≈ 54/46), a real but marginal edge that n_exp's 2–4 granularity hides in the average. A per-world cost that can move by fractional steps, or a longer switchrate fast phase, should let the hedge's direction either reach significance or be honestly retired.
  • A third feature. The 005→006 record shows the hazard monitor needs evidence more than machinery; a third feature gives a run-length model a second dimension to be wrong about and converts the f-vs-change divergence prediction (004) into a measurement.
  • Calibrated self-knowledge as a gate. The 007 calibration table is reported not gated; committing a Brier-based calibration gate in a later experiment would complete the metacognitive strand with the same harness discipline as everything else in the program.

Rule: never declare intelligence from performance on a fixed benchmark. Measure the system's ability to adapt when the rules, tasks, environment, and available information change.

Reproduce

python3 run.py                        # Experiment 007 and its verdict (default)
python3 run.py 007                    # Experiment 007 (the closed loop)
python3 run.py 006                    # Experiment 006 (hazard learned per observation)
python3 run.py 005                    # Experiment 005 (hazard learned from the winner sequence)
python3 run.py 004                    # Experiment 004 (change-aware salience)
python3 run.py 003                    # Experiment 003 (paired rototest v2)
python3 run.py 002                    # Experiment 002 (legacy run)
python3 -m unittest discover -s .     # the sanity suite (61 tests)

Stdlib only. No dependencies. Deterministic seed (random.Random(7)).

Layout

File Role
world.py generator of minimal unknown-worlds (Object color/shape, hidden rule, force_feature hook)
agent.py the loop + salience: bare prior (002), tempered ForgetAgent (fixed f), ChangePointAgent (run-length monitor, hazard h), HierarchicalChangePointAgent (learned hazard over a grid, 005), ObservationHazardAgent (per-observation learned hazard, 006), LatentHazardAgent / LatentHazardAnticipateAgent (grid-free three-level hierarchy + hazard-hedged ACT, 007)
protocol.py paired seeded harness (003), four-arm change-aware / regime-stream harnesses (004–007): exact permutation p, bootstrap CI, Cohen's dz, hazard-identification and switchrate gates, calibration readout, harness verdicts
run.py runs Experiment 007 by default; run.py 006 / 005 / 004 / 003 / 002 reproduce the earlier evidence
test_step1.py sanity suite (61 tests: world, salience, protocol, statistics, paired v2, change-aware, hierarchy, observation-hazard, latent-hazard, latent-hazard-anticipate)
tools/make_figures.py renders the README figures from the byte-verified report data (charts/*.png)

License

MIT © 2026 NullLabTests

Releases

Packages

Contributors

Languages