June 23, 2026
v1.0.0-beta ships behind a rebuilt discovery brain
Chalie hits v1.0.0-beta on the back of a rebuilt tool-discovery cascade and a fix for a loop the reasoning engine could get stuck in forever.
I tagged v1.0.0-beta today, and I wanted the tag to mean something — not a version bump for its own sake, but the last hard problem in the reasoning loop closed out first. Chalie is constantly asking two questions: what tool do I need, and did that tool actually work. Today fixed both.
Tool discovery was the bigger of the two. find_tools and find_skills used to score results with keyword and vector search fused together behind a relevance floor, and that floor was quietly killing correct answers. Ask Chalie something like “all available tools and capabilities” — no tool name, no exact phrase, just intent — and the old system returned nothing. The floor treated a real semantic match as noise because it didn’t also look right lexically. I replaced it with a single cascade: strip stopwords, try an exact name match first, then a keyword search scoped to just the tool’s name (substring-matching, so partial names still hit), then a full semantic search over everything the tool does, and only after all of that comes back empty does it honestly say “not found.” No score fusion, no floor to sneak under — the first rung that returns something wins. I wrote a test pinning the exact failure I’d seen: a vague prose query has to surface the docs tool through the semantic path alone. It fails against the old code and passes now — a regression test that reproduces the bug, not one that just checks the happy path.
The second fix is what happens when a tool call goes wrong. Chalie’s reasoning loop — perceive, remember, reason, act — has no hard iteration cap by design; I don’t want an arbitrary ceiling cutting off a task that’s legitimately close to done. But that means a genuinely broken call could spin forever instead of correcting course. I found exactly that in file_write’s read-required guard: it checked whether a file had been read against the wrong row in the tool-call history, so a read on any step after the first in a turn never satisfied it. The model would read the file, get told it hadn’t, read it again, and never escape. The guard now checks the whole turn’s history properly, so any read in that turn counts, plus a path fix so a ~/-prefixed read matches what got recorded. More important long-term: the dispatcher now watches for a tool returning the identical error twice in one turn and injects a one-time nudge to re-check the tool’s schema or escalate to the user instead of retrying blind. It’s a soft brake, not a cap — it doesn’t stop the loop, it refuses to let the model repeat a mistake without noticing.
Shipping v1.0.0-beta on top of this felt earned rather than arbitrary. A product that reasons and acts on your behalf is only as trustworthy as its ability to find the right tool and recognize when something’s actually broken — both got measurably better today, backed by tests that fail on the old behavior and pass on the new. Now that discovery doesn’t silently drop valid intents and the loop doesn’t spin on repeat failures, adding more tools and more autonomy stops being a safety risk and starts being pure surface area. That’s the direction from here — more tools, less babysitting.
-
Tagged v1.0.0-beta after reworking tool/skill discovery and closing a reasoning-loop-guard gap
-
find_tools/find_skillsnow run a precise-to-broad cascade (exact name → name-scoped keyword search → full semantic search → honest not-found) instead of a fused, floored hybrid score that could silently return nothing -
A regression test pins the exact failure that triggered the rework: a vague prose query with no tool name now correctly surfaces the docs tool via semantic search
-
Fixed a bug where
file_write’s read-check looked at the wrong history row, letting the model loop indefinitely between “read the file” and “you haven’t read it” -
Reasoning-loop dispatcher now nudges the model to re-check or escalate when a tool repeats the exact same error in one turn — a soft brake on an intentionally uncapped loop