Skip to content

refactor(mcp): port search tests to bm_search and remove search_notes - #1963

Merged
phernandez merged 6 commits into
mainfrom
test/mcp-bm-search-port
Oct 29, 2026
Merged

phernandez merged 6 commits into
mainfrom
test/mcp-bm-search-port

Conversation

@phernandez

@phernandez phernandez commented Oct 29, 2026 •

Copy link
Copy Markdown
Member

Summary

Stacked on #1964 (refactor/remove-cloud-only-legacy-tools), which removes read_note, the last core caller of search_notes. Merge #1964 first.

Two commits:

  1. test(mcp): port search tests to bm_search. Ports the search tests from the retired search_notes function to the published bm_search tool.
  2. refactor(mcp): remove search_notes. bm_search is now the only caller, so search.py keeps only the shared query pipeline (about 1,100 src lines deleted).
    • Deleted search_notes, _format_search_error_response, _format_service_unavailable_response, _format_search_markdown, _NO_SEARCH_CRITERIA_MESSAGE, METADATA_FILTERS_DESCRIPTION, and the tools/__init__ re-export.
    • _search_all_projects no longer takes output_format. It always returns the merged rows. MultiProjectRan carries payload, and MultiProjectFailed carries only reason. This removes bm_search's # pragma: no cover text branch.
    • Dropped the status parameter of _build_search_query and the tags parameter of split_tag_shorthand; only search_notes passed them. split_tag_shorthand now returns tags in query order instead of set order.
    • Deleted utils.strict_search_tags (the tags coercer for search_notes) and its tests in tests/test_coerce.py.
    • Ported the remaining callers: test_index_readiness.py, which refactor(mcp): port context and recent-activity tests to bm_context and bm_project #1962 also ports; the parity test in test_tool_posix.py, which refactor(cli)!: rebuild cat/grep/ls/find on bm_* tools and remove tail #1960 deletes; and the search_notes entries in test_tool_contracts.py and implementation_mcp.py.
    • Added tests for bm_search paths that were covered only incidentally before:
      • the explicit-scope refusal;
      • the (more matches from line N) hint;
      • the semantic excerpt in text output;
      • non-Markdown hits dropped by lines;
      • invalid and duplicate project refs;
      • workspace permalink qualification.

Files

Before After
tests/mcp/test_tool_search.py tests/mcp/test_tool_bm_search_query.py (new)
tests/mcp/test_mcp_note_type_normalization.py folded into test_tool_bm_search_query.py
tests/mcp/test_search_total_exactness.py folded into test_tool_bm_search_query.py
tests/mcp/test_tool_search_temporal.py tests/mcp/test_tool_bm_search_temporal.py
tests/mcp/tools/test_search_notes_multi_project.py tests/mcp/tools/test_bm_search_multi_project.py
tests/mcp/tools/test_search_notes_multi_project_temporal.py folded into test_bm_search_multi_project.py
tests/mcp/tools/test_cjk_search_guidance.py folded into test_bm_search_multi_project.py
tests/api/v2/test_cjk_search_guidance.py its MCP assertions now call bm_search
tests/mcp/test_tool_bm_search.py two tests that replaced _search_all_projects now run the real path or moved to the multi-project file

Ported to real code paths

These tests used to stub get_project_client, resolve_project_and_path and SearchClient and inspect the captured payload. They now do one of two things:

  • Run bm_search end to end over notes written with bm_write: title and permalink modes, note types including snake_case canonicalization, items, categories, since, the note_type filter alias, tag shorthand, total exactness per mode, default hybrid mode, Boolean queries defaulting to text, configured default_search_type, never-indexed versus indexed misses, and comma or JSON list strings through the MCP layer.
  • Call the shared pure helpers that bm_search uses on every request: _build_search_query, split_tag_shorthand and _search_type_for.

The valid-time doc tests now check bm-search(3) instead of the search_notes docstring.

Remaining monkeypatches, and why

  • Multi-project tests: several databases only exist in Cloud. These tests stub the per-database boundary: project discovery, the per-workspace get_client, ScopedSearchClient and the readiness probe. The merge, paging, attribution and failure handling run for real. A new test, test_hits_from_two_local_projects_name_their_project, runs the whole path with no stubs across two real local projects.
  • "Filter ran nowhere" temporal test: stubs only ScopedSearchClient, to stand in for a server older than SPEC-82.
  • Keyword-only host: two tests patch semantic_runtime_available, because sqlite-vec loads in the test environment.
  • Default-mode tests: these install the MCP container the way the server lifespan does. An earlier in-process MCP session leaves its container behind with a stale config, so each test sets its own.

Dropped, with reasons

  • Error formatting (TestSearchErrorFormatting, TestSearchToolErrorHandling, invalid search_type returned as a string): bm_search raises tool errors instead of returning guidance markdown. Its refusals are covered in test_tool_bm_search.py.
  • _format_search_markdown tests, and the valid-time label in markdown output: this is the legacy text format. bm_search renders with _format_results.
  • Workspace memory:// routing through search_notes: bm_search routes memory:// URLs through open_project_target. That path is covered by test_note_targets.py and the project-qualified memory URL test.
  • search_notes parameter-annotation tests and tags= tests (comma-split, invalid types, direct-call CLI regression): bm_search has no tags or status parameters, and no CLI calls search_notes any more. The equivalent bm_search list parameters are tested through MCP.
  • Multi-project opt-in: bm_search requires an explicit scope, and that refusal is already tested.
  • Redundant cases: plain text search, the project-prefixed memory URL and page_size=1 pagination are already covered in test_tool_bm_search.py.

Coverage

search.py and ranked_search.py are both at 100%, measured over the touched test files.

Verification

  • just fast-check
  • just test-unit-sqlite -k "search or test_index_readiness or test_tool_contracts or test_coerce or ...": 1146 passed. One failure, test_tokenizing_scales_linearly_with_query_length, is a timing test; it passes when rerun on its own.
  • just test-unit-postgres -k "bm_search or test_cjk_search_guidance or test_index_readiness or test_tool_contracts or test_coerce or bm_search_parity": all pass, after making one new test backend-neutral.
  • just test-int-sqlite -k search: 64 passed

🤖 Generated with Claude Code

https://claude.ai/code/session_01CMYVL1x91B8kJxy7nn2GU8

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-29T20:22:57.398325Z dbd4f12 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@phernandez
phernandez changed the base branch from main to refactor/remove-cloud-only-legacy-tools October 29, 2026 17:58
@phernandez
phernandez added this pull request to stack #1965 October 29, 2026 18:14
@phernandez
phernandez force-pushed the test/mcp-bm-search-port branch from 9ab3a5c to 7d775ce Compare October 29, 2026 18:14
@phernandez phernandez changed the title test(mcp): port search tests to bm_search refactor(mcp): port search tests to bm_search and remove search_notes Oct 29, 2026
@phernandez

Copy link
Copy Markdown
Member Author

@codex review

1 similar comment
@phernandez

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Swish!

Reviewed commit: 1e1f3d9513

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@phernandez

Copy link
Copy Markdown
Member Author

@codex review

@phernandez
phernandez force-pushed the test/mcp-bm-search-port branch from 1e1f3d9 to 3c96a93 Compare October 29, 2026 19:27

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3c96a93d9f

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Base automatically changed from refactor/remove-cloud-only-legacy-tools to main October 29, 2026 19:35
phernandez and others added 4 commits October 29, 2026 14:35
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CMYVL1x91B8kJxy7nn2GU8
Signed-off-by: phernandez <paul@basicmachines.co>
bm_search is the only caller left, so search.py keeps just the shared query
pipeline: the legacy markdown and error-guidance formatters go, the search
across projects always returns rows, and the status/tags parameters only
search_notes passed are dropped. strict_search_tags (search_notes' tags
coercer) goes with it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CMYVL1x91B8kJxy7nn2GU8
Signed-off-by: phernandez <paul@basicmachines.co>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CMYVL1x91B8kJxy7nn2GU8
Signed-off-by: phernandez <paul@basicmachines.co>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CMYVL1x91B8kJxy7nn2GU8
Signed-off-by: phernandez <paul@basicmachines.co>
@phernandez
phernandez force-pushed the test/mcp-bm-search-port branch from 3c96a93 to 750db74 Compare October 29, 2026 19:35
phernandez and others added 2 commits October 29, 2026 15:16
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CMYVL1x91B8kJxy7nn2GU8
Signed-off-by: phernandez <paul@basicmachines.co>
…n docs

The ui templates served the retired view_note/search UI tools; nothing imports
them. Comments and docstrings that named removed tools now describe the bm_*
surface.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CMYVL1x91B8kJxy7nn2GU8
Signed-off-by: phernandez <paul@basicmachines.co>
@phernandez

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep them coming!

Reviewed commit: dbd4f120e6

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@phernandez
phernandez merged commit 74aa039 into main Oct 29, 2026
54 checks passed
@phernandez
phernandez deleted the test/mcp-bm-search-port branch October 29, 2026 20:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant