An adversarial audit of the piragi -> in-house swap surfaced nine confirmed
issues; this fixes all of them.
- Re-ingest now REPLACES a source's chunks instead of appending. Add
VectorStore.delete_by_source and BaseIndexPlugin.replace_on_reingest (default
True), called before add_chunks in both ingest paths. Without it every
startup / periodic / manual reindex appended a fresh copy of each doc's
chunks, growing the tables unbounded and crowding out distinct results.
Conversations opt OUT (replace_on_reingest=False): their many messages share
one source URI, so delete-by-source would wipe history.
- index_* now honor the plugin IngestResult. The explicit record endpoints
(error / standard / decision / review / learning) raise on failure instead of
writing a green tracking row for content that never persisted;
conversation / journal indexing stays best-effort but skips the tracking row
when the embed fails. index_message / index_entry return IngestResult.
- A deprecated index type (code) now returns 404 instead of a 500 leaked from
_get_plugin's missing-plugin error: add OptimalService.is_index_registered
and guard the stats / clear / refresh routes. The panel drops the dead 'Code'
category, filter, badge, label, and mock data.
- Panel: getContext reads 'results' (matches SearchResponse) instead of a
non-existent 'context' field; the reindex toast no longer reports phantom
'0 code files'; the stats 'Updated' label uses the max timestamp across
indexes rather than indexes[0]; ProactiveContextItem matches the wire shape.
- Drop the always-zero per-document chunk_count from the documents API.
- Remove dead RAG settings (hybrid_search, cross_encoder) the engine never
consumed, and correct stale piragi / BM25 references in code, README, and
CLAUDE.md. Delete the unused duplicate roboco/kb embedder package the swap
shipped.
Adds tests for replace-on-reingest (incl. the conversations carve-out) and the
deprecated-index 404.