fix(search,eval): alias-hop injected results carry page_id (contradiction-probe crash)

applyAliasHop injected synthetic SearchResults without page_id (the `as
SearchResult` cast hid the missing field), so listActiveTakesForPages bound
undefined/NaN into ANY($1::int[]) and crashed the whole contradiction probe on
real Postgres. Stamp page_id=page.id at the injection site and add a finite-id
filter in generateIntraPagePairs as a defensive backstop (mirrors hybrid.ts:63).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Garry Tan
2026-06-23 15:04:46 -07:00
co-authored by Claude Opus 4.8
parent 51de806d99
commit a0db4072ef
2 changed files with 15 additions and 2 deletions
+10 -2
View File
@@ -171,11 +171,19 @@ async function generateIntraPagePairs(
results: SearchResult[],
): Promise<ContradictionPair[]> {
if (results.length === 0) return [];
// Unique page_ids only.
const pageIds = Array.from(new Set(results.map((r) => r.page_id)));
// Unique, FINITE page_ids only. Defensive backstop for the alias-hop bug
// (#2339 sibling): an alias-injected synthetic result with an undefined/NaN
// page_id must never reach `ANY($1::int[])` — postgres.js rejects it with
// UNDEFINED_VALUE and aborts the whole probe. Mirrors the hybrid.ts:63 filter.
const pageIds = Array.from(
new Set(
results.map((r) => r.page_id).filter((n): n is number => typeof n === 'number' && Number.isFinite(n)),
),
);
const takesByPage = await engine.listActiveTakesForPages(pageIds);
const out: ContradictionPair[] = [];
for (const r of results) {
if (typeof r.page_id !== 'number' || !Number.isFinite(r.page_id)) continue;
const takes = takesByPage.get(r.page_id) ?? [];
if (takes.length === 0) continue;
const chunkMember = searchResultToMember(r);
+5
View File
@@ -647,6 +647,11 @@ export async function applyAliasHop(
if (!page) continue;
injectScore += 1e-6;
out.push({
// #2339-sibling: include page_id. The `as SearchResult` cast hid its
// absence, so any consumer reading page_id off an alias-injected result got
// undefined — e.g. listActiveTakesForPages bound undefined/NaN into
// ANY($1::int[]) and crashed the contradiction probe on real Postgres.
page_id: page.id,
slug: page.slug,
title: page.title,
type: page.type,