TurboVec persists vectors via the sidecar but kept entry metadata
(sessionId/turnId/text) only in an in-memory map, so restarting with
backend=turbovec silently dropped every query hit (the id→metadata
lookup missed). Rebuild that map from the ChatTurnEvent log at startup.
- RehydratableL3MemoryStore: capability interface for stores whose
vectors persist independently of the JVM. TurboVec implements it;
InMemory deliberately does not (its vectors are volatile too).
- L3MetadataRehydrator replays ChatTurnEvents into the metadata map.
No embedder: the query path never reads entry.vector, so vectors
stay in the sidecar and metadata comes from the event log (the
source of truth, invariant #1). Short-circuits for non-rehydratable
backends before scanning the log.
- Wired into Main before the server accepts queries; no sidecar spawn.
Backfill of never-embedded history (needs the embedder) is a separate
follow-up. The in_memory non-durability warning already exists.
Defines the L3MemoryStore contract in core:router (entry, query, hit,
in-memory test default) and a new infrastructure:router:turbovec module
that adapts turbovec via a Python sidecar over stdin/stdout JSON-Lines.
Adapter manages the subprocess via ProcessBuilder with lazy start,
mutex-serialized requests, and shutdown via withTimeout. Wire-format
metadata that turbovec doesn't store (sessionId, turnId, text) is kept
in an in-memory map for now — durable persistence ships with the
upcoming ChatTurnEvent.
Not yet wired into RouterFacade, InfrastructureModule, or DI. Embedding
generation source is a separate concern.