Files
phernandez 1987581ee3 docs: update v0.19.0 release notes and apply formatting fixes
Add #634 (stale schema metadata) to bug fixes section.
Apply ruff formatting to schema.py, write_note.py, test files.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>
2026-03-01 12:08:25 -06:00

14 KiB

v0.19.0 Release Notes

Overview

v0.19.0 is a major release that introduces semantic vector search, a schema validation system, project-prefixed permalinks, per-project cloud routing, and a significant upgrade to FastMCP 3.0. It includes 90+ commits since v0.18.0 spanning new features, architectural improvements, and stability fixes across both SQLite and Postgres backends.


Major Features

Full vector and hybrid search for SQLite (via sqlite-vec) and Postgres (via pgvector).

  • Hybrid search mode combines full-text search (FTS) with vector similarity for best results
  • Score-based fusion replaces RRF for hybrid ranking — max(vec, fts) + 0.3 * min(vec, fts) preserves dominant signals and rewards dual-source agreement (#577)
  • Default search mode is now hybrid when semantic search is enabled, text when disabled
  • Embedding providers: FastEmbed (local, default) or OpenAI API
  • Configurable similarity threshold via semantic_min_similarity (default 0.55)
  • Per-query min_similarity override on search_notes tool
  • Auto-backfill: existing entities get embeddings generated on first startup
  • Backend-specific distance-to-similarity conversion (cosine for SQLite, inner product for Postgres)
  • FTS fallback: if semantic dependencies are missing, search gracefully degrades to text-only
  • sqlite-vec knn k parameter capped at 4096 to prevent backend errors

Configuration:

{
  "semantic_search_enabled": true,
  "semantic_embedding_provider": "fastembed",
  "semantic_embedding_model": "bge-small-en-v1.5",
  "semantic_min_similarity": 0.55
}

Usage:

search_notes("machine learning concepts", search_type="hybrid")
search_notes("similar to my notes on coffee", search_type="vector")
search_notes("exact phrase match", search_type="text")
search_notes("broad search", min_similarity=0.3)  # lower threshold for more results

Schema System

Validate note structure against user-defined schemas with frontmatter-based rules.

  • Define schemas as YAML in note frontmatter with field types, required fields, and constraints
  • Frontmatter validation during sync — malformed notes get clear error messages
  • Schema inference from existing notes to bootstrap schemas from your content
  • Schema diff to compare two schemas and see changes
  • Available via MCP tools and CLI

Permalinks now include the project name for unambiguous cross-project references.

  • Memory URLs like memory://project-name/folder/note route to the correct project
  • Existing non-prefixed permalinks continue to work (backwards compatible)
  • Controlled by permalinks_include_project config (default: true)
  • build_context and search_notes auto-detect project from URL prefix

Per-Project Cloud Routing

Individual projects can be routed through the cloud while others stay local.

  • Set a project to cloud mode: bm project set-cloud research
  • Revert to local: bm project set-local research
  • Uses API key authentication: bm cloud set-key bmc_abc123...
  • MCP tools automatically route based on each project's mode
  • Local MCP server (bm mcp) still uses local routing for all projects by default
  • --local and --cloud CLI flags override per-command

Workspace Selection

Cloud projects can target specific workspaces for multi-tenant environments.

  • workspace parameter on MCP tools for explicit workspace targeting
  • CLI workspace-aware project listing with bm project list
  • Spinner feedback while fetching cloud projects

New Tools and Capabilities

Dashboard (bm project info)

bm project info now displays an htop-inspired compact dashboard with:

  • Horizontal bar charts for note types (top 5)
  • Embedding coverage bar with Unicode block characters
  • Colored status dots for at-a-glance health
  • EmbeddingStatus schema and get_embedding_status() service method for programmatic access

search_by_metadata has been merged into search_notes — one tool for all searches. query is now optional, so you can search purely by frontmatter metadata.

search_notes(metadata_filters={"status": "in-progress"})
search_notes(metadata_filters={"tags": ["security", "oauth"]})
search_notes(metadata_filters={"priority": {"$in": ["high", "critical"]}})
search_notes(metadata_filters={"schema.confidence": {"$gt": 0.7}})
search_notes(tags=["security"])  # convenience shorthand
search_notes(status="draft")     # convenience shorthand

JSON Output Mode

All MCP tools now support output_format="json" for machine-readable responses.

  • Default remains "text" for human-readable output (no breaking changes)
  • build_context defaults to "json" with slimmed payloads (redundant fields stripped)
  • CLI tool commands support --format json flag

tag: Search Shorthand

Search by tag using convenient shorthand syntax.

search_notes("tag:security")
search_notes("tag:coffee AND tag:brewing")

Entity User Tracking

Entities now track created_by and last_updated_by fields for attribution.

Improved Search Result Content (#609)

Search results now surface more relevant context:

  • matched_chunk_text populated for FTS-only hybrid results (no more fallback to truncated content)
  • TOP_CHUNKS_PER_RESULT increased from 3 to 5, catching answers deeper in large notes (~2700 → ~4500 chars)
  • CONTENT_DISPLAY_LIMIT doubled from 2000 to 4000 chars for results without matched chunks

write_note Overwrite Guard (#632)

write_note is now non-idempotent by default. If a note already exists, the tool returns an error instead of silently overwriting. Pass overwrite=True to replace, or use edit_note for incremental updates. Config option write_note_overwrite_default restores the old upsert behavior.


Architecture Changes

Score-Based Hybrid Fusion (#577)

RRF (Reciprocal Rank Fusion) compressed all fused scores to ~0.016, destroying ranking differentiation. The new formula max(vec, fts) + FUSION_BONUS * min(vec, fts) preserves dominant signals and rewards dual-source agreement. Zero-score results now produce zero fused score instead of receiving a 0.1 weight floor.

FastMCP 3.0 Upgrade

Upgraded from FastMCP 2.12.3 to 3.0.1.

  • Tool annotations (readOnlyHint, openWorldHint) for better client integration
  • Improved MCP protocol compliance
  • Better error handling and context management

Prompts Call MCP Tools Directly

MCP prompts (search, continue_conversation) now call MCP tools directly instead of going through API endpoints. This fixes empty results in discovery mode and ensures prompts use the same resolution logic as tools (including LinkResolver fallback).

build_context LinkResolver Fallback

build_context now falls back to LinkResolver when an exact permalink lookup returns empty. This uses the same 7-strategy resolution pipeline as read_note, so callers no longer get empty results for valid note identifiers that don't match exact permalinks.

Sync Handles Semantic Dependency Errors Gracefully

When sqlite-vec or another embedding provider is unavailable, sync_file now catches SemanticDependenciesMissingError separately. The entity is created and FTS-indexed successfully — only vector embeddings are skipped, with a clear warning:

WARNING: Semantic search dependencies missing — vector embeddings skipped for path=note.md.
Run 'bm reindex --embeddings' after resolving the dependency issue.

Unified Project Path

Cloud projects with bisync now store the local filesystem path in path (not the Docker container path). Config migration automatically promotes local_sync_pathpath for existing configs.


CLI Improvements

Status and Doctor Default to Local Routing

bm status and bm doctor now default to local routing since they scan the local filesystem. Previously, cloud-mode projects would route these commands to the cloud API, which returned Docker-internal paths that don't exist locally.

--format json for CLI Tool Commands

All bm tool subcommands support --format json for machine-readable output, enabling integration with scripts and plugins.

--json for Top-Level CLI Commands

Five additional CLI commands now support --json for machine-readable output:

  • bm status --json — sync report with new/modified/deleted/moved files and skipped files
  • bm project list --json — structured project list with name, paths, routing mode, and defaults
  • bm schema validate --json — validation report with per-note pass/fail, warnings, and errors
  • bm schema infer --json — field frequency analysis and suggested schema definition
  • bm schema diff --json — drift report with new fields, dropped fields, and cardinality changes

This complements the existing bm project info --json and bm tool --format json support, making all major CLI commands scriptable for CI pipelines and automation.

Cloud Promo and Analytics

  • Cloud promo panel shown on first run or version bump with OSS discount code
  • Anonymous usage telemetry via Umami Cloud (promo/login funnel events only)
  • Opt out with BASIC_MEMORY_NO_PROMOS=1
  • No PII, no file contents, no per-command tracking
  • See Telemetry in README

Bug Fixes

  • #577: RRF fusion compressed all hybrid scores to ~0.016, destroying ranking differentiation
  • #582: build_context returns empty results on valid note identifiers
  • #575: Remove hardcoded "main" default from default_project
  • #595: recent_activity dedup and pagination across MCP tools
  • #593: Backend-specific distance-to-similarity conversion
  • #592: Strip NUL bytes from content before PostgreSQL search indexing
  • #562: Use VIRTUAL instead of STORED columns in SQLite migration
  • #558: Add X-Tigris-Consistent headers to all rclone commands
  • #541: Handle EntityCreationError as conflict
  • #536: Stabilize metadata filters on Postgres
  • #533: Fix recent_activity prompt defaults
  • #530: Prevent spurious metadata: {} in frontmatter output
  • #601: Return matched chunk text in search results
  • #606: Accept null for expected_replacements in edit_note
  • #579, #607: Guard against closed streams in promo panel and missing vector tables on shutdown
  • #609: FTS-only hybrid results missing matched_chunk_text; content limits too conservative
  • #631: build_context related_results schema validation failure — replaced fragile _slim_context() stripping with Pydantic exclude=True field config
  • #630: Skip workspace resolution when client factory is active — prevents 401 errors in cloud MCP server mode
  • #30: tag: prefix query fails with hybrid search — moved tag prefix parsing to MCP tool level so it works with all search modes
  • #31: search_notes returns cluttered observation/relation-level results — now defaults to entity-level results
  • #28: schema_infer and schema_diff return raw Pydantic models as "undefined" in LLM output — added markdown formatters
  • Fix schema_validate identifier resolution (now uses LinkResolver) and text rendering (markdown formatter)
  • #634: schema_validate and schema_diff use stale database metadata instead of reading schema definitions from file — now reads frontmatter directly from the file with fallback to database metadata
  • Fix Post(**metadata) crash when frontmatter contains content or handler keys
  • Fix list-valued frontmatter fields (title, type) crashing on .strip() — now coerced to strings
  • Cap sqlite-vec knn k parameter at 4096 to prevent backend errors
  • Parameterize SQL queries in search repository type filters
  • Double-default display in project list
  • ensure_frontmatter_on_sync default changed to True
  • Status/doctor commands fail with cloud-mode projects (Docker path error)
  • Prompts return "0 projects" in discovery mode

Security

  • Upgrade cryptography for CVE advisory
  • Upgrade python-multipart for security advisory

Internal / Developer

  • #598: Upgrade FastMCP 2.12.3 → 3.0.1 with tool annotations
  • #594: Add ty as supplemental type checker
  • #538: Add fast feedback loop tooling (just fast-check, just doctor, just testmon)
  • #600: Rename entity_type to note_type for consistency
  • #596: Fix CLI runtime defects and audit regressions
  • CLI refactoring and workspace-aware cloud project listing
  • Split and speed up PR test matrix in CI
  • Fix CI: collect coverage from test jobs instead of re-running all tests
  • Create search_vector_chunks in test fixtures for Postgres compatibility

Configuration Changes

Setting Old Default New Default Notes
semantic_search_enabled false true Semantic search on by default
ensure_frontmatter_on_sync false true Frontmatter added during sync
permalinks_include_project false true Project prefix in permalinks

Upgrade Notes

  • Semantic search dependencies are now included by default. If sqlite-vec fails to load, search gracefully falls back to FTS. Run bm reindex --embeddings to generate embeddings for existing content.
  • Hybrid search scoring has changed from RRF to score-based fusion. Search result ordering may differ — results should be more accurate with better score differentiation.
  • search_by_metadata is removed as a standalone tool. Use search_notes with metadata_filters instead (same parameters, same behavior).
  • Project-prefixed permalinks are enabled by default. Existing notes keep their current permalinks until modified. Set permalinks_include_project: false to disable.
  • Frontmatter on sync is now enabled by default. Files without frontmatter will have it added on next sync. Set ensure_frontmatter_on_sync: false to preserve old behavior.
  • Config migration runs automatically for cloud projects with bisync — local_sync_path is promoted to path so filesystem operations work correctly.
  • write_note is no longer idempotent — calls to write_note for existing notes now return an error unless overwrite=True is passed. Use edit_note for incremental changes, or set write_note_overwrite_default: true in config to restore the old behavior.