refactor(core): compile search filters over an explicit ProjectScope - #1562
Merged
Merged
Conversation
First step of #1558: one scope-parameterized read path shared by the single-project route, the database-scoped route, and MCP search_all_projects. This commit moves the FTS compilation out of the project-bound repositories and makes the project set an explicit value. No query behavior changes. - search_scope.ProjectScope: sorted, unique, positive project IDs built once at the boundary; predicate() renders `IN (:scope_N)` or `1 = 0` for empty. - search_filters: FilterDialect (the two spellings that differ per backend), CompiledFilter (named FROM/WHERE/params/order/score instead of a 5-tuple), and shared_filter_conditions for the filters both backends compile the same way. Removes the duplicated filter blocks the two repositories carried. - sqlite_search_query / postgres_search_query: term preparation, relaxed renderers, syntax-error classifiers, and compile_fts_filter as module functions. The SQLite compiler is pure; the repository passes the entity columns in instead of the compiler opening a session. - note_type_filters / temporal_filters take scope= and match search rows on their full (project_id, ...) identity. - SearchRepositoryBase gains self.scope (a scope of one) and drops the abstract _prepare_search_term hook nothing in the base called. - Tests call the module functions directly; Postgres tests patch the classifier on the repository module where it is bound. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_019YW9ysxugGGBCNEGzsxtFV Signed-off-by: phernandez <[email protected]>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
This was referenced Sep 15, 2026
phernandez
added this pull request to stack #1564
September 15, 2026 17:08
This was referenced Sep 15, 2026
Merged
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.
Why
Part 1 of the #1558 stack. Single-project search, the database-scoped search route (the contract from #1559 and cloud #2080), and MCP
search_all_projectsshould be one read pipeline parameterized by project scope, so one project ranks identically through every route. This PR makes the scope an explicit value and moves FTS compilation out of the project-bound repositories so a shared reader can call it next.No query behavior changes. Project repositories call the same compilers with a scope of one.
What changed
search_scope.ProjectScope: sorted, unique, positive project IDs, built once at the boundary withof()orsingle().predicate(column, params)renderscolumn IN (:scope_0, ...)and binds each ID once per statement; an empty scope renders1 = 0. Absence is not representable.search_filters:FilterDialectholds the two spellings that differ per backend (note-type JSON accessor,after_datecomparison).CompiledFilterreplaces the 5-tuple the compilers returned.shared_filter_conditionscompiles the filters both backends previously carried as copies: scope, permalink, directory subtree, candidate keys, item type, category, note type,after_date, valid time.sqlite_search_query/postgres_search_query: term preparation, relaxed renderers, syntax-error classifiers, andcompile_fts_filteras module functions. The SQLite compiler is pure; the repository resolves the entity table's columns and passes them in.note_type_filters/temporal_filters: takescope=and match search rows on their full(project_id, ...)identity.SearchRepositoryBase: gainsself.scope; drops the abstract_prepare_search_termhook nothing in the base called.fts_query(search_repository)helper; Postgres tests patch the syntax-error classifier on the repository module where it is bound. Newtest_search_scope.py.Not in this PR
SearchReader; projectsearch()delegates.QUERY /v2/search/and the scoped service method, porting the feat(core): add explicit multi-project API search #1559 tests.search_all_projectswith the scoped reader.This supersedes the extraction half of #1559. That PR should not merge as-is.
Testing
just fast-checkuv run pytest tests/repository tests/services/test_search*.py tests/api/v2/test_search*.py tests/api/v2/test_cjk_search_guidance.py --no-cov(SQLite)BASIC_MEMORY_TEST_POSTGRES=1 uv run pytestover the search repository, relaxation, temporal, metadata-filter, and search router suites (testcontainers)just doctor🤖 Generated with Claude Code
https://claude.ai/code/session_019YW9ysxugGGBCNEGzsxtFV