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
@@ -0,0 +1,918 @@
1
+ # videobook-engine MVP Requirements
2
+
3
+ > Historical design baseline: this document proposed the 3.x/schema-v5
4
+ > transition. The implemented package is 4.2.0 with catalog schema v19; current
5
+ > API and layout documentation take precedence.
6
+
7
+ ## Temporal media retrieval and a reversible edit engine
8
+
9
+ | Field | Value |
10
+ | --- | --- |
11
+ | Status | Proposed MVP baseline |
12
+ | Package | `videobook-engine` |
13
+ | Date | 2026-07-24 |
14
+ | Tracking | `ve-4i9` |
15
+ | Product dependency | `~/videobook/docs/mvp-prd.md` (`vb-c8a`) |
16
+ | Proposed release line | `3.x`, catalog schema v5 |
17
+
18
+ ## 1. Executive contract
19
+
20
+ `videobook-engine` will be the provider-agnostic, local-first semantic core for
21
+ the Videobook MVP. It must make two product promises true:
22
+
23
+ 1. any useful moment in a book can be retrieved by language, image/frame,
24
+ video range, audio range, transcript, OCR, metadata, or exact similarity;
25
+ 2. any edit proposed through UI, slash command, or chat can be previewed,
26
+ validated, atomically committed, audited, and restored without mutating
27
+ source media.
28
+
29
+ The engine owns media identity, rational source time, derived temporal indexes,
30
+ notebook truth, sequence truth, edit semantics, provenance, jobs, content
31
+ addressing, and revision integrity. It does not own React state, chat prompting,
32
+ hosted AI credentials, a cross-book catalog, or provider-specific generation
33
+ workflows.
34
+
35
+ The current whole-artifact similarity API and ordered-slot timeline are useful
36
+ foundations but cannot satisfy the MVP. Schema v5 is an intentional edit and
37
+ retrieval model expansion.
38
+
39
+ ## 2. Scope and boundaries
40
+
41
+ ### 2.1 Engine responsibilities
42
+
43
+ - exactly one durable book per engine root;
44
+ - stable UUIDv7 identity for books, artifacts, notebooks, cells, streams,
45
+ transcripts, sequences, tracks, clips, captions, actions, and jobs;
46
+ - immutable CAS objects and versioned logical file mappings;
47
+ - media stream identity, source object identity, rational timebase, and exact
48
+ source ranges;
49
+ - corrected transcripts, notebook graphs, sequences, captions, edit actions,
50
+ and provenance as semantic state;
51
+ - local, rebuildable temporal text/visual/audio/OCR indexes;
52
+ - a provider interface for local or injected embedding/analysis
53
+ implementations;
54
+ - deterministic hybrid retrieval and timecoded search results;
55
+ - deterministic edit preview, validation, conflict detection, and atomic
56
+ commit;
57
+ - durable jobs, leases, fencing, recovery, and terminal job audit;
58
+ - forward-only Dolt revisions and copy-forward schema migration;
59
+ - storage health, optional content publication, and catalog backup.
60
+
61
+ ### 2.2 Application responsibilities
62
+
63
+ - React presentation, interaction, keyboard behavior, and synchronized views;
64
+ - deterministic slash parsing into typed engine intents;
65
+ - conversational interpretation, clarification, and planning;
66
+ - all external AI/API access through `@apicity` providers;
67
+ - provider credentials, cost policy, and user consent;
68
+ - queue workers that run ffmpeg, transcription, OCR, provider calls, rendering,
69
+ and engine index primitives;
70
+ - cross-book/library search federation and global archive behavior;
71
+ - HTTP media serving and packaged application lifecycle;
72
+ - user analytics and experiment assignment.
73
+
74
+ ### 2.3 Engine non-goals for MVP
75
+
76
+ - a hosted service or multi-tenant database;
77
+ - direct calls to hosted LLM, vision, transcription, or generation APIs;
78
+ - UI command grammar or natural-language intent recognition;
79
+ - a global index spanning multiple engine roots;
80
+ - collaborative branches or live multi-user merge;
81
+ - arbitrary effect plugins, professional interchange, or a full compositor;
82
+ - model training;
83
+ - permanent storage of derived proxies or embeddings as semantic truth.
84
+
85
+ ## 3. Current baseline and gap analysis
86
+
87
+ The audited 2.0.1 package and catalog schema v4 already provide:
88
+
89
+ - one isolated book and timeline per engine root;
90
+ - CAS objects, artifact file mappings, workspaces, metadata, and optional
91
+ remote publication;
92
+ - notebooks, typed cells/edges, terminal notebook runs, prompts, and messages;
93
+ - forward-only Dolt semantic commits, operation provenance, high-level action
94
+ DAGs, write sets, conflict checks, and restore;
95
+ - persistent jobs, leases, status projections, recovery, and terminal job
96
+ records;
97
+ - a single ordered visual lane plus timed audio overlays and waveforms;
98
+ - opt-in local image/video similarity through CLIP-like vectors;
99
+ - opt-in local audio similarity through CLAP audio vectors;
100
+ - opt-in text-document similarity with chunk offsets;
101
+ - exact-byte reuse and in-memory approximate-nearest-neighbor indexes.
102
+
103
+ The current contracts do not meet the MVP because:
104
+
105
+ - video indexing samples up to 120 frames and stores their centroid as one
106
+ vector, so results identify a file rather than a moment;
107
+ - image and video searches are isolated by media kind even though they can
108
+ share an embedding space;
109
+ - the built-in visual provider does not expose a text encoder, so language
110
+ cannot search visual content;
111
+ - audio uses one bounded source vector and does not return time ranges;
112
+ - text similarity searches text artifacts, not transcript/OCR ranges inside
113
+ media;
114
+ - there is no unified hybrid query or score/rank explanation;
115
+ - the application does not configure or consume similarity;
116
+ - the timeline lacks source in/out, timeline start, duration, tracks,
117
+ timebase, transforms, transitions, captions, and normalized edit decisions;
118
+ - notebook cells use source, note, selects, scene, and asset primitives with
119
+ operation and tool metadata defining behavior;
120
+ - action history records workflows but there is no public deterministic edit
121
+ plan/diff/commit contract.
122
+
123
+ ## 4. Non-negotiable invariants
124
+
125
+ 1. **One book, one root.** Cross-book behavior remains above the engine.
126
+ 2. **Source bytes are immutable.** Editing changes semantic references and
127
+ produces derived/final artifacts; it never rewrites a source object.
128
+ 3. **Semantic state is versioned.** User corrections, selections, sequences,
129
+ captions, and committed edit intents participate in Dolt history.
130
+ 4. **Derived state is rebuildable.** Embeddings, ANN structures, OCR/vision
131
+ observations, proxies, thumbnails, and readiness projections are runtime
132
+ state keyed by source hash and extractor/model manifest.
133
+ 5. **Time is exact.** Timeline positions are integer sequence frames; source
134
+ positions are integer stream ticks with an explicit rational timebase.
135
+ Floating-point seconds are presentation/input conveniences only.
136
+ 6. **A result remains resolvable.** A pinned search hit records artifact,
137
+ source object, stream, source range, index manifest, and book revision.
138
+ 7. **A commit is atomic.** An edit batch either changes all requested semantic
139
+ structures and records its action/operation or changes none.
140
+ 8. **History moves forward.** Restore creates a new semantic revision; the
141
+ live Dolt branch is never detached or rewound.
142
+ 9. **Conflicts are explicit.** A stale base revision with overlapping writes
143
+ cannot silently commit.
144
+ 10. **Model identity is data.** Every derived observation names its embedding
145
+ space, provider/model revision, preprocessing contract, dimensions, and
146
+ extractor version.
147
+ 11. **No secret enters a book.** API keys, access tokens, and secret-bearing
148
+ provider configuration never enter semantic tables, runtime logs, action
149
+ details, or metadata.
150
+ 12. **Path access stays scoped.** All book and asset bytes pass through engine
151
+ file/CAS/workspace APIs.
152
+
153
+ ## 5. Time and media identity
154
+
155
+ ### 5.1 Required public concepts
156
+
157
+ ```ts
158
+ export interface Rational {
159
+ numerator: number
160
+ denominator: number
161
+ }
162
+
163
+ export interface SourceRange {
164
+ streamId: string
165
+ objectHash: string
166
+ startTick: number
167
+ durationTicks: number
168
+ timeBase: Rational
169
+ }
170
+
171
+ export interface SourcePoint {
172
+ streamId: string
173
+ objectHash: string
174
+ tick: number
175
+ timeBase: Rational
176
+ }
177
+
178
+ export type MediaSourceSnapshot =
179
+ | {
180
+ kind: "still"
181
+ artifactId: string
182
+ sourcePath: string
183
+ objectHash: string
184
+ }
185
+ | {
186
+ kind: "timed"
187
+ artifactId: string
188
+ range: SourceRange
189
+ }
190
+
191
+ export type SearchLocation =
192
+ | MediaSourceSnapshot
193
+ | {
194
+ kind: "document"
195
+ artifactId: string
196
+ sourcePath: string
197
+ objectHash: string
198
+ startUtf8Byte: number
199
+ endUtf8Byte: number
200
+ }
201
+
202
+ export interface SequenceRange {
203
+ sequenceId: string
204
+ startFrame: number
205
+ durationFrames: number
206
+ }
207
+ ```
208
+
209
+ Names may change, but the semantics may not.
210
+
211
+ - All source, sequence, and text ranges are half-open: the start is included
212
+ and the end (`start + duration`) is excluded.
213
+ - A media stream is tied to a logical artifact file and the CAS object that was
214
+ probed. Stream source versions are immutable. Replacing an artifact file
215
+ creates new stream IDs for the new object; prior stream rows remain while
216
+ referenced. Existing committed clips keep their object-hash-qualified source
217
+ reference until the user explicitly conforms them.
218
+ - `timeBase` expresses seconds per source tick. A 48 kHz audio stream can use
219
+ `1/48000`; a video stream uses the probed stream timebase.
220
+ - A sequence defines a rational frame rate. Sequence frame `n` is mapped using
221
+ rational arithmetic with documented rounding at edit boundaries.
222
+ - `durationTicks` and `durationFrames` are positive. A zero-length cursor
223
+ selection is an input convenience, never a persisted clip or search hit.
224
+ - Still images have a CAS-qualified `still` source and a sequence duration but
225
+ no invented source timebase. Timed audio/video use a stream range. Text
226
+ documents use half-open UTF-8 byte offsets only for retrieval and cannot be
227
+ inserted as media clips without a rendering step.
228
+ - Search result display seconds are derived and must not become the authority
229
+ when a result is inserted.
230
+
231
+ ### 5.2 Media profile
232
+
233
+ Every searchable audio/video artifact requires a runtime media profile keyed
234
+ by artifact ID, source path, object hash, probe version, and stream index. It
235
+ contains:
236
+
237
+ - container, codec, stream kind, duration, timebase, and start time;
238
+ - video dimensions, rotation, pixel aspect ratio, nominal/average frame rate,
239
+ color metadata when available, and keyframe hints;
240
+ - audio sample rate, channel layout, duration, and loudness data when derived;
241
+ - whether the profile is complete, partial, stale, failed, or unsupported.
242
+
243
+ User-authored stream selection and sequence references are semantic. Re-probed
244
+ technical fields are runtime unless required to interpret a committed source
245
+ range, in which case the committed clip carries the necessary snapshot.
246
+
247
+ ## 6. Semantic and runtime ownership
248
+
249
+ | Data | Ownership | Reason |
250
+ | --- | --- | --- |
251
+ | Artifact identity, source file mapping, object identity | Semantic | Required to reproduce and audit work |
252
+ | Corrected transcript text, speakers, word timing adjustments | Semantic | User-authored editorial truth |
253
+ | Raw provider transcript/analysis response | Versioned artifact file with provenance | Reproducible input without hard-coding provider schema |
254
+ | Notebook cells, saved queries, pinned selects | Semantic | Creative decisions |
255
+ | Sequence, tracks, clips, source ranges, transforms, transitions, captions | Semantic | Authoritative edit decision list |
256
+ | Normalized committed command intent and action lineage | Semantic | Audit, restore, and surface parity |
257
+ | Media probes, proxies, thumbnails, storyboards, loudness | Runtime | Derivable from source object |
258
+ | Shot/window segmentation, OCR, generated descriptions | Runtime until user corrects or pins | Model-derived observations |
259
+ | Text, visual, audio vectors and ANN/FTS structures | Runtime | Rebuildable and model-versioned |
260
+ | Index coverage, progress, errors, caches | Runtime | Operational state |
261
+ | Final renders | Semantic artifact/files | User-visible output pinned to a sequence revision |
262
+
263
+ Runtime observations selected into a notebook or sequence are snapshotted by
264
+ stable source identity/range and relevant display/explanation fields. The
265
+ runtime row ID itself is never the only durable reference.
266
+
267
+ ## 7. Catalog schema v5 requirements
268
+
269
+ Exact SQL is an implementation decision, but schema v5 must normalize the
270
+ following concepts and constraints.
271
+
272
+ ### 7.1 Media streams and transcripts
273
+
274
+ | Structure | Minimum fields and constraints |
275
+ | --- | --- |
276
+ | `artifact_streams` | UUIDv7 stream ID; artifact ID; logical source path; object hash; stream index; timed kind (`video` or `audio`); timebase numerator/denominator; duration ticks; codec snapshot; optional video/audio shape; unique artifact/object/stream index |
277
+ | `transcripts` | UUIDv7 transcript ID; artifact/stream ID; source object hash; language; provider/model provenance; current/derived state; created time |
278
+ | `transcript_segments` | UUIDv7 segment ID; transcript ID; ordinal; source start/duration ticks; speaker; text; confidence optional; segment kind |
279
+ | `transcript_words` | UUIDv7 word ID; segment ID; ordinal; source start/duration ticks; text; confidence optional; user-corrected flag |
280
+
281
+ Transcript segment and word ranges must be ordered and bounded by the source
282
+ stream. Correcting text does not change timing. Adjusting timing is an explicit
283
+ semantic operation with overlap/bounds validation.
284
+
285
+ ### 7.2 Sequences and edit decisions
286
+
287
+ | Structure | Minimum fields and constraints |
288
+ | --- | --- |
289
+ | `sequences` | UUIDv7 sequence ID; name; width/height; pixel-aspect rational; frame-rate rational; audio sample rate/channel layout; background RGBA; created time |
290
+ | `sequence_tracks` | UUIDv7 track ID; sequence ID; kind (`video`, `audio`, `caption`); ordinal; name; enabled/locked; audio mute/solo; video blend mode |
291
+ | `sequence_clips` | UUIDv7 clip ID; track ID; discriminated still or timed `MediaSourceSnapshot`; timeline start/duration frames; timed sources carry source start/duration ticks and speed rational; reverse; enabled |
292
+ | `clip_links` | Stable link-group ID; clip ID; role; unique membership |
293
+ | `clip_transforms` | Clip ID; position, scale, anchor, rotation, crop edges, opacity, blend mode with validated finite ranges |
294
+ | `transitions` | UUIDv7 transition ID; track; outgoing/incoming clip IDs; kind; duration frames; alignment; parameters; adjacency and handle validation |
295
+ | `caption_cues` | UUIDv7 cue ID; caption track; timeline start/duration frames; text; speaker/style reference; source transcript references optional |
296
+
297
+ P0 transition kinds are cut and dissolve. P0 transforms are fit/fill/crop,
298
+ position, scale, rotation, opacity, and blend mode. The schema may allow future
299
+ effect/keyframe structures, but they are not a P0 implementation requirement.
300
+
301
+ Sequence rules:
302
+
303
+ - track ordinals are unique within sequence/kind;
304
+ - clips cannot have negative timeline positions or non-positive durations;
305
+ - source ranges must fit the referenced source snapshot after rational speed
306
+ mapping;
307
+ - speed and reverse apply only to compatible timed sources; still clips use
308
+ sequence duration without synthetic source ticks;
309
+ - video/caption overlap is allowed across tracks; overlap rules within a track
310
+ are explicit and deterministic;
311
+ - audio overlap is allowed;
312
+ - locked tracks reject mutation;
313
+ - transitions require valid adjacency/overlap and sufficient media handles;
314
+ - deletion of referenced artifacts/streams is restricted;
315
+ - a new book has one primary sequence compatible with its default render
316
+ orientation.
317
+
318
+ ### 7.3 Notebook evolution
319
+
320
+ Schema v5 must support at least:
321
+
322
+ - `source`, `audio`, `transcript`, `note`, `search`, `selects`, `prompt`,
323
+ `character`, `scene`, `image`, `video`, and `sequence` cell behaviors;
324
+ - typed references from cells to artifacts, streams/ranges, transcripts,
325
+ sequences, and other cell outputs;
326
+ - saved query configuration and filters;
327
+ - pinned result snapshots;
328
+ - explicit cell execution state through existing job/run contracts.
329
+
330
+ The implementation may use a versioned cell payload plus normalized typed
331
+ reference tables. It may not rely on path strings or opaque UI-only state to
332
+ reconnect a notebook after reload.
333
+
334
+ ### 7.4 Actions and edit batches
335
+
336
+ Existing `actions`, `action_events`, `action_parents`, `action_artifacts`, and
337
+ `action_write_set` remain the audit foundation.
338
+
339
+ A committed edit batch must record:
340
+
341
+ - intent schema version and source surface;
342
+ - actor, sequence, base revision, and committed revision;
343
+ - normalized operations in deterministic order;
344
+ - affected resource/write-set keys;
345
+ - input/output artifact and parent action links;
346
+ - preview hash or canonical before/after diff hash;
347
+ - confirmation policy and confirmation metadata without secret or prompt-body
348
+ leakage;
349
+ - operation count, affected timeline ranges, and warnings accepted;
350
+ - failure/conflict events when a requested batch does not commit.
351
+
352
+ Plans that are never applied are runtime/application state unless the user
353
+ explicitly saves one in a message or notebook cell.
354
+
355
+ ### 7.5 Runtime indexing structures
356
+
357
+ Schema v5 replaces or supersedes the three schema-v4 similarity tables with
358
+ runtime structures capable of many segments and modalities per artifact:
359
+
360
+ | Runtime concept | Required behavior |
361
+ | --- | --- |
362
+ | Index manifests | Identify provider, model ID/revision, license metadata, embedding space, dimensions, supported languages/modalities, preprocessing/extractor versions, and created time |
363
+ | Artifact coverage | Track source object, modality phases, indexed ranges, completeness, progress, error, retryability, and manifest |
364
+ | Media segments | Artifact/stream/object, source range, segment kind, representative tick, segmentation version, optional derived text |
365
+ | Segment text | Transcript/OCR/description/metadata text, language, half-open UTF-8 byte offsets or timed source ranges, confidence, provenance |
366
+ | Segment embeddings | Segment, modality, embedding space, dimensions, quantized vector, source hash, updated time; multiple spaces permitted |
367
+ | Exact/near duplicates | Cryptographic hash and optional perceptual/frame fingerprints with extractor version |
368
+ | Lexical index | FTS-capable index over transcript, OCR, descriptions, labels, and selected metadata |
369
+ | ANN indexes | Cached per embedding space and compatible query modality, rebuilt from runtime rows |
370
+
371
+ All runtime tables remain excluded from Dolt staging. A stale manifest or source
372
+ object invalidates only the affected derived rows.
373
+
374
+ ## 8. Public API requirements
375
+
376
+ The API remains explicit, typed, named-export friendly, and uses
377
+ `Result<T, EngineError>` for expected failures.
378
+
379
+ ### 8.1 Search contract
380
+
381
+ ```ts
382
+ export type SearchModality =
383
+ | "auto"
384
+ | "visual"
385
+ | "speech"
386
+ | "ocr"
387
+ | "audio"
388
+ | "metadata"
389
+
390
+ export type SearchReference =
391
+ | { kind: "image"; artifact: string }
392
+ | { kind: "frame"; source: SourcePoint }
393
+ | { kind: "video"; range: SourceRange }
394
+ | { kind: "audio"; range: SourceRange }
395
+
396
+ export interface SearchQuery {
397
+ text?: string
398
+ reference?: SearchReference
399
+ modalities?: SearchModality[]
400
+ artifactKinds?: ArtifactKind[]
401
+ durationMs?: { min?: number; max?: number }
402
+ labels?: string[]
403
+ createdAfter?: number
404
+ createdBefore?: number
405
+ minScore?: number
406
+ limit?: number
407
+ cursor?: string
408
+ }
409
+
410
+ export interface SearchSignal {
411
+ kind: "visual" | "speech" | "ocr" | "audio" | "metadata" | "exact" | "near"
412
+ rank: number
413
+ score?: number
414
+ explanation?: string
415
+ }
416
+
417
+ export interface SearchHit {
418
+ artifactId: string
419
+ artifactSlug: string
420
+ artifactKind: ArtifactKind
421
+ location: SearchLocation
422
+ representativeTick?: number
423
+ score: number
424
+ signals: SearchSignal[]
425
+ excerpt?: string
426
+ indexManifestIds: string[]
427
+ }
428
+
429
+ export interface SearchPage {
430
+ hits: SearchHit[]
431
+ nextCursor?: string
432
+ coverage: SearchCoverage
433
+ }
434
+ ```
435
+
436
+ The final API must provide equivalents of:
437
+
438
+ - `prepare` or manifest/model readiness;
439
+ - an index plan for an artifact/source object;
440
+ - cancellable worker primitives for incremental index batches;
441
+ - artifact and book coverage/status/stats;
442
+ - hybrid query by text, reference media, or both;
443
+ - deterministic pagination;
444
+ - targeted invalidation and full rebuild;
445
+ - runtime cleanup by retired manifest/source object.
446
+
447
+ Indexing is a long-running queued operation in the consuming application. The
448
+ engine primitive must be idempotent, incremental, cancellation-aware, and safe
449
+ to retry after lease expiry.
450
+
451
+ ### 8.2 Sequence and edit contract
452
+
453
+ ```ts
454
+ export interface EditIntent {
455
+ intentVersion: number
456
+ commandId: string
457
+ sequenceId: string
458
+ baseRevision: string
459
+ actor: string
460
+ sourceSurface: "ui" | "slash" | "chat" | "system"
461
+ operations: EditOperation[]
462
+ }
463
+
464
+ export interface EditPreview {
465
+ commandId: string
466
+ baseRevision: string
467
+ valid: boolean
468
+ operations: NormalizedEditOperation[]
469
+ affectedRanges: SequenceRange[]
470
+ writeSet: string[]
471
+ warnings: EditWarning[]
472
+ conflicts: EditConflict[]
473
+ beforeHash: string
474
+ afterHash: string
475
+ }
476
+
477
+ export interface EditCommit {
478
+ commandId: string
479
+ actionId: string
480
+ revision: string
481
+ sequence: Sequence
482
+ previewHash: string
483
+ }
484
+ ```
485
+
486
+ The engine must provide:
487
+
488
+ - sequence create/list/get/get-at-revision/rename/delete with reference checks;
489
+ - preview that resolves aliases, normalizes rational time, validates all
490
+ operations, computes affected resources/ranges, and does not mutate state;
491
+ - atomic commit that verifies base revision and preview hash, records the
492
+ action and semantic operation, then returns the committed revision;
493
+ - restore of a sequence or committed edit action as a new revision;
494
+ - stable before/after projection suitable for UI diffs;
495
+ - deterministic serialization for contract fixtures.
496
+
497
+ P0 edit operations:
498
+
499
+ | Operation | Required semantics |
500
+ | --- | --- |
501
+ | Insert/overwrite clip | Resolve source snapshot and range; place on target track; optionally replace overlapped range |
502
+ | Remove/ripple remove | Remove selected clips/ranges; ripple is explicit and scoped |
503
+ | Move | Change track and/or timeline start with lock/overlap validation |
504
+ | Trim | Change source in/out and timeline duration using rational mapping |
505
+ | Split | Produce two stable clips whose source/timeline ranges exactly cover the original |
506
+ | Restore removed source range | Recreate a clip from action/source provenance |
507
+ | Set transform | Validate and replace the P0 transform projection |
508
+ | Set gain/fades/mute | Apply finite audio values with defined units |
509
+ | Set speed/reverse | Preserve explicit source mapping and audio policy |
510
+ | Set transition | Validate adjacency, duration, handles, and supported kind |
511
+ | Upsert caption cue | Validate time range, text, track, and style reference |
512
+ | Batch replace range | Support transcript-driven and rough-cut plans atomically |
513
+
514
+ Units must be explicit in type/property names. Percent, decibels, linear gain,
515
+ milliseconds, frames, ticks, and seconds cannot be accepted interchangeably.
516
+
517
+ ### 8.3 Transcript contract
518
+
519
+ The engine must provide:
520
+
521
+ - import of a validated timed transcript from an application/provider adapter;
522
+ - read by artifact/stream and at revision;
523
+ - text correction without media mutation;
524
+ - word/segment timing correction with rational validation;
525
+ - range delete/restore/reorder operations that compile to sequence edits;
526
+ - a stable mapping from transcript selections to source ranges and from
527
+ sequence clips back to transcript ranges;
528
+ - caption cue generation input that remains tied to the chosen transcript
529
+ revision.
530
+
531
+ Provider-specific JSON remains an artifact file. The normalized transcript API
532
+ accepts and returns the engine’s provider-neutral model.
533
+
534
+ ## 9. Temporal multimodal retrieval
535
+
536
+ ### 9.1 Segmentation
537
+
538
+ The engine search worker must support multiple overlapping evidence units:
539
+
540
+ - shot-bounded visual segments;
541
+ - short overlapping visual windows for long or uncut shots;
542
+ - representative frames and optional per-frame vectors;
543
+ - transcript segments/words with exact source timing;
544
+ - OCR spans with time coverage;
545
+ - audio-event windows;
546
+ - artifact-level metadata and user labels.
547
+
548
+ No fixed segmentation algorithm is mandated, but the manifest must identify it
549
+ and the acceptance benchmark must demonstrate moment-level recall. A whole-file
550
+ vector may contribute a global signal but may not be the only video/audio
551
+ representation.
552
+
553
+ The worker commits batches frequently enough to expose progressive results and
554
+ records covered source ranges. A crash cannot require successful earlier
555
+ batches to be recomputed.
556
+
557
+ ### 9.2 Cross-modal spaces
558
+
559
+ The search-provider contract must distinguish:
560
+
561
+ - image/frame/video-segment encoders that share a comparable visual space;
562
+ - a text encoder for that same visual space;
563
+ - audio-window and optional audio-text encoders in a comparable audio space;
564
+ - semantic text encoders for transcript/OCR/document retrieval.
565
+
566
+ The current `embedImage`/centroid `embedVideo` interface is retained only as a
567
+ compatibility layer. MVP reverse image-to-video requires image and video
568
+ segments to search the same visual index. MVP natural-language visual search
569
+ requires text-to-visual encoding or an injected observation/ranking provider
570
+ that satisfies the same contract.
571
+
572
+ ### 9.3 Reverse video
573
+
574
+ A reverse-video query uses a source range, not an artifact ID alone. It samples
575
+ multiple ordered query moments and scores candidates for both visual similarity
576
+ and temporal coherence. A single centroid match cannot satisfy the contract.
577
+
578
+ The exact order-aware algorithm is an implementation choice. It may use
579
+ multi-vector ANN candidates followed by sequence alignment, but it must:
580
+
581
+ - return one or more bounded candidate source ranges;
582
+ - penalize reversed or shuffled action unless the query requests it;
583
+ - avoid flooding results with overlapping windows from the same moment;
584
+ - preserve exact/near-duplicate signals separately from semantic similarity;
585
+ - meet the reverse-video benchmark in the application PRD.
586
+
587
+ ### 9.4 Hybrid ranking
588
+
589
+ The engine must combine lexical and vector evidence without assuming raw scores
590
+ from different embedding spaces are calibrated. Reciprocal-rank fusion or a
591
+ documented equivalent is the default baseline.
592
+
593
+ Ranking requirements:
594
+
595
+ - exact byte and strong near-duplicate matches are deterministically promoted;
596
+ - quoted text strongly favors exact transcript/OCR matches;
597
+ - natural-language queries can retrieve visual-only moments;
598
+ - reference-plus-text queries use the text to refine rather than discard the
599
+ reference;
600
+ - adjacent/overlapping hits are deduplicated into useful ranges;
601
+ - results are stably ordered using score, source identity/range, and artifact
602
+ ID tie-breakers;
603
+ - every final hit retains contributing signal ranks/scores and a concise
604
+ provider-neutral explanation;
605
+ - coverage reports whether the query language is measured, best-effort, or
606
+ unsupported for each active semantic space;
607
+ - pagination is stable for an unchanged index generation.
608
+
609
+ ### 9.5 Index lifecycle
610
+
611
+ - A manifest is immutable once used.
612
+ - Provider/model/preprocessing changes create a new manifest and index
613
+ generation.
614
+ - New and old generations may coexist during rebuild.
615
+ - Queries use one coherent active generation per space; they never mix
616
+ incompatible dimensions or preprocessing.
617
+ - Generation activation is atomic after minimum coverage is met.
618
+ - Retired generations are garbage-collected only when no running query/job or
619
+ pinned diagnostic requires them.
620
+ - An artifact file/object change marks affected coverage stale and schedules
621
+ reindex without deleting user selections.
622
+ - Search remains available from unaffected and previously active coverage
623
+ during rebuild.
624
+
625
+ ## 10. Edit preview and commit semantics
626
+
627
+ ### 10.1 Preview
628
+
629
+ Preview is pure with respect to semantic and runtime storage. Given the same
630
+ head, intent, and source manifests, it returns byte-for-byte canonical
631
+ normalized operations and hashes.
632
+
633
+ Preview validates:
634
+
635
+ - IDs, references, source-object availability, stream/timebase compatibility;
636
+ - bounds, positive durations, rational overflow, and rounding;
637
+ - track kind, lock state, overlap policy, and transition handles;
638
+ - artifact deletion/replacement conflicts;
639
+ - stale base revision and overlapping writes since base;
640
+ - operation ordering and intra-batch dependencies;
641
+ - supported renderer/edit capabilities;
642
+ - missing media or derived work that will be required after commit.
643
+
644
+ ### 10.2 Commit
645
+
646
+ Commit accepts the original intent plus the preview hash. It re-runs validation
647
+ inside the serialized semantic mutation boundary. If the current state no
648
+ longer produces that preview hash, it returns `STALE_REVISION` or
649
+ `ACTION_CONFLICT`.
650
+
651
+ One successful commit:
652
+
653
+ 1. applies every sequence/transcript/notebook semantic row change;
654
+ 2. writes the low-level `operations` record and commit outbox entry;
655
+ 3. writes or advances the high-level action and its normalized write set;
656
+ 4. records input/output artifact lineage and parent actions;
657
+ 5. creates one forward Dolt revision;
658
+ 6. returns the revision and semantic projection;
659
+ 7. invalidates only affected runtime renders/proxies/search observations.
660
+
661
+ Derived jobs are enqueued or requested after the semantic commit and can be
662
+ reconciled from committed state. Their failure does not roll back the edit.
663
+
664
+ ### 10.3 Restore
665
+
666
+ Restore materializes the selected sequence/notebook/transcript state from a
667
+ revision or action, validates it against source availability, and commits it as
668
+ a new revision. Immutable source and final objects remain addressable according
669
+ to retention policy.
670
+
671
+ ## 11. Jobs and derived media
672
+
673
+ The existing runtime queue, leases, fences, and terminal `job_runs` remain the
674
+ coordination foundation.
675
+
676
+ P0 derived job types include:
677
+
678
+ - media probe;
679
+ - proxy/transcode;
680
+ - thumbnail/storyboard/waveform/loudness;
681
+ - transcription normalization;
682
+ - shot/window segmentation;
683
+ - OCR;
684
+ - visual/text/audio embedding batches;
685
+ - ANN/FTS generation activation;
686
+ - caption derivation;
687
+ - preview render and final render.
688
+
689
+ Job requirements:
690
+
691
+ - deterministic dedupe key includes book/source object, operation, and
692
+ manifest/settings version;
693
+ - progress can report units completed/total and current phase;
694
+ - lease expiry and retry cannot cause duplicate semantic outputs;
695
+ - cancellation is cooperative and leaves previously committed index batches
696
+ valid;
697
+ - failure codes distinguish unsupported media, missing object, provider/model
698
+ unavailable, offline, invalid output, resource exhaustion, timeout, and
699
+ internal error;
700
+ - jobs do not place secrets or full prompt/transcript bodies in logs;
701
+ - source replacement or sequence edit invalidates affected downstream work by
702
+ identity, not path guessing.
703
+
704
+ Derived proxy/thumbnail files may live in disposable workspaces or a managed
705
+ runtime cache. A final or user-promoted derivative becomes a normal semantic
706
+ artifact/file mapping before it is relied on by history.
707
+
708
+ ## 12. Performance and quality requirements
709
+
710
+ The reference beta device is an Apple M2 Pro with 16 GB RAM and local SSD.
711
+ Quality thresholds use the frozen corpus defined in the application PRD.
712
+
713
+ | ID | Area | Creator-beta requirement |
714
+ | --- | --- | --- |
715
+ | VE-NFR-001 | Open | Open a healthy 1,000-artifact book and return semantic summary within 2 seconds, excluding optional remote object fetches |
716
+ | VE-NFR-002 | Text readiness | New metadata and an imported normalized transcript become lexically searchable within 5 seconds of their semantic commit |
717
+ | VE-NFR-003 | Progressive visual indexing | Commit searchable coverage at least once per 60 seconds of source media analyzed and resume from the last committed batch |
718
+ | VE-NFR-004 | Query latency | On 100,000 indexed moments, warm p50 is under 500 ms and p95 under 1.5 seconds, including hybrid rank but excluding remote provider calls and preview-byte download |
719
+ | VE-NFR-005 | Edit preview | Preview a 100-operation batch against a 1,000-clip sequence in under 250 ms p95 without storage mutation |
720
+ | VE-NFR-006 | Edit commit | Commit that batch in under 1 second p95 on a healthy local catalog, excluding derived jobs |
721
+ | VE-NFR-007 | Memory | Query/index structures for 100,000 moments stay within 4 GB process RSS beyond memory required by an actively loaded embedding model |
722
+ | VE-NFR-008 | Durability | Forced termination at every SQL/outbox/Dolt boundary produces either the prior or committed semantic state after reopen, never a partial batch |
723
+ | VE-NFR-009 | Determinism | Repeating search against an unchanged active generation returns stable ordering; repeating preview returns identical canonical operations/hashes |
724
+ | VE-NFR-010 | Search quality | Meet every recall, duplicate, boundary-error, and latency threshold in `~/videobook/docs/mvp-prd.md` |
725
+ | VE-NFR-011 | Offline | With required models cached, no search/index/edit/history operation initiates network access |
726
+ | VE-NFR-012 | Scale behavior | Larger books degrade through longer indexing/pagination, not catalog corruption, unbounded React payloads, or full-vector scans on every query |
727
+
728
+ Index throughput is reported, benchmarked, and visible but is not fixed to one
729
+ number until the reference model is selected in G0. First useful partial
730
+ coverage and safe resume are release requirements.
731
+
732
+ ## 13. Security and privacy
733
+
734
+ - Model downloads are opt-in/configurable, revision-pinned, checksum-verified
735
+ when upstream metadata supports it, and can be disabled.
736
+ - Search providers receive only scoped file/range/text inputs. The built-in
737
+ provider is local. Injected providers declare whether they can perform
738
+ network access; the application owns consent.
739
+ - Media subprocesses use argument arrays, bounded output locations, timeouts,
740
+ cancellation, and scoped workspaces; no untrusted value is interpreted by a
741
+ shell.
742
+ - Malformed codecs, oversized images, decompression bombs, and model
743
+ out-of-memory errors fail the job without corrupting the book.
744
+ - Search excerpts and explanations are treated as user content.
745
+ - Runtime logs use IDs, hashes, sizes, phases, and error codes rather than
746
+ secrets or full content.
747
+ - Content hashes are identity values, not authorization tokens.
748
+ - Remote content publication and catalog backup remain explicit operations and
749
+ are not triggered by local search.
750
+
751
+ ## 14. Migration and compatibility
752
+
753
+ Schema v5 is released on a new package major because timeline and similarity
754
+ contracts change materially.
755
+
756
+ The supported path from schema v4 is copy-forward migration:
757
+
758
+ 1. open v4 read-only and verify storage health;
759
+ 2. create a separate v5 root;
760
+ 3. preserve current book, artifact, entity, notebook, prompt/message, and
761
+ content identities where valid;
762
+ 4. preserve all object hashes and copy/hard-link bytes through engine CAS
763
+ primitives;
764
+ 5. convert ordered `timeline_slots` to sequential clips on the primary video
765
+ track using probed source duration;
766
+ 6. convert `timeline_audio` to clips on the first audio track;
767
+ 7. convert render orientation into primary sequence dimensions/frame rate;
768
+ 8. carry waveform and corrected semantic metadata where compatible;
769
+ 9. discard schema-v4 similarity runtime rows and schedule v5 reindex;
770
+ 10. create a migration report artifact plus one v5 import action/operation that
771
+ records the v4 book ID, v4 head revision, conversion decisions, and hashes;
772
+ 11. validate manifests, references, converted duration, and head state;
773
+ 12. leave the v4 root untouched until the application explicitly switches.
774
+
775
+ Schema-v4 Dolt commit IDs and action/operation rows are not inserted into the
776
+ live v5 history because their table snapshots and base revisions use the old
777
+ schema. The migration report preserves a machine-readable audit summary and
778
+ the untouched v4 root remains the authority for full legacy revision browsing.
779
+ New v5 history begins with the import revision.
780
+
781
+ Migration requirements:
782
+
783
+ - idempotent for the same source/destination contract;
784
+ - interruptible and resumable or safely restartable;
785
+ - dry-run report with unsupported/missing media and estimated reindex work;
786
+ - real-fixture tests for empty, representative, large, and partially missing
787
+ v4 books;
788
+ - no implicit in-place upgrade;
789
+ - a clear `SCHEMA_INCOMPATIBLE` result when a caller attempts an unsupported
790
+ open.
791
+
792
+ A compatibility adapter may expose the old `timeline` and `similarity` APIs
793
+ during application transition, but it must compile into v5 sequence/search
794
+ semantics and be marked deprecated. It cannot maintain a second truth.
795
+
796
+ ## 15. Verification and acceptance
797
+
798
+ All release-gate tests use real DoltLite, real filesystem/CAS paths, and real
799
+ ffmpeg/ffprobe where media is involved. Search quality gates use the pinned
800
+ local reference models, not deterministic test embeddings.
801
+
802
+ ### 15.1 Temporal retrieval
803
+
804
+ - Index a video containing several distinct scenes and prove that a query
805
+ returns the judged scene range rather than only the artifact.
806
+ - Query a selected frame and retrieve matching still images and ranges in other
807
+ videos from one visual space.
808
+ - Query a five-second ordered action and distinguish the coherent action from
809
+ clips containing the same objects in a different order.
810
+ - Query language with no transcript match and retrieve the correct visual-only
811
+ range.
812
+ - Query quoted speech and OCR, verify exact evidence and time range, and show
813
+ contributing signals.
814
+ - Replace a source object, preserve a pinned old selection, mark current
815
+ coverage stale, rebuild progressively, and atomically activate the new
816
+ generation.
817
+
818
+ ### 15.2 Sequence correctness
819
+
820
+ - Insert, overwrite, move, trim, split, ripple remove, transform, fade, speed,
821
+ reverse, dissolve, and caption operations round-trip through preview/commit.
822
+ - Rational-time property tests prove that a split followed by recombination
823
+ covers the original source/timeline ranges without gaps or double frames.
824
+ - Locked tracks, invalid handles, out-of-bounds source ranges, and wrong stream
825
+ kinds fail without mutation.
826
+ - The same normalized intent from UI/slash/chat fixtures produces equivalent
827
+ semantic sequence state.
828
+
829
+ ### 15.3 Concurrency and recovery
830
+
831
+ - A stale non-overlapping action can be explicitly rebased; an overlapping
832
+ action conflicts.
833
+ - Killing the process before SQL commit, after SQL commit/before Dolt commit,
834
+ and after Dolt commit/before outbox cleanup recovers to a valid single
835
+ semantic outcome.
836
+ - Killing index jobs between batches preserves activated generation and
837
+ completed coverage.
838
+ - Lease expiry with two workers cannot double-activate a generation or commit
839
+ duplicate terminal semantic records.
840
+
841
+ ### 15.4 Migration
842
+
843
+ - A representative v4 fixture migrates to v5 with identical artifact/file
844
+ hashes, equivalent ordered playback, equivalent audio placement, preserved
845
+ current notebooks/prompts/messages, a verified legacy-history report and
846
+ source-head link, and no v4 source mutation.
847
+ - Missing objects are reported before switch and never replaced with silent
848
+ placeholders.
849
+ - Re-running after interruption completes without duplicate semantic rows.
850
+
851
+ ### 15.5 Performance and quality
852
+
853
+ - Automated benchmark records model/manifest, device, corpus version, index
854
+ time, peak RSS, coverage cadence, query latency, recall, and boundary error.
855
+ - A release candidate cannot activate if it misses application search-quality
856
+ thresholds or regresses a query class by more than the permitted margin.
857
+
858
+ ## 16. Cross-repository contract fixtures
859
+
860
+ The engine repository publishes JSON/TypeScript fixtures for:
861
+
862
+ - source points/ranges and rational time conversion;
863
+ - each P0 `EditOperation`;
864
+ - intent normalization, preview warnings/conflicts, diff hashes, and commit
865
+ result;
866
+ - sequence with video/audio/caption tracks;
867
+ - transcript and transcript selection mapping;
868
+ - text, reverse-image, reverse-video, and reverse-audio queries;
869
+ - search pages, signal explanations, coverage, stale/partial states;
870
+ - jobs and progress/failure codes;
871
+ - schema-v4 migration dry-run/result.
872
+
873
+ The application consumes these fixtures in integration tests. Contract changes
874
+ require a version increment and coordinated PRD/issue review. Copying engine
875
+ types into application source is not an acceptable integration strategy.
876
+
877
+ ## 17. Delivery gates
878
+
879
+ Beads is the implementation source of truth. These gates define dependency
880
+ order and exit criteria rather than a second issue tracker.
881
+
882
+ | Gate | Engine slice | Exit criteria |
883
+ | --- | --- | --- |
884
+ | E0 — Contract | Time, stream, transcript, sequence, search, intent, preview, and migration types | Public types and cross-repo fixtures compile; invariants and error codes are fixed |
885
+ | E1 — Semantic model | Schema v5 tables/APIs, sequence read/write-at-revision, transcript normalization, action integration | Real Dolt integration tests and rational-time properties pass |
886
+ | E2 — Edit transactions | P0 preview/commit/restore operations and conflict/write-set behavior | Atomicity, surface fixture parity, and forced-crash suite pass |
887
+ | E3 — Temporal index | Media segments, manifests, progressive batches, visual/text/audio/OCR indexes, hybrid search | Moment, language-to-visual, reverse-frame, and partial-coverage scenarios pass |
888
+ | E4 — Reverse video and quality | Ordered multi-vector candidate rerank, deduplication, explanations, quality harness | Frozen reverse-video and full search benchmark thresholds pass |
889
+ | E5 — Migration and hardening | v4 copy-forward migration, compatibility adapter, cleanup, performance, security | Representative migrations, NFRs, pack dry run, and consumer build pass |
890
+
891
+ The application’s G1 search UI can begin against E3. Application G3 unified
892
+ commands depends on E2. Creator beta requires E5.
893
+
894
+ ## 18. Risks and mitigations
895
+
896
+ | Risk | Consequence | Mitigation |
897
+ | --- | --- | --- |
898
+ | Schema v5 becomes an entire professional NLE | Engine work blocks product indefinitely | Implement only P0 tracks/clips/transforms/dissolve/captions; reserve extensions without building them |
899
+ | Local visual model lacks language or action quality | Search misses the differentiating promise | Provider-neutral multi-vector contract, frozen benchmark, injected alternative providers, progressive model replacement |
900
+ | Reverse video explodes index size or query cost | Poor local performance | ANN candidate generation, bounded ranges, multi-stage rerank, quantization, overlap collapse, measured scale budgets |
901
+ | Runtime indexes drift from semantic sources | Stale or irreproducible results | Object-hash and manifest-qualified coverage, atomic generation activation, pinned hit snapshots |
902
+ | Corrected transcript and provider transcript conflict | Captions/search/edit disagree | One normalized current semantic transcript; raw provider response retained only as provenance artifact |
903
+ | Preview and commit disagree | Unsafe edits | Canonical normalization/hash and mandatory revalidation inside commit boundary |
904
+ | Migration corrupts existing books | Data loss | Copy-forward only, source read-only, preflight/dry run, post-verify, explicit switch |
905
+ | Cross-book requests leak into engine | Broken one-book isolation | Keep engine query book-scoped; application federation includes owning book identity |
906
+ | Model downloads undermine offline trust | Unexpected network/storage use | Explicit prepare, pinned manifests, `allowModelDownload=false`, readiness errors, application consent |
907
+
908
+ ## 19. Definition of engine MVP complete
909
+
910
+ The engine MVP is complete when schema v5 can copy-forward a real schema-v4
911
+ book; normalize transcripts and rational media time; progressively index and
912
+ retrieve judged timecoded moments by language, image/frame, video range, audio
913
+ range, transcript, OCR, metadata, and duplicate evidence; preview and atomically
914
+ commit every P0 edit operation with conflict detection and forward restore;
915
+ survive forced termination across semantic and indexing boundaries; meet the
916
+ frozen quality/performance thresholds; publish cross-repository fixtures; and
917
+ pass typecheck, tests, build, and package dry run without requiring hosted AI
918
+ access.