spb/cancerindex
Public
TypeScript 97.2%
SQL 1.5%
CSS 0.6%
JavaScript 0.5%
1# CancerIndex — AI policy23Status: **not implemented in Phase 1.** No language model is called anywhere in the platform today;4the `ai_answers` and `entity_embeddings` tables exist so that the policy below can be enforced by the5schema when the feature ships (spec §62-66, §158-159, §322).67## Principles891. **Database-grounded only.** An AI answer may only state facts that exist as rows in the10 CancerIndex database at answer time (observations, curated evidence, approvals, trials,11 publications, computed metrics). The model receives those rows as context and is instructed to12 answer exclusively from them. Anything not in the database is answered with "CancerIndex has no13 data on this" — never with general knowledge.142. **Every claim cites.** Each sentence that carries a fact must reference the `CI-*` id (and15 provenance) of the row it comes from; the UI renders these as the same source badges used16 elsewhere. Answers without a resolvable citation are rejected before display.173. **The label is `ai_generated_synthesis`.** AI text is displayed with its own category and is18 never merged with observed, curated or regulatory content (safety labels, CLAUDE.md §3, §12).194. **No medical advice.** Questions asking for diagnosis, prognosis for a person, or treatment20 choice receive a fixed refusal with pointers to population statistics and to a clinician.21 Population survival is never phrased as an individual prediction (§325).225. **Reconciliation stays deterministic.** Models may only propose candidate mappings for the23 curation queue (`unresolved_labels.suggested_*`); they never create aliases, merge entities or24 write canonical data (CLAUDE.md §5).256. **Reproducibility.** Every answer is cached in `ai_answers` with `model`, `prompt_version`,26 `question_hash`, the `source_snapshot` (ids + values that were shown to the model) and27 `data_as_of`. A cached answer is invalidated when any referenced row changes (`change_events`).287. **Privacy.** Questions are not stored with user identity; API keys are never sent to a provider;29 provider calls are server-side only, with the provider recorded per answer.3031## Answer contract3233```json34{35 "kind": "cancer_summary | ask",36 "subjectId": "CI-CAN-00000364",37 "answer": {38 "text": "…",39 "claims": [{ "sentence": 0, "refs": ["epidemiology_observations:1234", "rankings:5678"] }],40 "refusals": [],41 "limitations": ["No survival data available for this entity (SEER awaiting credentials)."]42 },43 "model": "provider/model-id",44 "promptVersion": "ci-summary-v1",45 "sourceSnapshot": { "rows": ["…"] },46 "dataAsOf": "2026-09-08T06:30:00Z",47 "category": "ai_generated_synthesis"48}49```5051## Planned implementation (Phase 5)5253- Retrieval: SQL over canonical/derived tables first; pgvector (`entity_embeddings`, model recorded54 per row) only for entity discovery, never as a source of facts.55- Providers: optional `ANTHROPIC_API_KEY` / `OPENAI_API_KEY` / `OPENAI_BASE_URL`56 (`.env.example`); the platform works fully without them.57- Evaluation: a fixture set of questions with expected refusals and citations must pass before the58 feature is enabled in production.59