Bitter-lesson GOFAI on Bend2: self-modifying agents worth trying
Written 2026-09-27 for Kelvin. Measured = run today on this box (kelvin-general-1, 16 vCPU, no clang, no GPU) on the Bend 2.0.29 JS lane under bun. est. = derived with the calibration in selfmod/research/bend2-hands-on.md §1. (unverified) = not fetched or run today. Each idea links a design note with a runnable lab; both judge verdicts are verbatim in selfmod/designs/judges.md.
1. TL;DR
- The DGM lineage is a thin selection loop around LLM coding runs. Almost all time and money goes to 30-60 minute LLM self-modification runs and to evaluation; the selection code is about 50 lines. Bend2 cannot speed that up. The idea worth keeping is HGM's lineage credit: judge an agent by how well its descendants do.
- The bitter-lesson GOFAI move: make the self-modifier a small symbolic program run by one fuel-bounded Bend interpreter. An evaluation then costs microseconds, not minutes and dollars, so DGM/HGM machinery (archive, lineage credit, editable meta level, frozen referee) runs at 10^6-10^9 evaluations instead of about 800.
- Bend2 today accelerates every balanced, batched, U32 inner loop: population evaluation, rollouts on shared random seeds, enumeration by rank, lineage rollouts. Measured 2.3-3.8 M evaluations/s per JS process; native est. 11-15x faster here. HVM5/SupGen is needed for enumeration with sharing, superposed rule sets and exact metaproductivity over every child. The type checker, library compression and LLM calls stay on the host.
-
Top ideas, ranked (both judges put idea 1 in their top two):
- A superoptimizer whose learned rewrite rules become its own interpreter and its own pruning, so each search is cheaper than the last.
- Search distilled into a policy, with exact counterfactual credit.
- DreamCoder on OEIS with a bijective Bend enumerator.
- Symbolic HGM as the outer selection layer.
- First experiment: one week of idea 1, admitting rules by idea 2's counterfactual credit, plus a half-day HVM4 SupGen vs cube head-to-head. Runs on this box now, $0 API.
- Decision for you: OK to install clang (system package, farol sudo route) so native numbers replace estimates. Nothing else blocks.
2. What the DGM lineage does and where its compute goes
From selfmod/research/dgm-lineage.md, which read the papers and repo code today.
| Lineage | What modifies itself | Selection and credit | Compute goes to | Reported cost and result |
|---|---|---|---|---|
| DGM (arXiv 2505.22954[1]) | coding-agent repo: tools, prompts, workflow | keep-all archive; parent weight = sigmoid(score) × 1/(1+children); own score | LLM self-mod run (1800 s timeout) + SWE-bench/Polyglot in Docker | ~$22k per SWE run, ~2 weeks; SWE-bench 20→50% |
| HGM (arXiv 2510.21614[2]) | same, on DGM's code | Thompson sampling on the clade's pooled counts (CMP); max 800 task evaluations | same | Polyglot 30.5% at 347 CPU-h vs DGM 27.1% at 2,385 |
| SICA (arXiv 2504.15228[3]) | own repo; best agent is next meta-agent | greedy on score, cost, time | LLM | ~$7k for 15 iterations |
| Gödel Agent (arXiv 2410.04444[4]) | running code, by monkey patching | one lineage, rollback | LLM | ~$15 for 30 self-improvements |
| Hyperagents (arXiv 2603.19461[5]) | task agent + meta agent in one program | DGM archive; selection fixed | LLM | ~88.6 M tokens per 100 iterations |
| GEA (arXiv 2602.04837[6]) | agent repos | parent groups by score × √novelty | LLM | ~$13k SWE, ~$1.5k Polyglot |
| SIFT (arXiv 2609.19526[7]) | as DGM | pairwise LLM judge + Bradley-Terry | LLM | Polyglot 35.1%, under 5 h, $150 |
| ASI-Arch (arXiv 2507.18074[8]) | linear-attention code | evolutionary database | GPU training | 20,000 GPU-h |
What carries over:
- Lineage credit is the one real algorithmic idea. HGM's Theorem 1 says a CMP oracle suffices for a Gödel Machine, assuming among other things that "proofs are free". With 800 LLM evaluations CMP is noisy; with microsecond evaluations it can be near exact.
- The outer loop stays hand-coded. When Hyperagents made parent selection editable (appendix E.5), it reinvented UCB but did not beat the handcrafted rule.
- Referees get hacked. DGM node 114 hit a perfect score by removing the logging its hallucination detector used, "despite instructions not to change the special tokens"; DGM's diagnosis prompt also sees SWE-bench's hidden test patch. Every idea below keeps the referee frozen and outside generated code.
3. The Bend2 acceleration map
The contract (research/bend2-status.md): BendRT[10] runs a fixed 128×128 fork-join cube with no work stealing, so forks must be balanced; numerics are U32/F32 (no U64); values are affine with no GC. Superposition and SupGen[11] live in HVM4/HVM5, not Bend2. The JS lane runs here; native needs clang ≥ 14; no GPU here.
| Inner loop | Fits the cube today | Needs HVM5/SupGen | LLM- or host-bound | Numbers |
|---|---|---|---|---|
| Population evaluation: N stack-VM programs × M inputs | yes | no | no | measured 2.26 M evals/s JS; C twin 151 M/s on 16 threads; est. 25-35 M/s native here, ~160 M/s M4 Max |
| Edit-chain rollouts on shared seeds (idea 2) | yes: mask × task × seed, U32 statistics | no | host refits the policy | measured 3.5-3.8 M evals/s JS, 21 M evaluations in 5.5-6.1 s |
| Fingerprint enumeration (idea 1) | yes: fixed length, min-reduce | yes, for sharing per equivalence class and superposed rule sets | host groups classes | measured 2.39 M candidates/s JS; est. 26-36 M/s native |
| Levin enumeration by rank (idea 3) | yes: bijective leaf→program per cost level | yes, for typed shared-prefix enumeration | library compression (Stitch) | measured 143k programs/s JS; Levin K=7, 2^21 programs × 16 points in 1.39 s |
| Lineage rollouts for CMP (idea 4) | yes: fixed fuel, latched success | yes, for exact metaproductivity over every K-edit child | Thompson sampling | measured 2.6k agent×task evals/s JS |
| Typed mutation with in-kernel checker | yes, but bimodal leaves (1.7 µs rejected, 16 µs accepted) | yes, for type-directed mutator synthesis | no | measured; 57-91% rejected |
| Bend checker as proof gate | no | no | host | measured 0.27 s per check, 512 defs in 0.52 s, 64/64 right |
| Artificial-life soup | yes | no | no | measured JS ~9-10 M steps/s vs C twin 206 M on one thread |
| Proof search, e-graphs, shared-hash dedup | no | proof search is SupGen-shaped | host | not measured |
| DGM-style LLM self-modification | no | no | LLM | 30-60 min per run |
| SupGen synthesis itself | no | runs on HVM4 today | no | measured HVM4 gen_mul4k: 10.3 s, 409 M interactions, 39.7 M/s, one core, 4.5 GB |
Sources: selfmod/research/bend2-hands-on.md §1-4, selfmod/research/gofai-self-mod.md §4, the design notes. Conversions (est.): native sequential ≈ JS/2.2-2.35; 16 threads here ≈ 11-15x JS; 16 threads on M4 Max ≈ JS/72. GPU would lose on these divergent interpreters (the paper's symbolic-regression analogue: 0.54 s GPU vs 0.29 s on 16 threads).
Two engineering points:
- Speed. C twins run about 20x (one thread, soup) to 67x (16 threads, population evaluation) faster than the JS lane, and native Bend is still an estimate. What Bend adds today: one source for 16 cores, an M4 Max and Metal; deterministic affine semantics, which make counterfactual replay on shared seeds exact; and a checker that can gate self-edits.
-
Cube hygiene kit (measured on twins), for every kernel below:
- hash-shuffle items to leaves (correlated skew gave 1.7x static vs 8.1x with stealing);
- latch results instead of exiting early;
- make fitness a count of exact matches, never a U32 error sum (a wrapped sum accepted wrong program 64954 in the Levin cube);
- fixed fuel per leaf;
- bijective rank→leaf maps instead of padding (padding idled 34% of library-learning leaves).
4. The ideas, ranked
Scores are judge 1 / judge 2 totals (selfmod/designs/judges.md).
Idea 1. The self-compounding superoptimizer (29 / 31; selfmod/designs/interpreter-evolution.md, lab selfmod/designs/interp-evo-lab/).
- Learned: rewrite rules found by exhaustive enumeration and testing, installed as the interpreter's normalization pass; rule priority; enumerator pruning (skip any candidate the rules reduce); a bandit that allocates enumeration.
- Hand-coded, frozen: 8-op U32 DSL, reference interpreter, step-count cost meter, differential gate, corpus. Evolving the optimizer, not the semantics, avoids rewarding an interpreter that returns 0.
-
Kernel:
superopt.bend.tmplforks evenly over candidate indices; each leaf runs one program on 16 U32 points, hashes outputs, min-reduces a packed (cost, length, index) key. Measured: 30/30 targets pass the gate at length 7; 1 fingerprint point gave 16 false rewrites, 16 points gave zero. Est. native here: length 8 (19 M candidates) 9-12 s, length 9 (153 M) 70-95 s, length 10 (1.2 G) 9-13 min. -
One week: mine rules from all candidate pairs; score each by exact leave-one-out Worth against a ~25-identity peephole baseline; turn on pruning; bandit vs uniform; a fueled
Foldop for loop→closed-form rules (for example Σi); native rerun if clang arrives. - Exciting if: the system's own rules make its next search ≥2x cheaper per wave, the learned library beats the hand-written one by ≥10%, and it finds a closed form unaided, the "eureka" step Burstall-Darlington transformation needed a human for.
- HVM path: evolve data encodings, metered in interactions. Taelin's SupGen+Fusion gist reports the same synthesis at 442 M vs 1.9 M interactions under two encodings, 232x (https://gist.github.com/VictorTaelin/0b68673e0e85437baae32f7e08f1e50c[12]). Runs on HVM4 today.
- Risk: without the closed loop this is Ruler/Enumo (arXiv 2108.10436[17]) in Bend; run Ruler as the baseline.
Idea 2. Search distilled into a policy, credited by counterfactual Worth (30 / 30; selfmod/designs/search-distillation.md, sketch selfmod/designs/search-distillation-sketch/).
- Learned: a policy compiled into the kernel as per-context U32 sampling tables, refit each wave from the search's own results (expert iteration, arXiv 1705.08439[15]); which operators live or die; invented pair-macros.
- Hand-coded: DSL, tasks, and the Gumbel-top-k plus sequential-halving schedule (a cube-safe stand-in for MCTS).
-
Kernel:
wave.bend.tmplforks over mask × task × seed on shared random numbers; each leaf runs D edits; the tree reduces U32 statistics. An operator's credit is the paired drop in solves when it is masked, exact because Bend is deterministic. - Measured smoke test (8 tasks, 8,192 attempts): uniform 57 solves, attribution 64, counterfactual 382 (375 on a second seed set). Confounded: masking let weight fall through to the next op, the step was hand-picked, and 8 tasks is tiny.
- One week: 16 opcodes; 256 hidden-grammar tasks (192/64 held out) plus 16 Hacker's Delight transfer tasks; renormalized sampling; arms uniform / attribution / counterfactual / counterfactual plus value at equal rollouts; 1,024 pair-macros on day 6. Pass: counterfactual ≥2x uniform and ≥1.5x attribution held out, Spearman ≥ 0.8.
- Exciting if: EURISKO's central bet, that Worth causes gains, holds under controls. It becomes the credit currency for every other idea.
Idea 3. DreamCoder on OEIS with a bijective Bend enumerator (26 / 31; selfmod/designs/library-learning-cube.md, lab selfmod/designs/libcube/).
- Learned: new opcodes (Stitch compressions of its own solutions, compiled into a regenerated interpreter); a prior as integer symbol costs, later task-conditioned; searcher settings under lineage credit.
- Hand-coded: a minimal base DSL near Gauthier and Urban's, fuel, host bignum checks on terms 17-32.
- Kernel: count-table unranking, leaf i → exactly one program of cost c, no queue, no duplicates. Measured: matches a Python reference on 1,390,871 programs (824 solutions, same minimum index).
- Toy: learned costs plus one library op cut programs-to-first-hit by 1.7x, 23x and 672x on three held-out tasks; without the prior refit one task got 1.8x worse. The op was hand-given.
-
One week: OEIS
stripped.gz(33.7 MB), 80/20 split, arms from Levin brute force up to library + conditioned prior + lineage selection, 2^20 programs per task per iteration. Pass: ≥1.5x brute force held out at equal enumeration, ≥30% of new solutions use a learned op. Kill: ≤1.1x, or near-zero reuse, which Berlot-Attwell et al. found in two library learners (arXiv 2410.20274[20]). - Exciting if: solves keep rising per iteration from base ops plus compute, with recognisable invented concepts. The bar: Gauthier and Urban found 27,987 sequences from scratch (arXiv 2202.11908[19]).
Idea 4. Symbolic HGM (27 / 27; selfmod/designs/hgm-clade-symbolic.md, kernel selfmod/designs/hgm-clade-kernel/). This answers "what do DGMs do without the LLM".
- Agent = (solver program, meta-program that rewrites the child's solver and itself): Spector's autoconstruction in the Hyperagents shape.
- Tasks: program synthesis, and sorting networks with a complete 0-1 verifier and known optimal sizes (19/25/29/35/39 comparators for n = 8-12).
- Arms: greedy, DGM's rule, batched HGM, exact-CMP rollouts, evolvability; each with self-modifying and frozen meta; 30 seeds.
- Measured pilot: 34,816 evaluations in 13 s; 59 of 64 roots tie on own score while CMP ranges 6-19 (Spearman 0.36). 10^6 evaluations: est. 6.3 min JS, 25-35 s native.
- Exciting if: lineage credit beats own score over 30 seeds instead of one expensive run. Best role: the outer layer over idea 1's rule sets and idea 2's policies.
Idea 5. Prove once, mutate forever (25 / 25; selfmod/designs/typed-self-mod-gm.md). Mutators typed Expr<t> -> Expr<t> are checked once by Bend (0.27 s) and then only produce well-typed children. Measured: 2.2x useful children per unit of work at 8.5% acceptance; the gate took the good mutator and rejected three bad ones. Limits: Base has only the U32.add_comm law; @unsafe exits 0, so gate on the exact text "All terms check."; checker bug #1028 is open. Use it as a graft: the safe meta alphabet for idea 4 and a rule gate for idea 1.
Idea 6. Artificial-life soup (17 / 20; selfmod/designs/computational-life.md). Replicators emerged and Bend matched C bit for bit, but random-walk mutation finds bff replicators 10-25x more efficiently than the soup (arXiv 2607.01483[22]). Not a main line; harvest its evolved editors as meta operators for idea 4.
Two HVM-lane proposals, not designed yet:
-
SupGen proposes, the cube disposes. HVM4 enumerates small components with sharing; the cube scores explicit populations built from them over large input batches (
bend2-hands-on.md§4). - Lemma synthesis. Missing U32 lemmas in Base stall proof-carrying self-edits. SupGen-style proof-term search gated by the Bend checker would make idea 5 learned (unverified; not probed).
5. Recommended first experiment
One week: the compounding superoptimizer with exact Worth.
- Half a day: HVM4 SupGen vs cube on the same length-7 U32 enumeration, to measure where sharing beats brute batching before anything waits on HVM5.
- Days 1-7: idea 1's plan, with idea 2's paired counterfactual test as the rule admission and eviction test, and the hygiene kit in the kernel from day 1.
- In parallel: idea 2's de-confounded rerun (its days 1-3), which judge 1 wanted first and which reuses existing kernels.
Pass: zero unsound rules; ≥30% cost cut vs no rules and ≥10% vs peephole; ≥2x distinct functions per unit of compute in the next wave; one unaided closed form. Kill: no compounding, and the write-up says it is a plain superoptimizer.
Needs:
-
clang: optional for week one, required for native numbers.
apt-get install clang-18needs sudo via the farol gcloud route and your OK. Without it, 16 bun processes cover the week. - HVM5: not needed; HVM4 is public and runs here. HVM5 is private; a Taelin X post reportedly says it is done and about 5x faster than HVM4 (search text only, unverified). Early access would make the head-to-head the real test.
- API budget: $0; an LLM mutation arm is an optional ablation.
- Box: this box's 16 vCPU, under 200 MB of disk.
6. Risks and unverified items
Risks:
- Every "Bend enables it" claim is a JS measurement times an estimated native speedup until clang lands.
- Toy DSLs may lack headroom: 59 of 64 HGM roots sat at the floor.
- Testing is not proof for two-variable U32 rules; no z3 here and one U32 lemma in Base. Edge-value sets and exhaustive one-variable checks help.
- Pruning and early exits break the balanced-fork contract.
- Meta levels may stay degenerate, as with DGM-H's editable selection.
- Hard limits force chunking: fork depth 31, counts of 2^24, and idea 1's packed key caps length at 7 as written.
Unverified:
- All native BendRT and M4 Max speeds (est.).
- HVM5's status and speed (search text only).
- The canonicity-pruning factor; measuring it is idea 1's point.
- How many OEIS sequences keep 32 terms in [0, 2^31) (est. tens of thousands).
- Gumbel AlphaZero's sequential-halving details (search summary only).
-
Native soup speed: two estimates disagree 6x (about 140-150 vs 22-24 M steps/s sequential,
designs/computational-life.md). - Whether the paid Bender agent ships SupGen (a stated promise, https://bend-lang.com/bender[14]).
7. Sources
- [1] DGM: https://arxiv.org/abs/2505.22954 ; https://github.com/jennyzzt/dgm
- [2] HGM: https://arxiv.org/abs/2510.21614 ; https://github.com/metauto-ai/HGM
- [3] SICA: https://arxiv.org/abs/2504.15228
- [4] Gödel Agent: https://arxiv.org/abs/2410.04444
- [5] Hyperagents / DGM-H: https://arxiv.org/abs/2603.19461
- [6] GEA: https://arxiv.org/abs/2602.04837
- [7] SIFT: https://arxiv.org/abs/2609.19526
- [8] ASI-Arch: https://arxiv.org/abs/2507.18074
- [9] Sutton, The Bitter Lesson: http://www.incompleteideas.net/IncIdeas/BitterLesson.html
- [10] Bend 2.0.29 and the BendRT paper: https://github.com/bendlang/bend
- [11] HVM4 and SupGen: https://github.com/HigherOrderCO/HVM4
- [12] Taelin, SupGen + Fusion gist: https://gist.github.com/VictorTaelin/0b68673e0e85437baae32f7e08f1e50c
- [13] Taelin X post on HVM5 (search text only): https://x.com/VictorTaelin/status/2063392469195338129
- [14] Bender: https://bend-lang.com/bender
- [15] ExIt: https://arxiv.org/abs/1705.08439
- [16] Gumbel AlphaZero (search summary only): https://iclr.cc/virtual/2022/spotlight/6419
- [17] Ruler: https://arxiv.org/abs/2108.10436 ; https://github.com/uwplse/ruler
- [18] DreamCoder: https://arxiv.org/abs/2006.08381 ; Stitch: https://arxiv.org/abs/2211.16605 ; https://github.com/mlb2251/stitch
- [19] Gauthier and Urban: https://arxiv.org/abs/2202.11908 ; Alien Coding: https://arxiv.org/abs/2301.11479
- [20] Berlot-Attwell et al.: https://arxiv.org/abs/2410.20274
- [21] OEIS stripped.gz: https://oeis.org/stripped.gz
- [22] Random walk vs soup: https://arxiv.org/abs/2607.01483 ; Computational Life: https://arxiv.org/abs/2406.19108
- [23] Sorting-network sizes: https://bertdobbelaere.github.io/sorting_networks.html
- [24] Spector, autoconstructive evolution (search text): https://faculty.hampshire.edu/lspector/pubs/ace.pdf
-
Local research:
/srv/agent-data/home/workspaces/eurisko-study/research/bend2-status.md,research/llm-discovery-systems.md,REPORT.md,/srv/agent-data/repos/hub/wiki/bend2-fleet-research.md -
Local selfmod research:
/srv/agent-data/home/workspaces/eurisko-study/selfmod/research/dgm-lineage.md,gofai-self-mod.md,bend2-hands-on.md -
Local designs:
/srv/agent-data/home/workspaces/eurisko-study/selfmod/designs/(six design notes and judges.md)