feat: min-similarity override, edit-note CLI, and strip-frontmatter#571
feat: min-similarity override, edit-note CLI, and strip-frontmatter#571phernandez merged 13 commits intomainfrom
Conversation
🔍 New feature: `min_similarity` parameter on `search_notes` MCP tool allows per-query override of the global `semantic_min_similarity` threshold. Set to 0.0 to see all vector results, or 0.8+ for high precision. Threaded through the full call chain: - SearchQuery schema → MCP tool → SearchService → repository base → concrete repos (SQLite + Postgres) Also includes accumulated fixes and improvements from recent feature merges (project-prefixed permalinks, MCP UI variants, config isolation, metadata filters, vector threshold tests, semantic search test suite). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: phernandez <paul@basicmachines.co>
- Split "Basic Memory initialized" into a pre-command plain line (shown once on first run) - Rewrite cloud upsell with benefit-led copy: pain point → solution → CTA - Use package version instead of manual CLOUD_PROMO_VERSION for promo gating - Set discount code to BMFOSS - Add "Learn more" link and dimmed opt-out hint below panel - Remove cloud emoji from panel title to fix box alignment - Collapse two message builders into single _build_cloud_promo_message() - Update tests for new behavior (15 tests, all passing) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: phernandez <paul@basicmachines.co>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: phernandez <paul@basicmachines.co>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: phernandez <paul@basicmachines.co>
…bled When semantic_search_enabled is true, the search_notes MCP tool now automatically upgrades the default "text" search_type to hybrid retrieval mode (FTS + vector similarity via RRF fusion). This ensures users benefit from semantic infrastructure without needing to explicitly pass search_type="hybrid". Falls back gracefully to FTS when the MCP container is unavailable (e.g., CLI context). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: phernandez <paul@basicmachines.co>
🎯 Fixes Claude Desktop "Tool execution failed" on large structuredContent
payloads by reducing build_context response size ~40%.
Changes:
- Add _slim_context() to strip redundant fields (IDs, timestamps, file_paths)
from nested ObservationSummary, RelationSummary, EntitySummary objects
- Add _format_context_markdown() for compact text output
- Add format parameter ("json" default, "markdown") to build_context tool
- Update CLI build_context to work with new dict return type
- Fix E402 lint error in test_ui_resources.py (pytestmark after imports)
- Fix flaky search assertions in move_note and chatgpt integration tests
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>
- Remove brittle `not in` assertions from search tests that assumed precise keyword-only matching (both SQLite FTS and Postgres tsvector match more broadly via stemming and shared terms) - Use unique nonsense query "xyzzy99nonexistent" for no-results test - Add 30-minute timeout to all CI jobs to prevent runaway hangs (FastEmbed/ONNX Runtime background threads can keep pytest alive) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: phernandez <paul@basicmachines.co>
Signed-off-by: phernandez <paul@basicmachines.co>
Signed-off-by: phernandez <paul@basicmachines.co>
Signed-off-by: phernandez <paul@basicmachines.co>
- New `tool edit-note` subcommand with append/prepend/find_replace/replace_section operations, text and JSON output modes, and routing flags - New `--strip-frontmatter` flag on `tool read-note` that strips opening YAML frontmatter from content; JSON mode includes parsed `frontmatter` field - Unit and integration tests for both features Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: phernandez <paul@basicmachines.co>
|
Claude finished @phernandez's task in 2m 22s —— View job PR Review CompleteI've reviewed PR #571 against the Basic Memory team checklist. This is a substantial feature PR (100 files, 8307 additions, 861 deletions) that introduces multiple improvements to search, CLI tooling, and test infrastructure. ✅ Code Quality & StandardsStrengths:
Concerns:
Recommendation: Replace Unicode emojis with ASCII alternatives in promo.py: # Instead of: "☁️ [bold]Your knowledge, everywhere.[/bold] ✨\n"
# Use: "[bold]☁ Your knowledge, everywhere.[/bold]\n"
# Or even simpler ASCII: "[bold]Your knowledge, everywhere.[/bold]\n"✅ Testing & DocumentationStrengths:
Coverage Assessment:
Minor Gap:
✅ Basic Memory ArchitectureStrengths:
Architectural Observations:
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 236c540978
ℹ️ 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".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| # --- Per-project routing (when project_name given and no CLI override) --- | ||
| # Trigger: CLI --local/--cloud flag was NOT explicitly passed | ||
| # Why: per-project routing is an explicit user declaration that should be | ||
| # honored even from the MCP server (which sets FORCE_LOCAL) |
There was a problem hiding this comment.
Keep --cloud from bypassing per-project cloud mode
This guard makes BASIC_MEMORY_EXPLICIT_ROUTING=true skip per-project routing entirely, but force_routing(cloud=True) now always sets that flag. For projects configured with mode=CLOUD while global cloud_mode_enabled is false, get_client(project_name=...) falls through to local ASGI instead of the cloud proxy, so CLI commands run with --cloud can hit the wrong backend and mutate/read local data unexpectedly.
Useful? React with 👍 / 👎.
| if ( | ||
| self.default_project is not None and self.default_project not in self.projects | ||
| ): # pragma: no cover |
There was a problem hiding this comment.
Reject null default_project before downstream asserts
This change intentionally allows default_project to remain None, but several call paths still assume a default exists (notably get_project_config() asserts actual_project_name is not None when no project arg is passed). With a config that sets default_project to null, commands that rely on that helper now fail with an AssertionError instead of returning a user-facing "project required" error.
Useful? React with 👍 / 👎.
|
Claude finished @phernandez's task in 2m 19s —— View job PR Review Complete - Edit-Note CLI and Frontmatter StrippingI've reviewed the 7 changed files in this PR (commit ✅ Code Quality & StandardsExcellent:
✅ Testing & DocumentationComprehensive:
Coverage appears complete - all new code paths have corresponding tests. ✅ Basic Memory ArchitectureProper patterns followed:
Design quality:
✅ Security & PerformanceNo issues found:
✅ CompatibilityGood:
🔍 P1 Codex Review Comments AnalysisThe two P1 comments reference files ( However, I reviewed the concerns:
Neither P1 concern is directly caused by or worsened by this commit's changes. Summary Assessment✅ All Checklist Items PassedThis is a well-implemented feature PR that:
RecommendationsNo blocking issues. The PR is ready to merge. Optional improvements for future work:
Strengths Worth Highlighting
|
Summary
min_similarityoverride for search resultsbuild_contextJSON output with markdown format optiontool edit-noteCLI command (append/prepend/find_replace/replace_section)--strip-frontmatterflag ontool read-notewith parsed frontmatter in JSON modeTest plan
just test)🤖 Generated with Claude Code