---
title: Vault Operator v2.7
---

# Vault Operator v2.7: Cross-surface MCP, vault summary maintenance, plugin store compliance

The v2.7 line opens Vault Operator up to other AI surfaces (Claude Desktop, ChatGPT, Perplexity), brings the Karpathy-style wiki-maintenance pattern into the vault, and lands the final round of plugin-store review-bot compliance fixes that block the Obsidian Community Plugin submission.

## Highlights

### Cross-surface AI workflow (EPIC-23)

External AI surfaces can now read and write Vault Operator's memory and history layers via MCP. Four new remote tools land:

- `save_to_memory`: fact persistence with source tagging
- `save_conversation`: conversation as living document
- `recall_memory`: cross-source memory retrieval
- `search_history`: cross-source history search

Each conversation carries an origin surface tag (claude / chatgpt / perplexity / obsilo / other / unknown). The history sidebar gets source tabs for filtering. Sync mode is configurable per provider for the privacy trade-off. The legacy `update_memory` tool is deprecated, with a migration helper in the Settings tab.

### Living documents + cross-interface threads

Multiple `save_conversation` calls within 30 minutes from the same source append to a single thread `thread-YYYY-MM-DD-{6-hex}` instead of creating new conversations. Living documents are append-only.

### Vault-to-memory bridge

Vault notes can now be marked as a memory source. The `FrontmatterIndexer` watches changes and triggers the `SingleCallProcessor` so the agent's facts stay in sync with the vault. Hooks: `addNoteAsMemorySource`, `removeNoteAsMemorySource` (FEAT-03-25, ADR-109).

### Karpathy-style wiki maintenance (BA-25)

A five-phase pipeline for keeping vault summaries fresh, ingesting external sources into clusters, and detecting tension between linked notes:

- **Phase 1**: KnowledgeDB schema v9 -> v10 (four new tables), auto-summary pipeline.
- **Phase 2**: Tension detection (hybrid: cosine + LLM judge).
- **Phase 3**: Pre-triage tool, auto-trigger detection on configurable frontmatter property.
- **Phase 4**: Frontmatter-conflict detection.
- **Phase 5**: Stage-3 job runner with token-budget enforcement and a top-hub block whose KV-cache lifecycle is bounded.

### Memory v2 stabilisation pass (Track 3)

Three impacts:

- IMP-03-17-01: `recall_memory` cosine NaN guard.
- IMP-03-18-01: `AgingService` daily scheduler.
- IMP-03-18-02: `DriftBus` throttle bypass.

### Architecture decisions

21 new ADRs (ADR-90 through ADR-110), all accepted and linked from arc42 section 9. Topics: cost-aware heuristics, KnowledgeDB v10, source identity, cluster half-life, frontmatter conflicts, MOC marker block, KV cache, pre-triage, tension detection, output mode, web search, stage-3 runner, MCP memory versioning, source-interface tagging, vault-to-memory bridge (supersedes ADR-87), living documents.

## v2.7.1 follow-up (2026-05-05)

### Plugin store review-bot compliance

The v2.7.0 release passed local lint with the project's brand allowlist, but the Obsidian Community Plugin review bot uses default plugin options without that allowlist. v2.7.1 brings every reported finding from PR #11394 to zero.

- **Stringification (no-base-to-string)**: type guards instead of `String(unknown)` in three call sites: `AutoTriggerObserver.matchesValue` (frontmatter property comparison), `SemanticIndexService` tag lookup, `validateNewTaskInput` (four fields).
- **Unbound method**: `DeepIngestPipeline` now wraps `TensionDetector.markerWorthy` in an arrow function so `this` stays bound.
- **Floating promise**: `updateMemory` legacy telemetry call is prefixed with `void`.
- **Redundant union**: `string | unknown` reduced to `unknown` in `executeVaultOp` (string is already a subtype).
- **Static-style disable**: the cluster-stale Notice in main.ts no longer disables `obsidianmd/no-static-styles-assignment`. A new utility class `.agent-u-cursor-pointer` replaces the inline `el.style.setProperty('cursor', 'pointer')`.
- **Sentence case (29 strings)**: locale strings and UI text rewritten to satisfy the bot's default brand/acronym list. "Vault Operator" was dropped from settings/error/onboarding copy ("the agent" instead). The ChatGPT account block was reworded to avoid `ChatGPT`/`OS`/`Plus`/`Pro` tokens. The eleven BA-25 commands and notices in main.ts were translated from German to English. "MOC" was replaced with "map-of-content"/"hub" in the vault settings.

### Relay quota fix (FIX-14-03)

Two bugs surfaced when the Cross-surface MCP relay started seeing real-world traffic.

- **FIX-14-03-01**: relay poll interval raised from 2s to 10s. Cloudflare Workers Free Plan caps requests at 100k/day per account; 2s polling produced 43.200 requests per day per open Obsidian instance, independent of actual MCP usage. With BRAT hot reloads and multi-device setups the cap was hit even on idle days. Poll interval and reconnect delays are now named constants for explicit cost tracking.
- **FIX-14-03-02**: the poll loop's bare `catch {}` hid HTTP status, body, and stack. A `describeRequestError` helper builds a one-line diagnostic and a `redactToken` helper strips the relay token before logging. After three consecutive failures a single Notice surfaces the issue without devtools. AUDIT-005 H-2/H-3 still hold: every logged string runs through token redaction.

## v2.7.2 follow-up (2026-05-10)

### Source-position provenance fixes (FEAT-19-28)

The Karpathy multi-turn deep-ingest pipeline now produces verifiable references. Five linked fixes close the gap between "the note has a marker" and "the marker actually points somewhere".

- **FIX-19-28-01**: the deep-ingest pipeline (`DeepIngestPipeline`, `BlockIdSetter`, `SummaryPositionAnnotator`) now wires block-IDs into the source note body and emits cross-file wikilinks `[[mirror#^block-N|↗]]` in the sense-making note. Earlier runs left raw `^block-N` text without the wikilink wrap, so clicking did nothing.
- **FIX-19-28-02**: chat attachments only exist for one turn. The `ingest_document` tool now returns an actionable error on later turns instead of an opaque "out of range", and the `/ingest-deep` skill saves to vault on turn one. No more retry loops that ran up Token costs.
- **FIX-19-28-05**: `AttachmentHandler.consumeFullDocTexts()` makes the snapshot-and-clear atomic. The previous split between `clear()` and `getFullDocTexts()` could lose the parsed text if the user sent before the clear settled.
- **FIX-19-28-06**: `IngestDocumentTool` now detects dead page-refs (page number out of range, or basename mismatch) and reports them as `Dead refs detected: ...` with an explicit instruction to remove them. The marker-presence regex also accepts a trailing block-anchor `^slug` so Karpathy-pattern bullets like `- claim. [[source#Page 87|↗]] ^seg-erzeugung` no longer falsely count as marker-less.
- **FIX-19-28 tool-group-drift**: `ingest_deep` and `ingest_triage` are now in the `TOOL_GROUP_MAP` for the edit group. Without this the agent silently fell back to `read_document` plus `write_vault` and rewrote the mirror itself, producing UTF-8 mojibake and selective coverage cuts. Same drift pattern as the earlier `vault_health_check` / `ingest_document` BUG-021.

The `/ingest-deep` skill default also flips from `source-plus-summary` to `source-only`. Take-aways belong in the chat dialog; per-aspect detail notes are created on-demand. Set `output_mode: "source-plus-summary"` explicitly to opt back into the Karpathy summary.

### Prompt cache settings (IMP-18-01-01)

A new `src/api/capabilities.ts` carries a static capability table for 18 model entries with a pure `getCacheCapability()` lookup. Wildcard matching is conservative; unknown models fall back to "no caching" instead of guessing. The settings tab gets a per-provider toggle for prompt-cache opt-in.

### Dependency hardening (AUDIT-017)

Three SCA findings closed via `package.json` overrides:

- `fast-uri >=3.1.2` (CWE-22 path traversal in MCP-SDK transitive)
- `fast-xml-builder >=1.1.7` (CWE-611 XXE in AWS Bedrock transitive)
- `hono >=4.12.18` (5 CVEs in MCP relay transitive: bodyLimit bypass, JSX injection, JWT validation, cache leakage)

After clean reinstall: `npm audit` reports **0 vulnerabilities** (down from 6: 2 High, 4 Moderate). All AUDIT-016 fixes (per-message cap, search_history wildcard escape, get_context strict source isolation, ConversationStore CSPRNG ID, pathValidation helper) verified still wired.

### Review-bot pre-check (0 findings)

35 ESLint errors auto-fixed (mostly `no-unnecessary-type-assertion` on test mocks). 3 manual fixes:

- `MemoryTab` setting name dropped its hyphen for sentence-case compliance.
- `VaultTab` description for `/ingest-deep` template dropped the "Karpathy" reference for sentence-case compliance.
- `SourceReader.test` got an `eslint-disable obsidianmd/no-tfile-tfolder-cast` with rationale for the prototype-clone test mock.

Phase 3 manual checks (`console.log/info`, `fetch(`, `innerHTML`) all clean or documented adapter exceptions.

## Verification

- 1356 / 1356 unit tests pass.
- `obsidianmd/*` review-bot check: 0 findings on the v2.7.2 commit.
- AUDIT-017 delta audit: 0 Critical / 0 High open after SCA-bumps. Release verdict GREEN.
- `npm audit`: 0 vulnerabilities.
- Build clean.

## Install

Via BRAT:

1. BRAT -> Add Beta Plugin -> `https://github.com/pssah4/vault-operator`

Manually:

1. Download `main.js`, `manifest.json`, `styles.css` into `.obsidian/plugins/vault-operator/`.

## What is next

- The plugin-store submission re-runs the review bot automatically on the next push to the public repo. v2.7.1 is the first commit that should clear it without `/skip` notes.
- Cross-surface MCP onboarding flow polish for first-time setup of Claude Desktop / ChatGPT.
- BA-25 stage-3 runner: token-budget tuning based on usage data from v2.7.0 in production.
