# Changelog

**Recent releases for MCP Memory Service (v8.0.0 and later)**

All notable changes to the MCP Memory Service project will be documented in this file.

For older releases, see [CHANGELOG-HISTORIC.md](./CHANGELOG-HISTORIC.md).

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [8.42.0] - 2025-11-27

### Added
- **Visible Memory Injection Display** - Users now see injected memories at session start (commit TBD)
  - Added `showInjectedMemories` config option to display top 3 memories with relevance scores
  - Shows memory age (e.g., "2 days ago"), tags, and relevance scores
  - Formatted with colored output box for clear visibility
  - Helps users understand what context the AI assistant is using
  - Configurable via `~/.claude/hooks/config.json`

### Changed
- **Session-End Hook Quality Improvements** - Raised quality thresholds to prevent generic boilerplate (commit TBD)
  - Increased `minSessionLength` from 100 → 200 characters (requires more substantial content)
  - Increased `minConfidence` from 0.1 → 0.5 (requires 5+ meaningful items vs 1+)
  - Added optional LLM-powered session summarizer using Gemini CLI
  - New files: `llm-session-summarizer.js` utility and `session-end-llm.js` core hook
  - Prevents low-quality memories like "User asked Claude to review code" from polluting database
  - Database cleaned from 3352 → 3185 memories (167 generic entries removed)

### Fixed
- **Duplicate MCP Fallback Messages** - Fixed duplicate "MCP Fallback → Using standard MCP tools" log messages (commit TBD)
  - Added module-level flag to track if fallback message was already logged
  - Message now appears once per session instead of once per query
  - Improved session start hook output clarity

### Performance
- **Configuration Improvements** - Better defaults for session analysis
  - Enabled relevance scores in context formatting
  - Improved memory scoring to prioritize quality over recency for generic content
  - Session-end hook re-enabled with improved quality gates

## [8.41.2] - 2025-11-27

### Fixed
- **Hook Installer Utility File Deployment** - Installer now copies ALL utility files instead of hardcoded lists (commit 557be0e)
  - **BREAKING**: Previous installer only copied 8/14 basic utilities and 5/14 enhanced utilities
  - Updated files like `memory-scorer.js` and `context-formatter.js` were not deployed with `--natural-triggers` flag
  - Replaced hardcoded file lists with glob pattern (`*.js`) to automatically include all utility files
  - Ensures v8.41.0/v8.41.1 project affinity filtering fixes get properly deployed
  - Future utility file additions automatically included without manual list maintenance
  - **Impact**: Users running `python install_hooks.py --natural-triggers` now get all 14 utility files, preventing stale hooks

## [8.41.1] - 2025-11-27

### Fixed
- **Context Formatter Memory Sorting** - Memories now sorted by recency within each category (commit 2ede2a8)
  - Added sorting by `created_at_iso` (descending) after grouping memories into categories
  - Ensures most recent memories appear first in each section for better context relevance
  - Applied in `context-formatter.js` after category grouping logic
  - Improves user experience by prioritizing newest information in memory context

## [8.41.0] - 2025-11-27

### Fixed
- **Session Start Hook Reliability** - Improved session start hook reliability and memory filtering (commit 924962a)
  - **Error Suppression**: Suppressed Code Execution ModuleNotFoundError spam
    - Added `suppressErrors: true` to Code Execution call configuration
    - Eliminates console noise from module import errors during session start
  - **Clean Output**: Removed duplicate "Injected Memory Context" output
    - Removed duplicate stdout console.log that caused double messages
    - Session start output now cleaner and easier to read
  - **Memory Filtering**: Added project affinity scoring to prevent cross-project memory pollution
    - New `calculateProjectAffinity()` function in `memory-scorer.js`
    - Hard filters out memories without project tag when in a project context
    - Soft scoring penalty (0.3x) for memories from different projects
    - Prevents Azure/Terraform memories from appearing in mcp-memory-service context
  - **Classification Fix**: Session summaries no longer misclassified as "Current Problems"
    - Excludes `session`, `session-summary`, and `session-end` memory types from problem classification
    - Prevents confusion between historical session notes and actual current issues
  - **Path Display**: "Unknown location" now shows actual path via `process.cwd()` fallback
    - When git repository detection fails, uses `process.cwd()` instead of "Unknown location"
    - Provides better context awareness even in non-git directories

## [8.40.0] - 2025-11-27

### Added
- **Session Start Version Display** - Automatic version information display during session startup (commit f2f7d2b, fixes #250)
  - **Version Checker Utility**: New `version-checker.js` utility in `claude-hooks/utilities/`
    - Reads local version from `src/mcp_memory_service/__init__.py`
    - Fetches latest published version from PyPI API
    - Compares versions and displays status labels (published/development/outdated)
    - Configurable timeout for PyPI API requests
  - **Session Start Integration**: Version information now appears automatically during session initialization
    - Displays format: `📦 Version → X.Y.Z (local) • PyPI: X.Y.Z`
    - Shows after storage backend information
    - Provides immediate visibility into version status
  - **Testing**: Includes `test_version_checker.js` for utility validation
  - **Benefits**:
    - Quick version verification without manual checks
    - Early detection of outdated installations
    - Improved development workflow transparency
    - Helps users stay current with latest features and fixes

## [8.39.1] - 2025-11-27

### Fixed
- **Dashboard Analytics Bugs** - Fixed three critical bugs in the analytics section (commit c898a72, fixes #253)
  - **Top Tags filtering**: Now correctly filters tags by selected timeframe (7d/30d/90d)
    - Implemented time-based filtering using `get_memories_by_time_range()`
    - Counts tags only from memories within the selected period
    - Maintains backward compatibility with all storage backends
  - **Recent Activity display**: Bars now show percentage distribution
    - Enhanced display to show both count and percentage of total
    - Tooltip includes both absolute count and percentage
    - Activity count label shows percentage (e.g., '42 (23.5%)')
  - **Storage Report field mismatches**: Fixed "undefined chars" display
    - Fixed field name: `size_kb` instead of `size`
    - Fixed field name: `preview` instead of `content_preview`
    - Fixed date parsing: `created_at` is ISO string, not timestamp
    - Added null safety and proper size display (KB with bytes fallback)

## [8.39.0] - 2025-11-26

### Performance
- **Analytics date-range filtering**: Moved from application layer to storage layer for 10x performance improvement (#238)
  - Added `get_memories_by_time_range()` to Cloudflare backend with D1 database filtering
  - Updated memory growth endpoint to use database-layer queries instead of fetching all memories
  - **Performance gains**:
    - Reduced data transfer: 50MB → 1.5MB (97% reduction for 10,000 memories)
    - Response time (SQLite-vec): ~500ms → ~50ms (10x improvement)
    - Response time (Cloudflare): ~2-3s → ~200ms (10-15x improvement)
  - **Scalability**: Now handles databases with >10,000 memories efficiently
  - **Benefits**: Pushes filtering to database WHERE clauses, leverages indexes on `created_at`

## [8.38.1] - 2025-11-26

### Fixed
- **HTTP MCP Transport: JSON-RPC 2.0 Compliance** - Fixed critical bug where HTTP MCP responses violated JSON-RPC 2.0 specification (PR #249, fixes #236)
  - **Problem**: FastAPI ignored Pydantic's `ConfigDict(exclude_none=True)` when directly returning models, causing responses to include null fields (`"error": null` in success, `"result": null` in errors)
  - **Impact**: Claude Code/Desktop rejected all HTTP MCP communications due to spec violation
  - **Solution**: Wrapped all `MCPResponse` returns in `JSONResponse` with explicit `.model_dump(exclude_none=True)` serialization
  - **Verification**:
    - Success responses now contain ONLY: `jsonrpc`, `id`, `result`
    - Error responses now contain ONLY: `jsonrpc`, `id`, `error`
  - **Testing**: Validated with curl commands against all 5 MCP endpoint response paths
  - **Credits**: @timkjr (Tim Knauff) for identifying root cause and implementing proper fix

## [8.38.0] - 2025-11-25

### Improved
- **Code Quality: Phase 2b Duplicate Consolidation COMPLETE** - Eliminated ~176-186 lines of duplicate code (issue #246)
  - **Document chunk processing consolidation (Group 3)**:
    - Extracted `process_document_chunk()` helper function from duplicate implementations
    - Consolidated chunk_text/chunk_size/chunk_overlap pattern across document ingestion tools
    - 2 occurrences reduced to 1 canonical implementation with consistent metadata handling
  - **MCP response parsing consolidation (Group 3)**:
    - Extracted `parse_mcp_response()` helper for isError/error/content pattern
    - Standardized error handling across MCP tool invocations
    - 2 occurrences reduced to 1 canonical implementation
  - **Cache statistics logging consolidation (Group 5)**:
    - Extracted `log_cache_statistics()` helper for storage/service cache metrics
    - Standardized cache performance logging format (hits, misses, hit rates)
    - 2 occurrences reduced to 1 canonical implementation with consistent percentage formatting
  - **Winter season boundary logic consolidation (Group 7)**:
    - Extracted `is_winter_boundary_case()` helper for cross-year winter season handling
    - Centralized December-January transition logic (Dec 21 - Mar 20 spans years)
    - 2 occurrences reduced to 1 canonical implementation
  - **Test tempfile setup consolidation (Groups 10, 11)**:
    - Extracted `create_test_document()` helper for pytest tmp_path fixture patterns
    - Standardized temporary file creation across document ingestion tests
    - 6 occurrences reduced to 2 canonical implementations (PDF, DOCX variants)
  - **MCP server configuration consolidation (Phase 2b-3)**:
    - Consolidated duplicate server config sections in install.py and scripts/installation/install.py
    - Unified JSON serialization logic for mcpServers configuration blocks
    - Improved maintainability through shared configuration structure
  - **User input prompt consolidation (Phase 2b-2)**:
    - Extracted shared prompt logic for backend selection and configuration
    - Standardized input validation patterns across installation scripts
    - Reduced code duplication in interactive installation workflows
  - **Additional GPU detection consolidation (Phase 2b-1)**:
    - Completed GPU platform detection consolidation from Phase 2a
    - Refined helper function extraction for test_gpu_platform() and related utilities
    - Enhanced configuration-driven GPU detection architecture
  - **Consolidation Summary**:
    - Total duplicate code eliminated: ~176-186 lines across 10 consolidation commits
    - Functions/patterns consolidated: 10+ duplicate implementations → canonical versions
    - Strategic deference: 5 groups intentionally skipped (high-risk/low-benefit per session analysis)
    - Code maintainability: Enhanced through focused helper methods and consistent patterns
    - 100% backward compatibility maintained (no breaking changes)
    - Test coverage: 100% maintained across all consolidations

### Code Quality
- **Phase 2b Duplicate Consolidation**: 10 consolidation commits addressing multiple duplication groups
- **Duplication Score**: Reduced from 5.5% (Phase 2a baseline) to estimated 4.5-4.7%
- **Complexity Reduction**: Helper extraction pattern applied consistently across codebase
- **Expected Impact**:
  - Duplication Score: Approaching <3% target with strategic consolidation
  - Complexity Score: Improved through helper function extraction
  - Overall Health Score: Strong progress toward 75+ target
- **Remaining Work**: 5 duplication groups intentionally deferred (high-risk backend logic, low-benefit shared imports)
- **Related**: Issue #246 Phase 2b (Duplicate Consolidation Strategy COMPLETE)

## [8.37.0] - 2025-11-24

### Improved
- **Code Quality: Phase 2a Duplicate Consolidation COMPLETE** - Eliminated 5 duplicate high-complexity functions (issue #246)
  - **detect_gpu() consolidation (3 duplicates → 1 canonical)**:
    - Consolidated ROOT install.py::detect_gpu() (119 lines, complexity 30) with refactored scripts/installation/install.py version (187 lines, configuration-driven)
    - Refactored scripts/validation/verify_environment.py::EnvironmentVerifier.detect_gpu() (123 lines, complexity 27) to use helper-based architecture
    - Final canonical implementation in install.py: GPU_PLATFORM_CHECKS config dict + test_gpu_platform() helper + CUDA_VERSION_PARSER
    - Impact: -4% high-complexity functions (27 → 26), improved maintainability
  - **verify_installation() consolidation (2 duplicates → 1 canonical)**:
    - Replaced scripts/installation/install.py simplified version with canonical ROOT install.py implementation
    - Added tokenizers check for ONNX dependencies, safer DirectML version handling
    - Improved error messaging and user guidance
  - **Consolidation Summary**:
    - Total duplicate functions eliminated: 5 (3x detect_gpu + 2x verify_installation)
    - High-complexity functions reduced: 27 → 24 (-11%)
    - Code maintainability improved through focused helper methods and configuration-driven design
    - 100% backward compatibility maintained (no breaking changes)

### Code Quality
- **Phase 2a Duplicate Consolidation**: 5 of 5 target functions consolidated (100% complete)
- **High-Complexity Functions**: Reduced from 27 to 24 (-11%)
- **Complexity Reduction**: Configuration-driven patterns replace monolithic if/elif chains
- **Expected Impact**:
  - Duplication Score: Reduced toward <3% target
  - Complexity Score: Improved through helper extraction
  - Overall Health Score: On track for 75+ target
- **Related**: Issue #246 Phase 2a (Duplicate Consolidation Strategy COMPLETE)

## [8.36.1] - 2025-11-24

### Fixed
- **CRITICAL**: HTTP server crash on v8.36.0 startup - forward reference error in analytics.py (issue #247)
  - Added `from __future__ import annotations` to enable forward references in type hints
  - Added `Tuple` to typing imports for Python 3.9 compatibility
  - Impact: Unblocks all v8.36.0 users experiencing startup failures
  - Root cause: PR #244 refactoring introduced forward references without future annotations import
  - Fix verified: HTTP server starts successfully, all 10 analytics routes registered

## [8.36.0] - 2025-11-24

### Improved
- **Code Quality: Phase 2 COMPLETE - 100% of Target Achieved** - Refactored final 7 functions, -19 complexity points (issue #240 PR #244)
  - **consolidator.py (-8 points)**:
    - `consolidate()`: 12 → 8 - Introduced SyncPauseContext for cleaner sync state management + extracted `check_horizon_requirements()` helper
    - `_get_memories_for_horizon()`: 10 → 8 - Replaced conditional logic with data-driven HORIZON_CONFIGS dict lookup
  - **analytics.py (-8 points)**:
    - `get_tag_usage_analytics()`: 10 → 6 - Extracted `fetch_storage_stats()` and `calculate_tag_statistics()` helpers (40+ lines)
    - `get_activity_breakdown()`: 9 → 7 - Extracted `calculate_activity_time_ranges()` helper (70+ lines)
    - `get_memory_type_distribution()`: 9 → 7 - Extracted `aggregate_type_statistics()` helper
  - **install.py (-2 points)**:
    - `detect_gpu()`: 10 → 8 - Data-driven GPU_PLATFORM_CHECKS dict + extracted `test_gpu_platform()` helper
  - **cloudflare.py (-1 point)**:
    - `get_memory_timestamps()`: 9 → 8 - Extracted `_fetch_d1_timestamps()` method for D1 query logic
  - **Gemini Review Improvements (5 iterations)**:
    - **Critical Fixes**:
      - Fixed timezone bug: `datetime.now()` → `datetime.now(timezone.utc)` in consolidator
      - Fixed analytics double-counting: proper use of `count_all_memories()`
      - CUDA/ROCm robustness: try all detection paths before failing
    - **Quality Improvements**:
      - Modernized deprecated APIs: `pkg_resources` → `importlib.metadata`, `universal_newlines` → `text=True`
      - Enhanced error logging with `exc_info=True` for better debugging
      - Improved code consistency and structure across all refactored functions

### Code Quality
- **Phase 2 Complete**: 10 of 10 functions refactored (100%)
- **Complexity Reduction**: -39 of -39 points achieved (100% of target)
- **Total Batches**:
  - v8.34.0 (PR #242): `analytics.py::get_memory_growth()` (-5 points)
  - v8.35.0 (PR #243): `install.py::configure_paths()`, `cloudflare.py::_search_by_tags_internal()` (-15 points)
  - v8.36.0 (PR #244): Remaining 7 functions (-19 points)
- **Expected Impact**:
  - Complexity Score: 40 → 51+ (+11 points, exceeded +10 target)
  - Overall Health Score: 63 → 68-72 (Grade B achieved!)
- **Related**: Issue #240 Phase 2 (100% COMPLETE), Phase 1: v8.33.0 (dead code removal, +5-9 health points)

## [8.35.0] - 2025-11-24

### Improved
- **Code Quality: Phase 2 Batch 1 Complete** - Refactored 2 high-priority functions (issue #240 PR #243)
  - **install.py::configure_paths()**: Complexity reduced from 15 → 5 (-10 points)
    - Extracted 4 helper functions for better separation of concerns
    - Main function reduced from 80 → ~30 lines
    - Improved testability and maintainability
  - **cloudflare.py::_search_by_tags_internal()**: Complexity reduced from 13 → 8 (-5 points)
    - Extracted 3 helper functions for tag normalization and query building
    - Method reduced from 75 → ~45 lines
    - Better code organization
  - **Gemini Review Improvements**:
    - Dynamic PROJECT_ROOT detection in scripts
    - Specific exception handling (OSError, IOError, PermissionError)
    - Portable documentation paths

### Code Quality
- **Phase 2 Progress**: 3 of 10 functions refactored (30% complete)
- **Complexity Reduction**: -20 points achieved of -39 point target (51% of target)
- **Remaining Work**: 7 functions with implementation plans ready
- **Overall Health**: On track for 75+ target score

## [8.34.0] - 2025-11-24

### Improved
- **Code Quality: Phase 2 Complexity Reduction** - Refactored `analytics.py::get_memory_growth()` function (issue #240 Phase 2)
  - Complexity reduced from 11 → 6-7 (-4 to -5 points, exceeding -3 point target)
  - Introduced PeriodType Enum for type-safe period validation
  - Data-driven period configuration with PERIOD_CONFIGS dict
  - Data-driven label formatting with PERIOD_LABEL_FORMATTERS dict
  - Improved maintainability and extensibility for analytics endpoints

### Code Quality
- Phase 2 Progress: 1 of 10 functions refactored
- Complexity Score: Estimated +1 point improvement (partial Phase 2)
- Overall Health: On track for 70+ target

## [8.33.0] - 2025-11-24

### Fixed
- **Critical Installation Bug**: Fixed early return in `install.py` that prevented Claude Desktop MCP configuration from executing (issue #240 Phase 1)
  - 77 lines of Claude Desktop setup code now properly runs during installation
  - Users will now get automatic MCP server configuration when running `install.py`
  - Bug was at line 1358 - early `return False` in exception handler made lines 1360-1436 unreachable
  - Resolves all 27 pyscn dead code violations identified in issue #240 Phase 1

### Improved
- Modernized `install.py` with pathlib throughout (via Gemini Code Assist automated review)
- Specific exception handling (OSError, PermissionError, JSONDecodeError) instead of bare `except`
- Fixed Windows `memory_wrapper.py` path resolution bug (now uses `resolve()` for absolute paths)
- Added config structure validation to prevent TypeError on malformed JSON
- Import optimization and better error messages
- Code structure improvements from 10+ Gemini Code Assist review iterations

### Code Quality
- **Dead Code Score**: 70 → 85-90 (projected +15-20 points from removing 27 violations)
- **Overall Health Score**: 63 → 68-72 (projected +5-9 points)
- All improvements applied via automated Gemini PR review workflow

## [8.32.0] - 2025-11-24

### Added
- **pyscn Static Analysis Integration**: Multi-layer quality workflow with comprehensive static analysis
  - New `scripts/pr/run_pyscn_analysis.sh` for PR-time analysis with health score thresholds (blocks <50)
  - New `scripts/quality/track_pyscn_metrics.sh` for historical metrics tracking (CSV storage)
  - New `scripts/quality/weekly_quality_review.sh` for automated weekly reviews with regression detection
  - Enhanced `scripts/pr/quality_gate.sh` with `--with-pyscn` flag for comprehensive checks
  - Three-layer quality strategy: Pre-commit (Groq/Gemini LLM) → PR Gate (standard + pyscn) → Periodic (weekly)
  - 6 comprehensive metrics: cyclomatic complexity, dead code, duplication, coupling, dependencies, architecture
  - Health score thresholds: <50 (blocker), 50-69 (action required), 70-84 (good), 85+ (excellent)
  - Complete documentation in `docs/development/code-quality-workflow.md` (651 lines)
  - Integration guide in `.claude/agents/code-quality-guard.md`
  - Updated `CLAUDE.md` with "Code Quality Monitoring" section

## [8.31.0] - 2025-11-23

### Added
- **Revolutionary Batch Update Performance** - Memory consolidation now 21,428x faster with new batch update API (#241)
  - **Performance Improvement**: 300 seconds → 0.014 seconds for 500 memory batch updates (21,428x speedup)
  - **Consolidation Workflow**: Complete consolidation time reduced from 5+ minutes to <1 second for 500 memories
  - **New API Method**: `update_memories_batch()` in storage backends for atomic batch operations
  - **Implementation**:
    - **SQLite Backend**: Single transaction with executemany for 21,428x speedup
    - **Cloudflare Backend**: Parallel batch updates with proper vectorize sync
    - **Hybrid Backend**: Optimized dual-backend batch sync with queue processing
  - **Backward Compatible**: Existing single-update code paths continue working
  - **Real-world Impact**: Memory consolidation that previously took 5+ minutes now completes in <1 second
  - **Files Modified**:
    - `src/mcp_memory_service/storage/sqlite_vec.py` (lines 542-571): Batch update implementation
    - `src/mcp_memory_service/storage/cloudflare.py` (lines 673-728): Cloudflare batch updates
    - `src/mcp_memory_service/storage/hybrid.py` (lines 772-822): Hybrid backend batch sync
    - `src/mcp_memory_service/consolidation/service.py` (line 472): Using batch update in consolidation

### Performance
- **Memory Consolidation**: 21,428x faster batch metadata updates (300s → 0.014s for 500 memories)
- **Consolidation Workflow**: Complete workflow time reduced from 5+ minutes to <1 second for 500 memories
- **Database Efficiency**: Single transaction instead of 500 individual updates with commit overhead

## [8.30.0] - 2025-11-23

### Added
- **Adaptive Chart Granularity** - Analytics charts now use semantically appropriate time intervals for better trend visualization
  - **Last Month view**: Changed from 3-day intervals to weekly aggregation for clearer monthly trends
  - **Last Year view**: Uses monthly aggregation for annual overview
  - **Human-readable labels**: Charts display clear interval formatting:
    - Daily view: "Nov 15" format
    - Weekly aggregation: "Week of Nov 15" format
    - Monthly aggregation: "November 2024" format
  - **Improved UX**: Better semantic alignment between time period and chart granularity
  - **Files Modified**: `src/mcp_memory_service/web/api/analytics.py` (lines 307-345), `src/mcp_memory_service/web/static/app.js` (line 3661)

### Fixed
- **CRITICAL: Interval Aggregation Bug** - Multi-day intervals (weekly, monthly) now correctly aggregate across entire period
  - **Problem**: Intervals were only counting memories from the first day of the interval, not the entire period
  - **Impact**: Analytics showed wildly inaccurate data (e.g., 0 memories instead of 427 for Oct 24-30 week)
  - **Root Cause**: `strftime` format in date grouping only used the first timestamp, not the interval's date range
  - **Solution**: Updated aggregation logic to properly filter and count all memories within each interval
  - **Files Modified**: `src/mcp_memory_service/web/api/analytics.py` (lines 242-267)

- **CRITICAL: Data Sampling Bug** - Analytics now fetch complete historical data with proper date range filtering
  - **Problem**: API only fetched 1,000 most recent memories, missing historical data for longer time periods
  - **Impact**: Charts showed incomplete or missing data for older time ranges
  - **Solution**: Increased fetch limit to 10,000 memories with proper `created_at >= start_date` filtering
  - **Files Modified**: `src/mcp_memory_service/web/api/analytics.py` (lines 56-62)
  - **Performance**: Maintains fast response times (<200ms) even with larger dataset

### Changed
- **Analytics API**: Improved data fetching with larger limits and proper date filtering for accurate historical analysis

## [8.29.0] - 2025-11-23

### Added
- **Dashboard Quick Actions: Sync Controls Widget** - Compact, real-time sync management for hybrid backend users (#234, fixes #233)
  - **Real-time sync status indicator**: Visual states for synced/syncing/pending/error/paused with color-coded icons
  - **Pause/Resume controls**: Safely pause background sync for database maintenance or offline work
  - **Force sync button**: Manual trigger for immediate synchronization
  - **Sync metrics**: Display last sync time and pending operations count
  - **Clean layout**: Removed redundant sync status bar between header and body, moved to sidebar widget
  - **Backend-aware**: Widget automatically hides for sqlite-vec only users (hybrid-specific feature)
  - **API endpoints**:
    - `POST /api/sync/pause` - Pause background sync
    - `POST /api/sync/resume` - Resume background sync
  - **Hybrid backend methods**: Added `pause_sync()` and `resume_sync()` for sync control

- **Automatic Scheduled Backup System** - Enterprise-grade backup with retention policies and scheduling (#234, fixes #233)
  - **New backup module**: `src/mcp_memory_service/backup/` with `BackupService` and `BackupScheduler`
  - **SQLite native backup API**: Uses safe `sqlite3.backup()` to prevent corruption (no file copying)
  - **Async I/O**: Non-blocking backup operations with `asyncio.to_thread`
  - **Flexible scheduling**: Hourly, daily, or weekly automatic backups
  - **Retention policies**: Configurable by days and max backup count
  - **Dashboard widget**: Backup status, last backup time, manual trigger, backup count, next scheduled time
  - **Configuration via environment variables**:
    - `MCP_BACKUP_ENABLED=true` (default: true)
    - `MCP_BACKUP_INTERVAL=daily` (hourly/daily/weekly, default: daily)
    - `MCP_BACKUP_RETENTION=7` (days, default: 7)
    - `MCP_BACKUP_MAX_COUNT=10` (max backups, default: 10)
  - **API endpoints**:
    - `GET /api/backup/status` - Get backup status and scheduler info
    - `POST /api/backup/now` - Trigger manual backup
    - `GET /api/backup/list` - List available backups with metadata
  - **Security**: OAuth protection on backup endpoints, no file path exposure in responses
  - **Safari compatibility**: Improved event listener handling with lazy initialization

### Changed
- **Quick Actions Layout**: Moved sync controls from top status bar to sidebar widget for cleaner, more accessible UI
- **Sync State Persistence**: Pause state is now preserved during force sync operations
- **Dashboard Feedback**: Added toast notifications for sync and backup operations

### Fixed
- **Sync Button Click Events**: Resolved DOM timing issues with lazy event listeners for reliable button interactions
- **Spinner Animation**: Fixed syncing state visual feedback with proper CSS animations
- **Security**: Removed file path exposure from backup API responses (used backup IDs instead)

## [8.28.1] - 2025-11-22

### Fixed
- **CRITICAL: HTTP MCP Transport JSON-RPC 2.0 Compliance** - Fixed protocol violation causing Claude Code rejection (#236)
  - **Problem**: HTTP MCP server returned `"error": null` in successful responses, violating JSON-RPC 2.0 spec which requires successful responses to OMIT the error field entirely (not include it as null)
  - **Impact**: Claude Code's strict schema validation rejected all HTTP MCP responses with "Unrecognized key(s) in object: 'error'" errors, making HTTP transport completely unusable
  - **Root Cause**: MCPResponse Pydantic model included both `result` and `error` fields in all responses, serializing null values
  - **Solution**:
    - Added `ConfigDict(exclude_none=True)` to MCPResponse model to exclude null fields from serialization
    - Updated docstring to document JSON-RPC 2.0 compliance requirements
    - Replaced deprecated `.dict()` with `.model_dump()` for Pydantic V2 compatibility
    - Moved json import to top of file per PEP 8 style guidelines
  - **Files Modified**:
    - `src/mcp_memory_service/web/api/mcp.py` - Added ConfigDict, updated serialization
  - **Affected Users**: All users attempting to use HTTP MCP transport with Claude Code or other strict JSON-RPC 2.0 clients
  - **Testing**: Verified successful responses exclude `error` field and error responses exclude `result` field
  - **Credits**: Thanks to @timkjr for identifying the issue and providing the fix

## [8.28.0] - 2025-11-21

### Added
- **Cloudflare Tag Filtering** - AND/OR operations for tag searches with unified API contracts (#228)
  - Added `search_by_tags(tags, operation, time_start, time_end)` to the storage base class and implemented it across SQLite, Cloudflare, Hybrid, and HTTP client backends
  - Normalized Cloudflare SQL to use `GROUP BY` + `HAVING COUNT(DISTINCT ...)` for AND semantics while supporting optional time ranges
  - Introduced `get_all_tags_with_counts()` for Cloudflare to power analytics dashboards without extra queries

### Changed
- **Tag Filtering Behavior** - `get_all_memories(tags=...)` now performs exact tag comparisons with AND logic instead of substring OR matching, and hybrid storage exposes the same `operation` parameter for parity across backends.

## [8.27.2] - 2025-11-18

### Fixed
- **Memory Type Loss During Cloudflare-to-SQLite Sync** - Fixed `memory_type` not being preserved in sync script
  - **Problem**: `scripts/sync/sync_memory_backends.py` did not extract or pass `memory_type` when syncing from Cloudflare to SQLite-vec
  - **Impact**: All memories synced via `--direction cf-to-sqlite` showed as "untyped" (100%) in dashboard analytics
  - **Root Cause**: Missing `memory_type` field in both memory dict extraction and Memory object creation
  - **Solution**:
    - Added `memory_type` to memory dictionary extraction from source
    - Added `memory_type` and `updated_at` parameters when creating Memory objects for target storage
  - **Files Modified**:
    - `scripts/sync/sync_memory_backends.py` - Added memory_type and updated_at handling
  - **Affected Users**: Users who ran `python scripts/sync/sync_memory_backends.py --direction cf-to-sqlite`
  - **Recovery**: Re-run sync from Cloudflare to restore memory types (Cloudflare preserves original types)

## [8.27.1] - 2025-11-18

### Fixed
- **CRITICAL: Timestamp Regression Bug** - Fixed `created_at` timestamps being reset during metadata sync
  - **Problem**: Bidirectional sync and drift detection (v8.25.0-v8.27.0) incorrectly reset `created_at` timestamps to current time during metadata updates
  - **Impact**: All memories synced from Cloudflare → SQLite-vec appeared "just created", destroying historical timestamp data
  - **Root Cause**: `preserve_timestamps=False` parameter reset **both** `created_at` and `updated_at`, when it should only update `updated_at`
  - **Solution**:
    - Modified `update_memory_metadata()` to preserve `created_at` from source memory during sync
    - Hybrid storage now passes all 4 timestamp fields (`created_at`, `created_at_iso`, `updated_at`, `updated_at_iso`) during drift detection
    - Cloudflare storage updated to handle timestamps consistently with SQLite-vec
  - **Files Modified**:
    - `src/mcp_memory_service/storage/sqlite_vec.py:1389-1406` - Fixed timestamp handling logic
    - `src/mcp_memory_service/storage/hybrid.py:625-637, 935-947` - Pass source timestamps during sync
    - `src/mcp_memory_service/storage/cloudflare.py:833-864` - Consistent timestamp handling
  - **Tests Added**: `tests/test_timestamp_preservation.py` - Comprehensive test suite with 7 tests covering:
    - Timestamp preservation with `preserve_timestamps=True`
    - Regression test for `created_at` preservation without source timestamps
    - Drift detection scenario
    - Multiple sync operations
    - Initial memory storage
  - **Recovery Tools**:
    - `scripts/validation/validate_timestamp_integrity.py` - Detect timestamp anomalies
    - `scripts/maintenance/recover_timestamps_from_cloudflare.py` - Restore corrupted timestamps from Cloudflare
  - **Affected Versions**: v8.25.0 (drift detection), v8.27.0 (bidirectional sync)
  - **Affected Users**: Hybrid backend users who experienced automatic drift detection or initial sync
  - **Data Recovery**: If using hybrid backend and Cloudflare has correct timestamps, run recovery script:
    ```bash
    # Preview recovery
    python scripts/maintenance/recover_timestamps_from_cloudflare.py --dry-run

    # Apply recovery
    python scripts/maintenance/recover_timestamps_from_cloudflare.py --apply
    ```

### Changed
- **Timestamp Handling Semantics** - Clarified `preserve_timestamps` parameter behavior:
  - `preserve_timestamps=True` (default): Only updates `updated_at` to current time, preserves `created_at`
  - `preserve_timestamps=False`: Uses timestamps from `updates` dict if provided, otherwise preserves existing `created_at`
  - **Never** resets `created_at` to current time (this was the bug)

### Added
- **Timestamp Integrity Validation** - New script to detect timestamp anomalies:
  ```bash
  python scripts/validation/validate_timestamp_integrity.py
  ```
  - Checks for impossible timestamps (`created_at > updated_at`)
  - Detects suspicious timestamp clusters (bulk reset indicators)
  - Analyzes timestamp distribution for anomalies
  - Provides detailed statistics and warnings

## [8.27.0] - 2025-11-17

### Added
- **Hybrid Storage Sync Performance Optimization** - Dramatic initial sync speed improvement (3-5x faster)
  - **Performance Metrics**:
    - **Before**: ~5.5 memories/second (8 minutes for 2,619 memories)
    - **After**: ~15-30 memories/second (1.5-3 minutes for 2,619 memories)
    - **3-5x faster** initial sync from Cloudflare to local SQLite
  - **Optimizations**:
    - **Bulk Existence Check**: `get_all_content_hashes()` method eliminates 2,619 individual DB queries
    - **Parallel Processing**: `asyncio.gather()` with Semaphore(15) for concurrent memory processing
    - **Larger Batch Sizes**: Increased from 100 to 500 memories per Cloudflare API call (5x fewer requests)
  - **Files Modified**:
    - `src/mcp_memory_service/storage/sqlite_vec.py` - Added `get_all_content_hashes()` method (lines 1208-1227)
    - `src/mcp_memory_service/storage/hybrid.py` - Parallel sync implementation (lines 859-921)
    - `scripts/benchmarks/benchmark_hybrid_sync.py` - Performance validation script
  - **Backward Compatibility**: Zero breaking changes, transparent optimization for all sync operations
  - **Use Case**: Users with large memory databases (1000+ memories) will see significantly faster initial sync times

### Changed
- **Hybrid Initial Sync Architecture** - Refactored sync loop for better performance
  - O(1) hash lookups instead of O(n) individual queries
  - Concurrent processing with controlled parallelism (15 simultaneous operations)
  - Reduced Cloudflare API overhead with larger batches (6 API calls vs 27)
  - Maintains full drift detection and metadata synchronization capabilities

### Fixed
- **Duplicate Sync Queue Architecture** - Resolved inefficient dual-sync issue
  - **Problem**: MCP server and HTTP server each created separate HybridStorage instances with independent sync queues
  - **Impact**: Duplicate sync work, potential race conditions, memory not immediately visible across servers
  - **Solution**: New `MCP_HYBRID_SYNC_OWNER` configuration to control which process handles Cloudflare sync
  - **Configuration Options**:
    - `"http"` - HTTP server only handles sync (recommended - avoids duplicate work)
    - `"mcp"` - MCP server only handles sync
    - `"both"` - Both servers sync independently (default for backward compatibility)
  - **Files Modified**:
    - `src/mcp_memory_service/config.py` - Added `HYBRID_SYNC_OWNER` configuration (lines 424-427)
    - `src/mcp_memory_service/storage/factory.py` - Server-type aware storage creation (lines 76-110)
    - `src/mcp_memory_service/mcp_server.py` - Pass server_type="mcp" (line 143)
    - `src/mcp_memory_service/web/dependencies.py` - Pass server_type="http" (line 65)
  - **Migration Guide**:
    ```bash
    # Recommended: Set HTTP server as sync owner to eliminate duplicate sync
    export MCP_HYBRID_SYNC_OWNER=http
    ```
  - **Backward Compatibility**: Defaults to "both" (existing behavior), no breaking changes

### Performance
- **Benchmark Results** (`python scripts/benchmarks/benchmark_hybrid_sync.py`):
  - Bulk hash loading: 2,619 hashes loaded in ~100ms (vs ~13,000ms for individual queries)
  - Parallel processing: 15x concurrency reduces CPU idle time
  - Batch size optimization: 78% reduction in API calls (27 → 6 for 2,619 memories)
  - Combined speedup: 3-5x faster initial sync

## [8.26.0] - 2025-11-16

### Added
- **Global MCP Server Caching** - Revolutionary performance improvement for MCP tools (PR #227)
  - **Performance Metrics**:
    - **534,628x faster** on cache hits (1,810ms → 0.01ms per MCP tool call)
    - **99.9996% latency reduction** for cached operations
    - **90%+ cache hit rate** in normal usage patterns
    - **MCP tools now 41x faster** than HTTP API after warm-up
  - **New MCP Tool**: `get_cache_stats` - Real-time cache performance monitoring
    - Track hits/misses, hit rate percentage
    - Monitor storage and service cache sizes
    - View initialization time statistics (avg/min/max)
  - **Infrastructure**:
    - Global cache structures: `_STORAGE_CACHE`, `_MEMORY_SERVICE_CACHE`, `_CACHE_STATS`
    - Thread-safe concurrent access via `asyncio.Lock`
    - Automatic cleanup on server shutdown (no memory leaks)
  - **Files Modified**:
    - `src/mcp_memory_service/server.py` - Production MCP server caching
    - `src/mcp_memory_service/mcp_server.py` - FastMCP server caching
    - `src/mcp_memory_service/utils/cache_manager.py` - New cache management utilities
    - `scripts/benchmarks/benchmark_server_caching.py` - Cache effectiveness validation
  - **Backward Compatibility**: Zero breaking changes, transparent caching for all MCP clients
  - **Use Case**: MCP tools in Claude Desktop and Claude Code are now the fastest method for memory operations

### Changed
- **Code Quality Improvements** - Gemini Code Assist review implementation (PR #227)
  - Eliminated code duplication across `server.py` and `mcp_server.py`
  - Created shared `CacheManager.calculate_stats()` utility for statistics
  - Enhanced PEP 8 compliance with proper naming conventions
  - Added comprehensive inline documentation for cache implementation

### Fixed
- **Security Vulnerability** - Removed unsafe `eval()` usage in benchmark script (PR #227)
  - Replaced `eval(stats_str)` with safe `json.loads()` for parsing cache statistics
  - Eliminated arbitrary code execution risk in development tools
  - Improved benchmark script robustness

### Performance
- **Benchmark Results** (10 consecutive MCP tool calls):
  - First Call (Cache Miss): ~2,485ms
  - Cached Calls Average: ~0.01ms
  - Speedup Factor: 534,628x
  - Cache Hit Rate: 90%
- **Impact**: MCP tools are now the recommended method for Claude Desktop and Claude Code users
- **Technical Details**:
  - Caches persist across stateless HTTP calls
  - Storage instances keyed by "{backend}:{path}"
  - MemoryService instances keyed by storage ID
  - Lazy initialization preserved to prevent startup hangs

### Documentation
- Updated Wiki: 05-Performance-Optimization.md with cache architecture
- Added cache monitoring guide using `get_cache_stats` tool
- Performance comparison tables now show MCP as fastest method

## [8.25.2] - 2025-11-16

### Changed
- **Drift Detection Script Refactoring** - Improved code maintainability in `check_drift.py` (PR #226)
  - **Refactored**: Cloudflare config dictionary construction to use dictionary comprehension
  - **Improvement**: Separated configuration keys list from transformation logic
  - **Benefit**: Easier to maintain and modify configuration keys
  - **Code Quality**: More Pythonic, cleaner, and more readable
  - **Impact**: No functional changes, pure code quality improvement
  - **File Modified**: `scripts/sync/check_drift.py`
  - **Credit**: Implements Gemini code review suggestions from PR #224

## [8.25.1] - 2025-11-16

### Fixed
- **Drift Detection Script Initialization** - Corrected critical bugs in `check_drift.py` (PR #224)
  - **Bug 1**: Fixed incorrect config attribute `SQLITE_DB_PATH` → `SQLITE_VEC_PATH` in AppConfig
  - **Bug 2**: Added missing `cloudflare_config` parameter to HybridMemoryStorage initialization
  - **Impact**: Script was completely broken for Cloudflare/Hybrid backends - now initializes successfully
  - **Error prevented**: `AttributeError: 'AppConfig' object has no attribute 'SQLITE_DB_PATH'`
  - **File Modified**: `scripts/sync/check_drift.py`
  - **Severity**: High - Script was non-functional for users with hybrid or cloudflare backends
- **CI Test Infrastructure** - Added HuggingFace model caching to prevent network-related test failures (PR #225)
  - **Root Cause**: GitHub Actions runners cannot access huggingface.co during test runs
  - **Solution**: Implemented `actions/cache@v3` for `~/.cache/huggingface` directory
  - **Pre-download step**: Downloads `all-MiniLM-L6-v2` model after dependency installation
  - **Impact**: Fixes all future PR test failures caused by model download restrictions
  - **Cache Strategy**: Key includes `pyproject.toml` hash for dependency tracking
  - **Performance**: First run downloads model, subsequent runs use cache
  - **File Modified**: `.github/workflows/main.yml`

### Technical Details
- **PR #224**: Drift detection script now properly initializes Cloudflare backend with all required parameters (api_token, account_id, d1_database_id, vectorize_index)
- **PR #225**: CI environment now caches embedding models, eliminating network dependency during test execution
- **Testing**: Both fixes validated in PR test runs - drift detection now works, tests pass consistently

## [8.25.0] - 2025-11-15

### Added
- **Hybrid Backend Drift Detection** - Automatic metadata synchronization using `updated_at` timestamps (issue #202)
  - **Bidirectional awareness**: Detects metadata changes on either backend (SQLite-vec ↔ Cloudflare)
  - **Periodic drift checks**: Configurable interval via `MCP_HYBRID_DRIFT_CHECK_INTERVAL` (default: 1 hour)
  - **"Newer timestamp wins" conflict resolution**: Prevents data loss during metadata updates
  - **Dry-run support**: Preview changes via `python scripts/sync/check_drift.py`
  - **New configuration variables**:
    - `MCP_HYBRID_SYNC_UPDATES` - Enable metadata sync (default: true)
    - `MCP_HYBRID_DRIFT_CHECK_INTERVAL` - Seconds between drift checks (default: 3600)
    - `MCP_HYBRID_DRIFT_BATCH_SIZE` - Memories to check per scan (default: 100)
  - **New methods**:
    - `BackgroundSyncService._detect_and_sync_drift()` - Core drift detection logic with dry-run mode
    - `CloudflareStorage.get_memories_updated_since()` - Query memories by update timestamp
  - **Enhanced initial sync**: Now detects and syncs metadata drift for existing memories

### Fixed
- **Issue #202** - Hybrid backend now syncs metadata updates (tags, types, custom fields)
  - Previous behavior only detected missing memories, ignoring metadata changes
  - Prevented silent data loss when memories updated on one backend but not synced
  - Tag fixes in Cloudflare now properly propagate to local SQLite
  - Metadata updates no longer diverge between backends

### Changed
- Initial sync (`_perform_initial_sync`) now compares timestamps for existing memories
- Periodic sync includes drift detection checks at configurable intervals
- Sync statistics tracking expanded with drift detection metrics

### Technical Details
- **Files Modified**:
  - `src/mcp_memory_service/config.py` - Added 3 configuration variables
  - `src/mcp_memory_service/storage/hybrid.py` - Drift detection implementation (~150 lines)
  - `src/mcp_memory_service/storage/cloudflare.py` - Added `get_memories_updated_since()` method
  - `scripts/sync/check_drift.py` - New dry-run validation script
- **Architecture**: Timestamp-based drift detection with 1-second clock skew tolerance
- **Performance**: Non-blocking async operations, configurable batch sizes
- **Safety**: Opt-in feature, dry-run mode, comprehensive audit logging

## [8.24.4] - 2025-11-15

### Changed
- **Code Quality Improvements** - Applied Gemini Code Assist review suggestions (issue #180)
  - **documents.py:87** - Replaced chained `.replace()` calls with `re.sub()` for path separator sanitization
  - **app.js:751-762** - Cached DOM elements in setProcessingMode to reduce query overhead
  - **app.js:551-553, 778-780** - Cached upload option elements to optimize handleDocumentUpload
  - **index.html:357, 570** - Fixed indentation consistency for closing `</div>` tags
  - Performance impact: Minor - reduced DOM query overhead
  - Breaking changes: None

### Technical Details
- **Files Modified**: `src/mcp_memory_service/web/api/documents.py`, `src/mcp_memory_service/web/static/app.js`, `src/mcp_memory_service/web/static/index.html`
- **Code Quality**: Regex-based sanitization more scalable, DOM element caching reduces redundant queries
- **Commit**: ffc6246 - refactor: code quality improvements from Gemini review (issue #180)

## [8.24.3] - 2025-11-15

### Fixed
- **GitHub Release Manager Agent** - Resolved systematic version history omission in README.md (commit ccf959a)
  - Fixed agent behavior that was omitting previous versions from "Previous Releases" section
  - Added v8.24.1 to Previous Releases list (was missing despite being valid release)
  - Enhanced agent instructions with CRITICAL section for maintaining version history integrity
  - Added quality assurance checklist item to prevent future omissions
  - Root cause: Agent was replacing entire Previous Releases section instead of prepending new version

### Added
- **Test Coverage for Tag+Time Filtering** - Comprehensive test suite for issue #216 (commit ebff282)
  - 10 unit tests passing across SQLite-vec, Cloudflare, and Hybrid backends
  - Validates PR #215 functionality (tag+time filtering to fix semantic over-filtering bug #214)
  - Tests verify memories can be retrieved using both tag criteria AND time range filters
  - API integration tests created (with known threading issues documented for future fix)
  - Ensures regression prevention for semantic search over-filtering bug

### Changed
- GitHub release workflow now more reliable with enhanced agent guardrails
- Test suite provides better coverage for multi-filter memory retrieval scenarios

### Technical Details
- **Files Modified**:
  - `.claude/agents/github-release-manager.md` - Added CRITICAL section for Previous Releases maintenance
  - `tests/test_time_filtering.py` - 10 new unit tests for tag+time filtering
  - `tests/integration/test_api_time_search.py` - API integration tests (threading issues documented)
- **Test Execution**: All 10 unit tests passing, API tests have known threading limitations
- **Impact**: Prevents version history loss in future releases, ensures tag+time filtering remains functional

## [8.24.2] - 2025-11-15

### Fixed
- **CI/CD Workflow Infrastructure** - Development Setup Validation workflow fixes (issue #217 related)
  - Fixed bash errexit handling in workflow tests - prevents premature exit on intentional test failures
  - Corrected exit code capture using EXIT_CODE=0 and || EXIT_CODE=$? pattern
  - All 5 workflow tests now passing: version consistency, pre-commit hooks, server warnings, developer prompts, docs accuracy
  - Root cause: bash runs with -e flag (errexit), which exits immediately when commands return non-zero exit codes
  - Tests intentionally run check_dev_setup.py expecting exit code 1, but bash was exiting before capture
  - Commits: b4f9a5a, d1bcd67

### Changed
- Workflow tests can now properly validate that the development setup validator correctly detects problems
- Exit code capture no longer uses "|| true" pattern (was making all commands return 0)

### Technical Details
- **Files Modified**: .github/workflows/dev-setup-validation.yml
- **Pattern Change**:
  - Before: `python script.py || true` (always returns 0, breaks exit code testing)
  - After: `EXIT_CODE=0; python script.py || EXIT_CODE=$?` (captures actual exit code, prevents bash exit)
- **Test Jobs**: All 5 jobs in dev-setup-validation workflow now pass consistently
- **Context**: Part of test infrastructure improvement efforts (issue #217)

## [8.24.1] - 2025-11-15

### Fixed
- **Test Infrastructure Failures** - Resolved 27 pre-existing test failures (issue #217)
  - Fixed async fixture incompatibility in 6 test files (19+ failures)
  - Corrected missing imports (MCPMemoryServer → MemoryServer, removed MemoryMetadata)
  - Added missing content_hash parameter to Memory() instantiations
  - Updated hardcoded version strings (6.3.0 → 8.24.0)
  - Improved test pass rate from 63% to 71% (412/584 tests passing)
  - Execution: Automated via amp-bridge agent

### Changed
- Test suite now has cleaner baseline for detecting new regressions
- All async test fixtures now use @pytest_asyncio.fixture decorator

### Technical Details
- **Automated Fix**: Used amp-bridge agent for pattern-based refactoring
- **Execution Time**: ~15 minutes (vs 1-2 hours manual)
- **Files Modified**: 11 test files across tests/ and tests/integration/
- **Root Causes**: Test infrastructure issues, not code bugs
- **Remaining Failures**: 172 failures remain (backend config, performance, actual bugs)

## [8.24.0] - 2025-11-12

### Added
- **PyPI Publishing Automation** - Package now available via `pip install mcp-memory-service`
  - **Workflow Automation**: Configured GitHub Actions workflow to automatically publish to PyPI on tag pushes
  - **Installation Simplification**: Users can now install directly via `pip install mcp-memory-service` or `uv pip install mcp-memory-service`
  - **Accessibility**: Resolves installation barriers for users without git access or familiarity
  - **Token Configuration**: Secured with `PYPI_TOKEN` GitHub secret for automated publishing
  - **Quality Gates**: Publishes only after successful test suite execution

### Changed
- **Distribution Method**: Added PyPI as primary distribution channel alongside GitHub releases
- **Installation Documentation**: Updated guides to include pip-based installation as recommended method

### Technical Details
- **Files Modified**:
  - `.github/workflows/publish.yml` - NEW workflow for automated PyPI publishing
  - GitHub repository secrets - Added `PYPI_TOKEN` for authentication
- **Trigger**: Workflow runs automatically on git tag creation (pattern: `v*.*.*`)
- **Build System**: Uses Hatchling build backend with `python-semantic-release`

### Migration Notes
- **For New Users**: Preferred installation is now `pip install mcp-memory-service`
- **For Existing Users**: No action required - git-based installation continues to work
- **For Contributors**: Tag creation now triggers PyPI publishing automatically

## [8.23.1] - 2025-11-10

### Fixed
- **Stale Virtual Environment Prevention System** - Comprehensive 6-layer strategy to prevent "stale venv vs source code" version mismatches
  - **Root Cause**: MCP servers load from site-packages, not source files. System restart doesn't help - it relaunches with same stale package
  - **Impact**: Prevented issue that caused v8.23.0 tag validation bug to persist despite v8.22.2 fix (source showed v8.23.0 while venv had v8.5.3)

### Added
- **Phase 1: Automated Detection**
  - New `scripts/validation/check_dev_setup.py` - Validates source/venv version consistency, detects editable installs
  - Enhanced `scripts/hooks/pre-commit` - Blocks commits when venv is stale, provides actionable error messages
  - Added CLAUDE.md development setup section with explicit `pip install -e .` guidance

- **Phase 2: Runtime Warnings**
  - Added `check_version_consistency()` function in `src/mcp_memory_service/server.py`
  - Server startup warnings when version mismatch detected (source vs package)
  - Updated README.md developer section with editable install instructions
  - Enhanced `docs/development/ai-agent-instructions.md` with proper setup commands

- **Phase 3: Interactive Onboarding**
  - Enhanced `scripts/installation/install.py` with developer detection (checks for git repo)
  - Interactive prompt guides developers to use `pip install -e .` for editable installs
  - New CI/CD workflow `.github/workflows/dev-setup-validation.yml` with 5 comprehensive test jobs:
    1. Version consistency validation
    2. Pre-commit hook functionality
    3. Server startup warnings
    4. Interactive developer prompts
    5. Documentation accuracy checks

### Changed
- **Developer Workflow**: Developers now automatically guided to use `pip install -e .` for proper setup
- **Pre-commit Hook**: Now validates venv consistency before allowing commits
- **Installation Process**: Detects developer mode and provides targeted guidance

### Technical Details
- **6-Layer Prevention System**:
  1. **Development**: Pre-commit hook blocks bad commits, detection script validates setup
  2. **Runtime**: Server startup warnings catch edge cases
  3. **Documentation**: CLAUDE.md, README.md, ai-agent-instructions.md all updated
  4. **Automation**: check_dev_setup.py, pre-commit hook, CI/CD workflow
  5. **Interactive**: install.py prompts developers for editable install
  6. **Testing**: CI/CD workflow with 5 comprehensive test jobs

- **Files Modified**:
  - `scripts/validation/check_dev_setup.py` - NEW automated detection script
  - `scripts/hooks/pre-commit` - Enhanced with venv validation
  - `CLAUDE.md` - Added development setup guidance
  - `src/mcp_memory_service/server.py` - Added runtime version check
  - `README.md` - Updated developer section
  - `docs/development/ai-agent-instructions.md` - Updated setup commands
  - `scripts/installation/install.py` - Added developer detection
  - `.github/workflows/dev-setup-validation.yml` - NEW CI/CD validation

### Migration Notes
- **For Developers**: Run `pip install -e .` to install in editable mode (will be prompted by install.py)
- **For Users**: No action required - prevention system is transparent for production use
- **Pre-commit Hook**: Automatically installed during `install.py`, validates on every commit

### Commits Included
- `670fb74` - Phase 1: Automated detection (check_dev_setup.py, pre-commit hook, CLAUDE.md)
- `9537259` - Phase 2: Runtime warnings (server.py) + developer documentation
- `a17bcc7` - Phase 3: Interactive onboarding (install.py) + CI/CD validation

