Search is engine-native

Full-text search over the same engine backs both the MCP tools and the PWA.

Context

Both agents and the human need to search feed events, artifacts, and session contents. A dedicated search service is the common answer, and it is the opposite of a single lean binary: another process, another index to keep consistent, and another thing to operate.

Decision

Search is engine-native. Full-text search over the same engine backs both the MCP search tool and the PWA search box. There is no separate search service.

Consequences

  • One index, updated with the data, and one fewer moving part.
  • Results rank on recency and text relevance, grouped by type, with snippets and filters for scope.
  • Encrypted artifacts are searchable by metadata only, such as title and summary, because their plaintext is never on the server.
  • Whether the engine's embedded full-text support covers every need is an open question to confirm at scaffold time. If it falls short, the fallback is a search-text column on the event store, still inside the same engine.

Amendment (2026-09-16)

Confirmed: the engine has a native full-text index, built on Tantivy, created with CREATE INDEX ... USING fts and queried with fts_match and fts_score. It is MVCC-aware and enabled by default in the Rust binding. The fallback is not needed.

One correction to the shape: indexes are per database, so searching session files by refreshing one index per file would not scale. The index is therefore centralised in hub.db over a search_docs table, populated write-through by the wrapper, which is the single writer and sees every change. Prune removes the affected rows.

The index method is gated behind an experimental flag on the engine connection, so the hub enables it explicitly and re-tests it on every engine bump.