import { bigint, boolean, index, integer, jsonb, pgTable, text, timestamp, uniqueIndex, uuid, } from "drizzle-orm/pg-core"; import { researchRuns } from "./runs.js"; export const researchSources = pgTable( "research_sources", { id: uuid("id").primaryKey().defaultRandom(), runId: uuid("run_id") .notNull() .references(() => researchRuns.id, { onDelete: "cascade" }), key: text("key").notNull(), kind: text("kind").notNull(), identifier: text("identifier").notNull(), title: text("title").notNull(), authors: jsonb("authors").$type().notNull().default([]), year: integer("year"), venue: text("venue"), url: text("url"), verified: boolean("verified").notNull().default(false), verifiedAt: timestamp("verified_at", { withTimezone: true }), verification: jsonb("verification").$type>().notNull().default({}), accessLevel: text("access_level").notNull().default("metadata"), }, (t) => [uniqueIndex("sources_run_key_uq").on(t.runId, t.key)], ); export const citations = pgTable( "citations", { id: uuid("id").primaryKey().defaultRandom(), runId: uuid("run_id") .notNull() .references(() => researchRuns.id, { onDelete: "cascade" }), claim: text("claim").notNull(), location: text("location"), kind: text("kind").notNull().default("literature"), sourceKeys: text("source_keys").array().notNull().default([]), artifactPaths: text("artifact_paths").array().notNull().default([]), }, (t) => [index("citations_run_idx").on(t.runId)], ); export const datasets = pgTable( "datasets", { id: uuid("id").primaryKey().defaultRandom(), runId: uuid("run_id") .notNull() .references(() => researchRuns.id, { onDelete: "cascade" }), name: text("name").notNull(), source: text("source").notNull(), url: text("url"), license: text("license").notNull(), acquiredAt: text("acquired_at").notNull(), sha256: text("sha256"), bytes: bigint("bytes", { mode: "number" }), synthetic: boolean("synthetic").notNull().default(false), transformations: text("transformations").array().notNull().default([]), notes: text("notes"), }, (t) => [index("datasets_run_idx").on(t.runId)], ); export const experimentRecords = pgTable( "experiment_records", { id: uuid("id").primaryKey().defaultRandom(), runId: uuid("run_id") .notNull() .references(() => researchRuns.id, { onDelete: "cascade" }), name: text("name").notNull(), command: text("command").notNull(), startedAt: text("started_at").notNull(), endedAt: text("ended_at").notNull(), exitCode: integer("exit_code").notNull(), seed: text("seed"), environment: jsonb("environment").$type>(), outputs: text("outputs").array().notNull().default([]), synthetic: boolean("synthetic").notNull().default(false), }, (t) => [index("experiments_run_idx").on(t.runId)], ); export const reviewFindings = pgTable( "review_findings", { id: uuid("id").primaryKey().defaultRandom(), runId: uuid("run_id") .notNull() .references(() => researchRuns.id, { onDelete: "cascade" }), round: integer("round").notNull(), findingKey: text("finding_key").notNull(), severity: text("severity").notNull(), category: text("category").notNull(), title: text("title").notNull(), detail: text("detail").notNull(), proposedTest: text("proposed_test"), resolution: text("resolution").notNull().default("open"), resolutionNote: text("resolution_note"), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), }, (t) => [uniqueIndex("review_findings_uq").on(t.runId, t.round, t.findingKey)], ); /** Every artifact of a run; immutable once written (new version = new row). */ export const artifacts = pgTable( "artifacts", { id: uuid("id").primaryKey().defaultRandom(), runId: uuid("run_id") .notNull() .references(() => researchRuns.id, { onDelete: "cascade" }), attemptId: uuid("attempt_id"), stage: text("stage").notNull(), path: text("path").notNull(), version: integer("version").notNull().default(1), kind: text("kind").notNull(), sha256: text("sha256").notNull(), bytes: bigint("bytes", { mode: "number" }).notNull(), contentType: text("content_type").notNull().default("application/octet-stream"), storageKey: text("storage_key").notNull(), visibility: text("visibility").notNull().default("private"), synthetic: boolean("synthetic").notNull().default(false), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), }, (t) => [ uniqueIndex("artifacts_run_path_version_uq").on(t.runId, t.path, t.version), index("artifacts_run_idx").on(t.runId), ], );