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 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 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.
exp-014's before/after check hinted that stronger churn helps lnd and
hurts the interval routers, which pointed straight at exp-008's
headline. Tested it properly: drift1 against the champions on one
fixed corpus with only payments_per_gap varying, 0 through 240 -- at
the fixed engine's settle rate the top rung is about eighteen times
the churn exp-008 actually ran under.
drift1 vs mx_c3 comes out -0.016, -0.005, -0.007, -0.003. A tie at
every level including no churn at all, every CI straddling zero, no
trend. exp-014's hint did not survive a controlled test.
The correction is not that the fixed engine changed the answer. It is
that the answer was a tie all along: exp-008 compared two point
estimates at n=8 with no paired test and read a 0.04 gap as a loss.
Re-scoring its own original corpus under the fixed engine gives -0.033
at p=0.453.
This matters beyond the record because the harness background prompt
told every candidate that decay LOST and to spend its complexity
budget elsewhere. An unsupported negative there is a search
restriction we imposed on ourselves, so the prompt now states the tie,
describes the evolved form that achieved it, and leaves the question
open.
In this commit, we port to CodexLM the defect ClaudeLM was fixed for:
the codex CLI spawns the vendored platform binary as a grandchild
sharing our stdout pipe, so subprocess.run's timeout killed the
wrapper and then blocked forever on a pipe the grandchild still held.
It stayed latent here only because codex reflections were always fast
enough that the timeout never fired, until a thousand-line seed made
one slow and exp-013 hung for eighty-five minutes on a single
reflection. The invocation now runs in its own process group and gets
killed as a group, a failed reflection degrades to a stub that costs
one iteration instead of the run, and --reflection-timeout lets a
large seed have the minutes it needs.
The lab record gains the exp-012 staleness result, which is a null
worth more than it looks. Six virtual hours of churn changes nothing
for any router, and the manipulation check passes, so the knob works
and the world does not move: only about eighteen percent of background
payments settle, and a failed payment moves no liquidity. Our
exogenous process is roughly five times weaker than its configuration
implies, which means exp-008's finding that decay buys nothing holds
only at the weak churn we generate, and exp-010b inherits the same
caveat.
In this commit, we extend the reflection background with the atomic
arena's economics -- held shards reserve real liquidity, siblings
contend, traffic drifts one slice per attempt, and failed payments
release atomically -- so candidates design for the new costs instead
of rediscovering them from failure traces. The exploit grep gains the
new hold-ledger API names (HoldHtlc, SettleHold, ReleaseHold): the
ledger belongs to the runner, and a candidate that touches it is
reaching through the sealed view.
In this commit, we extend the claude -p reflection backend with an
effort parameter, surfaced through the runner as
claude:<model>[:<effort>]. Lower effort trades per-proposal
deliberation for iteration throughput: the evolutionary loop supplies
the search, so a proposer that emits three medium-effort candidates
may outrun one that deliberates for ten minutes. A third exp-010 arm
(code_split_opusmed1) now runs at medium effort alongside the
default-effort Opus arm and the completed codex arm.
In this commit, we act on the deep audit of our optimize_anything
usage against the library source. The evaluator gains a batch form:
one Go compile per unique candidate instead of one per (candidate,
example) pair, which turns an eight-file valset pass from eight
identical builds into one -- a several-fold wall-clock win the gepa
engine consumes through the batch_evaluator hook, now wired into both
runner paths. Crash paths that could abort an overnight run are
closed: a build timeout under host load and malformed routesim output
now score zero with feedback instead of raising through the engine,
and raise_on_exception is off as a backstop, with
max_candidate_proposals as the enforceable cap now that evaluation
caching makes max_evals count only misses.
The reward-hack guard moves from post-hoc greps into the evaluator
itself: the banned-token regex now covers the hidden-state surfaces
(LocalBalances, AssignLiquidity, BalanceNodeChannels, SendHtlc, and
*routing.SimGraph assertions), verified clean against the seed and
every archived candidate. Fence stripping also slices from the
package clause when an agentic proposer prepends prose. Finally, the
codex harness home moves reflection to high reasoning effort --
medium was an unexamined default for 300-800 line Go rewrites.
In this commit, we act on two independent advisor reviews that
reframed the program: the paradigm ceiling we have been attributing to
algorithm space is partly a measurement ceiling, and the validation
story has holes that would surface immediately upstream.
Measurement: the evaluator now emits separate objective axes
(success, retry efficiency with shards disentangled from retries, and
fee efficiency) so the engine's hybrid Pareto frontier can keep
specialists alive, and evaluation caching is enabled now that the
evaluator is verified deterministic. The split corpus generator gains
--split-leads, replacing the single ambitious payment -- which left
two thirds of every file's score as free probes and quantized
minibatch selection above the very signal being selected for -- with
a descending ladder of mandatory-split payments whose completion count
grades the score. The original --split output is regression-tested
byte-identical.
Validation: sweep_validate.py replaces ad-hoc sweeps with paired
per-file comparisons, bootstrap confidence intervals, and sign tests;
gen_mainnet_scenarios.py generates multi-vantage mainnet corpora with
log-spaced source degrees (2024 down to 2) so claims stop resting on a
single hub-resident vantage; and params_lnd_bimodal.json adds the
baseline arm reviewers will ask for first, since lnd ships a bimodal
estimator that our defaults-only comparisons never exercised. The
exp-010 writeup gains a pre-registered caveat, logged before the live
runs finish, that corpus resolution may mute their verdicts.
In this commit, we add ClaudeLM, a GEPA reflection backend that runs
Anthropic models through the Claude Code CLI in headless mode, so
evolution runs can use Opus 5 as the proposer alongside the codex
backend. The runner accepts --reflection-lm claude:<model>.
The isolation lessons from the codex incident carry over directly:
claude -p injects global and project CLAUDE.md into its default
system prompt, so the wrapper replaces the system prompt wholesale
with a role-pinning one, runs from a neutral temporary directory so
project discovery finds nothing, opts into --bare mode when an API
key is available, and applies the same require_marker retry so a
chatty reply costs one retry rather than an optimizer iteration.
In this commit, we fix an incident that silently degraded the
code_split1 run: the codex CLI injects the user's global agent
instructions into every session, and the reflection model began
obeying their session-workflow rules instead of the reflection task,
returning "Watcher armed" as its final message. Twenty-one of the
run's first thirty proposals were tooling chatter rather than Go
source, burning roughly seventy percent of the reflection budget on
candidates that could never compile.
Two layers of defense. A preamble now pins the model to its actual
role -- a non-interactive text-generation function that must ignore
all session, watcher, and review instructions and reply with only the
requested artifact. And the code-mode runner passes a required marker
("package main") so any reply that still is not a candidate costs one
retry with a sterner preamble instead of a wasted optimizer
iteration. Verified with a live smoke call: clean Go out, no watcher
chatter.
In this commit, we update the code-mode reflection prompt for the
splitting-pressure run: the insights section now carries the exp-008
lesson that time-decay of evidence lost to plain hard bounds under
genuine drift, and names joint route-set planning -- choosing a set
of routes and their shard amounts together, min-cost-flow style -- as
the least explored region of the design space, since every winner so
far splits reactively.
We also log the exp-012 design in the ideas backlog: roasbeef's
observation that a new lnd node with no mission control weights burns
a long warmup on an unbalanced network, and the proposed hot-load API
for served weights. The measured warmup curves already reframe the
question -- mx_c3 needs 1.9 attempts on its first-ever mainnet
payment while lnd still burns 40+ attempts on hard payments late in a
batch, so the champions' prior does most of the work a served cache
would -- and the designed experiment covers the unscored warmup
phase, the staleness axis under drift, and the observation that
per-directed-channel bounds are shareable across nodes in a way
mission control's vantage-dependent history is not.
In this commit, we close the biggest fidelity gap the simulator had:
hidden liquidity only moved when the sender's own payments moved it,
so knowledge never went stale and evidence-based routing strategies
were unbeatable by construction. Real networks keep churning between a
node's sends.
Two additions, both opt-in per scenario file. A virtual clock advances
simulated time between payments (payment_gap_sec) and per attempt
(attempt_sec); the mission control stack behind the lnd baseline is
switched onto the same settable clock, so decay half-lives operate
over simulated rather than wall-clock time, and candidate routers can
read the current time through the new Now() method on SimNetworkView.
A background traffic engine executes seeded payments between random
node pairs in each gap: naive fee-optimizing senders route along the
cheapest public path with no knowledge of hidden balances, retrying
around failed edges a bounded number of times, so only the payments
that genuinely clear move liquidity, hop by hop, with per-channel
conservation.
The traffic sequence depends only on its seed, so competing routers
face the identical exogenous process, and scenario files without the
new sections reproduce their previous results bit for bit. The corpus
generator grows a --drift flag that scales traffic volume with network
size, and the code-mode reflection prompt now describes the drifting
environment neutrally, flagging that the champions' hard liquidity
bounds were learned in a static world, without prescribing whether
time-awareness is the answer -- that is exp-008's question to settle.
In this commit, we add the Python harness that drives GEPA's
optimize_anything over the routesim evaluator. Two modes are supported:
parameter mode tunes the existing heuristic's knobs as a JSON candidate,
while code mode evolves the entire routing algorithm as the full Go
source of candidate_impl.go, compiled per-eval via go build -overlay
with compiler errors fed back to the proposer as reflection signal.
The evaluator scores success rate with small saturating penalties for
retry attempts and fees, and guards against reward hacking by rejecting
candidates that reach for unsafe, reflect, or exec surfaces. The
reflection LM runs through the Codex CLI in headless mode via a small
LM-protocol wrapper, and omni-style two-phase composition (parallel
explore, then a fresh engine seeded with the winner) is available
alongside plain and adaptive runs. The background prompt encodes the
insights discovered by prior champion runs so follow-up evolution builds
on them rather than rediscovering them.