Drop7 Research
← Docs
docs/exploratory/finding-08-learned-leaf.md

Finding 08 — A learned leaf helps, and the chance-bias cap hypothesis is wrong

Status: exploratory. Evidence tier development for the gameplay arms (64 paired whole games per arm on a previously read reusable development cohort), CHECK for the export, parity and feasibility gates. Built and measured in this checkout on 2026-08-20. Namespace: approaches/lifetime-objective/learned-leaf/, run runs/RUN-A52-LEAF/, seed lease SEEDLEASE-A52-LEAF = 0xa52400000xa5247fff. Preregistration: PREREGISTRATION.md, written before any gameplay cohort was run. Nothing in docs/research/, artifacts/, research/, or any existing approach source was modified. The only files created are under approaches/lifetime-objective/learned-leaf/, build/lifetime-leaf/, runs/RUN-A52-LEAF/ and docs/exploratory/.

Summary

Four results, in descending order of how much they should change what the program does next.

  1. The preregistered prediction is refuted. A learned survival evaluator blended into the leaf of fair depth 4 is worth +39,105 points (95% lower bound +1,138) with the biased five-stratum chance estimator and +17,281 (95% lower bound −55,892) with the exact seven-stratum one. The difference-in-differences is −21,824 (95% lower bound −105,254): the effect is smaller where the prediction said it would be larger. Chance-node bias does not cap leaf-injected foresight the way it caps extra lookahead. Depth and estimator quality are complements (finding-05); a learned leaf and estimator quality behave like substitutes.

  2. The learned leaf is nonetheless a real, positive, significant result on the axis where it was tested. +39,105 points and +11.13 moves at five strata, 37–0–27 on paired games, with a one-sided 95% bootstrap lower bound above zero, and every quantile from Q25 up improving. Against the pattern status.md §4 records — learned public-state values that fitted the played action and then failed to rank unplayed siblings — this one is state-only and sibling-blind by construction, and it improved complete games.

  3. The model that was supposed to play could not. A depth-4 fair expectimax evaluates 615,090 leaves per decision at five chance strata and 2,271,280 at seven — measured, not estimated. The trained 3,006,543-parameter CNN costs 4,122 µs per state in the exported C++ path, so at the leaf it is ~2,860x over budget: 2,535 seconds per decision against a 0.887 s reference decision, or 18 days for one 64-game arm. The experiment ran on an NNUE-shaped student, trained on the same corpus and the same whole-origin split, that reaches 0.8564 held-out lifetime Pearson against the CNN's 0.8646 at 1/3,109th the cost. Model capacity was not the binding constraint; leaf arity was.

  4. torch.nn.Conv2d on this host's CPU is nondeterministic, which silently broke the parity gate before it was caught. Separate write-up: gpu-03.

The mechanism behind (1) is visible in the flow rates. Both the exact chance estimator and the learned leaf are ways of knowing what happens after the current move. Having bought that information once, buying it again returns less: seven strata is worth +101,171 over five with the frozen leaf and only +79,347 with the learned one; the learned leaf is worth +39,105 at five strata and +17,281 at seven. Read either way round, it is the same substitution.

1. The export, and the wall it ran into

1.1 A dependency-free C++ inference path

export_net.py writes the trained checkpoint to a versioned, self-describing binary (D7NET, format version 1: a magic, the architecture scalars, a name-keyed float32 tensor table in PyTorch's own contiguous order, and an FNV-1a digest of everything above it). net.hpp reads it and runs the model with no libtorch, no BLAS, no dynamic library and no allocation on the hot path. Everything is NHWC — 49 pixels, channels minor — so a 3x3 convolution is 49 x 9 rank-1 updates of a C_out-wide accumulator and the innermost loop is a unit-stride FMA over channels. Weights are repacked once at load into [tap][in][out] order.

Exported artifact: runs/RUN-A52-LEAF/model/survival-c128-shuffled.d7net, 54 tensors, 3,006,543 floats, 12,027,890 bytes, fnv1a=0x187dcaafbf6479bd.

1.2 The parity gate, with the tolerance stated

4,096 real board states drawn from runs/RUN-A51D-corpus/mix-d3.states by a deterministic stride that both the C++ and the Python side compute independently. Declared tolerance before the comparison: 2e-3 absolute or 2e-3 relative on every head, relative difference measured as |a-b| / max(|a|, |b|, 1.0) with the floor stated so a near-zero output cannot manufacture an infinite ratio.

headmax absolutemax relativereference range
hazard logits (12)4.900e-054.031e-05[−22.19, 17.57]
lifetime, log1p moves4.649e-062.333e-06[0.574, 4.353]
flow, clears3.767e-053.103e-05[−0.246, 11.46]
flow, reveals1.812e-051.252e-05[−0.201, 6.693]
hazard probabilities (derived)8.643e-068.643e-06[2.3e-10, 1.0]
lifetime in moves (derived)1.357e-045.383e-06[0.776, 76.73]

PASS, by a factor of about 40 on the worst head. Pearson between the two lifetime predictions is 1 − 4e-13. Ranking 4,096 states by predicted lifetime gives one adjacent inversion out of 4,095, and it occurs at an exact tie in the reference (gap 0.000), so it is a sort-stability artifact rather than a disagreement.

The same gate for the student that actually plays (§3), against a reference proved bit-repeatable over three trials:

headmax absolutemax relative
hazard logits3.815e-062.034e-06
lifetime, log1p moves1.192e-064.493e-07
flow, clears2.265e-062.265e-06
flow, reveals1.669e-061.179e-06
lifetime in moves6.515e-05

In the unit the search actually consumes — expm1(lifetime) x 3400, points — the largest disagreement anywhere in the 4,096 states is 0.22 points, against a 17,000-point row-rise bonus.

1.3 The gate initially failed for a reason that was not the code

The first CPU comparison passed at 1.1e-5. The identical command, re-run, reported failures on every head and a maximum relative error of 3.5e-2. Neither run was wrong about the C++ path: torch.nn.Conv2d on this host's CPU is nondeterministic. Two identical forward passes over the same tensor, in eval(), single-threaded, with every thread environment variable pinned to 1, differ in 6.25% of output elements by up to 0.15. GroupNorm, Linear and torch.mm are bit-exact; disabling the oneDNN path makes Conv2d bit-exact. Through GroupNorm's group statistics one perturbed stem activation moves every downstream output, so repeated whole-model passes differ in 100% of outputs by 0.18–0.35 per logit.

This is written up separately in gpu-03-onednn-conv-nondeterminism.md, because it is not specific to this experiment: any gate in this repository that compares against a CPU PyTorch convolution has been measuring that comparison plus an unknown perturbation. The parity scripts here now disable oneDNN and prove the reference repeats bit-for-bit before comparing anything to it, exiting non-zero on drift.

2. The affordability wall, measured rather than assumed

Nothing in the repository recorded how many leaves a depth-4 fair expectimax evaluates, so leaf-probe measured it over 30 whole-game decisions from 0xa5240000, counting both total leaf calls and distinct leaf states (the ceiling on what a perfect leaf memo could save).

depth 4, 5 stratadepth 4, 7 strata
logical work per decision1,271,7854,631,941
leaf evaluations per decision615,090 (max 1,110,435)2,271,280 (max 3,405,402)
distinct leaf states per decision380,3261,118,405
dedup ratio available to a perfect memo1.6x2.0x
reference decision, one thread0.887 s3.675 s

Against that, the exported CNN costs 4,122 µs per state on one thread (42 GFLOP/s for its ~174 MFLOP), and 2,218 states/s across 12 threads.

615,090 x 4,122 µs = 2,535 seconds per decision, against a 0.887 s reference decision. That is a factor of 2,860. One 87-move game would take 6.7 hours of the entire machine; the 64-game arm would take 18 days. A 1.6x memo, 4x int8 quantisation and a 2x better kernel together move that to ~220x, which is still not a slower experiment but an impossible one.

The premise that a ~3M-parameter CNN can be the leaf of a depth-4 expectimax in this game is false, and it is false by three orders of magnitude. That is the first result in this document and it is not close enough to argue about.

3. What can afford to play: LeafNet

A leaf evaluator has roughly one microsecond. That is an NNUE-shaped budget, so the student is NNUE-shaped: binary features that are gathered and summed rather than multiplied through a dense matrix.

8,902 features, exactly 135 active per state — 49 (cell, value) features, 1 next disc, 1 moves-until-rise, and 42 horizontal plus 42 vertical adjacent pair features (position, value_a, value_b). The pairs are the point: a Drop7 disc clears when its number equals the length of the run it lands in, so run structure is the mechanism, and a per-cell bag of features cannot see a run at all. Then EmbeddingBag(8902, 64, sum) + bias -> ReLU -> Linear(64, 32) -> ReLU -> Linear(32, 15), the 15 outputs being the same 12 hazard logits, log lifetime and 2 flow scalars the CNN predicts.

Trained on the same corpus, the same targets, the same loss weights and — this matters — the same whole-origin split seed, so the two models' held-out numbers are computed on the same 486,819 rows from the same games.

modelparametersheld-out lifetime Pearsonheld-out MAE (moves)µs per state
SurvivalNet CNN (teacher)3,006,5430.864614.254,122
LeafNet (deployed)572,3670.856414.441.33

The compression costs 0.008 of Pearson and 0.2 moves of MAE for a 3,109x speedup. On 4,096 held-out states the student's lifetime prediction agrees with the teacher's at Pearson 0.9815 and a mean absolute difference of 2.48 moves (teacher mean 35.81 moves, student 35.52). Mirroring the board changes the student's held-out Pearson from 0.85640 to 0.85644, so it carries no column preference — which matters because the frozen search hands the leaf a canonicalised state while the corpus stores boards in play orientation.

Training took 10 epochs at 3.4 s per epoch on the gfx1151 GPU. The student contains no convolution, so its PyTorch reference repeats bit-for-bit with no flags at all (§1.3).

A subsequent thirteen-run offline sweep (RS-20260822T024228Z-94090db1, mechanics-only tier) asked whether a wider student of the same shape closes the 0.008 gap to the teacher, and the answer is no — held-out accuracy falls as width grows even as training loss keeps improving:

NNUE capacity saturation — training loss falls monotonically with width while held-out Pearson falls NNUE capacity saturation — training loss falls monotonically with width while held-out Pearson falls. RS-20260822T024228Z-94090db1: a 13-run offline capacity/training sweep of the NNUE-shaped survival leaf on runs/RUN-A51D-corpus/all.states, all runs on the same whole-origin test split (486,819 held-out examples); evidence tier mechanics-only, gate verdict supported-as-tested. The width series charted here is copied verbatim from the record's summary (tag: parameters, Pearson, final train loss): h32-m32-e10 286,447 / 0.855 / 0.5238; h64-m32-e10 (baseline) 572,367 / 0.8546 / 0.511; h128-m32-e10 1,144,207 / 0.8543 / 0.5006; h256-m32-e10 2,287,887 / 0.8515 / 0.4857; h256-m64-e20 2,296,591 / 0.8446 / 0.4596; h512-m64-e20 4,592,143 / 0.8378 / 0.4197 — training loss falls while held-out accuracy falls: larger students overfit this corpus. The two h256 points differ in mid-width and epochs, not width alone. Seed-to-seed spread is 0.0023 over three seeds; the best configuration (h64-m64-e10, 0.8568) beats the baseline by +0.0022 <= max(0.005, 2 x spread), so capacity is saturated near 0.855-0.857 on this feature space and corpus. The record itself notes finding-08 recorded 0.8564 for the h64 baseline architecture on an earlier torch build — the 0.8546 charted here is this record's own measurement. Teacher CNN anchor, NOT charted (different architecture): 0.8646 at 3,006,543 parameters (finding-08 section 3). The x axis is linear; the plan's log-scale suggestion is not expressible by the generator. Sources: RS-20260822T024228Z-94090db1. NNUE capacity saturation — training loss falls monotonically with widthwhile held-out Pearson falls0.840.840.850.850.86286,447572,3671,144,2072,287,8872,296,5914,592,143held-out lifetime Pearson (Pearson r)parameter count (parameters)held-out lifetime Pearson (NNUE width sweep), parameter count 286447 | h32-m32-e10-lr3e3-s0; final train loss 0.5238 | held-out lifetime Pearson: 0.86 Pearson r | source: RS-20260822T024228Z-94090db1 · summary width series; | metrics.runs[]held-out lifetime Pearson (NNUE width sweep), parameter count 286447h32-m32-e10-lr3e3-s0; final train loss 0.5238held-out lifetime Pearson: 0.86 Pearson rsource: RS-20260822T024228Z-94090db1 · summary width series;metrics.runs[]held-out lifetime Pearson (NNUE width sweep), parameter count 572367 | h64-m32-e10-lr3e3-s0 (baseline); train loss 0.511; finding-08 | recorded 0.8564 on an earlier torch build | held-out lifetime Pearson: 0.85 Pearson r | source: RS-20260822T024228Z-94090db1 · summary width series; | metrics.runs[]held-out lifetime Pearson (NNUE width sweep), parameter count 572367h64-m32-e10-lr3e3-s0 (baseline); train loss 0.511; finding-08recorded 0.8564 on an earlier torch buildheld-out lifetime Pearson: 0.85 Pearson rsource: RS-20260822T024228Z-94090db1 · summary width series;metrics.runs[]held-out lifetime Pearson (NNUE width sweep), parameter count 1144207 | h128-m32-e10-lr3e3-s0; train loss 0.5006 | held-out lifetime Pearson: 0.85 Pearson r | source: RS-20260822T024228Z-94090db1 · summary width series; | metrics.runs[]held-out lifetime Pearson (NNUE width sweep), parameter count 1144207h128-m32-e10-lr3e3-s0; train loss 0.5006held-out lifetime Pearson: 0.85 Pearson rsource: RS-20260822T024228Z-94090db1 · summary width series;metrics.runs[]held-out lifetime Pearson (NNUE width sweep), parameter count 2287887 | h256-m32-e10-lr3e3-s0; train loss 0.4857 | held-out lifetime Pearson: 0.85 Pearson r | source: RS-20260822T024228Z-94090db1 · summary width series; | metrics.runs[]held-out lifetime Pearson (NNUE width sweep), parameter count 2287887h256-m32-e10-lr3e3-s0; train loss 0.4857held-out lifetime Pearson: 0.85 Pearson rsource: RS-20260822T024228Z-94090db1 · summary width series;metrics.runs[]held-out lifetime Pearson (NNUE width sweep), parameter count 2296591 | h256-m64-e20-lr3e3-s0; train loss 0.4596; mid-width and epochs | also changed | held-out lifetime Pearson: 0.84 Pearson r | source: RS-20260822T024228Z-94090db1 · summary width series; | metrics.runs[]held-out lifetime Pearson (NNUE width sweep), parameter count 2296591h256-m64-e20-lr3e3-s0; train loss 0.4596; mid-width and epochsalso changedheld-out lifetime Pearson: 0.84 Pearson rsource: RS-20260822T024228Z-94090db1 · summary width series;metrics.runs[]held-out lifetime Pearson (NNUE width sweep), parameter count 4592143 | h512-m64-e20-lr3e3-s0; train loss 0.4197 — lowest loss, worst | held-out | held-out lifetime Pearson: 0.84 Pearson r | source: RS-20260822T024228Z-94090db1 · summary width series; | metrics.runs[]held-out lifetime Pearson (NNUE width sweep), parameter count 4592143h512-m64-e20-lr3e3-s0; train loss 0.4197 — lowest loss, worstheld-outheld-out lifetime Pearson: 0.84 Pearson rsource: RS-20260822T024228Z-94090db1 · summary width series;metrics.runs[]held-out lifetime Pearson (NNUE width sweep)
Held-out lifetime Pearson against parameter count for the NNUE-shaped student on a log axis. More capacity fits the training set better and generalizes worse; the deployed width is already at the flat top.
Source data

RS-20260822T024228Z-94090db1: a 13-run offline capacity/training sweep of the NNUE-shaped survival leaf on runs/RUN-A51D-corpus/all.states, all runs on the same whole-origin test split (486,819 held-out examples); evidence tier mechanics-only, gate verdict supported-as-tested. The width series charted here is copied verbatim from the record's summary (tag: parameters, Pearson, final train loss): h32-m32-e10 286,447 / 0.855 / 0.5238; h64-m32-e10 (baseline) 572,367 / 0.8546 / 0.511; h128-m32-e10 1,144,207 / 0.8543 / 0.5006; h256-m32-e10 2,287,887 / 0.8515 / 0.4857; h256-m64-e20 2,296,591 / 0.8446 / 0.4596; h512-m64-e20 4,592,143 / 0.8378 / 0.4197 — training loss falls while held-out accuracy falls: larger students overfit this corpus. The two h256 points differ in mid-width and epochs, not width alone. Seed-to-seed spread is 0.0023 over three seeds; the best configuration (h64-m64-e10, 0.8568) beats the baseline by +0.0022 <= max(0.005, 2 x spread), so capacity is saturated near 0.855-0.857 on this feature space and corpus. The record itself notes finding-08 recorded 0.8564 for the h64 baseline architecture on an earlier torch build — the 0.8546 charted here is this record's own measurement. Teacher CNN anchor, NOT charted (different architecture): 0.8646 at 3,006,543 parameters (finding-08 section 3). The x axis is linear; the plan's log-scale suggestion is not expressible by the generator.

Seriesparameter countheld-out lifetime PearsonBoundsnSource
held-out lifetime Pearson (NNUE width sweep)286447 h32-m32-e10-lr3e3-s0; final train loss 0.52380.86 Pearson rRS-20260822T024228Z-94090db1 summary width series; metrics.runs[]
held-out lifetime Pearson (NNUE width sweep)572367 h64-m32-e10-lr3e3-s0 (baseline); train loss 0.511; finding-08 recorded 0.8564 on an earlier torch build0.85 Pearson rRS-20260822T024228Z-94090db1 summary width series; metrics.runs[]
held-out lifetime Pearson (NNUE width sweep)1144207 h128-m32-e10-lr3e3-s0; train loss 0.50060.85 Pearson rRS-20260822T024228Z-94090db1 summary width series; metrics.runs[]
held-out lifetime Pearson (NNUE width sweep)2287887 h256-m32-e10-lr3e3-s0; train loss 0.48570.85 Pearson rRS-20260822T024228Z-94090db1 summary width series; metrics.runs[]
held-out lifetime Pearson (NNUE width sweep)2296591 h256-m64-e20-lr3e3-s0; train loss 0.4596; mid-width and epochs also changed0.84 Pearson rRS-20260822T024228Z-94090db1 summary width series; metrics.runs[]
held-out lifetime Pearson (NNUE width sweep)4592143 h512-m64-e20-lr3e3-s0; train loss 0.4197 — lowest loss, worst held-out0.84 Pearson rRS-20260822T024228Z-94090db1 summary width series; metrics.runs[]

Spec: web/content/figures/nnue-capacity-saturation.json · 1 source record

4. The leaf, and why this leaf value

leafValue = (1 - w) * frozen::fairLeaf(state) + w * scale * learnedValue(state)

w = 0 short-circuits to frozen::fairLeaf before the model is touched, so the reference arms are the frozen search bit-for-bit and cost exactly what the reference costs.

The whole arrangement, drawn once:

The blended leaf: (1−w)·handLeaf + w·scale·learnedLifetime at the search frontier Parameter diagram: how the blended leaf of finding-08 works. Left: the blend sits at every leaf of the fair expectimax search frontier - leaves are 96.1% of all nodes (finding-13 section 2.1), 2,271,280 evaluations per depth-4 seven-strata decision (finding-08 section 2). Center: the formula blended = (1-w)*handLeaf + w*scale*learnedLifetime, where handLeaf is the frozen fairLeaf (nineteen hand-weighted structural terms, already in points) and learnedLifetime is LeafNet's predicted remaining lifetime mapped to points by scale = 3400. Bottom: the tuning response in w on the separate 32-game tuning cohort (finding-08 section 5): paired delta versus w = 0 is +8,174 at w = 0.25, +33,681 at w = 0.5, and -30,947 at w = 1.0 - an inverted U: the pure learned leaf is worse than the frozen one, so the two are complements and the blend is not a formality. w = 0 short-circuits to frozen::fairLeaf before the model is touched, making the reference arms bit-for-bit the frozen policy (they reproduced finding-05's published cohort to every digit; 0 score-identity violations in 26,934 decisions). w = 0.5, scale = 3400, lifetime head were frozen for the 2x2 before any evaluation cohort was read. In the 2x2 (finding-08 section 7) the gain is significant at five strata (+39,105, one-sided 95% lower bound +1,138), not at seven (+17,281), and the difference-in-differences of -21,824 refutes the preregistered chance-bias cap prediction. Sources: docs/exploratory/finding-08-learned-leaf.md sections 2-3, 5, 7, 11; docs/exploratory/finding-13-fast-engine.md. The blended leaf: (1−w)·handLeaf + w·scale·learnedLifetime at the search frontier w and scale are the blend parameters; w = 0 is the frozen policy bit-for-bit (finding-08 §5, §7) where the blend sits: the search frontier decision: pick a column c1 c2 c7 ? 1 2 3 4 5 6 7 × every ply every leaf 96.1% of nodes are leaves 2,271,280 leaf evaluations per d4 s7 decision handLeaf = frozen fairLeaf 19 hand-weighted structural terms learnedLifetime = LeafNet NNUE student · 1.33 µs per state scale = 3400 maps predicted moves to points (1 − w) w · 3400 Σ w = 0.50 blended leaf value (points) backed up the expectimax tree as the leaf's value the tuning response in w — paired Δ score vs w = 0 (finding-08 §5) 0 +8,174 +33,681 −30,947 w = 0 0.25 0.5 1.0 bit-identical fallback frozen for the 2x2: w = 0.5, scale = 3400 pure learned is worse: the blend is not a formality 32-game tuning cohort (seeds 0xa5241000+); it chooses w — the 64-game evaluation cohort tests it (§5) w = 0 is the frozen policy bit-for-bit; w = 0.5 blends half structural leaf with half learned lifetime × 3400. tuned on a separate 32-game cohort; in the 2x2 the gain is significant at s5 and the DiD refutes the cap hypothesis (§5–7) Where the blend sitsiThe blend is the leaf evaluator of the fair expectimax search: it runsat every frontier leaf — 96.1% of all nodes (finding-13 §2.1), which is2,271,280 evaluations per depth-4 seven-strata decision (finding-08 §2).That is why the leaf budget is ≈1 µs and the deployed model is anNNUE-shaped student, not the 4,122 µs CNN teacher (finding-08 §2–3).The ringed leaf is one frontier evaluation; the arrow is the blend below. The hand leafihandLeaf is the frozen fairLeaf: nineteen hand-weighted structuralterms (finding-08 §5), already denominated in points, pinned to theTypeScript reference and bit-identical across 225,183 corpus leaves inthe fast engine (finding-13 §4E). In the blend it keeps the structuralsibling ranking that the learned head on its own lacks (§5). The learned leafilearnedLifetime is LeafNet's prediction of remaining lifetime (moves).LeafNet: 572,367 parameters, 0.8564 held-out lifetime Pearson againstthe CNN teacher's 0.8646, at 1.33 µs vs 4,122 µs per state (§3).scale = 3400 maps predicted moves to leaf points; --leaf-value lifetimeselects this head over the hazard head, which priced at one level bonusper surviving rise was worth ≈ nothing (−3,276 paired Δ, §5). The blend formula, and w = 0iblended = (1 − w)·handLeaf + w·scale·learnedLifetime. At w = 0 thecode short-circuits to frozen::fairLeaf before the model is touched, sothe reference arms are the frozen policy bit-for-bit: they reproducedfinding-05's published cohort to every digit, with 0 score-identityviolations in 26,934 decisions (finding-08 §7). w = 0.5, scale = 3400and the lifetime head were frozen on the tuning cohort before the 2x2. The inverted UiTuning response (paired Δ vs w = 0, 32 games): +8,174 at w = 0.25,+33,681 at w = 0.5, −30,947 at w = 1.0. The pure learned leaf loses31k points and 8 moves, occupancy climbing to 25.53 cells: a goodlifetime predictor is still a worse ranker of sibling leaves than the19 structural terms — the two are complements (finding-08 §5). No32-game bound excludes zero; tuning chooses, evaluation tests. What the 2x2 showedi64 paired games per arm (finding-08 §7): d5 = +39,105 with one-sided95% lower bound +1,138 (significant); d7 = +17,281 (not significant);DiD = −21,824, lower bound −105,254 — the preregistered "helps more at7 strata" prediction is refuted, and the value of the exact chanceestimator falls 22% once the leaf carries a learned survival estimate.
At every frontier leaf of the search, the position's value is a weighted mix of the nineteen hand-tuned structural terms and the learned model's remaining-lifetime estimate scaled into points — w slides between the two, with w = 0 exactly the frozen policy.
Source

diagram-leaf-blend.svg — source and reading guide

Parameter diagram: how the blended leaf of finding-08 works — (1−w)·handLeaf + w·scale·learnedLifetime at the search frontier — and what w = 0 (bit-identical fallback) and w = 0.5 (the frozen choice) mean.

What it explains

  • Where the blend sits: it is the leaf evaluator of the fair expectimax search, run at every frontier leaf — leaves are 96.1% of all nodes (finding-13 §2.1), i.e. 2,271,280 evaluations per depth-4 seven-strata decision (finding-08 §2). That is why the leaf budget is "roughly one microsecond" and the deployed model is the NNUE-shaped LeafNet (1.33 µs per state), not the 4,122 µs CNN teacher (finding-08 §2–3).
  • The formula: blended = (1−w)·handLeaf + w·scale·learnedLifetime. handLeaf is the frozen fairLeaf — nineteen hand-weighted structural terms, already in points. learnedLifetime is LeafNet's predicted remaining lifetime in moves; scale = 3400 maps moves to leaf points.
  • What w = 0 means: the code short-circuits to frozen::fairLeaf before the model is touched, so the reference arms are the frozen policy bit-for-bit — they reproduced finding-05's published cohort to every digit, with 0 score-identity violations in 26,934 decisions (finding-08 §7).
  • What w = 0.5 means: half structural leaf, half learned lifetime × 3400. Frozen with the lifetime head on a separate 32-game tuning cohort (seeds 0xa52410000xa524101f) before the 2x2; the evaluation cohort was never touched by tuning (finding-08 §5).
  • The inverted U: paired Δ vs w = 0 on the tuning cohort: +8,174 at w = 0.25, +33,681 at w = 0.5, −30,947 at w = 1.0. The pure learned leaf is worse than the frozen one (occupancy climbs to 25.53 cells): a good lifetime predictor is still a worse ranker of sibling leaves than the 19 structural terms. The two are complements; the blend is not a formality.
  • The 2x2 outcome (popover): d5 = +39,105 (95% lower +1,138, significant); d7 = +17,281 (not significant); DiD = −21,824 → the preregistered chance-bias cap prediction is refuted; the value of the exact chance estimator falls 22% once the leaf carries a learned survival estimate (finding-08 §7).

Element-by-element

  • Left panel: a compact decision tree (decision node → 7 columns → chance node → 7 discs → dashed "× every ply" → frontier leaf row). One leaf is ringed in danger red; the arrow from it to the blend panel reads "every leaf". Notes give the 96.1% / 2,271,280 leaf counts.
  • Center panel: the two blend inputs as boxes — handLeaf (accent border, frozen fairLeaf, 19 structural terms) and learnedLifetime (LeafNet, 1.33 µs/state, with the scale = 3400 note) — feeding the Σ mixer through arrows labelled (1 − w) and w · 3400, with the frozen w = 0.50 badge, down to the blended leaf value in points that is backed up the tree.
  • Bottom panel: the tuning response in w as a small plot — dashed zero line (the w = 0 reference), the four measured points joined by an inverted-U curve, the w = 0.5 point ringed and annotated "frozen for the 2x2", w = 0 annotated "bit-identical fallback", and w = 1.0 (danger red) annotated "pure learned is worse: the blend is not a formality". A note states the tuning/evaluation cohort separation.
  • Caption strip: "w = 0 is the frozen policy bit-for-bit; w = 0.5 blends half structural leaf with half learned lifetime × 3400", plus the tuning-cohort / 2x2 outcome line.
  • Popovers: where the blend sits (leaf counts, the 1 µs budget); the hand leaf (19 terms, bit-exactness gate); the learned leaf (LeafNet vs CNN accuracy and cost, lifetime vs hazard head); the formula and the w = 0 short-circuit validity gate; the inverted U with the tuning numbers; and the 2x2 outcome on the caption.

Simplifications (stated explicitly)

  1. The tree is schematic (three of seven columns and strata arrows drawn, ellipses for the rest); no real position is implied. No board is drawn, so engine board orientation does not apply here.
  2. The w-response plot draws the four tuning-cohort paired deltas as points joined by a smooth curve for readability; the curve between measured points is illustrative, not interpolated data. None of the 32-game bounds excludes zero — the plot's own note and popover say tuning chooses, evaluation tests.
  3. "× 3400" in the caption is the frozen scale value; the diagram does not derive it (it was chosen on the tuning cohort, finding-08 §5).
  4. The hazard-head row of the tuning table (−3,276) appears only in a popover, to keep the plot to the lifetime blend that was frozen.

Sources

  • docs/exploratory/finding-08-learned-leaf.md — §2 (leaves per decision; CNN 4,122 µs/state), §3 (LeafNet 572,367 params, 0.8564 vs 0.8646 Pearson, 1.33 µs; the ≈1 µs leaf budget), §5 (blend parameters, tuning cohort, the inverted-U table, hazard head, "the blend is not a formality", the frozen w = 0.50, scale = 3400, --leaf-value lifetime), §7 (w = 0 short-circuit and the bit-for-bit validity gate; the 2x2 and DiD), §11 (CNN never played).
  • docs/exploratory/finding-13-fast-engine.md — §2.1 (96.1% leaves), §4E (bit-exact leaf gate, 225,183 leaves).
  • docs/exploratory/finding-05-chance-strata.md — the published cohort the w = 0 arms reproduced, quoted via finding-08 §7.
  • Figure spec: runs/RUN-20260823T191900Z-b9f8f80d/kimi-k3-figure-plan.md (parameter-diagrams batch, this diagram = "leaf blend").

Conventions

Same as the other diagrams in this directory: viewBox="0 0 760 540", width="100%", theme-aware CSS variables with light fallbacks, fig-pt/fig-pop pure-SVG hover/focus popovers with tabindex="0", <title>/<desc> with sources, matching diagram-two-hit-reveal.svg and the .research-fig block of web/app/globals.css. Under 30 KB.

Source: web/content/figures/diagrams/diagram-leaf-blend.source.md

Paired deltas, one-sided 95% bootstrap lower bounds over whole games

20,000 percentile-bootstrap resamples, RNG seed 0xa52a1eaf, resampling seeds so a game's four arm outcomes stay together.

comparisonΔ score95% lowerΔ movesW–T–Lreading
d5 = learned − reference, 5 strata+39,105+1,138+11.1337–0–27significant
d7 = learned − reference, 7 strata+17,281−55,892+6.0934–0–30not significant
DiD = d7d5−21,824−105,254−5.0329 of 64 games positiveprediction refuted
7 strata − 5 strata, reference leaf+101,171+46,730+27.5041–0–23significant (reproduces finding-05)
7 strata − 5 strata, learned leaf+79,347+17,053+22.4738–0–26significant, but 21,824 smaller

The last two rows are the same substitution seen from the other axis, and they are the more useful form of it: the value of making the chance estimator exact falls by 22% once the leaf already carries a learned survival estimate.

The validity gate that makes this comparable

Because w = 0 short-circuits to frozen::fairLeaf before the model is touched, the two reference arms are the frozen policy bit-for-bit and had to reproduce finding-05's published confirmation cohort. They did, to every digit reported there:

meanmedianQ25minmaxsdmovesmed movesclears/mvreveals/mvwork/mv
d4s5 here297,327260,415192,35286,935836,427150,55087.1677.51.94891.06971,296,034
d4s5 published297,327260,415192,35286,935836,427150,55087.1677.51.94891.06971,296,034
d4s7 here398,498344,630212,864103,3311,341,287254,414114.66102.52.05711.15494,956,614
d4s7 published398,498344,630212,864103,3311,341,287254,414114.66102.52.05711.15494,956,614

The 4,956,614 work per move also confirms the seven-stratum arms completed depth 4 rather than silently degrading to depth 3 at the frozen 3,200,000 bound — the failure mode finding-05 identified. Score-identity violations: 0 in all four arms, 5,578 + 6,290 + 7,338 + 7,728 = 26,934 decisions. Censored games: 0 of 256.

8. Flow rates and occupancy — is the gain mechanical or lucky?

Steady-state survival requires ≥ 2.400 numbered clears and ≥ 1.400 covered reveals per move (finding-01); a clairvoyant planner sustains 2.3875 / 1.3963 at 19–20 occupied cells (finding-06).

armclears/movereveals/movemean occupied cellspoints/movelevel sharechain share
d4 s5, reference1.94891.069724.293,41194.61%5.39%
d4 s5, learned1.98311.090924.683,42394.90%5.10%
d4 s7, reference2.05711.154923.153,47693.79%6.21%
d4 s7, learned2.07141.159523.873,44394.81%5.19%
requirement / clairvoyant2.400 / 2.38751.400 / 1.396319–20

At five strata the mechanism is present. Clears rise by +0.0342 and reveals by +0.0212 per move, closing 7.6% and 6.4% of the remaining gap to the conservation requirement, and the lifetime gain (+11.13 moves) is what that flow gain predicts. The score gain is not a tail artifact: the cohort median rises by +53,315, Q25 by +17,562 and the minimum by +17,387 — every reported quantile improves — and the median paired per-game delta is +54,319.

At seven strata the mechanism is absent. Pooled clears move +0.0143 and reveals +0.0046, and the paired per-game versions are slightly negative (−0.0139 and −0.0157, 95% lower bounds −0.0834 and −0.0682). The +17,281 score delta at seven strata is therefore not supported by a flow-rate movement, which is an independent reason — beyond its own bootstrap bound — to treat it as unresolved rather than as a smaller real effect. It also strengthens the refutation: the prediction required the learned leaf to work better here, and by the mechanistic test it does not work here at all.

Occupancy moves the wrong way in both cases. The learned leaf pushes the board from 24.29 to 24.68 cells at five strata and from 23.15 to 23.87 at seven, away from the 19–20 cell equilibrium where finding-06 measured the achievable clear rate crossing 2.400. The tuning sweep shows the same thing more sharply: the pure learned leaf at w = 1.00 runs at 25.53 cells and loses 31,000 points. The learned leaf buys lifetime without moving the board toward the operating point that makes lifetime free. It is trading inside fair D4's regime rather than relocating the policy to the clairvoyant one, and that is a concrete, measurable statement about its ceiling.

9. Inference cost, stated as a frontier point

docs/benchmarks.md requires a learned candidate to be presented as a point on the resource-performance frontier, not as a strength number alone.

armleaf evals / decisionmodel evals / decisionwall s / decisionCPU s / decisiongames / hourmean score
d4 s5, reference628,60900.1111.327373.5297,327
d4 s5, learned660,481660,4810.2152.575 (1.94x)170.7 (0.46x)336,432
d4 s7, reference2,423,50200.3784.53883.0398,498
d4 s7, learned2,496,9222,496,9220.7989.570 (2.11x)37.4 (0.45x)415,779

The frontier itself, as the two lines the table describes:

The learned leaf on the cost frontier — +39,105 points for 1.94x CPU, while exact chance buys +101,171 for 3.42x The learned leaf on the cost frontier — +39,105 points for 1.94x CPU, while exact chance buys +101,171 for 3.42x. finding-08 section 9 frontier table: 64 paired whole games per arm on the shared development cohort 0xa51d1000-0xa51d103f, depth 4, corrected 17,000-point scoring; the learned arms blend LeafNet at w=0.50, scale=3400, lifetime head, frozen on a disjoint tuning cohort. CPU seconds are NOT timing-grade: every arm shared the machine at load 11-19 (finding-08 limitation 6), so the seconds are the recorded cost axis but not a benchmark-grade one; the exact, machine-independent counts are 660,481 (s5) and 2,496,922 (s7) model inferences per decision — the model is called at every leaf — against reference logical work of 1,296,034 (s5) and 4,956,614 (s7) per move. Paired deltas with one-sided 95% lower bounds: s5 +39,105 (LB +1,138, significant) at 1.94x CPU; s7 +17,281 (LB -55,892, not significant, no supporting flow-rate movement) at 2.11x CPU. The recorded equal-compute reading (section 9): spending the same compute on the chance estimator instead — the d4s7 reference at 3.42x the CPU per decision — buys +101,171, so at equal compute fixing the chance estimator is the better purchase. Supplementary recorded anchors, not charted: 615,090 / 2,271,280 leaf evaluations per decision at s5/s7 (section 2); the 3,006,543-parameter CNN teacher costs 4,122 us/state against LeafNet's 1.33 us/state (section 3), ~2,860x over the leaf budget, and never played a move. Evidence tier: development. Sources: docs/exploratory/finding-08-learned-leaf.md. The learned leaf on the cost frontier — +39,105 points for 1.94x CPU,while exact chance buys +101,171 for 3.42x275,000300,000325,000350,000375,000400,000425,0001.332.584.549.57mean score (points)CPU seconds per decision (CPU s)reference leaf (frozen), CPU seconds per decision 1.327 | d4 s5 reference; 0 model evals; 373.5 games/hour | mean score: 297,327 points | n = 64 games | source: docs/exploratory/finding-08-learned-leaf.md · section 9 | frontier tablereference leaf (frozen), CPU seconds per decision 1.327d4 s5 reference; 0 model evals; 373.5 games/hourmean score: 297,327 pointsn = 64 gamessource: docs/exploratory/finding-08-learned-leaf.md · section 9frontier tablereference leaf (frozen), CPU seconds per decision 4.538 | d4 s7 reference; 83.0 games/hour; the fair-D4 operating point | mean score: 398,498 points | n = 64 games | source: docs/exploratory/finding-08-learned-leaf.md · section 9 | frontier tablereference leaf (frozen), CPU seconds per decision 4.538d4 s7 reference; 83.0 games/hour; the fair-D4 operating pointmean score: 398,498 pointsn = 64 gamessource: docs/exploratory/finding-08-learned-leaf.md · section 9frontier tablelearned leaf (w=0.50), CPU seconds per decision 2.575 | d4 s5 learned; 1.94x CPU; paired delta +39,105 (95% LB +1,138), | 37-0-27 | mean score: 336,432 points | n = 64 games | source: docs/exploratory/finding-08-learned-leaf.md · section 9 | frontier table; section 7 paired deltaslearned leaf (w=0.50), CPU seconds per decision 2.575d4 s5 learned; 1.94x CPU; paired delta +39,105 (95% LB +1,138),37-0-27mean score: 336,432 pointsn = 64 gamessource: docs/exploratory/finding-08-learned-leaf.md · section 9frontier table; section 7 paired deltaslearned leaf (w=0.50), CPU seconds per decision 9.57 | d4 s7 learned; 2.11x CPU; paired delta +17,281 (95% LB -55,892), | 34-0-30 — does not clear its bound | mean score: 415,779 points | n = 64 games | source: docs/exploratory/finding-08-learned-leaf.md · section 9 | frontier table; section 7 paired deltaslearned leaf (w=0.50), CPU seconds per decision 9.57d4 s7 learned; 2.11x CPU; paired delta +17,281 (95% LB -55,892),34-0-30 — does not clear its boundmean score: 415,779 pointsn = 64 gamessource: docs/exploratory/finding-08-learned-leaf.md · section 9frontier table; section 7 paired deltasreference leaf (frozen)learned leaf (w=0.50)
Mean score against CPU seconds per decision for the frozen and learned leaves at both chance resolutions. The learned leaf's curve sits above the reference's, but moving right along the reference curve — buying the exact chance estimator — buys more score per second than switching leaves.
Source data

finding-08 section 9 frontier table: 64 paired whole games per arm on the shared development cohort 0xa51d1000-0xa51d103f, depth 4, corrected 17,000-point scoring; the learned arms blend LeafNet at w=0.50, scale=3400, lifetime head, frozen on a disjoint tuning cohort. CPU seconds are NOT timing-grade: every arm shared the machine at load 11-19 (finding-08 limitation 6), so the seconds are the recorded cost axis but not a benchmark-grade one; the exact, machine-independent counts are 660,481 (s5) and 2,496,922 (s7) model inferences per decision — the model is called at every leaf — against reference logical work of 1,296,034 (s5) and 4,956,614 (s7) per move. Paired deltas with one-sided 95% lower bounds: s5 +39,105 (LB +1,138, significant) at 1.94x CPU; s7 +17,281 (LB -55,892, not significant, no supporting flow-rate movement) at 2.11x CPU. The recorded equal-compute reading (section 9): spending the same compute on the chance estimator instead — the d4s7 reference at 3.42x the CPU per decision — buys +101,171, so at equal compute fixing the chance estimator is the better purchase. Supplementary recorded anchors, not charted: 615,090 / 2,271,280 leaf evaluations per decision at s5/s7 (section 2); the 3,006,543-parameter CNN teacher costs 4,122 us/state against LeafNet's 1.33 us/state (section 3), ~2,860x over the leaf budget, and never played a move. Evidence tier: development.

SeriesCPU seconds per decisionmean scoreBoundsnSource
reference leaf (frozen)1.327 d4 s5 reference; 0 model evals; 373.5 games/hour297,327 points64docs/exploratory/finding-08-learned-leaf.md section 9 frontier table
reference leaf (frozen)4.538 d4 s7 reference; 83.0 games/hour; the fair-D4 operating point398,498 points64docs/exploratory/finding-08-learned-leaf.md section 9 frontier table
learned leaf (w=0.50)2.575 d4 s5 learned; 1.94x CPU; paired delta +39,105 (95% LB +1,138), 37-0-27336,432 points64docs/exploratory/finding-08-learned-leaf.md section 9 frontier table; section 7 paired deltas
learned leaf (w=0.50)9.57 d4 s7 learned; 2.11x CPU; paired delta +17,281 (95% LB -55,892), 34-0-30 — does not clear its bound415,779 points64docs/exploratory/finding-08-learned-leaf.md section 9 frontier table; section 7 paired deltas

Spec: web/content/figures/leaf-cost-frontier.json · 1 source record

The learned leaf calls the model at every leaf — 660,481 and 2,496,922 inferences per decision — and roughly doubles the cost of a decision. Read as a frontier, the +39,105 at five strata costs 1.94x, while spending the same compute on the chance estimator instead (d4s7 reference, 3.42x the CPU per decision) buys +101,171. On this machine, at equal compute, fixing the chance estimator is the better purchase, and it is not close.

For the same reason the CNN is not on the frontier at all. At the s5 learned arm's 660,481 inferences per decision it would need 2,723 s per decision on one thread, 298 s using all 12, and would complete 0.12 games per hour against the student arm's 170.7 — 1,388x slower for at most the 0.008 of held-out Pearson the student gives up.

Model bytes, for the record: CNN 12,027,890 (fnv1a=0x187dcaafbf6479bd), LeafNet 2,289,654 (fnv1a=0x051ae690acf7a212).

10. Verdict

FieldValue
Validityvalid
Outcome, preregistered predictionfail — the prediction is refuted
Outcome, learned leaf at 5 stratapass (+39,105, 95% lower +1,138, 37–0–27)
Outcome, learned leaf at 7 stratainconclusive (+17,281, 95% lower −55,892; no supporting flow-rate movement)
Evidence tierdevelopment — 64 paired whole games per arm on reusable development seeds; not fresh confirmation, not a qualification claim

Validity rests on things that were checked rather than assumed: both reference arms reproduce finding-05's published cohort to every digit; --parity at w = 0 matches the frozen reference on 50 of 50 compared moves; both exported models pass a stated-tolerance parity gate against a reference proved bit-repeatable; 0 score-identity violations in 26,934 decisions; 0 censored games in 256; the seven-stratum arms ran at --max-work 16000000 and their 4,956,614 work per move confirms a completed depth 4; and tuning used a disjoint leased cohort.

Conclusion required by the preregistration: the hypothesis that chance-node bias caps what leaf-injected foresight can contribute is wrong. It caps extra lookahead — finding-05 measured that, and this document reproduces the underlying arm exactly — but a learned leaf is not extra lookahead. Extra plies are processed through the chance expectation, so a biased expectation corrupts them; a leaf value is terminal, so it inherits the bias of the path that reached it but does not compound it. The measured relationship is substitution, not amplification.

What this changes for the research program

  • Do not spend the next experiment on a bigger or better survival model. The binding constraint is arity, not capacity: 615,090 leaves per decision. A model 5x more accurate than LeafNet, if it costs 5x more, is unplayable, and the 0.008 Pearson between LeafNet and a 5x-larger CNN says the accuracy is not there to be had anyway.
  • The learned-leaf and exact-chance axes should not both be bought. The cheapest strong configuration on this evidence is the frozen leaf with seven strata; adding the learned leaf to it costs 2.11x for a gain that does not clear its bound.
  • The occupancy result is the more actionable one. Every learned arm here moved the board away from the 19–20 cell equilibrium. A leaf that predicts remaining lifetime accurately still does not steer the policy to the operating point where lifetime becomes cheap, because remaining lifetime under the current policy is not the same target as remaining lifetime under a policy that holds flow balance. Targeting occupancy or flow directly — the quantity finding-06 identified — is a different and untested objective.
  • This is a positive result for the state-only, sibling-blind design. status.md §4 records sibling extrapolation as the repeated failure mode of learned public-state values: the model learns the outcome of the action that was played, then deployment asks it to choose among actions it never observed equally well. This evaluator never sees an action identity at all — the same function scores every legal successor inside the audited chance-averaging search — and it cleared a paired 64-game lower bound. That is a design worth keeping even though its magnitude is modest.

11. Limitations

  1. 64 paired games per arm. Score sd is 51–67% of the mean, so a 64-game mean carries roughly ±19,000 to ±35,000 at one standard error. d5's lower bound of +1,138 clears zero by very little; this is a result that wants replication on a fresh cohort before it is leaned on.
  2. The difference-in-differences interval is wide (point −21,824, lower bound −105,254). The data refute the preregistered positive interaction at the stated criterion. They do not establish that the true interaction is negative — a small positive interaction is still inside the interval. The claim made here is the refutation, not its mirror image.
  3. The evaluation cohort is previously read development data. It is finding-05's confirmation cohort, chosen deliberately so these arms are directly comparable to the published d4s5 and d4s7 figures. It is now doubly read and cannot serve as fresh confirmation for anything.
  4. The deployed model is not the model the brief specified, for the reason measured in §2. The CNN is exported and gated but never played a move. The student's foresight is close (0.9815 agreement, 0.008 Pearson behind) but it is not identical, and a result about LeafNet is not literally a result about the CNN.
  5. w, scale and the head were tuned only at five strata, on 32 games whose bounds all include zero. The direction of that bias is worth stating: it optimises the blend where the prediction said the leaf should help least, so it is conservative with respect to the prediction and cannot have manufactured the refutation. A seven-stratum tuning confirmation was preregistered as TUNE-B and was not run — the compute went to the 2x2 instead. If a different w is optimal at seven strata, d7 here is an underestimate.
  6. No fixed-time comparison and no timing-grade measurement. Every arm ran on a machine shared with other jobs at load averages of 11–19, using at most 12 threads. docs/benchmarks.md requires exclusive resources for a performance claim; none is made. Node, leaf and model-evaluation counts are exact and machine-independent; the seconds are not.
  7. The 5-strata and 7-strata arms are not equal-compute comparisons. The frontier table in §9 reports the cost so the reader can do the trade themselves, but no equal-compute variant of the learned leaf (e.g. shallower search plus learned leaf) was run.
  8. Mean 415,779 is far below the 1,050,000 the frozen protocol requires before a candidate may be frozen. Three games of 256 exceeded 1,000,000 points; that is a tail of one 64-game arm, not a qualification. No protected or final seed was opened, and none is justified by this result.
  9. This is the repository's simulator, including the two rise-boundary scoring discrepancies in audit-01. Zero board clears occurred in 26,934 decisions across all four arms, so audit-01 H2's fifth-drop bonus inflates nothing here.
  10. The oneDNN defect in gpu-03 was found here, not audited generally. Other measurements in this repository that compared against a CPU PyTorch convolution may be affected; that has not been checked.
  11. A model contribution record under research/contributions/ is owed and was not written, because this work was scoped to create files only under approaches/lifetime-objective/learned-leaf/ and docs/exploratory/ while another contributor held research/. The coordinator should add one (level L3 for the export path, the affordability measurement, LeafNet, the learned-leaf search, the preregistered experiment and this result, plus the gpu-03 host defect).

12. Reproduce

# build (clang++ explicitly; the Makefile's CXX ?= clang++ loses to make's
# builtin CXX=g++, which trips a false -Werror=array-bounds in
# src/core/native/public-behavior.hpp)
./approaches/lifetime-objective/learned-leaf/build.sh

# 0. feasibility: how many leaves does a depth-4 decision actually have?
./build/lifetime-leaf/leaf-probe --seed 0xa5240000 --moves 30 --chance-samples 5 --max-work 3200000
./build/lifetime-leaf/leaf-probe --seed 0xa5240000 --moves 30 --chance-samples 7 --max-work 16000000

# 1. export the CNN and gate it (oneDNN off; reference proved repeatable)
V=.venv-rocm/bin/python
OPENBLAS_NUM_THREADS=1 $V approaches/lifetime-objective/learned-leaf/export_net.py \
    --checkpoint runs/RUN-A51D-net/survival-c128-shuffled.pt \
    --out runs/RUN-A52-LEAF/model/survival-c128-shuffled.d7net
./build/lifetime-leaf/net-check --model runs/RUN-A52-LEAF/model/survival-c128-shuffled.d7net \
    --states runs/RUN-A51D-corpus/mix-d3.states --count 4096 \
    --out runs/RUN-A52-LEAF/parity/cpp-4096.bin --bench 400 --threads 12
OPENBLAS_NUM_THREADS=1 $V approaches/lifetime-objective/learned-leaf/parity_net.py \
    --checkpoint runs/RUN-A51D-net/survival-c128-shuffled.pt \
    --states runs/RUN-A51D-corpus/mix-d3.states \
    --cpp runs/RUN-A52-LEAF/parity/cpp-4096.bin --count 4096 --device cpu \
    --torch-threads 1 --determinism-trials 2 \
    --json runs/RUN-A52-LEAF/parity/parity-cnn.json

# 2. train, export and gate the leaf-affordable student
source approaches/lifetime-objective/gpu/activate.sh
python approaches/lifetime-objective/learned-leaf/train_leaf.py \
    --states runs/RUN-A51D-corpus/all.states \
    --out runs/RUN-A52-LEAF/model/leafnet-h64 --epochs 10 --batch 8192
OPENBLAS_NUM_THREADS=1 $V approaches/lifetime-objective/learned-leaf/export_leaf.py \
    --checkpoint runs/RUN-A52-LEAF/model/leafnet-h64.pt \
    --out runs/RUN-A52-LEAF/model/leafnet-h64.d7leaf
./build/lifetime-leaf/leaf-check --model runs/RUN-A52-LEAF/model/leafnet-h64.d7leaf \
    --states runs/RUN-A51D-corpus/mix-d3.states --count 4096 \
    --out runs/RUN-A52-LEAF/parity/leaf-cpp-4096.bin --bench 400000 --threads 1
OPENBLAS_NUM_THREADS=1 $V approaches/lifetime-objective/learned-leaf/parity_leaf.py \
    --checkpoint runs/RUN-A52-LEAF/model/leafnet-h64.pt \
    --states runs/RUN-A51D-corpus/mix-d3.states \
    --cpp runs/RUN-A52-LEAF/parity/leaf-cpp-4096.bin \
    --teacher-cpp runs/RUN-A52-LEAF/parity/cpp-4096.bin --count 4096 \
    --json runs/RUN-A52-LEAF/parity/parity-leaf.json

# 3. CHECK gate and leaf-scale diagnostic
./build/lifetime-leaf/search --parity --seed-start 0xa5240100 --parity-games 2 --parity-moves 25
./build/lifetime-leaf/search --model runs/RUN-A52-LEAF/model/leafnet-h64.d7leaf \
    --states runs/RUN-A51D-corpus/mix-d3.states --leaf-stats 20000 --leaf-value lifetime

# 4. the cohorts (reference arms + tuning, then the two learned arms)
THREADS=12 ./approaches/lifetime-objective/learned-leaf/run-stage1.sh
THREADS=12 W=0.50 SCALE=3400 KIND=lifetime \
    ./approaches/lifetime-objective/learned-leaf/run-stage2.sh

# 5. the tables
OPENBLAS_NUM_THREADS=1 $V approaches/lifetime-objective/learned-leaf/analyze.py \
    --label s5ref=runs/RUN-A52-LEAF/eval/s5-w000.json \
    --label s5learned=runs/RUN-A52-LEAF/eval/s5-learned.json \
    --label s7ref=runs/RUN-A52-LEAF/eval/s7-w000.json \
    --label s7learned=runs/RUN-A52-LEAF/eval/s7-learned.json \
    --pair s5ref:s5learned --pair s7ref:s7learned \
    --pair s5ref:s7ref --pair s5learned:s7learned \
    --did s5ref:s5learned:s7ref:s7learned \
    --json runs/RUN-A52-LEAF/eval/twobytwo.json

Seed lease

SEEDLEASE-A52-LEAF = 0xa52400000xa5247fff. Opened: 0xa52401000xa5240101 (parity probe), 0xa52402000xa5240207 (pilot), 0xa52410000xa524101f (tuning). 0xa52420000xa524201f was reserved for the seven-stratum tuning confirmation and was not opened. The binary refuses to start outside the lease except on the declared fixed evaluation cohort 0xa51d10000xa51d103f, which is finding-05's already-read confirmation cohort and was chosen precisely so these arms are comparable to it.

Environment

AMD clang 23.0.0git, -O3 -std=c++20 -pthread -Wall -Wextra -march=native. AMD Ryzen AI MAX+ 395 (Zen 5), 16 physical cores / 32 logical, 125 GiB unified memory, Radeon 8060S (gfx1151); torch 2.13.0+rocm7.1 for training and the parity references. Frozen source hashes are recorded at build time in build/lifetime-leaf/reference-sources.sha256, and the build refuses to proceed if the generated depth-4 reference copy differs from the original by more than its single entry-point line. Every cohort shared the machine with other jobs at load averages of roughly 11–19 and used at most 12 threads; no timing-grade claim is made.

For a walkthrough with board animations, start at how the game works and the concepts primer; every term is defined in the glossary.