Day 75 — 'what's in the bucket besides 2 apples?'
We flooded the chat with real questions and watched it bluff. Not fail — bluff, which is worse. 'What is in the bucket besides 2 apples?' got a confident token-bucket networking card. 'Want to play a game?' got a lecture about how the inside game targets officials. 'I want to go fishing for bass, what lures should I use?' got 'I can't tag along to go fishing.' Every one is the same failure wearing a different hat: a retrieval brain treats everything as a lookup, and keyword overlap will always find something to be confident about. So today was one long exercise in teaching it what KIND of question it's holding. The headline is the intelligence layer, brick one — a reasoning gate that catches state/count/negation word problems before retrieval and hands the model a state-tracking scaffold instead of a card. Verified: 'I put 3 apples in a bucket, then took one out — what's in there besides 2 apples?' → '1 apple.' And when the scaffold can't crack it, it abstains rather than falling through to the bluff. Intelligence is a scaffold, not a weight. Then the other half of the day: making it sound like it knows you — conversational memory recall, and emphasis, because 'I NEED you to leave right now' is not the same sentence as 'i need you to leave right now.'
“what is in the bucket besides 2 apples?”
The answer came back fast and confident and completely insane: a token bucket, the rate-limiting algorithm, retrieved from a networking card because the word bucket was in there.
That was the flood. We threw a few hundred real questions at the chat and read every reply, and the pattern wasn’t failure. It was bluffing — which is strictly worse, because a failure tells you where the edge is and a bluff hides it.
Four bluffs, one bug
- “want to play a game?” → a lecture about how “the inside game targets officials” (a political card, because game).
- “i want to go fishing for bass. what lures should i use?” → “I can’t tag along to go fishing.” It heard an invitation.
- “good! how about yourself?” → a Life Advice card.
- “what is in the bucket besides 2 apples?” → the token bucket.
Four different subsystems, one root cause: a retrieval brain treats every input as a lookup. And keyword overlap will always find something. There is no query so strange that TF-IDF returns nothing; it returns the least-bad match and the renderer says it with a straight face. Confidence is free. Being right isn’t.
So the whole day was one exercise: teach it to know what kind of question it is holding before it reaches for an answer.
The intelligence layer, brick 1
The bucket question isn’t a retrieval problem. It’s a reasoning problem — state, a count, and a negation (besides). No card contains the answer, because the answer is computed from the sentence itself.
So: looks_like_reasoning() catches state/count/negation word problems before retrieval fires, and
routes them to a state-tracking scaffold — decompose the problem, track the state through each step,
answer only what is literally asked. That last clause is the whole trick. “Besides 2 apples” is a
distractor engineered to make you answer the wrong question.
“I put 3 apples in a bucket, then took one out — what’s in there besides 2 apples?” → “1 apple.”
Not a networking card. And the honest part: when the scaffold can’t crack it, the reply is “that’s a reasoning problem I couldn’t work out with confidence — I’d rather not guess.” It does not fall through to retrieval, because falling through to retrieval is exactly how you get a token bucket.
Then we wired it into the live cascade — figurative → social → small talk → code → reasoning →
resolve() — so it’s the last gate before the retrieval loop that was doing the bluffing.
Honest boundary, stated up front: this is brick one, not a reasoner. Temporal problems, self-reference, and multi-hop chains are all still open. What shipped is a discriminator plus one scaffold. But it proves the shape:
Intelligence is a scaffold, not a weight.
The same 3B that bluffed the token bucket gets “1 apple” right when it’s handed a structure. We didn’t grow the model. We gave it a frame.
The other three bluffs died the same afternoon: an abstaining router now hands off to the knowledge bridge instead of being forced to pick a magnet skill; first-person “i want to…” plus an embedded wh-question routes to question, not invitation; invitation grounding only weaves in a fact that actually defines the noun; and the reciprocal “how about yourself?” is registered as the second half of a small-talk pair.
Tarot, rebuilt the werbos way
Same lesson, different corner. The /tarot skill had been leaning on qwen2.5:14b to improvise a
spread — a big rented model freewheeling, which is the thing this whole project exists to not do.
Rebuilt as capability = model × library: 480 gradeable cards (78 arcana × upright / reversed /
keywords / love / career / advice, Rider–Waite–Smith), and a composer that deals a seeded spread —
reproducible from the question — where every meaning is an exact hit in a (card, facet) index. Not
fuzzy retrieval, which can’t tell upright from reversed. No big model. Offline.
It also closes a loop from yesterday: self-study had flagged “can you do a 3-card draw” as one of its own failures. It studied it. We fixed it.
The other half — sounding like it knows you
A brain that doesn’t bluff is necessary. It isn’t sufficient. Two builds on the feel of a reply:
Memory recall. The chat had been injecting memory in bulk — dump the whole store into the system
context and hope. Now recall() surfaces the few memories relevant to this message (IDF-weighted,
with a light stemmer so hiking matches hike), so a reply weaves in the right thing instead of
reciting the file. Plus capture (turn a user statement into a memory) and an occasional, gated
“anything you want me to remember?” The loop: ask → told → remembered → referenced → feels known →
shares more.
Emphasis. “my house is on fire, what do i do” deserves:
I NEED you to leave right now, then call 911.
That’s high arousal rendered as typography. It works on both poles — stress and excitement (“that’s INCREDIBLE”) — and it’s a pure formatting pass: it only marks words already present in the reply, never adds advice, never changes meaning, capped at two marks. And it does nothing on chit-chat, because over-emphasis kills emphasis.
Sarcasm is the third register, rendered as italics (“oh great”), and here we were honest with
ourselves: sarcasm is not keyword-detectable. So it never gets sniffed — it only fires when the tone
label already says sarcastic. Guessing at sarcasm is just another bluff with better typography.
Then the chat UI had to actually render it, which it didn’t — **NEED** was showing literal asterisks.
A tiny hand-rolled inline parser (no dependency) now renders bold/italic/code and turns links into
anchors — scheme-validated to http(s)/mailto only, so a prompt-injected javascript: link stays inert
text.
The AHA
A wrong answer is a bug report. A confident wrong answer is a lie the system doesn’t know it’s telling. Every bluff we killed today came from the same assumption — that the next input is a lookup — and the fix was never a bigger model. It was asking what kind of question this is before reaching for an answer, and being willing to say “I’d rather not guess” when the honest answer is nothing.
Also shipped: mint_complex.py, a generator for layered answers (reframe → context hook → mechanism
→ validation → follow-ups) that weave in real user context — teaching the owned model to compose the
shape the composer will feed it at inference. And the stats page stopped reading all-zeros: the API was
scanning the home default instead of the configured archive dir, while the CLI happily reported 156
sessions from the right place.