@marinoscar/kvox-eval 0.0.0-bootstrap → 0.1.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (245) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/LICENSE +21 -0
  3. package/README.md +166 -0
  4. package/dist/ask/index.d.ts +6 -0
  5. package/dist/ask/index.js +28 -0
  6. package/dist/ask/question-schema.d.ts +121 -0
  7. package/dist/ask/question-schema.js +167 -0
  8. package/dist/ask/report.d.ts +88 -0
  9. package/dist/ask/report.js +170 -0
  10. package/dist/ask/scorer.d.ts +104 -0
  11. package/dist/ask/scorer.js +164 -0
  12. package/dist/ask-run/ask-command.d.ts +62 -0
  13. package/dist/ask-run/ask-command.js +254 -0
  14. package/dist/ask-run/host/app.d.ts +65 -0
  15. package/dist/ask-run/host/app.js +146 -0
  16. package/dist/ask-run/host/db.d.ts +38 -0
  17. package/dist/ask-run/host/db.js +126 -0
  18. package/dist/ask-run/host/ports.d.ts +35 -0
  19. package/dist/ask-run/host/ports.js +113 -0
  20. package/dist/ask-run/index.d.ts +13 -0
  21. package/dist/ask-run/index.js +35 -0
  22. package/dist/ask-run/replay.d.ts +128 -0
  23. package/dist/ask-run/replay.js +212 -0
  24. package/dist/ask-run/run-ask-eval.d.ts +125 -0
  25. package/dist/ask-run/run-ask-eval.js +193 -0
  26. package/dist/ask-run/seed-golden-graph.d.ts +64 -0
  27. package/dist/ask-run/seed-golden-graph.js +495 -0
  28. package/dist/cli/index.d.ts +3 -0
  29. package/dist/cli/index.js +12 -0
  30. package/dist/cli/kg-command.d.ts +66 -0
  31. package/dist/cli/kg-command.js +238 -0
  32. package/dist/cli/main.d.ts +18 -0
  33. package/dist/cli/main.js +69 -0
  34. package/dist/fixtures/domains.d.ts +16 -0
  35. package/dist/fixtures/domains.js +33 -0
  36. package/dist/fixtures/fixture-schema.d.ts +323 -0
  37. package/dist/fixtures/fixture-schema.js +199 -0
  38. package/dist/fixtures/index.d.ts +16 -0
  39. package/dist/fixtures/index.js +40 -0
  40. package/dist/fixtures/load.d.ts +73 -0
  41. package/dist/fixtures/load.js +137 -0
  42. package/dist/fixtures/questions.d.ts +15 -0
  43. package/dist/fixtures/questions.js +26 -0
  44. package/dist/index.d.ts +20 -0
  45. package/dist/index.js +36 -0
  46. package/dist/kg/gold-runner.d.ts +13 -0
  47. package/dist/kg/gold-runner.js +57 -0
  48. package/dist/kg/index.d.ts +17 -0
  49. package/dist/kg/index.js +65 -0
  50. package/dist/kg/internals.d.ts +7 -0
  51. package/dist/kg/internals.js +17 -0
  52. package/dist/kg/prediction-schema.d.ts +245 -0
  53. package/dist/kg/prediction-schema.js +102 -0
  54. package/dist/kg/predictions.d.ts +11 -0
  55. package/dist/kg/predictions.js +49 -0
  56. package/dist/kg/report.d.ts +84 -0
  57. package/dist/kg/report.js +125 -0
  58. package/dist/kg/run-kg-eval.d.ts +77 -0
  59. package/dist/kg/run-kg-eval.js +137 -0
  60. package/dist/kg/runner.d.ts +72 -0
  61. package/dist/kg/runner.js +51 -0
  62. package/dist/kg/runners/extract-resolve-runner.d.ts +40 -0
  63. package/dist/kg/runners/extract-resolve-runner.js +199 -0
  64. package/dist/kg/runners/extract-runner.d.ts +65 -0
  65. package/dist/kg/runners/extract-runner.js +243 -0
  66. package/dist/kg/scorer.d.ts +226 -0
  67. package/dist/kg/scorer.js +463 -0
  68. package/dist/kg/targets.d.ts +17 -0
  69. package/dist/kg/targets.js +16 -0
  70. package/dist/kg/text.d.ts +45 -0
  71. package/dist/kg/text.js +100 -0
  72. package/dist/live/adapters.d.ts +16 -0
  73. package/dist/live/adapters.js +58 -0
  74. package/dist/live/env.d.ts +39 -0
  75. package/dist/live/env.js +56 -0
  76. package/dist/live/index.d.ts +6 -0
  77. package/dist/live/index.js +16 -0
  78. package/dist/live/live-ai.d.ts +104 -0
  79. package/dist/live/live-ai.js +157 -0
  80. package/dist/parity/constants.d.ts +79 -0
  81. package/dist/parity/constants.js +104 -0
  82. package/dist/parity/index.d.ts +20 -0
  83. package/dist/parity/index.js +38 -0
  84. package/dist/parity/internals.d.ts +8 -0
  85. package/dist/parity/internals.js +16 -0
  86. package/dist/parity/scenario.d.ts +45 -0
  87. package/dist/parity/scenario.js +245 -0
  88. package/dist/parity/script.d.ts +44 -0
  89. package/dist/parity/script.js +136 -0
  90. package/dist/parity/snapshot.d.ts +43 -0
  91. package/dist/parity/snapshot.js +71 -0
  92. package/dist/real-data/index.d.ts +2 -0
  93. package/dist/real-data/index.js +12 -0
  94. package/dist/real-data/real-data.d.ts +76 -0
  95. package/dist/real-data/real-data.js +156 -0
  96. package/fixtures/kg-golden/README.md +136 -0
  97. package/fixtures/kg-golden/ask-questions.json +458 -0
  98. package/fixtures/kg-golden/meetings/m01-northwind-pilot-kickoff.json +792 -0
  99. package/fixtures/kg-golden/meetings/m02-halden-migration-planning.json +814 -0
  100. package/fixtures/kg-golden/meetings/m03-larkspur-weekly-sync.json +601 -0
  101. package/fixtures/kg-golden/meetings/m04-corvid-intake-discovery.json +690 -0
  102. package/fixtures/kg-golden/meetings/m05-hosting-vendor-selection.json +631 -0
  103. package/fixtures/kg-golden/meetings/m06-northwind-floor-data-review.json +649 -0
  104. package/fixtures/kg-golden/meetings/m07-gullwing-intro-notes.json +428 -0
  105. package/fixtures/kg-golden/meetings/m08-halden-migration-checkpoint.json +672 -0
  106. package/fixtures/kg-golden/meetings/m09-northwind-platform-org-update.json +711 -0
  107. package/fixtures/kg-golden/meetings/m10-corvid-prototype-review.json +623 -0
  108. package/fixtures/kg-golden/meetings/m11-solvane-grid-dashboard-scoping.json +689 -0
  109. package/fixtures/kg-golden/meetings/m12-northwind-pilot-replan.json +681 -0
  110. package/fixtures/kg-golden/meetings/m13-halden-cutover-go-no-go.json +721 -0
  111. package/fixtures/kg-golden/meetings/m14-gullwing-discovery-readout.json +719 -0
  112. package/fixtures/kg-golden/meetings/m15-halden-handover-ravi-leaving.json +716 -0
  113. package/fixtures/kg-golden/meetings/m16-varden-claims-portal-intro.json +704 -0
  114. package/fixtures/kg-golden/meetings/m17-corvid-usability-debrief.json +572 -0
  115. package/fixtures/kg-golden/meetings/m18-hosting-decision-revisited.json +655 -0
  116. package/fixtures/kg-golden/meetings/m19-solvane-integration-kickoff.json +726 -0
  117. package/fixtures/kg-golden/meetings/m20-northwind-go-live-retro.json +673 -0
  118. package/fixtures/kg-golden/meetings/m21-quarterly-account-review.json +449 -0
  119. package/fixtures/kg-golden/meetings/m22-halden-intro-call-2020.json +558 -0
  120. package/fixtures/kg-golden/meetings/m23-gullwing-model-review.json +702 -0
  121. package/fixtures/kg-golden/meetings/m24-varden-discovery-midpoint.json +643 -0
  122. package/fixtures/kg-golden/meetings/m25-corvid-rollout-planning.json +642 -0
  123. package/fixtures/kg-golden/meetings/m26-larkspur-engineering-prep.json +695 -0
  124. package/fixtures/kg-golden/meetings/m27-solvane-phase-one-demo.json +649 -0
  125. package/fixtures/kg-golden/meetings/m28-northwind-building-5-scoping.json +715 -0
  126. package/fixtures/kg-golden/meetings/m29-halden-southern-cutover-review.json +752 -0
  127. package/fixtures/kg-golden/meetings/m30-varden-portal-build-kickoff.json +697 -0
  128. package/fixtures/kg-golden/meetings/m31-gullwing-rollout-renewal.json +681 -0
  129. package/fixtures/kg-golden/meetings/m32-brambleway-weekly-sync.json +472 -0
  130. package/fixtures/kg-golden/meetings/m33-nina-oliver-one-on-one.json +342 -0
  131. package/fixtures/kg-golden/meetings/m34-coffee-with-dana.json +249 -0
  132. package/fixtures/kg-golden/meetings/m35-brambleway-june-sync.json +553 -0
  133. package/fixtures/kg-golden/meetings/m36-copenhagen-conference-planning.json +296 -0
  134. package/host/generated/client.d.ts +1 -0
  135. package/host/generated/client.js +5 -0
  136. package/host/generated/default.d.ts +1 -0
  137. package/host/generated/default.js +5 -0
  138. package/host/generated/edge.d.ts +1 -0
  139. package/host/generated/edge.js +1658 -0
  140. package/host/generated/index-browser.js +1684 -0
  141. package/host/generated/index.d.ts +192335 -0
  142. package/host/generated/index.js +1658 -0
  143. package/host/generated/package.json +139 -0
  144. package/host/generated/query_compiler_fast_bg.js +2 -0
  145. package/host/generated/query_compiler_fast_bg.wasm +0 -0
  146. package/host/generated/query_compiler_fast_bg.wasm-base64.js +2 -0
  147. package/host/generated/runtime/client.d.ts +3433 -0
  148. package/host/generated/runtime/client.js +110 -0
  149. package/host/generated/runtime/index-browser.d.ts +90 -0
  150. package/host/generated/runtime/index-browser.js +6 -0
  151. package/host/generated/runtime/wasm-compiler-edge.js +100 -0
  152. package/host/generated/schema.prisma +6312 -0
  153. package/host/generated/wasm-edge-light-loader.mjs +5 -0
  154. package/host/generated/wasm-worker-loader.mjs +5 -0
  155. package/host/prisma/fragments/kvox.ask.prisma +126 -0
  156. package/host/prisma/fragments/kvox.graph.prisma +1073 -0
  157. package/host/prisma/fragments/kvox.notes.prisma +787 -0
  158. package/host/prisma/fragments/kvox.search.prisma +211 -0
  159. package/host/prisma/fragments/kvox.transcripts.prisma +790 -0
  160. package/host/prisma/kvox.lock +101 -0
  161. package/host/prisma/migrations/20240101000000_initial/migration.sql +297 -0
  162. package/host/prisma/migrations/20240101000001_add_personal_access_tokens/migration.sql +31 -0
  163. package/host/prisma/migrations/20240101000002_add_credentials/migration.sql +20 -0
  164. package/host/prisma/migrations/20240101000003_add_notification_deliveries/migration.sql +27 -0
  165. package/host/prisma/migrations/20240101000004_drop_stale_uuid_defaults/migration.sql +35 -0
  166. package/host/prisma/migrations/20240101000005_add_notifications/migration.sql +22 -0
  167. package/host/prisma/migrations/20240101000006_add_push_subscriptions/migration.sql +25 -0
  168. package/host/prisma/migrations/20240101000007_add_jobs/migration.sql +110 -0
  169. package/host/prisma/migrations/20240101000008_add_worker_nodes/migration.sql +90 -0
  170. package/host/prisma/migrations/20240101000009_add_database_backup_runs/migration.sql +104 -0
  171. package/host/prisma/migrations/20240101000010_add_notification_broadcasts/migration.sql +57 -0
  172. package/host/prisma/migrations/20240101000011_add_backup_run_job_link/migration.sql +87 -0
  173. package/host/prisma/migrations/20240101000012_add_job_node_secrets/migration.sql +61 -0
  174. package/host/prisma/migrations/20240101000013_add_backup_run_pg_dump_version/migration.sql +26 -0
  175. package/host/prisma/migrations/20240101000014_add_job_claim_token/migration.sql +92 -0
  176. package/host/prisma/migrations/20240101000015_add_ai_platform/migration.sql +108 -0
  177. package/host/prisma/migrations/20240101000016_revoke_viewer_ai_use/migration.sql +32 -0
  178. package/host/prisma/migrations/20240101000017_add_user_credentials/migration.sql +29 -0
  179. package/host/prisma/migrations/20240101000018_add_device_session_credential_link/migration.sql +52 -0
  180. package/host/prisma/migrations/20240101000019_add_worker_node_vitals/migration.sql +3 -0
  181. package/host/prisma/migrations/20240101000020_add_job_trace_context/migration.sql +6 -0
  182. package/host/prisma/migrations/20240101000021_add_retention_created_at_indexes/migration.sql +13 -0
  183. package/host/prisma/migrations/20240101000022_add_organizations/migration.sql +142 -0
  184. package/host/prisma/migrations/20240101000023_split_system_org_roles/migration.sql +131 -0
  185. package/host/prisma/migrations/20240101000024_org_scoped_rls/migration.sql +215 -0
  186. package/host/prisma/migrations/20240101000025_add_groups/migration.sql +165 -0
  187. package/host/prisma/migrations/20240101000026_add_grants/migration.sql +117 -0
  188. package/host/prisma/migrations/20240101000027_add_org_settings/migration.sql +49 -0
  189. package/host/prisma/migrations/20240101000028_add_org_credentials/migration.sql +54 -0
  190. package/host/prisma/migrations/20240101000029_add_jobs_org_id/migration.sql +18 -0
  191. package/host/prisma/migrations/20240101000030_add_jobs_org_id_status_index/migration.sql +6 -0
  192. package/host/prisma/migrations/20240101000031_add_broadcast_target_org/migration.sql +21 -0
  193. package/host/prisma/migrations/20240101000032_add_android_app/migration.sql +60 -0
  194. package/host/prisma/migrations/20240101000033_open_job_reason/migration.sql +16 -0
  195. package/host/prisma/migrations/20240101000034_ai_usage_feature/migration.sql +37 -0
  196. package/host/prisma/migrations/20240101000035_add_app_metadata/migration.sql +49 -0
  197. package/host/prisma/migrations/20240101000036_open_sharing_vocabularies/migration.sql +97 -0
  198. package/host/prisma/migrations/20260914130000_kvox_add_transcripts/migration.sql +322 -0
  199. package/host/prisma/migrations/20260914140000_kvox_add_notes/migration.sql +311 -0
  200. package/host/prisma/migrations/20260915120000_kvox_add_search_vectors/migration.sql +150 -0
  201. package/host/prisma/migrations/20260915130000_kvox_add_search_embeddings/migration.sql +362 -0
  202. package/host/prisma/migrations/20260915210000_kvox_add_note_title_source/migration.sql +30 -0
  203. package/host/prisma/migrations/20260923120000_kvox_add_note_generation_context_snapshot/migration.sql +24 -0
  204. package/host/prisma/migrations/20260923130000_kvox_add_user_hidden_note_templates/migration.sql +35 -0
  205. package/host/prisma/migrations/20260923140000_kvox_add_transcript_speaker_identities/migration.sql +6 -0
  206. package/host/prisma/migrations/20260923150000_kvox_transcript_name_checks/migration.sql +95 -0
  207. package/host/prisma/migrations/20260923160000_kvox_add_note_body_format/migration.sql +27 -0
  208. package/host/prisma/migrations/20260923170000_kvox_add_note_version_body_format/migration.sql +23 -0
  209. package/host/prisma/migrations/20260926012548_kvox_add_knowledge_graph/migration.sql +680 -0
  210. package/host/prisma/migrations/20260926030000_kvox_fix_kg_relations_valid_precision_chk/migration.sql +29 -0
  211. package/host/prisma/migrations/20260926030100_kvox_add_transcript_recorded_at/migration.sql +9 -0
  212. package/host/prisma/migrations/20260926030200_kvox_kg_evidence_invariant/migration.sql +60 -0
  213. package/host/prisma/migrations/20260926040000_kvox_add_kg_graph_layouts/migration.sql +30 -0
  214. package/host/prisma/migrations/20260926050000_kvox_add_ask_conversations/migration.sql +99 -0
  215. package/host/prisma/migrations/20260926231512_kvox_add_kg_exports/migration.sql +52 -0
  216. package/host/prisma/migrations/20261016120000_kvox_transcripts_org_id/migration.sql +49 -0
  217. package/host/prisma/platform.lock +319 -0
  218. package/host/prisma/schema/app.kvox.ask.prisma +110 -0
  219. package/host/prisma/schema/app.kvox.graph.prisma +1030 -0
  220. package/host/prisma/schema/app.kvox.notes.prisma +746 -0
  221. package/host/prisma/schema/app.kvox.search.prisma +208 -0
  222. package/host/prisma/schema/app.kvox.transcripts.prisma +726 -0
  223. package/host/prisma/schema/platform.ai.prisma +419 -0
  224. package/host/prisma/schema/platform.android-app.prisma +46 -0
  225. package/host/prisma/schema/platform.base.prisma +15 -0
  226. package/host/prisma/schema/platform.credentials.prisma +156 -0
  227. package/host/prisma/schema/platform.db-backup.prisma +359 -0
  228. package/host/prisma/schema/platform.identity.prisma +638 -0
  229. package/host/prisma/schema/platform.jobs.prisma +824 -0
  230. package/host/prisma/schema/platform.notifications.prisma +641 -0
  231. package/host/prisma/schema/platform.settings.prisma +53 -0
  232. package/host/prisma/schema/platform.sharing.prisma +208 -0
  233. package/host/prisma/schema/platform.storage.prisma +118 -0
  234. package/package.json +112 -1
  235. package/parity/requests.ask.json +2681 -0
  236. package/parity/requests.m01.json +1554 -0
  237. package/parity/requests.m02.json +1554 -0
  238. package/parity/requests.m03.json +1554 -0
  239. package/parity/requests.m04.json +1554 -0
  240. package/parity/requests.m05.json +1554 -0
  241. package/parity/requests.m06.json +1554 -0
  242. package/parity/requests.m07.json +1554 -0
  243. package/parity/requests.m08.json +1554 -0
  244. package/parity/requests.m09.json +1554 -0
  245. package/parity/requests.m10.json +1554 -0
@@ -0,0 +1,211 @@
1
+ // GENERATED by kvox-db sync — do not edit
2
+ // source: @marinoscar/kvox-db:schema/kvox.search.prisma
3
+
4
+ // =============================================================================
5
+ // Semantic search: pgvector storage (issue #181, epic #165)
6
+ // =============================================================================
7
+ //
8
+ // Layer 2 of search, sitting beside layer 1's generated `tsvector` columns
9
+ // (`20260915120000_add_search_vectors`): MEANING-based retrieval over the
10
+ // same transcript/note content, via vectors an AI embedding model produces.
11
+ // This is storage only — no embedding call, no chunking pipeline, lives in
12
+ // this schema; that is later issues in epic #165. The full argument for
13
+ // every decision below (the `vector(1536)` width contract, why
14
+ // `document_id` carries no foreign key, HNSW vs. IVFFlat, the
15
+ // `vector_cosine_ops` opclass, why embeddings are not a column on the
16
+ // document row, content addressing via `content_hash`, and why `status` is
17
+ // a Prisma enum while `document_type`/`reason` stay plain text) is in the
18
+ // header of `20260915130000_add_search_embeddings/migration.sql` — read that
19
+ // first; this comment only orients the three models against each other.
20
+ // =============================================================================
21
+
22
+ enum SearchIndexStatus {
23
+ pending
24
+ indexing
25
+ indexed
26
+ failed
27
+ skipped
28
+ }
29
+ // One row per chunk of a document's text (issue #181). `documentType` +
30
+ // `documentId` is a polymorphic reference with NO foreign key in either
31
+ // direction — the same precedent `Job.subjectType`/`subjectId` sets (see the
32
+ // block comment above `model Job`) and for the identical reason: the set of
33
+ // searchable document types is open-ended and code-owned. See the migration
34
+ // header's point 2 for the cost of that choice (an orphan row is possible)
35
+ // and who owes the sweep (the deleting document's own `transcript.purge` /
36
+ // `note.purge` handler, wired by a later issue).
37
+ model SearchChunk {
38
+ id String @id @default(uuid()) @db.Uuid
39
+
40
+ documentType String @map("document_type")
41
+ documentId String @map("document_id") @db.Uuid
42
+
43
+ // Position among this document's chunks. Together with
44
+ // (documentType, documentId) this is the natural key — see the unique
45
+ // index below.
46
+ ordinal Int
47
+
48
+ text String
49
+
50
+ // sha256 of this chunk's FINAL text — the content-addressing key. See the
51
+ // migration header's point 6: re-indexing an edited document only needs to
52
+ // re-embed the chunks whose hash actually changed, and the bill for that
53
+ // is the document owner's own vendor account.
54
+ contentHash String @map("content_hash")
55
+
56
+ // Character offsets into the document's source text, so a search result's
57
+ // snippet can be built directly from this row without re-locating the
58
+ // chunk inside the document. See the migration header's point 5 for why
59
+ // this lives on its own row rather than as a column on the document.
60
+ charStart Int @map("char_start")
61
+ charEnd Int @map("char_end")
62
+
63
+ createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz
64
+
65
+ embeddings SearchEmbedding[]
66
+
67
+ // One chunk per position per document — the natural key a re-chunk
68
+ // upserts against.
69
+ @@unique([documentType, documentId, ordinal])
70
+ // The lookup every read of "this document's chunks" uses.
71
+ @@index([documentType, documentId])
72
+ // The content-addressing lookup the migration header's point 6 argues for.
73
+ @@index([contentHash])
74
+ @@map("search_chunks")
75
+ }
76
+ // One (chunk, model) embedding vector (issue #181). `chunkId` IS a real
77
+ // foreign key — unlike `SearchChunk.documentId` above, it points INSIDE this
78
+ // same module's own table, not sideways into another module's — and
79
+ // CASCADES: an embedding with no chunk left to belong to means nothing.
80
+ //
81
+ // ⚠ `embedding` is `Unsupported("vector(1536)")`, and it is REQUIRED, not
82
+ // optional — unlike the FTS `tsvector` columns in the sibling migration,
83
+ // which are database-GENERATED and so Prisma must never attempt to write
84
+ // them. This column is the opposite: application code writes it, on every
85
+ // insert, with no database-side generation at all. A REQUIRED `Unsupported`
86
+ // field makes `prisma.searchEmbedding.create(...)` (and every other
87
+ // generated-client write) UNCREATABLE for this model — the generated client
88
+ // has no way to construct a value for an unsupported type, so every write to
89
+ // this table MUST go through raw SQL (`$queryRaw`/`$executeRaw`, building the
90
+ // vector literal by hand). That is correct and intended, not a limitation to
91
+ // route around: a `vector` literal has to be assembled as raw SQL regardless
92
+ // of what the client layer offers, because there is no TypeScript
93
+ // representation of a pgvector value the generated client could accept in
94
+ // the first place. See the migration header's points 1, 3, 4 and 6 for the
95
+ // width contract, the HNSW index choice, the `vector_cosine_ops` opclass,
96
+ // and why `UNIQUE (chunkId, model)` is what makes a repeat embed cheap.
97
+ model SearchEmbedding {
98
+ id String @id @default(uuid()) @db.Uuid
99
+
100
+ chunkId String @map("chunk_id") @db.Uuid
101
+
102
+ // Which embedding model produced this vector — a plain string, open-ended,
103
+ // exactly like `Job.type` and `Transcript.provider` elsewhere in this
104
+ // schema, so a new or changed model costs this table zero migrations.
105
+ model String
106
+
107
+ // Recorded fact about the row, kept even though the column type already
108
+ // enforces the real width constraint. See the migration header's point 1
109
+ // for why this is not redundant: it is what lets a future width migration
110
+ // tell old rows from new ones without re-deriving the width from the
111
+ // vector itself.
112
+ dimensions Int
113
+
114
+ // `vector(1536)` — see the block comment above the model for the whole
115
+ // "why Unsupported, why required, why raw SQL" argument, and the migration
116
+ // header's point 1 for why 1536 specifically is a CONTRACT with
117
+ // `AiProvider`'s `EMBEDDING_DIMENSIONS`, not a default.
118
+ // Written as `Unsupported("vector(1536)")` with the parentheses as \u0028/\u0029: the
119
+ // composer's field reader (platform-db 0.1.0-next.5) stops a type at the first `)`.
120
+ // Prisma decodes the escapes, so the column type is still vector(1536).
121
+ embedding Unsupported("vector\u00281536\u0029")
122
+
123
+ createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz
124
+
125
+ // ⚠ Cascade — this row has no meaning once its chunk is gone. See the
126
+ // header above the model.
127
+ chunk SearchChunk @relation(fields: [chunkId], references: [id], onDelete: Cascade)
128
+
129
+ // One vector per chunk per model — the natural key a re-embed upserts
130
+ // against, and the index the migration header's point 6 argues makes a
131
+ // repeat-embed check a single indexed lookup rather than a scan.
132
+ @@unique([chunkId, model])
133
+ // HAND-WRITTEN in migration.sql only — Prisma has no DSL for `USING hnsw`
134
+ // or for an index's operator class. See the migration header's
135
+ // "INTENTIONAL SCHEMA DRIFT" section (occurrence 5 of 5: `jobs`,
136
+ // `database_backup_runs`, `transcript_speakers`, this migration's own
137
+ // sibling's generated tsvector columns, and this). Do not "fix" this by
138
+ // inventing a Prisma-expressible substitute — there isn't one, and
139
+ // `prisma migrate dev`/`diff` must never be asked to reconcile this index
140
+ // away.
141
+ @@map("search_embeddings")
142
+ }
143
+ // One row per DOCUMENT (not chunk) — the legibility surface an owner or
144
+ // admin reads to answer "is this document semantically searchable, and if
145
+ // not, why not" (issue #181). `documentType`/`documentId` mirror
146
+ // `SearchChunk`'s polymorphic reference exactly, and for the identical
147
+ // reason (no foreign key, open-ended document types). `ownerId` IS a real
148
+ // foreign key into `users` and CASCADES: an index-state row for a document
149
+ // whose owner no longer exists means nothing, the same reasoning
150
+ // `Transcript.ownerId`/`Note.ownerId` already establish in this schema.
151
+ model SearchIndexState {
152
+ id String @id @default(uuid()) @db.Uuid
153
+
154
+ documentType String @map("document_type")
155
+ documentId String @map("document_id") @db.Uuid
156
+
157
+ ownerId String @map("owner_id") @db.Uuid
158
+
159
+ // A CLOSED set this application owns end to end — every value is written
160
+ // by code inside this repository, nothing external ever proposes a new
161
+ // one — so, unlike documentType/reason beside it, this IS a Prisma enum.
162
+ // See the migration header's "STATUS" section for the full three-way
163
+ // argument.
164
+ status SearchIndexStatus @default(pending)
165
+
166
+ // WHY this document is not (yet, or ever) semantically searchable —
167
+ // `ai_key_missing`, `ai_not_configured`, `dimension_mismatch`, … Plain
168
+ // TEXT and deliberately not an enum: it is a diagnostic string for a human
169
+ // debugging a stuck document, and it will grow new values as new failure
170
+ // modes are discovered. NULL outside of `failed`/`skipped` is itself
171
+ // informative.
172
+ reason String?
173
+
174
+ chunkCount Int @default(0) @map("chunk_count")
175
+
176
+ // Which embedding model produced the current chunk set, so a later change
177
+ // to the deployment's active model can be detected against rows indexed
178
+ // under an earlier one.
179
+ model String?
180
+
181
+ // The per-document hash "has this document's content changed since it was
182
+ // last indexed" is checked against — one comparison, not a full re-chunk,
183
+ // to decide whether a re-index has anything to do at all.
184
+ contentFingerprint String? @map("content_fingerprint")
185
+
186
+ lastError String? @map("last_error")
187
+
188
+ indexedAt DateTime? @map("indexed_at") @db.Timestamptz
189
+ createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz
190
+ updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz
191
+
192
+ // ⚠ Cascade. See the block comment above the model.
193
+ owner User @relation("SearchIndexStateOwner", fields: [ownerId], references: [id], onDelete: Cascade)
194
+
195
+ // One state row per document — the address every read/write of "this
196
+ // document's indexing status" uses.
197
+ @@unique([documentType, documentId])
198
+ // The `unindexedCount` query: "how many of this owner's documents are in
199
+ // state X".
200
+ @@index([ownerId, status])
201
+ @@map("search_index_state")
202
+ }
203
+
204
+ // Back-relations onto the platform's User (an `extend model` block holds back-relation fields only).
205
+ extend model User {
206
+ // Semantic search index state (issue #181, epic #165). ONE relation, and
207
+ // it CASCADES — an index-state row for a document owned by nobody means
208
+ // nothing, the identical reasoning `transcripts`/`notes` already apply to
209
+ // their own `ownerId`. See the block comment above `SearchIndexState`.
210
+ searchIndexStates SearchIndexState[] @relation("SearchIndexStateOwner")
211
+ }