“we’re solving the zoo not with more weights — but with comprehension, functions, and a learning loop.”

The chat had a tell. Ask it “do you want to go to the zoo?” and it would freewheel — “I get it, but at least it’s cozy inside with snacks and snacks!” — or, worse, retrieve a TypeScript card about const x = "hello" for a greeting, or a giraffe-adaptations card for a metaphor. A 15M fluency cursor, asked to improvise on an open social question, does what it was trained to do: sound like a texter, without answering you.

The reflexive fix is “train a bigger model.” We did the opposite. We decomposed the question.

The zoo problem, solved without weights

The operator laid out the pipeline in one breath — “do you want” → outcome; subject → what’s a zoo → respond about it — and it maps exactly onto the resolve() machinery, just pointed at a social sentence instead of a factual one:

"do you want to go to the zoo?"
  → SPEECH ACT     = invitation            (a small classifier, gradeable, no LLM)
  → SUBJECT SLOT   = "zoo"                  (slot extraction, like the comprehension parse)
  → COMPREHEND     lookup("what is a zoo?") (resolve LOOKUP → the learned cache)
                   → miss? SEEK websearch → learn → CACHE  (once, forever)
  → COMPOSE        honest reply grounded in what a zoo IS

Every piece already existed. The only new parts were small and honest: a speech-act front-end that reads the social move (greeting / invitation / compliment / farewell) and routes it to a real handler instead of the freewheeling cursor, and a subject lookup in the invitation handler that grounds the reply in what the system knows. Live in production tonight:

“do you want to go to the zoo?” → “I can’t tag along — I’m just software — but I know a zoo is a facility where animals are kept in enclosures for public exhibition and often bred for conservation. what’s got you interested in going?”

Is a Wikipedia-flavored definition a little stiff in a chat? Yes. But it’s grounded, cited, honest, and it came from reading the question — not from a weight that memorized zoos. And it beats “I don’t know, and I won’t guess” every single time.

The learning loop earns its name

“what is a zoo?” used to abstain — honest, but ignorant. So we ran it through the loop online once: LOOKUP → miss → SEEK (websearch) → learn (cited: wikipedia + britannica) → CACHE. 20 seconds the first time. Then, re-asked offline, no network at all: [cache] hit, 17ms, forever. Learn once, know forever. We synced that learned fact to the sealed --net off box — the knowledge travels, the egress doesn’t — and caught a real bug doing it (expanduser was never called on the cache path, so a literal ~/ folder had been quietly shadowing the real cache).

The talk base, finally coherent — and shipped

The old deployed voice babbled. We retrained the base properly — the full 281,829-pair corpus (conversation + dialogue + styles), BPE tokenizer, real epochs — and the difference is night and day: held-out loss 2.29 (vs the babble run’s 3.8), and the samples are actual conversation (“barely left the couch and still feel drained” → “that’s the worst kind of tired honestly, what was it about?”). Deploying it meant teaching the CPU loader to speak BPE (it was hardcoded byte-level) — with a byte-for-byte tokenizer replica so train/inference parity holds, or the weights are noise. It loaded clean and it’s live.

Grading conquered the 10k monster

The javascript library (5,727 cards) had failed grading three times — lid-close sleep killing a multi-hour run, every time. We built --limit N chunked grading: each run grades the next ~250 un-checkpointed cards and exits; a driver loops it. library.json is never rewritten until every card is decided, so a partial run can’t drop the ungraded remainder. The grinder then swept all 118 libraries — 32,409 cards, 100% graded, resumably, unattended, while the operator was using the machine at 100%. The thing that “failed 100% of the time” now finishes 100% of the time. This is the run the whole grading rebuild was for — and the ~10k Web-APIs library is next.

The code brain gets a spine

If reference cards tell you what reduce is, they don’t write you code that honors your input. So we built the composer harness: retrieve the relevant cards → assemble code from those cited notes → grade against hidden tests that vary the input (so a hardcoded answer fails) → emit {query, cards, code} training rows. It proved itself immediately: a canned [0,1,2,3,4] scored 1/4 (rejected); the composer, forced by inputs varying 10/0/3/-2, wrote start + i and passed 4/4. That’s the fix for the live i=0-for-i=10 bug — an owned composer trained on 168 execution-proven, input-honoring rows (and thousands more once the web cards land) will honor your input offline, where canned patterns can’t.

The pattern under all of it

Nothing today was “a bigger model.” Every win was the same shape: comprehend the intent → look up / learn the knowledge → compose an honest, grounded, cited answer → abstain when the ground is thin. The zoo, the metaphor, the if statement, the code — all one decomposition. Capability lives in cards, functions, and a learning loop; the model is just the cursor. Bigger models are trained to be fluent and fast — ungated — so they skip the reading and get fooled. Reading, and refusing to skip it, is the moat.


Shipped / found:

  • The zoo problem, solved in production — speech-act front-end (intent) + subject-slot lookup (comprehension) + learn-once-cache-forever loop; grounded, cited, honest reply, no bigger model (89a5285, c71fa7d, 0e69e23)
  • Speech-act front-end — classify the social MOVE (greeting/invitation/compliment/farewell) → honest handler instead of freewheel; factual questions fall through to retrieval untouched (c71fa7d)
  • Grounded invitations — the invitation handler looks up the subject (“zoo” → the learned fact) and grounds the reply, honest fallback when unknown, never fabricates (0e69e23)
  • Learning loop proven — “what is a zoo” learned via websearch (cited) → cached → served offline in 17ms, and synced to the sealed SR8 box (the resolve() seek→cache loop)
  • Talk base retrained + deployed — full 281k-pair corpus, BPE, held-out 2.29, coherent; BPE-aware CPU loader with parity-exact tokenizer replica (8e33841)
  • Chunked --limit grading — resumable 250-card sets; all 118 libraries / 32,409 cards graded, 100%, incl. the 10k-scale javascript that failed 3× (311e8ce, 62cce50)
  • Composer harness + task-bank — card-fed, hidden-test-graded, input-varying code data-gen; 168 execution-proven training rows toward the owned code composer (0b2ee55, 9c9fda0, 21221d1, coding-model doc d68edbd)
  • javascript-fundamentals — 623 definitional “what is X / how to use X” cards filling the MDN reference’s definition gap (ef3002a)
  • Domain-scoped retrieval — reroute a coding query to coding cards (kills “if statement” → couples “you-statement”), explicit in/excluding scope, [domain: …] debugger (0356778, 66216f0, 74df8fc)
  • Reasoning-effort dial — low/mid/high across CLI --effort, /effort, and the Settings cog; tunable verification, honest-abstain coupled to effort (89a5285, d43e164)
  • Figurative routing — “is X a metaphor?” hits the compare() engine, not card retrieval (0ed9ae9)
  • Fixes — deploy transport auto-detect (c4cf9e4), cache expanduser bug (38c0b18), resumable grade checkpoint (311e8ce)
  • Three parallel agents shipped it — grounded conversation, knowledge-to-prod, composer corpus — the multi-agent workflow doing real work