recipe-manager/.harness/fts5-execution-board.md

115 lines
4.3 KiB
Markdown

# FTS5 Full-Text Search — Execution Board
**Feature:** Add true full-text search (FTS5) to Recipe Manager
**Created:** 2026-03-30
**Status:** Planning → In Progress
**Orchestrator:** Cleo (main agent)
**Target Model:** stepfun/step-3.5-flash (where applicable)
---
## 🎯 Goal
Replace the current `LIKE`-based search with a high-performance, relevant FTS5 virtual table that indexes:
- Recipe titles and descriptions
- Ingredient items and notes
- Step instructions
- Tag names (via recipe_tags join)
Provide a single backend search endpoint that:
- Supports phrase queries, prefix searches, AND/OR logic
- Returns ranked results by relevance
- Preserves pagination metadata
- Falls back gracefully if FTS fails
---
## 📦 Deliverables
1. **Schema & Migration**
- Add `recipes_fts` virtual table (FTS5) with `title`, `description`, `ingredient_item`, `ingredient_notes`, `step_instruction`, `tag_name` columns
- Create triggers to keep FTS in sync on INSERT/UPDATE/DELETE of recipes, ingredients, steps, tags, recipe_tags
- Backfill existing data in migration
2. **Backend Search Endpoint**
- New route: `GET /api/recipes/search`
- Params: `q` (query string), `page`, `limit`
- Uses `MATCH` with `bm25()` ranking
- Returns `{ results, total, page, limit, hasMore }` consistent with existing list endpoint
3. **Frontend Integration**
- Update search input to call new endpoint instead of filter-based search
- Show ranked order (highest relevance first)
- Preserve existing pagination UI
4. **Tests**
- Unit tests for FTS trigger logic (insert/update/delete sync)
- Backend integration tests: search relevance, phrase queries, no-results, pagination
- E2E test: search returns expected recipes by title/ingredient
5. **Migration & Rollback**
- Ensure `schemaVersion` increment and migration applied
- Document rollback steps (drop virtual table + triggers)
---
## 🔢 Task Breakdown
| Task | Owner | Est. (hrs) | Status |
|------|-------|------------|--------|
| T1: Design FTS5 virtual table schema + trigger plan | Sub-agent 1 | 1.5 | ⏳ |
| T2: Implement migration (create FTS, triggers, backfill) | Sub-agent 2 | 2 | ⏳ |
| T3: Build `/api/recipes/search` endpoint with ranking | Sub-agent 3 | 2 | ⏳ |
| T4: Write backend unit/integration tests for FTS/sync | Sub-agent 4 | 2 | ⏳ |
| T5: Update frontend to use new endpoint + pagination | Sub-agent 5 | 1.5 | ⏳ |
| T6: E2E verification: search by title, ingredient, tags | Sub-agent 6 | 1 | ⏳ |
| T7: Rollback plan, doc updates, final review | Sub-agent 7 | 1 | ⏳ |
---
## 🧩 Dependencies
- T3 depends on T2 (endpoint requires schema)
- T4 depends on T2 (tests need DB structure)
- T5 depends on T3 (frontend calls endpoint)
- T6 depends on T5
- T7 depends on all
Tasks T1 and T2 can run in parallel (T1 designs, T2 starts once design is signed).
---
## 📐 Acceptance Criteria
- ✅ FTS5 virtual table present and populated with all existing recipes
- ✅ Search returns recipes ranked by BM25 (most relevant first)
- ✅ Phrase queries ("chocolate chip cookies") match correctly
- ✅ Prefix searches ("choc") work
- ✅ Ingredient-only searches return correct recipes
- ✅ Pagination metadata consistent with list endpoint
- ✅ All tests pass (including new FTS tests)
- ✅ Rollback documented and tested (optional)
---
## 🛠️ Technical Notes
- Use `CREATE VIRTUAL TABLE recipes_fts USING fts5(...)`
- Triggers: `AFTER INSERT/UPDATE/DELETE` on recipes, ingredients, steps, tags, recipe_tags
- Use `content=''` and `content_triggers` to auto-sync if desired; but explicit triggers may be simpler
- Migration must be idempotent (check if FTS exists before creating)
- Backend: parameterized query `SELECT ... FROM recipes_fts WHERE recipes_fts MATCH ?`
- Rank: `bm25(recipes_fts)` ascending (lower score = better)
- Join back to `recipes` table to fetch full recipe objects
---
## 🧠 Success Metric
Search accuracy > current `LIKE` filter, no regressions in performance, tests green.
---
**Orchestration Plan:**
Main agent will spawn seven independent sub-agents (one per task) with clear primitives. Sub-agents will report back with status updates. Main agent will monitor progress and roll up into a final status. Use `stepfun/step-3.5-flash` for all sub-agents where model choice applies (per instruction).