# Tasks — Memory v2

## Prerequisites
- v2.8.0 on main (v1 memory module shipped)

## Tasks

### 1. BM25 ranker
- [ ] 1.1 Write `bm25.ts` — pure function, no deps. BM25Okapi formula: `sum over terms of IDF * (tf * (k1 + 1)) / (tf + k1 * (1 - b + b * docLen / avgDocLen))`
- [ ] 1.2 Unit tests with known corpus

### 2. Embedding module
- [ ] 2.1 Write `embeddings.ts` — load ONNX model, `embed(texts: string[]): number[][]`
- [ ] 2.2 Write `ranker.ts` — cosine similarity + BM25 weighted merge
- [ ] 2.3 Fallback to BM25-only when model unavailable

### 3. Hybrid recall
- [ ] 3.1 Refactor `recall.ts` — `rankByRelevance` → `rankByHybrid` using BM25 + embedding when available
- [ ] 3.2 Keep keyword-only path as `MEMORY_SEARCH=keyword` env fallback
- [ ] 3.3 Server tests pass

### 4. Agent tools
- [ ] 4.1 Create `extract_memory` tool — persists entry, returns path
- [ ] 4.2 Create `search_memory` tool — replaces raw injection when used
- [ ] 4.3 Tool tests pass

### 5. Smoke
- [ ] 5.1 Create `.boocode/memory/project/style.md` with "Use two-space indentation"
- [ ] 5.2 `search_memory("what spacing convention")` returns the entry
- [ ] 5.3 `extract_memory("project", "Naming", "PascalCase for components")` creates the file
