fix(web): count only training events for discrimination and split user-stop from validated range
Three collected events with a reserved holdout were stalling because the discriminator door counted holdout. Public selection_allowed still had snapshot fallbacks, and health only proved the image SHA. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,6 +1,14 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { getTruthSourceRuntimeIdentity } from "@/lib/truth-source-runtime-identity";
|
||||
import { loadLanguageModelCatalog } from "@/lib/model-catalog";
|
||||
import {
|
||||
databaseHealthFromFilenames,
|
||||
RECTIFICATION_CONTRACT_VERSION,
|
||||
REQUIRED_RECTIFICATION_MIGRATIONS,
|
||||
type DatabaseHealth,
|
||||
} from "@/lib/health-database-contract";
|
||||
|
||||
export const runtime = "nodejs";
|
||||
|
||||
type Check = {
|
||||
status: "ok" | "degraded" | "blocked";
|
||||
@@ -42,6 +50,56 @@ async function jyotishApiCheck(): Promise<Check> {
|
||||
}
|
||||
}
|
||||
|
||||
async function rectificationMigrationCheck(): Promise<{
|
||||
check: Check;
|
||||
database: DatabaseHealth;
|
||||
}> {
|
||||
const empty: DatabaseHealth = {
|
||||
latestMigration: null,
|
||||
rectificationContractVersion: RECTIFICATION_CONTRACT_VERSION,
|
||||
requiredMigrationsPresent: false,
|
||||
missingMigrations: [...REQUIRED_RECTIFICATION_MIGRATIONS],
|
||||
};
|
||||
if (process.env.AUTH_PROVIDER?.trim() !== "self-hosted") {
|
||||
return { check: { status: "ok", message: "skipped_non_local" }, database: empty };
|
||||
}
|
||||
const url = process.env.APP_DATABASE_URL?.trim();
|
||||
if (!url) {
|
||||
return { check: { status: "blocked", message: "missing:APP_DATABASE_URL" }, database: empty };
|
||||
}
|
||||
const started = Date.now();
|
||||
const { Client } = await import("pg");
|
||||
const client = new Client({ connectionString: url, connectionTimeoutMillis: 2000 });
|
||||
try {
|
||||
await client.connect();
|
||||
const result = await client.query<{ filename: string }>(
|
||||
"select filename from migration.schema_migrations order by filename",
|
||||
);
|
||||
const database = databaseHealthFromFilenames(result.rows.map((row) => row.filename));
|
||||
return {
|
||||
check: database.requiredMigrationsPresent
|
||||
? { status: "ok", latencyMs: Date.now() - started }
|
||||
: {
|
||||
status: "blocked",
|
||||
message: `missing_migrations:${database.missingMigrations.join(",")}`,
|
||||
latencyMs: Date.now() - started,
|
||||
},
|
||||
database,
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
check: {
|
||||
status: "blocked",
|
||||
message: error instanceof Error ? error.name : "database_migration_query_failed",
|
||||
latencyMs: Date.now() - started,
|
||||
},
|
||||
database: empty,
|
||||
};
|
||||
} finally {
|
||||
await client.end().catch(() => undefined);
|
||||
}
|
||||
}
|
||||
|
||||
async function modelCatalogCheck(): Promise<Check> {
|
||||
const catalog = await loadLanguageModelCatalog();
|
||||
const defaults = catalog.models.filter((model) => model.isDefault && model.id === catalog.defaultModelId);
|
||||
@@ -74,12 +132,14 @@ export async function GET() {
|
||||
supabasePublicConfig: envCheck(["NEXT_PUBLIC_SUPABASE_URL", "NEXT_PUBLIC_SUPABASE_ANON_KEY"]),
|
||||
supabaseServiceRole: envCheck(["SUPABASE_SERVICE_ROLE_KEY"]),
|
||||
};
|
||||
const migrations = await rectificationMigrationCheck();
|
||||
const checks = {
|
||||
web: { status: "ok" } satisfies Check,
|
||||
...databaseChecks,
|
||||
modelProviderEncryption: envCheck(["MODEL_PROVIDER_CONFIG_ENCRYPTION_KEY"]),
|
||||
modelCatalog: await modelCatalogCheck(),
|
||||
jyotishApi: await jyotishApiCheck(),
|
||||
rectificationMigrations: migrations.check,
|
||||
researchTruthSource: {
|
||||
status: truthSourceIdentity.status,
|
||||
message: truthSourceIdentity.mountStatus === "mounted" ? undefined : truthSourceIdentity.mountStatus,
|
||||
@@ -93,6 +153,11 @@ export async function GET() {
|
||||
deployment: {
|
||||
gitCommit,
|
||||
},
|
||||
database: {
|
||||
latestMigration: migrations.database.latestMigration,
|
||||
rectificationContractVersion: migrations.database.rectificationContractVersion,
|
||||
requiredMigrationsPresent: migrations.database.requiredMigrationsPresent,
|
||||
},
|
||||
truthSource: truthSourceIdentity,
|
||||
checks,
|
||||
},
|
||||
|
||||
@@ -3,6 +3,7 @@ import { z } from "zod";
|
||||
import { createAdminSupabaseClient } from "@/lib/supabase/admin";
|
||||
import { createServerSupabaseClient } from "@/lib/supabase/server";
|
||||
import {
|
||||
evidenceLedgerFingerprint,
|
||||
loadV9CaseDossier,
|
||||
loadV9CaseSkillIdentityStatus,
|
||||
loadV9TurnReceipt,
|
||||
@@ -10,8 +11,9 @@ import {
|
||||
RectificationToolServiceError,
|
||||
type V9CaseDossier,
|
||||
} from "@/lib/rectification-agentic/v9/tool-service";
|
||||
import { choiceCardFromCaseDossier } from "@/lib/rectification-agentic/v9/interview-state";
|
||||
import { choiceCardFromCaseDossier, decideFromDossier, overlayPublicDecision } from "@/lib/rectification-agentic/v9/interview-state";
|
||||
import { previousInferenceFromReceipt } from "@/lib/rectification-agentic/v9/inference-adapter";
|
||||
import { publicDecisionFields } from "@/lib/rectification-agentic/core/rectification-decision";
|
||||
|
||||
export const runtime = "nodejs";
|
||||
|
||||
@@ -83,6 +85,9 @@ function dossierResponse(
|
||||
receipts: Array<Awaited<ReturnType<typeof loadV9TurnReceipt>>>,
|
||||
skillIdentity: Awaited<ReturnType<typeof loadV9CaseSkillIdentityStatus>>,
|
||||
) {
|
||||
const decision = decideFromDossier(dossier, {
|
||||
currentEvidenceFingerprint: evidenceLedgerFingerprint(dossier.evidence),
|
||||
});
|
||||
return {
|
||||
case: {
|
||||
case_id: dossier.case.caseId,
|
||||
@@ -109,7 +114,8 @@ function dossierResponse(
|
||||
receipt: turnReceipt(turn.id, receipts),
|
||||
})),
|
||||
evidence: dossier.evidence,
|
||||
latest_result: dossier.latestResult,
|
||||
latest_result: dossier.latestResult ? overlayPublicDecision(dossier.latestResult, decision) : null,
|
||||
interview: publicDecisionFields(decision),
|
||||
choice_card: choiceCardFromCaseDossier(dossier),
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user