Research Log
Every experiment, step by step — what we trained, how we measured it, and what the numbers actually said (wins and losses). All runs are local, $0, and reproducible.
2026-07-17 · Report #26
The spec named nothing
Yesterday I switched off a prompt default because its benefit refused to reproduce. Today I found
out why it had ever seemed necessary: it was a patch for a spec that named zero of its
test functions and never said where a short code comes from — so the model reached past the API,
planted a link, and asked for a code it invented. 404, against handlers that were perfectly
correct. Naming the eight tests and showing six lines took the suite from 2 tests to 8 and killed
the failure class at the root; with the spec fixed, the default measures an exact null, four arms
out of four. Then a second spec refuted the generalisation I was building on — and both of the
day's wrong turns came from my own greps, not the model. All three real gains were invisible to
green and to coverage, which are the only two numbers this project reports.
2026-07-16 · Report #25
The number belonged to the process
I shipped a prompt default in the morning on a clean A/B — 42.4% coverage without it, 75.4% with
it, same session, arms isolated — and turned it off by evening. Nothing about the rule changed in
between; the baseline did. Chasing that number cost three retractions in one day and
produced the measurement this project needed: the server is deterministic within a
process and different across processes, so the +33 that bought the rule was measured
against a baseline belonging to one process's state, not to the model — and no A/B I have ever
compared across sessions was comparable. Along the way best-of-N turned out never to have worked:
2,905 draws, 320 dirty redraws, zero rescues, while the project's own notes marked it
done. What survives is worth more than the rule: the model drops tests a spec names, and
coverage cannot see it.
2026-07-15 · Report #24
A stack of masks
I went in to answer one question — were the week's gains the machine generalizing, or ten specs
memorized? A brand-new domain, a double-entry ledger the corpus had never seen, answered a better
one. It did not fail once; it failed in a stack, each defect masking the one beneath it,
because a compile error in a dependency hides every package that imports it. Peeling it took eight
runs. Two layers were the machinery's and it cleared them live — a package-qualifier gate, and the
deaf-routing widener this same session had taught to hear
money.Money. Underneath was a
runtime long tail: every run broke a different domain method the spec had described instead
of shown — a sentinel, a deadlock, a balance read off the wrong object — and each fell to showing the
code. One layer was a deadlock the model could not fix; the deepest was a spec contradiction no model
could ever satisfy, invisible for the entire experiment because the code never ran far enough to reach
it. Green twice, at 84.9%. When the code finally runs, the question is not whether the model overfit —
it is whose bug you find, and mostly it was not the model's.
2026-07-15 · Report #23
One run is not a green
Yesterday's ten greens were ten single rolls of a stochastic model, and this project's bar is two.
Re-running all ten earned the number — and the shape of the result proved two things at once:
every spec I had touched gained (+11.2, +13.5, +11.8), every spec I had not
came back flat to the decimal (88.8 → 88.8, 88.0 → 88.0). The same measurement that confirmed
the gains ruled out a regression in the rest. Then I got this report wrong: I watched two defects
vanish from the hardest spec and credited the model — and the log had named two gates on the
very next line. An outcome does not name its cause. In a report arguing "measure it,
do not believe it", I asserted something I had not measured.
2026-07-14 · Report #22
Four bugs under a green suite
Coverage is not a metric. It is a bug detector. Chasing uncovered blocks across ten Go backends
turned up a
paginate that panics on any ?offset=-1 and takes the server
down; a validator that never trimmed, so a title of three spaces was accepted; a validator that was
never called — not by Create, not by Update, dead code behind a status-code mapping with
nothing to map; and a router missing POST /projects, so a project could never be
created and half the API answered 405. All four shipped. All four sat under a suite that had been
green for a week. And all four were hiding in the same place: a branch the spec never named.
2026-07-13 · Report #21
Everything the spec does not say, the model says for you
I went in to raise coverage in one package. I came out with a live runtime panic that had been
shipping green for a week —
paginate had no negative-offset clamp, so any request with
?offset=-1 took the process down, and the spec itself said "never panic". The model had
written that guard correctly in one run and dropped it in another, and nothing noticed, because
nothing ever asked. Then three distinct ways a passing test can be a lie, all of them from the spec:
an assertion that cannot fail, one that cannot run, and one that was never asked for. And a fix loop
that had spent a week throwing away half of every default this project ever wrote. Six escalating
versions of a prompt rule could not stop one bug. Two go/ast gates did — and the deterministic layer
doubled, from 5 red projects driven to green with no model involved, to 10.
2026-07-12 · Report #20
The tests were wrong. So was the ruler.
The coverage sweep the last report promised. Two of three specs went red — and not one of the reds
was the model's fault: every one was a test that no correct implementation could have passed. An
invalid state made unreachable by the spec's own defaulting rule; a row expecting nil inside a loop
that demands an error; and a request replayed after its body was already drained, so a handler that
maps ErrExists to 409 perfectly correctly answers 400. That last one had a rule against it already —
a rule that named the mechanism and predicted the exact wrong status code — and the model walked into
it anyway, because the rule named the body and the model reused the request. A gate
is only as good as the sentence it listens for; a default is only as good as the noun the model acts
on. Then the ruler itself lied three times, the last time because the line-shifting gates poison their
own scoreboard — caught only because the number it produced was arithmetically impossible.
2026-07-12 · Report #19
A gate is only as good as the sentence it listens for
Three specs went red. In all three the gate already existed, and in all three it repaired the file
perfectly the moment it was handed it — and never fired, because the compiler had reported the same
defect in a sentence it wasn't listening for. From the outside, all three looked exactly like a model
that isn't good enough. Then the failure artifacts the harness used to delete become a corpus, and the
corpus becomes a test suite: the gate chain now drives five of eight red projects all the way to green
on its own, no model invoked — a number that was zero a week ago, and was reported as zero. And a new
measurement that is not flattering: the biggest projects are green while running a quarter of their
own code.
2026-07-12 · Report #18
The gates were breaking the files they were repairing
Every spec in the suite, one run each, no retries: 19 of 22 green. Then the three failures get
read, and the last one is not a model failure at all — the fix loop kept dying on a line no model
had written. The gates had written it. A gate that inserts an import shifts every line below it,
and the next gate, still holding the compiler's stale numbers, repairs the wrong line. True since
the day there were two kinds of gate, and it presents as "the loop failed to converge" — which
reads exactly like a model that isn't good enough. The chain is split into phases; the property
test written to pin the split fails on its first run, three more times. Also: the last hard compile
class finally gated (a two-value call in a single-value context, repaired off the enclosing
signature), and a green build found to be hiding an empty file the spec had asked for.
2026-07-11 · Report #17
The backlog was empty — auditing the gates, then moving upstream
Gates get written one at a time, by whatever failure is in front of you — a fine way to start and
a poor way to continue. So before writing a sixth, I audited the five against 138 real broken
artifacts and ranked what was left. The ranking collapsed: counted by distinct spec, no ungated
compile class is hit by more than two. The mechanical surface is covered; stop hunting gates. The
audit also caught the harness deleting its own evidence (every run rm -rf'd the artifact a gate
was verified against), and caught its own first ranking being wrong. With no gate left worth
writing, the leverage moved upstream: a prompt default that had been teaching the model the
failing pattern for six specs running, and a spec linter that — replayed against history —
catches 4/4 of the runs that actually failed.
2026-07-11 · Report #16
Renaming a single letter — the gate that needed a parser
One stochastic failure was left standing in the suite, and it was a single shadowed identifier:
for _, t := range tasks steals the *testing.T and every t.Fatalf stops compiling. It
is the one gate a regex cannot write — the same letter means the Task on one line and the tester
three lines down — so it runs on a real go/ast scope walk and refuses the file on anything it
cannot resolve. Then we ran it, and it never fired: the compiler was stopping earlier, and the
shadow was invisible behind it. Pulling that thread found three defects in the machinery, none of
them in the model — a fix loop routing to the wrong file, a root-cause widener that believed the
shadow was a genuinely missing method, and a regex that had been quietly truncating symbol names —
and a spec that was manufacturing its own failure by demanding a name the model reserves for
something else. Fixing the ask greens the spec 2/2. The subtractive probe is recorded as
inconclusive.
2026-07-10 · Report #15
Breadth: three new domains join the suite
After two gates and a set of defaults, breadth: point the system at Go the suite never touched.
Eight new stdlib-only specs — LRU cache (container/list), min-priority queue (container/heap),
generic Set (type parameters), recursive-descent expression evaluator, channel-based pub-sub
event bus, word-packed bitset, custom JSON codec, and a crash-recovering write-ahead-log KV
store. Seven greened first-generation on the unchanged 7B, including three picked as small-model
traps (bit off-by-ones; the MarshalJSON that calls itself forever; a log replay that must survive
a reopen). The LRU surfaced a runtime panic the compiler waved through — a hand-built *list.Element
double-wrapped by PushFront — an idiom for a prompt default, not a gate. A regression sweep
confirms the session's gates and defaults break none of the existing suite.
2026-07-10 · Report #14
A nudge is not a gate: promoting the authoring rules
Report #13 closed the suite by hardening each spec by hand — but a lesson in one spec's YAML
only helps that spec. This promotes three recurring authoring rules (field-named struct literals,
interface/impl parity, register-the-method-value) into the Builder's permanent, conditional prompt
defaults: unit-tested, regression-safe, 171 tests green. Then it tries to prove they're load-bearing
by deleting the hardening from a spec — and the probe fails, usefully. It separates what a prompt
nudge can carry (idioms) from what it can't (which methods must exist — a completeness failure the
model commits by dropping a method from both an interface and its impl, which only a deterministic
gate can catch). A negative result that marks exactly where the next lever goes.
2026-07-09 · Report #13
The sweep: every backend in the suite goes green
Report #12 cleared workapi by making one test's ask explicit. This turns that lever loose on the
rest of the suite: the six Go backends the system could never autonomously green — logstats,
shortener, kvservice, tasks-api, ratelimit, workapi — are now all green, the 7B completely
unchanged. Almost every "model ceiling" was an under-specified ask made explicit (a dropped step,
an uncomputed test oracle, a positional literal, a mega-test, a missing method, a mis-wired router,
a clock injected after construction); the genuinely mechanical ones became two new deterministic
gates. The moat is the system, and it builds real Go backends green for $0.
2026-07-09 · Report #12
The wall was the shape of the ask: workapi goes green
Report #11 peeled our hardest spec — an eight-package concurrent, bearer-authed backend —
to build-clean and vet-clean and stopped at one wall we called the model's own ceiling: the
router integration test. It wasn't the model's ceiling. It was the shape of the ask — one long
function demanding thirteen cases exceeded the 7B's single-function synthesis budget. Split it
into ten small focused per-endpoint tests — better Go practice anyway — and the same unchanged
champion writes every one correctly. workapi goes fully green: build, vet, and test-race across
all eight packages, model untouched, reproduced from scratch, $0.
2026-07-08 · Report #11
The algorithm composes: peeling an eight-package backend to the ceiling
Report #10 shut the door on making the model bigger, so we pushed the other lever all the way.
On the hardest spec — an eight-package concurrent, bearer-authed backend — six deterministic gates
and verified retrieval contracts, model completely unchanged, peeled its walls one by one until it
compiled and vet-passed clean across every package, stalling only at the documented 7B
integration-test-logic ceiling. The champion's green backends stayed green (regression-checked).
Plus three ways a retrieval corpus quietly poisons itself — ranking contamination, name collision,
helper leakage — each caught and fixed.
2026-07-08 · Report #10
The wheel overfits at long sequence
Report #9 named the next frontier: make the hard, large backends pay into the self-distillation
set with a longer training budget. We tried it — sequence length 8192 to keep the big cross-package
prompts. The budget worked (58 → 74 pairs, workapi included); then the model overfit them and
regressed — 27/48 and 23/48 on the unseen bench vs the 33/48 champion — and still failed the spec
it trained toward, at the same middleware wall. An honest negative: the champion stands, and the
remaining wall is the algorithm's, not the model's.
2026-07-07 · Report #9
The wheel closes: the model learns from its own verified output
Eight reports said the moat is the algorithm, not the model — but the goal is the best
Go model. So we closed the loop: the Builder's compiler-verified green runs become training
data and the model learns from its own output. Turn one regressed (14 pairs → 26/48); with
diversity and a longer budget, turn two passed the champion — 33/48 vs 31/48 on the unseen
bench, and still 3/3 on the project, converging cleaner. The first net gain from on-policy
self-distillation, at $0.
2026-07-04 · Report #8
The model's half wasn't training — it was retrieval
Report #7 blamed the last gap on the model and bet on pretraining. We ran the bet:
two DAPT recipes came back net-negative and a four-times-bigger base was rejected —
while the exact semantic gap that needed 20 hand edits fell to two verified retrieval
examples, model unchanged. All four backends are now autonomous 3/3. The moat is the algorithm.
2026-07-02 · Report #7
The algorithm scales: a six-package production backend from a 7B
Same 7B, never retrained — 7→11→13→16 files, one package to six, by turning every
recurring failure into a deterministic gate. Three specs fully-autonomous green; the
fourth stopped 20 human lines short, and the gap is precisely the model's half of the
bargain: semantic expected values. That half is now in (free-GPU) training.
2026-06-29 · Report #6
Data was the lever: grounding beats the SFT at the project level
Base vs specialist through the same loop on a real HTTP service — both stall at 2/3. The fix wasn't a
bigger model or the fine-tune; it was two verified retrieval examples (→ 3/3). The corpus, not the
algorithm, was the bottleneck.
2026-06-29 · Report #5
The algorithm runs: specialists + agent loop = a green backend
Two trained Go specialists served live ($0, MLX), wired into the Builder with role-routing — one
writes the code, another the tests. It builds a verified backend first try (score 3/3). A second spec
exposes the real gap: the base model's knowledge, not the scaffolding. Plus two shipped upgrades.
2026-06-28 · Report #4
On a harder benchmark, the picture sharpens
We made the benchmark harder to cut noise. Clean result: a code-specialized 7B beats a general one
robustly (+3/+4) — but the win is the base, not our fine-tuning. The lever for code-gen is base
choice + the agent loop.
2026-06-28 · Report #3
The guild, measured: three specialists, three lessons
All three Go specialists trained and benchmarked, $0. One clear win (go-test +2), one marginal
(go-dev), and one honest task-mismatch (go-review) that taught us to measure each specialist on its
own job.
2026-06-28 · Report #2
Where specialization actually pays: the go-test model
The go-test specialist beats its base at catching planted bugs (8/13 vs 6/13) on a mutation-testing
benchmark — a clearer win than code generation, and a lesson in where small-model specialization pays.
2026-06-28 · Report #1
The first GuildLM Go specialist, measured honestly
Trained a go-developer 7B locally for $0. On a 19-task hidden-test benchmark it beats a general 7B
(15/19 vs 12/19) — the thesis validated. Plus an honest negative: the 14B base did worse, not better.