videobook-engine 4.2.0 → 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 (244) hide show
  1. package/README.md +84 -39
  2. package/dist/artifacts.d.ts +5 -10
  3. package/dist/artifacts.d.ts.map +1 -1
  4. package/dist/artifacts.js +79 -142
  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 +16 -9
  9. package/dist/books.js.map +1 -1
  10. package/dist/cas.d.ts +2 -1
  11. package/dist/cas.d.ts.map +1 -1
  12. package/dist/cas.js +33 -4
  13. package/dist/cas.js.map +1 -1
  14. package/dist/catalog-gc-state.d.ts +4 -0
  15. package/dist/catalog-gc-state.d.ts.map +1 -0
  16. package/dist/catalog-gc-state.js +49 -0
  17. package/dist/catalog-gc-state.js.map +1 -0
  18. package/dist/catalog-metadata.d.ts +2 -2
  19. package/dist/catalog-metadata.js +3 -3
  20. package/dist/catalog-metadata.js.map +1 -1
  21. package/dist/context.d.ts +5 -5
  22. package/dist/context.d.ts.map +1 -1
  23. package/dist/context.js +17 -49
  24. package/dist/context.js.map +1 -1
  25. package/dist/domain.d.ts +35 -2
  26. package/dist/domain.d.ts.map +1 -1
  27. package/dist/domain.js +131 -161
  28. package/dist/domain.js.map +1 -1
  29. package/dist/edits.js +2 -2
  30. package/dist/edits.js.map +1 -1
  31. package/dist/engine-types.d.ts +159 -39
  32. package/dist/engine-types.d.ts.map +1 -1
  33. package/dist/engine-types.js +2 -1
  34. package/dist/engine-types.js.map +1 -1
  35. package/dist/engine.d.ts +30 -20
  36. package/dist/engine.d.ts.map +1 -1
  37. package/dist/engine.js +46 -4
  38. package/dist/engine.js.map +1 -1
  39. package/dist/files.d.ts +10 -0
  40. package/dist/files.d.ts.map +1 -1
  41. package/dist/files.js +49 -2
  42. package/dist/files.js.map +1 -1
  43. package/dist/fork.d.ts +14 -30
  44. package/dist/fork.d.ts.map +1 -1
  45. package/dist/fork.js +18 -27
  46. package/dist/fork.js.map +1 -1
  47. package/dist/generations.d.ts +9 -0
  48. package/dist/generations.d.ts.map +1 -0
  49. package/dist/generations.js +175 -0
  50. package/dist/generations.js.map +1 -0
  51. package/dist/history.d.ts +2 -1
  52. package/dist/history.d.ts.map +1 -1
  53. package/dist/history.js +30 -57
  54. package/dist/history.js.map +1 -1
  55. package/dist/index.d.ts +8 -6
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/index.js +5 -5
  58. package/dist/index.js.map +1 -1
  59. package/dist/inline-temporal-models.d.ts +43 -0
  60. package/dist/inline-temporal-models.d.ts.map +1 -0
  61. package/dist/inline-temporal-models.js +236 -0
  62. package/dist/inline-temporal-models.js.map +1 -0
  63. package/dist/isolated-models.d.ts +8 -0
  64. package/dist/isolated-models.d.ts.map +1 -0
  65. package/dist/isolated-models.js +25 -0
  66. package/dist/isolated-models.js.map +1 -0
  67. package/dist/job-queue.d.ts +1 -1
  68. package/dist/job-queue.d.ts.map +1 -1
  69. package/dist/job-queue.js +20 -6
  70. package/dist/job-queue.js.map +1 -1
  71. package/dist/media-image.d.ts +8 -0
  72. package/dist/media-image.d.ts.map +1 -0
  73. package/dist/media-image.js +41 -0
  74. package/dist/media-image.js.map +1 -0
  75. package/dist/media-process.d.ts +13 -0
  76. package/dist/media-process.d.ts.map +1 -0
  77. package/dist/media-process.js +89 -0
  78. package/dist/media-process.js.map +1 -0
  79. package/dist/media.d.ts +3 -3
  80. package/dist/media.d.ts.map +1 -1
  81. package/dist/media.js +5 -5
  82. package/dist/media.js.map +1 -1
  83. package/dist/merge-policy.d.ts +16 -36
  84. package/dist/merge-policy.d.ts.map +1 -1
  85. package/dist/merge-policy.js +13 -125
  86. package/dist/merge-policy.js.map +1 -1
  87. package/dist/metadata.d.ts +1 -0
  88. package/dist/metadata.d.ts.map +1 -1
  89. package/dist/metadata.js +13 -3
  90. package/dist/metadata.js.map +1 -1
  91. package/dist/migrate-grid-text.d.ts +17 -0
  92. package/dist/migrate-grid-text.d.ts.map +1 -0
  93. package/dist/migrate-grid-text.js +117 -0
  94. package/dist/migrate-grid-text.js.map +1 -0
  95. package/dist/migrate-grid-v22.d.ts +12 -0
  96. package/dist/migrate-grid-v22.d.ts.map +1 -0
  97. package/dist/migrate-grid-v22.js +166 -0
  98. package/dist/migrate-grid-v22.js.map +1 -0
  99. package/dist/migrate-grid-v23.d.ts +10 -0
  100. package/dist/migrate-grid-v23.d.ts.map +1 -0
  101. package/dist/migrate-grid-v23.js +31 -0
  102. package/dist/migrate-grid-v23.js.map +1 -0
  103. package/dist/migration-notebooks.d.ts +25 -0
  104. package/dist/migration-notebooks.d.ts.map +1 -0
  105. package/dist/migration-notebooks.js +131 -0
  106. package/dist/migration-notebooks.js.map +1 -0
  107. package/dist/migration-source.d.ts +6 -0
  108. package/dist/migration-source.d.ts.map +1 -0
  109. package/dist/migration-source.js +37 -0
  110. package/dist/migration-source.js.map +1 -0
  111. package/dist/migration-timeline.d.ts +36 -0
  112. package/dist/migration-timeline.d.ts.map +1 -0
  113. package/dist/migration-timeline.js +187 -0
  114. package/dist/migration-timeline.js.map +1 -0
  115. package/dist/migration-validation.d.ts +12 -0
  116. package/dist/migration-validation.d.ts.map +1 -0
  117. package/dist/migration-validation.js +68 -0
  118. package/dist/migration-validation.js.map +1 -0
  119. package/dist/migration.d.ts.map +1 -1
  120. package/dist/migration.js +220 -119
  121. package/dist/migration.js.map +1 -1
  122. package/dist/model-cache-paths.d.ts +2 -0
  123. package/dist/model-cache-paths.d.ts.map +1 -0
  124. package/dist/model-cache-paths.js +5 -0
  125. package/dist/model-cache-paths.js.map +1 -0
  126. package/dist/model-checksums.json +338 -0
  127. package/dist/model-file-resolver.d.ts +30 -0
  128. package/dist/model-file-resolver.d.ts.map +1 -0
  129. package/dist/model-file-resolver.js +304 -0
  130. package/dist/model-file-resolver.js.map +1 -0
  131. package/dist/model-identity.d.ts +13 -0
  132. package/dist/model-identity.d.ts.map +1 -0
  133. package/dist/model-identity.js +44 -0
  134. package/dist/model-identity.js.map +1 -0
  135. package/dist/model-worker-errors.d.ts +3 -0
  136. package/dist/model-worker-errors.d.ts.map +1 -0
  137. package/dist/model-worker-errors.js +12 -0
  138. package/dist/model-worker-errors.js.map +1 -0
  139. package/dist/model-worker-pool.d.ts +32 -0
  140. package/dist/model-worker-pool.d.ts.map +1 -0
  141. package/dist/model-worker-pool.js +269 -0
  142. package/dist/model-worker-pool.js.map +1 -0
  143. package/dist/model-worker-protocol.d.ts +42 -0
  144. package/dist/model-worker-protocol.d.ts.map +1 -0
  145. package/dist/model-worker-protocol.js +2 -0
  146. package/dist/model-worker-protocol.js.map +1 -0
  147. package/dist/model-worker.d.ts +2 -0
  148. package/dist/model-worker.d.ts.map +1 -0
  149. package/dist/model-worker.js +91 -0
  150. package/dist/model-worker.js.map +1 -0
  151. package/dist/mvp-contract-fixtures.js +1 -1
  152. package/dist/mvp-contract-fixtures.js.map +1 -1
  153. package/dist/mvp-contracts.d.ts +32 -8
  154. package/dist/mvp-contracts.d.ts.map +1 -1
  155. package/dist/mvp-contracts.js +1 -1
  156. package/dist/mvp-contracts.js.map +1 -1
  157. package/dist/notebook/types.d.ts +1 -29
  158. package/dist/notebook/types.d.ts.map +1 -1
  159. package/dist/notebook-grid.d.ts +46 -0
  160. package/dist/notebook-grid.d.ts.map +1 -0
  161. package/dist/notebook-grid.js +187 -0
  162. package/dist/notebook-grid.js.map +1 -0
  163. package/dist/notebook-media-artifact.d.ts +23 -0
  164. package/dist/notebook-media-artifact.d.ts.map +1 -0
  165. package/dist/notebook-media-artifact.js +67 -0
  166. package/dist/notebook-media-artifact.js.map +1 -0
  167. package/dist/notebook-mentions.d.ts +20 -0
  168. package/dist/notebook-mentions.d.ts.map +1 -0
  169. package/dist/notebook-mentions.js +54 -0
  170. package/dist/notebook-mentions.js.map +1 -0
  171. package/dist/runtime-services.js +4 -9
  172. package/dist/runtime-services.js.map +1 -1
  173. package/dist/schema.d.ts +4 -19
  174. package/dist/schema.d.ts.map +1 -1
  175. package/dist/schema.js +66 -92
  176. package/dist/schema.js.map +1 -1
  177. package/dist/search-provider-access.d.ts +11 -0
  178. package/dist/search-provider-access.d.ts.map +1 -0
  179. package/dist/search-provider-access.js +42 -0
  180. package/dist/search-provider-access.js.map +1 -0
  181. package/dist/similarity.d.ts +60 -1
  182. package/dist/similarity.d.ts.map +1 -1
  183. package/dist/similarity.js +174 -154
  184. package/dist/similarity.js.map +1 -1
  185. package/dist/status.js +8 -10
  186. package/dist/status.js.map +1 -1
  187. package/dist/store.d.ts +16 -2
  188. package/dist/store.d.ts.map +1 -1
  189. package/dist/store.js +171 -17
  190. package/dist/store.js.map +1 -1
  191. package/dist/temporal-index-cache.d.ts +13 -0
  192. package/dist/temporal-index-cache.d.ts.map +1 -0
  193. package/dist/temporal-index-cache.js +59 -0
  194. package/dist/temporal-index-cache.js.map +1 -0
  195. package/dist/temporal-model-manifests.d.ts +17 -0
  196. package/dist/temporal-model-manifests.d.ts.map +1 -0
  197. package/dist/temporal-model-manifests.js +33 -0
  198. package/dist/temporal-model-manifests.js.map +1 -0
  199. package/dist/temporal-models.d.ts +20 -35
  200. package/dist/temporal-models.d.ts.map +1 -1
  201. package/dist/temporal-models.js +23 -257
  202. package/dist/temporal-models.js.map +1 -1
  203. package/dist/temporal-search.d.ts +6 -3
  204. package/dist/temporal-search.d.ts.map +1 -1
  205. package/dist/temporal-search.js +438 -122
  206. package/dist/temporal-search.js.map +1 -1
  207. package/dist/temporal-vector-index.d.ts +46 -0
  208. package/dist/temporal-vector-index.d.ts.map +1 -0
  209. package/dist/temporal-vector-index.js +220 -0
  210. package/dist/temporal-vector-index.js.map +1 -0
  211. package/dist/third-party/@huggingface-jinja.LICENSE +21 -0
  212. package/dist/third-party/@huggingface-tokenizers.LICENSE +201 -0
  213. package/dist/third-party/@huggingface-transformers.LICENSE +202 -0
  214. package/dist/third-party/onnxruntime-common.LICENSE +21 -0
  215. package/dist/third-party/versions.json +23 -0
  216. package/dist/transformers-runtime.d.ts +2 -0
  217. package/dist/transformers-runtime.d.ts.map +1 -0
  218. package/dist/transformers-runtime.js +33014 -0
  219. package/dist/transformers-runtime.js.LEGAL.txt +12 -0
  220. package/dist/transformers-runtime.js.map +7 -0
  221. package/docs/doltlite-staging.md +69 -0
  222. package/docs/edit-performance.md +83 -0
  223. package/docs/engine-layout.md +56 -50
  224. package/docs/media-limits.md +57 -0
  225. package/docs/model-download-policy.md +15 -0
  226. package/docs/model-integrity.md +72 -0
  227. package/docs/model-isolation.md +72 -0
  228. package/docs/model-revisions.md +54 -0
  229. package/docs/mvp-prd.md +2 -2
  230. package/docs/release-evidence.md +300 -0
  231. package/docs/search-provider-consent.md +67 -0
  232. package/docs/semantic-durability.md +55 -0
  233. package/docs/temporal-search-performance.md +260 -0
  234. package/docs/v4-migration.md +83 -0
  235. package/fixtures/v5/contract-fixtures.json +4 -4
  236. package/package.json +31 -13
  237. package/dist/artifact-names.d.ts +0 -6
  238. package/dist/artifact-names.d.ts.map +0 -1
  239. package/dist/artifact-names.js +0 -56
  240. package/dist/artifact-names.js.map +0 -1
  241. package/dist/resolver.d.ts +0 -15
  242. package/dist/resolver.d.ts.map +0 -1
  243. package/dist/resolver.js +0 -81
  244. package/dist/resolver.js.map +0 -1
@@ -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.
@@ -106,8 +112,8 @@ There are 34 allowlisted semantic tables.
106
112
  | Table | Columns | Keys, constraints, and purpose |
107
113
  | --- | --- | --- |
108
114
  | `engine_schema` | `singleton INTEGER`<br>`version INTEGER`<br>`created_at INTEGER` | `singleton PK CHECK(singleton = 1)`. Records the clean-break catalog version. The recorded version rejects older catalogs rather than migrating them. |
109
- | `book` | `book_id TEXT`<br>`slug TEXT`<br>`created_at INTEGER` | `book_id PK`; `slug UQ`. Exactly one row per engine root. |
110
- | `artifacts` | `artifact_id TEXT`<br>`slug TEXT`<br>`kind TEXT`<br>`created_at INTEGER` | `artifact_id PK`; `slug UQ`; `kind CHECK IN (video, image, audio, script, character, prompt, scene, final)`. The artifact is the stable identity for source media, generated media, documents, and final renders. |
115
+ | `book` | `book_id TEXT`<br>`name TEXT`<br>`created_at INTEGER` | `book_id PK`. Exactly one row per engine root; `name` is free-text display. |
116
+ | `artifacts` | `artifact_id TEXT`<br>`label TEXT?`<br>`kind TEXT`<br>`created_at INTEGER` | `artifact_id PK`; `kind CHECK IN (video, image, audio, script, character, prompt, scene, final)`. `label` is optional, non-unique display text. The artifact id is the stable identity for source media, generated media, documents, and final renders. |
111
117
  | `objects` | `object_hash TEXT`<br>`size_bytes INTEGER`<br>`created_at INTEGER`<br>`forgotten_at INTEGER?` | `object_hash PK`; `size_bytes CHECK >= 0`. Versioned metadata for bytes stored outside the database. Rows are append-only: `forgotten_at` marks a tombstone whose bytes were deleted by `deleteObject`/`gc`. |
112
118
  | `artifact_files` | `artifact_id TEXT`<br>`path TEXT`<br>`object_hash TEXT`<br>`mtime_ms INTEGER`<br>`created_at INTEGER` | `(artifact_id, path) PK`; `artifact_id FK → artifacts.artifact_id ON DELETE CASCADE`; `object_hash FK → objects.object_hash ON DELETE RESTRICT`. Maps a logical artifact path to immutable content. |
113
119
  | `book_metadata` | `key TEXT`<br>`value_json TEXT` | `key PK`. Singleton-book key/value metadata; no redundant `book_id`. |
@@ -120,7 +126,7 @@ There are 34 allowlisted semantic tables.
120
126
  | `entities` | `entity_id TEXT`<br>`type TEXT`<br>`name TEXT`<br>`description TEXT?`<br>`prompt TEXT?`<br>`data_json TEXT DEFAULT '{}'`<br>`created_at INTEGER` | `entity_id PK`; `type CHECK IN (prompt, character, scene)`. Normalized reusable creative concepts. |
121
127
  | `notebooks` | `notebook_id TEXT`<br>`name TEXT`<br>`created_at INTEGER` | `notebook_id PK`. Owns a generation/authoring graph. Schema v18 removed the monolithic `properties_json` cell. |
122
128
  | `notebook_fields` | `notebook_id TEXT`<br>`field TEXT`<br>`value_json TEXT` | `(notebook_id, field) PK`; notebook `FK → notebooks ON DELETE CASCADE`; `field` is restricted to the typed public notebook fields. Stores optional notebook-level workflow values independently. |
123
- | `cells` | `notebook_id TEXT`<br>`cell_id TEXT`<br>`type TEXT`<br>`slug TEXT`<br>`grid_row INTEGER`<br>`grid_column INTEGER`<br>`output_entity_id TEXT?`<br>`prompt TEXT?`<br>`provider TEXT?`<br>`model TEXT?`<br>`operation TEXT?`<br>`tool TEXT?`<br>`inputs_json TEXT DEFAULT '{}'`<br>`output_artifact_id TEXT?` | `(notebook_id, cell_id) PK`; `(notebook_id, slug) UQ`; notebook `FK → notebooks ON DELETE CASCADE`; entity and output artifacts use `ON DELETE RESTRICT`. Cell types and kind-specific slug prefixes are checked by the schema. |
129
+ | `cells` | `notebook_id TEXT`<br>`cell_id TEXT`<br>`type TEXT`<br>`label TEXT?`<br>`grid_row INTEGER`<br>`grid_column INTEGER`<br>`output_entity_id TEXT?`<br>`prompt TEXT?`<br>`provider TEXT?`<br>`model TEXT?`<br>`operation TEXT?`<br>`tool TEXT?`<br>`inputs_json TEXT DEFAULT '{}'`<br>`output_artifact_id TEXT?` | `(notebook_id, cell_id) PK`; notebook `FK → notebooks ON DELETE CASCADE`; entity and output artifacts use `ON DELETE RESTRICT`. `label` is optional display text; the grid slot is the user-facing handle. |
124
130
  | `notebook_cell_executions` | `notebook_id TEXT`<br>`cell_id TEXT`<br>fingerprint/status/output/provider/run/timestamp/tool/error fields<br>`stale INTEGER`<br>`fixture_baseline INTEGER` | `(notebook_id, cell_id) PK` and composite cell FK with cascade. Gives each cell's execution and staleness state its own merge boundary. |
125
131
  | `notebook_generation_plans` | `notebook_id TEXT`<br>`plan_id TEXT`<br>`cell_id TEXT`<br>`status TEXT`<br>`plan_json TEXT`<br>output/error/timestamp fields | `(notebook_id, plan_id) PK`; composite cell FK with cascade. |
126
132
  | `notebook_run_plans` | `notebook_id TEXT`<br>`plan_id TEXT`<br>`status TEXT`<br>plan/cost/fingerprint/output fields<br>timestamps | `(notebook_id, plan_id) PK`. Stores approval and execution plans as independently mergeable rows. |
@@ -128,6 +134,7 @@ There are 34 allowlisted semantic tables.
128
134
  | `notebook_transcript_attachments` | `notebook_id TEXT`<br>`attachment_id TEXT`<br>`payload_json TEXT` | `(notebook_id, attachment_id) PK`; notebook FK with cascade. |
129
135
  | `edges` | `notebook_id TEXT`<br>`edge_id TEXT`<br>`source_cell_id TEXT`<br>`target_cell_id TEXT`<br>`target_input TEXT` | `(notebook_id, edge_id) PK`; notebook `FK → notebooks ON DELETE CASCADE`; composite source and target FKs reference cells in the same notebook and cascade on cell deletion. |
130
136
  | `runs` | `run_id TEXT`<br>`notebook_id TEXT`<br>`status TEXT`<br>`started_at INTEGER`<br>`completed_at INTEGER`<br>`cell_order_json TEXT`<br>`outputs_json TEXT`<br>`error TEXT?` | `run_id PK`; notebook `FK → notebooks ON DELETE CASCADE`; `status CHECK IN (completed, failed, aborted)`. Terminal, versioned notebook execution records. |
137
+ | `generations` | `generation_id TEXT`<br>`notebook_id TEXT`<br>`cell_id TEXT`<br>`output_cell_id TEXT?`<br>`run_id TEXT?`<br>`status TEXT`<br>`tool TEXT`<br>`provider TEXT?`<br>`model TEXT?`<br>`prompt TEXT?`<br>`resolved_prompt TEXT?`<br>`provider_artifact_id TEXT?`<br>`output_artifact_id TEXT?`<br>`error TEXT?`<br>`created_at INTEGER`<br>`updated_at INTEGER` | `generation_id PK`; composite cell FK with cascade; `status CHECK IN (dispatched, awaiting_provider, completed, failed)`. One row per generation attempt; every transition is its own attributed semantic commit, so `dolt_history_generations` is the per-attempt timeline. |
131
138
 
132
139
  ### Sequence timeline and media editing state
133
140
 
@@ -229,17 +236,10 @@ are the constraint-verification primitives.
229
236
  `SCHEMA_INCOMPATIBLE` before any merge is attempted
230
237
  (`assertSameSchemaVersion`). This was previously only implied by the
231
238
  engine's open-time version gate.
232
- - **`artifacts.slug` (globally unique) → user-facing conflict.** Two forks
233
- minting the same slug for different artifacts is detected before the
234
- merge by a three-way (merge-base/ours/theirs) simulation over the
235
- artifacts slug projection (`findSlugConflicts`, using `dolt_merge_base`
236
- and `dolt_at_artifacts`), and refused with `MERGE_CONFLICT` listing the
237
- slug and both artifact ids. doltlite's own verification is the backstop:
238
- refusals it reports are re-diagnosed and surface as `MERGE_CONFLICT`
239
- when attributable to slugs. Row-level same-row edits surface as
240
- `MERGE_CONFLICT` as well. At create time, slug dedup runs inside the
241
- serialized write chain (not as a read-then-write outside it), so
242
- concurrent creates cannot race onto the same slug.
239
+ - **Artifact identity is `artifact_id` (UUIDv7) → no name-conflict
240
+ class.** Forks mint collision-free ids, and `artifacts.label` is
241
+ non-unique display text that merges as an ordinary column. Row-level
242
+ same-row edits surface as `MERGE_CONFLICT`.
243
243
  - **RESTRICT foreign keys → verification-surfaced typed violation.** A
244
244
  fork that deletes a row another fork newly references is caught by
245
245
  doltlite's merge-time working-set verification, which refuses and rolls
@@ -271,19 +271,12 @@ are the constraint-verification primitives.
271
271
  both lineages) and two set values keep the earlier timestamp
272
272
  (`resolveObjectsRow` in `src/fork.ts`).
273
273
 
274
- ve-wsu: doltlite currently corrupts secondary UNIQUE indexes on
275
- `dolt_checkout` once a working set has three or more tables, corrupts full
276
- engine catalogs on checkout and `dolt_clone` (the cloned file's schema does
277
- not even parse: `invalid rootpage` on a secondary autoindex), misfires its
278
- "uncommitted changes" merge guard on the full 28-table catalog (every
279
- table reports a phantom `modified` status with zero row diffs), and — when
280
- the guard is bypassed by committing the phantom dirt — dies in schema
281
- loading on true merges (`schema conflict on table 'sqlite_autoindex_*'`).
282
- The dedicated merge-back flow therefore runs this policy around a
283
- projection-level three-way merge instead of `dolt_merge`; see "Forks and
284
- merge-back integration" below. `mergeWithPolicy` remains the drop-in merge
285
- mechanism once the upstream bugs are fixed, exercised against the real
286
- 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.
287
280
 
288
281
  ### Forks and merge-back integration
289
282
 
@@ -292,14 +285,13 @@ A fork of a public book is, from the engine's point of view:
292
285
  1. **A platform fork.** Creating the hosted copy of a catalog and giving
293
286
  it a URL is the hosting layer's job; it is out of engine scope.
294
287
  2. **A clone of the catalog into a local engine root** (`bootstrapFork` in
295
- [`src/fork.ts`](../src/fork.ts)). Because `dolt_clone` corrupts full
296
- catalogs (ve-wsu), bootstrap takes a byte snapshot of a healthy upstream
297
- `videobook.db` (captured while the upstream engine is closed) and opens
298
- it as a normal engine no `initialBookSlug`, the singleton book row
299
- comes along with the snapshot. A URL bootstrap path attempts
300
- `dolt_clone` and health-validates the result, surfacing a typed
301
- `FEATURE_UNAVAILABLE` while the upstream bug stands; it starts working
302
- 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.
303
295
  3. **A public-read object store keyed by SHA-256.** `ContentStore` stays
304
296
  the abstraction; the existing `ensureLocal` lazy fetch in
305
297
  [`src/cas.ts`](../src/cas.ts) downloads any object the fork lacks on
@@ -323,10 +315,10 @@ Integration is a dedicated flow, `mergeBack` in
323
315
  resolve heads and the merge base (`dolt_merge_base`; commit hashes via
324
316
  `dolt_log`/`dolt_branches` — `doltHashOf` returns content hashes, not
325
317
  commit hashes; the fetched remote-tracking ref gets a local branch
326
- pointer, a ref-only write that is safe under ve-wsu).
327
- 3. Run the merge policy: same-schema precondition, pre-merge slug-conflict
328
- detection (`MERGE_CONFLICT`), then a projection-level three-way row
329
- merge over `dolt_at_<table>` snapshots of base/ours/theirs (row
318
+ pointer without checking out the fetched branch).
319
+ 3. Run the merge policy: same-schema precondition, then a
320
+ projection-level three-way row merge over `dolt_at_<table>`
321
+ snapshots of base/ours/theirs (row
330
322
  semantics mirror Dolt: one-sided changes win, identical changes
331
323
  resolve, incompatible changes abort with `MERGE_CONFLICT`), deterministic
332
324
  singleton-flag reconcile, and post-merge constraint verification
@@ -338,14 +330,12 @@ Integration is a dedicated flow, `mergeBack` in
338
330
  `engine.storage.backup`.
339
331
  5. Land one forward integration commit on `main` and `dolt_push` it.
340
332
 
341
- ve-wsu makes a true two-parent `dolt_merge` commit impossible on full
342
- catalogs today, so the integration commit is single-parent and records the
343
- integrated fork head in a `merged-revision` commit-message trailer (plus
344
- `base-revision`, per the structured-message convention). Re-running the
345
- flow is a no-op when the fork's net changes are already on `main`. The
346
- projection merge in `mergeRefs` is the single swap point: when doltlite is
347
- fixed, `mergeWithPolicy` + `dolt_merge` replace it and the commit becomes
348
- 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.
349
339
 
350
340
  When a plain `engine.storage.backup()` push is rejected because upstream
351
341
  moved, the backup surfaces `DIVERGED` with guidance into this flow —
@@ -370,6 +360,7 @@ schema additionally defines every index below.
370
360
  | `runs_notebook_completed` | `runs(notebook_id, completed_at, run_id)` |
371
361
  | `prompt_entries_lookup` | `prompt_entries(surface, created_at, prompt_id)` |
372
362
  | `messages_created` | `messages(created_at, message_id)` |
363
+ | `generations_cell` | `generations(notebook_id, cell_id, created_at)` |
373
364
 
374
365
  ## Local-only runtime schema
375
366
 
@@ -495,7 +486,22 @@ the engine deliberately does not implement it.
495
486
  - doltlite exposes `dolt_gc()` as a SQL function (verified: it returns a
496
487
  `"N chunks removed, M chunks kept"` summary). `gc({ doltGc: true })` runs
497
488
  it after collecting to physically reclaim chunks left behind by dropped
498
- 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.
499
505
  - Run `deleteObject` and `gc` only while no imports are in flight; CAS puts
500
506
  happen outside the serialized write chain, so a concurrent import could
501
507
  race the sweep.
@@ -542,7 +548,7 @@ interface ArtifactManifestFile {
542
548
 
543
549
  interface ArtifactManifest {
544
550
  artifactId: string;
545
- slug: string;
551
+ label?: string;
546
552
  path: string; // disposable workspace path
547
553
  fileCount: number;
548
554
  files: ArtifactManifestFile[];
@@ -701,7 +707,7 @@ must reproduce a render.
701
707
  selections, UI panels, decode caches, thumbnails, temporary renders, active
702
708
  jobs, locks, and presence in ignored runtime tables.
703
709
  - Pin renders and derived analysis to source object hashes and a Dolt revision,
704
- not mutable artifact slugs or workspace paths.
710
+ not mutable artifact labels or workspace paths.
705
711
  - Treat color space, transfer function, matrix, range, alpha mode, rotation,
706
712
  sample rate, channel layout, and variable-frame-rate timing as first-class
707
713
  media facts.
@@ -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.