fix(config): read the KB metadata database path from config instead of hardcoding it#33
Merged
Merged
Conversation
# Conflicts: # CHANGELOG.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The vector store honours
database.chroma_path, but the KB-metadata SQLite was hardcoded to a working-directory-relative./data/perspicacite.db. Isolation between instances therefore depended entirely on the process working directory, which is undocumented and easy to get wrong.A second instance configured with its own
database.pathandchroma_pathlisted the main hub's ~795 knowledge bases (metadata read from the repo-root SQLite) while its Chroma directory was empty. Any KB it created registered metadata in the production database while its vectors landed in the isolated store — producing knowledge bases that exist in the listing and return nothing.The bug was in four places, not one
web/state.pywas the reported site. The same hardcoding exists in:mcp/server.py, which also hardcoded its provenance sidecar to./data/provenancewhile readingconfig.database.chroma_pathtwo lines earlier.cli.py, twice (create-kb --from-bibtexandadd-to-kb), whose--session-dbhelp text advertiseddata/perspicacite.dbas the default while--chroma-diralready defaulted to the configured value.Fixing
state.pyalone would have left the MCP server and CLI mis-isolated.A trap worth naming
Config().database.pathevaluates to the literalPosixPath('~/.local/share/perspicacite/memory.db')— pydantic v2 does not run field validators on defaults unlessvalidate_default=True, so theexpand_homevalidator never fires for the default.SessionStoredoes not callexpandusereither. Readingconfig.database.pathnaively would have created a directory literally named~under the working directory.Changes
config/paths.py(new):resolve_session_db_path(config)returnsdatabase.pathexpanded, but only when the value was actually supplied — by config file orPERSPICACITE_DB_PATH, detected via pydantic'smodel_fields_set. Otherwise it returns the legacy./data/perspicacite.db.This matters: applying the schema default unconditionally would silently relocate the metadata of every existing deployment, whose knowledge bases live in the legacy path. Existing installs are unaffected unless they opt in.
web/state.py,mcp/server.py,cli.py: all four sites use the shared resolver. The MCP provenance sidecar now derives from the resolved database's parent, matchingweb/state.py.Both resolved paths are logged at startup, so a mis-isolated instance is obvious immediately:
Behaviour change for operators
If your
config.ymlsetsdatabase.path(asconfig.example.ymldocuments), this instance will now read that database instead of./data/perspicacite.db. That is the point of the fix, but it means an existing hub whose KBs live in./data/perspicacite.dbmust either drop the key or point it at that file. The new startup log makes the resolved location explicit.Verification
tests/unit/test_config_database_path.py(5 tests): an unset path keeps the legacy location; setting onlychroma_pathdoes not move the metadata store; an explicit~path is expanded;PERSPICACITE_DB_PATHreaches the resolver through the real loader; andAppState.initialize()hands the configured path toSessionStore.AppStatetest fails onmainand passes with this change, so it is a real regression test rather than a tautology.ruff: no new findings against themainbaseline for the touched files.LEGACY_SESSION_DB_PATHinconfig/paths.pyis now the single definition.Context
Found while standing up an isolated, locally-embedded instance (port 8010,
all-MiniLM-L6-v2) for the Consilium rediscovery benchmark. The previous workaround was to launch with the working directory set to the isolated data directory.