refactor: Clean up search architecture, remove experimental contextualize endpoint (#133)

* Refactor code structure for improved readability and maintainability

* Add test results for search API and related functionalities

- Created test result files for various search-related functionalities, including:
  - test-11-search-server-changes.json
  - test-12-context-hook-changes.json
  - test-13-worker-service-changes.json
  - test-14-patterns.json
  - test-15-gotchas.json
  - test-16-discoveries.json
  - test-17-all-bugfixes.json
  - test-18-all-features.json
  - test-19-all-decisions.json
  - test-20-session-search.json
  - test-21-prompt-search.json
  - test-22-decisions-endpoint.json
  - test-23-changes-endpoint.json
  - test-24-how-it-works-endpoint.json
  - test-25-contextualize-endpoint.json
  - test-26-timeline-around-observation.json
  - test-27-multi-param-combo.json
  - test-28-file-type-combo.json

- Each test result file captures specific search failures or outcomes, including issues with undefined properties and successful execution of search queries.
- Enhanced documentation of search architecture and testing strategies, ensuring compliance with established guidelines and improving overall search functionality.

* feat: Enhance unified search API with catch-all parameters and backward compatibility

- Implemented a unified search API at /api/search that accepts catch-all parameters for filtering by type, observation type, concepts, and files.
- Maintained backward compatibility by keeping granular endpoints functional while routing through the same infrastructure.
- Completed comprehensive testing of search capabilities with real-world query scenarios.

fix: Address missing debug output in search API query tests

- Flushed PM2 logs and executed search queries to verify functionality.
- Diagnosed absence of "Raw Chroma" debug messages in worker logs, indicating potential issues with logging or query processing.

refactor: Improve build and deployment pipeline for claude-mem plugin

- Successfully built and synced all hooks and services to the marketplace directory.
- Ensured all dependencies are installed and up-to-date in the deployment location.

feat: Implement hybrid search filters with 90-day recency window

- Enhanced search server to apply a 90-day recency filter to Chroma results before categorizing by document type.

fix: Correct parameter handling in searchUserPrompts method

- Added support for filter-only queries and improved dual-path logic for clarity.

refactor: Rename FTS5 method to clarify fallback status

- Renamed escapeFTS5 to escapeFTS5_fallback_when_chroma_unavailable to indicate its temporary usage.

feat: Introduce contextualize tool for comprehensive project overview

- Added a new tool to fetch recent observations, sessions, and user prompts, providing a quick project overview.

feat: Add semantic shortcut tools for common search patterns

- Implemented 'decisions', 'changes', and 'how_it_works' tools for convenient access to frequently searched observation categories.

feat: Unified timeline tool supports anchor and query modes

- Combined get_context_timeline and get_timeline_by_query into a single interface for timeline exploration.

feat: Unified search tool added to MCP server

- New tool queries all memory types simultaneously, providing combined chronological results for improved search efficiency.

* Refactor search functionality to clarify FTS5 fallback usage

- Updated `worker-service.cjs` to replace FTS5 fallback function with a more descriptive name and improved error handling.
- Enhanced documentation in `SKILL.md` to specify the unified API endpoint and clarify the behavior of the search engine, including the conditions under which FTS5 is used.
- Modified `search-server.ts` to provide clearer logging and descriptions regarding the fallback to FTS5 when UVX/Python is unavailable.
- Renamed and updated the `SessionSearch.ts` methods to reflect the conditions for using FTS5, emphasizing the lack of semantic understanding in fallback scenarios.

* feat: Add ID-based fetch endpoints and simplify mem-search skill

**Problem:**
- Search returns IDs but no way to fetch by ID
- Skill documentation was bloated with too many options
- Claude wasn't using IDs because we didn't tell it how

**Solution:**
1. Added three new HTTP endpoints:
   - GET /api/observation/:id
   - GET /api/session/:id
   - GET /api/prompt/:id

2. Completely rewrote SKILL.md:
   - Stripped complexity down to essentials
   - Clear 3-step prescriptive workflow: Search → Review IDs → Fetch by ID
   - Emphasized ID usage: "The IDs are there for a reason - USE THEM"
   - Removed confusing multi-endpoint documentation
   - Kept only unified search with filters

**Impact:**
- Token efficiency: Claude can now fetch full details only for relevant IDs
- Clarity: One clear workflow instead of 10+ options to choose from
- Usability: IDs are no longer wasted context - they're actionable

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* chore: Move internal docs to private directory

Moved POSTMORTEM and planning docs to ./private to exclude from PR reviews.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* refactor: Remove experimental contextualize endpoint

- Removed contextualize MCP tool from search-server (saves ~4KB)
- Disabled FTS5 fallback paths in SessionSearch (now vector-first)
- Cleaned up CLAUDE.md documentation
- Removed contextualize-rewrite-plan.md doc

Rationale:
- Contextualize is better suited as a skill (LLM-powered) than an endpoint
- Search API already provides vector search with configurable limits
- Created issue #132 to track future contextualize skill implementation

Changes:
- src/servers/search-server.ts: Removed contextualize tool definition
- src/services/sqlite/SessionSearch.ts: Disabled FTS5 fallback, added deprecation warnings
- CLAUDE.md: Cleaned up outdated skill documentation
- docs/: Removed contextualize plan document

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* refactor: Complete FTS5 cleanup - remove all deprecated search code

This completes the FTS5 cleanup work by removing all commented-out
FTS5 search code while preserving database tables for backward compatibility.

Changes:
- Removed 200+ lines of commented FTS5 search code from SessionSearch.ts
- Removed deprecated degraded_search_query__when_uvx_unavailable method
- Updated all method documentation to clarify vector-first architecture
- Updated class documentation to reflect filter-only query support
- Updated CLAUDE.md to remove FTS5 search references
- Clarified that FTS5 tables exist for backward compatibility only
- Updated "Why SQLite FTS5" section to "Why Vector-First Search"

Database impact: NONE - FTS5 tables remain intact for existing installations

Search architecture:
- ChromaDB: All text-based vector search queries
- SQLite: Filter-only queries (date ranges, metadata, no query text)
- FTS5 tables: Maintained but unused (backward compatibility)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* refactor: Remove all FTS5 fallback execution code from search-server

Completes the FTS5 cleanup by removing all fallback execution paths
that attempted to use FTS5 when ChromaDB was unavailable.

Changes:
- Removed all FTS5 fallback code execution paths
- When ChromaDB fails or is unavailable, return empty results with helpful error messages
- Updated all deprecated tool descriptions (search_observations, search_sessions, search_user_prompts)
- Changed error messages to indicate FTS5 fallback has been removed
- Added installation instructions for UVX/Python when vector search is unavailable
- Updated comments from "hybrid search" to "vector-first search"
- Removed ~100 lines of dead FTS5 fallback code

Database impact: NONE - FTS5 tables remain intact (backward compatibility)

Search behavior when ChromaDB unavailable:
- Text queries: Return empty results with error explaining ChromaDB is required
- Filter-only queries (no text): Continue to work via direct SQLite

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: Address PR 133 review feedback

Critical fixes:
- Remove contextualize endpoint from worker-service (route + handler)
- Fix build script logging to show correct .cjs extension (was .mjs)

Documentation improvements:
- Add comprehensive FTS5 retention rationale documentation
- Include v7.0.0 removal TODO for future cleanup

Testing:
- Build succeeds with correct output logging
- Worker restarts successfully (30th restart)
- Contextualize endpoint properly removed (404 response)
- Search endpoint verified working

This addresses all critical review feedback from PR 133.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Alex Newman
2025-11-21 18:59:23 -05:00
committed by GitHub
parent d64939c379
commit c5e68a17c8
42 changed files with 2511 additions and 559 deletions
+648
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+83 -156
View File
@@ -1,196 +1,123 @@
---
name: mem-search
description: Search claude-mem's persistent cross-session memory database to find work from previous conversations days, weeks, or months ago. Access past session summaries, bug fixes, feature implementations, and decisions that are NOT in the current conversation context. Use when user asks "did we already solve this?", "how did we do X last time?", "what happened in last week's session?", or needs information from previous sessions stored in the PM2-managed database. Searches observations, session summaries, and user prompts across entire project history.
description: Search claude-mem's persistent cross-session memory database. Use when user asks "did we already solve this?", "how did we do X last time?", or needs work from previous sessions.
---
# Memory Search
Access claude-mem's persistent cross-session memory through HTTP API. Find past work, understand context across sessions, and learn from previous decisions.
Search past work across all sessions. Simple workflow: search → get IDs → fetch details by ID.
## When to Use This Skill
## When to Use
**Use when users ask about work from PREVIOUS sessions** (not current conversation):
Use when users ask about PREVIOUS sessions (not current conversation):
- "Did we already fix this?"
- "How did we solve X last time?"
- "What happened last week?"
### Temporal Triggers (Key Indicators)
- "Did we **already** fix this bug?" or "Have we seen this error **before**?"
- "How did we solve X **last time**?" or "What approach did we take **previously**?"
- "What did we do in **yesterday's/last week's/last month's** session?"
- "**When** did we last work on this?" or "What's the **history** of this file?"
## The Workflow
### Cross-Session Queries
- "Show me all authentication-related changes **across all sessions**"
- "What features did we add **last month**?" (not "today" or "this session")
- "Why did we choose this approach **before**?" (decisions from past sessions)
- "What files did we modify **when we added X**?" (historical context)
**ALWAYS follow this exact flow:**
**Do NOT use** for current session work, future planning, or questions Claude can answer from current conversation context.
1. **Search** - Get an index of results with IDs
2. **Review** - Look at titles/dates, pick relevant IDs
3. **Fetch** - Get full details ONLY for those IDs
## Common Trigger Phrases
### Step 1: Search Everything
This skill activates when detecting phrases about **cross-session history**:
```bash
curl "http://localhost:37777/api/search?query=authentication&format=index&limit=5"
```
- "Did we already solve this?" / "Have we done this before?"
- "How did we implement X last time?"
- "What did we work on yesterday/last week/last month?"
- "Show me the history of [file/feature/decision]"
- "When did we fix/add/change X?"
- "What was happening around [date/time]?"
- "Catch me up on recent sessions" / "What have we been doing?"
- "What changes to [filename] across all sessions?"
**Required parameters:**
- `query` - Search term
- `format=index` - ALWAYS start with index (lightweight)
- `limit=5` - Start small (3-5 results)
**Unique identifiers:** claude-mem, persistent memory, cross-session database, session history, PM2-managed database
**Returns:**
```
1. [feature] Added JWT authentication
Date: 11/17/2025, 3:48:45 PM
ID: 11131
## Available Operations
2. [bugfix] Fixed auth token expiration
Date: 11/16/2025, 2:15:22 PM
ID: 10942
```
### Full-Text Search
- **observations** - Search all observations by keyword (bugs, features, decisions, discoveries, changes)
- Use when: "How did we implement X?" or "What bugs did we fix?"
- Example: Search for "authentication JWT" to find auth-related work
### Step 2: Pick IDs
- **sessions** - Search session summaries to find what was accomplished when
- Use when: "What did we accomplish last time?" or "What was the goal of that session?"
- Example: Find sessions where "added login feature"
Review the index results. Identify which IDs are actually relevant. Discard the rest.
- **prompts** - Find what users have asked about in previous sessions
- Use when: "Did I ask about this before?" or "What did I request last week?"
- Example: Search for "database migration" in past user prompts
### Step 3: Fetch by ID
### Filtered Search
- **by-type** - Filter observations by type (bugfix, feature, refactor, decision, discovery, change)
- Use when: "Show me all bug fixes" or "List features we added"
- Example: Get all observations with type=bugfix from last month
For each relevant ID, fetch full details:
- **by-concept** - Find observations tagged with specific concepts (problem-solution, how-it-works, gotcha)
- Use when: "What patterns did we discover?" or "Show me gotchas"
- Example: Find all observations tagged with concept "gotcha"
```bash
# Fetch observation
curl "http://localhost:37777/api/observation/11131"
- **by-file** - Find all work related to a specific file path across all sessions
- Use when: "What changes to auth.ts?" or "History of this file"
- Example: Get all work related to "src/auth/login.ts"
# Fetch session
curl "http://localhost:37777/api/session/2005"
### Timeline & Context
- **recent-context** - Get last N sessions with summaries and observations
- Use when: "What's been happening?" or "Catch me up on recent work"
- Example: Get last 3 sessions with limit=3
# Fetch prompt
curl "http://localhost:37777/api/prompt/5421"
```
- **timeline** - Get chronological context around a specific point in time (before/after window)
- Use when: "What was happening around [date]?" or "Show me context from that time"
- Example: Timeline around session 123 with depth 5 before and after
**ID formats:**
- Observations: Just the number (11131)
- Sessions: Just the number (2005) from "S2005"
- Prompts: Just the number (5421)
- **timeline-by-query** - Search first, then get timeline context around best match
- Use when: "When did we implement auth?" combined with "show me context around that time"
- Example: Search for "OAuth implementation" then get surrounding timeline
## Search Parameters
For detailed instructions on any operation, read the corresponding file in [operations/](operations/).
**Basic:**
- `query` - What to search for (required)
- `format` - "index" or "full" (always use "index" first)
- `limit` - How many results (default 5, max 100)
## Quick Decision Guide
**Filters (optional):**
- `type` - Filter to "observations", "sessions", or "prompts"
- `project` - Filter by project name
- `dateRange[start]` - Start date (YYYY-MM-DD)
- `dateRange[end]` - End date (YYYY-MM-DD)
- `obs_type` - Filter observations by: bugfix, feature, decision, discovery, change
**What is the user asking about?**
## Examples
1. **Recent work** (last 3-5 sessions) → Use **recent-context** with limit=3-5
2. **Specific topic/keyword** (bugs, features, decisions) → Use **observations** search
3. **Specific file history** (changes to a file) → Use **by-file** search
4. **Timeline/chronology** (what happened when) → Use **timeline** or **timeline-by-query**
5. **Type-specific** (all bug fixes, all features) → Use **by-type** filter
**Find recent bug fixes:**
```bash
curl "http://localhost:37777/api/search?query=bug&type=observations&obs_type=bugfix&format=index&limit=5"
```
**Most common:** Use **observations** search for general "how did we..." questions.
**Find what happened last week:**
```bash
curl "http://localhost:37777/api/search?query=&type=observations&dateRange[start]=2025-11-11&format=index&limit=10"
```
## Progressive Disclosure Workflow (Token Efficiency)
**Search everything:**
```bash
curl "http://localhost:37777/api/search?query=database+migration&format=index&limit=5"
```
**Core Principle**: Find high-signal items in index format FIRST (~50-100 tokens each), then request full details ONLY for relevant items (~500-1000 tokens each).
## Why This Workflow?
**4-Step Workflow:**
**Token efficiency:**
- Index format: ~50-100 tokens per result
- Full format: ~500-1000 tokens per result
- **10x difference** - only fetch full when you know it's relevant
1. **Start with Index Format**
- Always use `format=index` initially
- Set `limit=3-5` (not 10-20)
- Review titles and dates to assess relevance
- Token cost: ~50-100 per result
2. **Identify Relevant Items**
- Scan index results
- Discard irrelevant items from list
- Keep only 1-3 most relevant
3. **Request Full Details Selectively**
- Use `format=full` ONLY for specific relevant items
- Token cost: ~500-1000 per result
- **10x cost difference** - be selective
4. **Refine with Filters**
- Use type, dateRange, concepts, files filters
- Paginate with offset if needed
- Narrow scope before expanding limits
**DO:**
- ✅ Start with `format=index` and `limit=3-5`
- ✅ Use filters (type, dateRange, concepts, files) to narrow results
- ✅ Request `format=full` ONLY for specific relevant items
- ✅ Use offset for pagination instead of large limits
**DON'T:**
- ❌ Jump straight to `format=full`
- ❌ Request `limit=20` without assessing index results first
- ❌ Load full details for all results upfront
- ❌ Skip index format to "save a step" (costs 10x more tokens)
See [principles/progressive-disclosure.md](principles/progressive-disclosure.md) for complete workflow with examples and token calculations.
## Quick Reference Table
| Need | Operation | Key Parameters |
|------|-----------|----------------|
| Recent context | recent-context | limit=3-5 |
| Search observations | observations | query, format=index, limit=5 |
| Search sessions | sessions | query, format=index, limit=5 |
| Find by type | by-type | type=(bugfix\|feature\|decision), format=index |
| Find by file | by-file | filePath, format=index |
| Timeline around event | timeline | anchor=(sessionDbId), depth_before=5, depth_after=5 |
| Search + timeline | timeline-by-query | query, mode=auto |
## Common Workflows
For step-by-step guides on typical user requests, see [operations/common-workflows.md](operations/common-workflows.md):
- Understanding past work from previous sessions
- Finding specific bug fixes from history
- Understanding file history across sessions
- Timeline investigation workflows
- Search composition patterns
## Response Formatting
For guidelines on presenting search results to users, see [operations/formatting.md](operations/formatting.md):
- Index format responses (compact lists with titles/dates)
- Full format responses (complete observation details)
- Timeline responses (chronologically grouped)
- Error handling and user-friendly messages
## Technical Notes
- **Port:** Default 37777 (configurable via `CLAUDE_MEM_WORKER_PORT`)
- **Response format:** Always JSON
- **Search engine:** ChromaDB semantic search (primary ranking) + SQLite FTS5 (fallback) + 90-day recency filter + temporal ordering (hybrid architecture)
- **All operations:** HTTP GET with query parameters
- **Worker:** PM2-managed background process
**Clarity:**
- See everything first
- Pick what matters
- Get details only for what you need
## Error Handling
If HTTP request fails:
1. Inform user the claude-mem search service isn't available
2. Suggest checking if worker is running: `pm2 list` or `pm2 status claude-mem-worker`
3. Offer to help troubleshoot using the troubleshoot skill
## Resources
**Principles:**
- [principles/progressive-disclosure.md](principles/progressive-disclosure.md) - Complete 4-step workflow with token calculations
- [principles/anti-patterns.md](principles/anti-patterns.md) - 5 anti-patterns to avoid with LLM behavior insights
**Operations:**
- [operations/](operations/) - Detailed instructions for each operation (9 operations + help)
- [operations/common-workflows.md](operations/common-workflows.md) - Step-by-step workflow guides
- [operations/formatting.md](operations/formatting.md) - Response formatting templates
If search fails, tell the user the worker isn't available and suggest:
```bash
pm2 list # Check if worker is running
```
---
**Remember:** This skill searches **cross-session persistent memory**, NOT current conversation. Start with index format for token efficiency. Use temporal triggers to differentiate from native Claude memory.
**Remember:** ALWAYS search with format=index first. ALWAYS fetch by ID for details. The IDs are there for a reason - USE THEM.
@@ -17,10 +17,16 @@ curl -s "http://localhost:37777/api/search/observations?query=authentication&for
## Parameters
- **query** (required): Natural language search query - uses semantic search (ChromaDB) for ranking with SQLite FTS5 fallback (e.g., "authentication", "bug fix", "database migration")
- **query** (optional): Natural language search query - uses semantic search (ChromaDB) for ranking with SQLite FTS5 fallback (e.g., "authentication", "bug fix", "database migration"). Can be omitted for filter-only searches.
- **format**: "index" (summary) or "full" (complete details). Default: "full"
- **limit**: Number of results (default: 20, max: 100)
- **project**: Filter by project name (optional)
- **dateRange**: Filter by date range (optional) - `dateRange[start]` and/or `dateRange[end]`
- **obs_type**: Filter by observation type: bugfix, feature, refactor, decision, discovery, change (optional)
- **concepts**: Filter by concept tags (optional)
- **files**: Filter by file paths (optional)
**Important**: When omitting `query`, you MUST provide at least one filter (project, dateRange, obs_type, concepts, or files)
## When to Use Each Format
@@ -76,13 +82,28 @@ Found 5 results for "authentication":
For complete formatting guidelines, see formatting.md (documentation coming soon).
## Filter-Only Examples
Search without query text (direct SQLite filtering):
```bash
# Get all observations from November 2025
curl -s "http://localhost:37777/api/search?type=observations&dateRange[start]=2025-11-01&format=index"
# Get all bug fixes from a specific project
curl -s "http://localhost:37777/api/search?type=observations&obs_type=bugfix&project=api-server&format=index"
# Get all observations from last 7 days
curl -s "http://localhost:37777/api/search?type=observations&dateRange[start]=2025-11-11&format=index"
```
## Error Handling
**Missing query parameter:**
**Missing query and filters:**
```json
{"error": "Missing required parameter: query"}
{"error": "Either query or filters required for search"}
```
Fix: Add the query parameter
Fix: Provide either a query parameter OR at least one filter (project, dateRange, obs_type, concepts, files)
**No results found:**
```json