/* #pprog_p8v2_gen5_report_20260817 @pprog_p8v2_gen5_goal_20260815 @variant_protocol @f-p8 @f-p8-forward @f-p8-decay @pp_wordsv2 @hutter_publication_handoff GENERATION 5 IS BUILT AND RUN The picks were carried in the goal block, so this waited on nothing. What landed: f is split, the six retired axis-A ideas are restated as decay alternatives on the cap-8 delivery, all 24 runs are done across e64/e1k/e10k, and the three pattern-visualisation specs are written as a document rather than built -- MJC: don't implement any of the viz, specify it, ../hutter will handle that work. Data: tests/pprog/gen5.tsv (27 rows), tests/pprog/gen5-pos/ (24 dumps), models retained under tests/pprog/models/p8v2/enwik9/, axes.json regenerated at generation 5 (8 axes, 28 alternatives), gen5.html rendered from gen5-pos by the existing gen1-viz.py, specs in tests/pprog/p8v2-pattern-viz-specs.md. Green: acceptance-p8v2 at P8V2_GEN=5 including the replay conformance gate, acceptance-p8v2-axes, and tests/run-all at 70/70. ## WHAT LANDED THE SPLIT. #f-p8-forward (delivery, digit 1 = cap at 8 both directions) and #f-p8-decay (decay, digit 1 = constant fall-off 1) are axes G and H, at model header bytes 42 and 43 -- choice B as answered. The digits are written ONLY when a variant names the split, so every earlier variant's axis string is still six characters and its spec, generated C, binary and model file are unchanged. That is not a claim: v024 and v025 reproduce all six of their generation-4 rows BYTE-IDENTICALLY, settled_ok, mean_sweeps and settle_apps alike. THE SIX RESTATED, as #f-p8-decay-assign / -const2 / -renorm / -deficit / -period / -indegree, digits 2..7, run as #wordsv2-v026..-v031 off v024 with #wordsv2-v025 as the B2 ground truth column. ## THE RUNS Unrecorded positions settling back to their true byte (recorded positions are clamped and correct by construction; unrecorded counts are 59 / 833 / 5349), and mean time steps to convergence: alternative e64 e1k e10k mean_sweeps e64/e1k/e10k H1 fall-off 1 (v024) 14/59 220/833 1288/5349 18.00 30.00 24.14 H2 assignment (v026) 59/59 775/833 5172/5349 41.00 27.88 14.68 H3 fall-off 2 (v027) 10/59 167/833 1133/5349 64.00 125.00 124.95 H4 renormalise (v028) 0/59 82/833 1248/5349 64.00 125.00 126.42 H5 deficit (v029) 13/59 174/833 1064/5349 27.00 101.00 122.08 H6 period (v030) 13/59 164/833 987/5349 1.00 13.50 8.43 H7 in-degree (v031) 6/59 135/833 972/5349 15.00 125.00 126.49 B2 ground truth (v025) 1/59 151/833 1369/5349 64.00 71.62 94.97 THE FINDING, and it is about the MEASUREMENT rather than about any alternative. H2, assignment, scores 59/59, 775/833 and 5172/5349 -- far above everything else, including the ground truth. It is not better. Generation 1's #wordsv2-v001 is the same rule at a delivery of 255 and it scored 64, 942 and 9828 in raw settled_ok against H2's 64, 942 and 9823 today: FOUR GENERATIONS APART AND A DELIVERY OF 255 AGAINST 8, THE SCORE IS THE SAME TO WITHIN FIVE POSITIONS OUT OF 5349, the residue being entropy-stream drift. Two things follow. First, it is a direct confirmation of generation 3's principle from the other side: a uniform delivery cannot reorder an ES either, so capping at 8 cannot move an argmax that assignment then reads out. Second, and this is the one that matters, SETTLED_OK IS PARTLY CIRCULAR. Assignment's readout is the argmax of the single strongest application, which is very nearly the causal predictor that omega used to DECIDE which bytes to record; the unrecorded positions are by construction the ones that predictor got right. A rule whose readout coincides with the sparsifier's predictor scores near-perfectly on this metric without settling doing any work at all. That is why A1 was pruned in generation 1 despite the best score on the board, and the prune was right; what generation 5 adds is the reason, and a warning that every settled_ok in generations 1..5 is a measure of AGREEMENT WITH THE CAUSAL PASS and not of recovery. THE MISSING CORNER IS FILLED, and generation 4's inference survives being measured. At e1k the three runs are (255, fall-off 2) = 165 from generation 4, (8, 2) = 167 here, and (8, 1) = 220 here. The fall-off carries essentially the whole gain and the strength carries two positions, which is what the generation-4 grid predicted from replay alone; it is now three real runs rather than an argument. At e10k the same corner says something the grid did not: (255, 2) = 1177, (8, 2) = 1133, (8, 1) = 1288, so at the larger sample the cap costs 44 positions when the fall-off is wrong and gains 111 when it is right. The pair really was a pair; it is now two axes and the interaction is visible. THE SUPPORT-DRIVEN RATES STILL DO NOT BEAT A CONSTANT. H5, H6 and H7 all sit below H1 at every sample (174, 164, 135 against 220 at e1k; 1064, 987, 972 against 1288 at e10k). The a5 direction has now been tried three ways across two generations on two deliveries and has not once won on this metric. H6 converges far faster than anything else (1.00, 13.50, 8.43 time steps) and spends the least (settle_apps 1,684,008 against the baseline's 1,834,607 at e10k) while recovering the least of the three, which is the rate idea doing exactly what it says and paying for it. H4, THE CORRECTED RENORMALISATION, behaves as its block predicted it would and the prediction is worth more than the score. It recovers 0 at e64 and 82 at e1k -- the worst on the board -- and then 1248 at e10k, within 40 of the baseline. That is what a rule that CANNOT REORDER AN ES looks like: subtracting one constant from every entry divides every count by the same factor, leaves the softmax distribution exactly unchanged, and can only act through the 0 floor, which at small samples annihilates and at large samples barely bites. The alternative is doing its job as an instrument even though it loses: it separates "how much evidence does this position claim" from "which byte does it favour", and only the second is what settled_ok scores. B2 CUTS BOTH WAYS AGAIN, unchanged from generation 4: the stated 8 beats the true learned weights at e64 and e1k (14 and 220 against 1 and 151) and the truth wins at e10k (1369 against 1288). Every constant-decay alternative here is below the truth at e10k. ## TWO IMPLEMENTATION FINDINGS, both caught by the conformance gate THE FOLD THAT TREATED ZERO AS ABSENT. H4 needs the combined support of the applications that fired, which is an LSA addition of their supports. The generated C wrote it as t ? lsa_add(t, s) : s, which reads a support of 0 as "nothing has contributed yet" -- but an LSA 0 means ONE OBSERVATION and is a real support, so a first contributor with support 0 was silently dropped and the fold's entropy draws went out of step with the reference. The NL now says to track the first contributor with a separate flag and never by testing whether t is zero. Found only because p8v2-replay.py disagreed. THE PRE-MESSAGE GATE WAS BACKED OUT. The goal block promised that H6 would decide each pattern's period BEFORE computing its vector, so settle_apps would finally measure the energy a rate is supposed to save (A5 computed the vectors and then skipped them, which is why generation 3 recorded that it bought nothing). Moving the decision ahead of the messages requires restructuring the position loop, and the generated settling then stopped honouring the frozen shell's clamping: all 64 positions at e64 diverged from the reference, including recorded positions that must never be updated at all. It was reverted. H6 is therefore A5's schedule on the cap-8 delivery -- a real restatement, and the delivery is the thing being varied -- but the vectors are still computed and settle_apps still measures work done rather than work saved. #f-p8-decay-period says so in place, and realising the saving is an open item AGAINST THE FROZEN SHELL, not against that alternative. ## THE VISUALISATION Three specs, not one, per MJC's answer on choice A ("write two more specs that do not use any of the same ideas from this one, and then build all three"), in tests/pprog/p8v2-pattern-viz-specs.md. Each is built on a different organizing principle so that the three disagree about what a pattern is: spec A the inventory in data space (the 16x16 byte grid, ink for support, selection to the firing footprint), spec B the topology (transition arcs on one baseline, support encoded as arc HEIGHT alone so the page has exactly one visual variable, hubs and cycles legible), spec C the change across sample sizes (a slopegraph of what the model learned at e64 / e1k / e10k, whose subject is the argmax flips and the falling share of the argmax). None is implemented here. The file names the model paths, the dumps, the TSV, axes.json and the query commands, so ../hutter can build without asking. T carries only the fact that they exist -- it is a channel for the state of work in flight, not for specs. ## What this generation did not do No forward-axis alternative was built: pass-through and attenuate are named in #f-p8-forward as the points the axis exists for, and generation 5 moves the decay axis only. No new ladder sizes. No change to generations 1..4 artifacts. No B2 crossed with the decay alternatives -- v025 is the ground-truth column, and a cross product is what #variant_protocol exists to avoid. Written 2026-08-17. */