@remnic/core 9.3.735 → 9.3.737

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.
Files changed (152) hide show
  1. package/dist/access-boundary.d.ts +17 -6
  2. package/dist/access-cli.js +1 -1
  3. package/dist/access-http.d.ts +17 -6
  4. package/dist/access-mcp.d.ts +17 -6
  5. package/dist/access-operations.d.ts +17 -6
  6. package/dist/access-schema.d.ts +4 -4
  7. package/dist/{access-service-CVx7mmvK.d.ts → access-service-DwQ6BIQw.d.ts} +3 -3
  8. package/dist/access-service.d.ts +16 -5
  9. package/dist/access-surface-catalog.d.ts +17 -6
  10. package/dist/action-confidence.d.ts +1 -1
  11. package/dist/active-memory-bridge.d.ts +1 -1
  12. package/dist/active-recall.d.ts +1 -1
  13. package/dist/behavior-learner.d.ts +1 -1
  14. package/dist/behavior-signals.d.ts +1 -1
  15. package/dist/bootstrap.d.ts +16 -4
  16. package/dist/briefing.d.ts +1 -1
  17. package/dist/buffer-surprise-report.d.ts +1 -1
  18. package/dist/buffer.d.ts +1 -1
  19. package/dist/calibration.d.ts +1 -1
  20. package/dist/capabilities.d.ts +1 -1
  21. package/dist/{catalog-BVhDEUhT.d.ts → catalog-_Bap6vfD.d.ts} +1 -1
  22. package/dist/causal-behavior.d.ts +1 -1
  23. package/dist/causal-consolidation.d.ts +1 -1
  24. package/dist/causal-trajectory-graph.d.ts +1 -1
  25. package/dist/{chunk-FLCYY5JX.js → chunk-PB5YON2G.js} +559 -481
  26. package/dist/chunk-PB5YON2G.js.map +1 -0
  27. package/dist/{cli-Cx5Mxwk7.d.ts → cli-BlEIWDQw.d.ts} +3 -3
  28. package/dist/cli.d.ts +9 -7
  29. package/dist/compounding/engine.d.ts +1 -1
  30. package/dist/compounding/preference-consolidator.d.ts +1 -1
  31. package/dist/compression-optimizer.d.ts +1 -1
  32. package/dist/config.d.ts +1 -1
  33. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  34. package/dist/connectors/codex-materialize.d.ts +1 -1
  35. package/dist/connectors/index.d.ts +1 -1
  36. package/dist/consolidation-provenance-check.d.ts +1 -1
  37. package/dist/consolidation-undo.d.ts +1 -1
  38. package/dist/contradiction/index.d.ts +1 -1
  39. package/dist/conversation-index/backend.d.ts +1 -1
  40. package/dist/conversation-index/chunker.d.ts +1 -1
  41. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  42. package/dist/conversation-index/indexer.d.ts +1 -1
  43. package/dist/conversation-index/search.d.ts +1 -1
  44. package/dist/day-summary.d.ts +1 -1
  45. package/dist/delinearize.d.ts +1 -1
  46. package/dist/direct-answer-wiring.d.ts +1 -1
  47. package/dist/direct-answer.d.ts +1 -1
  48. package/dist/embedding-fallback.d.ts +1 -1
  49. package/dist/enrichment/index.d.ts +1 -1
  50. package/dist/entity-retrieval.d.ts +1 -1
  51. package/dist/entity-schema.d.ts +1 -1
  52. package/dist/explicit-capture.d.ts +16 -4
  53. package/dist/extraction-faithfulness.d.ts +1 -1
  54. package/dist/extraction-judge-telemetry.d.ts +1 -1
  55. package/dist/extraction-judge-training.d.ts +1 -1
  56. package/dist/extraction-judge.d.ts +1 -1
  57. package/dist/extraction.d.ts +1 -1
  58. package/dist/fallback-llm.d.ts +1 -1
  59. package/dist/graph-dashboard-diff.d.ts +1 -1
  60. package/dist/graph-dashboard-key.d.ts +1 -1
  61. package/dist/graph-dashboard-parser.d.ts +1 -1
  62. package/dist/graph-edge-reinforcement.d.ts +1 -1
  63. package/dist/graph-snapshot.d.ts +1 -1
  64. package/dist/graph.d.ts +1 -1
  65. package/dist/identity-continuity.d.ts +1 -1
  66. package/dist/importance.d.ts +1 -1
  67. package/dist/index.d.ts +20 -18
  68. package/dist/index.js +1 -1
  69. package/dist/intent.d.ts +1 -1
  70. package/dist/lcm/engine.d.ts +1 -1
  71. package/dist/lcm/index.d.ts +1 -1
  72. package/dist/lcm/tools.d.ts +1 -1
  73. package/dist/lifecycle.d.ts +1 -1
  74. package/dist/live-connectors-runner.d.ts +1 -1
  75. package/dist/local-llm.d.ts +1 -1
  76. package/dist/local-model-endpoint.d.ts +1 -1
  77. package/dist/maintenance/memory-governance.d.ts +1 -1
  78. package/dist/mcp-memory-inspector-app.d.ts +17 -6
  79. package/dist/memory-action-policy.d.ts +1 -1
  80. package/dist/memory-cache.d.ts +1 -1
  81. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  82. package/dist/memory-projection-store.d.ts +1 -1
  83. package/dist/memory-provenance.d.ts +1 -1
  84. package/dist/memory-worth-outcomes.d.ts +1 -1
  85. package/dist/models-json.d.ts +1 -1
  86. package/dist/namespaces/migrate.d.ts +2 -2
  87. package/dist/namespaces/principal.d.ts +1 -1
  88. package/dist/namespaces/search.d.ts +1 -1
  89. package/dist/namespaces/storage.d.ts +2 -2
  90. package/dist/native-knowledge.d.ts +1 -1
  91. package/dist/operator-toolkit.d.ts +1 -1
  92. package/dist/orchestration/compression-guideline-coordinator.d.ts +1 -1
  93. package/dist/orchestration/maintenance.d.ts +2 -2
  94. package/dist/{orchestrator-oF0cceBX.d.ts → orchestrator-CJZ21ZiB.d.ts} +139 -14
  95. package/dist/orchestrator.d.ts +16 -4
  96. package/dist/orchestrator.js +1 -3
  97. package/dist/patterns-cli.d.ts +1 -1
  98. package/dist/policy-runtime.d.ts +1 -1
  99. package/dist/provenance.d.ts +1 -1
  100. package/dist/qmd-recall-cache.d.ts +1 -1
  101. package/dist/qmd.d.ts +1 -1
  102. package/dist/recall-disclosure-escalation.d.ts +1 -1
  103. package/dist/recall-explain-renderer.d.ts +1 -1
  104. package/dist/recall-planner-llm.d.ts +1 -1
  105. package/dist/recall-state.d.ts +1 -1
  106. package/dist/recall-tag-filter.d.ts +1 -1
  107. package/dist/recall-xray-cli.d.ts +1 -1
  108. package/dist/recall-xray-renderer.d.ts +1 -1
  109. package/dist/recall-xray.d.ts +1 -1
  110. package/dist/resolve-auth-token.d.ts +1 -1
  111. package/dist/retrieval-agents.d.ts +1 -1
  112. package/dist/retrieval-tiers.d.ts +1 -1
  113. package/dist/routing/engine.d.ts +1 -1
  114. package/dist/routing/store.d.ts +1 -1
  115. package/dist/schemas.d.ts +24 -24
  116. package/dist/search/embed-helper.d.ts +1 -1
  117. package/dist/search/factory.d.ts +1 -1
  118. package/dist/search/index.d.ts +1 -1
  119. package/dist/search/lancedb-backend.d.ts +1 -1
  120. package/dist/search/meilisearch-backend.d.ts +1 -1
  121. package/dist/search/noop-backend.d.ts +1 -1
  122. package/dist/search/orama-backend.d.ts +1 -1
  123. package/dist/search/port.d.ts +1 -1
  124. package/dist/search/remote-backend.d.ts +1 -1
  125. package/dist/{semantic-consolidation-DKGbufYO.d.ts → semantic-consolidation-DsIEiCka.d.ts} +1 -1
  126. package/dist/semantic-consolidation.d.ts +2 -2
  127. package/dist/semantic-rule-verifier.d.ts +1 -1
  128. package/dist/session-observer-bands.d.ts +1 -1
  129. package/dist/session-observer-state.d.ts +1 -1
  130. package/dist/shared-context/manager.d.ts +3 -3
  131. package/dist/signal.d.ts +1 -1
  132. package/dist/storage.d.ts +1 -1
  133. package/dist/summarizer.d.ts +1 -1
  134. package/dist/summary-snapshot.d.ts +1 -1
  135. package/dist/temporal-supersession.d.ts +1 -1
  136. package/dist/temporal-validity.d.ts +1 -1
  137. package/dist/threading.d.ts +1 -1
  138. package/dist/tier-migration.d.ts +1 -1
  139. package/dist/tier-routing.d.ts +1 -1
  140. package/dist/topics.d.ts +1 -1
  141. package/dist/transcript.d.ts +1 -1
  142. package/dist/transfer/types.d.ts +42 -42
  143. package/dist/trust-score-stage.d.ts +2 -2
  144. package/dist/trust-score.d.ts +1 -1
  145. package/dist/{types-C7UCxpuO.d.ts → types-CglNn2V-.d.ts} +1 -1
  146. package/dist/types.d.ts +1 -1
  147. package/dist/utility-runtime.d.ts +1 -1
  148. package/package.json +2 -2
  149. package/src/orchestration/entity-synthesis-coordinator.ts +319 -0
  150. package/src/orchestration/recall-result-formatter.ts +438 -0
  151. package/src/orchestrator.ts +34 -540
  152. package/dist/chunk-FLCYY5JX.js.map +0 -1
@@ -508,7 +508,7 @@ import {
508
508
  // src/orchestrator.ts
509
509
  import path4 from "path";
510
510
  import os2 from "os";
511
- import { createHash, randomBytes } from "crypto";
511
+ import { createHash as createHash2, randomBytes } from "crypto";
512
512
  import { existsSync, readFileSync } from "fs";
513
513
  import {
514
514
  lstat,
@@ -1436,6 +1436,509 @@ var LifecyclePolicyCoordinator = class {
1436
1436
  }
1437
1437
  };
1438
1438
 
1439
+ // src/orchestration/entity-synthesis-coordinator.ts
1440
+ import { createHash } from "crypto";
1441
+ function dedupeEntitySynthesisEvidenceEntries(entries) {
1442
+ const dedupedEvidenceEntries = [];
1443
+ const evidenceByFact = /* @__PURE__ */ new Map();
1444
+ for (const entry of entries) {
1445
+ const normalizedFact = entry.text.trim();
1446
+ if (!normalizedFact) continue;
1447
+ const existing = evidenceByFact.get(normalizedFact);
1448
+ if (!existing) {
1449
+ evidenceByFact.set(normalizedFact, { newest: entry, oldest: entry });
1450
+ continue;
1451
+ }
1452
+ if (compareEntityTimestamps(entry.timestamp, existing.newest.timestamp) > 0) {
1453
+ existing.newest = entry;
1454
+ }
1455
+ if (compareEntityTimestamps(entry.timestamp, existing.oldest.timestamp) < 0) {
1456
+ existing.oldest = entry;
1457
+ }
1458
+ }
1459
+ for (const { newest, oldest } of evidenceByFact.values()) {
1460
+ dedupedEvidenceEntries.push(newest);
1461
+ const newestKey = [
1462
+ newest.timestamp,
1463
+ newest.source ?? "",
1464
+ newest.sessionKey ?? "",
1465
+ newest.principal ?? "",
1466
+ newest.text
1467
+ ].join("\0");
1468
+ const oldestKey = [
1469
+ oldest.timestamp,
1470
+ oldest.source ?? "",
1471
+ oldest.sessionKey ?? "",
1472
+ oldest.principal ?? "",
1473
+ oldest.text
1474
+ ].join("\0");
1475
+ if (oldestKey !== newestKey) {
1476
+ dedupedEvidenceEntries.push(oldest);
1477
+ }
1478
+ }
1479
+ return dedupedEvidenceEntries;
1480
+ }
1481
+ function flattenStructuredSectionEvidence(sections) {
1482
+ return (sections ?? []).flatMap(
1483
+ (section) => section.facts.map((fact) => fact.trim()).filter((fact) => fact.length > 0).map((fact) => ({
1484
+ timestamp: "",
1485
+ text: fact,
1486
+ source: `section:${section.title}`
1487
+ }))
1488
+ );
1489
+ }
1490
+ function fingerprintEntitySynthesisEvidence(entity) {
1491
+ const fingerprint = createHash("sha256");
1492
+ const timelineEntries = entity.timeline.map((entry) => [
1493
+ entry.timestamp,
1494
+ entry.source ?? "",
1495
+ entry.sessionKey ?? "",
1496
+ entry.principal ?? "",
1497
+ entry.text
1498
+ ].join("\0")).sort();
1499
+ const timelineEntrySeparator = String.fromCharCode(1);
1500
+ const structuredFactsSeparator = String.fromCharCode(2);
1501
+ fingerprint.update(timelineEntries.join(timelineEntrySeparator));
1502
+ fingerprint.update(structuredFactsSeparator);
1503
+ fingerprint.update(fingerprintEntityStructuredFacts(entity) ?? "");
1504
+ return fingerprint.digest("hex");
1505
+ }
1506
+ var EntitySynthesisCoordinator = class {
1507
+ constructor(deps) {
1508
+ this.deps = deps;
1509
+ }
1510
+ deps;
1511
+ /**
1512
+ * Process up to `maxEntities` entities from the synthesis queue for the
1513
+ * given namespace. Returns the number of entities whose synthesis was
1514
+ * successfully refreshed.
1515
+ */
1516
+ async processQueue(namespace, maxEntities = 5) {
1517
+ const { config } = this.deps;
1518
+ if (!config.entitySummaryEnabled || maxEntities <= 0 || config.entitySynthesisMaxTokens <= 0) return 0;
1519
+ const storage = await this.deps.getStorage(namespace);
1520
+ const queued = await storage.refreshEntitySynthesisQueue();
1521
+ let processed = 0;
1522
+ let attempted = 0;
1523
+ for (const entityName of queued) {
1524
+ if (attempted >= maxEntities) break;
1525
+ attempted += 1;
1526
+ try {
1527
+ const raw = await storage.readEntity(entityName);
1528
+ if (!raw) continue;
1529
+ const entity = parseEntityFile(raw, config.entitySchemas);
1530
+ const previousSynthesis = entity.synthesis || entity.summary || "";
1531
+ const sortedTimelineEntries = entity.timeline.slice().sort((left, right) => compareEntityTimestamps(right.timestamp, left.timestamp));
1532
+ const newerTimelineEntries = sortedTimelineEntries.filter(
1533
+ (entry) => !entity.synthesisUpdatedAt || compareEntityTimestamps(entry.timestamp, entity.synthesisUpdatedAt) > 0
1534
+ );
1535
+ const appendedTimelineEntries = entity.synthesisTimelineCount === void 0 ? [] : entity.timeline.slice(Math.max(0, entity.synthesisTimelineCount));
1536
+ const structuredEvidenceEntries = flattenStructuredSectionEvidence(entity.structuredSections);
1537
+ const structuredEvidenceCount = structuredEvidenceEntries.length;
1538
+ const structuredEvidenceDigest = fingerprintEntityStructuredFacts(entity);
1539
+ const structuredEvidenceDrifted = structuredEvidenceDigest !== (entity.synthesisStructuredFactDigest?.trim() || void 0);
1540
+ const appendedStructuredEvidenceEntries = entity.synthesisStructuredFactCount === void 0 || structuredEvidenceDrifted ? structuredEvidenceEntries : structuredEvidenceEntries.slice(Math.max(0, entity.synthesisStructuredFactCount));
1541
+ const candidateEvidenceEntries = [
1542
+ ...newerTimelineEntries,
1543
+ ...appendedTimelineEntries,
1544
+ ...appendedStructuredEvidenceEntries
1545
+ ].slice().sort((left, right) => compareEntityTimestamps(right.timestamp, left.timestamp));
1546
+ const dedupedEvidenceEntries = dedupeEntitySynthesisEvidenceEntries(
1547
+ candidateEvidenceEntries.length > 0 ? candidateEvidenceEntries : [...sortedTimelineEntries, ...structuredEvidenceEntries]
1548
+ );
1549
+ const chronologicalEvidenceEntries = dedupedEvidenceEntries.slice().sort((left, right) => compareEntityTimestamps(left.timestamp, right.timestamp));
1550
+ if (chronologicalEvidenceEntries.length === 0) continue;
1551
+ const latestEvidenceTimestamp = chronologicalEvidenceEntries.slice().reverse().map((entry) => entry.timestamp?.trim() || void 0).find((timestamp) => Boolean(timestamp));
1552
+ const previousSynthesisUpdatedAt = entity.synthesisUpdatedAt?.trim() || void 0;
1553
+ const nextSynthesisUpdatedAt = compareEntityTimestamps(
1554
+ latestEvidenceTimestamp,
1555
+ previousSynthesisUpdatedAt
1556
+ ) >= 0 ? latestEvidenceTimestamp : previousSynthesisUpdatedAt;
1557
+ const evidenceBatches = [];
1558
+ for (let index = 0; index < chronologicalEvidenceEntries.length; index += 8) {
1559
+ evidenceBatches.push(chronologicalEvidenceEntries.slice(index, index + 8));
1560
+ }
1561
+ let nextSynthesis = previousSynthesis;
1562
+ let batchFailed = false;
1563
+ for (const evidenceEntries of evidenceBatches) {
1564
+ const evidenceText = evidenceEntries.map((entry) => {
1565
+ const sectionTitle = entry.source?.startsWith("section:") ? entry.source.slice("section:".length) : "";
1566
+ const metadata = [
1567
+ `timestamp=${entry.timestamp}`,
1568
+ sectionTitle ? `section=${sectionTitle}` : entry.source ? `source=${entry.source}` : "",
1569
+ entry.sessionKey ? `session=${entry.sessionKey}` : "",
1570
+ entry.principal ? `principal=${entry.principal}` : ""
1571
+ ].filter(Boolean).join(", ");
1572
+ return `- ${metadata}: ${entry.text}`;
1573
+ }).join("\n");
1574
+ const response = await this.deps.fastChatCompletion(
1575
+ [
1576
+ {
1577
+ role: "system",
1578
+ content: "Rewrite the entity synthesis as compact current truth. Preserve uncertainty when evidence conflicts. Return plain text only."
1579
+ },
1580
+ {
1581
+ role: "user",
1582
+ content: [
1583
+ `Entity: ${entity.name} (${entity.type})`,
1584
+ nextSynthesis ? `Previous synthesis:
1585
+ ${nextSynthesis}` : "Previous synthesis: none",
1586
+ `New evidence:
1587
+ ${evidenceText}`
1588
+ ].join("\n\n")
1589
+ }
1590
+ ],
1591
+ {
1592
+ temperature: 0.2,
1593
+ maxTokens: config.entitySynthesisMaxTokens,
1594
+ operation: "entity_summary",
1595
+ priority: "background"
1596
+ }
1597
+ );
1598
+ const synthesis = response?.content?.trim().replace(/^["']|["']$/g, "");
1599
+ const maxSynthesisChars = Math.max(2e3, config.entitySynthesisMaxTokens * 8);
1600
+ if (!synthesis || synthesis.length < 10 || synthesis.length > maxSynthesisChars) {
1601
+ batchFailed = true;
1602
+ break;
1603
+ }
1604
+ nextSynthesis = synthesis;
1605
+ }
1606
+ if (batchFailed || nextSynthesis.length === 0) continue;
1607
+ const latestRaw = await storage.readEntity(entityName);
1608
+ if (!latestRaw) continue;
1609
+ const latestEntity = parseEntityFile(latestRaw, config.entitySchemas);
1610
+ if (fingerprintEntitySynthesisEvidence(latestEntity) !== fingerprintEntitySynthesisEvidence(entity)) {
1611
+ continue;
1612
+ }
1613
+ await storage.updateEntitySynthesis(entityName, nextSynthesis, {
1614
+ entityUpdatedAt: (/* @__PURE__ */ new Date()).toISOString(),
1615
+ synthesisStructuredFactDigest: structuredEvidenceDigest,
1616
+ synthesisStructuredFactCount: structuredEvidenceCount,
1617
+ synthesisTimelineCount: entity.timeline.length,
1618
+ updatedAt: nextSynthesisUpdatedAt
1619
+ });
1620
+ processed += 1;
1621
+ } catch (err) {
1622
+ log.debug(`entity synthesis refresh failed for ${entityName}: ${err}`);
1623
+ }
1624
+ }
1625
+ return processed;
1626
+ }
1627
+ };
1628
+
1629
+ // src/orchestration/recall-result-formatter.ts
1630
+ function hasIdentityRecoveryIntent(prompt) {
1631
+ const text = typeof prompt === "string" ? prompt.toLowerCase() : "";
1632
+ if (!text) return false;
1633
+ return /\b(identity|continuity|recover(?:y|ing|ed)?|incident|drift|restore|regress(?:ion|ed|ing)?)\b/i.test(
1634
+ text
1635
+ );
1636
+ }
1637
+ function resolveEffectiveIdentityInjectionMode(options) {
1638
+ if (options.configuredMode === "recovery_only" && !hasIdentityRecoveryIntent(options.prompt)) {
1639
+ return { mode: "recovery_only", shouldInject: false };
1640
+ }
1641
+ if (options.recallMode === "minimal" && options.configuredMode === "full") {
1642
+ return { mode: "minimal", shouldInject: true };
1643
+ }
1644
+ return { mode: options.configuredMode, shouldInject: true };
1645
+ }
1646
+ var RecallResultFormatter = class {
1647
+ constructor(config) {
1648
+ this.config = config;
1649
+ }
1650
+ config;
1651
+ // ── QMD results (memory handles + epistemic hedge) ──────────────────────
1652
+ formatQmdResults(title, results, sessionKey, trustByPath) {
1653
+ const handleByIndex = buildHandleIndexForResults(
1654
+ results,
1655
+ this.config.recallMemoryHandles === true && sessionKey != null
1656
+ );
1657
+ const renderHedge = this.config.trustScoreEpistemicRendering && trustByPath !== null && trustByPath !== void 0;
1658
+ const hedgeMap = renderHedge ? trustByPath : null;
1659
+ const lines = results.map((r, i) => {
1660
+ const snippet = r.snippet ? r.snippet.slice(0, 500).replace(/\n/g, " ") : "(no preview)";
1661
+ const source = typeof r.line === "number" ? `${r.path}:${r.line}` : r.path;
1662
+ const head = `[${i + 1}] ${source} (score: ${r.score.toFixed(3)})
1663
+ ${snippet}`;
1664
+ const handle = handleByIndex.get(i);
1665
+ const hedged = head.replace(/\s+$/, "");
1666
+ const withHandle = handle ? `${hedged} ${handle}` : hedged;
1667
+ if (hedgeMap) {
1668
+ const item = hedgeMap.get(r.path);
1669
+ if (item) {
1670
+ const hedge = renderEpistemicHedge(item.trust);
1671
+ if (hedge.length > 0) return `${withHandle} ${hedge}`;
1672
+ }
1673
+ }
1674
+ return withHandle;
1675
+ });
1676
+ return `## ${title}
1677
+
1678
+ ${lines.join("\n\n")}`;
1679
+ }
1680
+ // ── Specialized recall result formatters ────────────────────────────────
1681
+ formatObjectiveStateResults(results) {
1682
+ const lines = results.map(({ snapshot }, index) => {
1683
+ const parts = [
1684
+ snapshot.recordedAt.replace("T", " ").slice(0, 16),
1685
+ `${snapshot.kind}/${snapshot.changeKind}`
1686
+ ];
1687
+ if (snapshot.outcome) parts.push(snapshot.outcome);
1688
+ const header = `[${index + 1}] ${parts.join(" | ")} | ${snapshot.scope}`;
1689
+ const detailParts = [snapshot.summary];
1690
+ if (snapshot.command) detailParts.push(`command: ${snapshot.command}`);
1691
+ else if (snapshot.toolName)
1692
+ detailParts.push(`tool: ${snapshot.toolName}`);
1693
+ return `${header}
1694
+ ${detailParts.join(" | ")}`;
1695
+ });
1696
+ return `## Objective State
1697
+
1698
+ ${lines.join("\n\n")}`;
1699
+ }
1700
+ formatCausalTrajectoryResults(results) {
1701
+ const lines = results.map(({ record, matchedFields }, index) => {
1702
+ const header = [
1703
+ `[${index + 1}] ${record.recordedAt.replace("T", " ").slice(0, 16)}`,
1704
+ record.outcomeKind
1705
+ ].join(" | ");
1706
+ const details = [
1707
+ `goal: ${record.goal}`,
1708
+ `action: ${record.actionSummary}`,
1709
+ `observation: ${record.observationSummary}`,
1710
+ `outcome: ${record.outcomeSummary}`
1711
+ ];
1712
+ if (record.followUpSummary)
1713
+ details.push(`follow-up: ${record.followUpSummary}`);
1714
+ if (matchedFields.length > 0)
1715
+ details.push(`matched: ${matchedFields.join(", ")}`);
1716
+ return `${header}
1717
+ ${details.join("\n")}`;
1718
+ });
1719
+ return `## Causal Trajectories
1720
+
1721
+ ${lines.join("\n\n")}`;
1722
+ }
1723
+ formatTrustZoneResults(results) {
1724
+ const lines = results.map(({ record, matchedFields }, index) => {
1725
+ const header = [
1726
+ `[${index + 1}] ${record.recordedAt.replace("T", " ").slice(0, 16)}`,
1727
+ record.zone,
1728
+ record.kind
1729
+ ].join(" | ");
1730
+ const details = [
1731
+ record.summary,
1732
+ `provenance: ${record.provenance.sourceClass}`
1733
+ ];
1734
+ if (record.entityRefs && record.entityRefs.length > 0) {
1735
+ details.push(`entities: ${record.entityRefs.join(", ")}`);
1736
+ }
1737
+ if (record.tags && record.tags.length > 0) {
1738
+ details.push(`tags: ${record.tags.join(", ")}`);
1739
+ }
1740
+ if (matchedFields.length > 0) {
1741
+ details.push(`matched: ${matchedFields.join(", ")}`);
1742
+ }
1743
+ return `${header}
1744
+ ${details.join("\n")}`;
1745
+ });
1746
+ return `## Trust Zones
1747
+
1748
+ ${lines.join("\n\n")}`;
1749
+ }
1750
+ formatHarmonicRetrievalResults(results) {
1751
+ const lines = results.map(
1752
+ ({ node, matchedAnchors, matchedFields, nodeScore, anchorScore }, index) => {
1753
+ const header = [
1754
+ `[${index + 1}] ${node.recordedAt.replace("T", " ").slice(0, 16)}`,
1755
+ `${node.kind}/${node.abstractionLevel}`,
1756
+ node.sessionKey
1757
+ ].join(" | ");
1758
+ const details = [
1759
+ node.title,
1760
+ node.summary,
1761
+ `scores: node=${nodeScore.toFixed(1)} anchor=${anchorScore.toFixed(1)}`
1762
+ ];
1763
+ if (matchedAnchors.length > 0) {
1764
+ details.push(
1765
+ `anchors: ${matchedAnchors.map((anchor) => `${anchor.anchorType}:${anchor.anchorValue}`).join("; ")}`
1766
+ );
1767
+ }
1768
+ if (matchedFields.length > 0) {
1769
+ details.push(`matched: ${matchedFields.join(", ")}`);
1770
+ }
1771
+ return `${header}
1772
+ ${details.join("\n")}`;
1773
+ }
1774
+ );
1775
+ return `## Harmonic Retrieval
1776
+
1777
+ ${lines.join("\n\n")}`;
1778
+ }
1779
+ formatWorkProductResults(results) {
1780
+ const lines = results.map(({ entry, matchedFields }, index) => {
1781
+ const header = [
1782
+ `[${index + 1}] ${entry.recordedAt.replace("T", " ").slice(0, 16)}`,
1783
+ `${entry.kind}/${entry.action}`,
1784
+ entry.sessionKey
1785
+ ].join(" | ");
1786
+ const details = [entry.summary, `scope: ${entry.scope}`];
1787
+ if (entry.artifactPath) details.push(`artifact: ${entry.artifactPath}`);
1788
+ if (entry.tags && entry.tags.length > 0)
1789
+ details.push(`tags: ${entry.tags.join(", ")}`);
1790
+ if (matchedFields.length > 0)
1791
+ details.push(`matched: ${matchedFields.join(", ")}`);
1792
+ return `${header}
1793
+ ${details.join("\n")}`;
1794
+ });
1795
+ return `## Work Products
1796
+
1797
+ ${lines.join("\n\n")}`;
1798
+ }
1799
+ formatVerifiedEpisodeResults(results) {
1800
+ const lines = results.map(
1801
+ ({ box, verifiedEpisodeCount, matchedFields }, index) => {
1802
+ const header = [
1803
+ `[${index + 1}] ${box.sealedAt.replace("T", " ").slice(0, 16)}`,
1804
+ box.traceId ? `trace:${box.traceId.slice(0, 12)}` : "trace:none"
1805
+ ].join(" | ");
1806
+ const details = [
1807
+ box.goal ?? `topics: ${box.topics.join(", ")}`,
1808
+ `verified episodes: ${verifiedEpisodeCount}`
1809
+ ];
1810
+ if (box.toolsUsed && box.toolsUsed.length > 0) {
1811
+ details.push(`tools: ${box.toolsUsed.join(", ")}`);
1812
+ }
1813
+ if (matchedFields.length > 0) {
1814
+ details.push(`matched: ${matchedFields.join(", ")}`);
1815
+ }
1816
+ return `${header}
1817
+ ${details.join("\n")}`;
1818
+ }
1819
+ );
1820
+ return `## Verified Episodes
1821
+
1822
+ ${lines.join("\n\n")}`;
1823
+ }
1824
+ formatVerifiedSemanticRuleResults(results) {
1825
+ const lines = results.map(
1826
+ ({
1827
+ rule,
1828
+ sourceMemoryId,
1829
+ verificationStatus,
1830
+ effectiveConfidence,
1831
+ matchedFields
1832
+ }, index) => {
1833
+ const header = [
1834
+ `[${index + 1}] ${rule.frontmatter.updated.replace("T", " ").slice(0, 16)}`,
1835
+ verificationStatus,
1836
+ `confidence:${effectiveConfidence.toFixed(2)}`
1837
+ ].join(" | ");
1838
+ const details = [rule.content, `source memory: ${sourceMemoryId}`];
1839
+ if (matchedFields.length > 0) {
1840
+ details.push(`matched: ${matchedFields.join(", ")}`);
1841
+ }
1842
+ return `${header}
1843
+ ${details.join("\n")}`;
1844
+ }
1845
+ );
1846
+ return `## Verified Rules
1847
+
1848
+ ${lines.join("\n\n")}`;
1849
+ }
1850
+ // ── Identity continuity helpers ─────────────────────────────────────────
1851
+ summarizeIdentityText(raw, maxLines, maxChars) {
1852
+ const lines = raw.replace(/\r/g, "").split("\n").map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
1853
+ const compact = lines.slice(0, Math.max(1, maxLines)).join(" ");
1854
+ if (compact.length <= maxChars) return compact;
1855
+ return `${compact.slice(0, Math.max(0, maxChars - 1))}\u2026`;
1856
+ }
1857
+ formatOpenIncidentLine(incident, includeDetails) {
1858
+ const base = `[${incident.id}] ${incident.symptom.trim()}`;
1859
+ if (!includeDetails) return `- ${base}`;
1860
+ const parts = [base];
1861
+ if (incident.suspectedCause)
1862
+ parts.push(`cause: ${incident.suspectedCause.trim()}`);
1863
+ if (incident.triggerWindow)
1864
+ parts.push(`window: ${incident.triggerWindow.trim()}`);
1865
+ return `- ${parts.join(" | ")}`;
1866
+ }
1867
+ trimIdentitySection(content, maxChars) {
1868
+ if (maxChars <= 0) return { text: "", truncated: false };
1869
+ if (content.length <= maxChars) return { text: content, truncated: false };
1870
+ const suffix = "\n\n...(identity continuity trimmed)";
1871
+ if (maxChars <= suffix.length) {
1872
+ return { text: content.slice(0, maxChars), truncated: true };
1873
+ }
1874
+ const headroom = Math.max(0, maxChars - suffix.length);
1875
+ return { text: `${content.slice(0, headroom)}${suffix}`, truncated: true };
1876
+ }
1877
+ async buildIdentityContinuitySection(options) {
1878
+ if (!resolveIdentityContinuityCapabilities(this.config).identityContinuity) return null;
1879
+ if (this.config.identityMaxInjectChars <= 0) return null;
1880
+ const resolved = resolveEffectiveIdentityInjectionMode({
1881
+ configuredMode: this.config.identityInjectionMode,
1882
+ recallMode: options.recallMode,
1883
+ prompt: options.prompt
1884
+ });
1885
+ if (!resolved.shouldInject) return null;
1886
+ const [anchorRaw, loopsRaw, incidents] = await Promise.all([
1887
+ options.storage.readIdentityAnchor(),
1888
+ options.storage.readIdentityImprovementLoops(),
1889
+ options.storage.readContinuityIncidents(200)
1890
+ ]);
1891
+ const openIncidents = incidents.filter(
1892
+ (incident) => incident.state === "open"
1893
+ );
1894
+ const lines = [];
1895
+ if (resolved.mode === "full") {
1896
+ lines.push("## Identity Continuity");
1897
+ if (anchorRaw && anchorRaw.trim().length > 0) {
1898
+ lines.push("", "### Anchor", "", anchorRaw.trim());
1899
+ }
1900
+ if (loopsRaw && loopsRaw.trim().length > 0) {
1901
+ lines.push("", "### Improvement Loops", "", loopsRaw.trim());
1902
+ }
1903
+ lines.push("", "### Open Incidents", "");
1904
+ if (openIncidents.length === 0) {
1905
+ lines.push("- none");
1906
+ } else {
1907
+ lines.push(
1908
+ ...openIncidents.slice(0, 5).map((incident) => this.formatOpenIncidentLine(incident, true))
1909
+ );
1910
+ }
1911
+ } else {
1912
+ const anchorSummary = anchorRaw ? this.summarizeIdentityText(anchorRaw, 3, 320) : "";
1913
+ const loopsSummary = loopsRaw ? this.summarizeIdentityText(loopsRaw, 2, 240) : "";
1914
+ lines.push("## Identity Continuity Signals", "");
1915
+ if (anchorSummary) lines.push(`- anchor: ${anchorSummary}`);
1916
+ if (loopsSummary) lines.push(`- loops: ${loopsSummary}`);
1917
+ if (openIncidents.length === 0) {
1918
+ lines.push("- incidents: 0 open");
1919
+ } else {
1920
+ lines.push(`- incidents: ${openIncidents.length} open`);
1921
+ lines.push(
1922
+ ...openIncidents.slice(0, 2).map((incident) => this.formatOpenIncidentLine(incident, false))
1923
+ );
1924
+ }
1925
+ }
1926
+ const body = lines.join("\n").trim();
1927
+ if (!body) return null;
1928
+ const { text, truncated } = this.trimIdentitySection(
1929
+ body,
1930
+ this.config.identityMaxInjectChars
1931
+ );
1932
+ if (!text) return null;
1933
+ return {
1934
+ section: text,
1935
+ mode: resolved.mode,
1936
+ injectedChars: text.length,
1937
+ truncated
1938
+ };
1939
+ }
1940
+ };
1941
+
1439
1942
  // src/maintenance/pattern-reinforcement.ts
1440
1943
  function patternReinforcementKey(content) {
1441
1944
  return content.trim().toLowerCase().replace(/\s+/g, " ").slice(0, 200);
@@ -2792,71 +3295,6 @@ var BulkImportBatchPartialFailureError = class extends Error {
2792
3295
  this.originalError = originalError;
2793
3296
  }
2794
3297
  };
2795
- function dedupeEntitySynthesisEvidenceEntries(entries) {
2796
- const dedupedEvidenceEntries = [];
2797
- const evidenceByFact = /* @__PURE__ */ new Map();
2798
- for (const entry of entries) {
2799
- const normalizedFact = entry.text.trim();
2800
- if (!normalizedFact) continue;
2801
- const existing = evidenceByFact.get(normalizedFact);
2802
- if (!existing) {
2803
- evidenceByFact.set(normalizedFact, { newest: entry, oldest: entry });
2804
- continue;
2805
- }
2806
- if (compareEntityTimestamps(entry.timestamp, existing.newest.timestamp) > 0) {
2807
- existing.newest = entry;
2808
- }
2809
- if (compareEntityTimestamps(entry.timestamp, existing.oldest.timestamp) < 0) {
2810
- existing.oldest = entry;
2811
- }
2812
- }
2813
- for (const { newest, oldest } of evidenceByFact.values()) {
2814
- dedupedEvidenceEntries.push(newest);
2815
- const newestKey = [
2816
- newest.timestamp,
2817
- newest.source ?? "",
2818
- newest.sessionKey ?? "",
2819
- newest.principal ?? "",
2820
- newest.text
2821
- ].join("\0");
2822
- const oldestKey = [
2823
- oldest.timestamp,
2824
- oldest.source ?? "",
2825
- oldest.sessionKey ?? "",
2826
- oldest.principal ?? "",
2827
- oldest.text
2828
- ].join("\0");
2829
- if (oldestKey !== newestKey) {
2830
- dedupedEvidenceEntries.push(oldest);
2831
- }
2832
- }
2833
- return dedupedEvidenceEntries;
2834
- }
2835
- function flattenStructuredSectionEvidence(sections) {
2836
- return (sections ?? []).flatMap(
2837
- (section) => section.facts.map((fact) => fact.trim()).filter((fact) => fact.length > 0).map((fact) => ({
2838
- timestamp: "",
2839
- text: fact,
2840
- source: `section:${section.title}`
2841
- }))
2842
- );
2843
- }
2844
- function fingerprintEntitySynthesisEvidence(entity) {
2845
- const fingerprint = createHash("sha256");
2846
- const timelineEntries = entity.timeline.map((entry) => [
2847
- entry.timestamp,
2848
- entry.source ?? "",
2849
- entry.sessionKey ?? "",
2850
- entry.principal ?? "",
2851
- entry.text
2852
- ].join("\0")).sort();
2853
- const timelineEntrySeparator = String.fromCharCode(1);
2854
- const structuredFactsSeparator = String.fromCharCode(2);
2855
- fingerprint.update(timelineEntries.join(timelineEntrySeparator));
2856
- fingerprint.update(structuredFactsSeparator);
2857
- fingerprint.update(fingerprintEntityStructuredFacts(entity) ?? "");
2858
- return fingerprint.digest("hex");
2859
- }
2860
3298
  function mapRecallSourceToXrayServedBy(source) {
2861
3299
  switch (source) {
2862
3300
  case "recent_scan":
@@ -3041,7 +3479,7 @@ function defaultWorkspaceDir() {
3041
3479
  }
3042
3480
  function sanitizeSessionKeyForFilename(sessionKey) {
3043
3481
  const readable = sessionKey.replace(/[^a-zA-Z0-9._-]/g, "_");
3044
- const hash = createHash("sha256").update(sessionKey).digest("hex").slice(0, 12);
3482
+ const hash = createHash2("sha256").update(sessionKey).digest("hex").slice(0, 12);
3045
3483
  return `${readable}-${hash}`;
3046
3484
  }
3047
3485
  function latestSourceValidAtFromTurns(turns) {
@@ -3286,22 +3724,6 @@ async function resolveRecallModeDecisionAsync(options) {
3286
3724
  plannerHeuristicMode: planned.heuristicMode
3287
3725
  };
3288
3726
  }
3289
- function hasIdentityRecoveryIntent(prompt) {
3290
- const text = typeof prompt === "string" ? prompt.toLowerCase() : "";
3291
- if (!text) return false;
3292
- return /\b(identity|continuity|recover(?:y|ing|ed)?|incident|drift|restore|regress(?:ion|ed|ing)?)\b/i.test(
3293
- text
3294
- );
3295
- }
3296
- function resolveEffectiveIdentityInjectionMode(options) {
3297
- if (options.configuredMode === "recovery_only" && !hasIdentityRecoveryIntent(options.prompt)) {
3298
- return { mode: "recovery_only", shouldInject: false };
3299
- }
3300
- if (options.recallMode === "minimal" && options.configuredMode === "full") {
3301
- return { mode: "minimal", shouldInject: true };
3302
- }
3303
- return { mode: options.configuredMode, shouldInject: true };
3304
- }
3305
3727
  function computeArtifactCandidateFetchLimit(targetCount) {
3306
3728
  const cappedTarget = Math.max(0, targetCount);
3307
3729
  if (cappedTarget === 0) return 0;
@@ -3597,6 +4019,7 @@ var Orchestrator = class _Orchestrator {
3597
4019
  compressionGuidelineCoordinator;
3598
4020
  semanticConsolidationCoordinator;
3599
4021
  lifecyclePolicyCoordinator;
4022
+ entitySynthesisCoordinator;
3600
4023
  /**
3601
4024
  * In-memory X-ray snapshot from the most recent `recall()` call that
3602
4025
  * was invoked with `xrayCapture: true` (issue #570 PR 1). Scope is
@@ -3685,6 +4108,11 @@ var Orchestrator = class _Orchestrator {
3685
4108
  * hands it to `enqueue`.
3686
4109
  */
3687
4110
  extractionQueueCoordinator;
4111
+ /**
4112
+ * Issue #1526: recall result formatting + identity continuity section moved
4113
+ * to RecallResultFormatter.
4114
+ */
4115
+ recallResultFormatter;
3688
4116
  heartbeatObserverChains = /* @__PURE__ */ new Map();
3689
4117
  recentExtractionFingerprints = /* @__PURE__ */ new Map();
3690
4118
  consolidationObservers = /* @__PURE__ */ new Set();
@@ -4390,6 +4818,7 @@ var Orchestrator = class _Orchestrator {
4390
4818
  namespaceCatalog: this.namespaceCatalog
4391
4819
  });
4392
4820
  this.extractionQueueCoordinator = new ExtractionQueueCoordinator();
4821
+ this.recallResultFormatter = new RecallResultFormatter(this.config);
4393
4822
  const conversationIndexRuntime = createConversationIndexRuntime(config, {
4394
4823
  getQmd: () => this.conversationQmd,
4395
4824
  getFaiss: () => this.conversationFaiss
@@ -4427,6 +4856,11 @@ var Orchestrator = class _Orchestrator {
4427
4856
  getStorage: () => this.storage,
4428
4857
  fastChatCompletion: (messages, options) => this.fastChatCompletion(messages, options)
4429
4858
  });
4859
+ this.entitySynthesisCoordinator = new EntitySynthesisCoordinator({
4860
+ config,
4861
+ getStorage: (namespace) => this.getStorage(namespace),
4862
+ fastChatCompletion: (messages, options) => this.fastChatCompletion(messages, options)
4863
+ });
4430
4864
  this.sessionObserver = new SessionObserverState({
4431
4865
  memoryDir: config.memoryDir,
4432
4866
  debounceMs: config.sessionObserverDebounceMs ?? 12e4,
@@ -4571,7 +5005,7 @@ var Orchestrator = class _Orchestrator {
4571
5005
  utilityPromoteThresholdDelta: this.utilityRuntimeValues?.promoteThresholdDelta ?? 0,
4572
5006
  utilityDemoteThresholdDelta: this.utilityRuntimeValues?.demoteThresholdDelta ?? 0
4573
5007
  };
4574
- return createHash("sha256").update(JSON.stringify(payload)).digest("hex").slice(0, 12);
5008
+ return createHash2("sha256").update(JSON.stringify(payload)).digest("hex").slice(0, 12);
4575
5009
  }
4576
5010
  effectiveLifecycleThresholds() {
4577
5011
  const archiveDecayThreshold = this.config.lifecycleArchiveDecayThreshold;
@@ -5440,114 +5874,7 @@ ${doc.content}` : doc.content,
5440
5874
  return this.storageRouter.storageFor(ns);
5441
5875
  }
5442
5876
  async processEntitySynthesisQueue(namespace, maxEntities = 5) {
5443
- if (!this.config.entitySummaryEnabled || maxEntities <= 0 || this.config.entitySynthesisMaxTokens <= 0) return 0;
5444
- const storage = await this.getStorage(namespace);
5445
- const queued = await storage.refreshEntitySynthesisQueue();
5446
- let processed = 0;
5447
- let attempted = 0;
5448
- for (const entityName of queued) {
5449
- if (attempted >= maxEntities) break;
5450
- attempted += 1;
5451
- try {
5452
- const raw = await storage.readEntity(entityName);
5453
- if (!raw) continue;
5454
- const entity = parseEntityFile(raw, this.config.entitySchemas);
5455
- const previousSynthesis = entity.synthesis || entity.summary || "";
5456
- const sortedTimelineEntries = entity.timeline.slice().sort((left, right) => compareEntityTimestamps(right.timestamp, left.timestamp));
5457
- const newerTimelineEntries = sortedTimelineEntries.filter(
5458
- (entry) => !entity.synthesisUpdatedAt || compareEntityTimestamps(entry.timestamp, entity.synthesisUpdatedAt) > 0
5459
- );
5460
- const appendedTimelineEntries = entity.synthesisTimelineCount === void 0 ? [] : entity.timeline.slice(Math.max(0, entity.synthesisTimelineCount));
5461
- const structuredEvidenceEntries = flattenStructuredSectionEvidence(entity.structuredSections);
5462
- const structuredEvidenceCount = structuredEvidenceEntries.length;
5463
- const structuredEvidenceDigest = fingerprintEntityStructuredFacts(entity);
5464
- const structuredEvidenceDrifted = structuredEvidenceDigest !== (entity.synthesisStructuredFactDigest?.trim() || void 0);
5465
- const appendedStructuredEvidenceEntries = entity.synthesisStructuredFactCount === void 0 || structuredEvidenceDrifted ? structuredEvidenceEntries : structuredEvidenceEntries.slice(Math.max(0, entity.synthesisStructuredFactCount));
5466
- const candidateEvidenceEntries = [
5467
- ...newerTimelineEntries,
5468
- ...appendedTimelineEntries,
5469
- ...appendedStructuredEvidenceEntries
5470
- ].slice().sort((left, right) => compareEntityTimestamps(right.timestamp, left.timestamp));
5471
- const dedupedEvidenceEntries = dedupeEntitySynthesisEvidenceEntries(
5472
- candidateEvidenceEntries.length > 0 ? candidateEvidenceEntries : [...sortedTimelineEntries, ...structuredEvidenceEntries]
5473
- );
5474
- const chronologicalEvidenceEntries = dedupedEvidenceEntries.slice().sort((left, right) => compareEntityTimestamps(left.timestamp, right.timestamp));
5475
- if (chronologicalEvidenceEntries.length === 0) continue;
5476
- const latestEvidenceTimestamp = chronologicalEvidenceEntries.slice().reverse().map((entry) => entry.timestamp?.trim() || void 0).find((timestamp) => Boolean(timestamp));
5477
- const previousSynthesisUpdatedAt = entity.synthesisUpdatedAt?.trim() || void 0;
5478
- const nextSynthesisUpdatedAt = compareEntityTimestamps(
5479
- latestEvidenceTimestamp,
5480
- previousSynthesisUpdatedAt
5481
- ) >= 0 ? latestEvidenceTimestamp : previousSynthesisUpdatedAt;
5482
- const evidenceBatches = [];
5483
- for (let index = 0; index < chronologicalEvidenceEntries.length; index += 8) {
5484
- evidenceBatches.push(chronologicalEvidenceEntries.slice(index, index + 8));
5485
- }
5486
- let nextSynthesis = previousSynthesis;
5487
- let batchFailed = false;
5488
- for (const evidenceEntries of evidenceBatches) {
5489
- const evidenceText = evidenceEntries.map((entry) => {
5490
- const sectionTitle = entry.source?.startsWith("section:") ? entry.source.slice("section:".length) : "";
5491
- const metadata = [
5492
- `timestamp=${entry.timestamp}`,
5493
- sectionTitle ? `section=${sectionTitle}` : entry.source ? `source=${entry.source}` : "",
5494
- entry.sessionKey ? `session=${entry.sessionKey}` : "",
5495
- entry.principal ? `principal=${entry.principal}` : ""
5496
- ].filter(Boolean).join(", ");
5497
- return `- ${metadata}: ${entry.text}`;
5498
- }).join("\n");
5499
- const response = await this.fastChatCompletion(
5500
- [
5501
- {
5502
- role: "system",
5503
- content: "Rewrite the entity synthesis as compact current truth. Preserve uncertainty when evidence conflicts. Return plain text only."
5504
- },
5505
- {
5506
- role: "user",
5507
- content: [
5508
- `Entity: ${entity.name} (${entity.type})`,
5509
- nextSynthesis ? `Previous synthesis:
5510
- ${nextSynthesis}` : "Previous synthesis: none",
5511
- `New evidence:
5512
- ${evidenceText}`
5513
- ].join("\n\n")
5514
- }
5515
- ],
5516
- {
5517
- temperature: 0.2,
5518
- maxTokens: this.config.entitySynthesisMaxTokens,
5519
- operation: "entity_summary",
5520
- priority: "background"
5521
- }
5522
- );
5523
- const synthesis = response?.content?.trim().replace(/^["']|["']$/g, "");
5524
- const maxSynthesisChars = Math.max(2e3, this.config.entitySynthesisMaxTokens * 8);
5525
- if (!synthesis || synthesis.length < 10 || synthesis.length > maxSynthesisChars) {
5526
- batchFailed = true;
5527
- break;
5528
- }
5529
- nextSynthesis = synthesis;
5530
- }
5531
- if (batchFailed || nextSynthesis.length === 0) continue;
5532
- const latestRaw = await storage.readEntity(entityName);
5533
- if (!latestRaw) continue;
5534
- const latestEntity = parseEntityFile(latestRaw, this.config.entitySchemas);
5535
- if (fingerprintEntitySynthesisEvidence(latestEntity) !== fingerprintEntitySynthesisEvidence(entity)) {
5536
- continue;
5537
- }
5538
- await storage.updateEntitySynthesis(entityName, nextSynthesis, {
5539
- entityUpdatedAt: (/* @__PURE__ */ new Date()).toISOString(),
5540
- synthesisStructuredFactDigest: structuredEvidenceDigest,
5541
- synthesisStructuredFactCount: structuredEvidenceCount,
5542
- synthesisTimelineCount: entity.timeline.length,
5543
- updatedAt: nextSynthesisUpdatedAt
5544
- });
5545
- processed += 1;
5546
- } catch (err) {
5547
- log.debug(`entity synthesis refresh failed for ${entityName}: ${err}`);
5548
- }
5549
- }
5550
- return processed;
5877
+ return this.entitySynthesisCoordinator.processQueue(namespace, maxEntities);
5551
5878
  }
5552
5879
  async generateDaySummary(memories) {
5553
5880
  if (this.initPromise) {
@@ -6716,7 +7043,7 @@ ${r.snippet.trim()}
6716
7043
  if (!options.onDebugSnapshot) return;
6717
7044
  await options.onDebugSnapshot({
6718
7045
  recordedAt: (/* @__PURE__ */ new Date()).toISOString(),
6719
- queryHash: createHash("sha256").update(prompt).digest("hex"),
7046
+ queryHash: createHash2("sha256").update(prompt).digest("hex"),
6720
7047
  queryLength: prompt.length,
6721
7048
  collection: options.collection,
6722
7049
  namespaces: options.recallNamespaces,
@@ -7045,7 +7372,7 @@ ${r.snippet.trim()}
7045
7372
  const payload = {
7046
7373
  recordedAt: now,
7047
7374
  mode: options.recallMode,
7048
- queryHash: createHash("sha256").update(options.prompt).digest("hex"),
7375
+ queryHash: createHash2("sha256").update(options.prompt).digest("hex"),
7049
7376
  queryLength: options.prompt.length,
7050
7377
  namespaces: options.recallNamespaces,
7051
7378
  seedCount: totalSeedCount,
@@ -7387,8 +7714,8 @@ ${r.snippet.trim()}
7387
7714
  timings,
7388
7715
  logger: log
7389
7716
  });
7390
- const promptHash = createHash("sha256").update(prompt).digest("hex");
7391
- const traceId = createHash("sha256").update(`${sessionKey ?? "default"}:${recallStart}:${promptHash}`).digest("hex").slice(0, 16);
7717
+ const promptHash = createHash2("sha256").update(prompt).digest("hex");
7718
+ const traceId = createHash2("sha256").update(`${sessionKey ?? "default"}:${recallStart}:${promptHash}`).digest("hex").slice(0, 16);
7392
7719
  const sectionBuckets = /* @__PURE__ */ new Map();
7393
7720
  const queryPolicy = buildRecallQueryPolicy(prompt, sessionKey, {
7394
7721
  cronRecallPolicyEnabled: this.config.cronRecallPolicyEnabled,
@@ -7397,7 +7724,7 @@ ${r.snippet.trim()}
7397
7724
  cronConversationRecallMode: this.config.cronConversationRecallMode
7398
7725
  });
7399
7726
  const retrievalQuery = queryPolicy.retrievalQuery || prompt;
7400
- const retrievalQueryHash = createHash("sha256").update(retrievalQuery).digest("hex");
7727
+ const retrievalQueryHash = createHash2("sha256").update(retrievalQuery).digest("hex");
7401
7728
  const policyVersion = this.currentPolicyVersion();
7402
7729
  let impressionRecorded = false;
7403
7730
  let recallSource = "none";
@@ -11437,7 +11764,7 @@ _Context: ${topQuestion.context}_`
11437
11764
  const shouldUseStableBatchKey = turns.some(
11438
11765
  (turn) => turn.persistProcessedFingerprint === true || typeof turn.turnFingerprint === "string" && turn.turnFingerprint.length > 0
11439
11766
  );
11440
- const stableBatchFingerprint = shouldUseStableBatchKey ? createHash("sha256").update(
11767
+ const stableBatchFingerprint = shouldUseStableBatchKey ? createHash2("sha256").update(
11441
11768
  turns.map(
11442
11769
  (turn) => [
11443
11770
  turn.role,
@@ -11687,7 +12014,7 @@ _Context: ${topQuestion.context}_`
11687
12014
  buildExtractionFingerprint(turns, bufferKey) {
11688
12015
  const normalized = this.normalizeExtractionFingerprintTurns(turns).join("\n");
11689
12016
  if (!normalized) return null;
11690
- return createHash("sha256").update(`${bufferKey}
12017
+ return createHash2("sha256").update(`${bufferKey}
11691
12018
  ${normalized}`).digest("hex");
11692
12019
  }
11693
12020
  shouldQueueExtraction(turns, options = {}) {
@@ -14337,306 +14664,58 @@ ${reflectionsContent.trim()}
14337
14664
  const patternsSection = [
14338
14665
  "## Learned Patterns (consolidated from reflections, " + (/* @__PURE__ */ new Date()).toISOString().slice(0, 10) + ")",
14339
14666
  "",
14340
- ...result.learnedPatterns.map((p) => `- ${p}`),
14341
- ""
14342
- ].join("\n");
14343
- const newContent = staticHeader + "\n\n" + patternsSection + "\n";
14344
- await storage.writeIdentity(
14345
- this.config.workspaceDir,
14346
- newContent,
14347
- identityNamespace
14348
- );
14349
- await storage.writeIdentityReflections("");
14350
- log.info(
14351
- `IDENTITY(${namespace}) consolidated: ${identityContent.length} \u2192 ${newContent.length} chars, ${result.learnedPatterns.length} patterns`
14352
- );
14353
- }
14354
- }
14355
- formatQmdResults(title, results, sessionKey, trustByPath) {
14356
- const handleByIndex = buildHandleIndexForResults(
14357
- results,
14358
- this.config.recallMemoryHandles === true && sessionKey != null
14359
- );
14360
- const renderHedge = this.config.trustScoreEpistemicRendering && trustByPath !== null && trustByPath !== void 0;
14361
- const hedgeMap = renderHedge ? trustByPath : null;
14362
- const lines = results.map((r, i) => {
14363
- const snippet = r.snippet ? r.snippet.slice(0, 500).replace(/\n/g, " ") : "(no preview)";
14364
- const source = typeof r.line === "number" ? `${r.path}:${r.line}` : r.path;
14365
- const head = `[${i + 1}] ${source} (score: ${r.score.toFixed(3)})
14366
- ${snippet}`;
14367
- const handle = handleByIndex.get(i);
14368
- const hedged = head.replace(/\s+$/, "");
14369
- const withHandle = handle ? `${hedged} ${handle}` : hedged;
14370
- if (hedgeMap) {
14371
- const item = hedgeMap.get(r.path);
14372
- if (item) {
14373
- const hedge = renderEpistemicHedge(item.trust);
14374
- if (hedge.length > 0) return `${withHandle} ${hedge}`;
14375
- }
14376
- }
14377
- return withHandle;
14378
- });
14379
- return `## ${title}
14380
-
14381
- ${lines.join("\n\n")}`;
14667
+ ...result.learnedPatterns.map((p) => `- ${p}`),
14668
+ ""
14669
+ ].join("\n");
14670
+ const newContent = staticHeader + "\n\n" + patternsSection + "\n";
14671
+ await storage.writeIdentity(
14672
+ this.config.workspaceDir,
14673
+ newContent,
14674
+ identityNamespace
14675
+ );
14676
+ await storage.writeIdentityReflections("");
14677
+ log.info(
14678
+ `IDENTITY(${namespace}) consolidated: ${identityContent.length} \u2192 ${newContent.length} chars, ${result.learnedPatterns.length} patterns`
14679
+ );
14680
+ }
14681
+ }
14682
+ // Issue #1526: recall result formatting moved to RecallResultFormatter. Thin
14683
+ // delegation keeps the private API stable for callers + tests.
14684
+ formatQmdResults(title, results, sessionKey, trustByPath) {
14685
+ return this.recallResultFormatter.formatQmdResults(title, results, sessionKey, trustByPath);
14382
14686
  }
14383
14687
  formatObjectiveStateResults(results) {
14384
- const lines = results.map(({ snapshot }, index) => {
14385
- const parts = [
14386
- snapshot.recordedAt.replace("T", " ").slice(0, 16),
14387
- `${snapshot.kind}/${snapshot.changeKind}`
14388
- ];
14389
- if (snapshot.outcome) parts.push(snapshot.outcome);
14390
- const header = `[${index + 1}] ${parts.join(" | ")} | ${snapshot.scope}`;
14391
- const detailParts = [snapshot.summary];
14392
- if (snapshot.command) detailParts.push(`command: ${snapshot.command}`);
14393
- else if (snapshot.toolName)
14394
- detailParts.push(`tool: ${snapshot.toolName}`);
14395
- return `${header}
14396
- ${detailParts.join(" | ")}`;
14397
- });
14398
- return `## Objective State
14399
-
14400
- ${lines.join("\n\n")}`;
14688
+ return this.recallResultFormatter.formatObjectiveStateResults(results);
14401
14689
  }
14402
14690
  formatCausalTrajectoryResults(results) {
14403
- const lines = results.map(({ record, matchedFields }, index) => {
14404
- const header = [
14405
- `[${index + 1}] ${record.recordedAt.replace("T", " ").slice(0, 16)}`,
14406
- record.outcomeKind
14407
- ].join(" | ");
14408
- const details = [
14409
- `goal: ${record.goal}`,
14410
- `action: ${record.actionSummary}`,
14411
- `observation: ${record.observationSummary}`,
14412
- `outcome: ${record.outcomeSummary}`
14413
- ];
14414
- if (record.followUpSummary)
14415
- details.push(`follow-up: ${record.followUpSummary}`);
14416
- if (matchedFields.length > 0)
14417
- details.push(`matched: ${matchedFields.join(", ")}`);
14418
- return `${header}
14419
- ${details.join("\n")}`;
14420
- });
14421
- return `## Causal Trajectories
14422
-
14423
- ${lines.join("\n\n")}`;
14691
+ return this.recallResultFormatter.formatCausalTrajectoryResults(results);
14424
14692
  }
14425
14693
  formatTrustZoneResults(results) {
14426
- const lines = results.map(({ record, matchedFields }, index) => {
14427
- const header = [
14428
- `[${index + 1}] ${record.recordedAt.replace("T", " ").slice(0, 16)}`,
14429
- record.zone,
14430
- record.kind
14431
- ].join(" | ");
14432
- const details = [
14433
- record.summary,
14434
- `provenance: ${record.provenance.sourceClass}`
14435
- ];
14436
- if (record.entityRefs && record.entityRefs.length > 0) {
14437
- details.push(`entities: ${record.entityRefs.join(", ")}`);
14438
- }
14439
- if (record.tags && record.tags.length > 0) {
14440
- details.push(`tags: ${record.tags.join(", ")}`);
14441
- }
14442
- if (matchedFields.length > 0) {
14443
- details.push(`matched: ${matchedFields.join(", ")}`);
14444
- }
14445
- return `${header}
14446
- ${details.join("\n")}`;
14447
- });
14448
- return `## Trust Zones
14449
-
14450
- ${lines.join("\n\n")}`;
14694
+ return this.recallResultFormatter.formatTrustZoneResults(results);
14451
14695
  }
14452
14696
  formatHarmonicRetrievalResults(results) {
14453
- const lines = results.map(
14454
- ({ node, matchedAnchors, matchedFields, nodeScore, anchorScore }, index) => {
14455
- const header = [
14456
- `[${index + 1}] ${node.recordedAt.replace("T", " ").slice(0, 16)}`,
14457
- `${node.kind}/${node.abstractionLevel}`,
14458
- node.sessionKey
14459
- ].join(" | ");
14460
- const details = [
14461
- node.title,
14462
- node.summary,
14463
- `scores: node=${nodeScore.toFixed(1)} anchor=${anchorScore.toFixed(1)}`
14464
- ];
14465
- if (matchedAnchors.length > 0) {
14466
- details.push(
14467
- `anchors: ${matchedAnchors.map((anchor) => `${anchor.anchorType}:${anchor.anchorValue}`).join("; ")}`
14468
- );
14469
- }
14470
- if (matchedFields.length > 0) {
14471
- details.push(`matched: ${matchedFields.join(", ")}`);
14472
- }
14473
- return `${header}
14474
- ${details.join("\n")}`;
14475
- }
14476
- );
14477
- return `## Harmonic Retrieval
14478
-
14479
- ${lines.join("\n\n")}`;
14697
+ return this.recallResultFormatter.formatHarmonicRetrievalResults(results);
14480
14698
  }
14481
14699
  formatWorkProductResults(results) {
14482
- const lines = results.map(({ entry, matchedFields }, index) => {
14483
- const header = [
14484
- `[${index + 1}] ${entry.recordedAt.replace("T", " ").slice(0, 16)}`,
14485
- `${entry.kind}/${entry.action}`,
14486
- entry.sessionKey
14487
- ].join(" | ");
14488
- const details = [entry.summary, `scope: ${entry.scope}`];
14489
- if (entry.artifactPath) details.push(`artifact: ${entry.artifactPath}`);
14490
- if (entry.tags && entry.tags.length > 0)
14491
- details.push(`tags: ${entry.tags.join(", ")}`);
14492
- if (matchedFields.length > 0)
14493
- details.push(`matched: ${matchedFields.join(", ")}`);
14494
- return `${header}
14495
- ${details.join("\n")}`;
14496
- });
14497
- return `## Work Products
14498
-
14499
- ${lines.join("\n\n")}`;
14700
+ return this.recallResultFormatter.formatWorkProductResults(results);
14500
14701
  }
14501
14702
  formatVerifiedEpisodeResults(results) {
14502
- const lines = results.map(
14503
- ({ box, verifiedEpisodeCount, matchedFields }, index) => {
14504
- const header = [
14505
- `[${index + 1}] ${box.sealedAt.replace("T", " ").slice(0, 16)}`,
14506
- box.traceId ? `trace:${box.traceId.slice(0, 12)}` : "trace:none"
14507
- ].join(" | ");
14508
- const details = [
14509
- box.goal ?? `topics: ${box.topics.join(", ")}`,
14510
- `verified episodes: ${verifiedEpisodeCount}`
14511
- ];
14512
- if (box.toolsUsed && box.toolsUsed.length > 0) {
14513
- details.push(`tools: ${box.toolsUsed.join(", ")}`);
14514
- }
14515
- if (matchedFields.length > 0) {
14516
- details.push(`matched: ${matchedFields.join(", ")}`);
14517
- }
14518
- return `${header}
14519
- ${details.join("\n")}`;
14520
- }
14521
- );
14522
- return `## Verified Episodes
14523
-
14524
- ${lines.join("\n\n")}`;
14703
+ return this.recallResultFormatter.formatVerifiedEpisodeResults(results);
14525
14704
  }
14526
14705
  formatVerifiedSemanticRuleResults(results) {
14527
- const lines = results.map(
14528
- ({
14529
- rule,
14530
- sourceMemoryId,
14531
- verificationStatus,
14532
- effectiveConfidence,
14533
- matchedFields
14534
- }, index) => {
14535
- const header = [
14536
- `[${index + 1}] ${rule.frontmatter.updated.replace("T", " ").slice(0, 16)}`,
14537
- verificationStatus,
14538
- `confidence:${effectiveConfidence.toFixed(2)}`
14539
- ].join(" | ");
14540
- const details = [rule.content, `source memory: ${sourceMemoryId}`];
14541
- if (matchedFields.length > 0) {
14542
- details.push(`matched: ${matchedFields.join(", ")}`);
14543
- }
14544
- return `${header}
14545
- ${details.join("\n")}`;
14546
- }
14547
- );
14548
- return `## Verified Rules
14549
-
14550
- ${lines.join("\n\n")}`;
14706
+ return this.recallResultFormatter.formatVerifiedSemanticRuleResults(results);
14551
14707
  }
14552
14708
  summarizeIdentityText(raw, maxLines, maxChars) {
14553
- const lines = raw.replace(/\r/g, "").split("\n").map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
14554
- const compact = lines.slice(0, Math.max(1, maxLines)).join(" ");
14555
- if (compact.length <= maxChars) return compact;
14556
- return `${compact.slice(0, Math.max(0, maxChars - 1))}\u2026`;
14709
+ return this.recallResultFormatter.summarizeIdentityText(raw, maxLines, maxChars);
14557
14710
  }
14558
14711
  formatOpenIncidentLine(incident, includeDetails) {
14559
- const base = `[${incident.id}] ${incident.symptom.trim()}`;
14560
- if (!includeDetails) return `- ${base}`;
14561
- const parts = [base];
14562
- if (incident.suspectedCause)
14563
- parts.push(`cause: ${incident.suspectedCause.trim()}`);
14564
- if (incident.triggerWindow)
14565
- parts.push(`window: ${incident.triggerWindow.trim()}`);
14566
- return `- ${parts.join(" | ")}`;
14712
+ return this.recallResultFormatter.formatOpenIncidentLine(incident, includeDetails);
14567
14713
  }
14568
14714
  trimIdentitySection(content, maxChars) {
14569
- if (maxChars <= 0) return { text: "", truncated: false };
14570
- if (content.length <= maxChars) return { text: content, truncated: false };
14571
- const suffix = "\n\n...(identity continuity trimmed)";
14572
- if (maxChars <= suffix.length) {
14573
- return { text: content.slice(0, maxChars), truncated: true };
14574
- }
14575
- const headroom = Math.max(0, maxChars - suffix.length);
14576
- return { text: `${content.slice(0, headroom)}${suffix}`, truncated: true };
14715
+ return this.recallResultFormatter.trimIdentitySection(content, maxChars);
14577
14716
  }
14578
14717
  async buildIdentityContinuitySection(options) {
14579
- if (!resolveIdentityContinuityCapabilities(this.config).identityContinuity) return null;
14580
- if (this.config.identityMaxInjectChars <= 0) return null;
14581
- const resolved = resolveEffectiveIdentityInjectionMode({
14582
- configuredMode: this.config.identityInjectionMode,
14583
- recallMode: options.recallMode,
14584
- prompt: options.prompt
14585
- });
14586
- if (!resolved.shouldInject) return null;
14587
- const [anchorRaw, loopsRaw, incidents] = await Promise.all([
14588
- options.storage.readIdentityAnchor(),
14589
- options.storage.readIdentityImprovementLoops(),
14590
- options.storage.readContinuityIncidents(200)
14591
- ]);
14592
- const openIncidents = incidents.filter(
14593
- (incident) => incident.state === "open"
14594
- );
14595
- const lines = [];
14596
- if (resolved.mode === "full") {
14597
- lines.push("## Identity Continuity");
14598
- if (anchorRaw && anchorRaw.trim().length > 0) {
14599
- lines.push("", "### Anchor", "", anchorRaw.trim());
14600
- }
14601
- if (loopsRaw && loopsRaw.trim().length > 0) {
14602
- lines.push("", "### Improvement Loops", "", loopsRaw.trim());
14603
- }
14604
- lines.push("", "### Open Incidents", "");
14605
- if (openIncidents.length === 0) {
14606
- lines.push("- none");
14607
- } else {
14608
- lines.push(
14609
- ...openIncidents.slice(0, 5).map((incident) => this.formatOpenIncidentLine(incident, true))
14610
- );
14611
- }
14612
- } else {
14613
- const anchorSummary = anchorRaw ? this.summarizeIdentityText(anchorRaw, 3, 320) : "";
14614
- const loopsSummary = loopsRaw ? this.summarizeIdentityText(loopsRaw, 2, 240) : "";
14615
- lines.push("## Identity Continuity Signals", "");
14616
- if (anchorSummary) lines.push(`- anchor: ${anchorSummary}`);
14617
- if (loopsSummary) lines.push(`- loops: ${loopsSummary}`);
14618
- if (openIncidents.length === 0) {
14619
- lines.push("- incidents: 0 open");
14620
- } else {
14621
- lines.push(`- incidents: ${openIncidents.length} open`);
14622
- lines.push(
14623
- ...openIncidents.slice(0, 2).map((incident) => this.formatOpenIncidentLine(incident, false))
14624
- );
14625
- }
14626
- }
14627
- const body = lines.join("\n").trim();
14628
- if (!body) return null;
14629
- const { text, truncated } = this.trimIdentitySection(
14630
- body,
14631
- this.config.identityMaxInjectChars
14632
- );
14633
- if (!text) return null;
14634
- return {
14635
- section: text,
14636
- mode: resolved.mode,
14637
- injectedChars: text.length,
14638
- truncated
14639
- };
14718
+ return this.recallResultFormatter.buildIdentityContinuitySection(options);
14640
14719
  }
14641
14720
  emitTrace(event) {
14642
14721
  try {
@@ -16315,6 +16394,8 @@ ${lines.join("\n\n")}`;
16315
16394
 
16316
16395
  export {
16317
16396
  buildProcedureRecallSection,
16397
+ hasIdentityRecoveryIntent,
16398
+ resolveEffectiveIdentityInjectionMode,
16318
16399
  decideSemanticDedup,
16319
16400
  DEFAULT_TAXONOMY,
16320
16401
  generateResolverDocument,
@@ -16332,7 +16413,6 @@ export {
16332
16413
  WearablesService,
16333
16414
  locateTranscriptPath,
16334
16415
  BulkImportBatchPartialFailureError,
16335
- dedupeEntitySynthesisEvidenceEntries,
16336
16416
  defaultWorkspaceDir,
16337
16417
  sanitizeSessionKeyForFilename,
16338
16418
  isArtifactMemoryPath,
@@ -16345,8 +16425,6 @@ export {
16345
16425
  resolveEffectiveRecallMode,
16346
16426
  resolveRecallModeDecision,
16347
16427
  resolveRecallModeDecisionAsync,
16348
- hasIdentityRecoveryIntent,
16349
- resolveEffectiveIdentityInjectionMode,
16350
16428
  computeArtifactCandidateFetchLimit,
16351
16429
  computeQmdHybridFetchLimit,
16352
16430
  mergeGraphExpandedResults,
@@ -16360,4 +16438,4 @@ export {
16360
16438
  resolvePersistedMemoryRelativePath,
16361
16439
  Orchestrator
16362
16440
  };
16363
- //# sourceMappingURL=chunk-FLCYY5JX.js.map
16441
+ //# sourceMappingURL=chunk-PB5YON2G.js.map