@equationalapplications/core-llm-wiki 6.4.0 → 6.5.1

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.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { __privateAdd, MetadataRepository, EmbeddingService, SearchService, JobManager, PromptService, IngestionService, MaintenanceService, ImportExportService, RetrievalService, WriteService, __privateGet, __privateSet, normalizeSourceRef, normalizeSourceHash, entitySummaryMetaKey, WikiSourceRefHashCollision, validateManifest, generateId, BaseRepository, emptyManifest, resolveNodeType, WikiStrictOntologyViolation, validateInlineEdges, resolveEdgeDefinitions, typeSatisfies, normalizeTitleKey, WikiTransactionError, extractSqliteCode } from './chunk-DPFM33WV.mjs';
2
- export { DEFAULT_CHUNK_OVERLAP, DEFAULT_MAX_CHUNK_LENGTH, DEFAULT_MAX_EMBED_CHARS, EMBED_CHARS_CEILING, HEAL_ANCHORS_PER_CANDIDATE, HEAL_BATCH_SIZE, HEAL_MAX_FACT_BODY_CHARS_L3, HEAL_MAX_TASKS, HEAL_RECHECK_MS, HOOK_TIMEOUT_MARKER, ONTOLOGY_BACKFILL_BATCH_SIZE, ONTOLOGY_BACKFILL_MAX_PROMPT_CHARS, ONTOLOGY_BACKFILL_RECHECK_MS, ONTOLOGY_BACKFILL_SYSTEM_PROMPT, PromptService, PrunePartialFailureError, WikiBusyError, WikiDuplicateHashError, WikiIngestEmptyError, WikiInvalidReadOptions, WikiParseError, WikiSourceRefHashCollision, WikiStrictOntologyViolation, WikiTransactionError, chunkText, configureRandomSource, parseEmbedding, safeSlice, validateManifest } from './chunk-DPFM33WV.mjs';
1
+ import { __privateAdd, MetadataRepository, EmbeddingService, SearchService, JobManager, PromptService, IngestionService, MaintenanceService, ImportExportService, RetrievalService, WriteService, __privateGet, __privateSet, normalizeSourceRef, normalizeSourceHash, entitySummaryMetaKey, WikiSourceRefHashCollision, validateManifest, generateId, BaseRepository, emptyManifest, resolveNodeType, WikiStrictOntologyViolation, validateInlineEdges, resolveEdgeDefinitions, typeSatisfies, normalizeTitleKey, WikiTransactionError, extractSqliteCode } from './chunk-YNFYSLR6.mjs';
2
+ export { DEFAULT_CHUNK_OVERLAP, DEFAULT_MAX_CHUNK_LENGTH, DEFAULT_MAX_EMBED_CHARS, EMBED_CHARS_CEILING, HEAL_ANCHORS_PER_CANDIDATE, HEAL_BATCH_SIZE, HEAL_MAX_FACT_BODY_CHARS_L3, HEAL_MAX_TASKS, HEAL_RECHECK_MS, HOOK_TIMEOUT_MARKER, ONTOLOGY_BACKFILL_BATCH_SIZE, ONTOLOGY_BACKFILL_MAX_PROMPT_CHARS, ONTOLOGY_BACKFILL_RECHECK_MS, ONTOLOGY_BACKFILL_SYSTEM_PROMPT, PromptService, PrunePartialFailureError, WikiBusyError, WikiDuplicateHashError, WikiIngestEmptyError, WikiInvalidReadOptions, WikiParseError, WikiSourceRefHashCollision, WikiStrictOntologyViolation, WikiTransactionError, chunkText, configureRandomSource, parseEmbedding, safeSlice, validateManifest } from './chunk-YNFYSLR6.mjs';
3
3
  import { appendRelatedSection, buildConceptDocument, buildLogMd, buildEntityIndexMd, buildRootIndexMd, isAllowedOkfPath, parseRootIndexMd, parseEntityIndexMd, parseConcept, splitRelatedSection, extractMarkdownLinks, parseLogMd, parseEventIdComment, latestVerified, formatSourcesJson, appendEventIdComment, parseVerifiedFlexible, parseCitationsList, deriveTrustTier, isStaleAfter } from '@equationalapplications/core-okf';
4
4
 
5
5
  // src/db/schema.ts
@@ -32,7 +32,10 @@ async function setupDatabase(db, prefix) {
32
32
  last_verified_by TEXT,
33
33
  okf_sources TEXT,
34
34
  okf_verified TEXT,
35
- okf_usage_window TEXT
35
+ okf_usage_window TEXT,
36
+ embedding_failed_at INTEGER,
37
+ embedding_failure_kind TEXT,
38
+ embedding_attempts INTEGER NOT NULL DEFAULT 0
36
39
  );
37
40
 
38
41
  CREATE INDEX IF NOT EXISTS ${prefix}entries_entity_idx ON ${prefix}entries(entity_id);
@@ -418,6 +421,24 @@ var MIGRATIONS = [
418
421
  CREATE INDEX IF NOT EXISTS ${prefix}tasks_last_verified_at_idx ON ${prefix}tasks(last_verified_at);
419
422
  `);
420
423
  }
424
+ },
425
+ {
426
+ version: 11,
427
+ description: "Add embedding_failed_at, embedding_failure_kind, embedding_attempts to entries for embed retry state",
428
+ run: async (db, prefix) => {
429
+ const cols = await db.getAllAsync(
430
+ `PRAGMA table_info(${prefix}entries)`
431
+ );
432
+ const existing = new Set(cols.map((c) => c.name));
433
+ const adds = [
434
+ ["embedding_failed_at", `ALTER TABLE ${prefix}entries ADD COLUMN embedding_failed_at INTEGER`],
435
+ ["embedding_failure_kind", `ALTER TABLE ${prefix}entries ADD COLUMN embedding_failure_kind TEXT`],
436
+ ["embedding_attempts", `ALTER TABLE ${prefix}entries ADD COLUMN embedding_attempts INTEGER NOT NULL DEFAULT 0`]
437
+ ];
438
+ for (const [name, sql] of adds) {
439
+ if (!existing.has(name)) await db.execAsync(sql);
440
+ }
441
+ }
421
442
  }
422
443
  ];
423
444
  for (let i = 1; i < MIGRATIONS.length; i++) {
@@ -563,6 +584,13 @@ var EntryRepository = class extends BaseRepository {
563
584
  * New-row INSERTs still bind a value so the column is populated; if the
564
585
  * caller supplied nothing, the schema DEFAULT 'stable' applies when the
565
586
  * bind is bound as 'stable' explicitly here.
587
+ *
588
+ * Marker discipline (spec §4.1): a conflict carrying a real
589
+ * `embedding_blob` clears the embedding failure markers, because the row now
590
+ * HAS a valid embedding and a surviving marker would be a self-contradictory
591
+ * diagnostic that inflates runReembed's permanentlyFailed counter. A conflict
592
+ * with no blob leaves marker state alone, matching the "absent means don't
593
+ * touch" semantics used for embedding_blob itself.
566
594
  */
567
595
  async upsert(fact, tx) {
568
596
  const executor = this.getExecutor(tx);
@@ -600,6 +628,9 @@ var EntryRepository = class extends BaseRepository {
600
628
  deleted_at = excluded.deleted_at,
601
629
  embedding_blob = CASE WHEN excluded.embedding_blob IS NULL THEN embedding_blob ELSE excluded.embedding_blob END,
602
630
  embedding = NULL,
631
+ embedding_failed_at = CASE WHEN excluded.embedding_blob IS NOT NULL THEN NULL ELSE embedding_failed_at END,
632
+ embedding_failure_kind = CASE WHEN excluded.embedding_blob IS NOT NULL THEN NULL ELSE embedding_failure_kind END,
633
+ embedding_attempts = CASE WHEN excluded.embedding_blob IS NOT NULL THEN 0 ELSE embedding_attempts END,
603
634
  okf_type = excluded.okf_type`,
604
635
  [
605
636
  fact.id,
@@ -728,6 +759,9 @@ var EntryRepository = class extends BaseRepository {
728
759
  deleted_at = excluded.deleted_at,
729
760
  embedding_blob = excluded.embedding_blob,
730
761
  embedding = NULL,
762
+ embedding_failed_at = CASE WHEN excluded.embedding_blob IS NOT NULL THEN NULL ELSE embedding_failed_at END,
763
+ embedding_failure_kind = CASE WHEN excluded.embedding_blob IS NOT NULL THEN NULL ELSE embedding_failure_kind END,
764
+ embedding_attempts = CASE WHEN excluded.embedding_blob IS NOT NULL THEN 0 ELSE embedding_attempts END,
731
765
  okf_type = excluded.okf_type,
732
766
  lifecycle_status = excluded.lifecycle_status,
733
767
  stale_after = excluded.stale_after,
@@ -1164,10 +1198,58 @@ var EntryRepository = class extends BaseRepository {
1164
1198
  async updateEmbeddingBlob(id, blob, tx) {
1165
1199
  const executor = this.getExecutor(tx);
1166
1200
  await executor.runAsync(
1167
- `UPDATE ${this.prefix}entries SET embedding_blob = ?, embedding = NULL WHERE id = ?`,
1201
+ `UPDATE ${this.prefix}entries
1202
+ SET embedding_blob = ?,
1203
+ embedding = NULL,
1204
+ embedding_failed_at = NULL,
1205
+ embedding_failure_kind = NULL,
1206
+ embedding_attempts = 0
1207
+ WHERE id = ?`,
1168
1208
  [blob, id]
1169
1209
  );
1170
1210
  }
1211
+ /**
1212
+ * Record a failed embedding attempt. Deliberately does NOT touch updated_at
1213
+ * (import merge is last-write-wins on it) and pushes no outbox event —
1214
+ * embedding lifecycle is local state, not replicated. Same discipline as
1215
+ * updateEmbeddingBlob. See spec §3.5.
1216
+ *
1217
+ * Only marker-eligible kinds (spec §3.3) are accepted: `no_provider` never
1218
+ * marks and `storage_error` never marks, so retry/permanent-failure policy
1219
+ * built on these rows only ever sees real embed failures.
1220
+ */
1221
+ async markEmbeddingFailure(id, kind, now, tx) {
1222
+ const executor = this.getExecutor(tx);
1223
+ await executor.runAsync(
1224
+ `UPDATE ${this.prefix}entries
1225
+ SET embedding_failed_at = ?,
1226
+ embedding_failure_kind = ?,
1227
+ embedding_attempts = embedding_attempts + 1
1228
+ WHERE id = ?`,
1229
+ [now, kind, id]
1230
+ );
1231
+ }
1232
+ /**
1233
+ * Clear marker state for every marked row. Called when the embedding
1234
+ * dimension is promoted: a new model produces different vectors, so past
1235
+ * failures — including `float32_overflow`, which is otherwise terminal —
1236
+ * no longer predict future ones (spec §2.3).
1237
+ *
1238
+ * Same discipline as markEmbeddingFailure: no `updated_at` touch and no
1239
+ * outbox event, because embedding lifecycle is local state, not replicated.
1240
+ * Returns the number of rows cleared.
1241
+ */
1242
+ async clearEmbeddingFailureMarkers(tx) {
1243
+ const executor = this.getExecutor(tx);
1244
+ const result = await executor.runAsync(
1245
+ `UPDATE ${this.prefix}entries
1246
+ SET embedding_failed_at = NULL,
1247
+ embedding_failure_kind = NULL,
1248
+ embedding_attempts = 0
1249
+ WHERE embedding_failed_at IS NOT NULL`
1250
+ );
1251
+ return result.changes;
1252
+ }
1171
1253
  async hasLegacySourceTypes(tx) {
1172
1254
  const executor = this.getExecutor(tx);
1173
1255
  const row = await executor.getFirstAsync(