← All experiments

Field notes / Experiment guide

The square-loop explanation that failed its test

Long opening runs can make an ant circle small squares on young cells. Does that explain their apparent boundary-occupation effect?

New to these ants? Start here.

An ant moves on a grid of coloured squares. Each colour tells it to turn left (L) or right (R). It advances that square to the next colour, then steps forward. A rule such as RLR is the list of turns, starting at colour zero. On a blank grid the same rule always makes the same trajectory.

Territory means every cell visited so far. Its boundary consists of visited cells with an unvisited neighbour. A highway is a repeating pattern of motion that carries the ant away. A tether means repeated returns to a small home region.

Growing like the cube root of time means taking eight times as many steps to double a linear size. The rotor walker is a comparison model that follows and rotates arrows stored on cells. A seed makes a random starting pattern reproducible; the ant itself can still move deterministically.

We distinguish c, the chance of discovering a cell per boundary step, from kappa (κ), time at the boundary normalized by perimeter divided by area. Explaining their values is harder than using them to account for growth.

The idea under test

Interior loop frequency should mediate the association strongly enough to pass a registered reduction and reliability test.

What we learned

The deciding mediation prediction fails. The attractive square-loop account is not established, and its proposed intervention follow-up is not launched.

What this leaves open

Loops can still occur without being the proposed mediator. This cohort was already used to discover the association, so it is not an independent replication.

Read the evidence and reproduction recipe ↗

Inside the experiment

Methods, registered predictions, exact commands and saved analysis. These are the working research documents; expand them for the detail behind the introduction.

Methods and original experiment record

kappa and the square-loop trap (H-loop)

Status (updated 2026-10-16 ~21:55 +13:00): instrument, tests and cohort run written/started; see Results at the bottom (filled after the single analysis run). The registered predictions below are unchanged.

Cohort caveat (stated plainly). The cohort here (the 300 fresh lead-stratified rules x seeds 601..608) is the same cohort in which the lead effect on ln kappa was found and measured (parent, +0.152 per lead step on the 176 stationary rules). Mediation tests on it are legitimate (the question is "what carries the effect that exists in these data"), but they are NOT a replication of the lead effect and cannot be read as independent confirmation of H-loop; any mechanism fitted here is fitted on the data that produced the phenomenon. The only out-of-sample element is C3 (the parent's mutants, different rules), which is unpowered.

Frozen analysis choices (NOTEBOOK entry 21:58, committed before any loop data): the deciding P3 mediator is the interior-only loop-step rate (loop steps on interior start cells / interior steps), not a boundary-based one (boundary-cell loop steps are boundary steps by construction, so that mediator is nearly an identity with B/S); the all-loop-steps fraction and boundary-based variants are accounting only. Pass rule, leads 1-4 check, and the ICC reliability rule are in that entry. Retention by lead is reported in every P2/P3 table. Parent: ../2026-10-16-kappa-leadrun-fresh/ (leading-run effect on ln kappa; read its README first). The hypothesis was first written in that folder's NOTEBOOK.md, entry "2026-10-16 20:45 ... question, intent", before any loop measurement. The statements below copy it. Do not reword predictions after seeing data; append instead. Causal follow-up (draft): ../2026-10-16-kappa-loop-surgery/.

Question

Why does a longer opening same-letter run ("lead" k: R^k L... or L^k R...) raise kappa = (B/S)/(P_end/A_end) at fixed area? kappa is defined in notes/kappa-mechanisms-2026-10-15.md. The effect, on fresh stationary rules: +0.152 ln-kappa per lead step [0.130, 0.174], concave (leads 1-3: +0.235), mean residual -0.15 (lead 1) to +0.42 (lead 6).

Mechanism under test (H-loop)

On fresh (colour 0) cells an all-R lead traces the 2x2 loop O -> E -> SE -> S -> O (4 steps per lap), and each lap raises all four cells by one colour. The loop persists while the four cells' colours are < k: k laps = 4k steps, until the first L-turn breaks it. Young cells are the frontier. So a longer lead means more of the ant's frontier time is spent circling in short loops, hence more boundary occupation (higher B/S) at the same area. Derivation check (P1): scripts/p1_sanity.py, result results/p1_sanity.txt.

Operational definitions (fixed before any code; do not tune after seeing data)

  • Loop step at time t: pos[t] == pos[t-4] AND the four turns made at steps t-3..t are the same letter. A same-turn closed 4-path is exactly a 2x2 lap; pos-repeat alone also catches back-and-forth artefacts. Chirality-agnostic.
  • Lead-colour loop step: a loop step in which all four cells entered in the lap had colour < lead (before the update). Other loop step: any other loop step (for example a lap inside a later same-letter run of the rule). This split is the specificity control.
  • Loop entry: first loop step of a maximal run of consecutive loop steps. Report loop-step fraction and loop-entry rate.
  • Boundary step: the probe's definition: the step starts on a cell with an unvisited 4-neighbour (Region::on_boundary, src/probe.rs).
  • Windows: probe octave windows (2^k, 2^(k+1)]. Reported kappa is the k = 26 window value (experiments/_lib/analyse_probe.py: KLO=20, KHI=26, kappa=float(g["kappa"][-1])); ln A uses k = 22. The instrument reports loop statistics for k = 20..26. Primary window for P2-P3 is k = 26; k = 22 and 24 are secondary. (The 20:45 notebook entry said only "the probe window"; this fixes it. See NOTEBOOK 20:58 decision.)

Registered predictions (copied from the 20:45 notebook entry; thresholds are my design choices, not findings)

  • P1 (rule-only): on a blank board a lead-k rule's opening 4k steps repeat with period 4 exactly (100%).
  • P2: loop-step fraction in the window rises monotonically with lead 1..6 on the fresh stationary rules (176 in ../2026-10-16-kappa-leadrun-fresh/results/fresh_rules.csv), and within each ln A22 tertile Spearman(fraction, lead) > 0.5.
  • P3 (mediation): adding per-rule loop fraction to spline(ln A22) + lead removes >= half of the lead coefficient (same stationary rules; coefficient before is 0.152). An unchanged coefficient means loops are a symptom, not the carrier.
  • P4: P(loop step | step on boundary cell) >= 2 x P(loop step | interior step).
  • Kill/downgrade logic (registered): P2 fails => H-loop dead. P2 holds, P3 fails => loops are a symptom of lead. P2 and P3 hold, P4 fails => loops matter but not through boundary occupation: unexplained, say so.

Added now, before any loop data (written after P1-P4, so flagged as later additions):

  • C1 (specificity): P3 repeated for the other loop kind only. H-loop predicts the mediation fraction for other-loops is less than half that of lead-colour loops. If both mediate equally, "loop" is a generic recurrence proxy, not the lead mechanism.
  • C2 (identity caveat): loop steps on boundary cells are boundary steps by construction, so P3 partly restates B/S. Also run P3 with interior-only loop steps and with loop-entry rate. If mediation vanishes when boundary loop steps are excluded, report it as accounting.
  • C3 (mutation link): on the usable base/mutant pairs of ../2026-10-16-kappa-leadrun-fresh/results/mutant_pairs.csv (exists only after that folder's analyse_mutants.py has run), the paired change in loop fraction should have the sign of d = ln kappa(mut) - ln kappa(base), Spearman > 0.3 over arms E and S pooled. Not powered; report whatever it is.

Competing explanations the data should also be able to support

  1. Young-cell exposure / colour phase (notes/kappa-mechanisms-2026-10-15.md section 2, ../2026-10-15-kappa-prefix-exposure/): lead matters only because early colours are read most. Would predict loop fraction adds nothing beyond exposure of colours 0..k-1.
  2. Lead as proxy for composition: R-count alone gained 0.29 vs lead 0.65 (parent L6), so composition is not the whole story; other prefix letters are untested.
  3. Survivor selection (parent L5 failed): high-lead rules drop out more. Loop statistics on survivors inherit this.
  4. Generic short-period recurrence (period 2/4/6 trapping of any kind, not tied to lead). C1 addresses this.

How to evaluate (decision table)

P2 P3 C1 P4 Reading
fail any any any H-loop dead at this scale. Write it up; add to notes/open-questions-hypotheses.md
hold fail any any loops correlate with lead but do not carry the kappa effect
hold hold fail any generic recurrence, not lead-specific
hold hold hold fail loops carry the effect, but not via boundary occupation as assumed: unexplained
hold hold hold hold consistent with H-loop, still observational. Proceed to ../2026-10-16-kappa-loop-surgery/

Files

PLAN.md instrument and analysis spec. SCHEMA.md output columns. HANDOFF.md first steps. NOTEBOOK.md lab notebook. notebook.ipynb executed write-up (built by scripts/build_notebook.py). scripts/p1_sanity.py, scripts/run.sh, scripts/analyse_loops.py. Sampler examples/kappa_square_loop_sampler.rs, tests tests/kappa_square_loop.rs.

Commands (WSL, repo root)

export UV_PROJECT_ENVIRONMENT=$HOME/.venvs/turmite UV_LINK_MODE=copy
uv run experiments/2026-10-16-kappa-square-loop/scripts/p1_sanity.py   # done: results/p1_sanity.txt
cargo test --release --test kappa_square_loop            # 7 tests: identity, calibration, 1-vs-6 threads
bash experiments/2026-10-16-kappa-square-loop/scripts/run.sh cohort    # 16 min, dumps/loops_cohort.csv (bulk, gitignored)
bash experiments/2026-10-16-kappa-square-loop/scripts/run.sh mutants   # 22 min, dumps/loops_mutants.csv (C3)
uv run experiments/2026-10-16-kappa-square-loop/scripts/analyse_loops.py   # results/analysis.txt, .json, loops_per_rule.csv, c3_pairs.csv

Results

P1 only: 240/240 rules (k = 1..6, both chiralities) repeat with exactly k laps (results/p1_sanity.txt, seed 20261016). This confirms the hand derivation for the blank-board opening. It says nothing about the 2^26-2^27 window, where the cells around the frontier are not blank and a pure lead-colour loop needs four cells all below the lead; how often that happens is what P2 measures.

Results (single analysis run 2026-10-16 ~22:31 +13:00, git f26b6ef; results/analysis.txt, analysis.json; full reasoning in NOTEBOOK 22:45-22:48)

Cohort: 300 fresh rules x seeds 601..608, 2400 runs to 2^27 steps (board 8192), 176 stationary rules (the parent's analysis set). Sampler run scripts/run.sh cohort (16 min), mutants scripts/run.sh mutants (22 min). Window = probe-CSV k = 26 (t_end = 2^26), the window that gives the parent's kappa (correcting the earlier text above which said "steps 2^26..2^27"; NOTEBOOK 22:36). Instrument checks before the run: 7 tests pass (identity to probe_walker and to a store-the-whole-path reference, 300 ant + 256 walker proptest cases, blank-board traps, PersistentWalk exact fractions q = 0.5/0.7/0.3 within 1.1 se, rotor exactly 0 loop steps (theorem), 1 vs 6 threads byte-identical); the sampler also reproduces the parent's probe rows (area, perimeter, new_cells, boundary_steps, escaped) on all 14509 rows with k >= 21.

Retention by lead 1..6 (kept / stationary of 50 sampled): 37/34, 32/32, 35/34, 31/31, 28/26, 20/19.

lead n stat total loop-step fraction lead-colour loop fraction interior loop rate M_int mean resid ln kappa
1 34 0.1587 0.00001 0.1597 -0.209
2 32 0.1839 0.00024 0.1843 -0.031
3 34 0.1661 0.00099 0.1660 +0.008
4 31 0.1791 0.0039 0.1791 +0.033
5 26 0.2016 0.0104 0.2010 +0.157
6 19 0.2567 0.0163 0.2559 +0.144
prediction verdict numbers
P1 held (before) 240/240 blank-board traps
P2 FAILED not monotone (lead 3 < lead 2); tertile Spearman +0.50 / +0.40 / +0.17 (need > 0.5 each)
P3 (deciding: interior-only loop rate M_int) FAILED b1/b0 = 0.957 [0.907, 0.997] (need <= 0.5); leads 1-4: 0.981 [0.930, 1.033]; g = +0.024/SD [0.002, 0.044]; log/rank variants 0.957/0.966
P3 accounting: all-loop fraction / boundary-loop rate 0.955 / 0.727 [0.560, 0.913] only the boundary-based variant removes anything (it is nearly B/S)
C1 FAILED lead-colour interior rate: b1/b0 = 1.134 (wrong sign, g = -0.048/SD); other loops 0.959
C2 FAILED is P3 on the interior-only variant
P4 FAILED median P(loop|boundary)/P(loop|interior) = 0.776 [0.579, 0.957] (needed >= 2)
C3 FAILED 154 E+S pairs, Spearman(dM_int, d ln kappa) = +0.218 [0.061, 0.364] (needed > 0.3; unpowered)
Reliability ICC(1) = 1.000 between-rule sd 0.080, between-seed sd 0.0002: informative, not a noise-limited null

Reading (decision table row 1): H-loop is dead at this scale. P2 failed, and every downstream test also failed. Loop steps are plentiful (16-26% of all steps at every lead) but almost all of them are "other" same-turn 4-loops that are present at lead 1 and are determined by the rule (ICC 1.0), not by the seed; the lead-colour laps that the mechanism is about rise monotonically with lead but are at most 1.6% of steps (8% of loop steps) even at lead 6, and their partial association with ln kappa at fixed area and lead is negative. (CI added 2026-10-20, post hoc, scripts/lead_share_ci.py -> results/lead_share_ci.txt, bootstrap over rules: the 8% is 7.6% [3.2, 12.3] at lead 6, n=20 rules; 5.4% [3.4, 7.4] at lead 5; 2.3% [1.6, 3.0] over all leads. The ratio-of-means variant gives 6.3% [2.9, 10.2] at lead 6.) Not shown: that loops of other shapes (period 6/8, mixed turns), or loops earlier in the run, play no role; and the lead effect itself is still unexplained. This is the cohort in which the lead effect was found: mediation here is legitimate but is not a replication of the effect, and the single out-of-sample element (C3, parent's mutants) is unpowered. ../2026-10-16-kappa-loop-surgery/ was not started (gate: P2 must hold).

Analysis notebook: notebook.ipynb

5 saved outputs · 5 code cells. Cells are not executed during publication. Download notebook

kappa and the square-loop trap (H-loop): a test that failed

Question and why it matters

Why does a longer opening same-letter run ("lead") raise kappa = (B/S)/(P/A) at fixed area? Hypothesis H-loop: an all-R lead traces 2x2 loops on young (colour < lead) frontier cells, so the ant spends more frontier time circling at the boundary. Parent: ../2026-10-16-kappa-leadrun-fresh/ (lead effect +0.152 ln-kappa per step on 176 stationary fresh rules). See README.md (registered predictions P1-P4, C1-C3) and NOTEBOOK.md.

Assumptions and definitions

  • Loop step: the ant's position equals its position 4 steps earlier and the last four turns are the same letter (a 2x2 lap). Lead-colour loop: all four cells read had colour < lead. Boundary/interior: the probe's boundary step. Window: probe-CSV k = 26 (t_end 2^26), the window of the parent's kappa.
  • Frozen before any loop data (NOTEBOOK 21:58): the deciding mediator is the interior-only loop-step rate (a boundary-based mediator is nearly an identity with B/S); pass = b1/b0 <= 0.5, ratio CI upper < 0.8, g > 0; reliability rule ICC(1) >= 0.5.
  • This cohort is the one in which the lead effect was found: mediation here is legitimate but not a replication.

Provenance

Code
In [1]:
import hashlib, subprocess, datetime, json
from pathlib import Path
import numpy as np, polars as pl
SEED = 20261016; np.random.seed(SEED)
root = Path.cwd()
while not (root / "AGENTS.md").exists():
    assert root != root.parent, "repo root not found"; root = root.parent
R = root / "experiments/2026-10-16-kappa-square-loop/results"
for f in ["analysis.txt", "analysis.json", "loops_per_rule.csv", "c3_pairs.csv", "run_cohort.log", "run_mutants.log"]:
    print(f"{f:20s} {hashlib.sha256((R / f).read_bytes()).hexdigest()[:16]}")
print("git", subprocess.run(["git", "rev-parse", "--short", "HEAD"], cwd=root, capture_output=True, text=True).stdout.strip(), "seed", SEED, datetime.date.today())
print((R / "run_cohort.log").read_text())
analysis.txt         785f72f4c26b7155
analysis.json        82d525a6c424ca39
loops_per_rule.csv   5bf73d400e0384f9
c3_pairs.csv         56ee5fec6972a828
run_cohort.log       a3fa7d5f83f0f892
run_mutants.log      1d7f63db457a0e9e
git d416073 seed 20261016 2026-10-16
git ce87387 2026-10-16T21:51:33+13:00 cmd: kappa_square_loop_sampler 27 8192 20 < experiments/2026-10-16-kappa-leadrun-fresh/results/specs.txt
2400 specs
0
200
400
600
800
1000
1200
1400
1600
1800
2000
2200
finished 2026-10-16T22:07:53+13:00
797895b9ccf77984ddf1161cb5ca396842a1171b172ac70ddedd81f13db650f9  target/release/examples/kappa_square_loop_sampler
cceddcd486199f2382ab161b514348ee3159ab30c97dc5b018c33ab86bc98ab6  experiments/2026-10-16-kappa-square-loop/dumps/loops_cohort.csv

Method

Rust sampler examples/kappa_square_loop_sampler.rs (copy of the probe_walker stepping loop plus loop counters), tested against probe_walker and a store-the-whole-path reference (tests/kappa_square_loop.rs: 300 ant + 256 walker proptest cases, blank-board traps, PersistentWalk against exact q^4+(1-q)^4, rotor = exactly 0, 1 vs 6 threads byte-identical). Cohort: 300 rules x seeds 601..608 to 2^27; analysis scripts/analyse_loops.py (run once). This notebook reads only the committed outputs.

Results 1: P2 (loops vs lead) and retention

Code
In [2]:
txt = (R / "analysis.txt").read_text()
print(txt.split("=== Reliability")[0])
# cmd: uv run experiments/2026-10-16-kappa-square-loop/scripts/analyse_loops.py  git: f26b6ef (working tree may be dirty)  seed 20261016  bootstraps 2000  window k=26
IDENTITY vs parent dumps/probe.csv (probe-CSV k = log2(t_end) >= 21): rows parent 14509, sampler 14509, all of area/perimeter/new_cells/boundary_steps/escaped equal: True
parent table reproduced: 183 kept rules, 176 stationary, ln kappa equal to fresh_rules.csv to float precision
retention (of 50 sampled per lead): L1: kept 37, stationary 34; L2: kept 32, stationary 32; L3: kept 35, stationary 34; L4: kept 31, stationary 31; L5: kept 28, stationary 26; L6: kept 20, stationary 19
stationary fresh rules n=176; per lead 1:34, 2:32, 3:34, 4:31, 5:26, 6:19

=== P2: loop-step fraction (all loop steps / steps, k=26) by lead; retention beside it ===
lead  n  kept/50 stat/50  frac_all   frac_lead_colour  M_int(interior rate)  lead_colour_share_of_loop_steps  mean_resid_lnk(vs spline-only fit)
  1  34    37    34   0.15865   0.00001   0.15971   0.000   -0.209
  2  32    32    32   0.18388   0.00024   0.18426   0.001   -0.031
  3  34    35    34   0.16607   0.00099   0.16599   0.007   +0.008
  4  31    31    31   0.17909   0.00393   0.17909   0.026   +0.033
  5  26    28    26   0.20163   0.01041   0.20099   0.058   +0.157
  6  19    20    19   0.25670   0.01633   0.25590   0.079   +0.144
  lnA22 tertile 1: n=59, Spearman(frac_all, lead) = +0.503 CI [+0.250,+0.688]
  lnA22 tertile 2: n=58, Spearman(frac_all, lead) = +0.399 CI [+0.137,+0.610]
  lnA22 tertile 3: n=59, Spearman(frac_all, lead) = +0.166 CI [-0.107,+0.406]
  pooled Spearman(frac_all, lead) = +0.279; strictly monotone mean over leads 1..6: False
P2 FAILED (monotone: False; tertile Spearman > 0.5 in all: False)
  secondary windows (frac_all by lead, mean over stationary rules):
    k=22: 0.15750 0.18306 0.16639 0.17816 0.20223 0.25873   monotone False
    k=24: 0.15824 0.18353 0.16622 0.17871 0.20185 0.25748   monotone False


Shows: the total loop-step fraction is large (16-26% of all steps) but is not monotone in lead (lead 3 < lead 2) and its within-area-tertile Spearman with lead is +0.50, +0.40, +0.17 (registered: > 0.5 in each). P2 failed, so by the registered logic H-loop is dead at this scale. Does not show: that the lead-colour laps are absent: they rise monotonically with lead (1e-5 to 1.6% of steps) but are too rare to matter in this window.

Results 2: reliability, P3 and C1 mediation

Code
In [3]:
print("=== Reliability" + txt.split("=== Reliability")[1].split("=== C2")[0])
=== Reliability of the deciding mediator M_int (frozen rule: ICC(1) across core-band runs < 0.5 => P3/C1/C2 uninformative) ===
  M_int: ICC(1) single run = 1.000 (between-rule sd 0.08012, within-rule (between-seed) sd 0.00020, 176 rules, mean runs/rule 7.91); reliability of the rule mean (Spearman-Brown) = 1.000
  frac_all: ICC(1) = 1.000
  M_int_lead: ICC(1) = 1.000
  M_int_other: ICC(1) = 1.000
  ent_int: ICC(1) = 1.000
  reliability rule: ICC >= 0.5, mediation test is informative

=== P3: ln kappa ~ spline(ln A22) + b*min(lead,6) [+ g*mediator]; census-quantile spline knots, OLS on the stationary fresh rules ===
  retention (of 50 sampled per lead): L1: kept 37, stationary 34; L2: kept 32, stationary 32; L3: kept 35, stationary 34; L4: kept 31, stationary 31; L5: kept 28, stationary 26; L6: kept 20, stationary 19
  Pass (frozen): b1/b0 <= 0.5 and ratio CI upper < 0.8 and g > 0 with CI excluding 0. DECIDING mediator = M_int (interior-only loop-step rate). Others are accounting/robustness.
  M_int (DECIDING) | all leads       n=176 b0=+0.152 b1=+0.145 ratio b1/b0=+0.957 [+0.907,+0.997]  g(per SD)=+0.024 [+0.002,+0.044]
  M_int (DECIDING) | leads 1-4       n=131 b0=+0.196 b1=+0.192 ratio b1/b0=+0.981 [+0.930,+1.033]  g(per SD)=+0.035 [+0.011,+0.054]
  log M_int | all leads              n=176 b0=+0.152 b1=+0.145 ratio b1/b0=+0.957 [+0.910,+1.000]  g(per SD)=+0.022 [-0.000,+0.042]
  log M_int | leads 1-4              n=131 b0=+0.196 b1=+0.191 ratio b1/b0=+0.976 [+0.926,+1.017]  g(per SD)=+0.031 [+0.007,+0.053]
  rank M_int | all leads             n=176 b0=+0.152 b1=+0.146 ratio b1/b0=+0.966 [+0.920,+1.010]  g(per SD)=+0.017 [-0.005,+0.037]
  rank M_int | leads 1-4             n=131 b0=+0.196 b1=+0.191 ratio b1/b0=+0.975 [+0.931,+1.005]  g(per SD)=+0.022 [-0.001,+0.045]
  ent_int (interior entry rate) | all leads n=176 b0=+0.152 b1=+0.154 ratio b1/b0=+1.019 [+0.994,+1.064]  g(per SD)=+0.027 [+0.006,+0.048]
  ent_int (interior entry rate) | leads 1-4 n=131 b0=+0.196 b1=+0.198 ratio b1/b0=+1.008 [+0.987,+1.043]  g(per SD)=+0.019 [-0.006,+0.047]
  M_int, fresh-quantile knots | all leads n=176 b0=+0.152 b1=+0.145 ratio b1/b0=+0.956 [+0.905,+0.996]  g(per SD)=+0.025 [+0.003,+0.045]
  M_int, fresh-quantile knots | leads 1-4 n=131 b0=+0.197 b1=+0.193 ratio b1/b0=+0.979 [+0.929,+1.028]  g(per SD)=+0.035 [+0.012,+0.054]
  ACCOUNTING all-loop frac_all | all leads n=176 b0=+0.152 b1=+0.145 ratio b1/b0=+0.955 [+0.904,+0.997]  g(per SD)=+0.025 [+0.002,+0.045]
  ACCOUNTING all-loop frac_all | leads 1-4 n=131 b0=+0.196 b1=+0.192 ratio b1/b0=+0.980 [+0.927,+1.031]  g(per SD)=+0.035 [+0.011,+0.054]
  ACCOUNTING boundary loop rate M_bnd | all leads n=176 b0=+0.152 b1=+0.110 ratio b1/b0=+0.727 [+0.560,+0.913]  g(per SD)=+0.061 [+0.020,+0.095]
  ACCOUNTING boundary loop rate M_bnd | leads 1-4 n=131 b0=+0.196 b1=+0.159 ratio b1/b0=+0.812 [+0.592,+1.003]  g(per SD)=+0.054 [-0.001,+0.109]
  ACCOUNTING all-loop entry rate | all leads n=176 b0=+0.152 b1=+0.155 ratio b1/b0=+1.020 [+0.995,+1.066]  g(per SD)=+0.027 [+0.006,+0.048]
  ACCOUNTING all-loop entry rate | leads 1-4 n=131 b0=+0.196 b1=+0.198 ratio b1/b0=+1.008 [+0.988,+1.045]  g(per SD)=+0.019 [-0.006,+0.047]
  corr(M_int, B/S) across stationary rules = +0.244; corr(M_int, lead) = +0.281; corr(M_int, ln A22) = -0.116
P3 verdict: not evaluated as support (P2 failed)  (main pass False; leads 1-4 point ratio +0.981)

=== C1 (specificity): mediation fraction f = 1 - b1/b0 for interior lead-colour loops vs interior other loops ===
  lead-colour interior rate | all    n=176 b0=+0.152 b1=+0.172 ratio b1/b0=+1.134 [+1.048,+1.244]  g(per SD)=-0.048 [-0.066,-0.024]
  lead-colour interior rate | leads 1-4 n=131 b0=+0.196 b1=+0.204 ratio b1/b0=+1.039 [+0.995,+1.099]  g(per SD)=-0.069 [-0.144,+0.012]
  other-loop interior rate | all     n=176 b0=+0.152 b1=+0.145 ratio b1/b0=+0.959 [+0.914,+0.995]  g(per SD)=+0.028 [+0.007,+0.047]
  other-loop interior rate | leads 1-4 n=131 b0=+0.196 b1=+0.193 ratio b1/b0=+0.983 [+0.932,+1.036]  g(per SD)=+0.035 [+0.011,+0.053]
  both jointly | all                 n=176 b0=+0.152 b1=+0.165 ratio b1/b0=+1.090 [+0.995,+1.210]  g(per SD)=-0.045 [-0.064,-0.022]
  both jointly | leads 1-4           n=131 b0=+0.196 b1=+0.198 ratio b1/b0=+1.010 [+0.942,+1.092]  g(per SD)=-0.045 [-0.120,+0.039]
  f_lead = -0.134, f_other = +0.041; C1 FAILED (needs f_lead > 0 and f_other < 0.5 f_lead; informative only if reliability ok: True)


Shows: the loop rate is a nearly deterministic property of the rule (ICC 1.0), so the null mediation is not a noise artefact. Adding the interior loop rate leaves the lead coefficient at 0.957 of its value (needed <= 0.5), also on leads 1-4 (0.98), under log/rank transforms, and for the lead-colour loops alone the sign is wrong (ratio 1.13). Only the boundary-based loop rate (accounting: nearly B/S by construction) removes part of it (0.73). Does not show: that no loops of another shape (period 6/8) matter; the lead effect itself remains unexplained.

Results 3: P4 (boundary concentration) and C3 (mutants)

Code
In [4]:
print("=== C2" + txt.split("=== C2")[1])
p = pl.read_csv(R / "c3_pairs.csv")
print(p.group_by("arm").agg(n=pl.len(), mean_dM=pl.col("dM").mean(), mean_d=pl.col("d").mean()).sort("arm"))
=== C2 (identity caveat) ===
  C2 holds iff the interior-only M_int passes P3: False. Boundary-loop mediator (accounting) ratio = +0.727; all-loop accounting ratio = +0.955; interior entry-rate ratio = +1.019

=== P4: P(loop | boundary step) / P(loop | interior step), k=26, per rule (pooled over its core runs), stationary rules ===
  median ratio 0.776 CI [0.579,0.957]; quartiles [0.189, 1.306]; by lead median: 1:0.13, 2:0.72, 3:0.76, 4:0.74, 5:1.18, 6:1.27
  P4 FAILED (median >= 2). Partly accounting by construction (the loop step is classed by its start cell).

=== C3 (mutation link) ===
  pairs (arms E+S, both kept): n=154 (E 81, S 73); Spearman(d M_int, d ln kappa) = +0.218 CI [+0.061,+0.364]; accounting Spearman(d frac_all, d) = +0.225
    arm E: n=81, mean dM_int = +0.03019, mean d ln kappa = -0.062, Spearman = +0.186
    arm S: n=73, mean dM_int = -0.01028, mean d ln kappa = -0.198, Spearman = +0.137
  C3 FAILED (Spearman > 0.3; not powered)

shape: (2, 4)
┌─────┬─────┬───────────┬───────────┐
│ arm ┆ n   ┆ mean_dM   ┆ mean_d    │
│ --- ┆ --- ┆ ---       ┆ ---       │
│ str ┆ u32 ┆ f64       ┆ f64       │
╞═════╪═════╪═══════════╪═══════════╡
│ E   ┆ 81  ┆ 0.030194  ┆ -0.061845 │
│ S   ┆ 73  ┆ -0.010277 ┆ -0.198357 │
└─────┴─────┴───────────┴───────────┘

Shows: loops are not concentrated on boundary steps (median ratio 0.78, registered >= 2) and the mutant link is weak (Spearman 0.22 < 0.3, 154 pairs, unpowered). Does not show: anything causal; the surgery experiment was not run because P2 failed.

Code
In [5]:
t = pl.read_csv(R / "loops_per_rule.csv", comment_prefix="#").filter(pl.col("stationary"))
print(t.group_by("lead").agg(n=pl.len(), frac_all=pl.col("frac_all").mean(), frac_lead=pl.col("frac_lead").mean(), M_int=pl.col("M_int").mean(), P4=pl.col("p4").median()).sort("lead"))
a = json.loads((R / "analysis.json").read_text())
assert not a["P2"]["held"] and not a["P3"]["pass_main"] and not a["C1"]["held"] and not a["P4"]["held"] and not a["C3"]["held"]
print("verdicts agree with README: P2, P3, C1, C2, P4, C3 all FAILED; reliability ICC", round(a["reliability"]["icc"], 3))
shape: (6, 6)
┌──────┬─────┬──────────┬───────────┬──────────┬──────────┐
│ lead ┆ n   ┆ frac_all ┆ frac_lead ┆ M_int    ┆ P4       │
│ ---  ┆ --- ┆ ---      ┆ ---       ┆ ---      ┆ ---      │
│ i64  ┆ u32 ┆ f64      ┆ f64       ┆ f64      ┆ f64      │
╞══════╪═════╪══════════╪═══════════╪══════════╪══════════╡
│ 1    ┆ 34  ┆ 0.158646 ┆ 0.000013  ┆ 0.159708 ┆ 0.129093 │
│ 2    ┆ 32  ┆ 0.183877 ┆ 0.000235  ┆ 0.184262 ┆ 0.723975 │
│ 3    ┆ 34  ┆ 0.166073 ┆ 0.000988  ┆ 0.165995 ┆ 0.760486 │
│ 4    ┆ 31  ┆ 0.179093 ┆ 0.003927  ┆ 0.179088 ┆ 0.743242 │
│ 5    ┆ 26  ┆ 0.201632 ┆ 0.010413  ┆ 0.200993 ┆ 1.177235 │
│ 6    ┆ 19  ┆ 0.256702 ┆ 0.016331  ┆ 0.255903 ┆ 1.273667 │
└──────┴─────┴──────────┴───────────┴──────────┴──────────┘
verdicts agree with README: P2, P3, C1, C2, P4, C3 all FAILED; reliability ICC 1.0

Caveats and controls

  • Same cohort that produced the lead effect; retention falls with lead (kept 37, 32, 35, 31, 28, 20 of 50), so leads 5-6 are the most selected; P3 on leads 1-4 gives the same answer.
  • Window labelling: the probe CSV's k is log2(t_end); the analysis uses that convention (NOTEBOOK 22:36).
  • Positive controls: the sampler reproduces the parent's probe rows on all 14509 rows and the exact PersistentWalk values; negative control: rotor has exactly zero loop steps (a theorem).
  • Registered thresholds are my design choices; none were changed after seeing data. Mutant C3 is unpowered.

What this changes / next steps

H-loop (as stated) is rejected for this cohort and window. Remaining open: mixed-turn period-6/8 loops, loops in the opening transient, a different outcome than B/S (e.g. kappa's P/A factor), and whether the lead effect is a rule-composition effect the loop statistic only proxies.

Open questions

Why is the generic same-turn loop rate 16-26% at every lead and nearly seed-independent? What does carry the lead effect, given that the interior loop rate, lead-colour laps and (by earlier work) R-count do not?

Read the dated lab log

Lab notebook: kappa and the square-loop trap

Append-only. Newest entry last. Never edit an old entry; correct it with a new one (corrects: <timestamp>). Tags: intent, assumption, observation, interpretation, surprise, decision, dead-end, question, deviation. See experiments/README.md.

2026-10-16 20:55 (+13:00) · 9dce376 · intent

Scaffolded this folder at the user's request ("scaffold experiment directories with detailed notes for subsequent researchers to evaluate your predictions"). The hypothesis comes from ../2026-10-16-kappa-leadrun-fresh/NOTEBOOK.md, entry 20:45. No instrument, no probe data yet. P1-P4 are copied into the README; C1-C3 are added there, written before any loop data but after P1-P4, and flagged as such. The sibling ../2026-10-16-kappa-loop-surgery/ holds the causal test (draft).

2026-10-16 20:57 (+13:00) · 9dce376 · observation (scripts/p1_sanity.py, results/p1_sanity.txt)

P1: 240/240 lead-k rules (k = 1..6, both chiralities, 20 random 8-letter tails each, tail preceded by a letter that breaks the lead, seed 20261016) repeat with exactly k laps of period 4 from t = 0. The simulator is pure Python written independently of src/: unbounded dict board, start heading north, R = clockwise, colour c turns by rule[c] then advances to (c+1) % n. Not yet cross-checked against reference; do that in the identity tests.

2026-10-16 20:58 (+13:00) · 9dce376 · decision

The reported kappa is the window k = 26 value (steps 2^26..2^27). I read this in experiments/_lib/analyse_probe.py (KLO=20, KHI=26, kappa=float(g["kappa"][-1])), not k = 22; ln A uses k = 22. My 20:45 wording "in the probe window" was ambiguous. The README now fixes k = 26 as primary, 22 and 24 as secondary. The sampler therefore must run to 2^27 steps like the parent probe (~22 min for 2400 runs). No prediction's content changed.

2026-10-16 20:59 (+13:00) · 9dce376 · assumption

(a) Chirality symmetry: L^k R... is the mirror of R^k L.... P1 covers both on the blank board only. (b) In the probe window the relevant loops use cells of colour < lead, not only all-fresh cells, so the lap count there is lead minus the highest colour among the four cells, not k. Check with the lap-length histogram. (c) The parent's PatchedAnt background (random 5x5 patch, colour 0 elsewhere) means frontier cells have colour 0 when first entered. All untested.

2026-10-16 21:00 (+13:00) · 9dce376 · question

Is a same-turn 4-loop the right unit? Longer closed paths (period 6, 8) with mixed turns exist on mixed colours. If P2 holds only weakly, check those before dropping the idea. Open for the implementer.

2026-10-16 20:56 (+13:00) · 9dce376 · deviation (corrects: timestamps of entries above)

The entries above carry times 20:55-21:02, written while the wall clock was at about 20:50-20:54, so some are stamped slightly in the future. Order is correct; treat the stamps as approximate. Also: the parent mutant probe run finished 20:53 (../2026-10-16-kappa-leadrun-fresh/dumps/mutants.done exists); analyse_mutants.py had not been run when this was written.

2026-10-16 20:58 (+13:00) · 9dce376 · observation

The parent mutant analysis exists now (../2026-10-16-kappa-leadrun-fresh/results/mutants_analysis.txt): M1, M2 failed as registered, M3 held, area-matched pairs and regression b = +0.158 agree with the lead slope. HANDOFF step 3 updated to say so; it no longer gates on a placeholder.

2026-10-16 21:47 (+13:00) · 3af758e · intent

Session start (implementer, main checkout, dirty tree from other sessions: src/probe.rs, src/bin/probe.rs, src/gpu/*, Cargo.toml, paper files; I touch none of them). Plan: (1) pin the probe oracle (diff src/probe.rs against HEAD, show the CPU output is unchanged, identify which probe produced the parent's k=26 kappa); (2) freeze the deciding P3 variant, pass threshold and reliability rule BEFORE any loop data exists; (3) write examples/kappa_square_loop_sampler.rs, tests/kappa_square_loop.rs (identity vs probe_walker, loop counters vs a store-the-whole-path reference, calibration, 1-vs-6 thread bytes); (4) run the 300 rules x seeds 601..608 cohort once to 2^27, analyse once; (5) C3 mutant run if time allows (cheap: 3336 runs). The surgery folder is NOT started unless P2 holds. P1-P4 and C1-C3 above are untouched; this entry and later ones only append.

2026-10-16 21:55 (+13:00) · 3af758e · decision (oracle pinning; supervisor requirement 1)

git diff HEAD -- src/probe.rs: the uncommitted edit (mtime 20:42, after the parent probe run finished at 20:07) is a refactor for the GPU port: Region::centroid/rg2 are replaced by WindowSums + finish_window (same expressions in the same operation order), plus csv_rows, CSV_HEADER, window_sums_exact, #[derive(Clone, Debug)] on ProbeResult. No stepping logic changed. Empirical check, not just reading: I exported HEAD (git archive HEAD) to ~/probe-head, built its probe, and ran HEAD-probe and working-tree-probe on 24 specs (every 100th line of the parent's specs.txt, spanning all leads) to 2^27 on board 8192: the two CSVs are byte-identical (sha256 84fa1fa8...). The parent's dumps/probe.csv rows for the same 24 specs (439 window rows; some runs escape) are identical to the HEAD-probe output byte for byte. Conclusion: the dirty edits do NOT change CPU probe output, and the parent's k=26 kappa in fresh_rules.csv came from the HEAD (d4fd349-era, committed) probe_walker, which the parent's log hashes as target/release/probe sha 38f8bba8.... My identity test therefore compares against turmite::probe::probe_walker in the working tree (equal to HEAD in output), and the scientific run additionally checks the sampler's first nine columns against the parent's dumps/probe.csv for all 2400 specs, so the link to the parent's numbers is direct, not inferred.

2026-10-16 21:58 (+13:00) · 3af758e · decision (FROZEN BEFORE ANY LOOP DATA EXISTS; supervisor requirements 2-3)

Written before the sampler exists. Nothing below may be changed after loop data are seen; variants go in new entries and are labelled accounting. (a) Deciding P3 mediator = the interior-only loop-step rate: M_int = (loop_lead_i + loop_other_i) / (steps - boundary_steps) at window k = 26, i.e. P(loop step | step starts on an interior cell), computed per run, then averaged over the same core-band runs that give the rule's ln kappa (rule_means: alpha_w in [0.25,0.42], kappa>0, not escaped, >=6 runs). Reason: a mediator built from boundary-cell loop steps is nearly an identity with B/S, and kappa = (B/S)/(P_end/A_end) (return-gates lesson); the interior conditional rate has no boundary-step in its numerator and is divided by interior steps, so it is not mechanically B/S. The all-loop-steps fraction ((all four loop_) / steps) and the loop-entry rate are accounting only; they never decide the verdict. (Caveat stated now: M_int is still not independent of the boundary definition, because B/S sets the denominator and which steps are classed interior; I report corr(M_int, B/S) at k = 26 and do not read anything into P3 without it.) (b) P2 variable is the registered one: total loop-step fraction (all four loop_ / steps), k = 26, mean per lead over the 176 stationary rules; "monotone" = strictly increasing point estimates over leads 1..6; tertile Spearman > 0.5 by point estimate in each ln A22 tertile (tertile cuts = 1/3, 2/3 quantiles of the 176 fresh values). Lead-colour-only and interior rates are reported beside it, not instead. (c) P3 spec: OLS of ln kappa on spline(ln A22) [knots 10/25/50/75/90% quantiles of the census stationary ln A22, standardised by the census, prefix_audit.basis(census, fresh)] + bmin(lead,6), on the 176 fresh stationary rules: b0. Add gM_int: b1. Pass iff b1/b0 <= 0.5 AND bootstrap (2000, seed 20261016, resample rules) 95% CI upper bound of b1/b0 < 0.8 AND g > 0 with bootstrap CI excluding 0 (a mediator must predict kappa in the stated direction). Unit of M_int is standardised (z-score over the 176 rules) before fitting; ratio is unit-free. Robustness variants, reported but not deciding: log M_int, rank M_int, fresh-quantile knots. (d) Selection check: the same fit on leads 1-4 only (leads 5-6 are the most selected; parent L5 failed). Reported next to the main fit in every P2/P3 table together with retention (kept share and stationary share of the 50 sampled rules per lead 1..6). If the main fit passes but the leads 1-4 point estimate of b1/b0 > 0.5, the verdict is "held on the full cohort, not robust to selection". (e) Reliability (ICC) rule: ICC(1) of M_int across the core-band runs of each rule (kcommon.icc_groups, rules with >= 6 runs, stationary rules). If ICC(1) < 0.5, P3/C1/C2 are declared uninformative (not a null, not a pass) and the verdict says so; the ICC of the 8-seed mean (Spearman-Brown) and the expected attenuation are also reported. (f) C1 uses M_int split by kind: mediation fraction f = 1 - b1/b0 for lead-colour interior rate and for other-loop interior rate (each: loops of that kind in interior steps / interior steps). C1 holds iff f_lead > 0 and f_other < 0.5 * f_lead (point estimates; CIs reported). C2: holds iff the deciding M_int itself passes (that is P3), i.e. C2 asks whether mediation survives removing boundary loop steps; the all-loop and boundary-loop variants are accounting. Interior loop-entry rate is reported as a second interior variant. P4 exactly as registered: per-rule ratio P(loop|boundary)/P(loop|interior) at k = 26, median over stationary rules with bootstrap CI, pass if median >= 2. P4 is by construction partly accounting (loops are only counted at a step's start cell). (g) C3 (needs a mutant run: 3336 more runs, about 15-25 min, cheap; I will run it after the cohort, same sampler/commit): paired d_loop = M_int(mutant) - M_int(base) vs d = ln kappa(mut) - ln kappa(base) over the usable pairs of mutant_pairs.csv, arms E and S pooled, Spearman > 0.3. Base M_int from the cohort run. Not powered; reported as is.

2026-10-16 22:20 (+13:00) · 3af758e (+ new files) · observation (examples/kappa_square_loop_sampler.rs, tests/kappa_square_loop.rs)

Instrument and tests written and run (cargo test --release --test kappa_square_loop, 7 tests pass, ~5 s). (1) Identity: 150 + 150 proptest cases over lead-structured and random ant rules (sizes 64/128/256, horizons 2^7..2^13, random seeds) plus 256 walker cases (PersistentWalk q in {0.5,0.7,0.3}, rotor): window area, perimeter, new_cells, boundary_steps, escaped flag and window set equal probe_walker, and ALL window counters including the loop counters equal a store-the-whole-path reference (reference::Ant with the same random 5x5 patch; turn letter taken from the rule, not from heading differences; counted by definition over the stored path). The test has teeth: changing t >= 3 to t >= 4 in the loop condition fails 4 tests, changing the lead colour test < to <= fails 2 (mutations reverted; the shrunk failing cases are kept in tests/kappa_square_loop.proptest-regressions). No failures with the correct code. (2) Blank board: all 240 (k = 1..6, both chiralities, 20 tails) have exactly 4k-3 loop steps in their first 4k+1 steps, they are pre-index 3..4k-1, one entry, step 4k+1 not a loop, and the sampler equals the definition on the first 32 steps. NB the registered P1 says "opening 4k steps repeat period 4" which is the same trap; in my loop-step definition (pos[t]==pos[t-4]) a k-lap trap contributes 4k-3 loop steps and k laps. (3) PersistentWalk: loop step iff the last four turns are equal, P = q^4+(1-q)^4, entry rate P-(q^5+(1-q)^5). Measured (24 seeds, windows 10..20, board 8192): q=.5 fraction 0.12508+-0.00007 vs exact 0.12500 (z 1.1), entry 0.06252 vs 0.06250; q=.7 0.24816 vs 0.24820, entry 0.07771 vs 0.07770; q=.3 0.24825 vs 0.24820. (4) Rotor: exactly zero loop steps. This is a theorem, not a finding (a lap would make a rotor cell exit in the same direction on two consecutive visits, but the arrow advances every visit). Consequence for the proptest: rotor loop counters are 0 = 0 and the identity there is vacuous for loops; the PersistentWalk and the ant cases carry the counter check. (5) 1 vs 6 rayon threads give byte-identical CSV (24 ant specs + pw + rotor, 5..17 windows). The sampler is NOT yet run on the cohort.

2026-10-16 21:54 (+13:00) · ce87387 · deviation (corrects: timestamps of the 21:55, 21:58 and 22:20 entries above)

Those three entries carry stamps ahead of the wall clock (the real times were about 21:46-21:52; the sampler tests finished about 21:50). Order is correct. The cohort run started 21:51:33 (results/run_cohort.log), i.e. AFTER the 21:58-stamped freeze entry was written and committed (commit 4b2f02e, before any loop data or sampler existed). Git history, not the stamps, is the evidence for ordering.

2026-10-16 22:09 (+13:00) · ce87387 · observation (cohort run; no loop statistic read yet)

Cohort run finished 22:07:53 (started 21:51:33; 16 min, 6 threads; results/run_cohort.log, binary sha 797895b9..., dumps/loops_cohort.csv sha cceddcd4..., 2400 specs, kappa_square_loop_sampler 27 8192 20). Nothing was opened or summarised. The mutant run for C3 (3336 specs, same binary) is started now so that the analysis script can be run once with everything; analyse_loops.py writes output only at the end and first asserts that the sampler's area, perimeter, new_cells, boundary_steps and escaped columns equal the parent's dumps/probe.csv for all rows with k >= 20, and that the parent's rule table (183 kept, 176 stationary, ln kappa) is reproduced.

2026-10-16 22:36 (+13:00) · f26b6ef · deviation (window labelling; found by the identity assertion, before any loop statistic was read)

Mutant run finished 22:30:42 (results/run_mutants.log, same binary sha 797895b9..., dumps/loops_mutants.csv sha 75bba944...). First analysis attempt aborted at its identity assertion (script writes nothing before that point; no loop statistic was computed or seen): sampler 14509 rows vs parent 16645 rows for k >= 20. Cause: the probe CSV's k is log2(t_end), i.e. window index + 1 (bin/probe.rs prints w.t_end.trailing_zeros()), while my sampler's k is the window index (steps pre-index in [2^k, 2^(k+1))), as in probe_walker. So the parent's "k = 26" kappa window is t_end = 2^26 = steps 2^25..2^26, my sampler's k = 25, and the notes' phrase "k = 26 window (steps 2^26..2^27)" (my 20:58 decision and the README) was wrong about the steps while right about which CSV column it is. The sampler emitted my k = 20..26 = probe-CSV k 21..27, which covers the needed CSV k = 22, 24, 26. No data are missing; only the label differs. Decision (no change of intent): the mediator is measured in the SAME window as the parent's kappa, i.e. probe-CSV k = 26 (= sampler k 25, t_end = 2^26), as the 21:58 freeze says "window k = 26" in the parent's convention; analysis maps k := log2(t) on load and the identity check now joins on probe-CSV k >= 21. Secondary windows: CSV k = 22, 24. The CSV I produced keeps the sampler's convention in column k (SCHEMA said it should mirror the probe's k; it does not: t is the key); schema note appended below. The sampler tests (which compare to probe_walker windows by t_end) are unaffected.

2026-10-16 22:45 (+13:00) · f26b6ef · observation (single analysis run: scripts/analyse_loops.py -> results/analysis.txt, analysis.json, loops_per_rule.csv, c3_pairs.csv)

Run once after the labelling fix above; no variant was added or removed after seeing output. Checks: sampler area/perimeter/new_cells/boundary_steps/escaped equal the parent's dumps/probe.csv on all 14509 rows with CSV k >= 21; parent rule table reproduced (183 kept, 176 stationary, ln kappa equal). Window = probe-CSV k = 26 (t_end 2^26). Retention by lead 1..6 (kept/stationary of 50): 37/34, 32/32, 35/34, 31/31, 28/26, 20/19.

  • P2 FAILED as registered. Mean total loop-step fraction by lead 1..6: 0.1587, 0.1839, 0.1661, 0.1791, 0.2016, 0.2567 (not monotone: lead 3 < lead 2). Within ln A22 tertiles Spearman(frac, lead) = +0.503 [0.25,0.69], +0.399 [0.14,0.61], +0.166 [-0.11,0.41] (needed > 0.5 in each). Pooled +0.279. Same shape at CSV k = 22 and 24. The lead-colour part alone rises monotonically with lead but is tiny: 0.00001, 0.00024, 0.00099, 0.0039, 0.0104, 0.0163 of steps (1.6% at lead 6; 8% of loop steps) - nearly all loop steps are "other" same-letter 4-loops present at every lead (16% of all steps at lead 1).
  • Reliability: ICC(1) of M_int = 1.000 (between-rule sd 0.080, between-seed sd 0.0002): the loop rate is essentially a deterministic property of the rule, so the mediation tests are informative, not noise-limited. Also a warning: a quantity this seed-independent behaves like a rule-composition statistic (frequency of equal-letter runs), not a measure of the frontier dynamics.
  • P3 (deciding M_int, interior-only): b0 = +0.152, b1 = +0.145, ratio 0.957 [0.907, 0.997]; g = +0.024 per SD [0.002, 0.044]. Pass needed ratio <= 0.5: FAIL (also reported "not evaluated as support" because P2 failed). Leads 1-4: b0 = +0.196, b1 = +0.192, ratio 0.981 [0.930, 1.033]. Log, rank, fresh-knot variants: 0.957 / 0.966 / 0.956. Accounting variants: all-loop fraction 0.955; boundary-loop rate 0.727 [0.560, 0.913] (leads 1-4: 0.812) - the only variant that removes anything, and the one I froze as accounting because it is nearly B/S. corr(M_int, B/S) = +0.244.
  • C1 FAILED: lead-colour interior rate has the WRONG sign (b1/b0 = 1.134 [1.048, 1.244], g = -0.048 per SD), other-loop rate ratio 0.959. C2 FAILED (it is P3). P4 FAILED: median P(loop|boundary)/P(loop|interior) = 0.776 [0.579, 0.957] (by lead 0.13, 0.72, 0.76, 0.74, 1.18, 1.27), not >= 2; loops are, if anything, under-represented on boundary steps at low lead.
  • C3 FAILED: 154 usable E+S pairs, Spearman(dM_int, d ln kappa) = +0.218 [0.061, 0.364] < 0.3 (E +0.186, S +0.137; unpowered).

2026-10-16 22:48 (+13:00) · f26b6ef · interpretation, decision

H-loop is dead at this scale: P2 failed, which the registered kill logic says kills it outright, and everything downstream also fails (P3, C1, C2, P4, C3). Two readings kept apart: (i) the mechanism as stated (lead-colour 2x2 laps on young cells) is real but quantitatively small in the window (<= 1.6% of steps at lead 6, rising with lead, strongest among the most selected leads 5-6) and has a negative partial association with ln kappa at fixed area and lead; (ii) the generic loop statistic that is large (16-26% of steps) is not lead-specific, is rule-determined and does not mediate. This is consistent with competing explanation 4 (generic same-turn recurrence) but a failing C1 means even the generic proxy does not carry the lead effect. NOT shown: that the lead effect is not carried by loops of a different shape (period 6/8 mixed-turn loops, question 21:00) or by loops earlier in the run. The lead effect on this cohort remains unexplained. Cohort caveat: all of this is on the cohort where the effect was found. The surgery folder ../2026-10-16-kappa-loop-surgery/ is NOT started (gate: P2 must hold).

2026-10-16 22:58 (+13:00) · d416073 · decision (end of session)

README Results, SCHEMA note, HANDOFF update, executed notebook.ipynb (built by scripts/build_notebook.py, 0 error outputs, its assertions agree with the README verdicts), a summary appended to notes/open-questions-hypotheses.md and a link appended to notes/kappa-mechanisms-2026-10-15.md (committed as appended hunks only; other sessions' uncommitted edits in those two files were left in the working tree, unstaged). Loop-surgery not started (P2 failed). Not done: mixed-turn period-6/8 loop census (question 21:00), loops of the opening transient, any CI-based statement about the 8% lead-colour share beyond the table. Deviations this session: window labelling (22:36); timestamps (21:54); C3 mutants run before the analysis rather than after the parent's analysis (the parent's M-analysis had finished); rotor identity is vacuous for loops (rotor has none).

2026-10-19 (+13:00) · 8f4b978 · interpretation

Co-reading note appended at the 2026-10-19 merge (the entry corrects nothing above). ../2026-10-19-c-law-mechanism/ Stage 4 (registered before computation; Q1-Q4, P-1 held; re-run of 4a/4b at merge reproduced the numbers) shows the fixed-area lead-on-ln-kappa slope (+0.15) is reproduced by conditioning on the collider ln A22 = f(ln c, ln kappa) with no direct effect (null +0.145 [0.137, 0.153]; adding ln c gives +0.014 [-0.045, +0.062]). Read the interpretation and any 'causal at fixed area' wording above as superseded in part: association conditional on area, not evidence of a direct lead effect. Unexplained and still open: the S-arm drop (-0.198) and its confounding with flip direction. See notes/open-questions-hypotheses.md, Reconciliation 2026-10-19.

2026-10-20 00:40 (+13:00) · 70c8050 · observation (post hoc, unregistered)

Closed the 'no CI on the 8% lead-colour share' gap with scripts/lead_share_ci.py (results/lead_share_ci.txt; seed 20261016, 4000 bootstraps over rules, from the committed loops_per_rule.csv, 183 rules). Mean of per-rule lead-colour share of loop steps by lead 1..6: 0.0001, 0.0015 [0.0010, 0.0020], 0.0066 [0.0040, 0.0093], 0.0260 [0.0168, 0.0350], 0.0541 [0.0343, 0.0741], 0.0758 [0.0317, 0.1228]; all leads 0.0225 [0.0158, 0.0303]. So the '8%' is 7.6% at lead 6 on only 20 rules, CI 3-12%. The ratio-of-means estimator is a bit lower (6.3% [2.9, 10.2]). The conclusion (small, rising with lead) is unchanged; the figure should be quoted with the interval.

2026-10-16-kappa-square-loop · Source revision ba38590b33e3

Original source ↗ · Input hashes

Introductions summarize the evidence; the expandable record preserves the original predictions, methods and caveats. Figures and notebooks are published as saved. Publication runs no simulations or notebook cells.