Field notes / Experiment guide
Does boundary occupation differ beyond territory size?
Boundary occupation and territory area are tied by growth. Is there a rule-specific difference left when similarly sized territories are compared?
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
A real rule effect should remain after area adjustment, and might track the longest interior excursions relative to radius.
What we learned
Area adjustment weakens the rule effect, while matched comparisons retain an excursion-cutoff association. The registered combined decision is unresolved.
What this leaves open
Matching observed area does not create a causal intervention. Seed noise and shared trajectories motivate the later independent-seed tests.
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-matched-area: does rule-specific kappa survive controlling for territory size?
Registered 2026-10-14 22:25 NZDT, base commit 797704a (dirty tree), before
scripts/matched_area.py was run. No new simulation: this reuses the committed T1/T1b
patched-start windows of 2026-10-14-t1-excursion-tomography (results/t1b_cutoff_seeds.csv;
k = 22 and 25, 44 rules, 6-8 seeds each, escaped windows excluded as there).
Question
T1/T1b found every strong excursion statistic collapsed to "inverse territory size", because at fixed t, kappa and A are tied through dA/dt = c kappa P/A. The one hint, rule-mean ln(L_99.9/R_eq) against rule-mean ln kappa (Spearman -0.835 at k=22, -0.918 at k=25), is size-contaminated. Is there rule-specific kappa left once area is held fixed, and does the cutoff association survive?
Quantities and estimators (fixed now)
Unit = window (rule, seed, k). ln A = ln area at window end, ln kappa as in the files.
- M1: pooled OLS ln kappa ~ ln A (all windows, both k); then a one-way ANOVA intraclass correlation (unbalanced-n correction) of the residual by rule, plus the same ICC for ln kappa without the area adjustment.
- M2: between-rule slope (regress rule-means) and within-rule slope (rule-demeaned) of ln kappa on ln A, with rule-bootstrap 95% intervals (seed 20261014, 500 resamples).
- M3: partial Spearman of rule-mean ln(L_99.9/R_eq) and rule-mean ln kappa given rule-mean ln A, separately for k = 22 and k = 25 (rank-residual method), with a rule-bootstrap interval (2000 resamples). The open-time-share <= 0.10 subset is the censoring sensitivity.
Predictions (fixed now)
- M1. The rule ICC of the area-adjusted residual is >= 0.40 at the window level (the earlier fixed-t kappa ICC was 0.58; area is allowed to absorb at most about a third of the rule signal). If < 0.25, rule dependence of kappa at fixed A is essentially nil.
- M2. The within-rule slope exceeds the between-rule slope by >= 0.3 (within a rule, A rises with t while kappa is flat in time, so its slope is near 0; across rules at fixed t the slope should be clearly negative). If the two agree within 0.15, area is the sole carrier of the between-rule differences.
- M3. The partial Spearman of ln(L_99.9/R_eq) with ln kappa given ln A is negative with |partial rho| >= 0.30 at both k = 22 and 25, and its bootstrap interval excludes 0 at both. Otherwise the excursion-cutoff hint is declared a size effect.
Decision rules
- 1 and 3 hold: rule-specific kappa at fixed area exists and tracks the extreme-excursion scale; next step is a transplant intervention (T2) with exact quantiles and matched-area pairs.
- 1 holds, 3 fails: kappa has a rule-specific part that is not the excursion cutoff; the T1 route
is closed and the next test needs a different observable (e.g. colour flux through the edge,
examples/kappa_rs_colourflux.rs). - 1 fails: kappa at matched area is not a rule property; the paper's ICC 0.58 should be qualified as "at fixed t".
- Observational only; no causal claim follows from any outcome.
Command
uv run experiments/2026-10-14-kappa-matched-area/scripts/matched_area.py
Output: results/matched_area.txt (commit, input hash, numbers). notebook.ipynb is the template
stub until results exist.
Status
Closed 2026-10-15: three registered analyses run (matched_area, matched_pairs, noise_floor); outcome unresolved-to-weak, no T2 on this pair set. Open: rule-level regression (unregistered, not run). notebook.ipynb executed from a clean kernel and agrees with this README.
Results (2026-10-14 22:35 NZDT; predictions above unchanged)
uv run experiments/2026-10-14-kappa-matched-area/scripts/matched_area.py -> results/matched_area.txt
(commit 797704a, dirty tree; input sha256[:16] e813c6f21f63421c; 1399 windows, 44 rules).
- M1: FAILED as registered, not into the "nil" band. Pooled ICC of the area-adjusted residual is 0.286 (needed >= 0.40; "essentially nil" was < 0.25). Raw ln kappa ICC 0.674. Post hoc, by window: adjusted ICC 0.561 (k=22) and 0.467 (k=25). These are not the registered estimator and are not used to rescue M1; the pooled slope mixes the between- and within-rule slopes below, which is what lowers the pooled value.
- M2: FAILED, and my sign assumption was wrong. Slopes of ln kappa on ln A are positive: between rules 1.271 [1.107, 1.403], within rules 0.420 [0.152, 0.652] (500 rule-bootstrap resamples). Registered: within - between >= 0.3; observed -0.851. I had assumed kappa falls with area across rules; the opposite holds at fixed t in this sample. Area is not the sole carrier (the two slopes differ), but the registered picture of the confound was wrong.
- M3: HELD. Partial Spearman of ln(L_99.9/R_eq) with ln kappa given ln A: -0.560 [-0.743, -0.333] at k=22, -0.695 [-0.827, -0.526] at k=25; with open share <= 0.10: -0.551 and -0.693. |rho| >= 0.30 with intervals excluding 0 at both windows.
Reading (interpretation, not observation). Decision rules: 1 failed outright by its own threshold, 3 held, so the registered branches conflict; the result is unresolved, not "kappa has a rule-specific part at fixed area". What survives is that the cutoff/radius association is not removed by a linear-in-ln A adjustment (M3), which is stronger than I expected. Caveats: the ICC treats windows of one seed as exchangeable; ln A adjustment is linear and is not matched-area pairs; the cutoff is a log-linear within-octave quantile with censoring; rule means share seeds across k; 44 rules; M2's sign error means the T1 narrative "inverse territory size" needs re-reading before the next design. Next: matched-area pairs (rules within 5% in A at a fixed k, difference in ln kappa against difference in ln cutoff/R), registered first, then a transplant intervention only if that holds.
Matched-pairs results (2026-10-15 19:45 NZDT; predictions above unchanged)
uv run experiments/2026-10-14-kappa-matched-area/scripts/matched_pairs.py -> results/matched_pairs.txt
(base commit 7eff085, dirty tree; input sha256[:16] e813c6f21f63421c; 44 rules per k).
- P-c held: 62 (k=22) and 67 (k=25) matched pairs at tolerance 0.05.
- P-a FAILED: median |d ln kappa| in matched pairs is 0.142 vs 0.593 for all pairs (ratio 0.24) at k=22 and 0.127 vs 0.658 (0.19) at k=25. Both are in the registered "< 0.25 -> kappa determined by area at fixed t" band (k=22 only just). Sensitivity at tol 0.10 gives 0.25 and 0.20: same conclusion.
- P-b HELD: in 82% (k=22, cluster-boot95 [0.64, 0.96]) and 76% (k=25, [0.55, 0.94]) of matched pairs the higher-kappa rule has the smaller ln(L_99.9/R_eq). Tol 0.10: 76%/77%, intervals exclude 0.5.
Reading (interpretation). The branches conflict again, now in a different way: most of kappa's rule variation at fixed t is carried by area, yet the small residual kappa difference still orders the cutoff in about 4 of 5 pairs. Per the registered decision rule P-a failing means the paper's rule-ICC for kappa should be qualified as "at fixed t". Not tested: the matched-pair |d ln kappa| of ~0.13 is not compared with the seed-to-seed noise (median between-seed ln-kappa sd is not computed here), so a residual of that size may be mostly noise; if so P-b's 76-82% would be surprising and worth a closer look, but a residual that small is also what a transplant (T2) would struggle to detect. Next: compute the seed-noise floor for ln kappa and ln ratio, and restrict P-b to pairs with |d ln kappa| above it, before designing T2. Observational only.
Seed-noise floor (registered 2026-10-15 20:10 NZDT, base commit da88e61, before scripts/noise_floor.py was run)
No new simulation; same input as above (t1b_cutoff_seeds.csv, escaped windows excluded), same matched pairs
(tol 0.05 registered, 0.10 sensitivity), rule means over seeds as before. Bootstrap seed 20261016.
Quantities: s_i = between-seed sd of ln kappa (and ln_ratio) within rule i at fixed k; SE of a pair difference = sqrt(s_i^2/n_i + s_j^2/n_j); z = |d ln kappa| / SE.
- N1: median within-rule seed sd and median pair SE(d ln kappa); fraction of matched pairs with z > 2.
- N2: P-b (higher-kappa rule has smaller ln_ratio) restricted to pairs with z > 2, cluster bootstrap by rule.
- N3 (shared-seed coupling control): split each rule's seeds by parity; kappa and area-free matching from the full-seed ln A as before, but kappa from even seeds and ln_ratio from odd seeds, so no trajectory contributes to both sides of a pair comparison. Fraction of pairs where the even-seed higher-kappa rule has smaller odd-seed ln_ratio. Rules with < 2 seeds in either half are dropped (count reported).
Predictions (fixed now):
- N1: median seed sd of ln kappa <= 0.10, median pair SE <= 0.05, and >= 60% of matched pairs at z > 2 (so the median matched |d ln kappa| of ~0.13 is mostly signal). If < 40% of pairs reach z > 2, the residual is mostly noise.
- N2: restricted fraction >= 0.75 at both k with bootstrap interval excluding 0.5 (if the z > 2 pairs are fewer than 20 per k, report but do not judge).
- N3: split-seed fraction >= 0.65 at both k. If <= 0.58 (or interval contains 0.5) at either k, the P-b result is attributed to within-seed coupling of kappa and ln_ratio, not a rule-level association.
Decision: 1-3 hold -> the residual is rule-level and orders the cutoff; design T2 on matched pairs with z > 2. N1 fails -> P-b is uninformative at this noise level, no T2. N3 fails alone -> P-b is a within-trajectory identity, not a rule property. Observational only.
Seed-noise floor: result (2026-10-15, commit da88e61)
Command: uv run experiments/2026-10-14-kappa-matched-area/scripts/noise_floor.py -> results/noise_floor.txt
(regenerated byte-identically on rerun). 44 rules per k, 6-8 seeds per rule, tol 0.05 (registered; 0.10 in the file).
| k=22 | k=25 | registered | verdict | |
|---|---|---|---|---|
| N1 median seed sd ln kappa | 0.089 | 0.089 | <= 0.10 | held |
| N1 median pair SE | 0.043 | 0.037 | <= 0.05 | held |
| N1 frac pairs z > 2 | 0.387 (24/62) | 0.582 (39/67) | >= 0.60 | failed at both k; k=22 is below the 0.40 "mostly noise" line |
| N2 P-b on z > 2 pairs | 0.917 [0.50, 1.00] (24 pairs) | 0.949 [0.78, 1.00] (39 pairs) | >= 0.75 and interval excludes 0.5 | k=22 failed (interval contains 0.5); k=25 held |
| N3 split-seed P-b | 0.790 [0.59, 0.95] | 0.806 [0.61, 0.95] | >= 0.65, interval excludes 0.5 | held at both k |
Sensitivity (tol 0.10) tells the same story: z > 2 fractions 0.43/0.59, N2 0.87 [0.61, 1.00] / 0.90 [0.75, 1.00], N3 0.72 [0.55, 0.88] / 0.77 [0.59, 0.91].
Reading against the pre-registered decision rule: N1 failed, so by the letter of the rule P-b is "uninformative at this noise level, no T2 on this matched set". Two things cut the other way and are reported rather than used to rewrite the rule. (i) N3, the control aimed at within-seed coupling, held clearly, so the association is not an artefact of kappa and ln_ratio sharing trajectories. (ii) Among pairs that do clear the noise floor P-b is high (0.92/0.95), and at k=22 the complement (z <= 2) is still 0.76, whereas at k=25 the complement is 0.50, i.e. at k=25 the association sits entirely in the resolved pairs, which is what a real signal diluted by noise would look like, and is not what pure noise would look like (it would be 0.5 everywhere). Caveats: z uses seed sd of ln kappa only and treats rule sd as known; pairs are matched on noisy mean ln A (selection on A noise can leak into kappa through Eq. 1); pairs share rules, so pair counts overstate independent information (the bootstrap is by rule, but the k=22 interval is wide); the z > 2 cut is a post-selection on |d ln kappa|, so a high P-b there is partly guaranteed to be easier to see, not independent evidence. Open: a rule-level (not pair-level) test, e.g. regress ln_ratio on odd-seed kappa residual given A with rule random effects, would use all 44 rules without matching.
Analysis notebook: notebook.ipynb
4 saved outputs · 4 code cells. Cells are not executed during publication. Download notebook
Does rule-specific kappa survive controlling for territory size?
Experiment 2026-10-14-kappa-matched-area. Written for a reader who has not seen the work. Observational reanalysis only: no new simulation.
Question. In the T1/T1b patched-start windows (44 rules, k = 22 and 25, 6-8 seeds each) kappa and territory area A are tied at fixed t by dA/dt = c kappa P/A. Once A is held fixed, is there still a rule-level kappa, and does it track the extreme-excursion cutoff ln(L_99.9/R_eq)?
Assumptions. Seeds are exchangeable replicates of a rule; windows from one seed at k=22 and 25 are not independent (the pooled ICC ignores this); escaped windows are excluded as in T1b; area adjustment is linear in ln A; matching uses rule-mean ln A with tolerance 0.05 (0.10 as sensitivity).
Three analyses, each registered in README.md before it was run: (1) matched_area.py (ICC, slopes, partial Spearman), (2) matched_pairs.py (matched-area pairs), (3) noise_floor.py (seed-noise floor). Notebook reads only committed results/.
Code
import hashlib, subprocess, pathlib
root = pathlib.Path('.').resolve()
res = root / 'results'
if not res.exists(): res = root / 'experiments/2026-10-14-kappa-matched-area/results'
print('git HEAD (at notebook run):', subprocess.run(['git','rev-parse','--short','HEAD'],capture_output=True,text=True).stdout.strip())
for f in sorted(res.glob('*.txt')):
print(f.name, hashlib.sha256(f.read_bytes()).hexdigest()[:16])
print('upstream input t1b_cutoff_seeds.csv sha256[:16] (recorded in results headers): e813c6f21f63421c')
1. Area adjustment (matched_area.txt)
Code
print((res/'matched_area.txt').read_text())
Shows: adjusted rule ICC 0.286 (registered threshold 0.40, so M1 failed, but above the 0.25 "nil" band); both slopes of ln kappa on ln A are positive (between rules 1.27, within 0.42), so my registered sign for M2 was wrong and M2 failed; the partial Spearman of cutoff with kappa given A is -0.56 / -0.70 (M3 held). Does not show: that the branches agree. M1 failed and M3 held, so the registered decision was unresolved. Per-k adjusted ICCs (0.56/0.47) are post hoc.
2. Matched-area pairs (matched_pairs.txt)
Code
print((res/'matched_pairs.txt').read_text())
Shows: matching on area removes most of the kappa spread (median |d ln kappa| ratio 0.24 / 0.19, P-a failed); the higher-kappa rule still has the smaller cutoff in 82% / 76% of pairs (P-b held). Does not show: that the residual exceeds seed noise; that is analysis 3.
3. Seed-noise floor (noise_floor.txt)
Code
print((res/'noise_floor.txt').read_text())
Shows (registered tolerance 0.05):
| k=22 | k=25 | registered | verdict | |
|---|---|---|---|---|
| N1 seed sd ln kappa / pair SE | 0.089 / 0.043 | 0.089 / 0.037 | <= 0.10 / <= 0.05 | held |
| N1 frac pairs z>2 | 0.39 | 0.58 | >= 0.60 | failed |
| N2 P-b on z>2 pairs | 0.92 [0.50, 1.00] (24 pairs) | 0.95 [0.78, 1.00] (39) | >= 0.75, interval excludes 0.5 | k=22 failed, k=25 held |
| N3 split-seed P-b | 0.79 [0.59, 0.95] | 0.81 [0.61, 0.95] | >= 0.65 | held |
By the registered decision rule N1 failed, so P-b is uninformative at this noise level and no T2 is designed on this pair set. Points the other way (not used to rewrite the rule): N3 held, so the association is not within-trajectory coupling of kappa and ln_ratio; at k=25 the z <= 2 complement is at 0.50 (about what pure noise gives) while resolved pairs are at 0.95.
Caveats
- z uses seed sd of ln kappa only; the z > 2 cut is a selection on |d ln kappa|, so the high P-b there is partly built in.
- Pairs share rules, so pair counts overstate independent information; the bootstrap is by rule, and the k=22 interval is wide.
- Matching on noisy mean ln A can leak area noise into kappa through the identity above.
- k=22 and k=25 windows share seeds and rules; they are not independent replications.
- 44 rules, 6-8 seeds each.
Conclusion and next steps
Rule-specific kappa at fixed area is not established: the effect may be real and small (N3, k=25 complement) but the matched pairs cannot resolve it in about half the cases, and two of the three registered noise-floor criteria failed. The paper's rule-ICC for kappa should be qualified as "at fixed t". Open (needs registering before it is run): a rule-level regression of ln_ratio on the kappa residual given ln A with rule random effects and split seeds, using all 44 rules and no matching.
Read the dated lab log
Kappa matched-area lab notebook
Append-only. Tags: intent, assumption, observation, interpretation, surprise, decision, dead-end, question, deviation.
2026-10-14 22:25 (+13:00) · 797704a · intent
Follow the T1b continuation's "next work": decide whether rule-specific kappa survives matching on territory size, using existing T1b windows, before spending simulation on interventions (T2). Predictions in README.
2026-10-14 22:25 (+13:00) · 797704a · assumption
Seeds are replicates of a rule, and windows from the same seed at k=22 and 25 are not independent; the pooled ICC treats them as exchangeable and overstates precision. Check: ICC by k separately (the script prints it). Untested.
2026-10-14 22:25 (+13:00) · 797704a · assumption
At fixed t, ln A and ln kappa are linked by the identity of Eq. 1, so "controlling for area" removes part of the signal by construction; the M1 threshold of 0.40 was chosen with that in mind, not derived.
2026-10-14 22:35 (+13:00) · 797704a · observation
matched_area.py (README command) -> results/matched_area.txt. Pooled ICC raw 0.674, area-adjusted 0.286; by k adjusted 0.561 / 0.467. Slopes of ln kappa on ln A: between rules +1.271, within rules +0.420. Partial Spearman cutoff/R vs kappa given A: -0.560 (k=22), -0.695 (k=25), intervals exclude 0.
2026-10-14 22:35 (+13:00) · 797704a · surprise
Both slopes are positive. The registered M2 assumed the across-rule slope would be clearly negative. I mis-signed the confound; M2 therefore failed for a reason unrelated to the hypothesis it was meant to test. T1's "inverse territory size" wording needs re-reading.
2026-10-14 22:35 (+13:00) · 797704a · interpretation
M1 failed (0.286 < 0.40) while M3 held, so the registered decision branches conflict; call it unresolved. The per-k adjusted ICCs (0.47-0.56) are post hoc and not a substitute. The pooled ICC is probably depressed because the pooled slope blends between (1.27) and within (0.42) slopes. Confidence low. Alternatives: seed replicates are not exchangeable across k; the linear area adjustment is wrong in form.
2026-10-14 22:35 (+13:00) · 797704a · decision
Do not run an intervention yet. Register matched-area pairs first (README "Next").
2026-10-15 19:45 (+13:00) · 7eff085 · intent
Register and run matched-area pairs (README second section) before any intervention.
2026-10-15 19:45 (+13:00) · 7eff085 · observation
matched_pairs.py -> results/matched_pairs.txt. Tol 0.05: 62/67 pairs; median |dlnk| ratio matched/all 0.24/0.19 (P-a failed, <0.25 band); higher-kappa rule has smaller cutoff in 82%/76% of pairs, intervals exclude 0.5 (P-b held).
2026-10-15 19:45 (+13:00) · 7eff085 · interpretation
Area carries most of kappa's rule variation at fixed t; a small residual still orders the cutoff. Confidence low-moderate: seed-noise floor for the residual not yet computed. Notebook.ipynb not updated (still template stub for this section) and should be before closing the experiment.
2026-10-15 19:45 (+13:00) · 7eff085 · decision
No intervention yet. Next: seed-noise floor and noise-restricted P-b.
2026-10-15 20:10 (+13:00) · da88e61 · intent
Compute the seed-noise floor and noise-restricted P-b per the third README registration (written before the run).
2026-10-15 20:30 (+13:00) · da88e61 · observation
noise_floor.py -> results/noise_floor.txt (rerun byte-identical). Seed sd ln kappa 0.089, pair SE 0.043/0.037. Frac z>2: 0.387 (k=22), 0.582 (k=25). P-b on z>2: 0.917 [0.50,1.00] (24 pairs), 0.949 [0.78,1.00] (39). Split-seed N3: 0.790 [0.59,0.95], 0.806 [0.61,0.95].
2026-10-15 20:30 (+13:00) · da88e61 · interpretation
Registered N1 (>=60% z>2) failed at both k and N2 failed at k=22 (interval contains 0.5); N3 held. Letter of the decision rule: no T2 on this matched set. N3 and the k=25 complement at 0.50 argue the residual is a real but small rule-level effect, only resolvable in about half the pairs. Confidence moderate-low; not a pass.
2026-10-15 20:30 (+13:00) · da88e61 · decision
Do not run T2 on these pairs. Next candidate (needs registering first): rule-level mixed-effects regression of ln_ratio on kappa residual given A using all 44 rules, split-seed. notebook.ipynb still lacks this section and the matched-pairs one.
2026-10-15 20:45 (+13:00) · da88e61 · decision
Close the experiment. notebook.ipynb written and executed (nbconvert under uv --with, jupyter not in pyproject.toml); covers all three analyses and matches the README. The rule-level mixed-effects regression stays an open, unregistered follow-up; not started. No commit made (not asked).