Skip to content

fix(mcp): address manual tool regressions - #1860

Closed
TPSJASPER wants to merge 1 commit into
basicmachines-co:mainfrom
TPSJASPER:fix/bm-search-line-matches
Closed

TPSJASPER wants to merge 1 commit into
basicmachines-co:mainfrom
TPSJASPER:fix/bm-search-line-matches

Conversation

@TPSJASPER

@TPSJASPER TPSJASPER commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

Why

Fixes #1843

Six defects found while verifying the bm_* manual examples. They misreport graph counts, make filtered searches look like matches, page the wrong row kinds, return empty reads, and point guidance at legacy tool names.

What changed

  • Write results. bm_write, bm_edit and bm_move report the accepted path, title, permalink and checksum. The observations/relations counts came from the pre-index response and always read zero, so they are gone; read the graph with bm_context.
  • One-note search. bm_search(identifier=...) now shows No matching lines. in text and keeps match_count: 0 with empty windows in JSON.
  • lines search. Ranked candidates whose accepted Markdown has no literal matching line are dropped in every mode. An empty filtered page keeps its next-page call, and total_is_exact is false because total counts ranked candidates, not matched rows.
  • bm_context patterns. Wildcard searches select notes first, so observations and relations are no longer primary rows. A pattern that names no note still addresses relation/observation permalinks directly, which keeps relation-shaped patterns such as components/*/part_of/*workflow* working; later pages of a note pattern do not fall back to graph rows.
  • Tiny read budgets. bm_read(max_tokens=...) keeps the first nonblank line and its leading whitespace even when it exceeds the approximate budget, so a small budget cannot return a whitespace-only page. Line coordinates and the continuation line stay usable.
  • Schema guidance. Missing-schema, missing-note and unresolved-field messages name bm_schema(command=...), bm_write, bm_search, bm_list and bm reindex --search instead of the legacy tool names.

The bm-write, bm-search, bm-context and bm-read manual pages document the resulting behavior.

Validation

  • 315 focused unit tests passed across the bm_* tools, schema, note writes, markdown sections, token budget, context service and glob context.
  • 73 manual-page tests passed.
  • test-int/mcp/test_build_context_underscore.py passed, covering the relation/observation wildcard patterns.
  • Full-repository ruff check, changed-file ruff format --check, ty check for the changed files, and git diff --check passed.
  • doctor --local completed sandboxed write, index and search in an isolated config directory.

The full-repository ty check still reports the same 8 environment diagnostics as the unmodified baseline (optional pymilvus/uvloop, Windows resource members); no ignores were added. The full test suite and Postgres tests were not run. The implementation was also replayed against origin/main with git apply --check.

Risks / rollback

The write result drops three JSON fields; callers that relied on the always-zero counts must read the graph instead. bm_context keeps graph-row patterns only when no note matches, so mixed note/relation patterns resolve to notes. Revert the commit to roll back.

Report only the accepted revision from bm_write, bm_edit and bm_move: the graph counts came from the pre-index response and always read zero.

Make bm_search's line view honest. A one-note search says when no line matches, ranked candidates without a literal matching line are dropped, and filtered line totals are marked inexact while the next page stays reachable. bm_context pattern searches prefer notes; a pattern that names no note still selects relation or observation permalinks directly, and later note pages do not fall back to graph rows.

Return the first nonblank line when bm_read's token budget is smaller than it, so a tiny budget cannot produce a whitespace-only page. Point bm_schema guidance at the bm_* tools and at bm reindex.

Fixes basicmachines-co#1843

Signed-off-by: TPSJASPER <592827953@qq.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 25, 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 ⚠️ Failed 2026-10-25T08:22:43.006259Z
We couldn’t complete this review. Comment @codex review to try again.
d4980fa PR opened
ℹ️ 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

Copy link
Copy Markdown
Member

Thanks, @TPSJASPER, for finding and fixing these manual-tool regressions, and for the regression coverage!

We’ve cherry-picked your commit into #1864, preserving your authorship and sign-off. That PR carries your fixes forward and adds integration coverage using real deferred materialization, files, indexing, and embeddings to exercise production behavior alongside our inline tests.

Closing this PR in favor of #1864. Thank you for the contribution!

@phernandez phernandez closed this Oct 25, 2026
phernandez added a commit that referenced this pull request Oct 25, 2026
## Why

Fixes #1843. Builds on contributor PR #1860, cherry-picked from
`TPSJASPER/basic-memory` at `d4980fa3a3975c2b73db39125625a29749f395d0`,
preserving the original author and sign-off.

The manual examples exposed misleading write counts, ambiguous empty
line searches, graph rows appearing as primary note results,
whitespace-only reads under tiny budgets, and guidance naming obsolete
tools. Existing tests missed the write-response problem because test
mode indexes writes inline while production accepts the note and queues
materialization.

## What Changed

- Carry forward the contributor's six fixes and manual updates: accepted
write identity/checksum results, explicit no-line-match output,
filtering of unmatched line candidates with honest pagination,
note-first graph patterns with graph-address compatibility, nonblank
tiny-budget reads, and current schema guidance.
- Add eight integration cases through the real MCP client/server and
ASGI API with file-backed SQLite or Postgres, production deferred
materialization, actual graph/index updates, and real FastEmbed
inference.
- Update existing write/edit integration tests to read graph counts
through `bm_context` after materialization, preserving their
observation/category/relation checks.
- Replace the new mocked search-candidate tests from #1860 with real
vector/hybrid integration cases, covering both matching and unmatched
candidates and continuation through an empty filtered page.

## Implementation Details

The integration context selects the production environment inside the
test call and opts out of the deterministic test embedder. A barrier
occupies the real single-worker materialization queue, so the tests can
assert that accepted content is readable while its file write is still
queued. Releasing the barrier and awaiting the existing
materialization/background drains proves eventual file and graph
convergence without polling sleeps or replaced application functions.

The new flows cover create/edit/move before and after materialization in
text and JSON, literal line filtering over real semantic candidates,
one-note misses, note-only graph pagination, nonblank read continuations
at tiny budgets, and public schema guidance. Existing inline tests
continue to provide fast focused coverage.

## Testing

- `uv run pytest test-int/mcp/test_deferred_manual_contracts.py -q -x -o
addopts=` — 8 passed on SQLite.
- `BASIC_MEMORY_TEST_POSTGRES=1 uv run pytest
test-int/mcp/test_deferred_manual_contracts.py -q -x -o addopts=` — 8
passed on real Docker Postgres.
- `uv run pytest test-int/mcp/test_build_context_underscore.py -q -o
addopts=` — 2 passed, preserving explicit relation/observation address
patterns.
- `uv run pytest tests/mcp/test_note_writes.py
tests/mcp/test_tool_bm_manual_regressions.py
tests/mcp/test_tool_bm_write.py tests/mcp/test_tool_bm_search.py
tests/mcp/test_tool_bm_context.py tests/mcp/test_tool_bm_read.py
tests/mcp/test_tool_schema.py tests/mcp/test_man_resources.py
tests/markdown/test_sections.py
tests/markdown/test_token_budget_nonempty.py
tests/services/test_context_glob_primary_notes.py
tests/services/test_context_service.py tests/test_man_pages.py
tests/cli/test_man_command.py -q -o addopts=` — 332 passed.
- `uv run pytest test-int/mcp/test_write_note_integration.py
test-int/mcp/test_edit_note_integration.py -q -x -o addopts=` — 48
passed on SQLite.
- `BASIC_MEMORY_TEST_POSTGRES=1 uv run pytest
test-int/mcp/test_write_note_integration.py::test_write_note_complex_content_with_observations_relations
test-int/mcp/test_edit_note_integration.py::test_edit_note_with_observations_and_relations
test-int/mcp/test_edit_note_integration.py::test_edit_note_special_characters_in_content
-q -x -o addopts=` — 3 passed on Postgres.
- `just fast-check` — lint, format and full typecheck passed.
- `just doctor` — sandboxed write/index/search passed.
- `git diff --check` — passed.

## Risks / Follow-ups

Write-result JSON drops the three graph-count fields; callers should use
`bm_context` after indexing when they need graph state. The new
integration tests require the real embedding model and take roughly a
minute on SQLite and two minutes on local Postgres. They use a real
queue barrier for deterministic scheduling and close both worker pools
during teardown. Full CI and current-head Codex review are checked on
this PR.

---------

Signed-off-by: TPSJASPER <592827953@qq.com>
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: TPSJASPER <592827953@qq.com>
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.

bm_* tools: six issues found while verifying the manual examples

2 participants