videobook-engine 5.0.1 → 5.3.2

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 (207) hide show
  1. package/README.md +73 -13
  2. package/dist/artifacts.d.ts +2 -2
  3. package/dist/artifacts.d.ts.map +1 -1
  4. package/dist/artifacts.js +42 -11
  5. package/dist/artifacts.js.map +1 -1
  6. package/dist/cas.d.ts +2 -1
  7. package/dist/cas.d.ts.map +1 -1
  8. package/dist/cas.js +33 -4
  9. package/dist/cas.js.map +1 -1
  10. package/dist/catalog-gc-state.d.ts +4 -0
  11. package/dist/catalog-gc-state.d.ts.map +1 -0
  12. package/dist/catalog-gc-state.js +49 -0
  13. package/dist/catalog-gc-state.js.map +1 -0
  14. package/dist/catalog-metadata.d.ts +1 -1
  15. package/dist/catalog-metadata.js +1 -1
  16. package/dist/context.d.ts +2 -0
  17. package/dist/context.d.ts.map +1 -1
  18. package/dist/context.js +7 -1
  19. package/dist/context.js.map +1 -1
  20. package/dist/domain.d.ts.map +1 -1
  21. package/dist/domain.js +2 -2
  22. package/dist/domain.js.map +1 -1
  23. package/dist/edits.js +2 -2
  24. package/dist/edits.js.map +1 -1
  25. package/dist/engine-types.d.ts +97 -12
  26. package/dist/engine-types.d.ts.map +1 -1
  27. package/dist/engine-types.js +2 -0
  28. package/dist/engine-types.js.map +1 -1
  29. package/dist/engine.d.ts +11 -3
  30. package/dist/engine.d.ts.map +1 -1
  31. package/dist/engine.js +43 -1
  32. package/dist/engine.js.map +1 -1
  33. package/dist/files.d.ts +10 -0
  34. package/dist/files.d.ts.map +1 -1
  35. package/dist/files.js +48 -1
  36. package/dist/files.js.map +1 -1
  37. package/dist/fork.d.ts +11 -28
  38. package/dist/fork.d.ts.map +1 -1
  39. package/dist/fork.js +5 -7
  40. package/dist/fork.js.map +1 -1
  41. package/dist/history.js +10 -9
  42. package/dist/history.js.map +1 -1
  43. package/dist/index.d.ts +1 -1
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +1 -1
  46. package/dist/index.js.map +1 -1
  47. package/dist/inline-temporal-models.d.ts +43 -0
  48. package/dist/inline-temporal-models.d.ts.map +1 -0
  49. package/dist/inline-temporal-models.js +236 -0
  50. package/dist/inline-temporal-models.js.map +1 -0
  51. package/dist/isolated-models.d.ts +8 -0
  52. package/dist/isolated-models.d.ts.map +1 -0
  53. package/dist/isolated-models.js +25 -0
  54. package/dist/isolated-models.js.map +1 -0
  55. package/dist/job-queue.d.ts +1 -1
  56. package/dist/job-queue.d.ts.map +1 -1
  57. package/dist/job-queue.js +20 -6
  58. package/dist/job-queue.js.map +1 -1
  59. package/dist/media-image.d.ts +8 -0
  60. package/dist/media-image.d.ts.map +1 -0
  61. package/dist/media-image.js +41 -0
  62. package/dist/media-image.js.map +1 -0
  63. package/dist/media-process.d.ts +13 -0
  64. package/dist/media-process.d.ts.map +1 -0
  65. package/dist/media-process.js +89 -0
  66. package/dist/media-process.js.map +1 -0
  67. package/dist/merge-policy.d.ts +6 -10
  68. package/dist/merge-policy.d.ts.map +1 -1
  69. package/dist/merge-policy.js +5 -10
  70. package/dist/merge-policy.js.map +1 -1
  71. package/dist/metadata.d.ts +1 -0
  72. package/dist/metadata.d.ts.map +1 -1
  73. package/dist/metadata.js +11 -0
  74. package/dist/metadata.js.map +1 -1
  75. package/dist/migrate-grid-text.d.ts +17 -0
  76. package/dist/migrate-grid-text.d.ts.map +1 -0
  77. package/dist/migrate-grid-text.js +117 -0
  78. package/dist/migrate-grid-text.js.map +1 -0
  79. package/dist/migrate-grid-v22.d.ts +12 -0
  80. package/dist/migrate-grid-v22.d.ts.map +1 -0
  81. package/dist/migrate-grid-v22.js +166 -0
  82. package/dist/migrate-grid-v22.js.map +1 -0
  83. package/dist/migrate-grid-v23.d.ts +10 -0
  84. package/dist/migrate-grid-v23.d.ts.map +1 -0
  85. package/dist/migrate-grid-v23.js +31 -0
  86. package/dist/migrate-grid-v23.js.map +1 -0
  87. package/dist/migration-notebooks.d.ts +25 -0
  88. package/dist/migration-notebooks.d.ts.map +1 -0
  89. package/dist/migration-notebooks.js +131 -0
  90. package/dist/migration-notebooks.js.map +1 -0
  91. package/dist/migration-source.d.ts +6 -0
  92. package/dist/migration-source.d.ts.map +1 -0
  93. package/dist/migration-source.js +37 -0
  94. package/dist/migration-source.js.map +1 -0
  95. package/dist/migration-timeline.d.ts +36 -0
  96. package/dist/migration-timeline.d.ts.map +1 -0
  97. package/dist/migration-timeline.js +187 -0
  98. package/dist/migration-timeline.js.map +1 -0
  99. package/dist/migration-validation.d.ts +12 -0
  100. package/dist/migration-validation.d.ts.map +1 -0
  101. package/dist/migration-validation.js +68 -0
  102. package/dist/migration-validation.js.map +1 -0
  103. package/dist/migration.d.ts.map +1 -1
  104. package/dist/migration.js +188 -117
  105. package/dist/migration.js.map +1 -1
  106. package/dist/model-cache-paths.d.ts +2 -0
  107. package/dist/model-cache-paths.d.ts.map +1 -0
  108. package/dist/model-cache-paths.js +5 -0
  109. package/dist/model-cache-paths.js.map +1 -0
  110. package/dist/model-checksums.json +338 -0
  111. package/dist/model-file-resolver.d.ts +30 -0
  112. package/dist/model-file-resolver.d.ts.map +1 -0
  113. package/dist/model-file-resolver.js +304 -0
  114. package/dist/model-file-resolver.js.map +1 -0
  115. package/dist/model-identity.d.ts +13 -0
  116. package/dist/model-identity.d.ts.map +1 -0
  117. package/dist/model-identity.js +44 -0
  118. package/dist/model-identity.js.map +1 -0
  119. package/dist/model-worker-errors.d.ts +3 -0
  120. package/dist/model-worker-errors.d.ts.map +1 -0
  121. package/dist/model-worker-errors.js +12 -0
  122. package/dist/model-worker-errors.js.map +1 -0
  123. package/dist/model-worker-pool.d.ts +32 -0
  124. package/dist/model-worker-pool.d.ts.map +1 -0
  125. package/dist/model-worker-pool.js +269 -0
  126. package/dist/model-worker-pool.js.map +1 -0
  127. package/dist/model-worker-protocol.d.ts +42 -0
  128. package/dist/model-worker-protocol.d.ts.map +1 -0
  129. package/dist/model-worker-protocol.js +2 -0
  130. package/dist/model-worker-protocol.js.map +1 -0
  131. package/dist/model-worker.d.ts +2 -0
  132. package/dist/model-worker.d.ts.map +1 -0
  133. package/dist/model-worker.js +91 -0
  134. package/dist/model-worker.js.map +1 -0
  135. package/dist/mvp-contracts.d.ts +31 -7
  136. package/dist/mvp-contracts.d.ts.map +1 -1
  137. package/dist/mvp-contracts.js +1 -1
  138. package/dist/mvp-contracts.js.map +1 -1
  139. package/dist/notebook-grid.d.ts +13 -4
  140. package/dist/notebook-grid.d.ts.map +1 -1
  141. package/dist/notebook-grid.js +35 -8
  142. package/dist/notebook-grid.js.map +1 -1
  143. package/dist/notebook-mentions.d.ts +1 -1
  144. package/dist/notebook-mentions.d.ts.map +1 -1
  145. package/dist/notebook-mentions.js +2 -1
  146. package/dist/notebook-mentions.js.map +1 -1
  147. package/dist/schema.d.ts +2 -1
  148. package/dist/schema.d.ts.map +1 -1
  149. package/dist/schema.js +7 -4
  150. package/dist/schema.js.map +1 -1
  151. package/dist/search-provider-access.d.ts +11 -0
  152. package/dist/search-provider-access.d.ts.map +1 -0
  153. package/dist/search-provider-access.js +42 -0
  154. package/dist/search-provider-access.js.map +1 -0
  155. package/dist/similarity.d.ts +60 -1
  156. package/dist/similarity.d.ts.map +1 -1
  157. package/dist/similarity.js +165 -145
  158. package/dist/similarity.js.map +1 -1
  159. package/dist/store.d.ts +15 -1
  160. package/dist/store.d.ts.map +1 -1
  161. package/dist/store.js +168 -14
  162. package/dist/store.js.map +1 -1
  163. package/dist/temporal-index-cache.d.ts +13 -0
  164. package/dist/temporal-index-cache.d.ts.map +1 -0
  165. package/dist/temporal-index-cache.js +59 -0
  166. package/dist/temporal-index-cache.js.map +1 -0
  167. package/dist/temporal-model-manifests.d.ts +17 -0
  168. package/dist/temporal-model-manifests.d.ts.map +1 -0
  169. package/dist/temporal-model-manifests.js +33 -0
  170. package/dist/temporal-model-manifests.js.map +1 -0
  171. package/dist/temporal-models.d.ts +20 -35
  172. package/dist/temporal-models.d.ts.map +1 -1
  173. package/dist/temporal-models.js +23 -257
  174. package/dist/temporal-models.js.map +1 -1
  175. package/dist/temporal-search.d.ts +6 -3
  176. package/dist/temporal-search.d.ts.map +1 -1
  177. package/dist/temporal-search.js +404 -132
  178. package/dist/temporal-search.js.map +1 -1
  179. package/dist/temporal-vector-index.d.ts +46 -0
  180. package/dist/temporal-vector-index.d.ts.map +1 -0
  181. package/dist/temporal-vector-index.js +220 -0
  182. package/dist/temporal-vector-index.js.map +1 -0
  183. package/dist/third-party/@huggingface-jinja.LICENSE +21 -0
  184. package/dist/third-party/@huggingface-tokenizers.LICENSE +201 -0
  185. package/dist/third-party/@huggingface-transformers.LICENSE +202 -0
  186. package/dist/third-party/onnxruntime-common.LICENSE +21 -0
  187. package/dist/third-party/versions.json +23 -0
  188. package/dist/transformers-runtime.d.ts +2 -0
  189. package/dist/transformers-runtime.d.ts.map +1 -0
  190. package/dist/transformers-runtime.js +33014 -0
  191. package/dist/transformers-runtime.js.LEGAL.txt +12 -0
  192. package/dist/transformers-runtime.js.map +7 -0
  193. package/docs/doltlite-staging.md +69 -0
  194. package/docs/edit-performance.md +83 -0
  195. package/docs/engine-layout.md +42 -31
  196. package/docs/media-limits.md +57 -0
  197. package/docs/model-download-policy.md +15 -0
  198. package/docs/model-integrity.md +72 -0
  199. package/docs/model-isolation.md +72 -0
  200. package/docs/model-revisions.md +54 -0
  201. package/docs/release-evidence.md +300 -0
  202. package/docs/search-provider-consent.md +67 -0
  203. package/docs/semantic-durability.md +55 -0
  204. package/docs/temporal-search-performance.md +260 -0
  205. package/docs/v4-migration.md +83 -0
  206. package/fixtures/v5/contract-fixtures.json +3 -3
  207. package/package.json +19 -13
@@ -0,0 +1,69 @@
1
+ # DoltLite staging and native merge verification
2
+
3
+ The engine pins DoltLite 0.50.6. It includes the fix for
4
+ [dolthub/doltlite#2644](https://github.com/dolthub/doltlite/issues/2644),
5
+ merged in [PR 2646](https://github.com/dolthub/doltlite/pull/2646) and
6
+ published in [0.50.6](https://github.com/dolthub/doltlite/releases/tag/v0.50.6).
7
+ The dependency adoption is tracked in `ve-ovz.23`; the remaining native-merge
8
+ failure stays in `ve-wsu`.
9
+
10
+ ## Fixed: incremental staging corrupts index roots
11
+
12
+ Staging twelve newly created tables individually produced invalid committed
13
+ UNIQUE-index roots on 0.11.37 and 0.50.5. Indexed reads worked before checkout,
14
+ then failed after checking out a branch at the same commit. Both controls now
15
+ pass on 0.50.6:
16
+
17
+ ```sh
18
+ node scripts/dolt-staging-probe.cjs @dolthub/doltlite
19
+ node scripts/dolt-staging-probe.cjs @dolthub/doltlite --stage-all
20
+ ```
21
+
22
+ Full engine URL bootstrap, backed-up catalog cloning, lazy object reads,
23
+ post-clone writes and reopen are verified in `tests/fork-flow.test.ts`.
24
+ `tests/merge-policy.test.ts` verifies repeated full-catalog checkout preserves
25
+ all 56 engine tables, ignored runtime rows, indexed file lookups, and integrity.
26
+ The transcript and primary-sequence tests now perform both native merges
27
+ instead of inserting the second branch's expected rows directly. Native row
28
+ conflicts are mapped to `MERGE_CONFLICT` and preserve the accepted head.
29
+
30
+ The upstream change prevents new corrupt commits; it does not rewrite
31
+ previously corrupted history. Snapshot bootstrap remains available for a
32
+ healthy working catalog whose old committed schema cannot be cloned.
33
+
34
+ ## Remaining: ignored runtime tables block native merge
35
+
36
+ A separate failure reproduces on 0.50.6 with one versioned table and one
37
+ ignored runtime table. Native merge refuses with an uncommitted-changes error
38
+ even after checkout and hard reset. Without an index, `dolt_status` is empty;
39
+ with a secondary runtime index it also incorrectly reports the ignored table
40
+ as modified. The control without the runtime table passes:
41
+
42
+ ```sh
43
+ node scripts/dolt-ignored-merge-probe.cjs @dolthub/doltlite --without-runtime
44
+ node scripts/dolt-ignored-merge-probe.cjs @dolthub/doltlite --without-index
45
+ node scripts/dolt-ignored-merge-probe.cjs @dolthub/doltlite
46
+ ```
47
+
48
+ The latter two commands deliberately exit nonzero when the defect reproduces.
49
+ All probes use temporary synthetic catalogs and remove them on exit. Replace
50
+ the package argument with an absolute installed-package directory to test a
51
+ future dependency version. The engine retains its working projection merge,
52
+ including singleton reconciliation and forget-wins object handling, while
53
+ this native merge gate remains unresolved.
54
+
55
+ A [native source patch with validation and reproduction steps](../patches/doltlite/README.md)
56
+ is now prepared on upstream commit `37a390eb7b021962d9d287a465a2da3c9f59c3cf`.
57
+ It passes 4,156 focused checks including allocation failures, all 126 native
58
+ suites, all 33 C suites, and the full 56-table engine catalog probe. Production
59
+ adoption still requires upstream review and validation of a published native
60
+ build; the dependency remains 0.50.6.
61
+
62
+ Compatibility smoke tests created separate synthetic catalogs with the previous
63
+ engine dependency (0.11.37) and the installed application dependency (0.11.51),
64
+ then opened them in separate 0.50.6 processes. Book identity, head, history
65
+ count, artifact/notebook projections, every table row count, source bytes, and
66
+ the runtime setting were preserved; historical restore, a new write, and
67
+ reopen passed. The engine fixture also retained the same semantic projections.
68
+ Dolt status diagnostics changed between versions and were compared separately
69
+ from stored state. These tests do not claim to repair old corrupt commits.
@@ -0,0 +1,83 @@
1
+ # Edit preview and commit distributions
2
+
3
+ VE-NFR-005, VE-NFR-006 and VE-NFR-009 require a 100-operation batch against a
4
+ 1,000-clip sequence to preview in under 250 ms p95 without storage mutation,
5
+ commit in under 1 second p95 on a healthy local catalog, and preview
6
+ deterministically. `tests/edit-transactions.test.ts` still measures one
7
+ preview and one commit as a coarse regression tripwire; distributions come
8
+ from the dedicated harness:
9
+
10
+ ```bash
11
+ npm run benchmark:edits -- --output /tmp/edit-distribution.json --assert
12
+ ```
13
+
14
+ The harness seeds one video stream and inserts `--clips` one-frame clips
15
+ (default 1,000) through a single edit commit. It then runs `--commits`
16
+ independent transactions (default 50). Every transaction:
17
+
18
+ 1. reads the primary sequence at the current head and builds a fresh
19
+ `--operations`-operation batch (default 100 `set-clip-transform`
20
+ operations on a rotating window of distinct clips, with transform values
21
+ that differ per transaction so each commit changes every addressed clip);
22
+ 2. records the head revision, every table row count and the canonical
23
+ sequence projection, previews the batch (timed as `preview`), and requires
24
+ all three snapshots to be unchanged afterwards;
25
+ 3. previews the identical intent again (timed as `preview.repeat`) and
26
+ requires identical canonical operations, affected ranges, write set,
27
+ diff, before/after hashes and preview hash;
28
+ 4. commits with the preview hash (timed as `commit`), requires the head to
29
+ advance to the returned revision, and requires the committed sequence to
30
+ carry every transform.
31
+
32
+ After the last commit the catalog is closed and reopened, and the reopened
33
+ sequence must expose the final revision and clip count. The report records
34
+ nearest-rank p50/p95/max and every raw sample for `preview`,
35
+ `preview.repeat`, `commit` and the seeding operations, the invariant counters,
36
+ process peak RSS, Node/CPU/memory, source commit and dirty state, and the
37
+ gates: `fullScale` (1,000 clips, 100 operations, 50 commits),
38
+ `previewP95Under250Ms`, `commitP95Under1Second`, `noStorageMutation`,
39
+ `deterministicPreviews` and `everyCommitAdvancedRevision`. `--assert` exits
40
+ nonzero when any gate fails. `tests/edit-benchmark.test.ts` runs a small
41
+ workload and checks the report structure and invariants on every test run.
42
+
43
+ Commit timings exclude derived jobs, which the engine does not start from
44
+ `edits.commit`. The workload uses transform operations only; other operation
45
+ kinds share the same projection, validation and persistence path but are not
46
+ separately measured here.
47
+
48
+ ## Recorded run
49
+
50
+ The [recorded distribution](../benchmarks/results/edit-100x1000-distribution.json)
51
+ measured the working tree on top of engine `8b235f2` on September 6, 2026,
52
+ using an Apple M1 Pro with 16 GB RAM and Node 24.10.0 while no other benchmark
53
+ was running:
54
+
55
+ | Measurement | Samples | p50 | p95 | Max |
56
+ | --- | ---: | ---: | ---: | ---: |
57
+ | Preview (100 operations, 1,000 clips) | 50 | 106 ms | 110 ms | 113 ms |
58
+ | Repeated preview of the same intent | 50 | 106 ms | 110 ms | 112 ms |
59
+ | Commit | 50 | 300 ms | 334 ms | 335 ms |
60
+
61
+ Seeding the 1,000 clips took 142 ms to preview and 297 ms to commit. All 50
62
+ previews left the head revision, row counts and sequence projection unchanged,
63
+ all 50 repeats were identical, all 50 commits advanced the head and applied
64
+ 5,000 transforms, and every gate passed. Process peak RSS was 2.8 GiB
65
+ including the embedded Dolt database. The PRD reference device is an M2 Pro
66
+ with 16 GB RAM; this run does not replace a reference-device measurement.
67
+
68
+ ## DoltLite 0.50.6 candidate
69
+
70
+ Engine `c4f1d89` (5.3.2) was measured from a clean committed tree on the same
71
+ M1 Pro, 16 GB RAM, Node 24.10.0. The
72
+ [complete report](../benchmarks/results/edit-100x1000-doltlite-0506.json)
73
+ records 50 independent 100-operation transactions over 1,000 clips:
74
+
75
+ | Measurement | Samples | p50 | p95 | Max |
76
+ | --- | ---: | ---: | ---: | ---: |
77
+ | Preview | 50 | 105 ms | 114 ms | 118 ms |
78
+ | Repeated preview | 50 | 105 ms | 111 ms | 115 ms |
79
+ | Commit | 50 | 299 ms | 331 ms | 348 ms |
80
+
81
+ All mutation, determinism, revision, and applied-transform gates pass. Peak
82
+ process RSS is 1.54 GiB. These M1 Pro results retain the M2 Pro reference-device
83
+ qualification; `ve-ovz.22` remains outstanding.
@@ -79,6 +79,12 @@ flowchart LR
79
79
  - JSON is stored as canonical text with recursively sorted object keys.
80
80
  - Deletes are hard deletes. Owned rows cascade; live artifact/entity
81
81
  references restrict deletion; prior Dolt revisions remain available.
82
+ `artifacts.delete(id, { deleteOwnedMedia: true })` explicitly removes the
83
+ artifact's streams and transcripts in the same semantic transaction.
84
+ Sequence clips, caption selections, notebook references, and pinned search
85
+ results still block deletion. Omitting the option retains the default
86
+ stream/transcript reference guard. Temporal runtime rows are removed with
87
+ the artifact; prior source and transcript revisions remain readable.
82
88
  - Objects are content-immutable but forgettable. `engine.storage.deleteObject`
83
89
  forgets one object (refusing `IN_USE` references at HEAD unless forced);
84
90
  `engine.storage.gc` sweeps every object nothing references at HEAD.
@@ -265,19 +271,12 @@ are the constraint-verification primitives.
265
271
  both lineages) and two set values keep the earlier timestamp
266
272
  (`resolveObjectsRow` in `src/fork.ts`).
267
273
 
268
- ve-wsu: doltlite currently corrupts secondary UNIQUE indexes on
269
- `dolt_checkout` once a working set has three or more tables, corrupts full
270
- engine catalogs on checkout and `dolt_clone` (the cloned file's schema does
271
- not even parse: `invalid rootpage` on a secondary autoindex), misfires its
272
- "uncommitted changes" merge guard on the full 28-table catalog (every
273
- table reports a phantom `modified` status with zero row diffs), and — when
274
- the guard is bypassed by committing the phantom dirt — dies in schema
275
- loading on true merges (`schema conflict on table 'sqlite_autoindex_*'`).
276
- The dedicated merge-back flow therefore runs this policy around a
277
- projection-level three-way merge instead of `dolt_merge`; see "Forks and
278
- merge-back integration" below. `mergeWithPolicy` remains the drop-in merge
279
- mechanism once the upstream bugs are fixed, exercised against the real
280
- semantic DDL in `tests/merge-policy.test.ts`.
274
+ DoltLite 0.50.6 fixes incremental staging and full-catalog URL cloning.
275
+ Native merge still refuses a catalog containing ignored runtime tables,
276
+ even with an empty semantic diff and, without a secondary runtime index,
277
+ an empty `dolt_status`. `ve-wsu` retains this gate; see the reproductions in
278
+ [docs/doltlite-staging.md](doltlite-staging.md). The dedicated merge-back flow
279
+ keeps its projection merge and application conflict policies.
281
280
 
282
281
  ### Forks and merge-back integration
283
282
 
@@ -286,14 +285,13 @@ A fork of a public book is, from the engine's point of view:
286
285
  1. **A platform fork.** Creating the hosted copy of a catalog and giving
287
286
  it a URL is the hosting layer's job; it is out of engine scope.
288
287
  2. **A clone of the catalog into a local engine root** (`bootstrapFork` in
289
- [`src/fork.ts`](../src/fork.ts)). Because `dolt_clone` corrupts full
290
- catalogs (ve-wsu), bootstrap takes a byte snapshot of a healthy upstream
291
- `videobook.db` (captured while the upstream engine is closed) and opens
292
- it as a normal engine no `initialBookSlug`, the singleton book row
293
- comes along with the snapshot. A URL bootstrap path attempts
294
- `dolt_clone` and health-validates the result, surfacing a typed
295
- `FEATURE_UNAVAILABLE` while the upstream bug stands; it starts working
296
- unchanged once doltlite is fixed.
288
+ [`src/fork.ts`](../src/fork.ts)). A URL bootstrap uses `dolt_clone` and
289
+ validates the resulting schema before opening the engine. It also accepts
290
+ a byte snapshot of a healthy upstream `videobook.db` captured while the
291
+ upstream engine is closed. Both preserve the singleton book row without
292
+ requiring `initialBookName`. The upstream staging fix does not repair
293
+ commits corrupted by older dependencies; those catalogs may still need
294
+ snapshot bootstrap.
297
295
  3. **A public-read object store keyed by SHA-256.** `ContentStore` stays
298
296
  the abstraction; the existing `ensureLocal` lazy fetch in
299
297
  [`src/cas.ts`](../src/cas.ts) downloads any object the fork lacks on
@@ -317,7 +315,7 @@ Integration is a dedicated flow, `mergeBack` in
317
315
  resolve heads and the merge base (`dolt_merge_base`; commit hashes via
318
316
  `dolt_log`/`dolt_branches` — `doltHashOf` returns content hashes, not
319
317
  commit hashes; the fetched remote-tracking ref gets a local branch
320
- pointer, a ref-only write that is safe under ve-wsu).
318
+ pointer without checking out the fetched branch).
321
319
  3. Run the merge policy: same-schema precondition, then a
322
320
  projection-level three-way row merge over `dolt_at_<table>`
323
321
  snapshots of base/ours/theirs (row
@@ -332,14 +330,12 @@ Integration is a dedicated flow, `mergeBack` in
332
330
  `engine.storage.backup`.
333
331
  5. Land one forward integration commit on `main` and `dolt_push` it.
334
332
 
335
- ve-wsu makes a true two-parent `dolt_merge` commit impossible on full
336
- catalogs today, so the integration commit is single-parent and records the
337
- integrated fork head in a `merged-revision` commit-message trailer (plus
338
- `base-revision`, per the structured-message convention). Re-running the
339
- flow is a no-op when the fork's net changes are already on `main`. The
340
- projection merge in `mergeRefs` is the single swap point: when doltlite is
341
- fixed, `mergeWithPolicy` + `dolt_merge` replace it and the commit becomes
342
- a true merge commit.
333
+ The integration commit remains single-parent and records the integrated fork
334
+ head in a `merged-revision` commit-message trailer (plus `base-revision`, per
335
+ the structured-message convention). Re-running the flow is a no-op when the
336
+ fork's net changes are already on `main`. A future native replacement must
337
+ pass the ignored-runtime merge gate in `ve-wsu` and retain singleton
338
+ reconciliation, forget-wins object handling, and object publication ordering.
343
339
 
344
340
  When a plain `engine.storage.backup()` push is rejected because upstream
345
341
  moved, the backup surfaces `DIVERGED` with guidance into this flow —
@@ -490,7 +486,22 @@ the engine deliberately does not implement it.
490
486
  - doltlite exposes `dolt_gc()` as a SQL function (verified: it returns a
491
487
  `"N chunks removed, M chunks kept"` summary). `gc({ doltGc: true })` runs
492
488
  it after collecting to physically reclaim chunks left behind by dropped
493
- table data in the versioned catalog.
489
+ table data in the versioned catalog. The store also GC's automatically
490
+ at open when `videobook.db` exceeds 64 MiB without a verified compaction
491
+ record (configurable via
492
+ `EngineConfig.catalogGc`) and at close after any runtime or semantic
493
+ write, returning a `CatalogGcReport` (`engine.lastCatalogGc` /
494
+ `engine.gcCatalog()`) with the summary and byte delta. GC never mints a
495
+ commit. Periodic GC-after-N-writes is not implemented: cached prepared
496
+ statements would have to be dropped, and `dolt_gc` cannot run inside
497
+ `serial()` or an open transaction.
498
+ - After successful GC, a clean close atomically writes `videobook.db.gc.json`
499
+ with the catalog's device, inode, size, and nanosecond modification/change
500
+ times. An unchanged catalog can then skip repeated open-time compaction.
501
+ Transactions invalidate this disposable record before writing. Missing,
502
+ malformed, mismatched records and nonempty WAL/journal files preserve the
503
+ size-triggered GC fallback. Runtime schema metadata is only rewritten when
504
+ its version changes, avoiding a write on every read-only open.
494
505
  - Run `deleteObject` and `gc` only while no imports are in flight; CAS puts
495
506
  happen outside the serialized write chain, so a concurrent import could
496
507
  race the sweep.
@@ -0,0 +1,57 @@
1
+ # Local media decoding limits
2
+
3
+ Temporal CLIP/CLAP and compatibility similarity use shared bounded decoding
4
+ helpers. FFmpeg and FFprobe run with argument arrays and no shell. Their
5
+ default execution deadline is 120 seconds. A caller can provide a positive,
6
+ finite `timeoutMs` and an `AbortSignal` through `MediaOperationOptions`.
7
+ Cancellation, deadline expiry or excessive output kills the process and waits
8
+ for its close before rejecting, allowing callers to clean temporary workspaces.
9
+
10
+ Standard error is capped at 64 KiB. Probe output is capped at 64 KiB; PCM
11
+ output is capped at the requested sample count times four bytes. Temporal
12
+ CLAP decodes at most ten seconds of 48 kHz mono audio. Other process output
13
+ has an 8 MiB default cap. Decoder failures report typed errors and exit
14
+ information without copying raw stderr, input paths or cancellation reasons
15
+ into the error message. `TIMEOUT`, `CANCELLED`, `RESOURCE_EXHAUSTED`,
16
+ `FEATURE_UNAVAILABLE` and `INVALID_INPUT` distinguish failure categories.
17
+
18
+ FFmpeg input protocols are restricted to `file,pipe`. Compatibility video
19
+ extraction uses a disposable directory, at most 120 PNG frames and a fixed
20
+ 224 by 224 output size, with cleanup in `finally`. These controls do not
21
+ constitute a filesystem sandbox for a decoder.
22
+
23
+ Image inputs must be regular local files no larger than 64 MiB and 40 million
24
+ pixels. Sharp reads only the first image, applies a processing timeout and
25
+ converts to RGB using the existing orientation and colour normalization.
26
+ Accepted images keep the same preprocessing; oversized images fail before
27
+ an unbounded RGB allocation. The pixel cap also limits expansion of compact
28
+ inputs such as large SVG canvases. No global Sharp settings are changed.
29
+
30
+ Compatibility preparation/index/query methods forward media options to their
31
+ providers. Indexing checks cancellation before publishing runtime coverage.
32
+ Temporal providers accept media options directly:
33
+
34
+ ```ts
35
+ await clip.embedImage(path, { signal });
36
+ await clap.embedAudio(path, 0, 10, { signal, timeoutMs: 30_000 });
37
+ await engine.similarity.index(artifactId, { signal });
38
+ ```
39
+
40
+ `tests/media-limits.test.ts` uses actual child processes for stalled/noisy
41
+ output, literal arguments, abort-before-spawn, running cancellation and safe
42
+ errors. Real Sharp fixtures cover malformed, oversized and high-expansion
43
+ images. A scoped engine fixture verifies failed decoding leaves source data
44
+ and prior coverage intact and allows retry. The opt-in cached CLIP/CLAP and
45
+ compatibility E2E tests verify real JPEG/MP4/WAV decoding, CLAP timeout and
46
+ cancellation, malformed audio and successful retry.
47
+
48
+ Built-in model loading, inference and Sharp decoding now run in the isolated
49
+ process pool described in `docs/model-isolation.md`. Its outer deadline and
50
+ process-group cancellation cover native work that cannot observe an AbortSignal
51
+ inside the call. Sharp's own processing deadline is rounded up to seconds.
52
+ Consumer `09647d69` forwards job cancellation through its provider overrides
53
+ and indexing/reference calls. Actual queue tests cancel stalled model requests,
54
+ preserve source bytes and ready status, fail malformed-image indexing with a
55
+ typed error, and successfully index a corrected retry. Audio-only indexing uses
56
+ CLAP without passing its source to the image decoder. A cancelled completed
57
+ batch is rejected before coverage publication, preserving the last cursor.
@@ -0,0 +1,15 @@
1
+ # Local model download policy
2
+
3
+ Temporal CLIP/CLAP and compatibility image, audio, and text similarity loaders use local files unless `allowModelDownload` is explicitly `true`. A missing or unusable model returns `OFFLINE` when downloads are disabled. An application should offer an explicit preparation step, then use the populated cache for ordinary search and indexing.
4
+
5
+ The pinned Transformers.js 4.2.0 dependency drops `cache_dir`, `local_files_only`, and `revision` during metadata discovery in `pipeline`, `loadTokenizer`, and the model-registry file-list helpers. Without correction, even cached or local-only preparation can request metadata from `main`.
6
+
7
+ `scripts/patch-transformers.mjs` corrects option forwarding in the dependency's Node ESM entry before tests and bundling. It checks the dependency version and exact source fragments, is idempotent, and fails when those fragments change. The packaged runtime includes this correction; applications do not need Transformers.js installed separately. The third-party version manifest records `model-discovery-options-v1`. Review and remove the patch when a verified upstream version preserves these options throughout discovery.
8
+
9
+ `tests/model-download-policy.test.ts` uses a real HTTP server to count requests. It checks zero requests with absent or false permission across temporal and compatibility providers, and pinned requests with explicit permission. The real-model transfer test serves the existing pinned snapshots from a local fixture cache into an empty destination, then prepares new providers and repeats inference with downloads omitted. It requires an explicit test opt-in and never accesses the public Hub:
10
+
11
+ ```bash
12
+ VIDEOBOOK_RUN_MODEL_POLICY_E2E=1 npm test -- tests/model-download-policy.e2e.test.ts
13
+ ```
14
+
15
+ The source fixture cache defaults to `~/.cache/videobook/models`; override it with `VIDEOBOOK_MODEL_FIXTURE_CACHE`. It must already contain the pinned CLIP and CLAP snapshots used by the engine. This Transformers.js cache layout differs from the Hugging Face Hub CLI cache layout.
@@ -0,0 +1,72 @@
1
+ # Model file integrity
2
+
3
+ Built-in model workers verify model files before the loader receives either
4
+ bytes or an ONNX file path. This covers configuration, tokenizers, processors,
5
+ model graphs and external ONNX weight shards. A verification error returns
6
+ `MODEL_UNAVAILABLE`; no corrupted download is published to the model cache.
7
+ Integrity failures remain fatal even if an upstream optional-file loader catches
8
+ the initial exception. They are not reported as missing-model readiness.
9
+
10
+ `src/model-checksums.json` records the complete file inventories of the three
11
+ built-in pinned CLIP, CLAP and MiniLM snapshots. The hashes and sizes come from
12
+ the Hugging Face repository tree at each exact revision. Git files use Git blob
13
+ SHA-1, including the `blob <byte-count>\0` prefix; LFS files use content SHA-256.
14
+ The distinction follows the [Hub file metadata contract](https://huggingface.co/docs/huggingface_hub/en/package_reference/file_download).
15
+ Existing built-in caches can therefore be verified offline without adding a
16
+ network dependency or changing the Transformers cache directory layout.
17
+
18
+ The checksums are for these revisions:
19
+
20
+ - [CLIP d15189d7](https://huggingface.co/Xenova/clip-vit-base-patch32/tree/d15189d7028b43f1d3e65039190477f6af591c2a)
21
+ - [CLAP c28f2883](https://huggingface.co/Xenova/clap-htsat-unfused/tree/c28f2883575e590e04d3146ff0713c2448d691ba)
22
+ - [MiniLM aff7a1dc](https://huggingface.co/onnx-community/all-MiniLM-L6-v2-ONNX/tree/aff7a1dc4e8a1ea593e6ea21e95c22ef0a25966f)
23
+
24
+ Maintainers can regenerate the inventories with
25
+ `node scripts/update-model-checksums.mjs`, using the installed `hf` CLI. Review
26
+ the generated diff and keep model revision constants and inventories aligned.
27
+ Builds and ordinary model use never run this networked maintenance command.
28
+
29
+ For other remote models, the resolver checks a supported strong ETag or
30
+ `X-Linked-ETag` on the original model response. Redirects retain that digest;
31
+ CDN ETags and Xet chunk identifiers are not substituted for the original file
32
+ hash. Authorization tokens are sent only to `https://huggingface.co`, and
33
+ redirects cannot downgrade HTTPS. If upstream supplies no supported checksum,
34
+ the cache receipt records a transport SHA-256 for subsequent corruption
35
+ detection, explicitly distinct from upstream verification.
36
+
37
+ Custom remote-model cache files without integrity metadata require an explicit
38
+ online preparation before offline use. Explicit local model directories remain
39
+ application-trusted inputs with no implied upstream authenticity. Local cache
40
+ receipts detect corruption; they do not defend against someone deliberately
41
+ rewriting both a custom model and its receipt with local filesystem access.
42
+
43
+ Each worker reads a cached file into its own verified snapshot before use. The
44
+ loader never receives the original mutable cache path. Relative names and
45
+ directory layout are retained so ONNX external data stays adjacent to its graph.
46
+ Loaded models and verified snapshots are reused within that worker. A new worker
47
+ verifies cached bytes again. Changing a cache file cannot change an already
48
+ verified worker snapshot.
49
+
50
+ Downloads stream into the owned worker workspace, are verified, then are copied
51
+ to an owned staging directory under the configured cache and atomically renamed.
52
+ Receipts are published separately; interrupted publication can require another
53
+ preparation for a custom model but cannot authorize mismatching bytes. Parent
54
+ cancellation, eviction and exit remove owned worker and cache-staging files.
55
+ Files are capped at 2 GiB and in-memory metadata returns at 16 MiB. The existing
56
+ worker deadlines, process limits and cancellation cover hashing and transfer.
57
+
58
+ An invalid existing cache entry is left intact for diagnosis. Remove or restore
59
+ the affected entry, then explicitly prepare the model to retry. Preparing does
60
+ not silently delete a corrupt file. The Hugging Face CLI's `hf cache verify`
61
+ supports `--local-dir` pointing at one Transformers model/revision directory
62
+ when an administrator needs a file-level audit.
63
+
64
+ Tests cover Git and LFS digests, redirects, unsupported metadata, corrupt
65
+ downloads and receipts, offline corruption, concurrent loads, snapshot isolation,
66
+ path/size limits, and killed cache-staging cleanup. Real-model tests transfer and
67
+ reuse CLIP/CLAP, reject modified JSON/tokenizer/ONNX bytes, and exercise MiniLM
68
+ external weights, offline reopen and a corrupt weight shard. The installed
69
+ package smoke always checks corrupted pinned configuration rejection and can
70
+ also run real cached model inference.
71
+
72
+ Custom remote compatibility models also require an explicit immutable commit. See [model revision selection](model-revisions.md) for coherent file loading, embedding-space isolation and migration from moving aliases. Explicit local-directory models remain trusted local inputs.
@@ -0,0 +1,72 @@
1
+ # Local model process isolation
2
+
3
+ Built-in temporal CLIP/CLAP and compatibility image/video/audio/text providers
4
+ load models and perform inference in child processes. Workers receive only
5
+ the selected text or absolute media path and a projected model configuration.
6
+ They do not receive an Engine, a catalog handle, book metadata, job payloads
7
+ or general provider credentials, and never open a book database.
8
+
9
+ Each calling Node process shares a pool of at most two model workers, keyed
10
+ by model/cache/download configuration. Calls to one worker are serialized;
11
+ the pool accepts at most 64 waiting calls. Matching workers reuse loaded models.
12
+ Idle workers are evicted when another configuration needs capacity or after
13
+ 30 seconds. They do not keep the host process alive. Host exit kills cached
14
+ workers and removes their owned scratch directories.
15
+
16
+ The worker environment includes basic executable/home/temp/locale settings.
17
+ Hugging Face token variables are forwarded only when downloads are explicitly
18
+ enabled. Provider keys, arbitrary environment variables and `NODE_OPTIONS`
19
+ are excluded. The existing Transformers remote-host/local-model settings are
20
+ projected into the worker so pinned offline discovery and configured mirrors
21
+ retain their behavior. Arbitrary JavaScript fetch hooks are not serialized.
22
+
23
+ Preparation defaults to a 15-minute deadline, covering explicit first-time
24
+ downloads. Inference defaults to two minutes, including waiting for a worker.
25
+ `MediaOperationOptions.timeoutMs` overrides the deadline; `signal` cancels a
26
+ queued call without affecting active work, or kills the active worker and its
27
+ decoder process group. A request resolves or rejects after required worker
28
+ cleanup. The next call after a failure starts a fresh process. Applications
29
+ must forward their job signal through provider overrides and calls.
30
+
31
+ Workers have a 512 MiB V8 heap limit. Model weights and native allocations are
32
+ outside that heap limit; it is not a total-RSS operating-system sandbox.
33
+ Input text is capped at 1 MiB, media paths at 4 KiB, IPC messages at 2 MiB and
34
+ diagnostic output at 64 KiB. Returned vector dimensions, finite values, text
35
+ offsets and video frame counts are validated before use. Media decoding also
36
+ uses the limits in `docs/media-limits.md`.
37
+
38
+ A fatal worker allocation failure or abrupt termination returns a typed
39
+ `RESOURCE_EXHAUSTED` or `MODEL_UNAVAILABLE` error to the host. Ordinary allocator
40
+ errors are classified as resource exhaustion even when a model loader wrapped
41
+ them in an offline-readiness error. Unrecognized exceptions do not forward
42
+ model inputs or raw native diagnostics. No semantic transaction spans an
43
+ inference call, and cancellation is checked before index coverage publication.
44
+
45
+ `tests/model-worker-pool.test.ts` uses actual child processes to verify reuse,
46
+ capacity, queue cancellation, blocked execution, decoder descendants, invalid
47
+ responses, environment filtering, idle cleanup and host-exit cleanup. A worker
48
+ with a deliberately small heap is exhausted while a real engine remains open;
49
+ the test then writes, reopens the book and successfully starts another worker.
50
+ An additional durable QueueRunner test records the allocation failure as a
51
+ failed job with `RESOURCE_EXHAUSTED`, then completes another job successfully.
52
+ QueueRunner preserves EngineFault codes instead of replacing them with the
53
+ exception class name.
54
+ This is a real V8 allocation failure, not a simulation of physical disk failure
55
+ or whole-machine memory pressure. `tests/local-models.e2e.test.ts`, compatibility
56
+ media E2E and the model-transfer fixture exercise actual models through the
57
+ same transport. The package smoke also starts the installed JavaScript worker,
58
+ checks missing-cache offline failure, and can run cached CLIP/CLAP inference.
59
+
60
+ The worker entry is compiled into the package and declared as an executable
61
+ entry in the dead-code configuration. Source tests use the installed `tsx`
62
+ loader; installed packages use JavaScript and need no `tsx` dependency.
63
+
64
+ Consumer `09647d69` vendors engine `da41904` and forwards cancellation through
65
+ all provider overrides and index/reference jobs. Local HTTP fixtures hold model
66
+ requests open until actual queue cancellation kills the worker and closes its
67
+ connections. Preparation failures and cancellation leave source artifacts ready
68
+ and byte-identical. Reference-preparation jobs are detached from source artifact
69
+ status, as indexing jobs already were. Missing-model offline readiness remains
70
+ deferred; execution failures fail the auxiliary job with their engine code.
71
+ Cached-model queue tests cover malformed-image failure and corrected retry, plus
72
+ audio-only indexing without invoking the image decoder.
@@ -0,0 +1,54 @@
1
+ # Immutable model revision selection
2
+
3
+ Built-in CLIP, CLAP and MiniLM models continue to use their existing pinned commits. No new model setting is needed for their default configuration. The compatibility image/video vector cache requires a one-time reindex, as described below. Temporal, audio and text default embedding identities are unchanged.
4
+
5
+ For a custom remote model used by the compatibility similarity API, supply `modelRevision` alongside `modelId`. It must be a full 40-character hexadecimal commit SHA from that model repository. Branch names, tags, abbreviated hashes and omitted custom revisions fail with `INVALID_INPUT` before any model request. Uppercase hashes are normalized to lowercase.
6
+
7
+ ```typescript
8
+ const engine = createEngine({
9
+ rootDir,
10
+ similarity: {
11
+ modelCacheDir,
12
+ modelId: "your-org/compatible-clip",
13
+ modelRevision: clipCommitSha,
14
+ allowModelDownload: true,
15
+ audio: {
16
+ modelId: "your-org/compatible-clap",
17
+ modelRevision: clapCommitSha,
18
+ },
19
+ text: {
20
+ modelId: "your-org/compatible-minilm",
21
+ modelRevision: textCommitSha,
22
+ },
23
+ },
24
+ });
25
+ const prepared = await engine.similarity.prepare();
26
+ ```
27
+
28
+ Each `*CommitSha` variable above is the actual full commit ID selected by the application. The engine does not resolve a moving alias implicitly. Supplying another commit for a built-in repository is also supported and creates a distinct custom embedding identity. Audio and text select their own repositories and revisions; they do not inherit the visual model selection. The existing cache-directory and download-permission inheritance rules are unchanged.
29
+
30
+ Custom models must remain compatible with the corresponding pipeline: 512-dimensional CLIP image/video embeddings, 512-dimensional CLAP audio embeddings or 384-dimensional MiniLM text embeddings, with the supported quantization and preprocessing. Selecting a commit does not make an incompatible model architecture compatible.
31
+
32
+ ## Coherent loading and index identity
33
+
34
+ The selected repository and commit are copied into the model worker configuration and worker-session key. Every model-file request must agree with them, including tokenizer/config files and external ONNX weights. A request for another repository, another commit or an omitted/moving revision fails with `MODEL_UNAVAILABLE`. Remote selections do not fall back to unversioned files under Transformers' `localModelPath`; use an explicit directory model ID for trusted local files.
35
+
36
+ Custom embedding-space identities include the provider kind, exact repository, full revision and preprocessing version through a SHA-256 digest. Repository names that previously collided after punctuation normalization now remain distinct. A different revision cannot reuse vectors from an existing space, even while the old model worker is warm. Changing a caller's configuration object after Engine construction does not alter the selected model.
37
+
38
+ Existing custom-model vector identities intentionally change. Reindex custom-model artifacts after supplying the commit. The API shape remains source-compatible on version 5.3.1, but old custom remote configurations without a commit now fail closed rather than loading `main`.
39
+
40
+ Older compatibility image/video vectors are ambiguous: custom image models previously used the same embedding-space string as the built-in CLIP model, without recording which model produced a row. The compatibility visual space now uses `compat-visual-v2`, including for the default model. This requires a one-time reindex of compatibility image/video artifacts and prevents old custom vectors from silently being treated as built-in vectors. Until reindexed, status returns `not_indexed` and similarity queries return `NOT_READY`. Source media and the old derived rows remain intact. The media library's temporal index and the default compatibility audio/text spaces retain their identities; model files do not need to be downloaded again.
41
+
42
+ Model downloads still require explicit permission. After online preparation, the selected revision's verified cached files and integrity receipts support offline preparation, indexing and queries. Changing to a revision that is not cached returns `OFFLINE`; it does not substitute another revision. [Model integrity verification](model-integrity.md) describes digest verification and its trust boundary for custom repositories.
43
+
44
+ ## Local directories
45
+
46
+ Absolute paths and explicit relative paths beginning with `.` remain supported as trusted local model directories, without `modelRevision` or network access. Relative paths are resolved when the provider is configured. Equivalent resolved paths share an identity; different directory paths have distinct identities. `modelRevision` applies only to remote repositories and is rejected for directory selections.
47
+
48
+ Keep each local model version in a separate immutable directory. Local directories do not carry a verified upstream commit, and their contents are not authenticated as a remote snapshot. Replacing files in place requires application-owned reindexing; the engine does not claim that a path alone makes local bytes immutable.
49
+
50
+ Injected embedding providers manage their own model identity and revisions. These options apply to built-in loader implementations, not to arbitrary injected code. Injected providers remain subject to the [network declaration and application consent contract](search-provider-consent.md).
51
+
52
+ ## Verification
53
+
54
+ `tests/model-revision.test.ts` uses actual Engine APIs and an HTTP receiver to cover rejected revisions with zero requests, all three modalities' pinned requests, separate identities, configuration snapshots, local-directory selection, and cross-repository/revision file rejection. `tests/model-revision.e2e.test.ts`, enabled by `VIDEOBOOK_RUN_CUSTOM_MODEL_E2E=1`, serves real cached CLIP/CLAP/MiniLM files under custom repository IDs and verifies coherent revision requests, indexing, offline reopen, revision isolation, retained source bytes and explicit local-directory inference. It requires the three fixture models to have been prepared separately; it does not download them from an external service.