import { pgTable, text, integer, bigserial, index, uniqueIndex, boolean, jsonb, real, timestamp } from 'drizzle-orm/pg-core'; import { ciId, createdAt, updatedAt } from './_common.js'; /** Knowledge graph edge with mandatory context and provenance (CLAUDE.md §28-29, §244). */ export const knowledgeEdges = pgTable( 'knowledge_edges', { id: bigserial('id', { mode: 'number' }).primaryKey(), sourceEntityType: text('source_entity_type').notNull(), // cancer | gene | variant | drug | biomarker | trial | publication | pathway | risk_factor sourceEntityId: text('source_entity_id').notNull(), targetEntityType: text('target_entity_type').notNull(), targetEntityId: text('target_entity_id').notNull(), relationshipType: text('relationship_type').notNull(), // HAS_SUBTYPE | OCCURS_IN | ASSOCIATED_WITH | HAS_VARIANT | HAS_BIOMARKER | TREATED_BY | STUDIED_IN | DESCRIBED_BY | TARGETS | APPROVED_FOR | INVESTIGATED_FOR | PREDICTS_RESPONSE_TO | CONFERS_RESISTANCE_TO | PREDISPOSES_TO | PROGNOSTIC_IN | DIAGNOSTIC_OF cancerContextIds: text('cancer_context_ids').array().notNull().default([]), predictive: boolean('predictive'), prognostic: boolean('prognostic'), diagnostic: boolean('diagnostic'), predisposing: boolean('predisposing'), direction: text('direction'), // supports | resistance | sensitivity | neutral | unknown evidenceLevel: text('evidence_level'), // source-native level (e.g. CIViC A-E) — never re-scaled silently evidenceScore: real('evidence_score'), evidenceCategory: text('evidence_category').notNull().default('curated_evidence'), // observed_data | published_evidence | curated_evidence | regulatory_status | clinical_guideline | computed_metric status: text('status').notNull().default('active'), // active | candidate | superseded | retracted_basis sourceId: ciId('source_id').notNull(), sourceRecordId: text('source_record_id'), provenanceIds: integer('provenance_ids').array().notNull().default([]), supportCount: integer('support_count').notNull().default(1), firstSeenAt: timestamp('first_seen_at', { withTimezone: true }).notNull().defaultNow(), lastSeenAt: timestamp('last_seen_at', { withTimezone: true }).notNull().defaultNow(), }, (t) => [ uniqueIndex('knowledge_edges_uq').on(t.sourceEntityType, t.sourceEntityId, t.targetEntityType, t.targetEntityId, t.relationshipType, t.sourceId, t.sourceRecordId), index('knowledge_edges_source_idx').on(t.sourceEntityType, t.sourceEntityId, t.relationshipType), index('knowledge_edges_target_idx').on(t.targetEntityType, t.targetEntityId, t.relationshipType), ], ); /** CIViC evidence items kept in their native structure (CLAUDE.md §10.9). */ export const civicEvidenceItems = pgTable( 'civic_evidence_items', { id: bigserial('id', { mode: 'number' }).primaryKey(), civicId: integer('civic_id').notNull(), name: text('name'), molecularProfileId: integer('molecular_profile_id'), molecularProfileName: text('molecular_profile_name'), geneSymbols: text('gene_symbols').array().notNull().default([]), geneIds: text('gene_ids').array().notNull().default([]), variantIds: text('variant_ids').array().notNull().default([]), civicVariantIds: integer('civic_variant_ids').array().notNull().default([]), diseaseName: text('disease_name'), doid: text('doid'), cancerId: ciId('cancer_id'), cancerMatchType: text('cancer_match_type'), therapyNames: text('therapy_names').array().notNull().default([]), therapyIds: text('therapy_ids').array().notNull().default([]), // CI-DRUG-… therapyInteractionType: text('therapy_interaction_type'), evidenceType: text('evidence_type'), // PREDICTIVE | PROGNOSTIC | DIAGNOSTIC | PREDISPOSING | ONCOGENIC | FUNCTIONAL evidenceLevel: text('evidence_level'), // A-E evidenceDirection: text('evidence_direction'), // SUPPORTS | DOES_NOT_SUPPORT significance: text('significance'), // SENSITIVITYRESPONSE | RESISTANCE | … evidenceRating: integer('evidence_rating'), status: text('status'), // ACCEPTED | SUBMITTED | REJECTED description: text('description'), pmid: text('pmid'), sourceCitation: text('source_citation'), phenotypes: text('phenotypes').array().notNull().default([]), provenanceId: integer('provenance_id').notNull(), ingestRunId: text('ingest_run_id'), updatedAt: updatedAt(), }, (t) => [uniqueIndex('civic_evidence_uq').on(t.civicId), index('civic_evidence_cancer_idx').on(t.cancerId), index('civic_evidence_gene_idx').on(t.geneSymbols)], ); /** Risk factors / carcinogens as first-class entities (CLAUDE.md §74, §133). */ export const riskFactors = pgTable( 'risk_factors', { id: bigserial('id', { mode: 'number' }).primaryKey(), slug: text('slug').notNull(), name: text('name').notNull(), kind: text('kind').notNull(), // behavioral | infectious | environmental | occupational | genetic | hormonal | demographic | carcinogen classificationAuthority: text('classification_authority'), classification: text('classification'), description: text('description'), createdAt: createdAt(), }, (t) => [uniqueIndex('risk_factors_slug_uq').on(t.slug)], );