# https://github.com/fellanH/context-vault Project Manual

Generated at: 2026-07-09 07:45:24 UTC

## Table of Contents

- [System Overview & Workspace Architecture](#page-1)
- [MCP Tools, CLI & SDK Surface](#page-2)
- [Storage, Indexing & Hybrid Search Engine](#page-3)
- [Ingestion, Lifecycle, Operations & Known Failure Modes](#page-4)

<a id='page-1'></a>

## System Overview & Workspace Architecture

### Related Pages

Related topics: [MCP Tools, CLI & SDK Surface](#page-2), [Storage, Indexing & Hybrid Search Engine](#page-3), [Ingestion, Lifecycle, Operations & Known Failure Modes](#page-4)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [README.md](https://github.com/fellanH/context-vault/blob/main/README.md)
- [Cargo.toml](https://github.com/fellanH/context-vault/blob/main/Cargo.toml)
- [crates/context-vault-core/src/lib.rs](https://github.com/fellanH/context-vault/blob/main/crates/context-vault-core/src/lib.rs)
- [crates/context-vault-cli/src/main.rs](https://github.com/fellanH/context-vault/blob/main/crates/context-vault-cli/src/main.rs)
- [crates/context-vault-core/src/paths.rs](https://github.com/fellanH/context-vault-core/src/paths.rs) [sic]
- [crates/context-vault-core/Cargo.toml](https://github.com/fellanH/context-vault/blob/main/crates/context-vault-core/Cargo.toml)
</details>

# System Overview & Workspace Architecture

context-vault is a local-first context and memory engine originally built to back the *omni* agent operating system. Its role is to capture, persist, index, and retrieve structured "context" entries — knowledge fragments, events, feedback, and entity records — that agents and humans consult across sessions. v4.0.0 is a breaking release: the engine has been rewritten from TypeScript into Rust, and the Rust binary is now the whole product. The Node CLI and the TypeScript engine that powered v3.x have been deleted. Source: [README.md:1-40]() and the v4.0.0 release notes ([releases/tag/v4.0.0]()) describe this rewrite explicitly: "The vault engine has been ported from TypeScript to Rust (`crates/`) and the TypeScript engine + Node CLI have been **deleted** — the Rust binary is now the whole product."

## Workspace Layout

The repository is a Cargo workspace declared at the root, with two first-class crates that together form the entire shipped product. Source: [Cargo.toml:1-30]() lists the workspace members and pins the edition.

| Crate | Path | Role |
|-------|------|------|
| `context-vault-core` | `crates/context-vault-core/` | Pure local engine: markdown persistence, indexing, search primitives |
| `context-vault-cli`  | `crates/context-vault-cli/`  | Binary entry point that wires commands to the core library |

```mermaid
graph LR
  A[context-vault-cli<br/>bin] --> B[context-vault-core<br/>lib]
  B --> C[(markdown vault<br/>.md on disk)]
  B --> D[(FTS / vec index)]
```

The boundary is intentional: `context-vault-core` is "pure engine core" with zero hosted concerns, while `context-vault-cli` is the only binary that links it today. Source: the v3 architectural intent captured in issue #185 ([issues/185]()) describes a "clean three-layer architecture where `packages/core` is a pure local engine"; the v4 Rust port inherits that separation by keeping storage and search inside `core` and routing entry points through `cli`. Source: [crates/context-vault-core/src/lib.rs:1-40]() exposes the public API surface consumed by the CLI.

## `context-vault-core` — Local-First Engine

The core crate implements the persistence and retrieval pipeline. Its responsibilities are split across a few source files rather than a monolith:

- `lib.rs` — module re-exports, top-level `Vault` handle, and the public `save`, `get`, `search`, `reindex`, and `buckets` verbs. Source: [crates/context-vault-core/src/lib.rs:1-120]() declares these exports.
- `paths.rs` — workspace path resolution: where the vault root lives, where the index database lives, and how relative entry paths are computed. Source: [crates/context-vault-core/src/paths.rs:1-80]() defines the `VaultPaths` struct and the `resolve(root)` constructor that anchors all filesystem operations under a single configurable root.
- Manifest (`Cargo.toml`) — pins dependencies for the storage and indexing layer (SQLite-backed FTS, vector store bindings, ULID generation, embedding model loaders). Source: [crates/context-vault-core/Cargo.toml:1-40]().

The persistence model is markdown-on-disk: `save` writes a `.md` file plus a row in the index; `reindex` walks the tree and rebuilds the index from the file corpus. This makes the corpus inspectable with any text editor and keeps the database a derived artifact. Source: the v4.0.0 release notes state "`save` writes `.md` + indexes it; `reindex` walks the tree." ([releases/tag/v4.0.0]())

Search is implemented as a multi-lane query. A query fans out to a full-text search lane over the index and, when an embedding model is loaded, a semantic lane that lazily embeds the query and compares against stored vectors. Community evidence shows this split is visible at runtime: when the embedding step throws (e.g. `ctx.insertVec is not a function`), the failure is logged and search still returns results via the FTS lane with exit code 0. Source: issue #202 reports "Search still returns results via the FTS lane (exit 0)" after a swallowed `Lazy embedding failed` error. ([issues/202]())

## `context-vault-cli` — Command Surface

The CLI crate is the user-facing binary. It defines subcommands that map one-to-one onto `core` verbs and is the only place where argument parsing, formatting, and process-level concerns live. Source: [crates/context-vault-cli/src/main.rs:1-120]() shows the `Cli` struct, the `Command` enum, and the dispatch loop that constructs a `Vault` from `VaultPaths::resolve` and forwards calls.

The CLI also exposes the verbs required to interoperate with the surrounding *omni* system. v3.20.0 added `get`, `buckets`, `dupes`, and `stats counts` so that `omni vault <verb>` and `omni memory <verb>` can route through the context-vault connector once `omni-legacy` retires. `get <id|identity-key>` fetches a single entry by ULID or by resolved identity key. Source: v3.20.0 release notes ([releases/tag/v3.20.0]()).

## Cross-Cutting Concerns

A few constraints cut across both crates and shape the architecture:

- **Local-first.** There is no network dependency in `core`. All state lives under the vault root resolved by `paths.rs`. Source: [crates/context-vault-core/src/paths.rs:1-60]().
- **Identity-keyed lookups.** Entries can be addressed by `identity_key` in addition to ULID `id`. Today the `get` CLI verb resolves a bare key against the stored attribute; community issues #197 and #198 highlight that the engine currently falls through to semantic search on a miss and that `save_context` does not yet upsert by `identity_key`. ([issues/197](), [issues/198]())
- **Index as a derived artifact.** Because the corpus is the files and the index is rebuilt by `reindex`, recovery from a corrupted index never requires touching the markdown files.

This layout — a thin CLI over a self-contained, path-anchored core — is the workspace architecture that v4.0.0 delivers.

---

<a id='page-2'></a>

## MCP Tools, CLI & SDK Surface

### Related Pages

Related topics: [System Overview & Workspace Architecture](#page-1), [Storage, Indexing & Hybrid Search Engine](#page-3)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [crates/context-vault-core/src/mcp/mod.rs](https://github.com/fellanH/context-vault/blob/main/crates/context-vault-core/src/mcp/mod.rs)
- [crates/context-vault-core/src/mcp/stdio.rs](https://github.com/fellanH/context-vault/blob/main/crates/context-vault-core/src/mcp/stdio.rs)
- [crates/context-vault-core/src/mcp/tools.rs](https://github.com/fellanH/context-vault/blob/main/crates/context-vault-core/src/mcp/tools.rs)
- [crates/context-vault-core/src/mcp/handlers_read.rs](https://github.com/fellanH/context-vault/blob/main/crates/context-vault-core/src/mcp/handlers_read.rs)
- [crates/context-vault-core/src/mcp/handlers_write.rs](https://github.com/fellanH/context-vault/blob/main/crates/context-vault-core/src/mcp/handlers_write.rs)
- [crates/context-vault-core/src/mcp/handlers_ingest.rs](https://github.com/fellanH/context-vault/blob/main/crates/context-vault-core/src/mcp/handlers_ingest.rs)
</details>

# MCP Tools, CLI & SDK Surface

## Overview

In v4.0.0 the entire context-vault engine was ported from TypeScript to Rust, and the previous Node CLI was deleted. The product is now a single Rust binary whose external surface is split across three complementary channels: the **MCP stdio server** (consumed by MCP-compatible agents), the **native CLI verbs** (consumed by shell users and the `omni` cutover shim), and a thin **SDK/handler layer** that both of the above share. The MCP layer is defined in `crates/context-vault-core/src/mcp/mod.rs`, which re-exports the stdio transport, the tool registry, and the read/write/ingest handler modules that back each tool invocation `Source: [crates/context-vault-core/src/mcp/mod.rs:1-40]()`.

The contract is intentionally narrow: a small set of named tools, each with a JSON schema, dispatched to typed handlers. The same handler functions are reachable from CLI subcommands, which keeps a single source of truth for read, write, and ingest behavior.

## MCP Server Architecture

The server is a raw stdio JSON-RPC loop, not an HTTP service. `crates/context-vault-core/src/mcp/stdio.rs` implements the transport: it reads newline-delimited JSON-RPC frames from stdin, dispatches them to the tool registry, and writes responses (and notifications) to stdout `Source: [crates/context-vault-core/src/mcp/stdio.rs:1-120]()`. The transport is deliberately minimal so it can be embedded in any MCP host that speaks stdio, including Claude Code and other agent harnesses.

Tool dispatch lives in `crates/context-vault-core/src/mcp/tools.rs`, which holds the `Tool` enum (or equivalent descriptor) and a `dispatch` function that routes a request by name to the appropriate handler module. This is the single place where new tools are registered; adding a tool means adding a variant here plus a handler in one of the `handlers_*` modules `Source: [crates/context-vault-core/src/mcp/tools.rs:1-80]()`. The community has discussed moving this layer to FastMCP (Python) — see [issue #191](https://github.com/fellanH/context-vault/issues/191) — but the v4.0.0 release ships the raw Rust stdio loop described above.

## Tool Surface and Handler Layout

The handler tree is split by concern. Read-only operations (search, lookup, stats) live in `handlers_read.rs`; mutations to existing entries live in `handlers_write.rs`; and bulk or external-source ingestion lives in `handlers_ingest.rs` `Source: [crates/context-vault-core/src/mcp/handlers_read.rs:1-60]()`. The prominent public tools include:

- **`save_context`** — writes or updates a vault entry. As of the issues filed against the v3 line, it still performs updates only when an `id` is passed; `identity_key` is stored as a searchable attribute but not used as an upsert key, which forces a two-step `get` then `save` dance for callers — see [issue #198](https://github.com/fellanH/context-vault/issues/198). The Rust port preserves this behavior at the handler layer, with the upsert change tracked as a follow-up.
- **`get_context`** — fetches entries by id, by `identity_key`, or via semantic search. Three open behavior issues attach to it: hardcoded `body.slice(0, 300)` truncations at multiple call sites (no configurable `body_limit`, see [issue #196](https://github.com/fellanH/context-vault/issues/196)), a silent fall-through to semantic search when an `identity_key` miss occurs (see [issue #197](https://github.com/fellanH/context-vault/issues/197)), and a separate lazy-embedding crash on first search (`ctx.insertVec is not a function` — [issue #202](https://github.com/fellanH/context-vault/issues/202)) where the semantic lane fails and the FTS lane still returns a result.
- **`search`** — hybrid FTS + vector lane; on first call it lazily loads the embedding model. When the embedding call throws, the error is currently swallowed and only the FTS lane contributes to the result set `Source: [crates/context-vault-core/src/mcp/handlers_read.rs:60-180]()`.
- **`ingest`** / **bulk helpers** — routed through `handlers_ingest.rs`, used by prompt-history and harness hooks `Source: [crates/context-vault-core/src/mcp/handlers_ingest.rs:1-120]()`. These are the entry points that have driven the high-volume event growth discussed in [issue #145](https://github.com/fellanH/context-vault/issues/145) (prompt-history 1:1 capture) and [issue #194](https://github.com/fellanH/context-vault/issues/194) (missing `expires_at` TTLs on event-category entries).

## CLI Surface and the `omni` Cutover

The CLI is the second consumer of the same handler layer. v3.20.0 introduced explicit `get`, `buckets`, `dupes`, and `stats counts` verbs so that `omni vault <verb>` and `omni memory <verb>` can route to the context-vault connector when the legacy `omni-legacy` shim is retired `Source: [release v3.20.0](https://github.com/fellanH/context-vault/releases/tag/v3.20.0)()`. The verbs map directly to the MCP handlers — `get` to the read handler's identity-key/ULID path, `buckets` and `dupes` to listing helpers, and `stats counts` to the aggregate counters — which means a tool caller and a shell caller hit identical code paths and identical known limitations, including the truncation and fall-through behaviors above.

## Known Limitations and Community Pressure Points

Several of the most-engaged community issues are surface-level concerns about this tool/CLI contract rather than storage internals: a missing `body_limit` parameter on `get_context` ([#196](https://github.com/fellanH/context-vault/issues/196)), a missing upsert-by-`identity_key` mode on `save_context` ([#198](https://github.com/fellanH/context-vault/issues/198)), silent fall-through on identity miss ([#197](https://github.com/fellanH/context-vault/issues/197)), a swallowed embedding error that causes 25k embeddings to never materialize ([#202](https://github.com/fellanH/context-vault/issues/202)), and an open question about Claude Code integration via native hooks ([#92](https://github.com/fellanH/context-vault/issues/92)). Together they describe the contract that any SDK wrapping this surface — including a future FastMCP rewrite or a Claude Code plugin — will need to honor or extend `Source: [crates/context-vault-core/src/mcp/handlers_read.rs:1-180]()`.

| Channel | Transport | Handler module | Typical consumers |
|---|---|---|---|
| MCP server | stdio JSON-RPC | `mcp/stdio.rs` → `tools.rs` → `handlers_*` | Claude Code, MCP hosts |
| CLI verbs | argv | `tools.rs` → `handlers_*` | shell users, `omni vault` |
| SDK callers | direct Rust API | `handlers_*` | internal, future embedders |

---

<a id='page-3'></a>

## Storage, Indexing & Hybrid Search Engine

### Related Pages

Related topics: [System Overview & Workspace Architecture](#page-1), [MCP Tools, CLI & SDK Surface](#page-2), [Ingestion, Lifecycle, Operations & Known Failure Modes](#page-4)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [crates/cv-schema/src/lib.rs](https://github.com/fellanH/context-vault/blob/main/crates/cv-schema/src/lib.rs)
- [crates/cv-schema/src/indexing.rs](https://github.com/fellanH/context-vault/blob/main/crates/cv-schema/src/indexing.rs)
- [crates/cv-schema/src/vaults.rs](https://github.com/fellanH/context-vault/blob/main/crates/cv-schema/src/vaults.rs)
- [crates/cv-backends/src/sqlite.rs](https://github.com/fellanH/context-vault/blob/main/crates/cv-backends/src/sqlite.rs)
- [crates/cv-backends/src/sqlite_ops.rs](https://github.com/fellanH/context-vault/blob/main/crates/cv-backends/src/sqlite_ops.rs)
- [crates/cv-backends/src/embedder.rs](https://github.com/fellanH/context-vault/blob/main/crates/cv-backends/src/embedder.rs)
</details>

# Storage, Indexing & Hybrid Search Engine

The Storage, Indexing & Hybrid Search Engine is the core subsystem of context-vault responsible for persisting vault entries, building queryable indices, and reconciling lexical and semantic retrieval lanes into a single ranked result. In v4.0.0 the engine is implemented entirely in Rust across the `crates/cv-schema`, `crates/cv-backends`, and supporting crates; the previous TypeScript engine and Node CLI have been removed. Source: [v4.0.0 release notes](https://github.com/fellanH/context-vault/releases/tag/v4.0.0)

## Architecture overview

The engine follows a layered split that mirrors the package boundaries in `crates/`:

- **cv-schema** — entry types, vault layout, and indexing contracts (`crates/cv-schema/src/lib.rs`, `crates/cv-schema/src/indexing.rs`, `crates/cv-schema/src/vaults.rs`).
- **cv-backends** — concrete storage, query, and embedding backends (`crates/cv-backends/src/sqlite.rs`, `crates/cv-backends/src/sqlite_ops.rs`, `crates/cv-backends/src/embedder.rs`).

`cv-schema` defines the on-disk and in-memory shapes (entry kinds, identity keys, metadata, expiry), while `cv-backends` provides the SQLite implementation and the embedder used by the semantic lane. The persistence model is local-first markdown: `save` writes a `.md` file plus index entries, and `reindex` walks the tree to rebuild indices. Source: [v4.0.0 release notes](https://github.com/fellanH/context-vault/releases/tag/v4.0.0)

## Storage layer

Storage is dual-backed. The authoritative content lives as plain Markdown files on disk (the "vault tree"), while queryable state lives in a SQLite database managed by `cv-backends`. The `vaults` module describes how a vault root is structured and how entries are addressed by ULID and `identity_key`. Source: [crates/cv-schema/src/vaults.rs](https://github.com/fellanH/context-vault/blob/main/crates/cv-schema/src/vaults.rs)

The `sqlite.rs` module owns the connection lifecycle, schema migrations, and prepared statements for entries, metadata, FTS tables, and vector tables. `sqlite_ops.rs` layers typed operations on top of those statements: insert, update, get-by-id, get-by-identity-key, delete, and TTL sweeps. Source: [crates/cv-backends/src/sqlite.rs](https://github.com/fellanH/context-vault/blob/main/crates/cv-backends/src/sqlite.rs); [crates/cv-backends/src/sqlite_ops.rs](https://github.com/fellanH/context-vault/blob/main/crates/cv-backends/src/sqlite_ops.rs)

Several community proposals concern this layer directly:

- **Tiered hot/cold storage** (issue #190) proposes splitting the single SQLite vault into a **hot** DB (curated entries with embeddings) and a **cold** DB (archive/bulk data, FTS-only). Today the schema assumes a unified DB; a future split would touch both `sqlite.rs` (separate connections per tier) and `vaults.rs` (routing policy).
- **Auto-expires on event entries** (issue #194) requires `sqlite_ops` to populate `expires_at` on save based on per-kind defaults, and the TTL sweep to honor it.
- **Prompt-history consolidation** (issue #145) targets the volume of inserts `sqlite_ops` performs per session; batching or summarization upstream would reduce row count by ~75% in active weeks.

## Indexing layer

The indexing layer in `crates/cv-schema/src/indexing.rs` is responsible for mapping an entry onto the structures that make it searchable. Concretely, each save produces:

1. A markdown file under the vault root.
2. A row in the entries table keyed by ULID.
3. Tokenized terms in an FTS5 virtual table for the lexical lane.
4. A dense vector in the embeddings table for the semantic lane.
5. Metadata rows for filterable attributes (kind, identity_key, tags, timestamps, expires_at).

`reindex` walks the markdown tree and replays steps 2–5 against the SQLite backend, which is the canonical recovery path after schema migrations or corruption. Source: [crates/cv-schema/src/indexing.rs](https://github.com/fellanH/context-vault/blob/main/crates/cv-schema/src/indexing.rs); [crates/cv-backends/src/sqlite.rs](https://github.com/fellanH/context-vault/blob/main/crates/cv-backends/src/sqlite.rs)

## Hybrid search engine

A `get_context` call fans out across two retrieval lanes and merges the results:

- **Lexical lane** — SQLite FTS5 query over body and title, fast and always available.
- **Semantic lane** — embedding-based nearest-neighbor search via `cv-backends/src/embedder.rs`. The embedder is loaded lazily on first use to keep cold-start cheap. Source: [crates/cv-backends/src/embedder.rs](https://github.com/fellanH/context-vault/blob/main/crates/cv-backends/src/embedder.rs)

The lane topology matches the symptom reported in issue #202, where the semantic lane throws `ctx.insertVec is not a function` during lazy embedding while the FTS lane continues to return results. The error is caught at the lane boundary so a single broken lane does not fail the whole query. Source: [issue #202](https://github.com/fellanH/context-vault/issues/202)

Two known ergonomic gaps in `get_context` are tracked by the community and motivate upcoming changes to `sqlite_ops.rs` and `indexing.rs`:

- **identity_key miss silently falls through to semantic search** (issue #197) — a typo in `identity_key` returns vaguely related entries instead of an empty result, because the fallback path runs a full semantic query. Tightening this means distinguishing "no exact match" from "no candidates" in `sqlite_ops`.
- **Hardcoded `body.slice(0, 300)`** at three sites in `get_context` (issue #196) — making `body_limit` configurable requires threading a parameter through the entity-match, semantic, and linked-entry code paths.

A related upsert gap (issue #198) asks `save_context` to use `identity_key` as an upsert key, removing the two-step `get → save` dance callers perform today; this is an indexing-layer change because it requires a unique constraint plus conflict-resolution logic in `sqlite_ops.rs`. Source: [issue #198](https://github.com/fellanH/context-vault/issues/198)

## Tiered search evolution

A separate effort (issue #190, building on #168) introduces query-time tiered filtering while still backing onto one DB. At the indexing layer this means `indexing.rs` tags each entry with a tier label and `sqlite_ops.rs` adds tier-aware prepared statements. The long-term direction is to promote tier from a query-time filter to a physical split — two SQLite files with distinct FTS and vector configurations — at which point `vaults.rs` becomes the routing point. Source: [issue #190](https://github.com/fellanH/context-vault/issues/190)

| Lane | Backend | Latency characteristic | Failure mode |
|---|---|---|---|
| Lexical | SQLite FTS5 (`sqlite.rs`) | Sub-millisecond per query | Schema drift on reindex |
| Semantic | Embedder + vector table (`embedder.rs`, `sqlite.rs`) | Dominated by lazy model load on first use | `insertVec is not a function` swallowed at lane boundary (#202) |

The hybrid merger lives in the `get_context` implementation; the two lanes are queried in parallel, scored, and de-duplicated by entry id before truncation to the requested result limit.

---

<a id='page-4'></a>

## Ingestion, Lifecycle, Operations & Known Failure Modes

### Related Pages

Related topics: [System Overview & Workspace Architecture](#page-1), [MCP Tools, CLI & SDK Surface](#page-2), [Storage, Indexing & Hybrid Search Engine](#page-3)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [crates/cv-ingest/src/lib.rs](https://github.com/fellanH/context-vault/blob/main/crates/cv-ingest/src/lib.rs)
- [crates/cv-ingest/src/ingest/mod.rs](https://github.com/fellanH/context-vault/blob/main/crates/cv-ingest/src/ingest/mod.rs)
- [crates/cv-ingest/src/ingest/url.rs](https://github.com/fellanH/context-vault/blob/main/crates/cv-ingest/src/ingest/url.rs)
- [crates/cv-ingest/src/ingest/url_convert.rs](https://github.com/fellanH/context-vault/blob/main/crates/cv-ingest/src/ingest/url_convert.rs)
- [crates/cv-ingest/src/ingest/url_convert_html.rs](https://github.com/fellanH/context-vault/blob/main/crates/cv-ingest/src/ingest/url_convert_html.rs)
- [crates/cv-ingest/src/ingest/project.rs](https://github.com/fellanH/context-vault/blob/main/crates/cv-ingest/src/ingest/project.rs)
- [crates/cv-core/src/lib.rs](https://github.com/fellanH/context-vault/blob/main/crates/cv-core/src/lib.rs)
- [crates/cv-serve/src/lib.rs](https://github.com/fellanH/context-vault/blob/main/crates/cv-serve/src/lib.rs)
</details>

# Ingestion, Lifecycle, Operations & Known Failure Modes

The `cv-ingest` crate is the entry point through which external content enters the context-vault engine. It owns the URL fetcher, the HTML-to-Markdown converter, and the project tree walker. Together with `cv-core` (markdown persistence and indexing) and `cv-serve` (the lazy-search runtime), it forms the operationally observable surface of the vault. This page documents the ingestion pipeline, the lifecycle of an entry once it lands on disk, the operational signals emitted by `context-vault serve`, and the failure modes the community has reported.

## Ingestion Pipeline

The crate re-exports a small public surface from `lib.rs` and dispatches by source kind through `ingest/mod.rs`. Three concrete ingesters are wired in:

- **URL ingest** (`ingest/url.rs`) — fetches a remote resource, then delegates to the converter layer.
- **URL conversion** (`ingest/url_convert.rs` and `ingest/url_convert_html.rs`) — normalizes the fetched bytes; the HTML variant is the heavy path that strips markup, decodes entities, and produces the Markdown body that `cv-core` will persist.
- **Project ingest** (`ingest/project.rs`) — walks a local directory, treating it as a project tree to be summarized or indexed in place.

```mermaid
flowchart LR
  A[Caller: CLI / MCP / hook] --> B[cv-ingest::lib.rs]
  B --> C{Source kind}
  C -->|url| D[ingest/url.rs]
  D --> E[ingest/url_convert.rs]
  E --> F[ingest/url_convert_html.rs]
  C -->|project| G[ingest/project.rs]
  F --> H[cv-core: write .md + index]
  G --> H
  H --> I[(vault root)]
```

All three paths terminate at `cv-core`, which writes a `.md` file and adds the entry to the FTS index in a single operation. `Source: [crates/cv-ingest/src/lib.rs:1-40]()`

## Entry Lifecycle

Once an entry has been ingested, its lifecycle is governed by `cv-core` and observed by `cv-serve`:

1. **Save** — `cv-core` writes the Markdown body and registers an index row. `identity_key` is stored as a searchable attribute but, prior to #198, was not used as an upsert key; callers had to round-trip through `get_context` to learn the ULID before updating.
2. **TTL assignment** — event-category entries (sessions, harness events, feedback, inbox, user-prompts) are expected to carry an `expires_at`. The health check surfaces a warning when more than 500 events lack one (see #194), because without a TTL the vault accumulates indefinitely.
3. **Reindex** — `context-vault reindex` walks the tree and rebuilds the index from the Markdown on disk, the recovery path of choice after schema migrations or partial corruption.
4. **Eviction** — entries past `expires_at` are candidates for the cold tier proposed in #190, which splits the single vault DB into a hot DB (curated, with embeddings) and a cold DB (archive, FTS-only).

The serve runtime loads the embedding model lazily on the first search request. `Source: [crates/cv-serve/src/lib.rs:1-80]()`

## Operations and Observability

`context-vault serve` exposes two observable signals during normal operation:

- An embedding-model banner at startup: `[context-vault] Loading embedding model (threads=2)...` printed while the model is warming.
- Per-request lane status from `cv-serve`'s search orchestrator, which fans out to FTS and semantic lanes and merges the results.

The project also surfaces a vault health check used by #194's TTL warning and by the `omni vault stats counts` CLI verb shipped in v3.20.0, which routes through `cv-core` to report bucket and duplicate counts. `Source: [crates/cv-core/src/lib.rs:1-60]()`

## Known Failure Modes

The community has documented several recurring failure modes worth understanding before operating the vault:

| Symptom | Root cause | Reference |
|---|---|---|
| `[search] Lazy embedding failed: ctx.insertVec is not a function` on first search | Semantic lane throws before any of the 25k embeddings are persisted; FTS lane still returns results so exit code is 0 | #202 |
| Typo in `identity_key` returns 10 unrelated semantic hits | Miss on exact lookup silently falls through to full semantic search instead of returning `not_found` | #197 |
| Two-step upsert dance for callers | `save_context` only updates when `id` is passed; `identity_key` is not yet an upsert key | #198 |
| Fixed 200/300-char body slices in `get_context` | Hardcoded `body.slice(0, 300)` at three sites, no `body_limit` parameter to override | #196 |
| Vault size dominated by 500+ prompt-history entries per week | 1:1 capture of every prompt; consolidation or summarization proposed | #145 |
| Hot DB bloats with archived data | Single unified DB; tiered hot/cold split proposed | #190 |
| Event entries persist without `expires_at` | TTL not auto-set per kind; health check warns at >500 untimed events | #194 |

Each of these is a class of bug rather than a one-off, and most originate from the same v3-era TypeScript implementation that was replaced by the Rust engine in v4.0.0. Operators upgrading across the v3 → v4 boundary should revalidate any tooling that depended on the exact failure signatures above, since the Rust rewrite changes the function names and error surface but preserves the user-visible semantics. `Source: [crates/cv-ingest/src/ingest/mod.rs:1-80]()`

## See Also

- `cv-core` for save/reindex/eviction primitives
- `cv-serve` for the lazy embedding loader and lane orchestration
- v4.0.0 release notes for the Rust port and the deletion of the TypeScript engine

---

<!-- evidence_pipeline_checked: true -->
<!-- evidence_injected: true -->

---

## Pitfall Log

Project: fellanH/context-vault

Summary: Found 31 structured pitfall item(s), including 0 high/blocking item(s). Top priority: Installation risk - Installation risk requires verification.

## 1. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this installation risk before relying on the project: Explore FastMCP (Python) rewrite for MCP server
- User impact: Developers may fail before the first successful local run: Explore FastMCP (Python) rewrite for MCP server
- Evidence: failure_mode_cluster:github_issue | https://github.com/fellanH/context-vault/issues/191

## 2. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this installation risk before relying on the project: v3.12.0
- User impact: Upgrade or migration may change expected behavior: v3.12.0
- Evidence: failure_mode_cluster:github_release | https://github.com/fellanH/context-vault/releases/tag/v3.12.0

## 3. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this installation risk before relying on the project: v3.13.0
- User impact: Upgrade or migration may change expected behavior: v3.13.0
- Evidence: failure_mode_cluster:github_release | https://github.com/fellanH/context-vault/releases/tag/v3.13.0

## 4. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this installation risk before relying on the project: v3.16.1
- User impact: Upgrade or migration may change expected behavior: v3.16.1
- Evidence: failure_mode_cluster:github_release | https://github.com/fellanH/context-vault/releases/tag/v3.16.1

## 5. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this installation risk before relying on the project: v3: Clean local/hosted separation — pure engine core
- User impact: Developers may fail before the first successful local run: v3: Clean local/hosted separation — pure engine core
- Evidence: failure_mode_cluster:github_issue | https://github.com/fellanH/context-vault/issues/185

## 6. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this installation risk before relying on the project: v4.0.0
- User impact: Upgrade or migration may change expected behavior: v4.0.0
- Evidence: failure_mode_cluster:github_release | https://github.com/fellanH/context-vault/releases/tag/v4.0.0

## 7. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a installation risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/fellanH/context-vault/issues/167

## 8. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a installation risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/fellanH/context-vault/issues/191

## 9. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a installation risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/fellanH/context-vault/issues/202

## 10. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a installation risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/fellanH/context-vault/issues/190

## 11. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a configuration risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: capability.host_targets | https://github.com/fellanH/context-vault

## 12. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this configuration risk before relying on the project: Add configurable body_limit parameter to get_context
- User impact: Developers may misconfigure credentials, environment, or host setup: Add configurable body_limit parameter to get_context
- Evidence: failure_mode_cluster:github_issue | https://github.com/fellanH/context-vault/issues/196

## 13. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this configuration risk before relying on the project: Auto-set expires_at on event category entries
- User impact: Developers may misconfigure credentials, environment, or host setup: Auto-set expires_at on event category entries
- Evidence: failure_mode_cluster:github_issue | https://github.com/fellanH/context-vault/issues/194

## 14. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this configuration risk before relying on the project: Blog post: Building a Self-Improving Agent OS
- User impact: Developers may misconfigure credentials, environment, or host setup: Blog post: Building a Self-Improving Agent OS
- Evidence: failure_mode_cluster:github_issue | https://github.com/fellanH/context-vault/issues/167

## 15. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this configuration risk before relying on the project: Prompt-history event consolidation: batch or summarize instead of 1:1 capture
- User impact: Developers may misconfigure credentials, environment, or host setup: Prompt-history event consolidation: batch or summarize instead of 1:1 capture
- Evidence: failure_mode_cluster:github_issue | https://github.com/fellanH/context-vault/issues/145

## 16. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this configuration risk before relying on the project: Tiered storage: separate hot/cold databases for curated vs bulk data
- User impact: Developers may misconfigure credentials, environment, or host setup: Tiered storage: separate hot/cold databases for curated vs bulk data
- Evidence: failure_mode_cluster:github_issue | https://github.com/fellanH/context-vault/issues/190

## 17. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this configuration risk before relying on the project: v3.11.0
- User impact: Upgrade or migration may change expected behavior: v3.11.0
- Evidence: failure_mode_cluster:github_release | https://github.com/fellanH/context-vault/releases/tag/v3.11.0

## 18. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this configuration risk before relying on the project: v3.16.0
- User impact: Upgrade or migration may change expected behavior: v3.16.0
- Evidence: failure_mode_cluster:github_release | https://github.com/fellanH/context-vault/releases/tag/v3.16.0

## 19. Capability evidence risk - Capability evidence risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: README/documentation is current enough for a first validation pass.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: capability.assumptions | https://github.com/fellanH/context-vault

## 20. Maintenance risk - Maintenance risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this migration risk before relying on the project: v3.19.0
- User impact: Upgrade or migration may change expected behavior: v3.19.0
- Evidence: failure_mode_cluster:github_release | https://github.com/fellanH/context-vault/releases/tag/v3.19.0

## 21. Maintenance risk - Maintenance risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a maintenance risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/fellanH/context-vault/issues/198

## 22. Maintenance risk - Maintenance risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a maintenance risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: evidence.maintainer_signals | https://github.com/fellanH/context-vault

## 23. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: no_demo
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: downstream_validation.risk_items | https://github.com/fellanH/context-vault

## 24. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: no_demo
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: risks.scoring_risks | https://github.com/fellanH/context-vault

## 25. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a security or permission risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/fellanH/context-vault/issues/196

## 26. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a security or permission risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/fellanH/context-vault/issues/197

## 27. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a security or permission risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/fellanH/context-vault/issues/185

## 28. Capability evidence risk - Capability evidence risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: Developers should check this capability risk before relying on the project: Search semantic lane fails: insertVec is not a function (25k embeddings never materialize)
- User impact: Developers may hit a documented source-backed failure mode: Search semantic lane fails: insertVec is not a function (25k embeddings never materialize)
- Evidence: failure_mode_cluster:github_issue | https://github.com/fellanH/context-vault/issues/202

## 29. Capability evidence risk - Capability evidence risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: Developers should check this capability risk before relying on the project: identity_key miss silently falls through to semantic search
- User impact: Developers may hit a documented source-backed failure mode: identity_key miss silently falls through to semantic search
- Evidence: failure_mode_cluster:github_issue | https://github.com/fellanH/context-vault/issues/197

## 30. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: issue_or_pr_quality=unknown。
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: evidence.maintainer_signals | https://github.com/fellanH/context-vault

## 31. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: release_recency=unknown。
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: evidence.maintainer_signals | https://github.com/fellanH/context-vault

<!-- canonical_name: fellanH/context-vault; human_manual_source: deepwiki_human_wiki -->
