@remnic/core 10.0.51 → 10.0.52

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.
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Orchestrator
3
- } from "./chunk-SJD334AG.js";
3
+ } from "./chunk-UM3ZLT2X.js";
4
4
  import "./chunk-YDIOMDBW.js";
5
5
  import "./chunk-V6Z4NAJZ.js";
6
6
  import "./chunk-5PHOU5QI.js";
@@ -5199,6 +5199,91 @@ async function readPromotionReceiptStatus(storage, filePath) {
5199
5199
  }
5200
5200
  }
5201
5201
 
5202
+ // src/orchestration/harmonic-construction-persist.ts
5203
+ function filterHarmonicEntityMentions(facts, entityMentions) {
5204
+ const identitiesBySegment = /* @__PURE__ */ new Map();
5205
+ for (const entity of entityMentions) {
5206
+ const segment = harmonicEntitySegment(entity.name);
5207
+ const identities = identitiesBySegment.get(segment) ?? /* @__PURE__ */ new Set();
5208
+ identities.add(normalizedHarmonicEntityIdentity(entity.name));
5209
+ identitiesBySegment.set(segment, identities);
5210
+ }
5211
+ return entityMentions.flatMap((entity) => {
5212
+ const allowSegmentFallback = identitiesBySegment.get(harmonicEntitySegment(entity.name))?.size === 1;
5213
+ const activeFacts = facts.filter(
5214
+ (fact) => typeof fact.entityRef === "string" && harmonicEntityReferenceMatches(fact.entityRef, entity.name, allowSegmentFallback)
5215
+ );
5216
+ return activeFacts.length > 0 ? [{ ...entity, facts: activeFacts.map((fact) => fact.content) }] : [];
5217
+ });
5218
+ }
5219
+ async function enqueueMergedTargetForHarmonicConstruction(entries, storage, fact, memoryId, content, insertedAt) {
5220
+ let committed = null;
5221
+ try {
5222
+ committed = await storage.getMemoryByIdIncludingArchived(memoryId);
5223
+ } catch {
5224
+ committed = null;
5225
+ }
5226
+ const derived = committed && committed.content === content ? {
5227
+ ...fact,
5228
+ category: committed.frontmatter.category,
5229
+ tags: [.../* @__PURE__ */ new Set([...committed.frontmatter.tags ?? [], ...fact.tags])],
5230
+ entityRef: committed.frontmatter.entityRef ?? fact.entityRef,
5231
+ validAt: committed.frontmatter.valid_at ?? fact.validAt
5232
+ } : fact;
5233
+ const entry = entries.get(storage.dir) ?? { storage, facts: [] };
5234
+ const prior = entry.facts.findIndex((existing) => existing.memoryId === memoryId);
5235
+ if (prior !== -1) {
5236
+ entry.facts[prior] = {
5237
+ ...derived,
5238
+ content,
5239
+ memoryId,
5240
+ insertedAt,
5241
+ cueAnchors: [
5242
+ ...entry.facts[prior].cueAnchors ?? [],
5243
+ ...derived.cueAnchors ?? []
5244
+ ]
5245
+ };
5246
+ } else {
5247
+ entry.facts.push({ ...derived, content, memoryId, insertedAt });
5248
+ }
5249
+ entries.set(storage.dir, entry);
5250
+ }
5251
+ async function persistConstructedHarmonicRecords(options) {
5252
+ const sessionKey = options.sessionKey?.trim();
5253
+ if (!sessionKey) {
5254
+ log.warn("harmonic construction skipped: extraction session key is missing");
5255
+ return;
5256
+ }
5257
+ const recordedAt = options.validAt && Number.isFinite(Date.parse(options.validAt)) ? new Date(options.validAt).toISOString() : (/* @__PURE__ */ new Date()).toISOString();
5258
+ const entries = [...options.entries];
5259
+ const sharedEpisodeTitle = entries.length === 1 ? options.episodeTitle : void 0;
5260
+ for (const entry of entries) {
5261
+ try {
5262
+ const records = deriveHarmonicRecords({
5263
+ sessionKey,
5264
+ recordedAt,
5265
+ episodeTitle: sharedEpisodeTitle,
5266
+ persistedFacts: entry.facts,
5267
+ entityMentions: filterHarmonicEntityMentions(entry.facts, options.entityMentions).map((entity) => ({
5268
+ name: entity.name,
5269
+ type: entity.type,
5270
+ facts: entity.facts
5271
+ }))
5272
+ });
5273
+ await persistHarmonicRecords({
5274
+ memoryDir: entry.storage.dir,
5275
+ abstractionNodeStoreDir: entry.storage.dir === options.baseStorageDir ? options.abstractionNodeStoreDir : void 0,
5276
+ nodes: records.nodes,
5277
+ anchors: options.anchorsEnabled ? records.anchors : []
5278
+ });
5279
+ } catch (error) {
5280
+ log.warn(
5281
+ `harmonic construction failed open for namespace ${entry.storage.dir}: ${error instanceof Error ? error.message : String(error)}`
5282
+ );
5283
+ }
5284
+ }
5285
+ }
5286
+
5202
5287
  // src/orchestration/extraction-persist-promotion.ts
5203
5288
  var confidenceTierOrder = [
5204
5289
  "explicit",
@@ -5246,11 +5331,57 @@ async function readActiveMemoriesBothTiers(storage) {
5246
5331
  ]);
5247
5332
  return coldMems.length === 0 ? hotMems : [...hotMems, ...coldMems];
5248
5333
  }
5249
- async function flushDeferredFactHashOnFailure(saveContentHashIndexes, deferred) {
5250
- if (!deferred) return;
5251
- await saveContentHashIndexes().catch(
5252
- (err) => log.warn(`content-hash flush after post-write failure failed: ${err}`)
5334
+ async function finalizeExtractionCommittedWrites(options) {
5335
+ await options.saveContentHashIndexes().catch((err) => {
5336
+ log.warn(`content-hash index save failed: ${err}`);
5337
+ });
5338
+ const behaviorEntries = [...options.behaviorSignalsByStorage];
5339
+ for (const { storage: targetStorage, events } of behaviorEntries) {
5340
+ const dedupedSignals = dedupeBehaviorSignalsByMemoryAndHash(events);
5341
+ if (dedupedSignals.length === 0) continue;
5342
+ await targetStorage.appendBehaviorSignals(dedupedSignals).catch(
5343
+ (err) => log.warn(`appendBehaviorSignals failed (non-fatal): ${err}`)
5344
+ );
5345
+ }
5346
+ const harmonic = options.harmonic;
5347
+ let harmonicEntryCount = 0;
5348
+ if (harmonic?.enabled) {
5349
+ const entries = [...harmonic.entries];
5350
+ harmonicEntryCount = entries.length;
5351
+ if (entries.length > 0) {
5352
+ await persistConstructedHarmonicRecords({
5353
+ entries,
5354
+ baseStorageDir: harmonic.baseStorageDir,
5355
+ abstractionNodeStoreDir: harmonic.abstractionNodeStoreDir,
5356
+ sessionKey: harmonic.sessionKey,
5357
+ validAt: harmonic.validAt,
5358
+ episodeTitle: harmonic.episodeTitle,
5359
+ anchorsEnabled: harmonic.anchorsEnabled,
5360
+ entityMentions: harmonic.entityMentions
5361
+ });
5362
+ }
5363
+ }
5364
+ void (async () => {
5365
+ if (options.persistedIdsByStorage.size === 0) {
5366
+ await options.updateTemporalTagIndexes(options.fallbackStorage, []);
5367
+ return;
5368
+ }
5369
+ for (const entry of options.persistedIdsByStorage.values()) {
5370
+ await options.updateTemporalTagIndexes(entry.storage, entry.ids);
5371
+ }
5372
+ })().catch(
5373
+ (err) => log.debug(`temporal-index update error (non-fatal): ${err}`)
5253
5374
  );
5375
+ if (!options.scheduleQmd || !options.requestQmdMaintenance) return;
5376
+ const hasCommitted = options.persistedIdsByStorage.size > 0 || behaviorEntries.length > 0 || harmonicEntryCount > 0;
5377
+ if (!hasCommitted) return;
5378
+ try {
5379
+ options.requestQmdMaintenance();
5380
+ } catch (err) {
5381
+ log.warn(
5382
+ `QMD maintenance schedule after partial persist failed (non-fatal): ${err}`
5383
+ );
5384
+ }
5254
5385
  }
5255
5386
  function promotionWithholdsToolScope(options) {
5256
5387
  return options.toolScoped === true || withholdToolScopedFromSharedNamespace(options);
@@ -5427,91 +5558,6 @@ async function retireStaleMergedTargetPromotionCopies(args) {
5427
5558
  return retired;
5428
5559
  }
5429
5560
 
5430
- // src/orchestration/harmonic-construction-persist.ts
5431
- function filterHarmonicEntityMentions(facts, entityMentions) {
5432
- const identitiesBySegment = /* @__PURE__ */ new Map();
5433
- for (const entity of entityMentions) {
5434
- const segment = harmonicEntitySegment(entity.name);
5435
- const identities = identitiesBySegment.get(segment) ?? /* @__PURE__ */ new Set();
5436
- identities.add(normalizedHarmonicEntityIdentity(entity.name));
5437
- identitiesBySegment.set(segment, identities);
5438
- }
5439
- return entityMentions.flatMap((entity) => {
5440
- const allowSegmentFallback = identitiesBySegment.get(harmonicEntitySegment(entity.name))?.size === 1;
5441
- const activeFacts = facts.filter(
5442
- (fact) => typeof fact.entityRef === "string" && harmonicEntityReferenceMatches(fact.entityRef, entity.name, allowSegmentFallback)
5443
- );
5444
- return activeFacts.length > 0 ? [{ ...entity, facts: activeFacts.map((fact) => fact.content) }] : [];
5445
- });
5446
- }
5447
- async function enqueueMergedTargetForHarmonicConstruction(entries, storage, fact, memoryId, content, insertedAt) {
5448
- let committed = null;
5449
- try {
5450
- committed = await storage.getMemoryByIdIncludingArchived(memoryId);
5451
- } catch {
5452
- committed = null;
5453
- }
5454
- const derived = committed && committed.content === content ? {
5455
- ...fact,
5456
- category: committed.frontmatter.category,
5457
- tags: [.../* @__PURE__ */ new Set([...committed.frontmatter.tags ?? [], ...fact.tags])],
5458
- entityRef: committed.frontmatter.entityRef ?? fact.entityRef,
5459
- validAt: committed.frontmatter.valid_at ?? fact.validAt
5460
- } : fact;
5461
- const entry = entries.get(storage.dir) ?? { storage, facts: [] };
5462
- const prior = entry.facts.findIndex((existing) => existing.memoryId === memoryId);
5463
- if (prior !== -1) {
5464
- entry.facts[prior] = {
5465
- ...derived,
5466
- content,
5467
- memoryId,
5468
- insertedAt,
5469
- cueAnchors: [
5470
- ...entry.facts[prior].cueAnchors ?? [],
5471
- ...derived.cueAnchors ?? []
5472
- ]
5473
- };
5474
- } else {
5475
- entry.facts.push({ ...derived, content, memoryId, insertedAt });
5476
- }
5477
- entries.set(storage.dir, entry);
5478
- }
5479
- async function persistConstructedHarmonicRecords(options) {
5480
- const sessionKey = options.sessionKey?.trim();
5481
- if (!sessionKey) {
5482
- log.warn("harmonic construction skipped: extraction session key is missing");
5483
- return;
5484
- }
5485
- const recordedAt = options.validAt && Number.isFinite(Date.parse(options.validAt)) ? new Date(options.validAt).toISOString() : (/* @__PURE__ */ new Date()).toISOString();
5486
- const entries = [...options.entries];
5487
- const sharedEpisodeTitle = entries.length === 1 ? options.episodeTitle : void 0;
5488
- for (const entry of entries) {
5489
- try {
5490
- const records = deriveHarmonicRecords({
5491
- sessionKey,
5492
- recordedAt,
5493
- episodeTitle: sharedEpisodeTitle,
5494
- persistedFacts: entry.facts,
5495
- entityMentions: filterHarmonicEntityMentions(entry.facts, options.entityMentions).map((entity) => ({
5496
- name: entity.name,
5497
- type: entity.type,
5498
- facts: entity.facts
5499
- }))
5500
- });
5501
- await persistHarmonicRecords({
5502
- memoryDir: entry.storage.dir,
5503
- abstractionNodeStoreDir: entry.storage.dir === options.baseStorageDir ? options.abstractionNodeStoreDir : void 0,
5504
- nodes: records.nodes,
5505
- anchors: options.anchorsEnabled ? records.anchors : []
5506
- });
5507
- } catch (error) {
5508
- log.warn(
5509
- `harmonic construction failed open for namespace ${entry.storage.dir}: ${error instanceof Error ? error.message : String(error)}`
5510
- );
5511
- }
5512
- }
5513
- }
5514
-
5515
5561
  // src/orchestration/semantic-merge-persist.ts
5516
5562
  import path5 from "path";
5517
5563
 
@@ -6925,6 +6971,28 @@ var ExtractionPersistCoordinator = class {
6925
6971
  0,
6926
6972
  this.deps.config.extractionMaxProfileUpdatesPerRun
6927
6973
  );
6974
+ const finalizeCommittedWrites = async (scheduleQmd) => {
6975
+ await finalizeExtractionCommittedWrites({
6976
+ saveContentHashIndexes: () => this.deps.saveContentHashIndexes(),
6977
+ behaviorSignalsByStorage: behaviorSignalsByStorage.values(),
6978
+ harmonic: {
6979
+ enabled: harmonicConstructionEnabled,
6980
+ entries: harmonicFactsByStorage.values(),
6981
+ baseStorageDir: storage.dir,
6982
+ abstractionNodeStoreDir: !scopeProfileWritePlan && harmonicBaseNamespace === this.deps.config.defaultNamespace ? this.deps.config.abstractionNodeStoreDir : void 0,
6983
+ sessionKey: sourceContext?.sessionKey,
6984
+ validAt: sourceContext?.validAt,
6985
+ episodeTitle: result.episodeTitle,
6986
+ anchorsEnabled: harmonicAnchorsEnabled,
6987
+ entityMentions: entities
6988
+ },
6989
+ updateTemporalTagIndexes: (target, ids) => this.deps.updateTemporalTagIndexes(target, ids),
6990
+ fallbackStorage: storage,
6991
+ persistedIdsByStorage,
6992
+ requestQmdMaintenance: () => this.deps.requestQmdMaintenance(),
6993
+ scheduleQmd
6994
+ });
6995
+ };
6928
6996
  if (facts.length < result.facts.length || entities.length < result.entities.length || questions.length < result.questions.length || profileUpdates.length < result.profileUpdates.length) {
6929
6997
  log.warn(
6930
6998
  `persistExtraction: capped extraction payload to guardrails (facts ${facts.length}/${result.facts.length}, entities ${entities.length}/${result.entities.length}, questions ${questions.length}/${result.questions.length}, profile ${profileUpdates.length}/${result.profileUpdates.length})`
@@ -7860,6 +7928,22 @@ var ExtractionPersistCoordinator = class {
7860
7928
  const memoryId = factWrite.id;
7861
7929
  const tombstoneBlocked = factWrite.tombstoneBlocked;
7862
7930
  const postWriteGuard = faithfulnessEnforceStatus === "pending_review" || tombstoneBlocked;
7931
+ trackBehaviorSignals(
7932
+ targetStorage,
7933
+ buildBehaviorSignalsForMemory({
7934
+ memoryId,
7935
+ category: writeCategory,
7936
+ content: fact.content,
7937
+ namespace: this.deps.storageDirNamespace(targetStorage.dir),
7938
+ confidence: fact.confidence,
7939
+ source: "extraction"
7940
+ })
7941
+ );
7942
+ trackPersistedId(targetStorage, memoryId, {
7943
+ pendingReview: postWriteGuard,
7944
+ category: writeCategory,
7945
+ harmonicFact
7946
+ });
7863
7947
  try {
7864
7948
  const contradictionOutcome = await this.deps.applyDeferredContradictionResolve(
7865
7949
  contradiction,
@@ -7871,7 +7955,9 @@ var ExtractionPersistCoordinator = class {
7871
7955
  await anchorSnapshots.remove(targetStorage, contradiction.supersededId);
7872
7956
  }
7873
7957
  } catch (err) {
7874
- await flushDeferredFactHashOnFailure(() => this.deps.saveContentHashIndexes(), factDedupEnabled);
7958
+ await finalizeCommittedWrites(true).catch(
7959
+ (finalizeErr) => log.warn(`committed-write finalization after post-write failure failed: ${finalizeErr}`)
7960
+ );
7875
7961
  throw err;
7876
7962
  }
7877
7963
  if (routedRuleId) {
@@ -7899,22 +7985,6 @@ var ExtractionPersistCoordinator = class {
7899
7985
  }
7900
7986
  }
7901
7987
  try {
7902
- trackBehaviorSignals(
7903
- targetStorage,
7904
- buildBehaviorSignalsForMemory({
7905
- memoryId,
7906
- category: writeCategory,
7907
- content: fact.content,
7908
- namespace: this.deps.storageDirNamespace(targetStorage.dir),
7909
- confidence: fact.confidence,
7910
- source: "extraction"
7911
- })
7912
- );
7913
- trackPersistedId(targetStorage, memoryId, {
7914
- pendingReview: postWriteGuard,
7915
- category: writeCategory,
7916
- harmonicFact
7917
- });
7918
7988
  await anchorSnapshots.replace(targetStorage, memoryId, writeCategory, memoryPathById);
7919
7989
  if (!postWriteGuard && threadEpisodeIdsForGraph && !threadEpisodeIdsForGraph.includes(memoryId)) {
7920
7990
  threadEpisodeIdsForGraph.push(memoryId);
@@ -8015,7 +8085,9 @@ var ExtractionPersistCoordinator = class {
8015
8085
  );
8016
8086
  }
8017
8087
  } catch (err) {
8018
- await flushDeferredFactHashOnFailure(() => this.deps.saveContentHashIndexes(), factDedupEnabled);
8088
+ await finalizeCommittedWrites(true).catch(
8089
+ (finalizeErr) => log.warn(`committed-write finalization after post-write failure failed: ${finalizeErr}`)
8090
+ );
8019
8091
  throw err;
8020
8092
  }
8021
8093
  }
@@ -8051,7 +8123,10 @@ var ExtractionPersistCoordinator = class {
8051
8123
  recordDurableNonFactWrite();
8052
8124
  }
8053
8125
  } catch (err) {
8054
- log.warn(`persistExtraction: entity write failed: ${err}`);
8126
+ await finalizeCommittedWrites(true).catch(
8127
+ (finalizeErr) => log.warn(`committed-write finalization after entity failure failed: ${finalizeErr}`)
8128
+ );
8129
+ throw err;
8055
8130
  }
8056
8131
  }
8057
8132
  if (resolveRecallEnhancementCapabilities(this.deps.config).entityRelationships && Array.isArray(result.relationships)) {
@@ -8131,19 +8206,7 @@ ${q.context ?? ""}`], entityScreenOn, entityScreenProfile);
8131
8206
  if (durableNonFactWritten) {
8132
8207
  touchBaseNonFactNamespace();
8133
8208
  }
8134
- await this.deps.saveContentHashIndexes().catch((err) => {
8135
- log.warn(`content-hash index save failed: ${err}`);
8136
- });
8137
- for (const {
8138
- storage: targetStorage,
8139
- events
8140
- } of behaviorSignalsByStorage.values()) {
8141
- const dedupedSignals = dedupeBehaviorSignalsByMemoryAndHash(events);
8142
- if (dedupedSignals.length === 0) continue;
8143
- await targetStorage.appendBehaviorSignals(dedupedSignals).catch(
8144
- (err) => log.warn(`appendBehaviorSignals failed (non-fatal): ${err}`)
8145
- );
8146
- }
8209
+ await finalizeCommittedWrites(false);
8147
8210
  const dedupSuffix = `${dedupedCount > 0 ? ` (${dedupedCount} deduped)` : ""}${semanticMergedCount > 0 ? ` (${semanticMergedCount} merged)` : ""}`;
8148
8211
  const gatedSuffix = importanceGatedCount > 0 ? ` (${importanceGatedCount} gated)` : "";
8149
8212
  const judgeSuffix = judgeGatedCount > 0 ? ` (${judgeGatedCount} judge-rejected)` : "";
@@ -8151,29 +8214,6 @@ ${q.context ?? ""}`], entityScreenOn, entityScreenProfile);
8151
8214
  log.info(
8152
8215
  `persisted: ${facts.length - dedupedCount - importanceGatedCount - judgeGatedCount - redactionGatedCount - semanticMergedCount} facts${dedupSuffix}${gatedSuffix}${judgeSuffix}${redactionSuffix}, ${entities.length} entities, ${questions.length} questions, ${profileUpdates.length} profile updates`
8153
8216
  );
8154
- if (harmonicConstructionEnabled && harmonicFactsByStorage.size > 0) {
8155
- await persistConstructedHarmonicRecords({
8156
- entries: harmonicFactsByStorage.values(),
8157
- baseStorageDir: storage.dir,
8158
- abstractionNodeStoreDir: !scopeProfileWritePlan && harmonicBaseNamespace === this.deps.config.defaultNamespace ? this.deps.config.abstractionNodeStoreDir : void 0,
8159
- sessionKey: sourceContext?.sessionKey,
8160
- validAt: sourceContext?.validAt,
8161
- episodeTitle: result.episodeTitle,
8162
- anchorsEnabled: harmonicAnchorsEnabled,
8163
- entityMentions: entities
8164
- });
8165
- }
8166
- void (async () => {
8167
- if (persistedIdsByStorage.size === 0) {
8168
- await this.deps.updateTemporalTagIndexes(storage, []);
8169
- return;
8170
- }
8171
- for (const entry of persistedIdsByStorage.values()) {
8172
- await this.deps.updateTemporalTagIndexes(entry.storage, entry.ids);
8173
- }
8174
- })().catch(
8175
- (err) => log.debug(`temporal-index update error (non-fatal): ${err}`)
8176
- );
8177
8217
  this.deps.setLastPersistExtractionPendingReviewIds(pendingReviewPersistedIds);
8178
8218
  return { persistedIds, memoryPathById };
8179
8219
  }
@@ -22023,7 +22063,8 @@ var Orchestrator = class {
22023
22063
  indexPersistedMemory: (storage, memoryId) => this.indexPersistedMemory(storage, memoryId),
22024
22064
  buildGraphEdge: (storage, memoryRelPath, entityRef, memoryId, factContent, allMemsForGraph, memoryPathById, threadIdForEdge, threadEpisodeIdsForGraph, fallbackCausalPredecessor, graphCaps) => this.buildGraphEdge(storage, memoryRelPath, entityRef, memoryId, factContent, allMemsForGraph, memoryPathById, threadIdForEdge, threadEpisodeIdsForGraph, fallbackCausalPredecessor, graphCaps),
22025
22065
  invalidateGraphEdgeCache: (storage) => this.graphIndexFor(storage).invalidateEdgeCache(),
22026
- updateTemporalTagIndexes: (storage, persistedIds) => this.updateTemporalTagIndexes(storage, persistedIds)
22066
+ updateTemporalTagIndexes: (storage, persistedIds) => this.updateTemporalTagIndexes(storage, persistedIds),
22067
+ requestQmdMaintenance: () => this.requestQmdMaintenance()
22027
22068
  });
22028
22069
  }
22029
22070
  return this._extractionPersistCoordinator;
@@ -31573,4 +31614,4 @@ export {
31573
31614
  qmdStartupCollectionChecksWithTimeout,
31574
31615
  Orchestrator
31575
31616
  };
31576
- //# sourceMappingURL=chunk-SJD334AG.js.map
31617
+ //# sourceMappingURL=chunk-UM3ZLT2X.js.map