{
 "made": {
  "utc": "2026-10-15T13:58:30+00:00",
  "halifax": "2026-10-15T10:58:30-03:00"
 },
 "label": "pilot lock",
 "what": "The dated pilot lock for step 3 of the scattering-side design: the exploratory pilot on fresh starts 135 to 146, as plan-final.md fixes it and Amendment 1 amends it (comparison A and arm U out; four arms). Made on Colson's approval of Amendment 1, before the pilot's code is written. It fixes the pilot's settings, the details of its readings that the plan leaves to the code, the checks that must pass first, and the commands. Colson authorized preparing this lock and rerunning the required checks. Running anything on a fresh start needs his separate go. Nothing here may change in response to what the checks or the pilot show.",
 "plan": {
  "file": "analysis/cancer-research/scattering-side/plan-final.md",
  "sha256": "0e3f8f114ed44eade7e211317217f23e27c1075008e561c2b07ea11645823121"
 },
 "lock": {
  "file": "analysis/cancer-research/scattering-side/lock.json",
  "sha256": "3c7f70973247a327067a1817766b0dae3e0d72154f1de7785df7213ff271b23d",
  "note": "steps 1 and 2's lock, unchanged"
 },
 "amendment": {
  "file": "analysis/cancer-research/scattering-side/amendment-2026-10-15.md",
  "sha256": "d1edbec186079043706fa6ee63b756de4e7c1e52f011b06d491fd379335f1c75",
  "status": "approved by Colson on October 15, 2026, as drafted; his words are below"
 },
 "steps_1_and_2_code": {
  "file": "analysis/cancer-research/scattering-side/scattering_side.py",
  "sha256": "2a20b872d594a53b50f7b124e700c58e0e4efe12377324ac17105818f9e94634",
  "use": "imported unchanged: the arms, run_arm, the rhythm rule and the 11 step-1 checks"
 },
 "follows": {
  "file": "analysis/cancer-research/safekeeping/change-2026-10-15-4.json",
  "sha256": "44b0fcf022e1ca2b8fc697a76032a73a620f1ed2a505e2ba14f5b354a30e3717"
 },
 "authorization": {
  "given": "October 15, 2026",
  "words": "I approve Amendment 1 as drafted. Remove comparison A and arm U from the upcoming scattering-side pilot, preserving the original locked comparison, its 18/20 feasibility requirement, and the observed 10/20 result in the historical record. Keep comparisons B and B′ exactly as specified, including the 0.6 and 0.4 levels, detection criteria, margins, uncertainty rules, and fresh starts 135–146. The old-start feasibility observations must remain separate from the exploratory pilot results. Please prepare the dated pilot lock and rerun the required checks, then return for separate authorization before executing any fresh starts. No retrospective changes to the earlier locks, no website changes, and no publication. ~ Amendment 1 approved. Pilot execution not yet authorized.",
  "scope": "Amendment 1 approved; prepare this dated pilot lock, add the pilot's code, and rerun the required checks",
  "not_authorized": [
   "running anything on a fresh start: the base runs and the 120 moments on starts 135 to 146",
   "step 4, any locked replication",
   "comparison A or arm U in any form",
   "any website change or publication"
  ],
  "if_a_check_fails": "stop: nothing runs on a fresh start, and the failure is reported"
 },
 "unchanged": [
  "plan-final.md, lock.json, scattering_side.py and every earlier record, word for word",
  "comparison A's section, its 18-of-20 feasibility requirement and step 2's 10 of 20, kept on record; comparison A is not run in the pilot",
  "the old-start results of step 2: feasibility observations only, with no labels, never pooled with the pilot's",
  "comparisons B and B-prime exactly as plan-final.md specifies them: the levels 0.6 and 0.4, B1 and B2, their margins (0.25 and 0.005) and labels",
  "the rhythm rule (L at least 1.5, S at least 0.057, the band 0.80 to 1.30, intervals 0.03 wide, the read over (T + 150, R]), the readings E-pair, E-any and E-steady, their labels (0.05 and 0.10), the rate range 0.90 to 1.10, and the combined readings in their order",
  "the uncertainty rules: starts are the units; the larger of the resampled bar (400 resamples, seed 20261016) and SD/sqrt(n); shares of averages (B1, and the share of any gain still there after R) take the resampled bar, and the E-readings the larger bar, as plan-final.md says of them",
  "the model and its settings, the raised pull's size (0.005 of K) and the 200-unit window (lock.json's settings)"
 ],
 "settings": {
  "starts": {
   "numbers": [
    135,
    136,
    137,
    138,
    139,
    140,
    141,
    142,
    143,
    144,
    145,
    146
   ],
   "seeds": [
    134,
    135,
    136,
    137,
    138,
    139,
    140,
    141,
    142,
    143,
    144,
    145
   ]
  },
  "moments": {
   "per_start": 10,
   "all": 120,
   "window": 200,
   "after": 500,
   "units": 700
  },
  "base_runs": {
   "run": 6000.0,
   "keep": "the full state at every moment's T and R",
   "gap_growth": true
  },
  "arms": {
   "names": [
    "untouched",
    "raised",
    "f06",
    "f04"
   ],
   "copies": 2,
   "window_pull": [
    1.9,
    1.9094999999999998,
    1.9,
    1.9
   ],
   "window_rates": [
    "original",
    "original",
    0.6,
    0.4
   ],
   "after_pull": 1.9,
   "after_rates": "original"
  },
  "read": [
   150,
   200
  ],
  "error_bars": {
   "units": "starts",
   "resamples": 400,
   "seed": 20261016,
   "clear_bars": 3.0,
   "inside_bars": 2.0
  },
  "margins": {
   "B1": 0.25,
   "B2": 0.005,
   "rhythm_inside": 0.05,
   "rhythm_as_expected_at_0_4": 0.1,
   "rate_range": [
    0.9,
    1.1
   ]
  },
  "descriptions": {
   "rule_block": 50,
   "coherence_block": 100,
   "after_R_stretch": [
    200,
    500
   ],
   "benchmark": 0.1602,
   "sham_later_growth": 0.0015,
   "in_step_rate": 0.03,
   "in_step_turns": 0.25
  },
  "pieces": {
   "workers": 7,
   "budget_seconds": 240.0,
   "start_by_seconds": 150.0,
   "hard_limit_seconds": 285
  },
  "checks": {
   "moment_check": {
    "seed": 102,
    "moment": 0,
    "T": 2055
   },
   "made_up": {
    "seed": 20261015,
    "stream": 10,
    "scenarios": 8
   }
  }
 },
 "meaning": {
  "bit_for_bit": "every number exactly equal (numpy array_equal), with nothing rounded first",
  "arms": "At each moment, from the base run's state at T, both copies with the gap put back every 5 units, 700 units in two stretches, run by scattering_side.run_arm as in steps 1 and 2. Untouched: nudge_test's own step at K = 1.9 for 200 units and then 500. The raised pull: nudge_test's own step at K x 1.005 for 200 units, then at 1.9 for 500. Arm F (c_f = 0.6) and arm F' (c_f = 0.4): the copied step with lock.json's 'arms_f' rates at K = 1.9 for 200 units, then nudge_test's own step with the original rates for 500. Arm U and its search are not run (Amendment 1).",
  "base_runs": "the medium pilot's own base_task and base_run, unchanged, for each fresh start: the full state (both copies) kept at every moment's T and R, with coherence every unit and the gap's growth",
  "moments": "the medium pilot's rule and draws (medium_test.moment_times, lock.json's 'moments'): 10 per start, R = T + 200",
  "C_at_R": "the average of the two groups' coherence at R, first copy",
  "B1": "per start, the mean over its 10 moments of C_F(R) - C_untouched(R), and the same for the raised pull; B1 is the mean over starts of the first divided by the mean over starts of the second, with the resampled bar (medium_test.ratio_summary: the starts resampled 400 times, seed 20261016)",
  "B2": "the faster half's own coherence at R (|the mean of e^(i theta) over its 1,936 pulled oscillators|, first copy), the two groups' average, arm minus untouched; per start the mean over its moments; the reading is the mean over starts, its bar the larger of the resampled bar and SD/sqrt(n) (medium_test.summary)",
  "E_readings": "each group at each moment counts once, 20 per start in each arm: pair, a rhythm in both directions; any, a rhythm in at least one; steady, S >= 0.057 in at least one, whatever L shows. Per start, the arm's share minus untouched's; the reading is the mean over starts, with medium_test.summary's bar",
  "inside": "the reading minus 2 bars is above -margin and the reading plus 2 bars below +margin, both strictly (as the medium pilot's ruled_out); an undefined bar is never inside",
  "clear": "'more than 3 bars from zero': |reading| exceeds 3 bars, strictly; 'more than 3 bars above zero': the reading itself exceeds 3 bars. An undefined bar is never clear",
  "labels_at_0_6": "B1 (margin 0.25) and B2 (margin 0.005), each: as expected (no meaningful change) if inside its margin; contradicts (a meaningful change) if more than 3 bars from zero and at least the margin in size, either way; otherwise unresolved, noted 'a small change' if more than 3 bars from zero but smaller than the margin. E-any: as expected (no edge synchronization) if inside 0.05; contradicts if more than 3 bars above zero and at least 0.05; otherwise unresolved. E-pair is described.",
  "labels_at_0_4": "B2: as expected (up) if more than 3 bars above zero and at least 0.005; contradicts (inside its margin) if inside 0.005; otherwise unresolved, noted 'a small change' if more than 3 bars from zero but smaller than 0.005. E-pair and E-any, each: as expected if more than 3 bars above zero and at least 0.10; contradicts if inside 0.05; otherwise unresolved, noted 'a rare rhythm' if more than 3 bars above zero and from 0.05 up to, not including, 0.10. B1 is described, not labelled.",
  "E_steady": "used only inside the combined readings, as inside 0.05 or not",
  "rate": "the median |Omega*| over every direction holding a rhythm in arm F' (each group, moment and direction counted once, all starts pooled); within means 0.90 <= median <= 1.10; with no rhythm it is undefined, and not within",
  "combined_at_0_4": [
   "checked in this order; the first that applies is the reading",
   "1. The predicted counter-rotating edge rhythm: E-pair as expected, B2 up, and the rate within 0.90 to 1.10",
   "2. A counter-rotating rhythm that didn't lift B2: E-pair as expected and the rate within 0.90 to 1.10, but B2 not up",
   "3. A one-directional edge rhythm, not the predicted pair: E-any as expected and E-pair contradicts",
   "4. A rise in magnitude without a separate rhythm: B2 up, E-any contradicts, and E-steady inside",
   "5. No edge order formed: B2 inside its margin (its contradicts label), E-any contradicts, and E-steady inside. This goes against the theory",
   "6. Anything else: unresolved, with each part described"
  ],
  "combined_at_0_6": [
   "checked in this order; the first that applies is the reading",
   "1. No additional edge synchronization, as the theory expects: E-any as expected, E-steady inside, and B2 as expected",
   "2. A change in the faster half's coherence without a separate rhythm: B2 contradicts (either way), E-any as expected, and E-steady inside",
   "3. Edge synchronization at 0.6, against the theory: E-any contradicts, whatever B2 shows; E-pair says whether it's counter-rotating",
   "4. Anything else: unresolved, with each part described"
  ],
  "against_the_theory": "a reading that goes against the theory sends me first to check the arm and the code for a fault",
  "descriptions": {
   "contributions": "at R, each group's coherence split exactly along its own rhythm into the slower half's, the faster half's and the free turners' parts (the Fluidity Replication's measure: each part's sum turned by -arg z_g, real part, over N; they add up to |z_g|), the two groups' average, arm minus untouched; and each half's own coherence at R, arm minus untouched",
   "coherence_blocks": "C, arm minus untouched, averaged over each 100-unit block of the 700 (two in the window, five after R)",
   "persistence": "the share of the gain at R still there over (R + 200, R + 500]: per start, the mean over moments of C_arm - C_untouched averaged over that stretch, and of the gain at R; the ratio of the means over starts, with the resampled bar. It only means something if B1 shows a change",
   "later_growth": "gap growth per time unit over (R + 200, R + 500] (medium_test.growth), arm minus untouched, with medium_test.summary's bar; shown beside the medium pilot's shams (+0.0015 on average) and the benchmark, 0.1602 x |the mean gain at R|",
   "B2_course": "the faster half's own coherence, arm minus untouched, averaged over each 50-unit block of the window",
   "rhythm": "for every arm, untouched included: the share of group-moments with a rhythm in one direction only; L, S and Omega* (medians and largest); each rhythm's size: how many of the 968 share its interval, its S, and how many slower-half oscillators turn in the same interval",
   "in_step": "at each moment and direction where both groups hold a rhythm: whether their Omega* agree within 0.03, and whether their steady parts, both taken at the average of the two Omega*, lie within a quarter turn of each other",
   "blocks": "for each direction holding a rhythm: S at its Omega* in each 50-unit block from T to R + 500 (growth through the window, fading after R), and the turning rate of w in each block (the mean of wrap(arg(w_t conj(w_(t-1))))), signed so that turning in the direction's own sense is positive",
   "delivered": "the extra pull the raised pull delivered: 0.005 x K x the sum of |z_g| over the window's 200 units, as in the medium pilot",
   "moved_rates": "how far each reshaping moved the rates: the faster half's median and largest |natural rate|",
   "raised_pull": "the same rhythm numbers for the raised pull; it enters no reading (the theory expects no edge rhythm)"
  },
  "untouched_rerun": "at every moment, the untouched rerun's coherence every unit and gap growth are compared with the base run's, bit for bit, and its first copy's state at R with the base run's kept state; reported with the results, not a reading",
  "order": "the report is made once, after all 120 moments are done, from the fresh starts' saved runs only. Nothing is looked at before: the pieces print only each task's status",
  "old_starts": "step 2's numbers on old starts 16 and 17 are feasibility observations: no labels, never pooled with the pilot's, and never in its readings or its report"
 },
 "checks": [
  "All must pass before anything runs on a fresh start; if any fails, nothing runs and the failure is reported.",
  "The 11 step-1 checks of lock.json, unchanged: scattering_side.py's own check, run by the pilot's check command with the pilot code in place. Its record goes into pilot_checks.txt and pilot_checks.json; step 1's checks.txt and checks.json stay as they are.",
  "P1. The lock and the sealed files: the code's pilot settings equal this lock's after a JSON round trip; plan-final.md, lock.json, the amendment and scattering_side.py are the versions named here; this lock is the version change-2026-10-15-5 sealed; and no fresh start has been run (no pilot run or run log exists before Colson's go).",
  "P2. The pilot's own moment code on pilot start 103's first moment (T = 2,055), the medium pilot's start, not a fresh one, written to a temporary folder that is then deleted: the untouched rerun matches the base run and the raised pull matches the medium pilot's saved arrays, bit for bit (coherence every unit and gap growth, 700 units); the untouched state at R matches the base run's kept state; in all four arms the pull and rates are as scheduled, with the original ones after R; every reading is present and finite and the sums add up; S over (150, 200] equals the rule's S; and the numbers the report reads come out. Mechanics only: no value of arms F and F' is shown or kept.",
  "P3. The readings, labels and combined readings on made-up numbers, no model run: a table of boundary cases for each label and each combined reading, and eight made-up pilots drawn from (20261015, 10, scenario), each built for a known combined reading at both levels. Every label and combined reading must come out as built, B1, B2 and the E-readings must equal the values the numbers were built to give, and the report must be written end to end."
 ],
 "commands": [
  "timeout -k 10 285 python3 -B scattering_pilot.py check",
  "timeout -k 10 285 python3 -B scattering_pilot.py base",
  "timeout -k 10 285 python3 -B scattering_pilot.py moments"
 ],
 "go": "base and moments refuse to run unless pilot_go.json exists. It is written only on Colson's separate go for running step 3, with his words, and names this lock's SHA-256 and pilot_checks.json's; a dated change record seals it before any fresh start runs.",
 "how_it_runs": "each command in the foreground with a hard limit under 5 minutes, up to 7 worker processes that end with it, nothing left running. base and moments run only after every check passed with this same code, lock, plan, amendment and steps-1-and-2 code, in the same numerical environment. A base run stopped at a piece's deadline keeps its exact state and goes on in the next piece; each moment is written whole or not at all. base takes about 2 pieces and moments about 6 to 7; the report is made after the last moment.",
 "outputs": {
  "reports": "analysis/cancer-research/scattering-side/ (pilot_checks.txt/.json; later pilot_runlog.json and pilot_results.txt/.json)",
  "saved_runs": "generated-artifacts/scattering-side/pilot/ (kept out of the project's history)"
 }
}
