An evidence-first media recall search app for finding a half-remembered movie, show, song, book, or game. P1 uses Flask and Typesense hybrid search; it does not require an LLM or RAG service.
Prerequisites: Python 3.11+ and Docker Desktop.
Copy-Item .env.example .env
python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -r requirements.txt
docker compose up -dThe Docker service is bound only to 127.0.0.1:8108, persists its data in a named volume, and does not enable browser CORS. The Flask server is the only browser-facing search boundary.
Validate and deploy the checked-in 250-item catalog:
python -m flask catalog validate data\media.jsonl
python -m flask catalog create-index --name media_v1
python -m flask catalog import --collection media_v1 data\media.jsonl
python -m flask catalog activate --collection media_v1The first hybrid index creation can take longer while Typesense downloads and warms its built-in embedding model. activate checks all five media counts before atomically pointing the media_current alias at the new collection. To restore the prior target recorded in data/deployment.json:
python -m flask catalog rollbackRun the app at http://127.0.0.1:5000:
python run.pyFor a Windows production process use waitress-serve --call app:create_app; on Linux use gunicorn 'app:create_app()'. Restarting Flask clears its bounded in-memory search cache.
Copy .env.example; never commit .env. TYPESENSE_ADMIN_API_KEY is read only by catalog CLI commands. The serving process uses TYPESENSE_SEARCH_API_KEY; use a scoped, search-only key for hosted deployments. Point TYPESENSE_HOST, TYPESENSE_PORT, and TYPESENSE_PROTOCOL at Typesense Cloud without changing application code.
P1 leaves RAG_ENABLED=false. Search orchestration is isolated behind SearchService, so a future hosted guidance/RAG stage can consume retrieved records without changing the public search contract.
GET /health/live— Flask liveness; no dependency call.GET /health/ready(and/health) — Typesense health and serving-alias readiness.POST /api/search— validated recall, explore, or similarity request.GET /api/media/<id>— projected catalog detail.
There are no public indexing or admin routes. API errors use a stable {request_id, error: {code, message, fields}} envelope. Search responses exclude raw embeddings and internal search text.
python -m pytest -q
node --check app\static\js\app.jsUnit and API tests use an injected gateway and do not require Docker. A useful live smoke sequence is: readiness, a fuzzy recall search, card detail, then “More like this.” Full release/evaluation requirements and parallel task ownership are in agents_context/specs.
app/
catalog/ normalization, schema, index lifecycle
routes/ health and public HTTP boundary
services/ intent, safe filters, retrieval, evidence
static/ accessible CSS and browser modules
templates/ single-page search interface
data/ curated JSONL catalog and deployment metadata
tests/ contracts, catalog, intent, retrieval, API, factory
agents_context/ product overview, design, implementation specs