@semiont/make-meaning 0.4.18 → 0.4.20

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.
package/dist/index.js CHANGED
@@ -10000,7 +10000,7 @@ import { WorkingTreeStore } from "@semiont/content";
10000
10000
  var import_rxjs = __toESM(require_cjs(), 1);
10001
10001
  var import_operators = __toESM(require_operators(), 1);
10002
10002
  import { EventQuery } from "@semiont/event-sourcing";
10003
- import { didToAgent, burstBuffer } from "@semiont/core";
10003
+ import { didToAgent, burstBuffer, errField } from "@semiont/core";
10004
10004
  import { resourceId as makeResourceId, annotationId as makeAnnotationId, findBodyItem } from "@semiont/core";
10005
10005
 
10006
10006
  // src/batch-utils.ts
@@ -10109,7 +10109,7 @@ var GraphDBConsumer = class _GraphDBConsumer {
10109
10109
  this.logger.error("Failed to apply event to graph", {
10110
10110
  eventType: storedEvent.type,
10111
10111
  resourceId: storedEvent.resourceId,
10112
- error
10112
+ error: errField(error)
10113
10113
  });
10114
10114
  }
10115
10115
  }
@@ -10148,7 +10148,7 @@ var GraphDBConsumer = class _GraphDBConsumer {
10148
10148
  this.logger.error("Failed to process batch run", {
10149
10149
  eventType: run[0].type,
10150
10150
  runSize: run.length,
10151
- error
10151
+ error: errField(error)
10152
10152
  });
10153
10153
  }
10154
10154
  const last = run[run.length - 1];
@@ -10218,7 +10218,8 @@ var GraphDBConsumer = class _GraphDBConsumer {
10218
10218
  archived: false,
10219
10219
  dateCreated: (/* @__PURE__ */ new Date()).toISOString(),
10220
10220
  wasAttributedTo: didToAgent(event.userId),
10221
- creationMethod: event.payload.creationMethod
10221
+ creationMethod: event.payload.creationMethod,
10222
+ ...event.payload.storageUri ? { storageUri: event.payload.storageUri } : {}
10222
10223
  };
10223
10224
  }
10224
10225
  /**
@@ -10304,8 +10305,7 @@ var GraphDBConsumer = class _GraphDBConsumer {
10304
10305
  } catch (error) {
10305
10306
  this.logger.error("Error in annotation.body.updated handler", {
10306
10307
  annotationId: event.payload.annotationId,
10307
- error,
10308
- stack: error instanceof Error ? error.stack : void 0
10308
+ error: errField(error)
10309
10309
  });
10310
10310
  }
10311
10311
  break;
@@ -10417,23 +10417,25 @@ var GraphDBConsumer = class _GraphDBConsumer {
10417
10417
  // src/smelter.ts
10418
10418
  var import_rxjs2 = __toESM(require_cjs(), 1);
10419
10419
  var import_operators2 = __toESM(require_operators(), 1);
10420
- import { EventQuery as EventQuery2 } from "@semiont/event-sourcing";
10421
- import { burstBuffer as burstBuffer2 } from "@semiont/core";
10420
+ import { burstBuffer as burstBuffer2, errField as errField2 } from "@semiont/core";
10422
10421
  import { resourceId as makeResourceId2, annotationId as makeAnnotationId2 } from "@semiont/core";
10423
10422
  import { chunkText, DEFAULT_CHUNKING_CONFIG } from "@semiont/vectors";
10424
10423
  import { getExactText, getTargetSelector } from "@semiont/api-client";
10425
10424
  var Smelter = class _Smelter {
10426
- constructor(eventStore, eventBus, vectorStore, embeddingProvider, contentStore, logger, chunkingConfig) {
10427
- this.eventStore = eventStore;
10425
+ constructor(_eventStore, eventBus, vectorStore, embeddingProvider, contentStore, embeddingStore, viewStorage, logger, chunkingConfig) {
10428
10426
  this.eventBus = eventBus;
10429
10427
  this.vectorStore = vectorStore;
10430
10428
  this.embeddingProvider = embeddingProvider;
10431
10429
  this.contentStore = contentStore;
10430
+ this.embeddingStore = embeddingStore;
10431
+ this.viewStorage = viewStorage;
10432
10432
  this.logger = logger;
10433
10433
  this.chunkingConfig = chunkingConfig ?? DEFAULT_CHUNKING_CONFIG;
10434
10434
  }
10435
10435
  static SMELTER_RELEVANT_EVENTS = /* @__PURE__ */ new Set([
10436
10436
  "yield:created",
10437
+ "yield:updated",
10438
+ "yield:representation-added",
10437
10439
  "mark:archived",
10438
10440
  "mark:added",
10439
10441
  "mark:removed"
@@ -10485,68 +10487,121 @@ var Smelter = class _Smelter {
10485
10487
  this.logger.info("Smelter actor stopped");
10486
10488
  }
10487
10489
  /**
10488
- * Rebuild the vector store from persisted embedding events in the event log.
10489
- * Reads all embedding:computed / embedding:deleted events and replays them.
10490
- * Bypasses the live pipeline reads directly from the event store.
10490
+ * Rebuild the vector store from the EmbeddingStore (.semiont/embeddings/).
10491
+ *
10492
+ * For each stored file, checks whether the model matches the configured
10493
+ * provider. On mismatch, re-embeds from the stored text and overwrites the
10494
+ * file before upserting into Qdrant. On match, loads the stored vectors
10495
+ * directly — no embedding provider calls needed.
10491
10496
  */
10492
10497
  async rebuildAll() {
10493
- this.logger.info("Rebuilding vector store from events");
10498
+ this.logger.info("Rebuilding vector store from EmbeddingStore");
10494
10499
  await this.vectorStore.clearAll();
10495
- const allResourceIds = await this.eventStore.log.getAllResourceIds();
10496
- this.logger.info("Found resources to scan", { count: allResourceIds.length });
10497
- const query = new EventQuery2(this.eventStore.log.storage);
10498
- let indexed = 0;
10499
- for (const rid of allResourceIds) {
10500
- const events = await query.getResourceEvents(makeResourceId2(rid));
10501
- const embeddingEvents = events.filter(
10502
- (e) => e.type === "embedding:computed" || e.type === "embedding:deleted"
10503
- );
10504
- if (embeddingEvents.length === 0) continue;
10505
- const lastEvent = embeddingEvents[embeddingEvents.length - 1];
10506
- if (lastEvent.type === "embedding:deleted" && !lastEvent.payload.annotationId) {
10507
- continue;
10508
- }
10509
- const deletedAnnotations = /* @__PURE__ */ new Set();
10510
- for (const e of embeddingEvents) {
10511
- if (e.type === "embedding:deleted") {
10512
- const payload = e.payload;
10513
- if (payload.annotationId) deletedAnnotations.add(String(payload.annotationId));
10514
- }
10515
- }
10516
- const resourceChunks = [];
10517
- for (const e of embeddingEvents) {
10518
- if (e.type !== "embedding:computed") continue;
10519
- const payload = e.payload;
10520
- if (payload.annotationId) {
10521
- if (deletedAnnotations.has(String(payload.annotationId))) continue;
10522
- await this.vectorStore.upsertAnnotationVector(
10523
- makeAnnotationId2(String(payload.annotationId)),
10524
- payload.embedding,
10525
- {
10526
- annotationId: makeAnnotationId2(String(payload.annotationId)),
10527
- resourceId: makeResourceId2(e.resourceId),
10528
- motivation: "",
10529
- entityTypes: [],
10530
- exactText: payload.chunkText
10531
- }
10532
- );
10533
- } else {
10534
- resourceChunks.push({
10535
- chunkIndex: payload.chunkIndex,
10536
- text: payload.chunkText,
10537
- embedding: payload.embedding
10538
- });
10539
- }
10540
- }
10541
- if (resourceChunks.length > 0) {
10542
- await this.vectorStore.upsertResourceVectors(
10543
- makeResourceId2(rid),
10544
- resourceChunks
10500
+ const currentModel = this.embeddingProvider.model();
10501
+ const currentDimensions = this.embeddingProvider.dimensions();
10502
+ const resourceIds = await this.embeddingStore.getAllResourceIds();
10503
+ this.logger.info("Found resource embedding files", { count: resourceIds.length });
10504
+ let resourcesIndexed = 0;
10505
+ for (const rid of resourceIds) {
10506
+ const resourceId7 = makeResourceId2(rid);
10507
+ const stored = await this.embeddingStore.readResourceEmbeddings(resourceId7);
10508
+ if (!stored || stored.chunks.length === 0) continue;
10509
+ let chunks;
10510
+ if (stored.model !== currentModel) {
10511
+ this.logger.info("Re-embedding resource (model mismatch)", {
10512
+ resourceId: rid,
10513
+ storedModel: stored.model,
10514
+ currentModel
10515
+ });
10516
+ const texts = stored.chunks.map((c) => c.text);
10517
+ const embeddings = await this.embeddingProvider.embedBatch(texts);
10518
+ chunks = stored.chunks.map((c, i) => ({
10519
+ chunkIndex: c.chunkIndex,
10520
+ text: c.text,
10521
+ embedding: embeddings[i]
10522
+ }));
10523
+ await this.embeddingStore.writeResourceChunks(resourceId7, currentModel, currentDimensions, chunks);
10524
+ } else {
10525
+ chunks = stored.chunks;
10526
+ }
10527
+ await this.vectorStore.upsertResourceVectors(resourceId7, chunks);
10528
+ resourcesIndexed++;
10529
+ }
10530
+ const annotationIds = await this.embeddingStore.getAllAnnotationIds();
10531
+ this.logger.info("Found annotation embedding files", { count: annotationIds.length });
10532
+ let annotationsIndexed = 0;
10533
+ for (const aid of annotationIds) {
10534
+ const annotationId3 = makeAnnotationId2(aid);
10535
+ const stored = await this.embeddingStore.readAnnotationEmbedding(annotationId3);
10536
+ if (!stored) continue;
10537
+ let embedding;
10538
+ if (stored.model !== currentModel) {
10539
+ this.logger.info("Re-embedding annotation (model mismatch)", {
10540
+ annotationId: aid,
10541
+ storedModel: stored.model,
10542
+ currentModel
10543
+ });
10544
+ embedding = await this.embeddingProvider.embed(stored.text);
10545
+ await this.embeddingStore.writeAnnotationEmbedding(
10546
+ annotationId3,
10547
+ makeResourceId2(stored.resourceId),
10548
+ currentModel,
10549
+ currentDimensions,
10550
+ stored.text,
10551
+ embedding,
10552
+ stored.motivation,
10553
+ stored.entityTypes
10545
10554
  );
10555
+ } else {
10556
+ embedding = stored.embedding;
10546
10557
  }
10547
- indexed++;
10558
+ const payload = {
10559
+ annotationId: annotationId3,
10560
+ resourceId: makeResourceId2(stored.resourceId),
10561
+ motivation: stored.motivation,
10562
+ entityTypes: stored.entityTypes,
10563
+ exactText: stored.text
10564
+ };
10565
+ await this.vectorStore.upsertAnnotationVector(annotationId3, embedding, payload);
10566
+ annotationsIndexed++;
10567
+ }
10568
+ const storedResourceIdSet = new Set(resourceIds);
10569
+ const allViews = await this.viewStorage.getAll();
10570
+ let backfilled = 0;
10571
+ for (const view of allViews) {
10572
+ const ridStr = view.resource["@id"];
10573
+ if (storedResourceIdSet.has(ridStr)) continue;
10574
+ if (view.resource.archived) continue;
10575
+ if (!view.resource.storageUri) continue;
10576
+ let content;
10577
+ try {
10578
+ content = await this.contentStore.retrieve(view.resource.storageUri);
10579
+ } catch (err) {
10580
+ this.logger.warn("Smelter back-fill skipped \u2014 content missing", {
10581
+ resourceId: ridStr,
10582
+ storageUri: view.resource.storageUri,
10583
+ error: err instanceof Error ? err.message : String(err)
10584
+ });
10585
+ continue;
10586
+ }
10587
+ const text = new TextDecoder().decode(content);
10588
+ if (!text.trim()) continue;
10589
+ const chunks = chunkText(text, this.chunkingConfig);
10590
+ if (chunks.length === 0) continue;
10591
+ const rid = makeResourceId2(ridStr);
10592
+ const embeddings = await this.embeddingProvider.embedBatch(chunks);
10593
+ const embeddingChunks = chunks.map((chunkText2, i) => ({
10594
+ chunkIndex: i,
10595
+ text: chunkText2,
10596
+ embedding: embeddings[i]
10597
+ }));
10598
+ await this.embeddingStore.writeResourceChunks(rid, currentModel, currentDimensions, embeddingChunks);
10599
+ await this.vectorStore.upsertResourceVectors(rid, embeddingChunks);
10600
+ backfilled++;
10601
+ resourcesIndexed++;
10602
+ this.logger.info("Smelter back-filled missing resource embedding", { resourceId: ridStr });
10548
10603
  }
10549
- this.logger.info("Vector store rebuild complete", { resourcesIndexed: indexed });
10604
+ this.logger.info("Vector store rebuild complete", { resourcesIndexed, annotationsIndexed, backfilled });
10550
10605
  }
10551
10606
  async processBatch(events) {
10552
10607
  const runs = partitionByType(events);
@@ -10561,15 +10616,13 @@ var Smelter = class _Smelter {
10561
10616
  this.logger.error("Smelter failed to process batch run", {
10562
10617
  eventType: run[0].type,
10563
10618
  runSize: run.length,
10564
- error
10619
+ error: errField2(error)
10565
10620
  });
10566
10621
  }
10567
10622
  }
10568
10623
  }
10569
10624
  /**
10570
10625
  * Batch-optimized processing for consecutive events of the same type.
10571
- * Collects all texts across events, embeds in a single embedBatch() call,
10572
- * then distributes results back to their respective resources/annotations.
10573
10626
  */
10574
10627
  async applyBatchByType(events) {
10575
10628
  const type = events[0].type;
@@ -10587,8 +10640,8 @@ var Smelter = class _Smelter {
10587
10640
  }
10588
10641
  }
10589
10642
  /**
10590
- * Batch-embed chunks from multiple resource.created events in a single
10591
- * embedBatch() call, then emit events and index per resource.
10643
+ * Batch-embed chunks from multiple yield:created events in a single
10644
+ * embedBatch() call, then write to EmbeddingStore and index per resource.
10592
10645
  */
10593
10646
  async batchResourceCreated(events) {
10594
10647
  const resourceData = [];
@@ -10613,18 +10666,12 @@ var Smelter = class _Smelter {
10613
10666
  const dimensions = this.embeddingProvider.dimensions();
10614
10667
  let offset = 0;
10615
10668
  for (const { rid, chunks } of resourceData) {
10616
- const embeddingChunks = chunks.map((text, i) => {
10617
- const embedding = allEmbeddings[offset + i];
10618
- this.eventBus.get("embedding:compute").next({
10619
- resourceId: rid,
10620
- chunkIndex: i,
10621
- chunkText: text,
10622
- embedding,
10623
- model,
10624
- dimensions
10625
- });
10626
- return { chunkIndex: i, text, embedding };
10627
- });
10669
+ const embeddingChunks = chunks.map((text, i) => ({
10670
+ chunkIndex: i,
10671
+ text,
10672
+ embedding: allEmbeddings[offset + i]
10673
+ }));
10674
+ await this.embeddingStore.writeResourceChunks(rid, model, dimensions, embeddingChunks);
10628
10675
  await this.vectorStore.upsertResourceVectors(rid, embeddingChunks);
10629
10676
  this.logger.debug("Smelter batch-indexed resource", {
10630
10677
  resourceId: String(rid),
@@ -10634,8 +10681,8 @@ var Smelter = class _Smelter {
10634
10681
  }
10635
10682
  }
10636
10683
  /**
10637
- * Batch-embed exact texts from multiple annotation.added events in a
10638
- * single embedBatch() call, then emit events and index per annotation.
10684
+ * Batch-embed exact texts from multiple mark:added events in a single
10685
+ * embedBatch() call, then write to EmbeddingStore and index per annotation.
10639
10686
  */
10640
10687
  async batchAnnotationAdded(events) {
10641
10688
  const annotationData = [];
@@ -10650,30 +10697,34 @@ var Smelter = class _Smelter {
10650
10697
  rid: makeResourceId2(event.resourceId),
10651
10698
  aid: makeAnnotationId2(annotation.id),
10652
10699
  exactText,
10653
- annotation
10700
+ motivation: annotation.motivation ?? "",
10701
+ entityTypes: annotation.entityTypes ?? []
10654
10702
  });
10655
10703
  }
10656
10704
  if (annotationData.length === 0) return;
10657
10705
  const allEmbeddings = await this.embeddingProvider.embedBatch(
10658
10706
  annotationData.map((a) => a.exactText)
10659
10707
  );
10708
+ const model = this.embeddingProvider.model();
10709
+ const dimensions = this.embeddingProvider.dimensions();
10660
10710
  for (let i = 0; i < annotationData.length; i++) {
10661
- const { rid, aid, exactText, annotation } = annotationData[i];
10711
+ const { rid, aid, exactText, motivation, entityTypes } = annotationData[i];
10662
10712
  const embedding = allEmbeddings[i];
10663
- this.eventBus.get("embedding:compute").next({
10664
- resourceId: rid,
10665
- annotationId: aid,
10666
- chunkIndex: 0,
10667
- chunkText: exactText,
10713
+ await this.embeddingStore.writeAnnotationEmbedding(
10714
+ aid,
10715
+ rid,
10716
+ model,
10717
+ dimensions,
10718
+ exactText,
10668
10719
  embedding,
10669
- model: this.embeddingProvider.model(),
10670
- dimensions: this.embeddingProvider.dimensions()
10671
- });
10720
+ motivation,
10721
+ entityTypes
10722
+ );
10672
10723
  const payload = {
10673
10724
  annotationId: aid,
10674
10725
  resourceId: rid,
10675
- motivation: annotation.motivation ?? "",
10676
- entityTypes: annotation.entityTypes ?? [],
10726
+ motivation,
10727
+ entityTypes,
10677
10728
  exactText
10678
10729
  };
10679
10730
  await this.vectorStore.upsertAnnotationVector(aid, embedding, payload);
@@ -10696,19 +10747,24 @@ var Smelter = class _Smelter {
10696
10747
  }
10697
10748
  }
10698
10749
  async processEvent(storedEvent) {
10699
- const event = storedEvent;
10700
- switch (event.type) {
10750
+ switch (storedEvent.type) {
10701
10751
  case "yield:created":
10702
- await this.handleResourceCreated(event);
10752
+ await this.handleResourceCreated(storedEvent);
10753
+ break;
10754
+ case "yield:updated":
10755
+ await this.handleResourceUpdated(storedEvent);
10756
+ break;
10757
+ case "yield:representation-added":
10758
+ await this.handleRepresentationAdded(storedEvent);
10703
10759
  break;
10704
10760
  case "mark:archived":
10705
- await this.handleResourceArchived(event);
10761
+ await this.handleResourceArchived(storedEvent);
10706
10762
  break;
10707
10763
  case "mark:added":
10708
- await this.handleAnnotationAdded(event);
10764
+ await this.handleAnnotationAdded(storedEvent);
10709
10765
  break;
10710
10766
  case "mark:removed":
10711
- await this.handleAnnotationRemoved(event);
10767
+ await this.handleAnnotationRemoved(storedEvent);
10712
10768
  break;
10713
10769
  }
10714
10770
  }
@@ -10743,18 +10799,13 @@ var Smelter = class _Smelter {
10743
10799
  dimensions,
10744
10800
  heapMB: Math.round(process.memoryUsage().heapUsed / 1024 / 1024)
10745
10801
  });
10746
- const embeddingChunks = chunks.map((text2, i) => {
10747
- this.eventBus.get("embedding:compute").next({
10748
- resourceId: rid,
10749
- chunkIndex: i,
10750
- chunkText: text2,
10751
- embedding: embeddings[i],
10752
- model,
10753
- dimensions
10754
- });
10755
- return { chunkIndex: i, text: text2, embedding: embeddings[i] };
10756
- });
10757
- this.logger.info("Smelter emitted events", {
10802
+ const embeddingChunks = chunks.map((text2, i) => ({
10803
+ chunkIndex: i,
10804
+ text: text2,
10805
+ embedding: embeddings[i]
10806
+ }));
10807
+ await this.embeddingStore.writeResourceChunks(rid, model, dimensions, embeddingChunks);
10808
+ this.logger.info("Smelter wrote resource embeddings to store", {
10758
10809
  resourceId: String(rid),
10759
10810
  chunkCount: embeddingChunks.length,
10760
10811
  heapMB: Math.round(process.memoryUsage().heapUsed / 1024 / 1024)
@@ -10766,13 +10817,51 @@ var Smelter = class _Smelter {
10766
10817
  heapMB: Math.round(process.memoryUsage().heapUsed / 1024 / 1024)
10767
10818
  });
10768
10819
  }
10820
+ /**
10821
+ * Re-embed a resource whose content has changed in-place.
10822
+ *
10823
+ * Used by yield:updated and yield:representation-added handlers. Reads the
10824
+ * current storageUri from the materialized view (which is updated before the
10825
+ * EventBus fires), deletes stale Qdrant vectors, and overwrites the
10826
+ * EmbeddingStore file with fresh chunks.
10827
+ */
10828
+ async reembedResource(rid) {
10829
+ const view = await this.viewStorage.get(rid);
10830
+ const storageUri = view?.resource.storageUri;
10831
+ if (!storageUri) return;
10832
+ const content = await this.contentStore.retrieve(storageUri);
10833
+ if (!content) return;
10834
+ const text = new TextDecoder().decode(content);
10835
+ if (!text.trim()) return;
10836
+ const chunks = chunkText(text, this.chunkingConfig);
10837
+ if (chunks.length === 0) return;
10838
+ const embeddings = await this.embeddingProvider.embedBatch(chunks);
10839
+ const model = this.embeddingProvider.model();
10840
+ const dimensions = this.embeddingProvider.dimensions();
10841
+ const embeddingChunks = chunks.map((chunkText2, i) => ({
10842
+ chunkIndex: i,
10843
+ text: chunkText2,
10844
+ embedding: embeddings[i]
10845
+ }));
10846
+ await this.embeddingStore.writeResourceChunks(rid, model, dimensions, embeddingChunks);
10847
+ await this.vectorStore.deleteResourceVectors(rid);
10848
+ await this.vectorStore.upsertResourceVectors(rid, embeddingChunks);
10849
+ this.logger.debug("Smelter re-embedded resource", {
10850
+ resourceId: String(rid),
10851
+ chunks: embeddingChunks.length
10852
+ });
10853
+ }
10854
+ async handleResourceUpdated(event) {
10855
+ await this.reembedResource(makeResourceId2(event.resourceId));
10856
+ }
10857
+ async handleRepresentationAdded(event) {
10858
+ await this.reembedResource(makeResourceId2(event.resourceId));
10859
+ }
10769
10860
  async handleResourceArchived(event) {
10770
10861
  const rid = makeResourceId2(event.resourceId);
10771
10862
  await this.vectorStore.deleteResourceVectors(rid);
10772
- this.eventBus.get("embedding:delete").next({ resourceId: rid });
10773
- this.logger.debug("Smelter deleted resource vectors", {
10774
- resourceId: String(rid)
10775
- });
10863
+ await this.embeddingStore.deleteResourceEmbeddings(rid);
10864
+ this.logger.debug("Smelter deleted resource vectors", { resourceId: String(rid) });
10776
10865
  }
10777
10866
  async handleAnnotationAdded(event) {
10778
10867
  await new Promise((resolve2) => setTimeout(resolve2, 0));
@@ -10790,20 +10879,25 @@ var Smelter = class _Smelter {
10790
10879
  heapMB: Math.round(process.memoryUsage().heapUsed / 1024 / 1024)
10791
10880
  });
10792
10881
  const embedding = await this.embeddingProvider.embed(exactText);
10793
- this.eventBus.get("embedding:compute").next({
10794
- resourceId: rid,
10795
- annotationId: aid,
10796
- chunkIndex: 0,
10797
- chunkText: exactText,
10882
+ const model = this.embeddingProvider.model();
10883
+ const dimensions = this.embeddingProvider.dimensions();
10884
+ const motivation = annotation.motivation ?? "";
10885
+ const entityTypes = annotation.entityTypes ?? [];
10886
+ await this.embeddingStore.writeAnnotationEmbedding(
10887
+ aid,
10888
+ rid,
10889
+ model,
10890
+ dimensions,
10891
+ exactText,
10798
10892
  embedding,
10799
- model: this.embeddingProvider.model(),
10800
- dimensions: this.embeddingProvider.dimensions()
10801
- });
10893
+ motivation,
10894
+ entityTypes
10895
+ );
10802
10896
  const payload = {
10803
10897
  annotationId: aid,
10804
10898
  resourceId: rid,
10805
- motivation: annotation.motivation ?? "",
10806
- entityTypes: annotation.entityTypes ?? [],
10899
+ motivation,
10900
+ entityTypes,
10807
10901
  exactText
10808
10902
  };
10809
10903
  await this.vectorStore.upsertAnnotationVector(aid, embedding, payload);
@@ -10815,16 +10909,134 @@ var Smelter = class _Smelter {
10815
10909
  async handleAnnotationRemoved(event) {
10816
10910
  const annotationId3 = String(event.payload.annotationId);
10817
10911
  if (!annotationId3) return;
10818
- const rid = makeResourceId2(event.resourceId);
10819
10912
  const aid = makeAnnotationId2(annotationId3);
10820
10913
  await this.vectorStore.deleteAnnotationVector(aid);
10821
- this.eventBus.get("embedding:delete").next({
10822
- resourceId: rid,
10823
- annotationId: aid
10824
- });
10825
- this.logger.debug("Smelter deleted annotation vector", {
10826
- annotationId: String(aid)
10827
- });
10914
+ await this.embeddingStore.deleteAnnotationEmbedding(aid);
10915
+ this.logger.debug("Smelter deleted annotation vector", { annotationId: String(aid) });
10916
+ }
10917
+ };
10918
+
10919
+ // src/embedding-store.ts
10920
+ import { promises as fs } from "fs";
10921
+ import * as path from "path";
10922
+ import { getShardPath } from "@semiont/event-sourcing";
10923
+ var EmbeddingStore = class {
10924
+ constructor(project) {
10925
+ this.project = project;
10926
+ }
10927
+ // ── Path helpers ────────────────────────────────────────────────────────────
10928
+ resourceFilePath(resourceId7) {
10929
+ const [ab, cd] = getShardPath(String(resourceId7));
10930
+ return path.join(this.project.embeddingsDir, ab, cd, `${String(resourceId7)}.jsonl`);
10931
+ }
10932
+ annotationFilePath(annotationId3) {
10933
+ const [ab, cd] = getShardPath(String(annotationId3));
10934
+ return path.join(this.project.embeddingsDir, ab, cd, `${String(annotationId3)}.json`);
10935
+ }
10936
+ // ── Resource embeddings ─────────────────────────────────────────────────────
10937
+ async writeResourceChunks(resourceId7, model, dimensions, chunks) {
10938
+ const filePath = this.resourceFilePath(resourceId7);
10939
+ await fs.mkdir(path.dirname(filePath), { recursive: true });
10940
+ const header = JSON.stringify({ model, dimensions });
10941
+ const lines = chunks.map(
10942
+ (c) => JSON.stringify({ chunkIndex: c.chunkIndex, text: c.text, embedding: c.embedding })
10943
+ );
10944
+ await fs.writeFile(filePath, [header, ...lines].join("\n") + "\n", "utf-8");
10945
+ }
10946
+ async readResourceEmbeddings(resourceId7) {
10947
+ const filePath = this.resourceFilePath(resourceId7);
10948
+ try {
10949
+ const content = await fs.readFile(filePath, "utf-8");
10950
+ const lines = content.trim().split("\n").filter((l) => l.trim());
10951
+ if (lines.length === 0) return null;
10952
+ const header = JSON.parse(lines[0]);
10953
+ const chunks = lines.slice(1).map((l) => JSON.parse(l));
10954
+ return { model: header.model, dimensions: header.dimensions, chunks };
10955
+ } catch (err) {
10956
+ if (err.code === "ENOENT") return null;
10957
+ throw err;
10958
+ }
10959
+ }
10960
+ async deleteResourceEmbeddings(resourceId7) {
10961
+ const filePath = this.resourceFilePath(resourceId7);
10962
+ try {
10963
+ await fs.unlink(filePath);
10964
+ } catch (err) {
10965
+ if (err.code !== "ENOENT") throw err;
10966
+ }
10967
+ }
10968
+ // ── Annotation embeddings ───────────────────────────────────────────────────
10969
+ async writeAnnotationEmbedding(annotationId3, resourceId7, model, dimensions, text, embedding, motivation, entityTypes) {
10970
+ const filePath = this.annotationFilePath(annotationId3);
10971
+ await fs.mkdir(path.dirname(filePath), { recursive: true });
10972
+ const data = {
10973
+ model,
10974
+ dimensions,
10975
+ resourceId: String(resourceId7),
10976
+ text,
10977
+ embedding,
10978
+ motivation,
10979
+ entityTypes
10980
+ };
10981
+ await fs.writeFile(filePath, JSON.stringify(data), "utf-8");
10982
+ }
10983
+ async readAnnotationEmbedding(annotationId3) {
10984
+ const filePath = this.annotationFilePath(annotationId3);
10985
+ try {
10986
+ const content = await fs.readFile(filePath, "utf-8");
10987
+ return JSON.parse(content);
10988
+ } catch (err) {
10989
+ if (err.code === "ENOENT") return null;
10990
+ throw err;
10991
+ }
10992
+ }
10993
+ async deleteAnnotationEmbedding(annotationId3) {
10994
+ const filePath = this.annotationFilePath(annotationId3);
10995
+ try {
10996
+ await fs.unlink(filePath);
10997
+ } catch (err) {
10998
+ if (err.code !== "ENOENT") throw err;
10999
+ }
11000
+ }
11001
+ // ── Scan ────────────────────────────────────────────────────────────────────
11002
+ /**
11003
+ * Scan embeddings directory and return all resource IDs (from *.jsonl files).
11004
+ */
11005
+ async getAllResourceIds() {
11006
+ return this.scanIds((name) => name.endsWith(".jsonl"), ".jsonl");
11007
+ }
11008
+ /**
11009
+ * Scan embeddings directory and return all annotation IDs (from *.json files).
11010
+ */
11011
+ async getAllAnnotationIds() {
11012
+ return this.scanIds((name) => name.endsWith(".json"), ".json");
11013
+ }
11014
+ async scanIds(filter, ext) {
11015
+ const base = this.project.embeddingsDir;
11016
+ try {
11017
+ await fs.access(base);
11018
+ } catch {
11019
+ return [];
11020
+ }
11021
+ const results = [];
11022
+ const scan = async (dir) => {
11023
+ let entries;
11024
+ try {
11025
+ entries = await fs.readdir(dir, { withFileTypes: true });
11026
+ } catch {
11027
+ return;
11028
+ }
11029
+ for (const entry of entries) {
11030
+ const full = path.join(dir, entry.name);
11031
+ if (entry.isDirectory()) {
11032
+ await scan(full);
11033
+ } else if (filter(entry.name)) {
11034
+ results.push(entry.name.slice(0, -ext.length));
11035
+ }
11036
+ }
11037
+ };
11038
+ await scan(base);
11039
+ return results;
10828
11040
  }
10829
11041
  };
10830
11042
 
@@ -10856,12 +11068,15 @@ async function createKnowledgeBase(eventStore, project, graphDb, eventBus, logge
10856
11068
  };
10857
11069
  if (options?.vectorStore && options?.embeddingProvider) {
10858
11070
  kb.vectors = options.vectorStore;
11071
+ const embeddingStore = new EmbeddingStore(project);
10859
11072
  kb.smelter = new Smelter(
10860
11073
  eventStore,
10861
11074
  eventBus,
10862
11075
  options.vectorStore,
10863
11076
  options.embeddingProvider,
10864
11077
  content,
11078
+ embeddingStore,
11079
+ views,
10865
11080
  logger.child({ component: "smelter" }),
10866
11081
  options.chunkingConfig
10867
11082
  );
@@ -10876,7 +11091,7 @@ async function createKnowledgeBase(eventStore, project, graphDb, eventBus, logge
10876
11091
  // src/gatherer.ts
10877
11092
  var import_rxjs3 = __toESM(require_cjs(), 1);
10878
11093
  var import_operators3 = __toESM(require_operators(), 1);
10879
- import { annotationId as makeAnnotationId3, resourceId } from "@semiont/core";
11094
+ import { annotationId as makeAnnotationId3, resourceId, errField as errField3 } from "@semiont/core";
10880
11095
 
10881
11096
  // src/generation/resource-generation.ts
10882
11097
  async function generateResourceSummary(resourceName, content, entityTypes, client) {
@@ -11664,7 +11879,7 @@ var Gatherer = class {
11664
11879
  } catch (error) {
11665
11880
  this.logger.error("Gather annotation context failed", {
11666
11881
  annotationId: event.annotationId,
11667
- error
11882
+ error: errField3(error)
11668
11883
  });
11669
11884
  resultBus.get("gather:failed").next({
11670
11885
  correlationId: event.correlationId,
@@ -11693,7 +11908,7 @@ var Gatherer = class {
11693
11908
  } catch (error) {
11694
11909
  this.logger.error("Gather resource context failed", {
11695
11910
  resourceId: event.resourceId,
11696
- error
11911
+ error: errField3(error)
11697
11912
  });
11698
11913
  resultBus.get("gather:resource-failed").next({
11699
11914
  correlationId: event.correlationId,
@@ -11722,7 +11937,7 @@ var Gatherer = class {
11722
11937
  // src/matcher.ts
11723
11938
  var import_rxjs4 = __toESM(require_cjs(), 1);
11724
11939
  var import_operators4 = __toESM(require_operators(), 1);
11725
- import { resourceId as resourceId2 } from "@semiont/core";
11940
+ import { resourceId as resourceId2, errField as errField4 } from "@semiont/core";
11726
11941
  import { getResourceId as getResourceId4, getResourceEntityTypes as getResourceEntityTypes4 } from "@semiont/api-client";
11727
11942
  var Matcher = class {
11728
11943
  constructor(kb, eventBus, logger, inferenceClient, embeddingProvider) {
@@ -11771,7 +11986,7 @@ var Matcher = class {
11771
11986
  } catch (error) {
11772
11987
  this.logger.error("Bind search failed", {
11773
11988
  referenceId: event.referenceId,
11774
- error
11989
+ error: errField4(error)
11775
11990
  });
11776
11991
  this.eventBus.scope(event.resourceId).get("match:search-failed").next({
11777
11992
  correlationId: event.correlationId,
@@ -12041,7 +12256,7 @@ For each candidate, output a line with the number and score, like:
12041
12256
  // src/stower.ts
12042
12257
  var import_rxjs5 = __toESM(require_cjs(), 1);
12043
12258
  var import_operators5 = __toESM(require_operators(), 1);
12044
- import { promises as fs } from "fs";
12259
+ import { promises as fs2 } from "fs";
12045
12260
  import { resourceId as resourceId3, userId as makeUserId, annotationId as makeAnnotationId4, CREATION_METHODS, generateUuid } from "@semiont/core";
12046
12261
  import { resolveStorageUri } from "@semiont/event-sourcing";
12047
12262
  var Stower = class {
@@ -12069,9 +12284,7 @@ var Stower = class {
12069
12284
  pipe("job:start", (e) => this.handleJobStart(e)),
12070
12285
  pipe("job:report-progress", (e) => this.handleJobReportProgress(e)),
12071
12286
  pipe("job:complete", (e) => this.handleJobComplete(e)),
12072
- pipe("job:fail", (e) => this.handleJobFail(e)),
12073
- pipe("embedding:compute", (e) => this.handleEmbeddingComputed(e)),
12074
- pipe("embedding:delete", (e) => this.handleEmbeddingDeleted(e))
12287
+ pipe("job:fail", (e) => this.handleJobFail(e))
12075
12288
  ).subscribe({
12076
12289
  error: (err) => this.logger.error("Stower pipeline error", { error: err })
12077
12290
  });
@@ -12275,7 +12488,7 @@ var Stower = class {
12275
12488
  if (event.storageUri) {
12276
12489
  const absPath = this.kb.content.resolveUri(event.storageUri);
12277
12490
  try {
12278
- await fs.access(absPath);
12491
+ await fs2.access(absPath);
12279
12492
  } catch {
12280
12493
  this.logger.warn("Unarchive failed: file not found at storageUri", { storageUri: event.storageUri });
12281
12494
  return;
@@ -12375,33 +12588,6 @@ var Stower = class {
12375
12588
  }
12376
12589
  });
12377
12590
  }
12378
- async handleEmbeddingComputed(event) {
12379
- await this.kb.eventStore.appendEvent({
12380
- type: "embedding:computed",
12381
- resourceId: resourceId3(event.resourceId),
12382
- userId: makeUserId("did:web:system:smelter"),
12383
- version: 1,
12384
- payload: {
12385
- annotationId: event.annotationId,
12386
- chunkIndex: event.chunkIndex,
12387
- chunkText: event.chunkText,
12388
- embedding: event.embedding,
12389
- model: event.model,
12390
- dimensions: event.dimensions
12391
- }
12392
- });
12393
- }
12394
- async handleEmbeddingDeleted(event) {
12395
- await this.kb.eventStore.appendEvent({
12396
- type: "embedding:deleted",
12397
- resourceId: resourceId3(event.resourceId),
12398
- userId: makeUserId("did:web:system:smelter"),
12399
- version: 1,
12400
- payload: {
12401
- annotationId: event.annotationId
12402
- }
12403
- });
12404
- }
12405
12591
  async stop() {
12406
12592
  this.subscription?.unsubscribe();
12407
12593
  this.subscription = null;
@@ -12412,25 +12598,25 @@ var Stower = class {
12412
12598
  // src/browser.ts
12413
12599
  var import_rxjs6 = __toESM(require_cjs(), 1);
12414
12600
  var import_operators6 = __toESM(require_operators(), 1);
12415
- import { promises as fs3 } from "fs";
12416
- import * as path2 from "path";
12417
- import { resourceId as resourceId4, annotationId } from "@semiont/core";
12601
+ import { promises as fs4 } from "fs";
12602
+ import * as path3 from "path";
12603
+ import { resourceId as resourceId4, annotationId, errField as errField5 } from "@semiont/core";
12418
12604
  import { getExactText as getExactText2, getTargetSource as getTargetSource2, getTargetSelector as getTargetSelector3, getResourceEntityTypes as getResourceEntityTypes5, getBodySource as getBodySource2 } from "@semiont/api-client";
12419
- import { EventQuery as EventQuery3 } from "@semiont/event-sourcing";
12605
+ import { EventQuery as EventQuery2 } from "@semiont/event-sourcing";
12420
12606
  import { getEntityTypes as getEntityTypes2 } from "@semiont/ontology";
12421
12607
 
12422
12608
  // src/views/entity-types-reader.ts
12423
- import { promises as fs2 } from "fs";
12424
- import * as path from "path";
12609
+ import { promises as fs3 } from "fs";
12610
+ import * as path2 from "path";
12425
12611
  async function readEntityTypesProjection(project) {
12426
- const entityTypesPath = path.join(
12612
+ const entityTypesPath = path2.join(
12427
12613
  project.stateDir,
12428
12614
  "projections",
12429
12615
  "__system__",
12430
12616
  "entitytypes.json"
12431
12617
  );
12432
12618
  try {
12433
- const content = await fs2.readFile(entityTypesPath, "utf-8");
12619
+ const content = await fs3.readFile(entityTypesPath, "utf-8");
12434
12620
  const projection = JSON.parse(content);
12435
12621
  return projection.entityTypes || [];
12436
12622
  } catch (error) {
@@ -12473,7 +12659,7 @@ var Browser = class {
12473
12659
  // ========================================================================
12474
12660
  async handleBrowseResource(event) {
12475
12661
  try {
12476
- const eventQuery = new EventQuery3(this.kb.eventStore.log.storage);
12662
+ const eventQuery = new EventQuery2(this.kb.eventStore.log.storage);
12477
12663
  const events = await eventQuery.getResourceEvents(resourceId4(event.resourceId));
12478
12664
  const stored = await this.kb.eventStore.views.materializer.materialize(events, resourceId4(event.resourceId));
12479
12665
  if (!stored) {
@@ -12497,7 +12683,7 @@ var Browser = class {
12497
12683
  }
12498
12684
  });
12499
12685
  } catch (error) {
12500
- this.logger.error("Browse resource failed", { resourceId: event.resourceId, error });
12686
+ this.logger.error("Browse resource failed", { resourceId: event.resourceId, error: errField5(error) });
12501
12687
  this.eventBus.get("browse:resource-failed").next({
12502
12688
  correlationId: event.correlationId,
12503
12689
  message: error instanceof Error ? error.message : String(error)
@@ -12527,7 +12713,7 @@ var Browser = class {
12527
12713
  }
12528
12714
  });
12529
12715
  } catch (error) {
12530
- this.logger.error("Browse resources failed", { error });
12716
+ this.logger.error("Browse resources failed", { error: errField5(error) });
12531
12717
  this.eventBus.get("browse:resources-failed").next({
12532
12718
  correlationId: event.correlationId,
12533
12719
  message: error instanceof Error ? error.message : String(error)
@@ -12545,7 +12731,7 @@ var Browser = class {
12545
12731
  }
12546
12732
  });
12547
12733
  } catch (error) {
12548
- this.logger.error("Browse annotations failed", { resourceId: event.resourceId, error });
12734
+ this.logger.error("Browse annotations failed", { resourceId: event.resourceId, error: errField5(error) });
12549
12735
  this.eventBus.get("browse:annotations-failed").next({
12550
12736
  correlationId: event.correlationId,
12551
12737
  message: error instanceof Error ? error.message : String(error)
@@ -12577,7 +12763,7 @@ var Browser = class {
12577
12763
  }
12578
12764
  });
12579
12765
  } catch (error) {
12580
- this.logger.error("Browse annotation failed", { resourceId: event.resourceId, annotationId: event.annotationId, error });
12766
+ this.logger.error("Browse annotation failed", { resourceId: event.resourceId, annotationId: event.annotationId, error: errField5(error) });
12581
12767
  this.eventBus.get("browse:annotation-failed").next({
12582
12768
  correlationId: event.correlationId,
12583
12769
  message: error instanceof Error ? error.message : String(error)
@@ -12586,7 +12772,7 @@ var Browser = class {
12586
12772
  }
12587
12773
  async handleBrowseEvents(event) {
12588
12774
  try {
12589
- const eventQuery = new EventQuery3(this.kb.eventStore.log.storage);
12775
+ const eventQuery = new EventQuery2(this.kb.eventStore.log.storage);
12590
12776
  const filters = {
12591
12777
  resourceId: resourceId4(event.resourceId)
12592
12778
  };
@@ -12609,7 +12795,7 @@ var Browser = class {
12609
12795
  }
12610
12796
  });
12611
12797
  } catch (error) {
12612
- this.logger.error("Browse events failed", { resourceId: event.resourceId, error });
12798
+ this.logger.error("Browse events failed", { resourceId: event.resourceId, error: errField5(error) });
12613
12799
  this.eventBus.get("browse:events-failed").next({
12614
12800
  correlationId: event.correlationId,
12615
12801
  message: error instanceof Error ? error.message : String(error)
@@ -12626,7 +12812,7 @@ var Browser = class {
12626
12812
  });
12627
12813
  return;
12628
12814
  }
12629
- const eventQuery = new EventQuery3(this.kb.eventStore.log.storage);
12815
+ const eventQuery = new EventQuery2(this.kb.eventStore.log.storage);
12630
12816
  const allEvents = await eventQuery.queryEvents({ resourceId: resourceId4(event.resourceId) });
12631
12817
  const annotationEvents = allEvents.filter((stored) => {
12632
12818
  const p = stored.payload;
@@ -12645,7 +12831,7 @@ var Browser = class {
12645
12831
  }
12646
12832
  });
12647
12833
  } catch (error) {
12648
- this.logger.error("Browse annotation history failed", { resourceId: event.resourceId, annotationId: event.annotationId, error });
12834
+ this.logger.error("Browse annotation history failed", { resourceId: event.resourceId, annotationId: event.annotationId, error: errField5(error) });
12649
12835
  this.eventBus.get("browse:annotation-history-failed").next({
12650
12836
  correlationId: event.correlationId,
12651
12837
  message: error instanceof Error ? error.message : String(error)
@@ -12687,7 +12873,7 @@ var Browser = class {
12687
12873
  response: { referencedBy }
12688
12874
  });
12689
12875
  } catch (error) {
12690
- this.logger.error("Referenced-by query failed", { resourceId: event.resourceId, error });
12876
+ this.logger.error("Referenced-by query failed", { resourceId: event.resourceId, error: errField5(error) });
12691
12877
  this.eventBus.get("browse:referenced-by-failed").next({
12692
12878
  correlationId: event.correlationId,
12693
12879
  message: error instanceof Error ? error.message : String(error)
@@ -12702,7 +12888,7 @@ var Browser = class {
12702
12888
  response: { entityTypes }
12703
12889
  });
12704
12890
  } catch (error) {
12705
- this.logger.error("Entity types read failed", { error });
12891
+ this.logger.error("Entity types read failed", { error: errField5(error) });
12706
12892
  this.eventBus.get("browse:entity-types-failed").next({
12707
12893
  correlationId: event.correlationId,
12708
12894
  message: error instanceof Error ? error.message : String(error)
@@ -12715,8 +12901,8 @@ var Browser = class {
12715
12901
  async handleBrowseDirectory(event) {
12716
12902
  const { correlationId, path: reqPath, sort = "name" } = event;
12717
12903
  const projectRoot = this.project.root;
12718
- const resolved = path2.resolve(projectRoot, reqPath);
12719
- if (!resolved.startsWith(projectRoot + path2.sep) && resolved !== projectRoot) {
12904
+ const resolved = path3.resolve(projectRoot, reqPath);
12905
+ if (!resolved.startsWith(projectRoot + path3.sep) && resolved !== projectRoot) {
12720
12906
  this.eventBus.get("browse:directory-failed").next({
12721
12907
  correlationId,
12722
12908
  path: reqPath,
@@ -12726,7 +12912,7 @@ var Browser = class {
12726
12912
  }
12727
12913
  let dirents;
12728
12914
  try {
12729
- dirents = await fs3.readdir(resolved, { withFileTypes: true, encoding: "utf8" });
12915
+ dirents = await fs4.readdir(resolved, { withFileTypes: true, encoding: "utf8" });
12730
12916
  } catch (err) {
12731
12917
  const msg = err.code === "ENOENT" ? "path not found" : String(err);
12732
12918
  this.eventBus.get("browse:directory-failed").next({
@@ -12740,16 +12926,16 @@ var Browser = class {
12740
12926
  const allViews = await this.views.getAll();
12741
12927
  const prefix = `file://${resolved}`;
12742
12928
  const viewsByUri = new Map(
12743
- allViews.filter((v) => v.resource.storageUri?.startsWith(prefix + "/") || v.resource.storageUri?.startsWith(prefix + path2.sep)).map((v) => [v.resource.storageUri, v])
12929
+ allViews.filter((v) => v.resource.storageUri?.startsWith(prefix + "/") || v.resource.storageUri?.startsWith(prefix + path3.sep)).map((v) => [v.resource.storageUri, v])
12744
12930
  );
12745
12931
  const entries = [];
12746
12932
  for (const dirent of visible) {
12747
- const entryPath = path2.join(resolved, dirent.name);
12748
- const relPath = path2.relative(projectRoot, entryPath);
12933
+ const entryPath = path3.join(resolved, dirent.name);
12934
+ const relPath = path3.relative(projectRoot, entryPath);
12749
12935
  if (dirent.isDirectory()) {
12750
12936
  let mtime = (/* @__PURE__ */ new Date(0)).toISOString();
12751
12937
  try {
12752
- const stat = await fs3.stat(entryPath);
12938
+ const stat = await fs4.stat(entryPath);
12753
12939
  mtime = stat.mtime.toISOString();
12754
12940
  } catch {
12755
12941
  }
@@ -12759,7 +12945,7 @@ var Browser = class {
12759
12945
  let size = 0;
12760
12946
  let mtime = (/* @__PURE__ */ new Date(0)).toISOString();
12761
12947
  try {
12762
- const stat = await fs3.stat(entryPath);
12948
+ const stat = await fs4.stat(entryPath);
12763
12949
  size = stat.size;
12764
12950
  mtime = stat.mtime.toISOString();
12765
12951
  } catch {
@@ -13430,9 +13616,7 @@ async function exportBackup(options, output) {
13430
13616
  for (const [streamId, events] of streamData) {
13431
13617
  streamSummaries.push({
13432
13618
  stream: streamId,
13433
- eventCount: events.length,
13434
- firstChecksum: events[0].metadata.checksum || "",
13435
- lastChecksum: events[events.length - 1].metadata.checksum || ""
13619
+ eventCount: events.length
13436
13620
  });
13437
13621
  }
13438
13622
  const manifestHeader = {
@@ -13501,26 +13685,11 @@ async function replayEventStream(jsonl, eventBus, resolveBlob, contentStore, log
13501
13685
  annotationsCreated: 0,
13502
13686
  entityTypesAdded: 0
13503
13687
  };
13504
- let hashChainValid = true;
13505
- for (let i = 1; i < storedEvents.length; i++) {
13506
- const prev = storedEvents[i - 1];
13507
- const curr = storedEvents[i];
13508
- if (curr.metadata.prevEventHash && prev.metadata.checksum) {
13509
- if (curr.metadata.prevEventHash !== prev.metadata.checksum) {
13510
- logger?.warn("Hash chain break", {
13511
- index: i,
13512
- expected: prev.metadata.checksum,
13513
- got: curr.metadata.prevEventHash
13514
- });
13515
- hashChainValid = false;
13516
- }
13517
- }
13518
- }
13519
13688
  for (const stored of storedEvents) {
13520
13689
  await replayEvent(stored, eventBus, resolveBlob, contentStore, stats, logger);
13521
13690
  stats.eventsReplayed++;
13522
13691
  }
13523
- return { stats, hashChainValid };
13692
+ return { stats };
13524
13693
  }
13525
13694
  async function replayEvent(event, eventBus, resolveBlob, contentStore, stats, logger) {
13526
13695
  switch (event.type) {
@@ -13749,7 +13918,6 @@ async function importBackup(archive, options) {
13749
13918
  const resolveBlob = buildBlobResolver(entries);
13750
13919
  const systemData = entries.get(".semiont/events/__system__.jsonl");
13751
13920
  let stats = { eventsReplayed: 0, resourcesCreated: 0, annotationsCreated: 0, entityTypesAdded: 0 };
13752
- let hashChainValid = true;
13753
13921
  if (systemData) {
13754
13922
  const result = await replayEventStream(
13755
13923
  systemData.toString("utf8"),
@@ -13759,7 +13927,6 @@ async function importBackup(archive, options) {
13759
13927
  logger
13760
13928
  );
13761
13929
  stats = mergeStats(stats, result.stats);
13762
- if (!result.hashChainValid) hashChainValid = false;
13763
13930
  }
13764
13931
  for (const summary of streamSummaries) {
13765
13932
  if (summary.stream === "__system__") continue;
@@ -13776,10 +13943,9 @@ async function importBackup(archive, options) {
13776
13943
  logger
13777
13944
  );
13778
13945
  stats = mergeStats(stats, result.stats);
13779
- if (!result.hashChainValid) hashChainValid = false;
13780
13946
  }
13781
- logger?.info("Backup import complete", { ...stats, hashChainValid });
13782
- return { manifest: header, stats, hashChainValid };
13947
+ logger?.info("Backup import complete", { ...stats });
13948
+ return { manifest: header, stats };
13783
13949
  }
13784
13950
  function mergeStats(a, b) {
13785
13951
  return {