All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Develop-line release focused on broader AI maintainer workflows: codebase graph analysis, reversible context compression, structured mail tools, CAD read/edit tools, and long-running agent-output evaluation.
anvil-defscodebase graph (Doc 57) — expands the SQLite defs index into call-graph analysis for Elisp, Python, JavaScript, and TypeScript. Adds trace-path, change blast-radius, caller/callee ranking, dead-code hints, file-level clustering, architecture summaries, and default exclusions for.worktrees/andtarget/.anvil-semantic(Doc 18) — lands the local-first semantic search module on develop/master. Search combines SQLite FTS5, CJK LIKE fallback, lexical overlap, and optional vector cosine retrieval. The embedding provider defaults to ollama-local, with Gemini/OpenAI opt-in.anvil-context— Headroom-inspired reversible context compression for arbitrary JSON, diffs, logs, code excerpts, and prose. Addscontext-compress,context-retrieve, andcontext-stats; raw context is retained by ccr-id throughanvil-state.anvil-mu4eandanvil-wl(Docs 53/56) — structured mail tools over local mu4e and Wanderlust/Maildir stores. Read/search/compose paths are structured and CJK-aware; send paths are gated.anvil-cad— ASCII DXF/SVG read/edit/generate tools through a shared entity IR: outline, extract, annotate, batch-update, and generate.- Fusion modules (Docs 54/55) — panel, async, long-run store, and MCP surfaces for comparing agent outputs and preserving compact review summaries.
- Client documentation — README now documents both Claude Code and
Codex CLI MCP registration, plus AGENTS.md / CLAUDE.md guidance for
shell-run,shell-tee-get,context-compress,context-retrieve, andcontext-stats.
- Use
#!/usr/bin/env bashin the stdio bridge for NixOS-friendly execution. - Decode literal newline escapes in the mu4e compose body path.
- Improve test isolation around orchestrator task-table state.
- Skip org-habit assertions on older org-habit builds where the habit summary format differs.
First stable release. Two landmark capabilities ship together:
- anvil.el now runs without an Emacs install — thanks to NeLisp's
v1.0 standalone Rust runtime (
anvil-runtime).bin/anvil mcp serve --no-emacsspawns zero Emacs processes; the Rust binary itself reads + evaluates the loaded anvil modules and serves MCP tools over stdio. - anvil-ide split — Emacs-only IDE features (treesit-based code
navigation, the worker dashboard, Info/Help lookup) moved out of
anvil.elinto the dedicated anvil-ide.el repo. The remaininganvil.elis the AI-side workbench: pure stdio MCP server + tool registry + library helpers, no human IDE surface.
This is a breaking release (anvil-ide tools are no longer in this repo) and a major architecture milestone (anvil + NeLisp standalone proves the AI workbench can run on a substrate other than the Emacs binary). Hence the jump 0.4.x → 1.0.0.
- Doc 38 §3 — full split pipeline shipped 2026-04-26 → 04-27.
Phase A (audit + classification of all 60+ modules) → Phase B
(5-wave adapter migration: anvil-buffer / anvil-elisp / anvil-org-index /
anvil-org / anvil-browser) → Phase C (rename
anvil-treesit/anvil-worker-ui→anvil-ide-*, splitinfo-lookup-symbolintoanvil-ide-elisp.el) → Phase D (git filter-repoextract preserving 12-commit history) → Phase E (cleanup + soft(require 'anvil-ide-* nil 'noerror)) → Phase F (treesit backend abstraction so anvil-ts / anvil-js / anvil-py stay AI-callable on NeLisp substrate via subprocess fallback) → Phase G (subprocess backend impl: Python full ast / JavaScript acorn / TypeScript degraded acorn). All phases documented in docs/design/38-anvil-ide-split.org. - Architecture α now active — anvil-defs, anvil-state, anvil-http
internals delegate to NeLisp side via
fboundpguard + fallback, letting the Rust runtime evaluate them without a host Emacs.
- Stage D v2.0 (bundled-Emacs path) and v3.0 (Rust-only
path via
bin/anvil mcp serve --no-emacs) ship as part of NeLisp v1.0; both expose the same MCP tools so existing Claude Code.mcp.jsonentries keep working.
anvil-treesit.el,anvil-worker-ui.el,anvil-ide.el, theelisp-info-lookup-symbolMCP tool, and the org-element / org-edit-body tree-walk surface are no longer in this repo. Install anvil-ide.el separately if you want the IDE layer. Cross-package wires use(require 'anvil-ide-* nil 'noerror)so anvil.el continues to load even when anvil-ide is absent.
- CI subprocess test gating — 49 slow subprocess ERTs gated on
ANVIL_SLOW_TESTS=1so the default GitHub Actions matrix exits 0 on every push. Localmake test-allstill runs everything. - Test count: 1198 (v0.4.0) → 1610+ (v1.0.0), with all of Phase F backend abstraction + Phase G subprocess paths under ERT.
- 3 audit-correction notes appended to Doc 38: anvil-buffer is
namespace-disjoint, not drop-in compatible; the
org-capture-templatesreference in anvil-browser is docstring-only; anvil-ts / -js / -py wraptreesit-*and were reclassified PURE-via-backend in Phase F.
Two small fixes released same-day as v0.4.0, both reached the repo after the v0.4.0 tag was pushed.
- Release-audit false positive on
anvil-discovery.el— four private accessors (--tool-intent/--tool-layer/--tool-stability/--tool-summary) triggered the MCP-tool wrapper regex and failed the release-audit gate on master, leaving the v0.4.0 CI build red. Renamed to-ofsuffixes (--intent-of/--layer-of/--stability-of/--summary-of) so the audit no longer treats them as MCP tools. No public API change; the actualanvil-tools-by-intent/anvil-tools- usage-reportsurfaces are unchanged. treesit_infoparser initialisation (@yours57) — the tool ran through the TreeSitter node walker without creating a parser first, so callers got a stale / empty info payload on buffers where treesit hadn't been warmed. Addedtreesit-parser-create- integer-param parse helper + autoload for
anvil-treesit-language-for-file/-ensure-grammar.
- integer-param parse helper + autoload for
AI agent workbench release. Fourteen new design documents (Doc 21-34) worth of primitives turn anvil from a tool-per-task module collection into a cohesive agent development platform: memory engine, intent-based tool discovery + profile filter, structural edits for Python / TS / JS / Elisp-CST, shell output compression, session snapshot + Claude Code lifecycle hooks.
Test suite: 640 → 1198 passing (+558, +87%). 20 new anvil-*.el
modules. +39,343 / -408 lines across 145 files.
memorymodule (Doc 29) — Bayesian + TTL + FTS5 auto-memory engine with 16 MCP tools (memory-scan/memory-audit/memory-access/memory-list/memory-search/memory-duplicates/memory-promote/memory-serve-startetc.). Indexes~/.claude/projects/*/memory/*.mdinto SQLite, tracks contradictions and URL liveness, surfaces stale rows tomemory-pruner. +115 ERT.sessionmodule (Doc 17) — session snapshot / resume plus 5 Claude Code lifecycle hooks (PreCompact / SessionStart / PostToolUse / UserPromptSubmit / SessionEnd).session-snapshotcaptures branch- task summary into anvil-state ns=session (14-day TTL), returns a
preamble-suggestedresume block;anvil-hook installwires the hook set into~/.claude/settings.json. +19 ERT.
- task summary into anvil-state ns=session (14-day TTL), returns a
shell-filtermodule (Doc 27) — shell output compression with 20 bundled filters (git status / git log / git diff / rg / find / pytest / ert-batch / emacs-batch / make / docker-logs / …) + tee + gain statistics. Raw output stashed undershell-teenamespace with TTL so callers can recover on demand. Depends onstate.disclosuremodule (Doc 28) — 3-layer read contract and citation URI scheme.file-outline/org-index-index/defs-index/journal-index/http-cache-index(Layer 1),file-read-snippet(Layer 2),file-read/org-read-headline/org-read-by-id/elisp-get-function-definition/http-cache-get(Layer 3).disclosure-helptool prints the contract;anvil-uri-fetchis a cross-layer resolver.discoverymodule (Doc 34) — intent-based MCP tool discovery (Phase A) +agent/editintent-based profiles (Phase B) + orchestrator auto-injection + per-tool usage counter + release-audit:unused-sincescanner (Phase C).anvil-tools-by-intentreturns tools matching intent CSV / layer / query regex, sorted by layer rank and intent overlap. All 198 registered tools tagged with:intent/:layer/:stabilitymetadata. +27 ERT across discovery / manifest / orchestrator / dev.
manifestmodule (Doc 26) — per-sessiontools/listprofile filter driven byANVIL_PROFILE. Five legacy profiles (ultra/nav/core/lean/full) advertise curated tool subsets to shrink the manifest token cost; handlers of hidden tools stay callable via explicittools/call. Phase 1b auto-injects--mcp-configinto orchestrator child sessions.- Intent-based profiles (Doc 34 Phase B) —
agent(orchestrator / session / memory / browser + edit tools, layer=core+workflow) andedit(file / org / code / json / db only, layer=core). Filter by metadata instead of hand-curated ID lists.
sexpmodule (Doc 12 Phase 1+2) — reader-based edits for Elisp:sexp-read-file/sexp-surrounding-form/sexp-rename-symbol/sexp-replace-call/sexp-replace-defun/sexp-wrap-form/sexp-macroexpand/sexp-verify. +48 ERT.sexp-cstmodule (Doc 31) — tree-sitter-elisp CST + runtimeinspect-objecttool for any live Lisp value.sexp-cst-read(comment-preserving CST),sexp-cst-edit+-write(point-offset replacement with re-parse validation),sexp-cst-repair(paren + unterminated-string balancing). +47 ERT.pymodule (Doc 21 Phase 1) — Python structural locators and edits via treesit:py-list-imports/py-list-functions/py-list-classes/py-list-methods/py-list-decorators/py-find-definition/py-surrounding-formplus edit toolspy-add-import/py-remove-import/py-rename-import/py-replace-function/py-wrap-expr. +55 ERT.ts+jsmodules (Doc 21 Phase 2) — TS/TSX + JS/JSX locators:ts-list-imports/exports/functions/classes/methods/interfaces/ type-aliases/find-definition/surrounding-formand thejs-*mirror. +25 ERT (ts) + ts-test fixtures.defsmodule (Doc 11) — SQLite-backed Elisp symbol index.defs-search/defs-references/defs-signature/defs-who-requires/defs-index-rebuild/defs-index-status. +52 ERT.
benchmodule (Doc 14) —bench-compare/bench-profile-expr/bench-last.bisectmodule (Doc 13) — test-driven git bisect via worktree- isolatedemacs --batch.bisect-testpins a failing ERT to the introducing commit. +12 ERT.git-msgmodule (Doc 15) —git-commit-message(from staged diff) andgit-pr-body(from branch log). +17 ERT.lintmodule (Doc 16) — repo hygiene scanner with pluggable registry:conflict-markers(error),orphan-ids(info),broken-scheduled(warning). +13 ERT.datamodule (Doc 33) — JSON path-based edits with preview-by- default:data-get-path/data-set-path/data-delete-path/data-list-keysfor~/.claude.json,package.json, MCP configs. +28 ERT.
- Provider latency routing (Doc 22) —
orchestrator-routing-selectfor per-provider latency-aware dispatch. +13 ERT. - Consensus presets (Doc 23) — named provider combinations ship
with
orchestrator-consensus-*family. +16 ERT. - Orchestrator submit-and-collect — one-shot dispatch + wait combinator for programmatic callers.
- Preamble management —
orchestrator-preamble-set/-get/-list/ -delete/-set-from-filefor reusable system prompts. - Live streaming —
orchestrator-stream+orchestrator-tailforward provider stdout as MCP events while the task runs. - Cross-session stats —
orchestrator-statsaggregates batch history across daemon restarts via anvil-state.
anvil-tools-by-intent— intent CSV / layer / query regex / stability filter, deprecated always hidden, experimental opt-in, layer-ranked output.anvil-tools-usage-report— per-tool counter summary (days threshold, never-called bucket, unused-since bucket, recency sort).anvil-dev-release-auditgains:unused-since Nscanner — advisory-only Phase C hazard: does not flip:clean-p.
anvil-server-encode-handlerinternals — replacedeval + constructed lambdawithmake-symbol + fset + apply-partially + symbol-property(anvil-server-raw-handler/anvil-server-encode-result).anvil-server-register-toolnormalizes wrappers back to the raw handler for schema generation and docstring validation. Fixes silentenableskip forsexp/py/bench/git-msgoptional modules (PR #12, @yours57).gitMCP handlers — sentinels:null/:empty-array→ literal strings"null"/"[]"(visible wire-format change). All 8 git tools now wrapped viaanvil-server-encode-handlerat registration; 6 dedicated ERT.- Worker server files — path moved from
user-emacs-directory/server/toserver-auth-dir/server-socket-dir; liveness check usesserver-running-pfor local sockets, PID parsing for TCP auth files. anvil-server-tool-filter-function— now receives(TOOL-ID TOOL-PLIST SERVER-ID)so filters can branch on metadata.anvil-manifestuses the full signature for intent-based filtering.anvil-server-tool-dispatch-hook(new abnormal hook) — runs after each successful handler return with(TOOL-ID SERVER-ID); used byanvil-discoveryto maintain usage counters without couplinganvil-servertoanvil-state.
- Encoded handler registration bug —
anvil-server-encode-handlerpreviously returned(lambda (&rest args) ...)whichanvil-server--generate-schema-from-functionrejected; silently skippedenableforsexp/py/bench/git-msgand made every re-register viaunload-featurebreak. Fixed via the symbol-backed wrapper path above (PR #12). - JSON encoder on dotted pairs —
anvil-server--to-json-valuecrashed withlistperror on alist entries like(cons "k" 1.0). Newanvil-server--list-to-json-arrayemits[car, cdr]for improper lists somapcarcan't trip. xref_find_apropos— missing(require 'apropos)made the tool void-function on fresh Emacs installs.- Worker liveness — Unix-socket workers wrongly reported alive
via file existence alone; now goes through
server-running-p.
- Fourteen new design docs (Doc 21-34). Six docs (18 / 19 / 20 / 24 / 25 / 30) explicitly DEFERRED — out of scope for this release. Doc 32 is an audit memo (rhblind/emacs-mcp-server positioning, informational only).
CLAUDE.mdselection flowchart trimmed (11 rows → 5) — discoverable entries moved toanvil-tools-by-intentruntime query; only size/shape heuristics kept.- Platform files (
linux.md/windows.md) gained atool 探索section documentingANVIL_PROFILE=agent/editusage.
0.3.1 - 2026-04-19
Hotfix surfaced by the v0.3.0 orchestrator benchmark
(develop: benchmarks/results/report-2026-04-19.org).
The bench's first programmatic orchestrator-* call hit the
cons-return bug; every fix here fell out of the investigation.
orchestratorMCP wrappers returned plists instead of strings, tripping theanvil-servercontract and breaking every programmaticorchestrator-*call from Claude Code / OpenCode / other MCP clients with"Tool handler must return string or nil, got: cons". Addedanvil-orchestrator--encode-handlerwhich wraps each registered tool at registration time and JSON-encodes the plist result. Tool bodies stay unchanged (and still return rich plists for direct Elisp / ERT callers).- Added
anvil-orchestrator--batch-task-idsaccessor + docstring note on theanvil-orchestrator--batches/anvil-orchestrator--consensus-groupsshape asymmetry, so future callers stay decoupled from the storage representation.
- Raised the
codexper-provider concurrency default from 3 → 6. The v0.3.0 ramp benchmark reached 8 concurrentcodexjobs on ChatGPT Plus OAuth with zero 429s; the old default was defensive past its evidence. Users on throttled accounts can set it back viaanvil-orchestrator-per-provider-concurrency.
0.3.0 - 2026-04-19
Major release covering 10 design documents worth of new primitives: orchestrator (Doc 10), browser framework (Doc 07), disk-first helpers (Doc 05), code-transform tools (Doc 06), state KV store (Doc 08), HTTP client (Doc 09), pty-broker (Doc 04), worker pool v2 (Doc 01), org index (Doc 02), offload framework (Doc 03). Test suite grew from 292 to 508 passing.
orchestratormodule (Doc 10) — parallel AI CLI dispatcher.- 5 native providers:
claude,aider,gemini,ollama,codex(OpenAI ChatGPT Plus OAuth). - Pool with per-provider concurrency caps, state-persisted queue, tabulated-list dashboard, git worktree isolation.
:depends-onDAG with cycle / unknown-name detection and propagating failure semantics. DAG resume across daemon restart viaorchestrator-resume-interrupted.- Cross-model consensus (Jaccard verdict) and meta-LLM judge (synthesized answer via 3rd provider).
- Auto-retry with exponential backoff + jitter,
Retry-Afterhonouring, per-provider backoff overrides. - Live streaming events (Phase 7c) — per-event callbacks without SQLite writes, overflow compression.
- Context preamble registry (Phase 7b) — reusable prompt preludes
via
:preamble-ref, auto-resolved at submit. submit-and-collectconvenience for synchronous fan-out,submit-one/extract-result/tailglue helpers.- Observability:
orchestrator-statswith percentile / provider filter,anvil-orchestrator-stats-dashboardcommand. anvil-cronintegration (Phase 2b) viaanvil-cron-register :fnexamples/nightly-orchestrator.org.
- gemma4 thinking-mode guard (XML
<think>and plain-text delimiter).
- 5 native providers:
browsermodule (Doc 07) — agent-browser wrapper.- Phase A:
browser-fetch/-interact/-capture/-screenshot/-closeMCP tools with in-memory cache + metrics +M-x anvil-browser-status. - Phase A': auth primitives (
profile,user-agent,auto-connect,session-presets) for login-walled / anti-bot sites.
- Phase A:
pty-brokermodule (Doc 04 Phase 1) — Node-pty TCP broker + Elisp client + 5 MCP tools, structurally avoids filter-starvation and ConPTY headless-stdin limitations.statemodule (Doc 08) — SQLite-backed KV store with namespaces, TTL, andprin1value serialization.anvil-browsercache now persists across daemon restarts.httpmodule (Doc 09 Phase 1a) —http-fetch/-head/-cache-purgewith ETag/TTL cache viaanvil-state.org-index(Doc 02 Phase 1-4 + 5a) — SQLite org index, filenotify watcher + periodic scan, 177× speed-up on 1500 files / 71k headlines;org-read-*routed through index.- Disk-first helpers (Doc 05) —
:warningson every mutatingfile-*tool, plusbuffer-read/buffer-save/buffer-list-modifiedMCP tools. - Code-transform tools (Doc 06) —
code-extract-pattern(read-only structured block extraction) andcode-add-field-by-map(TS/JS object literal bulk field add for i18n). - Worker pool v2 (Doc 01) — 3-lane split with
:kindclassifier, batch warmup, latency metrics, optionalserver-eval-attransport. - Offload framework (Doc 03) — pipe REPL + pool,
:offload t, hard-kill, handler-side checkpoint for:value/:cursorpersistence. anvil-devtools —anvil-dev-release-audit(3 scanners: Emacs 30_argsarglist-strip hazard, missingMCP Parameters:docstring sections, non-SHIPPED design docs),anvil-dev-test-run-all :minimal,anvil-dev-self-sync-check,anvil-dev-journal-memo-append,anvil-scaffold-module.- Efficiency bundle —
anvil-server-register-toolsbulk registration,anvil-orchestrator-preamble-set-from-file,anvil-orchestrator-dashboard-autofollow,anvil-dev-release-audit :scope. anvil-gitextensions — worktree helpers +git-branch-current/git-head-sha/git-repo-root/git-worktree-listMCP tools.
anvil-orchestrator-summary-max-charsdefault raised 300 → 4000 to eliminate the common re-parse round-trip; pass:full ttoorchestrator-extract-resultfor the unbounded form.- No-arg MCP wrapper convention: write
()not(_args). Emacs 30help-function-argliststrips_-prefix, which broke MCP schema registration for worker, cron, orchestrator, browser, and other modules — all audited and fixed.
orchestrator: close stdin after spawn to prevent ollama CLI hang (31d2f3f).orchestrator: deep-copy task plist insubmitso consensus fan-out does not share tails — previously caused:cost-usd/:elapsed-msclobber across providers (5a2610f).orchestrator: gemma4 thinking-strip now handles the plain-textThinking... ...done thinking.delimiter in addition to XML<think>blocks (86a0e7c).- Windows stdio CR robustness — tools/list decode reliably on MSYS2 + gawk 5.0.0 + coreutils 8.32 (issue #6).
- Emacs 30
help-function-arglistunderscore-strip regressions across worker, cron, orchestrator (issue #9, v0.2.1) + remaining no-arg wrappers audited viaanvil-release-audit.
0.2.1 - 2026-04-18
- Worker + cron module load failure on Emacs 30 due to
help-function-argliststripping_argsprefix (issue #9).
0.2.0 - 2026-04-17
Initial tagged release — see git history for details.
0.1.0 - 2026-04
Project inception.