> ## Documentation Index
> Fetch the complete documentation index at: https://prism.ntecdev.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Retro: Phase 3 — Hybrid recall + Learning + Admin

> Phase 3 — Hybrid recall + Learning + Admin

<Info>**Phase:** Phase 3 — Hybrid recall + Learning + Admin · **Status:** `closed` · Filed 2026-04-16</Info>

## What Worked

* RRF for hybrid recall — ranks-only fusion, zero normalization tuning needed
* Generated tsvector column — Postgres recomputes on content change, zero app-layer sync
* Idempotent candidate sync — checks existing (retro\_id, lesson\_index) before insert
* Promote/reject in DB instead of docs — enforced in code, audit trail permanent
* Dedicated audit session for last\_used\_at — decoupled from request semantics (ADR-020)
* Smoke-test-as-you-go continued — caught candidate backfill gap immediately
* Dogfooding the new endpoints — product is used to build itself

## What Didn't

* global\_fact\_candidates was a Phase 0 stub that sat empty for three phases — stubs decay
* PowerShell quoting tripped up in bash-spawned pipeline — use single quotes or here-doc
* Forgot to commit Phase 2 retro to DB first time — PID-PGR01 wasn't registered as project
* First learning\_service Write call failed because file existed as Phase 0 stub — always Read first
* regex parameter on FastAPI Query deprecated in favor of pattern — trivial, deferred
* MEMORY.md global feedback memory wasn't checked at session start

## Lessons

* **\[project]** L8 — Generated columns over application-maintained denorm. Prefer Postgres GENERATED ALWAYS AS ... STORED
* **\[project]** L9 — Idempotency via composite key check before insert is the Prism idiom
* **\[project]** L10 — Audit-style writes own their own sessions. Don't piggyback on the request session
* **\[project]** L11 — Stubs decay. If a model is in the registry, it should be a real table
* **\[global]** G5 — RRF (RRF\_K=60) is the default for hybrid retrieval in agent-memory systems
* **\[global]** G6 — Cross-platform script parity from day one. Every .ps1 ships with a .sh
