Field notes / Experiment guide
Does the opening-run effect survive a different growth clock?
A rule’s initial run of identical letters predicts boundary occupation after area adjustment. Does using current rather than early area change that association?
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
Matched rule families with fixed composition should retain a positive effect if early-area conditioning is not creating it.
What we learned
The support gate fails: too few complete families survive. The registered effects are therefore not fitted or scored.
What this leaves open
Differential retention is the result here, not evidence for or against the effect. Lowering the gate after the run would change the test.
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
Does the leading run predict boundary occupation beyond the growth clock?
Registered 2026-10-16 21:14 +13:00, base c9811f56911ff4e7fd8cfe5e76cd5d461968265b, dirty shared workspace. No measurements of this cohort have been made.
Question and design
The fresh-leading-run study found a positive lead coefficient after controlling early area, but early area is a post-treatment variable and the mutation response is asymmetric. Does the association survive replacing early area with area at the actual measurement window? This is a descriptive growth-history audit, not a causal adjustment or a new explanation for kappa.
Generate 16 independent nine-letter suffixes using numpy default_rng(2026101607).
Each family contains four 14-letter rules R^k L R^(4-k) SUFFIX, k=1..4. Thus
length, total R count and all letters at indices >=5 are identical within family.
Exclude any family containing a rule in the earlier fresh or mutant manifests.
Four fresh patch seeds 202610160701..202610160704; probe 24 4096 (2^24 steps).
These are fresh rules and starts; neither stationarity nor growth exponent is
used to select the cohort. Moving the first L also changes its index: this design
does not distinguish lead length from the position of that letter.
Primary window k=23, secondary k=21,22. Early area is end-of-window A18. For each rule, average logs across seeds that complete the target and early windows with B>0. Require >=3/4 seeds per rule. Report all escapes and exclusions. Primary gate: >=12 complete families, all four rules qualifying. Fit only those complete families; report selection by lead. Gate failure makes scientific predictions uninformative. Report between-seed sd alongside means.
Predictions fixed before measurement
Thresholds are design choices. Primary P1: in OLS ln kappa ~ spline(ln A23)+lead, the lead coefficient is positive with 95% family-bootstrap interval above zero and at least half its coefficient in ln kappa ~ spline(ln A18)+lead. Splines are linear hinges at 25/50/75% training quantiles, with a linear term and intercept. If the early coefficient is <=0, the expected effect has not replicated and P1 fails.
P2: adding lead to the current-area spline improves leave-one-family-out R2 by >=0.05, with lower 95% family-bootstrap interval above zero. R2 denominator is squared deviation from each fold's training mean. Knots are fit in each fold. Bootstrap 2000 draws, seed 2026101608; gain intervals resample out-of-fold loss contributions by family (uncertainty conditional on fitted folds).
Specificity/accounting, descriptive only: decompose the lead coefficient using ln kappa = ln(B/S) - ln(P/A), with exactly the same design matrix. Report current area + early area (linear) sensitivity, and all three windows. Never call this decomposition independent prediction. No intervention is justified by this audit.
Controls and reproducibility
Before ant analysis, calibrate coefficient recovery and zero added signal on
synthetic responses in the exact spline model; verify the decomposition identity.
There is no growth-exponent estimator in this experiment, so rotor/random-walk
exponent calibration is not used. Run release tests. Spot-check four first-family
specs on CPU against GPU, byte for byte, before the main GPU batch; GPU lanes=256,
pool=4 GB, grid=4096. Record source/input hashes, exact commands and dirty state.
Batch checkpoint .done is accepted only when recipe hashes match. Completed
CSV windows are published under results; bulk CSV stays in dumps. No existing
results are overwritten. All scripts run from the repo root under uv in WSL.
export UV_PROJECT_ENVIRONMENT=$HOME/.venvs/turmite UV_LINK_MODE=copy
uv run experiments/2026-10-16-kappa-growth-clock/scripts/sample.py
bash experiments/2026-10-16-kappa-growth-clock/scripts/run.sh
uv run experiments/2026-10-16-kappa-growth-clock/scripts/analyse.py
uv run --with nbconvert --with ipykernel --with nbformat jupyter nbconvert --to notebook --execute --inplace experiments/2026-10-16-kappa-growth-clock/notebook.ipynb
Related: ../2026-10-16-kappa-leadrun-fresh/README.md,
../../notes/kappa-mechanisms-2026-10-15.md. No literature claim is being made.
Results
UNINFORMATIVE: support gate failed. All three windows retain only 7/16 complete families versus the required 12. P1/P2 were not fitted or scored. There are 212 usable starts of 256 in each window; 40 miss A18 and four more miss the target. Overall 45 starts eventually escape, including one after a complete target window. No zero-boundary exclusions occur. Qualifying rules (>=3 starts) by lead 1/2/3/4: 16/9/15/13 out of 16 each. This is differential retention, not evidence for or against the lead effect.
Do not lower the gate or interpret a survivor-only fit as confirmation. A larger board could diagnose censoring, but this run does not identify highways or other growth regimes; no detector was run. Any follow-up must retain this cohort, preserve its failures and register its cap/grid before measurement.
Recipe: commands above, base c9811f5 (dirty source hashes in
results/run-sources.sha256; frozen protocol in results/registration.md).
results/seed_status.csv lists every exclusion; rule_means_k*.csv includes all
64 rules, with n=0 for absent usable starts. results/windows.csv publishes
k=18..23; analysis.json records hashes, counts and estimator calibration.
Seeds and parameters remain as registered. No effect uncertainty is reported
because the gate stopped fitting; per-rule between-seed sd(log kappa) is in the
CSV summaries where available.
All release tests passed, GPU probe tests 5/5 passed, and four CPU/GPU 2^24 trajectories are byte-identical. Synthetic planted slope 0.20 is recovered to roundoff; with correlated lead/area and family noise, 200 synthetic repeats have mean bias +0.000212 for both null and planted 0.15 slopes. The known area-only cross-validation gain is 0.0000231. These calibrate the instrument, not the ants. GPU batch: lanes=256, pool=4 GiB, grid=4096, 15.66 seconds, no requeues (descriptive timing, no CPU speed benchmark). The notebook is executed separately.
The full 256-spec CPU replay is byte-identical to the frozen GPU output
(results/cpu-replay-check.txt). This also supplies a reproduction path without
the GPU port, which was uncommitted shared work when this investigation ran:
bash experiments/2026-10-16-kappa-growth-clock/scripts/replay_cpu.sh.
If the GPU dump is absent, copy dumps/cpu-replay.csv to dumps/probe.csv
inside this experiment before running analyse.py. The replay verifies the frozen
digest before reporting success. scripts/check_replay.py verifies seven
published analysis files byte for byte; batch resume verifies its recipe/digest.
Analysis notebook: notebook.ipynb
3 saved outputs · 3 code cells. Cells are not executed during publication. Download notebook
Question and why it matters
Does opening-run length predict late boundary occupation after adjusting for the area reached in that same window? Earlier area is a post-treatment variable and may leave growth-history confounding. See registration and results and mechanism context.
Assumptions and definitions
Kappa = (B/S)/(P/A), where B counts steps starting on visited boundary cells and P counts visited cells with an unvisited four-neighbour. All quantities use the probe's octave windows. Conditioning on area is descriptive and cannot estimate a causal direct effect. Constant composition does not distinguish leading-run length from first-L position. CPU/GPU equivalence is checked before the sweep.
Code
from pathlib import Path
import hashlib, json
SEED = 2026101608
root = Path.cwd().resolve()
while not (root / 'Cargo.toml').exists():
if root == root.parent:
raise RuntimeError('Repository root not found')
root = root.parent
exp = root / 'experiments/2026-10-16-kappa-growth-clock'
paths = [exp / 'results' / s for s in ['analysis.json', 'cohort.csv', 'windows.csv', 'registration.md', 'spot-check.txt']]
for p in paths:
assert p.is_file(), p
print(str(p.relative_to(root)), hashlib.sha256(p.read_bytes()).hexdigest())
report = json.loads(paths[0].read_text())
print('Seed:', SEED, 'Simulation base commit:', report['git'])
print('Run commit:', (exp / 'results/run-commit.txt').read_text().strip())
print('Date: 2026-10-16 +13:00; exact raw/source hashes are in analysis.json and run-sources.sha256')
Data and method
Sixteen nine-letter suffixes each supply four 14-letter rules with leading runs 1..4; all rules in a family have equal composition. Four patch seeds per rule, 2^24 steps, grid 4096. Primary k=23, secondary k=21,22; early area is A18. No stationarity or exponent filtering. Require three completed seeds per rule and twelve complete families. OLS area controls use training-fitted spline hinges. Prediction uses leave-one-family-out folds. Uncertainty resamples whole families. The heavy computation lives in scripts/run.sh and scripts/analyse.py; this notebook reads only published results and makes no new estimates.
Code
print('Runs:', report['runs'], 'Escaped:', report['escaped'])
print((exp / 'results/spot-check.txt').read_text().strip())
print((exp / 'results/cpu-replay-check.txt').read_text().strip())
print(json.dumps(report['calibration'], indent=2))
print('Attrition:', report['status_counts'])
Results
The early and current slopes use the same response and rules, changing only the area-control window. P1 requires the current slope to retain half the early slope and have a positive interval. P2 requires gain >=0.05 and a positive interval.
Code
for r in report['windows']:
print('Window', r['k'], 'families', r['complete_families'], 'retention', r['qualifying_by_lead'])
if not r['gate_passed']:
print(r['verdict']); continue
print('Early slope %.4f %s; current %.4f %s' % (r['early_slope'], r['early_ci'], r['current_slope'], r['current_ci']))
print('Held-out gain %.4f %s; P1 %s; P2 %s' % (r['gain'], r['gain_ci'], r['P1'], r['P2']))
print('Accounting: boundary %.4f - edge fraction %.4f = kappa %.4f' % (r['boundary_log_slope'], r['edge_fraction_log_slope'], r['current_slope']))
print('Both-area linear slope %.4f; median between-seed sd(log kappa) %.4f' % (r['both_area_linear_slope'], r['between_seed_sd_median']))
These tables show whether the registered association survives a different growth-clock control. They do not separate cause from response to growth history.
Final verdict: UNINFORMATIVE. All three windows retain seven complete families, below the registered twelve-family gate. P1/P2 were not fitted or scored. Of 256 starts, 45 eventually escape; 40 miss the early window and four more miss the targets. The 212 valid starts do not supply balanced families. This does not support or reject the lead association.
Caveats and controls
Synthetic exact-spline and correlated-noise controls calibrate the regression; the coefficient decomposition is an identity. CPU/GPU outputs are compared byte for byte on all 256 specs and release tests recorded. The cohort has only sixteen independent suffix families and uses a shorter horizon than the previous 2^27 study. Area and perimeter are measured on the response trajectories; neither is an independent causal control. Gain intervals condition on fitted folds. Support failure means uninformative, and failed thresholds remain failed.
What this changes / next steps
Read the frozen primary verdict in results/analysis.json together with the final README interpretation. If current-area adjustment removes the association, early area alone was insufficient at this horizon; if it survives, test transport with independent pre-window predictors before interventions. Longer-horizon and fixed-area replication are needed in either case.
Open questions: how much is survivor selection, which field history matters, and can first-L position be separated from opening-run length?
Read the dated lab log
Lab notebook
2026-10-16 21:14 (+13:00) · c9811f5 · intent
User requested a fresh experiment. Test whether the leading-run association survives contemporaneous area adjustment, using new paired-suffix families and fresh seeds. Registration is in README.md. Keep work isolated because the shared tree contains ongoing GPU and ribbon work.
2026-10-16 21:14 (+13:00) · c9811f5 · assumption
The current CPU/GPU probe implements the same octave window definition. Verify four specs byte-for-byte before trusting the GPU batch. Conditioning on current area remains post-treatment and cannot identify a direct causal lead effect.
2026-10-16 21:14 (+13:00) · c9811f5 · decision
Use constant length/composition families instead of independent random rules. Choose leads 1..4 because the prior study lost many high-lead rules; do not filter stationarity here. Record retention rather than silently changing the cohort.
2026-10-16 21:18 (+13:00) · c9811f5 · observation
bash experiments/2026-10-16-kappa-growth-clock/scripts/run.sh completed.
results/release-tests.log passes, gpu-tests.log has 5/5 passes, and
spot-check.txt records four byte-identical CPU/GPU trajectories. The GPU batch
has no pool requeues (results/gpu.json). Synthetic controls from
uv run experiments/2026-10-16-kappa-growth-clock/scripts/calibrate.py recover
the planted coefficient; finite-noise mean bias is +0.000212 over 200 repeats
(results/calibration.json).
2026-10-16 21:18 (+13:00) · c9811f5 · observation
uv run experiments/2026-10-16-kappa-growth-clock/scripts/analyse.py yields
7/16 complete families in all three windows; support threshold is 12.
results/analysis.json and seed_status.csv: 45/256 eventual escapes, 40
missing early windows, four further missing target windows, 212 usable starts.
rule_means_k23.csv: qualifying rule counts 16/9/15/13 by lead. No models fit.
2026-10-16 21:18 (+13:00) · c9811f5 · surprise, interpretation
Restricting lead to 1..4 did not preserve balanced support. Lead 2 loses most rules here, unlike a monotone high-lead attrition story. This does not diagnose highways: the instrument only records board escape. The complete-family gate prevents an unplanned survivor analysis. Growth-clock confounding remains open.
2026-10-16 21:18 (+13:00) · c9811f5 · decision
Close as UNINFORMATIVE. Keep the cohort and threshold fixed; do not expand the board or replace families after seeing attrition. Publish all seed statuses, including rules with no usable starts. Next candidate is a separately registered censoring audit on this same cohort. Finish notebook execution and deterministic rerun checks before committing the final record.
2026-10-16 21:21 (+13:00) · 9af869a · deviation
First replay comparison failed because another investigation committed to the shared branch between analysis runs, changing the report's ambient HEAD field. No scientific decision changes. Pin that provenance field to run-commit.txt; the analysis source is separately SHA-256 pinned. Rerun analysis and require byte-identical outputs before closing. Preserve unrelated staged/working changes.
2026-10-16 21:23 (+13:00) · 9af869a · observation
bash experiments/2026-10-16-kappa-growth-clock/scripts/replay_cpu.sh reproduces
the entire 256-spec GPU CSV byte for byte (results/cpu-replay-check.txt).
uv run experiments/2026-10-16-kappa-growth-clock/scripts/check_replay.py now
preserves all seven published outputs byte for byte (results/replay-check.txt).
Batch resume verifies its recipe and raw digest, then skips computation.
2026-10-16 21:24 (+13:00) · 916d2f4 · decision
Closed: registered support gate failed; P1/P2 remain untested. Notebook executed
top to bottom against committed inputs using the README nbconvert command
(results/notebook-check.log). Analysis replay still matches after commit.
README, executed notebook and JSON agree. No Rust instrument or dependency was
changed by this experiment. Retain fresh cohort for a prospectively registered
censoring follow-up; no additional runs are launched in this session.