---
estimated_steps: 8
estimated_files: 5
skills_used: []
---

# T01: Add technique page slug to Qdrant payloads, search service, and schema

Fix the backend so key moment search results include the parent technique page slug. Three areas need changes:

1. **Qdrant payload enrichment** (`backend/pipeline/qdrant_client.py` + `backend/pipeline/stages.py`): Add `slug` to technique page payloads and `technique_page_slug`/`technique_page_id` to key moment payloads. The stage 6 code in `stages.py` (~line 960) builds `page_dicts` and `moment_dicts` — add the missing fields there. For moments, build a `page_id_to_slug` mapping from the `pages` list, then look up each moment's `technique_page_id` to get the slug.

2. **Search service** (`backend/search_service.py`):
   - `_enrich_results()` (~line 310): Currently falls back to `title.lower().replace(' ', '-')` for slug. Add `technique_page_slug` to the enriched dict, reading from `payload.get('technique_page_slug', '')`. For technique pages, use `payload.get('slug', '')` directly (no longer need the naive fallback once re-indexed, but keep it as fallback for old data).
   - `keyword_search()` (~line 137): Key moment results currently set `slug: ''`. Add an outerjoin to `TechniquePage` via `KeyMoment.technique_page_id == TechniquePage.id` to get the parent slug. Add `technique_page_slug` to the result dict.
   - Also add `technique_page_slug` to technique_page keyword results (set to same as `slug` — a technique page IS its own parent).

3. **Schema** (`backend/schemas.py`): Add `technique_page_slug: str = ''` to `SearchResultItem`.

4. **Tests** (`backend/tests/test_search.py`): Update the keyword fallback test to verify `technique_page_slug` is present in results. Add a test for key moment keyword search returning the correct parent technique page slug.

## Inputs

- ``backend/pipeline/stages.py` — stage 6 embed_and_index, builds page_dicts and moment_dicts (~line 950-1010)`
- ``backend/pipeline/qdrant_client.py` — upsert_technique_pages() and upsert_key_moments() payload structure`
- ``backend/search_service.py` — _enrich_results() and keyword_search() methods`
- ``backend/schemas.py` — SearchResultItem Pydantic model (line ~203)`
- ``backend/tests/test_search.py` — existing search tests`
- ``backend/models.py` — KeyMoment.technique_page_id FK, TechniquePage.slug`

## Expected Output

- ``backend/pipeline/stages.py` — page_dicts include 'slug', moment_dicts include 'technique_page_slug' and 'technique_page_id'`
- ``backend/pipeline/qdrant_client.py` — upsert payloads include slug fields`
- ``backend/search_service.py` — _enrich_results returns technique_page_slug; keyword_search joins TechniquePage for key moments`
- ``backend/schemas.py` — SearchResultItem has technique_page_slug field`
- ``backend/tests/test_search.py` — tests verify technique_page_slug in search results`

## Verification

cd /home/aux/projects/content-to-kb-automator && python -m pytest backend/tests/test_search.py -v 2>&1 | tail -30
