Skip to content

REST semantic search does not load persisted LanceDB indexes #834

Description

@GautamSharma99

The REST server does not reuse the persistent vector index created by the CLI.

repowise init stores embeddings in the repository-local .repowise/lancedb directory. However, repowise serve always initializes a new, empty
InMemoryVectorStore, so semantic searches made through the REST API cannot see the existing embeddings.

This also affects workspace indexing jobs because the job executor always passes the global primary vector store to every repository pipeline.

Exact failure path

1. CLI persists embeddings to LanceDB

The CLI’s vector-store factory prefers a repository-local LanceDB store:

  • packages/cli/src/repowise/cli/providers/vector_store.py:9
  • LanceDB path: /.repowise/lancedb
  • It only falls back to InMemoryVectorStore when LanceDB is unavailable.

During repowise init, that store is passed to the generation pipeline and populated with page and decision embeddings.

2. REST startup discards that persisted index

When the REST server starts, it builds the configured embedder but unconditionally creates a new in-memory store:

  • packages/server/src/repowise/server/app.py:193
  • packages/server/src/repowise/server/app.py:195

embedder = _build_embedder()
vector_store = InMemoryVectorStore(embedder=embedder)

There is no code here that checks for .repowise/lancedb or opens a configured pgvector backend.

The comment claiming that LanceDB or pgvector can be configured through the environment does not match the implementation; no corresponding
server configuration path exists.

3. Single-repository search queries the empty store

In single-repository mode, workspace_config is None, so semantic search immediately queries the primary in-memory store:

  • packages/server/src/repowise/server/routers/search.py:149
  • packages/server/src/repowise/server/routers/search.py:153
  • packages/server/src/repowise/server/routers/search.py:156

Because this store was created during server startup and contains no vectors, InMemoryVectorStore.search() returns an empty list.

The existing workspace-only LanceDB resolver is never called in this path.

4. Workspace jobs use the wrong vector store

The job executor resolves the correct repository database through session_factory_override, but still takes the vector store from the global
application state:

  • packages/server/src/repowise/server/job_executor.py:317
  • packages/server/src/repowise/server/job_executor.py:319
  • packages/server/src/repowise/server/job_executor.py:395

vector_store = app_state.vector_store

That same store is used for generation, decision embeddings, and deletion of swept page vectors.

Consequences in workspace mode include:

  • New embeddings being written to the primary repository’s store or a shared in-memory store.
  • Existing per-repository LanceDB indexes remaining stale.
  • Embeddings disappearing after a server restart.
  • Repository-scoped searches potentially falling back to a shared store containing vectors from another repository.
  • Swept page IDs being deleted from the wrong vector store.

Reproduction

  1. Run repowise init inside a repository with LanceDB installed.
  2. Confirm that .repowise/lancedb exists and contains the wiki_pages table.
  3. Stop the CLI process.
  4. Run repowise serve from the same repository.
  5. Call:

GET /api/search?query=authentication&search_type=semantic

  1. Observe that semantic search returns no results even though the persisted LanceDB index contains matching pages.
  2. Run the equivalent CLI semantic search and observe that it can use the persisted index.

Expected behavior

  • Single-repository REST startup should open the repository’s existing .repowise/lancedb store.
  • Semantic search should work immediately after repowise init, without requiring a server-side reindex.
  • Workspace jobs should use the vector store belonging to the job’s repository.
  • Vector writes, deletes, and searches should remain isolated by repository.
  • InMemoryVectorStore should remain an explicit fallback when persistent storage is unavailable.

Proposed implementation direction

Introduce a shared, repository-aware vector-store resolver that can be used by:

  • REST application startup for the primary repository.
  • Workspace semantic-search routing.
  • The background job executor.
  • API-managed repositories registered after startup.

For a repository with a .repowise/lancedb directory, the resolver should open LanceDBVectorStore with the configured embedder and cache it by
repository ID. The job executor should resolve the store only after it has loaded the job’s repository metadata.

All cached stores should be closed during application shutdown.

Test gap

The current REST semantic-search test manually inserts vectors into the server’s in-memory store:

  • tests/unit/server/test_search.py:21
  • tests/unit/server/test_search.py:41

This proves that the endpoint works when its transient store is manually populated, but it does not test the actual repowise init → repowise
serve lifecycle.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions