diff --git a/components/pandora/RetrievalEvalCard.tsx b/components/pandora/RetrievalEvalCard.tsx
new file mode 100644
index 0000000..fc10e70
--- /dev/null
+++ b/components/pandora/RetrievalEvalCard.tsx
@@ -0,0 +1,2 @@
+import type { RetrievalEvalSummary } from "./types";
+export function RetrievalEvalCard({ evalSummary }: { evalSummary: RetrievalEvalSummary }) { return
Retrieval eval
Status: {evalSummary.status === "not_run" ? "Not run" : evalSummary.status}
{evalSummary.resultLabel}Source: {evalSummary.source}Latest run: {evalSummary.latestRunId ?? "None"}Run at: {evalSummary.latestRunAt ?? "None"}{evalSummary.realResultAvailable ? "Real eval/log row displayed" : "No score displayed without evidence"}
{evalSummary.warnings.map((warning) => {warning}
)}; }
diff --git a/components/pandora/Sidebar.tsx b/components/pandora/Sidebar.tsx
index 8bb5278..8e0fbc8 100644
--- a/components/pandora/Sidebar.tsx
+++ b/components/pandora/Sidebar.tsx
@@ -1,5 +1,5 @@
import { Activity, Brain, Circle, FolderKanban, Gauge, History, ListChecks, Settings, Users } from "lucide-react";
-import { navItems } from "./mock-data";
+import { navItems } from "./nav-items";
const icons = [Gauge, History, FolderKanban, Brain, ListChecks, Users, FolderKanban, Activity, Settings];
diff --git a/components/pandora/VerificationConsoleCard.tsx b/components/pandora/VerificationConsoleCard.tsx
new file mode 100644
index 0000000..7c10854
--- /dev/null
+++ b/components/pandora/VerificationConsoleCard.tsx
@@ -0,0 +1,9 @@
+import { AuditEvidenceCard } from "./AuditEvidenceCard";
+import { NamespaceInvariantCard } from "./NamespaceInvariantCard";
+import { PackSupersessionCard } from "./PackSupersessionCard";
+import { RetrievalEvalCard } from "./RetrievalEvalCard";
+import type { PandoraVerificationData } from "./types";
+
+export function VerificationConsoleCard({ verification }: { verification: PandoraVerificationData }) {
+ return
Operator Verification Console
Memory health evidence
Read-only verification for master packs, namespace separation, retrieval eval status, context-pack distillation audit evidence, and smoke evidence.
Read-onlyNo unsafe actions{verification.status}
{verification.warnings.length ? Verification warnings
Evidence gaps are not green
{verification.warnings.map((warning) => {warning})}
: null};
+}
diff --git a/components/pandora/mock-data.ts b/components/pandora/mock-data.ts
index aa0bab0..ce76719 100644
--- a/components/pandora/mock-data.ts
+++ b/components/pandora/mock-data.ts
@@ -16,6 +16,6 @@ export const workQueue: WorkQueueData = { needsReview: 0, openLoops: 0, stalePac
export const timelineEvents: TimelineEventData[] = [{ id: "fixture", color: "slate", title: "Fixture", time: "No live data", desc: "Mock only", namespace: "real_life" }];
export const coreSystems: SystemRow[] = [{ label: "Fixture", value: "No live data", state: "idle" }];
export const gatedSystems: SystemRow[] = [{ label: "Semantic retrieval", value: "Gated", state: "gated" }];
-export const fixtureDashboardData: PandoraDashboardData = { generatedAt: "No live data", operatorLabel: "Fixture", live: false, warnings: ["Mock only"], hero: { title: "Fixture dashboard", description: "Mock only: no live data.", primaryAction: "No live data", secondaryAction: "Semantic gated" }, evidence: "No live data", stats: [{ id: "fixture", title: "Fixture", value: "No live data", subtitle: "Mock only", color: "slate", sparklineData: [0, 0] }], memorySpaces, workQueue, profileSnapshot, timelineEvents, diagnostics: { coreSystems, gatedSystems, envelope: { title: "Fixture", description: "Mock only: no live data." } } };
-export const navItems = ["Dashboard", "Memory Feed", "Context Packs", "Adaptive Profiles", "Open Loops", "People", "Projects", "Retrieval Tests", "Settings"] as const;
-export const mobileNavItems = ["Dashboard", "Memory Feed", "Queue", "Profiles", "More"];
+const verification = { generatedAt: "No live data", status: "not_run" as const, namespaces: [], packSupersession: { status: "not_run" as const, namespaces: [], warnings: ["Mock only"] }, retrievalEval: { status: "not_run" as const, source: "fixture", latestRunId: null, latestRunAt: null, resultLabel: "Not run", realResultAvailable: false, warnings: ["Mock only"] }, auditEvidence: [], smokeEvidence: { status: "not_run" as const, latest: null, warnings: ["Mock only"] }, invariantStatus: { exactlyOneActiveMasterPerNamespace: "not_run" as const, noCrossNamespacePackMixing: "not_run" as const, noDuplicateActiveMaster: "not_run" as const, retrievalEvalHasNoFabricatedScore: "pass" as const, smokeEvidence: "not_run" as const }, warnings: ["Mock only"] };
+export const fixtureDashboardData: PandoraDashboardData = { generatedAt: "No live data", operatorLabel: "Fixture", live: false, warnings: ["Mock only"], hero: { title: "Fixture dashboard", description: "Mock only: no live data.", primaryAction: "No live data", secondaryAction: "Semantic gated" }, evidence: "No live data", stats: [{ id: "fixture", title: "Fixture", value: "No live data", subtitle: "Mock only", color: "slate", sparklineData: [0, 0] }], memorySpaces, workQueue, profileSnapshot, timelineEvents, diagnostics: { coreSystems, gatedSystems, envelope: { title: "Fixture", description: "Mock only: no live data." } }, verification };
+
diff --git a/components/pandora/nav-items.ts b/components/pandora/nav-items.ts
new file mode 100644
index 0000000..3dfbaa0
--- /dev/null
+++ b/components/pandora/nav-items.ts
@@ -0,0 +1,2 @@
+export const navItems = ["Dashboard", "Memory Feed", "Context Packs", "Adaptive Profiles", "Open Loops", "People", "Projects", "Retrieval Tests", "Settings"] as const;
+export const mobileNavItems = ["Dashboard", "Memory Feed", "Queue", "Profiles", "More"];
diff --git a/components/pandora/types.ts b/components/pandora/types.ts
index 17ab35c..b0134f9 100644
--- a/components/pandora/types.ts
+++ b/components/pandora/types.ts
@@ -68,6 +68,79 @@ export type ProfileSnapshot = {
evidence: string;
};
+export type VerificationStatus = "pass" | "warning" | "fail" | "not_run";
+export type PandoraNamespace = "real_life" | "au";
+
+export type PackMetadata = {
+ id: string;
+ namespace: PandoraNamespace;
+ packType: string;
+ status: string;
+ title: string;
+ createdAt: string;
+ updatedAt?: string;
+ supersededAt?: string;
+};
+
+export type NamespaceVerificationSummary = {
+ namespace: PandoraNamespace;
+ status: VerificationStatus;
+ activeMasterCount: number;
+ archivedMasterCount: number;
+ newestActiveMaster: PackMetadata | null;
+ previousArchivedMaster: PackMetadata | null;
+ duplicateActiveMasterIds: string[];
+ warnings: string[];
+};
+
+export type PackSupersessionSummary = {
+ status: VerificationStatus;
+ namespaces: NamespaceVerificationSummary[];
+ warnings: string[];
+};
+
+export type RetrievalEvalSummary = {
+ status: VerificationStatus;
+ source: string;
+ latestRunId: string | null;
+ latestRunAt: string | null;
+ resultLabel: string;
+ realResultAvailable: boolean;
+ warnings: string[];
+};
+
+export type AuditEvidenceItem = {
+ id: string;
+ action: string;
+ namespace: PandoraNamespace | "unknown";
+ recordId: string;
+ createdAt: string;
+};
+
+export type SmokeEvidenceSummary = {
+ status: VerificationStatus;
+ latest: AuditEvidenceItem | null;
+ warnings: string[];
+};
+
+export type PandoraVerificationData = {
+ generatedAt: string;
+ status: VerificationStatus;
+ namespaces: NamespaceVerificationSummary[];
+ packSupersession: PackSupersessionSummary;
+ retrievalEval: RetrievalEvalSummary;
+ auditEvidence: AuditEvidenceItem[];
+ smokeEvidence: SmokeEvidenceSummary;
+ invariantStatus: {
+ exactlyOneActiveMasterPerNamespace: VerificationStatus;
+ noCrossNamespacePackMixing: VerificationStatus;
+ noDuplicateActiveMaster: VerificationStatus;
+ retrievalEvalHasNoFabricatedScore: VerificationStatus;
+ smokeEvidence: VerificationStatus;
+ };
+ warnings: string[];
+};
+
export type PandoraDashboardData = {
generatedAt: string;
operatorLabel: string;
@@ -93,4 +166,5 @@ export type PandoraDashboardData = {
description: string;
};
};
+ verification: PandoraVerificationData;
};
diff --git a/docs/pandora-verification-console.md b/docs/pandora-verification-console.md
new file mode 100644
index 0000000..1fc8a0b
--- /dev/null
+++ b/docs/pandora-verification-console.md
@@ -0,0 +1,44 @@
+# Pandora Operator Verification Console
+
+## What is live
+
+`/pandora` remains an authenticated operator dashboard. The verification console adds read-only server-side checks for the authenticated Supabase user only:
+
+- active and archived/superseded `memory_context_packs` master-pack counts per namespace;
+- newest active master pack metadata and previous archived/superseded master-pack metadata;
+- recent `memory_context_pack_distilled` audit evidence from `audit_logs`;
+- retrieval-log/eval evidence when a real row exists;
+- smoke evidence when a real audit row exists.
+
+The loader fails safe: missing or unreadable tables become warnings and empty evidence states, not green success.
+
+## What remains gated
+
+The console does not enable model calls, embeddings, semantic retrieval, GPT Actions, MCP, public reads, public persistence, destructive actions, production ingest writes, protected non-dry-run jobs, or pruning application/archive/delete behavior.
+
+## Status meanings
+
+- `pass`: real rows support the invariant or evidence claim.
+- `warning`: the dashboard rendered safely, but evidence is incomplete or a table was unavailable.
+- `fail`: an invariant is violated, such as duplicate active master packs.
+- `not_run`: no real evidence was returned, so the console makes no success claim.
+
+## Why retrieval eval must not show fake accuracy
+
+Retrieval status is only shown from real persisted evidence. If no retrieval eval/log row exists, the console says `Not run`. It must not display placeholder percentages or marketing copy because that would falsely imply retrieval quality has been measured.
+
+## Why smoke evidence is read-only
+
+Smoke evidence is an audit proof surface. The dashboard only reads audit rows and never starts a smoke test, writes proof rows, mutates memory, or marks a smoke check as successful without persisted evidence.
+
+## Manual Supabase verification
+
+When needed, verify with authenticated, user-scoped SQL or table views:
+
+1. Check `memory_context_packs` filtered by `user_id`, `namespace`, `pack_type = 'master'`, and `status`.
+2. Confirm exactly one active master pack for `real_life` and exactly one for `au`.
+3. Confirm archived/superseded previous master packs exist when supersession has happened.
+4. Check `audit_logs` for `action = 'memory_context_pack_distilled'` and smoke/proof actions.
+5. Check retrieval evidence tables/logs only if a real eval has been run.
+
+Do not use service-role browser code or client-supplied user IDs for this verification.
diff --git a/lib/services/pandora-dashboard-service.ts b/lib/services/pandora-dashboard-service.ts
index d8cbb12..a7ec8ad 100644
--- a/lib/services/pandora-dashboard-service.ts
+++ b/lib/services/pandora-dashboard-service.ts
@@ -1,5 +1,6 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import type { PandoraDashboardData } from "@/components/pandora/types";
+import { loadPandoraVerificationData } from "@/lib/services/pandora-verification-service";
export type PandoraDashboardDbClient = { from: (table: string) => any };
type Namespace = "real_life" | "au";
@@ -36,6 +37,7 @@ function eventSummary(event: Row) {
export async function loadPandoraDashboardData(client: PandoraDashboardDbClient, input: { userId: string; operatorLabel?: string }): Promise
{
const warnings: string[] = [];
+ const verification = await loadPandoraVerificationData(client, { userId: input.userId });
const data = await Promise.all(namespaces.map(async (namespace) => ({
namespace,
events: await rows(client, "memory_events", input.userId, namespace, warnings, 500),
@@ -61,7 +63,7 @@ export async function loadPandoraDashboardData(client: PandoraDashboardDbClient,
generatedAt: new Date().toISOString(),
operatorLabel: input.operatorLabel ?? input.userId,
live: warnings.length === 0,
- warnings,
+ warnings: Array.from(new Set([...warnings, ...verification.warnings])),
hero: { title: "Pandora dashboard is reading live memory state.", description: "This route renders authenticated Supabase data for memory state while semantic retrieval, embeddings, model calls, GPT Actions, and MCP remain gated.", primaryAction: "Context pack data live", secondaryAction: "Retrieval eval Gated" },
evidence: warnings.length ? "Live dashboard read completed with safe empty states for unavailable tables." : "Live dashboard read complete from server-derived session scope.",
stats: [
@@ -82,5 +84,6 @@ export async function loadPandoraDashboardData(client: PandoraDashboardDbClient,
profileSnapshot: { name: profile?.title ?? "No active profile", status: profile ? "Live read" : "No live data", confidencePercent: confidence.percent, confidenceLabel: confidence.label, summary: profile?.summary ?? "No active adaptive profile returned for this session.", lastRefreshed: profile?.updated_at ?? "No profile timestamp returned", traits: ["Authenticated", "RLS scoped"], evidence: profile?.id ? `Live profile row ${profile.id}` : "No active profile row" },
timelineEvents: events.slice(0, 6).map((event) => ({ id: String(event.id ?? `${event.namespace}-${event.created_at ?? "event"}`), title: `${event.namespace} • ${event.status ?? "unknown"}`, time: event.created_at ?? "Live read", desc: eventSummary(event), namespace: event.namespace === "au" ? "au" : "real_life", color: event.namespace === "au" ? "purple" : "emerald" })),
diagnostics: { coreSystems: [{ label: "Route exposure", value: "Auth gated", state: "healthy" }, { label: "Displayed data", value: warnings.length ? "Partial live reads" : "Live reads", state: warnings.length ? "attention" : "healthy" }, { label: "Master-pack invariant", value: duplicates ? `${duplicates} duplicate` : "OK", state: duplicates ? "attention" : "healthy" }, { label: "Client user_id", value: "Rejected", state: "healthy" }], gatedSystems: [{ label: "Semantic retrieval", value: "Gated Off", state: "gated" }, { label: "Embeddings", value: "Gated Off", state: "gated" }, { label: "Model calls", value: "Gated Off", state: "gated" }, { label: "Pruning automation", value: "Review-only", state: "gated" }], envelope: { title: "Dashboard Truth Envelope", description: warnings.length ? "Unavailable reads were converted to warnings and empty UI state." : "Live loader completed from authenticated Supabase reads." } },
+ verification,
};
}
diff --git a/lib/services/pandora-verification-service.ts b/lib/services/pandora-verification-service.ts
new file mode 100644
index 0000000..586b80a
--- /dev/null
+++ b/lib/services/pandora-verification-service.ts
@@ -0,0 +1,120 @@
+/* eslint-disable @typescript-eslint/no-explicit-any */
+import type { AuditEvidenceItem, NamespaceVerificationSummary, PackMetadata, PandoraNamespace, PandoraVerificationData, RetrievalEvalSummary, VerificationStatus } from "@/components/pandora/types";
+
+export type PandoraVerificationDbClient = { from: (table: string) => any };
+type Row = Record;
+const namespaces: PandoraNamespace[] = ["real_life", "au"];
+const archivedStatuses = new Set(["archived", "superseded"]);
+
+async function readRows(client: PandoraVerificationDbClient, table: string, userId: string, warnings: string[], namespace?: PandoraNamespace, limit = 100): Promise {
+ try {
+ let query = client.from(table).select("*").eq("user_id", userId);
+ if (namespace) query = query.eq("namespace", namespace);
+ const result = await query.order("created_at", { ascending: false }).limit(limit);
+ if (result.error) {
+ warnings.push(`${table}${namespace ? `/${namespace}` : ""} read unavailable; verification shows safe empty state.`);
+ return [];
+ }
+ return Array.isArray(result.data) ? result.data : [];
+ } catch {
+ warnings.push(`${table}${namespace ? `/${namespace}` : ""} read unavailable; verification shows safe empty state.`);
+ return [];
+ }
+}
+
+function asNamespace(value: unknown): PandoraNamespace | "unknown" {
+ return value === "real_life" || value === "au" ? value : "unknown";
+}
+
+function packMeta(row: Row | undefined): PackMetadata | null {
+ if (!row) return null;
+ const namespace = asNamespace(row.namespace);
+ if (namespace === "unknown") return null;
+ return {
+ id: String(row.id ?? "unknown"),
+ namespace,
+ packType: String(row.pack_type ?? "unknown"),
+ status: String(row.status ?? "unknown"),
+ title: String(row.title ?? row.id ?? "Untitled pack"),
+ createdAt: String(row.created_at ?? "No created_at returned"),
+ updatedAt: row.updated_at ? String(row.updated_at) : undefined,
+ supersededAt: row.superseded_at ? String(row.superseded_at) : undefined,
+ };
+}
+
+function worst(statuses: VerificationStatus[]): VerificationStatus {
+ if (statuses.includes("fail")) return "fail";
+ if (statuses.includes("warning")) return "warning";
+ if (statuses.includes("not_run")) return "not_run";
+ return "pass";
+}
+
+function summarizeNamespace(namespace: PandoraNamespace, packs: Row[]): NamespaceVerificationSummary {
+ const scoped = packs.filter((pack) => pack.namespace === namespace && pack.pack_type === "master");
+ const active = scoped.filter((pack) => pack.status === "active");
+ const archived = scoped.filter((pack) => archivedStatuses.has(String(pack.status ?? "")));
+ const warnings: string[] = [];
+ if (active.length === 0) warnings.push(`No active master pack returned for ${namespace}.`);
+ if (active.length > 1) warnings.push(`${namespace} has ${active.length} active master packs; supersession needs review.`);
+ if (archived.length === 0) warnings.push(`No previous archived/superseded master pack evidence returned for ${namespace}.`);
+ return {
+ namespace,
+ status: active.length === 1 ? (archived.length > 0 ? "pass" : "warning") : "fail",
+ activeMasterCount: active.length,
+ archivedMasterCount: archived.length,
+ newestActiveMaster: packMeta(active[0]),
+ previousArchivedMaster: packMeta(archived[0]),
+ duplicateActiveMasterIds: active.slice(1).map((pack) => String(pack.id ?? "unknown")),
+ warnings,
+ };
+}
+
+function auditItem(row: Row): AuditEvidenceItem {
+ return { id: String(row.id ?? "unknown"), action: String(row.action ?? "unknown"), namespace: asNamespace(row.namespace), recordId: String(row.record_id ?? row.recordId ?? "unknown"), createdAt: String(row.created_at ?? "No created_at returned") };
+}
+
+function retrievalSummary(rows: Row[], warnings: string[]): RetrievalEvalSummary {
+ if (warnings.some((warning) => warning.includes("retrieval_logs read unavailable"))) {
+ return { status: "not_run", source: "retrieval_logs", latestRunId: null, latestRunAt: null, resultLabel: "Unavailable", realResultAvailable: false, warnings: ["Retrieval eval source could not be read; no score is shown."] };
+ }
+ const latest = rows[0];
+ if (!latest) return { status: "not_run", source: "retrieval_logs", latestRunId: null, latestRunAt: null, resultLabel: "Not run", realResultAvailable: false, warnings: ["No retrieval eval/log rows returned for this operator."] };
+ const label = latest.eval_result ?? latest.result ?? latest.status ?? latest.retrieval_service ?? "Real retrieval log row present; no score column returned";
+ return { status: "pass", source: "retrieval_logs", latestRunId: String(latest.id ?? "unknown"), latestRunAt: String(latest.created_at ?? "No created_at returned"), resultLabel: String(label), realResultAvailable: true, warnings: [] };
+}
+
+export async function loadPandoraVerificationData(client: PandoraVerificationDbClient, input: { userId: string }): Promise {
+ const warnings: string[] = [];
+ const [packRowsByNamespace, auditRows, retrievalRows] = await Promise.all([
+ Promise.all(namespaces.map((namespace) => readRows(client, "memory_context_packs", input.userId, warnings, namespace, 100))),
+ readRows(client, "audit_logs", input.userId, warnings, undefined, 50),
+ readRows(client, "retrieval_logs", input.userId, warnings, undefined, 25),
+ ]);
+ const packs = packRowsByNamespace.flat().filter((pack) => namespaces.includes(pack.namespace));
+ const namespaceSummaries = namespaces.map((namespace) => summarizeNamespace(namespace, packs));
+ const crossNamespaceRows = packRowsByNamespace.flat().filter((pack) => pack.namespace !== "real_life" && pack.namespace !== "au");
+ if (crossNamespaceRows.length) warnings.push("Unreadable or unexpected pack namespace values were excluded from verification.");
+ const distillAudit = auditRows.filter((row) => row.action === "memory_context_pack_distilled").map(auditItem).slice(0, 10);
+ const smokeRows = auditRows.filter((row) => ["first_live_append_proof_executed", "live_one_reviewed_item_executed", "operator_smoke_test_passed"].includes(String(row.action ?? ""))).map(auditItem);
+ if (distillAudit.length === 0) warnings.push("No memory_context_pack_distilled audit evidence returned.");
+ if (smokeRows.length === 0) warnings.push("No smoke evidence audit rows returned; smoke status is not_run.");
+ const retrievalEval = retrievalSummary(retrievalRows, warnings);
+ const duplicateCount = namespaceSummaries.reduce((sum, item) => sum + item.duplicateActiveMasterIds.length, 0);
+ const exactlyOne = namespaceSummaries.every((item) => item.activeMasterCount === 1) ? "pass" : "fail";
+ const noDuplicates = duplicateCount === 0 ? "pass" : "fail";
+ const noCross = crossNamespaceRows.length === 0 ? "pass" : "fail";
+ const smokeEvidence = { status: smokeRows.length ? "pass" as const : "not_run" as const, latest: smokeRows[0] ?? null, warnings: smokeRows.length ? [] : ["No smoke evidence exists for this operator session scope."] };
+ const packStatus = worst(namespaceSummaries.map((item) => item.status));
+ const status = worst([packStatus, retrievalEval.status, smokeEvidence.status, warnings.length ? "warning" : "pass"]);
+ return {
+ generatedAt: new Date().toISOString(),
+ status,
+ namespaces: namespaceSummaries,
+ packSupersession: { status: packStatus, namespaces: namespaceSummaries, warnings: namespaceSummaries.flatMap((item) => item.warnings) },
+ retrievalEval,
+ auditEvidence: distillAudit,
+ smokeEvidence,
+ invariantStatus: { exactlyOneActiveMasterPerNamespace: exactlyOne, noCrossNamespacePackMixing: noCross, noDuplicateActiveMaster: noDuplicates, retrievalEvalHasNoFabricatedScore: "pass", smokeEvidence: smokeEvidence.status },
+ warnings: Array.from(new Set([...warnings, ...retrievalEval.warnings, ...smokeEvidence.warnings])),
+ };
+}
diff --git a/tests/unit/pandora-dashboard-guard.test.ts b/tests/unit/pandora-dashboard-guard.test.ts
index b11921d..b93baf8 100644
--- a/tests/unit/pandora-dashboard-guard.test.ts
+++ b/tests/unit/pandora-dashboard-guard.test.ts
@@ -1,7 +1,7 @@
import { readFileSync } from "node:fs";
import { describe, expect, it } from "vitest";
-const productionFiles = ["app/pandora/page.tsx", "components/pandora/PandoraDashboard.tsx"];
+const productionFiles = ["app/pandora/page.tsx", "components/pandora/PandoraDashboard.tsx", "components/pandora/Sidebar.tsx", "components/pandora/MobileBottomNav.tsx"];
describe("Pandora production dashboard guards", () => {
it("does not import mock data from the route or dashboard shell", () => {
@@ -10,17 +10,24 @@ describe("Pandora production dashboard guards", () => {
it("does not accept user_id query params or props for dashboard loading", () => {
const page = readFileSync("app/pandora/page.tsx", "utf8");
+ const dashboard = readFileSync("components/pandora/PandoraDashboard.tsx", "utf8");
expect(page).not.toMatch(/searchParams/);
- expect(page).not.toMatch(/searchParams.*user_id|searchParams.*userId|query.*user_id|query.*userId/s);
+ expect(`${page}\n${dashboard}`).not.toMatch(/searchParams\.user_id|searchParams\.userId|query\.user_id|query\.userId|body\.user_id|body\.userId|props\.userId/);
expect(page).toContain("session.session.userId");
});
it("does not ship fake accuracy claims in production dashboard code", () => {
- const files = ["app/pandora/page.tsx", "components/pandora/PandoraDashboard.tsx", "components/pandora/StatCard.tsx", "components/pandora/DiagnosticsCard.tsx", "lib/services/pandora-dashboard-service.ts"];
+ const files = ["app/pandora/page.tsx", "components/pandora/PandoraDashboard.tsx", "components/pandora/StatCard.tsx", "components/pandora/DiagnosticsCard.tsx", "components/pandora/VerificationConsoleCard.tsx", "components/pandora/RetrievalEvalCard.tsx", "lib/services/pandora-dashboard-service.ts", "lib/services/pandora-verification-service.ts"];
for (const file of files) {
const source = readFileSync(file, "utf8");
expect(source).not.toContain("94.3");
expect(source).not.toMatch(/retrieval accuracy/i);
}
});
+
+ it("verification loader remains read-only and service-role-free", () => {
+ const source = readFileSync("lib/services/pandora-verification-service.ts", "utf8");
+ expect(source).not.toMatch(/insert\(|update\(|delete\(|upsert\(|rpc\(/);
+ expect(source).not.toMatch(/service-role|serviceRole|SUPABASE_SERVICE_ROLE|createAdmin/i);
+ });
});
diff --git a/tests/unit/pandora-dashboard-ui.test.tsx b/tests/unit/pandora-dashboard-ui.test.tsx
index dd66fdb..7b57d9b 100644
--- a/tests/unit/pandora-dashboard-ui.test.tsx
+++ b/tests/unit/pandora-dashboard-ui.test.tsx
@@ -4,6 +4,22 @@ import { describe, expect, it } from "vitest";
import { PandoraDashboard } from "@/components/pandora/PandoraDashboard";
import type { PandoraDashboardData } from "@/components/pandora/types";
+
+const verification = {
+ generatedAt: "2026-07-03T00:00:00Z",
+ status: "warning" as const,
+ namespaces: [
+ { namespace: "real_life" as const, status: "pass" as const, activeMasterCount: 1, archivedMasterCount: 1, newestActiveMaster: { id: "rl-pack", namespace: "real_life" as const, packType: "master", status: "active", title: "real", createdAt: "now" }, previousArchivedMaster: { id: "rl-old", namespace: "real_life" as const, packType: "master", status: "archived", title: "old", createdAt: "before" }, duplicateActiveMasterIds: [], warnings: [] },
+ { namespace: "au" as const, status: "warning" as const, activeMasterCount: 1, archivedMasterCount: 0, newestActiveMaster: { id: "au-pack", namespace: "au" as const, packType: "master", status: "active", title: "au", createdAt: "now" }, previousArchivedMaster: null, duplicateActiveMasterIds: [], warnings: ["No previous archived/superseded master pack evidence returned for au."] },
+ ],
+ packSupersession: { status: "warning" as const, namespaces: [], warnings: ["No previous archived/superseded master pack evidence returned for au."] },
+ retrievalEval: { status: "not_run" as const, source: "retrieval_logs", latestRunId: null, latestRunAt: null, resultLabel: "Not run", realResultAvailable: false, warnings: ["No retrieval eval/log rows returned for this operator."] },
+ auditEvidence: [],
+ smokeEvidence: { status: "not_run" as const, latest: null, warnings: ["No smoke evidence exists for this operator session scope."] },
+ invariantStatus: { exactlyOneActiveMasterPerNamespace: "pass" as const, noCrossNamespacePackMixing: "pass" as const, noDuplicateActiveMaster: "pass" as const, retrievalEvalHasNoFabricatedScore: "pass" as const, smokeEvidence: "not_run" as const },
+ warnings: ["visible warning"],
+};
+
const data: PandoraDashboardData = {
generatedAt: "2026-07-03T00:00:00Z",
operatorLabel: "operator@example.com",
@@ -17,6 +33,7 @@ const data: PandoraDashboardData = {
profileSnapshot: { name: "Operator", status: "Live read", confidencePercent: 77, confidenceLabel: "77%", summary: "Live profile", lastRefreshed: "now", traits: ["Authenticated"], evidence: "profile row" },
timelineEvents: [{ id: "event", title: "real_life • captured", time: "now", desc: "Live event summary", namespace: "real_life", color: "emerald" }],
diagnostics: { coreSystems: [{ label: "Displayed data", value: "Live reads", state: "healthy" }], gatedSystems: [{ label: "Semantic retrieval", value: "Gated Off", state: "gated" }], envelope: { title: "Dashboard Truth Envelope", description: "Live loader completed" } },
+ verification,
};
describe("PandoraDashboard", () => {
@@ -29,5 +46,8 @@ describe("PandoraDashboard", () => {
expect(html).toContain("operator@example.com");
expect(html).toContain("memory_profiles/au read unavailable");
expect(html).toContain("Gated Off");
+ expect(html).toContain("Operator Verification Console");
+ expect(html).toContain("Not run");
+ expect(html).toContain("visible warning");
});
});
diff --git a/tests/unit/pandora-verification-service.test.ts b/tests/unit/pandora-verification-service.test.ts
new file mode 100644
index 0000000..d772364
--- /dev/null
+++ b/tests/unit/pandora-verification-service.test.ts
@@ -0,0 +1,22 @@
+/* eslint-disable @typescript-eslint/no-explicit-any */
+import { describe, expect, it } from "vitest";
+import { loadPandoraVerificationData } from "@/lib/services/pandora-verification-service";
+
+type Row = Record;
+const USER = "user-1";
+const OTHER = "other-user";
+function makeClient(store: Record, failTables: string[] = [], ops: string[] = []) {
+ return { from(table: string) { if (failTables.includes(table)) throw new Error("missing"); let selected = [...(store[table] ?? [])]; const builder: any = { select() { return builder; }, eq(k: string, v: any) { selected = selected.filter((r) => r[k] === v); return builder; }, order(k: string) { selected = selected.sort((a,b)=>String(b[k]??"").localeCompare(String(a[k]??""))); return builder; }, limit(n: number) { selected = selected.slice(0,n); return builder; }, insert() { ops.push("insert"); return builder; }, update() { ops.push("update"); return builder; }, delete() { ops.push("delete"); return builder; }, upsert() { ops.push("upsert"); return builder; }, then(resolve: any, reject: any) { return Promise.resolve({ data: selected, error: null }).then(resolve, reject); } }; return builder; } } as any;
+}
+function pack(id: string, namespace: "real_life"|"au", status="active", user_id=USER): Row { return { id, user_id, namespace, pack_type: "master", status, title: id, created_at: id }; }
+function base() { return { memory_context_packs: [pack("rl-active", "real_life"), pack("rl-old", "real_life", "archived"), pack("au-active", "au"), pack("au-old", "au", "superseded"), pack("other", "real_life", "active", OTHER)], audit_logs: [{ id: "a1", user_id: USER, namespace: "real_life", action: "memory_context_pack_distilled", record_id: "rl-active", created_at: "2026-07-03T00:00:00Z" }, { id: "s1", user_id: USER, namespace: "real_life", action: "first_live_append_proof_executed", record_id: "m1", created_at: "2026-07-03T01:00:00Z" }, { id: "other-a", user_id: OTHER, namespace: "au", action: "memory_context_pack_distilled", record_id: "x", created_at: "x" }], retrieval_logs: [] }; }
+
+describe("loadPandoraVerificationData", () => {
+ it("passes exactly one active master per namespace and hides other users", async () => { const data = await loadPandoraVerificationData(makeClient(base()), { userId: USER }); expect(data.invariantStatus.exactlyOneActiveMasterPerNamespace).toBe("pass"); expect(JSON.stringify(data)).not.toContain(OTHER); });
+ it("fails duplicate active master in real_life", async () => { const s = base(); s.memory_context_packs.push(pack("rl-dup", "real_life")); const data = await loadPandoraVerificationData(makeClient(s), { userId: USER }); expect(data.namespaces.find((n)=>n.namespace==="real_life")?.status).toBe("fail"); expect(data.invariantStatus.noDuplicateActiveMaster).toBe("fail"); });
+ it("fails duplicate active master in au", async () => { const s = base(); s.memory_context_packs.push(pack("au-dup", "au")); const data = await loadPandoraVerificationData(makeClient(s), { userId: USER }); expect(data.namespaces.find((n)=>n.namespace==="au")?.status).toBe("fail"); expect(data.invariantStatus.noDuplicateActiveMaster).toBe("fail"); });
+ it("shows archived previous master and warns when missing", async () => { const data = await loadPandoraVerificationData(makeClient(base()), { userId: USER }); expect(data.namespaces[0].previousArchivedMaster?.id).toBe("rl-old"); const s = base(); s.memory_context_packs = s.memory_context_packs.filter((p)=>!(p.namespace==="au" && p.status!=="active")); const missing = await loadPandoraVerificationData(makeClient(s), { userId: USER }); expect(missing.namespaces.find((n)=>n.namespace==="au")?.status).toBe("warning"); });
+ it("marks retrieval eval missing as not_run and present as real", async () => { const missing = await loadPandoraVerificationData(makeClient(base()), { userId: USER }); expect(missing.retrievalEval.status).toBe("not_run"); const s = base(); s.retrieval_logs.push({ id: "r1", user_id: USER, namespace: "real_life", retrieval_service: "internal_eval", created_at: "2026-07-03" }); const present = await loadPandoraVerificationData(makeClient(s), { userId: USER }); expect(present.retrievalEval).toMatchObject({ status: "pass", latestRunId: "r1", realResultAvailable: true }); });
+ it("warns when audit or table reads are missing and never mutates", async () => { const ops: string[] = []; const data = await loadPandoraVerificationData(makeClient({ memory_context_packs: [] }, ["audit_logs"], ops), { userId: USER }); expect(data.warnings.length).toBeGreaterThan(0); expect(data.smokeEvidence.status).toBe("not_run"); expect(ops).toEqual([]); });
+ it("never mixes AU and real_life rows", async () => { const data = await loadPandoraVerificationData(makeClient(base()), { userId: USER }); expect(data.namespaces.find((n)=>n.namespace==="real_life")?.newestActiveMaster?.id).toBe("rl-active"); expect(data.namespaces.find((n)=>n.namespace==="au")?.newestActiveMaster?.id).toBe("au-active"); });
+});