All notable changes to CALM are documented here. Format loosely follows Keep a Changelog; versions match the git tags in Releases.
- Resolver context-intelligence upgrade (WS0-WS6,
docs/plans/2026-08-18-context-intelligence-upgrade-plan.md): a call site whose surviving candidate set exceedsMAX_CALLEE_CANDIDATESis now recorded in a newambiguity_groupstable (with target-awareambiguity_group_candidatesmembership, not a bare-name key that could leak an unrelated same-named symbol's caveat) instead of vanishing with zero trace —callers()/reference_impact()surface anunresolved_group_count/unresolved_many_countcaveat. Inheritance/interface closure (extends/implements) is now a realresolved-confidence resolution mechanism, walked nearest-level-first.call_edgesgainedcandidate_rankso C/C++'s same-directory heuristic ranks candidates instead of destructively filtering them (Go/Java keep their pre-existing hard package-scoping filter, since — unlike C/C++ — they have real compiler-enforced package scoping). Net effect on the WS0 benchmark corpus: call recall 0.75 → 0.875 with no precision cost. evidence_conflictstable +provider_conflict_ratemetric: when the SCIP/LSP overlay's proposed target contradicts an already-confident static resolution, the rejection is now countable evidence instead of a silent skip.- Evidence ledger v1 foundation (Wave 3,
docs/plans/2026-08-19-evidence-architecture-execution-plan.mdPart E PR#10):reference_evidencegeneralizesexternal_proofswith adispositionaxis (supports/excludes) recording both accepted provider proofs and rejected ones (theevidence_conflictscase, now dual-written here too);reference_verdictsis a derived, fully recomputable reconciliation answering "what shouldcall_edgessay" for every call site with real evidence. Both are additive and read-only in this release — nocall_edgeswriter was changed, and neither table is wired into any automatic pipeline yet. target_type_kind/target_type_qnoncall_sites(PR#8): a call site's receiver type is now qualified (e.g.com.foo.Uservscom.bar.User), not just a bare class name —resolve_sites_to_edgesuses this to disambiguate two same-named classes in different packages/modules that previously collided into one candidate bucket.- Call-site identity v3 (PR#9): call-site identity can now be relative to its enclosing symbol's own start byte instead of absolute-in-file, and reindexing now upserts
call_sitesby identity (matching existing rows, preserving their id) instead of deleting and re-inserting every row for a changed file — an edit that only shifts a call site's absolute position (e.g. adding a comment line above it) no longer churns everyexternal_proofs/evidence_conflicts/ambiguity_group_candidatesrow CASCADE-keyed to that call site. new Foo(...)now produces a call edge in JS/TS/Java (previously invisible:new_expression/object_creation_expressionis a distinct tree-sitter node kind from the ordinary call node each language's grammar already tracked) — a class invoked exclusively vianewhad zero call edges before this fix.reference_impact's import-edge lookup now walksexport_statement, closing a zero-coverage gap where anyexport { x } from 'y're-export in a JS/TS project never produced animport_edgesrow; a wildcard re-export chain (export * from './x') is followed transitively (bounded BFS,REFERENCE_IMPACT_MAX_REEXPORT_HOPS), not just one hop.compute_touch_risk(the function feeding bothedit_lines_impl_gated's real write gate andedit_context'sgate_prediction) now escalates risk for a manifest-file edit or an edit to code with no recorded test coverage, reading the project's real.calm/policy.tomlfloors — previously only the CCK-10 authority-digest path considered these two axes, so a plainconfirm+reasonedit to e.g.Cargo.tomlsailed through ungated regardless of this project's own configured policy.calm review approve-via-agent-relay/decline-via-agent-relayCLI subcommands: a non-TTY-compatible mirror of the existingreview_decide_via_agent_relayMCP tool, for an agent with no MCP bridge and no real terminal (opt-in via[edit] elicit_via_agent_relay).scripts/ci-local.sh: one command mirroring every blocking CI gate (fmt/clippy/test/doc-truth by default,--fulladds the feature-matrix, stack-graphs corpus, B2 thresholds, audit, and fitness-check gates), so a "green locally" push can't still fail CI on a check nobody ran.- New cross-language competitor benchmark (B15,
benchmarks/b15_cross_lang_competitor_ab/): calm vs CodeGraph vs two additional real competitors (Ctxo, Context+) across all 6 Tier-0 languages on file-recall for "who calls this symbol." The investigation this benchmark drove found and fixed two real resolver bugs (below) that took calm's own aggregate recall from 68/72 (94.4%, behind CodeGraph) to 73/73 (100%, tied with the recall-maximizing ceiling, via a real resolver rather than substring matching).
- False-confidence P0 (D8): the SCIP overlay could insert a formal edge contradicting an already-confident static resolution (
resolved, or a non-SCIPformaledge) to a different target — a real case where scip-python followed an import binding that a later same-scopedefactually shadows, producing a top-tier edge to a target Python semantics never call.insert_missing_exact_edgesnow skips the insert (recording the rejection inevidence_conflicts/reference_evidenceinstead) when a confident static edge already claims the call site; deliberately narrow —ambiguous/textual/inferrededges stay overridable, since disambiguating those is the overlay's actual job. - External-crate-rooted calls (
std::fs::write(...)) no longer bind to an unrelated local same-named function (e.g.txn.rs::write) — the qualification itself proves the call isn't local, so the parser now drops it instead of letting it fall through to the unscoped by-name fallback. - An inherited-method call through a receiver of known static type (formal parameter, Go's parameter declaration, etc.) was dropped entirely when the method was declared on an ancestor class, not the exact type — an unknown-type receiver correctly fell back to an ambiguous fan-out edge, but a known type made the resolver strictly worse at finding the edge. Now falls back to the unscoped lookup, but only when the receiver's class is itself a symbol this project declares (an unmodeled external/stdlib type keeps the original no-candidates behavior).
- Express/Zod B7 benchmark misses, both root-caused to real bugs, not benchmark artifacts: a source file with zero top-level named declarations (any Mocha/Jest-style
describe/ittest file) never got apath_langentry, silently zeroing every outgoing call edge from that file regardless of confidence tier; and theexport_statementgap above meant Zod's real two-hop wildcard barrel re-export was invisible toreference_impactentirely. B7 now passes 6/6 via thecalm_v2arm with zero regressions. tools/list/prompts/listnow setttlMs/cacheScope(SEP-2549) — at least one real client rejects both responses outright when these fields are absent, silently registering zero tools even though the underlying MCP connection looks healthy.review_decide_via_agent_relaywas defined in the wrongimpl CalmServerblock and had silently never registered as a callable MCP tool since it was added.- Several benchmark ground-truth bugs found while auditing calm's own correctness on HEAD (not calm bugs): rust-analyzer's SCIP symbol naming doesn't disambiguate same-named private functions across independently-compiled test binaries, silently letting one file's occurrence overwrite another's as B2's oracle; a call-shaped
NAME(match inside a same-line quoted string (e.g. a pytest parametrize tuple) was counted as a real call site by B12/B13's git-grep oracle; the Java oracle's method-definition pattern required an explicit access modifier, miscounting package-private JUnit test methods (the standard convention) as call sites instead of definitions. cargo run -p calm-cli(no--bin) was ambiguous once a second binary (the WS-1 crash-injection harness) existed, breaking every benchmark script that spawns the server this way.
crates/calm-core/src/indexer/pipeline.rs(issue #67, ~7,200 lines) split into 9 focused modules (discovery/extraction/context/reconcile/modules/graph/driver/cache/identity_migration) — move-only, zero net logic diff, each slice verified againstgolden_graph_equivalence's continued/incremental-vs-fresh mutation-round tests as the real safety oracle beyond build/clippy/test alone.- README.md/AGENTS.md/SECURITY.md/llms.txt backfilled for tools that had shipped without their hand-authored doc entries (
plan_change/review_change,batch_status) and the reviewable-change authority's own security-scope entry.
- Reviewable change authority, a new facade over the existing edit gate:
plan_changedeclares aChangeIntent(what you're about to do, why) as a durable, reviewable record;review_changemints a signedReviewAuthorityfor it onceapproved:trueis set (client self-attestation, sufficient for low/medium risk only) or refuses outright for a change a realPolicyEngine/RiskVectorevaluation classifies as needing independent human review. AReviewAuthoritybinds the exact target scope, source/graph/config/provider-state snapshot, caller-set digest, and thePolicyDecisionit was reviewed against — spending it viaedit_lines/edit_symbolre-verifies all of that fresh, not just at mint time. calm review— a new, MCP-protocol-independent second channel for independent review alongside elicitation, not a replacement for it: when a high-risk edit is refused with no working elicitation round-trip, it opens a durablepending_reviewsentry;calm review list/show/approve/declinerequires a real interactive TTY (refuses on non-TTY stdin) and renders the same bounded, sanitized diff the elicitation prompt shows. An agent's retry against a matching approved review is honestly recorded asmechanism: "cli_manual_review", never as"elicitation".approval_receipts: a durable, HMAC-signed record of every approval decision (self_attestedatreview_changemint time,elicitation/cli_manual_reviewat spend time), with asignature_provenancefield (nativevslegacy_unverified) folded into the signed payload so it can't be silently upgraded by raw DB write access alone.RootedFilesystem(crates/calm-core/src/fs/rooted.rs): a kernel-enforced (openat2(RESOLVE_BENEATH), Linux x86_64) TOCTOU-safe path-containment primitive, closing the check-then-use racepath_policy's textual canonicalize-and-compare check can't rule out. Opt-in today via[edit].kernel_enforced_writes(defaultfalse); every other platform falls back to the existing textual check, honestly reported as such.- Cross-file type-relation resolution:
extends/implementstargets defined in a different file from their reference now resolve across the whole repo (previously same-file only), surfaced throughsymbol_info/understand's semantic facts. Effect facts (throws/writes) now carry separate event- and target-confidence, recovering several previously-dropped Python "uncertain raise" cases instead of silently omitting them. - Verified Index Bundles (
calm bundle export/import/inspect) and a declared external-dependency graph (Cargo/npm/go.mod/requirements.txt/pyproject.toml) shipped as part of this cycle's derived-artifact work — seedocs/architecture.md. - New
DerivedStatus(Ready/NeedsBaseline/Stale) surfaced onindexing_statusfor T1 semantic facts and graph-derived artifacts independently, plus versioned drift-guards (SOURCE_EXTRACTION_VERSION/GRAPH_DERIVATION_VERSION/PACKAGE_GRAPH_VERSION) so a behavior change without a matching version bump fails CI instead of silently shipping a stale incremental index. symbol_info/understand/ArchitectureDigestOutputgained acontent_warningfield: derived text (type-relation targets, effect targets, rendered architecture digest) now runs through the same credential-redaction/prompt-injection heuristicssourcealready applies to raw code, closing a gap where CALM's own derived analysis text was treated as more trustworthy than the code it was derived from.
- Approval-bypass regression (CCK-23, P0): a validated
ReviewAuthorityletedit_lines/edit_symbolskipHIGH_RISK_REQUIRES_INDEPENDENT_REVIEWentirely — a high-risk edit could land with no independent review at all, because a valid authority proved what was touched, never who reviewed it. The check now applies unconditionally regardless of authority state. - Human-tier review was dead code (P0):
EvidenceSnapshot::compute_after_reconciliationhad zero production callers, so a Human-tierReviewAuthoritycould never actually clear its own freshness bar and mint — the entire "a real human approves a risky edit" flow was unreachable in any released version.WatchSupervisor::refreshnow records aReconciledevidence snapshot after each full reconciliation cycle; a new integration test drives the previously-broken loop end-to-end (reconciliation → mint → spend → receipt written). - Redacted-secret writeback: submitting a
source()-returned body with its[REDACTED:...]placeholder still intact as new content is now refused outright (LOSSY_WRITE_REJECTED) instead of silently overwriting the real secret on disk with the literal placeholder string. - Authority mint and transaction-begin are now atomic (
authorize_and_begin_edit): previously, atxn::beginfailure — or a gate check firing after the authority was already consumed — could permanently burn a valid authority with no file write and no durable transaction row to show for it. - A stale
ChangeIntent(evidence drifted sinceplan_change) is now superseded rather than silently reused:review_changerefuses to mint against a superseded intent and points the caller at its replacement. state.dbmigration no longer bootstraps the full current schema before running version migrations on a non-empty database — previously safe only by accident (every current-schema statement happened to be idempotent); now branches cleanly on empty-vs-versioned, both paths transactional.compute_hotspotswithmin_churn=0now actually surfaces zero-churn complexity debt (previously always empty, since candidates were seeded only from the git churn map).- A full reindex previously left stale
type_relations/symbol_effectsrows behind for any symbol whose qualified name survived the rebuild, silently corrupting T1 facts and the Architecture Digest built from them. import_bundlenow honorsconfig_fingerprintdrift (previously only commit/version match) when deciding whether a full reindex is required.- 13 further correctness fixes from a line-by-line audit of the maintenance outbox, transaction/graph logic,
diff_impact, and memory/session subsystems (race conditions intxn::advanceand the maintenance-job lease, coreness split into confirmed-only vs.possible_coreness, C-style quoted-path parsing in diff output, language-aware signature-change comparison, HTTP session-leak cleanup, and more) — see commitda3c14ffor the full list. - SCIP-Ruby occurrences were silently dropped (missing encoding-fallback entry); nightly indexer-subprocess failures across languages were undiagnosable because the test harness never installed a tracing subscriber, hiding the real stderr failure reason for weeks.
- Rust resolver: unqualified method calls no longer confidently fan out to an unrelated same-named local function.
resolve_sites_to_edges(crates/calm-core/src/indexer/pipeline.rs) now downgrades a.-receiver call toAmbiguouswhenever its receiver's type never resolved (target_classstayedNone), whichever narrowing branch (same-file, same-directory, or the final unscoped by-name fallback) happened to produce the match —self/thisreceivers are excluded (their real type is the enclosing impl by construction). Root-caused viabenchmarks/b2_call_graph_quality, which had silently measured 0.0 precision on theinferred/resolved/textualconfidence tiers in CI since the gate was added (2026-08-04) without ever passing:crates/calm-core/src/analysis/coverage.rs's realrow.get(..)calls (arusqlite::Row::get, receiver of a type this indexer never tracks) were among 1114 false edges all pointing at the unrelatedcrates/calm-core/src/txn.rs::get— the only "get" in the entire Rust symbol table — andcrates/calm-server/src/tools/edit.rs's own.as_str()on aStringfield was similarly misattributed to the unrelated localGateRequirement::as_strpurely by same-file coincidence. See issue #72 for the full investigation, including a documented-but-not-yet-fixed third mechanism (fully-qualifiedstd::-rooted paths) and a separate benchmark-oracle coverage gap unrelated to the resolver itself.
state.dbschema advanced through several versions over this cycle (a forward-migration executor was added and then reused for authority durability, approval receipts, provenance, and signature columns) — seedocs/plans/2026-08-08-master-change-control-execution-blueprint.mdfor the full audit trail.docs/guarantee-levels.toml/docs/status.generated.mdare the live source of truth for which of the behaviors above areenforcedvs.advisory/best_effort— several entries in this release tightened from the latter to the former.
- Opt-in WS-6 first-slice verification (
docs/plans/2026-08-03-ws6-verification-pipeline-execution-plan.md):[verification] rust_check_on_write(default off) routes a.rswrite through the durable transaction'sVERIFY_PENDINGstate instead of straight toDone; newverify_change(tx_id)tool runscargo checkscoped to the nearest Cargo package and advances the transaction toDone/Failed-- a failed check does not revert the file already written to disk plugins/calm/.claude-plugin/plugin.json'sversionis now checked againstCargo.toml's (scripts/check-doc-truth.sh) so the Claude Code plugin manifest can't silently drift from the release it bundles againverify_changenow binds to the transaction'sproposed_digest, checked both immediately before and immediately aftercargo checkruns -- a concurrent write can no longer get bound to someone else's verification receipt (VERIFICATION_SNAPSHOT_CHANGED)[verification] timeout_secs(default 120s):cargo checkis killed if it hangs (a stuckbuild.rs/proc-macro/registry fetch) instead of blocking the tool call indefinitelycalm initnow creates.calm/atomically at0700(matching the daemon's own posture) instead of a plaincreate_dir_allat the umask default;calm doctor --fixadditionally retightens an already-loose.calm/and its sensitive files (index.db,memory.key,daemon.log,audit.log,daemon.sock)- Non-loopback
calm serve --httpnow forces a capability-derivedremote-safepreset (every tool declaringread_only_hint = true, computed live off the tool router) instead of the oldfull,-edittoolset exclusion, which only ever disablededit_lines/edit_symbol/format_files--remember,verify_change,retry_maintenance,scip_refresh,lsp_refresh,set_toolset, andpattern_debt_registerare now also excluded by default over an unauthenticated-by-default remote transport - The audit ledger (
audit_ledger) is now HMAC-SHA256-signed (keyed by a new 0600.calm/audit.key, separate frommemory.key) instead of a plain unkeyed SHA-256 chain -- an actor with only SQLite file write access can no longer forge a chain that still passesverify_chain calm setup --npxnow pins the written entry to@eilodon/calm-mcp@<this binary's own version>by default instead of an unpinnednpx -y @eilodon/calm-mcp, so a coldnpxinvocation always resolves to the same release;--track latestopts back into the old unpinned behavior.calm/config.jsonrisk_rules(default empty): a path-glob-to-minimum-risk floor (e.g.{glob: "**/auth/**", minimum: "high"}) that the write gate can never classify below, closing the gap where a low-fan-in but security-sensitive file read as low risk regardless of caller countremembernow quarantines a note whose content trips the prompt-injection heuristic (still saved, same detection-only philosophy) andrecallexcludes quarantined notes from its ambient/broad paths (FTSquery, no-args list-all) by default -- an exacttopiclookup still always returns it, mirroringedit_context's existingrelated_notesambient-surfacing gateKNOWN_LIMITATIONS.md: an honest catalog of what CALM doesn't do yet and why each gap is deliberately deferred rather than half-built- Indexing now skips any file over 8 MiB (
read_source_capped, checked via a cheapmetadata()stat before ever reading the file) and bounds a single tree-sitter parse to 5s (Parser::set_timeout_micros) -- a pathologically huge or deeply-nested file can no longer hang or balloon the indexer's memory compute_touch_risknow escalates risk to"high"when an edit's own proposed content actually changes a touched function/method's signature TEXT (not just overlaps its line range -- a whole-body replace that leaves the signature byte-for-byte identical does not escalate), reusingdiff_impact's ownis_signature_semantically_changed/escalate_risk_if_signature_changedcalm serve --httpnow caps request body size (16 MiB,axum::extract::DefaultBodyLimit) and concurrent in-flight requests (64,tower::limit::ConcurrencyLimitLayer) as defense-in-depth against the unbounded-resource gap a bareaxum::Routerhad; still not a substitute for a reverse proxy's real rate limiting- New
reference_impacttool: merges call edges, import edges naming a symbol, and a repo-wide textual grep into one classified reference list (must_change/likely_change/review/textual_only) for rename/removal planning -- closes the exact gap behind two realbenchmarks/b7_task_correctnessmisses (a bare re-export statement invisible to the call graph alone) edit_lines/edit_symbolgained an optionalcitesparam: the EXACTqualified_nameof a calleredit_contextreturned this session, checked by equality rather than the existingreasonfield's word-boundary substring search -- closes the "paste a real caller name into an unrelated sentence" gaming path for callers that opt in; the free-textreasonpath remains for backward compatibility- A real on-disk audit ledger connection whose
audit.keycan't be read or created (e.g. a read-only.calm/) now fails the write closed (LedgerError::KeyUnavailable) instead of silently falling back to the old unkeyed, forgeable SHA-256 chain -- the existingappend_ledger_in_savepointsavepoint rollback (P0-4: a ledger failure must never block the write it's auditing) already does the right thing onceappendactually signals failure, now with a warn-level log so the gap is observable calm connect --presetnow takes effect even when attaching to an already-live daemon, not just when this connection is the one that spawns it: a one-line handshake preamble ahead of the raw MCP byte stream lets each connection narrow its own effective tool ceiling (CalmServer::narrow_connection_preset), reusing the sameresolve_preset/current_visible_tool_namesmachineryset_toolsetalready enforces -- a too-wide request is a no-op, never a privilege escalation, since the daemon's owntool_router(built once at spawn time) stays the hard ceiling- New
batch_statustool: takes a caller-supplied list oftx_ids (the ones a set ofedit_lines/edit_symbol/format_filescalls already returned) and reports one aggregate view -- counts by state, which are missing, whether any failed -- instead of requiring a separateedit_transaction_statuscall per file for a multi-file change. Observability only: doesn't group transactions server-side or change what those write tools do (seeKNOWN_LIMITATIONS.md"No multi-file change-set / transaction") - New
calm guardCLI command: runs the exactdiff_impacttool an MCP agent's own Stage-7 pre-commit gate uses against the staged diff (git diff --cached) and exits non-zero whenaggregate_riskis at or above--fail-on(defaulthigh) -- a first Git/CI-native integration point for changes made outside any MCP session (a teammate's native editor, a bot PR), usable directly as a pre-commit hook or CI step - Durable state (
project_memory,project_memory_refs,edit_transactions,tx_events,maintenance_jobs,audit_ledger) now lives in a separatestate.db(PRAGMA synchronous=FULL,db::conn::open_state_writer) instead of sharing the rebuildable index'sindex.db(synchronous=NORMAL) -- every real call site (remember/recall,edit_transaction_status/batch_status/maintenance_status/retry_maintenance/repair_consistency/verify_change, the shadow-tx paths insideedit_lines/edit_symbol/format_files, and the OS-level crash-injection harness) now reads and writes through it;db::schema::migrate_legacy_durable_tablescopies any pre-splitindex.db's durable rows intostate.dbonce, idempotently, on first startup after upgrading. ClosesKNOWN_LIMITATIONS.md"Durable state and the rebuildable index share one SQLite file at runtime"
- Durable edit-transaction journal (
txn.rs) and maintenance outbox, wired intoedit_lines/format_files, with a startup recovery hook and 4 new admin tools (edit_transaction_status,maintenance_status,retry_maintenance,repair_consistency) exposed under a newtxntoolset - Append-only, hash-chained audit ledger (SHA-256 evidence digests) as a durable channel alongside tracing
- Caller-set-digest TOCTOU guard on the edit gate: an unrelated edit that changes a symbol's caller set since
edit_contextreviewed it now rejects the stale review (STALE_CALLER_SET) instead of trusting it - Write-safety enforce-transition: no write path can bypass
EditTransaction; critical-risk edits without an approver are blocked - 3-mode symlink containment (
path_policy.rs) wired into repo-path resolution - OS-level crash-injection test suite (
txn_crash_injection): self-raised SIGKILL after every reachable transaction-state transition, verified against disk/ledger consistency, 100 iterations/transition release.ymlqualify-releasegate (fmt/clippy/test/audit/stack-graphs corpus/fitness-check/doc-drift/cross-SDK interop) that binary and container publish jobs now depend on — a tag push can no longer reach a release without it- Refresh reconciliation and bounded watcher supervision: shared input catalog, durable input fingerprints, explicit health reporting distinguishing completed-index state from live filesystem observation
edit.rsand the transaction tool surface reuse a single writer connection per file instead of re-opening per step; independent transaction advances batch under oneBEGIN/COMMIT
- Rust
Self::method()calls (insideimpl/traitblocks) resolved to zero call edges instead of the enclosing type —target_classnow substitutes the real enclosing type/trait name instead of the literalSelfkeyword - Duplicate
call_sitesinserts aborted the whole indexing transaction instead of being skipped, permanently failing indexing on affected repos watcher_integrationtests could leak a background thread and temp directory for the process's life if a panic unwound past cleanup- Indexer-to-analysis architecture boundary violation introduced by watcher-supervision work
- CI jobs had no
timeout-minutes, letting a hung test silently occupy a runner for GitHub's 6h default instead of failing fast Cargo.lockinternal package versions left stale after a workspace version bumpcargo fmtviolations in the indexer test module
0.4.0 - 2026-08-01
- Martin/OOD metrics, ownership-entropy risk signal, churn-aware search ranking
- Dart call-edge extraction
- Elixir bare-name calls gated by arity, not just name
- JVM and Go imports resolved from declarations instead of layout guesses
b7_task_correctnessbenchmark: real rename refactors across 6 language corpora (Rust, Python, JS, TS, Go, Java), checked against an independent pass/fail oracle- Optional local-ONNX embedding backend (
tract) as an alternative to the vendored default model - Per-session dynamic toolsets:
enabled_toolsetsfield,set_toolsettool, safety-floor enforcement atlist_tools/call_tool - Opt-in OpenTelemetry span export behind the
otelfeature - Opt-in Streamable-HTTP transport (
calm serve --http) — loopback-only by default, fail-closed (--allow-remote+ bearer token required for non-loopback), forces a read-only preset remotely formal_sourceper-edge provenance surfaced on 5 read tools; SCIP-vs-stack-graphs override disagreement observabilitystack-graphs-formalfeature gate — the stack-graphs family is now default-on but opt-out, instead of hard-wired- SCIP-primary
CallSitebyte-span provenance - Issue templates, CODEOWNERS, and this CHANGELOG
- The 6 resolution maps bundled into a single
ResolutionMapsstruct tools/common.rssplit into toolset/outcome/detail modules to clear thehotspot_riskfitness gate- Formal-resolution timeout ceilings made deterministic; a previously-silent timeout swallow now surfaces
- Deduplicated derived-edge tables; sharpened
search/edit_contextprecision - SCIP-disproven and ambiguous edges no longer corrupt graph traversal (
ruled_out_by_scipfilter applied across all remainingcall_edgesconsumers) - Vendor packages no longer counted as first-party imports in benchmarks
- Transitive
@hono/node-serverdependency bumped to patched 2.0.10+ knn/knn_chunksembedding cache no longer collides across:memory:SQLite connections- B1-B4 call-graph accuracy gaps found by the 2026-07-28 benchmark root-cause (indexer/SCIP)
- B12 upgrade-plan findings F1/F2+F2b/F4 (JS/TS call-graph blind spots outside named-function bodies; edit/diff-impact fixes)
- Java
this.field.method()call-graph blind spot opentelemetry_sdkdependency alignment — pinned to a single resolved core version after a Dependabot bump broke the build
0.3.6 - 2026-07-22
- Repo overview timeout analysis and follow-up fixes.
0.3.5 - 2026-07-21
- Human-in-the-loop elicitation veto for hub/high-risk edits — escalates confirmation to the client UI instead of agent self-confirmation.
- Transient re-acquire failure in the
instance_lockCI test (flake, not a real race) cargo fmtCI check
0.3.4 - 2026-07-19
server.jsonwas missing theservepackage argument, so registry-driven installs launched a dead server. Metadata-only release; no code changes.
0.3.3 - 2026-07-19
- Release job now only downloads
calm-*artifacts — an unfiltereddownload-artifactstep was racing Docker's*.dockerbuildartifact, which broke v0.3.2's release.
0.3.1 - 2026-07-18
- Windows and macOS Intel (x64) binary distribution
- Native hooks doctor-fix CLI subcommand and markdown semantics specs
- Daemon respawn race and flaky test timing assumptions
- Stale
"ci"reference inedit_linestool description
0.3.0 - 2026-07-15
- Composable toolset presets, tool schema snapshot tests (toolsnaps), cosign-signed release images, cross-SDK interop CI
calm init --hooks[=nudge|enforce|off]generic hook scaffold (portable beyond Claude Code)calm init --agents-mdscaffold +get_infoinstructions pointer for external onboardingcalm_workflowMCP Prompt +calm-guideSkill- SCIP toolchain sidecar Containerfile (Java/C#/PHP)
- Release binary provenance attestation (
actions/attest-build-provenance) - Install hint surfaced in
repo_overviewwhen a SCIP provider is unavailable
- DEBT-010 hook-state TOCTOU race
- Source-aware idempotent SessionStart injection
deny()hook migrated to exit-2 (also fixed a real stderr-swallowing bug found along the way)scip-nightlyrestructured into per-language jobs; added Ruby + Clang; fixed a PHP crash
- Session-state parse skipped and cleanup made probabilistic on the hot hook path
0.2.0 - 2026-07-13
- One-command install:
calm setup --npx, automated release train - Line-numbered, edit-ready
source()reads with range mode edit_symboltop_of_file/end_of_fileanchors and small-text-match mode- Incremental graph update, on by default
edit_contextgate mishandling path-form arguments (false-denies)calm-nudgeadvisory hook redesigned for precision and a visible cost signal- Local
config.jsonoverrides now surfaced inrepo_overview's health summary
0.1.4 - 2026-07-08
- Official MCP Registry listing, Claude Code plugin, Cursor deeplink
- SCIP providers: Java, JS/TS, Python, Go
- Standalone SQL indexer (
sqlparser-based, deliberately no call graph — "calls" isn't coherent across SQL dialects) - C#, C/C++, PHP heuristic indexers; JavaScript formal tier via Stack Graphs
- SCIP ops surface:
calm scip-run,--scip-file,scip_refresh
crossbeam-epochbumped to 0.9.20 (RUSTSEC-2026-0204)
0.1.1 - 2026-07-05
install.shand npm package distribution- Default embedding model vendored into the binary at build time (no Git LFS, no runtime network call)
- Several indexer accuracy gaps: dead-code/hub false positives, credential-redaction coverage,
super::sibling-submodule import resolution, SCIP confidence-upgrade overlay re-running on incremental reindex (not just server startup)
0.1.0 - 2026-07-02
Initial public release — core MCP tool surface, resolver, search, fitness-check CLI, Layer-2 code-body chunk embeddings for semantic search.