videobook-engine 5.3.2 → 5.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/README.md +6 -0
  2. package/dist/catalog-metadata.d.ts +1 -1
  3. package/dist/catalog-metadata.js +1 -1
  4. package/dist/domain.js +15 -5
  5. package/dist/domain.js.map +1 -1
  6. package/dist/engine-types.d.ts +140 -1
  7. package/dist/engine-types.d.ts.map +1 -1
  8. package/dist/engine-types.js.map +1 -1
  9. package/dist/engine.d.ts +21 -0
  10. package/dist/engine.d.ts.map +1 -1
  11. package/dist/engine.js +3 -0
  12. package/dist/engine.js.map +1 -1
  13. package/dist/fork.d.ts +3 -4
  14. package/dist/fork.d.ts.map +1 -1
  15. package/dist/fork.js +4 -4
  16. package/dist/fork.js.map +1 -1
  17. package/dist/index.d.ts +5 -0
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +4 -0
  20. package/dist/index.js.map +1 -1
  21. package/dist/merge-policy.d.ts +3 -4
  22. package/dist/merge-policy.d.ts.map +1 -1
  23. package/dist/merge-policy.js +5 -4
  24. package/dist/merge-policy.js.map +1 -1
  25. package/dist/migrate-tags-v24.d.ts +12 -0
  26. package/dist/migrate-tags-v24.d.ts.map +1 -0
  27. package/dist/migrate-tags-v24.js +40 -0
  28. package/dist/migrate-tags-v24.js.map +1 -0
  29. package/dist/mvp-contracts.d.ts +2 -2
  30. package/dist/mvp-contracts.js +1 -1
  31. package/dist/schema.d.ts +3 -2
  32. package/dist/schema.d.ts.map +1 -1
  33. package/dist/schema.js +59 -0
  34. package/dist/schema.js.map +1 -1
  35. package/dist/store.d.ts +6 -0
  36. package/dist/store.d.ts.map +1 -1
  37. package/dist/store.js +150 -54
  38. package/dist/store.js.map +1 -1
  39. package/dist/tag-merge.d.ts +4 -0
  40. package/dist/tag-merge.d.ts.map +1 -0
  41. package/dist/tag-merge.js +85 -0
  42. package/dist/tag-merge.js.map +1 -0
  43. package/dist/tag-queries.d.ts +30 -0
  44. package/dist/tag-queries.d.ts.map +1 -0
  45. package/dist/tag-queries.js +313 -0
  46. package/dist/tag-queries.js.map +1 -0
  47. package/dist/tag-rows.d.ts +36 -0
  48. package/dist/tag-rows.d.ts.map +1 -0
  49. package/dist/tag-rows.js +48 -0
  50. package/dist/tag-rows.js.map +1 -0
  51. package/dist/tag-transfer.d.ts +26 -0
  52. package/dist/tag-transfer.d.ts.map +1 -0
  53. package/dist/tag-transfer.js +341 -0
  54. package/dist/tag-transfer.js.map +1 -0
  55. package/dist/tag-validation.d.ts +15 -0
  56. package/dist/tag-validation.d.ts.map +1 -0
  57. package/dist/tag-validation.js +36 -0
  58. package/dist/tag-validation.js.map +1 -0
  59. package/dist/tag-values.d.ts +68 -0
  60. package/dist/tag-values.d.ts.map +1 -0
  61. package/dist/tag-values.js +107 -0
  62. package/dist/tag-values.js.map +1 -0
  63. package/dist/tags.d.ts +44 -0
  64. package/dist/tags.d.ts.map +1 -0
  65. package/dist/tags.js +488 -0
  66. package/dist/tags.js.map +1 -0
  67. package/docs/doltlite-staging.md +35 -15
  68. package/docs/edit-performance.md +2 -4
  69. package/docs/engine-layout.md +92 -4
  70. package/docs/mvp-prd.md +2 -1
  71. package/docs/release-evidence.md +74 -35
  72. package/docs/temporal-search-performance.md +4 -6
  73. package/fixtures/v5/contract-fixtures.json +3 -3
  74. package/package.json +7 -3
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tags.d.ts","sourceRoot":"","sources":["../src/tags.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAGhB,oBAAoB,EAEpB,WAAW,EACX,wBAAwB,EACxB,MAAM,EACP,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,aAAa,EAA0B,MAAM,cAAc,CAAC;AAMrE,OAAO,KAAK,EAEV,gBAAgB,EAChB,QAAQ,EACT,MAAM,iBAAiB,CAAC;AASzB,iDAAiD;AACjD,eAAO,MAAM,kBAAkB,MAAM,CAAC;AAiCtC,wBAAgB,aAAa,CAAC,OAAO,EAAE,aAAa;uBAQ7B,MAAM,KAAG,MAAM,CAAC,gBAAgB,EAAE,WAAW,CAAC;4BAGlD,SAAS,MAAM,EAAE,KAC7B,MAAM,CAAC,gBAAgB,EAAE,EAAE,WAAW,CAAC;sBAG5B,MAAM,OACb,QAAQ,KACZ,OAAO,CAAC,MAAM,CAAC,gBAAgB,EAAE,WAAW,CAAC,CAAC;0BAGnC,MAAM,QACZ,SAAS,QAAQ,EAAE,KACxB,OAAO,CAAC,MAAM,CAAC,gBAAgB,EAAE,WAAW,CAAC,CAAC;yBAGnC,MAAM,OACb,gBAAgB,KACpB,OAAO,CAAC,MAAM,CAAC,gBAAgB,EAAE,WAAW,CAAC,CAAC;0BAGnC,MAAM,OACb,gBAAgB,KACpB,OAAO,CAAC,MAAM,CAAC,gBAAgB,EAAE,WAAW,CAAC,CAAC;;+BAIjC,MAAM,KACjB,MAAM,CAAC,oBAAoB,GAAG,SAAS,EAAE,WAAW,CAAC;yBAG/C,wBAAwB,KAC9B,OAAO,CAAC,MAAM,CAAC,gBAAgB,EAAE,WAAW,CAAC,CAAC;;;;;;;;aAlB/C,CAAC;;;EAsBR"}
package/dist/tags.js ADDED
@@ -0,0 +1,488 @@
1
+ /**
2
+ * Asset tags: durable automatic and user-managed tagging.
3
+ *
4
+ * The engine owns state, normalization, transactions and provenance; the
5
+ * consumer owns inference, scheduling and vocabulary. Three rules shape
6
+ * everything here:
7
+ *
8
+ * 1. Semantic identity is (facet, canonical key). Two facets carrying the
9
+ * same word stay distinct assignments.
10
+ * 2. Manual intent outranks analysis. An automatic snapshot replaces only
11
+ * the automatic rows; it can never add, drop or relabel a manual row,
12
+ * and it can never clear a dismissal.
13
+ * 3. Automatic output is fenced to the content it described. A snapshot
14
+ * records the analyzed source hash and a per-artifact generation, so a
15
+ * late result cannot overwrite a newer one and tags for replaced
16
+ * content drop out of the effective set instead of lying.
17
+ */
18
+ import { ok } from "./engine-types.js";
19
+ import { resultOf, syncResultOf } from "./context.js";
20
+ import { EngineFault } from "./store.js";
21
+ import { createTagQueriesApi } from "./tag-queries.js";
22
+ import { automaticTagsMatch, compareTags, snapshotMatches } from "./tag-rows.js";
23
+ import { createTagTransferApi } from "./tag-transfer.js";
24
+ import { normalizeAutomaticTags } from "./tag-validation.js";
25
+ import { MANUAL_TAGS_PER_ARTIFACT_MAX, TAG_DISMISSALS_PER_ARTIFACT_MAX, normalizeTagIdentity, normalizeTagList, tagIdentity, } from "./tag-values.js";
26
+ /** Artifacts a single batched read may cover. */
27
+ export const TAG_READ_BATCH_MAX = 500;
28
+ const READ_CHUNK = 200;
29
+ export function createTagsApi(context) {
30
+ const queries = createTagQueriesApi(context);
31
+ const transfer = createTagTransferApi(context, (artifactId) => tagState(context, artifactId));
32
+ return {
33
+ ...queries,
34
+ ...transfer,
35
+ read: (artifactId) => syncResultOf(() => readTagState(context, artifactId)),
36
+ readMany: (artifactIds) => syncResultOf(() => readTagStates(context, artifactIds)),
37
+ add: (artifactId, tag) => addManualTags(context, artifactId, [tag]),
38
+ addMany: (artifactId, tags) => addManualTags(context, artifactId, tags),
39
+ remove: (artifactId, tag) => removeTag(context, artifactId, tag),
40
+ restore: (artifactId, tag) => restoreTag(context, artifactId, tag),
41
+ automatic: {
42
+ snapshot: (artifactId) => syncResultOf(() => readSnapshot(context, artifactId)),
43
+ replace: (input) => replaceAutomaticTags(context, input),
44
+ },
45
+ };
46
+ }
47
+ // ---------------------------------------------------------------- reads
48
+ function readTagState(context, artifactReference) {
49
+ const artifact = context.artifactRow(artifactReference);
50
+ return tagState(context, artifact.artifact_id);
51
+ }
52
+ function readTagStates(context, artifactReferences) {
53
+ if (artifactReferences.length > TAG_READ_BATCH_MAX) {
54
+ throw new Error(`Tag reads must cover at most ${TAG_READ_BATCH_MAX} artifacts; received ${artifactReferences.length}`);
55
+ }
56
+ const artifactIds = artifactReferences.map((reference) => context.artifactRow(reference).artifact_id);
57
+ const tags = chunkedRows(context, artifactIds, (placeholders) => `SELECT artifact_id, origin, facet, tag_key, label, entity_id, created_at
58
+ FROM artifact_tags
59
+ WHERE artifact_id IN (${placeholders})
60
+ ORDER BY artifact_id, facet, tag_key`);
61
+ const dismissals = chunkedRows(context, artifactIds, (placeholders) => `SELECT artifact_id, facet, tag_key, label, dismissed_at
62
+ FROM artifact_tag_dismissals
63
+ WHERE artifact_id IN (${placeholders})
64
+ ORDER BY artifact_id, facet, tag_key`);
65
+ const snapshots = chunkedRows(context, artifactIds, (placeholders) => `SELECT artifact_id, source_hash, generator, model, extractor_version,
66
+ tag_count, generation, analyzed_at
67
+ FROM artifact_tag_snapshots
68
+ WHERE artifact_id IN (${placeholders})`);
69
+ const snapshotByArtifact = new Map(snapshots.map((row) => [row.artifact_id, row]));
70
+ const liveHashes = artifactFileHashes(context, artifactIds);
71
+ return artifactIds.map((artifactId) => assembleState(artifactId, tags.filter((row) => row.artifact_id === artifactId), dismissals.filter((row) => row.artifact_id === artifactId), snapshotByArtifact.get(artifactId), liveHashes.get(artifactId) ?? new Set()));
72
+ }
73
+ function tagState(context, artifactId) {
74
+ const tags = context.store.db
75
+ .prepare(`SELECT artifact_id, origin, facet, tag_key, label, entity_id, created_at
76
+ FROM artifact_tags
77
+ WHERE artifact_id=?
78
+ ORDER BY facet, tag_key`)
79
+ .all(artifactId);
80
+ const dismissals = context.store.db
81
+ .prepare(`SELECT artifact_id, facet, tag_key, label, dismissed_at
82
+ FROM artifact_tag_dismissals
83
+ WHERE artifact_id=?
84
+ ORDER BY facet, tag_key`)
85
+ .all(artifactId);
86
+ const snapshot = snapshotRow(context, artifactId);
87
+ return assembleState(artifactId, tags, dismissals, snapshot, artifactFileHashes(context, [artifactId]).get(artifactId) ??
88
+ new Set());
89
+ }
90
+ /**
91
+ * Effective tags: every manual assignment, plus automatic assignments that
92
+ * are neither dismissed nor stale, deduplicated on identity with the
93
+ * manual display label and ownership preferred.
94
+ */
95
+ function assembleState(artifactId, tagRows, dismissalRows, snapshotRow, liveHashes) {
96
+ const dismissed = new Set(dismissalRows.map((row) => tagIdentity(row.facet, row.tag_key)));
97
+ const stale = snapshotRow !== undefined && !liveHashes.has(snapshotRow.source_hash);
98
+ const manual = tagRows
99
+ .filter((row) => row.origin === "manual")
100
+ .map((row) => assetTag(row));
101
+ const automatic = tagRows
102
+ .filter((row) => row.origin === "automatic")
103
+ .map((row) => ({
104
+ ...assetTag(row),
105
+ dismissed: dismissed.has(tagIdentity(row.facet, row.tag_key)),
106
+ stale,
107
+ }));
108
+ const effective = [...manual];
109
+ const claimed = new Set(manual.map((tag) => tagIdentity(tag.facet, tag.key)));
110
+ for (const tag of automatic) {
111
+ if (tag.dismissed || tag.stale)
112
+ continue;
113
+ const identity = tagIdentity(tag.facet, tag.key);
114
+ if (claimed.has(identity))
115
+ continue;
116
+ claimed.add(identity);
117
+ effective.push({
118
+ facet: tag.facet,
119
+ key: tag.key,
120
+ label: tag.label,
121
+ origin: tag.origin,
122
+ ...(tag.entityId ? { entityId: tag.entityId } : {}),
123
+ createdAt: tag.createdAt,
124
+ });
125
+ }
126
+ effective.sort(compareTags);
127
+ return {
128
+ artifactId,
129
+ effective,
130
+ manual,
131
+ automatic,
132
+ dismissed: dismissalRows.map((row) => ({
133
+ facet: row.facet,
134
+ key: row.tag_key,
135
+ label: row.label,
136
+ dismissedAt: row.dismissed_at,
137
+ })),
138
+ ...(snapshotRow
139
+ ? { snapshot: snapshotFromRow(snapshotRow, stale) }
140
+ : {}),
141
+ };
142
+ }
143
+ function assetTag(row) {
144
+ return {
145
+ facet: row.facet,
146
+ key: row.tag_key,
147
+ label: row.label,
148
+ origin: row.origin,
149
+ ...(row.entity_id ? { entityId: row.entity_id } : {}),
150
+ createdAt: row.created_at,
151
+ };
152
+ }
153
+ function readSnapshot(context, artifactReference) {
154
+ const artifact = context.artifactRow(artifactReference);
155
+ const row = snapshotRow(context, artifact.artifact_id);
156
+ if (!row)
157
+ return undefined;
158
+ const hashes = artifactFileHashes(context, [artifact.artifact_id]);
159
+ const live = hashes.get(artifact.artifact_id) ?? new Set();
160
+ return snapshotFromRow(row, !live.has(row.source_hash));
161
+ }
162
+ function snapshotRow(context, artifactId) {
163
+ return context.store.db
164
+ .prepare(`SELECT artifact_id, source_hash, generator, model, extractor_version,
165
+ tag_count, generation, analyzed_at
166
+ FROM artifact_tag_snapshots
167
+ WHERE artifact_id=?`)
168
+ .get(artifactId);
169
+ }
170
+ function snapshotFromRow(row, stale) {
171
+ return {
172
+ artifactId: row.artifact_id,
173
+ sourceHash: row.source_hash,
174
+ generator: row.generator,
175
+ ...(row.model === null ? {} : { model: row.model }),
176
+ extractorVersion: row.extractor_version,
177
+ tagCount: row.tag_count,
178
+ generation: row.generation,
179
+ analyzedAt: row.analyzed_at,
180
+ stale,
181
+ };
182
+ }
183
+ /**
184
+ * Current content hashes per artifact. An automatic snapshot is stale once
185
+ * the hash it analyzed is no longer one of the artifact's files, which is
186
+ * how replaced originals drop their automatic tags without deleting the
187
+ * provenance that explains them.
188
+ */
189
+ function artifactFileHashes(context, artifactIds) {
190
+ const rows = chunkedRows(context, artifactIds, (placeholders) => `SELECT artifact_id, object_hash FROM artifact_files
191
+ WHERE artifact_id IN (${placeholders})`);
192
+ const hashes = new Map();
193
+ for (const row of rows) {
194
+ const existing = hashes.get(row.artifact_id);
195
+ if (existing)
196
+ existing.add(row.object_hash);
197
+ else
198
+ hashes.set(row.artifact_id, new Set([row.object_hash]));
199
+ }
200
+ return hashes;
201
+ }
202
+ function chunkedRows(context, artifactIds, sql) {
203
+ const rows = [];
204
+ const uniqueIds = [...new Set(artifactIds)];
205
+ for (let index = 0; index < uniqueIds.length; index += READ_CHUNK) {
206
+ const chunk = uniqueIds.slice(index, index + READ_CHUNK);
207
+ if (chunk.length === 0)
208
+ continue;
209
+ const placeholders = chunk.map(() => "?").join(", ");
210
+ rows.push(...context.store.db
211
+ .prepare(sql(placeholders))
212
+ .all(...chunk));
213
+ }
214
+ return rows;
215
+ }
216
+ // --------------------------------------------------------------- writes
217
+ async function addManualTags(context, artifactReference, inputs) {
218
+ return resultOf(() => context.store.semanticOperation((commit) => {
219
+ const artifact = context.artifactRow(artifactReference);
220
+ const artifactId = artifact.artifact_id;
221
+ const tags = normalizeTagList(inputs);
222
+ if (tags.length === 0) {
223
+ throw new Error("At least one tag is required");
224
+ }
225
+ for (const tag of tags)
226
+ requireEntity(context, tag);
227
+ const existing = manualRowsByIdentity(context, artifactId);
228
+ const added = tags.filter((tag) => !existing.has(tagIdentity(tag.facet, tag.key)));
229
+ const total = existing.size + added.length;
230
+ if (total > MANUAL_TAGS_PER_ARTIFACT_MAX) {
231
+ throw new EngineFault({
232
+ code: "RESOURCE_EXHAUSTED",
233
+ message: `Artifact ${artifactId} would carry ${total} manual tags; the limit is ` +
234
+ `${MANUAL_TAGS_PER_ARTIFACT_MAX}`,
235
+ details: { artifactId, requested: total, limit: MANUAL_TAGS_PER_ARTIFACT_MAX },
236
+ });
237
+ }
238
+ const dismissed = dismissedIdentities(context, artifactId);
239
+ const changed = tags.filter((tag) => {
240
+ const identity = tagIdentity(tag.facet, tag.key);
241
+ if (dismissed.has(identity))
242
+ return true;
243
+ const row = existing.get(identity);
244
+ if (!row)
245
+ return true;
246
+ return row.label !== tag.label || (row.entity_id ?? undefined) !== tag.entityId;
247
+ });
248
+ if (changed.length === 0)
249
+ return ok(tagState(context, artifactId));
250
+ const mutation = commit({
251
+ operation: "add_artifact_tags",
252
+ tables: ["artifact_tags", "artifact_tag_dismissals"],
253
+ artifactId,
254
+ details: { artifactId, tags: changed.map(identityDetail) },
255
+ writeSet: changed.map((tag) => writeSetKey(artifactId, tag)),
256
+ }, (_operationId, now) => {
257
+ const insert = context.store.db.prepare(`INSERT INTO artifact_tags(
258
+ artifact_id, origin, facet, tag_key, label, entity_id, created_at
259
+ ) VALUES (?, 'manual', ?, ?, ?, ?, ?)
260
+ ON CONFLICT(artifact_id, origin, facet, tag_key) DO UPDATE SET
261
+ label=excluded.label,
262
+ entity_id=excluded.entity_id`);
263
+ const clearDismissal = context.store.db.prepare(`DELETE FROM artifact_tag_dismissals
264
+ WHERE artifact_id=? AND facet=? AND tag_key=?`);
265
+ for (const tag of changed) {
266
+ insert.run(artifactId, tag.facet, tag.key, tag.label, tag.entityId ?? null, now);
267
+ // An explicit add is explicit consent: it clears the durable
268
+ // suppression that a previous removal recorded.
269
+ clearDismissal.run(artifactId, tag.facet, tag.key);
270
+ }
271
+ });
272
+ return ok(tagState(context, artifactId), mutation.revision);
273
+ }));
274
+ }
275
+ async function removeTag(context, artifactReference, input) {
276
+ return resultOf(() => context.store.semanticOperation((commit) => {
277
+ const artifact = context.artifactRow(artifactReference);
278
+ const artifactId = artifact.artifact_id;
279
+ const identity = normalizeTagIdentity(input);
280
+ const manual = manualRowsByIdentity(context, artifactId).get(tagIdentity(identity.facet, identity.key));
281
+ const dismissal = context.store.db
282
+ .prepare(`SELECT artifact_id, facet, tag_key, label, dismissed_at
283
+ FROM artifact_tag_dismissals
284
+ WHERE artifact_id=? AND facet=? AND tag_key=?`)
285
+ .get(artifactId, identity.facet, identity.key);
286
+ if (!manual && dismissal)
287
+ return ok(tagState(context, artifactId));
288
+ if (!dismissal)
289
+ assertDismissalCapacity(context, artifactId);
290
+ // The dismissal keeps the label the user actually saw, so a restored
291
+ // suppression reads the same way it did when it was removed.
292
+ const label = manual?.label ?? automaticLabel(context, artifactId, identity) ??
293
+ identity.label;
294
+ const mutation = commit({
295
+ operation: "remove_artifact_tag",
296
+ tables: ["artifact_tags", "artifact_tag_dismissals"],
297
+ artifactId,
298
+ details: {
299
+ artifactId,
300
+ facet: identity.facet,
301
+ key: identity.key,
302
+ },
303
+ writeSet: [writeSetKey(artifactId, identity)],
304
+ }, (_operationId, now) => {
305
+ context.store.db
306
+ .prepare(`DELETE FROM artifact_tags
307
+ WHERE artifact_id=? AND origin='manual' AND facet=? AND tag_key=?`)
308
+ .run(artifactId, identity.facet, identity.key);
309
+ context.store.db
310
+ .prepare(`INSERT INTO artifact_tag_dismissals(
311
+ artifact_id, facet, tag_key, label, dismissed_at
312
+ ) VALUES (?, ?, ?, ?, ?)
313
+ ON CONFLICT(artifact_id, facet, tag_key) DO UPDATE SET
314
+ label=excluded.label`)
315
+ .run(artifactId, identity.facet, identity.key, label, now);
316
+ });
317
+ return ok(tagState(context, artifactId), mutation.revision);
318
+ }));
319
+ }
320
+ async function restoreTag(context, artifactReference, input) {
321
+ return resultOf(() => context.store.semanticOperation((commit) => {
322
+ const artifact = context.artifactRow(artifactReference);
323
+ const artifactId = artifact.artifact_id;
324
+ const identity = normalizeTagIdentity(input);
325
+ const present = context.store.db
326
+ .prepare(`SELECT 1 AS present FROM artifact_tag_dismissals
327
+ WHERE artifact_id=? AND facet=? AND tag_key=?`)
328
+ .get(artifactId, identity.facet, identity.key);
329
+ if (!present)
330
+ return ok(tagState(context, artifactId));
331
+ const mutation = commit({
332
+ operation: "restore_artifact_tag",
333
+ tables: ["artifact_tag_dismissals"],
334
+ artifactId,
335
+ details: { artifactId, facet: identity.facet, key: identity.key },
336
+ writeSet: [writeSetKey(artifactId, identity)],
337
+ }, () => {
338
+ context.store.db
339
+ .prepare(`DELETE FROM artifact_tag_dismissals
340
+ WHERE artifact_id=? AND facet=? AND tag_key=?`)
341
+ .run(artifactId, identity.facet, identity.key);
342
+ });
343
+ return ok(tagState(context, artifactId), mutation.revision);
344
+ }));
345
+ }
346
+ async function replaceAutomaticTags(context, input) {
347
+ return resultOf(() => context.store.semanticOperation((commit) => {
348
+ const artifact = context.artifactRow(input.artifactId);
349
+ const artifactId = artifact.artifact_id;
350
+ const { sourceHash, generator, extractorVersion, model, tags } = normalizeAutomaticTags(input);
351
+ if (input.expectedGeneration !== undefined &&
352
+ (!Number.isSafeInteger(input.expectedGeneration) || input.expectedGeneration < 0)) {
353
+ throw new Error("Automatic tag expectedGeneration must be a nonnegative integer");
354
+ }
355
+ for (const tag of tags)
356
+ requireEntity(context, tag);
357
+ const current = snapshotRow(context, artifactId);
358
+ const generation = current?.generation ?? 0;
359
+ if (input.expectedGeneration !== undefined &&
360
+ input.expectedGeneration !== generation) {
361
+ throw new EngineFault({
362
+ code: "STALE_REVISION",
363
+ message: `Automatic tags for ${artifactId} expected generation ` +
364
+ `${input.expectedGeneration} but the catalog is at ${generation}`,
365
+ details: {
366
+ artifactId,
367
+ expectedGeneration: input.expectedGeneration,
368
+ generation,
369
+ },
370
+ });
371
+ }
372
+ if (snapshotMatches(current, {
373
+ sourceHash,
374
+ generator,
375
+ ...(model ? { model } : {}),
376
+ extractorVersion,
377
+ }) &&
378
+ automaticTagsMatch(context.store.db, artifactId, tags)) {
379
+ // Re-running the same analyzer over the same bytes with the same
380
+ // answer is not history; it mints no commit and does not advance
381
+ // the fence.
382
+ return ok(tagState(context, artifactId));
383
+ }
384
+ const mutation = commit({
385
+ operation: "replace_automatic_artifact_tags",
386
+ tables: ["artifact_tags", "artifact_tag_snapshots"],
387
+ artifactId,
388
+ details: {
389
+ artifactId,
390
+ sourceHash,
391
+ generator,
392
+ extractorVersion,
393
+ generation: generation + 1,
394
+ tags: tags.map(identityDetail),
395
+ },
396
+ writeSet: [`artifact-tags-automatic:${artifactId}`],
397
+ }, (_operationId, now) => {
398
+ context.store.db
399
+ .prepare("DELETE FROM artifact_tags WHERE artifact_id=? AND origin='automatic'")
400
+ .run(artifactId);
401
+ const insert = context.store.db.prepare(`INSERT INTO artifact_tags(
402
+ artifact_id, origin, facet, tag_key, label, entity_id, created_at
403
+ ) VALUES (?, 'automatic', ?, ?, ?, ?, ?)`);
404
+ for (const tag of tags) {
405
+ insert.run(artifactId, tag.facet, tag.key, tag.label, tag.entityId ?? null, now);
406
+ }
407
+ context.store.db
408
+ .prepare(`INSERT INTO artifact_tag_snapshots(
409
+ artifact_id, source_hash, generator, model, extractor_version,
410
+ tag_count, generation, analyzed_at
411
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
412
+ ON CONFLICT(artifact_id) DO UPDATE SET
413
+ source_hash=excluded.source_hash,
414
+ generator=excluded.generator,
415
+ model=excluded.model,
416
+ extractor_version=excluded.extractor_version,
417
+ tag_count=excluded.tag_count,
418
+ generation=excluded.generation,
419
+ analyzed_at=excluded.analyzed_at`)
420
+ .run(artifactId, sourceHash, generator, model || null, extractorVersion, tags.length, generation + 1, now);
421
+ });
422
+ return ok(tagState(context, artifactId), mutation.revision);
423
+ }));
424
+ }
425
+ // --------------------------------------------------------------- helpers
426
+ function manualRowsByIdentity(context, artifactId) {
427
+ const rows = context.store.db
428
+ .prepare(`SELECT artifact_id, origin, facet, tag_key, label, entity_id, created_at
429
+ FROM artifact_tags
430
+ WHERE artifact_id=? AND origin='manual'`)
431
+ .all(artifactId);
432
+ return new Map(rows.map((row) => [tagIdentity(row.facet, row.tag_key), row]));
433
+ }
434
+ function dismissedIdentities(context, artifactId) {
435
+ const rows = context.store.db
436
+ .prepare("SELECT facet, tag_key FROM artifact_tag_dismissals WHERE artifact_id=?")
437
+ .all(artifactId);
438
+ return new Set(rows.map((row) => tagIdentity(row.facet, row.tag_key)));
439
+ }
440
+ function assertDismissalCapacity(context, artifactId) {
441
+ const row = context.store.db
442
+ .prepare("SELECT COUNT(*) AS total FROM artifact_tag_dismissals WHERE artifact_id=?")
443
+ .get(artifactId);
444
+ if (row.total >= TAG_DISMISSALS_PER_ARTIFACT_MAX) {
445
+ throw new EngineFault({
446
+ code: "RESOURCE_EXHAUSTED",
447
+ message: `Artifact ${artifactId} already carries ${row.total} dismissals; the limit is ` +
448
+ `${TAG_DISMISSALS_PER_ARTIFACT_MAX}`,
449
+ details: {
450
+ artifactId,
451
+ total: row.total,
452
+ limit: TAG_DISMISSALS_PER_ARTIFACT_MAX,
453
+ },
454
+ });
455
+ }
456
+ }
457
+ function automaticLabel(context, artifactId, identity) {
458
+ const row = context.store.db
459
+ .prepare(`SELECT label FROM artifact_tags
460
+ WHERE artifact_id=? AND origin='automatic' AND facet=? AND tag_key=?`)
461
+ .get(artifactId, identity.facet, identity.key);
462
+ return row?.label;
463
+ }
464
+ /**
465
+ * Entity references are carried, never invented: a tag may point at an
466
+ * entity the caller has already confirmed, and the reference must resolve.
467
+ */
468
+ function requireEntity(context, tag) {
469
+ if (!tag.entityId)
470
+ return;
471
+ const row = context.store.db
472
+ .prepare("SELECT 1 AS present FROM entities WHERE entity_id=?")
473
+ .get(tag.entityId);
474
+ if (!row) {
475
+ throw new EngineFault({
476
+ code: "NOT_FOUND",
477
+ message: `Tag entity does not exist: ${tag.entityId}`,
478
+ details: { entityId: tag.entityId },
479
+ });
480
+ }
481
+ }
482
+ function identityDetail(tag) {
483
+ return tagIdentity(tag.facet, tag.key);
484
+ }
485
+ function writeSetKey(artifactId, tag) {
486
+ return `artifact-tag:${artifactId}:${tagIdentity(tag.facet, tag.key)}`;
487
+ }
488
+ //# sourceMappingURL=tags.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tags.js","sourceRoot":"","sources":["../src/tags.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,18 @@
1
1
  # DoltLite staging and native merge verification
2
2
 
3
- The engine pins DoltLite 0.50.6. It includes the fix for
3
+ The engine pins the temporary DoltLite `0.50.6-videobook.1` fork package from
4
+ [justintanner/doltlite](https://github.com/justintanner/doltlite/tree/videobook-node-package/packaging/videobook-node).
5
+ Its native source is `b3981dc9ed6b2e39c247b4d598b2691e19dd0b25`; its Node
6
+ wrapper is the published 0.50.6 wrapper at `4bed4889be31c683f81291e2f661d07e50b7a3fe`.
7
+ The dependency uses the [versioned release tarball](https://github.com/justintanner/doltlite/releases/tag/videobook-node-v0.50.6-videobook.1) and lockfile integrity.
8
+ Tarball SHA256: `4968a0be9b32aad3d2052b556a5b89c465f9a7959f053e0f12148a2f9d0faf3c`.
9
+ All 12 [package CI jobs](https://github.com/justintanner/doltlite/actions/runs/34049056350) passed, including clean installs on all five platforms and a source rebuild.
10
+ It includes the fix for
4
11
  [dolthub/doltlite#2644](https://github.com/dolthub/doltlite/issues/2644),
5
12
  merged in [PR 2646](https://github.com/dolthub/doltlite/pull/2646) and
6
13
  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`.
14
+ The original adoption is tracked in `ve-ovz.23`; fork packaging and installed
15
+ native-merge verification are tracked in `ve-wsu.6`.
9
16
 
10
17
  ## Fixed: incremental staging corrupts index roots
11
18
 
@@ -21,7 +28,7 @@ node scripts/dolt-staging-probe.cjs @dolthub/doltlite --stage-all
21
28
 
22
29
  Full engine URL bootstrap, backed-up catalog cloning, lazy object reads,
23
30
  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
31
+ `tests/merge-policy.test.ts` verifies full-catalog checkout and native merges preserve
25
32
  all 56 engine tables, ignored runtime rows, indexed file lookups, and integrity.
26
33
  The transcript and primary-sequence tests now perform both native merges
27
34
  instead of inserting the second branch's expected rows directly. Native row
@@ -31,7 +38,7 @@ The upstream change prevents new corrupt commits; it does not rewrite
31
38
  previously corrupted history. Snapshot bootstrap remains available for a
32
39
  healthy working catalog whose old committed schema cannot be cloned.
33
40
 
34
- ## Remaining: ignored runtime tables block native merge
41
+ ## Fixed in the fork: ignored runtime tables block native merge
35
42
 
36
43
  A separate failure reproduces on 0.50.6 with one versioned table and one
37
44
  ignored runtime table. Native merge refuses with an uncommitted-changes error
@@ -45,19 +52,32 @@ node scripts/dolt-ignored-merge-probe.cjs @dolthub/doltlite --without-index
45
52
  node scripts/dolt-ignored-merge-probe.cjs @dolthub/doltlite
46
53
  ```
47
54
 
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.
55
+ The latter two commands exit nonzero on unpatched 0.50.6. All three pass with
56
+ the pinned fork. All probes use temporary synthetic catalogs and remove them
57
+ on exit. Replace the package argument with an absolute installed-package
58
+ directory to test another build. The engine's merge-back flow keeps its
59
+ application policies, including singleton reconciliation and forget-wins
60
+ object handling.
54
61
 
55
62
  A [native source patch with validation and reproduction steps](../patches/doltlite/README.md)
56
- is now prepared on upstream commit `37a390eb7b021962d9d287a465a2da3c9f59c3cf`.
63
+ was prepared on upstream commit `37a390eb7b021962d9d287a465a2da3c9f59c3cf`.
57
64
  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.
65
+ suites, all 33 C suites, and the full 56-table engine catalog probe. It was
66
+ merged upstream in [PR 2664](https://github.com/dolthub/doltlite/pull/2664).
67
+ The temporary package provides prebuilt addons for Linux x64/arm64, macOS
68
+ x64/arm64, and Windows x64, plus matching source for the existing build fallback.
69
+ Its `fork-provenance.json` records source commits and binary checksums.
70
+ For npm versions that enforce `allowScripts`, the policy key is the exact
71
+ release asset URL; a registry-style name/version key does not match this
72
+ remote tarball dependency.
73
+
74
+ `npm run test:package` installs the engine in an empty project and checks the
75
+ actual installed fork with `scripts/native-full-catalog-merge-probe.mjs`.
76
+ That probe preserves 23 runtime tables, 107 schema objects, and deleted job ID
77
+ high-water marks through fast-forward, three-way, conflict rollback, and reopen.
78
+ Replace the fork with an upstream release once that installed artifact passes
79
+ the same checks; remove the fork-version assertion in the package smoke at that
80
+ time. No schema or file-format change is required for this adoption.
61
81
 
62
82
  Compatibility smoke tests created separate synthetic catalogs with the previous
63
83
  engine dependency (0.11.37) and the installed application dependency (0.11.51),
@@ -62,8 +62,7 @@ Seeding the 1,000 clips took 142 ms to preview and 297 ms to commit. All 50
62
62
  previews left the head revision, row counts and sequence projection unchanged,
63
63
  all 50 repeats were identical, all 50 commits advanced the head and applied
64
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.
65
+ including the embedded Dolt database.
67
66
 
68
67
  ## DoltLite 0.50.6 candidate
69
68
 
@@ -79,5 +78,4 @@ records 50 independent 100-operation transactions over 1,000 clips:
79
78
  | Commit | 50 | 299 ms | 331 ms | 348 ms |
80
79
 
81
80
  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.
81
+ process RSS is 1.54 GiB.