/teal-sea
teal-sea / zeta-labstate of record · compiled 02 Nov 2026 · revision b09fa4dd · source

Library · hunts/rung3_ball_production/RUNS.md

rung3_ball_production: estimates and run manifests

10,530 words · 1,025 lines · source

The swarm box <box>: 32 vCPU reported as "Intel Core Processor (Haswell, no TSX)", one thread per core, 115 GiB, no swap, shared with other workflows. Times are UTC. Lean is v4.35.0-rc2 (lean/lean-toolchain) against Mathlib 065356127b1d (lean/lake-manifest.json). Every Lake command ran in this worktree's own lean/.lake, fetched fresh; no .lake was copied. No production shard was launched by this lane.

Estimate before spending, 2026-10-21

Written before any compile, from the figures main records; every number in this section is a prior estimate, not a measurement.

unitbasisestimate
fresh Lake fetch (lake exe cache get)network-bound clone of nine packages and the Mathlib cacheabout 10 min wall
ZetaLean closure of the certificate (15 modules, lake build ZetaLean.BallCertSupport ZetaLean.BallTerm)hunt #132 built four ZetaLean modules in about 4 min20 to 40 min wall, under 2 core-hours
one staged prime tower (scripts/68, prime 2), 3 runs plus 3 import baselinesscripts/67 records about 30 s wall and 42 CPU-s per run under v4.33.0-rc2about 3 min
ten composite atoms (scripts/66), 3 runsscripts/66 records about 8 s wall per runabout 1 min
pilot site B_right_06 (K = 17: 23 prime towers, 48 composites, 36 kappa products, 774 atoms by scripts/67's count)909 CPU-s atom-only at the v4.33.0-rc2 rates; the unsharded K = 17 file recorded USER 1369 s1400 to 2000 CPU-s; 5 to 35 min wall at one process, depending on Lean's in-process threads
planted faults: one prime-tower radius, the tail radius, M, and the centre's eps'one shard or the root module each, recompiled against the clean pilot's oleansunder 30 min in all

Total well under 3 hours of compute at one process at a time. The site compile is the only unit that may exceed 20 minutes; scripts/72 checkpoints it per module, so a restart resumes at the first unfinished module. Stop rule: stop the newest job if MemAvailable falls below 20 GiB, and wait while the 1-minute load average is above 64 before starting a heavy unit.

First attempt, 17:41 to 18:08 UTC: interrupted, kept, not used for the cost table

Work directory <cache>/rung3-ball-production-pilot, left as it was. The 1-minute load average was 50 to 76 on the 32 vCPU throughout. Recorded there: two scripts/68 tower runs at p = 2 with their import baselines, the generation of B_right_06 and of the centre's sources (Python only), and the first four modules of the B_right_06 compile (Base, Primes00, Primes01, Primes02, all exit 0, checkpointed by scripts/72). The session ended while Primes03 was compiling; no Lean process from it survives. Those records are a load-sensitivity cross-check only.

id: rung3_ball_production-2026-10-21-attempt1
hunt: rung3_ball_production
started: 2026-10-21T16:41Z
finished: 2026-10-21T18:08Z
ran:
  - lake exe cache get into a fresh lean/.lake (inferred from the clone times of the nine packages, 16:41 to 16:45, and of Mathlib.olean, 16:44)
  - a lake build of the certificate's ZetaLean imports (inferred from the 15 ZetaLean oleans dated 17:39 to 17:41)
  - hunts/rung3_ball_production/pilot.py tower --prime 2 --repeat 3, stopped after two repeats
  - hunts/rung3_ball_production/pilot.py site --site B_right_06, stopped during Primes03
  - hunts/rung3_ball_production/pilot.py centre-eps --generate-only
outcome: Lean and the ZetaLean closure were set up and four of the ten pilot-site modules compiled with exit 0 before the session ended; nothing from this attempt enters the cost table
artifacts:
  - <cache>/rung3-ball-production-pilot/runs.jsonl
  - <cache>/rung3-ball-production-pilot/site/B_right_06/out/checkpoints/CB_right_06

Second attempt, from 21:29 UTC: estimate before spending

Fresh work directory <cache>/rung3-ball-production-pilot-2, so every number in pilot.json comes from one session. scripts/72 is main's version (merge commit e08e801da), byte-identical to origin/main 5da48eed7. The ZetaLean closure built at 17:38 to 17:41 is reused: no file under lean/ differs between fb647bfc7 and 5da48eed7.

unitbasis (first attempt, at load 50 to 76)estimate
tower p = 2, 3 runs plus 3 baselines108 to 125 s wall per tower run, 13 to 73 s per baseline7 to 9 min
tower p = 1801, 2 runs plus 2 baselinestext about 3 times the p = 2 tower8 to 15 min
ten composite atoms (scripts/66), 3 runs plus 3 baselinesnot run yet2 to 4 min
B_right_06, 10 modules, one processBase 19 s, Primes00 166 s, Primes01 135 s, Primes02 117 s wall15 to 30 min; checkpointed per module
import-only probes, 10 modules, 2 runs each13 s for the warm BallTerm baseline5 to 12 min
axioms print, three faults, centre eps' probes, mirrorone shard or the root module per fault15 to 30 min

In all, about 1 to 2 hours of wall time at one Lean process at a time, every unit gated on a 1-minute load average of at most 64 and MemAvailable of at least 30 GiB. Added after this estimate, each under ten minutes: the -j1 tower and the -j1 shard, a 100-atom composite file, and the tower with Lean's linters off.

Decision recorded at 22:07 UTC, before the p = 1801 tower ran

The first four prime shards of B_right_06 in this attempt cost, net of an import of about 11 CPU-s, between 61 and 85 CPU-s per tower, while their CPU per source byte fell as the primes grew (from about 2.8e-4 in Primes00, p = 2 to 17, to about 1.8e-4 in Primes03, p = 67 to 83). So "CPU follows the text" is not supported by the shards, and "CPU per tower is flat in p" is not tested above p = 89. The projection therefore prices the towers both ways, and the request uses the larger total. The scripts/68 towers at p = 2 and p = 1801 are reported beside the shards as the only evidence on the dependence on p; they do not choose the model.

Correction at 22:25 UTC, after the site finished: the per-tower figures above miscounted the towers in Primes00 (seven, not six) and Primes01 (five, not six). With the right counts the five shards cost 69 to 75 CPU-s per tower net of import, flat in p up to 89, while the per-byte trend stands. The decision is kept as recorded: both models are priced, and the request uses the larger, which is the per-byte one.

Second attempt: what ran (UTC)

id: rung3_ball_production-2026-10-21-attempt2
hunt: rung3_ball_production
started: 2026-10-21T21:29Z
finished: 2026-10-21T22:45Z
ran:
  - hunts/rung3_ball_production/pilot.py tower --prime 2 --repeat 3
  - hunts/rung3_ball_production/pilot.py composite --atoms 10 --repeat 3
  - hunts/rung3_ball_production/pilot.py site --site B_right_06
  - hunts/rung3_ball_production/pilot.py axioms --site B_right_06
  - hunts/rung3_ball_production/pilot.py imports --site B_right_06 --repeat 2
  - hunts/rung3_ball_production/pilot.py fault --site B_right_06 --kind tower-rad
  - hunts/rung3_ball_production/pilot.py fault --site B_right_06 --kind tail-rad
  - hunts/rung3_ball_production/pilot.py fault --site B_right_06 --kind M
  - hunts/rung3_ball_production/pilot.py centre-eps
  - hunts/rung3_ball_production/pilot.py mirror --site B_right_06
  - hunts/rung3_ball_production/pilot.py tower --prime 2 --repeat 3 --lean-threads 1
  - hunts/rung3_ball_production/pilot.py shard --site B_right_06 --module CB_right_06/Primes02.lean --lean-threads 1
  - hunts/rung3_ball_production/pilot.py tower --prime 1801 --repeat 2
  - hunts/rung3_ball_production/pilot.py composite --atoms 100 --repeat 3
  - hunts/rung3_ball_production/pilot.py tower --prime 2 --repeat 3 --lean-opt linter.all=false
  - hunts/rung3_ball_production/report.py
outcome: the pilot site compiled with every module exit 0 and only the three standard axioms, all three planted site faults and both eps' perturbations below the bound were refused, and the costs and projection in pilot.json were measured; no production shard was launched
artifacts:
  - hunts/rung3_ball_production/pilot.json
  - <cache>/rung3-ball-production-pilot-2/runs.jsonl
  - <cache>/rung3-ball-production-pilot-2/loadlog.tsv
  - <cache>/rung3-ball-production-pilot-2/site/B_right_06/out/results/CB_right_06.json

Resumed 2026-10-26: decide +kernel re-pricing pilot, estimate before spending

Owner decision of 2026-10-26 (MISSION.md): this box takes pilots under one core-hour only; this unit was pre-approved by the coordinator under that cap. One Lean process at a time, nice -n 10, gated on a 1-minute load of at most 64 and MemAvailable of at least 30 GiB before each run. Instrument: decide_pilot.py, work directory <cache>/rung3-ball-production-decide. Every figure in this table is a prior estimate.

unitbasisestimate
import-only baseline, 2 runsabout 10 CPU-s each on 2026-10-21under 1 min
scripts/68 tower p = 2, staged equalities by norm_num, equalities only, 1 run2.09 CPU-s per atom, 30 atoms, plus importabout 75 CPU-s
the same tower with every staged equality by decide +kernel, equalities only and full file, 2 runs eachunknown; bounded above by the norm_num run if the kernel is no slowerunder 6 min
planted fault: one staged literal one unit of 2^-64 off, 1 runas one decide rununder 2 min
one composite product and one kappa product, decide +kernel (2 runs) and norm_num (1 run) eachabout 0.67 CPU-s per composite atom plus importunder 3 min
whole-tower dirichletTermBallB ... = lit := by decide +kernel, 1 rununknown; Nat.sqrt and the recursive tower in the kernelcapped at 10 min wall by a timeout

Total under 30 core-minutes, well inside the one core-hour cap. Threshold recorded before any run: a full tower (the decide +kernel file with its containment theorem, net of the import baseline) at at most 10 CPU-s confirms the repricing of production to roughly 20 to 90 core-hours; above that, the norm_num price in OWNER_MEMO.md (416 core-hours) stands.

Resumed 2026-10-26: what ran (UTC)

In all, 22 logged Lean runs and 7.4 core-minutes of CPU, against the estimate of under 30.

id: rung3_ball_production-2026-10-26-decide
hunt: rung3_ball_production
started: 2026-10-26T12:50Z
finished: 2026-10-26T13:05Z
ran:
  - hunts/rung3_ball_production/decide_pilot.py emit
  - hunts/rung3_ball_production/decide_pilot.py run
  - hunts/rung3_ball_production/decide_pilot.py run --only TowerNormNum.lean TowerWhole_p2.lean TowerWhole_p1801_box.lean TowerWholeFault_p2.lean
  - hunts/rung3_ball_production/decide_pilot.py summarize
outcome: every decide +kernel file with correct literals was accepted with only the three standard axioms, both planted one-unit faults were refused at the named declaration, the staged variant missed the 10 CPU-s threshold (43.4 net) and the whole-decision tower met it (3.4 and 5.3 net), repricing production to 50 to 58 core-hours by extrapolation, conditional on a generator change; no production shard was launched
artifacts:
  - hunts/rung3_ball_production/pilot.json (decide_kernel)
  - <cache>/rung3-ball-production-decide/runs.jsonl
  - <cache>/rung3-ball-production-decide/src

Resumed 2026-10-26: the assembly harness

Estimate before spending: Support.lean about 15 CPU-s (one module, against the built ZetaLean); the stub module about 20 CPU-s; the harness about 1,100 small norm_num calls, guessed at 2 to 10 CPU-min. Under 15 core-minutes in all, one process, gated as above. Measured: 12.7, 17.8 and 124.2 CPU-s. CI then refused the committed emitted files, which are not module files and cannot be (PILOT.md section 8). So Support.lean became a module, the emitted files moved out of the tree with a SHA-256 pin, and the three compiles ran again from 13:16 (10.6, 17.1 and 124.1 CPU-s, exit 0, no errors). The record in pilot.json is the second run.

id: rung3_ball_production-2026-10-26-assembly
hunt: rung3_ball_production
started: 2026-10-26T13:09Z
finished: 2026-10-26T13:21Z
ran:
  - hunts/rung3_ball_production/assembly.py --stubs <cache>/rung3-ball-production-assembly --real B_right_06
  - (from 13:16, after the module change) hunts/rung3_ball_production/assembly.py --out <cache>/rung3-ball-production-assembly --stubs <cache>/rung3-ball-production-assembly --real B_right_06 --pin, then the three compiles below again
  - lake env lean --root=hunts/rung3_ball_production/lean -o <cache>/rung3-ball-production-assembly/Rung3Assembly/Support.olean hunts/rung3_ball_production/lean/Rung3Assembly/Support.lean
  - lake env lean --root=<cache>/rung3-ball-production-assembly -o <cache>/rung3-ball-production-assembly/StubSites.olean StubSites.lean (LEAN_PATH adds the work directory and the pilot site's gen directory)
  - lake env lean <cache>/rung3-ball-production-assembly/Harness.lean (same LEAN_PATH)
  - hunts/rung3_ball_production/assembly.py --real B_right_06 --record <cache>/rung3-ball-production-assembly/harness.record.log --check
outcome: Support.lean and the emitted assembly body elaborated with exit 0 and no errors against 214 stub site interfaces and the real B_right_06 oleans; the three theorems rest on the three standard axioms and the 214 stubs only; no production shard was launched and davenport_heilbronn is not proved
artifacts:
  - hunts/rung3_ball_production/lean/Rung3Assembly/Support.lean
  - <cache>/rung3-ball-production-assembly/Rung3Assembly/Assembly.lean and Separation.lean (pinned in pilot.json, assembly_emitted)
  - hunts/rung3_ball_production/pilot.json (assembly_harness)
  - <cache>/rung3-ball-production-assembly/harness.log

The second run's shell wrote the harness's exit status into harness.record.log as rc=<status>, which --record parses.

Follow-up 2026-10-26: the opt-in whole-tower generator mode

The change. The coordinator extended this lane's scope under the owner's production grant. scripts/69_rung3_ball_generate.py gained tower_mode="whole" and scripts/60_rung3_generate.py a --tower {staged,whole} flag, staged by default. In whole mode each prime tower is one private lemma ev_whole : dirichletTermBallB ... = Sq_10 := by decide +kernel plus theorem pilot_contains_cpow through contains_dirichletTermBallB, in the same Prime_<p> namespace with the same exported names, so nothing downstream changes. The literal is the mirror's dirichletTermBox2. The generator raises if it differs from the staged chain's last ball in any field. Why: section 7 of PILOT.md measured 3.4 to 5.3 CPU-s per tower this way against about 66 staged, which reprices production by a factor of about 7.

Byte identity of the default. Before the change (at 304dee102) and after it, scripts/60 ... --arith ball --shard --only <id> wrote 94 files for B_right_06 and the centre. Their SHA-256 lists compare equal (cmp of the two sorted sha256sum lists). tests/test_rung3_ball_whole_tower.py pins that an explicit staged equals the default, and the hunt test pins the default B_right_06 sources against the SHA-256 recorded on 2026-10-21.

Estimate before spending (prior figures): generation a few seconds. The site in whole mode is 5 modules: towers at about 4 CPU-s each (23 of them), the composites, terms and root at their 2026-10-21 cost of about 150 to 200 CPU-s, so 250 to 400 CPU-s. Two fault recompiles of Primes.lean, about 110 CPU-s each. Four import probes, about 12 CPU-s each. Under 15 core-minutes, one process, nice -n 10, gated as before; outputs under <cache>/rung3-ball-production-whole, expected well under 300 MB.

What ran (UTC)

In all, about 6 core-minutes of Lean and 51 of Python. The whole follow-up was just under the one core-hour cap for this box. The census was not in the estimate, which is a miss recorded here. Disk: 17 MB under <cache>/rung3-ball-production-whole.

id: rung3_ball_production-2026-10-26-whole
hunt: rung3_ball_production
started: 2026-10-26T13:40Z
finished: 2026-10-26T14:05Z
ran:
  - hunts/rung3_ball_production/whole_pilot.py site
  - hunts/rung3_ball_production/whole_pilot.py imports
  - hunts/rung3_ball_production/whole_pilot.py faults
  - hunts/rung3_ball_production/whole_pilot.py census --part {0,1,2} --parts 3
  - hunts/rung3_ball_production/whole_pilot.py summarize
outcome: B_right_06 compiled in whole mode with every module exit 0 (163.6 CPU-s, 16.8 MB of oleans, against 1861 CPU-s and 180 MB staged); both one-unit tower faults refused at ev_whole; the import ratio re-measured at 0.70; the census emitted all 215 sites with every whole-tower literal equal to the staged chain's, and production re-projects to 29.8 core-hours and 14.8 to 16.0 GB of oleans; no production shard was launched
artifacts:
  - hunts/rung3_ball_production/pilot.json (whole_site, whole_projection)
  - <cache>/rung3-ball-production-whole/runs.jsonl
  - <cache>/rung3-ball-production-whole/site/out/results/CB_right_06.json
  - <cache>/rung3-ball-production-whole/census.jsonl and census.{0,1,2}.jsonl

Follow-up 2026-10-26: the production workflow (not yet run)

.github/workflows/rung3-production.yml and production.py were added; PRODUCTION.md section 2 describes them. They were pushed without RUN_REQUEST.json, so nothing runs until the coordinator's 'go' and the request commit.

Smoke on this box before pushing, all Python except two small Lean runs under the usual gate:

Estimate for the calibration run, before spending (at this box's rates; a runner's speed is unmeasured): the centre at 2,173 CPU-s and B_right_06 at 162. That is about 40 minutes at one process, plus about 15 to 25 minutes of setup (cache get and the ZetaLean closure), so about 1 hour of one job. It runs on free GitHub Actions minutes.

2026-10-26: the calibration run on GitHub Actions

After the coordinator's 'go', RUN_REQUEST.json (calibrate: the centre and B_right_06) was committed at c697df4f0 and pushed; that push started run

  1. The estimate above was about 1 hour of one job; it took 15.5 minutes. The

figures are in PILOT.md section 10.

id: rung3_ball_production-2026-10-26-calibrate-runner
hunt: rung3_ball_production
started: 2026-10-26T14:30Z
finished: 2026-10-26T14:47Z
ran:
  - .github/workflows/rung3-production.yml, mode calibrate, run 40340279740 (https://github.com/teal-sea/zeta-lab/actions/runs/40340279740), commit c697df4f0
  - gh run download 40340279740 -n rung3-production-record-job0-attempt1 (the record, into <cache>/rung3-ball-production-calib)
outcome: plan, sites 0 and verdict succeeded; the centre (1348.1 CPU-s, 556.6 s wall, 11.32 GB peak RSS, 343.5 MB of oleans) and B_right_06 (65.9 CPU-s, 7.20 GB, 16.8 MB) compiled under --tower whole with exactly the three standard axioms; setup 295 s; the full plan is re-sized to 20 jobs at one Lean process each, every job bounded at 1.43 to 1.49 h
artifacts:
  - hunts/rung3_ball_production/pilot.json (calibration_runner)
  - GitHub artifacts rung3-production-job0-attempt1 (oleans of both sites) and rung3-production-record-job0-attempt1, 30-day retention

2026-10-26: the full run cancelled, the cross-site name collision fixed

About 12 core-minutes of Lean and the census's Python, about 50 core-minutes, together under the one core-hour cap. Next: the calibration re-run with the new names ("attempt": 2 in the request), then a new full request for the coordinator's 'go'.

id: rung3_ball_production-2026-10-26-calibrate-runner-attempt2
hunt: rung3_ball_production
started: 2026-10-26T15:32Z
finished: 2026-10-26T15:48Z
ran:
  - .github/workflows/rung3-production.yml, mode calibrate, "attempt": 2, run 40350287309 (https://github.com/teal-sea/zeta-lab/actions/runs/40350287309), commit 4bac8d79d
  - gh run download 40350287309 -n rung3-production-record-job0-attempt1 (into <cache>/rung3-ball-production-calib/40350287309)
outcome: success; with site-qualified tower namespaces the centre (1229.1 CPU-s, 533.8 s wall, 11.31 GB, 343.5 MB of oleans) and B_right_06 (58.1 CPU-s, 7.19 GB) compiled with exactly the three standard axioms; setup 308 s; the full plan is bounded at 1.32 to 1.37 h per job
artifacts:
  - hunts/rung3_ball_production/pilot.json (calibration_runner; the first run is calibration_runner_v1)
  - GitHub artifacts of run 40350287309, 30-day retention

2026-10-26: the full run, and the assembly on this box (estimate before spending)

Full run 40353536947 started at 15:52Z from RUN_REQUEST.json at 85cabd55b. Its watcher, a detached process on this box (<cache>/rung3-ball-production-full/watcher.log), waits for the run's terminal state and writes it to terminal.json; its outcome is recorded below when it ends. No second request will be pushed while the run is live.

The coordinator placed the assembly on this box, with the oleans on /dev/shm, on these conditions:

Prepared before the verdict (measured):

Estimate, from this hunt's measurements:

unitbasisestimate
collect: 20 zips (about 5 GB compressed, about 16 GB unzipped) into /dev/shm, SHA-256 eachthe calibration artifact (113 MB) took seconds5 to 10 min wall, under 5 CPU-min
Support.olean10.6 CPU-s measuredunder 1 min
Assembly.lean, 215 rootsthe two-site harness 127 CPU-s, plus imports5 to 15 CPU-min, 17 to 18 GB RSS
Separation.lean and #print axioms on every final declarationthe probe above, plus the 215-root import again5 to 10 CPU-min
four planted faults on the production output (tower radius, tail radius, M, centre eps')35 to 110 CPU-s each on 2026-10-21 and todayunder 8 CPU-min

That totals 20 to 40 core-minutes, under the one core-hour cap. Anything beyond goes back to the coordinator first.

The full run's terminal state, the fault re-run, and the assembly (measured)

Then /dev/shm was deleted, and the receipts (site-root and assembly olean SHA-256, logs, collected.json, assemble.json) were kept in <cache>/rung3-ball-production-full/receipts. On-box total: about 10 core-minutes, inside the estimate of 20 to 40.

id: rung3_ball_production-2026-10-26-production
hunt: rung3_ball_production
started: 2026-10-26T15:52Z
finished: 2026-10-26T18:00Z
ran:
  - .github/workflows/rung3-production.yml mode full, run 40353536947 (https://github.com/teal-sea/zeta-lab/actions/runs/40353536947), commit 85cabd55b
  - .github/workflows/rung3-production.yml mode fault, run 40372531479 (https://github.com/teal-sea/zeta-lab/actions/runs/40372531479), commit 78e91a542
  - hunts/rung3_ball_production/production.py verdict --runs 40353536947 40372531479
  - hunts/rung3_ball_production/production.py collect --run 40353536947 --dest /dev/shm/rung3-assembly
  - hunts/rung3_ball_production/pilot.py fault --kind tail-rad and --kind M, production.py fault + scripts/72 + refused, pilot.py centre-eps (work directory <cache>/rung3-ball-production-faults4)
  - hunts/rung3_ball_production/production.py assemble --dest /dev/shm/rung3-assembly --overlay <cache>/rung3-ball-production-assembly/overlay --rh100 <cache>/rh100-out
outcome: theorem davenport_heilbronn, dh_zero_located, dh_zero_located' and dh_separation_hundred compiled with zero sorry, and all 17 final declarations print exactly propext, Classical.choice and Quot.sound; 215/215 sites ok; every planted fault refused at its declaration; /dev/shm cleared
artifacts:
  - hunts/rung3_ball_production/RESULTS.md
  - hunts/rung3_ball_production/pilot.json (production)
  - <cache>/rung3-ball-production-full/receipts

2026-10-26: the strip re-assembly on this box (estimate before spending)

Door 2 of RESULTS.md: one theorem, davenport_heilbronn_strip, in a new emitted module Strip.lean that imports Rung3Assembly.Assembly alone (assembly.py). Assembly.lean and Separation.lean are emitted byte for byte as before (cmp against the copies in the first receipts). The site oleans are gone from this box, so collect downloads run 40353536947's 20 artifacts again.

Conditions set by the coordinator for this run:

A syntax smoke ran first, outside the log: the emitted Strip.lean body after a scratch file that states dh_zero_located as a stub (lake env lean, importing ZetaLean.DHAnalytic only). Exit 0, 8.8 CPU-s, 6.7 GB; it printed the three standard axioms and the stub, as a stub harness must.

Estimate, from the first assembly's measurements (production.assembly_box):

unitbasisestimate
collect: 20 zips, 4,744,646,464 bytes, to disk; about 15.1 GB unzipped106 CPU-s and 179 s of wall into /dev/shm100 to 150 CPU-s; 3 to 10 min wall, since the unzip writes to disk
Support.olean9.1 CPU-s, 3.8 GBabout 10 CPU-s
Assembly.lean, 215 roots85.3 CPU-s, 17.87 GB85 to 120 CPU-s, 17.5 to 18.5 GB peak RSS
Separation.lean11.8 CPU-s, 17.57 GBabout 12 CPU-s, the same RSS
Strip.lean, which imports Assemblythe same import as Separation10 to 20 CPU-s, the same RSS
#print axioms, 18 declarations11.6 CPU-sabout 12 CPU-s
strip-faults: the control and two planted faultsthree imports as above30 to 60 CPU-s, one process at a time

In all, 250 to 400 CPU-s (4 to 7 core-minutes) and 17.5 to 18.5 GB peak RSS per Lean process. With the oleans in the page cache instead of a tmpfs, MemAvailable is expected to start near 65 GiB and stay above 40 GiB. Disk: about 15.1 GB of oleans plus one zip.

What ran (UTC, measured)

Against the estimate: about 280 CPU-s in all (collect 116.8; assemble 121.5 for the driver, 114.4 of it Lean; the faults 32.7; the smoke 8.8), inside 250 to 400; peak RSS 18.03 GB, inside 17.5 to 18.5; MemAvailable low 63.7 GiB, above the 40 expected. Assembly took less CPU than the first time (73.8 against 85.3) with the oleans in the page cache straight after the unzip; that comparison is one run each.

Then the unpacked oleans (<cache>/rung3-ball-production-strip-20261026, about 15 GB) were deleted, keeping the receipts, with the zips' digests in collected.json.

id: rung3_ball_production-2026-10-26-strip
hunt: rung3_ball_production
started: 2026-10-26T23:36Z
finished: 2026-10-26T23:43Z
ran:
  - hunts/rung3_ball_production/production.py collect --request <receipts>/RUN_REQUEST.full.json --run 40353536947 --dest <cache>/rung3-ball-production-strip-20261026
  - hunts/rung3_ball_production/production.py assemble --dest <cache>/rung3-ball-production-strip-20261026 --overlay <cache>/rung3-ball-production-assembly/overlay --rh100 <cache>/rh100-out
  - hunts/rung3_ball_production/production.py strip-faults --dest <cache>/rung3-ball-production-strip-20261026 --overlay <cache>/rung3-ball-production-assembly/overlay
outcome: theorem davenport_heilbronn_strip compiled with zero sorry and prints exactly propext, Classical.choice and Quot.sound, as do the 17 earlier final declarations; the 20 artifacts, the 215 root oleans and the Support, Assembly and Separation oleans are byte-identical to the first assembly's; both planted strip faults refused at davenport_heilbronn_strip and the control accepted; no Lake build, the ZetaLean oleans unchanged; the unpacked oleans deleted afterwards
artifacts:
  - hunts/rung3_ball_production/RESULTS.md
  - hunts/rung3_ball_production/pilot.json (production.strip_assembly)
  - <cache>/rung3-ball-production-full/receipts-strip-20261026

2026-10-27: door 1, the replay (estimate before spending, part 1: the sampling windows)

The coordinator's brief of 2026-10-27: Stage A, leanchecker --fresh over the closure of all 18 final declarations, Lean's own kernel; Stage B, if it fits, an export by leanexport checked by con-ron --verified. Same constraints as the strip re-assembly: no Lake build, oleans on disk, MemAvailable above 20 GiB, ulimit -s unlimited, kills by recorded PID only. The height-100 leanchecker job has finished.

No emitted module imports all 18 declarations (Separation lacks the strip theorem and Strip lacks dh_separation_hundred), so assembly.py now also emits Final.lean, which imports both and declares nothing. Assembly, Separation and Strip are emitted byte for byte as before. assemble compiles Final after Strip.

leanchecker --fresh replays every constant the module imports, and ZetaLean imports all of Mathlib, so Stage A replays the whole of Mathlib as well as the sites; the export of Stage B holds only the constants the 18 declarations use. Neither tool reports progress, so the estimate is built from samples, each one Lean process, before the run:

unitestimate
collect and assemble again, as on 2026-10-26, with Finalabout 250 CPU-s, 18 GB peak RSS, 15.1 GB of disk
a census of the closure's constants by origin (one import of Final)about 15 CPU-s, 18 GB
leanchecker on a module that does not exist (must exit 1)seconds
leanchecker without --fresh on the site CB_right_06 (its own constants, replayed into its imports): a timing sample and the control for the olean fault1 to 3 min, about 10 GB
a planted kernel-level fault: one byte of a big literal changed in a scratch copy of CB_right_06/Primes.olean, then leanchecker on that module1 to 3 min, about 10 GB
a progress replay for a short window: a script that replays the closure module by module in import order through the same Kernel.Environment.replay, logging each module's time, stopped after 10 minutes10 min of one core, about 20 GB
Stage B sample: leanexport of the closure of upper_B_right_06 alone, then con-ron --verified --jobs=8 on ita few minutes, under 10 GB

In all, under 40 core-minutes. The full estimate follows from these samples, before the replay starts.

The sampling windows (measured, 2026-10-27, 00:05 to 00:33 UTC)

Estimate for Stage A, leanchecker --fresh Rung3Assembly.Final, one thread (sample totals scaled by constants, by olean bytes and by module count, or for sites by runner compile CPU and by olean bytes; the range is the spread of those estimators):

partestimate
the 215 sites18,400 to 20,200 s
Mathlib2,300 to 2,700 s
hunt #137's modules1,700 to 2,200 s
Lean's core and dependenciesabout 200 s
ZetaLean and the assemblyabout 5 s
import and the search-path walkabout 25 s

That is 6.3 to 7.0 hours from the sample. The same method would put height 100's closure under about 4,700 s, against its measured 6,000 s, so the estimate written down is 6 to 10 hours of one core. Peak RSS: the import of the closure alone is 17.9 GB (the census run); the kernel environment then grows by the 1.57 million replayed constants, so 18 to 26 GB, with MemAvailable expected to stay above 35 GiB. The guard is guard.py of hunt #137, copied unchanged (SHA-256 cbdcd817bea525f0...): no wall limit, SIGTERM to the checker's process group below 20 GiB, a status file every minute, a receipt at the end.

Stage A, launched (00:35:12 UTC)

guard.py leanchecker-fresh <receipts> -- <toolchain>/bin/leanchecker --fresh Rung3Assembly.Final, with the toolchain's bin first on PATH (the checker runs lean --print-prefix) and the LEAN_PATH of lean-path.txt in the receipts: the overlay, the assembly, the 215 site outputs and hunt #137's oleans ahead of the paths lake env reports (read with lake env printenv, which builds nothing). Guard PID 308349, checker PID 308357, recorded in the receipts. Its outcome is below when it ends.

Planted kernel-level fault in a scratch olean (measured, 00:36 to 00:40 UTC)

In a scratch copy of CB_right_06/Primes.olean, the radius of Prime_B_right_06_2.Sq_10, 36391283805789411/2^63, was lowered by one unit. The literal is below 2^63, so the olean stores it as the tagged word 2n + 1; the word occurs once in the file, at byte 62304, and the copy differs from the original in that one byte. The scratch directory went first on LEAN_PATH, beside links to the site's other oleans. (A first try without those links stopped before any replay, at "object file ... CB_right_06/Base.olean does not exist", because Lean resolves CB_right_06.* in the first directory holding CB_right_06/; that was a setup miss, not a verdict.)

runoutcome
leanchecker CB_right_06.Primes, the unchanged oleanexit 0, 31.1 s wall
the same, the planted copyexit 1: "(kernel) application type mismatch" while replaying Prime_B_right_06_2.ev_whole._proof_1_1; the decision no longer evaluates to true
con-ron --verified on the export of Prime_B_right_06_2.pilot_contains_cpow from the unchanged olean (26,561 declarations)exit 0, accepted, 41 s
the same from the planted copy (the two exports differ in one record, natVal 36391283805789411 against 36391283805789410)exit 1, rejected: "application type mismatch" at the same ev_whole._proof_1_1

Stage B: estimate, and the decision to stop there

Measured samples, each under the guard:

Projection for the export of the 18 declarations' closure: about 13.3 GB for the sites (by olean bytes) plus a base under 1.5 GB, so 14 to 15 GB, against 0.53 GB at height 100. The export itself, by a line through the two leanexport samples (50.6 s for 486.5 MB, 18.3 s for 150.3 MB), takes 20 to 30 minutes at 30 to 40 GB of RSS (the 17.9 GB import of Final plus about 0.9 bytes per export byte) and 14 to 15 GB of disk. con-ron used 4.0 to 5.2 bytes of RSS per export byte on the three samples and 6.8 at height 100, so 56 to 102 GB of peak RSS. The 15,608 towers (each site uses the first T primes other than 5, T from the generator census), priced by interpolating the measured tower times in log p, come to about 1,300 core-hours: 81 hours of wall at con-ron's default cap of 16 workers and 43 at 30. Both the time (over 24 hours) and the memory (this box had 72 GiB available after Stage A, so about 52 GiB above the 20 GiB floor) exceed the brief's bounds, so Stage B stops at this estimate, and neither the full export nor its check was launched. It needs a larger machine: about 128 GB of RAM, and 1,300 core-hours, which is about 20 hours on 64 cores if con-ron scales there (--jobs above its default cap of 16 must be set by hand). Per-site exports (about 0.5 to 0.9 GB each, about 3 GB of con-ron RSS) would remove the memory bound but not the CPU, and would leave the assembly's own closure to check separately. NanoDa was not run.

Stage A: the outcome (measured)

The parent session was restarted at about 02:59Z and this lane's copy stopped at about 03:35Z; the detached guard and checker were not touched and ran on. The guard's receipt (<receipts>/leanchecker-fresh.receipt.json):

estimatemeasured
exit0, stdout and stderr empty, stop_reason null
wall, one core6 to 10 h7 h 17 min 46 s (00:35:12 to 07:52:58 UTC, 26,266 s)
peak RSS18 to 26 GB23.3 GB, 21.7 GiB (22,759,764 KiB, sampled every 5 s; first recorded as "22.76 GB", the KiB count read as GB, corrected 2026-10-30)
lowest MemAvailableabove 35 GiB49.3 GiB (51,670,496 KiB)

The checker binary hashes the same before and after (SHA-256 9e36e955a251b131...). The sample's projection, 22,605 to 25,325 s, fell 4 to 14 % short of the measured time; the widened estimate written down, 6 to 10 hours, held. Final imports Separation, which imports RHHeight100.Main100, so this replay also re-checked hunt #137's closure.

Then the unpacked oleans and the sample exports (<cache>/rung3-ball-production-replay-20261027, about 16 GB) were deleted, keeping the receipts, the zips' digests (collected.json) and the exports' SHA-256.

id: rung3_ball_production-2026-10-27-door1
hunt: rung3_ball_production
started: 2026-10-27T00:05Z
finished: 2026-10-27T07:53Z
ran:
  - hunts/rung3_ball_production/production.py collect --request <receipts>/RUN_REQUEST.full.json --run 40353536947 --dest <cache>/rung3-ball-production-replay-20261027
  - hunts/rung3_ball_production/production.py assemble --dest <cache>/rung3-ball-production-replay-20261027 --overlay <cache>/rung3-ball-production-assembly/overlay --rh100 <cache>/rh100-out
  - <toolchain>/bin/leanchecker --fresh Rung3Assembly.NoSuchModule
  - <toolchain>/bin/leanchecker -v CB_right_06, and leanchecker Rung3Assembly.Support twice (import baseline)
  - lean --run hunts/rung3_ball_production/lean/ReplayProgress.lean (first version: census, then a stopped progress replay), and its sample mode in 4 guarded streams over 175 modules
  - <toolchain>/bin/leanchecker CB_right_06.Primes on the unchanged olean and on a scratch copy with one radius literal one unit low
  - <toolchain>/bin/leanexport CB_right_06 -- ZetaLean.DH.Cert.upper_B_right_06; leanexport Ccentre.Primes (towers 2, 401, 1801); leanexport CB_right_06.Primes (tower 2, clean and planted)
  - <toolchain>/bin/con-ron --verified --jobs=8 --progress=1 on each of those four exports, under guard.py
  - guard.py leanchecker-fresh <receipts> -- <toolchain>/bin/leanchecker --fresh Rung3Assembly.Final
outcome: Stage A accepted, a same-kernel fresh replay of the closure of all 18 final declarations (1,569,505 constants, Mathlib and hunt 137 included), exit 0 in 7 h 17 min at 22.8 GB; a missing module exits 1 and a one-unit radius fault in a scratch olean is refused by the kernel at Prime_B_right_06_2.ev_whole; Stage B ran on samples only (con-ron accepted the closure of upper_B_right_06 and three centre towers, and rejected the planted fault at the same declaration) and stopped at its estimate, about 1,300 core-hours and 56 to 102 GB for the full closure
artifacts:
  - hunts/rung3_ball_production/pilot.json (production.replay)
  - hunts/rung3_ball_production/lean/ReplayProgress.lean
  - <cache>/rung3-ball-production-full/receipts-replay-20261027

2026-10-27: door 1, Stage B on a fleet: design, pilot estimate (before spending)

The operator's brief of 2026-10-27: run con-ron --verified (the toolchain's second kernel, SHA-256 4e5616d94374cae3...) over the whole assembled closure, split site by site across InstaBox VMs (primary) and Novita sandboxes (second provider), exported on this box one artifact zip at a time. Hard cap USD 40 across both providers (corrected 2026-10-30: the code never enforced USD 40; HARD_CAP_USD was defined and unused, and the only spend control was a gate on new launches at a projected USD 36, STOP_LAUNCH_USD; spend stayed at USD 8.93, so nothing turned on it); a dead-man deletes every VM of this run 12 hours after the first launch or when a stop file appears. Work directory and state: <cache>/rung3-conron-fleet-20261027 (exports.json, phase0.json, fleet.json, the VM registry vms.jsonl, the spool, the manifests, the receipts and every log).

Why the top shard is glued, not stubbed. con-ron --verified declines any axiom but the three standard ones (measured on a two-line scratch export: declined: non-standard axiom, exit 2), so the site theorems cannot enter the top shard as axioms. lean/ExportShard.lean (compiled with lean -c and leanc, no Lake) instead abstracts them: for each of the site theorems S the assembly modules name, a definition Rung3Glue.T.S : Prop := <type of S>, and for each assembly constant c that reaches one, Rung3Glue.c : ∀ h₁ … hₙ, <type of c>, whose value is c's own value with Sᵢ replaced by hᵢ. Lean's kernel checks each new declaration as it is added, then the toolchain's own exporter (LeanExport.dumpEnv, the code of leanexport) writes the shard. A site shard holds every constant of one site's five modules (not only its theorem's closure), each with its closure. shard_manifest.py hashes every declaration of every shard (BLAKE2b Merkle hashes over the exported structure), so the coverage step can match the shards' shared constants and each Rung3Glue.T.S against the type of S in its site shard. The assembled oleans were deleted after Stage A, so phase0 re-collects all 20 zips onto /dev/shm once, re-assembles, compares the assembly oleans with the Stage A receipts, writes the census and the closure of the 18 final declarations in the real environment, exports the top shard, and clears /dev/shm. The site shards then stream one zip at a time (export), compressed with zstd -9 into a spool capped at 7 GB, with free disk kept above 10 GB.

Controls measured before any VM (this box).

Pilot estimate. Three shards: site:B_right_06 on an InstaBox 8/16 VM (Stage A's sample took 690 s at 8 workers here, so about 15 minutes with boot and upload, about USD 0.02), the same file on a Novita 2/4 sandbox (about 4,300 CPU-s, so 40 to 50 minutes at 2 workers, list about USD 0.09), and the grid site site:g_left_16 on an InstaBox 8/16 VM (96 towers, interpolated in log p at about 8 core-hours, so about 1 to 1.5 hours, about USD 0.10). In all, under USD 0.25. The full estimate follows from the pilot, before the full launch.

Launched (detached, setsid nohup):

Pilot spend: InstaBox about USD 0.07, Novita about USD 0.04 at list price.

The full estimate, from the pilot (written 15:58 UTC, before the full launch). The tower model of Stage A (tower_cpu_s, interpolated in log p) over-prices the VMs: measured CPU over model is 0.466 for B_right_06 (23 towers, p up to 89) and 0.592 for g_left_16 (96 towers, p up to 509), so the ratio grows with p. Charging big boxes at 0.55, grid sites at 0.60 and the centre (278 towers, p past 1,800) at 0.80:

classsitescon-ron CPU
big boxes110236 core-hours
grid points104523 core-hours
centre130 core-hours (107,000 CPU-s, about 4.1 h of wall on 8 workers)
top shard1about 1 core-hour

About 790 core-hours, so about 141 VM-hours of InstaBox 8/16 at 80 % use plus 5 minutes per VM, about USD 9.6 (band 7.7 to 14.4); eight small big boxes (23 to 36 towers, at most about 4,000 CPU-s each, so about 35 minutes on 2 vCPU) and a second fault shard go to Novita, about USD 0.7 at list price. Wall: about 4 to 5 hours, set by the centre. Peak RSS per shard 1.5 to 3.2 GB measured, about 4 GB expected for the centre (export 788 MB, against 487 to 566 MB for the others). Far under the USD 40 cap; the orchestrator stops launching if its running projection (spent plus what is left, priced the same way) reaches USD 36.

The full fleet, launched 15:57 UTC

conron_fleet.py run --add <the centre, the 104 grid sites by projected cost, the top shard, the 110 big boxes, a second fault shard on Novita> --novita --novita-max 5 --novita-shards <8 small big boxes> --instabox-max 90 --workers 8 --poll-s 300 --scale 0.6, PID 4031895, log <cache>/rung3-conron-fleet-20261027/logs/fleet-full.log, state fleet.json (one record per shard: its VMs with ids, creation and deletion times, every status poll, the verdict). The exporter (PID 3897463) keeps feeding the spool; a shard is launched once its export is spooled. The dead-man (PID 3793391) still holds the 03:04 UTC deadline.

The full fleet: the outcome (measured)

id: rung3_ball_production-2026-10-27-door1-stage-b
hunt: rung3_ball_production
started: 2026-10-27T14:35Z
finished: 2026-10-27T19:14Z
ran:
  - hunts/rung3_ball_production/conron_fleet.py build (lean -c and leanc on lean/ExportShard.lean; no Lake)
  - hunts/rung3_ball_production/conron_fleet.py phase0 (production.py collect and assemble on /dev/shm; exportshard census, closure and top against Rung3Assembly.Final)
  - hunts/rung3_ball_production/conron_fleet.py export (the 215 site shards and the planted-fault shard, one zip at a time)
  - hunts/rung3_ball_production/conron_fleet.py run (pilot, then the full fleet; conron_shard.py on each VM)
  - hunts/rung3_ball_production/conron_fleet.py deadman --deadline 2026-10-28T03:04:12Z
  - hunts/rung3_ball_production/conron_fleet.py remanifest; coverage; record --write-pilot
outcome: con-ron --verified accepted all 216 shards (the 215 sites and the glued top shard, 13,982,741 declarations); the coverage join found no clash in kernel hash across shards, all 435 glue types equal to their site theorems' types, and no constant of the 675,388 in the closure of the 18 final declarations unchecked; the planted one-byte fault was rejected on InstaBox and on Novita at Prime_B_right_06_2.ev_whole._proof_1_1; 834 core-hours, USD 8.93; every VM deleted
artifacts:
  - hunts/rung3_ball_production/RESULTS.md
  - hunts/rung3_ball_production/pilot.json (production.replay.stage_b_fleet)
  - <cache>/rung3-conron-fleet-20261027

2026-10-27: dead-man defect found after the run, fixed before any reuse

An automated code review of #366 (P1, conron_fleet.py cmd_deadman) found that at the deadline the dead-man deleted VMs without writing RUN/STOP. Fleet.step and wait_for gate every launch on STOP, not on the deadline, so a fleet still running at its deadline could provision replacements after the sweep had finished and the dead-man had exited.

The completed run was not affected. It ended after 4 h 6 min, well inside its 12-hour deadline. Its dead-man was triggered by the stop file (above), not by the deadline, and its final sweep found nothing left on either provider.

The fix (branch fix/conron-deadman-stop):