Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/branch-review-ledger.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -392,11 +392,14 @@ Use this ledger to prevent repeated branch and PR reviews when the reviewed HEAD
| 2026-07-13 | origin/codex/rag-canary-completion | d1b7647bde73e7d0558472ad6aa19c3b49d94639 | branch-cleanup | Retained for open PR #612 and active worktree activity. | Fresh GitHub open-PR query and moving-head observation; deletion prohibited. |
| 2026-07-13 | origin/main | 528a1752f41cd29a518ca9341c93c724030173ae | branch-cleanup | Protected base branch retained. | Final refreshed origin/main snapshot before the ledger PR. |
| 2026-07-14 | PR #629 / codex/eval-canary-quota-handling | 8fe1be6d0c58c60afeeb82f720b03c90ce57c2cf | review-followup | One P2 structured-error retry defect confirmed and fixed on `codex/eval-canary-structured-errors`. | GitHub connector thread inspection; `tests/eval-utils.test.ts` 14/14; focused ESLint and Prettier. |
| 2026-07-14 | codex/global-answer-reliability | 01d2749978d4e8f3b4ac508e068ec7b8d331f816 | release-readiness / answer generation, source governance, progress, and document access | No unresolved P0-P2 findings after fixing demo-path governance parity, preserving feedback-token binding during the `origin/main` rebase, and binding legacy-summary feedback to the delivered governed answer. Ready for hosted PR checks. | `npm run verify:pr-local` (2,223 passed, 1 skipped; production build and offline RAG evaluation passed); focused Chromium answer regressions (4/4 passed); focused answer and route regressions (124/124 passed). |
| 2026-07-14 | claude/repo-next-steps-e53523 | 3f7d6d76f597f2a0311af1052480f84b68ecc259 | launch-readiness and RAG-performance follow-up | Branch changes were already squash-merged by PR #513. Fresh review found one P1 governance inconsistency (Singapore app/worker processing omitted from the PIA's cross-border account) and three P2 follow-ups: degraded-answer SLO overcounting, a second blocking shared-cache miss diagnostic query, and stale launch/RAG backlog status. No source fix was applied in this review. | `git diff --check c3828ceb9f3812abeebc1b653361fc254dda9f5e..3f7d6d76f597f2a0311af1052480f84b68ecc259`; focused Vitest 92/92; `npm run eval:rag:offline` 36 fixtures and 59/59 contract tests; `npm run verify:cheap` passed runtime, action pins, sitemap, type scale, lint, typecheck, and 1,672 passed/1 skipped tests. Provider-backed Supabase/OpenAI, browser, release, drift, and live retrieval-quality checks were not run. |
| 2026-07-14 | codex/rag-performance-followups | 5502fd498ea2069f810795a8659f98ab3abf8c80 | release-readiness review | The local release review found no P0-P2 defect after correcting one stale PIA statement; the later hosted review follow-up is recorded below. The scoped RAG round-trip, SLO, retention, privacy, and documentation changes were ready for PR handoff. Highest residual risk is the known live hybrid-RPC latency tail; model experiments remain blocked by provider quota and legal execution remains operator/counsel work. | Rebased onto `origin/main`; runtime and full Prettier check; ESLint; TypeScript; Vitest 2,213 passed/1 skipped; Next.js production build (636 pages) plus client-bundle secret scan; offline RAG 36 fixtures and 277/277 contract tests; `git diff --check`. Live retention jobs 13/16 were already verified during this workstream. |
| 2026-07-14 | PR #632 / codex/rag-performance-followups | aa264e92c44b42fdcceeac6292011ba51169b862 | review-followup | One P2 SLO-classification defect was confirmed: the broad source-only `degraded` flag also included healthy extractive answers. Fixed by persisting and counting a separate `provider_generation_degraded` flag derived only from `generation_fallback`. | GitHub connector plus UTF-8 thread-aware review inspection; focused ESLint; 45/45 targeted Vitest tests; TypeScript; offline RAG 36 fixtures and 277/277 contract tests; `git diff --check`. |
| 2026-07-14 | PR #632 / codex/rag-performance-followups | 07cac8f4e094bf4b5ccd264feb6420fbd4e35e2b | review-followup | CodeRabbit's APP 1/5 governance contradiction was confirmed and corrected; Railway's pending DPA and Singapore processor basis are now explicit checklist/status items. The optional cache-miss granularity suggestion was not adopted because it would undo the reviewed single-read cold-miss design or require a broader schema/RPC change. | GitHub review-thread inspection; focused Prettier and `git diff --check` passed. Local production-readiness inspection reported the expected missing provider env; the Railway production-context check had already passed on this workstream. |
| 2026-07-14 | PR #632 / codex/rag-performance-followups | 0c792b8c10516c85d18832fc96562dd70a671b5f | review-followup | One P1 privacy-disclosure defect was confirmed: OpenAI retrieval embedding can receive query text even when answer synthesis remains source-only. Fixed the PIA and public `/privacy` copy to distinguish retrieval-embedding egress from model-backed synthesis egress, with focused copy coverage. | GitHub connector review-thread inspection; focused privacy UI test, ESLint, TypeScript, Prettier, production-readiness, and `git diff --check`. |
| 2026-07-14 | PR #632 / codex/rag-performance-followups | a2eb6db0efbef983e1b3242261d5cc6b2b9d839d | review-followup | One late P2 rollout-compatibility defect was confirmed: the provider-fallback SLO would omit recent rows written before `provider_generation_degraded` existed. Fixed the count predicate to include the new flag or legacy `generation_fallback:` reasons while continuing to exclude intentional extractive routes. | GitHub connector review-thread inspection; focused answer-SLO test, ESLint, TypeScript, Prettier, and `git diff --check`. |
| 2026-07-14 | PR #634 / codex/global-answer-reliability | 588c34c3d455c367e6aa38dc9fce64191678631b | review-followup | One late P2 quota-bypass defect was confirmed: streamed full-document summaries consumed only the general answer quota. Fixed the route to enforce the stricter `document_summarize` quota before starting the stream or provider work while retaining the general answer ceiling. | GitHub connector review-thread inspection; focused private-access route suite 116/116; ESLint; TypeScript; Prettier; `git diff --check`. |
| 2026-07-14 | codex/specifiers-design | c3e7024e15d2157bbc0b989276324cc6ad3eea5c | Specifiers UI, clinical decision-support, accessibility, and release-readiness review | One P2 WCAG contrast defect was reproduced and fixed across the builder, comparison, and map accent eyebrows. No remaining high-confidence defect was found in the changed scope; residual risk is clinical/manual governance of the original specifier summaries. | Focused Vitest 18/18; focused Chromium desktop/mobile 2/2 with serious/critical axe WCAG A/AA scanning and overflow checks; `npm run check:production-readiness:ci` READY; `npm run verify:cheap` 2,210 passed/1 skipped; `npm run verify:pr-local` 2,213 passed/1 skipped plus production build and client-bundle secret scan; `git diff --check`. Full advisory `verify:ui` exceeded the local 10-minute execution window; provider-backed checks were not run. |
| 2026-07-14 | PR #633 / codex/specifiers-design | 03daca3bfdf86517b9956f3c7d91be27d9f1a751 | Review follow-up and failed UI regression | Eight distinct P2 behaviors across nine review threads were confirmed and fixed: initial selection normalization, duplicate query removal, clinical applicability mapping, canonical Specifiers routing, severity-neutral base wording, diagnostic-section ordering, base/specifier compatibility, and severe psychotic-features wording. The failed app-menu keyboard test was a stale order assertion and now covers the inserted Specifiers item. | Focused Vitest 6/6; focused Chromium 4/4; scoped ESLint and TypeScript; CI-mode production readiness READY; production build and client-bundle secret scan passed. Hosted required checks passed on the refreshed `main` merge before the final compatibility fixes; provider-backed Supabase/OpenAI checks were not run. |
| 2026-07-14 | PR #634 / codex/global-answer-reliability | b411329ec5f181661e5d49276c398440aa928fa2 | review-followup | One late P2 fast-context defect was confirmed: Australian tier ordering could push a higher-ranked supplementary passage outside the four-chunk routine fast budget. Fixed by preserving the retrieval-ranked, crowding-capped candidate budget before applying the order-only Australian preference within that set. | GitHub connector review-thread inspection; focused RAG context-budget suite 22/22; ESLint; TypeScript; Prettier; `git diff --check`. |
90 changes: 22 additions & 68 deletions src/app/api/answer/route.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,20 +16,19 @@ import { buildSmartRagApiPlan } from "@/lib/smart-rag-api";
import { clinicalQueryModeSchema, queryClassForClinicalMode, queryForClinicalMode } from "@/lib/clinical-query-mode";
import { resolveSearchScope, searchScopeFiltersSchema } from "@/lib/search-scope";
import { resolveRetrievalAccessScope } from "@/lib/owner-scope";
import {
hasDangerSourceGovernanceWarning,
sourceGovernanceRefusalAnswer,
sourceGovernanceWarnings,
} from "@/lib/source-governance";
import { sourceGovernanceWarnings } from "@/lib/source-governance";
import { parseJsonBody } from "@/lib/validation/body";
import { toClientAnswerPayload } from "@/lib/answer-client-payload";
import {
answerDegradedModeSignal,
buildGovernedAnswerClientResponse,
buildGovernedDemoAnswerClientResponse,
} from "@/lib/answer-response";
import { answerServerTimingEntries, buildServerTimingHeader } from "@/lib/server-timing";
import { createAdminClient } from "@/lib/supabase/admin";
import { captureServerException } from "@/lib/observability/error-capture";
import { logAnswerDiagnostics } from "@/lib/answer-telemetry";
import { nonProductionSupabaseDemoFallbackReason } from "@/lib/supabase/errors";
import * as serverAuth from "@/lib/supabase/auth";
import type { RagAnswer } from "@/lib/types";
import { answerFeedbackMetadata } from "@/lib/answer-feedback-token";

export const runtime = "nodejs";
Expand All@@ -46,15 +45,6 @@ type AnswerRequestBody = z.infer<typeof answerSchema>;
const emptyScopeAnswer =
"The selected filters did not match any indexed documents, so I cannot generate an answer for that scope.";

function answerDegradedModeSignal(answer?: Pick<RagAnswer, "degradedMode" | "answerQualityTier" | "fallbackReason">) {
if (answer?.degradedMode) return answer.degradedMode;
const active = answer?.answerQualityTier === "source_only";
return {
active,
reason: active ? (answer?.fallbackReason ?? "source_only") : null,
};
}

function buildDemoAnswerPayload(body: AnswerRequestBody, fallbackReason?: string) {
const answer = demoAnswer(body.query, body.documentId, body.documentIds);
const answerFocusQuery = queryForClinicalMode(body.query, body.queryMode);
Expand All@@ -65,14 +55,14 @@ function buildDemoAnswerPayload(body: AnswerRequestBody, fallbackReason?: string
routeMode: answer.routingMode,
retrievalStrategy: "hybrid",
});
return {
...answer,
responseMode: smartApiPlan.displayMode,
smartApiPlan,
demoMode: true,
degradedMode: fallbackReason ? { active: true, reason: fallbackReason } : answerDegradedModeSignal(answer),
...(fallbackReason ? { fallbackMode: "non_production_demo", fallbackReason } : {}),
};
return buildGovernedDemoAnswerClientResponse(
{
...answer,
responseMode: smartApiPlan.displayMode,
smartApiPlan,
},
fallbackReason,
);
}

export async function POST(request: Request) {
Expand DownExpand Up@@ -137,59 +127,23 @@ export async function POST(request: Request) {
queryMode: answerBody.queryMode,
signal: request.signal,
});
const warnings = sourceGovernanceWarnings({
results: answer.sources ?? [],
relevance: answer.relevance ?? answer.smartPanel?.relevance ?? null,
const governedResponse = buildGovernedAnswerClientResponse(answer);
logAnswerDiagnostics({
supabase,
query: answerBody.query,
ownerId: access.ownerId,
answer: governedResponse.telemetryAnswer,
});
const shouldUseSourceGovernanceRefusal =
answer.grounded !== false && answer.confidence !== "unsupported" && answer.responseMode !== "evidence_gap";
if (shouldUseSourceGovernanceRefusal && hasDangerSourceGovernanceWarning(warnings)) {
// Build the refusal explicitly — never spread ...answer here, or the original
// (refused) sources/smartPanel/smartApiPlan would still reach the client and
// defeat the refusal. Keep only the safe "unsupported" contract fields, matching
// the empty-scope branch above.
void logAnswerDiagnostics({
supabase,
query: answerBody.query,
ownerId: access.ownerId,
answer: {
...answer,
grounded: false,
confidence: "unsupported",
sources: [],
responseMode: "evidence_gap",
fallbackReason: "source_governance_refusal",
routingReason: [answer.routingReason, "source_governance_refusal"].filter(Boolean).join("; "),
},
});
return NextResponse.json({
answer: sourceGovernanceRefusalAnswer,
grounded: false,
confidence: "unsupported",
citations: [],
sources: [],
degradedMode: answerDegradedModeSignal(answer),
scope: { ...scope, queryMode: answerBody.queryMode },
sourceGovernanceWarnings: warnings,
...answerFeedbackMetadata(interactionId, sourceGovernanceRefusalAnswer),
});
}

logAnswerDiagnostics({ supabase, query: answerBody.query, ownerId: access.ownerId, answer });

// Durations only — see server-timing.ts for the trust-boundary constraint.
const serverTiming = buildServerTimingHeader(
answerServerTimingEntries(answer.latencyTimings, Date.now() - routeStartedAt),
);
return NextResponse.json(
{
// Boundary trim only — governance warnings and diagnostics above
// consumed the full answer (see answer-client-payload.ts).
...toClientAnswerPayload(answer),
degradedMode: answerDegradedModeSignal(answer),
...governedResponse.payload,
scope: { ...scope, queryMode: answerBody.queryMode },
sourceGovernanceWarnings: warnings,
...answerFeedbackMetadata(interactionId, answer.answer),
...answerFeedbackMetadata(interactionId, governedResponse.payload.answer),
},
serverTiming ? { headers: { "Server-Timing": serverTiming } } : undefined,
);
Expand Down
Loading