@equationalapplications/core-llm-wiki 4.18.0 → 4.19.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.
package/README.md CHANGED
@@ -590,6 +590,14 @@ A `WikiEdge` represents a directed link between two concepts (`source_id`, `targ
590
590
 
591
591
  See [`docs/okf-profile.md`](https://github.com/equationalapplications/expo-llm-wiki/blob/main/docs/okf-profile.md) for the full normative spec and [`packages/okf/fixtures/`](https://github.com/equationalapplications/expo-llm-wiki/tree/main/packages/okf/fixtures) for conformance bundles.
592
592
 
593
+ `importDump` persists an imported entity summary (profile ≥ 1 bundles) and
594
+ `exportDump` re-emits it, so the profile §4 round-trip holds across storage.
595
+ Read it directly with `wiki.getEntitySummary(entityId)`. The value lives in the
596
+ `{prefix}meta` table under `entity_summary:{entity_id}` and is removed by
597
+ `forget(entityId, { clearAll: true })`. See the
598
+ [design spec](../../docs/superpowers/specs/2026-07-05-okf-summary-persistence-design.md)
599
+ for import/merge semantics and wipe-path cleanup.
600
+
593
601
  ### The `okf_type` Field
594
602
 
595
603
  Facts and tasks include a nullable `okf_type` column. This preserves the literal OKF `type` string from an imported bundle frontmatter, independent of whether the item was routed to the `entries` or `tasks` table. When `formatOkfBundle` runs, it restores this specific string, falling back to `'fact'` or `'task'` if the field is null (ensuring non-imported rows export cleanly).
@@ -1156,6 +1156,169 @@ var IngestionService = class {
1156
1156
  }
1157
1157
  };
1158
1158
 
1159
+ // src/repositories/BaseRepository.ts
1160
+ var BaseRepository = class {
1161
+ constructor(db, prefix) {
1162
+ this.db = db;
1163
+ this.prefix = prefix;
1164
+ }
1165
+ /**
1166
+ * Return the DB executor for a given transaction handle.
1167
+ * If tx is provided, use it; otherwise fall back to this.db.
1168
+ */
1169
+ getExecutor(tx) {
1170
+ return tx ?? this.db;
1171
+ }
1172
+ };
1173
+
1174
+ // src/repositories/MetadataRepository.ts
1175
+ function entitySummaryMetaKey(entityId) {
1176
+ return `entity_summary:${entityId}`;
1177
+ }
1178
+ var MetadataRepository = class extends BaseRepository {
1179
+ // CHECKPOINTS TABLE METHODS
1180
+ async getCheckpoint(entityId, tx) {
1181
+ const executor = this.getExecutor(tx);
1182
+ const row = await executor.getFirstAsync(
1183
+ `SELECT memory_checkpoint, heal_checkpoint FROM ${this.prefix}checkpoints WHERE entity_id = ?`,
1184
+ [entityId]
1185
+ );
1186
+ if (!row) return {};
1187
+ return {
1188
+ memory: row.memory_checkpoint ?? void 0,
1189
+ heal: row.heal_checkpoint ?? void 0
1190
+ };
1191
+ }
1192
+ async updateCheckpoint(entityId, updates, tx) {
1193
+ const fields = [];
1194
+ const values = [];
1195
+ if (updates.memory !== void 0) {
1196
+ fields.push("memory_checkpoint = ?");
1197
+ values.push(updates.memory);
1198
+ }
1199
+ if (updates.heal !== void 0) {
1200
+ fields.push("heal_checkpoint = ?");
1201
+ values.push(updates.heal);
1202
+ }
1203
+ if (fields.length === 0) return;
1204
+ const executor = this.getExecutor(tx);
1205
+ await executor.runAsync(
1206
+ `INSERT INTO ${this.prefix}checkpoints (entity_id, memory_checkpoint, heal_checkpoint)
1207
+ VALUES (?, ?, ?)
1208
+ ON CONFLICT(entity_id) DO UPDATE SET ${fields.join(", ")}`,
1209
+ [entityId, updates.memory ?? 0, updates.heal ?? 0, ...values]
1210
+ );
1211
+ }
1212
+ async deleteCheckpoint(entityId, tx) {
1213
+ const executor = this.getExecutor(tx);
1214
+ await executor.runAsync(
1215
+ `DELETE FROM ${this.prefix}checkpoints WHERE entity_id = ?`,
1216
+ [entityId]
1217
+ );
1218
+ }
1219
+ // META TABLE METHODS
1220
+ async getMeta(key, tx) {
1221
+ const executor = this.getExecutor(tx);
1222
+ const row = await executor.getFirstAsync(
1223
+ `SELECT value FROM ${this.prefix}meta WHERE key = ?`,
1224
+ [key]
1225
+ );
1226
+ return row ? row.value : null;
1227
+ }
1228
+ async setMeta(key, value, tx) {
1229
+ const executor = this.getExecutor(tx);
1230
+ await executor.runAsync(
1231
+ `INSERT INTO ${this.prefix}meta (key, value) VALUES (?, ?)
1232
+ ON CONFLICT(key) DO UPDATE SET value = excluded.value`,
1233
+ [key, value]
1234
+ );
1235
+ }
1236
+ async deleteMeta(key, tx) {
1237
+ const executor = this.getExecutor(tx);
1238
+ await executor.runAsync(
1239
+ `DELETE FROM ${this.prefix}meta WHERE key = ?`,
1240
+ [key]
1241
+ );
1242
+ }
1243
+ async clearDimensionMismatch(tx) {
1244
+ const executor = this.getExecutor(tx);
1245
+ await executor.runAsync(
1246
+ `DELETE FROM ${this.prefix}meta WHERE key = 'embedding_dimension_mismatch'`
1247
+ );
1248
+ }
1249
+ async tableExists(tableName, tx) {
1250
+ const executor = this.getExecutor(tx);
1251
+ const row = await executor.getFirstAsync(
1252
+ `SELECT name FROM sqlite_master WHERE type='table' AND name=?`,
1253
+ [tableName]
1254
+ );
1255
+ return row != null;
1256
+ }
1257
+ async getTableDdl(tableName, tx) {
1258
+ const executor = this.getExecutor(tx);
1259
+ const row = await executor.getFirstAsync(
1260
+ `SELECT sql FROM sqlite_master WHERE type='table' AND name=?`,
1261
+ [tableName]
1262
+ );
1263
+ return row?.sql ?? null;
1264
+ }
1265
+ async vacuum() {
1266
+ await this.db.execAsync(`PRAGMA wal_checkpoint(TRUNCATE)`);
1267
+ await this.db.execAsync(`VACUUM`);
1268
+ }
1269
+ async getDistinctEntityIds(tx) {
1270
+ const executor = this.getExecutor(tx);
1271
+ const rows = await executor.getAllAsync(
1272
+ `SELECT DISTINCT entity_id FROM (
1273
+ SELECT entity_id FROM ${this.prefix}entries WHERE deleted_at IS NULL
1274
+ UNION
1275
+ SELECT entity_id FROM ${this.prefix}tasks WHERE deleted_at IS NULL
1276
+ UNION
1277
+ SELECT entity_id FROM ${this.prefix}events
1278
+ ) ORDER BY entity_id`
1279
+ );
1280
+ return rows.map((r) => r.entity_id);
1281
+ }
1282
+ async getManifest(entityId, tx) {
1283
+ const executor = this.getExecutor(tx);
1284
+ const row = await executor.getFirstAsync(`SELECT mode, manifest_json FROM ${this.prefix}entity_manifests WHERE entity_id = ?`, [entityId]);
1285
+ if (!row) return null;
1286
+ if (row.mode !== "off" && row.mode !== "strict" && row.mode !== "emergent") {
1287
+ throw new Error(`Invalid ontology mode for entity ${entityId}: ${JSON.stringify(row.mode)}`);
1288
+ }
1289
+ let manifest;
1290
+ try {
1291
+ manifest = JSON.parse(row.manifest_json);
1292
+ } catch (error) {
1293
+ throw new Error(`Invalid manifest_json for entity ${entityId}: ${error.message}`);
1294
+ }
1295
+ validateManifest(manifest);
1296
+ return {
1297
+ mode: row.mode,
1298
+ manifest
1299
+ };
1300
+ }
1301
+ async setManifest(entityId, data, tx) {
1302
+ validateManifest(data.manifest);
1303
+ const executor = this.getExecutor(tx);
1304
+ await executor.runAsync(
1305
+ `INSERT INTO ${this.prefix}entity_manifests (entity_id, mode, manifest_json, updated_at)
1306
+ VALUES (?, ?, ?, ?)
1307
+ ON CONFLICT(entity_id) DO UPDATE SET mode = excluded.mode, manifest_json = excluded.manifest_json, updated_at = excluded.updated_at`,
1308
+ [entityId, data.mode, JSON.stringify(data.manifest), Date.now()]
1309
+ );
1310
+ }
1311
+ async mergeManifestUpdates(entityId, updates, tx) {
1312
+ const current = await this.getManifest(entityId, tx) ?? {
1313
+ mode: "emergent",
1314
+ manifest: emptyManifest()
1315
+ };
1316
+ const merged = mergeOntologyUpdates(current.manifest, updates);
1317
+ await this.setManifest(entityId, { mode: current.mode, manifest: merged }, tx);
1318
+ return merged;
1319
+ }
1320
+ };
1321
+
1159
1322
  // src/services/MaintenanceService.ts
1160
1323
  var FUZZY_THRESHOLD = 0.5;
1161
1324
  var MIN_TOKENS_TO_QUALIFY = 3;
@@ -1331,6 +1494,7 @@ var MaintenanceService = class {
1331
1494
  deletedEntries = await this.entryRepo.bulkSoftDeleteByEntityId(entityId, tx);
1332
1495
  deletedTasks = await this.taskRepo.bulkSoftDeleteByEntityId(entityId, tx);
1333
1496
  await this.metadataRepo.updateCheckpoint(entityId, { memory: 0, heal: 0 }, tx);
1497
+ await this.metadataRepo.deleteMeta(entitySummaryMetaKey(entityId), tx);
1334
1498
  } else {
1335
1499
  const hasIdSelectors = params.entryId !== void 0 || params.taskId !== void 0;
1336
1500
  const hasSourceSelectors = params.sourceRef !== void 0 || params.sourceHash !== void 0;
@@ -1679,11 +1843,12 @@ var ImportExportService = class {
1679
1843
  }
1680
1844
  }
1681
1845
  async getFullBundle(entityId, opts) {
1682
- const [factsRaw, tasks, events, edges] = await Promise.all([
1846
+ const [factsRaw, tasks, events, edges, summaryValue] = await Promise.all([
1683
1847
  opts?.includeBlobs ? this.entryRepo.findAllByEntityIdWithBlobs(entityId) : this.entryRepo.findAllByEntityId(entityId),
1684
1848
  this.taskRepo.findAllByEntityId(entityId),
1685
1849
  this.eventRepo.getByEntityId(entityId, opts?.maxEvents),
1686
- this.edgeRepo.getByEntityId(entityId)
1850
+ this.edgeRepo.getByEntityId(entityId),
1851
+ this.metadataRepo.getMeta(entitySummaryMetaKey(entityId))
1687
1852
  ]);
1688
1853
  const facts = factsRaw.map((f) => {
1689
1854
  const {
@@ -1702,7 +1867,13 @@ var ImportExportService = class {
1702
1867
  tags: typeof factBase.tags === "string" ? JSON.parse(factBase.tags) : factBase.tags
1703
1868
  };
1704
1869
  });
1705
- return { facts, tasks, events, edges };
1870
+ return {
1871
+ facts,
1872
+ tasks,
1873
+ events,
1874
+ edges,
1875
+ ...summaryValue != null ? { summary: summaryValue } : {}
1876
+ };
1706
1877
  }
1707
1878
  /** Single-entity import transaction + post-processing; package-internal hook for tests. */
1708
1879
  async doImportEntity(entityId, bundle, merge) {
@@ -1727,6 +1898,11 @@ var ImportExportService = class {
1727
1898
  await this.edgeRepo.bulkDeleteByEntityId(entityId, tx);
1728
1899
  await this.metadataRepo.deleteCheckpoint(entityId, tx);
1729
1900
  }
1901
+ if (bundle.summary !== void 0) {
1902
+ await this.metadataRepo.setMeta(entitySummaryMetaKey(entityId), bundle.summary, tx);
1903
+ } else if (!merge) {
1904
+ await this.metadataRepo.deleteMeta(entitySummaryMetaKey(entityId), tx);
1905
+ }
1730
1906
  const factIds = bundle.facts.map((fact) => fact.id);
1731
1907
  const existingFactsById = /* @__PURE__ */ new Map();
1732
1908
  const existingFacts = await this.entryRepo.findExistingMetadataByIds(
@@ -2815,6 +2991,6 @@ var WriteService = class {
2815
2991
  }
2816
2992
  };
2817
2993
 
2818
- export { EmbeddingService, HOOK_TIMEOUT_MARKER, ImportExportService, IngestionService, JobManager, MaintenanceService, PromptService, PrunePartialFailureError, RetrievalService, SearchService, WikiBusyError, WriteService, __privateAdd, __privateGet, __privateSet, configureRandomSource, emptyManifest, generateId, mergeOntologyUpdates, normalizeSourceHash, normalizeSourceRef, normalizeTitleKey, parseEmbedding, resolveEdgeDefinition, resolveNodeType, validateInlineEdges, validateManifest };
2819
- //# sourceMappingURL=chunk-V7QNRQFK.mjs.map
2820
- //# sourceMappingURL=chunk-V7QNRQFK.mjs.map
2994
+ export { BaseRepository, EmbeddingService, HOOK_TIMEOUT_MARKER, ImportExportService, IngestionService, JobManager, MaintenanceService, MetadataRepository, PromptService, PrunePartialFailureError, RetrievalService, SearchService, WikiBusyError, WriteService, __privateAdd, __privateGet, __privateSet, configureRandomSource, emptyManifest, entitySummaryMetaKey, generateId, normalizeSourceHash, normalizeSourceRef, normalizeTitleKey, parseEmbedding, resolveEdgeDefinition, resolveNodeType, validateInlineEdges };
2995
+ //# sourceMappingURL=chunk-3GMXRLKU.mjs.map
2996
+ //# sourceMappingURL=chunk-3GMXRLKU.mjs.map