← Research log
Report #15 · 2026-07-10

Breadth — three new domains join the suite

Report #14 built two gates and sharpened the taxonomy — idiom → prompt default, compiler-named defect → gate, spec knowledge → spec. The obvious next move is breadth: point the whole system at Go the suite had never seen. Seven new stdlib-only specs, each a different muscle — an LRU cache on container/list, a min-priority queue on container/heap, a generic Set on type parameters, a recursive-descent expression evaluator, a pub-sub event bus on channels (the one concurrency the suite had only ever tested through mutexes), a bitset on word-packed bit manipulation, a custom JSON codec (the infinite-recursion trap), and — the hardest probe — a write-ahead-log key/value store that recovers its state by replaying an on-disk log. Seven of the eight greened on the first generation. The one that didn't — the LRU — surfaced a residual worth the whole exercise.

Three muscles the suite hadn't used

SpecNew muscleResult
priorityqueuea full heap.InterfaceLen/Less/Swap plus the pointer-receiver Push/Pop with any assertionsgreen, first generation, 33s
genericsetgenerics — Set[T comparable], a top-level New[T]() (methods can't add type params), non-mutating Union/Intersectgreen, first generation, 30s
exprevala recursive-descent parser — tokenizing, operator precedence, left associativity, and error paths (div-by-zero, missing operand, unbalanced parens, trailing junk)green, first generation, 40s
eventbuschannel concurrency — per-topic buffered subscriber channels with a non-blocking send under lock (select … default) so a slow subscriber can't deadlock the publishergreen, first generation, race-clean
bitsetword-packed bit manipulation — i/64 word index, 1<<(i%64) mask, popcount via math/bits, slice growthgreen, first generation
jsoncodeccustom JSON marshaling — the recursion trap (marshal a wire struct, not the type itself), value-receiver Marshal + pointer-receiver Unmarshalgreen, first generation
walkvdurability — an append-only write-ahead log with crash recovery by replaying SET/DEL records on open (last-write-wins), os+bufio file I/O under a mutexgreen, first generation, race-clean
lrucachecontainer/list recency ordering + a map + a mutexgreen after one new default (below)

The seven that greened cold are the point of the whole "system, not a model" thesis: an unchanged 7B, handed a clear spec and the accumulated defaults, wrote a correct heap, a correct generic container, a precedence-respecting parser, a deadlock-free channel bus, correct word-packed bit math, a recursion-safe JSON codec, and a crash-recovering write-ahead log on the first try — domains nowhere in its fine-tuning corpus. Three were chosen precisely because they are small-model traps (bit off-by-ones; the MarshalJSON that calls itself forever; a log replay that must survive a reopen); the explicit spec plus the accumulated defaults walked the model straight past all three. The synthesis ceiling that shows on multi-package integration simply does not appear for a well-specified single-package library, however unfamiliar the domain.

The LRU residual — a runtime panic the compiler waved through

The cache built clean and vetted clean, then panicked under test:

panic: interface conversion: interface {} is *list.Element, not *lru.entry

The cause is a genuine container/list trap:

newElement := &list.Element{Value: &entry{key, value}}   // hand-built an Element…
c.items[key] = c.ll.PushFront(newElement)               // …and PushFront wraps it AGAIN

PushFront takes the value to store and creates the *list.Element for you. Hand it a *list.Element and it double-wraps — the stored element's Value becomes another *list.Element, so a later el.Value.(*entry) blows up. Crucially, the compiler accepts this: PushFront takes any, so the type error only exists at runtime.

Which bucket? An idiom, so a default

Report #14's taxonomy answered it immediately. This is not a compiler-named defect, so it isn't a gate — and it can't safely be one anyway: the wrong Element hides behind a local variable, so there is no crisp PushFront(&list.Element{…}) token to rewrite. It is an idiom the model doesn't know, which is what a prompt default is for. So container/list usage now carries one: PushFront/PushBack take the value and return the element; never hand-build a &list.Element{Value: v}; read a value back with el.Value.(*entry). It fires only on files whose purpose uses the list — targeted, not a tax on every prompt. With it in place the re-run greened in 70 seconds: el := ll.PushFront(&entry{...}), and a second run reproduced it — 2/2 green with the default, where the un-nudged generation had panicked.

Eight new domains, all green; one new conditional default; the Builder's test suite at 193, corpus 36/36, the 7B untouched. And the new machinery is safe on the old work: a regression sweep re-ran taskapi, usersapi, jsonapi and ratelimit with every gate and default from this session active — all four still green. The loop that built the gates is the same loop that grows the breadth: run it, read the residual, and sort it into the bucket it belongs in — gate, default, or spec. The best Go developer is a system, and the system keeps learning new rooms of the language for $0.

All training, serving, benchmarking and Builder runs are local on an M1 Max with Apple MLX — total cloud spend: $0. The specs, the defaults, the gates, the verified retrieval corpus and the Builder loop: github.com/guildlm/builder.