# Cause test: the plan, fixed before the run

Written on October 12, 2026 (Halifax), at Colson's request, before any new start or branch is run. Revised the same
day after Colson's review of the first draft (SHA-256
fbbbfb2fe46f23ae76940a9a7fc14620e9a9da6148c38a798ad769be20ada30b), and again after his review of the second version
(SHA-256 69e94fff9c7e9d411f321c957fc04737a62ed8a79ff8f728da390488c586a08e). Nothing is run on the new starts until
he approves this version.

**What the first revision changed.** (1) Every intervention's immediate effects are recorded, and the matching of the
shams is checked as part of M1. (2) The starts are the units: the aggregation, the error bars and the decision are
written out as equations, and the decision code (cause_rule.py) is fixed with this plan. (3) PASS is worded as a
causal effect of the interventions in the model, not coherence as the only mechanism. (4) The gap at each moment is
specified, identical in every branch. (5) The chance of each decision was worked out with the final rule, and the
sample was doubled to 42 starts. (6) How the run is carried out in pieces is fixed.

**What the second revision changed.** (7) Up, down and sham must each reach their own coherence target, in each
group at every moment, not only through the difference between up and down. A target that cannot be reached and a
solver failure are handled by a rule fixed now: the moment is not carried out and the reason is recorded. Nothing is
clipped and nothing is replaced (section "Each arm reaches its own target"). The amplitude solver is specified
exactly, and the count of moments not carried out is part of M1. (8) The sham diagnostics are stronger: for each arm,
the achieved coherence changes and the changes in the phases' higher-order structure (|z₂|, |z₃|, |z₄|, the mean
phases and ψ_A − ψ_B) are reported against the sham, separately from the sizes of the moves, which are matched by
construction. (9) The 0.23% chance of a false positive is stated with the assumptions it rests on. (10) Before this
version, cause_test.py was written and tried: a target check worked out the planned changes at 4,200 states of old
starts (no branch was run from them), and a dry run tried every step. The decision code now averages each start over
the moments carried out and holds M1's count; with every moment carried out it gives the same numbers to the last
digit (design_numbers.py, run again with it, wrote its three files byte for byte as before). The run's pieces are
smaller, to stay well inside their time limit. The sample is still 42 starts.

When approved, cause_test.py's freeze step locks this plan. It writes the SHA-256 of this file (which must equal the
one Colson approved), of cause_test.py, of cause_rule.py, of design_numbers.py and its outputs, of the moment table,
of the target check's outputs, and of every script and saved result the test depends on into cause_lock.json, with
the time. The run and report steps stop if any of them has changed since. Nothing is run on the new starts before the
lock.

A toy model (two groups of phase oscillators, as in Memory in Motion). Whatever the result, it shows structure in
the model, not proof about anything beyond it.

## What led here (all on record, unchanged)

1. **The noticing** (Test 16, the long run at the threshold, starts 1 to 6): windows with higher coherence had
   slower growth of tiny gaps. Noticed after the run, not tested.
2. **The coherence–growth test** (starts 7 to 12, measures fixed before that run): no clear same-time link, but
   coherence now against the growth rate 200 to 500 time units later: −0.2061 (0.0186), below 0 in 6 of 6.
3. **The earlier-growth check** (exploratory, chosen after the test): with the growth over the 500 time units
   before held fixed, the later link stayed below 0 in all twelve starts.
4. **Test 17, the replication** (starts 13 to 18, pre-registered): with the earlier growth held fixed, −0.1044
   (error bar 0.0239), 4.4 error bars below 0, below 0 in 6 of 6: PASS. Unadjusted: −0.1927 (0.0205). It was
   replicated on new starts with the same code.

All of these are correlations in untouched runs: moments with more coherence are followed, 200 to 500 time units
later, by slower growth of a tiny gap, even with the earlier growth held fixed. Something else could drive both.
This test changes coherence directly, with everything else matched, and asks whether the later growth follows.

## Primary question

If coherence is raised or lowered at a chosen moment, does the growth of a tiny gap 200 to 500 time units later
change in the direction the correlation predicts (raised: slower; lowered: faster), compared with a matched sham
that moves the same phases by the same amounts without changing coherence?

## The baseline

- **The model, exactly as in Tests 16 and 17,** using nudge_test.py's own model and step code, imported unchanged
  (its SHA-256 is the one the page checks). Two groups of N = 4,000 phase oscillators, natural rates spread evenly
  over a Lorentzian of width 1, coupling K = 1.90 inside each group and ε = 0.1 between them, and no push.
  Oscillators with natural rates beyond ±20 turn freely: they count in the coherence but are never moved. Steps
  are 0.025 time units, settling 300 time units, then 6,000 time units.
- **The gap**, as before: a second copy with every pulled phase moved by a tiny random amount (rms 10⁻⁷ radians,
  overall timing unchanged). The gap is measured every 5 time units, the log of its growth noted, and it is put
  back to 10⁻⁷ in the direction it then points.
- **The base run** of each new start is that long run, step for step. It also keeps the full state (every phase of
  both copies) at each chosen moment. Its code must repeat the saved long run exactly (checked before the lock).
- **Test 17 and every earlier file stay as they are.** Test 17's link gives this test its expected direction and its
  benchmark size. Nothing in it is analysed again.

## The new data

- **Starts 19 to 60** (42 starts: seeds 18 to 59, gap directions from (20261011, 18 to 59), as nudge_test.py
  derives them). None has been run at this size: N = 4,000 has used starts 1 to 18 only.
- All 42 starts are used. None is dropped, replaced or added. A moment that is not carried out is not replaced
  either (section "Each arm reaches its own target").
- **Unbroken tasks.** The work is split into tasks: one start's base run, or all six branches of one moment. Each
  task runs from beginning to end without pausing, and finished tasks are kept until all are done. So the results do
  not depend on how the run is divided into pieces, and every branch starts from exactly the saved state.

## The moments

Ten per start, 350 time units apart:

    T = 2,000 + o + 350 m,   m = 0, 1, …, 9

The offset o is a multiple of 5 from 0 to 345, drawn once per start from seed (20261012, seed of the start). The
moments run from 2,000 to 5,495, so T + 500 stays inside the run. The windows measured after two moments of a start
never overlap. The table of all 420 moments (cause_moments.csv) is written now and locked. The run regenerates it
and must get the same table.

## The interventions

At a moment T, group g (A or B) has coherence

    z_g = R_g e^{iψ_g} = (1/N) Σ_j e^{iθ_j}

over all N oscillators, as it is measured throughout. Moving oscillator j by Δθ_j changes R_g, to first order, by

    ΔR_g ≈ (1/N) Σ_j sin(ψ_g − θ_j) Δθ_j

so moving each oscillator along sin(ψ_g − θ_j), toward or away from the group's mean phase, changes the coherence
most for the least movement.

- **Dense method:** every pulled oscillator of both groups is moved:

      Δθ_j = ± a_g sin(ψ_g − θ_j)

  The plus sign is **up** and the minus sign is **down**. The amplitude a_g is the value for which

      ½ [R_g(+a_g) − R_g(−a_g)] = f R_g,   f = 0.5

  where R_g(±a) is the group's coherence after the change. So up takes each group's coherence to about 1.5 R_g and
  down to about 0.5 R_g. Up and down share the amplitude, so their moves are mirror images; each arm is then checked
  against its own target (next section). To first order a_g = f R_g / [(1/N) Σ sin²(ψ_g − θ_j)], about 1.03 R_g.
  In the target check (next section), a_g was 1.03 R_g at the median (at most 1.08 R_g), and the largest move in a
  change was 0.032 radians at the median state (below 0.066 in 99% of states, 0.088 at most).
- **Sparse method:** the same form, applied only to a random tenth of each group's pulled oscillators (387 of
  3,872), drawn afresh for each moment and group, with its own amplitude b_g set by the same equation. This gives
  the same coherence change made by moving fewer oscillators further. In the target check, b_g was 10.5 R_g at the
  median (at most 12.3 R_g), and the largest move was 0.32 radians at the median state (below 0.71 in 99% of
  states, 0.99 at most). Moving a tenth of the oscillators by at most π/2 can change a group's coherence by only
  about 0.055 when the phases are spread evenly around the circle, so the sparse target cannot be reached when R_g
  is above about 0.11.
- **The amplitude, exactly** (a_g, and b_g for sparse): the smallest a in (0, π/2] that meets the equation. The left
  side, h(a), is worked out at a = π/512, 2π/512, …, π/2 (256 values). The first value where h reaches f R_g and the
  one before it (or 0) are halved between until they are less than 10⁻¹² apart; the upper one is the amplitude. The
  target is **feasible** if h reaches it at one of the 256 values. It is **solved** if every number is finite and h
  at the amplitude is within a relative 10⁻⁶ of f R_g. Otherwise the target is infeasible or the solver failed, and
  the moment is not carried out (next section). The amplitude stops at π/2 because beyond it an oscillator at right
  angles to the mean phase would be moved past the mean.
- **Sham, one for each method:** the same oscillators, each moved by exactly the amount it moves in up and down,
  a_g |sin(ψ_g − θ_j)| (b_g for sparse), with signs that cancel in the coherence. The oscillators are ranked by
  sin²(ψ_g − θ_j) and taken in pairs of neighbours. A random draw decides which one of each pair moves as in up
  and which as in down; if the count is odd, the last one gets a random sign. The phases change by the same amounts
  as in up and down, while the coherence stays close to where it was (within 5% in each group, checked in the next
  section).
- **None:** the base run carrying on untouched. This is a reference only.
- **What stays the same:** the same Δθ_j goes to both copies, so the gap itself is not changed (next section). Free
  turners are not moved. Natural rates and coupling are unchanged, and there is no push. The change is instantaneous
  at T, and then everything runs as before.

Every branch of a moment (up, down and sham for each method: six) starts from the identical saved state. Dense and
sparse are kept as separate methods throughout, each with its own sham.

## Each arm reaches its own target

Up and down share one amplitude, chosen so that their changes average f R_g. That alone does not show that each arm
reached its own target, so each is checked on its own. Just after the change, before any branch is run, each group's
coherence in each branch is compared with the group's coherence before the change. It must fall inside that arm's
band:

    up      1.45 ≤ R_g(after) / R_g(before) ≤ 1.55
    down    0.45 ≤ R_g(after) / R_g(before) ≤ 0.55
    sham    0.95 ≤ R_g(after) / R_g(before) ≤ 1.05

for both groups and both methods: twelve checks at every moment. Each band is the arm's target ± 0.05 R_g, a tenth of
the intended change of 0.5 R_g.

A moment is carried out only if all of the following hold:

1. all four amplitudes (two methods, two groups) are feasible and solved;
2. all twelve band checks pass;
3. in each method, up, down and sham move the same oscillators by the same amounts, and every branch leaves the gap
   as it was (the matching and gap checks of M1; the gap is in the next section).

If any of these fails, **none of the moment's six branches is run.** The moment is recorded as not carried out, with
every reason (such as "sparse target infeasible, group A (R = 0.1213)" or "dense down, group B at 0.5512 x R"). Both
methods lose the moment together, so they always rest on the same moments. **Nothing is clipped:** an amplitude is
never cut back to π/2 and used anyway, and a change outside its band is never kept. **Nothing is replaced:** no
moment is moved, redrawn or added, no start is dropped or added, and the amplitude is worked out once, from the
saved state, and never again with other settings.

Each start's averages are then over its moments carried out (normally all ten; see the primary outcome). The count
is part of M1: at most 21 of the 420 moments (1 in 20) may fail to be carried out, and every start must keep at least
5 of its 10. Otherwise the decision is INCONCLUSIVE. A failed matching or gap check (3) would be a code error, so M1
then fails for that method whatever the count.

**The target check, before this version** (cause_targets.txt and cause_targets.json, fixed with this plan). The
planned changes were worked out at every multiple of 5 from t = 2,000 to 5,495 in old starts 13 to 18 (Test 17's
replication starts): 4,200 states, each just after the gap was put back, as at the run's moments, with random draws
the run never uses. No branch was run from these states and no growth was looked at. The base-run code repeated all
six saved runs exactly, every value to t = 5,495.

- Each group's coherence at these states: median 0.025, 99% centile 0.060, largest 0.084 (the sparse limit is about
  0.11).
- Targets: all 16,800 feasible and solved (8,400 per method); none infeasible, no solver failure.
- Achieved R_g after / before, smallest to largest over both groups: dense up 1.4991 to 1.5002, down 0.4991 to
  0.5002, sham 0.9991 to 1.0003; sparse up 1.4839 to 1.5073, down 0.4839 to 0.5073, sham 0.9820 to 1.0097. None
  outside its band.
- Moments that would not be carried out: 0 of 4,200.
- Matching: the same oscillators and the same sizes of move in all three arms at every state (largest relative
  difference in Σ Δθ²: 0). Gap: largest |d_after − d_before| / |d_before|, 4.5 × 10⁻¹⁰.
- What the changes did beyond coherence (in full in cause_targets.txt): the sham changed C by −0.01% on average in
  the dense method and −0.12% in the sparse; ψ_A − ψ_B changed by under 0.001 radians on average in every arm; and
  each arm's average change in |z₂|, |z₃| and |z₄| differed from the sham's by at most 0.0006 (for example, |z₂| of
  group A, up − sham: +0.00015 dense and +0.00043 sparse, with SDs over states of 0.001 and 0.002).

## The gap at each moment

Every moment T is a multiple of 5, so it falls exactly where the base run has just measured the gap and put it
back. At T the second copy differs from the first by a gap of rms exactly 10⁻⁷ radians over both groups' pulled
oscillators, with the overall timing lined up, pointing in the direction the gap had reached by then. The saved state
at T is both copies at that instant.

In every branch the change is worked out from the first copy alone (its ψ_g and θ_j), and the identical Δθ_j is
applied to the same oscillator in both copies. With θ′ the second copy and d_j = θ′_j − θ_j the gap,

    d_j after the change = (θ′_j + Δθ_j) − (θ_j + Δθ_j) = d_j before

So the gap has the same size and direction before and after the change, and is the same in all six branches of the
moment and in the base run. Only the state it sits on differs. It is checked in every branch from the phases
themselves:

    |d_after − d_before| / |d_before| < 10⁻⁶      (|·|: the rms over both groups' pulled oscillators)

The phases are carried as points on the unit circle, so rounding moves the gap by about one part in a billion at
most. After T every branch runs exactly as the base run does: the gap is measured every 5 time units, the log of its
growth noted, and it is put back to 10⁻⁷ in the direction it then points. The free turners are the same in both
copies.

## Assignment: every moment gets every branch

Random assignment is needed when each unit can receive only one treatment. Here every moment receives all six
branches from the identical state, so each moment is its own control (a fully matched design). No moment is chosen
for one intervention over another, and nothing about a moment can favour one arm. The random parts are drawn
before anything is seen, from seed 20261012 with the seed of the start, the moment and the use (0: dense sham signs;
1: sparse subsets; 2: sparse sham signs; group A before B). They are the moment offsets, the sparse subsets and the
sham's signs. Nothing depends on what any branch does.

## What is recorded, for each branch

Just before and just after the change, from the first copy:

- each group's R_g and ψ_g, and C, the average of R_A and R_B; each group's R_g after / R_g before, and whether it
  is inside the arm's band;
- each group's |z₂,g|, |z₃,g| and |z₄,g|, where z_{n,g} = (1/N) Σ_j e^{inθ_j}: how the phases are arranged beyond
  their mean (a change can leave R_g where it was and still rearrange the phases);
- ψ_A − ψ_B, the phase difference between the groups.

For the change itself, both groups together:

- Σ_j Δθ_j², the total squared phase displacement (the sparse method's is about ten times the dense one's for the
  same coherence change);
- the number of oscillators moved, the largest |Δθ_j|, and the rms of Δθ_j over those moved;
- the gap's size before and after, and |d_after − d_before| / |d_before|.

For each method and group: the amplitude, and whether it was solved, infeasible or a solver failure. For each
moment: whether it was carried out, and if not, every reason.

After the change (moments carried out only):

- each group's coherence every time unit from T to T + 500;
- the gap's log growth for each 5-unit interval in (T, T + 500].

The outcome of the branch is

    G = (the sum of the log growths over the 60 intervals in (T + 200, T + 500]) / 300

the growth rate over the original 200 to 500 time-unit window.

## Primary outcome

For start s, moment m, method k (dense or sparse) and arm (up, down, sham), G_{s,m,k,arm} is the outcome above.
Each arm is compared with its own method's sham, at the same moment and from the same saved state:

    d^up_{s,m,k}   = G_{s,m,k,up}   − G_{s,m,k,sham}
    d^down_{s,m,k} = G_{s,m,k,down} − G_{s,m,k,sham}

Within a start, the moments carried out are averaged with equal weights:

    D^up_{s,k} = (1/M_s) Σ_m d^up_{s,m,k},   D^down_{s,k} = (1/M_s) Σ_m d^down_{s,m,k}
    S_{s,k} = (D^down_{s,k} − D^up_{s,k}) / 2

The sums run over the M_s moments of start s that were carried out: M_s = 10 when all are, and the same moments for
both methods.

Then the two methods are averaged with equal weights:

    D^up_s = ½ (D^up_{s,dense} + D^up_{s,sparse}),   D^down_s = ½ (D^down_{s,dense} + D^down_{s,sparse})
    S_s = (D^down_s − D^up_s) / 2 = ½ (S_{s,dense} + S_{s,sparse})
    P_s = (D^up_s + D^down_s) / 2

S is the effect of the direction of the change. The sham cancels from it: S_{s,k} is the average of
(G_down − G_up) / 2. P is whatever a change of this size does, either way.

**Predicted directions (registered):** D^up < 0 (raised coherence, slower later growth), D^down > 0, so S > 0.

## Uncertainty: the starts are the units

The 42 starts are independent: different starting phases and gap directions, a model with no noise, and nothing
shared between starts. They are the units of replication. The moments of a start are not treated as
independent: they come from one run and may go together. Averaging them first, inside the start, takes care of
that. However strongly they go together, it is already in the spread of the 42 per-start values, and that spread
is the only one the error bars use.

For any per-start quantity X_s (s = 1, …, n; n = 42):

    mean                   X̄ = (1/n) Σ_s X_s
    textbook error bar     e_t(X) = SD(X) / √n,   SD(X)² = Σ_s (X_s − X̄)² / (n − 1)
    resampled error bar    e_r(X) = the SD of the 400 means X̄⁽¹⁾, …, X̄⁽⁴⁰⁰⁾,   X̄⁽ᵇ⁾ = (1/n) Σ_i X_{π_b(i)}
    error bar              e(X) = the larger of e_t(X) and e_r(X)

Here π_b(1), …, π_b(n) are n starts drawn with replacement, the b-th of 400 draws from seed 20261015 (as in every
earlier part). The same draws are used for every quantity.

**How often chance alone crosses the lines, and what that rests on.** With no effect, a mean lands more than
3 error bars from 0 at most 0.23% of the time in each direction, and more than 2 error bars at most 2.6%. These
figures rest on assumptions: the 42 starts are independent, and their per-start values are close to normal with a
common spread (each is an average of up to 20 differences of growth rates). Then the mean divided by SD/√n follows
Student's t with 41 degrees of freedom, and because e(X) is never below SD/√n, the chances are at most those of t.
They are not guarantees beyond these assumptions: per-start values with heavier tails or stronger skew than the
normal curve could cross the lines more often. The simulated repeats in the sample-size section check the figures
under four noise models, one of them drawn from the shape measured in the saved runs, not under every possible one.

Also reported, not used for the decision: how much the moments of a start go together. This is the intraclass
correlation of the moment-level values x_{s,m} (those of S, D^up and D^down, for each method and pooled, over the
moments carried out), with x̄_s the start's mean over its M_s moments and x̄ the mean over all moments carried out:

    ICC = (MS_between − MS_within) / (MS_between + (n₀ − 1) MS_within)
    MS_between = Σ_s M_s (x̄_s − x̄)² / (n − 1),   MS_within = Σ_s Σ_m (x_{s,m} − x̄_s)² / (Σ_s M_s − n)
    n₀ = (Σ_s M_s − Σ_s M_s² / Σ_s M_s) / (n − 1)

With every moment carried out, n₀ = 10 and these are the usual formulas for equal groups. It comes with the design
effect 1 + (n₀ − 1) ICC. In the saved runs, the later growth left over at moments 350 apart went together at −0.07
on average (−0.18 to +0.03 by start), so the moments are close to independent. The analysis does not depend on this.

## The threshold

Test 17's link is a correlation. This test needs the same link in units of growth, so the benchmark is the slope
from the 18 saved starts. Start by start, least squares over every moment T = 2,000, 2,005, …, 5,500:

    W(T) = a + β·C(T) + c1·g1(T) + … + c5·g5(T)

Here W is the growth rate over (T + 200, T + 500], C(T) the coherence at T, and g1 … g5 the growth rate in the five
100-unit windows up to T. Averaged over the 18 starts, **β = −0.1602** (SD 0.0934), below 0 in all 18. By set,
starts 1 to 6 give −0.2251, 7 to 12 give −0.1420 and 13 to 18 give −0.1134. Starts 1 to 6 are where the link was
first noticed, so the average may be on the high side.

    δ = ½ × 0.1602 × |ΔC|

Here |ΔC| is the average size of the achieved coherence change in the up and down branches (both methods, over the
moments carried out). In words, δ is half the effect expected if the whole link measured in the untouched runs were
cause. Expected: ½ × 0.1602 × (0.5 × 0.0260) = **0.00104**, against an average later growth rate of 0.0140. Each
method's own reading uses its own δ_k, from that method's achieved |ΔC|.

## Manipulation checks

- **M1, the change happened as planned and the branches are matched.** For each method:
  - every branch carried out took each group's coherence inside its arm's band (up 1.45 to 1.55 times R_g, down
    0.45 to 0.55, sham 0.95 to 1.05; a moment where any branch misses its band is not carried out);
  - at every moment where the method's changes were worked out, up, down and sham move the same oscillators, and
    their Σ Δθ² agree within a relative 10⁻⁹ (by construction each oscillator moves by the same amount in all three);
  - in every branch worked out, the change leaves the gap as it was: |d_after − d_before| / |d_before| < 10⁻⁶.

  For both methods together, the count: at most 21 of the 420 moments not carried out (1 in 20), and at least 5 of
  every start's 10 carried out. If any part of M1 fails for either method, the decision is **INCONCLUSIVE**, whatever
  the outcomes, and is not read as a negative result. A failed matching or gap check would mean the code did not do
  what this plan says.
- **M2, the change lasted.** The share of the up–down coherence difference still there, on average, over
  (T, T + 200]:

      Φ = average of [mean C over (T, T + 200], up − down] / average of [C just after the change, up − down]

  Both averages are over the moments carried out. In the untouched runs, the matching share for a natural coherence
  difference is 0.363 (from the 18 saved starts). If Φ is below **0.181** (half of that), the change faded much
  faster than natural differences do. At that floor, an effect carried only by the coherence that remains would be
  expected at about half the benchmark, which is the threshold. A null result then cannot be read as negative, and
  FAIL becomes **INCONCLUSIVE**. Other readings stand.
  Φ is worked out for the two methods together (the overall decision) and for each method (its own reading).

## Decision rule (primary measure, starts 19 to 60 only)

The conditions, all from the per-start values above (pooled unless marked k):

    clear      S̄ > 3 e(S)
    sides      D̄^up < −2 e(D^up)   and   D̄^down > 2 e(D^down)
    agree      S̄_k > 2 e(S_k), for the dense and for the sparse method
    reversed   S̄ < −3 e(S)
    excluded   S̄ + 2 e(S) < δ

The overall decision is the first of these that applies:

1. M1 fails for either method (including the count of moments carried out): **INCONCLUSIVE**.
2. clear, sides and agree: **PASS** if S̄ ≥ δ; **SMALL** if S̄ < δ (real and in the predicted direction, but under
   half the benchmark).
3. clear, but sides or agree fails: **PARTIAL**. The report names each condition that failed: up not clearly below
   its sham, down not clearly above its sham, or a method whose S is not clearly above 0.
4. reversed: **REVERSED**.
5. excluded, and M2 holds: **FAIL** (no effect as large as half the benchmark).
6. otherwise: **INCONCLUSIVE**. The report says why: an effect of half the benchmark cannot be ruled out
   (S̄ + 2 e(S) ≥ δ), or the change faded too fast (M2).

**Each method's own reading** is reported beside the overall decision, but it is not the decision. It uses the same
rule with that method's per-start values (D^up_{s,k}, D^down_{s,k}, S_{s,k}), its own δ_k, M1 and M2, and no "agree"
condition.

The rule is written once, in cause_rule.py (its SHA-256 is listed below). The chances in the next section were
worked out with that code, and the report will use it unchanged.

No other window, method, subset of moments or set of starts will be read as the result. The individual-start values
and signs are reported whatever the decision.

## Sample size and the chance of each decision

The sample is 42 starts × 10 moments × 2 methods × 3 branches (2,520 branches), plus the 42 base runs. The chance of
each decision was worked out before the run by the decision code itself (design_numbers.txt). Each row is 4,000
simulated repeats of the whole test (20,000 for no effect), with the spread of later growth measured in the saved
runs standing in for the outcomes. This is sampling, not the model, and the manipulation checks are taken as passed,
with every moment carried out (the target check found none that would not be).

| assumed truth | expected noise | most cautious noise |
| --- | --- | --- |
| no effect | FAIL 99.6% | FAIL 91%, INCONCLUSIVE 9% |
| a quarter of the benchmark | PARTIAL 66%, FAIL 20%, SMALL 14% | INCONCLUSIVE 52%, FAIL 38%, PARTIAL 10% |
| half the benchmark | PASS 49%, SMALL 43%, PARTIAL 7% | PARTIAL 56%, INCONCLUSIVE 33%, PASS 8% |
| the benchmark | PASS 100% | PASS 80%, PARTIAL 20% |
| the benchmark, starts differing by half of it | PASS 100% | PASS 78%, PARTIAL 22% |
| the benchmark, plus a kick speeding growth as much either way | PARTIAL 98%, PASS 2% | PARTIAL 97%, PASS 3% |
| only lowering changes growth (the benchmark's size) | PARTIAL 97%, PASS 2% | PARTIAL 63%, INCONCLUSIVE 33%, PASS 1% |
| the benchmark in one method only | PARTIAL 97–98%, PASS 2–3% | PARTIAL 62%, INCONCLUSIVE 33%, PASS 2% |
| reversed, the benchmark's size | REVERSED 100% | REVERSED 100% |

**Expected noise** is the spread of later growth left over once C(T) and the earlier growth are known (0.0055),
with every branch and every moment independent. **Most cautious** is all of later growth's spread (0.0065), with the
two methods' noise taken as identical and a tenth of its variance shared by the ten moments of a start. In the saved
runs the moments went together at −0.07 on average, and at most +0.03 in any start. The branches of a moment share
their start, so both models probably overstate the noise.

**More noise** (the benchmark, PASS / no effect, FAIL; 2,000 repeats each): 99.8% / 99.5% at 1.5 times the expected
noise, 92% / 96% at twice, 73% / 86% at 2.5 times, and 45% / 70% at three times. Noise drawn from the measured shape
of what is left over gives the same chances as normal noise. With a tenth of the noise shared by a start's moments,
the benchmark gives PASS 99.9% and no effect gives FAIL 99.6%.

**False positives:** with no effect, a reading in the predicted direction (PASS, SMALL or PARTIAL) needs S̄ more than
3 error bars above 0. Since e(S) is never below SD/√42, this happens at most 0.23% of the time at any noise level,
under the assumptions stated in the uncertainty section (independent starts; per-start values close to normal with a
common spread). The four noise models run 20,000 times each give 0.20% to 0.24% (±0.03%); REVERSED likewise. Three
of them draw normal noise and one draws noise with the shape measured in the saved runs, so they check the figure
under those models, not under every possible one: per-start values with heavier tails or stronger skew could give a
higher rate. PASS itself never occurred with no effect. A one-sided effect (only up, only down, or only one method)
is read PASS 1% to 3% of the time, when noise makes the missing side look clear.

**Why 42 starts:** with the first draft's 21, the same rule would read the benchmark PASS only 37% of the time under
the most cautious noise (PARTIAL 57%), and no effect FAIL only 65% (INCONCLUSIVE 35%). With the expected noise, 21
starts would do nearly as well: PASS 99.98% and FAIL 99.2% (design_numbers.txt). Doubling the starts raises the
cautious chances to 80% and 91%, so the test is likely to give a clear answer even if the noise is much worse than
expected.

**Computing:** about 3.0 million copy-time-units (0.5 million of base runs, 2.5 million of branches). Measured in the
checks, the dry run and the target check: a moment task takes about 65 to 76 seconds on one worker, and with 6
workers at once each ran about 30% slower. The run takes about 2 hours of computing, in 36 pieces of about 3 minutes
each.

## Also reported (fixed now, not used for the decision)

- **Each method alone:** its own reading (above); D^up, D^down, S and P with error bars; and the difference between
  the two methods' S with its error bar, which shows whether the effect depends on how the phases were moved.
- **What each arm did to the state**, just after the change (moments carried out), reported separately from the
  sizes of the moves: by method and arm, the averages over starts (with error bars) and the ranges over moments of
  each group's R_g after / R_g before, the change in C (also relative to C before), and the changes in ψ_A, ψ_B,
  ψ_A − ψ_B and each group's |z₂,g|, |z₃,g| and |z₄,g|. For each of these, up − sham and down − sham with error
  bars: how far up's and down's changes differ from the sham's, beyond the coherence change itself. Also each
  group's |z₂|, |z₃| and |z₄| before and after, by method and arm.
- **The moves themselves**, kept apart from their effects: by method and arm, Σ Δθ², the number moved, and the
  largest and rms moves (alike in the three arms by construction).
- **Moments not carried out:** each one, with its start, moment, T and every reason.
- **How much the moments of a start go together:** the intraclass correlations and design effects (above).
- **P**, read by the 3-error-bar rule: does a change of this size, either way, change later growth?
- **Sham against none** (G_sham − G_none, each method): does moving phases without changing coherence change later
  growth?
- **The causal slope**, −S / |ΔC| with its error bar, beside the benchmark −0.1602. Also shown scaled by 0.363 / Φ,
  which matches the change's persistence to natural differences.
- **The same differences** for the growth over (T, T + 200] and over (T, T + 500].
- **The coherence paths:** up − sham and down − sham every time unit to T + 500 (averaged), Φ for each against sham,
  and the share left over (T + 200, T + 500].
- **From the base runs** (the 42 untouched new starts):
  - the long-run rate over t = 3,000 to 6,000 against Test 16's +0.0147 (0.0006), as a check that the new starts
    behave like the old ones (they agree if within 3 combined error bars);
  - Test 17's conditional coefficient on these starts by its own code, a further look at the correlation (not part of
    this decision).

## How the run is carried out

- **Tasks, in an order fixed now:** first the 42 base runs (starts 19 to 60 in turn), then the 420 moment tasks
  (start by start, moment by moment), each running that moment's six branches from its saved state. That makes 462
  tasks in all.
- **Pieces:** the run is carried out in short pieces on 7 workers, each piece a single foreground command with a hard
  time limit under 5 minutes. A piece takes the next unfinished tasks in the fixed order: 7 base runs or 14 moment
  tasks, about 3 minutes either way. That is 36 pieces in all. Nothing runs between pieces or in the background.
- **The lock first:** every piece first checks every locked file against cause_lock.json and stops if any has
  changed. No piece writes to the plan, the lock, the decision code, the design files or any earlier file.
- **Hidden until the end:** a piece prints only counts and times (tasks done, tasks left, seconds). No outcome,
  coherence or check value is printed, not even whether a moment was carried out, and no finished task's results are
  looked at until all 462 are done (a moment task reads only its saved state from the base run). Nothing seen
  during the run depends on the outcomes, so neither stopping nor carrying on can follow them. There is no early
  stopping: the run continues until every task is done.
- **Parts:** each finished task writes one file in cause_parts/, which is kept out of the project's history. Its
  SHA-256 goes into cause_runlog.json with the time and the piece. A task that does not finish (an error, a piece cut
  off by its time limit, or a restart) leaves nothing and is run again from the beginning in the next piece. It gives
  the same numbers, because every random draw is fixed by its seed and every branch starts from the saved state.
- **The report** refuses to run until all 462 parts exist and match their logged SHA-256. It then assembles them into
  sim_cause4000.npz, runs the manipulation checks and the decision with cause_rule.py, and writes the outputs. After
  that, cause_parts/ is removed. Its contents are in sim_cause4000.npz, except the saved full states (about 100 MB),
  which the base runs regenerate exactly. Every part's SHA-256 stays in the run log.

## Checks before the lock

- nudge_test.py is the copy the page carries (its SHA-256). Every script and saved result the test depends on goes
  into the lock as it is.
- cause_rule.py, design_numbers.py, its outputs, the moment table and the target check's outputs match the SHA-256
  values listed below.
- The base-run code repeats the saved long run exactly: start 1 for 50 time units, with the same settling, coherence
  and gap.
- A branch with no change, from start 1's state at t = 25 of that check, matches the base run to t = 50 within
  rounding (coherence within 10⁻⁹, log of the gap within 10⁻⁶).
- The planned changes on that same state are carried out: all four targets feasible and solved, all twelve branches
  inside their bands, and the matching and gap checks met. This is a trial of the change code; no growth is looked
  at.
- The regenerated moment table equals cause_moments.csv.
- No new data exist: no saved run, no run log, no parts.

Before the freeze, a dry run tries the code: the base and branch code on start 1 for a short stretch; the piece and
assembly steps on those, including a half-written part and a stray part, both removed; the refusal of a moment whose
sparse target cannot be reached, and of a target that is not a number; and the report on made-up numbers with three
moments not carried out. It writes only to /tmp and prints no growth result.

## What a result would mean

- **PASS:** in this toy model, the interventions as specified changed later growth as predicted. Raising coherence
  at a moment slowed the growth of tiny gaps 200 to 500 time units later, and lowering it sped that growth up. Each
  was compared with a matched sham that moved the same oscillators by the same amounts without changing coherence.
  The effect held in both methods and was at least half the size the correlation predicts. This supports a causal
  effect of these interventions on later growth within the model. It does not show that coherence is the only route:
  the interventions change coherence together with other features of the state (recorded for every branch: |z₂|,
  |z₃|, |z₄| and the mean phases), and any of them could carry part of the effect. It says nothing about systems
  beyond the model.
- **SMALL:** a real effect of the interventions in the predicted direction, but under half the benchmark: most of the
  correlation would come from something else.
- **PARTIAL:** raising and lowering differ as predicted, but up or down is not clearly apart from its sham, or one
  method does not show it. Either only one direction matters, the effect depends on how the phases are moved, or it
  is too small to see on each side. The report says which condition failed.
- **REVERSED:** the interventions move later growth the opposite way to the correlation.
- **FAIL:** no effect of the interventions as large as half the benchmark. The correlation in the untouched runs is
  then most likely carried by something else, such as a slower feature of the state that drives both.
- **INCONCLUSIVE:** the change did not happen as planned (including too many moments not carried out), the branches
  were not matched, the change faded too fast, or the data cannot tell a benchmark-sized effect from none. Not a
  negative result.

Any change after the lock is a deviation. It will be written down beside the result with its reason, and the locked
analysis will still be reported. Nothing on the website changes and nothing is published.

## Frozen settings

| setting | value |
| --- | --- |
| starts | 19 to 60 (seeds 18 to 59), 42 |
| oscillators per group | 4,000 (3,872 pulled, 128 free) |
| K / ε / Lorentzian width | 1.90 / 0.1 / 1 |
| step / settling / run | 0.025 / 300 / 6,000 time units |
| gap / put back every / direction seed | 10⁻⁷ radians / 5 time units / 20261011 |
| gap at each moment | carried from the base run (just put back at T); the same Δθ_j on both copies, so identical in every branch |
| moments | 10 per start (420), T = 2,000 + o + 350 m; o from seed (20261012, seed of the start) |
| change | f = 0.5: ½ [R_g(+a) − R_g(−a)] = 0.5 R_g, one amplitude per method and group, shared by up and down |
| amplitude | the smallest a in (0, π/2]: 256 values to π/2, then halving to 10⁻¹²; solved if within a relative 10⁻⁶; otherwise infeasible or a solver failure |
| each arm's target | R_g after / before, in each group and method: up 1.45 to 1.55, down 0.45 to 0.55, sham 0.95 to 1.05 |
| moment not carried out | any target infeasible or unsolved, any band missed, or a matching or gap check failed: none of its six branches run; reasons recorded; nothing clipped or replaced |
| methods | dense: every pulled oscillator; sparse: a random tenth (387 per group); separate throughout |
| sham | one per method: the same oscillators and amounts, paired signs that cancel the coherence change |
| random draws | seed 20261012 with (seed of the start, moment, use) |
| record | R_g, ψ_g, \|z₂,g\|, \|z₃,g\|, \|z₄,g\|, C, ψ_A − ψ_B before and after; R_g after / before and its band; amplitudes and their status; Σ Δθ², number moved, largest and rms move; the gap before and after; carried out or not, with reasons |
| outcome | G: the growth rate over (T + 200, T + 500] |
| primary | D^up, D^down (each minus its own method's sham), averaged over the moments carried out within each start, then over the two methods; S = (D^down − D^up) / 2 |
| units | the 42 starts |
| error bar | the larger of: 400 resamples of the starts (seed 20261015); SD / √42 |
| threshold | δ = ½ × 0.1602 × achieved \|ΔC\| (expected 0.00104); each method its own δ_k |
| M1 | every branch carried out inside its band; same oscillators and Σ Δθ² within 10⁻⁹; gap within 10⁻⁶; at most 21 of 420 moments not carried out, at least 5 of 10 in every start |
| M2 | Φ at least 0.181 |
| decision | as in the decision rule above, by cause_rule.py |
| run | 462 tasks in a fixed order, in pieces of 7 base runs or 14 moment tasks (36 pieces); counts and times only until all are done; no early stopping |

## Files fixed with this plan

| file | SHA-256 |
| --- | --- |
| cause_rule.py (the decision rule) | 5fdd1c90df371675d1113a5eca799abdc2c639c00adbeaeb0339c05b02f487ca |
| design_numbers.py | 103241b2fb361649f3e53cea900fedb1ee475c11200e8e8e8feeb2c2af4fecd3 |
| design_numbers.txt | 76d68062720f21e7c5f62ae14092e6c135ae207b036564ccb30e1a9770edca39 |
| design_numbers.json | 39bc39762c551631327d5120b69a6b5daf27f7a6c5cdb5f06fe59a22b281af28 |
| cause_moments.csv | 1a1d72113ab035b14b9e80e413e7030291915d8d1a365ad1f658f95c277709a8 |
| cause_targets.txt (the target check) | 5e3f8a8dba33a11bad8a0693e65803cfbfdb3bd83bfbaa7e868d41b02882d30c |
| cause_targets.json | 225058b7c11159c412ced9b2f1d8c7ea48d9e48d2805b913be4bdc2278acbe19 |
| nudge_test.py (the page's copy) | b06730e7772be1f719cadae7924cdca3c2e0ebb89efb17104969363431f782e7 |

## Outputs

cause_test.py was written and tried before this version. It does the checks, the target check, the dry run, the
freeze, the pieces and the report. Its SHA-256 goes into the lock at the freeze, and it is not changed after that.
The run writes cause_test.txt, cause_test.json, cause_lock.json, cause_runlog.json, sim_cause4000.npz and the figure
screenshots/nudge-test-cause-test.png. Already written: cause_rule.py, design_numbers.py, design_numbers.txt,
design_numbers.json and cause_moments.csv (read-only numbers from the saved runs, and the chance of each decision by
simulated sampling), and cause_targets.txt and cause_targets.json (the target check on old starts 13 to 18). Earlier
files are not touched.
