In this commit, we record the concurrency-tier corpus decisions:
authored drift+atomic tiers with calibrated background churn across
windows, rungs one, two and four, and the H-D3 smoke reversal left
to the champion sweep to adjudicate.
In this commit, we write up the concurrency stage: the schema as landed,
the event loop as built, the identity proof, the labelled smoke, and the
six things implementation taught the spec.
The two that matter most for the sweep are corpus decisions rather than
simulator ones. No sealed tier configures a virtual clock at all, so the
spec's concurrent tiers cannot be derived from hard-test, ood-test or
mainnet as they stand. And the obvious tier does not overlap: the atomic
tier holds three payments per file spaced by a six hundred second gap,
so a four-payment window never has more than 1.12 payments live, and the
manipulation check earns its keep on the first tier it is pointed at.
The smoke also points the opposite way to H-D3. lnd was predicted to
degrade gracefully under self-contention because its mission control is
shared across payments by construction; it absorbs two to three times
the seed candidate's self-contention rate per attempt at both windows.
Recorded as a starting gun rather than a result.
In this commit, we add --concurrency, the stage D knob. It lets the
sender run several of its own payments at once, racing itself for its
own outbound liquidity. Every tier this program has run sent one payment
at a time, so the only contention a router has ever seen came from its
own shards or from other people's payments.
Like every stamped section before it, the flag makes no rng draw, so a
corpus generated without it is byte identical to one generated before it
existed: seven paired generator trees at a fixed seed, across the
default, hard, drift, split, split-atomic and drift-atomic modes, all
diff identical.
A bare number is the common case. The long form pins the arrival
spacing, and that is the knob a tier designer has to think about: a
window that empties before it fills tests nothing, so inter_arrival_sec
wants to be at or below the time a payment takes on the tier, and
mean_concurrent in the output is what says which happened.
The flag help says where the tier comes from, because the section alone
is not enough. Without a clock the payments cannot overlap at all and
the simulator refuses the section outright; without atomic_mpp a shard
settles the instant it arrives and reserves nothing, so nothing
contends. The concurrency tier is therefore generated alongside --drift
and --atomic.
poisson is rejected here by the same name the simulator rejects it by.
An arrival rate interacts with the background traffic prorating carry,
and that carry is the one piece of the simulator whose draw order every
sealed tier depends on.
In this commit, we record the four lead decisions at the stage C
merge: the fee accounting fix ships unconditionally, the objective
keeps fee_ppm_on_success now that neither metric is abandonment
proof, the sweep adopts the data-driven rung ladders, and champion
fee blindness gets measured as-is before anyone hand-writes a
budget-aware variant.
In this commit, we record what stage C put in the tree and the five
things building it taught the spec: that the alternative fee metric is
not abandonment proof and the 1/N rule governs both metrics, that two
fifths of the fees the sealed tiers pay have never been counted, that a
constraint the arms can see binds at plan time for the third stage
running, that the rung ladder is two orders of magnitude apart between
mainnet and the synthetic tiers, and that the zero value of
SimPaymentSpec stopped being inert.
It also records the one place stage C's off state is not literally byte
identical, why, and the two-part proof used instead, so the lead can
reverse that call knowing exactly what it costs.
In this commit, we fix a claim we shipped in a comment two commits ago,
because measuring it made it false.
The exp-023 design spec argues that fee_ppm_attempted escapes the 1/N
rule: the abandoned amount stays in the denominator, so abandonment
cannot improve the ratio, so the fee weight could safely rise once the
term was charged against it. Fixing the denominator only stops
abandonment from shrinking it. The numerator falls all the same, because
a payment nobody completes pays no fee: abandoning a payment that would
have cost f and spent s on partial shards moves the ratio from (F+f)/A to
(F+s)/A, a weak improvement for every payment that pays a fee at all.
fee_ppm_on_success is the partly self-limiting one by comparison. It
improves only when the abandoned payment was dearer than its file's
average, and abandoning a cheap payment makes it worse. So the
substitution the spec proposed as the safe way to raise the weight is, on
this axis, the less safe of the two, and the 1/N rule governs both.
The sealed hard tier says the same thing out loud. Re-scored on the
alternative metric with no re-execution, the lnd arm gains +0.036 of
objective and the seed candidate +0.014, and the arm that gains more is
the arm that abandoned more payments.
What the metric is actually for survives intact, and the comment now says
that instead: it counts money that LEFT THE SENDER, including on payments
that then failed, which is 41% of all fees on the sealed tiers and which
fee_ppm_on_success cannot see at all.
In this commit, we add --fee-limit-ppm, which gives every payment of an
emitted corpus a fee budget in parts per million of its own amount. One
number covers a corpus whose amounts run over four orders of magnitude,
and a payment that pins its own limit keeps it. Absent stamps nothing:
the generator's output tree is diff-identical at a fixed seed either side
of this change, checked both ways.
The value is validated at two ends rather than trusted. Zero and negative
are rejected with the instruction to omit the flag, since zero at the file
level already means no limit and a caller writing it means something else.
Anything past a million ppm is rejected as a units mistake, because a
budget of the whole payment is indistinguishable from no budget in any
tier this program runs.
The help text carries the rung guidance, because the rung IS the
experiment. It is set from the realized fee distribution of the same
corpus run without a limit: above the distribution nothing binds and the
tier is a control, below it nothing completes and the tier scores
difficulty rather than routing. Measuring first is what keeps stage C
from producing a tier that fires nowhere, which is the failure stage A's
empirical family and stage B's mainnet family each walked into from their
own direction.
In this commit, we move the objective's arithmetic into one function, put
the design rule that constrains its fee term next to the constants that
would break it, and give both evaluators the sentence about how to read a
falling fee.
The rule has a number in it. A scored file holds 6 to 10 payments, so
abandoning one payment in the smallest file costs 1/6 = 0.167 of
objective, while the entire fee term is worth at most FEE_PPM_CAP *
FEE_WEIGHT = 0.100. The fee term is therefore structurally incapable of
paying for abandonment, by a factor of 1.67, and that margin is the only
thing standing between it and the exp-013 give-up attractor. The rule:
the fee term's maximum value must stay strictly below 1/N, where N is the
payment count of the smallest scored file. Doubling the weight breaks it;
removing the cap breaks it unconditionally.
The safe way to make fees matter more is a different metric rather than a
bigger weight, so the metric is now named: FEE_METRIC is what every
published number was scored with, FEE_METRIC_ATTEMPTED is the alternative
whose denominator abandonment cannot shrink. composite_score takes either,
which is what lets the pre-registered arm re-score archived runs offline
with no re-execution and no change to what the optimizer maximizes.
The hint gains the fee rule in the unconditional style exp-017
established, because a thresholded warning fails here for the reason it
failed there: fees falling is not by itself evidence of anything. Fees
fall for two reasons, cheaper routes and fewer completed payments, and
only the first is an improvement. The code evaluator additionally tells a
candidate that a fee budget exists and where to read it, since a route
refused for cost spends an attempt and teaches nothing.
The scores are unchanged to the last bit, checked against the old inline
formula on the pre-change binary's own output.
In this commit, we record the lead decision on the stage B
discovery that the mainnet tier was never byte-reproducible: accept
and caveat. The tie-break wobble predates every published number,
stays inside the tolerance the gates already carry, and a
deterministic sort would shift the numbers it is meant to protect,
so it waits for a full re-baseline.
In this commit, we write up what stage B taught the spec, in the shape
stage A's writeup established: the census verified independently against
the snapshot, the findings implementation surfaced, the byte identity
proof, and the smoke labelled as smoke.
The fourth finding is the one worth reading first, and it is not about
inbound fees at all. The mainnet tier is not byte reproducible and never
was: the PRE-change binary produces two or more distinct whole outputs
across repeated runs of the same file, on all eleven mainnet files and on
both arms. The cause is lnd's own pathfinding iterating a Go map to break
ties, which is fine on a synthetic tier where ties are rare and is not
fine on a 12,161 node graph. Aggregates are mostly stable, but two files
moved their attempt counts across five runs. Nothing published is
invalidated, and every future mainnet claim carries a run-to-run
component no seed controls. The decision about what to do belongs to the
lead, since it predates this stage and touches every published mainnet
number.
In this commit, we add --inbound-fees, which mirrors --htlc-limits: a bare
family name is the common case, the long form pins a seed, and the section
is stamped last and makes no rng draw of its own, so a corpus generated
without the flag is byte identical to every corpus generated before the
flag existed. Verified by regenerating a fixed-seed tree either side of
the change and diffing it whole.
Three families are namable. mainnet_empirical is the measured one and the
realism anchor. heavy is the authored stress rung and says so. as_loaded
draws nothing and prices what the network already announces, which is the
only family that makes sense on a describegraph tier, where the announced
values are the measurement this stage exists to recover.
In this commit, we note the merge of exp-023 stage A and the three
things implementation taught the spec: announced htlc limits bind at
plan time so the wire counters are an alarm rather than a measure,
source-side enforcement narrows to limits-only because full policy
checks are unsatisfiable at hop zero, and the mainnet tier has
carried real binding limits all along while only the synthetic tiers
were sterile. The tight family is where the pressure lands; the
empirical family is the realism anchor.
In this commit, we grow gen_scenarios.py the flag that stamps the stage
A section, mirroring --attribution: it makes no rng draw of its own and
is written last, so a corpus generated without it is byte identical to
one generated before the flag existed. Verified against the pre-change
generator on the hard profile at a fixed seed, and every stamped file
differs from its control by the added section and nothing else.
A bare family name is the common case and sets both limits, since a tier
that redraws only one of them is the paired exception rather than the
rule. The long form exists for exactly that exception, and the simulator
burns the same draws per policy either way so that moving one limit does
not move the other. Both forms validate the family name here rather than
letting a typo reach the simulator as a fatal error mid-sweep.
In this commit, we swap the live-run panel's lineage data from the
exp-018 gepa arm to code_deg1, the most recently completed run, so
the telemetry matches the runs the page now discusses.
In this commit, we add findings sections 15 and 16: the ceiling arm
(meta_harness at ten times the budget converges to a lower shelf,
closing both halves of the exp-018 question) and the lying-channel
breed (the first evolved attribution-confidence machinery, the
flattest degradation profile measured, and the attempt-cap subsidy
that reframes the verdict). Timeline gains exp-022, the exp-023
spec, and exp-024; the challenger count moves to eight everywhere it
appears; the live-run panel now states plainly that no optimizer is
live and that the interval-router branch is unbenchmarked in this
simulator.
In this commit, we close exp-022 with the pre-registered sweep: 648
paired runs, gates exact to four decimals against exp-020 and
exp-019. deg1 is challenger failure number eight — zero CI-solid
wins over the champions in either channel condition, unanimous
losses on split and mainnet, and the first evolved router to land
below production lnd on the mainnet tier. What it was bred for it
achieved: the flattest degradation profile ever measured, with the
champion gap narrowing under the lying channel exactly as predicted.
The mechanism is the finding — it never stops, and the objective's
attempt cap made never stopping free. The cap-sensitivity re-scoring
turns that subsidy into a measured objective weakness, and the
plan-time thesis takes its third independent confirmation.
In this commit, we harvest the code_deg1 run before a reboot can wipe
scratch. The winner is the first candidate in the program to evolve
attribution-confidence machinery: quarantined suspect bounds kept
apart from the hard intervals, payment-local penalties for unreadable
failures that write nothing to shared beliefs, and an escalation
threshold after repeated unknowns. It gains +0.044 on the degraded
world it was bred for and lands 0.009 below its own seed on the clean
held-out test, so the verdict stays open until the pre-registered
three-way sweep runs on the sealed tiers in both channel conditions.
The candidate was matched byte for byte against the runner's final
selection rather than trusted from the iteration log, which named a
different pool index.
In this commit, we close the exp-018 open question with the 10x
meta_harness run. Given 1,496 evals the engine finally iterates, and
the trajectory is the finding: five new-bests in the first three
iterations, then a flatline where the last 950 evals buy +0.0002.
It converges at 0.4677 val / 0.5136 held-out test, below gepa's
result at one tenth the eval budget, so the ~0.64 band is neither a
gepa artifact nor budget starvation. The full-set benchmark is the
mechanism: 68 evals per candidate turned 1,500 evals into 22
candidate evaluations, so gepa's eval-efficiency moat compounds with
scale instead of closing. log_bimodal_cost is challenger failure
number seven, exploit-grep clean, harvested with the adjudication
JSON and run log before a reboot could wipe scratch.
In this commit, we add the pre-registered design spec for economic
realism: min/max HTLC pressure, inbound fees, fee limits as an
environment constraint, concurrent payments, and latency as a cost,
each behind its own flag and landing in that order. The spec turns
the give-up attractor into a rule with a number (the fee term must
stay below 1/N of the smallest scored file, currently 1.67x of
headroom), routes fee pressure through a per-scenario fee limit
rather than a bigger objective weight, and specifies concurrency as
a deterministic virtual-time event loop with per-payment router
instances over the shared belief store that every evolved router
already carries.
The survey work behind it also surfaced three standing gaps worth
recording: the mainnet loader silently discards 4,783 real
inbound-fee policies because DirectedChannel.InboundFee is never
populated, the lnd arm has always run with no fee or cltv limit at
all, and fees paid on partially settled non-atomic MPPs vanish from
the aggregate. The lead decisions on the spec's three open questions
are recorded at the bottom of the doc.
In this commit, we check in the training and validation splits of
corpus-mix, the corpus behind exp-011, exp-018 and the code_deg1 run.
exp-020 already established that these files come from an uncommitted
working copy of the generator and cannot be regenerated from any
committed revision; until now the only copy lived in a session
scratch directory that a reboot wipes. The test split is already
sealed as the hard-test and ood-test tiers. The README records the
provenance, the one-field recipe for the degraded twin corpus, and
the verification gate (the in-tree seed reproduces the exp-011
iteration-0 val score to full float precision on these files).
In this commit, we add a --degraded flag to the code-mode runner for
corpora whose scenario files carry an attribution section. The flag
appends a new section to the background prompt telling candidates the
truth about the channel: roughly one failure in five arrives with its
attribution stripped, one in ten arrives blamed on an adjacent hop
with a plausible intact code, and successes are always truthful. It
then states the exp-019 findings (hard bounds from unattributed
failures poison the belief store; the champions survive by treating
no-information as no-information) and poses the open question nobody
has evolved an answer to yet: machinery that actively exploits a
lying channel. With the flag off the prompt is byte-identical to the
one every prior run used.
In this commit, we add a standalone explainer for the distillation
patch (9c07cbe7f), written for lnd co-workers reading this branch
cold. It walks the two flag-gated mechanisms in their real lnd code
paths, quotes the exp-019 pathology and the exp-021 recovery table
for soft_unknown with the attempts cost stated plainly, records the
three-design arc that reduced adaptive_split to lnd's own halving,
and closes with where the patch stops: capacity threading for the
hop choice, and the plan-time architecture (success-side memory plus
joint route-set construction) that no small patch can reach. A short
section at the end shows how to flip the flags and reproduce the
paired runs against the sealed tiers.
In this commit, we add §14 with both halves of the distillation
result — the soft_unknown recovery tables and Fig. 6, the four-way
descent trace that is the null's whole proof — plus the timeline
entries, and we resolve every place the site promised the patch as
future work with a pointer to the measured outcome. The writeup's
mainnet recovery cell gains the footnote the site pass flagged: 17%
is of the success loss, since lnd's objective rose under degradation
on that tier.
In this commit, we close the distillation experiment. soft_unknown
is the program's first constructive upstream deliverable: it
recovers 86-148% of the exp-019 collapse with unanimous
success/give-up direction, is provably inert on clean channels, and
carries its cost line (success bought with attempts) stated plainly.
adaptive_split closes as a genuine null after three designs each
reduced to geometric bound-descent that lnd's halving already
performs fastest and free — which, with exp-002b, kills both halves
of the reactive distillation theory and prices the champions'
remaining edge as plan-time architecture. The queue now leads with
the soft_unknown upstream PR prep.
In this commit, we land exp-021's instrument: two flag-gated changes
to lnd's own payment stack, byte-identical to stock with both flags
off (proven against a pre-change binary across four tiers).
soft_unknown is the live half. An unreadable failure now penalizes
exactly one pair (the lowest-probability hop at the attempt amount)
instead of every pair of the route in both directions, which is the
mechanism exp-019 showed spiraling lnd into give-ups from a 10%
unreadable-error rate. The smoke shows the intended signature: with
the flag on, lnd's trajectory is invariant to the unreadable rate.
adaptive_split is the measured negative, kept as instrumentation.
Three designs were built and each reduced to the same thing:
descend geometrically from the learned bound, which lnd's blind
halving already does at the fastest ratio of any variant, for free.
The supremum search paid a wire attempt per linear step; the backoff
variant re-derived halving with a slower constant; the
expected-value ladder degenerates to its top rung under apriori's
flat belief and cannot escape the retry loop bimodal pins itself
into. The conclusion the writeup carries: the reactive split-retry
control flow is not where the evolved routers' edge lives, so the
distillation question moves to plan-time mechanisms.
In this commit, we add §13 — three engines, one starting line: the
engines table, why the claude arms produced nothing, the adjudication
statement with its limits, omni1 as challenger failure number six,
and the two idea-ledger mechanisms — plus the timeline entry, the
ceiling sections' resolution notes, and the freshened counts (twenty
experiments, six failed challengers). The stale live-run panel now
points at the adjudication's gepa arm, and its run telemetry ships
with this version.
In this commit, we close the omni adjudication. Three engines, one
seed, one corpus, one 150-eval budget: gepa alone produced a
candidate, because its minibatch loop stretches a budget across
thirteen iterations while meta_harness's full-set benchmarking buys
exactly one and autoresearch burns everything in thirteen minutes
without beating the seed. The moat is eval efficiency, not proposal
quality. At practical budgets the exp-011 band is not a gepa
artifact; whether it is a true problem ceiling now has a specified,
costed test (meta_harness at roughly ten times the evals).
The candidate omni1 is challenger failure number six: no collapse
tier, beats no champion, and the inverse of the give-up attractor --
the most attempts of any evolved router on every tier, apparently
because it evolved none of the champions' guardrail caps. Its dual
belief ledgers (own-shard contention separated from standing balance)
and contradiction-triggered confidence decay go into the idea ledger.
Champions unchanged: hb1 + mx_c3.
In this commit, we retune the codex searcher defaults with exp-018's
measurements in hand: the gepa arm at xhigh lost four of thirteen
iterations to the 600s reflection timeout and took nine hours for 150
evals. The evolutionary loop supplies the search, so iteration
throughput beats per-proposal depth; the default effort drops back to
high with a 900s timeout for headroom on large seeds, and xhigh stays
one flag away via codex:<model>:xhigh for runs where a deep single
proposal is the point.
In this commit, we fold the shift-isolated mainnet arm into the
exp-019 record. Shift does not help lnd on mainnet: both CIs straddle
zero, the sign flips between levels, and the decomposition shows the
small positive at 0.1 is the give-up spiral's attempt term with
success falling on eight of eight files. The anomaly is hard-tier
only, and the route-geometry story fails by its own premise — it
predicted the vanishing because mainnet routes would be longer, and
they are three times shorter (hub source, 1.9 mean first-attempt hops
against 5.4). An outcome can match a prediction while refuting its
premise; this one did, and the check ran before anything was
published rather than after. The anomaly now ships with two facts and
no mechanism, and the queue drops the isolation arm as done.
In this commit, we add §12 — the degraded-attribution ladder, its two
tables, the five findings, and the anomaly labelled as an anomaly —
plus the two exp-019 timeline entries, and we sweep the 8.6x claim
across the whole site: every place that quoted the attempt ratio as a
live headline now carries the retirement (the ratio was a
perfect-channel figure; under realistic degradation the edge converts
to success), while historical narration keeps its numbers and gains a
pointer instead of a rewrite. The masthead moves to nineteen
experiments, title-defended champions, and attribution-tested status.
In this commit, we resolve the precision-paradise section with
exp-019's measurement: the degraded-attribution run WHY.md said the
8.6x was waiting on has now happened, the champions' margins hold or
widen under unreadable errors, and the number that dies is the 8.6x
itself, replaced by the success-edge claim.
In this commit, we write up the degraded-attribution ladder. The
feared result did not happen: the champions are not calibrated to the
perfect channel, because none of them writes a liquidity bound from
an unattributed failure, and at the realistic mix every champion
still clears lnd on every tier. What collapses is lnd itself — its
unknown-failure handling penalizes the whole route in both
directions, so a 10% unreadable-error rate drives its give-up rate
from 0.31 to 0.71, and at 30% four of ten hard files pin to zero
success. That is a self-contained upstream finding, and the third
input to the distillation patch.
The headline consequence: the 8.6x attempt-reduction framing is
retired. Under degradation lnd uses fewer attempts than the champions
because it stops paying for hard payments, so the ratio is
meaningless in both directions. The durable claim is on degraded
mainnet, where the champions hold success at exactly their
undegraded values while lnd trades six points of success for its
attempt drop: the edge converts from attempts into success. The
shift-helps-lnd anomaly ships labelled as an anomaly with its
mechanism unproven, and the delay arm shows staleness of delivery is
free for everyone: misattribution is the binding constraint.
In this commit, we give the simulator the one thing mainnet has that
it never had: an unreliable failure channel. A new attribution
section on the scenario file can strip a failed attempt's source and
code with probability unknown_prob (what a sender holds after an
onion error it cannot decrypt), blame an adjacent hop with
shift_prob (a well formed, plausible, wrong answer), and hold every
result back delay_slices of virtual time during which the background
traffic engine keeps moving liquidity.
The degradation applies at the single ReportAttempt delivery point,
so lnd and the candidates face the identical draw sequence — three
uniforms per attempt regardless of outcome, so the stream is a
function of the attempt index and not of how often a router fails.
The lnd path converts the unreadable marker to a nil failure message
before ReportPaymentFail, which is exactly what the switch hands
mission control on ErrUnreadableFailureMessage, so lnd exercises its
real processPaymentOutcomeUnknown logic (fail every pair of the
route, both directions) rather than anything sim-invented. Truth is
preserved upstream of the delivery point: attempt traces and the
served-observation export still record what actually happened.
Scenarios without the section are proven byte-identical against a
pre-change binary across three tiers, and the zero-value config
equals the unconfigured run result-for-result under test. Every
evolved router survives the degraded channel; notably none of them
writes a liquidity bound from an unattributed failure, and mx_c3
turns out to have EVOLVED an anonymous-failure contingency
(recordAnonymousFailure) that a truly unreadable error routes past.
In this commit, we close the loop the v58 publish opened: every
"title in adjudication" caption across the findings page, drift page,
index and chart series notes now carries the exp-020 resolution, the
§11 note box gains a same-day postscript with the split-test result,
and the timeline gains the exp-020 verdict entry including the
sealed-corpus provenance findings.
In this commit, we write up the adjudication the exp-017 docs
promised before repeating the "generalist" framing. On the original
tier set — the ground the title was earned on, with mainnet, hard and
OOD gates reproducing published numbers to three decimals — hb1
significantly beats mx_c3 nowhere, while mx_c3 takes split_test
unanimously (+0.062, 8/0, p=.008), the one tier where hb1 alone
cannot beat lnd. The two significant hb1 signals from exp-015 and
exp-017 were real but family-specific, and neither transfers.
Champions unchanged, mx_c3 the generalist of record, and the
methodological lesson goes on the wall: two independent p<.02 signals
failed to replicate on held-out original ground, which is exactly the
outcome the no-swap-without-a-paired-sweep rule exists to catch. The
headline table, twin-question bullet, closed list, queue, and the
scratch-regenerability gotcha ride along.
In this commit, we promote the two headline validation tiers into the
repo verbatim, because exp-020's corpus archaeology found both
assumptions about them false: the scratch copy of the sealed hard
tier had been silently overwritten by exp-010's regenerated corpus
(the pristine files survived only inside corpus-mix, identified by
reproducing the published scores exactly), and neither tier is
regenerable from any committed generator revision — they came from an
uncommitted 2026-07-24 working copy, so the on-disk files were the
only artifact in existence. The scenarios README records the history;
drift, split and atomic still regenerate from the committed generator
and stay that way.
In this commit, we sync the run lineage data the v58 bundle shipped
with (code_hybrid1, 28 candidates), so the committed site matches
what Litbucket serves.
In this commit, we add §11 to the findings page — the thirteen-world
sweep, the full scores table, the seed-as-control argument, atomic1's
regime specialization, and the eroding generalist title — plus two
timeline entries, and we bring the stale framing current everywhere
it appears: masthead counts and date, the §00 circularity note now
pointing at its half-closure, and the mx_c3 "generalist / best
overall" captions on index, drift, and the chart series notes now
carrying the in-adjudication qualifier. Design untouched; everything
additive or a one-line text correction.
In this commit, we tighten a sentence the site-update pass caught:
atomic1's ladder rank sequence (4, 4, 3, 1, 1, 1) is monotone, but
its margin over lnd peaks at +0.283 on beta:0.3:0.3 and eases back
to +0.257 on the flattest worlds, so "rising monotonically" was
wrong on the second clause. The finding is unchanged; the wording
now matches the numbers in its own table.
In this commit, we bring WHY.md current with the de-circularization
result. Section 0.2 gains the measured answer to its own worry: the
fitted constant explains very little of the margin, since the
ordering survives thirteen generator-moved tiers and the never-fitted
seed compresses exactly like the champions on the easy worlds. The
pending list drops "draw mainnet liquidity from something we did not
write" from the top slot; what remains of it folds into degraded
attribution and offline replay, which now lead.
In this commit, we write up the generator-family robustness sweep: 13
paired tiers moving the liquidity family, the amount family, and the
mainnet balances underneath five routers, 650 runs, with the
untouched mainnet control reproducing exp-009 to three decimals. lnd
is rank 5 on all thirteen tiers and an evolved router is rank 1 on
all thirteen. The margins compress on easy worlds, but the
hand-written seed (never fit to anything) compresses with the same
shape, so the compression is a difficulty ceiling rather than the
overfitting signature we were hunting. The paradigm wins, not the
fitted constants.
Secondary findings restructure the champion picture: atomic1 is a
flat-liquidity specialist (ladder rank 4 to 1, monotone), hb1 is at
or above mx_c3 on 12 of 13 tiers with liq-uniform significant at
p=.004, and the pair ties to 0.001 on every mainnet family. The
"generalist champion" framing now rests only on OOD/split tiers this
sweep did not touch; a dedicated adjudication is queued in CLAUDE.md
before that framing gets repeated. The notebook entry, headline
table, closed list, and the reprioritized next-steps list ride along.
In this commit, we replace the give_up_rate threshold warning with an
unconditional read-the-pair rule. exp-017 measured that for candidate
routers give_up_rate equals 1 - success_rate on every tier, since a
candidate "gives up" whenever it returns failure without exhausting
its attempt budget, which is how candidates always fail. A warning
keyed on that field alone fires universally and becomes noise the
reflection model learns to skip. Abandonment is only readable jointly
(attempts AND success both falling), so the hint now states that rule
every time instead of pretending the field can detect it.
In this commit, we replace the two-phase explore/continue omni script
with an adjudication runner. exp-011's "paradigm ceiling" claim is
confounded with the optimizer: every lineage that converged on the
~0.64 band ran engine="gepa", so three lineages agreeing says as much
about that engine's attractor as about the problem. The new runner
gives each engine (gepa, meta_harness, autoresearch, best_of_n) an
independent run from the same seed with the same eval budget, and the
scientific output is the per-engine comparison table, not a single
winner.
Design points worth knowing at review time: the gepa arm mirrors
run_gepa_code.py exactly so its result stays comparable to exp-011;
per-arm failures are isolated and recorded rather than fatal; and the
adjudication JSON records each arm's actual budget mechanism, because
the units are not as equal as they look. In this gepa build every
engine takes max_evals (the cap is enforced centrally in the eval
server), but cache_evaluation means the gepa arm's budget counts
cache misses while other arms count raw calls, and proposal caps are
not a shared unit at all. Those asymmetries are recorded in the
output instead of papered over, with a --no-gepa-cache escape hatch
if we ever want to equalize the eval unit at the cost of exp-011
comparability.
The claude-CLI arms run under the sterile CLAUDE_CONFIG_DIR harness
home with the OAuth token loaded from disk into the environment only,
never printed.
In this commit, we lift give_up_rate and bg_settle_rate out of the
aggregate dict into top-level side information, and inject an
explicit warning into the reflection hint whenever a candidate
abandons more than 5% of its payments. exp-013 showed the composite
objective hides giving up on hard payments inside the same number as
attempt efficiency, so a seed at the attempt frontier evolves toward
abandonment; the searcher can only avoid that attractor if it can
see it. This is also one of the two prerequisites the advisor named
for the exp-018 omni adjudication run.
In this commit, we pass model_reasoning_effort as a per-call -c
override on the codex exec command line instead of relying on the
harness home's config.toml. That file is only written on first use,
so it had silently pinned every reflection to "high" regardless of
what we thought we were running. The runner grammar becomes
codex:<model>[:<effort>] to match the existing claude spec, and the
default effort for search/reflection agents is now xhigh.
In this commit, we promote the ten mn_*.json files and the
scen-mainnet.json smoke file from the session scratch directory into
the repo, verbatim. These are the exact scenarios behind every
published mainnet number (lnd 0.694 through mx_c3 0.791), and until
now they lived only in a directory that reboots wipe: the headline
results were one power cycle away from being unreproducible. The
README records their provenance, the graph-file setup step, and the
known synthetic-liquidity caveat that exp-017 exists to measure.
In this commit, we give the corpus generator the two knobs exp-017
sweeps over. gen_scenarios.py grows --liquidity-family (override the
emitted liquidity_model string verbatim) and --amount-family
(lognormal with the median pinned to the tiered amount, or amounts
snapped to a round-value ladder so they collide with each other and
with liquidity bounds, the way real payments do). The default path
makes exactly the original rng draws in the original order, verified
byte-identical across six invocation shapes against the pre-change
script.
gen_family_corpora.py emits the exp-017 layout: ten hard-tier base
scenarios drawn once from a fixed master seed, then one directory per
family where file i is identical to the base except the single field
under test. That pairing property is what lets per-file paired deltas
isolate the generator from topology noise. gen_mainnet_variants.py
does the same transform to existing mainnet scenario files as a
one-line text substitution, with a parse-and-compare assertion that
nothing else moved.
The published explanation of why served weights hurt lnd was wrong, and
it reached the dashboard. It said lnd files a failure as a pair penalty
carrying no amount, suppressing a corridor for every payment size.
probability_apriori.go:363 returns the unpenalized prior whenever
amt < FailAmt, so the estimator gates on amount correctly. A Fable
advisor found it by reading the estimator rather than the summary.
Its replacement hypothesis was wrong too. Node-level contagion is real
-- getNodeProbability folds pair results into a node prior used for all
that node's untried channels, which the "761 edges, 761 pairs" check
never ruled out -- but disabling it with apriori.weight=1.0 leaves the
loss at -0.038 against -0.046.
The third guess, staleness, looked decisive and was a confound.
Failures from a one-payment server cost lnd +0.000 on 0 of 10 files,
but that set holds 232 observations against the stale set's 2,808. A
size-matched random subsample of the STALE set gives -0.003. At equal
volume stale and fresh are indistinguishable.
What survives is volume. Each imported failure blocks one directed edge
at or above its amount, and server and consumer draw amounts from the
same distribution, so the bounds land where the consumer is about to
send. At 232 observations nothing happens; at 2,808 over a 761-edge
graph lnd finds its amount blocked almost everywhere and can only route
around, onto longer and worse paths.
The upstream thesis survives in a sharper form. lnd's estimator does not
ignore amounts. Nothing DOWNSTREAM of it can act on an amount bound,
because findPath takes the amount as a fixed argument -- so knowing that
at least X fails on an edge can only subtract routes, never resize the
payment. That is exp-002b's finding from the opposite direction, and the
two now converge on one patch instead of two observations.
Two further claims are labelled rather than deleted. exp-011's paradigm
ceiling is confounded with the optimizer, since every run in this
program used engine="gepa" and three lineages converging on one band is
evidence about that engine's attractor as much as about the problem; the
adjudicating run is specified in the writeup. And the proposer law from
exp-010b was fitted to two opposite-sign runs, so it is downgraded to a
hypothesis.
Also stages params_lnd_no_contagion.json, the weight=1.0 configuration
that isolates node-level aggregation, so the contagion control is
reproducible.
WHY.md predated the last four experiments and still described two of
its own open problems as open. Section 3 said the drift tier was
weaker than it looked and asked for a traffic fix; the fix has run, and
the interesting part is that the two obvious causes explained almost
none of it -- uniform endpoint sampling on a graph whose median degree
is one did. The same section quoted exp-008's decay loss, which the
churn ladder has since corrected to a tie at every level. Section 6
called free knowledge unconstructible; --import-weights constructs it,
and the answer inverts by consumer rather than staying negative.
Section 9 gains the sixth portable idea, which is the only one whose
absence actively harms: serve observations rather than weights, and
fix the consumer first, because an API serving failure observations to
lnd as it stands makes lnd worse.
CLAUDE.md's headline section had drifted furthest from the evidence. It
pointed at exp-001 through exp-009 when the record runs to exp-016,
omitted atomic1 entirely despite it holding the attempt record and the
program's only win over a champion, and claimed the parameter result
without the estimator control that now supports it.