@equationalapplications/core-llm-wiki 7.7.4 → 7.7.6

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.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { M as MemoryBundle, F as FormatContextOptions, G as GraphNeighborhood, a as MemoryDump, b as FormattedMemoryDump, R as ReadOptions, S as SQLiteAdapter, W as WikiOptions, c as WikiMemory } from './testing-CH_Kk34-.mjs';
2
- export { C as ChunkFailure, d as ClassifierAnswer, e as ClassifierQuestion, f as ClassifyRequest, g as ClassifyResponse, D as DegradedRecord, h as DraftPage, E as EmbedFactResult, i as EmbedFailureKind, j as EmbeddingMarkerKind, k as EntityStatus, l as ExtractedFact, m as ExtractedFactEdge, n as ExtractedFactWithOntology, o as ExtractedTask, p as GraphTraversalOptions, q as GroundingConfig, H as HEAL_BATCH_SIZE, r as HEAL_RECHECK_MS, s as HOOK_TIMEOUT_MARKER, t as HealResult, I as IngestDocumentResult, L as LLMProvider, O as ONTOLOGY_BACKFILL_BATCH_SIZE, u as ONTOLOGY_BACKFILL_MAX_PROMPT_CHARS, v as ONTOLOGY_BACKFILL_RECHECK_MS, w as OntologyBackfillResult, x as OntologyConfig, y as OntologyEdgeType, z as OntologyManifest, A as OntologyMode, B as OntologyNodeType, J as OntologyPromptContext, K as OntologyUpdates, P as PendingSourceStatus, N as PromptOverrides, Q as PromptService, T as PrunePartialFailureError, U as ReembedResult, V as VectorRanker, X as VectorRankerFallback, Y as VectorRankerRankArgs, Z as VectorRankerSemanticResult, _ as WikiBusyError, $ as WikiBusyOperation, a0 as WikiCheckpoint, a1 as WikiConfig, a2 as WikiDiagnostic, a3 as WikiDiagnosticCode, a4 as WikiDiagnosticDetail, a5 as WikiDiagnosticOperation, a6 as WikiDiagnosticSeverity, a7 as WikiDiagnosticTrigger, a8 as WikiDraftNotFound, a9 as WikiDuplicateHashError, aa as WikiEdge, ab as WikiEvent, ac as WikiFact, ad as WikiGraphNodeOwnershipConflict, ae as WikiIngestEmptyError, af as WikiInstructions, ag as WikiInvalidReadOptions, ah as WikiLintReport, ai as WikiMemoryTestAccess, aj as WikiOutboxEvent, ak as WikiParseError, al as WikiSourceRefHashCollision, am as WikiStrictOntologyViolation, an as WikiTask, ao as WikiTransactionError, ap as validateManifest } from './testing-CH_Kk34-.mjs';
1
+ import { M as MemoryBundle, F as FormatContextOptions, G as GraphNeighborhood, a as MemoryDump, b as FormattedMemoryDump, R as ReadOptions, S as SQLiteAdapter, W as WikiOptions, c as WikiMemory } from './testing-BIFNLUva.mjs';
2
+ export { C as ChunkFailure, d as ClassifierAnswer, e as ClassifierQuestion, f as ClassifyRequest, g as ClassifyResponse, D as DegradedRecord, h as DraftPage, E as EmbedFactResult, i as EmbedFailureKind, j as EmbeddingMarkerKind, k as EntityStatus, l as ExtractedFact, m as ExtractedFactEdge, n as ExtractedFactWithOntology, o as ExtractedTask, p as GraphTraversalOptions, q as GroundingConfig, H as HEAL_BATCH_SIZE, r as HEAL_RECHECK_MS, s as HOOK_TIMEOUT_MARKER, t as HealResult, I as IngestDocumentResult, L as LLMProvider, O as ONTOLOGY_BACKFILL_BATCH_SIZE, u as ONTOLOGY_BACKFILL_MAX_PROMPT_CHARS, v as ONTOLOGY_BACKFILL_RECHECK_MS, w as OntologyBackfillResult, x as OntologyConfig, y as OntologyEdgeType, z as OntologyManifest, A as OntologyMode, B as OntologyNodeType, J as OntologyPromptContext, K as OntologyUpdates, P as PendingSourceStatus, N as PromptOverrides, Q as PromptService, T as PrunePartialFailureError, U as ReembedResult, V as VectorRanker, X as VectorRankerFallback, Y as VectorRankerRankArgs, Z as VectorRankerSemanticResult, _ as WikiBusyError, $ as WikiBusyOperation, a0 as WikiCheckpoint, a1 as WikiConfig, a2 as WikiDiagnostic, a3 as WikiDiagnosticCode, a4 as WikiDiagnosticDetail, a5 as WikiDiagnosticOperation, a6 as WikiDiagnosticSeverity, a7 as WikiDiagnosticTrigger, a8 as WikiDraftNotFound, a9 as WikiDuplicateHashError, aa as WikiEdge, ab as WikiEvent, ac as WikiFact, ad as WikiGraphNodeOwnershipConflict, ae as WikiIngestEmptyError, af as WikiInstructions, ag as WikiInvalidReadOptions, ah as WikiLintReport, ai as WikiMemoryTestAccess, aj as WikiOutboxEvent, ak as WikiParseError, al as WikiSourceRefHashCollision, am as WikiStrictOntologyViolation, an as WikiTask, ao as WikiTransactionError, ap as validateManifest } from './testing-BIFNLUva.mjs';
3
3
  import { OkfFile } from '@equationalapplications/core-okf';
4
4
  import 'minisearch';
5
5
 
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { M as MemoryBundle, F as FormatContextOptions, G as GraphNeighborhood, a as MemoryDump, b as FormattedMemoryDump, R as ReadOptions, S as SQLiteAdapter, W as WikiOptions, c as WikiMemory } from './testing-CH_Kk34-.js';
2
- export { C as ChunkFailure, d as ClassifierAnswer, e as ClassifierQuestion, f as ClassifyRequest, g as ClassifyResponse, D as DegradedRecord, h as DraftPage, E as EmbedFactResult, i as EmbedFailureKind, j as EmbeddingMarkerKind, k as EntityStatus, l as ExtractedFact, m as ExtractedFactEdge, n as ExtractedFactWithOntology, o as ExtractedTask, p as GraphTraversalOptions, q as GroundingConfig, H as HEAL_BATCH_SIZE, r as HEAL_RECHECK_MS, s as HOOK_TIMEOUT_MARKER, t as HealResult, I as IngestDocumentResult, L as LLMProvider, O as ONTOLOGY_BACKFILL_BATCH_SIZE, u as ONTOLOGY_BACKFILL_MAX_PROMPT_CHARS, v as ONTOLOGY_BACKFILL_RECHECK_MS, w as OntologyBackfillResult, x as OntologyConfig, y as OntologyEdgeType, z as OntologyManifest, A as OntologyMode, B as OntologyNodeType, J as OntologyPromptContext, K as OntologyUpdates, P as PendingSourceStatus, N as PromptOverrides, Q as PromptService, T as PrunePartialFailureError, U as ReembedResult, V as VectorRanker, X as VectorRankerFallback, Y as VectorRankerRankArgs, Z as VectorRankerSemanticResult, _ as WikiBusyError, $ as WikiBusyOperation, a0 as WikiCheckpoint, a1 as WikiConfig, a2 as WikiDiagnostic, a3 as WikiDiagnosticCode, a4 as WikiDiagnosticDetail, a5 as WikiDiagnosticOperation, a6 as WikiDiagnosticSeverity, a7 as WikiDiagnosticTrigger, a8 as WikiDraftNotFound, a9 as WikiDuplicateHashError, aa as WikiEdge, ab as WikiEvent, ac as WikiFact, ad as WikiGraphNodeOwnershipConflict, ae as WikiIngestEmptyError, af as WikiInstructions, ag as WikiInvalidReadOptions, ah as WikiLintReport, ai as WikiMemoryTestAccess, aj as WikiOutboxEvent, ak as WikiParseError, al as WikiSourceRefHashCollision, am as WikiStrictOntologyViolation, an as WikiTask, ao as WikiTransactionError, ap as validateManifest } from './testing-CH_Kk34-.js';
1
+ import { M as MemoryBundle, F as FormatContextOptions, G as GraphNeighborhood, a as MemoryDump, b as FormattedMemoryDump, R as ReadOptions, S as SQLiteAdapter, W as WikiOptions, c as WikiMemory } from './testing-BIFNLUva.js';
2
+ export { C as ChunkFailure, d as ClassifierAnswer, e as ClassifierQuestion, f as ClassifyRequest, g as ClassifyResponse, D as DegradedRecord, h as DraftPage, E as EmbedFactResult, i as EmbedFailureKind, j as EmbeddingMarkerKind, k as EntityStatus, l as ExtractedFact, m as ExtractedFactEdge, n as ExtractedFactWithOntology, o as ExtractedTask, p as GraphTraversalOptions, q as GroundingConfig, H as HEAL_BATCH_SIZE, r as HEAL_RECHECK_MS, s as HOOK_TIMEOUT_MARKER, t as HealResult, I as IngestDocumentResult, L as LLMProvider, O as ONTOLOGY_BACKFILL_BATCH_SIZE, u as ONTOLOGY_BACKFILL_MAX_PROMPT_CHARS, v as ONTOLOGY_BACKFILL_RECHECK_MS, w as OntologyBackfillResult, x as OntologyConfig, y as OntologyEdgeType, z as OntologyManifest, A as OntologyMode, B as OntologyNodeType, J as OntologyPromptContext, K as OntologyUpdates, P as PendingSourceStatus, N as PromptOverrides, Q as PromptService, T as PrunePartialFailureError, U as ReembedResult, V as VectorRanker, X as VectorRankerFallback, Y as VectorRankerRankArgs, Z as VectorRankerSemanticResult, _ as WikiBusyError, $ as WikiBusyOperation, a0 as WikiCheckpoint, a1 as WikiConfig, a2 as WikiDiagnostic, a3 as WikiDiagnosticCode, a4 as WikiDiagnosticDetail, a5 as WikiDiagnosticOperation, a6 as WikiDiagnosticSeverity, a7 as WikiDiagnosticTrigger, a8 as WikiDraftNotFound, a9 as WikiDuplicateHashError, aa as WikiEdge, ab as WikiEvent, ac as WikiFact, ad as WikiGraphNodeOwnershipConflict, ae as WikiIngestEmptyError, af as WikiInstructions, ag as WikiInvalidReadOptions, ah as WikiLintReport, ai as WikiMemoryTestAccess, aj as WikiOutboxEvent, ak as WikiParseError, al as WikiSourceRefHashCollision, am as WikiStrictOntologyViolation, an as WikiTask, ao as WikiTransactionError, ap as validateManifest } from './testing-BIFNLUva.js';
3
3
  import { OkfFile } from '@equationalapplications/core-okf';
4
4
  import 'minisearch';
5
5
 
package/dist/index.js CHANGED
@@ -744,7 +744,7 @@ function mapRowToFactWithBlobs(row) {
744
744
  const embeddingBlob = normalizeEmbeddingBlobValue(row.embedding_blob);
745
745
  return embeddingBlob ? { ...base, embedding_blob: embeddingBlob } : base;
746
746
  }
747
- var EntryRepository = class extends BaseRepository {
747
+ var _EntryRepository = class _EntryRepository extends BaseRepository {
748
748
  constructor(db, prefix, outbox) {
749
749
  super(db, prefix);
750
750
  this.outbox = outbox;
@@ -1429,14 +1429,34 @@ var EntryRepository = class extends BaseRepository {
1429
1429
  const executor = this.getExecutor(tx);
1430
1430
  if (entityId !== void 0) {
1431
1431
  return executor.getAllAsync(
1432
- `SELECT id, entity_id, title, body, tags FROM ${this.prefix}entries WHERE deleted_at IS NULL AND entity_id = ?`,
1432
+ `SELECT ${_EntryRepository.MINI_SEARCH_COLUMNS} FROM ${this.prefix}entries ${_EntryRepository.MINI_SEARCH_LIVE_WHERE} AND entity_id = ?`,
1433
1433
  [entityId]
1434
1434
  );
1435
1435
  }
1436
1436
  return executor.getAllAsync(
1437
- `SELECT id, entity_id, title, body, tags FROM ${this.prefix}entries WHERE deleted_at IS NULL`
1437
+ `SELECT ${_EntryRepository.MINI_SEARCH_COLUMNS} FROM ${this.prefix}entries ${_EntryRepository.MINI_SEARCH_LIVE_WHERE}`
1438
1438
  );
1439
1439
  }
1440
+ /**
1441
+ * Keyword-index rows for specific ids — the incremental counterpart of
1442
+ * {@link findMiniSearchRows}, with identical columns. Soft-deleted rows and
1443
+ * rows of other entities are omitted, so a caller can pass every id a write
1444
+ * touched and get back exactly what should be indexed. Spec 2026-09-28 §4.4.
1445
+ */
1446
+ async findMiniSearchRowsByIds(entityId, ids, tx) {
1447
+ if (ids.length === 0) return [];
1448
+ const executor = this.getExecutor(tx);
1449
+ const rows = [];
1450
+ for (let i = 0; i < ids.length; i += this.chunkSize) {
1451
+ const chunk = ids.slice(i, i + this.chunkSize);
1452
+ const placeholders = chunk.map(() => "?").join(",");
1453
+ rows.push(...await executor.getAllAsync(
1454
+ `SELECT ${_EntryRepository.MINI_SEARCH_COLUMNS} FROM ${this.prefix}entries ${_EntryRepository.MINI_SEARCH_LIVE_WHERE} AND entity_id = ? AND id IN (${placeholders})`,
1455
+ [entityId, ...chunk]
1456
+ ));
1457
+ }
1458
+ return rows;
1459
+ }
1440
1460
  async updateEmbeddingBlob(id, blob, tx) {
1441
1461
  const executor = this.getExecutor(tx);
1442
1462
  await executor.runAsync(
@@ -1977,6 +1997,15 @@ var EntryRepository = class extends BaseRepository {
1977
1997
  return rows.map((r) => ({ id: r.id, title: r.title }));
1978
1998
  }
1979
1999
  };
2000
+ /**
2001
+ * Column list and liveness predicate shared by findMiniSearchRows and
2002
+ * findMiniSearchRowsByIds, so the full rebuild and the incremental read
2003
+ * can never drift apart (spec 2026-09-28 §4.4: both must produce
2004
+ * identical documents).
2005
+ */
2006
+ _EntryRepository.MINI_SEARCH_COLUMNS = "id, entity_id, title, body, tags";
2007
+ _EntryRepository.MINI_SEARCH_LIVE_WHERE = "WHERE deleted_at IS NULL";
2008
+ var EntryRepository = _EntryRepository;
1980
2009
 
1981
2010
  // src/utils/ids.ts
1982
2011
  var _injectedGetRandomValues = null;
@@ -3113,7 +3142,31 @@ var _SearchService = class _SearchService {
3113
3142
  * auto-vacuum debt behind the TypeError in #64.
3114
3143
  */
3115
3144
  this.syncChain = Promise.resolve();
3116
- this.miniSearch = new MiniSearch__default.default({
3145
+ /**
3146
+ * Entities whose index may have drifted from SQLite: an incremental update
3147
+ * failed part-way, or core wrote rows it could not index (upsertGraph runs in
3148
+ * the host's transaction). Their next syncEntries rebuilds the entity in full.
3149
+ * See spec 2026-09-28 §5.
3150
+ */
3151
+ this.staleEntities = /* @__PURE__ */ new Set();
3152
+ /**
3153
+ * Per-entity count of markStale() calls. A rebuild clears an entity's stale
3154
+ * flag only when the count it snapshotted before its read still holds
3155
+ * afterwards: markStale() runs inside the host's still-open transaction, so
3156
+ * a call landing mid-read belongs to rows the read cannot have seen, and
3157
+ * its flag must outlive the turn (#233 review).
3158
+ */
3159
+ this.staleEpochs = /* @__PURE__ */ new Map();
3160
+ this.miniSearch = this.createMiniSearch();
3161
+ }
3162
+ /**
3163
+ * A fresh index with the production options. clearAll() swaps one in because
3164
+ * MiniSearch.removeAll() empties the index but leaves dirtCount (and its
3165
+ * vacuum bookkeeping) at its old value, which would trip syncEntries'
3166
+ * conditional vacuum early after a clear.
3167
+ */
3168
+ createMiniSearch() {
3169
+ return new MiniSearch__default.default({
3117
3170
  fields: ["title", "body", "tags"],
3118
3171
  storeFields: ["entity_id"],
3119
3172
  // Vacuuming is driven explicitly at the end of each serialized rebuild
@@ -3140,7 +3193,19 @@ var _SearchService = class _SearchService {
3140
3193
  const work = this.syncChain.then(async () => {
3141
3194
  try {
3142
3195
  try {
3196
+ const epochsBefore = new Map(this.staleEpochs);
3143
3197
  await this.rebuildIndex(entityId);
3198
+ if (entityId) {
3199
+ if ((this.staleEpochs.get(entityId) ?? 0) === (epochsBefore.get(entityId) ?? 0)) {
3200
+ this.staleEntities.delete(entityId);
3201
+ }
3202
+ } else {
3203
+ for (const id of [...this.staleEntities]) {
3204
+ if ((this.staleEpochs.get(id) ?? 0) === (epochsBefore.get(id) ?? 0)) {
3205
+ this.staleEntities.delete(id);
3206
+ }
3207
+ }
3208
+ }
3144
3209
  await this.miniSearch.vacuum();
3145
3210
  } finally {
3146
3211
  this.evictCache(entityId);
@@ -3152,6 +3217,68 @@ var _SearchService = class _SearchService {
3152
3217
  this.syncChain = work;
3153
3218
  return work;
3154
3219
  }
3220
+ /**
3221
+ * Re-indexes only `ids` for `entityId`: drops each from the index, then
3222
+ * re-adds the ones still live in SQLite, so soft-deleted or missing ids end
3223
+ * up absent. Costs O(ids), where sync(entityId) costs O(entity) — callers that
3224
+ * know what a write touched use this so chunked imports stay linear (#232).
3225
+ *
3226
+ * Serialized with sync() on the same chain and, like it, never rejects. An
3227
+ * entity that is stale or has never been indexed gets a full rebuild instead
3228
+ * — including on an empty `ids` list, which is a no-op only for an entity
3229
+ * the index already tracks, and even then one that waits for rebuilds
3230
+ * already queued on the chain.
3231
+ */
3232
+ async syncEntries(entityId, ids) {
3233
+ const uniqueIds = [...new Set(ids)];
3234
+ if (uniqueIds.length === 0 && !this.staleEntities.has(entityId) && this.miniSearchEntryIdsByEntity.has(entityId)) {
3235
+ return this.syncChain;
3236
+ }
3237
+ const work = this.syncChain.then(async () => {
3238
+ try {
3239
+ try {
3240
+ const epochsBefore = new Map(this.staleEpochs);
3241
+ const needsRebuild = () => this.staleEntities.has(entityId) || !this.miniSearchEntryIdsByEntity.has(entityId);
3242
+ if (!needsRebuild()) {
3243
+ const rows = await this.entryRepo.findMiniSearchRowsByIds(entityId, uniqueIds);
3244
+ const tracked = this.miniSearchEntryIdsByEntity.get(entityId);
3245
+ if (tracked && !this.staleEntities.has(entityId)) {
3246
+ for (const id of uniqueIds) {
3247
+ if (tracked.delete(id) && this.miniSearch.has(id)) this.miniSearch.discard(id);
3248
+ }
3249
+ const documents = rows.map((row) => this.normalizeMiniSearchRow(row));
3250
+ if (documents.length > 0) this.miniSearch.addAll(documents);
3251
+ for (const document of documents) tracked.add(document.id);
3252
+ if (this.miniSearch.dirtCount > 0) {
3253
+ await this.miniSearch.vacuum();
3254
+ }
3255
+ return;
3256
+ }
3257
+ }
3258
+ await this.rebuildIndex(entityId);
3259
+ if ((this.staleEpochs.get(entityId) ?? 0) === (epochsBefore.get(entityId) ?? 0)) {
3260
+ this.staleEntities.delete(entityId);
3261
+ }
3262
+ await this.miniSearch.vacuum();
3263
+ } finally {
3264
+ this.evictCache(entityId);
3265
+ }
3266
+ } catch (err) {
3267
+ this.staleEntities.add(entityId);
3268
+ console.warn(`[WikiMemory] search index incremental sync failed for ${entityId}:`, err);
3269
+ }
3270
+ });
3271
+ this.syncChain = work;
3272
+ return work;
3273
+ }
3274
+ /**
3275
+ * Forces the entity's next syncEntries to rebuild it in full. For writes core
3276
+ * cannot index itself, such as upsertGraph inside a host transaction.
3277
+ */
3278
+ markStale(entityId) {
3279
+ this.staleEntities.add(entityId);
3280
+ this.staleEpochs.set(entityId, (this.staleEpochs.get(entityId) ?? 0) + 1);
3281
+ }
3155
3282
  /**
3156
3283
  * Clears the parsed vector cache. Useful for mid-loop flush guarantees
3157
3284
  * or memory pressure evictions.
@@ -3168,8 +3295,10 @@ var _SearchService = class _SearchService {
3168
3295
  */
3169
3296
  clearAll() {
3170
3297
  this.vectorCache.clear();
3171
- this.miniSearch.removeAll();
3298
+ this.miniSearch = this.createMiniSearch();
3172
3299
  this.miniSearchEntryIdsByEntity.clear();
3300
+ this.staleEntities.clear();
3301
+ this.staleEpochs.clear();
3173
3302
  }
3174
3303
  /**
3175
3304
  * Executes a keyword search against the active MiniSearch index.
@@ -3180,7 +3309,7 @@ var _SearchService = class _SearchService {
3180
3309
  filter: (r) => entityIdSet.has(r.entity_id),
3181
3310
  combineWith: "OR"
3182
3311
  });
3183
- return results.slice(0, limit);
3312
+ return results.sort((a, b) => this._compareSearchResults(a, b)).slice(0, limit);
3184
3313
  }
3185
3314
  /**
3186
3315
  * Pre-fetches MiniSearch scores for candidate hydration, used during hybrid weighting.
@@ -3190,7 +3319,7 @@ var _SearchService = class _SearchService {
3190
3319
  let results = this.miniSearch.search(query, {
3191
3320
  filter: (r) => entityIdSet.has(r.entity_id),
3192
3321
  combineWith: "OR"
3193
- });
3322
+ }).sort((a, b) => this._compareSearchResults(a, b));
3194
3323
  if (preFilterLimit !== void 0) {
3195
3324
  results = results.slice(0, preFilterLimit);
3196
3325
  }
@@ -3318,6 +3447,18 @@ var _SearchService = class _SearchService {
3318
3447
  if (updatedAtDiff !== 0) return updatedAtDiff;
3319
3448
  return a.id.localeCompare(b.id);
3320
3449
  }
3450
+ /**
3451
+ * MiniSearch breaks equal-score ties by internal insertion order, which
3452
+ * syncEntries changes: a discarded-and-re-added id moves to the end. Every
3453
+ * caller truncates these results to a limit, so which ids survive a tie at
3454
+ * the boundary must not depend on write history. Re-sort exact score ties
3455
+ * by id — the same final tie-break _compareScoredRows applies.
3456
+ */
3457
+ _compareSearchResults(a, b) {
3458
+ const scoreDiff = b.score - a.score;
3459
+ if (!Number.isNaN(scoreDiff) && scoreDiff !== 0) return scoreDiff;
3460
+ return a.id.localeCompare(b.id);
3461
+ }
3321
3462
  };
3322
3463
  /**
3323
3464
  * Maximum number of entities whose parsed embedding vectors are held in
@@ -4971,7 +5112,10 @@ var IngestionService = class {
4971
5112
  return zeroChunkResult(canonical);
4972
5113
  }
4973
5114
  diagBuffer.flush(this.options);
4974
- await this.searchService.sync(entityId);
5115
+ await this.searchService.syncEntries(
5116
+ entityId,
5117
+ [...deletedSourceFactIds, ...insertedFacts.map((fact) => fact.id)]
5118
+ );
4975
5119
  if (failedChunks === 0) {
4976
5120
  const uniqueDeletedSourceFactIds = Array.from(new Set(deletedSourceFactIds));
4977
5121
  for (const factId of uniqueDeletedSourceFactIds) {
@@ -6974,7 +7118,11 @@ var ImportExportService = class {
6974
7118
  );
6975
7119
  }
6976
7120
  });
6977
- await this.searchService.sync(entityId);
7121
+ if (merge) {
7122
+ await this.searchService.syncEntries(entityId, [...upsertedFactIds]);
7123
+ } else {
7124
+ await this.searchService.sync(entityId);
7125
+ }
6978
7126
  for (const fact of bundle.facts) {
6979
7127
  if (!fact.deleted_at && upsertedFactIds.has(fact.id) && !factsWithPreservedBlob.has(fact.id)) {
6980
7128
  const clipped = clippedTextByFactId.get(fact.id);
@@ -9112,6 +9260,7 @@ var WikiMemory = class {
9112
9260
  adapter,
9113
9261
  { diag: { buffer: diagBuffer, operation: "upsertGraph" } }
9114
9262
  );
9263
+ this.searchService.markStale(entityId);
9115
9264
  diagBuffer.flush(this.options);
9116
9265
  return result;
9117
9266
  }