Skip to content

What's New for Soma

Agent-facing changelog: 'what NEW capabilities can I use, with just enough detail to use them.' Distinct from the technical CHANGELOG.md — this is action-oriented, dense, version-tagged, and tells YOU (the agent) which tools just landed and how to invoke them.

Read this when you wake up in a session that just ran soma update, or when starting fresh after a release. Each section is a version’s agent-actionable surface: NEW caps you can call, behavior changes you should know, bugs you can stop stepping around. Not the technical commit log — that’s CHANGELOG.md. This is the answer to “what can I do now that I couldn’t yesterday?”.


How to read this

Each version section follows the same shape:

  • 🆕 New caps — agent-callable surfaces with one-line invocation hints. Format: cap_name(args) → outcome.
  • 🔄 Behavior changes — defaults flipped, conventions shifted. What you did yesterday may now be wrong.
  • 🐛 Bugs you can stop stepping around — known issues that are now closed.
  • 📁 New files / locations — useful paths the runtime now writes/reads.
  • 🧰 Workflows — new patterns worth muscle memory.

A [dev] tag = dev install only (build-excluded from soma-beta end-user tarball).


v0.42.1 — July 2026

🐛 Bugs you can stop stepping around

  • soma:browser.render with format:'markdown' and no selector now actually converts. It was silently reading document.body.innerText (plain rendered text, no HTML) instead of outerHTML, so the converter had nothing to clean — every real-world call reported format:"markdown" while returning near-0% “reduction” and full page chrome. Fixed; verified live (89050 → 13215 chars, −85.2%, real content preserved, nav/footer gone). A page’s own in-content <header>/<nav> (an article’s title + breadcrumbs) also survives now instead of being stripped identically to global site chrome.
  • A claude-cli/* role’s max-cost-usd budget is now actually enforced. It read the wrong frontmatter key and had two separate falsy-zero bugs that silently turned an explicit 0 into “no cap.” If your role declares a real number, it’s held to it now — including a genuine 0 hard cap (never draw billed overage). Only applies to default-model: claude-cli/*; every other backend (mistral/groq/cohere) still has no dollar-cost enforcement, only max-tool-calls.

📁 New files / locations

  • _boot.md shows a last-session/last-reflection breadcrumb ({{last_session_ref}} / {{last_mlx_ref}}) on a fresh boot with no preload loaded — a pointer to what’s still on disk, not a summary. Zero-cost on a brand-new project with no memory/ history yet.

v0.42.0 — July 2026

🆕 New caps

soma:agent.claude — delegate through a FILE contract, no ARG_MAX ceiling

soma:agent.claude({task:'...', role?:'general', model?:'sonnet', maxBudgetUsd?:3})
  → runId + tmux session + contract/report/log paths
soma:agent.claude_harvest({runDir})   → the child's report, or not-finished

delegate passes the compiled prompt as a claude -p ARGUMENT, so a large role + task can exceed ARG_MAX and fail. This writes the contract to a file and hands the child a tiny instruction to read it. Always background (tmux). Use delegate normally; reach for this when the prompt is large, or when delegate already failed on argument length. Poll claude_harvest rather than attaching to tmux.

🔄 Behavior changes

  • Role frontmatter is parsed by real YAML now (Pi’s parseFrontmatter). It is STRICT: an unquoted value containing ": " becomes a mapping, and one containing " #" truncates at the comment. If a role errors or a value arrives half-length, quote it — 7 bundled roles needed exactly that. The previous hand-rolled parser accepted both and was silently masking them.
  • context: in a role’s frontmatter actually stacks now. It shipped inert: the parser’s promotion allowlist omitted the key, so declared files rendered as "(none)". Declared muscles/docs now arrive as <context_file path=...> blocks. A child spawned from a session older than this change still gets the old compiler — reload for it to take effect.
  • The shipped harness asks you to cite only from files you have OPEN. Naming a doc as support asserts you read it this session; a routing table says which file owns a fact, never what the fact is.

🐛 Bugs you can stop stepping around

  • soma-dev sync dev / sync main now actually write STATE.md’s activity log (all writers were broken; on a default install none had ever appended a row) — and they assert the row arrived, not just exit 0.
  • dist/.dev-synced carries provenance (branch@sha, version, piVersion, timestamp) instead of being a zero-byte flag; soma-dev switch status prints it and states that the git ref describes the CHECKOUT, not the dist.

v0.41.2 — July 2026

Maintenance release. Nothing to try.

No user-facing change shipped in this one, and it is listed here only so the trail has no gap. The single code addition was an internal delegation backend whose capability was never registered — unreachable, so there was nothing a user could call. It became reachable in a later release and is documented there.

These notes were written retroactively: the release originally shipped with no narrative at all, because the changelog-promotion step matched on a heading format that had since changed, found nothing, and exited reporting success. Both the match and the silent success are fixed.


v0.41.1 — July 2026

🐛 Fixes

  • Leanstral models no longer error when reasoning is on. labs-leanstral-* were sending a reasoning flag the Mistral API rejects outright (400 code 3051); they now send the field the API actually expects.
  • The runtime no longer breaks after a Pi version bump. Syncing a bump that changed package.json skipped reinstalling dependencies, so a newly-built runtime could run against the previous version’s modules and crash at boot. The sync now reinstalls before rebuilding.

v0.41.0 — July 2026

🆕 Delegation goes multi-model

Child roles are no longer pinned to a single Claude model. A role can declare a chain — an ordered list of models with a cost class — and delegation walks it, falling through to the next entry when one is unavailable. In practice that means a cheap model does the routine pass and a capable one is reached for only when the work needs it.

default-model: claude-cli/haiku
model-chain:
  - id: claude-cli/haiku
    class: cheap
  - id: claude-cli/sonnet
    class: coding

🔄 Behavior changes

  • Child defaults moved to the free tier. New child templates no longer default to a paid model. Existing roles that name their own default-model are unaffected.
  • Pi runtime 0.80.6 → 0.80.10.

🐛 Fixes

  • /body stopped crying wolf. Unreferenced body files used to emit one warning each; they now collapse into a single line.
  • Large delegate prompts no longer fail on argument length. The compiled role prompt is written to a file instead of passed as a command-line argument, so prompt size no longer has a ceiling.

v0.40.0 — July 2026

🆕 You can see, and scope, which models are available

soma:agent.models            → live catalog, honouring settings.json scoping
soma:extensions.search       → search pi.dev packages
soma:extensions.show         → inspect one before installing
soma install npm:<pkg>       → install through Pi's own package manager

The delegate model catalog is now built at call time from the live registry rather than a hardcoded list, so a provider you have configured shows up without a code change. {{enabled_models}} and {{active_extensions}} are available as template variables, so a prompt can state what this install actually has rather than what it assumed.

🔄 Behavior changes

  • A budget guardrail on the system prompt — systemPrompt.maxTokens. Compiling a prompt over the configured budget warns rather than failing, so a body grows lean by decision rather than by accident. Check yours with soma:body.slots.

v0.39.0 — July 2026

🆕 New caps

soma:refdocs.* — external platform docs (BUNDLED)

soma:refdocs.find({query:'cloudflare'})        → {baseUrl, method, pageCount, pages}
soma:refdocs.tree({query:'react'})              → {pageCount, tree} (section-organized)
soma:refdocs.fetch({query:'cloudflare', topic:'durable objects'}) → {matches, pages: [{content}]}
soma:refdocs.download({query:'cloudflare', topic:'workers', depth:5}) → writes to .soma/refdocs/<name>/
  Flags: output:'/path' (custom dir), output:false (inline JSON), all:true (full download)

Discovers docs via llms.txt convention (Cloudflare, Vercel, React, Mintlify, 25+ known domains). Falls back to HTML scraping. Fetches pages as clean markdown via Accept: text/markdown. Use BEFORE researching any third-party platform docs.

soma:cf-docs.* — Cloudflare docs (HUB, soma install soma-cf-docs)

soma:cf-docs.index({product:'workers'})  → {product, pages, count}
soma:cf-docs.read({url:'/containers/'})   → {title, url, content}
soma:cf-docs.query({product:'containers', topic:'outbound traffic'}) → {matches, pages}

CF-specific, no API key needed.

🔄 Behavior changes

  • Pi runtime bumped to 0.80.6max thinking level available. showCacheMissNotices toggle (complementary to our predictive cache TTL in the statusline). New extension hooks: agent_settled, before_provider_headers. pi config -l for project-local config.
  • Freebuff harness uses JSON extraction — reads chat-messages.json instead of scraping tmux capture-pane. Multi-paragraph + table responses now reliable. TUI parsing is fallback.

📁 New files / locations

  • .soma/refdocs/<name>/ — auto-created by refdocs.download, organized by section with index.md
  • ~/.soma/agent/scripts/dev-only/soma-freebuff.{sh,py} — $0 AI model harness (6 free models)

🧰 Workflows

  • $0 delegation: write spec → hand to freebuff (~/.soma/agent/scripts/dev-only/soma-freebuff.sh ask) → gate → commit. Six free models. Same pattern as soma:agent.delegate but costs nothing.
  • Pi bump TUI smoke: after bumping Pi, boot with a free model in tmux to catch import errors and duplicate declarations that build+tests+sandbox miss. soma --model opencode/deepseek-v4-flash-free

v0.38.0 — June 2026

🆕 New caps

soma:caselaw.* — Caselaw Researcher cap family.

🐛 Bugs you can stop stepping around

  • Script subcommands get clean userArgs, not injected argv. A subcommand no longer inherits arguments meant for the wrapper — if you passed flags and the script saw extra ones, that was this.
  • Browser-driving caps are serialized. Two browser caps in flight at once raced each other; they now queue. Symptom was an operation returning another call’s page.

v0.37.1 — June 2026

🐛 Bugs you can stop stepping around

  • Exiting a session no longer garbles your shell. Two soma-driven exits left the terminal in a bad state. If you were reflexively running reset after quitting — stop, it’s fixed.

v0.37.0 — June 2026

🔄 Behavior changes

  • The system prompt split along a scaffold-vs-behavior line. prompts/system-core.md holds what is always true of Soma; your body files hold what is true of you. Why you care: editing your body no longer risks clobbering framework scaffolding, and core updates arrive without touching your files.
  • template-migration plumbing for core_rules.md and _protocol-template.md.

🆕 New caps

soma:browser.render — render a JS-heavy / SPA page in an ephemeral tab and return its text. Use when fetch returns an empty shell because the content is client-rendered.


v0.36.0 — June 2026

🔄 Behavior changes

  • The always-loaded core was restructured and sharpened — shorter, and generally useful to every install rather than shaped by one workspace’s habits.
  • The prompt now states the .soma/ layout rule and that .soma/ commits itself. Two recurring confusions — “where does this file go?” and “do I git add .soma?” — are answered in the prompt instead of being re-derived per session. You do not commit .soma/; it checkpoints itself.
  • Prompt refined from corpus mining of the two most-recurring anti-patterns across real sessions.

v0.35.0 — June 2026

🐛 Bugs you can stop stepping around

  • Opus Edit mis-shape is coerced, not rejected. A crammed second oldText2/newText2 pair used to fail the whole edit; it is now folded into a normal edit.
  • /inhale no longer crashes the TUI. The error-sanitizer import is prepended and fails loud rather than silently producing a broken module.

🔄 Behavior changes

  • Body templates lead with “ground before think.” soul.md and core_rules.md now open with the discipline of checking an artifact before reasoning about it.
  • headless is documented as the reliable delegation mode. If background children were behaving unpredictably, this is the mode to use.

v0.34.0 — June 2026

🆕 New caps

  • soma:inbox.list({status?}) → list markdown-inbox letters (default unread; 'all' for every status). Each entry shows the filename to act on.
  • soma:inbox.read({file}) → mark a letter read once you’ve read it, so it stops surfacing at boot.
  • soma:inbox.actioned({file}) → mark a letter actioned (read AND acted on — e.g. shipped the fix it reported).
  • soma:inbox.archive({file}) → move a processed letter to inbox/_archive/.
  • file = filename, slug, or unique partial; ambiguous refs list their candidates. Resolves the .soma/ chain, so a parent-inbox letter is clearable from a child project.

🧰 Workflows

  • Close the inbox loop. The inbox-handling muscle always required marking letters read — now there’s a tool instead of hand-editing frontmatter. Read a letter → soma:inbox.read/.actioned/.archive. The boot summary now shows what’s actually pending instead of piling up.

🐛 Bugs you can stop stepping around

  • Exhale no longer crashes in an uninitialized directory. Ending a session where the local .soma/ didn’t exist threw ENOENT from saveProtocolState and aborted the whole save — it now creates the directory first.

v0.27.2 — May 2026

The soma:seam.* family lands — archaeology caps for tracing concepts through your own writings.

🆕 New — shared preload lifecycle (cycle 29)

Preload state tracking across /exhale, /breathe, auto-rotation, and keepalive auto-exhale is now unified into a single shared state machine (extensions/_shared/preload-lifecycle.ts). Four states: UNREQUESTEDREQUESTEDSAVEDSTALE. Three route caps for read/write/reset.

What changed:

  • /exhale at high context (85%+) no longer causes the safety net to override and rotate immediately. The exhale handler signals REQUESTED → safety net defers.
  • Keepalive exhaustion no longer double-requests a preload if one is already in flight.
  • Statusline’s 📝saved / 📝stale indicator now reads from the same state as the breathe extension — no drift.
  • 7 local let flags removed from soma-breathe.ts.

Route caps: preload:lifecycle, preload:transition, preload:reset, preload:noteToolCall.

Detail: .soma/cycles/audit-improve/29-preload-lifecycle/cycle.md

🆕 New caps

  • soma:seam.trace — walk a concept across docs + code + sessions + blog + kanban + soul-space. Use BEFORE raw grep for any “where did X come from?” question. args: {term, limit?:200}. Free tier.
  • soma:seam.ancestors — trace a concept through vault agents + Pi sessions + Claude sessions, with agent attribution. Returns who-said-what-and-when across the lineage. Closure test: seam.ancestors "breathe" returns Zenith (openclaw-dev) — soma's daddy. args: {term, limit?:200}. PRO feature (wraps _pro/soma-seam.sh).
  • soma:seam.timeline — chronological evolution of a concept. Optional tag filter. args: {tag?, limit?:300}. PRO.
  • soma:seam.sessions — search .soma/memory/sessions/ + preloads + ~/.pi/agent/sessions/ JSONLs. args: {query, limit?:200}. Dev tree only.
  • soma:seam.seeds — forward pointers (frontmatter seeds: field). {unplanted: true} for ones not yet referenced. args: {unplanted?:bool}. PRO.
  • soma:seam.gaps — orphan documents (no inbound refs). Hygiene scan. No args. PRO.
  • soma:seam.webPERSISTENT — writes markdown trace to .soma/memory/webs/web-<term>-<date>.md. Becomes a memory artifact next-self can read without re-running. args: {term, output?:path}. PRO.
  • soma:seam.stats — Pi JSONL session analytics: tool usage, errors, interrupts. args: {mode?, limit?:200}. Dev tree only.
  • soma:docs.related — frontmatter graph walk from a file (forward + back refs via related:, seams:, seeds:). args: {file}. Dev tree only.
  • soma:docs.impact — what docs/protocols/muscles reference this file? Run BEFORE renaming or deleting a doc. args: {file}. Dev tree only.

🧰 New workflow: reach for seam before grep

When the question shape is “where did X come from?” / “who said X?” / “when did X evolve?” — the seam family beats raw grep + find every time. PRO caps fail gracefully on free tier with a “PRO feature” message; dev-tree caps fail gracefully on user installs. Caps live in the route registry — zero cache cost at register-time.

Tier breakdown:

  • Free tier (everyone): seam.trace (wraps amps/scripts/soma-trace.sh).
  • PRO tier (soma-beta tarball): seam.ancestors, seam.timeline, seam.seeds, seam.gaps, seam.web.
  • Dev tree only (internal): seam.sessions, seam.stats, docs.related, docs.impact.

📁 New files / locations

  • extensions/_shared/script-resolver.ts — shared helper for addons that wrap shell scripts. Path resolution + subprocess + graceful fallback messages.
  • extensions/soma-addons/seam.ts — the new family.
  • .soma/memory/webs/ — where seam.web persists trace artifacts.

Detail: .soma/releases/v0.27.x/plans/seam-addon-family.md.


v0.27.1 — May 2026

The “first end-to-end autonomous PR ship” patch. Cycles 16 + 17 land together: Sonnet’s long-context wall now triggers warn/exhale BEFORE the wall hits, /inhale no longer double-injects preload, and release-please becomes the canonical ship pipeline.

🆕 New caps & workflows

  • soma-dev delegate cycle <brief> — full implementation pipeline for any markdown brief (cycle.md, inbox/.md, plans/.md). Pipeline: intern (investigate, 80-call) → intern (build, 80-call) → verifier (25-call) → pr_author (30-call). 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. Use this when builder’s 25-call default is too small for a multi-step cycle.
  • /auto-breathe model-aware — NEW subcommand. The auto-breathe enum is now tri-state: off / global / model-aware. model-aware reads ctx.model.id and selects per-glob thresholds from breathe.thresholds map. Default install ships model-aware. Backward-compat: boolean still parses (true → “global”, false → “off”) via migration breathe-tri-state-v0.27.0.
  • tokens_input now includes cache_read in runDelegation() results. Previously reported only the uncached delta (showing tokens_input: 3 for repeated calls with stable prefix). New fields: tokens_input_uncached + tokens_input_cached for transparency. Was NOT a delegation-degraded bug — was a metric-display bug. The model received the full prompt all along.
  • route.provide("preload:wasInjected", ...) — new route cap exposing whether session_start’s “new”/“resume” branch already injected the preload. /inhale post-await queries this and skips its own send if true. Available cycle-17+.

🔄 Behavior changes

  • Sonnet thresholds: model-aware default for *sonnet* is warnRange [28,33] / exhaleRange [34,50] — fires BEFORE the empirical ~48% “extra usage required for long context” wall. Opus: [60,74] / [75,90]. Default fallback: [50,64] / [65,85]. If you’re on Sonnet and were used to 50/70 thresholds, you’ll see notifications much earlier now — by design.
  • /inhale no longer produces double preload in rotated sessions. Previously, every /inhale triggered TWO preload-injection user messages ([Soma Boot — rotated session] from session_start + [Soma Inhale — Loading Preload] from /inhale post-await). ~8K tokens duplicated per rotation, verified across 10 sessions. Now: single inject from session_start, /inhale skips when wasInjected=true. Print-mode safety preserved (when ctx.hasUI=false, /inhale falls back to direct send).
  • Auto-breathe notify text changed: 🪵 Auto-breathe: rotating at N%🪵 Preload requested at N% — rotating after agent writes it. Honest about the request-vs-rotation distinction. Other branch (preload-already-written, immediate .rotate-signal) keeps Rotating — preload already written.
  • soma-release-ship.sh now bumps .github/.release-please-manifest.json in lockstep with package.json. Without this, release-please’s view of “current version” stays stuck and the next push to dev files a confused PR (caught when v0.27.0 ship left manifest at 0.26.2 → release-please filed PR #18 “release 0.26.3” with conflicts everywhere).
  • Catch-block fallback in /inhale is race-safe: the previous catch (err) block always sent the fallback preload regardless of state. Now checks route.get("preload:wasInjected") — if session_start already injected (rare race where newSession() throws AFTER emitting), catch suppresses its send.

🤖 Release flow now PR-driven (canonical)

PRIMARY (cycle-17, v0.27.1+): Push commits to dev with conventional-commit messages (feat:, fix:, chore:, etc.) → release-please GHA auto-files release PR with versioned CHANGELOG → review + amend the PR (move rich [Unreleased] narratives into [X.Y.Z] if release-please’s auto-bullets are too thin) → merge → build dist + publish draft GH release + npm publish + force-push main + rsync.

FALLBACK (high-stakes): soma-release-prepare.sh (10 checklog gates) → soma-release-ship.sh. Use for major bumps, breaking changes, or mid-flight rescues. Both flows now bump the manifest in lockstep.

🐛 Bugs you can stop stepping around

  • pr-check.yml silent test-failure — GHA’s bash -e {0} shell exited the test loop on the first failing test BEFORE logging which one. Now uses set +e inside the loop + captures failed names + logs them at the end.
  • In-flight detection robustness — 4 tests had brittle chore(release): vX.Y.Z regex that broke on release-please’s chore(dev): release X.Y.Z format AND on amendment commits. Switched to NO-TAG-YET detection (if package.json bumped to vX.Y.Z but no git tag v$PKG_VERSION exists, we're in-flight). Robust against ALL release-commit shapes.
  • test-preload-notify-state-machine runtime-mirror gate failed on CI runners (no ~/.soma/agent install dir). Now skips on CI=true OR when install dir absent.
  • Release-please Summarize step bash-escape — the PR JSON output contains parens (v0.27.0...v0.27.1) which broke echo "... ${{ steps.release.outputs.pr }}" interpolation. Moved interpolation to env block.

📁 New files / locations

  • .soma/cycles/audit-improve/16-model-aware-breathe-collapse/cycle.md — full plan for tri-state + per-model thresholds.
  • .soma/cycles/audit-improve/17-rotation-mechanism-repair/cycle.md — 5-bug rotation-mechanism audit + fixes.
  • migrations/phases/v0.26.2-to-v0.27.0.md — the breathe-tri-state migration journal.
  • 5 new test files: test-breathe-tri-state.sh, test-breathe-migration.sh, test-breathe-model-thresholds.sh, test-breathe-warn-range.sh, test-breathe-exhale-once.sh. 81 new test cases covering the tri-state + per-model paths.

🧠 Architecture notes worth knowing

  • {{skills_block}} is a transplant, not a duplicate. core/body.ts:775 extracts <available_skills>...</available_skills> from Pi’s compiled prompt, then re-injects it into soma’s templated prompt via the {{skills_block}} slot. Soma’s compiled output FULLY REPLACES Pi’s prompt (when Pi’s is the default-shape — the normal case), so the slot is the ONLY copy of the skills XML in the final prompt. Removing the slot from _mind.md would lose skills entirely. (The earlier muscle_digests removal was different: muscle_digests was rendered by soma + ALSO injected by Pi compiler-prepend — a true double. Skills are not.)
  • Auto-rotation Path A (.rotate-signal + process re-exec) is canonical. Per Pi types (pi-coding-agent/dist/core/extensions/types.d.ts), newSession lives on ExtensionCommandContext, not on the base ExtensionContext event handlers receive. The route cap "session:new" is therefore only registered when a user explicitly invokes /breathe//inhale//auto-breathe (provideCommandCapabilities runs from those handlers). Auto-breathe’s performRotation falling back to .rotate-signal (Path A) is correct by design — Pi treats process re-exec as the safer auto-path. In-process Path B is a happy-path optimization available only after a command was invoked.

v0.27.0 — May 2026

The “autonomous CI/PR pipeline” minor. Three layers ship together: nightly tests + auto-issue-filing + delegate-driven fix orchestration.

🆕 New caps & workflows

  • soma-dev delegate <workflow> — multi-agent orchestrator. Workflows: pr (full PR pipeline), pr-brief (brief only), ci-fix <url> (issue → fix → verify), changelog (rich CHANGELOG), doc-update, audit [tickets...]. Composes changelog_curator + pr_author + doc_writer + verifier (or issue_investigator + builder + verifier for ci-fix).
  • dev:issue.{create,list} — GitHub issues from inside soma sessions. create files structured nightly-failure issues with dedupe gate (skip if open issue exists for same failure).
  • soma-dev check-phases — 30-second pre-release gate (upstream sync + tests + tsc) before the full 5-min soma-release-prepare.sh.
  • soma-pr-brief.sh — generates structured PR brief (git-cliff CHANGELOG diff, affected files, semver bump type, docs to update, roadmap suggestion). Used as input to delegate workflows.
  • {{pi_gap}} body var — reads PI_UPSTREAM.md at session start, injects live Pi version-gap into the system prompt. Updated by 6h GitHub Actions monitor.
  • 3 new child role bodiespr_author (rich PR descriptions), issue_investigator (root-cause tracer for nightly failures), changelog_curator (rich [Unreleased] narratives, replaces auto-bullet noise).

🔄 Behavior changes

  • Pi 0.72.1 → 0.73.1 lockstep bump. All 4 pi-* packages move together (pi-coding-agent, pi-ai, pi-agent-core, pi-tui). Bumping only one causes silent API mismatches.
  • MODEL_ALIASES reverted to 4-5 (NOT bumped to 4-6) — default-tier safety. Bumping aliases would silently force users onto 1M-context variants.
  • Nightly test failures auto-file GitHub issues with nightly-failure label. Dedupe gate prevents floods. Issue body includes failing tests, error excerpts, Pi version, last 5 commits, and a fix brief for the next agent.
  • 18 tests gained CI=true skip guards — workspace/dist-dependent tests self-skip on CI runners.

🧰 Release flow consolidation

  • Archived stale soma-ship.sh. Wired soma-dev ship/release/beta subcommands.
  • pr-check.yml hardened: tsc typecheck job + changelog blocking + conventional-commit format validation.
  • cliff.toml added — git-cliff configured for Keep-A-Changelog format from conventional commits (feat→Added, fix→Fixed, ci/chore/test filtered).
  • release-please auto-trigger enabled on push to dev (proposes; release-please takes over as canonical in v0.27.1).

📁 New files / locations

  • PI_UPSTREAM.md (auto-updated by 6h GHA) — live Pi version gap + flagged commits relevant to Soma (33 Pi API usages tracked).
  • tests/test-children-roles-exist.sh — drift-prevention regression test: every _run_role reference in delegate.sh must have a matching body/children/<role>.md.

v0.26.x — May 2026

Maintenance arc: cache-invalidation hardening, Pi runtime bump rehearsals, soma-github local-mode runtime ship gap fix, body audit + state slimming, anti-accretion discipline. Two reverted patches (long-context, briefly enabled) that were rolled back when they broke a client’s Anthropic billing wall — documented in docs/anthropic-long-context.md with the anthropic.enableLongContext opt-in setting as the durable replacement.


v0.25.x — May 2026

The /inhale stale-ctx fix family + preflight update prompt + sentinel migrations made unconditional + body-template migration mind-prepend-cleanup-v0.25.0 with backup safety + Pi-cruft startup warnings removed. Cycle 12 (preload notify state machine) shipped — transitions only fire once per state change (none→saved, saved→stale, stale→saved). breathe:detail cap added.


v0.24.1 — May 2026

The “releases verify they actually completed” patch arc: protect the release pipeline from silently incomplete ships, and lock the cap-bus surface against accidental drift.

🛠 New tests you can run

  • tests/test-release-completeness.sh — asserts CHANGELOG ↔ git tag parity, devmain ff-merge reachability, dist/manifest.jsonpackage.json, npm/package.jsonpackage.json (collapsed-train case). Auto-runs in orchestrator Phase 1 (tests gate). If a previous release was incomplete, the next prepare fails CONFLICT-HARD before any new bump.
  • tests/test-namespaced-caps.sh — static-analysis floor for the ~92-cap soma:/dev:/somaverse: bus surface. Per-family minimums, named-cap presence (18 specific from CHANGELOG), duplicate-registration detection, namespace hygiene. Catches accidental cap deletion or rename.

Both run as part of npm test; both fail loud if real drift exists.

🔄 Behavior changes

  • soma-release-ship.sh Step 7 now verifies post-pull (was silent on failure). Reads ~/.soma/agent/package.json after git pull --ff-only and asserts version matches NEW_VERSION; on mismatch prints diagnostic + manual fix path + exits 1. Fixes the case where v0.24.0 silently shipped to npm with the runtime worktree stuck at v0.23.0 because pull failure was being swallowed).
  • tests/test-doctor.sh, test-release-completeness.sh, test-release-surfaces.sh, and test-version-truth.sh are now in-flight aware: detect HEAD subject chore(release): vX.Y.Z and skip transient assertions during the ship window. Without this, npm test fails mid-ship because dist/manifest.json lags the bumped package.json. Re-run post-ship to confirm the assertion holds.

🧰 Workflows

  • Anti-accretion sweep (governed by amps/protocols/atlas.md v1.1.0): when body/STATE.md exceeds 6KB, run an anti-accretion sweep — session-history paragraphs (“sNN-XXXXXX shipped…”) belong in memory/sessions/ and memory/journal/, not in STATE. STATE holds current state + pointers; history references the actual session log. Fired live s01-f1230f: cut body/STATE.md 18,148 → 5,513 bytes (-70%) without losing any current state.
  • Phase 6 (Reflect) step 4 expanded (releases/cycles/soma-dev/phases/6-reflect.md): post-release body+state audit now mechanical. Run soma:body.audit (catches duplicate slot interpolations, lazy-frontmatter lies) + soma:body.slots (token budget per slot) + the size gate on STATE.md. Plus stale-state scan: pulse.md, _recent-lessons.md, ecosystem.md, journal.md “Latest”.
  • In-flight test detection pattern (for any future test asserting build artifacts or release-pipeline state): detect chore(release): vX.Y.Z HEAD subject; if matches, skip the transient assertion with a SKIP not FAIL. Re-run post-ship for verification. Pattern lives in body/_recent-lessons.md § In-flight test detection.

📁 New files / locations

  • body/STATE.md frontmatter governed-by: amps/protocols/atlas.md field — makes the protocol discoverable from the file.
  • releases/v0.24.x/plans/cycle-cross-check-audit.md — audit doc surfacing five Curtis-decision items from the cycle MAP cross-check (e.g., should 5-release.md Steps 4-13 be split into orchestrator-internal vs human-action sections?).

🐛 Bugs you can stop stepping around

  • soma-scrape.sh lost fetched docs silently when _website/ dest dir didn’t exist. Now mkdir -p before write. (scripts/_pro/* is gitignored from soma-beta release — dev/main only.)
  • tsconfig.json was type-checking extensions/_archive/** — cleared 15 TS7006 errors from _archive/sx594-flat-wrappers/. npm run check now exit 0.

v0.24.0 — May 2026

The “audit + scan + remember” patch arc: tooling for auditing your own kanban, scanning third-party repos as if they were local, and protecting your input from auto-rotation.

🆕 New caps

Kanban audit [dev] — close the “is SX-N actually still open?” question

  • dev:kanban.audit({ticket: 'SX-N'}) → JSON verdict + evidence (verdicts: SHIPPED / STALE / STALE-CROSS-PROJECT / STILL-VALID / NEEDS-REPRO / UNCLEAR)
  • dev:kanban.audit_batch({tickets: [...]} | {all_open: true} | {all: true}, mode?: 'default'|'md'|'json'}) → grouped table or markdown for cycle docs
  • dev:kanban.audit_open() → every non-✅ row in workspace kanban (one-shot)
  • Backbone triangulates: kanban row + git log + soma:code.* + sessions/preloads + cross-project trees (somaverse/somadian/website)
  • For high-stakes verdicts, follow with soma:agent.delegate({role: 'verifier', background: true}) — independent second-opinion catches what heuristics miss
  • Read first: dev(op='help', cap='dev:kanban.audit') or docs/_dev/kanban-audit.md

GitHub scanner v2 — treat any repo as local without cloning

  • soma:github.local_path({repo: 'owner/name'}) → fetch tarball + return extract path. Cache by SHA at ~/.soma/cache/gh/. ~1–5s cold, instant warm.
  • soma:github.local_map({repo, file}) → function/struct/class map of any file (12 langs: rs / ts-tsx / js-jsx / py / go / java / c-cpp / rb / sh / md / json / toml). API-mode soma:github.map only knew rs/ts/py — local mode is the upgrade.
  • soma:github.local_find({repo, pattern, path?, ext?}) → full ripgrep regex (API search is literal-only). Auto-scopes to repo’s primary language via meta.json language hint.
  • soma:github.local_refs({repo, symbol, path?}) → DEF/IMP/USE classification across the cached repo
  • soma:github.local_blast({repo, symbol, path?}) → blast radius (files × risk) for a symbol
  • soma:github.local_structure({repo, path?}) → faster + richer than API once cached
  • soma:github.cache_list() / soma:github.cache_clean({days?: N | all?: true}) → cache management
  • Plus 5 API-mode caps that were missing from the addon but already in the script: audit, releases, diff, compare, file_diff

Soma docs got smarter

  • soma:docs.whats_new({version?, limit?: 3}) → THIS doc, version-scoped if asked
  • soma:docs.guide({name}) → resolves from guides/ first, _dev/ second. Convenience over .show.
  • soma:docs.list now recursive (catches guides/ and _dev/) and shows TL;DR per entry, grouped by section

🔄 Behavior changes

  • breathe.auto is now opt-in by default (was on by default). Auto-rotation at 70% context was wiping user input mid-compose. If you want it back: set breathe.auto: true in .soma/settings.json. Existing installs are migrated once via breathe-auto-off-v0.23.1 (recorded in new settings.migrations[] array; respects re-enable).
  • soma init now writes the correct version to .soma/settings.json. Pre-fix it stamped 0.10.0 because the package.json walk-up only walked one level. Fresh inits + repaired existing installs.
  • soma update auto-detects your remote name (was hardcoded to origin; broke on dogfood worktrees with meetsoma remote).
  • soma doctor persists version bump even when fixes==0 (was printing “version bumped” without writing settings.json).

🐛 Bugs you can stop stepping around

  • /inhale stale-after-reload — extension code that captured pi.sendUserMessage went stale after session rotation. Now consumes route.get("message:send") for fresh closure. Pattern: any pi.X consumed across rotation should go through soma-route’s capability bus. See amps/muscles/internal/route-plumbing-first.md.
  • soma:code.find returned 0 results silently when ext was passed without path (positional CLI shifted ext into path slot). Cap now defaults path to . when ext is set.
  • GitHub script silently 404’d on master-default reposBRANCH=main was hardcoded. v2 auto-detects via default_branch API field, falls back to main only on API failure.
  • GitHub script --help ran structure on a repo named --help — now short-circuits to usage block.

📁 New files / locations

  • ~/.soma/cache/gh/<owner>--<repo>--<sha>/ → GitHub tarball cache. .soma-meta.json per entry with {owner, repo, sha, ref, language, fetched_at, size_bytes}.
  • .soma/settings.json now has migrations: [] array — list of one-time semantic migration IDs that have been applied. The runtime appends to this; you don’t typically write to it.
  • docs/_dev/ [dev] — dev-only docs subdir, surfaced by soma:docs.list when present.

🧰 Workflows

  • End-of-arc kanban sweep: dev:kanban.audit_open() before cutting a release. Closes 3–4 wrongly-marked tickets in seconds; spawns verifier delegations for the high-stakes ones.
  • Survey a third-party repo without cloning: soma:github.local_path({repo: 'owner/name'}) → returns cache dir → run anything against it. Map / find / blast / refs all work locally with full toolchain. ~5s one-time cost, then instant.
  • Soma-code env override: SOMA_CODE_DEFAULT_EXT="go,md" (or any ext list) overrides cwd-marker auto-detect. Use when working in monorepo subdirs or pre-modules language repos that lack manifest files.

🛠 New scripts

  • scripts/_pro/soma-github-cache.sh — tarball fetch + extract + cache management
  • .soma/amps/scripts/soma-audit-ticket.py [dev] — single-ticket audit (Python; the heuristics engine)
  • .soma/amps/scripts/soma-audit-tickets.sh [dev] — parallel batch wrapper (xargs -P 8)

📜 Plans referenced this arc

  • releases/v0.23.x/plans/github-tool-10x.md — the soma-github v1 → v2 architectural pivot
  • releases/v0.23.x/plans/discovered-tools-body-injection.md — the seed for self-discovering tool surface (Phase 0 done, Phase 1+ queued)

v0.23.0 — April 2026

The “release orchestrator + tree-hygiene” arc.

🆕 New caps

  • soma:agent.list({role: 'X'}) → filter children by role string. Stacks with existing active_only/all/cleanup. Useful when a parent has spawned multiple roles and wants to inspect just one cohort.

🔄 Behavior changes

  • Release orchestrator is now 10 gates (was 8). New: tree-hygiene (Phase 0.5) — halts on uncommitted state in repos/agent/ other than M CHANGELOG.md. Prevents agent-spawned files leaking into ship. website-readiness (Phase 5.5) — calls tests/test-release-surfaces.sh for CHANGELOG ↔ roadmap.json drift.
  • Phase 4-ship.md and 4.5-audit.md are archived. Their work is now inside soma-release-prepare.sh + soma-release-ship.sh.

📜 Plans referenced this arc

  • releases/RELEASE-FLOW.md — current head (10 gates documented)
  • Old phase docs: releases/cycles/soma-dev/phases/_archive/

v0.22.x and earlier

For the technical commit-by-commit history, see CHANGELOG.md at the repo root or https://soma.gravicity.ai/changelog. This whats-new.md only goes back to v0.23.0 — versions older than that didn’t have an agent-facing digest layer.


Conventions for whoever maintains this

  • One section per release. Latest at top. Version + month + a one-line tagline.
  • Density first. Skip the “why” if a one-liner won’t shrink the gain. Ship the “how to use it” — that’s what an agent reads to pick up the new surface.
  • Tag dev-only. [dev] after the cap name when it’s only on dev installs.
  • Always include invocation hint. cap_name(args) → outcome. The agent reads this and can call it on the next turn.
  • No commits. Commits go in CHANGELOG.md. This file isn’t generated from git; it’s hand-curated for the agent’s benefit. Treat it like a muscle: dense, action-oriented.
  • TL;DR up top so soma:docs.list extracts a useful preview.