@equationalapplications/core-llm-wiki 7.15.0 → 7.15.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3887,7 +3887,7 @@ var MIGRATIONS = [
3887
3887
  if (duplicates.length > 0) {
3888
3888
  const sample = duplicates.slice(0, 5).map((d) => `(entity_id=${d.entity_id}, source_hash=${d.source_hash.slice(0, 12)}\u2026, n_refs=${d.n_refs})`).join(", ");
3889
3889
  throw new Error(
3890
- `Migration v9 (add_source_ref_index) failed: existing live rows have multiple sourceRefs sharing a hash. Found ${duplicates.length} duplicate (entity_id, source_hash) groups. First ${Math.min(5, duplicates.length)}: ${sample}. Resolve each by calling forget({ sourceRef: <loser> }) for the offending sourceRef, then re-run setup.`
3890
+ `Migration v9 (add_source_ref_index) failed: existing live rows have multiple sourceRefs sharing a hash. Found ${duplicates.length} duplicate (entity_id, source_hash) groups. First ${Math.min(5, duplicates.length)}: ${sample}. Resolve each group by calling forget(entityId, { sourceRef: <loser>, sourceHash: <group's full source_hash> }) for every losing sourceRef in that group (works on pre-v9 databases; list full hashes with the query in the docs' errors reference), then re-run setup().`
3891
3891
  );
3892
3892
  }
3893
3893
  await db.execAsync(
@@ -5262,6 +5262,7 @@ var MaintenanceService = class {
5262
5262
  if (params.sourceRef !== void 0 && !sourceRef) throw new Error("Invalid sourceRef");
5263
5263
  const sourceHash = params.sourceHash !== void 0 ? normalizeSourceHash(params.sourceHash) : null;
5264
5264
  if (params.sourceHash !== void 0 && !sourceHash) throw new Error("Invalid sourceHash (must be 64-char hex string)");
5265
+ const touchSourceRefIndex = sourceRef !== null && await this.sourceRefIndexPresent(tx);
5265
5266
  if (params.entryId) {
5266
5267
  const entryId = await this.entryRepo.findIdById(params.entryId, entityId, tx);
5267
5268
  if (entryId) deletedEntryIds.push(entryId);
@@ -5272,7 +5273,7 @@ var MaintenanceService = class {
5272
5273
  const entryPromise = params.entryId ? this.entryRepo.softDelete(params.entryId, entityId, tx).then((r) => r.changes > 0) : null;
5273
5274
  const taskDeletedPromise = params.taskId ? this.taskRepo.softDeleteById(params.taskId, entityId, tx).then((r) => r.changes > 0) : null;
5274
5275
  const refPromise = sourceRef || sourceHash ? this.entryRepo.softDeleteBySource(entityId, tx, sourceRef, sourceHash) : null;
5275
- const sourceRefIndexPromise = sourceRef ? this.sourceRefIndexRepo.softDeleteByEntityAndSourceRef(entityId, sourceRef, tx).then(() => void 0) : null;
5276
+ const sourceRefIndexPromise = touchSourceRefIndex && sourceRef ? this.sourceRefIndexRepo.softDeleteByEntityAndSourceRef(entityId, sourceRef, tx).then(() => void 0) : null;
5276
5277
  const [entryResult, taskResult, refResult] = await Promise.all([
5277
5278
  entryPromise ?? Promise.resolve(false),
5278
5279
  taskDeletedPromise ?? Promise.resolve(false),
@@ -5306,6 +5307,33 @@ var MaintenanceService = class {
5306
5307
  this.jobManager.releaseLock("forget", entityId);
5307
5308
  }
5308
5309
  }
5310
+ /**
5311
+ * Whether forget() should soft-delete in source_ref_index (#316,
5312
+ * specs/forget-pre-v9 §3.1). Normally true: setup()'s DDL creates the table.
5313
+ * False only when the table is absent AND the store is pre-v9 (stored
5314
+ * schema_version < 9; a missing key or unparseable value counts as 0, like
5315
+ * detectSchemaVersion; a store without the meta table at all is not
5316
+ * supported and fails as before) — the v9 recovery path, where there is no index row
5317
+ * to retire and v9's backfill reads live entries only. A v9+ store without
5318
+ * its index is corrupt: throw rather than skip, so the TOCTOU guard is never
5319
+ * silently bypassed.
5320
+ *
5321
+ * Every read runs on `tx`, so a v9 committed by *another connection* between
5322
+ * this probe and forget()'s writes can only fail the write-lock upgrade
5323
+ * (SQLite serializes writers), never make forget() skip a live index. A
5324
+ * setup() racing forget() on the *same* connection (expo passes the shared
5325
+ * db as tx) is not serialized against it; v9 runs in autocommit, a
5326
+ * pre-existing limit out of scope here. Await setup() before other calls,
5327
+ * as WikiMemory.setup() documents.
5328
+ */
5329
+ async sourceRefIndexPresent(tx) {
5330
+ if (await this.metadataRepo.tableExists(`${this.prefix}source_ref_index`, tx)) return true;
5331
+ const raw = await this.metadataRepo.getMeta("schema_version", tx);
5332
+ const parsed = raw ? parseInt(raw, 10) : 0;
5333
+ const version = Number.isFinite(parsed) ? parsed : 0;
5334
+ if (version < 9) return false;
5335
+ throw new Error(`forget(): source_ref_index is missing on a schema_version=${version} database; run setup()`);
5336
+ }
5309
5337
  /**
5310
5338
  * Read-only dry-run preview of {@link forget}. Returns the same shape as a
5311
5339
  * real call would, without acquiring the lock, opening a transaction, staging
@@ -7679,5 +7707,5 @@ var WriteService = class {
7679
7707
  };
7680
7708
 
7681
7709
  export { BaseRepository, CURRENT_SCHEMA_VERSION, DEFAULT_CHUNK_OVERLAP, DEFAULT_MAX_CHUNK_LENGTH, DEFAULT_MAX_EMBED_CHARS, DiagnosticBuffer, EMBED_CHARS_CEILING, EmbeddingService, FTS5_DRAIN_CHUNK, FTS5_REBUILD_SNAPSHOT_KEY, FTS5_REBUILD_WM_KEY, FTS5_RECLAIM_MERGE_PAGES, FTS5_RETIRED_COUNTER_KEY, FTS5_RETIRED_TABLES_KEY, FTS5_STATE_KEY, FTS5_SWEEP_CURSOR_KEY, HEAL_ANCHORS_PER_CANDIDATE, HEAL_BATCH_SIZE, HEAL_MAX_FACT_BODY_CHARS_L3, HEAL_MAX_TASKS, HEAL_RECHECK_MS, HOOK_TIMEOUT_MARKER, ImportExportService, IngestionService, JobManager, MAX_EMBED_ATTEMPTS, MIGRATIONS, MaintenanceService, MetadataRepository, ONTOLOGY_BACKFILL_BATCH_SIZE, ONTOLOGY_BACKFILL_MAX_PROMPT_CHARS, ONTOLOGY_BACKFILL_RECHECK_MS, ONTOLOGY_BACKFILL_SYSTEM_PROMPT, PromptService, PrunePartialFailureError, RetrievalService, SearchService, TemporalService, UnavailableIndexStrategy, UsageMeter, WikiBusyError, WikiDraftNotFound, WikiDuplicateHashError, WikiGraphNodeOwnershipConflict, WikiIngestEmptyError, WikiInvalidReadOptions, WikiMigrationRequiredError, WikiParseError, WikiSearchUnavailableError, WikiSourceRefHashCollision, WikiStrictOntologyViolation, WikiSupersedeError, WikiTransactionError, WriteService, __privateAdd, __privateGet, __privateSet, assertEntityId, assertEpochMs, chunkText, configureRandomSource, createLegacySourceTypeIndex, detectSchemaVersion, drainChunkSql, drainHiSql, edgeTripleAllowed, emptyManifest, entityDrainChunkSql, entityDrainHiSql, entitySummaryMetaKey, extractSqliteCode, factTokenCost, fts5LedgerDropSql, fts5PendingIndexesDdl, fts5TablesDdl, fts5TriggerNames, fts5TriggersDdl, generateId, idDrainChunkSql, idReindexChunkSql, isLiveAt, isRetiredTableName, isWikiSearchUnavailableError, liveAtSql, normalizeSourceHash, normalizeSourceRef, normalizeTitleKey, packFactsByBudget, parseEmbedding, parseJsonArray, parseJsonObject, probePendingWork, readRebuildProgress, reanchorRebuildFingerprint, resolveEdgeDefinitions, resolveGrounding, resolveNodeType, retiredTableName, runSourceRefNormalize, safeSlice, setupDatabase, sweepChunkSql, sweepHiSql, typeSatisfies, validateInlineEdges, validateManifest, windowChunkSql, windowHiSql, writeNormalizeStamp, writeRebuildStart };
7682
- //# sourceMappingURL=chunk-BC3QHSF3.mjs.map
7683
- //# sourceMappingURL=chunk-BC3QHSF3.mjs.map
7710
+ //# sourceMappingURL=chunk-G7F5QPVR.mjs.map
7711
+ //# sourceMappingURL=chunk-G7F5QPVR.mjs.map