Skip to content

Changelog

What shipped, what changed, version history.

All notable changes to the Soma agent are documented here.

Format follows Keep a Changelog. Versioning follows Semantic Versioning.


[Unreleased] —

[0.41.2] — 2026-07-17

Maintenance release — nothing user-facing. These notes are written retroactively: v0.41.2 shipped without any, because the step that promotes pending entries into a version section failed silently and the release went out anyway. That step now fails loudly instead.

The only code change was an internal delegation backend that isn’t yet reachable from the tool set — so there is nothing here to try. It will be listed in the release that wires it up.

[0.41.1] — 2026-07-17

Fixed

  • Leanstral models no longer error on reasoninglabs-leanstral-* now send reasoning_effort instead of promptMode:"reasoning", which the Mistral API rejected with 400 code 3051. (Site J patch)
  • Runtime no longer breaks after a Pi bump syncsoma-dev sync main now runs npm install when a merge changes package.json/lockfile, before rebuilding dist. Prevents the version skew that crashed boot with this.models.getAvailable is not a function (0.80.10 dist on 0.80.6 node_modules).
  • verify CHANGELOG promotion survived sync-main (Step 4.5)

[0.41.0] — 2026-07-17

Added

  • Delegation goes multi-model. Child roles no longer default to a single Claude model — 13 roles now carry a model-chain in frontmatter spanning Mistral, Gemini, Cohere, and Groq, with automatic fallback on rate-limit or failure, and a configurable global default (settings.jsondelegate.defaultModel). Every delegate call now prints the resolved model and where it came from (explicit arg / role default / settings.json / built-in fallback) before spawning, and a deliverable: field in role frontmatter injects a hard write-to-disk rule when a child owes a file on disk. Free-tier children get a keepalive note so they don’t mistake [cache keepalive] pings for real tasks.
  • System prompt budget guardrail. New project setting maxTokens warns when a compiled system prompt exceeds its budget, so a bloated body gets flagged before it costs you tokens on every turn.

Changed

  • Delegate defaults flipped to free-tier. default-model for child templates moved off claude-sonnet-4-6/claude-haiku-4-5 onto Mistral (mistral-large-2512 for quality, ministral-8b-2512 for speed), with the same swap in the spawnBackground fallback chain. Delegate help text and docs/guides/background-delegation.md now list Mistral first and mark Claude models as premium-with-billing-note.
  • Pi runtime: 0.80.6 → 0.80.10. Four patch versions. AuthStorage was removed from the SDK in favor of readStoredCredential; edit-diff.js was re-forked against the new base. tsc clean, sandbox 106/106.

Fixed

  • /body detector false positives. Unreferenced body files now collapse into one warning instead of one per file; backtick-quoted code and fenced blocks are stripped before {{var}} extraction so prose mentions stop triggering it; authoring scaffolds (_*-template.md) are excluded from template-variable validation.
  • Delegate + Pi 0.80.x compat. Delegate calls were hitting ARG_MAX passing the system prompt inline; switched to --system-prompt-file with a temp file, and updated Pi’s import paths for the 0.80.x restructuring. Stale preloads no longer leak into child processes, and boot warnings were fixed alongside.

[0.40.0] — 2026-07-13

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • ‘soma install npm:’ pass-through to Pi package manager + hub shows pi.dev (s01-2b2368)
  • {{enabled_models}} template variable — scoped models at boot (s01-2b2368)
  • pi.dev package search — soma:extensions.search + .show (s01-2b2368)
  • {{active_extensions}} template variable — auto-discovered at boot (s01-2b2368)
  • extensions list cap + body-parts dedup + discovered-vs-core split (s01-2b2368)
  • dynamic delegate model catalog + body parts auto-discovery (s01-2b2368)

Fixed

  • soma:agent.models now shows enabled/scoped models from settings.json (s01-2b2368)
  • sync core/ in soma-dev + add {{active_extensions}} to project _mind.md (s01-2b2368)
  • guard fix.sh against missing AGENT_DIR in wrong workspace

[0.39.0] — 2026-07-12

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • soma:refdocs — General-purpose external docs fetcher. Discover + fetch ANY external platform docs as clean markdown using the llms.txt convention (Cloudflare, Vercel, React, and 25+ known domains). Four caps: refdocs.find discovers the source, refdocs.tree shows the organized structure, refdocs.fetch gets a single page, refdocs.download bulk-fetches to .soma/refdocs/<name>/ with section-organized .md files and an index. Bundled with Soma.
  • soma:cf-docs — Cloudflare developer docs cap family. Query CF docs as clean markdown with no API key. Three caps: index, read, query. Hub package (soma install).
  • Freebuff harness — $0 AI model access. Headless freebuff sessions in tmux, programmatic prompt→response via JSON extraction from chat-messages.json. Six free models available (DeepSeek V4 Pro/Flash, MiniMax M3, Kimi K2.7, MiMo 2.5/Pro). Dev-only tool.

Changed

  • Pi runtime: 0.79.6 → 0.80.6. 13 versions (0.79.7–0.79.10, 0.80.1–0.80.6). New features available: max thinking level, showCacheMissNotices toggle, extension hooks (agent_settled, before_provider_headers), pi config -l for project-local config, Claude Sonnet 5, GPT-5.6 family. edit-diff patch re-forked for surgical fuzzy matching. Build verified: tests green, sandbox 106/106, TUI smoke with free model.

Fixed

  • Freebuff parser: TUI scraping → JSON extraction. Line-wrapping in tmux capture-pane broke multi-paragraph responses. Switched to reading freebuff’s chat-messages.json for clean, wrapping-immune output. TUI parsing retained as fallback.
  • Pi 0.80.6 compat fixes. Fixed setBedrockProviderModule import path (moved in 0.80.0 API restructuring) and duplicate baseContent declaration in re-forked edit-diff.
  • edit-diff.soma.js cleanup. Removed dead countOccurrences (superseded by findEditSpan), documented trailing-whitespace quirk in fuzzy matching.

[0.38.0] — 2026-06-26

Fixed

  • script subcommands must use clean userArgs, not injected argv (SX-811)
  • serialize browser-driving caps — concurrency race

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • soma:caselaw. — Caselaw Researcher cap family*

Changed

  • Internal: removed the dead systemPromptBlock protocol renderer (SX-806). buildProtocolInjection (core/protocols.ts) assembled a ## Active Protocols / ## Protocol Awareness / ## Available Protocols / ## Core Protocols string block on every boot that had no production consumer — the live system prompt renders protocols via two other paths: prompt.ts compileFrontalCortex## Active Behavioral Rules (TL;DR summaries, hot+warm) and soma-boot.ts## Hot Protocols (full reference) (from injection.hot). Removed the systemPromptBlock field, its ~40-line assembly, and the test assertions that exercised it (test-protocols.sh §9 systemPromptBlock checks + the §9b breadcrumb- fallback test). No user-facing behavior change — the compiled boot prompt is byte-identical.

[0.37.1] — 2026-06-23

Fixed

  • Exiting a session no longer garbles your shell (SX-808). Two soma-driven exits — the keepalive idle shutdown (“shutting down to prevent zombie session”) and the /exit command — called process.exit(0) directly, bypassing the TUI teardown that restores the terminal. Your shell was left in the Kitty keyboard protocol, so the next thing you typed (soma -c, soma inhale, …) rendered as garbage like so15;1:3um11;1:3u. Both now route through a shared graceful shutdown (core/shutdown.ts) that triggers the runtime’s own teardown via SIGTERM — restoring cooked mode, the cursor, and disabling the Kitty/bracketed-paste/modifyOtherKeys sequences before exiting. Two regression guards ship with the fix: a Pi-upstream contract check (fails loudly if the runtime ever stops handling SIGTERM gracefully) and a static scan that flags ANY naked timer-driven process.exit() in an extension — the bug shape — going forward. (The scan caught the /exit instance the moment it was added.)

[0.37.0] — 2026-06-23

Changed

  • The system prompt was split along a scaffold-vs-behavior line. prompts/system-core.md (the always- loaded framework harness, identical on every install) is now pure scaffold — session mechanics, the memory tree, tool-discovery, docs, commands, rhythm, and pointers to the behavioral layer. All behavioral rules now live in core_rules.md — a body file you own and tune (ours-vs-theirs like soul.md / voice.md). Four behaviors moved from system-core into the core_rules seed: Match the Codebase · Name the Approach · Mark Reversals, Don’t Delete · Guard Secrets, Refuse Harm. Why: the always-loaded scaffold stays lean and universal, while the behavioral layer becomes yours to shape — the same separation soul/voice already have. Existing installs keep their core_rules untouched; an agent-run migration (migrations/phases/v0.36.0-to-v0.37.0.md, fix-mode: agent) diffs the new seed against yours and merges the missing behaviors, preserving every customization (never a mechanical clobber).
  • SX-805 — v0.37.0 template-migration plumbing. The core_rules.md and _protocol-template.md seeds bumped to 0.37.0 (core_rules gained the 4 behavior sections; the protocol template moved ## Summary## TL;DR so warm-loading reads the right block). A template-auto-update-v0.37.0 boot step auto-updates a pristine _protocol-template.md to the new content and keeps a customized one (byte-exact pristine check against the archived v0.36.0 seed — the anti-clobber guard). core_rules.md is user-owned and never auto-written; new installs get the full v0.37.0 set, existing installs migrate via the agent-run map above.

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • soma:browser.render — render a JS-heavy / SPA page in an ephemeral tab and return its text (SX-807). Static fetch() returns only a ~400-char shell on JS-rendered sites; this drives a real browser via raw CDP over WebSocket: create a throwaway tab → wait for hydration → read innerText (or outerHTML, or a CSS selector’s content) → close the tab. No bridge required, and the ephemeral tab sidesteps the tab-UUID-registry churn. args: {url, selector?, format?:'text'|'html', waitMs?(5000), keepOpen?}. (Inherits bot-detection — CAPTCHA / Cloudflare can still block.)

Fixed

  • soma:browser.evaluate + .navigate now fall back to raw CDP-WS when the bridge is down (SX-807). The bridge proxies CDP control-plane ops, but it dies mid-session — and these caps used to hard-fail with “requires bridge” even though CDP itself (:9333) was still alive. Now they detect an unreachable bridge and talk CDP directly (resolving the target tab by id / url / title, else the first page). The bridge-up path is unchanged. The direct-CDP WebSocket helper rewrites the target host to the resolved config (127.0.0.1), avoiding the localhost→IPv6 (::1) footgun where a browser listening on IPv4 only is unreachable.
  • SX-794 — soma:agent.delegate({ model:'claude-cli/*', background:true }) now actually runs. Background delegation booted soma --model claude-cli/sonnet in the terminal pane, but claude-cli/* is a delegate backend, not a base-resolver model — the child died with “Model not found” and the task text leaked into the shell. The synchronous path already intercepted claude-cli/* (→ claude -p); the background path never reached that branch. Now spawnBackground detects a claude-cli backend and boots a real claude -p one-shot in the pane instead: the role’s declared default-tools drive the allowlist (SX-801; read-only fallback when a role declares nothing), the role’s compiled prompt rides as --append-system-prompt, ANTHROPIC_API_KEY is blanked so it draws from the subscription (never silent extra-usage), and --permission-mode acceptEdits keeps a detached, non-interactive pane from hanging on a tool prompt. Task + prompt are passed via temp files referenced as "$(cat …)" so no user content is inlined into the send-keys command. Drivers gained a generic SpawnOpts.bootCommand (run verbatim instead of the default soma boot). Verified end-to-end: a background builder child wrote a file (Write) and ran a command (Bash) via claude -p in tmux. (root-cause handoff from a peer soma instance.)
  • scrub names from shipping .ts + close leak-scan .js gap
  • block peer/client soma-instance names from soma-beta

[0.36.0] — 2026-06-21

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • The always-loaded core (system-core.md) restructured + sharpened — generally useful for every agent. Reorganized the behavioral guidance into a clear Orient → Work → Remember loop (was a flat 15-bullet wall), and added high-value beats every Soma benefits from: read the docs (Soma ships its own docs in docs/; soma:docs.search <topic> finds the right one — read + follow cross-references before reinventing, vs reconstructing from memory); keep your body current (when you change a file, update the body file that owns it — an un-updated body file lies to your next self); match the codebase (follow existing style, verify a library is actually used before assuming it, don’t add unrequested comments); guard secrets / refuse harm; and name the approach before a multi-step change. The body/*.md files are now framed as the agent’s living model of the project (body.md = index, domain files = grown knowledge). Lean throughout — denser, not longer.
  • System prompt now states the .soma/ layout rule + that it commits itself. Two recurring confusions got a one-line fix each in the always-loaded core prompt (prompts/system-core.md): (1) stay in the lines — new content goes in its standard home (skills/, amps/{muscles,protocols,scripts,automations}/, releases/, memory/), never a fresh top-level .soma/ folder (which is almost always drift); (2) .soma/ auto-checkpoints (settings.checkpoints.soma.autoCommit, on by default) — don’t git add/git commit inside .soma/ manually. Full layout reference in docs/memory-layout.md (now also notes the checkpoint behavior). Putting the canon in the always-loaded prompt (not a drift-prone protocol) is the fix: an unloaded rule drifts.
  • System prompt refined from corpus mining (the two most-recurring anti-patterns). Mining session logs + preloads + soul-space surfaced two patterns the always-loaded core wasn’t guarding: (1) a preload’s causal claims (“FIXED”/“BLOCKED”/“dead”) drift from its STATE and get chased stale (24 corpus files) — the “Trust the preload” guidance now distinguishes trustworthy STATE from the past-self THEORY to verify; (2) the proxy drifts from the ground it stands for (16 files + 2 soul-space syntheses) — “Run before theorize” now names committed≠pushed, dist/≠source, status-string≠real-state as the ground to probe.

Changed

  • Preload format (_memory.md template) refined from dogfood — better briefings for your next self. The preload template gained three sections proven in daily use: ⛔ Ground Truth (settled facts + corrected beliefs the next self would otherwise waste time re-deriving — the anti-wander slot), Open Loops (numbered, prioritized forward blockers with a “start here if cold” marker), and Decisions Made (closed architectural choices, so the next session doesn’t re-debate them). Gaps/Unfinished/Prior Preloads fold into an Optional sections note (add only if they carry weight), and Warnings+Traps merge into one. Existing pristine _memory.md files auto-update on first boot; a customized one is never touched. soma_template_version 0.35.0 → 0.36.0.
  • SX-804 (P5) — Tier-2 (somaverse) extension source consolidated into the agent repo; one factory, no cross-repo symlinks. The somaverse extensions (bridge-connect, hub-connect, the somaverse:* meta-tool + addons) used to live in a sibling repo (somaverse/builds/local/extensions/) and were wired into agent sessions by symlinking their source into .soma/extensions/ — a set that had leaked into the meetsoma parent, forcing somaverse’s whole toolset (and a stale dev-tool extraction) into every agent-dev session (the boot-token surprise that opened this cycle). Source now lives in repos/agent/extensions/somaverse/ (one home) and is consumed only as the obfuscated, auth-gated .min.js built by build-extensions/build.sh — no live .ts symlinks. The meta-tool-factory had diverged 149 lines across the two repos; somaverse now imports the agent’s single-source factory (../_shared) directly — there is exactly one. space-office (+ its orphaned neumann DB layer) dropped to _archive/. Also fixes a latent release bug the divergence had masked: the release step overlaid somaverse’s _shared/meta-tool-factory.js over the agent’s canonical one (“byte-identical invariant” — false post-divergence), silently shipping the older factory; the overlay now ships only env.js + bridge-client.js. Build/release/sandbox/install scripts all repointed; the required sandbox gate’s assertions rewritten to the new layout.
  • SX-804 (P4) — muscle + automation heat moved off .md frontmatter into state.json. Every session used to rewrite muscle/automation .md files (heat bumped on load, decayed on idle) — constant churn in .soma checkpoints, and runtime state bleeding into source content files. Heat now lives in state.json (muscles / automations dicts, same shape as protocols), mutated in-memory during the session and persisted once at exhale (mirroring the protocol model). Frontmatter heat: becomes a static seed — read once to seed a muscle’s first state entry, then never written. Selection is unchanged (live heat overlays each muscle before tiering); the transition is seamless (first boot seeds from the current frontmatter values). Kills the per-session .md churn; stale state entries are pruned on load.
  • SX-804 (P3) — tool config moved from _tools.md to settings.json tools.disabled, and is now authoritative. Disabling a tool used to require a separate .soma/body/_tools.md file, and its gate only caught tools registered through somaRegisterTool — raw pi.registerTool tools (and the meta-tools) silently bypassed it. Now: (1) disable via settings.jsontools: { disabled: ["name"] } (unioned across the body chain); (2) the active set is filtered at session start (pi.setActiveTools), so the disable applies to every tool, not just soma-registered ones; (3) _tools.md is retired — its parser, the per-tool ## Overrides, and the never-shipped ## Custom markdown-tools (unused everywhere) are removed. Existing _tools.md files auto-migrate on next boot: disabled entries port to settings.json, the file is archived to body/_archive/. Hardwired tools (delegate) still can’t be disabled. Simpler config, one home, actually works.

Fixed

  • SX-804 (P2) — extension loader hygiene: _-prefixed files no longer auto-register dummy tools. The seeded ~/.soma/extensions/_template.ts example and the _tool-template.ts reference each registered a placeholder tool (myTool/MyTool) into every session’s tool schema — cruft the model saw on every request. The soma extension injector now skips _-prefixed files (templates/partials aren’t loadable extensions), and the canonical extension template moved from extensions/_tool-template.ts to templates/extension-template.ts, out of Pi’s auto-load path. Smaller per-request tool schema, cleaner tool list.
  • SX-803 — Edit tool: fuzzy matches no longer silently flatten the whole file’s typography, and “Could not find” now shows the actual bytes to copy. Two fixes to the upstream Pi edit tool (vendored full-file override of core/tools/edit-diff.js, drift-guarded against the 0.79.6 fork base). (1) Surgical fuzzy match: when oldText differed from the file only by whitespace/quote/dash formatting, pristine Pi performed the replacement in whole-file–normalized space — silently rewriting every em-dash → hyphen, smart quote → straight, NBSP → space, and stripping every line’s trailing whitespace, across the entire file, on a single fuzzy edit. Destructive for typography-heavy prose (blog posts, body files). The match is now mapped back to a byte span in the original content and only that span is spliced; all untouched bytes are preserved (verified by re-normalizing the chosen span — a non-round-tripping match falls through to a hint rather than a wrong write). (2) Near-match hint: a genuine miss now appends the actual nearby file lines (token-overlap located, typo-tolerant) so the model copies the exact bytes instead of reconstructing oldText from memory — the #1 cause of the error. Discovered and verified live (s01-4409c8); 16-case regression harness at scripts/_dev/patches/edit-diff.test.mjs.
  • SX-801 — claude-cli delegate children can build, not just read. The claude-cli/* delegate backend (subscription-billed children via the official claude CLI) read tools from a claude-cli-tools frontmatter field that no role declares — every role declares default-tools. So every claude-cli child silently fell back to the read-only safe set (Read/Grep/Glob/WebSearch/WebFetch) and could never edit, write, or run bash, even for build roles. The backend now resolves tools from the role’s declared default-tools (mapped soma→Claude tool names, default-deny on anything unmapped), with claude-cli-tools kept as an optional explicit override and read-only still the default when a role declares nothing. Roles declare their tools once; existing roles immediately gain write capability on the claude-cli path with no per-role edits. Also hardens the backend to scrub ANTHROPIC_API_KEY from the child env (so claude -p always bills the subscription, never silent extra-usage) and returns an actionable “run claude setup-token” message on an expired-token 401 instead of an opaque error. (Reported by a sibling Soma instance.)
  • SX-800 — preload badge no longer lies green while the staleness warning fires. The statusline showed 📝saved (green) at the same moment soma-breathe warned “Preload now stale (N tool calls since save)”. A user-turn reset zeroes the staleness counter and the statusline reconcile re-lands “saved”, so a genuinely stale preload (work happened since it was written, file never rewritten) pinned green. The badge now derives staleness from ground truth — whether tool work post-dates the preload file’s mtime — so it shows 📝stale and agrees with the warning. Fresh preloads still show green; a real re-exhale clears it.
  • SX-799 — /inhale runtime-staleness guard. /inhale resets the session via newSession() but stays in the same node process, so a process that booted before a mid-session runtime update replays stale in-memory modules — making an already-fixed crash appear to “recur.” /inhale now detects a runtime updated after boot (module mtime vs process start) and blocks with a restart hint (--force to override) instead of running stale code.

[0.35.0] — 2026-06-20

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • coerce Opus oldText2/newText2 Edit mis-shape (SX-795) — the Edit tool now folds a crammed second pair / strips empty leftovers in prepareEditArguments before validation, instead of rejecting the whole call. Clean input untouched.

Changed

  • Body templates carry the “ground before think” disciplinesoul.md and core_rules.md lead with “Ground before think” / “Ground Before Reason” (reasoning interprets evidence, it doesn’t stand in for it); _memory.md preload format adds the verified-vs-inherited check + orient-by-live-artifact guidance. Pristine _memory.md auto-updates on first boot; user-owned soul.md/core_rules.md ship to new installs only (never clobbered).
  • Delegation docs surface headless as the reliable mode (SX-794)background-delegation.md now documents all three modes (sync / headless / background) + a “which one?” guide.

Fixed

  • error-sanitizer import injection prepends + fails loud (SX-793) — fixes the /inhale TUI crash (sanitizeApiError is not defined) that shipped half-applied in v0.34.0.
  • build halts on a failed patch (SX-798)build-dist.mjs previously swallowed an apply-patches.sh failure (logged a ⚠, kept building) and could ship a half-patched dist. That is precisely how v0.34.0 shipped the crash. The build now refuses to continue when patching fails.

[0.34.0] — 2026-06-18

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • soma:inbox.* caps — mark inbox letters read/actioned/archived. The markdown inbox (.soma/inbox/*.md) surfaces unread letters at boot, but the only way to clear one was hand-editing its status: frontmatter — high friction, so letters were read and never marked, and the boot summary piled up indefinitely. Four new caps mechanize it: soma:inbox.list (letters by status), soma:inbox.read, soma:inbox.actioned, soma:inbox.archive (move to inbox/_archive/). Each accepts a filename, slug, or unique partial; ambiguous refs list their candidates. Resolves the .soma/ chain from cwd, so a letter in a parent inbox can be cleared from a child project. Free tier, no bridge. (SX-791)

Fixed

  • Exhale crashed in an uninitialized directory. saveProtocolState wrote state.json without ensuring .soma/ existed, so running an exhale where the local .soma/ was missing (e.g. a project that resolves state to a parent/grandparent soma) threw ENOENT and aborted the whole exhale. It now creates the directory first. Regression-tested.

[0.33.1] — 2026-06-18

Changed

  • Pi runtime bumped 0.79.3 → 0.79.6. All four @earendil-works/pi-* packages in lockstep. Patch-grade gap — bug fixes and opt-in features only, no API or behavior changes. Picks up a bash-tool settlement/draining fix (#5753) and SIGTERM signal-exit hardening (#5724). The edit tool is unchanged.
  • Dropped the pi-tui-exit-cleanup runtime patch as redundant — Pi now restores the terminal on a crash natively (InteractiveMode.uncaughtCrashTerminal.stop()), so the Soma-injected process.on('exit') handler is no longer needed. Terminal modes (bracketed-paste, Kitty keyboard, modifyOtherKeys, raw mode) are still restored on crash; the guarding test now verifies the native path.

Fixed

  • soma init could fail on a clean production install with ERR_MODULE_NOT_FOUND for semver (and latently ignore / yaml). The bundled runtime imports these packages, but they were undeclared dependencies that only resolved via dev-only transitive hoisting; under npm install --omit=dev they vanished. They’re now declared explicitly. (Caught by the pre-release sandbox during the Pi 0.79.6 bump.)

[0.33.0] — 2026-06-15

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • Per-model guard allowlist (guard.trustedModels). When the active model matches a glob in the list (e.g. ["*sonnet*", "*opus*"]), the coreFiles and bashCommands prompts relax to "allow" for that turn — capable models skip the nags while weaker models and new users keep full protection. Settable per-project or globally (child wins). Empty by default = no change.
  • Always-on irreversibility guards. Destroying a .soma workspace or a .git history, running git init, destructive ops on the runtime install, and expensive operations (npm publish, docker push, …) now always require confirmation — they cannot be silenced by bashCommands: "allow" or a trusted model. Capability relaxes the routine prompts, never the catastrophic ones.
  • New documentation: Statusline & Notices — the canonical reference for all three statusline lines, every indicator, and Soma’s toast notices (including the preload lifecycle).

Fixed

  • Preload “saved” double-notification. A single preload write now shows exactly one confirmation (✅ Preload written) plus the statusline 📝saved indicator, instead of a redundant second toast.
  • guard.bashNotify is now a real setting. It was already in use but missing from the settings schema (so it was untyped and invisible); it’s now documented and configurable ("notify" | "off").
  • git-identity pre-commit hook silently blocked all commits in any repo whose settings.json had no configured email (a pipefail crash). Commits work again with no email set.
  • Core-file guard now also covers edit. Previously only write was gated, so a model could edit a runtime file or settings.json with no prompt. Editing them is now gated like writing (ordinary body files like soul.md remain free to edit).

[0.32.1] — 2026-06-15

Fixed

  • consolidate map to v0.28.1-to-v0.32.0 (close the chain gap, SX-785)
  • archive-match protection in template-auto-update sentinel (SX-789)
  • gap-safe —fix actually migrates behind workspaces (SX-789)
  • npm-lag is SOFT for independent trains, not HARD (s01-542b99)

[0.32.0] — 2026-06-15

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • v0.31.2→v0.32.0 phase + sentinels + template archive (SX-785)
  • credential-file tree-scan in channel guard (s01-542b99)
  • fail-fast migration gate (phase 0.6) + halt-before-slow-phases (SX-785)
  • add ‘The Through-Line’ to the preload template (cross-soma convergence)
  • surface the children pattern + claude-cli in delegate help (SX-784)
  • claude-cli backend + ‘soma claude’ — headless sub-agents via the official Claude CLI (SX-782)
  • SOMA_SYSTEM_CORE A/B override for prompt split-testing (SX-779)
  • teach the meta-tool arg-discovery reflex (SX-778)

Fixed

  • persist preload-saved notice + always surface runtime branch (SX-783)
  • guard keepalive timer against session-replacement stale ctx (SX-781)
  • system-core.md was silently dropped from every prompt (SX-780)
  • post-ship narrative reconcile that doesn’t depend on HEAD (SX-777)

[0.31.2] — 2026-06-14

Fixed

  • SX-776 — soma model --list (and bare soma model) showed 0 models. Resource-path injection (the --extension/--skill/… flags Soma appends for Pi’s loader) leaked into utility-subcommand argument parsing, so model read an injected extension path as its search term → “0 models matching …/_template.ts”. Utility subcommands now parse a clean copy of your args; Pi sessions still receive the full set (extension loading unaffected).
  • SX-736 — statusline /reload worktree-mismatch label. When an extension/core edit lands in a different worktree than the runtime actually loads from (e.g. editing a dev checkout while the runtime runs its own copy), the statusline now shows ⚠ sync dev + /reload instead of a plain 🔄 /reload that wouldn’t pick up the change. Detection is topology-independent — it compares the edited path against the running code’s own import.meta.url, so end users (whose runtime is their only worktree) never see it.

[0.31.1] — 2026-06-14

Changed

  • Pi runtime bumped 0.79.1 → 0.79.3 (all 4 @earendil-works/pi-* in lockstep). Inherits upstream bug fixes: Codex context-window billing-hazard fix, GPT-5 metadata corrections, Anthropic refusal stop_details preserved in error messages, Claude Fable 5 thinking-off payload fix (#5567), project-trust detection fix (#5619), model-resolution / /fork / /share / loose-list fixes, and ignored late tool-progress updates. Soma patches re-derived against the new upstream shapes (agent-loop tool-result wrap, OpenRouter session_id body param); the httpIdleTimeoutMs patch was dropped — upstream now ships it natively for all providers.

Fixed

  • SX-771/SX-736 — runtime-aware indicator, ungated + smart-show
  • SX-774 — sync dev now syncs source extensions/ (the loaded path)
  • SX-773 — path resolver broke from inside repos/agent
  • SX-770 — dev(op=‘list’) showed 0 caps (untiered families)
  • ship Step 5 npm-publish detection excludes the just-created tag (was always skipping)

[0.31.0] — 2026-06-11

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • Pi runtime 0.79.1 — native Claude Fable 5. Bumped the Pi runtime (all four @earendil-works/pi-* packages, in lockstep) from 0.78.0 → 0.79.1. Fable 5’s model definition (1M context, vision, xhigh adaptive thinking, $10/$50 per M) now ships natively in Pi’s model registry — Soma no longer needs a local models.json stopgap to describe it, so a fresh install gets Fable with correct cost metadata out of the box. (s01-781277)
  • Meta-workflow cadence — now a core protocol, with guided adoption. The operating cadence (three nested loops — BREATH → ARC → EVOLUTION; a self-amending Observation Ledger; a Decision Register) ships as the meta-workflow protocol (v1.1.0) alongside breath-cycle v3.0.0 (self-initiated rotation; the exhale is a complete checklist, preload last). Installing the protocol delivers the shape; a new adoption checklist + inline starter META_WORKFLOW.md skeleton turn it on per-project (just ask Soma “set up the meta-workflow cadence”). New docs/meta-workflow.md (Setup & Overview) + a how-it-works section. The protocol declares requires: breath-cycle so minimal installs self-heal the eager-trigger dependency. (s01-5d6a30)
  • soma doctor advisory: meta-workflow protocol present but no instance. doctor/status/health now nudge when the cadence protocol is installed but the project has no META_WORKFLOW.md instance (it’s inert until instantiated), pointing at docs/meta-workflow.md. Advisory only — not a warning/issue; checks the three real-world instance locations (.soma/ root, cycles/, releases/) so it never false-positives; no-ops outside a project. (s01-5d6a30)
  • Claude Fable 5 model support. Fable 5 (Anthropic’s Mythos-class model — 1M context, vision, xhigh adaptive thinking, $10/$50 per M) is now first-class: MODEL_ALIASES (fable / fable-5claude-fable-5), premium classification in inferClass, the model definition in ~/.soma/agent/models.json (the installed pi-ai 0.78.0 didn’t define it — it was resolving metadata-blind with no cost tracking), enabledModels (Ctrl+P selectable), and a *fable* breathe-threshold block. Refreshed the stale opus/sonnet aliases to current ids (-4-8 / -4-6) while there. (s01-81f576)

Fixed

  • Soma transparently trusts its own projects under Pi 0.79’s project-trust gating. Pi 0.79 added a trust gate around project-local config (.soma/settings.json, project extensions) — and non-interactive runs (delegate, soma -p) would silently resolve untrusted and drop your per-project settings. Soma now auto-trusts any genuine Soma project (one with a .soma/body/) via a project_trust handler, so your project config always loads with no prompt; non-Soma directories still follow Pi’s normal trust flow. (s01-781277)
  • Fresh installs reliably resolve every runtime dependency. The compiled runtime imports several packages directly (undici, chalk, execa, pi-agent-core) that the runtime package previously left to transitive resolution — under some npm install strategies (nested rather than hoisted) this surfaced as ERR_MODULE_NOT_FOUND at boot. The runtime package now declares its full dependency set explicitly. (s01-781277)
  • Statusline preload indicator no longer sticks on “stale” after a fresh write. The consolidated lifecycle’s transition map (Cycle 29) only allowed requested→saved, so the deterministic preload-write detector was silently dropped whenever state was stale or unrequested — re-writing a stale preload left the statusline showing 📝stale despite the fresh save. Added stale→saved + unrequested→saved (a file write is ground truth). The statusline now reads the lifecycle state for the indicator rather than existsSync(file) + a raw counter, so a prior session’s preload file no longer shows a false green 📝saved at a fresh boot. (s01-5d6a30)
  • Keepalive no longer closes the TUI before the auto-exhale preload lands. On keepalive exhaustion the auto-exhale only sends a message asking the agent to write a preload (async, multi-turn), but checkIdleShutdown would process.exit gated only on isAgentBusy — and since the user had been idle long enough to exhaust keepalive, the exit fired between turns before the write completed. The post-exhale shutdown now waits while the lifecycle is requested; the 30-minute absolute-idle backstop still prevents zombie sessions. (s01-5d6a30)
  • Delegate sync path repaired — pi-agent-core.Agent class not found. The sync delegate used a dynamic import("@earendil-works/pi-agent-core"), which bypasses Pi’s jiti alias map (only static imports are rewritten) and resolved to the installed top-level package (new AgentSession API, no Agent) instead of Pi’s bundled copy (which still exports class Agent). Switched to a static import. Prevention: any @earendil-works/pi-* import in jiti-loaded extension code must be static top-level. (s01-81f576)
  • Delegate honors the role’s default-model in background spawn + shows the real model. spawnBackground() hardcoded ?? "claude-haiku-4-5" and never consulted the role’s frontmatter, so delegate({role:X}) ignored the role’s model. Resolution is now explicit model > role default-model > haiku fallback (new resolveRoleDefaultModel). Also fixed the model: "auto" display bug (the spawn record + soma:agent.list now show the actually-booted model). (s01-81f576)
  • Shell-injection hardening (3 surfaces). A security audit found a systemic execSync-with-string-interpolation pattern; all converted to execFileSync(cmd, [args]) (array args, no shell): /hub share (name + a file-derived frontmatter description flowed into gh/git shell strings — a malicious description in a cloned/hub .soma could run arbitrary shell on an innocent share), drop-in slash-commands (unquoted restArgs), and scan-logs (toolArgs/cwd). Behavior preserved for valid input. (Still open — folds into the Pi 0.79.1 / project-trust work: project-local .soma scripts execute with no trust gate.) (s01-81f576)
  • Image paste into the TUI works — @mariozechner/clipboard is now a direct dependency. Same bug class as the photon image-reads fix: soma bundles the engine’s clipboard reader (dist/utils/clipboard-native.js) which loads the native @mariozechner/clipboard by bare specifier, but it was only a transitive dep — so soma’s top-level copy resolved it to null and image paste (Ctrl+V) silently read an empty clipboard, regardless of keybinding. Declaring it directly (pinned 0.3.9) forces hoisting. Note: on macOS, terminals can’t receive image data via Cmd+V — use Ctrl+V, which makes the app read the OS clipboard. (s01-cfe9ac)
  • soma-release-ship.sh: push dev to meetsoma before the main-sync (SX-768). Recurring ship bug (bit v0.30.0 + v0.30.1): the release/bump commit was made locally but never pushed before the dev→main sync fetched meetsoma/dev, so the sync merged stale dev (missing the bump) and the runtime landed a version behind. New Step 3.5 pushes dev first and aborts loudly on failure. (s01-cfe9ac)

[0.30.1] — 2026-06-04

Fixed

  • Image reads no longer silently break — @silvia-odwyer/photon-node is now a direct dependency. Soma bundles the engine’s image code (resize via photon WASM), which imports photon by bare specifier. Photon was only a transitive dep, so when npm nested it instead of hoisting, image reads died with a misleading “could not be resized below size limit” note — regardless of actual size. Declaring it directly (pinned 0.3.4) forces top-level hoisting; soma update runs npm install on pull, so installs self-heal. (s01-cfe9ac, reported by a sibling soma)
  • Release-prepare gate: Phase 1 split into unit vs release-state tests (SX-765). The gate ran the full suite as one blunt hard-block, but tests validating release state (installed-runtime version, dev↔main parity, npm registry) can’t pass before ship — so they false-blocked releases whose code was sound. Tests now opt into release-state handling with a # @release-state marker; pre-ship failures route to NEEDS-REVIEW (re-checked in their dedicated phases + post-ship), while unit failures still hard-gate. (s01-cfe9ac)

[0.30.0] — 2026-06-04

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • Headless delegation — soma:agent.delegate {headless:true} — a minimal-inference delegation path that spawns soma -p as a subprocess (not a tmux TUI), captures structured output, and detects completion via exit code (fixing the flaky pane-tail completion of background mode). Routes to OpenCode free models (big-pickledeepseek-v4-flash-free), off the Claude subscription extra-usage wall, with auto-retry + model fallback on rate-limit. Role system prompts inject via --append-system-prompt. runHeadless/loadRole/stripPreamble in extensions/soma-delegate.ts. Patterns adapted from upstream pi-mono’s subagent example. (v0.30.0 Phase 1, s01-3a1d9b)
  • Chain delegation — soma:agent.delegate {chain:[{role,task,model?},...]} — sequential headless steps where {previous} is substituted with the prior step’s output (scout→planner→worker style). Each step gets the same retry+fallback. (v0.30.0 Phase 2)
  • soma-dev cycle — the test-before-main dev→release flow: curate CHANGELOG (headless, free) → commit → build dev dist → smoke the dev build before main → gate → hand off to the release orchestrator. Main only ever receives tested-good code. Only the changelog + smoke steps use a model (both free); the rest is bash. (v0.30.0 Phase 3)
  • soma-series-rollover.sh — scaffolds releases/vX.Y.x/INDEX.md + sweeps current-series markers on a minor bump, closing the orphaned-step drift the version-truth gate flags but couldn’t fix. (s01-3a1d9b)

Changed

  • npm and agent are independent version trains (supersedes SX-659 collapsed train) — the npm thin-CLI is a one-time bootstrap; soma update pulls the agent runtime via git pull from soma-beta and never re-fetches npm, so publishing npm on an agent-only release delivers users nothing. npm now publishes only when the thin-CLI code changes (ship.sh Step 5 is conditional on npm/thin-cli.js/npm/lib/ diffs); when it does publish, the version syncs to the agent’s so soma --version stays legible (it shows both, labeled). The version-drift gates (test-doctor, test-release-completeness) now treat npm lagging the agent as the expected steady state. This is what RELEASE-FLOW.md + body/soma-cli.md already documented; the collapsed-train enforcement was the stale half. (s01-cfe9ac)
  • RELEASE-FLOW.md rewired to two modes (orchestrated / manual) — Step 7 now calls the gated soma-release-prepare.sh orchestrator instead of bypassing it; the doc describes decisions, the scripts own mechanics (stops the doc↔script drift). phase-5-release.md slimmed 390→169 lines (history lifted to release-lessons.md). (s01-3a1d9b)

Fixed

  • soma --help shows Soma’s commands when a project has extensions--help delegates to the runtime cli.js via delegateToCore(), which prepends project -e <ext> flags before the command. cli.js checked args[0] === "--help", so with extensions present —help fell through to Pi’s native help instead of Soma’s command list. Fixed by skipping leading -e/--extension pairs to find the effective command (subcommand help like soma focus --help stays intact). Manifested with a project .soma/extensions dir (dogfood + power users). (s01-cfe9ac)
  • release-prepare crash: PREP_VERSION unbound in Phase 5.5 — the website-readiness phase referenced $PREP_VERSION at a [[ -z ]] check but only assigned it inside the PROPOSAL_FILE conditional; with set -u, the common unset-PROPOSAL_FILE path crashed the whole prepare run at the tone-check. Initialized before the block. (Completes the partial fix a7ba618c made on main.) (s01-cfe9ac)
  • universal timeout for all providers (upstream 7c531d05)
  • soma:body.audit no longer false-flags compiler-prepended slots — the audit told users to “move muscle_digests after <rules>,” but that slot is prepended by compileFrontalCortex (not template-interpolated, gate-locked) and essential: true (removing it breaks muscle loading). The advice could have moved a load-bearing slot. Check 3 now skips prepended slots (muscle_digests/protocol_summaries/scripts_table) and the audit gained a “Slot mechanics” footer that points at body/DNA.md (the canonical explanation) rather than duplicating it. (s01-3a1d9b)

Pending (not yet shipped)

  • Browser Ship 2 — end-to-end smoke across CDP ports (needs bridge running).

[0.29.1] — 2026-06-02

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • /body update CLI command — version-aware template comparison and update workflow. Subcommand on /body, reads prompts/body-update.md and sends as followUp. Agent walks user through classified comparison (current/updateable/customized/legacy/extra), respects customized: true flag, creates backups before overwriting. (5d1a965b, s01-34d9de)
  • Doctor /body update suggestion — both “current” and “migration needed” paths now suggest /body update when stale or missing templates are detected. Bridges the gap between structural migrations (doctor) and content evolution (/body update). (f092e239, s01-34d9de)

Fixed

  • /exhale <note> now processed in all paths — note extracted before early-return check so it works when preload already exists (new, update-existing, already-saved). Note format upgraded to ⚠️ USER NOTE with action hint. (a241d635, b788848e, s01-8f2308)
  • Statusline preload detection simplified — checks preload file directly on disk instead of depending on breatheDetail.preloadWritten lifecycle state. (a241d635, s01-8f2308)
  • Preload validator no longer warns about missing “Next Session” — renamed to “Start Here” in required + recommended section checks. Recommended sections updated to match current template (Who You Were, Gaps, Unfinished, Traps, Patterns). (s01-8f2308)

Changed

  • Exhale note visibility### Note⚠️ USER NOTE with scope/directive hint. Template _memory.md and docs (commands.md, getting-started.md) updated. (a241d635, b788848e, s01-8f2308)
  • Preload template fallback synced with _memory.md — hardcoded fallback in core/preload.ts now matches canonical format. (f73d75e9, s01-8f2308)

[0.29.0] — 2026-06-02

Fixed

  • poll preload file on disk to detect manual exhale writes (s01-e56328)
  • muscle_digests slot estimate now capped by configured tokenBudget (s01-e56328)
  • system-core.md now ships from correct source + adds structure-aware tools guidance — build was copying from wrong path, runtime couldn’t find it. Now ships from repos/agent/prompts/ to dist/prompts/. Added “Structure-aware before raw” reflex: soma:code.map, .find, .outline, soma:seam.trace listed as first-reach tools. (ebdd6306)

Improved

  • Website docs synced for 21 caps — tools.md (20→21), cli-tools.md (17→21), browser-setup.md (new caps in matrix, cap-based quick start, bridge note), pro-tools.md (updated browser entry).
  • Roadmap browser-tools.svg — DOM scanning + click/fill/wait visualization for the browser automation story.

Infrastructure

  • Bridge CDP endpoints committedcdp.ts click() via Input.dispatchMouseEvent (bypasses React Aria isTrusted), fill() with value injection + events, waitForElement() with polling. bridge.ts POST /api/browser/xray, /click, /fill, /wait endpoints. (somaverse 7093f62)

[0.28.4] — 2026-06-01

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • gap-safe settings backfill + template auto-update (v0.28.1) — three sentinel-gated migrations run at every boot regardless of migration chain gaps: settings keys backfill, template auto-update, exhale-note template header update.
  • v0.28.0 → v0.28.1 migration phase file — exhale note + template drift + inhale model fix documented with gap-safe sentinel pattern.
  • /exhale note header redesign### User's Note for Next Session renamed to ### Note, dual-purpose: scopes the current wrap AND passes directives forward. Template (_memory.md) and docs updated.

Fixed

  • Theme crash on /inhale --model"warm", "gitCyan", "gitYellow", "gitBlue" weren’t in Pi’s ThemeColor union, causing TUI render crash. Replaced with valid union members: "muted", "warning", "accent". (47a0de5f, s01-72adde)
  • PROPOSAL_FILE unbound variable in release prepare Phase 5.5set -euo pipefail halted the script before Phase 6 created the proposal file.

[0.28.1] — 2026-06-01

Fixed

  • soma inhale --model <model> now loads the preload instead of treating the model name as a preload target — the CLI’s nameArg extraction stole model values (e.g. opencode/big-pickle) as preload names, setting SOMA_INHALE_TARGET and failing findPreloadByName. PassThrough values are now excluded from nameArg extraction. (s01-14580a)
  • Full preload format at all context thresholds — minimal format loses context — high-context preloads now use the full structured template with Resume Point, What Shipped, and In-Flight sections. (1ae67a38)
  • /exhale <note> directs the current agent during preload writing. Text after /exhale is injected as a ### Note block in the EXHALE follow-up. The agent uses it to scope the wrap (“quick” → skip body audit + MLR) AND to pass directives forward to the next session’s Start Here. --note prefix and quotes stripped. /exhale alone works the same. (89efd1b6, s01-65fd1e)
  • ANSI colors replaced with theme.fg() calls — header and statusline in the TUI now respect Pi’s theme system instead of hardcoded escape codes across 33 points. (5a824c6c, s01-6a544e)
  • Release Step 6 delegates to soma-dev sync main — replaces inline push+branch logic with the dedicated command. (256e968d)
  • Release Step 6 main-sync is now a HARD gate⚠ push failed no longer lets the release continue; exits 1 if main-sync fails, preventing v0.28.0-style stale-runtime-after-ship. (3c51de02, s01-5c0055)

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • soma-dev sync main as a proper command — release Step 6 extracted from inline bash into a proper soma-dev sync main command that handles CI-drift detection, rebase + merge, conflict resolution, dist rebuild, and version verification. (4d53663c)

[0.28.0] — 2026-05-30

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • All models from Together AI, OpenCode Go, Gemini 3.x — Pi 0.74+ unlocked new providers and model families. Together AI inference, Google Gemini 3.x support, OpenCode Go models — all available without configuration.
  • Claude Opus 4.8 support — Pi 0.77+ supports Anthropic’s latest model.
  • 842+ models total — Pi 0.78 resolver sees everything the ecosystem offers.
  • roadmap tone-check as hard gate in release prepare script Phase 5.5.

Changed

  • Pi runtime upgraded 5 versions@mariozechner/*@0.73.1@earendil-works/*@0.78.0. Full namespace migration across all four Pi packages, 61 source files swept, 8 patches audited against new compiled shapes. (3414a84)
  • Two patches retired — title-symbol (Pi now reads piConfig.name → APP_TITLE dynamically) and compaction.js estimateTokens guard (upstream refactored to guard internally). One patch rewritten for 0.78.0 API (pi-tui image height cap).

Fixed

  • soma model <p> set now actually worksenabledModels[0] always unshifts to front. Pi’s model resolver picks scopedModels[0] before defaultModel, so in-place updates never took effect. Months-old bug.
  • soma model <p> project support — project-local defaults via .soma/settings.json. Four options: global, project-only, global+start, cancel.
  • soma inhale --model <p> flag forwarding — inhale now extracts --model, --provider, --thinking-level, and --models flags and passes them through to Pi. Previously all three inhale paths called main([]), silently dropping flags.
  • Stale project defaultModel removedclaude-opus-4-7 was silently overriding global via deep-merge, producing nonexistent openrouter/claude-opus-4-7.
  • 13 transitive deps restorednpm uninstall dropped undici, chalk, minimatch, diff, glob, highlight.js, hosted-git-info, jiti, typebox, cross-spawn, execa, proper-lockfile.
  • Test suite hardened for migration — 3 stale grep patterns updated, resetBreatheState now resets preloadNotifyState, seam/trace and compaction tests fixed for 0.78.0.

[0.27.6] — 2026-05-28

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • shared preload lifecycle state machine_shared/preload-lifecycle.ts module unifies preload tracking across breathe, boot, and statusline extensions. Single source of truth replaces 7 independent let flags. (Cycle 29)
  • route capabilities for lifecycle accesspreload:lifecycle (read state), preload:transition (write transitions), preload:reset (fresh session), preload:noteToolCall (track work after save). (Cycle 29)
  • three-state auto-breath configbreathe.auto now accepts "on" (proactive), "auto" (adaptive), "off" (passive). Backward-compat with boolean and "global" values. (Cycle 28)
  • sandbox --dummy mode — simulated API responses, no API key needed. Runs all 10 API-dependent tests offline. (Cycle 28)
  • sandbox --brief mode — compact dot-progress output, details on failures only. Clean CI logs.
  • wire kanban search/related/similar caps — Cycle 27
  • dev-sync dist provenance indicator.dev-synced marker written by soma-dev sync dev; statusline shows (main +dev) when running dev-synced dist on main branch. Marker cleared by soma-dev switch main/rollback.
  • tiered progressive-disclosure format for soma(op=‘list’)

Fixed

  • 85% safety net no longer overrides manual /exhale or keepalive auto-exhale — safety net checks shared lifecycle state before acting. If preload is already REQUESTED (by /exhale or keepalive), it notifies instead of initiating a competing breathe or rotating immediately. (Cycle 29)
  • /exhale at high context no longer triggers immediate rotation without preload update — exhaleHandler calls preloadLifecycle.transition("requested", { source: "manual" }) before the followUp, so the safety net sees state=REQUESTED and waits for the preload write. Stale-preload immediate rotation case fixed. (Cycle 29)
  • keepalive auto-exhale no longer double-requests preload — gated on lifecycle state: skips if already REQUESTED or SAVED. (Cycle 29)
  • preload now loads after auto-rotate.rotate-signal was cleaned at extension load before session_start could read it. Deferred cleanup to startup handler, which detects rotation and injects preload. (Cycle 28)
  • sandbox help text testrc --help triggered Pi model resolution, polluting stdout. Changed to thin-cli.js --help which bypasses Pi init. (Cycle 28 carry)
  • sandbox license header test in --main mode — source worktree lacks release-injected headers; skip like --local mode. Updated checked path to dist/extensions/ for shipped builds.
  • sandbox --dev timeoutsoma-release.sh --dry-run ran npm test (55 scripts × 2 passes). Added SKIP_TESTS=1 to release dry-run in dev sandbox mode.
  • restore protocol paths after repos/agent/.soma/ skeleton removal

Test

  • rotate-signal continuity — 14 assertions verifying .rotate-signal not cleared at extension load, read at session_start, cleaned after consumption. (Cycle 28)
  • tri-state string value normalization — 4 tests for "on", "auto", "global" legacy compat, default fallback.

[0.27.5] — 2026-05-26

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • ancestor .soma/ walk-up + example extensions seeding + inherit gating
  • SX-763 — OpenRouter session_id in request body

Fixed

  • scan and load extension files instead of directory path for —extension flag
  • show model.name instead of model.id + Free for $0 cost models
  • strip injected resource paths from inhale nameArg extraction
  • revert models.generated.js patch — use models.json instead
  • obfuscation coverage tightened — addons + _shared correctly scoped
  • obfuscation pipeline hardened — blanket coverage for core, extensions, addons, _shared
  • —skip-tests flag for soma-release.sh, wired into ship script

Removed

  • stale repos/agent/.soma/ directory — dead skeleton, gitignore blanket

[0.27.4] — 2026-05-22

Fixed

  • SX-762 — argv.push instead of splice(2,0) for user-global paths
  • repair doctor —help assertions + github runtime test script path
  • SX-762 — defense-in-depth: env override + existence guard + build gate
  • SX-762 — call soma-code.sh directly via execFile, not ‘soma code’ CLI
  • bump obfuscator string-array-threshold 0.8→1.0
  • harden blacklist — dual-signal + obfuscation pipeline
  • harden blacklist — dual-signal + obfuscation pipeline

[0.27.3] — 2026-05-14

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.

  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.

  • soma:seam.* addon family — concept archaeology caps (s01-345201, SX-744). Eight new caps + 2 docs caps wire the existing shell archaeology tools into the cap surface so the agent reaches for them under context pressure. soma:seam.trace (free tier — wraps amps/scripts/soma-trace.sh), soma:seam.ancestors (PRO — vault agents + Pi/Claude sessions w/ attribution), soma:seam.timeline (PRO — chronological evolution), soma:seam.sessions (dev tree — search .soma/memory/sessions/ + Pi JSONLs), soma:seam.seeds (PRO), soma:seam.gaps (PRO — orphan docs), soma:seam.web (PRO — persistent markdown trace written to .soma/memory/webs/), soma:seam.stats (dev tree — Pi JSONL analytics). Plus soma:docs.related + soma:docs.impact (dev tree — frontmatter graph walk). Caps degrade gracefully when underlying scripts aren’t present (PRO/dev message). Honors Recall’s “mind of the place” lineage. New file extensions/_shared/script-resolver.ts extracts the shared shell-out + path-resolution helper. Closure test (passing): soma:seam.ancestors "breathe" returns Zenith (openclaw-dev) — dev lead, vault refactorer, soma's daddy. 10/10 smoke tests green in tests/test-seam-caps.sh. Plan: .soma/releases/v0.27.x/plans/seam-addon-family.md.

Fixed

  • exclude tincture/_generated from path scan

0.27.2 (2026-05-10)

Features

  • meta-tools: family-summary view for op=‘list’ (action-oriented cheat sheet) (8a0aee0)

Documentation

  • catch up whats-new + skills_block transplant + auto-breathe variants + delegate cycle workflow (88afed8)

0.27.1 (2026-05-10)

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.

  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.

  • Model-aware breathe thresholds (cycle 16, s01-7b287c). New tri-state breathe.auto: "off" / "global" / "model-aware" (boolean still parsed for back-compat via migration breathe-tri-state-v0.27.0). New breathe.thresholds map with glob patterns (e.g. "*sonnet*") selects per-model warnRange/exhaleRange percentages from ctx.model.id. Sonnet’s empirical extra usage required for long context wall (~48% on default-tier accounts) now triggers warn at 28-33% and auto-exhale at 34-50% — well before the wall, instead of the old fixed 50/70 thresholds that fired AFTER the wall hit. Opus uses 60-74 / 75-90; default fallback uses 50-64 / 65-85. Default install ships auto: "model-aware". /auto-breathe accepts off|global|model-aware|status subcommands. 76 tests pass (was 47/55 before, +21 new tests for tri-state + per-model resolution + migration). Closes the wall-before-threshold bug that crashed s01-8b3cb3 mid-pipeline.

  • soma-dev delegate cycle <brief> workflow (cycle 17, s01-7b287c). Full implementation pipeline for any markdown brief (cycle.md, inbox/.md, plans/.md). Composes intern (investigate, 80-call budget) → intern (build, 80-call budget) → verifier (test, 25 calls) → pr_author (description, 30 calls). Total ~215 tool calls / ~$2.50 per cycle. Outputs /tmp/soma-cycle-investigation.md, /tmp/soma-cycle-impl-summary.md, /tmp/soma-pr-description.md. Flags: --no-pr, --no-verify. Built because single builder (25-call budget) was too small for multi-step cycles like cycle 16 (9 steps, ~80+ tool calls).

Fixed

  • /inhale no longer double-injects preload after rotation (cycle 17 bug #1, s01-7b287c). Empirically verified across 10 sessions in the last 14 days: every /inhale-triggered rotation produced TWO preload-injection messages in the new session — one from soma-boot’s session_start “new” branch ([Soma Boot — rotated session], ~16K chars), one from /inhale’s post-await send() ([Soma Inhale — Loading Preload], ~16K chars). ~8K tokens duplicated per /inhale. Fix: soma-boot now exposes route.provide("preload:wasInjected", ...); /inhale queries this after await ctx.newSession({}) and skips its own send if session_start already injected. Print-mode safety preserved (when ctx.hasUI=false the session_start branch skips, flag stays false, /inhale falls back to direct send).
  • /inhale catch-fallback race (cycle 17 bug #2, s01-7b287c). The catch block at soma-boot.ts:3007-3020 previously fired its fallback preload-send unconditionally on any newSession() throw. If the throw came AFTER session_start had emitted (e.g. apply() / setup() / finishSessionReplacement() failure post-runtime-creation), the fallback would TRIPLE-stack with both the session_start injector and the happy-path injector. Same preload:wasInjected flag now discriminates: catch only sends if session_start hadn’t already.
  • session_start “new” branch fallback when boot template missing (cycle 17, s01-7b287c). Previously, if loadBootMessage() returned null (boot template not found), the rotation message was silently skipped — the new session had no preload injection, and /inhale’s old post-await send was the only thing carrying it. After bug #1 fix, that path no longer exists, so session_start now falls back to a minimal ## Preload (from last session)\n\n${preload.content} message when the template is missing.
  • Honest auto-breathe notification text (cycle 17 bug #3, s01-7b287c). The 🪵 Auto-breathe: rotating at N% notification fired when the threshold was hit, but actual rotation only happens later in turn_end after the agent writes the preload (within graceSeconds, default 30s). New text: 🪵 Preload requested at N% — rotating after agent writes it. The other branch (preload-already-written, immediate .rotate-signal) keeps its honest “Rotating — preload already written” text.

Documentation

  • Auto-rotation Path A vs Path B clarification (cycle 17 bug #5 audit, s01-7b287c). Per Pi types (pi-coding-agent/dist/core/extensions/types.d.ts), newSession lives on ExtensionCommandContext, not on the base ExtensionContext event handlers receive. Auto-breathe’s performRotation falling back to .rotate-signal + process re-exec (Path A) is correct by design — Pi treats process re-exec as the safer auto-rotation route. In-process route.get("session:new") (Path B) is a happy-path optimization available only after a user has invoked /breathe//inhale//auto-breathe in the current session. Comment block added to soma-breathe.ts:performRotation documenting this; notify text changed to 🪵 Rotating session (process re-exec)....

[0.27.0] — 2026-05-09

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.

  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.

  • Pi upstream monitor — live version gap in every session (s01-8b3cb3). GitHub Actions workflow (.github/workflows/upstream-monitor.yml) watches badlogic/pi-mono (source of @earendil-works/pi-coding-agent) every 6 hours. Writes PI_UPSTREAM.md to the agent root with: current pinned version, latest npm version, releases behind count, and flagged commits relevant to Soma (covers all 33 Pi API usages: registerTool, registerCommand, sendUserMessage, 11 event hooks, 7 patch targets). New {{pi_gap}} body var in resolveBlockVariables reads PI_UPSTREAM.md at session start and injects live gap into the system prompt. soma-dev status surfaces flagged ⚠️ items in yellow. Eliminates manually tracking Pi version drift.

  • Autonomous CI loop — nightly tests + issue filing + fix pipeline (s01-8b3cb3, smoke-validated s01-ae942e). Three-layer self-healing CI: (1) .github/workflows/test-nightly.yml runs 25 portable tests on schedule (4am UTC) and on push to dev/main; on failure, auto-files a structured GitHub issue tagged nightly-failure with failing tests, error excerpts, Pi version, last 5 commits, and a fix brief for the next agent. Dedupe gate skips filing when an open issue already exists for the same failure. (2) dev:issue.create + dev:issue.list addon caps for agent-filed issues from within sessions. (3) soma-dev delegate ci-fix <url> orchestrates: issue_investigatorbuilderverifier. 18 tests gained CI=true skip guards (workspace/dist-dependent tests self-skip). pr-check.yml hardened: tsc typecheck job + changelog blocking + conventional-commit format validation. End-to-end smoke s01-ae942e drove a deliberate test failure through nightly→issue→dedupe→revert→green.

  • Autonomous PR workflow — soma-dev delegate pr (s01-8b3cb3). Full pipeline from commits to complete PR: soma-pr-brief.sh generates structured brief (git-cliff CHANGELOG, affected files, semver bump type, docs to update, roadmap entry suggestion); changelog_curator writes rich [Unreleased] narrative; pr_author writes PR description; doc_writer updates flagged docs; verifier confirms tests pass. cliff.toml added — git-cliff configured for Keep-A-Changelog format from conventional commits (feat→Added, fix→Fixed, ci/chore/test filtered). release-please manifest updated from stale 0.22.1 → 0.26.2; auto-trigger enabled on push to dev.

  • soma-dev delegate — multi-agent workflow orchestrator (s01-8b3cb3). New command composes child agents into named end-to-end pipelines: pr / pr-brief / ci-fix <url> / changelog / doc-update / audit. Wired into soma-dev as soma-dev delegate | soma-dev workflow. Eliminates manually orchestrating multiple soma-dev children run calls.

  • 3 new child role bodies (s01-ae942e). body/children/issue_investigator.md (read-mostly root-cause tracer for nightly failures — writes /tmp/fix-brief.md), body/children/pr_author.md (writes rich PR descriptions from a brief, voice-hygiene + solo-editorial inherited), body/children/changelog_curator.md (curates [Unreleased] narratives from git-cliff output, replaces auto-appended bullet noise). Past-self in s01-8b3cb3 declared the roles in delegate.sh + CHANGELOG narratives but the body files were never written — every soma-dev delegate ci-fix call would have failed at phase 1 with role 'X' not found in body/children/.... Surfaced via the s01-ae942e smoke; fixed in the same session.

  • tests/test-children-roles-exist.sh (s01-ae942e). Drift-prevention regression test: extracts every _run_role reference from delegate.sh, asserts a matching body/children/<role>.md exists, plus validates required frontmatter fields. Catches the s01-8b3cb3 class of “declared role, missing body” drift before it ships.

  • soma-dev check-phases pre-release gate (s01-8b3cb3). 30-second sanity check (upstream sync + tests + tsc) before running the full 5-minute soma-release-prepare.sh orchestrator. Exits non-zero if any of the three signals is off, saving the cost of a full prepare run that would fail.

Changed

  • Pi runtime: 0.72.10.73.1 (s01-8b3cb3, commit 42ef127). All 4 pi-* packages bumped together (pi-coding-agent, pi-ai, pi-agent-core, pi-tui) per the lockstep rule — mismatched bumps cause silent API mismatches (e.g. cleanupSessionResources in pi-ai@0.73.1 not found if pi-ai stayed at 0.72.1). All 7 runtime patches apply cleanly against new upstream; CI green.

  • docs/anthropic-long-context.md — long-context wall claim corrected (s01-ae942e). Previous prose asserted the long-context tier triggers at “~200K” of context, presented as Anthropic-published behavior. That number wasn’t sourced; empirical evidence on Curtis’s Claude Max plan shows the wall hits at ≈40-48% of Sonnet 4-6’s reported 1M context window (~400-480K tokens) — substantially higher than the doc claimed. Three prose blocks + the per-model behavior table updated with hedge language naming the empirical observation; users probe their own account threshold via the extra usage required for long context 429.

Fixed

  • Release flow consolidation (s01-8b3cb3). soma-ship.sh (both in repos/agent/scripts/_dev/ and .soma/amps/scripts/internal/) archived to _archive/pre-orchestrator-v0.22.x/ — it referenced repos/agent-stable (dead since SX-652 worktree topology) and a 10-phase spiral that no longer exists. soma-dev ship replaced with clean git push meetsoma dev (branch guard + unpushed count). soma-dev release now routes to prepare/ship/beta subcommands.

  • 3 stale model-ID references (s01-ae942e). Test fixture in scripts/_dev/tests/test-children-list.sh referenced claude-sonnet-4-5; verify script scripts/_dev/soma-verify.sh referenced claude-3-5-haiku-latest (a generation-old alias); scripts/soma-model-sync.sh error-message hint suggested retired IDs. All bumped to current available IDs. Behavior defaults intentionally NOT changed: core/delegate/models.ts MODEL_ALIASES still pin sonnet/haiku/opus to 4-5 (default-tier safety — bumping aliases would silently force users onto 1M-context variants and their long-context billing tier).

  • Premature v0.26.3 roadmap entry removed from website (s01-ae942e). Past-self in s01-8b3cb3 drafted a v0.26.3 entry covering the autonomous CI/CD work but the version was never released (npm view meetsoma version = 0.26.2). Entry deleted; this work surfaces under v0.27.0.

[0.26.2] — 2026-05-07

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.

  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.

  • extraUsageRecovery setting (default "auto", s01-c62a62, cycle 13 successor). Narrow-scoped recovery for the boot-turn-after-/inhale variant of Anthropic’s extra usage 400 error. When /inhale rotates the session and the first API call returns Anthropic’s "You're out of extra usage. Add more at claude.ai/settings/usage and keep going.", Soma surfaces a single notice and auto-injects . after a 1s debounce so the conversation advances and subsequent turns can run cleanly. Three modes: "auto" (default — notify + auto-.), "notify" (notice only; user sends any message to continue), "off" (silent — Pi’s raw error display passes through). Hard fence: only fires when error contains literal "extra usage" AND turnCount <= 2 AND no keepalive fired. Auto-injection is 1 char (.) — no full-context resend, no 2× billing amplifier (the SX-709 failure mode that killed the original auto-retry stays killed). Migration phase doc: migrations/phases/v0.26.1-to-v0.26.2.md. Plan: .soma/cycles/audit-fix/13-startup-only-retry-redesign/cycle.md.

[0.26.1] — 2026-05-07

Fixed

  • Cycle 21 — test-release-completeness.sh Section 4 in-flight aware (s01-c62a62). The npm/package.json drift gate now respects the existing IN_FLIGHT_VERSION guard (same pattern as Section 2 dev↔main parity and test-version-truth.sh cycle 18). During the release ship window, npm test ran in orchestrator Step 4 (preflight) was reporting a real drift that resolved moments later when Step 5 (soma-npm-publish.sh) bumped + committed npm/package.json. Now skips cleanly with a SKIP not FAIL during ship. Re-run post-ship for verification.

  • Cycle 22 — soma:github.local_* runtime ship gap (s01-c62a62, commit 005005e). The 8 local-mode caps shipped in v0.24.0 (local_path / local_map / local_find / local_refs / local_blast / local_structure / cache_list / cache_clean) registered cleanly on the route bus but failed at runtime in every install with "ERROR: soma-github-cache.sh not found at /var/folders/.../T/" because compile-pro-scripts.sh PRO_SCRIPTS list bundled soma-github without its companion cache helper. Static-only test-namespaced-caps.sh never invoked the caps so the gap was invisible. Fix (Option A — inline w/ clean-extraction markers): refactored soma-github-cache.sh case-dispatcher into named _cache_* functions wrapped in {{INLINE-LIFT-START / END}} markers; soma-github.sh got {{INLINE-START / END}} markers + a comment block explaining the rationale + clean-extraction pattern (so cache can later be promoted to a separate Pro tool); new lift-cache-helper.sh build gate (idempotent, hooked into compile-pro-scripts.sh) regenerates the inline block from canonical before b64-encode. Plus 1 sub-bug fix: cache_info dispatcher branch now passes $REPO (was empty $@). New runtime regression test tests/test-soma-github-local-runtime.sh drives the shipped soma binary through all 8 caps + a regression guard for the exact “not found” string — 10/10 pass. v0.24.0 marketing/docs surfaces (docs/_dev/github-scanner.md, docs/whats-new.md, docs/tools.md, website mirrors) described correct behavior all along; the fix makes those descriptions true at runtime.

[0.26.0] — 2026-05-07

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.

  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.

  • Cycle 10 — _tool-template.ts modern shape + Pi tool runner runtime guard (s01-a6b91e). Replaces broken canonical example (2-arg execute, bare-string return) with the contract Pi’s runtime actually expects: 5-arg (toolCallId, params, signal, onUpdate, ctx) => Promise<AgentToolResult>, including required label field. Adds Site G defensive wrap in pi-agent-core/agent-loop.js executePreparedToolCall so any tool returning a string OR an object with undefined .content gets lifted into the canonical {content: [{type:"text", text}], details} envelope before persistence. Closes the bare-string-return bug class that was producing malformed toolResult records (no .content key) and crashing downstream consumers (renderer, compaction, anthropic provider). Verified all 7 runtime patches still needed against upstream Pi 0.73.0 main — audit recorded in .soma/cycles/audit-fix/10-pi-tool-result-shape-mismatch/VERIFY.md.

  • Cycle 10 — 6 defensive runtime guards against malformed ToolResult.content (s01-a6b91e). Added Sites A-F across 4 files: render-utils.getTextOutput, tool-execution.maybeConvertImagesForKitty, tool-execution.updateDisplay, compaction.estimateTokens, pi-ai/anthropic.convertContentBlocks, plus pi-tui/terminal.start process-exit cleanup (CSI-u + bracketed-paste + modifyOtherKeys + raw-mode restoration so terminal doesn’t leak escape sequences into shell after TUI crash). Defense-in-depth: Site G prevents the malformation upstream; Sites A-F catch anything that slips past.

  • Cycle 12 — Preload notify state machine (s01-a6b91e). extensions/soma-breathe.ts replaces the every-turn-end ”🟢 Preload saved…” notify with a transition-only state machine ('none' | 'saved' | 'stale'). Adds yellow stale notify (🟡 Preload now stale (N tool calls...)) and green refresh notify (🟢 Preload refreshed) on STALE→SAVED. Single source of truth for the stale threshold (PRELOAD_STALE_TOOL_COUNT = 5); breathe:detail route cap exposes isStale/staleThreshold/notifyState for downstream consumers (statusline + soma-boot). Removes dead opt-in breathe.preloadStaleThreshold setting (was default 0 = disabled).

  • Cycle 14 — Regression tests for runtime patches (s01-a6b91e). 27 new gates across 3 test scripts (test-tool-result-content-guard.sh, test-pi-ai-anthropic-content-guard.sh, test-pi-tui-exit-cleanup.sh) lock Sites A-G against regression. Plus test-preload-notify-state-machine.sh (15 gates) for cycle 12. Total: 42 new test gates, 100% passing.

  • Cycle 03-meta — META_CYCLE.md adoption (s01-a6b91e). New releases/META_CYCLE.md umbrella dashboard (live state + cycles index + routing + cross-cycle artifact pointers + pattern + changelog). Pattern adopted from a peer soma instance (s01-ddcd84) v0.1.0; meetsoma is domain #2 of the validation arc that muscle’s “Strengthen” phase needs.

  • Three new disciplines locked as muscles (s01-a6b91e):

    • amps/muscles/meta-cycle-pattern.md — single SoT per cycle; umbrella META_CYCLE.md dashboard; persistent service artifacts at <umbrella>/<service>/.
    • amps/muscles/verify-patch-against-upstream.mdgit show upstream/main:<path> from your local pi-mono clone BEFORE adding any apply-patches.sh entry. Don’t patch what upstream already fixed.
    • amps/muscles/blast-radius-before-change.mdsoma:code.blast + regression test BEFORE claiming a fix shipped. No claim-shipped without a test.
  • docs/extending.md § Cache-safe registration vs hot-reload — four-concept table (cache-safe registration / module hot-reload / prompt rebuild / subprocess pickup) with explicit “don’t conflate the four” rule. Cited authority: agent-session.js:1894, loader.js:271, soma-boot cache-stickiness, Pi changelog 0.56.0 (#1720), meta-tool-factory.ts:96-130, soma-addons/code.ts:38. Decision matrix: per-edit-class × cache-impact × what-to-run.

  • docs/commands.md § /reload — row clarified to cover both pi.registerTool and route.provide registration shapes. Pair-with-/rebuild guidance for prompt-visible field edits.

  • body/body.md Before Doing X table — added 4 new routing rows (verify-patch-against-upstream, blast-radius-before-change, meta-cycle-pattern, runtime-patch entry).

  • 5 queued cycles for follow-up work filed in .soma/cycles/:

    • audit-fix/11-soma-inhale-double-preload-load — deep code trace done, hypothesis space narrowed (H-A/H-B/H-C), smoke recipe ready for runtime repro.
    • audit-fix/13-startup-only-retry-redesign — Pi 0.73 retry regex audited; gap = DNS/TLS/handshake errors; needs Curtis’s actual error class to scope.
    • audit-fix/15-stale-test-cleanup-sx727-sx734 — deletes stale tests asserting reverted features.

Fixed

  • cycle 15 — delete stale SX-727/SX-734 tests + replacement upstream-tracking gate (s01-a6b91e)

  • CHANGELOG entries from s01-a54f21 reflect what was originally shipped, not what’s currently on main. Two entries below describe features that were subsequently REVERSED or further GUTTED in the same session and not back-propagated to this changelog:

    • SX-727 (context-1m-2025-08-07 beta header patch) — REVERSED in commit da6b971 (s01-a54f21). Always-on header rejected requests on accounts without long-context billing (Curtis’s case). Patch is DISABLED in apply-patches.sh; manifest entry marked "removed": "2026-05-04". To re-enable as opt-in, see SX-741 (auto-apply on settings flip). Original CHANGELOG entry retained below for ancestry; reality is the patch does NOT ship.
    • SX-734 (billing-retry gate) — FULLY GUTTED in commit 7109ce1 (s01-a54f21). The autoRetryBilling setting gate landed (commit 54f7ef5), then SX-738 fixed undefined-settings ref (commit e403fab), then the entire layer was REMOVED — letting Pi handle billing errors natively (its _isRetryableError correctly excludes extra usage). Existing tests/test-billing-retry-disabled.sh is now stale and fails; cycle 15 plans cleanup.

    Both entries above need cleanup before this changelog is promoted to a versioned section. Cycle 15 (audit-fix/15-stale-test-cleanup-sx727-sx734) deletes the stale tests; the CHANGELOG entries themselves should be either removed or rewritten as REVERSED markers.

Original (stale) entries — retained for ancestry, do NOT promote as-is

  • SX-737 stable-v0.25.0 fallback branch + generic switch ref
  • Pi 0.72.1 bump (SX-732). Updates pi-ai, pi-coding-agent, pi-tui, pi-agent-core from 0.71.0 to 0.72.1. Unlocks shouldStopAfterTurn agent loop callback (Pi 0.72.0+) — documented use case: “request a graceful stop after the current turn, e.g. before context gets too full” — the canonical mechanism for the upcoming v0.27 auto-breathe redesign. Pi’s internal API rename (compat.reasoningEffortMapthinkingLevelMap) audited clean: zero usage in Soma extensions. Removed providers (Gemini CLI / Antigravity) we don’t reference. npm audit: 0 vulnerabilities post-bump.
  • Anthropic context-1m-2025-08-07 beta header patch (SX-727) — REVERSED s01-a54f21 commit da6b971. See “Fixed” section above for full context. Original entry: Soma now adds context-1m-2025-08-07 to Anthropic’s OAuth anthropic-beta header via scripts/_dev/patches/apply-patches.sh. Without this opt-in, Sonnet 4.6 hits the long-context billing tier (“extra usage” wall) at ~400K tokens.
  • Doctor migration: ## Next Session## Start Here in active preloads (SX-733). Closes the SX-729 loop for existing user preloads. Sentinel-gated applyOnce("memory-section-rename-v0.26.0") in BOTH Tier 1 sites (extensions/soma-boot.ts + npm/thin-cli.js). Strict heading-only regex; _archive/ untouched (provenance). New regression test: tests/test-memory-section-rename-migration.sh (7 scenarios).
  • Billing-error auto-retry disabled by default (SX-734) — GATE GUTTED s01-a54f21 commit 7109ce1. See “Fixed” section above for full context. Original entry: Fix: gate auto-retry behind settings.errors.autoRetryBilling (default false). […] New regression test: tests/test-billing-retry-disabled.sh (6 gates). Reality: the autoRetryBilling gate AND the entire Soma billing-retry layer are now removed; Pi handles billing errors natively.

[0.25.0] — 2026-05-04

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • Preflight update prompt (s01-86b0fd). Cached ~/.soma/config.json:updateAvailable (set by soma-statusline background check) now surfaces an interactive prompt at startup: (c)ontinue / (u)pdate now / (s)kip this version. Skip persists via skipUpdateUntilTs matched against updateCheckTs — new commits arrive, prompt re-fires. Zero network at boot. Replaces the misfiring Pi-cruft deprecation prompt that nagged on every startup. See docs/troubleshooting.md § Startup Prompts.
  • tests/test-shipped-templates-clean.sh regression. Locks the shipped templates/default/_mind.md AND the in-code getDefaultMindTemplate() fallback against re-introducing redundant {{protocol_summaries}} / {{muscle_digests}} / {{scripts_table}} interpolations. Four gates: source clean, dist mirrors source, warning comment present, fallback string clean.
  • tests/test-stale-ctx-after-rotation.sh regression. Static-scan + Pi runner.js invalidate(...) snapshot. Catches the SX-713 family (Pi 0.71.0 expanded the stale-ctx guard from pi.X to also cover ctx.X).
  • tests/test-mind-prepend-cleanup-migration.sh + tests/test-preflight-prompt.sh — fixture-based migration tests for v0.25.0 changes.
  • Migration map migrations/phases/v0.24.1-to-v0.25.0.md documenting the body/_mind.md cleanup migration + always-run sentinel pattern + preflight prompt.

Changed

  • Migrations now run UNCONDITIONALLY (s01-86b0fd). Previously gated behind if (status.needsMigration) (project version < agent version), missing users on current version with no sentinel — e.g. fresh init at current version, or manual settings.json edit. Now applyOnce() migrations run on every boot/doctor invocation; sentinels make them O(1) idempotent. Affects both extensions/soma-boot.ts Tier 1 and npm/thin-cli.js doctor mirror.
  • Doc updates: docs/troubleshooting.md gains a ## Startup Prompts section. docs/getting-started.md mentions the preflight prompt at first run. docs/body.md and body/DNA.md updated with the rationale for why {{protocol_summaries}} / {{muscle_digests}} / {{scripts_table}} are NOT in the shipped _mind.md template (compileFrontalCortex prepends them).
  • amps/muscles/internal/route-plumbing-first.md: TL;DR + symptom table now cover ctx.X access post-rotation (was pi.X only). Pi 0.71.0 expanded the guard.

Fixed

  • /inhale stale-ctx after Pi 0.71.0 guard expansion (s01-86b0fd). extensions/soma-boot.ts /inhale handler made 3 ctx.ui.notify calls AFTER await ctx.newSession({}), which Pi 0.71.0’s expanded runner.js invalidate() guard now flags as stale. Fix: drop 2 redundant success notifies, route the degraded-state warning through getRoute()?.get("ui:notify"). Same family as SX-713 (pi.sendUserMessage post-rotation); muscle updated.
  • getDefaultMindTemplate() inline fallback cleaned (s01-86b0fd). The fallback string at core/body.ts:925 (used in test environments / /soma debug output when no shipped template is present) still interpolated {{protocol_summaries}}\n\n{{muscle_digests}} — inconsistent with the shipped template since fcd32bd. Fixed; locked by the new test-shipped-templates-clean.sh.
  • Pi-cruft startup warnings removed (s01-86b0fd). npm/migrations.js checkDeprecatedExtensionDirs (Pi-inherited via SX-391 absorption) was warning users with .soma/tools/ (Python scripts), .soma/hooks/, or .soma/commands/ directories — none of which are Soma conventions. The Pi-rename history (Pi’s old tools/extensions/ migration) doesn’t apply to Soma. Function preserved as a no-op stub for future Soma-specific deprecations; warnings no longer fire.

[0.24.1] — 2026-05-03

Fixed

  • SX-722 — release-ship Step 7 silently swallowed pull failures (dcf8a3c). soma-release-ship.sh was (cd ~/.soma/agent && git pull ... || true) and printed ✓ runtime updated regardless of outcome. v0.24.0 shipped with the runtime worktree silently stuck at v0.23.0 because of this. Now: git pull --ff-only, then verify package.json version matches NEW_VERSION post-pull; on mismatch print full diagnostic + manual fix path and exit 1.
  • scrape: mkdir -p dest before writing llms.txt (1ad8469). Silent failure when _website/ wasn’t created — previously lost a fetched llms.txt this way (2026-04-27, lightpanda). Found as uncommitted edit on the runtime worktree during the s01-f1230f cycle pass; lifted to dev. (scripts/_pro/* is gitignored from soma-beta release — dev/main only.)
  • tsconfig hygiene (9f6b091). Added extensions/_archive/** to tsconfig.json exclude. Cleared 15 TS7006 errors from _archive/sx594-flat-wrappers/ that npm run check was reporting. Archived code shouldn’t be type-checked.

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • tests/test-release-completeness.sh regression (9f6b091). Asserts CHANGELOG ↔ git tag parity, dev ↔ main ff-merge reachability, dist/manifest.jsonpackage.json, npm/package.jsonpackage.json (SX-659 collapsed train). Wired into orchestrator Phase 1 (tests gate) automatically because soma-release-prepare.sh iterates tests/test-*.sh. If a previous release was incomplete (main behind), the next prepare fails CONFLICT-HARD before any new bump — the proactive layer of the SX-722 prevention rule.
  • tests/test-namespaced-caps.sh regression (9f6b091). Static-analysis floor for the cap-bus surface (~92 registered caps): per-family minimum thresholds, v0.24.0 named-cap presence (18 specific caps from CHANGELOG), duplicate-registration detection, namespace hygiene. Catches accidental cap deletion or rename across all addons before runtime.

[0.24.0] — 2026-05-01

Fixed

  • add required Actions section to v0.23.0-to-v0.23.1.md
  • bump pi- to 0.71.0 — clears CVE-2026-41686 (GHSA-p7fg-763f-g4gf)*
  • Bump pi- deps 0.71.0 + clear CVE-2026-41686 (GHSA-p7fg-763f-g4gf)* — upgraded @earendil-works/pi-{ai,coding-agent,tui,agent-core} from ^0.69.0 to ^0.71.0. Clears @anthropic-ai/sdk advisory (affects >=0.79.0 <0.91.1). Also picks up: cache-control model-compat awareness, fine-grained tool streaming beta, empty tools array fix, stream truncation detection. fast-xml-parser (AWS Bedrock SDK transitive) remains at moderate — not reachable through soma’s Anthropic provider path.

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • soma:github. v2 (SX-720)* — 21 caps total. API-mode (metadata; 13 caps including new audit/releases/diff/compare/file_diff parity wires) + new local-mode (tarball + soma-code shim; 8 caps): local_path, local_map, local_find, local_refs, local_blast, local_structure, cache_list, cache_clean. Treat any GitHub repo as local: fetch tarball ~1–5s to ~/.soma/cache/gh/<owner>--<repo>--<sha>/, then run soma-code (12 langs, full ripgrep regex, DEF/IMP/USE refs, blast radius). Architectural pivot from “per-file API” to “fetch-once-then-local-toolchain.” Plan: releases/v0.23.x/plans/github-tool-10x.md. Commits: e7ff177, 907013a, 96a511c. Guide: docs/_dev/github-scanner.md.
  • dev:kanban. (SX-720)* — dev-only ticket audit caps. dev:kanban.audit({ticket}), dev:kanban.audit_batch({tickets|all_open|all, mode?}), dev:kanban.audit_open(). Triangulates kanban + git log + soma:code.* + sessions/preloads + cross-project trees (somaverse/somadian/website). Verdicts: SHIPPED / STALE / STALE-CROSS-PROJECT / STILL-VALID / NEEDS-REPRO / UNCLEAR. Used to close SX-588/SX-589/SX-642 in same session. Build-excluded from npm tarball. Commit: 4d667a3. Guide: docs/_dev/kanban-audit.md.
  • soma:docs. upgrade (SX-720)* — 5 caps total. New: whats_new({version?, limit?: 3}) reads docs/whats-new.md (agent-facing changelog); guide({name}) resolves guides/ then _dev/. Improved: list is now recursive (catches guides/ and _dev/), groups by section, extracts TL;DR per entry; show accepts subdir paths. New docs/whats-new.md populated with v0.23.1 + v0.23.0 sections (action-oriented invocation hints). New docs/_dev/ subdir convention (build-excluded; gated by filesystem presence). Commits: 75b78f9, a7fe2f8.
  • Heat-system docs: cold-start boost (SX-708) — added ## New Muscle Visibility (cold-start boost) section to docs/heat-system.md (formula, code excerpt from core/utils.ts:215-225, scope, budget-overflow detail, verifying checklist). Mirrored to docs/muscles.md ## Heat & Loading Tiers. Commit: e4fdbe2.
  • v3.1 — Tier 1 wins from ripgrep study (0be844f)
  • v3 agent-first redesign — never hangs, self-correcting, auto-detects (28a5850)
  • add Phase 5.6 version-truth gate (5798e66)
  • add Phase 5.5 website-readiness gate (6478fc3)

Changed

  • breathe.auto now opt-in by default (SX-718) — proactive auto-rotation at rotateAt% (default 70%) wipes user input mid-compose with no warning. Existing users with breathe.auto: true are flipped once via Tier 1 migration breathe-auto-off-v0.23.1; sentinel recorded in settings.migrations[] so re-enable is respected. Migration map: migrations/phases/v0.23.0-to-v0.23.1.md. Also introduces the reusable applyOnce(id, fn) pattern + settings.migrations[] tracker for future one-time semantic migrations beyond addIfMissing.
  • Phase 5.5 calls test-release-surfaces.sh (closes SX-510) (a6302c1)
  • meetsoma@0.23.0 (18f9c1d)

Fixed

  • soma-github: follow 301 redirects on moved repos (curl -sL) (96a511c)
  • SX-713 inhale stale-after-reload — consume message:send via route (cf18064)
  • SX-717 default path + clarify legacy soma:code.find description (2a313fc)
  • SX-716 walk up looking for agent package.json on fallback A (17b9f1e)
  • SX-715 auto-detect github.com remote name + surface fetch errors (53cbed7)
  • SX-714 persist version bump in no-fixes branch (86213f2)
  • rewrite CHANGELOG promotion regex for our actual format (2034516)
  • manually promote [Unreleased] → [0.23.0] (orchestrator regex bug) (2b578f4)

[0.23.0] — 2026-04-27

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • tree-hygiene gate (Phase 0.5, SX-712)soma-release-prepare.sh halts if repos/agent/ has uncommitted files other than M CHANGELOG.md. Closes the agent-spawned-files-leaking-into-soma-beta hole observed s01-030d41. Override with --skip-tree-hygiene (writes audit trail). .releaseignore widened to cover .soma/, .husky/, node_modules/.
  • soma:agent.list role filter (SX-701) — pass {role: 'librarian'} (or any role string) to filter children by role. Stacks with existing active_only/all/cleanup filters. Useful when a parent has spawned multiple roles and wants to inspect just one cohort.
  • somadian drift discipline — verify + lift + pre-commit gate (SOMADIAN-002, s01-ef2bdc) — three scripts that enforce byte-identical shared code across the 4 somadian bins (cloud / enterprise / local / sidecar): somadian-verify detects drift, somadian-mirror lifts a canonical bin to the others, and install-hooks.sh wires a pre-commit gate that blocks divergent commits. Closes the silent-drift hole.
  • namespace-rooted workspace target path (s01-ef2bdc)soma-workspace-migrate-legacy.sh now writes to ~/.soma/<namespace>/workspaces/__legacy__/... (was ~/.soma/workspaces/...). Aligns with first-name-wins namespace shape (SOMAVERSE-019).
  • soma-workspace-migrate-legacy.sh — lazy migration W2 of plan 02 (s01-680a9c, preload #3) — walks ~/.soma/plugins/<type>/state.json and copies each into ~/.soma/workspaces/__legacy__/<type>/<type>-1.json + registers in ~/.soma/workspaces/__legacy__/panes.json. Idempotent (re-run skips already-registered instances). Skips leading-underscore types (_test, _regression_test) by default. Preserves old paths for one release cycle as fallback. Per 02-workspace-pane-config.md § Migration W2 (lazy) and ~/.soma/workspaces/README.md. Smoke-verified end-to-end against a tmp clone of ~/.soma/plugins/: 8 panes migrated, registry built with types/paths/timestamps/provenance markers, re-run skipped all 8.
  • soma-somaverse-deploy.sh — closes the build-vs-stamp race for somaverse (s01-680a9c, SOMAVERSE-009) — mirrors soma-somadian-deploy.sh for the somaverse side. Enforces commit → build → deploy → verify ordering. The somaverse build embeds git rev-parse HEAD as the cache-buster (main.js?v=<sha>); building with uncommitted changes makes the deployed bundle report an older sha than its actual contents. Caught s01-680a9c cycle 10 mid-deploy. Builds: local (build-only), enterprise (→ a client enterprise host), vps (→ somaverse.ai). End-to-end smoke verified live on enterprise build.
  • soma-somadian-deploy.sh — closes the build-vs-rsync race (s01-1bf0bb Cycle 15) — enforces commit→rsync→build→deploy→verify order. Includes rollback command. Future deploys won’t have stamp-vs-source mismatch. The Cycle 13 build had this race (binary had Cycle 13.5 fix but git_sha stamp was Cycle 13 commit).
  • soma-voice-switch.sh — voice backend mutex orchestrator (s01-1bf0bb W-3c) — top-level orchestrator wraps the 3 individual lifecycle scripts and applies the mutex matrix (use voxtral kills openvoice + tts-server, starts voxtral; etc.). Used by somaverse/.../server/bridge.ts POST /voice/use-backend (pane wiring) AND somaverse-addons/voice.ts cap (agent surface) — single source of truth. status returns JSON for machine consumption.
  • voice-backend lifecycle scripts (s01-1bf0bb) — 3 dev:* scripts in scripts/_dev/:
    • soma-voxtral.sh — local mlx Voxtral TTS (port 18795). macOS arm64 only; sweeps orphan procs.
    • soma-openvoice.sh — OpenVoice V2 voice-clone server (port 18793). Mirrors soma-racecar pattern.
    • soma-tts-server.sh — soma-voice/server/tts-server.py (port 18790, edge-tts + clone routing). All 3 build-excluded from npm tarball. Companion: somaverse somaverse-addons/voice.ts mutex cap. Plan: .soma/releases/sidecar/consolidated-plan/07-smallest-wedge.md § W-2.
  • dev:* namespace foundation (SX-694) — new top-level meta-tool family for dev-only operations (dev:hub.*, dev:release.*, dev:audit.*, dev:lint.*). Stripped from end-user beta builds via soma-release.sh Step 3; verified by verify-bootstrap-clean.sh Test 5 (NEW). Dogfood works locally; end users never see dev:*.
  • dev:hub.* x5 caps (SX-695, SX-696) — read-only audit-grade introspection of community-tier content: dev:hub.list (items by type), dev:hub.read (raw markdown), dev:hub.canonical (paths), dev:hub.diff (vs workspace/fallback), dev:hub.audit (drift report). Replaces 5-step shell pipelines with a single cap call.
  • dev:audit.deps + dev:audit.ci caps — dependency + CI-config audits surfaced as caps under the new dev:* namespace.
  • soma:code.history cap (SX-700)git log for a file as a structured cap (sha + date + author + subject). Replaces 6 raw git log --format shell calls observed in a single session. Cap-only addition; zero cache-bust cost.
  • 3 missing roles synced + 3 drift fixes — community-tier body/children/<role>.md content reconciled against canonical: 3 roles re-synced and 3 drifted definitions corrected.
  • soma-dev switch rewritten for worktree-on-main (SX-686) — the legacy soma-switch.sh managed symlinks pre-SX-652. Replaced with a worktree-aware soma-dev switch [dev|main|help]: flips ~/.soma/agent between branches (detached HEAD on dev since it’s checked out in repos/agent), rebuilds dist/, ff-pulls main. paths.sh now exports AGENT_RUNTIME (canonical); AGENT_STABLE retained as deprecated alias.
  • frozen-protocols fallback warning (SX-691) — stepping stone before SX-691-full removal: when build-dist.mjs falls back to repos/agent/.soma/protocols/ (frozen at v0.6.6), it now logs a triple-warning and labels the source agent .soma/ (FROZEN v0.6.6) so anyone hitting the fallback sees they’re shipping stale content. Fully removed in the SX-691 fix below.
  • release-please proposer workflow + config (SX-667).github/workflows/release-please.yml opens release PRs from conventional commits. Manual-trigger only (workflow_dispatch) until first proposer-output validation. Activates on default branch after next release sync.
  • gh release create as Step 6.5 of soma-release-ship.sh (S4, SX-667) — auto-publishes a GitHub Release with generated notes on every release. Idempotent + non-fatal.
  • Full Step 4 log on failure (S2, SX-667)soma-release-ship.sh now captures full soma-release.sh output to /tmp/soma-release-step4-v$VERSION.log and dumps the entire log on failure (was tail -10).

Fixed

  • body/STATE.md now scaffolds on fresh init (SX-669 follow-through) — SX-669 (s01-88d4bd) retired the root .soma/STATE.md scaffold and declared body/STATE.md the canonical state slot. The migration comment in core/init.ts:608 said body/STATE.md would be created by templates/default/body/STATE.md (handled by scaffoldBody) — but no STATE.md was ever added to templates/default/. Result: fresh init never created STATE.md anywhere, but the _memory.md preload template still told users to “Update STATE.md if branches, versions, or known bugs changed.” Latent for ~6 weeks. Caught by sandbox smoke-test s01-b97ce5. Now ships a generic skeleton (Versions / Services / Tools / Known bugs / Recent shifts).
  • soma-release-prepare.sh commit-msg-lint regex synced with .git-hooks/commit-msg (SX-702 follow-through) — SX-702 fixed the hook to allow . in scope ([a-z0-9_.-]+) so dotted cap-name scopes like agent.list and code.history would pass. The companion regex in the orchestrator at soma-release-prepare.sh:281 was missed and still rejected dots. Result: every dotted-scope commit was flagged NEEDS-REVIEW by the orchestrator even though the hook accepted it. Synced.
  • soma-sandbox.sh --main worktree-aware (s01-b97ce5) — pre-SX-652 the main branch lived at $MEETSOMA/repos/agent-stable. Post-SX-652 it lives at $HOME/.soma/agent (worktree-on-main). The --main source path was never updated and silently failed (agent-stable not found). Now points at the canonical runtime worktree.
  • soma-dev sandbox wrapper repaired (s01-b97ce5) — the wrapper at scripts/_dev/soma-dev/commands/sandbox.sh redirected to $SOMA_DIR/amps/scripts/internal/soma-sandbox.sh, a path that moved during s01-c6944c consolidation. Wrapper was missed; soma-dev sandbox was silently broken for ~5 weeks. Now forwards to scripts/_dev/sandbox/soma-sandbox.sh (canonical kit).
  • soma-new no longer pollutes agent install with spawned content (SX-710)resolve_soma_dir() walks up from $PWD looking for any .soma/; when invoked from inside ~/.soma/agent/, it would resolve to the install’s own dogfood .soma/ (source-controlled, not a valid user-content target). Any soma:new.muscle / soma:new.protocol / soma:new.child call from inside the install would write into ~/.soma/agent/.soma/amps/.... Fix: skip ~/.soma/agent/.soma (symlink-safe via pwd -P) and continue the walk-up. Latent bug — no pollution found today, but the class is now closed.
  • build-dist.mjs removes v0.6.6 protocols fallback entirely (SX-691 full) — the fallback silently shipped frozen v0.6.6 protocols when repos/community/ wasn’t cloned alongside repos/agent/. 5 core protocols had drifted between canonical and frozen (verified by dev:hub.audit). Build now exits 1 with a clear pointer (gh repo clone meetsoma/community) instead of shipping stale.
  • commit-msg lint allows . in scope (SX-702) — conventional-commit scope regex was [a-z0-9_-]+, rejecting dotted scopes like agent.list and code.history (which match cap names). Caught when feat(agent.list): ... was silently rejected and git push said “Everything up-to-date” — cost ~2 min to diagnose. Fix: add . to the scope class.
  • commit-msg lint accepts revert type — was missing from VALID_TYPES; needed for git revert commits to pass the gate.
  • GitHub repo URL reverted to canonical meetsoma/soma-agent (SX-704) — a prior “canonicalization” (71c2c62) flipped the URL the wrong direction. gh api confirmed the canonical name IS meetsoma/soma-agent. Both URLs resolve via GitHub redirect, but if the redirect ever drops, the previous direction would break. Reverted in 6 source files + 4 .soma/ files + 2 git remotes.
  • soma-channel-guard hook resolves through symlinks (SX-693) — the hook is symlinked into each public repo’s .git/hooks/pre-push. dirname $0 resolved to .git/hooks/, which broke the relative source _lib/find-root.sh. Fix: walk through readlink until $0 is no longer a symlink. Affects all 6 public repos using the hook.
  • test-doctor version-equality assertion inverted (SX-659 align) — the test asserted agent_version != cli_version; SX-659 (v0.22.1) collapsed the two version trains so they’re intentionally equal now. Test was failing because reality finally matched the spec. Inverted: pass when versions match, fail on drift.
  • soma-release-ship.sh Step 6 (main-sync) hardened (SX-685) — dropped three buggy operations silently misbehaving under SX-652 worktree-on-main: git push origin v$VERSION (no origin remote, only meetsoma), git branch -f main (fatal under worktree-on-main), git push --force-with-lease meetsoma main:main (would silently rewind remote main from a stale local ref). Step 6 is now just the agent-repo tag push; main sync is owned by soma-release.sh Step 6.
  • soma-release-ship.sh Step 7 worktree detection-d "$HOME/.soma/agent/.git" was wrong under worktree-on-main (worktrees use a gitfile, not a directory). Silently skipped runtime-pull on every release. Fixed to -e (matches dir / file / symlink).

Changed

(no other behavior changes this release — see Added/Fixed.)

[0.22.1] — 2026-04-25

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • soma-workspace-migrate-legacy.sh — lazy migration W2 of plan 02 (s01-680a9c, preload #3) — walks ~/.soma/plugins/<type>/state.json and copies each into ~/.soma/workspaces/__legacy__/<type>/<type>-1.json + registers in ~/.soma/workspaces/__legacy__/panes.json. Idempotent (re-run skips already-registered instances). Skips leading-underscore types (_test, _regression_test) by default. Preserves old paths for one release cycle as fallback. Per 02-workspace-pane-config.md § Migration W2 (lazy) and ~/.soma/workspaces/README.md. Smoke-verified end-to-end against a tmp clone of ~/.soma/plugins/: 8 panes migrated, registry built with types/paths/timestamps/provenance markers, re-run skipped all 8.
  • soma:new.child cap + bundled _child-template.md (SX-663)
  • progressive teach + child monitor improvements (SX-665, SX-666)
  • cache-TTL rollback on aborted/errored turns (SX-660)
  • add Phase 1.5 commit-message lint (G1, SX-667)
  • delegate progressive teaching (SX-665)soma:agent.delegate bare call (or {help: true}) returns a structured help payload: roles available (auto-discovered from body/children/*.md), models, recent children, examples, and a notice that async children don’t yet ping on completion (see SX-664). Tool teaches itself; saves a tool round-trip when the parent doesn’t remember the surface.
  • child monitor improvements (SX-666)soma:agent.list now defaults to last-7-days (registry can grow long); accepts {active_only: true} to filter to running/spawning/completed-not-harvested; accepts {cleanup: true} to remove aborted/completed entries >24h old. Pass {all: true} to override the 7-day default.
  • soma:new.child cap (SX-663) — scaffold a new child role at .soma/body/children/<name>.md from _child-template.md, matching soma:new.muscle / soma:new.protocol pattern. Then edit the scaffold (set summary, default-model, inherits, guidelines), then delegate({role:'<name>', task:'...'}). Bundled _child-template.md ships with soma init.
  • keepalive.rollbackOnAbort setting (SX-660, opt-in) — when true, lastActivityTs rolls back on aborted/errored turns so the cache-TTL counter doesn’t overstate after a Curtis-aborted long-running tool call. Default false (no behavior change). Empirical evidence: aborted assistant messages have zero usage — API request never round-trips, so cache wasn’t actually refreshed at the optimistic turn_start reset. Opt in via .soma/settings.json keepalive.rollbackOnAbort: true. See releases/plans/active/agent-infra/README.md § SX-660.
  • Pi auto-fix loop on isolated worktree (SX-654)
  • prepare + ship orchestrator with checklog pattern (SX-653)
  • collapse agent + thin-CLI version trains (SX-659)
  • Pi changelog parser utility (Bucket 2 / SX-653 dep)
  • version-aware path interpolation (SX-656) — 5 new template vars (current_version, current_series, active_plans_dir, active_index, active_release_dir) derived from agent_version or settings.releases.activeSeries override. New # Active Release block in body/_mind.md. Eliminates the stale-reference drift on version bumps.
  • externalize overlay manifest + bootstrap-clean verifier (Bucket 2 G+J / SX-653 deps)

Fixed

  • cleanup mode prunes all finished entries, no time gate (SX-666 amend)
  • triage 6 pre-existing test failures (32 assertions)
  • count cache TTL from turn_start, not turn_endstate.lastActivityTs was reset at turn_end, making cacheRemaining() overstate by however long the turn took. Anthropic’s prompt-cache TTL counts from cache write (= turn_start). Validated against session JSONL: two invalidations both fell within the 300s window measured from turn_end but BOTH past 300s when measured from turn_start. Bumped keepaliveThresholdSeconds 45 → 90 as safety margin.
  • migrate to unscoped ‘typebox’ package (SX-655) — Pi 0.69.0 renamed @sinclair/typebox 0.34.x → typebox 1.x. Migrated 6 imports and added 'typebox' to all three external arrays in scripts/build-dist.mjs (was missed; build size doubled to 611 KB before the fix, recovered to 286.4 KB).

[0.22.0] — 2026-04-24 — Namespaced meta-tools end-to-end + bridge CLI + init hardening

Fixed

  • harden pairing flow — secret in header, umask, curl --fail, device-key shape-check (SX-audit, s01-d7bdf0)
  • SOMAVERSE_DIR consumers use builds/local/extensions (SX-616)
  • stale-ctx guard on footer render; no more pi-tui crashes post-/reload (SX-633)
  • wire soma-addons/ + _shared/ end-to-end; Tier 2 addon-ship through release script (SX-594 Phase 3 / gap-addon-ship.md, SX-610)
  • AGENT_VERSION reads dist/manifest.json not package.json (SX-624 revises SX-619)
  • refresh docs/guides/code-navigator.md example + cap inventory (pre-release audit stale-ref sweep, s01-e3e1ed)
  • always stamp AGENT_VERSION in settings.json even when user template provides version field (SX-620)
  • copy package.json into dist/ so AGENT_VERSION stamps correctly (SX-619, superseded by SX-624 for runtime path)
  • backport v0.21 cache economics to bundled defaults (SX-600)
  • health check reads Pi version from dist/manifest.json (authoritative) instead of CORE_DIR/node_modules (stale-prone) (SX-622)
  • ship templates/ to dist/ so body/ scaffolds fully (SX-594)
  • smart partial-state handling + rootName + doctor bail on soma init (SX-592)

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • soma-workspace-migrate-legacy.sh — lazy migration W2 of plan 02 (s01-680a9c, preload #3) — walks ~/.soma/plugins/<type>/state.json and copies each into ~/.soma/workspaces/__legacy__/<type>/<type>-1.json + registers in ~/.soma/workspaces/__legacy__/panes.json. Idempotent (re-run skips already-registered instances). Skips leading-underscore types (_test, _regression_test) by default. Preserves old paths for one release cycle as fallback. Per 02-workspace-pane-config.md § Migration W2 (lazy) and ~/.soma/workspaces/README.md. Smoke-verified end-to-end against a tmp clone of ~/.soma/plugins/: 8 panes migrated, registry built with types/paths/timestamps/provenance markers, re-run skipped all 8.
  • soma bridge CLI — start/stop/restart/status/logs/config/setup (SX-522) — first-class bridge daemon lifecycle. Works standalone without Somaverse; mirrored by somaverse:bridge.* (7 caps) + somaverse:auth.* (3 caps) for agent-side automation.
  • soma:agent.* meta-tool — delegate/children collapsed (SX-609) — 7 caps: delegate, list, tail, steer, kill, harvest, focus (focus op recovered from original plan). Extension shrank 606→330 lines.
  • soma:focus.* / soma:new.* / soma:terminals.* — 11 new caps wrapping bundled CLIs. Also fixed soma focus dispatcher’s inverted discovery order.
  • soma-install.sh dev cross-repo extension union + node_modules symlink (SX-629) — reproducible end-to-end; fixed a latent Pi 0.66.1→0.69.0 drift.
  • soma:docs.* for bundled docs search + retrieval (SX-594 Phase 3 Step C + SX-588 + SX-596)
  • progressive-awareness entry point for meta-tools (SX-594) — bare-prefix family discovery + op='help' block for every meta-tool.
  • soma:body.* (slots/cost/audit) from dev:body.* move (SX-594 Phase 3 Step B)
  • family-level capability discovery via bare-prefix call (SX-594)
  • register soma:* meta-tool + soma:browser.* (17 caps, SX-594 Phase 2 Step C) — direct-CDP default; bridge required only for advanced ops (evaluate, styles, emulate, performance).
  • v0.22.0 version infrastructure + soma-release --vbump / --vaudit + dev-install package.json symlink (SX-622)
  • hash-based bundled template drift refresh (SX-621) — doctor auto-refreshes pristine-older body templates to current bundled; warns with diff path for customized files. Keyed off migrations/template-hashes.json shipped with the agent.
  • Pi runtime upgrade 0.67.68 → 0.69.0 (SX-623) — 42 upstream commits (17 coding-agent fixes, 4 new features, 5 ai fixes, 2 tui fixes). Non-breaking: tool registration + extension API unchanged. Internal refactor: cwd-singleton tool filtering replaced by name-based allowlists (same behavior for extensions that register unique names). Notable improvements: symlink session resolution, skills dedup, xterm uppercase input, shell-path uses session cwd, OpenAI-compatible prompt caching (anthropic-style cache_control).
  • teach verify + symlink commands about somaverse-tools + addons (SX-613)
  • progressive-awareness retrofit across 4 commands (SX-590)soma body, soma tool, soma concepts, soma-dev status now emit a curated What next: block after every state. Bare command == --help. Suppressed when piped (isatty check). Helper soma_next_steps added to scripts/soma-theme.sh; parallel next_steps in scripts/_dev/soma-dev/lib/colors.sh. Muscle: amps/muscles/cli-progressive-awareness.md (heat 3).
  • dev:cli.* addon — 17 soma-shell capabilities (SX-585) — wraps soma plans/reflect/trace/concepts/threads/blog-audit/blog-graph/body/protocol-audit/compat + pro (refactor/github/scrape/seam) + dev (dev/deploy) + cli.raw escape. Agents see the CLI surface via dev(op='list', prefix='dev:cli.'). Zero cache bust (addon lives outside cached prefix).
  • docs/amps.md + docs/migrating.md seeded from website (SX-586) — the two website-only docs now have agent-side sources. Next sync-to-website.sh run is a no-op (zero byte drift verified). Future edits happen agent-side.

Changed

  • SX-594 wrapper sweep — archived deprecation shims (SX-601)workspace_*, plugin_state_*, flat browser_*, code_*, dev:ai.*, dev:body.*, file_outline no longer register at boot. The cached prompt no longer carries the double surface. Wrappers moved to _archive/sx594-flat-wrappers/ in both agent + somaverse repos.
  • Tier C stale-reference sweep across muscles / docs / MAPs (SX-628) — remaining references to archived flat tool names cleaned up.

Changed

  • ai_*dev:ai.* addon extraction (SX-591 Phase A) — 5 flat Pi-registered tools (ai_status, ai_load, ai_index, ai_search, ai_embed) removed from the cached prompt surface; same capabilities behind the dev meta-tool. Call via dev(op='call', cap='dev:ai.search', args={...}). ~3KB reduction in cache_creation_input_tokens per session on cold boot. Pilot for the v0.22.x namespaced-meta-tools arc (SX-594).

[0.21.1.1] — 2026-04-22 — Same-cycle audit patches

Micro-release caught during a post-ship audit of v0.21.0..HEAD. Three findings with real code impact; two dead-code + hygiene tidy-ups.

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.

  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.

  • soma-workspace-migrate-legacy.sh — lazy migration W2 of plan 02 (s01-680a9c, preload #3) — walks ~/.soma/plugins/<type>/state.json and copies each into ~/.soma/workspaces/__legacy__/<type>/<type>-1.json + registers in ~/.soma/workspaces/__legacy__/panes.json. Idempotent (re-run skips already-registered instances). Skips leading-underscore types (_test, _regression_test) by default. Preserves old paths for one release cycle as fallback. Per 02-workspace-pane-config.md § Migration W2 (lazy) and ~/.soma/workspaces/README.md. Smoke-verified end-to-end against a tmp clone of ~/.soma/plugins/: 8 panes migrated, registry built with types/paths/timestamps/provenance markers, re-run skipped all 8.

  • soma model-sync — audit + set defaultModel across all scopes. New bundled script scripts/soma-model-sync.sh. Audits global (~/.soma/settings.json) + project (<cwd>/.soma/settings.json) + any .soma/ dirs under $HOME (with --crawl). --set <id> writes everywhere; --yes skips confirmation; idempotent. Bundled default is claude-opus-4-7 (the latest Opus on Claude Max plans). Creates settings.json where missing; preserves all unrelated keys in files that are already populated. Closes the “keep every project on the current model without hand-editing” gap. 23-assertion test suite at tests/test-model-sync.sh. Guide: docs/guides/sane-defaults.md.

Fixed

  • TmuxDriver shell-quoting. tmuxExec used JSON.stringify per-arg, which wraps in double quotes — bash double-quotes let $(...) + backticks + $VAR expand on the parent shell before tmux sees them. A task like "list files in $(pwd)/logs" would arrive at the child with $(pwd) already substituted for the parent’s cwd. Switched to single-quote wrapping with the classic '\'' escape for embedded quotes. Verified against 7 edge cases (plain, single + double quotes, backticks, $(), paths, semicolons — all round-trip literal).

    Not a security bug (self-injection only; same user), but a correctness bug that landed in v0.21.1 and would surface the first time a user wrote a task with shell metacharacters.

  • soma-model-sync shell-to-python interpolation. read/write_default_model built python -c source via $var interpolation. A model id with a single quote character (or shell metacharacter) would break the -c block. Moved path + model to env vars (SOMA_MS_PATH, SOMA_MS_MODEL); python source is now static.

  • .gitignore: __pycache__/ + *.pyc. An accidentally-tracked scripts/__pycache__/soma-children.cpython-313.pyc landed in the v0.21.1 agent dev commits. Confirmed it did NOT ship to soma-beta (.releaseignore filtered it), so no user runtime impact. Cleaned up + prevented future recurrence.

  • Dead code removed. shEscape helper in core/terminal-drivers/tmux.ts was orphaned after the signature changed during the driver refactor.

  • Import order. biome --write --unsafe on core/terminal-drivers/index.ts

    • extensions/soma-delegate.ts to match the project’s import conventions.

[0.21.1] — 2026-04-22 — Children control panel + tmux baseline

Patch release. Three themes woven together: complete the background- delegation surface (Phase B ops), ship background delegation to npm users (tmux driver), and fix a months-old dead branch in the boot resume path so the delta-diff and /reload signal can actually fire.

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.

  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.

  • soma-workspace-migrate-legacy.sh — lazy migration W2 of plan 02 (s01-680a9c, preload #3) — walks ~/.soma/plugins/<type>/state.json and copies each into ~/.soma/workspaces/__legacy__/<type>/<type>-1.json + registers in ~/.soma/workspaces/__legacy__/panes.json. Idempotent (re-run skips already-registered instances). Skips leading-underscore types (_test, _regression_test) by default. Preserves old paths for one release cycle as fallback. Per 02-workspace-pane-config.md § Migration W2 (lazy) and ~/.soma/workspaces/README.md. Smoke-verified end-to-end against a tmp clone of ~/.soma/plugins/: 8 panes migrated, registry built with types/paths/timestamps/provenance markers, re-run skipped all 8.

  • children tool — Phase B ops (SX-553)tail / steer / kill / harvest on top of list. tail uses the driver’s capture; steer sends a chat message (blocked on non-running); kill closes the driver container + marks aborted; harvest returns the MLR placeholder + removes the entry from the registry. findChild(id) accepts either the child id or the driver handle id (e.g. surface:8, soma-child-abc).

  • TerminalDriver interface + TmuxDriver baseline (SX-580 Phase C.1–C.2) — new core/terminal-drivers/ package with a unified driver interface. Two implementations: TmuxDriver (ships to npm — detached tmux sessions, attach-on-demand via tmux attach -t soma-child-<id>, works on any Unix with tmux installed, no TTY issues, CI-compatible) and CmuxDriver (dev- mode only, existing logic refactored with zero behavior change). Auto- pick prefers tmux > cmux. delegate gains optional terminal:'tmux'|'cmux' param. ChildEntry schema gains driver, handle_id, attach_hint; legacy pane/surface kept for pre-refactor entries. children list table gains a driver column. First time delegate(background:true) works for a non-cmux user in any Soma release.

  • soma terminals CLI + persistent driver preference (SX-580 Phase C.3–C.4) — new bundled scripts/soma-terminals.sh modeled on soma-blog’s self-describing pattern. Subcommands: list, detect (list + recommendation), status (current configured driver), prefer <driver> (persist to ~/.soma/settings.json delegate.terminal), setup [<driver>] (install walkthrough), doctor [<driver>] (diagnose why a driver isn’t working). pickDriver() consults settings before auto-pick. Precedence: per-call terminal: param → settings → auto-pick. Agent can run soma terminals setup and walk a user through install when delegate(background:true) fails with no-driver-available.

  • /reload distinguished from resume in boot messagesoma-boot now stamps process.pid on every fingerprint entry. On resume, if the most recent entry’s PID matches process.pid, the extension re-activated in- process (= user ran /reload) and the boot message becomes [Soma Boot — /reloaded] with the explicit signal any 'needs /reload' work from the last turn is now live. Prompt cache is already busted by /reload so emitting a message here costs nothing. Distinguishes from: ctrl-C restart (new PID, resumed session) and periodic checkpoints (not a boot at all).

  • Background-delegation guide — new docs/guides/background-delegation.md with the sync-vs-background decision tree, tmux install hints, mental model, attach-on-demand pattern, full children-ops examples, kill-vs-harvest semantics, the MLR-writing gap stated honestly, troubleshooting entries for the two surfaced bugs, and a pointer for authoring new drivers. docs/tools.md + docs/commands.md gain cross-links and CLI table rows.

  • Upstream Pi patches shipped as dist overlays:

    • pi-tui inline image height cap (SX-579) — tall clipboard screenshots no longer take over the terminal. Capped at a readable row count via PI_TUI_MAX_IMAGE_ROWS (default 80% of process.stdout.rows, min 20). Patch is PR-shaped (opt-in, backward-compatible) pending the upstream CONTRIBUTING.md flow.
    • Compaction ephemeral-path filter (SX-569)extractFileOpsFromMessage in Pi’s compaction util was collecting every read/write/edit path into <read-files> / <modified-files> XML blocks. macOS clipboard paste-temp files (/var/folders/.../T/clipboard-*.jpeg) + /tmp/*.{png,jpg,…} screenshots accumulated across compactions. Added isEphemeralPath(p) guard. Zero payload mutation.

Fixed

  • Boot resume fingerprint reader was reading the wrong field — filter code read entry.content?.fingerprint, but Pi’s SessionManager.appendEntry stores payloads under entry.data. The delta-diff branch had been silently dead since it was written; every resume fell through to the “no fingerprint” fallback. Fixed — delta-diff resume now actually fires when heat or muscles changed.
  • delegate(background:true) was broken since Phase A shippedCMUX_SCRIPT path resolution used an unset env var + a dev-install symlink that doesn’t cover scripts/. Every call hit “install cmux” even when cmux was running. New resolution walks SOMA_CMUX_SCRIPT env → SOMA_CODING_AGENT_DIR → cwd-relative → walk-up → dev-symlink → PATH. Uncovered by end-to-end exercise.
  • Model alias leakage to childrenspawnBackground passed bare aliases (haiku, sonnet, opus) straight to soma --model, and Pi’s model registry picked the wrong provider (us.anthropic.haiku-4-5 = bedrock) in the child’s environment. Child died on missing bedrock creds. MODEL_ALIASES now exported from core/delegate-core.ts; aliases are pre-resolved to fully-qualified ids (claude-haiku-4-5) before building the boot command.
  • Registry stayed running after a child’s container closed — no auto status-transition on pane death. New reconcileChildStatuses() pass runs at the start of children(op:'list'): any registry entry whose driver container is gone auto-flips to completed with ended_at.
  • Channel guard false-positive on SOMA_PROJECT_DIR — the soma_pro keyword in the guard’s pattern matched SOMA_PROJECT_DIR env mentions in benign output. Narrowed the pattern.

Verified end-to-end (s01-b1b654)

delegate(background:true, terminal:'tmux', model:'haiku')children(op:'list')tailsteerkillharvest against a real tmux-spawned child. Child booted in a detached tmux session, executed the task, responded to steer, kill cleanly closed the session (tmux ls confirmed: no server), harvest returned the summary and removed the registry entry. Model resolved to claude-haiku-4-5 end-to-end. Same flow also verified against a cmux-spawned child earlier in the same session — both drivers work.

Release notes: .soma/releases/v0.20.x/v0.21.1/release-notes.md.

[0.21.0] — 2026-04-22 — Cache Economics + Discoverability + Self-Knowledge

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • soma-workspace-migrate-legacy.sh — lazy migration W2 of plan 02 (s01-680a9c, preload #3) — walks ~/.soma/plugins/<type>/state.json and copies each into ~/.soma/workspaces/__legacy__/<type>/<type>-1.json + registers in ~/.soma/workspaces/__legacy__/panes.json. Idempotent (re-run skips already-registered instances). Skips leading-underscore types (_test, _regression_test) by default. Preserves old paths for one release cycle as fallback. Per 02-workspace-pane-config.md § Migration W2 (lazy) and ~/.soma/workspaces/README.md. Smoke-verified end-to-end against a tmp clone of ~/.soma/plugins/: 8 panes migrated, registry built with types/paths/timestamps/provenance markers, re-run skipped all 8.
  • suppress preventive OAuth-billing warning at boot (SX-566)
  • test-audit command + hygiene rule engine (SX-564)
  • swap Pi’s π terminal-title glyph for Soma’s σ
  • Agent Notes relocation + preload ancestry + v0.21.0
  • Terminal tab title now shows σ - <session> - <cwd> — build-time patch to Pi’s interactive-mode.js swaps the π brand glyph for Soma’s σ. Display-only, zero cache/payload impact. Closes the last Pi brand leak in the TUI chrome.
  • Declarative migration replay via map frontmatter (SX-562)soma doctor is now data-driven. Migration maps can declare replay-until: <version> in frontmatter + a ## Doctor Actions JSON block in the body (schema: settings-defaults, settings-subkeys, scaffold-files). While the running agent is below replay-until, doctor re-evaluates that map on every invocation and applies its actions idempotently. Once agent catches up, the map retires from the replay pass automatically. Future backfill-class migrations don’t need CLI code changes — they just add the block to their map. Session-start boot path untouched; only explicit soma doctor runs the replay.
  • Agent Notes relocated out of body/ecosystem.md (SX-547, v0.21.0) — the rolling session-observation log now lives at memory/notes/soma-log.md (bundled template seeds at init, doctor tier-1 soft-check backfills for upgrades via writeIfMissing). body/ecosystem.md shrank from 33KB/322 lines to 10KB/174 lines and is now lazy: true so its content no longer hits the cached prefix on every boot. Expected cacheWrite savings: ~5.5K tokens/boot (~25%).
  • Recent Ancestry auto-injected into preload (SX-549) — last N entries from memory/notes/soma-log.md inject as ## Recent Ancestry in the preload user-message on fresh boot. Configured via settings.preload.recentNotesCount (default 3; set 0 to disable). User-message injection only; does not affect the cached system prompt. Graceful no-op if memory/notes/soma-log.md is missing.
  • Children monitor promoted to bundled scripts (SX-557 follow-up)soma children list/tail/kill/focus/watch + new soma children spawn <role> "<task>" now ship via repos/agent/scripts/ (was workspace-only). Shell-spawned children register themselves in ~/.soma/state/children.json so the shipped children Pi tool and the CLI dashboard share the same registry. Hex IDs (child-xxxxxx) match the SX-553 shape. tmux default driver, cmux optional when available.
  • Doctor tier-1 soft-check for v0.21.0 structural pieces — pre-0.21.0 users never received the backfilled migration chain, so addIfMissing + a new scaffoldMemoryNotes check run on every boot. Missing memory/notes/soma-log.md gets scaffolded from the bundled template (writeIfMissing, never clobbers). Tier-2 (agent-driven) handles body/_memory.md customization review via the migration map’s agent-prompt.
  • Crystallize Phase A: soma new muscle / soma new protocol + templates (SX-559) — lowers the friction of creating new muscles or protocols. Scaffolds the file at the right location (.soma/amps/muscles/<name>.md or --global for ~/.soma/...) from a canonical template with frontmatter pre-filled (created date, session origin, author, description, triggers). Idempotent — re-running on an existing name opens it in $EDITOR instead of clobbering. Templates live at templates/default/_muscle-template.md + _protocol-template.md as single source of truth for frontmatter conventions. Addresses the “she’ll see patterns but won’t crystallize them because the ceremony is too high” gap. Phase B (the crystallize Pi tool) + Phase C (idempotent update semantics) scoped in releases/v0.20.x/plans/crystallize/README.md.
  • Discoverability: soma tool CLI + capabilities Pi tool (SX-558) — two surfaces to introspect Soma’s tool registry without re-reading the whole system prompt. soma tool (no args) lists every registered tool with a one-liner; soma tool <name> prints the full authored guidance (description, promptSnippet, promptGuidelines, parameters). Runs offline via static parse of extensions/*.ts — no session needed. For the runtime view (post-_tools.md overrides), a new capabilities Pi tool with op:'list' and op:'detail' does the same thing from inside a session. Closes the “soma delegate --help does nothing” gap. Bundled docs at docs/tools.md#discovering-whats-registered and docs/commands.md.
  • Lazy-loaded body files (SX-548) — body files with lazy: true in frontmatter now contribute only their description field to the cached system prompt. Full content loaded on demand via the read tool. Opt-in per file; missing flag preserves existing behavior. Enables Tier 2 loading for volatile files (ecosystem.md Agent Notes, journal.md index) with a one-line config change. Expected cacheWrite savings: ~5K tokens per boot when applied to ecosystem + journal.
  • Project core_rules.md additions (SX-555) — projects can now place a body/core_rules.md in their .soma/ directory; content is appended after the agent-shipped system-core.md rather than replacing it. Shipped rules cannot be accidentally removed by a project override. Missing file = identical behavior to pre-0.20.4.
  • delegate(background:true) + children tool (SX-553 Phase A)delegate now accepts background:true to spawn a child soma in a new cmux pane and return a handle immediately ({childId, pane, surface, status}) instead of blocking. New children Pi tool with op:"list" reads ~/.soma/state/children.json and formats a status table (id, role, model, status, cost, runtime, pane). Atomic-rename IO helpers (appendChild, updateChild, readChildrenJson, writeChildrenJson). Backward-compat: omitting background preserves existing synchronous behavior. Phase B (tail/steer/kill/harvest) + Phase C (ghostty/tmux drivers) pending.
  • cache.retention setting (SX-544 Phase A) — new settings schema cache: { retention: 'long' | 'short' | 'none' | null }. When set to "long", soma-boot injects PI_CACHE_RETENTION=long for Pi’s provider layer, enabling 1-hour Anthropic prompt cache TTL (2× write cost, break-even at one re-hit within 60m). Default null = inherit shell env or Pi default (5m). Doctor migration adds the key to existing settings.json. No behavior change until user opts in. Phase B (validation) + Phase C (keepalive coupling) still pending.
  • soma-deploy.sh — thin wrapper on Dokploy API
  • browserCdpHost + browserCdpUrl — browser can live anywhere
  • browser profile tokenization — userDataDir + profileDirectory
  • Endpoint resolver (SX-513, s01-6d05dd) — single source of truth for every URL the agent touches. Tier 2 extensions (bridge-connect, workspace-tools) + dev scripts (launch-browser) now route through _shared/env.ts (Node side) + soma-env.sh (bash side). Mode taxonomy: local / cloud / pro / enterprise / auto. User default cloud; our dev default auto (probes localhost:18800, falls back to cloud). Config lives under environment in settings.json and is only read by the dev extension — prod has endpoints baked at build time.
  • bridge-connect-dev.ts — dev-only sibling of the shipped bridge-connect.ts. Reads environment.mode + overrides live, exposes a new env_status tool for runtime diagnostics. Installed via soma-dev symlink extensions --dev.
  • soma-env.sh — pure-bash resolver helper (no node dep, no cold start). Mirrors env.ts’s defaults table. Parity guarded by test-env-resolver-parity.sh so the two implementations can’t drift.
  • environment block in SomaSettings interface (core/settings.ts) — typed config for future agent-side soma env CLI; dev extensions read it today, prod extensions ignore it.
  • Three new test suites (tests/test-env-resolver.sh, test-env-resolver-parity.sh, test-no-hardcoded-endpoints.sh) — 25 + 24 + 4 assertions covering resolver behavior, shell/TS parity, and a golden-rule guard that catches any regression back to literal endpoints in migrated Tier 2 files.
  • SOMA_PROJECT_DIR env var exported to discovered scripts (SX-555) — when soma <cmd> dispatches to a discovered script (bundled / project / global), it now walks up from $PWD to find the nearest .soma/ directory and exports the path as SOMA_PROJECT_DIR. Scripts can trust the env var instead of recomputing from $0 (which breaks for bundled scripts living far from the user’s project). Paired with the resolve_soma_dir helpers in soma-refactor.sh / soma-seam.sh.
  • soma update --yes / -y — skip the Y/N confirmation prompt in scripted upgrades. Closes the documented one-liner npm install -g meetsoma@latest && soma update --yes. Surfaced during the s01-c6944c CLI audit (post-v0.20.3 follow-up).

Fixed

  • ship .py helpers + _lib/ alongside .sh scripts
  • comprehensive settings backfill + Pro auth scaffold + upgrade test
  • add digest blocks to 3 bundled muscles (SX-563)
  • run tier-1 soft-check unconditionally
  • resolve soma_dir correctly + bash 3.2 compat + honest stable error
  • soma refactor / soma seam now resolve the right project directory when run outside cwd (SX-555) — both scripts previously computed SOMA_DIR relative to their own install location, which broke for users whose project .soma/ wasn’t a sibling of the script. Added resolve_soma_dir helper that prefers $SOMA_PROJECT_DIR, then walks up from $PWD, then falls back to the legacy relative path. Also handles SIGPIPE gracefully (was killing piped output).
  • soma plans bash 3.2 compat restored (SX-555) — the overlap command used declare -A (associative arrays), which macOS bash 3.2 doesn’t support. Rewrote to emit topic/path tuples to a tempfile, sort, and group — portable across bash versions. get_field now returns || true so missing frontmatter fields don’t trip pipefail.
  • soma-install.sh stable gives an honest error (SX-555)repos/agent-stable was retired s01-419457 in favor of git tags. Stable mode now prints an explanation and points to the tag-based-install plan instead of failing silently.
  • extractTldr no longer truncates multi-line TL;DRs
  • symlink-extensions.sh used stale post-restructure path — was pointing at somaverse/extensions/ (moved to somaverse/builds/local/extensions/ in s01-efe898). Updated + added --dev flag that swaps the bridge-connect symlink to the dev variant.
  • build.sh auth-gate temp files broke relative imports — temps were written to /tmp/ so esbuild couldn’t resolve ./_shared/env.js. Moved temps next to sources.

[0.20.3] — 2026-04-20

Patch release. Cache-stickiness: /reload no longer invalidates the Anthropic prompt cache. The compiled system prompt is persisted to .soma/state/.session-prompt-cache.json and restored across reload/resume/fork. A new /rebuild command forces explicit recompile when body edits should be picked up.

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • soma-workspace-migrate-legacy.sh — lazy migration W2 of plan 02 (s01-680a9c, preload #3) — walks ~/.soma/plugins/<type>/state.json and copies each into ~/.soma/workspaces/__legacy__/<type>/<type>-1.json + registers in ~/.soma/workspaces/__legacy__/panes.json. Idempotent (re-run skips already-registered instances). Skips leading-underscore types (_test, _regression_test) by default. Preserves old paths for one release cycle as fallback. Per 02-workspace-pane-config.md § Migration W2 (lazy) and ~/.soma/workspaces/README.md. Smoke-verified end-to-end against a tmp clone of ~/.soma/plugins/: 8 panes migrated, registry built with types/paths/timestamps/provenance markers, re-run skipped all 8.
  • /rebuild command (SX-495) — forces recompile of the system prompt and deletes the disk cache. Optional — only run it if you’ve edited body/*.md mid-session AND you want the change to apply right now. Otherwise /reload keeps the prompt sticky and body edits land naturally on your next session.
  • Disk-backed prompt cache (SX-495).soma/state/.session-prompt-cache.json written on first compile, restored on subsequent reloads. Eliminates the ~$1 cache-invalidation cost per /reload.
  • Severity-aware change indicator on statusline line 3 — replaced the intrusive “Changes detected” toast with a subtle third-line tag. Labels: 🔄 /reload (extensions/.ts + core/.ts; picked up by jiti re-import — confirmed in Pi’s extensions.md), 📝 /rebuild? (body/.md — the ? denotes optional), ⚠ relaunch (dist/ or core/*.js — Pi’s static imports are frozen at process boot, /reload can’t help; /exit and run soma again). Signal writer + reader updated; legacy severity: restart still read for back-compat. Parser handles both YAML and JSON payloads (SX-497 will unify writers).
  • Commands doc — Reload & Rebuild section (docs/commands.md) — explains the two commands, when to use each, and what the statusline indicators mean.

Fixed

  • Tier 2 extension build path updated for somaverse restructurebuild-extensions/build.sh SOMAVERSE_EXT now points to somaverse/builds/local/extensions/ (moved s01-efe898). Unblocked v0.20.3 dry-run.

  • soma focus restored. Was silently broken since the Pro-scripts refactor moved soma-seam.sh into scripts/_pro/ (and released form renamed to .js). soma-focus.sh only looked for scripts/soma-seam.sh and always errored. Now searches scripts/, scripts/_pro/, $SOMA_DIR/amps/scripts/, ~/.soma/amps/scripts/ and dispatches node for .js / bash for .sh. End-to-end verified.

  • docs/focus.md accuracy. Scoring table, force-include threshold, and heat formula were all out of date. Corrected to match core/muscles.ts:matchMusclesToFocus — trigger/keywords/topic list match (10), name (3), digest (2); force-include at >= 8; heat = score + 2; tags don’t participate.

  • soma-dev sync-docs walks subdirs. docs/guides/ was missing from the website; bash 3.2-compatible explicit loop added.

  • /reload no longer invalidates Anthropic prompt cache (SX-495) — previously, re-importing soma-boot reset compiledSystemPrompt to null; next turn recompiled from disk and re-sealed a fresh cache, forcing a miss. Now tryRestoreCompiledPrompt() rehydrates from disk when session_start.reason ∈ {reload, resume, fork}. Fresh launches (reason=startup|new) still compile from scratch. invalidateCompiledPrompt() also unlinks the cache file (called by /pin and /kill).

Plan

  • .soma/releases/v0.20.x/plans/cache-stickiness.md — full audit + fix spec + acceptance criteria.

[0.20.2.1] — 2026-04-19

Patch release. Closes the _mind.md template orphan, adds the Soma tool registry with _tools.md configuration, documents tools + extension plumbing, softens the restart alert. Three Soma tools added (context_status, file_outline, search). Four script-UX no-flag fixes. CLI version label corrected in dev mode.

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • soma-workspace-migrate-legacy.sh — lazy migration W2 of plan 02 (s01-680a9c, preload #3) — walks ~/.soma/plugins/<type>/state.json and copies each into ~/.soma/workspaces/__legacy__/<type>/<type>-1.json + registers in ~/.soma/workspaces/__legacy__/panes.json. Idempotent (re-run skips already-registered instances). Skips leading-underscore types (_test, _regression_test) by default. Preserves old paths for one release cycle as fallback. Per 02-workspace-pane-config.md § Migration W2 (lazy) and ~/.soma/workspaces/README.md. Smoke-verified end-to-end against a tmp clone of ~/.soma/plugins/: 8 panes migrated, registry built with types/paths/timestamps/provenance markers, re-run skipped all 8.
  • Soma tool registry (core/tool-registry.ts) with somaRegisterTool() helper — the man-in-the-middle between extension-defined tools and Pi’s registry. Preserves promptSnippet + promptGuidelines in the compiled system prompt (Pi’s ToolInfo strips them).
  • _tools.md configuration (project → parent → global body chain). Sections: Disabled (opt-out list), Overrides (per-tool field tweaks), Custom (parsed; registration lands v0.20.3). Hardwired set (delegate) cannot be disabled.
  • context_status tool — returns {percent, tokens, contextWindow} so the agent can ground its runway decisions instead of estimating.
  • file_outline tool — markdown/text headings with line numbers. 10–15× cheaper than full-file reads for orientation.
  • search tool (MVP) — unified search with pluggable backends. Default: ripgrep over cwd, respects .gitignore. scope="api" uses Brave Search when BRAVE_API_KEY or SOMA_SEARCH_API_KEY is set. scope="semantic" deferred to v0.20.3.1.
  • docs/tools.md (new) — Soma tools reference: three registration routes, _tools.md format, sub-agent scoping, bundled set, invocation vs prompt registries.
  • docs/extending.md additions: pi.registerTool + pi.getActiveTools + pi.getAllTools in API table; hot-reload notes; “Modifying the System Prompt” section; full Soma Tools section (writing a tool with somaRegisterTool, comparison table vs pi.registerTool); External tool → Soma bridge (the inbox) section documenting the drop-in CLI integration (token, allowlist, JSON format).
  • body/_tools.md seeded in meetsoma + bundled templates/default/_tools.md.
  • Refactor breadcrumbs at top of extensions/soma-boot.ts — clean-break candidates noted (~3700 LOC file) for a future refactor session.

Fixed

  • Tool-registry timing fix (37106e0)_tools.md disable/override rules now apply at extension-load time. Pi loads extensions (calling somaRegisterTool) BEFORE firing session_start, so the previous setToolConfigChain() call ran too late. Fix: lazy chain self-discovery in getToolConfig() — walks up from process.cwd() if no explicit chain is set. 6 new timing tests added (62/62 total passing, was 56).

  • _mind.md was orphaned since Phase 1c.1 (s01-a1a6aa). The Pi-native shortcut returned event.systemPrompt unchanged when SYSTEM.md + APPEND_SYSTEM.md existed, bypassing the template compiler. User customizations to body/_mind.md had no effect. The shortcut is removed. compileFullSystemPrompt (template-driven via compileWithTemplate) is now the single path. SYSTEM.md / APPEND_SYSTEM.md writes redirect to .soma/state/ as introspection artifacts; Pi no longer auto-discovers them.

  • soma --version in dev mode showed runtime v0.20.2 instead of CLI v0.3.5. npm/thin-cli.js read __dirname/../package.json, which resolved to agent’s package.json in dev-symlink installs. Esbuild --define:__CLI_VERSION__ + build-dist.mjs string-substitution now inject the correct literal.

  • Restart alert too aggressive. Pi /reload hot-reloads extensions via jiti.import (mtime-keyed cache) — extensions/*.ts edits don’t need a full process restart. .git-hooks/post-commit now classifies changed files: extensions/*.ts and core/*.tsseverity=reload; core/*.js and dist/*severity=restart. soma-statusline reads severity and shows the matching message.

  • Script no-flag UX (SX-490): soma-login no longer starts OAuth without an explicit start subcommand. soma-snapshot no longer snapshots CWD without an explicit path — bare invocation prints help + recent snapshots. soma-theme now prints help when executed directly (still sources cleanly). git-identity-hook unchanged (silent exit-0 is correct for a git hook).

Changed

  • somaRegisterTool replaces pi.registerTool across all Soma bundled tool files (soma-delegate, soma-code-tools, soma-context, soma-search). Third-party extensions using pi.registerTool directly still work; tools just render with description-only (no per-tool promptSnippet/promptGuidelines).
  • buildToolSection accepts an optional somaTools registry. When present, rendered output includes per-tool guideline bullets prefixed [tool_name].
  • .git-hooks/ now tracked in git (was gitignored under a non-existent “generator”). Install path unchanged: git config core.hooksPath .git-hooks.

Docs

  • New docs/tools.md.
  • Substantial docs/extending.md expansion (tools, inbox, system-prompt hook, hot-reload).

Deferred / parked for v0.20.3

  • Full deletion of compileFullSystemPrompt + extractSections + buildToolSection legacy helpers (reversed this session — the compiler is staying; _mind.md drives the prompt).
  • Custom markdown-defined tools (_tools.md Custom section) — shell execution + security model.
  • Multi-provider search backends (tavily, exa, perplexity).
  • Local-semantic search backend + soma index command.
  • Audit-token release tool.
  • Upstream ask to Mario re: exposing promptSnippet/promptGuidelines on ToolInfo.

[0.20.2] — 2026-04-18

The v0.20.3 prompt refactor arc. Moves Soma from “replace Pi’s prompt wholesale” (compileFullSystemPrompt rebuild path) to “let Pi compile; we augment” (SYSTEM.md

  • APPEND_SYSTEM.md via Pi’s native auto-discovery). Option B from the REFACTOR-PLAN. Also: 5 script-backed Pi tools, a pretest CLI, and two version-check bug fixes.

Pi-native mode is now DEFAULT when SYSTEM.md + APPEND_SYSTEM.md exist. Escape hatch: SOMA_LEGACY_PROMPT=1 forces the old full-replacement path. Kept alive until Phase 1c.2 (planned deletion of ~300 LOC rebuild path).

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • soma-workspace-migrate-legacy.sh — lazy migration W2 of plan 02 (s01-680a9c, preload #3) — walks ~/.soma/plugins/<type>/state.json and copies each into ~/.soma/workspaces/__legacy__/<type>/<type>-1.json + registers in ~/.soma/workspaces/__legacy__/panes.json. Idempotent (re-run skips already-registered instances). Skips leading-underscore types (_test, _regression_test) by default. Preserves old paths for one release cycle as fallback. Per 02-workspace-pane-config.md § Migration W2 (lazy) and ~/.soma/workspaces/README.md. Smoke-verified end-to-end against a tmp clone of ~/.soma/plugins/: 8 panes migrated, registry built with types/paths/timestamps/provenance markers, re-run skipped all 8.
  • smarter randomizer + version-aware skeletons + CLI integration
  • three-layer version snapshot + update check (SX-489)

Phase 1a/1b — SYSTEM.md + APPEND_SYSTEM.md auto-discovery pipeline:

  • compileSystemMd(options) + writeSystemMd(options) in core/prompt.ts. Compiles identity-only content (soul + voice + body + ecosystem + core_rules) to <somaPath>/SYSTEM.md. Pi auto-discovers via resource-loader.js:660 discoverSystemPromptFile() and uses as customPrompt.
  • compileAppendSystemMd(options) + writeAppendSystemMd(options) in core/prompt.ts. Compiles AMPS + tools + guard + docs to <somaPath>/APPEND_SYSTEM.md. Pi auto-discovers via resource-loader.js:671 discoverAppendSystemPromptFile() and uses as appendSystemPrompt.
  • Writers wired in extensions/soma-boot.ts: writeSystemMd at session_start, writeAppendSystemMd at before_agent_start (eagerly, before path split, so both Pi-native and legacy paths keep APPEND current).
  • SYSTEM_MD_FALLBACKS constant: minimum-viable Soma-voice prose for empty soul/voice/body/ core_rules. Keeps SYSTEM.md coherent in fresh-install directories.

Phase 1c.1 — Pi-native as default:

  • before_agent_start now defaults to Pi-native when SYSTEM.md + APPEND_SYSTEM.md exist.
  • Legacy opt-out via SOMA_LEGACY_PROMPT=1. First-run safety: missing files → legacy path runs, seeds files for session N+1.

Phase 1d — XML tag experiment (Anthropic-style adherence aid):

  • <rules> tag around core_rules in SYSTEM.md output (first behavioral tag in our compiled prompt — previously we had only Pi’s native <available_skills>).
  • <behavioral_rules> + <tool_guidance> tags in APPEND_SYSTEM.md. Matches Anthropic’s own prompt conventions (Sonnet 4.5 → 4.6 doubled tag count; we were at 1).

Phase 2 — 5 script-backed Pi tools (extensions/soma-code-tools.ts):

  • code_find — grep with file:line:match output, respects .gitignore (cap 500)
  • code_map — function/class/method index for a file
  • code_refs — symbol references classified as DEF / USE / IMP (run before renaming)
  • code_structure — directory tree with file sizes, max depth 3
  • code_blast — blast radius: all files touching a symbol with severity (run before deleting)
  • All executionMode: "parallel" (read-only, safe concurrent), ANSI colors stripped, output capped with helpful refinement hints when truncated.
  • promptSnippet + promptGuidelines populated on all 5 so Pi surfaces them in the “Available tools:” / “Guidelines:” prose (first effect visible post Phase 1c.1).

soma preview — pretest CLI (scripts/soma-preview.{sh,ts}):

  • Compiles SYSTEM.md + APPEND_SYSTEM.md from live body files without a sandbox restart.
  • Flags: --out <dir>, --system-only, --append-only, --quiet, --diff, --help.
  • --diff compares fresh compile against on-disk files with byte deltas and staleness.
  • Runs outside the TUI. No API cost.
  • Distinct from scripts/prompt-preview.ts (fixtures-based scenarios for testing).

Fixed

  • cap items per version (highlights only, not full changelog)

  • pi-agent keyword false-positive on public package

  • auto-advance workspace marker when no migration is pending

  • soma update false positive on dev versions. The CLI update check used string comparison (latest > VERSION) which made "0.3.4" > "0.20.1.1" true ('3' > '2' lexically). Dev users on 0.20.x were told to “update” to stable 0.3.x — which is older. Fix: use semverCmp() (already defined in the module, just not called here). Applied to both repos/agent/npm/thin-cli.js and repos/agent-2x/npm/thin-cli.js.

  • npm install -g meetsoma EEXIST on dev installs. When soma bin is a manual symlink to repos/agent/dist/cli.js (typical dev setup via soma-install.sh dev), npm refuses to overwrite the unowned file. Fix: detectDevInstall() reads the bin’s symlink target and, when it’s not an npm-managed path, guides to soma-install.sh stable first before npm install -g meetsoma.

  • delegate tool invisible in Pi’s “Available tools:” prose. Pi intentionally omits custom tools when promptSnippet is absent (per ToolDefinition contract at types.d.ts:289). Added promptSnippet + promptGuidelines to soma-delegate.ts. Previously unobservable because our rebuild path stripped the section entirely; became visible after Phase 1c.1 landed.

  • APPEND_SYSTEM.md went stale between sessions. Was only refreshed inside the legacy branch — Pi-native sessions never rewrote it even when body files or heat changed. Moved writeAppendSystemMd to run BEFORE the path split so both paths keep APPEND current.

Changed

  • before_agent_start restructured: APPEND refresh happens eagerly, path selection (Pi-native vs legacy) happens after. Escape hatch env var renamed from SOMA_PI_NATIVE_PROMPT (opt-in gate, Phase 1b Commit 3) to SOMA_LEGACY_PROMPT (opt-out gate, Phase 1c.1) as the default flipped.
  • compileSystemMd source comment stamp bumped: Phase 1aPhase 1d (tag adoption).
  • compileAppendSystemMd source comment stamp bumped: Phase 1bPhase 1d.

Notes

  • Sandbox verified end-to-end (session s01-5c01df): Pi-native path active, APPEND content visible in system prompt including Behavioral Rules, Muscle Memory, Tools section with all 6 tools (read, bash, edit, write, code_find, code_map, code_refs, code_structure, code_blast, delegate), and Tool Guidelines. Model naturally preferred code_find over bash('soma code find ...') — typed-tool adherence signal positive.
  • Phase 1c.2 deliberately deferred. Deleting ~300 LOC of compileFullSystemPrompt
    • extractSections + buildToolSection + BUILTIN_TOOL_DESCRIPTIONS + helpers is the next step after one real session of Pi-native-default observation. Bisectable single commit when it lands.
  • Tag experiment signal pending. _mind.md tags affect the legacy path (still reachable via SOMA_LEGACY_PROMPT=1). New-path tags are in place. The real adherence delta measurement requires parent meetsoma session-level observation.

Refs: .soma/releases/v0.20.x/plans/v0.20.3-prompt-refactor.md (living plan, all phases + progress), .soma/releases/v0.20.x/plans/v0.20.4-tool-audit.md (next arc, seeded).


[0.20.1.1] — 2026-04-18

Role expansion + curator polish. Closes the Phase-2 delegation arc: the curator can now run apply inline (opt-in), pending gaps flow to a human-editable scratchpad, and roles can declare where their canonical file lives (source-of-truth) + where artifacts go (paths block).

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • soma-workspace-migrate-legacy.sh — lazy migration W2 of plan 02 (s01-680a9c, preload #3) — walks ~/.soma/plugins/<type>/state.json and copies each into ~/.soma/workspaces/__legacy__/<type>/<type>-1.json + registers in ~/.soma/workspaces/__legacy__/panes.json. Idempotent (re-run skips already-registered instances). Skips leading-underscore types (_test, _regression_test) by default. Preserves old paths for one release cycle as fallback. Per 02-workspace-pane-config.md § Migration W2 (lazy) and ~/.soma/workspaces/README.md. Smoke-verified end-to-end against a tmp clone of ~/.soma/plugins/: 8 panes migrated, registry built with types/paths/timestamps/provenance markers, re-run skipped all 8.
  • Three more roles: planner (writes plan files, [read, bash, write]), doc_writer (markdown-only edits, [read, edit, write]), reflector (journal entries under memory/journal/, [read, write]). 7 roles total. Researcher deferred to v0.20.2 pending search integration.
  • source-of-truth frontmatter field on roles. Project-root-relative or absolute path to the canonical role file. When set, discoverRole re-reads from there and apply writes amendments there — fixes the runtime-copy vs git-source drift v0.20.1 highlighted. Missing file → stderr warning + fallback to chain-walked copy.
  • paths: frontmatter block on roles. Per-role artifact paths (invocations, proposals, proposalsApplied, scratchpad) with {role} templating. Absent block = hardcoded defaults (zero migration). All paths live under memory/ so writes stay cache-safe.
  • --auto-apply flag on soma-dev children curate. When set, auto-apply-class proposals apply inline during curate (one command for the round trip). Default OFF — proposals stay in proposals/ for human review.
  • Scratchpad (memory/children/<role>/scratchpad.md). When --auto-apply is off, auto-apply-class findings still write proposals AND append dated sections to the scratchpad so pending gaps are visible at a glance. Append-only; human-editable.
  • applyProposal exported from core/delegate-core.ts as a library function. CLI stub is a thin wrapper now. curateRole calls it directly under --auto-apply. Returns structured ApplyProposalResult with 8 reason codes.
  • resolveRolePaths(role, somaDir, roleDef?) — single source of truth for per-role artifact paths. Threaded through logInvocation, scanMLRQueue, writeProposal, hasProposalBeenApplied, and applyProposal.

Fixed

  • Classifier false-positive on what_worked entries. An MLR observation like what_worked: ['Task completed within budget'] matched the config-keyword regex for budget and produced a bogus propose-class amendment. inferAmendmentSection now short-circuits on sourceField === 'what_worked' and routes to accumulated_knowledge unconditionally — success reports are observations, not config changes.

Changed

  • curateRole signature extends with opts?: { autoApply?: boolean } (back-compat default false). Returns extended CurateResult with applied array and scratchpadAppended count.
  • buildProposal now accepts roleDef to avoid redundant discoverRole I/O.

Cache-safety confirmed

core/body.ts:628-648 iterates readdirSync(bodyDir) filtering .endsWith(".md") — directories (incl. body/children/) are skipped. Role edits don’t invalidate parent cache. All new artifacts (scratchpad, proposals, invocations) live under memory/ which is likewise not walked. Verified empirically: source-of-truth writes to canonical body/children/verifier.md completed without cache storm.


[0.20.0.1] — 2026-04-18

Delegation hardening. v0.20.0 shipped the MVP; v0.20.0.1 makes it production-shaped: model fallback chain (free-tier friendly), per-invocation health cache + cooldown, MLR parsed into structured objects, cost/token tracking, and CLI paths (children run, children health) for driving delegations outside the TUI.

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • soma-workspace-migrate-legacy.sh — lazy migration W2 of plan 02 (s01-680a9c, preload #3) — walks ~/.soma/plugins/<type>/state.json and copies each into ~/.soma/workspaces/__legacy__/<type>/<type>-1.json + registers in ~/.soma/workspaces/__legacy__/panes.json. Idempotent (re-run skips already-registered instances). Skips leading-underscore types (_test, _regression_test) by default. Preserves old paths for one release cycle as fallback. Per 02-workspace-pane-config.md § Migration W2 (lazy) and ~/.soma/workspaces/README.md. Smoke-verified end-to-end against a tmp clone of ~/.soma/plugins/: 8 panes migrated, registry built with types/paths/timestamps/provenance markers, re-run skipped all 8.
  • Structured model chain in role frontmatter (model-chain: list of entries with id, class, cooldown-on-rate-limit). Scalar default-model: <id> still works (1-entry chain back-compat).
  • Model policies (model-policy:order | free-only | paid-only | prefer-free). Runtime walks the chain per-policy, skipping unavailable or cooldown’d models.
  • Health cache + cooldown at .soma/state/model-health.json. Rate-limited or dead models get marked and skipped for a TTL (default 1h). Survives across sessions.
  • MLR (Memory-Lane-Reflection) yaml parsing on child final messages. Observations flow to inv.mlr.{what_worked, what_struggled, missing_capability, suggested_amendments, map_issues} in memory/children/<role>/invocations.jsonl. Foundation for v0.20.1’s curator loop.
  • Cost + token tracking per attempt (inv.cost_usd, inv.tokens_input, inv.tokens_output). Attempts array records each model tried in the chain.
  • soma-dev children run <role> "<task>" — CLI stub that invokes runDelegation outside the TUI. Useful for dev regression + batch testing.
  • soma-dev children health <role> — shows chain with per-model class, resolvable state, cooldown, filtered (per policy). Diagnostic for “why is my child using sonnet when I declared a chain?”

Changed

  • extensions/soma-delegate.ts refactored to thin wrapper (~50 lines) over core/delegate-core.ts (~800 lines at v0.20.0.1). Logic lives in core; extension just registers the Pi tool. Enables CLI stubs to call runDelegation without Pi’s extension harness.
  • loadAgentClass is now async (dual-strategy: createRequire for CJS, dynamic import() for ESM). Callers must await.

Fixed

  • Free-tier rate limits (429/503) on openrouter/*:free models. v0.20.0’s hardcoded Haiku default was a workaround; v0.20.0.1’s chain-walking is the real fix. Role can declare a free-first chain and fall through to paid-cheap on rate limit.

Sandbox-verified (5 cases)

T1 scalar back-compat, T3 chain gemma→qwen→haiku fall-through, T4 cooldown skip, T6 MLR parsed into structured object, T7 cost $0.0044 / 2819+313 tokens.


[0.20.0] — 2026-04-18

Delegation MVP. Team Soma begins. The delegate Pi tool spawns an in-process child agent via pi-agent-core.Agent, running a role-tuned system prompt while inheriting parent soul/voice/ecosystem. Foundation for everything in v0.20.x.

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • soma-workspace-migrate-legacy.sh — lazy migration W2 of plan 02 (s01-680a9c, preload #3) — walks ~/.soma/plugins/<type>/state.json and copies each into ~/.soma/workspaces/__legacy__/<type>/<type>-1.json + registers in ~/.soma/workspaces/__legacy__/panes.json. Idempotent (re-run skips already-registered instances). Skips leading-underscore types (_test, _regression_test) by default. Preserves old paths for one release cycle as fallback. Per 02-workspace-pane-config.md § Migration W2 (lazy) and ~/.soma/workspaces/README.md. Smoke-verified end-to-end against a tmp clone of ~/.soma/plugins/: 8 panes migrated, registry built with types/paths/timestamps/provenance markers, re-run skipped all 8.
  • delegate tool (registered via extensions/soma-delegate.ts). Called as delegate(task, role?, model?). Spawns pi-agent-core.Agent in-process, tool budget enforced (max-tool-calls), returns summary + cost + MLR.
  • Role files in body/children/: _child.md (sub-compiler template), _child-template.md (scaffold for new roles), general.md (starter role: Sonnet, full tools, budget 25/$0.25).
  • Role discovery via body chain. discoverRole walks body/children/<role>.md across the soma chain (project → parent → global) so a workspace can ship roles its child projects inherit.
  • Prompt compilation for children. Compact soul (1500 chars) + voice (1000) + ecosystem (2000) + role identity + role accumulated knowledge + task. Haiku by default so cost stays tight.
  • soma-dev children CLI (new subcommand group). list / show / add / edit / stats / tail / validate for inspecting + managing roles and their invocation logs.
  • Invocation log at memory/children/<role>/invocations.jsonl. Append-only JSONL per role: timestamp, model, tool calls, duration, cost, summary.
  • pi-agent-core added as direct dependency (was transitive). Uses its Agent class as the child-spawning primitive.
  • Sandbox architecture — persistent ~/soma-2x-sandbox/ folder (her filesystem) + dedicated ~/.soma-2x/agent/ install (runtime symlinks to repos/agent-2x/, auth/settings shared from main install). Keeps parent session’s ~/.soma/agent/ untouched during iteration.
  • soma-2x-cmux.sh launcher. Opens a cmux workspace with Sonnet parent + invocation-monitor pane. --focus / --close / --restart flags for iteration cycle.

Fixed (during MVP verification, same release cycle)

  • pi-agent-core.Agent via createRequire bypass. Pi’s extension loader aliases @earendil-works/pi-agent-core and can resolve to wrong package under jiti. Switched to createRequire(import.meta.url) for that one import — native Node resolution bypasses jiti. pi-ai + pi-coding-agent stay ESM-only (static imports at module top).
  • Inline flow YAML arrays. inherits: [] was parsed as the string "[]"; parser now detects and splits [a, b, c] inline.
  • Inline YAML comments. default-model: claude-sonnet-4-5 # comment previously included the comment in the value. stripComment handles this now (respects # inside quoted strings).
  • getModel returning undefined (not throwing) when a model id was unknown. Now surfaces as a typed error the chain walker can react to.
  • OpenRouter Claude models — wired provider + normalized id forms; openrouter/google/gemma-4-31b-it:free resolves correctly now.

Notes

  • Not tagged as a discrete release; delegation MVP was sandbox-internal on dev-2x and consolidated under the v0.20.1 tag when the curator loop landed. This entry backfills the history.

[0.20.1] — 2026-04-18

Curator loop + specialized child roles (verifier, builder, curator). Closes the self-improvement cycle: delegation observations (MLR) → classifier → proposal files → human-apply → role.md amended.

Shipped on dev-2x branch. Merged to dev at tag time. Follows v0.20.0 (delegation MVP) + v0.20.0.1 (delegation hardening).

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • soma-workspace-migrate-legacy.sh — lazy migration W2 of plan 02 (s01-680a9c, preload #3) — walks ~/.soma/plugins/<type>/state.json and copies each into ~/.soma/workspaces/__legacy__/<type>/<type>-1.json + registers in ~/.soma/workspaces/__legacy__/panes.json. Idempotent (re-run skips already-registered instances). Skips leading-underscore types (_test, _regression_test) by default. Preserves old paths for one release cycle as fallback. Per 02-workspace-pane-config.md § Migration W2 (lazy) and ~/.soma/workspaces/README.md. Smoke-verified end-to-end against a tmp clone of ~/.soma/plugins/: 8 panes migrated, registry built with types/paths/timestamps/provenance markers, re-run skipped all 8.
  • Three role files in body/children/: verifier.md (read-only, read + bash, PASS/FAIL + evidence), builder.md (write-capable, read + bash + edit + write, bounded edits with verify-after), curator.md (meta-role, read + write, proposes amendments). All bound to claude-haiku-4-5 by default with per-role budgets.
  • MLR queue reader scanMLRQueue(role, somaDir, sinceTs?) in core/delegate-core.ts. Scans memory/children/<role>/invocations.jsonl, flattens mlr.{what_worked, what_struggled, missing_capability, suggested_amendments} into structured amendment candidates.
  • Amendment classifier classifyAmendment(entry, evidence) returns auto-apply | propose | human-only | skip. Auto-apply requires accumulated_knowledge section + ≥2 distinct invocations + text < 200 chars. default-tools/budget/success_criteriapropose. Identity/soul/voice/inherits → human-only.
  • Proposal writer writeProposal emits memory/children/<role>/proposals/<id>.md with frontmatter (id, role, class, section, evidence) + body (amendment, reason, apply command).
  • soma-dev children mlr [<role>] — scan MLR queue, table output (ts, source, section, text).
  • soma-dev children curate [<role>] — classify queue → write proposals. Summary by class (auto-apply / propose / human-only).
  • soma-dev children apply <proposal-id> [--force] — append amendment to role.md section, archive to proposals/_applied/. Auto-apply default; --force for propose-class (v0.20.1 still gates non-accumulated_knowledge sections).
  • Chain-walk in children.sh (SX-482). Port of core/discovery.ts:getSomaChain to bash. Shell subcommands now resolve roles across the full soma chain (project → parent → global ~/.soma), matching runtime behavior. Adds per-role source column in list (project/parent/global) and --soma=<path> pin flag.
  • Dedup in curator flow (SX-481 fixup). hasAmendmentInRole + hasProposalBeenApplied helpers prevent duplicate bullets when curator runs on different days (slug-based dedup includes date, so same text on new day previously slipped through). Applied at both buildProposal (skip before write) and apply-proposal (skip + archive-only, defense in depth).
  • resolveTools honors bash in read-only roles (s01-b420d5 fix). createReadOnlyTools() upstream returns [Read, Grep, Find, Ls] with no Bash; resolveTools was dropping the bash declaration for any role without edit/write. Now rebuilt declaratively from 7 individual constructors so [read, bash] resolves correctly.

Changed

  • buildProposal signature: optional cwd + somaDirPath params so library callers can thread the caller’s chain into role discovery (instead of relying on process.cwd()).
  • curateRole signature: optional cwd param threaded to buildProposal.
  • children list output includes a SOURCE column (project/parent/global).

Deferred to v0.20.1.1 / v0.20.2

  • Remaining 4 roles: planner, doc_writer, researcher, reflector.
  • Path-gated edit tool for curator (direct role.md edits without proposal round-trip).
  • Direct auto-apply during curator run (today: curator writes proposals, human runs apply).
  • source-of-truth frontmatter field — route amendments to git-canonical path, not chain-walk result (SX-483, v0.20.2).
  • soma-dev children audit — diff runtime copies vs git source, merge in either direction (SX-484, v0.20.2).

[0.12.4] — 2026-04-18

Follow-up to v0.12.3 shipping integrity. Pi runtime bump, thin-CLI UX cleanup, release-flow parity (dev ↔ main auto-sync), and a script pipefail fix.

Changed

  • Pi runtime 0.67.6 → 0.67.68 — 2 upstream releases. Network connection retry (#3317), stable date format in system prompts (#2814), scoped-models Alt+Up/Down fix (#3331), afterToolCall error forwarding (#3051, #3084), git update notification reliability (#3027). New: Bedrock bearer-token auth, prompt template argument-hint frontmatter, after_provider_response extension hook, OSC 8 hyperlink rendering.
  • Release script auto-syncs agent-stable/main. soma-release.sh now squash-merges dev → agent-stable/main after building soma-beta and tags both branches. Prevents the drift where agent-stable fell a full release behind dev (the v0.12.2 → v0.12.3 gap that this release closes).

Fixed

  • Thin-CLI update / check-updates / status now guard on isInstalled(). Previously these commands assumed ~/.soma/agent/ existed and crashed unhelpfully on a fresh global install before soma init. Now they show a clear “not installed — run soma init” message.
  • Thin-CLI header textStatusUpdate on the update subcommand (matches what the command actually does).
  • Thin-CLI help textpostInstallCmds expanded from 8 to 16 commands, covers update, check-updates, status, doctor, health, focus, model, exhale, etc.
  • Pre-versioning project guidance — correct instructions for projects that pre-date soma init (no version file, but .soma/ exists).
  • Stale soma initsoma update references in thin-cli.js, docs/updating.md, and docs/troubleshooting.md. Missed during the v0.12.3 command reshuffle.
  • check-phases.sh pipefail crash on clean working tree. grep -v returns 1 on empty input, which under set -o pipefail killed the script mid-run. Same bug class as soma-plans.sh bash 3.2 issues. Script now runs all 10 phases to completion.

[0.12.3] — 2026-04-17

Shipping integrity release. Fixes a critical bug where npm install -g meetsoma@0.3.3 produced a broken install (missing internal imports), and makes the update flow actually work. If you’ve been stuck on an older Pi runtime despite cutting newer Soma versions, this is why.

Fixed

  • meetsoma@0.3.3 broken npm install. The published tarball imported from ./lib/ and ./welcome/ paths that weren’t included, so every fresh npm install -g meetsoma failed with ERR_MODULE_NOT_FOUND on first run. Fixed by bundling thin-cli.js with esbuild into a single self-contained file before publish. Has been broken since the npm/ reorg — unnoticed because existing users had working installs from before.
  • TUI leakage from extensions. soma-route.ts had console.error calls that leaked into the input buffer on shutdown and during security rejects. hub-connect.ts (somaverse) had WebSocket handshake logs that appeared mid-keystroke in the prompt. Both silenced — matches bridge-connect.ts’s silent pattern.
  • Silent Pi staleness in dev. soma-dev status now compares dist/ vs node_modules/ Pi versions and flags drift (was the root cause of the “opus-4-7 missing” bug several users hit).

Changed

  • soma init no longer updates the runtime. Previously, typing soma init in an already-initialized project silently ran a runtime update instead of doing project work — the confusing overload is removed. soma init now always means “set up this project.”
  • soma update now actually updates. Was previously status-only (told you to run soma init). Now it performs the update: git pull --ff-only in ~/.soma/agent/ + npm install --omit=dev if dependencies changed.
  • Pi runtime is now locked to Soma version. soma-beta/package.json pins Pi exact (was ^0.67.6, now 0.67.6). soma-beta now ships a package-lock.json too — users get the exact Pi dependency tree we tested against. Pi updates only when Soma cuts a new release.
  • soma doctor / soma status now shows installed Pi runtime version and flags drift between declared and installed. Catches the class of bug where npm install hadn’t been re-run after a Pi bump.
  • soma check-updates preserves the old “report-only” behavior that soma update used to have, for when you just want to see what’s available without updating.

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • soma-workspace-migrate-legacy.sh — lazy migration W2 of plan 02 (s01-680a9c, preload #3) — walks ~/.soma/plugins/<type>/state.json and copies each into ~/.soma/workspaces/__legacy__/<type>/<type>-1.json + registers in ~/.soma/workspaces/__legacy__/panes.json. Idempotent (re-run skips already-registered instances). Skips leading-underscore types (_test, _regression_test) by default. Preserves old paths for one release cycle as fallback. Per 02-workspace-pane-config.md § Migration W2 (lazy) and ~/.soma/workspaces/README.md. Smoke-verified end-to-end against a tmp clone of ~/.soma/plugins/: 8 panes migrated, registry built with types/paths/timestamps/provenance markers, re-run skipped all 8.
  • Periodic update check inside the agent. soma-statusline.ts runs a silent git fetch every 30 minutes while the agent is running. If behind, shows ⬆ update in the statusline and writes to ~/.soma/config.json so the next soma boot prints a one-line notice. Zero network latency at CLI launch.
  • Pre-publish smoke test. soma-npm-publish.sh now packs the tarball, extracts it to a clean temp dir, and runs node dist/thin-cli.js --version before allowing npm publish. Aborts if the tarball has broken imports or contains forbidden content (dist/core/, .ts, node_modules/, etc.). Also integrated into soma-dev pipeline so dev cycles catch breakage early.
  • Docker e2e sandbox (soma-sandbox-docker.sh local) now reliably tests our local bundle. Previous Dockerfile had a broken COPY ... local-pkg* glob that created a file literally named local-pkg*, so the sandbox was silently falling through to the registry version. Fixed — 24/24 tests pass in clean node:22-slim container.

[0.12.2] — 2026-04-17

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • soma-workspace-migrate-legacy.sh — lazy migration W2 of plan 02 (s01-680a9c, preload #3) — walks ~/.soma/plugins/<type>/state.json and copies each into ~/.soma/workspaces/__legacy__/<type>/<type>-1.json + registers in ~/.soma/workspaces/__legacy__/panes.json. Idempotent (re-run skips already-registered instances). Skips leading-underscore types (_test, _regression_test) by default. Preserves old paths for one release cycle as fallback. Per 02-workspace-pane-config.md § Migration W2 (lazy) and ~/.soma/workspaces/README.md. Smoke-verified end-to-end against a tmp clone of ~/.soma/plugins/: 8 panes migrated, registry built with types/paths/timestamps/provenance markers, re-run skipped all 8.
  • soma model command — Switch your default model from the CLI. Fuzzy matching (soma model opus), interactive selection when multiple matches, persistent save to settings. Subcommands: soma model <pattern> set (save without starting), soma model <pattern> start (save + start session), soma model --list [search] (browse models).
  • Claude Opus 4.7 support — Available via /model in-session or soma model opus-4-7 set from CLI. Includes adaptive thinking support.
  • soma-dev check-upstream — Detect and audit Pi runtime updates. Checks changelog, extension surface, provider diffs, patch compatibility. Supports --audit (full analysis) and --json (machine-readable).
  • soma-dev check-docs — Stale reference sweep across docs and website. Catches old version numbers, deprecated APIs, provider count mismatches.
  • soma-dev check-phases — Verify dev cycle phase completion before release. Checks artifacts across all 10 phases. Supports --patch for reduced requirements.
  • --no-context-files / -nc flag — Skip AGENTS.md and CLAUDE.md loading for clean sessions without project context injection.
  • after_provider_response extension hook — Extensions can inspect provider HTTP status and headers after each response.

Changed

  • CLI help reorganized — Session flags (--model, --provider, --thinking) now grouped under “Session Options (apply to this session only)” to distinguish from persistent project commands (soma model, soma focus).
  • Prompt caching improved — Tool schemas now cached independently from the system prompt. Adding/removing tools no longer invalidates your entire system prompt cache (reduces cost when workspace tools connect/disconnect).
  • Fresh boot greeting — When a preload exists but wasn’t loaded (plain soma vs soma inhale), the greeting now says so explicitly and suggests /inhale. Prevents the agent from reading stale preloads on clean starts.

Fixed

  • grep tool performance — No longer stalls on broad searches with context=0.
  • find tool gitignore — Nested .gitignore rules no longer leak across sibling directories.
  • Type safety — Fixed breathe.preloadStaleThreshold type cast for Pi 0.67.6 compatibility.
  • Preload validator — Section header matching is now fuzzy — accepts ## Next Session, ## Next Session: Priorities, ## Next Session: [Task Name], etc.
  • Protocol warm fallback — Protocols with description in frontmatter now use it for warm-tier display when breadcrumb is absent. Most protocols already use description — this fix makes them visible at warm tier.
  • Template sync — Shipped improved _memory.md template to all users (Traps section, phase breadcrumbs, warning-task binding guidance).
  • 4 missing providers — Kimi Coding, Minimax, Z.ai, and Vercel AI Gateway added to docs. Provider count updated from 17 to 23.

Upgraded

  • Pi runtime 0.67.1 → 0.67.6 (5 releases, 15+ fixes)

[0.12.1] — 2026-04-15

Fixed

  • Image budget auto-compact loopcheckImageBudget() runs on a 5-second timer but ctx.compact() is async. The image counter wasn’t reset until onComplete, so the next timer tick re-fired the warning and compact attempt, looping 6+ times. Added imageCompactInFlight guard flag.

[0.12.0] — 2026-04-15 — Somaverse Edition

Soma meets the Somaverse. Your agent can now connect to somaverse.ai, control your workspace remotely, and pair with your browser — all through a secure relay. Data stays on your machine. The shard is just the pipe.

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • soma-workspace-migrate-legacy.sh — lazy migration W2 of plan 02 (s01-680a9c, preload #3) — walks ~/.soma/plugins/<type>/state.json and copies each into ~/.soma/workspaces/__legacy__/<type>/<type>-1.json + registers in ~/.soma/workspaces/__legacy__/panes.json. Idempotent (re-run skips already-registered instances). Skips leading-underscore types (_test, _regression_test) by default. Preserves old paths for one release cycle as fallback. Per 02-workspace-pane-config.md § Migration W2 (lazy) and ~/.soma/workspaces/README.md. Smoke-verified end-to-end against a tmp clone of ~/.soma/plugins/: 8 panes migrated, registry built with types/paths/timestamps/provenance markers, re-run skipped all 8.
  • soma login — Pair your agent with Somaverse. Creates a pairing code, opens your browser, and saves your device key. One command to connect.
  • Hub-connect extension — Connects your agent to the Somaverse hub as a provider. Your browser pairs with it automatically. Works alongside bridge-connect (local + cloud simultaneously).
  • Workspace proxy — All 28 workspace + browser tools work through the hub relay. Your agent controls the workspace even from a remote machine.
  • Device-key auth — Workspace tools auto-detect hub mode when ~/.soma/device-key exists. Routes to hub URL with Bearer auth instead of localhost.
  • 28 agent tools — 10 workspace, 10 browser, 5 AI, 2 plugin state, 1 browser_links (new).

Architecture

  • Reverse proxy model — The Somaverse hub relays WebSocket messages between your browser and your agent. It never stores your data — everything flows through to your machine.
  • Per-user isolation — Device keys are Argon2-hashed. Each user’s workspace connection is paired by user_id. No cross-user access possible.
  • Modular extensions — bridge-connect (local), hub-connect (cloud). Both run simultaneously with dedup. Add a service, add an extension.

Security

  • Device keys: 192-bit random, Argon2 hashed in DB
  • Transport: WSS via Traefik + Let’s Encrypt
  • Hub proxy: Bearer device_key + JWT cookie auth on every request
  • CORS: restricted to somaverse.ai, somaverse.space, dev.somaverse.ai

Fixed

  • Breathe stale warning — disabled by default. Was firing every turn in long sessions (“28 tool calls since preload”). Now fires at most once, configurable via breathe.preloadStaleThreshold in settings.

[0.11.4] — 2026-04-14

Fixed

  • Script root-finding_find_root() in 10 dev scripts now checks repos/agent/package.json to distinguish meetsoma/ from repos/agent/ (both had .soma/ and repos/ dirs).
  • sync-docs.sh — prefers agent/ (dev) over agent-stable/ (main) for Phase 5 doc sync.

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • soma-workspace-migrate-legacy.sh — lazy migration W2 of plan 02 (s01-680a9c, preload #3) — walks ~/.soma/plugins/<type>/state.json and copies each into ~/.soma/workspaces/__legacy__/<type>/<type>-1.json + registers in ~/.soma/workspaces/__legacy__/panes.json. Idempotent (re-run skips already-registered instances). Skips leading-underscore types (_test, _regression_test) by default. Preserves old paths for one release cycle as fallback. Per 02-workspace-pane-config.md § Migration W2 (lazy) and ~/.soma/workspaces/README.md. Smoke-verified end-to-end against a tmp clone of ~/.soma/plugins/: 8 panes migrated, registry built with types/paths/timestamps/provenance markers, re-run skipped all 8.
  • Image budget — auto-compact when screenshots accumulate. Soft notify at 8 images, hard auto-compact at 10. Counts all image sources (browser_screenshot, Read tool, user-pasted). Counter resets on compact. Visible in /status.
  • imageBudget settingssoftAt and hardAt configurable via settings.json. Set hardAt: 0 to disable.
  • breathe.maxTokens setting — caps the effective context window for breathe threshold calculations. Fixes breathe being dormant on 1M-context models where 50% = 500K tokens.
  • Sandbox source flagssoma-sandbox.sh --dev builds and tests from dev branch. --main tests agent-stable. --beta (default) tests soma-beta. API tests default to claude-haiku-4-5.
  • 14 new settings tests — covers removed fields, new fields, multi-level inheritance, array replacement.

Changed

  • Settings cleanup — removed 3 never-implemented settings: memory.flowUp, sessions.overwriteGuard, checkpoints.project.workingBranch. Default version updated 0.6.4 → 0.11.3.

[0.11.3] — 2026-04-14

Fixed

  • Script description parsergetScriptMeta() was parsing YAML frontmatter delimiters (---) as the script description. Every frontmatter-using script showed ”---” in the system prompt. Parser now skips frontmatter blocks, extracts # description: fields, skips decorative lines, and scans 30 lines instead of 15.

Changed

  • Docs version sweep — 6 docs updated: stale version refs (v0.9.0→v0.11.2, v0.2.0→v0.3.3), extension table 4→8, scripts.md restructured into Bundled/Advanced/Hub sections.

[0.11.2] — 2026-04-14

Fixed

  • soma-install.sh paths — updated products/somameetsoma/repos references.
  • Duplicate session files in rotation boot — rotation path embedded file hints in both greeting AND session_files template variable. Now greeting is narrative only, session_files handled by template (matching normal boot pattern from 4d8331f).
  • Triple error cascade on API failure — three independent handlers fired on single error. Added errorHandled flag, else-if chain, gated fatal-session check.
  • False-positive billing detection removederr.includes("extra usage") matched Claude consumer error text, not actual billing issues. Pi shows raw API errors natively. Removed our pattern matching entirely.
  • Doctor fallback version — hardcoded 0.10.0 → 0.11.1.
  • Build pipelinebuild-dist.mjs was reading Pi 0.64.0 from stale repos/cli/dist. Now reads from npm (Pi 0.67.1). Root cause of months of invisible dist/ drift.
  • Release script — removed stale CLI_DIST reference; Soma brand themes were being overwritten by Pi defaults.
  • Dev-mode theme crash — Pi’s config.js resolves to src/ when it exists. Added symlinks for theme, export-html, and assets paths.
  • Stale docsrepos/cli ref in install-architecture.md.

Changed

  • Pi runtime 0.64.0 → 0.67.1 — dist/ was stuck at Pi 0.64.0 despite package.json claiming ^0.66.1. Synced from npm. Gets stack overflow fix for long sessions (#2651), subscription auth warning, queued message flush fix.
  • Pi telemetry disabled — set PI_TELEMETRY=0 in cli.js to prevent install ping added in Pi 0.67.1.
  • Rotation boot aligned with decomposition — greeting no longer embeds session file hints. Consistent with normal boot path pattern.
  • Error handling — auth-aware (OAuth vs API key). Account rate limits (real plan limit) handled separately from extra-usage classification errors (often transient). OAuth: progressive retry → warn → pause at 4th. API key: pause immediately.
  • Error display — build-time error-sanitizer patch converts raw JSON API errors to human-readable messages. Billing errors show progressive messages. Retryable errors (overloaded, 500) pass through untouched.

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • soma-workspace-migrate-legacy.sh — lazy migration W2 of plan 02 (s01-680a9c, preload #3) — walks ~/.soma/plugins/<type>/state.json and copies each into ~/.soma/workspaces/__legacy__/<type>/<type>-1.json + registers in ~/.soma/workspaces/__legacy__/panes.json. Idempotent (re-run skips already-registered instances). Skips leading-underscore types (_test, _regression_test) by default. Preserves old paths for one release cycle as fallback. Per 02-workspace-pane-config.md § Migration W2 (lazy) and ~/.soma/workspaces/README.md. Smoke-verified end-to-end against a tmp clone of ~/.soma/plugins/: 8 panes migrated, registry built with types/paths/timestamps/provenance markers, re-run skipped all 8.
  • soma-dev verify upstream — detects dist/ vs node_modules/ drift by fingerprinting key runtime files. Prevents the 0.64→0.66 invisible drift.
  • Runtime integrity tests — test-hygiene.sh now checks telemetry disable, boot decomposition, billing removal, error cascade flag, verify-upstream existence.
  • Release pipeline gatesoma-release.sh now blocks on dist/ upstream drift detection before building.
  • Error-sanitizer — build-time patch to Pi’s display layer. Progressive billing messages, auth/model rewrites. Zero cache impact.
  • Patch manifestscripts/_dev/patches/manifest.json tracks applied dist/ patches.
  • CLI repo archived — content merged to agent README. meetsoma/cli archived on GitHub.

[0.11.1] — 2026-04-13

Fixed

  • Cache invalidation from image stripping — removed progressive image stripping from before_provider_request in soma-guard. Each new screenshot changed the strip set, invalidating the entire cache ($2-3 per invalidation, $152/day on Apr 12). Image management now handled by capture-time optimization + future auto-compact.
  • Zombie sessions — idle shutdown timer now runs independently of keepalive. Post-exhale shutdown (15 min) + absolute timeout (30 min). Previously, disabling keepalive also disabled the shutdown check.
  • Boot resume cache waste — silent resume when no .soma files changed. Was injecting “Nothing changed” message that cost ~$1.78 in cache rewrite with zero value.
  • Keepalive on fatal errors — kill keepalive on first-turn API failures to prevent infinite retry loops.
  • Billing notice handling — separate billing notices from error-pause logic so keepalive isn’t killed on credit warnings.
  • Pipeline — remove streamingBehavior (not in Pi types), fix focus --help without seam.

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • soma-workspace-migrate-legacy.sh — lazy migration W2 of plan 02 (s01-680a9c, preload #3) — walks ~/.soma/plugins/<type>/state.json and copies each into ~/.soma/workspaces/__legacy__/<type>/<type>-1.json + registers in ~/.soma/workspaces/__legacy__/panes.json. Idempotent (re-run skips already-registered instances). Skips leading-underscore types (_test, _regression_test) by default. Preserves old paths for one release cycle as fallback. Per 02-workspace-pane-config.md § Migration W2 (lazy) and ~/.soma/workspaces/README.md. Smoke-verified end-to-end against a tmp clone of ~/.soma/plugins/: 8 panes migrated, registry built with types/paths/timestamps/provenance markers, re-run skipped all 8.
  • Cache health tracking — statusline tracks cacheRead, cacheWrite, cost per session. Alerts on cache invalidations (>50K token writes). Footer shows ✓cache / Ninv indicator.
  • Idle session detection — auto-shutdown after configurable idle period with no user input.

Changed

  • Cache health indicator moved to statusline line 2 (line 1 was crowded).

[0.11.0] — 2026-04-12

Identity overhaul + first-run experience. soul.md replaces SOMA.md as default. Minimal boot for new projects. 11 bundled scripts. Critical doctor fix.

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • soma-workspace-migrate-legacy.sh — lazy migration W2 of plan 02 (s01-680a9c, preload #3) — walks ~/.soma/plugins/<type>/state.json and copies each into ~/.soma/workspaces/__legacy__/<type>/<type>-1.json + registers in ~/.soma/workspaces/__legacy__/panes.json. Idempotent (re-run skips already-registered instances). Skips leading-underscore types (_test, _regression_test) by default. Preserves old paths for one release cycle as fallback. Per 02-workspace-pane-config.md § Migration W2 (lazy) and ~/.soma/workspaces/README.md. Smoke-verified end-to-end against a tmp clone of ~/.soma/plugins/: 8 panes migrated, registry built with types/paths/timestamps/provenance markers, re-run skipped all 8.
  • soma session — session maintenance tool. strip-images removes base64 image data from JSONL (16MB → 2.6MB), list shows all sessions with sizes, stats analyzes image payload.
  • test-install-flows.sh — 36-assertion E2E test suite covering fresh init, v0.6→current upgrade, edge cases (corrupt settings, missing version, empty body/).
  • Discovery marker: bodyfindSomaDir() now detects projects with only body/soul.md (no SOMA.md).
  • User extension preservation — reinstall preserves user-installed extensions (bridge-connect.ts, workspace-tools.ts) alongside auth.json and models.json.
  • Extension allowlist — configure approved extensions in settings.json, /soma doctor reports unlisted extensions.
  • Image payload guardbefore_provider_request strips old images when >15 accumulate in conversation. Prevents Anthropic many-image 2000px limit.

Changed

  • Identity: soul.md is primaryinitSoma creates body/soul.md instead of SOMA.md. ensureGlobalSoma creates body/soul.md at ~/.soma/. SOMA.md and identity.md still work as fallbacks. All docs, templates, tree diagrams updated (30+ files).
  • autoInject default: false — new projects use soma inhale for intentional preload loading. Existing settings preserved on upgrade.
  • First-run minimal boot — first session skips hot protocol/muscle injection into system prompt. Agent discovers through use.
  • Pi 0.65 migrationsession_switch/session_forksession_start with event.reason.
  • Protocol heat-defaults reclassified — only breath-cycle and working-style start warm. All others cold.
  • 11 bundled scripts (was 6) — added soma-body, soma-refactor, soma-reflect, soma-plans, soma-session.
  • Template single sourcebody/_public/ deleted, templates read from templates/default/.
  • Hub template install — fetches soul.md → SOMA.md → identity.md, writes to body/soul.md for new projects.

Fixed

  • Critical: semver comparison in thin-cli.js — doctor used JS string comparison ("0.6.2" > "0.10.0"), so upgrades NEVER ran for any project. Added semverCmp() for proper numeric comparison.
  • CLI UXsoma help, soma version now work (bare words). soma init when .soma/ exists routes to doctor instead of broken TUI.
  • Image payload guard — strips old images from conversation history, pauses keepalive on 400/invalid_request errors (was only 429). Prevents infinite retry deadlock.
  • Parent chain detection — init.ts walker now checks body/soul.md and settings.json, not just SOMA.md/identity.md.
  • soma verify crash${*} with set -u caused unbound variable when called without args.
  • Stale refs sweep — 30+ files across docs, core, templates, scripts, community. identity.mdbody/soul.md in all user-facing strings.
  • Script path leaks — soma-health, soma-verify, soma-seam, soma-refactor guarded behind path existence checks.
  • Sandbox — was creating identity.md (deprecated), now creates body/soul.md.

[0.10.0] — 2026-04-10

Restructure release. AMPS consolidated, CLI script routing, Pi runtime bumped, 25 commits since v0.9.0.

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • soma-workspace-migrate-legacy.sh — lazy migration W2 of plan 02 (s01-680a9c, preload #3) — walks ~/.soma/plugins/<type>/state.json and copies each into ~/.soma/workspaces/__legacy__/<type>/<type>-1.json + registers in ~/.soma/workspaces/__legacy__/panes.json. Idempotent (re-run skips already-registered instances). Skips leading-underscore types (_test, _regression_test) by default. Preserves old paths for one release cycle as fallback. Per 02-workspace-pane-config.md § Migration W2 (lazy) and ~/.soma/workspaces/README.md. Smoke-verified end-to-end against a tmp clone of ~/.soma/plugins/: 8 panes migrated, registry built with types/paths/timestamps/provenance markers, re-run skipped all 8.
  • v0.8.1→v0.9.0 migration map — settings additions (inherit, keepalive, heat.autoDetectBump), script routing syntax, AMPS consolidation notes. Chains with existing migration maps.
  • soma-health.sh — project health dashboard script.
  • Docker sandboxsoma-sandbox.sh can now use Docker for isolated E2E testing (21/21 tests pass).
  • test-hygiene.sh — repo cleanliness checks (secrets, sessions, dev artifacts).
  • verify-amps command — CWD path resolution, community protocol source validation.
  • 3 scripts promoted to bundled — soma-verify.sh, soma-refactor.sh, soma-browser.sh moved from dev to discoverable.

Changed

  • Pi runtime 0.64.0 → 0.66.1 — 2 minor versions, bug fixes, no breaking changes.
  • Docs: CLI syntax — all 8 doc files updated from soma-code.sh to soma code syntax. Website synced.
  • Scripts reorganized — 39 dev scripts moved to _dev/, 3 promoted to bundled, redundant scripts archived.
  • CWD safety audit — dev-path guards on Tier 2 scripts, soma-query demoted to _dev/.

Fixed

  • soma-guard: orphaned tool_result sanitizerbefore_provider_request handler removes orphaned tool_result blocks before API call. Prevents 400 errors from upstream Pi bug.
  • soma-statusline: auto-pause keepalive on rate limit — detects 429/rate_limit errors, auto-disables keepalive. Prevented 67+ wasted requests per rate-limit window.
  • soma-doctor.sh: follow core/ symlink — was reading stale ~/.soma/agent/package.json (v0.6.0) instead of following symlink to dev repo. Now resolves through readlink.
  • init.ts: read version from package.json — was hardcoded to 0.6.2, now reads dynamically.
  • Sandbox: deterministic prompt template test — replaced LLM-dependent test with file-read verification.
  • Sandbox: extension/protocol count comparison — use >= instead of == for forward compatibility.
  • soma-boot: streamingBehavior on all sendUserMessage calls — 10 calls patched, prevents runtime errors.
  • Keepalive infinite loopkeepaliveInFlight flag prevents auto-exhale from re-triggering keepalive.
  • CI: npm ci + tsx PATH — added to all test suites for clean CI runs.

[0.9.0] — 2026-04-04

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • soma-workspace-migrate-legacy.sh — lazy migration W2 of plan 02 (s01-680a9c, preload #3) — walks ~/.soma/plugins/<type>/state.json and copies each into ~/.soma/workspaces/__legacy__/<type>/<type>-1.json + registers in ~/.soma/workspaces/__legacy__/panes.json. Idempotent (re-run skips already-registered instances). Skips leading-underscore types (_test, _regression_test) by default. Preserves old paths for one release cycle as fallback. Per 02-workspace-pane-config.md § Migration W2 (lazy) and ~/.soma/workspaces/README.md. Smoke-verified end-to-end against a tmp clone of ~/.soma/plugins/: 8 panes migrated, registry built with types/paths/timestamps/provenance markers, re-run skipped all 8.
  • {{inbox_summary}} template variable — scans .soma/inbox/ at boot, injects unread message summary into system prompt. File-based async messaging between agents.
  • {{scripts_table}} in default _mind.md — agents can now see their discovered scripts in the system prompt.
  • preload.autoInject setting — auto-inject most recent preload on fresh boot (default: true). No longer requires soma inhale CLI command for preload loading.
  • 7 new documentation pagesinbox.md, doctor.md, hub.md, troubleshooting.md, guides/daily-workflow.md, guides/customization.md, guides/first-protocol.md. Total: 33 pages (~36K words).
  • inter-agent-inbox community protocol — published to community hub. Formal spec for file-based inter-agent messaging.
  • Script drift detectionsoma-verify.sh drift now checks scripts across agent repo → working copies → global.

Changed

  • Digest → TL;DR migration complete — 96 files converted from <!-- digest:start/end --> to ## TL;DR. Both formats still accepted, ## TL;DR is the standard going forward.
  • Docs accuracy overhaul — 13 existing pages updated: autoInject mental model, version refs, breadcrumbdescription, maxTokens default, session log naming format, identity.md deprecated.

Fixed

  • Keepalive limit not enforcing — keepalive-triggered turns reset the ping counter, making keepalives infinite. Now tracks keepaliveInFlight flag to skip reset on self-initiated turns.
  • Changelog hook targets [0.12.2] — 2026-04-17 only — old hook appended to first ### Added/### Fixed globally, which could hit released versions.
  • Test suite — added tsx to devDependencies (bare tsx calls failed), fixed 10 stale test paths (body/publicbody/_public, identity.mdSOMA.md).
  • Stale body/public references — updated to body/_public across comments, docs, templates, and scripts (6 files).

[0.8.1] — 2026-04-02

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • soma-workspace-migrate-legacy.sh — lazy migration W2 of plan 02 (s01-680a9c, preload #3) — walks ~/.soma/plugins/<type>/state.json and copies each into ~/.soma/workspaces/__legacy__/<type>/<type>-1.json + registers in ~/.soma/workspaces/__legacy__/panes.json. Idempotent (re-run skips already-registered instances). Skips leading-underscore types (_test, _regression_test) by default. Preserves old paths for one release cycle as fallback. Per 02-workspace-pane-config.md § Migration W2 (lazy) and ~/.soma/workspaces/README.md. Smoke-verified end-to-end against a tmp clone of ~/.soma/plugins/: 8 panes migrated, registry built with types/paths/timestamps/provenance markers, re-run skipped all 8.
  • Unified warm content format## TL;DR replaces <!-- digest:start/end --> across all AMPS. Protocols, muscles, and automations all use the same format. Code accepts both during transition.
  • extractTldr() — shared utility for extracting TL;DR sections, used by protocols, muscles, and automations.
  • MAP = automation aliasmap accepted as type alias in /hub install, /hub fork, /hub share. MAPs are a type of automation.
  • Discovery unificationdiscoverMaps() now scans amps/automations/ root alongside maps/ subdirectories. Installed hub automations are visible as MAPs.
  • Keepalive limits — 5 pings per idle period (configurable 0–5), countdown in notification (♥ Keepalive 3/5), resets on user message.
  • Auto-exhale on idle — when keepalive lives are exhausted and context exceeds 75k tokens, the agent automatically writes a preload. Configurable via keepalive.autoExhale and keepalive.autoExhaleMinTokens.
  • Migration phase v0.8.0→v0.8.1 — Tier 1 auto-converts muscle digest blocks to TL;DR format, adds keepalive settings.

Changed

  • soma-doctor.sh — reads agent version from package.json instead of hardcoded string.
  • Hub validator — accepts description/triggers/tags, prefers ## TL;DR over <!-- digest -->, warns on legacy format.

[0.8.0] — 2026-04-02

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • soma-workspace-migrate-legacy.sh — lazy migration W2 of plan 02 (s01-680a9c, preload #3) — walks ~/.soma/plugins/<type>/state.json and copies each into ~/.soma/workspaces/__legacy__/<type>/<type>-1.json + registers in ~/.soma/workspaces/__legacy__/panes.json. Idempotent (re-run skips already-registered instances). Skips leading-underscore types (_test, _regression_test) by default. Preserves old paths for one release cycle as fallback. Per 02-workspace-pane-config.md § Migration W2 (lazy) and ~/.soma/workspaces/README.md. Smoke-verified end-to-end against a tmp clone of ~/.soma/plugins/: 8 panes migrated, registry built with types/paths/timestamps/provenance markers, re-run skipped all 8.
  • soma doctor — project health check and migration from CLI. Tier 1 auto-fixes (settings, body, protocols) run silently on every boot. TUI /soma doctor provides interactive Tier 2+ migration with compareTemplates() analysis.
  • soma status / soma health — quick project health check (renamed from old soma doctor).
  • soma --version — shows both agent and CLI versions.
  • soma --help — delegates to core agent for full branded help output.
  • Migration phase systemcycle.md + 9 phase files covering v0.6.1 → v0.8.0. Each phase is self-contained with from/to versions, actions, and what changed. Complete chain with no gaps.
  • _doctor-update.md + _doctor-pending.md — boot templates for agent-assisted migration. Pending template injected into followUp when updates available.
  • compareTemplates() — three-category file diff (content files, metadata, runtime) for doctor analysis.
  • findChildSomaDirs() — walks filesystem to discover child .soma/ directories for multi-project support.
  • doctor.autoUpdate + declinedVersion — per-project settings controlling update notification behavior.
  • Warm AMPS — skill loader shows full TL;DR or digest for warm content, short description for cold. All AMPS types unified.
  • Body templates — improved starters for soul.md, voice.md, journal.md, pulse.md, body.md. DNA.md rewrite with self-awareness, owner’s manual, and deep reference links.
  • _first-breath.md — context-aware first-run template with conditional blocks for monorepos, blank projects, code projects, global/inherited .soma/.
  • Test suitestest-doctor.sh (46 tests), test-migrations.sh (48 tests) covering all doctor features and migration chain integrity.
  • Docsupdating.md (migration guide), install-architecture.md (CLI → agent flow), body.md (full body architecture reference with variables, templates, chain, lifecycle).

Changed

  • CLI routing overhauldoctor, status, health, update, version all route through thin-cli. --help delegates to core when agent is installed.
  • Starter content — code fallbacks synced to _public/ templates, HTML comments stripped from shipped content.
  • Bundled scriptssoma-theme.sh seeds on init, breadcrumbs added to all bundled scripts for docs and community references.
  • _first-breath.md — added self-exploration guidance (agent reads its own docs), breath cycle explanation, learn-the-user prompts.
  • _memory.md — added Step 1.5 (update living docs), Before You Start (conditional loading), corrections emphasis.

Fixed

  • CHANGELOG auto-append bug — post-commit hook was appending to every section, not just [0.12.2] — 2026-04-17. Rewrote hook, cleaned 172 duplicate entries.
  • Boot version-bump race — version was bumped before notification, causing re-check loops. Now bumps after Tier 1 fixes complete.
  • CLI help header — shows “CLI v0.2.0” instead of bare version number.
  • Dev mode health check — no longer reports false “git repo has issues” in development.
  • Tier 1 body scaffold — adds missing body files to existing body/ directory (was only creating on fresh init).

[0.7.1] — 2026-04-01

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • soma-workspace-migrate-legacy.sh — lazy migration W2 of plan 02 (s01-680a9c, preload #3) — walks ~/.soma/plugins/<type>/state.json and copies each into ~/.soma/workspaces/__legacy__/<type>/<type>-1.json + registers in ~/.soma/workspaces/__legacy__/panes.json. Idempotent (re-run skips already-registered instances). Skips leading-underscore types (_test, _regression_test) by default. Preserves old paths for one release cycle as fallback. Per 02-workspace-pane-config.md § Migration W2 (lazy) and ~/.soma/workspaces/README.md. Smoke-verified end-to-end against a tmp clone of ~/.soma/plugins/: 8 panes migrated, registry built with types/paths/timestamps/provenance markers, re-run skipped all 8.
  • rewrite DNA.md — self-awareness, owner’s manual, link to docs for deep reference
  • soma --help rewrite — Soma-branded help with session commands, project commands, options, and TUI slash commands. Replaces generic Pi help output.
  • soma --help scripts — show installed scripts with descriptions. Works from CLI and inside sessions.
  • soma --help commands — full command reference organized by category (CLI, session, heat, hub, info).
  • soma-theme.sh bundled — shared script theming now seeds on init (was a missing dependency for 3 bundled scripts).

Fixed

  • help header shows ‘CLI v…’ not bare version
  • help rewrite, script theme crash, focus session, postinstall, docs
  • Scripts crash on fresh projectssource soma-theme.sh with set -e caused fatal exit when theme file wasn’t present. Fixed with if [ -f ]; then source; fi pattern across all 8 scripts.
  • soma focus <keyword> didn’t start sessionmain() call wasn’t awaited, process.exit(0) ran before session could start.
  • postinstall.js missing from builds — deleted during Pi 0.64.0 dist sync, restored to CLI repo. Added to OUR_DIST_FILES and release script.
  • Docs: /inhale vs soma inhale confusion — commands.md and getting-started.md now clearly distinguish CLI commands (shell) from TUI slash commands, with comparison table.

[0.7.0] — 2026-04-01

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • soma-workspace-migrate-legacy.sh — lazy migration W2 of plan 02 (s01-680a9c, preload #3) — walks ~/.soma/plugins/<type>/state.json and copies each into ~/.soma/workspaces/__legacy__/<type>/<type>-1.json + registers in ~/.soma/workspaces/__legacy__/panes.json. Idempotent (re-run skips already-registered instances). Skips leading-underscore types (_test, _regression_test) by default. Preserves old paths for one release cycle as fallback. Per 02-workspace-pane-config.md § Migration W2 (lazy) and ~/.soma/workspaces/README.md. Smoke-verified end-to-end against a tmp clone of ~/.soma/plugins/: 8 panes migrated, registry built with types/paths/timestamps/provenance markers, re-run skipped all 8.
  • rewrite DNA.md — self-awareness, owner’s manual, link to docs for deep reference
  • /inhale guard — warns when no preload exists (suggests /exhale), warns when preload is stale (>5 tool calls since write). Use /inhale --force to override.
  • Slash command usage hints — 10 commands now include Usage: patterns in their descriptions: /pin, /kill, /auto-commit, /inhale, /install, /auto-breathe, /hub, /scratch, /keepalive, /soul-space, /soma.
  • Hub: 5 new scripts — soma-seam, soma-reflect, soma-query, soma-focus, soma-plans. All with coaching-voice digests.
  • Hub: soma-code v2.0.0 — added blast (blast radius analysis), tsc-errors (TypeScript errors with context), improved refs (DEF/IMP/USE), improved find (extension filter).
  • Scripts docsscripts.md rewritten with hub links for each script.

Changed

  • Upstream sync R4 — Pi 0.63.1 → 0.64.0. New APIs: setHiddenThinkingLabel, signal/getSignal, prepareArguments, async getArgumentCompletions.
  • Core scripts trimmed — init seeds 5 core scripts (soma-code, soma-seam, soma-focus, soma-update-check, validate-content). Others available via soma hub install script <name>.
  • Semver discipline — feature releases now bump minor version (0.X.0). Patch (0.x.Y) reserved for bug-fix-only releases.

Fixed

  • help header shows ‘CLI v…’ not bare version
  • help rewrite, script theme crash, focus session, postinstall, docs
  • Changelog hooksoma-dev.sh post-commit hook now targets only the first ### Added/### Fixed section (was appending to all version sections).
  • Hub table rendering — markdown tables in hub detail pages now render with proper <table>/<thead>/<tbody> structure.
  • Community CI clean — 21 frontmatter fixes across protocols and muscles (missing breadcrumb, tier, license, author, version fields).
  • Script drift — 7 scripts synced from working copies to agent repo (soma-code v1→v2, soma-reflect, soma-seam, soma-scrape, soma-spell, soma-plans, soma-query).
  • Hub scripts sanitized — private paths (Gravicity, vault) stripped from soma-seam.sh.

[0.6.7] — 2026-03-30

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • soma-workspace-migrate-legacy.sh — lazy migration W2 of plan 02 (s01-680a9c, preload #3) — walks ~/.soma/plugins/<type>/state.json and copies each into ~/.soma/workspaces/__legacy__/<type>/<type>-1.json + registers in ~/.soma/workspaces/__legacy__/panes.json. Idempotent (re-run skips already-registered instances). Skips leading-underscore types (_test, _regression_test) by default. Preserves old paths for one release cycle as fallback. Per 02-workspace-pane-config.md § Migration W2 (lazy) and ~/.soma/workspaces/README.md. Smoke-verified end-to-end against a tmp clone of ~/.soma/plugins/: 8 panes migrated, registry built with types/paths/timestamps/provenance markers, re-run skipped all 8.
  • rewrite DNA.md — self-awareness, owner’s manual, link to docs for deep reference
  • /soma doctor — migration command. Detects version mismatch on boot, prompts to run migration script with confirmation, shows output, reloads settings. Post-migration guidance for body file review.
  • Boot migration check — notifies when project .soma/ version is behind agent version.
  • Global vs parent detectiondetectProjectContext() distinguishes ~/.soma/ (global runtime) from real parent workspaces. Init prompt has three-way messaging: real parent choice, global fallback, or no soma.
  • Monorepo-aware first breath — detects multi-repo projects, lists sub-projects with detected stacks. Points agent to soma-code.sh structure for orientation.
  • First-breath tool hints — all first-breath messages include soma-code.sh and soma-seam.sh usage examples.
  • Body template scaffoldingbody.md (Project, Structure, Workflow, Current Focus sections) and voice.md (Delivery, Tone, Rhythm sections) ship with header scaffolding and comment breadcrumbs.
  • Richer _memory.md — preload template now includes Weather, Who You Were, Orient From, Do NOT Re-Read sections.
  • Stash checkpoint stylecheckpoints.project.style: "stash" now wired. Uses git stash push --include-untracked with session ID.
  • Migration systemv0.6.6-to-v0.6.7.md map + migrate-0.6.6-to-0.6.7.sh script. Handles settings, body templates, protocols. Backs up before replacing, skips customized files.

Changed

  • System prompt budget — default systemPrompt.maxTokens raised from 4000 to 10000. Anthropic’s system prompt is ~25k; ours at ~5k was triggering false warnings.

Fixed

  • help header shows ‘CLI v…’ not bare version
  • help rewrite, script theme crash, focus session, postinstall, docs
  • Preload resume false-positivesoma -c no longer falsely detects preloads from previous rotations as “written this session.” Uses mtime check (2-min threshold).
  • Body template instructions — moved from frontmatter description: (invisible to agent) to HTML comment breadcrumbs in file body (visible, replaceable).
  • Migration script path resolution — resolves bundled templates relative to script location, works in sandbox/dev/installed contexts.

[0.6.6] — 2026-03-29

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • soma-workspace-migrate-legacy.sh — lazy migration W2 of plan 02 (s01-680a9c, preload #3) — walks ~/.soma/plugins/<type>/state.json and copies each into ~/.soma/workspaces/__legacy__/<type>/<type>-1.json + registers in ~/.soma/workspaces/__legacy__/panes.json. Idempotent (re-run skips already-registered instances). Skips leading-underscore types (_test, _regression_test) by default. Preserves old paths for one release cycle as fallback. Per 02-workspace-pane-config.md § Migration W2 (lazy) and ~/.soma/workspaces/README.md. Smoke-verified end-to-end against a tmp clone of ~/.soma/plugins/: 8 panes migrated, registry built with types/paths/timestamps/provenance markers, re-run skipped all 8.
  • rewrite DNA.md — self-awareness, owner’s manual, link to docs for deep reference
  • /inhale guard + stale warning, slash command usage hints
  • Init UX — prompt before auto-scaffolding (ctx.ui.confirm), parent .soma/ inheritance when user declines, scaffoldBody templateDir priority chain. (SX-164, SX-165, SX-241)
  • Command provenance/soma status shows which extension registered each command via Pi’s sourceInfo. (SX-233)
  • cli.js tracked sourcesrc/cli.js in agent repo is source of truth. sync-to-cli.sh and soma-release.sh use it. (SX-252)
  • Protocol coaching voice — 14/17 protocol TL;DRs rewritten from spec/documentation voice to coaching voice. (SX-109)

Changed

  • Upstream sync R3 — Pi 0.61.1 → 0.63.1 (71 commits, 3 releases). SourceInfo provenance, built-in tools as extensions, multi-edit, sessionDir, compaction fixes. 0 breaking changes on our imports. (SX-230)
  • Stale branches cleaned — deleted feat/docs-system, feat/runtime (archived to patches), protocol-quality-pass, feature/ship-breath-cycle. Agent repo: dev + main + backup only.
  • scaffoldBody priority chain: templateDir → bundled _public/ → bundled body/.

Fixed

  • help header shows ‘CLI v…’ not bare version
  • help rewrite, script theme crash, focus session, postinstall, docs
  • restore walk-up, keep .soma-only + runtime-home skip
  • findSomaDir checks current dir only, no walk-up
  • only .soma/ is a valid soma root, not .claude/ or .cursor/
  • skip global runtime home in findSomaDir walk-up
  • /soma prompt diagnostic checked for “Learned Patterns” but actual heading is “Muscle Memory”.

[0.6.5] — 2026-03-28

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • soma-workspace-migrate-legacy.sh — lazy migration W2 of plan 02 (s01-680a9c, preload #3) — walks ~/.soma/plugins/<type>/state.json and copies each into ~/.soma/workspaces/__legacy__/<type>/<type>-1.json + registers in ~/.soma/workspaces/__legacy__/panes.json. Idempotent (re-run skips already-registered instances). Skips leading-underscore types (_test, _regression_test) by default. Preserves old paths for one release cycle as fallback. Per 02-workspace-pane-config.md § Migration W2 (lazy) and ~/.soma/workspaces/README.md. Smoke-verified end-to-end against a tmp clone of ~/.soma/plugins/: 8 panes migrated, registry built with types/paths/timestamps/provenance markers, re-run skipped all 8.
  • rewrite DNA.md — self-awareness, owner’s manual, link to docs for deep reference
  • /inhale guard + stale warning, slash command usage hints
  • soma inhale --list — show available preloads with age and staleness markers from CLI.
  • soma inhale <name> — partial name match. Load a specific preload by date, session ID, or any substring. Ambiguous matches show alternatives.
  • soma inhale --load <path> — load any file as a preload by absolute or relative path.
  • soma map <name> — top-level subcommand replacing --map flag. Runs a MAP with prompt-config and targeted preload.
  • soma map --list — show available MAPs with status and description from CLI.
  • /soma preload (in-session) — enhanced to list all preloads + inject by partial name match.
  • listPreloads() + findPreloadByName() in core/preload.ts — preload discovery and partial name matching.
  • Settings-driven heat overrides (settings.heat.overrides) — per-project AMPS heat control. Values act as both seed and decay floor. Plan/MAP overrides take priority. (31e1383)
  • inherit.automations — separate from tools inheritance, allows projects to opt out of parent MAPs independently. (3f01343)
  • Statusline preload indicator — shows preload status in footer. Smart /exhale detects edit vs write mode. (76cd246)
  • Auto-archive stale preloads after exhale — archiveStalePreloads() moves old preloads to _archive/. (7f2f086)
  • Restart signal — auto-create .restart-required on extension/core file changes, check across full soma chain. Signal moved to ~/.soma/ (global). (14d0253, 635d36e, e252a63)

Changed

  • --preload flag deprecated — shows warning pointing to soma inhale or soma map. Still works for backward compat.
  • Boot greeting decomposed — session ID and file paths now separate template variables. (4d8331f)

Fixed

  • help header shows ‘CLI v…’ not bare version
  • help rewrite, script theme crash, focus session, postinstall, docs
  • restore walk-up, keep .soma-only + runtime-home skip
  • findSomaDir checks current dir only, no walk-up
  • only .soma/ is a valid soma root, not .claude/ or .cursor/
  • skip global runtime home in findSomaDir walk-up
  • Crash on partial settingssettings.heat.overrides access without optional chaining crashed when heat section missing. Now defensive. (b837a37)
  • Breathe graceSeconds mismatch — runtime fallback was 60s, settings default was 30s. Aligned to 30s. (b837a37)
  • 5 auto-breathe UX gaps — smart context warnings, resume awareness, write heuristic for preload detection. (0f86bec)

[0.6.4] — 2026-03-23

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • soma-workspace-migrate-legacy.sh — lazy migration W2 of plan 02 (s01-680a9c, preload #3) — walks ~/.soma/plugins/<type>/state.json and copies each into ~/.soma/workspaces/__legacy__/<type>/<type>-1.json + registers in ~/.soma/workspaces/__legacy__/panes.json. Idempotent (re-run skips already-registered instances). Skips leading-underscore types (_test, _regression_test) by default. Preserves old paths for one release cycle as fallback. Per 02-workspace-pane-config.md § Migration W2 (lazy) and ~/.soma/workspaces/README.md. Smoke-verified end-to-end against a tmp clone of ~/.soma/plugins/: 8 panes migrated, registry built with types/paths/timestamps/provenance markers, re-run skipped all 8.
  • rewrite DNA.md — self-awareness, owner’s manual, link to docs for deep reference
  • /inhale guard + stale warning, slash command usage hints
  • prompt before auto-init + parent inheritance (SX-164, SX-165, SX-241)
  • show command provenance in /soma status (SX-233)
  • track cli.js as source in agent repo (SX-252)
  • Body architecture — structured identity system. .soma/body/ with content files (soul.md{{soul}}, voice.md{{voice}}, body.md{{body}}) and templates (_mind.md, _memory.md, _boot.md). Content files become template variables. Templates control system prompt and preload structure.
  • Template engine (core/body.ts) — {{variable}} interpolation with 5 modifiers (|tldr, |section:Name, |lines:N, |last:N, |ref), conditional blocks ({{#var}}...{{/var}}), graceful degradation for missing vars.
  • AMPS Skill Loader (core/skill-loader.ts) — unified content scanner. All AMPS classified by heat: hot (8+) = full body in prompt, warm (3-7) = <available_skills> XML (agent reads on demand), cold (0-2) = hidden. Claude’s native skill format.
  • /body command — template inspector with 4 subcommands: check (health report), vars (all variables by category), map (template structure), render (full compiled system prompt, fresh from disk).
  • Variable registry — 50+ template variables categorized (context, identity, section, boot, session, focus, metadata, preload-tpl, deprecated) with essential flags and descriptions.
  • SOMA.md replaces identity.md as canonical identity file. Resolution: body/soul.mdSOMA.mdidentity.md (legacy fallback).
  • body.md — project-shaped working context variable ({{body}}). Changes per project, placed anywhere in _mind.md.
  • First-breath template — conditional blocks ({{#has_code}}, {{#is_blank}}) for first-run experience.
  • /exit command — save state and quit cleanly.
  • Boot greetings rewritten — “You woke up” not “You’ve booted into a session.”
  • Header bar shows soul/body status indicators.
  • soma-verify.sh drift_public/ sync check across protocols, muscles, body files, community repo, and agent repo.
  • systemPrompt.maxTokens wired as soft warning — notification when compiled prompt exceeds budget.
  • Muscle heat bumps on load — muscles that stay relevant gain heat naturally (+1 per boot). Previously only bumped when explicitly read.
  • Body file inheritance — content files and templates walk the soma chain (project → parent → global). Child wins on collision.
  • user.name, user.style settings with {{user_name}}, {{user_style}} variables.

Changed

  • System prompt driven by body/_mind.md template when present. Users control structure, sections, custom text. Falls back to built-in compiler.
  • Warm AMPS appear as <available_skills> XML alongside Pi native skills — Claude’s trained format for lazy-loaded content.
  • prompts/system-core.md — removed explicit context percentages (50/70/80/85%). Auto-breathe handles thresholds; agent shouldn’t guess.
  • AMPS cleanup — 44 → 34 active muscles (10 archived), 9 → 2 high-overlap triggers (16 cleaned), 34/34 have descriptions.
  • Docs sweep — 9 pages updated for body architecture, SOMA.md, skill loader, template engine, removed gendered pronouns.
  • sync-docs.sh manifest expanded — 10 new docs added (focus, maps, sessions, prompts, skills, settings, themes, keybindings, models, terminal-setup).
  • Protocol test accepts description: alongside breadcrumb: (migration compat).
  • Sandbox test updated for 8 extensions, 19 protocols, SOMA.md init.

Fixed

  • help header shows ‘CLI v…’ not bare version
  • help rewrite, script theme crash, focus session, postinstall, docs
  • restore walk-up, keep .soma-only + runtime-home skip
  • findSomaDir checks current dir only, no walk-up
  • only .soma/ is a valid soma root, not .claude/ or .cursor/
  • skip global runtime home in findSomaDir walk-up
  • defensive settings.heat access + stale test mocks — 567/567 pass
  • 5 UX gaps — smart warnings, resume awareness, write heuristic
  • Conversation tail injection removed — was scanning stale Pi JSONL sessions from wrong runtime, sidetracking agent with old conversations.
  • Soul frontmatter leaking into rendered system prompt — loadIdentity() now strips YAML frontmatter.
  • Duplicate # Identity headingbuildLayeredIdentity() no longer hardcodes heading; template handles it.
  • _public/ drift — 22 files synced across community + agent repos. Drift detection tool built.
  • Boot message duplication — stripped content already in system prompt from boot followUp.
  • /body render compiles fresh from disk each time (was using stale boot cache).

[0.6.3] — 2026-03-22

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • soma-workspace-migrate-legacy.sh — lazy migration W2 of plan 02 (s01-680a9c, preload #3) — walks ~/.soma/plugins/<type>/state.json and copies each into ~/.soma/workspaces/__legacy__/<type>/<type>-1.json + registers in ~/.soma/workspaces/__legacy__/panes.json. Idempotent (re-run skips already-registered instances). Skips leading-underscore types (_test, _regression_test) by default. Preserves old paths for one release cycle as fallback. Per 02-workspace-pane-config.md § Migration W2 (lazy) and ~/.soma/workspaces/README.md. Smoke-verified end-to-end against a tmp clone of ~/.soma/plugins/: 8 panes migrated, registry built with types/paths/timestamps/provenance markers, re-run skipped all 8.
  • rewrite DNA.md — self-awareness, owner’s manual, link to docs for deep reference
  • /inhale guard + stale warning, slash command usage hints
  • prompt before auto-init + parent inheritance (SX-164, SX-165, SX-241)
  • show command provenance in /soma status (SX-233)
  • track cli.js as source in agent repo (SX-252)
  • settings-driven heat overrides — per-project AMPS control
  • inherit.automations — separate from tools inheritance
  • statusline preload indicator + smart /exhale (edit vs write)
  • auto-archive stale preloads after exhale + archiveStalePreloads()
  • /hub command — unified hub interface for community content. Install, fork, share, find, list, status. Replaces old /install and /list commands (kept as backward compat aliases).
  • Smart sharing (/hub share) — quality scoring (0-100%), privacy auto-fix with _public/ staging, README generation that captures --help output and extracts functions, dependency resolution.
  • Drop-in commands — scripts in .soma/amps/scripts/commands/ become /soma <name> commands. Hot-loadable, no restart needed. Tab completions included.
  • scope: core protocols — documentation protocols whose behavior is coded in TypeScript. Never loaded into prompt (saves ~2000 tokens). Discoverable, readable on demand via docs section. /pin and /kill block with explanation.
  • 5 core protocols — breath-cycle, heat-tracking, session-checkpoints, git-identity, hub-sharing.
  • automation content type — MAPs are now installable hub content. 3 published: debug, refactor, visual-gap-analysis.
  • Dependency resolutionrequires: in frontmatter auto-installs dependencies (scripts, protocols, muscles) alongside content.
  • gitIdentity.email array support — multiple valid emails for multi-account users.
  • Default preload template — Weather (emotional tone) + Warnings (traps for next session) sections.
  • Preload template on community hub — customizable preload format.
  • Regression test suite — test-hub.sh (25 tests) + test-commands.sh (26 tests). Side-effect testing for -p mode.

Changed

  • Hub: 40 items across 5 content types (17 protocols, 8 muscles, 3 scripts, 3 automations, 9 templates).
  • /soma prompt shows core protocols with 📄 icon instead of misleading heat display.
  • Bundled protocols updated with shipped tool references (soma-code, soma-scrape, soma-spell).
  • Community CI — validate-frontmatter accepts triggers (replaces topic+keywords), description OR breadcrumb. Format-check supports scope: core. Attribution allows org identity for owners. Actions upgraded to v6 (Node 22).

Fixed

  • help header shows ‘CLI v…’ not bare version
  • help rewrite, script theme crash, focus session, postinstall, docs
  • restore walk-up, keep .soma-only + runtime-home skip
  • findSomaDir checks current dir only, no walk-up
  • only .soma/ is a valid soma root, not .claude/ or .cursor/
  • skip global runtime home in findSomaDir walk-up
  • defensive settings.heat access + stale test mocks — 567/567 pass
  • 5 UX gaps — smart warnings, resume awareness, write heuristic
  • /hub list --remote — flag was parsed as type filter, returning 0 results.
  • Drop-in command output — ANSI escape codes stripped (sendUserMessage renders markdown, not terminal).
  • Stale git-identity heat rule removed from HEAT_RULES (protocol was archived).
  • soma-refactor.sh scan — string references now exclude node_modules/dist/.git.

Security

  • soma-beta.map files (128) and .d.ts files (64) stripped from dist. Source maps contained full sourcesContent.
  • soma-beta — orphan history on every release. Old commits can’t recover source code.

[0.6.2] — 2026-03-21

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • soma-workspace-migrate-legacy.sh — lazy migration W2 of plan 02 (s01-680a9c, preload #3) — walks ~/.soma/plugins/<type>/state.json and copies each into ~/.soma/workspaces/__legacy__/<type>/<type>-1.json + registers in ~/.soma/workspaces/__legacy__/panes.json. Idempotent (re-run skips already-registered instances). Skips leading-underscore types (_test, _regression_test) by default. Preserves old paths for one release cycle as fallback. Per 02-workspace-pane-config.md § Migration W2 (lazy) and ~/.soma/workspaces/README.md. Smoke-verified end-to-end against a tmp clone of ~/.soma/plugins/: 8 panes migrated, registry built with types/paths/timestamps/provenance markers, re-run skipped all 8.
  • rewrite DNA.md — self-awareness, owner’s manual, link to docs for deep reference
  • /inhale guard + stale warning, slash command usage hints
  • prompt before auto-init + parent inheritance (SX-164, SX-165, SX-241)
  • show command provenance in /soma status (SX-233)
  • track cli.js as source in agent repo (SX-252)
  • settings-driven heat overrides — per-project AMPS control
  • inherit.automations — separate from tools inheritance
  • statusline preload indicator + smart /exhale (edit vs write)
  • auto-archive stale preloads after exhale + archiveStalePreloads()
  • Natural muscle heat detection — muscles now heat-bump from natural use, not just focus. Script execution matches against tools: field. File edits match path segments against triggers. Zero configuration needed.
  • Migration systemversion field in settings.json. core/migrations.ts discovers and chains migration maps. soma doctor checks workspace health. soma doctor --fix auto-repairs. soma doctor --migrate spawns agent for complex fixes.
  • Community template sync — boot fetches latest protocols from community repo. Bundled protocols serve as offline fallback. Add content to community → add name to template → all new users get it.
  • tools: field in muscle frontmatter — declares which scripts a muscle references. Parsed and used for natural heat detection.

Changed

  • Triggers consolidationtriggers + keywords + topic merged into single triggers list at parse time. tags stays for categorization only. Old format works indefinitely (backwards compat).
  • Muscle interface simplified — one activation list instead of four redundant fields with different score weights.
  • Personality engine — welcome flow is honest about being templates, not the agent.

Fixed

  • help header shows ‘CLI v…’ not bare version
  • help rewrite, script theme crash, focus session, postinstall, docs
  • restore walk-up, keep .soma-only + runtime-home skip
  • findSomaDir checks current dir only, no walk-up
  • only .soma/ is a valid soma root, not .claude/ or .cursor/
  • skip global runtime home in findSomaDir walk-up
  • defensive settings.heat access + stale test mocks — 567/567 pass
  • 5 UX gaps — smart warnings, resume awareness, write heuristic
  • Runtime delegation — soma-beta now includes cli.js and Pi runtime files. Previously thin-cli fell through to raw Pi (no version skip, no auto-rotate, “Update Available” banner).
  • Fresh installs now include version field in settings.json.
  • Stale test assertions — test suite checked for removed frontmatter fields and nonexistent commands.

[0.6.1] — 2026-03-20

Changed

  • Pi runtime upgraded 0.61.0 → 0.61.1 — Release Round 3 (#3cbf2bc)
    • Keybinding eviction fix (stop removing unrelated defaults)
    • agentDir respected for SDK session paths
    • Suspend/resume stability (Ctrl+Z/fg)
    • ToolCallEventResult exported

Fixed

  • help header shows ‘CLI v…’ not bare version
  • help rewrite, script theme crash, focus session, postinstall, docs
  • restore walk-up, keep .soma-only + runtime-home skip
  • findSomaDir checks current dir only, no walk-up
  • only .soma/ is a valid soma root, not .claude/ or .cursor/
  • skip global runtime home in findSomaDir walk-up
  • defensive settings.heat access + stale test mocks — 567/567 pass
  • 5 UX gaps — smart warnings, resume awareness, write heuristic
  • CLI dist synced from pi-mono 0.61.1 — getEditorKeybindingsgetKeybindings crash resolved
  • Stale content-cli.js import removed (Pi 0.61.0 moved install/list/content to main.js)
  • --help fixed — printGumHelp removed in 0.61.0, replaced with printHelp
  • Heat system docs: .protocol-state.jsonstate.json across 6 files, 3 repos
  • Protocols page: collapsed 60-line heat duplication to reference, renamed “Protocols & Heat” → “Protocols”
  • soma-verify.sh self-analysis: script search recurses into subdirectories, skips archived .soma/
  • 7 muscles: missing topic: / keywords: frontmatter restored
  • .protocol-state.json deleted (dead since March 13)

Docs

  • 27 pages across 5 sections (was 24 across 5 disorganised sections)
  • New: amps.md (four-layer overview), migrating.md (from CLAUDE.md/.cursorrules), troubleshooting.md
  • Collapsible sidebar with section icons
  • Roadmap curated for all 7 versions, “Next” section added
  • /beta redesigned: “Private Beta” → “Source Access” with tier cards and Known Gaps

Blog

  • “Three Files” — solo, on identity and architecture
  • “The Ratio” — solo, on code vs behavior growth
  • “The Operating System We Didn’t Plan” — solo, on AMPS as dev process
  • Interlinks across all 8 published posts + doc page SEO links

[0.6.0] — 2026-03-20

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • soma-workspace-migrate-legacy.sh — lazy migration W2 of plan 02 (s01-680a9c, preload #3) — walks ~/.soma/plugins/<type>/state.json and copies each into ~/.soma/workspaces/__legacy__/<type>/<type>-1.json + registers in ~/.soma/workspaces/__legacy__/panes.json. Idempotent (re-run skips already-registered instances). Skips leading-underscore types (_test, _regression_test) by default. Preserves old paths for one release cycle as fallback. Per 02-workspace-pane-config.md § Migration W2 (lazy) and ~/.soma/workspaces/README.md. Smoke-verified end-to-end against a tmp clone of ~/.soma/plugins/: 8 panes migrated, registry built with types/paths/timestamps/provenance markers, re-run skipped all 8.
  • rewrite DNA.md — self-awareness, owner’s manual, link to docs for deep reference
  • /inhale guard + stale warning, slash command usage hints
  • prompt before auto-init + parent inheritance (SX-164, SX-165, SX-241)
  • show command provenance in /soma status (SX-233)
  • track cli.js as source in agent repo (SX-252)
  • settings-driven heat overrides — per-project AMPS control
  • inherit.automations — separate from tools inheritance
  • statusline preload indicator + smart /exhale (edit vs write)
  • auto-archive stale preloads after exhale + archiveStalePreloads()

MAP System — Plan-Driven Agent Orchestration

  • maps.ts — MAP discovery + prompt-config YAML parser (#1039512)
  • PlanPromptConfig — plan-driven system prompt overrides: heat overrides, force-include/exclude, section toggles, budget overrides, supplementary identity (#28d71fe)
  • soma --map <name> — MAP targeting via .boot-target signal file. Loads prompt-config, targeted preload, and MAP content as navigation context (#a12709e)
  • 18 tests for MAP parser + plan override compilation (#df835cb)

Focus Targeting — Seam-Traced Boot

  • soma-focus.sh — pre-model seam-traced boot priming. Traces keyword through memory, scores relevance, generates .boot-target with heat overrides (#116c4bb)
  • Focus handler in soma-boot.tstype: "focus" .boot-target support. Loads focus preload, related MAPs (max 3), focus summary (#2f7d302)
  • Muscle trigger engine — triggers: frontmatter parsed and matched at boot. Muscles auto-activate when focus keyword matches their tags, keywords, topics, or explicit triggers (#1bc1c57)
  • matchMusclesToFocus() — TypeScript-native muscle matching with scored relevance (10=trigger, 5=tag/keyword, 4=topic, 3=name, 2=digest) (#1bc1c57)
  • trackMapRun() — programmatic MAP usage tracking. Auto-increments runs: and updates last-run: in frontmatter when MAP loads via .boot-target (#893f176)

Scripts — Agent Tools That Ship

  • 5 Tier 1 scripts now ship with Soma and are seeded on soma init (#116c4bb):
    • soma-code.sh — multi-language codebase navigator (map, find, refs, replace, structure, tsc-errors)
    • soma-seam.sh — trace concepts through memory, code, and sessions
    • soma-focus.sh — seam-traced boot priming
    • soma-reflect.sh — parse session logs for patterns and observations
    • soma-plans.sh — plan lifecycle management
  • scaffoldScripts() in init.ts — copies bundled scripts to .soma/amps/scripts/ on init (#116c4bb)
  • ensureGlobalSoma() — bootstraps ~/.soma/ with AMPS layout on first boot. Seeds scripts, creates global identity template. Idempotent. (#47422e8)
  • Protocol scope fix — 5 protocols changed from hub/internal to bundled for proper CLI distribution (#47422e8)
  • Recursive AMPS discovery — muscles, protocols, scripts, MAPs now scan subdirectories (max 2 levels). Directories with _ or . prefix are skipped. Enables organized layouts: muscles/ui/, scripts/dev/, maps/runtime/ (#c36dcd0)
  • Identity template enhanced — 5 working patterns (read-before-write, scripts-first, verify-before-claiming, corrections-as-signal, log-your-work) in both built-in and smart templates (#98035e9)
  • soma-pr.sh moved to _dev/ — requires GitHub App secrets users don’t have (#98035e9)
  • soma-scrape.sh — intelligent doc discovery + scraping (resolve, pull, search, discover). Requires gh, curl, jq (#18e5bde)
  • soma-query.sh — unified search replacing soma-scan + soma-search. Commands: find, list, search, sessions, related, impact (#5604f2a)
  • /scan-logs --send flag — injects search results into agent conversation (#1f891a5)

Guard & Safety

  • Worktree boundary enforcement — hard-block writes outside allowed worktree path (#961f2bc)
  • Soul-space command gated behind .gate.md file (#2b0d819)

Agent Infrastructure

  • PR template, agent contribution standards for GitHub App bot PRs (#743b48d)
  • Soul-space mode — /soul-space on replaces keepalive with MLR prompts (#caea905)
  • TypeScript type checking (npm run check) + biome linting (npm run lint) (#20ab881)

Identity & Protocols

  • Identity bootstrap with 4 sections: This Project, Voice, How I Work, Review & Evolve (#c5086ea)
  • response-style protocol — set voice, length, emoji, and format preferences (#50aee8a)
  • Dignity clause in correction-capture — acknowledge without over-apologizing (#50aee8a)
  • maps protocol — teaches MAP system: check before tasks, build after repeated processes (#4a85b53)
  • plan-hygiene protocol — plan lifecycle: status tracking, ≤12 active budget, verify before claiming (#4a85b53)
  • soma inhale CLI subcommand — fresh session with preload from last session (#f61064f)
  • soma (no args) now starts clean — no preload injection (#f61064f)
  • User interrupt detection during auto-breathe — 1st interrupt resets timer, 2nd cancels (#d530af8)
  • Gum-formatted --help output with tables and styled header (cli)

Changed

  • Pi runtime upgraded 0.60.0 → 0.61.0 — full upstream sync (Release Round 2), 76 upstream commits (#de7bd1c)
  • PI_PACKAGE_DIR + SOMA_CODING_AGENT_DIR env vars — correct path delegation for .soma/ project dirs (#5c9ba4d, #f5818a6)
  • system-core.md updated — scripts-first workflow, tool-building guidance, session logging format, preload coaching, verify-before-claiming (#116c4bb)
  • tool-discipline.md v3.0.0 — script-first workflow, when to build scripts, script standards (#116c4bb)
  • soma-breathe.ts extracted from soma-boot.ts — cleaner separation of concerns (#aa4ae19)
  • Protocol quality-standards expanded — close-the-loop, tests-match-code, conventional commits (#d2dc95d)
  • Preload quality added to breath-cycle TL;DR (#0632fad)
  • Author attribution + CC BY 4.0 license footers on protocols (#0a2e0ac)

Fixed

  • help header shows ‘CLI v…’ not bare version
  • help rewrite, script theme crash, focus session, postinstall, docs
  • restore walk-up, keep .soma-only + runtime-home skip
  • findSomaDir checks current dir only, no walk-up
  • only .soma/ is a valid soma root, not .claude/ or .cursor/
  • skip global runtime home in findSomaDir walk-up
  • defensive settings.heat access + stale test mocks — 567/567 pass
  • 5 UX gaps — smart warnings, resume awareness, write heuristic
  • Edit tool detection in preload + overwrite-safe breathe instructions (#9e7684f)
  • Auto-breathe graceSeconds consistency + DRY path helpers (#ec857f8)
  • Auto-breathe timeout + session log -2 suffix bugs (#baaf51b)
  • Session ID extraction from Pi entry format (#7b3931e)
  • Reuse session ID on resume — no more orphan logs (#01bc3b7)
  • Guard session_start against Pi cache re-fire (#04571ed)
  • All 10 pre-existing TypeScript errors resolved — 0 type errors (#13bfaf9)
  • /auto-breathe off now cancels in-flight rotation (#2bdcf99)
  • Stray ‘t’ in boot causing “Failed to load extension: t is not defined” (#be18665)
  • findSomaDir returns SomaDir object — use .path for join() (#73eca3b)
  • Settings test allows partial override files (guard-only) (#d372373)
  • Maps test output format matches Results: pattern for soma-ship (#45017ce)
  • /scrape route.provide moved inside handler scope (#cf0170d)
  • Warm protocol TL;DRs shortened from 400-555 to ~150 chars — saves ~1500 tokens per boot (#9008d43)
  • pre-flight heat lowered from 8 (hot) to 5 (warm) — too heavy for empty repos (#9008d43)
  • scaffoldProtocols() now copies ALL bundled protocols on init, not just breath-cycle (#9008d43)
  • Auto-breathe grace period is now time-based (30s default) instead of turn-based (#8ca5e52)
  • Preload trust hierarchy — boot instructions explicitly require stating resume point (#dfb5ca9)
  • Hub protocol TL;DRs tightened (git-identity, session-checkpoints, tool-discipline) (#dd8c4cf)
  • Breadcrumbs synced from community — consistent cross-repo references (#9461185)
  • All 14 bundled protocols synced to workspace — zero drift. 7 had diverged since v0.5.2 (#d49d9c7)
  • soma-focus.sh unbound variable fix when no .soma/ exists (#d49d9c7)
  • soma-focus.sh regex updated for recursive AMPS paths (subdirectory muscles/protocols/MAPs) (#6f7549f)
  • MAP discovery now scans projects/*/phases/*/map.md — phase MAPs co-located with project specs (#9f9cca7)
  • findMap() falls back to full discovery when direct path lookup fails (#9f9cca7)
  • MAP scope: 8 root MAPs changed from internal to public (build-muscle, build-script, debug, plan-to-maps, refactor, soma-focus, plan-validation, sdk-research)
  • MAP test uses temp fixture instead of hardcoded workspace path (#bd53f45)
  • Focus fast mode for common keywords — skip seam trace when 50+ matches, scan frontmatter directly (#027fc87)
  • Focus heat scoring fixed — score * 2 reaches HOT tier (was score + 2, max WARM). Force-include at score 5+ (was 8+) (#5d572d6)
  • Focus MAP prompt-config merging — related MAPs’ heat overrides and force-includes merge into focus session (#5d572d6)
  • ensureGlobalSoma() now seeds bundled protocols — existing users get new protocols on upgrade (#fe29c0e)
  • Tests updated for soma-query consolidation, maps protocol frontmatter fixed (#29687e7)
  • Removed dead getScriptDescription() function (#6ddc8f7)
  • Maps protocol TL;DR updated with soma focus + tracking mention (#a4e8413)
  • scaffoldScripts now seeds all 10 shipped scripts (was 8) (#2757bdb)
  • All directory trees in docs aligned with amps/ layout (#705e089)
  • Stale memory/muscles paths fixed → amps/muscles (#ba5c5ca)

Docs

  • New page: models.md — comprehensive Models & Providers guide: 17+ providers, API key storage, custom providers (#1781d24)
  • New page: keybindings.md — keyboard shortcuts and customisation (#56ab090)
  • New page: themes.md — built-in and custom themes (#56ab090)
  • New page: settings.md — engine settings reference (#56ab090)
  • New page: terminal-setup.md — terminal recommendations and tmux (#56ab090)
  • New page: sessions.md — session tree, fork, compaction, branch summarisation (#cdb7cd1)
  • New page: prompts.md — prompt template format and usage (#cdb7cd1)
  • New page: skills.md — SKILL.md format and skill authoring (#cdb7cd1)
  • getting-started.md updated — “Set Up a Provider” section, model switching (#1781d24)
  • commands.md updated — Model Commands section, CLI model flags (#1781d24)
  • extending.md updated — custom model providers section (#b99902a)
  • Pi doc parity: 23/23 docs covered (was 15/23)
  • New page: maps.md — MAP system guide: creation, prompt-config, loading, tracking (#14744fb)
  • New page: focus.md — seam-traced boot priming: usage, matching scores, triggers (#14744fb)
  • scripts.md rewritten — 6→14 scripts documented, core/utility sections, “Building Your Own” guide (#14744fb)
  • how-it-works.md — added MAPs + Focus sections, fixed duplicated paragraph, context scaling note (#14744fb)
  • configuration.md — added Custom Content Paths, Script Discovery, Global Config (~/.soma/) sections (#6ddc8f7)
  • muscles.md — added tags, triggers, tools frontmatter fields (#14744fb)
  • protocols.md — 4→16 protocol table with all shipped protocols (#14744fb)
  • Commands page: add /code, /scrape, /scan-logs, fix auto-continue→rotate, add —orphan (#5629dd3)
  • Guard: add cross-references to related muscles, MAPs, scripts (#dd1a117)
  • How-it-works: add router and CLI rotation to auto-breathe section (#35c939e)
  • Add /route command and soma-route.ts extension docs (#668b23f)
  • Scripts: add soma-scan and soma-search, fix usage paths for npm users (#e791660)
  • Fix preload naming convention docs (#2b1be52)
  • Reality check — remove stale scripts, fix AMPS layout, update commands (#dfce881)

Protection & Distribution

  • BSL 1.1 license deployed to all repos (agent, cli, community, core)
  • All GitHub repos → private (soma-agent, cli, community, core)
  • npm: 6/7 versions unpublished, v0.1.0 deprecated
  • Beta signup: Vercel serverless API → GitHub Issue via soma-agent[bot]
  • beta-testers GitHub team created (read access to soma-agent)
  • esbuild obfuscation pipeline — scripts/build-dist.mjs compiles 7 extensions + core to 140KB minified+mangled JS (#ef86ff5)
  • Distribution verification — scripts/verify-dist.mjs with 23 checks (#8962681)
  • npm run build:dist — clean + compile + verify in one command
  • Protocols ship as readable .md in dist/content/

Thin CLI (repos/cli)

  • Thin CLI wrapper — 37KB total, zero dependencies, pure Node built-ins
  • Personality engine (personality.js) — 12 skeleton intents, 46 variants, 9 spintax topics, 14 paragraph templates
  • Interactive Q&A — press ? to ask about 9 topics with keyword matching (50+ triggers)
  • Typing animation — typeOut() with punctuation pauses, random jitter, ANSI-aware
  • soma init — GitHub CLI auth: gh → team membership (with repo access fallback) → clone dev → npm install
  • soma doctor — 11 health checks with personality engine summary
  • soma update — npm CLI + core git versions (fetch-first)
  • soma status — version, home, install state, beta access, core branch@hash
  • soma about — full explainer with generated pitch footer
  • No-compaction topic — key differentiator messaging
  • Daily rotating concepts (8 topics) on welcome screen
  • Beta access cached with 1-hour TTL
  • Delegation: PI_CODING_AGENT_DIR env var → Pi discovers Soma extensions (#8598c56)
  • Smart command detection — post-install commands show “requires runtime”
  • PI_PACKAGE_DIR delegation — thin-cli.js resolves piConfig from soma-beta package.json, all project paths → .soma/ (#5c9ba4d)
  • SOMA_CODING_AGENT_DIR — both PI_ and SOMA_ env vars set for delegation regardless of piConfig load order (#f5818a6)
  • User extension discovery — .soma/extensions/ passed via -e flags to Pi runtime
  • soma-beta v0.6.0-rc.6 — self-contained: thin-cli + personality + extensions + core + themes + export-html + protocols (680KB)
  • soma-release.sh — reads Pi dep versions dynamically from agent package.json, bundles thin-cli.js + personality.js, piConfig verification gate

Testing

  • soma-sandbox.sh — 30 automated E2E tests: branding (5), paths (3), infra (7), bundled CLI (5), models (3), identity (1), path resolution (3), tools (3), extensions (1), features (2)
  • soma-seam.sh audit upstream — cross-references upstream Pi changes against our imports, flags breaking changes, maps API usage frequency
  • Test suite overhaul — 7/13 suites execute real TypeScript via tsx (487+ total assertions)
  • test-settings.sh — 21 executed tests: defaults, cascade, malformed JSON, path resolution (#c13a7d3)
  • test-identity.sh — 13 executed tests: hasIdentity, loadIdentity, buildLayeredIdentity (#c13a7d3)
  • test-preload.sh — 15 executed tests: findPreload, hasPreload, filenames, instructions (#c13a7d3)
  • test-protocols.sh — +11 executed: detectProjectSignals, protocolMatchesSignals (#5dcc324)
  • test-utils.sh — 26 executed: every exported function tested (#5dcc324)
  • test-muscles.sh — enforces triggers, applies-to, frontmatter integrity (#db5c5a4)

AMPS Hygiene

  • 33 muscles patched — all active muscles have triggers: and applies-to:
  • 2 corrupted frontmatter fixes + 31 YAML merge artifacts fixed
  • e2e-flow-testing muscle — test in isolation pattern
  • Visual gap analysis MAP expanded (9 steps, 7 patterns, E2E test phase)
  • 5 MAPs updated with test quality info
  • release-cycle MAP: +Phase 5 (changelog sync) +Phase 6 (E2E verification)

[0.5.2] — 2026-03-15

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.
  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.
  • soma-workspace-migrate-legacy.sh — lazy migration W2 of plan 02 (s01-680a9c, preload #3) — walks ~/.soma/plugins/<type>/state.json and copies each into ~/.soma/workspaces/__legacy__/<type>/<type>-1.json + registers in ~/.soma/workspaces/__legacy__/panes.json. Idempotent (re-run skips already-registered instances). Skips leading-underscore types (_test, _regression_test) by default. Preserves old paths for one release cycle as fallback. Per 02-workspace-pane-config.md § Migration W2 (lazy) and ~/.soma/workspaces/README.md. Smoke-verified end-to-end against a tmp clone of ~/.soma/plugins/: 8 panes migrated, registry built with types/paths/timestamps/provenance markers, re-run skipped all 8.
  • rewrite DNA.md — self-awareness, owner’s manual, link to docs for deep reference
  • /inhale guard + stale warning, slash command usage hints
  • prompt before auto-init + parent inheritance (SX-164, SX-165, SX-241)
  • show command provenance in /soma status (SX-233)
  • track cli.js as source in agent repo (SX-252)
  • settings-driven heat overrides — per-project AMPS control
  • inherit.automations — separate from tools inheritance
  • statusline preload indicator + smart /exhale (edit vs write)
  • auto-archive stale preloads after exhale + archiveStalePreloads()
  • /scan-logs command — search previous tool calls + results across sessions (#31a7e17)
  • /scrape command + scrape:build router capability — intelligent doc discovery (#c950f2b)
  • Boot session warnings injection — tool usage stats from previous session (#0cda314)
  • Boot last conversation context — inject last N messages on fresh boot (#f1d7f3d)
  • Periodic auto-commit for crash resilience (#c6caccc)
  • graceTurns setting — configurable grace period before auto-breathe rotation (#c9ab5a8)
  • Guard v2: tool→muscle gating — require reading muscles before dangerous commands (#1c6b725)
  • Protocol TL;DR extraction — protocolSummary() prefers ## TL;DR body section (#83ec9ee)
  • Scratch lifecycle: session IDs, date sections, note management, auto-inject (#fd0bda2, #0d364f2)
  • Combined session ID format (sNN-<hex>) — sequential for order, hex for uniqueness (#e7c4057)
  • Statusline session ID display (#d474cbf)
  • Polyglot script discovery — .sh, .py, .ts, .js, .mjs (#1acb8c2)
  • Session log nudge with template at trigger point (#eb8acc8)
  • Identity layer in pattern-evolution, tool-awareness in working-style (#5e4219d)
  • Post-commit auto-changelog + pre-push docs-drift nudge hooks (#cc2ef55)

Changed

  • System prompt trimmed ~19% — remove duplication and stale content (#de9c517)
  • Self-awareness protocols rewritten — 5 redundant protocols → configuration guides (#b70ca44)
  • Config-first script extensions via settings.scripts.extensions (#dadb78e)
  • Unified rotation through /inhale, removed /auto-continue (#7b7ba52)
  • Migrated globalThis.__somaKeepalive to router (#e919481)

Fixed

  • help header shows ‘CLI v…’ not bare version
  • help rewrite, script theme crash, focus session, postinstall, docs
  • restore walk-up, keep .soma-only + runtime-home skip
  • findSomaDir checks current dir only, no walk-up
  • only .soma/ is a valid soma root, not .claude/ or .cursor/
  • skip global runtime home in findSomaDir walk-up
  • defensive settings.heat access + stale test mocks — 567/567 pass
  • 5 UX gaps — smart warnings, resume awareness, write heuristic
  • Boot: clean up muscle/protocol/automation formatting (#38a643f)
  • Boot: resume without fingerprint sends minimal boot, not full redundant injection (#7fd064b)
  • Boot: grace countdown skips tool turns during auto-breathe (#53bd421)
  • Boot: preload filename overwrites + rotation when preload pre-exists (#378a1b1)
  • Boot: auto-init .soma/.git when autoCommit is true (#276f6f2)
  • Boot: clear restart signal at factory load time (#0bddce2, #bb8350c)
  • Muscles/automations: filter archived status + README in discovery (#5f5ccae, #e42da9b)
  • Protocols: clean stale references, fix broken frontmatter (#7087d6a)
  • Protocols: correct attribution — Curtis Mercier only on personal/protocols-derived (#5d8fb83)
  • Heat: dynamic muscle read + script execution detection (#99a7663)
  • Extensions: soma-route.ts import path — use pi-coding-agent not claude-code (#49454ea)
  • Scripts: stop shipping dev-only scripts to users (#2c8db4a)
  • Scripts: sync paths after _dev/ move, AGENT_DIR resolution (#46615ef, #a520c13)
  • Statusline: restart detection, fs/path imports, signal path fixes (#f845894, #926fd4a, #18eba69)
  • Auto-breathe: reduce triple notifications, preload-as-signal rotation (#927bd74)

[0.5.1] — 2026-03-14

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.

  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.

  • soma-workspace-migrate-legacy.sh — lazy migration W2 of plan 02 (s01-680a9c, preload #3) — walks ~/.soma/plugins/<type>/state.json and copies each into ~/.soma/workspaces/__legacy__/<type>/<type>-1.json + registers in ~/.soma/workspaces/__legacy__/panes.json. Idempotent (re-run skips already-registered instances). Skips leading-underscore types (_test, _regression_test) by default. Preserves old paths for one release cycle as fallback. Per 02-workspace-pane-config.md § Migration W2 (lazy) and ~/.soma/workspaces/README.md. Smoke-verified end-to-end against a tmp clone of ~/.soma/plugins/: 8 panes migrated, registry built with types/paths/timestamps/provenance markers, re-run skipped all 8.

  • rewrite DNA.md — self-awareness, owner’s manual, link to docs for deep reference

  • /inhale guard + stale warning, slash command usage hints

  • prompt before auto-init + parent inheritance (SX-164, SX-165, SX-241)

  • show command provenance in /soma status (SX-233)

  • track cli.js as source in agent repo (SX-252)

  • settings-driven heat overrides — per-project AMPS control

  • inherit.automations — separate from tools inheritance

  • statusline preload indicator + smart /exhale (edit vs write)

  • auto-archive stale preloads after exhale + archiveStalePreloads()

  • Capability router for inter-extension communication (soma-route.ts) — provides/gets capabilities, emits/listens signals. Replaces globalThis hacks (#94576f3, #e919481)

  • CLI-based session rotation via .rotate-signal file — auto-breathe can now rotate without command context (#2da3155)

  • Per-session log files with auto-incrementing names (YYYY-MM-DD-sNN.md) — prevents overwrites across rotations (#d776dd6)

  • Session log and preload paths surfaced in boot message (#d934799)

  • Resume boot diffing — soma -c skips redundant preload injection (#de39fd1)

  • Restart-required detection — signal file, cmux notification, and statusline indicator when core/extension files change (#9f2a103, #f845894, #926fd4a, #18eba69)

  • soma-changelog.sh — generate categorized changelog entries from conventional commits with [cl:tag] consolidation

  • soma-changelog-json.sh — parse CHANGELOG.md into JSON for website consumption

  • ChangelogIsland.tsx + RoadmapTimeline.tsx — Preact islands for /changelog/ and /roadmap/ pages

  • soma-threads.sh — chain-of-thought tracing tool for blog seeds across session logs

  • soma-verify.sh self-analysis — muscle health, cross-location divergence, orphan detection

  • Protocol TL;DR extraction — protocolSummary() prefers ## TL;DR body section over breadcrumb (#83ec9ee)

  • Combined session ID format (sNN-<hex>) — sequential for human scanning, hex for collision safety (#e7c4057, #618cd9f)

  • commit-msg git hook — validates conventional commit format + [cl:tag] syntax

  • guard.toolGates setting — require reading muscles before dangerous bash commands (#1c6b725)

  • breathe.graceTurns setting — configurable auto-breathe grace period, replaces hardcoded 6-turn limit (#c9ab5a8)

  • Session log nudge with template at breathe trigger point (#eb8acc8)

  • Periodic auto-commit every 5th turn for crash resilience (#c6caccc)

  • Scratch note lifecycle — session IDs, date sections, active/done/parked status, router capabilities, auto-inject (#0d364f2)

  • Statusline shows session ID on line 2 (#d474cbf)

  • Polyglot script discovery — .sh, .py, .ts, .js, .mjs (#1acb8c2)

Changed

  • Auto-breathe rotation now writes .rotate-signal and calls ctx.shutdown() immediately when preload already exists — no more waiting for turn_end that may not fire (#378a1b1)
  • Preload filenames use sNN iterating pattern (was static session ID suffix) to prevent overwrites within a session (#378a1b1)
  • Self-awareness protocols consolidated — 5 redundant protocols became configuration guides (#b70ca44)
  • /scratch extracted to standalone soma-scratch.ts extension (#932f446)
  • Shared helpers extracted to utils.ts — deduplication across core modules (#2dbea9a, #3d8467e)
  • Unified rotation through /inhale, removed /auto-continue (#7b7ba52)
  • Changelog pipeline switched to Ghostty-style commit-driven entries (#ec27a11)
  • pattern-evolution protocol updated with identity maturation layer; working-style with tool-awareness (#5e4219d)
  • Dev hooks generated locally by soma-dev.sh, not committed to repo (#efc6ed4)

Fixed

  • help header shows ‘CLI v…’ not bare version

  • help rewrite, script theme crash, focus session, postinstall, docs

  • restore walk-up, keep .soma-only + runtime-home skip

  • findSomaDir checks current dir only, no walk-up

  • only .soma/ is a valid soma root, not .claude/ or .cursor/

  • skip global runtime home in findSomaDir walk-up

  • defensive settings.heat access + stale test mocks — 567/567 pass

  • 5 UX gaps — smart warnings, resume awareness, write heuristic

  • Muscle and automation discovery — filter archived status and README files (#e42da9b, #5f5ccae)

  • Scratch completions — remove PRO commands from free completions list (#fd0bda2)

  • Auto-breathe race condition — sendUserMessage from before_agent_start raced with Pi’s prompt processing, now deferred to agent_end via pending message queue (#2823ee9, #927bd74)

  • Auto-breathe phase 1 ignored by agent — wrap-up trigger now sends a followUp user message, not just system prompt + UI toast (#9d09dd5)

  • Auto-breathe triple notification spam reduced (#927bd74)

  • Session management — /inhale reset, heat dedup on rotation (#044fb2c)

  • Dev-only scripts no longer shipped to users (#2c8db4a)

  • Restart signal cleared at factory load time, not session_start (#0bddce2)

  • Dynamic muscle read and script execution detection for heat tracking (#99a7663)

  • soma-route.ts import path — uses @earendil-works/pi-coding-agent, not @anthropic-ai/claude-code (#49454ea)

  • Internal protocols (content-triage, community-safe) removed from bundled set (#3ad0884)

  • Auto-init .soma/.git when autoCommit is true (#276f6f2)

  • Missing TL;DRs on 4 self-awareness protocols (#c457752)

  • sync-to-cli path after _dev/ directory move (#46615ef)

  • Grace countdown skips tool turns during auto-breathe — tool-call turns no longer count toward 6-turn limit (#53bd421)

  • Resume without fingerprint sends minimal boot instead of full redundant injection — saves ~4-6k tokens (#7fd064b)

  • Preload overwrite guard + auto-breathe rotation fix when preload pre-exists (#378a1b1)

  • All doc paths updated to amps/ layout — .soma/amps/protocols/, .soma/amps/muscles/, etc. (#420f19b)

  • Memory layout docs rewritten — core structure is amps/, memory/, projects/, skills/ (#b35c2be)


[0.5.0] — 2026-03-12

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.

  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.

  • soma-workspace-migrate-legacy.sh — lazy migration W2 of plan 02 (s01-680a9c, preload #3) — walks ~/.soma/plugins/<type>/state.json and copies each into ~/.soma/workspaces/__legacy__/<type>/<type>-1.json + registers in ~/.soma/workspaces/__legacy__/panes.json. Idempotent (re-run skips already-registered instances). Skips leading-underscore types (_test, _regression_test) by default. Preserves old paths for one release cycle as fallback. Per 02-workspace-pane-config.md § Migration W2 (lazy) and ~/.soma/workspaces/README.md. Smoke-verified end-to-end against a tmp clone of ~/.soma/plugins/: 8 panes migrated, registry built with types/paths/timestamps/provenance markers, re-run skipped all 8.

  • rewrite DNA.md — self-awareness, owner’s manual, link to docs for deep reference

  • /inhale guard + stale warning, slash command usage hints

  • prompt before auto-init + parent inheritance (SX-164, SX-165, SX-241)

  • show command provenance in /soma status (SX-233)

  • track cli.js as source in agent repo (SX-252)

  • settings-driven heat overrides — per-project AMPS control

  • inherit.automations — separate from tools inheritance

  • statusline preload indicator + smart /exhale (edit vs write)

  • auto-archive stale preloads after exhale + archiveStalePreloads()

  • Auto-breathe mode — proactive context management that triggers wrap-up at configurable %, auto-rotates at higher %. Safety net at 85% always on. Opt-in via breathe.auto in settings (#1d533bf)

  • /auto-breathe command — runtime toggle (on|off|status), persists to settings.json

  • Smarter /breathe — context-aware instructions (light/full/urgent), handles preload-already-written and timeout edge cases

  • Cold-start muscle boost — muscles created <48h get +3 effective heat for at least 2 sessions

  • Orient-from preloads — preload template includes ## Orient From pointing to files next session should read first

  • soma:recall event signal — extensions can listen for context pressure events (steno integration)

  • /auto-commit command — toggle .soma/ auto-commit on exhale/breathe (on|off|status)

  • Auto-commit .soma/ state — changes committed to local git on every exhale/breathe via checkpoints.soma.autoCommit

  • /pin and /kill invalidate prompt cache — heat changes take effect next turn, not next session

  • /soma prompt diagnostic — shows compiled sections, identity status, heat levels, context %, runtime state

  • sync-to-cli.sh and sync-to-website.sh — one-command repo sync scripts

  • soma-compat.sh — detect protocol/muscle overlap, redundancy, directive conflicts

  • soma-update-check.sh — compare local protocol/muscle versions against hub

  • /scratch command — quick notes to .soma/scratchpad.md, append-only, agent doesn’t see unless /scratch read

  • guard.bashCommands setting — allow/warn/block for dangerous bash command prompts

  • Automations system — .soma/automations/ for step-by-step procedural flows

  • Polyglot script discovery — boot discovers .sh, .py, .ts, .js, .mjs scripts with auto-extracted descriptions

  • soma init --orphan--orphan/-o flag for clean child projects with zero parent inheritance

  • Git hooks: post-commit auto-changelog + pre-push docs-drift nudge

  • Bundled protocols: correction-capture + detection-triggers — learning-agent protocols

Changed

  • Config-first script extensions — settings.scripts.extensions controls which file types are discovered
  • Command cleanup — removed /flush, folded /preload into /soma preload and /debug into /soma debug
  • CI improvements — PR check and release workflows now run all test suites

Fixed

  • help header shows ‘CLI v…’ not bare version

  • help rewrite, script theme crash, focus session, postinstall, docs

  • restore walk-up, keep .soma-only + runtime-home skip

  • findSomaDir checks current dir only, no walk-up

  • only .soma/ is a valid soma root, not .claude/ or .cursor/

  • skip global runtime home in findSomaDir walk-up

  • defensive settings.heat access + stale test mocks — 567/567 pass

  • 5 UX gaps — smart warnings, resume awareness, write heuristic

  • System prompt dropped after turn 1 — Pi resets each before_agent_start, now caches compiled prompt

  • Identity never in compiled prompt — isPiDefaultPrompt() checked wrong string

  • Context warnings never fired — getContextUsage() returns undefined on turn 1, handled gracefully

  • Identity lost after /auto-continue or /breathesession_switch now rebuilds from chain

  • Guard false positive on 2>/dev/null — stderr redirects no longer trigger write warnings

  • Bash guard false positive on >> — append redirects no longer trigger dangerous redirect guard

  • Preload auto-injected on continue/resume — soma -c and soma -r no longer inject stale preloads

  • /soma prompt crash — getProtocolHeat import missing

  • Audit false positives — all 11 audit scripts improved across the board


[0.4.0] — 2026-03-11

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.

  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.

  • soma-workspace-migrate-legacy.sh — lazy migration W2 of plan 02 (s01-680a9c, preload #3) — walks ~/.soma/plugins/<type>/state.json and copies each into ~/.soma/workspaces/__legacy__/<type>/<type>-1.json + registers in ~/.soma/workspaces/__legacy__/panes.json. Idempotent (re-run skips already-registered instances). Skips leading-underscore types (_test, _regression_test) by default. Preserves old paths for one release cycle as fallback. Per 02-workspace-pane-config.md § Migration W2 (lazy) and ~/.soma/workspaces/README.md. Smoke-verified end-to-end against a tmp clone of ~/.soma/plugins/: 8 panes migrated, registry built with types/paths/timestamps/provenance markers, re-run skipped all 8.

  • rewrite DNA.md — self-awareness, owner’s manual, link to docs for deep reference

  • /inhale guard + stale warning, slash command usage hints

  • prompt before auto-init + parent inheritance (SX-164, SX-165, SX-241)

  • show command provenance in /soma status (SX-233)

  • track cli.js as source in agent repo (SX-252)

  • settings-driven heat overrides — per-project AMPS control

  • inherit.automations — separate from tools inheritance

  • statusline preload indicator + smart /exhale (edit vs write)

  • auto-archive stale preloads after exhale + archiveStalePreloads()

  • Compiled system prompt (“Frontal Cortex”) — core/prompt.ts assembles complete system prompt from identity chain, protocol summaries, muscle digests, dynamic tool section

  • Session-scoped preloads — preload-<sessionId>.md prevents multi-terminal conflicts

  • Identity in system prompt — moved from boot user message for better token caching

  • Parent-child inheritance — inherit: { identity, protocols, muscles, tools } in settings

  • Persona support — persona: { name, emoji, icon } for named agent instances

  • Smart init — detectProjectContext() scans for parent .soma/, CLAUDE.md, project signals

  • systemPrompt settings — toggle docs, guard, CLAUDE.md awareness in system prompt assembly

  • prompts/system-core.md — static behavioral DNA skeleton

  • Debug mode — .soma/debug/ logging, /soma debug on|off

  • Protocol graduation — heat decay floor, frontmatter enforcement, preload quality validation

  • Configurable boot sequence — settings.boot.steps array

  • Git context on boot — git-context step injects recent commits and changed files

  • Configurable context warnings — settings.context thresholds

Changed

  • Extension ownership refactor — soma-boot.ts owns lifecycle + commands, soma-statusline.ts owns rendering + keepalive
  • Boot user message trimmed — identity, protocol breadcrumbs, and muscle digests moved to system prompt
  • CLAUDE.md awareness, not adoption — system prompt notes existence but doesn’t inject content

Fixed

  • help header shows ‘CLI v…’ not bare version

  • help rewrite, script theme crash, focus session, postinstall, docs

  • restore walk-up, keep .soma-only + runtime-home skip

  • findSomaDir checks current dir only, no walk-up

  • only .soma/ is a valid soma root, not .claude/ or .cursor/

  • skip global runtime home in findSomaDir walk-up

  • defensive settings.heat access + stale test mocks — 567/567 pass

  • 5 UX gaps — smart warnings, resume awareness, write heuristic

  • Print-mode race condition — ctx.hasUI guard on sendUserMessage in session_start

  • Skip scaffolding core extensions into project .soma/extensions/

  • Template placeholder substitution on install


[0.3.0] — 2026-03-10

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.

  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.

  • soma-workspace-migrate-legacy.sh — lazy migration W2 of plan 02 (s01-680a9c, preload #3) — walks ~/.soma/plugins/<type>/state.json and copies each into ~/.soma/workspaces/__legacy__/<type>/<type>-1.json + registers in ~/.soma/workspaces/__legacy__/panes.json. Idempotent (re-run skips already-registered instances). Skips leading-underscore types (_test, _regression_test) by default. Preserves old paths for one release cycle as fallback. Per 02-workspace-pane-config.md § Migration W2 (lazy) and ~/.soma/workspaces/README.md. Smoke-verified end-to-end against a tmp clone of ~/.soma/plugins/: 8 panes migrated, registry built with types/paths/timestamps/provenance markers, re-run skipped all 8.

  • rewrite DNA.md — self-awareness, owner’s manual, link to docs for deep reference

  • /inhale guard + stale warning, slash command usage hints

  • prompt before auto-init + parent inheritance (SX-164, SX-165, SX-241)

  • show command provenance in /soma status (SX-233)

  • track cli.js as source in agent repo (SX-252)

  • settings-driven heat overrides — per-project AMPS control

  • inherit.automations — separate from tools inheritance

  • statusline preload indicator + smart /exhale (edit vs write)

  • auto-archive stale preloads after exhale + archiveStalePreloads()

  • AMPS content type system — 4 shareable types: Automations, Muscles, Protocols, Skills. scope field controls distribution

  • Hub commands — /install <type> <name>, /list local|remote with dependency resolution

  • core/content-cli.ts — non-interactive content commands for CLI wiring

  • core/install.ts — hub content installation with dependency resolution

  • core/prompt.ts — compiled system prompt assembly (12th core module)

  • soma-guard.ts extension — safe file operation enforcement with /guard-status command

  • soma-audit.sh — ecosystem health check orchestrating 11 focused audits

  • /rest command — disable cache keepalive + exhale

  • /keepalive command — toggle cache keepalive on/off/status

  • Cache keepalive system — 300s TTL, 45s threshold, 30s cooldown

  • Session checkpoints — .soma/ committed every exhale (local git)

  • 10 test suites with 255 passing tests

  • Workspace scripts — soma-scan.sh, soma-search.sh, soma-snapshot.sh, soma-tldr.sh

Changed

  • Bundled protocols slimmed from all to 4 core (breath-cycle, heat-tracking, session-checkpoints, pattern-evolution)

Fixed

  • help header shows ‘CLI v…’ not bare version

  • help rewrite, script theme crash, focus session, postinstall, docs

  • restore walk-up, keep .soma-only + runtime-home skip

  • findSomaDir checks current dir only, no walk-up

  • only .soma/ is a valid soma root, not .claude/ or .cursor/

  • skip global runtime home in findSomaDir walk-up

  • defensive settings.heat access + stale test mocks — 567/567 pass

  • 5 UX gaps — smart warnings, resume awareness, write heuristic

  • PII scrubbed from git history across all repos

  • CLI stripped to distribution only — agent is source of truth


[0.2.0] — 2026-03-09

Added

  • System prompt budget guardrail — maxTokens: 17000 (s01-639c5f). Project-level setting warns when compiled prompt exceeds 17K tokens, enforcing lean-body discipline.

  • State-disk sync muscle (s01-639c5f). Documents the state.json drift pattern — when files are moved to _archive/ or deleted, JSON entries persist as ghosts. Proposed boot-time fix: prune entries for non-existent files during discovery.

  • soma-workspace-migrate-legacy.sh — lazy migration W2 of plan 02 (s01-680a9c, preload #3) — walks ~/.soma/plugins/<type>/state.json and copies each into ~/.soma/workspaces/__legacy__/<type>/<type>-1.json + registers in ~/.soma/workspaces/__legacy__/panes.json. Idempotent (re-run skips already-registered instances). Skips leading-underscore types (_test, _regression_test) by default. Preserves old paths for one release cycle as fallback. Per 02-workspace-pane-config.md § Migration W2 (lazy) and ~/.soma/workspaces/README.md. Smoke-verified end-to-end against a tmp clone of ~/.soma/plugins/: 8 panes migrated, registry built with types/paths/timestamps/provenance markers, re-run skipped all 8.

  • rewrite DNA.md — self-awareness, owner’s manual, link to docs for deep reference

  • /inhale guard + stale warning, slash command usage hints

  • prompt before auto-init + parent inheritance (SX-164, SX-165, SX-241)

  • show command provenance in /soma status (SX-233)

  • track cli.js as source in agent repo (SX-252)

  • settings-driven heat overrides — per-project AMPS control

  • inherit.automations — separate from tools inheritance

  • statusline preload indicator + smart /exhale (edit vs write)

  • auto-archive stale preloads after exhale + archiveStalePreloads()

  • Protocols and Heat System — behavioral rules loaded by temperature, heat rises through use, decays through neglect

  • Muscle loading at boot — sorted by heat, loaded within configurable token budget

  • Settings chain — settings.json with resolution: project → parent → global

  • Mid-session heat tracking — auto-detects protocol usage from tool results

  • Domain scoping — applies-to frontmatter + detectProjectSignals()

  • Breath cycle commands — /exhale, /inhale, /pin, /kill

  • Script awareness — boot surfaces .soma/scripts/ inventory

  • 9 core modules — discovery, identity, protocols, muscles, settings, init, preload, utils, index

Fixed

  • help header shows ‘CLI v…’ not bare version

  • help rewrite, script theme crash, focus session, postinstall, docs

  • restore walk-up, keep .soma-only + runtime-home skip

  • findSomaDir checks current dir only, no walk-up

  • only .soma/ is a valid soma root, not .claude/ or .cursor/

  • skip global runtime home in findSomaDir walk-up

  • defensive settings.heat access + stale test mocks — 567/567 pass

  • 5 UX gaps — smart warnings, resume awareness, write heuristic

  • Extensions load correctly

  • Skills install to correct path


[0.1.0] — 2026-03-08

Born

  • σῶμα (sōma) — Greek for “body.” The vessel that grows around you.
  • Built on Pi with piConfig.configDir: ".soma"
  • Identity system: .soma/identity.md — discovered, not configured
  • Memory structure: .soma/memory/ — muscles, sessions, preloads
  • Breath cycle concept: sessions exhale what was learned, next session inhales it
  • 9 core modules, 4 extensions, logo through 36 SVG iterations