Label the judge, then measure it
judge.logContent (off by default) keeps the query, draft head and candidate heads beside each logged verdict. metalmind judge review walks unlabelled decisions and stores right or wrong; judge report turns those labels into precision for refusals, uncertain verdicts and recall, split by score and confidence band, and counts how often the top judged hit is the note you opened next. Local file, owner only.
Antigravity is a host
init and burn brass offer Antigravity when ~/.gemini/antigravity exists (--host antigravity, or all). The metalmind block lands in ~/.gemini/AGENTS.md, which Antigravity reads as a global rule, and the six skills go to ~/.gemini/config/skills, its global customization root. Uninstall strips both and leaves your own rules alone.
The judge sees what a reader would, and keeps a log
Drafts, overlap candidates and recall hits now reach the judge with title, kind, project, tags and dates beside the text. A covered verdict refuses only when the judge is confident (0.6 and up); a spread-out one creates the note with a covered? line. Every judged call appends one content-free line to ~/.metalmind/judge-log.jsonl (scores, confidence, probabilities, files, decision, --force overrides, latency, tokens), and metalmind judge report --days N turns a week of use into refusal and override counts, kept ratio, histograms and cost. METALMIND_JUDGE_MODE=each sends one request per hit for comparison; batched stays the default. Without a key nothing changes.
pass is the Linux key store for the judge
The judge key is resolved from TYPESAFE_API_KEY, then the macOS Keychain, then pass show typesafe-api-key; init and judge enable write to pass on Linux. judge status names which source answered, so a key that is set but not found is a one-line diagnosis rather than a silent unjudged.
init asks about Jev judgments
Default no. On yes it finds an existing key or takes one and stores it in the macOS Keychain under typesafe-api-key; elsewhere it points at TYPESAFE_API_KEY. --judge and --no-judge cover scripted installs, and --yes leaves the judge off. Without a key metalmind behaves exactly as it did before 0.25.0.
An opt-in judge replaces the cross-encoder, and scribe refuses covered drafts
metalmind judge status|enable|disable turns on Jev (TypeSafe) judgments; METALMIND_JUDGE=0 turns them off for one shell. tap copper sends the top 10 fused hits to the judge and shows them in judged relevance order with off-topic hits dropped and judged: N of M kept beneath; --no-judge per call. scribe create and scribe update score a draft against overlapping notes before writing and refuse one an existing note already covers, naming that note and the scribe update shortcut; --force overrides, and a partial overlap prints an extends line instead. Every judged command reports its own failure inline as unjudged: <reason> and keeps its exit code. The cross-encoder --rerank tier is removed: on the maintainer vault the judge matched or beat it on every query and, unlike it, returns nothing on questions the vault cannot answer. --rerank survives as an alias of the judged order; the Python [rerank] extra stays one release for installs that already have it.
teardown swept the real ~/.claude instead of the directory it was given
cleanupOutputStyle defaulted its four paths to the running user's home and teardown overrode only two of them. Uninstall was unaffected, since there the two directories are the same; running the test suite was not, and it deleted the developer's own output-styles/marsh.md and skills/marsh. Teardown now derives every path from its claudeDir, and a regression test pins the sweep inside the sandbox.
The marsh and telegraph output styles are gone
Claude Code now ships its own brevity styles, so maintaining a competing pair stopped earning its keep. The whole subsystem goes with them: the style assets, the two self-triggering skill bundles, the SessionStart activation hook, the UserPromptSubmit re-anchor hook, and the outputStyle object in config. Deleting the code does not undo what earlier versions wrote into ~/.claude, so metalmind stamp now sweeps the style files, skill directories, hook scripts and settings registrations, and restores settings.outputStyle to whatever it held before metalmind first overwrote it. A style you chose yourself is never touched. Config schema v5 drops the outputStyle object. flavor: scadrial | classic still picks the verb set; it no longer picks a voice.
Reranking is 5.6x faster and ranks the same
0.22.0 shipped the cross-encoder at 8.0s per query. That cost was almost entirely batch shape: scoring is one ONNX call over a candidates-by-tokens tensor, and the batch was 20 x 512. It is now 10 x 256 and the query takes 1.3s instead of 7.5s. Ten candidates because only 2 of 93 adversarial queries have the wanted note deeper than rank 10; 256 tokens because that is the knee of the length curve, with hit@1 holding at 62% and falling to 55% at 128. Measured identical on 593 queries, including LongMemEval hit@1 49% to 50% with MRR unchanged. Trading model size for sequence length is the wrong direction: the smallest cross-encoders rank worse than not reranking at all. METALMIND_RERANK_GATE (off by default) skips the pass when fusion already separated a winner, and METALMIND_RERANK_MIN_CANDIDATES exposes a floor that was hardcoded at 20.
The reranker informs the ranking instead of replacing it
Reranking cost competing-near-duplicates 15 points of hit@1 and 0.21.0 called that a property of cross-encoders. Tracing all 20 regressions showed every one was a sibling swap caused by two defects: the cross-encoder was scored against chunk text with no note title attached, so it never saw what distinguished a note from its sibling, and it then sorted on its own score alone, discarding the fusion rank BM25 had earned by matching that title. The title is now supplied and the two rankings are fused with RRF (METALMIND_RERANK_ALPHA, default 0.5). Near-duplicates goes 65% to 85%, adversarial hit@1 58% to 63%, and LongMemEval 44% to 49% with MRR 0.54 to 0.59. Date ordering now shifts by bounded rank positions (METALMIND_TEMPORAL_MAX_SHIFT, default 8) instead of multiplying a score whose scale depended on the previous stage. Also fixed: the vector index is sized from the model rather than a hardcoded 384, and the LongMemEval harness refuses to benchmark a build that is not the checkout under test.
Two chunks of one note are two documents, and the index says what built it
Fusion de-duplicated hits on (file, heading), which is a proxy for chunk identity that holds only while a section produces one chunk. Past that, two different chunks collapsed into one hit keeping whichever retriever answered first - neither the best-scoring nor a deliberate choice. Identity now includes chunk position, worth hit@1 36% to 44% on LongMemEval at 3,000 sessions and 17% to 39% on the category that asks what you said about yourself once, measured in isolation against a single index rather than inferred from the bundle. A cap of one chunk per note stops a long note taking every slot it now competes for individually. The index also carries a stamp naming the format, chunker and embedder that built it, so a stale index is detectable rather than quietly answering with chunks this code would never produce: metalmind index status reports it, metalmind index rebuild fixes it. Published recall-v0 numbers are remeasured against a distractor corpus that is now committed instead of regenerated, because a formatting sweep had edited the generator months earlier and the corpus behind those numbers no longer existed.
sync stops calling every archive move note loss
The deletion guard matched a removed note against surviving content by blob hash alone, and archiving is not a byte-for-byte move: metalmind gold rewrites status: and updated: on the way to Archive/, and a session note often gains its outcome at the same time. Git's own rename detection does not bridge that either - on the change set that prompted this, a note grew from 46 lines to 103 and -M failed to pair them. Every archive move therefore hit unexplained-deletion and needed --force, which is exactly the habit a safety guard should not teach. A deletion now also counts as explained when a note of the same name is added anywhere in the same commit, and is reported as a move rather than passing silently. Deletions whose name and content both vanish are still refused.
0.20.0 never switched itself on
Calibration ran at the end of a full reindex, and the watcher only rebuilds when the index is empty, so an existing install upgraded, restarted, and silently kept reporting no confidence. There was no way for a user to trigger it either, since metalmind reindex is retired. The watcher now derives bands at startup when the collection has none, working against the index already on disk: seconds rather than the minutes a rebuild costs, after the recall endpoint is already serving, and once per collection. A vault that cannot support bands retries on the next start rather than recording its refusal, because a vault too small to calibrate today may be large enough tomorrow and a marker file would need to solve its own staleness problem.
Recall says when the vault probably does not hold an answer
A recall whose best hit falls below the vault's own low edge now says so, instead of returning five confident-looking hits about nothing. The threshold is derived per vault rather than shipped as a constant, because cosine distributions are shaped by the genre and vocabulary of the corpus, and a number tuned on one vault describes that vault. Calibration can refuse, and refusing is the point: a vault under 50 usable samples, or one whose probes score as highly as its answerable questions, produces no bands at all rather than a wrong threshold. Nothing changes until a vault reindexes, so no install silently acquires a gate it did not ask for. Verified on a second vault nobody here wrote - xy-241/CS-Notes, MIT, 683 notes - which calibrated unaided.
A reindex no longer locks recall out of the vault
Pulling a synced vault on a second machine, sweeping notes into Archive/, or any bulk edit would take recall down entirely for the duration of the reindex, returning database is locked rather than degrading. Measured on a real pull of 81 changed files: two and a half minutes during which every query, and even a bare PRAGMA read, was refused. Two causes: both SQLite databases opened with the default rollback journal, where a write transaction that outgrows the page cache escalates to an exclusive lock and blocks readers outright, and reindex_paths wrapped an entire batch in one transaction so that lock spanned the whole run. Both now open through a single helper setting WAL and a 30-second busy timeout, and the reindex commits per file. Journal mode is a property of the file, so existing installs upgrade in place the first time the updated watcher opens them. This is the workflow metalmind exists to support failing precisely when an agent is most likely to ask for context.
First externally-labelled recall numbers, including unflattering ones
bench/longmemeval/ builds a fixture from the third-party LongMemEval dataset (MIT): one markdown note per conversation session, with human-labelled answer_session_ids as the expected files. At a 3,000-session haystack, plain hybrid retrieval scores 36% hit@1 and 68% hit@5 over 470 answerable questions. The spread matters more than the average: single-session-assistant, the task closest to vault recall, scores 91% hit@1 with zero misses, while single-session-preference scores 13%. That is the retrieval-versus-extraction boundary, now with numbers on it. The abstention control also found a structural blind spot: questions with no answer anywhere in the corpus produce fused scores indistinguishable from answerable ones, because RRF ranks by position and discards similarity magnitude.
Token-lean recall, and a port that refuses browsers
The cheapest recall call is now paths and titles only (--files); --budget caps total output at roughly N tokens by shrinking snippets down a ladder before dropping hits, so a tight budget yields thinner hits rather than fewer; --neighbors returns the prev/next chunks around each hit for snippets that cut off mid-thought, recovering chunk position from the FTS table with no index change and no reindex. Separately, 127.0.0.1:17317 is loopback-only but reachable by every UNIX account on the machine, unlike the vault directory that file permissions protect: browser-origin requests are now refused unconditionally, and an opt-in token generated at ~/.metalmind/recall-token (mode 0600) is sent automatically by the CLI but not enforced by default, since on a single-user machine it would buy nothing. Also: scribe create warns about near-duplicate notes, vault-doctor --stale reports notes untouched for 90+ days, and both recall harnesses gained MRR and NDCG@5 because hit@k could not distinguish everything at rank 1 from everything at rank 2.
Try the memory thesis without installing the workflow layer
Evaluating whether recall is any good used to mean accepting the whole library first: Serena, 15 subagents, four team commands, and the deliberation skill, behind eight prompts. metalmind init --core installs recall, scribe, the stamped CLAUDE.md block, the rules and uninstall - 10 files against 40, zero subagents against 15 - and stops asking about what it is not installing. Re-run init without the flag to add the rest; the copy is idempotent, so nothing is lost by starting small. --core narrows defaults rather than overriding you: pass --teams or --serena alongside it and you get those, and an explicit --teams brings the subagents its commands dispatch instead of leaving a surface that looks installed and fails on first use.
The Qdrant + Ollama backend is gone, and 50k proved it could be
sqlite-vec + fastembed became the default in v0.5.0 and the escape hatch went unused for ten minors while charging a qdrant-client dependency, two backend implementations, 142 lines of Docker setup, a Docker prerequisite, and three doctor probes. Removing it was gated on one unanswered question: does in-process retrieval hold at 50,000 notes? It does - 95% hit@1, 100% hit@3, zero misses at k=5, 617ms p95, no server and no daemon. Getting that answer meant fixing the bench first, which had been scoring correct answers as misses: it froze the gold set at seed time, so once the corpus grew to include unlabelled comments from the same thread, a right answer outranked a labelled one and reported 25% hit@1 while 19 of 20 top hits were on the correct story. METALMIND_BACKEND=legacy now raises instead of silently re-embedding your vault with a different model than the index was built with.
burn iron returns, and the graphify hook actually goes
0.15.0 retired burn iron along with the graphify dependency, but those were not the same decision - the dependency had to go, the capability did not. It is rebuilt on metalmind's own symbol extractor: where is this symbol declared, in one repo or across a forge, with no index and no external tool. Callers and call paths still need a parser, so the output says so and points at codegraph instead of pretending. Also: 0.15.0 delegated hook removal to graphify claude uninstall, which is project-scoped and never touches ~/.claude/settings.json - so the user-scope PreToolUse hook survived the upgrade and kept firing against a graph file whose generator was gone, while doctor reported graphify-residue none because it never inspected hooks. metalmind now strips that hook itself, the residue check reads settings.json, and the repair runs automatically on the next ordinary command rather than requiring init. Also: init stops discarding config it does not own (registered forge groups, verbose, embeddings, recall all survive a re-run) and backs up any file in ~/.claude/rules/ you had edited before replacing it. Plus: the supersede integrity check treated every frontmatter value as a note pointer, so a note that said supersedes: v1 (Gateway+Relay), v2 (bookings share_sessions) reported an unresolvable pointer with no way to declare it prose - permanently red, on every machine the vault reached. Values are now classified by shape: anything with whitespace, commas or brackets was never a stem, so it is surfaced as a notice with the fix rather than a failure. Stem-shaped pointers that do not resolve still fail, and still outrank prose in the report. scribe supersede also stops demanding --force to overwrite a prose value, since that was never a link to protect.
codegraph owns the inside of a repo; forge owns what happens between them
burn bronze, burn iron, burn pewter and the graphify dependency are gone. Within-repo code-graph work belongs to codegraph, which is local, MIT-licensed and does it better - metalmind installs alongside it rather than wrapping it. Forge, the one part that genuinely depended on graphify, now extracts symbols from your source during the walk that already produced route edges, so name-match and route-match edges both survive with no external tool and no indexing step. Querying moves to metalmind forge query. The retired commands print the codegraph equivalent instead of failing as unknown, config migrates itself, and doctor names any graphify left on your machine.
doctor surfaces the Intent skills sitting unused in your dependencies
Packages can ship SKILL.md guidance that travels with them through the registry. The new intent-skills check asks each forge-registered repo's own intent binary how many its dependencies expose, and names them. Informational by design: it never fails, never changes doctor's exit code, installs nothing, and deliberately does not copy skills into the vault - their value is that they stay versioned with the package, so a vault copy would manufacture the staleness Intent exists to prevent.
scribe --code and auto-memory naming get their rough edges filed off
scribe update --code blocked on stdin without a body, so re-stamping refs meant piping a dummy body, and --code "" could never clear refs. Auto-memory filenames joined project and topic with a single hyphen, so project a + topic b-c collided with a-b + c; the separator is now a double hyphen and notes imported under the old name are renamed rather than duplicated. Ingest conflicts now name the source file as well as the vault note.
Code refs tell a definition from a call site
The definition pattern and the loose fallback ran as one ripgrep call, so a leftover call site or a mock was indistinguishable from a real definition and the exact staleness the feature exists to catch reported a clean ok. They now run as separate stages, with reference-only matches surfaced by doctor as worth checking rather than as failures - and func, record, object, and module join the definition keywords, since Go definitions had been reaching ok through the fallback. Also: tap copper --json emits structured code_refs per hit, repeated lookups are memoised per run, notes sharing a filename stem no longer vanish from the checks, and imported auto-memory carries no username in source_path.
Frontmatter parsed with a real YAML parser
metalmind already shipped the yaml package and used it only for OpenAPI specs, while ten files hand-rolled note frontmatter parsing - the source of a cluster of bugs. Quoted values kept their quotes, Obsidian's block-sequence lists were invisible, a value on the line below its key was missed, a multi-line block scalar could leak what looked like a nested key, and a fixed 2 KB read dropped the frontmatter of notes with many tags or links. One shared reader now backs scribe, code refs, doctor, ingest, and recall. The write path is untouched, so no existing note is reformatted.
Code-aware memory validation and auto-memory ingest
Notes can carry code: ["repo#symbol"] refs; tap copper --verify-code and a new doctor check flag refs whose code no longer exists in your forge-registered repos, resolved by definition-shaped ripgrep with per-repo and per-run time caps. metalmind ingest auto-memory pulls Claude Code native auto-memory topic files into the vault as Memory/ notes with hash-based provenance - idempotent, and it reports a conflict rather than clobbering a note you edited. Also hardens vault containment against symlinks arriving via git sync, quotes control characters in frontmatter values, and stops ingest from dropping frontmatter keys it does not own.
Temporal supersedes: decisions replace each other without deleting history
scribe supersede <old> <new> marks a note as replaced by its successor via frontmatter (status: superseded, superseded_by, supersedes). Recall downweights superseded notes 0.4x in fusion - stacking with folder penalties, surviving archive, reaching the rerank path - and every hit from one carries superseded_by so agents land on current truth. Nothing is hidden: history re-ranks below its successor with a signpost. Also fixes stamp to restart the watcher after a vault-rag reinstall, so recall-layer changes actually take effect on upgrade instead of waiting for an unrelated restart.
Adaptive recall fusion, folder penalties, and in-place note edits
Recall fusion weights now adapt per query: exact-match tokens (UUIDs, numeric IDs, ticket IDs, hostnames, emails) raise the keyword-leg weight, since BM25 beats embeddings on literal identifiers. Fused scores are folder-weighted - Archive/ 0.4x, Inbox/ 0.7x - so stale notes re-rank below in-flight work without being excluded. scribe patch gains --find/--replace for targeted in-place edits (frontmatter protected, ambiguity resolved via --occurrence). tap copper gains --semantic-only/--keyword-only, previously documented but unimplemented. stamp now refreshes installed output styles from bundled assets, and release-check gates docs version claims against package.json.
Shell-alias install reports what actually happened
stamp printed "sourced in 0 shell rc file(s)" after a successful re-run because the append helper returned the same false for "already present" and "file missing", and the wizard hardcoded .zshrc in its success line even on bash-only machines. The helper now returns a three-way outcome and both commands name the actual files touched. templates/zsh/ renamed to templates/shell/ since the file has been shell-agnostic since bash support landed.
metalmind duralumin: vault sync with note-loss guards
One command pulls with rebase and autostash, stages, checks the change set, commits, pushes, and then asks git whether the remote actually advanced instead of trusting the push exit code. It refuses three shapes: a deleted note whose content survives nowhere in the commit, a commit that only removes notes, and entries left unstaged after git add -A. Matching is by blob SHA, so undetected renames pass while genuine deletions do not. Born from a real incident: the vault lost 19 notes to an archive move that staged its deletions and dropped its additions. --dry-run, --no-push, and --force available; a refusal resets the index cleanly.
stamp --no-prompt works headless
Commander parses --no-prompt as a negation (opts.prompt = false) but both call sites read the nonexistent opts.noPrompt, so the documented CI flag was a silent no-op that fell through to a TTY-requiring multi-select and crashed with uv_tty_init EINVAL. Now wired correctly, and promptHosts falls back to the previously-chosen host set when stdin is not a TTY.
Recall no longer surfaces trashed notes
scribe delete moves a note into .trash/, and the live watcher indexed that move as a fresh note, letting trashed notes outrank their replacements. Bulk indexer, watcher, and incremental reindex now share one SKIP_DIRS set, and reindex treats skip-dir paths as delete-only so polluted entries self-heal. Also bumps vault-rag to 0.3.1 so the 0.9.3 cache fix actually reaches installed machines on the next stamp.
Scribe path-resolution fixes and a durable model cache
scribe rename with a bare-slug destination silently moved notes to the vault root without .md; plan slugs that already carried a date prefix got double-dated; and macOS periodically purged the fastembed model cache from the system temp dir, breaking recall until the half-cache was cleared by hand. The cache now lives at ~/.metalmind/cache/fastembed/ where temp cleanup cannot reach it.
Bundled agents bumped to Opus 4.8
All 15 bundled agent templates pin an explicit model, and the pin had fallen a version behind. Refreshed from claude-opus-4-7[1m] to claude-opus-4-8[1m]; re-stamp propagates the new pin. No behavioural change.
--compact recall: 74% fewer output tokens, zero retrieval drift
New --compact flag on tap copper / recall renders each hit as a lean envelope (score, path, heading, snippet) instead of full per-hit JSON; the path is the recovery handle for scribe show. Measured at roughly 74% fewer recall-output tokens on a real vault with the returned file set byte-identical between modes, gated by the new bench/compact-v0/ harness. Session stamps now steer agents to compact-by-default; the CLI default stays verbose for scripts.
Cursor as the third metalmind host
metalmind init auto-detects ~/.cursor and stamps it alongside Claude Code and Codex CLI; --host gains cursor and all. Recall rides on the metalmind-recall skill because Cursor 3.1.15 drops sessionStart additional context (staff-confirmed bug); a correct hook ships latent and activates when Cursor fixes it. Also installs 15 subagents, three skills, and opt-in --with-mcp. doctor --deep reports Cursor health; uninstall strips the footprint. 440 tests pass.
Colons in note titles no longer break frontmatter
A title like "Topic: subtitle" was interpolated raw into the YAML title field, producing malformed frontmatter that Obsidian, Dataview, and scribe show all failed to parse, invisibly, because the filename slug was already sanitised. Both frontmatter writers now route scalars through a yamlScalar helper that double-quotes any value carrying a YAML indicator character.
Persona-first output styles; terse renamed telegraph
Rule-list styles drift under load because they compete with the content prior; persona prompts swap the distribution wholesale and stick. Both bundled styles now open with an identity (Marsh the Steel Inquisitor; the Telegraph operator for whom every word costs money) with the rules as supporting material. stamp migrates a legacy terse.md in place, frontmatter rewritten, body preserved.
Per-turn output-style re-anchor hook
The SessionStart anchor from 0.8.10 handles fresh sessions, but styles still faded on long sessions. A new UserPromptSubmit hook emits a ~25-token reminder every turn, keeping the active style at the top of attention. Claude Code only; independent settings entry so either hook can be disabled alone.
scribe create examples corrected in skill and cookbook
Follow-up to 0.8.11: scribe create takes a plain title plus --kind, never a kind:slug argument; that shortcut only addresses existing notes (update, patch, gold, delete, show, rename). The writing-vault-notes skill and cookbook now state the distinction explicitly.
Wikilink guidance is plain-stem only
The skill and cookbook told agents to write [[kind:slug]] wikilinks. Obsidian has no kind: resolver and : is an illegal filename character, so every such link was broken by construction. Guidance is now plain stems only ([[cache-fingerprints]]), which resolve vault-wide and survive archives.
Output styles stop drifting after /compact
Claude Code loads a style body into the system prompt once at session start; the section then loses weight against accumulating context. A new SessionStart hook re-anchors the active style body as additionalContext every session, and marsh / terse skill bundles add phrase-match self-triggering ("be brief", "marsh mode") for mid-session activation.
Shipped rules trimmed under the 12k cap; Obsidian is optional, says so
The bundled rules/ set carried ~14k chars across 7 files, over the recommended 12k combined limit that Opus 4.7 punishes more literally than 4.6 did. principles.md is cut to six load-bearing sections and tool-philosophy.md is deleted, including from existing installs on next stamp. Fourteen call sites stopped implying Obsidian is a runtime dependency: the vault is plain markdown and Obsidian is one optional viewer.
Claude and Codex managed blocks share one source of truth
The two host block templates were maintained as parallel files and had drifted: the Codex variant silently omitted classic aliases, --dry-run, and the entire Forge paragraph. Both now reduce to a shared partial include, with a regression test that fails if either ever holds inline body content again. Shipped rules also stop naming the maintainer’s private tools and scope JS/TS-only guidance under explicit subsections.
Watcher unit crash-looped on every fresh install
The launchd/systemd unit invoked uv tool run --from metalmind-vault-rag, which resolves against PyPI where the package has never been published, so the watcher exited 1 on a 10-second restart throttle and recall silently fell back to a broken stdio path while pulse reported all systems nominal. Units now invoke the entry-point shim uv tool install already creates at ~/.local/bin/. A new regression test reads the real bundled templates instead of synthetic ones.
metalmind stamp self-heals broken output-style frontmatter
v0.8.3 fixed fresh installs but the installer (output-style.ts:122 - if !existsSync) skipped the file on upgrade - so every v0.8.0-v0.8.2 user kept the broken name: Marsh stamp and silent default voice through any number of metalmind stamp re-runs. installOutputStyle now detects the case-mismatched twin pattern (on-disk name differs from choice only by case AND body is byte-equal to the bundled asset) and overwrites from the asset. User-edited bodies (case-twin name but diverged body) are left alone. Five tests cover heal-fires / skips-on-edit / skips-on-unrelated-name / skips-when-correct / terse-twin. No rm step required to recover.
Bundled output styles silently inactive on fresh install
Claude Code matches settings.outputStyle against the name: frontmatter case-sensitively. The CLI wrote settings.outputStyle = "marsh" (lowercase) but the bundled cli/assets/marsh.md shipped with name: Marsh (capitalized) - so on every fresh install the file landed, the setting pointed at it, the file looked correct, and the style never applied. Same for terse. Caught only because the user had a pre-existing hand-authored lowercase copy. Fixed by lowercasing the asset name field and the legacy-migration write path. Bonus: dropped keep-coding-instructions: true from both shipped frontmatters - not a recognized output-style field.
metalmind gold rewrites wikilinks across the vault on archive
Same shape as scribe rename: when you archive a note, [[wikilinks]] in every other note that references it get rewritten to the new Archive/ path. Closes the v0.8.1 gotcha where archiving the two Codex plans left dangling links scattered across the MOC. Basename-only wikilinks survive unchanged. Plus: README anti-personas section dropped (was the same fabricated content we removed from the site in v0.7.x); releases page caught up to v0.8.x.
Three v0.8.0 follow-ups cleared
(1) doctor codex-mcp check no longer misattributes 5s timeouts as "binary not on PATH" - disambiguated via a `which codex` probe first. (2) synod + writing-vault-notes skill bundles extracted to cli/templates/.shared/skills/ - drift impossible by construction. (3) New doctor codex-agents-mirror check warns when ~/.agents/skills/ holds stale broken copies. No template-content changes, no re-stamp required for v0.8.0 users.
Codex CLI as a first-class metalmind host
metalmind init --host codex (or via the new multi-select prompt) stamps Codex with the same recall-first behaviour Claude Code gets. Seven artifacts: AGENTS.md sentinel block, SessionStart hook (reuses CC hook script verbatim - Codex JSON shape is identical), [sandbox_workspace_write] network_access=true, ~/.codex/rules/metalmind.rules pre-approving the metalmind command surface, three skills (writing-vault-notes, synod, save), opt-in --with-mcp. /save body extracted to .shared partial; CC slash-command + Codex skill source from one body - drift impossible by construction.
Repositioned as the Claude Code standard library
The module set at this release - memory, code intelligence, daily workflow, deliberation, desktop integration, health - shares state through one vault, one CLI, one stamped CLAUDE.md rule. Vault sync joined them in 0.10.0. Memory stays the headline; the rest is the moat. New site, new comparison-matrix rows, new Architecture + Cookbook docs.
Vault CLAUDE.md aligned with global block
Closed four contradictions between the vault stamped block and the global one (folder list, write contract, raw-Write rule, MOC location).
Stamped rules no longer contradict the CLI contract
Scribe daily-date guard (Fixed + Breaking) - every mutating scribe verb refuses non-today daily writes without --date. Plus eight stamped-rule contradictions closed across CLAUDE.md.block.template, save.md, and writing-vault-notes/SKILL.md.
Synod skill + metalmind synod command
A 7-persona deliberative council debate. Each persona spawns as a parallel subagent, the main agent synthesises a structured verdict (position, confidence %, 3 risks, 5 next steps, minority report).
graphify no longer pollutes ~/CLAUDE.md
graphify claude install was running with cwd=$HOME, dropping a graphify stamp at ~/CLAUDE.md that injected unrelated instructions into every session under $HOME. Now spawns from a temp directory; legacy stale stamps are stripped on every init.