July 31, 2026
v1.2.0-beta, and Two Workflows That Were Already Broken
The release two weeks of file-tool and context-window work was building toward finally shipped — alongside a threading bug that could freeze a whole conversation and two CI workflows that had been quietly failing the entire time.
Shipped v1.2.0-beta today. Everything from the last couple of weeks — the file tool split, the context-window fixes, the test audit — lands in this one.
Before tagging it, the version number itself needed fixing. Three places claim to say what release is running: a VERSION file the app reads at /health, pyproject.toml, and the git tag. They’d drifted — VERSION still said 1.1.0-beta because 1.1.1 got tagged without bumping it, and pyproject.toml hadn’t moved since 1.0.0-beta, two releases back. Three answers for one number is no answer at all. Set both files to match the tag and moved on.
Then killed two CI workflows, and this is the better story. One synced release notes from the product repo to the website automatically — except the website’s release notes are curated by hand, so an automatic sync was never the right idea to begin with; it just sat there doing unwanted work nobody asked for. The other published the installer to a separate repo, and its one green run turned out not to be a successful publish — it was the change-detection gate correctly deciding to skip the job, because the credential it needed to actually push had already stopped working. A green check that means “I didn’t try” is worse than a red one. Both gone now: the installer is served straight from this repo by a redirect, so there’s nothing left to sync.
The bug worth explaining: reply inside a thread, and the main conversation would sometimes refuse to send a new message, sitting there as if something else was still working. Cause was an identity collision. The main conversation and a thread both track “is something running here” by scanning their own container for work in progress, keyed by the turn a piece of work belongs to. A thread reply continues the exact same turn its thread was opened from — so the reply’s work got stamped with an ID the main conversation recognized as its own, and read it as “I’m still busy” when it wasn’t. Fixed by giving every lane — the main conversation and each thread — its own independent identity instead of sharing one. Threads were already isolated from each other; now the main conversation is isolated from all of them too.
Smaller but worth a mention: the number in the usage dashboard that shows what’s been billed to background thinking versus what you actually asked for — the two labels had drifted apart from the raw data underneath them across a few renames, to the point where the stored value and the label shown on screen didn’t use the same words for the same thing. Lined them up end to end, then found the meter reading that data had zero test coverage — only the write side did. A dropped filter or a broken date range there would have quietly mis-reported every number on the dashboard with nothing going red. Closed that gap.
Rest of the day was cleanup riding along: a stale example in the internal ability vocabulary got fixed, a comment explains why a field on one ability class looks unused but isn’t, and mcp_manager — the thing that tracks which external tool servers are connected — joined the small set of abilities that are always available, so Chalie always knows what’s plugged in without having to go looking.
Next release is a clean slate: no version drift, no fake-green CI, and one confirmed threading bug fewer to worry about.
-
Shipped v1.2.0-beta, closing out the last two weeks of file-tool and context-window work
-
Fixed three disagreeing version numbers (a stale file, a stale config, and the tag) down to one
-
Deleted two CI workflows that looked fine but weren’t — one syncing release notes nobody wanted synced, one publishing an installer with a dead credential, its only green run actually a skipped job
-
Fixed a threading bug where replying inside a thread could make the main conversation falsely appear busy and refuse to send
-
Renamed a spend-tracking column to match what it’s actually called on screen, and added test coverage for the read path that had none