A user opened a session and asked why doctor was reporting v0.11.4 when the agent showed v0.20.x. Curtis traced it. The doctor wasn’t wrong — the workspace marker really was at v0.11.4. What was wrong was that there were three different version concepts living in one Soma install, drifting independently, and only two of them had ever been visible at once.
This release made all three visible. With one command. And every drift comes with the next step baked in.
The three layers
The CLI on npm is the thin bootstrap that ships as meetsoma. It’s barely a hundred KB — its job is to find or install the runtime, then hand off. The agent runtime at ~/.soma/agent/ is the real thing: extensions, protocols, body templates, the prompt machinery. The workspace marker in <project>/.soma/settings.json tracks which migrations have run on this specific project. Three things, three lifecycles.
A user can be on the latest CLI, ahead of npm on the agent (dev install), and behind on the workspace (settings.json says v0.11.4 because no migration was needed since). Each combination tells a different story. The old soma update only told the first one — CLI vs npm — and silently shrugged at the rest.
What it looks like now
$ soma check-updates
Version snapshot:
CLI (meetsoma) v0.3.3 ⬆ stale (npm: v0.3.4)
Agent (soma-agent) v0.20.1.1 ✓ dev-ahead
Workspace (.soma) v0.11.4 ⬆ marker lag
→ CLI stale: run npm i -g meetsoma
→ Workspace marker behind agent: run soma doctor
Every layer has a status: aligned | dev-ahead | stale | marker-lag | no-workspace. Every drift carries the recovery command, so there’s no closed end where the user has to ask “ok, what now?” Doctor itself learned a new trick in the same arc: when no migration is pending and the marker is behind, it silently advances it — so most “marker lag” cases resolve in one step and the next snapshot reads clean.
Where the truth lives
The whole thing rests on one new function. getVersionSnapshot() in npm/lib/detect.js returns a struct with all three layers, the dev-install detection, and a flag for whether everything’s aligned. soma update, soma doctor, and soma status all read from it. One source of truth, one comparator, one place to fix when something changes.
The comparator matters. '0.3.4' > '0.20.3' is true lexically, false semantically — the kind of bug that crept into three places this arc, all in the same week. Now everything flows through semverCmp (CLI side) or versionCompare (agent side), both N-segment safe so a hotfix like 0.20.1.1 compares correctly against 0.20.1. The pattern is muscle memory now, written down at .soma/amps/muscles/version-comparison.md so it doesn’t re-enter the codebase.
Why this matters for Team Soma
The auditor child — introduced in Team Soma — reads version snapshots across recent sessions and flags layers that have been silently drifting. Without the snapshot it couldn’t see them. The same pattern that made soma check-updates legible to humans makes it legible to the auditor. Every signal we surface to one becomes a signal the others can use.
That’s the version-of-the-version story: an install that knows what it is, all the way down.
Changelog: Unreleased · SX-489 Related: Team Soma — the larger arc this ships inside.