videobook-engine 2.0.1 → 5.0.1

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 (171) hide show
  1. package/README.md +99 -68
  2. package/dist/artifacts.d.ts +4 -9
  3. package/dist/artifacts.d.ts.map +1 -1
  4. package/dist/artifacts.js +78 -138
  5. package/dist/artifacts.js.map +1 -1
  6. package/dist/books.d.ts +1 -1
  7. package/dist/books.d.ts.map +1 -1
  8. package/dist/books.js +18 -10
  9. package/dist/books.js.map +1 -1
  10. package/dist/cas.d.ts +27 -1
  11. package/dist/cas.d.ts.map +1 -1
  12. package/dist/cas.js +78 -6
  13. package/dist/cas.js.map +1 -1
  14. package/dist/catalog-metadata.d.ts +56 -0
  15. package/dist/catalog-metadata.d.ts.map +1 -0
  16. package/dist/catalog-metadata.js +42 -0
  17. package/dist/catalog-metadata.js.map +1 -0
  18. package/dist/communications.js +4 -2
  19. package/dist/communications.js.map +1 -1
  20. package/dist/context.d.ts +9 -6
  21. package/dist/context.d.ts.map +1 -1
  22. package/dist/context.js +42 -51
  23. package/dist/context.js.map +1 -1
  24. package/dist/domain.d.ts +39 -2
  25. package/dist/domain.d.ts.map +1 -1
  26. package/dist/domain.js +846 -64
  27. package/dist/domain.js.map +1 -1
  28. package/dist/edit-policy.d.ts +3 -0
  29. package/dist/edit-policy.d.ts.map +1 -0
  30. package/dist/edit-policy.js +6 -0
  31. package/dist/edit-policy.js.map +1 -0
  32. package/dist/edits.d.ts +10 -0
  33. package/dist/edits.d.ts.map +1 -0
  34. package/dist/edits.js +1392 -0
  35. package/dist/edits.js.map +1 -0
  36. package/dist/engine-types.d.ts +171 -86
  37. package/dist/engine-types.d.ts.map +1 -1
  38. package/dist/engine-types.js +32 -0
  39. package/dist/engine-types.js.map +1 -1
  40. package/dist/engine.d.ts +89 -26
  41. package/dist/engine.d.ts.map +1 -1
  42. package/dist/engine.js +27 -21
  43. package/dist/engine.js.map +1 -1
  44. package/dist/files.d.ts.map +1 -1
  45. package/dist/files.js +32 -28
  46. package/dist/files.js.map +1 -1
  47. package/dist/fork.d.ts +148 -0
  48. package/dist/fork.d.ts.map +1 -0
  49. package/dist/fork.js +602 -0
  50. package/dist/fork.js.map +1 -0
  51. package/dist/generations.d.ts +9 -0
  52. package/dist/generations.d.ts.map +1 -0
  53. package/dist/generations.js +175 -0
  54. package/dist/generations.js.map +1 -0
  55. package/dist/history.d.ts +2 -5
  56. package/dist/history.d.ts.map +1 -1
  57. package/dist/history.js +183 -640
  58. package/dist/history.js.map +1 -1
  59. package/dist/index.d.ts +21 -7
  60. package/dist/index.d.ts.map +1 -1
  61. package/dist/index.js +15 -5
  62. package/dist/index.js.map +1 -1
  63. package/dist/job-queue.d.ts +2 -0
  64. package/dist/job-queue.d.ts.map +1 -1
  65. package/dist/job-queue.js +29 -2
  66. package/dist/job-queue.js.map +1 -1
  67. package/dist/media.d.ts +3 -3
  68. package/dist/media.d.ts.map +1 -1
  69. package/dist/media.js +6 -5
  70. package/dist/media.js.map +1 -1
  71. package/dist/merge-policy.d.ts +83 -0
  72. package/dist/merge-policy.d.ts.map +1 -0
  73. package/dist/merge-policy.js +203 -0
  74. package/dist/merge-policy.js.map +1 -0
  75. package/dist/metadata.d.ts.map +1 -1
  76. package/dist/metadata.js +17 -23
  77. package/dist/metadata.js.map +1 -1
  78. package/dist/migration.d.ts +9 -0
  79. package/dist/migration.d.ts.map +1 -0
  80. package/dist/migration.js +564 -0
  81. package/dist/migration.js.map +1 -0
  82. package/dist/mvp-contract-fixtures.d.ts +244 -0
  83. package/dist/mvp-contract-fixtures.d.ts.map +1 -0
  84. package/dist/mvp-contract-fixtures.js +556 -0
  85. package/dist/mvp-contract-fixtures.js.map +1 -0
  86. package/dist/mvp-contracts.d.ts +761 -0
  87. package/dist/mvp-contracts.d.ts.map +1 -0
  88. package/dist/mvp-contracts.js +59 -0
  89. package/dist/mvp-contracts.js.map +1 -0
  90. package/dist/mvp-time.d.ts +54 -0
  91. package/dist/mvp-time.d.ts.map +1 -0
  92. package/dist/mvp-time.js +148 -0
  93. package/dist/mvp-time.js.map +1 -0
  94. package/dist/notebook/types.d.ts +85 -8
  95. package/dist/notebook/types.d.ts.map +1 -1
  96. package/dist/notebook-grid.d.ts +37 -0
  97. package/dist/notebook-grid.d.ts.map +1 -0
  98. package/dist/notebook-grid.js +160 -0
  99. package/dist/notebook-grid.js.map +1 -0
  100. package/dist/notebook-media-artifact.d.ts +23 -0
  101. package/dist/notebook-media-artifact.d.ts.map +1 -0
  102. package/dist/notebook-media-artifact.js +67 -0
  103. package/dist/notebook-media-artifact.js.map +1 -0
  104. package/dist/notebook-mentions.d.ts +20 -0
  105. package/dist/notebook-mentions.d.ts.map +1 -0
  106. package/dist/notebook-mentions.js +53 -0
  107. package/dist/notebook-mentions.js.map +1 -0
  108. package/dist/order-keys.d.ts +22 -0
  109. package/dist/order-keys.d.ts.map +1 -0
  110. package/dist/order-keys.js +262 -0
  111. package/dist/order-keys.js.map +1 -0
  112. package/dist/runtime-services.js +8 -11
  113. package/dist/runtime-services.js.map +1 -1
  114. package/dist/schema.d.ts +8 -5
  115. package/dist/schema.d.ts.map +1 -1
  116. package/dist/schema.js +624 -141
  117. package/dist/schema.js.map +1 -1
  118. package/dist/search-benchmark.d.ts +4 -0
  119. package/dist/search-benchmark.d.ts.map +1 -0
  120. package/dist/search-benchmark.js +144 -0
  121. package/dist/search-benchmark.js.map +1 -0
  122. package/dist/sequences.d.ts +20 -0
  123. package/dist/sequences.d.ts.map +1 -0
  124. package/dist/sequences.js +825 -0
  125. package/dist/sequences.js.map +1 -0
  126. package/dist/similarity.js +10 -10
  127. package/dist/similarity.js.map +1 -1
  128. package/dist/status.js +8 -10
  129. package/dist/status.js.map +1 -1
  130. package/dist/storage.d.ts +3 -1
  131. package/dist/storage.d.ts.map +1 -1
  132. package/dist/storage.js +388 -7
  133. package/dist/storage.js.map +1 -1
  134. package/dist/store.d.ts +64 -3
  135. package/dist/store.d.ts.map +1 -1
  136. package/dist/store.js +354 -68
  137. package/dist/store.js.map +1 -1
  138. package/dist/streams.d.ts +10 -0
  139. package/dist/streams.d.ts.map +1 -0
  140. package/dist/streams.js +183 -0
  141. package/dist/streams.js.map +1 -0
  142. package/dist/temporal-models.d.ts +48 -0
  143. package/dist/temporal-models.d.ts.map +1 -0
  144. package/dist/temporal-models.js +278 -0
  145. package/dist/temporal-models.js.map +1 -0
  146. package/dist/temporal-search.d.ts +29 -0
  147. package/dist/temporal-search.d.ts.map +1 -0
  148. package/dist/temporal-search.js +1551 -0
  149. package/dist/temporal-search.js.map +1 -0
  150. package/dist/transcripts.d.ts +16 -0
  151. package/dist/transcripts.d.ts.map +1 -0
  152. package/dist/transcripts.js +519 -0
  153. package/dist/transcripts.js.map +1 -0
  154. package/docs/engine-layout.md +345 -110
  155. package/docs/mvp-prd.md +918 -0
  156. package/fixtures/media/vancat.mp4 +0 -0
  157. package/fixtures/media/vancat_profile.jpg +0 -0
  158. package/fixtures/v5/contract-fixtures.json +1532 -0
  159. package/package.json +42 -5
  160. package/dist/history-types.d.ts +0 -74
  161. package/dist/history-types.d.ts.map +0 -1
  162. package/dist/history-types.js +0 -2
  163. package/dist/history-types.js.map +0 -1
  164. package/dist/resolver.d.ts +0 -15
  165. package/dist/resolver.d.ts.map +0 -1
  166. package/dist/resolver.js +0 -81
  167. package/dist/resolver.js.map +0 -1
  168. package/dist/timeline.d.ts +0 -9
  169. package/dist/timeline.d.ts.map +0 -1
  170. package/dist/timeline.js +0 -236
  171. package/dist/timeline.js.map +0 -1
package/dist/schema.js CHANGED
@@ -1,34 +1,70 @@
1
- export const SCHEMA_VERSION = 4;
1
+ export { SCHEMA_VERSION } from "./catalog-metadata.js";
2
+ export const NOTEBOOK_CELL_TYPES = [
3
+ "audio",
4
+ "image",
5
+ "video",
6
+ "extract_audio",
7
+ "split_video",
8
+ "prompt",
9
+ "character",
10
+ "analyze",
11
+ "analysis",
12
+ "generate_video",
13
+ "generate_image",
14
+ "generate_audio",
15
+ "concat",
16
+ "splice",
17
+ ];
18
+ // Cell types that were removed from the union but may still exist in stored
19
+ // rows (the cells-table CHECK below deliberately keeps accepting them so
20
+ // history.restore can reinsert legacy rows). Reads map them to their modern
21
+ // equivalent; writes stay strict.
22
+ export const LEGACY_NOTEBOOK_CELL_TYPE_ALIASES = {
23
+ extract_frame: "image",
24
+ };
25
+ // The staging allowlist is also the restore table list: history.restore
26
+ // reloads every table below from its dolt_at_* projection, deleting in
27
+ // reverse order and inserting in forward order. Keep the list ordered
28
+ // parent-before-child so the mechanical reload satisfies foreign keys.
2
29
  export const SEMANTIC_TABLES = [
3
30
  "engine_schema",
4
31
  "book",
5
32
  "artifacts",
6
33
  "objects",
7
34
  "artifact_files",
35
+ "artifact_streams",
8
36
  "book_metadata",
9
37
  "artifact_metadata",
10
38
  "entities",
11
39
  "notebooks",
40
+ "notebook_fields",
12
41
  "cells",
42
+ "notebook_cell_executions",
43
+ "notebook_generation_plans",
44
+ "notebook_run_plans",
13
45
  "edges",
14
46
  "runs",
15
- "timeline",
16
- "timeline_slots",
17
- "timeline_audio",
47
+ "cell_references",
48
+ "pinned_search_results",
49
+ "transcripts",
50
+ "transcript_segments",
51
+ "transcript_words",
52
+ "sequences",
53
+ "sequence_tracks",
54
+ "sequence_clips",
55
+ "clip_links",
56
+ "clip_transforms",
57
+ "transitions",
58
+ "caption_cues",
18
59
  "audio_waveforms",
19
60
  "prompt_entries",
20
61
  "messages",
21
- "operations",
22
- "actions",
23
- "action_events",
24
- "action_parents",
25
- "action_artifacts",
26
- "action_write_set",
27
- "job_runs",
62
+ "generations",
28
63
  ];
29
64
  export const RUNTIME_TABLES = [
30
65
  "runtime_meta",
31
66
  "runtime_jobs",
67
+ "job_runs",
32
68
  "runtime_resource_leases",
33
69
  "runtime_object_publications",
34
70
  "runtime_workspace_entries",
@@ -38,10 +74,46 @@ export const RUNTIME_TABLES = [
38
74
  "runtime_settings",
39
75
  "runtime_logs",
40
76
  "runtime_commit_outbox",
77
+ "runtime_index_manifests",
78
+ "runtime_index_generations",
79
+ "runtime_index_coverage",
80
+ "runtime_media_segments",
81
+ "runtime_segment_text",
82
+ "runtime_segment_embeddings",
83
+ "runtime_segment_fingerprints",
84
+ "runtime_index_batches",
41
85
  "runtime_similarity_embeddings",
42
86
  "runtime_text_similarity_documents",
43
87
  "runtime_text_similarity_chunks",
44
88
  ];
89
+ const CELLS_TABLE_SQL = `
90
+ CREATE TABLE IF NOT EXISTS cells (
91
+ notebook_id TEXT NOT NULL
92
+ REFERENCES notebooks(notebook_id) ON DELETE CASCADE,
93
+ cell_id TEXT NOT NULL,
94
+ type TEXT NOT NULL CHECK (
95
+ type IN (
96
+ 'audio','image','video','extract_audio','extract_frame','split_video',
97
+ 'prompt','character',
98
+ 'analyze','analysis','generate_video','generate_image','generate_audio',
99
+ 'concat','splice'
100
+ )
101
+ ),
102
+ label TEXT,
103
+ grid_row INTEGER NOT NULL CHECK (grid_row BETWEEN 0 AND 25),
104
+ grid_column INTEGER NOT NULL CHECK (grid_column BETWEEN 0 AND 12),
105
+ output_entity_id TEXT
106
+ REFERENCES entities(entity_id) ON DELETE RESTRICT,
107
+ prompt TEXT,
108
+ provider TEXT,
109
+ model TEXT,
110
+ operation TEXT,
111
+ tool TEXT,
112
+ inputs_json TEXT NOT NULL DEFAULT '{}',
113
+ output_artifact_id TEXT
114
+ REFERENCES artifacts(artifact_id) ON DELETE RESTRICT,
115
+ PRIMARY KEY(notebook_id, cell_id)
116
+ );`;
45
117
  export const SEMANTIC_SCHEMA_SQL = `
46
118
  CREATE TABLE IF NOT EXISTS engine_schema (
47
119
  singleton INTEGER PRIMARY KEY CHECK (singleton = 1),
@@ -51,13 +123,13 @@ export const SEMANTIC_SCHEMA_SQL = `
51
123
 
52
124
  CREATE TABLE IF NOT EXISTS book (
53
125
  book_id TEXT PRIMARY KEY,
54
- slug TEXT NOT NULL UNIQUE,
126
+ name TEXT NOT NULL,
55
127
  created_at INTEGER NOT NULL
56
128
  );
57
129
 
58
130
  CREATE TABLE IF NOT EXISTS artifacts (
59
131
  artifact_id TEXT PRIMARY KEY,
60
- slug TEXT NOT NULL UNIQUE,
132
+ label TEXT,
61
133
  kind TEXT NOT NULL CHECK (
62
134
  kind IN (
63
135
  'video','image','audio','script','character',
@@ -69,7 +141,8 @@ export const SEMANTIC_SCHEMA_SQL = `
69
141
  CREATE TABLE IF NOT EXISTS objects (
70
142
  object_hash TEXT PRIMARY KEY,
71
143
  size_bytes INTEGER NOT NULL CHECK (size_bytes >= 0),
72
- created_at INTEGER NOT NULL
144
+ created_at INTEGER NOT NULL,
145
+ forgotten_at INTEGER
73
146
  );
74
147
 
75
148
  CREATE TABLE IF NOT EXISTS artifact_files (
@@ -78,10 +151,28 @@ export const SEMANTIC_SCHEMA_SQL = `
78
151
  path TEXT NOT NULL,
79
152
  object_hash TEXT NOT NULL
80
153
  REFERENCES objects(object_hash) ON DELETE RESTRICT,
81
- mtime_ms INTEGER NOT NULL,
82
154
  created_at INTEGER NOT NULL,
83
155
  PRIMARY KEY(artifact_id, path)
84
156
  );
157
+ CREATE TABLE IF NOT EXISTS artifact_streams (
158
+ stream_id TEXT PRIMARY KEY,
159
+ artifact_id TEXT NOT NULL
160
+ REFERENCES artifacts(artifact_id) ON DELETE RESTRICT,
161
+ source_path TEXT NOT NULL,
162
+ object_hash TEXT NOT NULL
163
+ REFERENCES objects(object_hash) ON DELETE RESTRICT,
164
+ stream_index INTEGER NOT NULL CHECK (stream_index >= 0),
165
+ kind TEXT NOT NULL CHECK (kind IN ('video','audio')),
166
+ time_base_numerator INTEGER NOT NULL CHECK (time_base_numerator > 0),
167
+ time_base_denominator INTEGER NOT NULL CHECK (time_base_denominator > 0),
168
+ duration_ticks INTEGER NOT NULL CHECK (duration_ticks > 0),
169
+ codec TEXT NOT NULL,
170
+ profile_json TEXT NOT NULL DEFAULT '{}',
171
+ created_at INTEGER NOT NULL,
172
+ UNIQUE(artifact_id, source_path, object_hash, stream_index),
173
+ FOREIGN KEY(artifact_id, source_path)
174
+ REFERENCES artifact_files(artifact_id, path) ON DELETE RESTRICT
175
+ );
85
176
  CREATE TABLE IF NOT EXISTS book_metadata (
86
177
  key TEXT PRIMARY KEY,
87
178
  value_json TEXT NOT NULL
@@ -107,27 +198,72 @@ export const SEMANTIC_SCHEMA_SQL = `
107
198
  CREATE TABLE IF NOT EXISTS notebooks (
108
199
  notebook_id TEXT PRIMARY KEY,
109
200
  name TEXT NOT NULL,
110
- properties_json TEXT NOT NULL DEFAULT '{}',
111
201
  created_at INTEGER NOT NULL
112
202
  );
113
- CREATE TABLE IF NOT EXISTS cells (
203
+ CREATE TABLE IF NOT EXISTS notebook_fields (
114
204
  notebook_id TEXT NOT NULL
115
205
  REFERENCES notebooks(notebook_id) ON DELETE CASCADE,
116
- cell_id TEXT NOT NULL,
117
- type TEXT NOT NULL CHECK (
118
- type IN ('prompt','character','scene','asset','image','video')
206
+ field TEXT NOT NULL CHECK (
207
+ field IN (
208
+ 'description','lifecycle_state','workflow_version',
209
+ 'analysis_revision','fixture'
210
+ )
119
211
  ),
120
- title TEXT NOT NULL,
121
- position_x REAL NOT NULL,
122
- position_y REAL NOT NULL,
123
- entity_id TEXT
124
- REFERENCES entities(entity_id) ON DELETE RESTRICT,
125
- prompt TEXT,
126
- model TEXT,
127
- inputs_json TEXT NOT NULL DEFAULT '{}',
128
- output_artifact_id TEXT
129
- REFERENCES artifacts(artifact_id) ON DELETE RESTRICT,
130
- PRIMARY KEY(notebook_id, cell_id)
212
+ value_json TEXT NOT NULL,
213
+ PRIMARY KEY(notebook_id, field)
214
+ );
215
+ ${CELLS_TABLE_SQL}
216
+ CREATE TABLE IF NOT EXISTS notebook_cell_executions (
217
+ notebook_id TEXT NOT NULL,
218
+ cell_id TEXT NOT NULL,
219
+ fingerprint TEXT,
220
+ status TEXT,
221
+ output_artifact_id TEXT,
222
+ provider_artifact_id TEXT,
223
+ run_id TEXT,
224
+ completed_at TEXT,
225
+ started_at TEXT,
226
+ updated_at TEXT,
227
+ tool TEXT,
228
+ error TEXT,
229
+ stale INTEGER NOT NULL DEFAULT 0 CHECK (stale IN (0, 1)),
230
+ fixture_baseline INTEGER NOT NULL DEFAULT 0
231
+ CHECK (fixture_baseline IN (0, 1)),
232
+ PRIMARY KEY(notebook_id, cell_id),
233
+ FOREIGN KEY(notebook_id, cell_id)
234
+ REFERENCES cells(notebook_id, cell_id) ON DELETE CASCADE
235
+ );
236
+ CREATE TABLE IF NOT EXISTS notebook_generation_plans (
237
+ notebook_id TEXT NOT NULL
238
+ REFERENCES notebooks(notebook_id) ON DELETE CASCADE,
239
+ plan_id TEXT NOT NULL,
240
+ cell_id TEXT NOT NULL,
241
+ status TEXT NOT NULL,
242
+ plan_json TEXT NOT NULL,
243
+ output_artifact_id TEXT,
244
+ error TEXT,
245
+ created_at TEXT NOT NULL,
246
+ updated_at TEXT NOT NULL,
247
+ PRIMARY KEY(notebook_id, plan_id),
248
+ FOREIGN KEY(notebook_id, cell_id)
249
+ REFERENCES cells(notebook_id, cell_id) ON DELETE CASCADE
250
+ );
251
+ CREATE TABLE IF NOT EXISTS notebook_run_plans (
252
+ notebook_id TEXT NOT NULL
253
+ REFERENCES notebooks(notebook_id) ON DELETE CASCADE,
254
+ plan_id TEXT NOT NULL,
255
+ status TEXT NOT NULL,
256
+ plan_json TEXT NOT NULL,
257
+ paid_cell_ids_json TEXT NOT NULL,
258
+ cell_fingerprints_json TEXT NOT NULL,
259
+ known_cost_usd REAL NOT NULL CHECK (known_cost_usd >= 0),
260
+ unknown_cost_count INTEGER NOT NULL CHECK (unknown_cost_count >= 0),
261
+ created_at TEXT NOT NULL,
262
+ updated_at TEXT NOT NULL,
263
+ run_id TEXT,
264
+ outputs_json TEXT,
265
+ error TEXT,
266
+ PRIMARY KEY(notebook_id, plan_id)
131
267
  );
132
268
  CREATE TABLE IF NOT EXISTS edges (
133
269
  notebook_id TEXT NOT NULL
@@ -140,7 +276,8 @@ export const SEMANTIC_SCHEMA_SQL = `
140
276
  FOREIGN KEY(notebook_id, source_cell_id)
141
277
  REFERENCES cells(notebook_id, cell_id) ON DELETE CASCADE,
142
278
  FOREIGN KEY(notebook_id, target_cell_id)
143
- REFERENCES cells(notebook_id, cell_id) ON DELETE CASCADE
279
+ REFERENCES cells(notebook_id, cell_id) ON DELETE CASCADE,
280
+ UNIQUE(notebook_id, target_cell_id, target_input)
144
281
  );
145
282
  CREATE TABLE IF NOT EXISTS runs (
146
283
  run_id TEXT PRIMARY KEY,
@@ -153,32 +290,276 @@ export const SEMANTIC_SCHEMA_SQL = `
153
290
  outputs_json TEXT NOT NULL,
154
291
  error TEXT
155
292
  );
156
- CREATE TABLE IF NOT EXISTS timeline (
157
- book_id TEXT PRIMARY KEY
158
- REFERENCES book(book_id) ON DELETE CASCADE,
159
- render TEXT NOT NULL DEFAULT 'landscape'
160
- CHECK (render IN ('landscape','portrait','square'))
293
+ CREATE TABLE IF NOT EXISTS cell_references (
294
+ notebook_id TEXT NOT NULL,
295
+ cell_id TEXT NOT NULL,
296
+ reference_id TEXT NOT NULL,
297
+ kind TEXT NOT NULL CHECK (
298
+ kind IN (
299
+ 'artifact','stream','source-range','transcript',
300
+ 'sequence','cell-output'
301
+ )
302
+ ),
303
+ target_id TEXT NOT NULL,
304
+ snapshot_json TEXT NOT NULL DEFAULT '{}',
305
+ ordinal INTEGER NOT NULL CHECK (ordinal >= 0),
306
+ PRIMARY KEY(notebook_id, cell_id, reference_id),
307
+ FOREIGN KEY(notebook_id, cell_id)
308
+ REFERENCES cells(notebook_id, cell_id) ON DELETE CASCADE
161
309
  );
162
-
163
- CREATE TABLE IF NOT EXISTS timeline_slots (
164
- slot_id TEXT PRIMARY KEY,
310
+ CREATE TABLE IF NOT EXISTS pinned_search_results (
311
+ notebook_id TEXT NOT NULL,
312
+ cell_id TEXT NOT NULL,
313
+ result_id TEXT NOT NULL,
165
314
  artifact_id TEXT NOT NULL
166
315
  REFERENCES artifacts(artifact_id) ON DELETE RESTRICT,
316
+ object_hash TEXT NOT NULL
317
+ REFERENCES objects(object_hash) ON DELETE RESTRICT,
318
+ location_json TEXT NOT NULL,
319
+ representative_json TEXT,
320
+ query_json TEXT NOT NULL,
321
+ signals_json TEXT NOT NULL,
322
+ selected_revision TEXT NOT NULL,
167
323
  ordinal INTEGER NOT NULL CHECK (ordinal >= 0),
168
- volume REAL CHECK (volume IS NULL OR volume >= 0),
169
- audio_fade_in REAL CHECK (audio_fade_in IS NULL OR audio_fade_in >= 0),
170
- audio_fade_out REAL CHECK (audio_fade_out IS NULL OR audio_fade_out >= 0)
324
+ created_at INTEGER NOT NULL,
325
+ PRIMARY KEY(notebook_id, cell_id, result_id),
326
+ FOREIGN KEY(notebook_id, cell_id)
327
+ REFERENCES cells(notebook_id, cell_id) ON DELETE CASCADE
171
328
  );
172
- CREATE TABLE IF NOT EXISTS timeline_audio (
173
- audio_id TEXT PRIMARY KEY,
329
+ CREATE TABLE IF NOT EXISTS transcripts (
330
+ transcript_id TEXT PRIMARY KEY,
174
331
  artifact_id TEXT NOT NULL
175
332
  REFERENCES artifacts(artifact_id) ON DELETE RESTRICT,
333
+ stream_id TEXT NOT NULL
334
+ REFERENCES artifact_streams(stream_id) ON DELETE RESTRICT,
335
+ object_hash TEXT NOT NULL
336
+ REFERENCES objects(object_hash) ON DELETE RESTRICT,
337
+ payload_hash TEXT NOT NULL
338
+ REFERENCES objects(object_hash) ON DELETE RESTRICT,
339
+ language TEXT NOT NULL,
340
+ provider TEXT,
341
+ model TEXT,
342
+ state TEXT NOT NULL CHECK (state IN ('current','derived')),
343
+ created_at INTEGER NOT NULL
344
+ );
345
+ CREATE INDEX IF NOT EXISTS transcripts_current
346
+ ON transcripts(artifact_id, stream_id, object_hash, state);
347
+ CREATE TABLE IF NOT EXISTS transcript_segments (
348
+ segment_id TEXT PRIMARY KEY,
349
+ transcript_id TEXT NOT NULL
350
+ REFERENCES transcripts(transcript_id) ON DELETE CASCADE,
351
+ ordinal INTEGER NOT NULL CHECK (ordinal >= 0),
352
+ start_tick INTEGER NOT NULL CHECK (start_tick >= 0),
353
+ duration_ticks INTEGER NOT NULL CHECK (duration_ticks > 0),
354
+ speaker TEXT,
355
+ confidence REAL CHECK (
356
+ confidence IS NULL OR (confidence >= 0 AND confidence <= 1)
357
+ ),
358
+ kind TEXT NOT NULL CHECK (
359
+ kind IN ('speech','music','sound','silence','other')
360
+ ),
361
+ UNIQUE(transcript_id, ordinal)
362
+ );
363
+ CREATE TABLE IF NOT EXISTS transcript_words (
364
+ word_id TEXT PRIMARY KEY,
365
+ segment_id TEXT NOT NULL
366
+ REFERENCES transcript_segments(segment_id) ON DELETE CASCADE,
176
367
  ordinal INTEGER NOT NULL CHECK (ordinal >= 0),
177
- start_frame INTEGER NOT NULL CHECK (start_frame >= 0),
368
+ start_tick INTEGER NOT NULL CHECK (start_tick >= 0),
369
+ duration_ticks INTEGER NOT NULL CHECK (duration_ticks > 0),
370
+ confidence REAL CHECK (
371
+ confidence IS NULL OR (confidence >= 0 AND confidence <= 1)
372
+ ),
373
+ corrected INTEGER NOT NULL DEFAULT 0 CHECK (corrected IN (0,1)),
374
+ UNIQUE(segment_id, ordinal)
375
+ );
376
+ CREATE TABLE IF NOT EXISTS sequences (
377
+ sequence_id TEXT PRIMARY KEY,
378
+ book_id TEXT NOT NULL
379
+ REFERENCES book(book_id) ON DELETE CASCADE,
380
+ name TEXT NOT NULL,
381
+ is_primary INTEGER NOT NULL DEFAULT 0 CHECK (is_primary IN (0,1)),
382
+ width INTEGER NOT NULL CHECK (width > 0),
383
+ height INTEGER NOT NULL CHECK (height > 0),
384
+ pixel_aspect_numerator INTEGER NOT NULL
385
+ CHECK (pixel_aspect_numerator > 0),
386
+ pixel_aspect_denominator INTEGER NOT NULL
387
+ CHECK (pixel_aspect_denominator > 0),
388
+ frame_rate_numerator INTEGER NOT NULL
389
+ CHECK (frame_rate_numerator > 0),
390
+ frame_rate_denominator INTEGER NOT NULL
391
+ CHECK (frame_rate_denominator > 0),
392
+ audio_sample_rate_hz INTEGER NOT NULL CHECK (audio_sample_rate_hz > 0),
393
+ audio_channel_layout TEXT NOT NULL,
394
+ background_rgba_json TEXT NOT NULL,
395
+ created_at INTEGER NOT NULL
396
+ );
397
+ CREATE INDEX IF NOT EXISTS sequences_primary
398
+ ON sequences(book_id, is_primary);
399
+ CREATE TABLE IF NOT EXISTS sequence_tracks (
400
+ track_id TEXT PRIMARY KEY,
401
+ sequence_id TEXT NOT NULL
402
+ REFERENCES sequences(sequence_id) ON DELETE CASCADE,
403
+ kind TEXT NOT NULL CHECK (kind IN ('video','audio','caption')),
404
+ order_key TEXT NOT NULL,
405
+ name TEXT NOT NULL,
406
+ enabled INTEGER NOT NULL DEFAULT 1 CHECK (enabled IN (0,1)),
407
+ locked INTEGER NOT NULL DEFAULT 0 CHECK (locked IN (0,1)),
408
+ muted INTEGER CHECK (muted IS NULL OR muted IN (0,1)),
409
+ solo INTEGER CHECK (solo IS NULL OR solo IN (0,1)),
410
+ blend_mode TEXT,
411
+ CHECK (
412
+ (kind = 'audio' AND muted IS NOT NULL AND solo IS NOT NULL)
413
+ OR (kind <> 'audio' AND muted IS NULL AND solo IS NULL)
414
+ ),
415
+ CHECK (
416
+ (kind = 'video' AND blend_mode = 'normal')
417
+ OR (kind <> 'video' AND blend_mode IS NULL)
418
+ )
419
+ );
420
+ CREATE TABLE IF NOT EXISTS sequence_clips (
421
+ clip_id TEXT PRIMARY KEY,
422
+ track_id TEXT NOT NULL
423
+ REFERENCES sequence_tracks(track_id) ON DELETE CASCADE,
424
+ source_kind TEXT NOT NULL CHECK (source_kind IN ('still','timed')),
425
+ artifact_id TEXT NOT NULL
426
+ REFERENCES artifacts(artifact_id) ON DELETE RESTRICT,
427
+ source_path TEXT,
428
+ stream_id TEXT
429
+ REFERENCES artifact_streams(stream_id) ON DELETE RESTRICT,
430
+ object_hash TEXT NOT NULL
431
+ REFERENCES objects(object_hash) ON DELETE RESTRICT,
432
+ source_start_tick INTEGER,
433
+ source_duration_ticks INTEGER,
434
+ time_base_numerator INTEGER,
435
+ time_base_denominator INTEGER,
436
+ timeline_start_frame INTEGER NOT NULL CHECK (timeline_start_frame >= 0),
178
437
  duration_frames INTEGER NOT NULL CHECK (duration_frames > 0),
179
- volume REAL CHECK (volume IS NULL OR volume >= 0),
180
- fade_in REAL CHECK (fade_in IS NULL OR fade_in >= 0),
181
- fade_out REAL CHECK (fade_out IS NULL OR fade_out >= 0)
438
+ speed_numerator INTEGER,
439
+ speed_denominator INTEGER,
440
+ reverse INTEGER,
441
+ audio_policy TEXT,
442
+ gain_db REAL,
443
+ audio_muted INTEGER CHECK (audio_muted IS NULL OR audio_muted IN (0,1)),
444
+ fade_in_frames INTEGER CHECK (fade_in_frames IS NULL OR fade_in_frames >= 0),
445
+ fade_out_frames INTEGER CHECK (fade_out_frames IS NULL OR fade_out_frames >= 0),
446
+ enabled INTEGER NOT NULL DEFAULT 1 CHECK (enabled IN (0,1)),
447
+ CHECK (
448
+ (
449
+ source_kind = 'still'
450
+ AND source_path IS NOT NULL
451
+ AND stream_id IS NULL
452
+ AND source_start_tick IS NULL
453
+ AND source_duration_ticks IS NULL
454
+ AND time_base_numerator IS NULL
455
+ AND time_base_denominator IS NULL
456
+ AND speed_numerator IS NULL
457
+ AND speed_denominator IS NULL
458
+ AND reverse IS NULL
459
+ AND audio_policy IS NULL
460
+ )
461
+ OR
462
+ (
463
+ source_kind = 'timed'
464
+ AND source_path IS NULL
465
+ AND stream_id IS NOT NULL
466
+ AND source_start_tick >= 0
467
+ AND source_duration_ticks > 0
468
+ AND time_base_numerator > 0
469
+ AND time_base_denominator > 0
470
+ AND speed_numerator > 0
471
+ AND speed_denominator > 0
472
+ AND reverse IN (0,1)
473
+ AND audio_policy IN ('preserve-pitch','resample','mute')
474
+ )
475
+ ),
476
+ CHECK (
477
+ (
478
+ gain_db IS NULL
479
+ AND audio_muted IS NULL
480
+ AND fade_in_frames IS NULL
481
+ AND fade_out_frames IS NULL
482
+ )
483
+ OR
484
+ (
485
+ gain_db IS NOT NULL
486
+ AND audio_muted IS NOT NULL
487
+ AND fade_in_frames IS NOT NULL
488
+ AND fade_out_frames IS NOT NULL
489
+ )
490
+ )
491
+ );
492
+ CREATE TABLE IF NOT EXISTS clip_links (
493
+ link_group_id TEXT NOT NULL,
494
+ clip_id TEXT NOT NULL UNIQUE
495
+ REFERENCES sequence_clips(clip_id) ON DELETE CASCADE,
496
+ role TEXT NOT NULL,
497
+ PRIMARY KEY(link_group_id, clip_id)
498
+ );
499
+ CREATE TABLE IF NOT EXISTS clip_transforms (
500
+ clip_id TEXT PRIMARY KEY
501
+ REFERENCES sequence_clips(clip_id) ON DELETE CASCADE,
502
+ fit TEXT NOT NULL CHECK (fit IN ('fit','fill','crop')),
503
+ position_x REAL NOT NULL,
504
+ position_y REAL NOT NULL,
505
+ scale_x REAL NOT NULL CHECK (scale_x > 0),
506
+ scale_y REAL NOT NULL CHECK (scale_y > 0),
507
+ anchor_x REAL NOT NULL,
508
+ anchor_y REAL NOT NULL,
509
+ rotation_degrees REAL NOT NULL,
510
+ crop_top REAL NOT NULL CHECK (crop_top >= 0 AND crop_top <= 1),
511
+ crop_right REAL NOT NULL CHECK (crop_right >= 0 AND crop_right <= 1),
512
+ crop_bottom REAL NOT NULL CHECK (crop_bottom >= 0 AND crop_bottom <= 1),
513
+ crop_left REAL NOT NULL CHECK (crop_left >= 0 AND crop_left <= 1),
514
+ opacity REAL NOT NULL CHECK (opacity >= 0 AND opacity <= 1),
515
+ blend_mode TEXT NOT NULL CHECK (blend_mode = 'normal')
516
+ );
517
+ CREATE TABLE IF NOT EXISTS transitions (
518
+ transition_id TEXT PRIMARY KEY,
519
+ track_id TEXT NOT NULL
520
+ REFERENCES sequence_tracks(track_id) ON DELETE CASCADE,
521
+ outgoing_clip_id TEXT NOT NULL
522
+ REFERENCES sequence_clips(clip_id) ON DELETE CASCADE,
523
+ incoming_clip_id TEXT NOT NULL
524
+ REFERENCES sequence_clips(clip_id) ON DELETE CASCADE,
525
+ kind TEXT NOT NULL CHECK (kind IN ('cut','dissolve')),
526
+ duration_frames INTEGER NOT NULL CHECK (duration_frames > 0),
527
+ alignment TEXT NOT NULL CHECK (alignment IN ('start','center','end')),
528
+ parameters_json TEXT NOT NULL DEFAULT '{}',
529
+ UNIQUE(track_id, outgoing_clip_id, incoming_clip_id)
530
+ );
531
+ CREATE TABLE IF NOT EXISTS caption_cues (
532
+ cue_id TEXT PRIMARY KEY,
533
+ track_id TEXT NOT NULL
534
+ REFERENCES sequence_tracks(track_id) ON DELETE CASCADE,
535
+ timeline_start_frame INTEGER NOT NULL CHECK (timeline_start_frame >= 0),
536
+ duration_frames INTEGER NOT NULL CHECK (duration_frames > 0),
537
+ text TEXT NOT NULL,
538
+ speaker TEXT,
539
+ style_id TEXT NOT NULL,
540
+ transcript_id TEXT
541
+ REFERENCES transcripts(transcript_id) ON DELETE RESTRICT,
542
+ transcript_revision TEXT,
543
+ start_word_id TEXT,
544
+ end_word_id TEXT,
545
+ source_range_json TEXT,
546
+ CHECK (
547
+ (
548
+ transcript_id IS NULL
549
+ AND transcript_revision IS NULL
550
+ AND start_word_id IS NULL
551
+ AND end_word_id IS NULL
552
+ AND source_range_json IS NULL
553
+ )
554
+ OR
555
+ (
556
+ transcript_id IS NOT NULL
557
+ AND transcript_revision IS NOT NULL
558
+ AND start_word_id IS NOT NULL
559
+ AND end_word_id IS NOT NULL
560
+ AND source_range_json IS NOT NULL
561
+ )
562
+ )
182
563
  );
183
564
  CREATE TABLE IF NOT EXISTS audio_waveforms (
184
565
  artifact_id TEXT PRIMARY KEY
@@ -199,95 +580,49 @@ export const SEMANTIC_SCHEMA_SQL = `
199
580
  body_json TEXT NOT NULL,
200
581
  created_at INTEGER NOT NULL
201
582
  );
202
- CREATE TABLE IF NOT EXISTS operations (
203
- operation_id TEXT PRIMARY KEY,
204
- operation TEXT NOT NULL,
205
- artifact_id TEXT,
206
- details_json TEXT NOT NULL DEFAULT '{}',
207
- write_set_json TEXT NOT NULL DEFAULT '[]',
208
- base_revision TEXT,
209
- created_at INTEGER NOT NULL,
210
- author TEXT NOT NULL
211
- );
212
- CREATE TABLE IF NOT EXISTS actions (
213
- action_id TEXT PRIMARY KEY,
214
- operation TEXT NOT NULL,
215
- scope TEXT NOT NULL CHECK (
216
- scope IN ('book','artifact','layout','external','system')
217
- ),
218
- actor TEXT NOT NULL,
219
- lane TEXT NOT NULL,
220
- phase TEXT NOT NULL CHECK (
221
- phase IN (
222
- 'requested','started','completed','failed','cancelled','conflicted'
223
- )
224
- ),
225
- base_revision TEXT,
226
- target_artifact_id TEXT,
227
- target_action_id TEXT,
228
- layout_json TEXT,
229
- details_json TEXT NOT NULL DEFAULT '{}',
230
- created_at INTEGER NOT NULL
231
- );
232
-
233
- CREATE TABLE IF NOT EXISTS action_events (
234
- event_id TEXT PRIMARY KEY,
235
- action_id TEXT NOT NULL
236
- REFERENCES actions(action_id) ON DELETE CASCADE,
237
- operation_id TEXT NOT NULL,
238
- phase TEXT NOT NULL CHECK (
239
- phase IN (
240
- 'requested','started','completed','failed','cancelled','conflicted'
241
- )
583
+ CREATE TABLE IF NOT EXISTS generations (
584
+ generation_id TEXT PRIMARY KEY,
585
+ notebook_id TEXT NOT NULL,
586
+ cell_id TEXT NOT NULL,
587
+ output_cell_id TEXT,
588
+ run_id TEXT,
589
+ status TEXT NOT NULL CHECK (
590
+ status IN ('dispatched','awaiting_provider','completed','failed')
242
591
  ),
243
- details_json TEXT NOT NULL DEFAULT '{}',
244
- created_at INTEGER NOT NULL
245
- );
246
- CREATE TABLE IF NOT EXISTS action_parents (
247
- action_id TEXT NOT NULL
248
- REFERENCES actions(action_id) ON DELETE CASCADE,
249
- parent_action_id TEXT NOT NULL
250
- REFERENCES actions(action_id) ON DELETE RESTRICT,
251
- PRIMARY KEY(action_id, parent_action_id)
252
- );
253
-
254
- CREATE TABLE IF NOT EXISTS action_artifacts (
255
- action_id TEXT NOT NULL
256
- REFERENCES actions(action_id) ON DELETE CASCADE,
257
- artifact_id TEXT NOT NULL,
258
- direction TEXT NOT NULL CHECK (direction IN ('input','output')),
259
- PRIMARY KEY(action_id, artifact_id, direction)
260
- );
261
-
262
- CREATE TABLE IF NOT EXISTS action_write_set (
263
- action_id TEXT NOT NULL
264
- REFERENCES actions(action_id) ON DELETE CASCADE,
265
- resource TEXT NOT NULL,
266
- PRIMARY KEY(action_id, resource)
267
- );
268
-
269
- CREATE TABLE IF NOT EXISTS job_runs (
270
- run_id TEXT PRIMARY KEY,
271
- artifact_id TEXT,
272
- job_type TEXT NOT NULL,
273
- state TEXT NOT NULL CHECK (state IN ('done','failed','aborted')),
274
- payload_json TEXT NOT NULL,
275
- result_json TEXT,
276
- error_json TEXT,
277
- started_at INTEGER,
278
- finished_at INTEGER NOT NULL
592
+ tool TEXT NOT NULL,
593
+ provider TEXT,
594
+ model TEXT,
595
+ prompt TEXT,
596
+ resolved_prompt TEXT,
597
+ provider_artifact_id TEXT,
598
+ output_artifact_id TEXT,
599
+ error TEXT,
600
+ created_at INTEGER NOT NULL,
601
+ updated_at INTEGER NOT NULL,
602
+ FOREIGN KEY(notebook_id, cell_id)
603
+ REFERENCES cells(notebook_id, cell_id) ON DELETE CASCADE
279
604
  );
280
605
 
281
606
  CREATE INDEX IF NOT EXISTS artifacts_created
282
607
  ON artifacts(created_at, artifact_id);
283
608
  CREATE INDEX IF NOT EXISTS artifact_files_object
284
609
  ON artifact_files(object_hash);
610
+ CREATE INDEX IF NOT EXISTS artifact_streams_artifact
611
+ ON artifact_streams(artifact_id, source_path, stream_index);
612
+ CREATE INDEX IF NOT EXISTS artifact_streams_object
613
+ ON artifact_streams(object_hash, stream_id);
285
614
  CREATE INDEX IF NOT EXISTS entities_type_created
286
615
  ON entities(type, created_at, entity_id);
287
616
  CREATE INDEX IF NOT EXISTS notebooks_created
288
617
  ON notebooks(created_at, notebook_id);
289
- CREATE INDEX IF NOT EXISTS cells_entity
290
- ON cells(entity_id);
618
+ CREATE INDEX IF NOT EXISTS cells_output_entity
619
+ ON cells(output_entity_id);
620
+ CREATE INDEX IF NOT EXISTS notebook_generation_plans_cell
621
+ ON notebook_generation_plans(notebook_id, cell_id, updated_at, plan_id);
622
+ CREATE INDEX IF NOT EXISTS notebook_run_plans_updated
623
+ ON notebook_run_plans(notebook_id, updated_at, plan_id);
624
+ CREATE INDEX IF NOT EXISTS cells_grid
625
+ ON cells(notebook_id, grid_row, grid_column, cell_id);
291
626
  CREATE INDEX IF NOT EXISTS cells_output_artifact
292
627
  ON cells(output_artifact_id);
293
628
  CREATE INDEX IF NOT EXISTS edges_source
@@ -296,24 +631,32 @@ export const SEMANTIC_SCHEMA_SQL = `
296
631
  ON edges(notebook_id, target_cell_id);
297
632
  CREATE INDEX IF NOT EXISTS runs_notebook_completed
298
633
  ON runs(notebook_id, completed_at, run_id);
299
- CREATE INDEX IF NOT EXISTS timeline_slots_order
300
- ON timeline_slots(ordinal, slot_id);
301
- CREATE INDEX IF NOT EXISTS timeline_slots_artifact
302
- ON timeline_slots(artifact_id);
303
- CREATE INDEX IF NOT EXISTS timeline_audio_order
304
- ON timeline_audio(ordinal, audio_id);
305
- CREATE INDEX IF NOT EXISTS timeline_audio_artifact
306
- ON timeline_audio(artifact_id);
634
+ CREATE INDEX IF NOT EXISTS cell_references_target
635
+ ON cell_references(kind, target_id);
636
+ CREATE INDEX IF NOT EXISTS pinned_search_results_artifact
637
+ ON pinned_search_results(artifact_id, created_at, result_id);
638
+ CREATE INDEX IF NOT EXISTS transcripts_artifact
639
+ ON transcripts(artifact_id, stream_id, state, created_at);
640
+ CREATE INDEX IF NOT EXISTS transcript_segments_order
641
+ ON transcript_segments(transcript_id, ordinal);
642
+ CREATE INDEX IF NOT EXISTS transcript_words_order
643
+ ON transcript_words(segment_id, ordinal);
644
+ CREATE INDEX IF NOT EXISTS sequence_tracks_order
645
+ ON sequence_tracks(sequence_id, kind, order_key);
646
+ CREATE INDEX IF NOT EXISTS sequence_clips_timeline
647
+ ON sequence_clips(track_id, timeline_start_frame, clip_id);
648
+ CREATE INDEX IF NOT EXISTS sequence_clips_artifact
649
+ ON sequence_clips(artifact_id, object_hash);
650
+ CREATE INDEX IF NOT EXISTS transitions_track
651
+ ON transitions(track_id, outgoing_clip_id, incoming_clip_id);
652
+ CREATE INDEX IF NOT EXISTS caption_cues_timeline
653
+ ON caption_cues(track_id, timeline_start_frame, cue_id);
307
654
  CREATE INDEX IF NOT EXISTS prompt_entries_lookup
308
655
  ON prompt_entries(surface, created_at, prompt_id);
309
656
  CREATE INDEX IF NOT EXISTS messages_created
310
657
  ON messages(created_at, message_id);
311
- CREATE INDEX IF NOT EXISTS operations_created
312
- ON operations(created_at, operation_id);
313
- CREATE INDEX IF NOT EXISTS operations_artifact_created
314
- ON operations(artifact_id, created_at, operation_id);
315
- CREATE INDEX IF NOT EXISTS action_events_action_created
316
- ON action_events(action_id, created_at, event_id);
658
+ CREATE INDEX IF NOT EXISTS generations_cell
659
+ ON generations(notebook_id, cell_id, created_at);
317
660
  `;
318
661
  const RUNTIME_SIMILARITY_SCHEMA_SQL = `
319
662
  CREATE TABLE IF NOT EXISTS runtime_similarity_embeddings (
@@ -375,6 +718,18 @@ export const RUNTIME_SCHEMA_SQL = `
375
718
  ON runtime_jobs(type, external_task_id)
376
719
  WHERE external_task_id IS NOT NULL;
377
720
 
721
+ CREATE TABLE IF NOT EXISTS job_runs (
722
+ run_id TEXT PRIMARY KEY,
723
+ artifact_id TEXT,
724
+ job_type TEXT NOT NULL,
725
+ state TEXT NOT NULL CHECK (state IN ('done','failed','aborted')),
726
+ payload_json TEXT NOT NULL,
727
+ result_json TEXT,
728
+ error_json TEXT,
729
+ started_at INTEGER,
730
+ finished_at INTEGER NOT NULL
731
+ );
732
+
378
733
  CREATE TABLE IF NOT EXISTS runtime_resource_leases (
379
734
  lease_id TEXT PRIMARY KEY,
380
735
  artifact_id TEXT,
@@ -463,6 +818,134 @@ export const RUNTIME_SCHEMA_SQL = `
463
818
  created_at INTEGER NOT NULL
464
819
  );
465
820
 
821
+ CREATE TABLE IF NOT EXISTS runtime_index_manifests (
822
+ manifest_id TEXT PRIMARY KEY,
823
+ provider TEXT NOT NULL,
824
+ model_id TEXT NOT NULL,
825
+ model_revision TEXT NOT NULL,
826
+ license TEXT,
827
+ embedding_space TEXT NOT NULL,
828
+ dimensions INTEGER NOT NULL CHECK (dimensions > 0),
829
+ modalities_json TEXT NOT NULL,
830
+ supported_languages_json TEXT NOT NULL,
831
+ preprocessing_version TEXT NOT NULL,
832
+ extractor_version TEXT NOT NULL,
833
+ created_at INTEGER NOT NULL
834
+ );
835
+
836
+ CREATE TABLE IF NOT EXISTS runtime_index_generations (
837
+ embedding_space TEXT NOT NULL,
838
+ generation TEXT NOT NULL,
839
+ manifest_id TEXT NOT NULL
840
+ REFERENCES runtime_index_manifests(manifest_id) ON DELETE RESTRICT,
841
+ state TEXT NOT NULL CHECK (state IN ('building','active','retired')),
842
+ activated_at INTEGER,
843
+ created_at INTEGER NOT NULL,
844
+ PRIMARY KEY(embedding_space, generation)
845
+ );
846
+ CREATE UNIQUE INDEX IF NOT EXISTS runtime_index_generation_active
847
+ ON runtime_index_generations(embedding_space)
848
+ WHERE state='active';
849
+
850
+ CREATE TABLE IF NOT EXISTS runtime_index_coverage (
851
+ artifact_id TEXT NOT NULL,
852
+ object_hash TEXT NOT NULL,
853
+ manifest_id TEXT NOT NULL
854
+ REFERENCES runtime_index_manifests(manifest_id) ON DELETE CASCADE,
855
+ generation TEXT NOT NULL,
856
+ phase TEXT NOT NULL,
857
+ state TEXT NOT NULL,
858
+ covered_ranges_json TEXT NOT NULL,
859
+ indexed_units INTEGER NOT NULL CHECK (indexed_units >= 0),
860
+ total_units INTEGER,
861
+ retryable INTEGER NOT NULL CHECK (retryable IN (0,1)),
862
+ error_json TEXT,
863
+ cursor TEXT,
864
+ updated_at INTEGER NOT NULL,
865
+ PRIMARY KEY(artifact_id, object_hash, manifest_id, generation, phase)
866
+ );
867
+ CREATE INDEX IF NOT EXISTS runtime_index_coverage_state
868
+ ON runtime_index_coverage(generation, state, artifact_id);
869
+
870
+ CREATE TABLE IF NOT EXISTS runtime_media_segments (
871
+ segment_id TEXT PRIMARY KEY,
872
+ artifact_id TEXT NOT NULL,
873
+ stream_id TEXT,
874
+ object_hash TEXT NOT NULL,
875
+ source_range_json TEXT,
876
+ source_path TEXT,
877
+ segment_kind TEXT NOT NULL,
878
+ representative_tick INTEGER,
879
+ segmentation_version TEXT NOT NULL,
880
+ generation TEXT NOT NULL,
881
+ manifest_id TEXT NOT NULL
882
+ REFERENCES runtime_index_manifests(manifest_id) ON DELETE CASCADE,
883
+ created_at INTEGER NOT NULL
884
+ );
885
+ CREATE INDEX IF NOT EXISTS runtime_media_segments_source
886
+ ON runtime_media_segments(
887
+ generation, artifact_id, stream_id, representative_tick
888
+ );
889
+
890
+ CREATE TABLE IF NOT EXISTS runtime_segment_text (
891
+ text_id TEXT PRIMARY KEY,
892
+ segment_id TEXT NOT NULL
893
+ REFERENCES runtime_media_segments(segment_id) ON DELETE CASCADE,
894
+ kind TEXT NOT NULL,
895
+ language TEXT,
896
+ text TEXT NOT NULL,
897
+ start_utf8_byte INTEGER,
898
+ end_utf8_byte INTEGER,
899
+ confidence REAL,
900
+ provenance_json TEXT NOT NULL,
901
+ generation TEXT NOT NULL
902
+ );
903
+ CREATE INDEX IF NOT EXISTS runtime_segment_text_lookup
904
+ ON runtime_segment_text(generation, kind, segment_id);
905
+
906
+ CREATE TABLE IF NOT EXISTS runtime_segment_embeddings (
907
+ embedding_id TEXT PRIMARY KEY,
908
+ segment_id TEXT NOT NULL
909
+ REFERENCES runtime_media_segments(segment_id) ON DELETE CASCADE,
910
+ modality TEXT NOT NULL,
911
+ embedding_space TEXT NOT NULL,
912
+ dimensions INTEGER NOT NULL,
913
+ vector_blob BLOB NOT NULL,
914
+ source_hash TEXT NOT NULL,
915
+ generation TEXT NOT NULL,
916
+ updated_at INTEGER NOT NULL,
917
+ UNIQUE(segment_id, modality, embedding_space, generation)
918
+ );
919
+ CREATE INDEX IF NOT EXISTS runtime_segment_embeddings_space
920
+ ON runtime_segment_embeddings(
921
+ generation, embedding_space, modality, segment_id
922
+ );
923
+
924
+ CREATE TABLE IF NOT EXISTS runtime_segment_fingerprints (
925
+ fingerprint_id TEXT PRIMARY KEY,
926
+ segment_id TEXT NOT NULL
927
+ REFERENCES runtime_media_segments(segment_id) ON DELETE CASCADE,
928
+ kind TEXT NOT NULL,
929
+ value TEXT NOT NULL,
930
+ extractor_version TEXT NOT NULL,
931
+ generation TEXT NOT NULL,
932
+ UNIQUE(kind, value, extractor_version, segment_id)
933
+ );
934
+ CREATE INDEX IF NOT EXISTS runtime_segment_fingerprints_lookup
935
+ ON runtime_segment_fingerprints(generation, kind, value);
936
+
937
+ CREATE TABLE IF NOT EXISTS runtime_index_batches (
938
+ batch_key TEXT PRIMARY KEY,
939
+ artifact_id TEXT NOT NULL,
940
+ object_hash TEXT NOT NULL,
941
+ manifest_id TEXT NOT NULL,
942
+ generation TEXT NOT NULL,
943
+ phase TEXT NOT NULL,
944
+ cursor TEXT,
945
+ result_json TEXT NOT NULL,
946
+ committed_at INTEGER NOT NULL
947
+ );
948
+
466
949
  ${RUNTIME_SIMILARITY_SCHEMA_SQL}
467
950
 
468
951
  CREATE TABLE IF NOT EXISTS runtime_text_similarity_documents (