From 414a4cc837b61fddedd63d3c5358f0fd9b61f419 Mon Sep 17 00:00:00 2001 From: BigSimmo <87357024+BigSimmo@users.noreply.github.com> Date: Mon, 13 Jul 2026 01:30:25 +0800 Subject: [PATCH 1/2] docs(drift): stage forward-codify runbook for live-ahead retrieval RPCs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drift backlog item 0 (docs/database-drift-detection.md): prepare the non-live-gated half of forward-codifying the 7 retrieval RPCs whose live bodies are ahead of the repo, without touching the live project or hand-authoring the (two-way-diverged, actively churning) bodies. - docs/forward-codify-retrieval-rpcs-workorder.md: operator runbook — read-only capture, fill-in-the-blanks migration skeleton, schema.sql reconcile, byte-faithful drift:manifest (Docker) + check:drift validation, allowlist cleanup, rollback. - scripts/sql/capture-live-retrieval-rpcs.sql: READ-ONLY pg_get_functiondef capture for the target set (search_path=''). - tests/forward-codify-retrieval-targets.test.ts: offline guard keeping the capture query's targets in lockstep with the "LIVE IS AHEAD" allowlist entries. - docs/database-drift-detection.md: link the runbook from backlog item 0. No runtime, schema.sql, or migration changes; the live capture + apply remain an operator step gated on a quiescent DB. Co-Authored-By: Claude Opus 4.8 --- docs/database-drift-detection.md | 8 +- ...forward-codify-retrieval-rpcs-workorder.md | 265 ++++++++++++++++++ scripts/sql/capture-live-retrieval-rpcs.sql | 53 ++++ .../forward-codify-retrieval-targets.test.ts | 54 ++++ 4 files changed, 379 insertions(+), 1 deletion(-) create mode 100644 docs/forward-codify-retrieval-rpcs-workorder.md create mode 100644 scripts/sql/capture-live-retrieval-rpcs.sql create mode 100644 tests/forward-codify-retrieval-targets.test.ts diff --git a/docs/database-drift-detection.md b/docs/database-drift-detection.md index c64fcf327..e8dd14f7b 100644 --- a/docs/database-drift-detection.md +++ b/docs/database-drift-detection.md @@ -108,7 +108,13 @@ live project need explicit operator approval. > operator-approved migration action. 0. **NEW — forward-codify the live-ahead retrieval RPCs** (was the "apply - 20260705210000" item, inverted). Live carries newer raw-SQL retrieval bodies + 20260705210000" item, inverted). **Staged runbook: + `docs/forward-codify-retrieval-rpcs-workorder.md`** — the read-only capture + query (`scripts/sql/capture-live-retrieval-rpcs.sql`), the fill-in-the-blanks + migration skeleton, the byte-faithful validation, and the allowlist cleanup; + a guard test (`tests/forward-codify-retrieval-targets.test.ts`) keeps the + capture query and this allowlist in lockstep. The capture + apply steps still + need a quiescent live DB and operator approval. Live carries newer raw-SQL retrieval bodies than the repo: `match_document_chunks` (hnsw.ef_search=100 plpgsql wrapper), `match_document_chunks_text` / `match_document_table_facts_text` (richer multi-strategy), `match_document_chunks_hybrid` (left-join quality_score), diff --git a/docs/forward-codify-retrieval-rpcs-workorder.md b/docs/forward-codify-retrieval-rpcs-workorder.md new file mode 100644 index 000000000..d210cd29e --- /dev/null +++ b/docs/forward-codify-retrieval-rpcs-workorder.md @@ -0,0 +1,265 @@ +# Work order: forward-codify the live-ahead retrieval RPCs + +Status: **staged, awaiting operator run.** Drift backlog item 0 +(`docs/database-drift-detection.md#reconciliation-backlog`). + +This is the fill-in-the-blanks procedure for reconciling the retrieval RPCs +whose **live bodies are ahead of the repo**. Everything that does not touch the +live project is prepared and committed (this doc, the capture query, and a guard +test). The remaining steps require a **quiescent live database** and **explicit +operator approval**, because capturing the bodies reads the live project and +applying the migration writes migration history to it. + +## Why this exists (read before running) + +The four hybrid retrieval RPCs plus several siblings were, historically, edited +directly on the live `Clinical KB Database` via raw SQL. Migration +`20260705210000` tried to reconcile them but carried **older** bodies than live; +applying it would have regressed production retrieval, so it was +**neutralized** on 2026-07-08. Since then the live bodies have kept churning +under concurrent multi-session editing, and they have diverged in **both** +directions — e.g. `match_document_chunks_hybrid` in `supabase/schema.sql` already +carries the fail-closed `retrieval_owner_matches(...)` predicate (applied via +`20260708160001`), while live is ahead on richer candidate construction (the +left-joined `document_index_quality.quality_score`, multi-strategy text ranking, +an `hnsw.ef_search=100` wrapper on `match_document_chunks`). + +Because of that two-way divergence, **do not hand-author these bodies.** The +only correct source is a verbatim `pg_get_functiondef` capture from live. The +established precedent is `20260701140631_codify_live_retrieval_rpcs.sql` and +`20260707000000_codify_live_observed_drift.sql`: transcribe live verbatim, +validate byte-faithful, then apply as an idempotent no-op. + +## Target set (7 functions) + +The authoritative target set is every `functions` entry in +`supabase/drift-allowlist.json` whose `kind` is `mismatch` and whose `reason` +begins with **`LIVE IS AHEAD`**. As of this writing that is exactly seven: + +| Signature (`oid::regprocedure`, `search_path=''`) | +| -------------------------------------------------------------------------------------------------- | +| `public.get_related_document_metadata(uuid[],uuid)` | +| `public.match_document_chunks(extensions.vector,integer,double precision,uuid,uuid)` | +| `public.match_document_chunks_hybrid(extensions.vector,text,integer,double precision,uuid[],uuid)` | +| `public.match_document_chunks_text(text,integer,uuid[],uuid)` | +| `public.match_document_table_facts_text(text,integer,uuid[],uuid)` | +| `public.match_documents_for_query(text,integer,uuid)` | +| `public.repair_strict_enrichment_gate_batch(integer)` | + +This list is duplicated in `scripts/sql/capture-live-retrieval-rpcs.sql`; +`tests/forward-codify-retrieval-targets.test.ts` fails if the two ever drift +apart, so reconciling a sibling (removing its allowlist entry) forces a matching +update to the capture query. + +**Already reconciled siblings — do not re-add** (they are not in the allowlist +`LIVE IS AHEAD` set): `match_document_embedding_fields_text` was applied to live +via `20260706130000` and now matches the repo; `20260701140631` codified the +hybrid cores `match_document_embedding_fields_hybrid`, +`match_document_index_units_hybrid`, and the memory-cards wrapper + +`match_document_memory_cards_hybrid_v2`. Note that `match_document_chunks_hybrid` +_was_ codified by `20260701140631` but has since **re-drifted ahead** on live, so +it is back in the seven targets above — a reminder that codifying a churning RPC +buys parity only until the next live edit. + +## Preconditions + +- [ ] Explicit operator approval to read and later write the live project. +- [ ] The live retrieval RPCs are **quiescent** — no other session is mid-edit. + A capture taken during churn is stale before it lands. Coordinate a window. +- [ ] Docker is running (`docker info` succeeds) — needed for the byte-faithful + replay in `npm run drift:manifest`. +- [ ] Live service-role env is present for `npm run check:drift` + (`NEXT_PUBLIC_SUPABASE_URL`, `SUPABASE_PROJECT_REF`, `SUPABASE_PROJECT_NAME`, + `SUPABASE_SERVICE_ROLE_KEY`) and points at ref `sjrfecxgysukkwxsowpy`. +- [ ] Working on a feature branch (never author migrations on `main`). + +## Step 1 — Capture the verbatim live bodies (provider read) + +Run `scripts/sql/capture-live-retrieval-rpcs.sql` against live via the Supabase +Dashboard SQL editor, an approved service-role SQL path, or the Supabase MCP +`execute_sql` tool. It is read-only (`pg_proc` only). **Expect exactly 7 rows**, +each a `signature` + a full `CREATE OR REPLACE FUNCTION …` `definition`. + +If you get fewer than 7 rows, a target signature no longer resolves on live. +Find which with: + +```sql +set search_path = ''; +select s as missing_signature +from unnest(array[ + 'public.get_related_document_metadata(uuid[],uuid)', + 'public.match_document_chunks(extensions.vector,integer,double precision,uuid,uuid)', + 'public.match_document_chunks_hybrid(extensions.vector,text,integer,double precision,uuid[],uuid)', + 'public.match_document_chunks_text(text,integer,uuid[],uuid)', + 'public.match_document_table_facts_text(text,integer,uuid[],uuid)', + 'public.match_documents_for_query(text,integer,uuid)', + 'public.repair_strict_enrichment_gate_batch(integer)' +]) as s +where to_regprocedure(s) is null; +``` + +Resolve the mismatch (update the target set + allowlist) before continuing. + +> Note: the Dashboard SQL editor shows only the last statement's result set. If +> you use it, run the capture `select` on its own so its 7 rows are visible. +> `psql`/`execute_sql` return every result set. + +## Step 2 — Author the forward migration + +Create `supabase/migrations/_codify_live_retrieval_rpcs_forward.sql` +(e.g. `20260713NNNNNN_…`). Use the skeleton below. Paste each captured +`definition` **verbatim** into its slot — do not reformat, re-indent, or +"clean up" the body; verbatim is what makes the apply a byte-faithful no-op. + +```sql +-- Forward-codify the live-ahead retrieval RPC bodies (drift backlog item 0). +-- +-- The live Clinical KB Database carried newer raw-SQL retrieval bodies than the +-- repo for these 7 functions; migration 20260705210000 (older bodies) was +-- neutralized so a db push could not regress live. These definitions are +-- transcribed VERBATIM from live pg_get_functiondef (captured on a quiescent DB +-- via scripts/sql/capture-live-retrieval-rpcs.sql) and validated byte-faithful +-- before applying, so applying to live is a no-op while a clean replay now +-- reproduces exactly what production runs. Supersedes the older definitions in +-- the migration chain for these functions. +-- +-- See docs/forward-codify-retrieval-rpcs-workorder.md. + +set search_path = public, extensions, pg_temp; + +-- 1. public.get_related_document_metadata(uuid[],uuid) +-- <<< PASTE captured definition verbatim >>> + +-- 2. public.match_document_chunks(extensions.vector,integer,double precision,uuid,uuid) +-- <<< PASTE captured definition verbatim >>> + +-- 3. public.match_document_chunks_hybrid(extensions.vector,text,integer,double precision,uuid[],uuid) +-- <<< PASTE captured definition verbatim >>> + +-- 4. public.match_document_chunks_text(text,integer,uuid[],uuid) +-- <<< PASTE captured definition verbatim >>> + +-- 5. public.match_document_table_facts_text(text,integer,uuid[],uuid) +-- <<< PASTE captured definition verbatim >>> + +-- 6. public.match_documents_for_query(text,integer,uuid) +-- <<< PASTE captured definition verbatim >>> + +-- 7. public.repair_strict_enrichment_gate_batch(integer) +-- <<< PASTE captured definition verbatim >>> + +-- ACLs: pg_get_functiondef does NOT include grants. check:drift compares the +-- `acl` field too, so add the revoke/grant statements only for functions whose +-- acl actually differs from schema.sql (Step 4 reports this). Precedent +-- (service-role-only), append per differing function: +-- revoke execute on function from public, anon, authenticated; +-- grant execute on function to service_role; +``` + +## Step 3 — Reconcile `supabase/schema.sql` + +For each of the 7 functions, replace its existing definition **statement** in +`supabase/schema.sql` with the captured verbatim definition. Each block starts at + +``` +create or replace function public.( +``` + +and ends at its dollar-quote terminator (`$$;` or `$function$;`). Current +start lines (they shift as you edit — search by name, don't trust the numbers): + +| Function | `create or replace function` at | +| ------------------------------------- | ------------------------------- | +| `match_document_chunks` | ~line 2188 | +| `match_document_chunks_hybrid` | ~line 2243 | +| `match_documents_for_query` | ~line 3186 | +| `match_document_chunks_text` | ~line 3272 | +| `get_related_document_metadata` | ~line 3540 | +| `match_document_table_facts_text` | ~line 3593 | +| `repair_strict_enrichment_gate_batch` | ~line 3881 | + +Leave the surrounding statements alone: only `repair_strict_enrichment_gate_batch` +has its own `revoke`/`grant` lines immediately after it (keep them, or update +them if Step 4 shows an `acl` diff); the `match_*` / `get_related_*` functions +have no adjacent per-function grants — their privileges come from the schema's +default/bulk grants, so do not invent new grant lines for them unless check:drift +reports an `acl` mismatch. + +Verbatim `pg_get_functiondef` renders `CREATE OR REPLACE FUNCTION` in uppercase +with `$function$` delimiters; that cosmetic difference from schema.sql's +lowercase style is fine — check:drift and the manifest compare a +comment/whitespace-stripped hash, not raw text. + +## Step 4 — Validate byte-faithful (Docker + live) + +1. Regenerate the expected-state manifest from the edited schema (Docker replay): + + ``` + npm run drift:manifest + ``` + + This replays `supabase/schema.sql` into a scratch `supabase/postgres` + container and recaptures `schema_drift_snapshot()`. It never touches live. + +2. Confirm the manifest's `def_hash` for the 7 functions now equals live's. The + cleanest proof is the full check: + + ``` + npm run check:drift # needs live service-role env + ``` + + The 7 target functions should **no longer** appear as drift. (They will still + be listed while their allowlist entries exist — as _allowlisted_, not as + unexpected drift; remove the entries in Step 5 and they disappear entirely.) + +3. Offline gate — manifest freshness + snapshot parity: + + ``` + npm run test -- tests/drift-detection.test.ts tests/forward-codify-retrieval-targets.test.ts + ``` + +4. Retrieval quality is unchanged (required) and schema health is green: + + ``` + npm run eval:retrieval:quality # expect 36/36 (provider-backed; approve) + ``` + + `select public.search_schema_health();` should return `ok`. + +If a `def_hash` still differs after replay, the pasted body was altered in +transit (whitespace inside a dollar-quoted string, a smart-quote, a dropped +line). Re-capture and re-paste verbatim; do not "fix" it by editing the body. + +## Step 5 — Remove the allowlist entries + +Delete the 7 `functions`/`mismatch` entries whose reason begins `LIVE IS AHEAD` +from `supabase/drift-allowlist.json`, update +`tests/forward-codify-retrieval-targets.test.ts`'s expectation to empty (or +delete the guard once the backlog item is closed), mark item 0 done in +`docs/database-drift-detection.md`, and re-run `npm run check:drift` — it should +now report **no** allowlisted retrieval divergence and **no** stale entries. + +## Step 6 — Apply to live + +Apply the new migration through the normal linked migration workflow (operator). +Because the bodies were captured from live, this is an **idempotent no-op** on +the live project; its value is that `supabase db reset`, branch/preview DBs, and +disaster-recovery replays now rebuild production's retrieval layer exactly. + +## Rollback / safety + +- The migration only issues `create or replace function` (+ any needed grants). + If a body was captured wrong and applied, re-running with a corrected capture + supersedes it; there is no destructive DDL here. +- Never edit these functions on live with raw SQL — that is how this incident + class started. Fixes go through migrations only. +- If the DB was not actually quiescent (a concurrent edit landed between capture + and apply), `check:drift` will flag the residual diff. Re-capture and repeat. + +## Division of labor + +- 🤖 **Prepared (committed, no live access):** this work order, the read-only + capture query, the offline guard test, and the backlog link. +- 🧑 **Operator (needs approval + a quiescent DB):** run the capture (Step 1), + paste the verbatim bodies (Steps 2–3), run the Docker + live validation + (Step 4), prune the allowlist (Step 5), and apply (Step 6). diff --git a/scripts/sql/capture-live-retrieval-rpcs.sql b/scripts/sql/capture-live-retrieval-rpcs.sql new file mode 100644 index 000000000..60ebfa84a --- /dev/null +++ b/scripts/sql/capture-live-retrieval-rpcs.sql @@ -0,0 +1,53 @@ +-- capture-live-retrieval-rpcs.sql (READ-ONLY) +-- +-- Captures the VERBATIM live bodies of the retrieval RPCs that are still flagged +-- "LIVE IS AHEAD" in supabase/drift-allowlist.json, so their definitions can be +-- forward-codified into a migration + supabase/schema.sql WITHOUT hand-authoring +-- them. These bodies are complex, have diverged in both directions (e.g. the +-- fail-closed retrieval_owner_matches predicate was applied to live while live +-- also grew richer multi-strategy candidate sets), and are under active +-- concurrent multi-session editing — so only a verbatim capture is correct. A +-- hand-written body is exactly what got migration 20260705210000 neutralized. +-- +-- Full procedure: docs/forward-codify-retrieval-rpcs-workorder.md +-- Backlog item 0: docs/database-drift-detection.md#reconciliation-backlog +-- +-- HOW TO RUN — this is a provider action (it reads the live project); get +-- explicit approval first and run it only when the live DB is QUIESCENT (no +-- concurrent edits to these functions). It changes nothing — it only reads +-- pg_proc. Run it via the Supabase Dashboard SQL editor, an approved +-- service-role SQL path, or the Supabase MCP execute_sql tool. +-- +-- Expect EXACTLY 7 rows back (one per target). Fewer rows means a target +-- signature no longer resolves on live (renamed, dropped, or already +-- reconciled) — see the "missing signatures" snippet in the work-order and +-- reconcile the target set + allowlist before continuing. +-- +-- search_path is pinned to '' so oid::regprocedure renders fully-qualified and +-- matches the allowlist keys / schema_drift_snapshot() signatures exactly, and +-- so pg_get_functiondef emits fully-qualified, replay-safe text (the same style +-- as migrations 20260701140631 / 20260707000000). This is cosmetic, not +-- correctness-critical: check:drift hashes pg_get_functiondef under search_path +-- '' on both live and the schema.sql replay, so a verbatim body always hashes +-- equal regardless of how it was rendered at capture time. + +set search_path = ''; + +-- >>> forward-codify targets >>> (kept in lockstep with the "LIVE IS AHEAD" +-- retrieval entries in supabase/drift-allowlist.json — see +-- tests/forward-codify-retrieval-targets.test.ts) +select + t.signature, + pg_get_functiondef(t.signature::regprocedure) as definition +from ( + values + ('public.get_related_document_metadata(uuid[],uuid)'), + ('public.match_document_chunks(extensions.vector,integer,double precision,uuid,uuid)'), + ('public.match_document_chunks_hybrid(extensions.vector,text,integer,double precision,uuid[],uuid)'), + ('public.match_document_chunks_text(text,integer,uuid[],uuid)'), + ('public.match_document_table_facts_text(text,integer,uuid[],uuid)'), + ('public.match_documents_for_query(text,integer,uuid)'), + ('public.repair_strict_enrichment_gate_batch(integer)') +) as t(signature) +order by t.signature; +-- <<< forward-codify targets <<< diff --git a/tests/forward-codify-retrieval-targets.test.ts b/tests/forward-codify-retrieval-targets.test.ts new file mode 100644 index 000000000..2f7b41503 --- /dev/null +++ b/tests/forward-codify-retrieval-targets.test.ts @@ -0,0 +1,54 @@ +import { readFileSync } from "node:fs"; +import { join } from "node:path"; +import { describe, expect, it } from "vitest"; + +// Guards drift backlog item 0 (docs/forward-codify-retrieval-rpcs-workorder.md): +// the read-only capture query scripts/sql/capture-live-retrieval-rpcs.sql must +// target exactly the retrieval RPCs still flagged "LIVE IS AHEAD" in the drift +// allowlist. Reconciling a sibling (removing its allowlist entry) then forces a +// matching edit to the capture query, so the work-order artifact cannot silently +// rot as the backlog is worked down. + +const root = join(__dirname, ".."); +const read = (relative: string) => readFileSync(join(root, relative), "utf8"); + +// Allowlist entries the work-order treats as its authoritative target set. +const LIVE_AHEAD_PREFIX = "LIVE IS AHEAD"; + +type AllowlistEntry = { category: string; kind: string; key: string; reason: string }; + +function liveAheadRetrievalSignatures(): string[] { + const { entries } = JSON.parse(read("supabase/drift-allowlist.json")) as { entries: AllowlistEntry[] }; + return entries + .filter((e) => e.category === "functions" && e.kind === "mismatch" && e.reason.startsWith(LIVE_AHEAD_PREFIX)) + .map((e) => e.key) + .sort(); +} + +function captureQuerySignatures(): string[] { + const sql = read("scripts/sql/capture-live-retrieval-rpcs.sql"); + const start = sql.indexOf(">>> forward-codify targets >>>"); + const end = sql.indexOf("<<< forward-codify targets <<<"); + expect(start, "capture query is missing its `>>> forward-codify targets >>>` marker").toBeGreaterThanOrEqual(0); + expect(end, "capture query is missing its `<<< forward-codify targets <<<` marker").toBeGreaterThan(start); + const region = sql.slice(start, end); + // Signatures are single-quoted VALUES literals; regprocedure text never + // contains a single quote, so this is an exact extraction. + const matches = [...region.matchAll(/'([^']+)'/g)].map((m) => m[1]); + return matches.sort(); +} + +describe("forward-codify retrieval target set stays in sync with the drift allowlist", () => { + it("finds a non-empty set of live-ahead retrieval functions in the allowlist", () => { + expect(liveAheadRetrievalSignatures().length).toBeGreaterThan(0); + }); + + it("the capture query lists every live-ahead retrieval signature, and only those", () => { + expect(captureQuerySignatures()).toEqual(liveAheadRetrievalSignatures()); + }); + + it("the capture query has no duplicate target signatures", () => { + const signatures = captureQuerySignatures(); + expect(new Set(signatures).size).toBe(signatures.length); + }); +}); From e8ee696dd6db4a991e6964d96e4ded40131596a5 Mon Sep 17 00:00:00 2001 From: BigSimmo <87357024+BigSimmo@users.noreply.github.com> Date: Mon, 13 Jul 2026 02:05:58 +0800 Subject: [PATCH 2/2] fix(drift): tolerate missing capture targets + scope the capture query MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Address PR #524 review (CodeRabbit + Codex): the capture query cast each signature with ::regprocedure, which THROWS on a missing/renamed/reconciled target instead of returning fewer rows — contradicting the file's documented "expect 7, fewer means missing" contract. Resolve via to_regprocedure + filter nulls (validated against a supabase/postgres container: 0 rows, no error when the target functions are absent). Also clarify the query covers only the allowlist "LIVE IS AHEAD" retrieval subset, not the live-only/(verify) functions the runbook fingerprint table codifies. The remaining review comments anchored to the pre-merge 265-line work-order that merging origin/main replaced with the fingerprinted version (now 113 lines); those line references (164/213/257) no longer exist. Co-Authored-By: Claude Opus 4.8 --- ...forward-codify-retrieval-rpcs-workorder.md | 11 +++- scripts/sql/capture-live-retrieval-rpcs.sql | 54 ++++++++++++------- 2 files changed, 43 insertions(+), 22 deletions(-) diff --git a/docs/forward-codify-retrieval-rpcs-workorder.md b/docs/forward-codify-retrieval-rpcs-workorder.md index 509304b48..686c04ad4 100644 --- a/docs/forward-codify-retrieval-rpcs-workorder.md +++ b/docs/forward-codify-retrieval-rpcs-workorder.md @@ -99,8 +99,15 @@ target set cannot silently drift from the machine-checked source of truth: `LIVE IS AHEAD` retrieval entries, so reconciling a sibling (removing its allowlist entry) forces a matching edit to the capture query and this file. -The fingerprint table above remains the point-in-time reference snapshot; the -committed query is the maintained, always-in-sync-with-the-allowlist capture. +The committed query covers **only** the `LIVE IS AHEAD` retrieval subset (its +guard invariant). It is **not** the full codification set: the live-only +(`unexpected_live`) and `(verify)` functions in the fingerprint table above — +`get_visual_evidence_cards`, `run_visual_eval_case`, `run_all_visual_eval_cases`, +`repair_enrichment_quality_batch`, `match_document_index_units_hybrid`, +`match_document_memory_cards_hybrid[_v2]` — are captured from that table per +Step 1, not from this query. The fingerprint table remains the point-in-time +reference snapshot; the committed query is the maintained, +always-in-sync-with-the-allowlist capture of its subset. ## Not in this work-order (separate allowlist backlog) diff --git a/scripts/sql/capture-live-retrieval-rpcs.sql b/scripts/sql/capture-live-retrieval-rpcs.sql index 60ebfa84a..8476af969 100644 --- a/scripts/sql/capture-live-retrieval-rpcs.sql +++ b/scripts/sql/capture-live-retrieval-rpcs.sql @@ -9,6 +9,15 @@ -- concurrent multi-session editing — so only a verbatim capture is correct. A -- hand-written body is exactly what got migration 20260705210000 neutralized. -- +-- SCOPE: this covers ONLY the allowlist "LIVE IS AHEAD" retrieval subset — the +-- guard-tested set (tests/forward-codify-retrieval-targets.test.ts). It is NOT +-- the complete codification set. The runbook also codifies live-only +-- (unexpected_live) and "verify" functions — get_visual_evidence_cards, +-- run_visual_eval_case, run_all_visual_eval_cases, repair_enrichment_quality_batch, +-- match_document_index_units_hybrid, match_document_memory_cards_hybrid[_v2]. +-- Capture those from the fingerprint table in +-- docs/forward-codify-retrieval-rpcs-workorder.md, not here. +-- -- Full procedure: docs/forward-codify-retrieval-rpcs-workorder.md -- Backlog item 0: docs/database-drift-detection.md#reconciliation-backlog -- @@ -18,10 +27,11 @@ -- pg_proc. Run it via the Supabase Dashboard SQL editor, an approved -- service-role SQL path, or the Supabase MCP execute_sql tool. -- --- Expect EXACTLY 7 rows back (one per target). Fewer rows means a target --- signature no longer resolves on live (renamed, dropped, or already --- reconciled) — see the "missing signatures" snippet in the work-order and --- reconcile the target set + allowlist before continuing. +-- Expect EXACTLY 7 rows back (one per target). A target that no longer resolves +-- on live (renamed, dropped, or already reconciled) is filtered out and simply +-- yields FEWER rows — the query does not error. If you get fewer than 7, find +-- which with the "missing signatures" snippet in the work-order and reconcile +-- the target set + allowlist before continuing. -- -- search_path is pinned to '' so oid::regprocedure renders fully-qualified and -- matches the allowlist keys / schema_drift_snapshot() signatures exactly, and @@ -33,21 +43,25 @@ set search_path = ''; --- >>> forward-codify targets >>> (kept in lockstep with the "LIVE IS AHEAD" --- retrieval entries in supabase/drift-allowlist.json — see --- tests/forward-codify-retrieval-targets.test.ts) select - t.signature, - pg_get_functiondef(t.signature::regprocedure) as definition + r.signature, + pg_get_functiondef(r.proc) as definition from ( - values - ('public.get_related_document_metadata(uuid[],uuid)'), - ('public.match_document_chunks(extensions.vector,integer,double precision,uuid,uuid)'), - ('public.match_document_chunks_hybrid(extensions.vector,text,integer,double precision,uuid[],uuid)'), - ('public.match_document_chunks_text(text,integer,uuid[],uuid)'), - ('public.match_document_table_facts_text(text,integer,uuid[],uuid)'), - ('public.match_documents_for_query(text,integer,uuid)'), - ('public.repair_strict_enrichment_gate_batch(integer)') -) as t(signature) -order by t.signature; --- <<< forward-codify targets <<< + select t.signature, to_regprocedure(t.signature) as proc + from ( + -- >>> forward-codify targets >>> (kept in lockstep with the "LIVE IS AHEAD" + -- retrieval entries in supabase/drift-allowlist.json — see + -- tests/forward-codify-retrieval-targets.test.ts) + values + ('public.get_related_document_metadata(uuid[],uuid)'), + ('public.match_document_chunks(extensions.vector,integer,double precision,uuid,uuid)'), + ('public.match_document_chunks_hybrid(extensions.vector,text,integer,double precision,uuid[],uuid)'), + ('public.match_document_chunks_text(text,integer,uuid[],uuid)'), + ('public.match_document_table_facts_text(text,integer,uuid[],uuid)'), + ('public.match_documents_for_query(text,integer,uuid)'), + ('public.repair_strict_enrichment_gate_batch(integer)') + -- <<< forward-codify targets <<< + ) as t(signature) +) as r +where r.proc is not null +order by r.signature;