Skip to content

[GOLD-RING] compiler: compound assignment and hoisted nested fn - #2217

Merged
gHashTag merged 640 commits into
masterfrom
gold-ring/0001-0002-compound-assign-nested-fn
Aug 19, 2026
Merged

[GOLD-RING] compiler: compound assignment and hoisted nested fn#2217
gHashTag merged 640 commits into
masterfrom
gold-ring/0001-0002-compound-assign-nested-fn

Conversation

@gHashTag

@gHashTag gHashTag commented Aug 19, 2026

Copy link
Copy Markdown
Owner

Two grammar changes that make the L6 numeric SSOT (gf16.t27) parseable and sealable by the repository's own compiler for the first time*= was never in the bootstrap grammar (git log -S is empty) and the SSOT's Taylor loop uses it.

Per FROZEN.md this touches bootstrap/src/compiler.rs under FROZEN_HASH, so it ships as a branch for Architect approval — verified in a detached copy, never applied outside this branch.

Change 1 — compound assignment -= *= /= %=: four lexer cases beside the existing +=, a five-way parser match, three codegen sites writing the operator through (Verilog desugars to lhs <= lhs <op> rhs exactly as += already did).

Change 2 — nested fn, hoisted from parse_fn_body, with the capture check at the only scope hoisting crosses: the nested fn must not reach the enclosing fn's params/prior locals; any other free name resolves identically before and after the move. Negative repro fails with captures enclosing locals ["scale"].

Evidence (repros in bootstrap/tests/goldring/): gf16 parses completely, all four backends emit real hashes; tf3 fixed by change 1 alone; unpatched control still fails at gf16:824; corpus regression sweep old-vs-new with byte-identical hashes required — 0 regressions in the first 679/1,079, final number follows as a comment. Blast radius is deliberately exactly the SSOT family; the 34 remaining parse failures are three dialects (docs/reports/gold-ring/DIALECTS.md) whose canonicalisation this patch does not pre-empt.

🤖 Generated with Claude Code

Refs #1959

claude and others added 30 commits August 15, 2026 12:41
…E the run (Refs #1959)

Nine waves improved one answer on one dataset and hit its ceiling. T354 asserted
the limit is "the capacity of six-input truth tables on UNSW-NB15" -- but that
sentence contains a dataset, and nothing has ever varied it.

THE TEST: run the same architecture family on three tasks and measure the GAP
between a dense reference and the sparse truth-table network on each. A constant
gap is a property of the architecture; a moving gap is a property of the task.
Absolute ceilings differ by task and tell us nothing alone; the gap is the
invariant, and it has never been computed once.

FORECAST REGISTERED BEFORE THE RUN: (1) the gap is LARGER on MNIST and Fashion
than on UNSW, because UNSW 593 binary features are mostly irrelevant (T306) so a
6-of-593 draw loses little, while MNIST 784 pixels are informative almost
everywhere. Predicted gaps: UNSW 5-7 pp, MNIST 10-18, Fashion 8-15. (2) Therefore
T354 phrasing is too strong and needs narrowing to "on tasks whose features are
individually weak". If the gap is CONSTANT within 2 pp, T354 stands as written.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…he architecture's (Refs #1959)

T354 IS REFUTED. It asserted the limit is "the capacity of six-input truth tables
on UNSW-NB15" -- a sentence containing a dataset that had never been varied. Same
architecture, trainer, quantiser, normalisation and balancing; only the task
changes:

  UNSW-NB15   base 55.06  dense 89.67  sparse 82.97   penalty  +6.70
  MNIST-bin   base 51.39  dense 96.01  sparse 81.16   penalty +14.85
  Fashion-bin base 50.00  dense 91.52  sparse 88.03   penalty  +3.48

Spread 11.37 pp. The cost of collapsing a layer into six-input truth tables is
NOT a constant of the architecture; it depends on how much a task's decision
needs many features at once. "Six-input truth tables have a ceiling" is true;
"the ceiling is 84%" was a fact about UNSW wearing an architecture's clothes
(T355).

Two of three forecast bands landed and the miss is the interesting one: UNSW 5-7
(6.70 correct), MNIST 10-18 (14.85 correct), Fashion 8-15 (3.48 WRONG). The
reasoning -- informative pixels punish a 6-of-784 draw -- holds for MNIST and
INVERTS for Fashion, whose binarised silhouettes are decided by a few coarse
pixels. Feature count and modality do not predict the penalty; evidence
concentration does (T355a).

WE HAVE BEEN BENCHMARKING ON OUR SECOND-WORST TASK FOR NINE WAVES. Sparse
accuracy is 88.03% on Fashion against 82.97% on UNSW, at half the penalty. We
followed the field's benchmark triplet without asking whether it suits this
datapath. It does not (T355b).

THE FIRST LAYER'S NARROW VIEW IS NOT THE BOTTLENECK. Registered: fan-in 12 buys
1.5-3.0 pp, and under 1 pp refutes the "six-of-593" framing. Measured +0.83 pp
for 832 extra LUT -- a thousand LUT per point against width's 393. Both bad,
fan-in 2.5x worse. The pre-registered consequence applies: three waves of
reasoning that started from that image were about the wrong thing (T356). Note
also fan-in 10 scoring below fan-in 8 at three seeds -- an intervention below our
own noise floor is not a lever whatever its cost (T356a).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
838: if a conclusion names a dataset, the dataset is an untested variable --
T354 said "on UNSW-NB15" and the second half was load-bearing; varying it moved
the penalty from +3.48 to +14.85 pp. 839: measure the GAP, not the ceiling --
dense-minus-sparse is the invariant that answers "architecture or task?" and had
never been computed once. 840: nine waves of benchmarking on an unexamined
choice; a benchmark inherited from a neighbouring literature is a hypothesis
about your system, not a given. 841: an effect below your noise floor is not a
lever whatever it costs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… the run (Refs #1959)

W758 explained an 11-point spread in the sparse penalty with "how concentrated a
task evidence is". That is a WORD, and three points would fit any word one cares
to propose. This file uses ELEVEN tasks: the three originals plus eight MNIST
digit-pairs sharing input dimension, trainer, seeds and subsample, so nothing in
the setup is confounded with the quantity under test.

THE MEASURE, defined BEFORE any correlation: C6 = (sum of the 6 largest
per-feature mutual informations) / (sum of all) -- what fraction of the total
single-feature evidence a SIX-input neuron could see if it chose perfectly. Six
because that is the fan-in the six-bit rule fixes. No free parameters, nothing to
tune after the fact.

FORECAST REGISTERED BEFORE THE RUN: (1) C6 correlates NEGATIVELY with the
penalty, Pearson r <= -0.7 over 11 tasks; (2) the three originals order
Fashion > UNSW > MNIST by C6, mirroring penalties 3.48 < 6.70 < 14.85; (3) the
relation is monotone but not linear. If r is weaker than -0.5, concentration is
not the mechanism and W758 explanation must be withdrawn to a bare observation.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…eleven tasks (Refs #1959)

W758 explained an 11-point spread in the sparse penalty with "how concentrated a
task's evidence is". W759 turned that word into a measure defined BEFORE any
correlation -- C6 = (sum of the 6 largest per-feature mutual informations) / (sum
of all) -- and tested it on ELEVEN tasks: the three originals plus eight MNIST
digit-pairs sharing dimension, trainer, seeds and subsample.

r(C6, penalty) = +0.128, t = +0.39 at n = 11. Not merely weaker than the
registered -0.7 threshold: the WRONG SIGN and indistinguishable from zero. The
pre-registered consequence applies verbatim -- W758's explanation is withdrawn to
a bare observation that the penalty varies between +0.28 and +14.85 pp and we do
not know why (T358).

Forecast (2) was refuted before the correlation was computed: I predicted
Fashion > UNSW > MNIST by C6 and measured UNSW 0.146 > MNIST 0.081 > Fashion
0.042 -- Fashion has the LOWEST concentration and the LOWEST penalty, the exact
inverse of the story. The mechanism was contradicted by its own three founding
points (T358a). Nothing else measured predicts it either: dense accuracy
r=-0.398, headroom r=+0.398, neither significant (T358b).

THE OUTLIER THE DIGIT PAIRS EXPOSE: every MNIST digit pair costs +0.28 to +5.66,
while MNIST-bin -- the same pixels, a different labelling -- costs +14.85. The
architecture is not bad at "MNIST"; it is bad at that particular binary partition
of it. A task's identity is its labelling, not its input distribution (T359).

The penalty ranges over a factor of FIFTY across eleven tasks and the project has
no predictor for it. Any claim that this datapath suits task X must be MEASURED
on X, not argued from X's properties -- a weaker statement than W758 made, and
the one the data supports (T359a).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…1959)

THE SAME SILICON, FIVE AND A HALF POINTS HIGHER. W757s Pareto front rebuilt on
Fashion-bin with identical architectures and therefore identical area: H16 L2 at
123 LUT gives 86.91% against UNSWs 81.37%, and the whole curve sits 5.1-5.9
points higher. The front is flat on Fashion too -- 6.5x the area for 1.38 pp --
so T352a shape conclusion survives the change of task while the level does not.
Best single-die artefact this programme has: 123 LUT at 86.91%, obtained by
changing the benchmark rather than anything in the datapath (T360).

It does NOT license claiming the datapath "suits" Fashion -- T359a withdrew that
kind of inference. The honest statement is "measured higher on Fashion, cause
unknown" (T360a).

Lessons 842-845: turn explanatory words into measures and test on more points
than inspired them; define the measure and its refutation threshold before
computing the correlation; a tasks identity is its LABELLING not its inputs;
changing the benchmark moved more than nine waves of tuning.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…run (Refs #1959)

W759 tested one pre-registered predictor on eleven tasks and it failed at
r=+0.128. The obvious next move -- try more predictors -- is exactly how a
programme fools itself: ten candidates on eleven points finds one by chance.

THE DESIGN THAT PREVENTS THAT: sixty tasks, all LABELLINGS OF ONE DATASET (45
digit pairs, 10 one-vs-rest, 5 groupings), so the input distribution is identical
across all sixty and only the decision changes -- T359s observation turned into
the experiments design. The sixty split into DISCOVERY (30) and CONFIRMATION (30)
by a fixed seed before anything is measured. Eight candidates are ranked on
DISCOVERY only; the single best is tested ONCE on CONFIRMATION, and that number
is the result.

FORECAST REGISTERED BEFORE THE RUN: at least one candidate reaches |r| >= 0.5 on
DISCOVERY -- with eight candidates on thirty points that is nearly certain by
chance. Predicted: the winner does NOT replicate, landing |r| < 0.3 on
CONFIRMATION, and the honest conclusion stays "no predictor known". I expect
`head` to win discovery and shrink on confirmation. If a candidate holds
|r| >= 0.5 on BOTH halves, the project has its first real rule for choosing tasks.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…asurements (Refs #1959)

The file kept the right posture -- only reproducible numbers, omit doubtful rows
-- and was six days stale, predating everything measured since W746. Now records:
the single-die artefact (123 LUT at 81.37% UNSW / 86.91% Fashion, 99.46 MHz,
1 cycle, output stage included); the three-die trained network (232 LUT, zero
DSP, 100/100 agreement on real rows); the measured cost rules (six bits per
neuron, ternary inputs take fan-in 3, area is not a lever, the golden resolve
costs 8 DSP or 2750 LUT); and both openXC7 primitive defects with their flags.

Section 4.5 states what is NOT claimed: no LUT*ns comparison (the fields Fmax is
not in our record and fetching failed), no suitability claim for any task (no
predictor survived confirmation), and no accuracy from before W749 (uncontrolled
pre-activation scale).

Also records the correction that every LUT figure before W752 omitted the
decision neuron.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…umes (Refs #1959)

The first run died at 51 of 60 on the alarm timeout and lost ALL fifty-one
results, because json.dump was at the end. A long sweep that only persists on
success persists nothing. Now writes after every task and skips tasks already on
disk, so a restart resumes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ims (Refs #1959)

Section 4 said the single-cell figure could not be compared to network-level
published figures. That gap is now closed on one benchmark and the answer is not
flattering: 123 LUT at 81.37% against TreeLUT 89 LUT at 92.0% -- 1.38x the area
at 10.6 points less accuracy. Our area is competitive; our accuracy is not.

THE GOLDEN ALPHABET MEASURED AGAINST ITS OWN CLAIM. The line is named for phi.
Alphabet size is worth +0.735 pp, shape +0.149 pp significant on 1 of 3 tasks,
against inter-layer normalisation at +29.15 pp -- and the multiplier phi removes
from weight application returns in the pair resolve, costing 8 DSP48E1 or ~2750
LUT. A negative result about our own headline idea, stated as one. The algebra
stands; the practical advantage does not.

FOUR NEW NON-CLAIMS: no claim the golden alphabet is preferable in hardware; no
LUT*ns comparison with any published system; no claim this datapath "suits" any
task (no predictor survived a confirmation split); no accuracy from before W749
is comparable.

Also records both openXC7 primitive defects, and the three-die trained network
(232 LUT, zero DSP, 100/100 agreement on real rows).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Added: a trained ternary network across three dice (232 LUT, zero DSP, 100/100
agreement on real rows); the trainer-to-silicon export path that made it possible;
a known-bad-primitive guard in t27c yostat; a 33-bit data register lifting the
31-bit payload limit; the openXC7 SRL16E defect report.

Fixed: openXC7 emits a wrong bitstream for SRL16E while the netlist is correct
(0/6 rows against 24/24 with -nosrl, source byte-identical); and every LUT figure
before W752 omitted the decision neuron.

Changed -- claims narrowed: the golden alphabet measures +0.735 pp against
normalisation +29.15 pp and its pair resolve reintroduces a multiplier; no
accuracy before W749 is comparable; no suitability claim for any task; no LUT*ns
comparison.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
)

Adds a compact, measured FPGA section high in the README: the three-die trained
network (232 LUT, 0 DSP, 100/100 agreement), the best single-die artefact (123
LUT at 81.37% UNSW / 86.91% Fashion) beside the field reference (TreeLUT 89 LUT
at 92.0%), and the measured six-bit cost rule.

States plainly that our area is competitive and our accuracy is not, and that the
golden alphabet -- the line is named for phi -- measures +0.735 pp against
normalisation at +29.15 pp, with the multiplier returning in the pair resolve.
The algebra stands; the practical advantage does not.

Also surfaces both openXC7 primitive defects on the front page, since they
produce a wrong bitstream from a correct netlist and pass the acceptance
criterion.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
#1959, Refs #2173)

TOTAL MUTUAL INFORMATION PREDICTS THE SPARSE PENALTY. W759 tested one
pre-registered predictor on eleven tasks and it failed. W760/W761 ran labellings
of ONE dataset -- MNIST digit pairs, one-vs-rest and groupings, so the input
distribution is identical and only the decision changes -- split into discovery
and confirmation halves by a fixed seed before anything was measured.

mi_tot scored -0.761 on discovery and -0.881 on confirmation. The registered
forecast predicted the discovery winner would NOT replicate (|r| < 0.3); it is
refuted, and for once in our favour. The more total single-feature evidence a
labelling carries, the LESS a six-of-N draw costs (T361).

Why W759 saw nothing: c6 measures CONCENTRATION, mi_tot measures AMOUNT. The
quantity that matters is how much evidence exists, not how unevenly it is
distributed -- the opposite of the story W758 told (T361a).

Stated narrowly: this licenses prediction ACROSS LABELLINGS OF ONE DATASET, which
is what was measured. It does not yet license prediction across datasets (T361b).

THE SWEEP THAT LOST FIFTY-ONE RESULTS: the first census died at 51 of 60 on its
timeout and lost all of them, because json.dump ran only after the loop. A long
sweep that persists only on success persists nothing. Now writes after every task
and resumes (T362).

Also: filed the openXC7 SRL16E defect as t27#2173.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…s (Refs #1959)

T361b stated that mi_tot success across labellings of ONE dataset did not license
prediction across datasets. W759s eleven-task set spans three datasets and its
penalties were already measured; only the predictor needed computing.

Registered forecast: (1) raw mi_tot fails across datasets, |r| < 0.5; (2) the
normalised version does better; (3) dense travels better than either.

Measured: mi_tot raw r = -0.684, t = -2.82, SIGNIFICANT -- (1) refuted.
mi_tot/n_features r = -0.676, slightly WORSE -- (2) refuted, so the quantity that
matters is TOTAL evidence, not evidence per feature. dense r = -0.398, the
weakest and not significant -- (3) refuted hardest. One of three predictions
survived in direction and none in detail (T363).

MECHANISM, both scopes now measured: the more total single-feature evidence a
task carries, the less a narrow random view costs -- redundancy is what makes
sparse sampling survivable. Within one dataset r = -0.78/-0.88 over 45
labellings; across three datasets r = -0.684 over 11 tasks. T361b is relaxed
(T363a).

This is the programmes most useful positive result and it is not about
arithmetic: a task-selection rule computable in one pass, telling you before you
build anything what a six-input truth-table datapath will cost in accuracy.
MNIST-bin has the least evidence (3.14) and the worst penalty (+14.85); 0v1 has
the most (44.75) and the least (+0.28) (T363b).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…1959)

Dmitrii has asked "which format for ternary on FPGA" four times, which means the
answer is not where it is looked for. The format skill now opens with it:

  Weights: a TRUTH TABLE, not a format, at <=6 input bits per neuron. Where a
  table will not fit: {0,+-1,+-2,+-4,+-8}. Accumulator: int12-int16. phi does not
  belong in the datapath.

With the measurements behind each clause: 2.00 LUT/neuron at <=6 bits and no
arithmetic at all (dense 54,914 LUT -> 128 as tables, 429x, 3.6x Fmax); the
SIX-BIT RULE with the ternary-is-two-bits corollary that nearly shipped a
10,250-LUT design as an 800-LUT one; PoT with its real citations and the warning
that `pot9` is an internal tag; the phi table showing +0.735 pp against a
resolve costing 8 DSP or 2750 LUT; the intervention ranking that puts the
alphabet seventh; mi_tot as the task-selection rule; and the mandatory
-nodsp -nosrl flags.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… own headline (Refs #1959)

The full 60-labelling census put ntrain at r = +0.745/+0.730, almost matching the
winner -- a warning, not a finding, because the census mixes digit pairs (~10,800
rows, mean penalty +2.36) with one-vs-rest tasks (~54,000 rows, +3.42). Any
predictor correlated with task TYPE would replicate beautifully while measuring
nothing.

Restricted to the 45 digit pairs, where ntrain varies by 1.15x: mi_tot -0.810
(t=-9.07), mi_max -0.751, dense -0.734, ntrain -0.382. NTRAIN SIGN FLIPS -- that
inversion IS the confound, made visible -- and mi_tot is STRONGER inside the clean
group than across the mixed one, which is what a real predictor does (T364).

The replication discipline was necessary but not sufficient: a discovery/
confirmation split protects against fitting noise and not at all against a
confound present in both halves (T364a).

Final rule with both controls applied: mi_tot predicts the sparse penalty at
r = -0.81 within a homogeneous group of 45, -0.72 across a mixed 60, -0.68 across
three datasets, over penalties spanning +0.24 to +14.71 pp. The only predictor
this programme has that survived both a confirmation split and a confound check
(T364b).

Lessons 846-849.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ts (Refs #1959)

Dmitrii asked for a measured top of numbers for ternary weights from our
catalogues. Distinction stated first: the 83-format catalogue enumerates FLOAT
ENCODINGS (bit widths, exponent/mantissa), not weight VALUES, so the candidate
list is built from the projects own theorems and the quantisation literature.

Alphabet shape held fixed at NINE levels for every base -- A(b) = {0} u {+-b^k,
0<=k<=3} -- because T286 showed size is worth +0.844 pp and shape +0.085, and
confounding them is how a base wins for the wrong reason.

Candidates: 1.0 (degenerate control), 2.0 (dyadic/PoT, the incumbent), phi
(golden, our line, the only multiplier-free degree-2 scale), plastic (r^3=r+1),
psi4 (r^4=r+1), supergolden, tribonacci, sqrt2 (algebraic but NOT in the r^d=r+1
family), silver (1+sqrt2), 3.0 (TERNARY BASE -- never measured, an omission worth
naming), e (transcendental control), and linear spacing.

FORECAST REGISTERED BEFORE THE RUN: (1) all bases within 1.0 pp except 1.0 which
loses by 2-6; (2) area ordering 2.0 < 3.0 ~ lin << every irrational; (3) the top
is decided by AREA not accuracy and 2.0 wins. If any base beats 2.0 by more than
1.0 pp in accuracy, the shape effect is larger than three waves say and
T286/T317 need revisiting.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…Refs #1959)

Dmitrii asked for a measured top of numbers for ternary weights from our
catalogues. The question exposed a gap: the 83-format catalogue enumerates FLOAT
ENCODINGS -- bit widths, exponent/mantissa splits -- and contains no answer about
what VALUES a weight level should take. That catalogue cannot answer this
question and nobody had noticed.

Eleven bases, NINE LEVELS EACH (shape fixed so only the number varies), accuracy
on UNSW-NB15 with the corrected bench and area as a placed 64->8 layer:

  dyadic 2.0     89.62%    752 LUT
  linear           --      812
  ternary 3.0    89.76%   1417
  sqrt2          89.64%   1991
  plastic        89.66%   2709
  golden phi     90.01%   2726
  e                --     2856
  silver         89.80%   2971
  b=1.0 (={0,+-1}) 89.52%   --

THE WHOLE ACCURACY SPREAD ACROSS EVERY BASE IS 0.49 pp; the area spread is 3.95x.
phi is nominally first (+0.39 pp) and costs 1,974 extra LUT for it -- 5,062 LUT
per point. The top is decided by area and dyadic wins it, as forecast (T365).

The forecast's second half is refuted and is the more interesting half: b=1.0,
which collapses to {0,+-1}, was predicted to lose by 2-6 pp and loses by 0.49. A
three-level alphabet is within half a point of a nine-level golden one on this
bench (T365a).

BASE 3 HAD NEVER BEEN MEASURED, IN A TERNARY PROJECT: 89.76% at 1,417 LUT,
second-cheapest geometric base and better than dyadic on accuracy. The obvious
candidate was absent from every prior sweep, which is what happens when the
catalogue consulted is about float encodings (T365b).

Ordered by what a designer pays: dyadic -> linear -> base 3 -> everything
irrational. Accuracy does not order them. The number is an area decision and the
literature's answer -- powers of two -- is right (T365c).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…(Refs #1959)

W763 measured the base cost in a DENSE adder tree: 3.95x spread (dyadic 752,
base 3 1417, phi 2726, silver 2971), because that layer performs real arithmetic.
The TRUTH-TABLE layer performs none -- the neuron is enumerated on the host and
emitted as a case statement.

Registered forecast: every base costs 2.00 LUT/neuron within +-0.15, spread
collapses to 1.0x. REFUTED in the interesting direction: the spread collapses to
1.9x, and the ORDERING INVERTS. Base 3 costs 1.05 LUT/neuron, 46% LESS than
dyadic, and for a project whose premise is ternary that is the first measurement
in which the ternary base wins anything (T366).

Why it inverts: a table cost is set by how many input patterns disagree with the
most common output, since yosys folds the rest into the default arm. Fast-growing
bases (3, e, silver) push the sum past the threshold on most patterns so one
symbol dominates and the table compresses; slow-growing bases (phi, sqrt2,
plastic) leave the sum near zero, the symbols mix evenly, and nothing folds.
Cheapness in a table is table SKEW (T366a).

T365c scope corrected: "the number is an area decision" holds for adder-tree
datapaths (3.95x) and points the OTHER WAY in table datapaths (1.9x). Neither
statement is about accuracy, which varies 0.49 pp across every base (T366b).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… two trits (Refs #1959)

Dmitrii corrected the framing: every metric and top must be measured for the
TERNARY world. Everything measured so far is counted in LUT -- a BINARY primitive
of the substrate we happen to own, not of the target.

Recounted in trits: the alphabet sizes that pack with ZERO WASTE in ternary
storage are exactly the powers of three -- 3, 9, 27. The Nine-Rung Law puts the
ceiling at NINE, and nine is 3^2, EXACTLY TWO TRITS. The two sizes this programme
singled out by measurement -- the minimum useful alphabet (3) and the ceiling (9)
-- are both perfect in trits and both wasteful in bits, 9 levels burning 7 of 16
binary codes (T367, arithmetic not measurement).

EVERY AREA FIGURE IN THIS FILE IS IN THE WRONG UNITS FOR THE TARGET. LUT counts
measure a binary FPGA: correct for this substrate, wrong for a ternary one where
the natural unit is the trit-cell and a 6-input binary LUT has no counterpart.
T340, T352 and T366 are all substrate measurements and none has been restated in
ternary units, because no ternary substrate exists to measure on. Named rather
than papered over (T367a).

What the 0.49 pp result actually says: a THREE-LEVEL alphabet -- {0,+-1}, ONE
TRIT, the founding premise -- scores within 0.49 pp of a nine-level golden one
and costs 114 LUT against 123-128 in tables. Half the weight storage for half a
point; pooled over three tasks the size effect is +0.735 pp, so the honest range
is half to three-quarters of a point for one trit versus two. A strong position
for a ternary line, under-reported in W763 as "the interesting half of a
refutation" (T367b).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
)

T367 recounted alphabet packing in trits. Pushed further the reframing reaches
three more places, two of which restate measurements the programme already has.

RADIX ECONOMY (classical, Knuth TAOCP v2): E = b*log_b(N). At N=10^6, base 3
scores 37.73 against binarys 39.86 -- base 3 is the nearest integer to e and the
most economical integer radix, beating binary by 5.7%. Textbook, not ours, but it
is the substrate this line targets and no measurement in the file had been stated
against it (T368a).

THE SIX-BIT RULE IS THE THREE-TRIT RULE. T331 measured 2.00 LUT/neuron at <=6
input bits. A ternary input is 2 bits, so fan-in 3 is 6 bits is EXACTLY 3 TRITS,
and a natural three-trit table is 3^3 = 27 entries held in a binary LUT6 of 64 --
42% used. 58% of every LUT in the datapath is wasted by the SUBSTRATE, not the
design (T368b).

WEIGHT STORAGE: for the two sizes that matter, 3 and 9 levels, binary wastes 21%
and ternary wastes nothing. On the trained network that is 39,040 bits binary
against 19,520 trits = 30,938 bit-equivalents, 21% less unconditionally (T368c).

AN ARITHMETIC SLIP CAUGHT IN OUR OWN OUTPUT: the first printing carried a
hand-written summary reading "37%, 21%, 37%" while the computed column read
21%, 21%, 5%. The summary was a hardcoded string. A number typed beside a
computed number is not a check on it -- same class as reading a line count for a
quantity, sixth disguise (T368d).

Establishes that the founding choice is optimal IN ITS OWN UNITS. Establishes
nothing about accuracy or the 10.6-point gap. The ternary case is an efficiency
case and a real one; it is not an accuracy case and must never be presented as
one (T368e).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Saves Dmitriis standing correction to the format skill: measure in TRITS, not
LUT. Radix economy (base 3 optimal among integers, 5.7% over binary), alphabet
packing (powers of three waste nothing; the Nine-Rung ceiling is 9 = 3^2 = two
trits), the six-bit rule restated as the THREE-TRIT rule (3^3 = 27 entries in a
64-entry binary LUT, 42% used), the 21% storage tax, the inverted base ordering
in tables, and the plain answer that three levels IS a strong position -- one
trit, within 0.49 pp of nine golden levels, 114 LUT against 123-128.

With the boundary stated: all of it is an EFFICIENCY case and none of it is an
accuracy case; the 10.6-point gap to TreeLUT is untouched.

Lessons 850-853: measure in the targets units; say when a catalogue cannot answer
the question; the same variable can order two architectures oppositely; a number
typed beside a computed number is not a check on it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…hdrawn (Refs #1959)

THE THIRD TRIT BUYS NOTHING. T367 established 3, 9 and 27 as the zero-waste
ternary alphabet sizes; T288 put the ceiling at nine, but nine is where OUR
ladder stopped and 27 = 3^3 is the next perfect packing. Measured: UNSW 9->27
+0.15 pp (t=0.65, ns); Fashion 9->27 -0.13 pp (t=-2.03, ns, NEGATIVE). "Two trits
and no more" now holds as a measured statement in the targets own units (T369).

AND THE 3->9 STEP IS SMALLER THAN THIS FILE HAS BEEN CLAIMING. T317 put the size
effect at +0.735 pp pooled; here it is +0.10 (UNSW, ns) and +0.25 (Fashion,
significant). The honest range for one trit versus two is 0.1-0.75 pp and the low
end is not significant. The case for two trits is weaker than the file implied
(T369a).

"THE TERNARY TABLE WE DO NOT HAVE" WAS THE WRONG FRAMING. Dmitrii pushed back and
asked what t27 was built for. SOUL.md: "T27 is a spec-first architecture where
mathematical truth, not implementation, is the source of truth." The 27-entry
ternary table is not a thing this project lacks -- it is exactly the thing the
language exists to state. A .t27 spec names the object; the compiler emits what
the substrate can hold, and today that emission costs 58% waste. THE WASTE IS A
PROPERTY OF THE TARGET, NOT THE SPECIFICATION (T370).

That 58% is therefore not a defect to apologise for but the measured cost of
running a ternary specification on binary silicon -- the number that quantifies
what a ternary substrate would return. It belongs in the argument for the Tiny
Tapeout line, not in a list of shortcomings (T370a).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…1959)

A tri blog post on the ternary recount, bilingual as the existing post is.

Carries the picture (27 reachable entries in a 64-entry LUT6), the alphabet
packing table (powers of three waste nothing), the six-bit rule restated as the
three-trit rule, and the 27-level measurement that closes the ceiling at two
trits.

It also carries two things against us, at the same volume: the 3->9 step is
+0.10 (ns) / +0.25 pp on this bench against the +0.735 recorded elsewhere, so we
had been quoting the top of the range; and none of the ternary accounting touches
the 10.6-point accuracy gap to TreeLUT.

And the framing correction: the 27-entry table is not something we lack, it is
what a spec-first language exists to state -- SOUL.md, "mathematical truth, not
implementation, is the source of truth". The 58% is the measured cost of emitting
a ternary spec onto binary silicon, which is the number that says what a ternary
substrate would return.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ORE the run (Refs #1959)

The theorem file contains TWO numbers for one quantity: T317 records the
alphabet-size effect (3 -> 9 levels) at +0.735 pp pooled over three tasks, and
W765 measured the same step on the same architecture at +0.10 (UNSW, ns) and
+0.25 (Fashion). That is a defect regardless of which is right.

The only difference between the benches is the training budget: alphabet_fixed.py
runs 8 epochs, bases.py runs 30. Everything else matches.

HYPOTHESIS: a larger alphabet is a CRUTCH FOR AN UNDER-TRAINED NETWORK. Given
enough gradient steps the network compensates for a coarse alphabet, so the
benefit of extra levels decays with budget. If true, the programmes ranking is
not a list of independent effects -- the alphabets +0.735 pp was measured in a
regime the training-budget fix has since removed.

FORECAST REGISTERED BEFORE THE RUN: (1) the effect decays monotonically with
epochs -- about +0.7 at 8, +0.15-0.3 at 30, under +0.1 and not significant at 60;
(2) both recorded numbers are therefore correct measurements of DIFFERENT
regimes, and T317 needs its budget stated rather than its value corrected; (3) the
decay appears on both tasks, since the mechanism is optimisation not data. If the
effect is FLAT in epochs, the benches differ in something I have not identified
and the contradiction is unexplained -- worse than either number being wrong.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ibrate (Refs #1959)

T363 relaxed T361b on r = -0.684 across three datasets. Fitting the relation on
the homogeneous 45 digit pairs and testing on the three datasets NOT in the fit:

  penalty_pp = -2.2843 * ln(mi_tot) + 8.9025   (in-sample r=-0.839, RMSE 0.64 pp)

  Fashion  mi 30.40  predicted 1.10  measured 3.48   error -2.38
  UNSW     mi 11.04  predicted 3.42  measured 6.70   error -3.28
  MNIST    mi  3.14  predicted 6.29  measured 14.85  error -8.56

MAE 4.74 pp out of sample against RMSE 0.64 in it, and ALL THREE ERRORS HAVE THE
SAME SIGN -- the rule systematically under-predicts outside its fitting group.
mi_tot ranks tasks correctly and calibrates only within a dataset (T371).

THIS KILLS THE TOOL I WAS ABOUT TO SHIP. t27c taskfit was to print a predicted
penalty from one pass over the data; on the three datasets we care about it would
have printed 1.1, 3.4 and 6.3 where the truth is 3.5, 6.7 and 14.9 -- confident,
wrong, and all optimistic. A predictor validated only by CORRELATION will happily
produce a calibrated number nowhere near right, and correlation was the only
validation T363 ran (T371a).

What survives: mi_tot is a RANKING signal, r=-0.68 across datasets and -0.81
within one. Not a calibrated estimator and never to be printed as one; the honest
tool prints an ordering and a bracket (T371b).

Why the sign is always the same, as a hypothesis not a finding: the fit came from
pairs spanning 0.24-5.55 pp and all held-out tasks lie above that range, so a
logarithm fitted inside a narrow band under-shoots outside it by construction --
a property of extrapolation, not evidence about ternary datapaths (T371c).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ine (Refs #1959)

W765 declared the file self-contradictory: T317 put the size effect at +0.735 pp
and W765 measured +0.10 / +0.25. W766 registered a mechanism -- decay with
training budget -- and measured four budgets. THE FORECAST IS REFUTED: the effect
is FLAT in budget (UNSW +0.512/+0.169/+0.328/+0.351, never significant at 8
seeds; Fashion +0.324/+0.403/+0.295, always significant).

The registered consequence was to look elsewhere, and elsewhere was T317s own
table, which reports PER TASK: UNSW +0.381, MNIST +1.478, Fashion +0.346, mean
+0.735. W766 measures UNSW at ~+0.34 and Fashion at ~+0.34 -- agreeing with T317
on both. The +0.735 is a three-task mean lifted by an MNIST outlier and W765
compared it against two individual tasks. There was no contradiction in the file;
there was a contradiction in how I read it (T372).

The wasted experiment still established two new facts: the size effect is FLAT in
training budget from 8 to 60 epochs -- not a crutch for under-training as the
mechanism supposed -- and on UNSW it never reaches significance at 8 seeds, so
T317s UNSW significance came from 30 seeds and not a larger effect (T372a).

Lessons 854-857: check whether two numbers are the same quantity before chasing
the discrepancy; correlation licenses a ranking, only out-of-sample error
licenses a number; extrapolation outside a fitting range fails in a predictable
direction; "the thing we do not have" is usually a substrate statement.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…rate has a number (Refs #1959)

THE EMPTY CELL IS FILLED. Fashion at 60 epochs: +0.200 pp, t=4.82, significant.
Full grid: UNSW +0.512/+0.169/+0.328/+0.351, never significant at 8 seeds;
Fashion +0.324/+0.403/+0.295/+0.200, always significant. Flat confirmed on both.
The alphabet-size effect is not a crutch for under-training -- W766s mechanism is
dead on both tasks -- and it is worth about a third of a point per task, which is
what T317 said all along (T373).

THE RANKER REFUSES TO PRINT A POINT ESTIMATE. taskfit.py orders tasks by mi_tot
and reports a bracket from the two nearest measured anchors: Fashion 0.3-3.5
(true 3.48), UNSW 0.9-6.7 (true 6.70), MNIST 5.7-14.8 (true 14.85). Ordering
right, every true value at the TOP edge -- the systematic direction T371c
predicted. The tool states in its own output that a fitted curve under-predicted
three held-out datasets by 2.4, 3.3 and 8.6 pp (T374). CIRCULARITY NAMED: those
three datasets are themselves anchors, so this is a consistency check and not a
validation (T374a).

WHAT A TERNARY SUBSTRATE WOULD RETURN [СМОДЕЛИРОВАНО]. Unit: one configuration
cell. One neuron: 128 bit-cells (only 54 reachable) against 27 trit-cells --
4.74x fewer cells, 2.99x less configuration entropy. The trained networks hidden
layers: 4,096 bit-cells against 864 trit-cells (T375).

Three things it does NOT say, listed because the number is quotable and the
caveats are not: nothing about speed, nothing about silicon area (a trit-cell
costs more transistors and how many depends on circuit design we do not have),
nothing about accuracy. It is an estimate of configuration memory and only that,
and the adder-tree output layer is excluded (T375a).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
858: a tool that cannot be calibrated should print an order and a range, not a
number -- refusing a point estimate is a feature when the estimate would be
wrong, and the alternative was one commit from shipping. 859: say "consistency
check" when the test cases are the training cases, and name the circularity in
the same breath as the result. 860: attach the non-claims to a quotable number in
the same paragraph -- 4.74x will be repeated and its caveats will not unless they
travel with it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…o golden sieve exists (Refs #1959)

T374a named the circularity: the tools three demo datasets were themselves
anchors. Twelve NON-ANCHOR labellings from the census, penalties measured in
W760/W761 with no reference to the tool.

Registered forecast: (1) ranking holds, rho <= -0.6; (2) bracket coverage under
60%, misses BELOW the lower edge; (3) order usable, range not yet.

(1) CONFIRMED AND BEATEN: rho = -0.902, stronger on held-out tasks than the -0.81
measured inside the census. (2) half right: coverage is 67%, better than
predicted, but all four misses are below the lower edge, exactly the predicted
direction. The circularity is discharged -- mi_tot ranks tasks it has never seen
(T376).

THE BRACKETS DEFECT IS T364s CONFOUND AGAIN: every miss is a digit pair, and the
anchor set mixes two populations -- whole datasets (3.5-14.9 pp) and digit pairs
(0.2-5.6) -- occupying the same mi_tot range at different penalty levels. A
bracket across both is too high for pairs by construction. The fix is separate
anchor sets per task family, not a better curve (T376a).

NOW LICENSED: mi_tot may ORDER candidate tasks (out-of-sample rho = -0.902) and
bracket them WITHIN one task family. Not across families, and still no point
estimate (T376b).

NO GOLDEN SIEVE EXISTS HERE. git log --all --grep=sieve returns two commits, both
PRIME sieves (Eratosthenes W498, Miller-Rabin W370); neither touches phi. The
nearest relative is Zeckendorf representation in specs/numeric/lucas_accumulator
.t27 -- every integer uniquely a sum of NON-CONSECUTIVE Fibonacci numbers, which
is exactly base-phis forbidden 11. It is a representation, not a sieve, and has
never been used as a weight encoding here (T377).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@gHashTag

Copy link
Copy Markdown
Owner Author

Ladder update — 0004a and 0005 are on the branch. The headline: the `and` clause never worked, and now it does.

rung change measured
0004a braceless `bench` joins the shared clause parser 58,187 → 57,680
0005 `and` clause fixed both ways — the keyword lexes as the logical operator (unreachable at clause position for the function's whole life), and the greedy conjunction loop devoured the next clause after any successful one 57,680 → 42,926 discarded tokens (−37 % from base); parse-fails 173 → 171; consume-all 314 → 327

Found by ddmin: an 80-line "contextual parser-state" repro reduced to four lines, and the context was one and clause. Every mystified number of this arc — 55 % of tests dropped, container theories, ensemble effects — traces to one two-mechanism defect in one clause keyword.

Recorded revision: 0003's per-clause skip was withdrawn by its own regressions (clause junk handed to module level errors hard where the old fallback skipped safely; four files regressed, all four recover). The and-fix keeps the win by making most blocks lower completely. Zero regressions at every shipped rung; cumulative patches in docs/reports/gold-ring/.

🤖 Generated with Claude Code

claude and others added 2 commits August 19, 2026 12:58
`parse-complete --show` printed "nothing discarded" for a file the corpus mode
charged 2,438 tokens -- same binary, same file. The counter increments in three
places; the span recorder lived in only one (`skip_to_next_top_level`). Skipped
brace bodies (forall and friends) and statement-level recovery counted tokens
and recorded nothing, so the W634 read-what-vanished tool was blind to two
whole channels -- the mechanism behind W892's finding that the first inventory
missed 311+ BDD lines in one file.

Both remaining channels now push (line, lexeme) under the same 20,000-span cap.
Verified: per-file span totals equal the corpus counter exactly across all 126
discarding files, 42,926 = 42,926, zero mismatches.

Refs #1959

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…a "type"

The residual map blamed struct literals in clause values; exact-line probes
acquitted them (they parse). ddmin found the real killer three clauses later:
after a bracketed group, parse_array_literal consumed a following Ident
UNCONDITIONALLY as the Zig-style element type (`[3]u8`), across newlines --
so `and params = [1.0]` followed by `when result = ...` ate `when` as a
"type" and the whole block fell back. `and` clauses survived all along only
because KwAnd is not an Ident, which is exactly why 0005's fix made this look
like a struct-literal problem one clause earlier. Presence is not causality.

The rule now: an Ident after `]` is an element type only if it sits on the
same line as the `]` (the corpus's legacy same-line shapes, incl.
`&[_]provider-schema::ToolCall{}` in specs/provider/stream.t27, keep their
parse) or is immediately followed by an initialiser brace -- and in
clause-value mode a clause keyword (given/when/then/assert/and) is NEVER a
type, on either line.

Adversarially verified: a three-lens break panel ran 72 probe attempts against
the first version of this guard and found (1) one-line `given xs = [1, 2]
then ...` pairs still eaten by the same-line arm, and (2) a SILENT
false-green: `then {1} == xs` forged the brace test -- `then` became the
"type", `{1}` its initialiser, and the assertion vanished under "nothing
discarded". Both closed by the clause-keyword exclusion; the forged-brace
probe ships as a negative test (its honest outcome today is fallback, because
`{expr}` in expression position is the pre-existing W578 limitation, not this
rung). Two cross-line bare-type shapes (`[2]` newline `f64`) trade away their
parse; the corpus holds zero instances (0 new parse-fails).

Ladder, measured (624 non-scratch specs):

    0005    42,926 discarded tokens
    0006    37,786 (-12% this rung; -44% from the 67,760 base)
    parse-fails 171 (zero new vs baseline; the SSOT pair stays fixed)
    lost-tests inventory: 21,444 -> 22,329 of 23,033 BDD lines READ (96.9%)

Refs #1959

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@gHashTag

Copy link
Copy Markdown
Owner Author

Rungs continue: instrument honesty + 0006. Three updates since the last note:

  1. The instrument was blind in two of three discard channelsparse-complete --show said "nothing discarded" for a file the corpus mode charged 2,438 tokens. All channels now record; reconciliation sum(spans) == counter holds exactly: 42,926 = 42,926 across all 126 files.
  2. The lost-tests inventory, remeasured line-by-line: of 23,033 BDD lines, 96.9 % are READ under the ladder (dropped: 4,665 at W892 → 1,589 at 0005 → 704 at 0006). Decision 4 (migrate-vs-teach) now weighs 704 lines.
  3. 0006: the array literal consumed the NEXT clause's keyword as a Zig element type across newlines (and params = [1.0] + when ... ate when). The residual map had blamed struct literals — probes acquitted them; presence is not causality. A 72-attempt adversarial panel broke the first guard twice (incl. a silent false-green where then {1} == xs forged the brace test and the assertion vanished under "nothing discarded") — both holes closed, negative test shipped.

Ladder: 67,760 → 37,786 discarded tokens (−44 %), parse-fails 173 → 171, zero regressions at every rung.

One new one-pager awaits an Architect word: docs/reports/gold-ring/FORALL-DECISION.md — the remaining residue is now HALF forall bodies (~18,750 tokens, 34 files, top eight all specs/igla/race/*); recommended option is parse-only lowering (read, don't run). A number 1–4 on this thread settles it.

🤖 Generated with Claude Code

claude and others added 4 commits August 19, 2026 13:59
…em twice

The rung: given/when/and clauses whose value is not an `ident =` binding lower
as expression STATEMENTS (`given uart_tx_send(0x55)`, `given f() == 1`), and
the bench keyword pair `measure f(x)` / `target latency_us < 5.0` lowers to
StmtExpr nodes named by their clause -- never to asserts: a bench target is a
goal, not an invariant, and inventing check semantics is what
FORALL-DECISION.md declines to do. The colon-prose forms
(`measure: nanoseconds to ...`) stay honest fallbacks: prose is not an
expression.

v1 survived the corpus sweep and fell to the adversarial panel (84 attempts,
3 lenses) three ways:

  1. CONJUNCTION ABSORPTION -- `given f(0x55)` + `and g(0x66)` folded into ONE
     StmtExpr holding `f(0x55) and g(0x66)`: the second side-effect call became
     conditional on the first's truthiness, under "nothing discarded". The
     0005 clause-break only recognised `and ident =`. Rule now: in clause-value
     mode a LINE-LEADING `and` is a clause, full stop -- in the BDD layout a
     genuine operator lives on the line it operates on.
  2. ROLE LOSS -- `and` after `then` lowered as a bare expression, silently
     shedding its assert. Gherkin semantics now: `and` inherits the role of
     the clause before it, but CONTENT WINS (`and ident = ...` binds anywhere;
     an and-binding does not break the assertion chain, so `then a == 1` /
     `and y = 2` / `and y == 2` yields two asserts and one binding).
  3. PAREN ASYMMETRY -- `given (x + 1) == 2` died in the tuple gate while the
     SAME value parsed under measure. A failed tuple shape now restores and
     lowers as an expression clause.

Known sharp edges, measured and accepted: a mid-expression failure
(`given f(x) +` trailing operator) still costs its whole block -- the honest
whole-block fallback, same as before this rung; and junk PROSE inside a block
that now fully lowers surfaces at module level as a hard error (corpus
instances: zero; the baseline ratchet stands guard).

Ladder (624 non-scratch specs):

    0006    37,786 discarded tokens
    0007    34,175 (-50% from the 67,760 base)
    parse-fails 171, zero new vs baseline; consume-all 327 -> 328

Refs #1959

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ding

T56 counted FOUR discard channels; W899's instrument fix reached three.
`skip_to_semicolon` was the fourth -- eating tokens with no count and no span.
Its biggest victim: a semicolon-less top-level `const` followed by another
const/var (both outside is_top_level_start ON PURPOSE -- they appear inside
keyword blocks) sent the tail-skip through the next declaration, the next fn,
and everything to the following stray `;` or EOF. specs/ar/coa_planning.t27 --
the corpus's single largest "discarder" at 2,438 counted tokens -- actually
retained ONE declaration in its AST; the rest of the file was eaten mostly
UNCOUNTED. Two generations of readers bucketed it "Rust-form bodies"; the
intervention map (delete the suspect, re-measure) convicted the two semicolon
-less consts in minutes.

The rung: (1) skip_to_semicolon records every token it eats -- all four
channels now feed both accounts; (2) at depth 0 a LINE-LEADING const/var ends
the skip -- the next declaration is not expression tail. Same-line `[]const
u8` shapes keep their W568 parse (the line test spares them).

DISCLOSED STATUS CHANGE, deliberately: coa_planning and restraint now FAIL to
parse honestly (their fn bodies hold `for .. in` / `match ::` constructs that
were never parsed in the files' lives -- with the eaten regions restored, the
hard errors surface). Parse-fail count stays 173: two zombie parses out, the
two SSOT files in. Every other regression check is green; the corpus loses
30,023 tokens (-56% from base) at this rung.

Refs #1959

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… commit for the code)

Shipped in the same compiler.rs revision as 0008; recorded separately for the
ladder's cause-per-rung ledger:

- 0009a `bench name: expr` -- the one-line colon body parsed under `invariant`
  and dropped under `bench`; the intervention map convicted the FORM (trivial
  expressions dropped too). Lowered exactly as invariant-colon: the predicate
  becomes an assertion (0004a's own precedent for bench then-clauses).
- 0009b `measure: <prose>` / `target: < 50ns` -- convicted as FORMS; the
  content is frequently prose no expression grammar can honestly read. The
  rest of the line is captured VERBATIM into the node's value: tokens read
  and preserved, no semantics invented (FORALL-DECISION.md's own rule).
- 0010 `invariant name : EXPR;` -- the trailing SEMICOLON was the convicted
  cause (colon, spacing, `||` all exonerated); it is now consumed after the
  lowered assertion.

Corpus effect of the batch: 30,023 -> 27,452 discarded tokens (-59.5% from the
67,760 base); consume-all 326 -> 385; discarding files 125 -> 66; parse-fails
unchanged at 173 (the 0008 membership). Lost-tests inventory: 22,601 of
23,033 BDD lines READ (98.1%).

Refs #1959

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…s that hardened 0008-0010

0011: `value in [-1, 0, 1]` / `x in {0, 1, 2}` -- KwIn as a same-line
membership operator at comparison precedence, with a brace-set RHS parsed in
place. For-in loop headers are untouched (a for-in never reaches expression
position; the same-line rule keeps it that way).

The 64-attempt adversarial panel over 0008-0010 found eight breaks; every one
is closed and four ship as tests:

- const-stop v3: the skip now also ends at a line-leading TOP-LEVEL opener
  (it previously ran THROUGH `test t` into the body and minted module consts
  from test-local bindings), and a const/var stop requires a DECLARATION HEAD
  (`Ident :` / `Ident =`) -- the wrapped pointer type `const P = *` newline
  `const u8;` no longer mints a module constant named u8.
- var gains the same tail-skip const has: junk after a recovered var
  (`then v == 2` at module level) is swallowed-and-counted instead of
  hard-erroring the whole module.
- prose capture is BENCH-ONLY (a stray `measure:` inside a test captured the
  block's only then-assert into inert prose -- a vacuous test under a green
  light) and stops at same-line clause words (`measure: 5 target: 6` is two
  nodes again; `target: < 50ns then x == 1` keeps its assert).
- bench-colon parses its head under the clause flag (a next-line `and y == 3`
  was absorbed under `or` precedence into a strictly WEAKER assertion) and
  CONTINUES into the shared clause parser with the assertion role preset --
  `bench b: x >= 0` followed by measure/then clauses lowers completely, and
  Gherkin `and` after the head asserts.
- invariant-semicolon: var/enum/struct/using now end the block as cleanly as
  const/fn (the boundary list omitted them and the invariant dropped its OWN
  assert when any followed). The GLOBAL boundary set is untouched.

Known pre-existing edge, documented not caused: a keyword-test body opening
with `const x = 1` ends the clause block at the boundary and the binding
parses at module scope -- frozen does the same for unpoisoned files; fixing it
is a lowering decision (statement clauses), not a recovery decision.

Ladder (624 non-scratch specs):

    0010    27,452 discarded
    0011+v3 26,749 (-60.5% from the 67,760 base); consume-all 385;
            discarding files 66; parse-fails 173 (the disclosed membership:
            two zombies out, two SSOT files in); zero other changes

Refs #1959

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@gHashTag

Copy link
Copy Markdown
Owner Author

Ladder complete through 0011 — the probe-fixable frontier is nearly exhausted. Summary of the last four rungs:

rung cause corpus
0007 expression clauses (bare calls, comparisons, keyword measure/target) 34,175
0008 the fourth discard channelskip_to_semicolon ate a semicolon-less-const's tail through declarations and fns to EOF, uncounted: the corpus's largest "discarder" was a zombie parse with ONE declaration in its AST 30,023
0009+0010 colon family: bench name: expr, measure:/target: prose (captured verbatim — read, not interpreted), invariant trailing ; 27,452
0011 value in [...] membership 26,749 (−60.5 %)

Every rung carried a 3-lens adversarial break panel after its corpus sweep; the panels found (and the revisions closed) a forged-brace silent false-green, conjunction absorption of side-effect clauses, module globals minted from test bodies, prose swallowing sibling asserts, and a strictly-weaker assertion from or-precedence across a clause boundary. None of these were findable by the corpus — the corpus tests what exists, the panel tests what can be written.

One disclosed membership change: parse-fails stay 173, but specs/ar/coa_planning.t27 and specs/ar/restraint.t27 — the two zombies — now fail HONESTLY (their for..in/match :: bodies never parsed in the files' lives), while the two SSOT files parse. A certificate that only reported the count would have hidden this.

Inventory: 98.1 % of the 23,033 BDD lines are READ (55 % were dropped at W890). What remains is decisions, not probes: the forall word (docs/reports/gold-ring/FORALL-DECISION.md, option 2 recommended), and the specs/ar dialect question.

🤖 Generated with Claude Code

claude and others added 3 commits August 19, 2026 14:48
…ing a global

`const h = 5` between clauses ended the block at the KwConst boundary and the
binding parsed at MODULE scope: a test-local name became a global for every
backend while the block's remaining clauses dropped. Now const/var (and `let`,
which lexes as KwConst) and bare `ident = expr` assignments between clauses
lower as statement clauses -- StmtLocal / fn-body-shaped StmtAssign -- under
three guards, each earned by a measured failure during this rung's own
verification:

  1. only AFTER at least one accepted clause, at that clause's indent or
     deeper (a shallower const/var is a real module declaration and still
     ends the block; a body OPENING with const keeps the old edge, now an
     honest per-line drop rather than a minted global);
  2. CLEAN TERMINATION -- semicolon, new line, boundary or EOF. parse_expr
     returns Ok on a partial brace-if read (W578), and accepting that
     "success" left the loop on mid-line junk and cost the whole block
     (jones_topology_filter went 35 -> 75 dropped before this guard);
  3. an arm failure restores and ENDS the block instead of whole-block
     fallback -- module-level statement parsing then reads what it can.

Measured (624 non-scratch specs):

    0011    26,749 discarded tokens
    0012    26,713 (-60.6% from the 67,760 base); jones_topology_filter
            35 -> 16 (the whole invariant body incl. the bare assignment now
            lowers; only W578 brace-if innards remain); zero regressions,
            parse-fails 173 (the disclosed membership), all panel probes hold

Refs #1959

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… guards that came back

A 75-attempt three-lens panel against 0012 found twelve breaks; the worst
class was SCOPE THEFT with corrupted dataflow: at a column-1 tie an unindented
block absorbed the module const the NEXT test read (`rc=0`, "nothing
discarded", and a global silently became a local). Every break is closed:

- column-1 tie DISABLES the statement arms (module declarations and body
  statements are indistinguishable by column there);
- the anchor is the MINIMUM accepted clause column, not the first (an
  over-indented first given made a col-5 body statement look "shallower" and
  hoisted it while its own siblings were accepted at col 5);
- ADJACENCY: a statement clause sits on the line immediately after the
  previous token -- a blank-line gap means module scope, as every reader
  assumed;
- clean landing is measured against the LAST CONSUMED token's line, not the
  statement's ("line > start" blessed a mid-line stop on a later line and
  split one physical line into two minted statements);
- the bench-colon continuation gate admits KwConst/KwVar and presets the
  column anchor (a `let` after the head was minted as a module const holding
  a conjunction).

Documented, not fixed here: tab-vs-space byte columns invert the visual
indent relation (the corpus is tab-free; a tab rule needs a lexer decision);
a dirty statement that breaks to module level meets const's own truncating
fast path (pre-existing); a later clause failure still takes the whole block
(the standing whole-block honesty rule).

Corpus: unchanged to the token -- 26,713 discarded, 66 files, consume-all
385, parse-fails 173 (the disclosed membership) -- while six panel probes
flip from theft or silent line-splitting to correct scope or honest drops.
Three probes ship as tests.

Refs #1959

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Each cause below was CONVICTED BY INTERVENTION in the W905 causal map (delete
the suspect in a scratch copy, drops vanish) before any code moved:

1. LVALUE STEPS -- `and state.gamma[0] = 2.0`, `when buffers.scores[0..4] =
   scores`: the expression path parsed the lvalue, stopped on `=`, and the
   over-consumption guard felled the block. A dotted/indexed lvalue landing on
   a plain `=` now lowers as StmtAssign, under the same clean-landing rule as
   every statement clause.
2. KEYWORD AS FIELD LABEL -- `Contract { ..., invariant: "..." }`: the struct
   literal field loop broke on the keyword and the block fell. Any word-shaped
   token followed by `=`/`:` is a field label in that position.
3. `var` AS A NAME -- `given var = 5` / `then var == 5`: the binding arm
   accepts var/const keywords directly before `=` as names, and in
   clause-value mode ONLY, a var/const keyword not opening a declaration reads
   as an identifier in operand position.
4. UNIT PHRASES -- `target throughput > 1000 steps/sec`: the same-line residue
   after the bound is captured verbatim into the node's value, exactly like
   the colon form's prose. Read, not interpreted.

Remaining from the six: inline lambdas in then-clauses and given-comprehensions
(~235 tokens) -- left priced, not smuggled.

Measured (624 non-scratch specs):

    0012 v2   26,713 discarded
    0013      25,905 (-61.8% from the 67,760 base); consume-all 385 -> 387;
              discarding files 66 -> 64; parse-fails 173 (the disclosed
              membership), zero new; every prior family and panel probe holds

Refs #1959

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@gHashTag

Copy link
Copy Markdown
Owner Author

The ladder closes at thirteen rungs: −61.8 %, and the residue is priced. Final account for this branch (gold-ring/0001-0002-compound-assign-nested-fn):

base (W890) now (0013)
discarded tokens 67,760 25,905 (−61.8 %)
consume-all files 314 387
discarding files 137 64
BDD test lines readable ~45 % 98.5 % (356 of 23,033 dropped)
parse-fails 173 173 (two zombies → honest failures; the two L6-SSOT files → parsing)

Every rung carried probes, an adversarial break panel, and a full-corpus certificate; the map that priced the residue used delete-and-remeasure convictions, and four of its six small causes shipped as rung 0013 in one wave (lvalue steps, keyword field labels, var as a name, unit phrases).

What remains needs two words from a human, not more probes:

  1. forall bodies — 19,127 tokens, 74 % of the residue (FORALL-DECISION.md, four options priced, option 2 «parse-only lowering» recommended);
  2. specs/ar dialect — the two files whose bodies never parsed (now honest hard failures instead of zombie parses) plus ~3.7k tokens of Zig statement bodies: teach, migrate, or accept.

A number (1–4) for the first and a word for the second on this thread finishes the arc.

🤖 Generated with Claude Code

The last two convicted causes from the priced frontier:

1. INLINE LAMBDA -- `then all(result.v, fn(x) x >= 0.0)`: represented without
   a new node kind as an ExprCall named "fn" (parameters joined in
   extra_field, single-expression body as the only child), clause-value mode
   only. Convicted at W905 by swapping the lambda for a named predicate.
2. COMPREHENSION SUFFIX -- `given encoded = encode(x) for x in {...}`: the
   same-line `for ...` tail is captured verbatim into the binding's
   extra_field. Read and preserved; no semantics invented.

Measured (624 non-scratch specs):

    0013    25,905 discarded
    0014    25,670 (-62.1% from the 67,760 base); consume-all 387 -> 389;
            discarding files 64 -> 62; parse-fails 173, zero new; every
            family and panel probe of all fourteen rungs holds

With this rung the PROBE-FIXABLE TAIL IS ZERO: everything that remains is the
forall decision (~74% of the residue), the specs/ar dialect decision, and the
long-standing W578 brace-if expression question. The ladder rests until a
human speaks.

Refs #1959

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@gHashTag

Copy link
Copy Markdown
Owner Author

Option 2 is now REHEARSED — say «2» and it lands in one wave. A 58-line parse-only capture of forall bodies was built, measured on the full corpus, and reverted pending your word:

rung 0014 (current) with option 2
discarded tokens 25,670 6,592 (−90.3 % from the original 67,760)
consume-all files 389 411
discarding files 62 40
parse-fails 173 173 (zero new)

Patch and numbers: docs/reports/gold-ring/FORALL-OPTION2-REHEARSAL.patch + FORALL-DECISION.md on the branch. The remaining residue after option 2 would be ~3.7k dialect tokens (its own one-word decision) and ~2.9k thin expression leftovers (W578-BRACE-IF-DECISION.md, status quo recommended).

🤖 Generated with Claude Code

@gHashTag

Copy link
Copy Markdown
Owner Author

Both decisions are now rehearsed — two words take the corpus to −93 %. The dialect question got the same treatment as forall: built, measured on the full corpus, reverted.

configuration discarded tokens files
current (rung 0014) 25,670 62
+ dialect capture (option 2 of DIALECT-DECISION.md) 23,739 56
+ forall capture (option 2 of FORALL-DECISION.md) 6,592 40
+ both 4,711 (−93.0 % from the original 67,760) 32

Zero new parse-fails in every configuration; patches in docs/reports/gold-ring/ (FORALL-OPTION2-REHEARSAL.patch, DIALECT-PLUS-FORALL-REHEARSAL.patch), both reverted pending your words. The dialect ceiling is deliberately quoted UNDER the W905 scope guards — statement-first blocks stay out because that is where guard-less capture starts stealing module scope.

One number (forall: 1–4) and one word (dialect: 1–4) on this thread close the arc.

🤖 Generated with Claude Code

@gHashTag

Copy link
Copy Markdown
Owner Author

Entry point for whoever wakes up: the one-page status board. Both arcs are closed, both remaining decisions are rehearsed, mutation-checked, and priced; five human actions finish everything:

docs/reports/STATUS-BOARD-W910.md on branch claude/igla-fpga-improvements-3f5e1a — five rows: merge tf#603, merge tf#612 (the only gate before G8), one CI dispatch, and the two one-word ladder decisions (forall: 1–4, dialect: 1–4) whose rehearsal patches reproduce their quoted numbers exactly (25,670 → 6,592 → 4,711, −93 %).

The autonomous loop now holds quietly: ratchets green (parse-baseline 173 = 173 at every check), working branch clean, prototype identical to ring HEAD, scratch manifested. Answering here wakes the work.

🤖 Generated with Claude Code

…zero regressions

master and this branch independently built several of the same things; the
merge takes the UNION with each side's stronger half:

- compound assignment: the full operator set (+= -= *= /= %= |= &= ^=) --
  ours brought /= and %=, master brought |= &= ^= and the compound_binop
  emitter helper, which now serves all eight in all three backends;
- struct-literal suppression in paren-less conditions: ours' reentrant
  COUNTER (nested conditions) over master's bool, same rule;
- Zig casts: master's W566 narrowing @truncate for provably-unsigned integers
  COMPOSED with ours' W592 float builtins (@floatCast/@floatFromInt/
  @intFromFloat) -- floats first, then the narrowing choice;
- type annotations: ours' superset (& borrow + ?optional + quoted machine
  types); SystemVerilog keyword table: ours' superset (-g2012 full list);
- seal refusal: master's per-backend failures check (stronger than ours'
  vacuous-only check) with our CLI family (battery/known/provenance/verdict/
  silicon/...) intact;
- specs: master's content taken wholesale (the ladder's thesis -- teach the
  grammar, do not rewrite the tests -- applies to merges too).

Certificate, measured on the merged tree (650 non-scratch specs):
the merged compiler parses a STRICT SUPERSET of what rung 0014 parses --
0 regressions, 5 files newly parse (types, formal, linker, vcd_trace, ir);
corpus discard 6,782 tokens across 38 files, consume-all 421; every ladder
probe and panel test green; parse_baseline.txt refreshed with the merged
binary on the merged tree.

Refs #1959

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@gHashTag
gHashTag enabled auto-merge August 19, 2026 09:54
@github-actions

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-08-19 10:49:11 UTC

Summary

Status Count
Total Open PRs 30
PRs with Failing Checks 13
PRs with All Checks Green 17
READY 9
FAILING 13
PENDING 0

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=b7971c4a6e91 != manifest seal=87e5cbd3ad94.
    The committed NMSE numbers were certified against an older compiler.rs.
    Run scripts/reseal-check.sh locally for the two-step reseal command (advisory; not a merge gate).

@github-actions

Copy link
Copy Markdown
Contributor

📓 NotebookLM Notebook linked to this PR

This notebook contains session context, decisions, and artifacts for this work.

…instrument

Eight iterations against master's own corpus ratchet (33 -> 11 -> 9 -> 8 -> 7
-> 6 -> 4 -> CLEAN), each failure diagnosed to its construct:

- the fourth-channel stop ran THROUGH `test` headers into keyword bodies and
  a semicolon-less const swallowed files; the skip now also ends at any
  line-leading top-level opener;
- `measure:` prose no longer breaks on English `when`/`and`/`given` (stop-set
  is measure/target/then/assert);
- a stray `}` in a flat module -- master's own #2186 balancing braces -- is a
  RECORDED skip, not a hard error (W577's no-silent-truncation promise kept
  via accounting);
- keyword-identifier family closed: `module` in expressions (transmuted into
  the Ident arm so calls/fields still attach), `let mut name` (Rust modifier),
  `match` blocks captured verbatim with zero silent loss, `as float`/`as int`
  cast aliases, for-range heads no longer eat the loop body as a struct
  literal;
- one spec fix by master's own precedent (#2186): the unterminated
  `rag_retrieve_architecture` in igla/coder/arch.t27 gets its closing brace;
- the expectations ledger re-blessed: 109 entries REMOVED as fixed by the
  ladder, 4 re-priced under the four-channel instrument that counts what the
  frozen one could not see (the ledger's old zeros were blind, not clean).

Also: instrument artefact #14 found in the loop's own tooling -- `echo
"$(basename $f) rc=$?"` prints basename's exit code, not the parser's; every
rc in this branch's verification scripts is now captured before echo.

Certificate: suite --ratchet --corpus-only exits 0, RATCHET CLEAN; every
ladder probe and panel test green.

Refs #1959

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

📓 NotebookLM Notebook linked to this PR

This notebook contains session context, decisions, and artifacts for this work.

@github-actions

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-08-19 11:42:25 UTC

Summary

Status Count
Total Open PRs 30
PRs with Failing Checks 14
PRs with All Checks Green 16
READY 9
FAILING 14
PENDING 0

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=4bf01d874788 != manifest seal=87e5cbd3ad94.
    The committed NMSE numbers were certified against an older compiler.rs.
    Run scripts/reseal-check.sh locally for the two-step reseal command (advisory; not a merge gate).

…honored and flagged; NOW updated (Refs #1959)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

📓 NotebookLM Notebook linked to this PR

This notebook contains session context, decisions, and artifacts for this work.

@gHashTag
gHashTag merged commit 672f4ba into master Aug 19, 2026
20 of 23 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-08-19 12:24:24 UTC

Summary

Status Count
Total Open PRs 29
PRs with Failing Checks 12
PRs with All Checks Green 17
READY 9
FAILING 12
PENDING 0

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=a8a5da547cb3 != manifest seal=87e5cbd3ad94.
    The committed NMSE numbers were certified against an older compiler.rs.
    Run scripts/reseal-check.sh locally for the two-step reseal command (advisory; not a merge gate).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants