# Changelog All notable changes to YAMS (Yet Another Memory System) will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - [SourceHut](https://sr.ht/~trvon/yams/): https://sr.ht/~trvon/yams/ ## Archived Changelogs - v0.6.x archive: docs/changelogs/v0.6.md - v0.5.x archive: docs/changelogs/v0.5.md - v0.4.x archive: docs/changelogs/v0.4.md - v0.3.x archive: docs/changelogs/v0.3.md - v0.2.x archive: docs/changelogs/v0.2.md - v0.1.x archive: docs/changelogs/v0.1.md ## [v0.7.7] - Unreleased ### Added - Hierarchical Embedding Architecture & Two-Stage Hybrid Search - Data model extensions for hierarchical embeddings - Added `EmbeddingLevel` enum (CHUNK, DOCUMENT) to distinguish embedding granularity - Extended `VectorRecord` with `level`, `source_chunk_ids`, `parent_document_hash`, `child_document_hashes` fields - Modified `embed_and_insert_document` to generate document-level embeddings (normalized mean of chunk vectors) - Document-level embeddings stored alongside chunk-level for two-stage search readiness - Added `twoStageVectorSearch` method that retrieves broader candidate set and applies hierarchical boosting - Configuration fields: `enable_two_stage`, `doc_stage_limit`, `chunk_stage_limit`, `hierarchy_boost` - Groups results by document and boosts scores based on document-level similarity - Wired into both parallel and sequential search paths for transparent operation - Profiling build support for performance analysis - New build type: `./setup.sh Profiling` enables instrumentation for Tracy, Valgrind, Perf - Builds to `build/profiling` directory with debug symbols + profiling hooks - Fuzzing build stub: `./setup.sh Fuzzing` reserved for future AFL++/libFuzzer integration - See `docs/developer/profiling.md` for comprehensive profiling guide - **EmbeddingService Architecture** - **Problem**: PostIngestQueue workers were blocking on slow embedding generation, causing: - Documents not searchable until embeddings complete - Add commands hanging/timing out - Ingest pipeline stalled waiting for embedding models - **Solution**: Separated embedding generation into dedicated `EmbeddingService` that consumes from `InternalBus` - PostIngestQueue now 2-stage pipeline (Metadata + KnowledgeGraph) - embeddings removed - Documents searchable immediately after FTS5 indexing (~milliseconds) - Embeddings generated asynchronously in background by EmbeddingService workers - Better resource isolation: ingest and embedding workers independently tunable - No more blocking: add commands return immediately, documents queryable right away - **ServiceManager & Daemon Lifecycle Improvements** - **Structured Concurrency**: Replaced manual backpressure logic with `std::counting_semaphore` for natural bounded concurrency - **SocketServer Improvements**: - Converted async_accept to `as_tuple` pattern, eliminating exception overhead during shutdown - Connection future tracking for graceful shutdown with 2s timeout verification - **Modern Error Handling**: Consistent use of `boost::asio::as_tuple(use_awaitable)` for error codes instead of exceptions - **Future Tracking**: Replaced detached spawns with `use_future` for verifiable connection lifecycle management - **Doctor Prune Command**: Intelligent cleanup of build artifacts, logs, cache, and temporary files - Support for 9 build systems (CMake, Ninja, Meson, Make, Gradle, Maven, NPM/Yarn, Cargo, Go) - Detection across 10+ programming languages (C/C++, Java, Python, JavaScript, Rust, Go, OCaml, Haskell, Erlang, etc.) - Hierarchical category system: build-artifacts, build-system, logs, cache, temp, coverage, IDE - **Extended package manager support**: Added 9 new categories for package dependencies and caches - IDE-specific: `ide-vscode`, `ide-intellij`, `ide-eclipse` for workspace caches - Dependencies: `package-node-modules` (npm/yarn/pnpm), `package-composer-vendor` (PHP), `package-cargo-target` (Rust) - Caches: `package-python-cache` (__pycache__/), `package-maven-repo`, `package-gradle-cache`, `package-go-cache`, `package-gem-cache`, `package-nuget-cache` - Composite groups: `package-deps`, `package-cache`, `packages` (all), `ide-all` - Path-based detection for directories: node_modules/, __pycache__/, .vscode/, target/, vendor/, etc. - Dry-run by default with `--apply` flag for execution - Usage: `yams doctor prune --category build-artifacts --older-than 30d --apply` - Usage: `yams doctor prune --category packages --apply` (clean all package artifacts) - Started C++23 Compatibility support expansion - Migrated vectordb to [https://github.com/trvon/sqlite-vec-cpp](https://github.com/trvon/sqlite-vec-cpp) - **Tree-sitter Symbol Extraction Plugin** Enhanced multi-language symbol extraction with Solidity support - **Solidity Support**: Added complete Solidity language support with 4 query patterns (functions, constructors, modifiers, fallback/receive) - **Enhanced C++ Patterns**: 16 function patterns + 6 class patterns including templates, constructors, destructors, operator overloads, method declarations inside class bodies - **Multi-Language Improvements**: Enhanced patterns for Python (decorated functions), Rust (impl/trait methods), JavaScript/TypeScript (arrow functions, generators, async), Kotlin (property declarations) across all 15 supported languages - **Critical Bug Fix**: Fixed query execution early-return bug that caused pattern short-circuiting - now executes all patterns resulting in **2.2x recall improvement** (20.6% → 45.1%) - **Benchmark Infrastructure**: Catch2-based benchmark suite with quality metrics (Recall/Precision/F1), performance metrics (Throughput/Latency), and JSON output for CI integration - **GTest Suite**: 7 Solidity tests covering ERC20 tokens, inheritance, interfaces, events, and modifiers (372 lines, all passing) - Plugin auto-downloads tree-sitter grammars on first use (configurable via `plugins.symbol_extraction.auto_download_grammars`) - CLI commands: `yams config grammar list/download/path/auto-enable/auto-disable` - Supports tree-sitter v13-15 grammar versions - **Entity Graph Service**: Background service for extracting and materializing code symbols into Knowledge Graph - Wired into IndexingPipeline and RepairCoordinator for automatic symbol extraction - Supports plugin-based language-specific symbol extraction - Foundation for symbol-aware search and code intelligence features - **Database Schema v16**: Added `symbol_metadata` table for rich symbol information storage - Stores symbol definitions, references, and metadata from code analysis plugins - Indexed by document hash and symbol name for efficient lookups - Integrated with Knowledge Graph for entity relationship tracking - Migration includes tests for both schema changes and symbol metadata storage - **Symbol-Aware Search Infrastructure**: Enhanced search with symbol/entity detection and enrichment - `SymbolEnricher` class extracts rich metadata from Knowledge Graph (definitions, references, call graphs) - Symbol context includes type, scope, caller/callee counts, and related symbols - **Hybrid Search Symbol Integration**: Symbol metadata now actively boosts search ranking - Added `symbol_weight` configuration field (default: 0.15 = 15% multiplicative boost) - `HybridSearchEngine::setSymbolEnricher()` method wires SymbolEnricher into search pipeline - Symbol matches receive score boost when `isSymbolQuery && symbolScore > 0.3` ### Fixed - **Grep Command Duplicate Output**: Fixed `yams grep` printing results twice when stderr is redirected - **Migration System Crash (macOS)**: Fixed SIGSEGV crash in `MigrationManager::recordMigration()` during daemon startup - **Root Cause**: `ServiceManager::co_migrateDatabase()` called `mm.initialize()` but ignored its return value. If initialization failed to create the `migration_history` table, migrations would continue and crash when attempting to INSERT into the non-existent table. - **Fix**: Added error checking for `mm.initialize()` with early return and proper error logging in `ServiceManager.cpp` - **Embedding System Architecture Simplification**: Simplified FSM readiness logic to check provider availability directly instead of waiting for model load events - IModelProvider checks `isAvailable()` immediately after plugin adoption - Eliminates unnecessary ModelLoading state transition - Fixes "Embedding Ready: Waiting" status showing incorrectly when embeddings were actually available - Model dimension retrieved via `getEmbeddingDim()` at adoption time - **Database Schema Recovery**: Manual creation of missing `kg_doc_entities` table from migration 7 - Table includes 8 columns with foreign keys to documents and kg_nodes - Created indexes: `idx_kg_doc_entities_document`, `idx_kg_doc_entities_node` - Fixes search query errors: "no such table: kg_doc_entities" - **Worker Thread Premature Exit**: Fixed io_context workers exiting immediately on startup by adding `executor_work_guard` to keep the context alive until explicit shutdown. - **SocketServer Backpressure**: Manual backpressure polling with `std::counting_semaphore`, eliminating 5-20ms delay loops and providing natural bounded concurrency. - **Embedding Consumer Deadlock**: Fixed race condition causing embedding job consumer to stall - Added defensive retry mechanism with exponential backoff for queue state recovery - Impact: Embedding background processing now reliable under high load - **FSM Cleanup & Degradation Tracking**: Standardized FSM usage across ServiceManager - Added `DaemonLifecycleFsm` reference to ServiceManager for centralized subsystem degradation tracking - **ServiceManager FSM Architecture**: Centralized state management and eliminated duplication - Added `DaemonLifecycleFsm& lifecycleFsm_` reference to ServiceManager for daemon-level degradation tracking - Removed scattered manual FSM state checks in favor of FSM query methods (`isReady()`, `isLoadingOrReady()`) - **Text Extraction for Source Code**: Fixed critical issue where JavaScript/TypeScript/Solidity/config files failed FTS5 extraction - `src/extraction/extraction_util.cpp`: Replaced hardcoded `is_text_like()` with `FileTypeDetector::isTextMimeType()` which uses comprehensive `magic_numbers.hpp` database; added extension normalization (handles both `.js` and `js` formats) - `src/extraction/plain_text_extractor.cpp`: - Removed hardcoded 50+ extension list, delegating to `FileTypeDetector` for dynamic detection - Enhanced `isBinaryFile()` with UTF-8 BOM support and reduced false positives - Added `isParseableText()` with proper UTF-8 validation (validates multi-byte sequences, continuation bytes) - Baseline registration now includes common config/markup extensions (`.toml`, `.ini`, `.yml`, `.md`, `.rst`) - `src/app/services/search_service.cpp`: Updated lightweight indexing to use `FileTypeDetector::isTextMimeType()` ### Changed - **Embedding Provider Lifecycle**: Transitioned from event-driven model loading to direct availability checking - Provider adoption now immediately dispatches `ModelLoadedEvent` if `isAvailable()` returns true - Simplified from 4-state FSM (Unavailable → ProviderAdopted → ModelLoading → ModelReady) to immediate ready transition - Aligns FSM with IModelProvider on-demand model loading architecture ### Removed - **Fuzzy Index Memory Optimization**: Enhanced BK-tree index building with intelligent document prioritization - Uses metadata and Knowledge Graph to rank documents by relevance (tagged > KG-connected > recent > code files) - Limits index to 50,000 documents by default (configurable via `YAMS_FUZZY_INDEX_LIMIT` environment variable) - Graceful degradation with `std::bad_alloc` handling prevents daemon crashes on large repositories - **Known Limitation**: Fuzzy search on very large repositories (>100k documents) may experience memory pressure. Consider using metadata/KG filters or grep with exact patterns for better performance - **ONNX Plugin Model Path Resolution**: Enhanced model path search to support XDG Base Directory specification - **Platform-Aware Plugin Installation**: Build system now auto-detects Homebrew prefix on macOS - `/opt/homebrew` on Apple Silicon, `/usr/local` on Intel Macs and Linux - System plugin directory automatically trusted by daemon at runtime - Override via `YAMS_INSTALL_PREFIX` environment variable - Model loading timeouts hardened: adapter and ONNX plugin now use std::async with bounded wait; removed detached threads causing UAF/segfaults (AsioConnectionPool guarded) - Vector DB dim resolution no longer hardcodes 384; resolves from DB/config/env/provider preferred model, else warns and defers embeddings - ONNX plugin: removed implicit 384 defaults, derives embeddingDim dynamically from model/config; added env override YAMS_ONNX_PRECREATE_RESOURCES - Improved load diagnostics: detailed logs for ABI table pointers, phases, and timeout causes - **Search Service Path Heuristic**: Tightened path-first detection to only trigger for single-token or quoted path-like queries (slashes, wildcards, or extensions). Multi-word queries now proceed to hybrid/metadata search, restoring results for phrases such as `"docs/delivery backlog prd tasks PBI"` while preserving fast path lookups for actual paths. - Daemon stop reliability: `yams daemon stop` now only reports success after the process actually exits and will fall back to PID-based termination (and orphan cleanup) when the socket path is unresponsive. - Prompt termination on signals: the daemon now handles SIGTERM/SIGINT to exit promptly when graceful shutdown isn't possible, addressing lingering yams-daemon processes after stop. - **Hybrid Search Simplification**: Removed complexity and environment variable overrides - Removed 6 environment variables: `YAMS_DISABLE_KEYWORD`, `YAMS_DISABLE_ONNX`, `YAMS_DISABLE_KG`, `YAMS_ADAPTIVE_TUNING`, `YAMS_FUSION_WEIGHTS`, `YAMS_OVERRELIANCE_PENALTY` - Kept `YAMS_DISABLE_VECTOR` for CI compatibility - Removed adaptive weight tuning logic (~30 LOC) - Removed over-reliance penalty mechanism - Keyword search now always executes (controlled by `config.keyword_weight`) - Fixed fusion weights for `LEARNED_FUSION` strategy: `{-2.0f, 3.0f, 2.0f, 1.5f, 1.0f}` ### Removed - Removed WASM, and legacy plugin system from codebase and ServiceManager ## [v0.7.6] - 10-13-2025 ### Added - **CLI Pattern Ergonomics**: Added `--pattern/-p` flag to `list` command as an alias for `--name`, improving consistency with other commands. The flag supports glob wildcards (`*`, `?`, `**`) and auto-normalizes relative paths to absolute when no wildcards are present. (`src/cli/commands/list_command.cpp`) - **Grep Literal Text Hints**: Added smart error detection and helpful hints when grep patterns contain regex special characters. When a pattern fails regex compilation or returns no results, grep now suggests using the `-F` flag with the exact command to run. Added `-Q` as a short alias for `-F/--fixed-strings/--literal-text` to match git grep convention. (`src/cli/commands/grep_command.cpp`) - **Search Literal Text Aliases**: Added `-F/-Q/--fixed-strings` aliases to `search` command for consistency with `grep`. These short flags make it easier to search for literal text containing special characters like `()[]{}.*+?`. Updated help text with concrete examples. (`src/cli/commands/search_command.cpp`) - Grep: enabling `[search.path_tree]` now lets explicit path filters reuse the metadata-backed path-tree engine, and tag-only invocations default the pattern to `.*`, removing the need for placeholder expressions. citesrc/app/services/grep_service.cpp:240src/cli/commands/grep_command.cpp:305 - **Tree-based List with Filters**: Extended tree-based path queries to support tag, MIME type, and extension filtering. The `list` command now uses the tree index even when filters are applied, improving performance for pattern+filter queries (e.g., `yams list --name "docs/**" --tags "test"`). - **Benchmark: Tree List Filters**: New benchmark suite (`tree_list_filter_bench`) measures query performance with various filter combinations. Results show 100-160μs query times with up to 10k queries/sec throughput. Filter queries often outperform path-only queries due to reduced result set sizes. - **Grep SQL-Level Pattern Filtering**: Added `queryDocumentsByGlobPatterns()` function that converts glob patterns (e.g., `tests/**/*.cpp`) to SQL LIKE patterns and queries the database directly, eliminating the need to load all documents into memory before filtering. Grep performance with `--include` patterns improved dramatically on large repositories. - **Search Multi-Pattern Support**: Added `pathPatterns` vector field to `SearchRequest` IPC protocol (field 34) enabling server-side filtering of multiple include patterns. Search command now sends all patterns to daemon instead of filtering results client-side, eliminating timeouts and OOM errors in sandboxed environments. - **MCP Search Multi-Pattern Support**: Added `include_patterns` array parameter to MCP search tool, enabling clients to specify multiple path patterns with OR logic. The MCP server now populates `pathPatterns` in daemon requests, matching CLI behavior. (`include/yams/mcp/tool_registry.h`, `src/mcp/mcp_server.cpp`) ### Changed - MCP stdio transport: stdout buffering now adapts to interactive vs non-interactive streams, stderr is forced unbuffered, and JSON-RPC batch arrays over stdio are parsed in-line to match the Model Context Protocol 2025-03-26 transport requirements. Additional unit coverage exercises batch handling and error budgets for framed headers. - **MCP Server**: `cat` and `get` tools now resolve relative paths using `weakly_canonical`, improving document lookup for non-absolute paths. - **Path Canonicalization**: Document paths are now canonicalized using `weakly_canonical()` at ingestion time to ensure consistent path matching across symlinked directories (e.g., `/var` → `/private/var` on macOS). This fixes pattern-based queries that previously failed due to path mismatch between indexed and query paths. (`src/metadata/path_utils.cpp`) - **Integration Test Stability**: Improved `TreeBasedListE2E` test reliability by replacing fixed sleep with polling-based wait for document indexing completion. Test pass rate improved from ~60% to 100%. - **Grep Performance**: Grep service now uses SQL-level pattern filtering when `--include` patterns are provided, fetching only matching documents from the database instead of loading all documents and filtering in memory. Converts glob patterns to SQL LIKE patterns (e.g., `*.cpp` → `%.cpp`, `tests/**/*.h` → `tests/%.h`). This eliminates hangs on large repositories (10K+ documents). - **Search Service**: Updated to handle multiple path patterns via `pathPatterns` vector field, iterating through all patterns with OR logic for server-side filtering. Removed client-side filtering that previously caused timeouts with multiple `--include` patterns. - **Build System**: Fixed VS Code task definitions with correct Conan 2.x output paths. Meson native file paths updated from `builddir/conan_meson_native.ini` to `builddir/build-debug/conan/conan_meson_native.ini` and `build/release/build-release/conan/conan_meson_native.ini` to match actual Conan 2 directory structure. (`.vscode/tasks.json`) ### Fixed - **MCP Search/Grep Hang**: Fixed MCP server's `search` and `grep` tools hanging indefinitely by ensuring all async components use the same io_context. The root cause was a multi-layered async execution mismatch: (1) The DaemonClient's config didn't specify an executor, causing it to create its own internal io_context. (2) `callTool()` was spawning work on GlobalIOContext and blocking a worker thread waiting for results. (3) The two separate io_contexts couldn't communicate, causing deadlock. Fixed by: (a) Configuring daemon_client to use GlobalIOContext executor in MCPServer constructor. (b) Removing the nested local io_context from `callTool()` - now correctly spawns on GlobalIOContext (which has background worker threads) and waits for results. (c) Removing nested io_context from `handleSearchDocuments()` to use `co_await` directly. (`src/mcp/mcp_server.cpp:403,2029-2039,2225-2226`) - **Document Service**: Improved `resolveNameToHash` to correctly handle filename-only lookups by searching for paths ending with the given name, ensuring that commands like `cat` with a simple filename succeed. - **Tree Query Pattern Matching**: Fixed wildcard pattern parsing to correctly handle recursive patterns (`/**`) by stripping all trailing wildcards iteratively instead of checking for a single wildcard character. (`src/app/services/document_service.cpp`) - **Grep Hang**: Fixed grep command hanging indefinitely when using `--include` patterns on large repositories. The service was fetching all documents before filtering; now uses SQL-level pattern matching to fetch only relevant documents. - **Search Timeout**: Fixed search command timeouts/OOM when using multiple `--include` patterns. Previously only the first pattern was sent to daemon with remaining patterns filtered client-side after retrieving ALL results. Now all patterns are sent to daemon for server-side filtering. - **Search Pattern Matching**: Fixed glob pattern normalization to correctly match filename patterns like `*.md` and `*.cpp` anywhere in the path tree. Patterns starting with a single `*` (e.g., `*.ext`) are now automatically prefixed with `**/` to match paths at any depth. This ensures patterns like `--include="*.md,*.cpp"` correctly return all matching files regardless of their directory location. - **Search Async Path**: Fixed `SearchCommand::executeAsync()` not populating `pathPatterns` field in daemon request, causing server-side multi-pattern filtering to fail. The async code path (default execution) now correctly sends all include patterns to the daemon, matching the behavior of the sync path. (`src/cli/commands/search_command.cpp:1360-1365`) - **Database Schema Compatibility**: Fixed "constraint failed" errors during document insertion on databases with migration v12 (pre-path-indexing schema). The `insertDocument()` function now conditionally builds INSERT statements based on the `hasPathIndexing_` flag, supporting both legacy (13-column) and modern (17-column with path indexing) schemas. This allows YAMS to work correctly regardless of whether migration v13 has been applied. (`src/metadata/metadata_repository.cpp:318-380`) - **MCP Protocol Version Negotiation**: Fixed "Unsupported protocol version requested by client" error (code -32901) by making protocol version negotiation permissive by default (`strictProtocol_ = false`). The server now gracefully accepts any protocol version requested by clients, falling back to the latest supported version (`2025-03-26`) if the requested version is not in the supported list. Also added intermediate MCP protocol versions (`2024-12-05`, `2025-01-15`) to the supported list. This ensures maximum compatibility with MCP clients regardless of which spec version they implement. (`src/mcp/mcp_server.cpp:560,1254-1260`)