@remnic/core 9.3.742 → 9.3.743

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 (261) hide show
  1. package/dist/access-boundary.d.ts +5 -5
  2. package/dist/access-boundary.js +10 -10
  3. package/dist/access-cli.js +29 -29
  4. package/dist/access-http.d.ts +5 -5
  5. package/dist/access-http.js +15 -15
  6. package/dist/access-mcp.d.ts +5 -5
  7. package/dist/access-mcp.js +14 -14
  8. package/dist/access-operations-batch.js +12 -12
  9. package/dist/access-operations.d.ts +5 -5
  10. package/dist/access-operations.js +13 -13
  11. package/dist/{access-service-K8n12dXu.d.ts → access-service-BeW5GOg1.d.ts} +3 -3
  12. package/dist/access-service.d.ts +5 -5
  13. package/dist/access-service.js +9 -9
  14. package/dist/access-surface-catalog.d.ts +5 -5
  15. package/dist/action-confidence.d.ts +1 -1
  16. package/dist/active-memory-bridge.d.ts +1 -1
  17. package/dist/active-memory-bridge.js +3 -3
  18. package/dist/active-recall.d.ts +1 -1
  19. package/dist/behavior-learner.d.ts +1 -1
  20. package/dist/behavior-signals.d.ts +1 -1
  21. package/dist/bootstrap.d.ts +4 -4
  22. package/dist/briefing.d.ts +1 -1
  23. package/dist/buffer-surprise-report.d.ts +1 -1
  24. package/dist/buffer.d.ts +1 -1
  25. package/dist/buffer.js +2 -2
  26. package/dist/calibration.d.ts +1 -1
  27. package/dist/capabilities.d.ts +10 -5
  28. package/dist/capabilities.js +1 -1
  29. package/dist/{catalog-_Bap6vfD.d.ts → catalog-CX0CjOaf.d.ts} +1 -1
  30. package/dist/causal-behavior.d.ts +1 -1
  31. package/dist/causal-consolidation.d.ts +1 -1
  32. package/dist/causal-consolidation.js +2 -2
  33. package/dist/causal-trajectory-graph.d.ts +1 -1
  34. package/dist/{chunk-X5PMDVY4.js → chunk-3EA5LIFJ.js} +4 -4
  35. package/dist/{chunk-YNHRWFAP.js → chunk-4DLFJJOQ.js} +2 -2
  36. package/dist/{chunk-WIMKOTNY.js → chunk-5QANTTY2.js} +2 -2
  37. package/dist/{chunk-AM7YKD7V.js → chunk-5UNSGRCR.js} +5 -5
  38. package/dist/{chunk-Y6PNYJVO.js → chunk-A2KKLCOS.js} +2 -2
  39. package/dist/{chunk-O4IWVWSW.js → chunk-AVBT5WEW.js} +3 -3
  40. package/dist/{chunk-QUNH5UZH.js → chunk-BYLC4DKI.js} +2 -2
  41. package/dist/{chunk-UOVDO6TC.js → chunk-CHELXDTO.js} +3 -3
  42. package/dist/{chunk-TQQN64J2.js → chunk-DBSMLRTO.js} +2 -2
  43. package/dist/{chunk-EZZUNKMJ.js → chunk-DYK27X7V.js} +3 -3
  44. package/dist/{chunk-K2N6WIZM.js → chunk-E7RGJQWP.js} +2 -2
  45. package/dist/{chunk-M4WI23X3.js → chunk-EEKDRAWX.js} +2 -2
  46. package/dist/{chunk-GFJ5ABKS.js → chunk-G5FP7VSQ.js} +11 -11
  47. package/dist/{chunk-BE6NEQLF.js → chunk-HAZVVOYT.js} +3 -3
  48. package/dist/{chunk-OT5K26NG.js → chunk-HM6UJPPO.js} +2 -2
  49. package/dist/{chunk-PI4JHLDD.js → chunk-IP5SANO2.js} +2 -2
  50. package/dist/{chunk-WHEF76BQ.js → chunk-JRZV3767.js} +2 -2
  51. package/dist/{chunk-OS5RKJOH.js → chunk-JZ7P26GF.js} +2 -2
  52. package/dist/{chunk-Y62QPRKV.js → chunk-K5LLP4CY.js} +2 -2
  53. package/dist/{chunk-C3Z5YJSM.js → chunk-LOPZ2DWR.js} +2 -2
  54. package/dist/{chunk-BJPL5WAL.js → chunk-MXDG6SRH.js} +3 -3
  55. package/dist/{chunk-UYYSOMS2.js → chunk-NBP3YHHS.js} +4 -4
  56. package/dist/{chunk-USHVHI6J.js → chunk-NNL4LJAD.js} +3 -3
  57. package/dist/{chunk-GPX5E36D.js → chunk-OSMBC3JU.js} +2 -2
  58. package/dist/{chunk-OUSOMUFV.js → chunk-PE6XR4GG.js} +2 -2
  59. package/dist/{chunk-CMPXLMC3.js → chunk-PI23H7FV.js} +3 -3
  60. package/dist/{chunk-WGDE2TJP.js → chunk-QOGXUNWL.js} +4 -4
  61. package/dist/{chunk-ELL5VYXC.js → chunk-RNWWAS5V.js} +3 -3
  62. package/dist/{chunk-JMMSVRF4.js → chunk-TQPSOTC7.js} +7 -7
  63. package/dist/{chunk-AX4TRSRE.js → chunk-U5WVRMCA.js} +2 -2
  64. package/dist/{chunk-7ADHJ6SU.js → chunk-VE54E6RP.js} +4 -4
  65. package/dist/{chunk-7HUGLMSW.js → chunk-VO4VARZL.js} +465 -321
  66. package/dist/chunk-VO4VARZL.js.map +1 -0
  67. package/dist/{chunk-G7Q4D2G3.js → chunk-VSF7AAGE.js} +1 -3
  68. package/dist/chunk-VSF7AAGE.js.map +1 -0
  69. package/dist/{chunk-OVYBENIJ.js → chunk-W3M34XT4.js} +3 -3
  70. package/dist/{chunk-NHJYUIII.js → chunk-WPLRJ4XM.js} +7 -7
  71. package/dist/{chunk-UEIF7RWQ.js → chunk-XEADGIAA.js} +6 -6
  72. package/dist/{cli-BEOLy1xo.d.ts → cli-BYad9YYY.d.ts} +3 -3
  73. package/dist/cli.d.ts +6 -6
  74. package/dist/cli.js +21 -21
  75. package/dist/compounding/engine.d.ts +1 -1
  76. package/dist/compounding/engine.js +3 -3
  77. package/dist/compounding/preference-consolidator.d.ts +1 -1
  78. package/dist/compression-optimizer.d.ts +1 -1
  79. package/dist/config.d.ts +1 -1
  80. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  81. package/dist/connectors/codex-materialize.d.ts +1 -1
  82. package/dist/connectors/index.d.ts +1 -1
  83. package/dist/connectors/index.js +2 -2
  84. package/dist/consolidation-provenance-check.d.ts +1 -1
  85. package/dist/consolidation-undo.d.ts +1 -1
  86. package/dist/contradiction/index.d.ts +1 -1
  87. package/dist/contradiction/index.js +2 -2
  88. package/dist/{contradiction-scan-UERKJESC.js → contradiction-scan-3FJYWS3G.js} +3 -3
  89. package/dist/conversation-index/backend.d.ts +1 -1
  90. package/dist/conversation-index/chunker.d.ts +1 -1
  91. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  92. package/dist/conversation-index/indexer.d.ts +1 -1
  93. package/dist/conversation-index/search.d.ts +1 -1
  94. package/dist/day-summary.d.ts +1 -1
  95. package/dist/day-summary.js +2 -2
  96. package/dist/delinearize.d.ts +1 -1
  97. package/dist/direct-answer-wiring.d.ts +1 -1
  98. package/dist/direct-answer.d.ts +1 -1
  99. package/dist/embedding-fallback.d.ts +1 -1
  100. package/dist/embedding-fallback.js +2 -2
  101. package/dist/enrichment/index.d.ts +1 -1
  102. package/dist/entity-retrieval.d.ts +1 -1
  103. package/dist/entity-retrieval.js +2 -2
  104. package/dist/entity-schema.d.ts +1 -1
  105. package/dist/explicit-capture.d.ts +4 -4
  106. package/dist/explicit-capture.js +2 -2
  107. package/dist/extraction-faithfulness.d.ts +1 -1
  108. package/dist/extraction-judge-telemetry.d.ts +1 -1
  109. package/dist/extraction-judge-training.d.ts +1 -1
  110. package/dist/extraction-judge.d.ts +1 -1
  111. package/dist/extraction.d.ts +1 -1
  112. package/dist/extraction.js +4 -4
  113. package/dist/fallback-llm.d.ts +1 -1
  114. package/dist/{first-start-migration-GQ3UQNIL.js → first-start-migration-4I3VDSYS.js} +2 -2
  115. package/dist/graph-dashboard-diff.d.ts +1 -1
  116. package/dist/graph-dashboard-key.d.ts +1 -1
  117. package/dist/graph-dashboard-parser.d.ts +1 -1
  118. package/dist/graph-edge-reinforcement.d.ts +1 -1
  119. package/dist/graph-snapshot.d.ts +1 -1
  120. package/dist/graph.d.ts +1 -1
  121. package/dist/identity-continuity.d.ts +1 -1
  122. package/dist/importance.d.ts +1 -1
  123. package/dist/index.d.ts +9 -9
  124. package/dist/index.js +36 -36
  125. package/dist/intent.d.ts +1 -1
  126. package/dist/lcm/engine.d.ts +1 -1
  127. package/dist/lcm/index.d.ts +1 -1
  128. package/dist/lcm/tools.d.ts +1 -1
  129. package/dist/lifecycle.d.ts +1 -1
  130. package/dist/live-connectors-runner.d.ts +1 -1
  131. package/dist/local-llm.d.ts +1 -1
  132. package/dist/local-llm.js +2 -2
  133. package/dist/local-model-endpoint.d.ts +1 -1
  134. package/dist/maintenance/memory-governance.d.ts +1 -1
  135. package/dist/mcp-memory-inspector-app.d.ts +5 -5
  136. package/dist/memory-action-policy.d.ts +1 -1
  137. package/dist/memory-cache.d.ts +1 -1
  138. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  139. package/dist/memory-projection-store.d.ts +1 -1
  140. package/dist/memory-provenance.d.ts +1 -1
  141. package/dist/memory-worth-outcomes.d.ts +1 -1
  142. package/dist/models-json.d.ts +1 -1
  143. package/dist/namespaces/migrate.d.ts +2 -2
  144. package/dist/namespaces/migrate.js +6 -6
  145. package/dist/namespaces/principal.d.ts +1 -1
  146. package/dist/namespaces/principal.js +2 -2
  147. package/dist/namespaces/search.d.ts +1 -1
  148. package/dist/namespaces/search.js +4 -4
  149. package/dist/namespaces/storage.d.ts +2 -2
  150. package/dist/namespaces/storage.js +2 -2
  151. package/dist/native-knowledge.d.ts +1 -1
  152. package/dist/operator-toolkit.d.ts +1 -1
  153. package/dist/operator-toolkit.js +11 -11
  154. package/dist/orchestration/compression-guideline-coordinator.d.ts +1 -1
  155. package/dist/orchestration/compression-guideline-coordinator.js +2 -2
  156. package/dist/orchestration/maintenance.d.ts +2 -2
  157. package/dist/orchestration/maintenance.js +6 -6
  158. package/dist/{orchestrator-Dr-1v5EL.d.ts → orchestrator-CupigmWu.d.ts} +163 -7
  159. package/dist/orchestrator.d.ts +4 -4
  160. package/dist/orchestrator.js +24 -24
  161. package/dist/patterns-cli.d.ts +1 -1
  162. package/dist/policy-runtime.d.ts +1 -1
  163. package/dist/provenance.d.ts +1 -1
  164. package/dist/qmd-recall-cache.d.ts +1 -1
  165. package/dist/qmd.d.ts +1 -1
  166. package/dist/recall-disclosure-escalation.d.ts +1 -1
  167. package/dist/recall-explain-renderer.d.ts +1 -1
  168. package/dist/recall-planner-llm.d.ts +1 -1
  169. package/dist/recall-state.d.ts +1 -1
  170. package/dist/recall-tag-filter.d.ts +1 -1
  171. package/dist/recall-xray-cli.d.ts +1 -1
  172. package/dist/recall-xray-renderer.d.ts +1 -1
  173. package/dist/recall-xray.d.ts +1 -1
  174. package/dist/resolve-auth-token.d.ts +1 -1
  175. package/dist/retrieval-agents.d.ts +1 -1
  176. package/dist/retrieval-tiers.d.ts +1 -1
  177. package/dist/routing/engine.d.ts +1 -1
  178. package/dist/routing/store.d.ts +1 -1
  179. package/dist/search/embed-helper.d.ts +1 -1
  180. package/dist/search/embed-helper.js +2 -2
  181. package/dist/search/factory.d.ts +1 -1
  182. package/dist/search/factory.js +3 -3
  183. package/dist/search/index.d.ts +1 -1
  184. package/dist/search/index.js +3 -3
  185. package/dist/search/lancedb-backend.d.ts +1 -1
  186. package/dist/search/meilisearch-backend.d.ts +1 -1
  187. package/dist/search/noop-backend.d.ts +1 -1
  188. package/dist/search/orama-backend.d.ts +1 -1
  189. package/dist/search/port.d.ts +1 -1
  190. package/dist/search/remote-backend.d.ts +1 -1
  191. package/dist/{semantic-consolidation-DsIEiCka.d.ts → semantic-consolidation-ByzGwC9c.d.ts} +1 -1
  192. package/dist/semantic-consolidation.d.ts +2 -2
  193. package/dist/semantic-consolidation.js +2 -2
  194. package/dist/semantic-rule-verifier.d.ts +1 -1
  195. package/dist/session-observer-bands.d.ts +1 -1
  196. package/dist/session-observer-state.d.ts +1 -1
  197. package/dist/shared-context/manager.d.ts +1 -1
  198. package/dist/shared-context/manager.js +2 -2
  199. package/dist/signal.d.ts +1 -1
  200. package/dist/storage.d.ts +1 -1
  201. package/dist/summarizer.d.ts +1 -1
  202. package/dist/summarizer.js +3 -3
  203. package/dist/summary-snapshot.d.ts +1 -1
  204. package/dist/temporal-supersession.d.ts +1 -1
  205. package/dist/temporal-validity.d.ts +1 -1
  206. package/dist/threading.d.ts +1 -1
  207. package/dist/tier-migration.d.ts +1 -1
  208. package/dist/tier-routing.d.ts +1 -1
  209. package/dist/{tier-stats-CSKL7BDG.js → tier-stats-5XF4UBRQ.js} +2 -2
  210. package/dist/topics.d.ts +1 -1
  211. package/dist/transcript.d.ts +1 -1
  212. package/dist/trust-score-stage.d.ts +1 -1
  213. package/dist/trust-score.d.ts +1 -1
  214. package/dist/{types-CglNn2V-.d.ts → types-5Jik3r4G.d.ts} +1 -1
  215. package/dist/types.d.ts +1 -1
  216. package/dist/utility-runtime.d.ts +1 -1
  217. package/package.json +2 -2
  218. package/src/capabilities.test.ts +0 -2
  219. package/src/capabilities.ts +7 -6
  220. package/src/orchestration/contradiction-linking-coordinator.ts +336 -0
  221. package/src/orchestration/recall-section-coordinator.ts +349 -0
  222. package/src/orchestrator.ts +67 -400
  223. package/dist/chunk-7HUGLMSW.js.map +0 -1
  224. package/dist/chunk-G7Q4D2G3.js.map +0 -1
  225. /package/dist/{chunk-X5PMDVY4.js.map → chunk-3EA5LIFJ.js.map} +0 -0
  226. /package/dist/{chunk-YNHRWFAP.js.map → chunk-4DLFJJOQ.js.map} +0 -0
  227. /package/dist/{chunk-WIMKOTNY.js.map → chunk-5QANTTY2.js.map} +0 -0
  228. /package/dist/{chunk-AM7YKD7V.js.map → chunk-5UNSGRCR.js.map} +0 -0
  229. /package/dist/{chunk-Y6PNYJVO.js.map → chunk-A2KKLCOS.js.map} +0 -0
  230. /package/dist/{chunk-O4IWVWSW.js.map → chunk-AVBT5WEW.js.map} +0 -0
  231. /package/dist/{chunk-QUNH5UZH.js.map → chunk-BYLC4DKI.js.map} +0 -0
  232. /package/dist/{chunk-UOVDO6TC.js.map → chunk-CHELXDTO.js.map} +0 -0
  233. /package/dist/{chunk-TQQN64J2.js.map → chunk-DBSMLRTO.js.map} +0 -0
  234. /package/dist/{chunk-EZZUNKMJ.js.map → chunk-DYK27X7V.js.map} +0 -0
  235. /package/dist/{chunk-K2N6WIZM.js.map → chunk-E7RGJQWP.js.map} +0 -0
  236. /package/dist/{chunk-M4WI23X3.js.map → chunk-EEKDRAWX.js.map} +0 -0
  237. /package/dist/{chunk-GFJ5ABKS.js.map → chunk-G5FP7VSQ.js.map} +0 -0
  238. /package/dist/{chunk-BE6NEQLF.js.map → chunk-HAZVVOYT.js.map} +0 -0
  239. /package/dist/{chunk-OT5K26NG.js.map → chunk-HM6UJPPO.js.map} +0 -0
  240. /package/dist/{chunk-PI4JHLDD.js.map → chunk-IP5SANO2.js.map} +0 -0
  241. /package/dist/{chunk-WHEF76BQ.js.map → chunk-JRZV3767.js.map} +0 -0
  242. /package/dist/{chunk-OS5RKJOH.js.map → chunk-JZ7P26GF.js.map} +0 -0
  243. /package/dist/{chunk-Y62QPRKV.js.map → chunk-K5LLP4CY.js.map} +0 -0
  244. /package/dist/{chunk-C3Z5YJSM.js.map → chunk-LOPZ2DWR.js.map} +0 -0
  245. /package/dist/{chunk-BJPL5WAL.js.map → chunk-MXDG6SRH.js.map} +0 -0
  246. /package/dist/{chunk-UYYSOMS2.js.map → chunk-NBP3YHHS.js.map} +0 -0
  247. /package/dist/{chunk-USHVHI6J.js.map → chunk-NNL4LJAD.js.map} +0 -0
  248. /package/dist/{chunk-GPX5E36D.js.map → chunk-OSMBC3JU.js.map} +0 -0
  249. /package/dist/{chunk-OUSOMUFV.js.map → chunk-PE6XR4GG.js.map} +0 -0
  250. /package/dist/{chunk-CMPXLMC3.js.map → chunk-PI23H7FV.js.map} +0 -0
  251. /package/dist/{chunk-WGDE2TJP.js.map → chunk-QOGXUNWL.js.map} +0 -0
  252. /package/dist/{chunk-ELL5VYXC.js.map → chunk-RNWWAS5V.js.map} +0 -0
  253. /package/dist/{chunk-JMMSVRF4.js.map → chunk-TQPSOTC7.js.map} +0 -0
  254. /package/dist/{chunk-AX4TRSRE.js.map → chunk-U5WVRMCA.js.map} +0 -0
  255. /package/dist/{chunk-7ADHJ6SU.js.map → chunk-VE54E6RP.js.map} +0 -0
  256. /package/dist/{chunk-OVYBENIJ.js.map → chunk-W3M34XT4.js.map} +0 -0
  257. /package/dist/{chunk-NHJYUIII.js.map → chunk-WPLRJ4XM.js.map} +0 -0
  258. /package/dist/{chunk-UEIF7RWQ.js.map → chunk-XEADGIAA.js.map} +0 -0
  259. /package/dist/{contradiction-scan-UERKJESC.js.map → contradiction-scan-3FJYWS3G.js.map} +0 -0
  260. /package/dist/{first-start-migration-GQ3UQNIL.js.map → first-start-migration-4I3VDSYS.js.map} +0 -0
  261. /package/dist/{tier-stats-CSKL7BDG.js.map → tier-stats-5XF4UBRQ.js.map} +0 -0
@@ -104,7 +104,9 @@ import { EntitySynthesisCoordinator } from "./orchestration/entity-synthesis-coo
104
104
  import { RecallResultFormatter } from "./orchestration/recall-result-formatter.js";
105
105
  import { ConversationIndexCoordinator } from "./orchestration/conversation-index-coordinator.js";
106
106
  import { RecallRerankCoordinator } from "./orchestration/recall-rerank-coordinator.js";
107
+ import { RecallSectionCoordinator } from "./orchestration/recall-section-coordinator.js";
107
108
  import { QmdResultResolver, qmdCollectionPathParts, qmdResultPathCandidates } from "./orchestration/qmd-result-resolver.js";
109
+ import { ContradictionLinkingCoordinator } from "./orchestration/contradiction-linking-coordinator.js";
108
110
  export { hasIdentityRecoveryIntent, resolveEffectiveIdentityInjectionMode } from "./orchestration/recall-result-formatter.js";
109
111
  import {
110
112
  runLiveConnectorsOnce,
@@ -1840,7 +1842,9 @@ export class Orchestrator {
1840
1842
  */
1841
1843
  readonly conversationIndexCoordinator: ConversationIndexCoordinator;
1842
1844
  readonly recallRerankCoordinator: RecallRerankCoordinator;
1845
+ readonly recallSectionCoordinator: RecallSectionCoordinator;
1843
1846
  readonly qmdResultResolver: QmdResultResolver;
1847
+ readonly contradictionLinkingCoordinator: ContradictionLinkingCoordinator;
1844
1848
  private heartbeatObserverChains = new Map<string, Promise<void>>();
1845
1849
  private recentExtractionFingerprints = new Map<string, number>();
1846
1850
  private readonly consolidationObservers = new Set<
@@ -2841,6 +2845,19 @@ export class Orchestrator {
2841
2845
  readQmdResultMemory: (resultPath, fallbackStorage, recallNamespaces) =>
2842
2846
  this.readQmdResultMemory(resultPath, fallbackStorage, recallNamespaces),
2843
2847
  });
2848
+ this.recallSectionCoordinator = new RecallSectionCoordinator({
2849
+ getConfig: () => this.config,
2850
+ resolveSectionEnabled: (id, def) => this.isRecallSectionEnabled(id, def),
2851
+ });
2852
+ this.contradictionLinkingCoordinator = new ContradictionLinkingCoordinator({
2853
+ getConfig: () => this.config,
2854
+ isSearchAvailable: () => this.isSearchAvailableForNamespaceRouting(),
2855
+ searchAcrossNamespaces: (options) => this.searchAcrossNamespaces(options),
2856
+ extractMemoryIdsFromResults: (results) => this.extractMemoryIdsFromResults(results),
2857
+ namespaceFromPath: (p) => this.namespaceFromPath(p),
2858
+ storageForNamespace: (namespace) => this.storageRouter.storageFor(namespace),
2859
+ getExtraction: () => this.extraction,
2860
+ });
2844
2861
  this.modelRegistry = new ModelRegistry(config.memoryDir);
2845
2862
  this.relevance = new RelevanceStore(config.memoryDir);
2846
2863
  this.negatives = new NegativeExampleStore(config.memoryDir);
@@ -6377,52 +6394,46 @@ export class Orchestrator {
6377
6394
  }));
6378
6395
  }
6379
6396
 
6397
+ // Issue #1526 (seam 13): recall section budgeting/assembly moved to
6398
+ // RecallSectionCoordinator. Thin delegation keeps the orchestrator's
6399
+ // recallInternal call sites stable.
6380
6400
  private getRecallSectionEntry(
6381
6401
  sectionId: string,
6382
6402
  ): RecallSectionConfig | undefined {
6383
- const pipeline = Array.isArray(this.config.recallPipeline)
6384
- ? this.config.recallPipeline
6385
- : [];
6386
- return pipeline.find((entry) => entry.id === sectionId);
6403
+ return this.recallSectionCoordinator.getRecallSectionEntry(sectionId);
6387
6404
  }
6388
6405
 
6389
6406
  private isRecallSectionEnabled(
6390
6407
  sectionId: string,
6391
6408
  defaultEnabled: boolean = true,
6392
6409
  ): boolean {
6393
- const entry = this.getRecallSectionEntry(sectionId);
6394
- if (!entry) return defaultEnabled;
6395
- return entry.enabled !== false;
6410
+ return this.recallSectionCoordinator.isRecallSectionEnabled(
6411
+ sectionId,
6412
+ defaultEnabled,
6413
+ );
6396
6414
  }
6397
6415
 
6398
6416
  private isSpecializedRecallSectionEnabled(
6399
6417
  sectionId: string,
6400
6418
  topLevelEnabled: boolean,
6401
6419
  ): boolean {
6402
- const entry = this.getRecallSectionEntry(sectionId);
6403
- if (!entry) return topLevelEnabled;
6404
- return entry.enabled === true || (topLevelEnabled && entry.enabled !== false);
6420
+ return this.recallSectionCoordinator.isSpecializedRecallSectionEnabled(
6421
+ sectionId,
6422
+ topLevelEnabled,
6423
+ );
6405
6424
  }
6406
6425
 
6407
6426
  private getRecallSectionMaxChars(
6408
6427
  sectionId: string,
6409
6428
  ): number | null | undefined {
6410
- const entry = this.getRecallSectionEntry(sectionId);
6411
- if (!entry) return undefined;
6412
- if (entry.maxChars === null) return null;
6413
- if (typeof entry.maxChars !== "number") return undefined;
6414
- return Math.max(0, Math.floor(entry.maxChars));
6429
+ return this.recallSectionCoordinator.getRecallSectionMaxChars(sectionId);
6415
6430
  }
6416
6431
 
6417
6432
  private getRecallSectionNumber(
6418
6433
  sectionId: string,
6419
6434
  key: keyof RecallSectionConfig,
6420
6435
  ): number | undefined {
6421
- const entry = this.getRecallSectionEntry(sectionId);
6422
- if (!entry) return undefined;
6423
- const value = entry[key];
6424
- if (typeof value !== "number" || !Number.isFinite(value)) return undefined;
6425
- return Math.max(0, Math.floor(value));
6436
+ return this.recallSectionCoordinator.getRecallSectionNumber(sectionId, key);
6426
6437
  }
6427
6438
 
6428
6439
  private appendRecallSection(
@@ -6430,104 +6441,25 @@ export class Orchestrator {
6430
6441
  sectionId: string,
6431
6442
  content: string,
6432
6443
  ): boolean {
6433
- // Returns true when the section was actually appended to sectionBuckets,
6434
- // false when it was dropped (disabled, empty, or maxChars===0). Callers
6435
- // that need to know whether injection occurred (e.g. xray annotation for
6436
- // peer-profile) must gate on this return value rather than on whether the
6437
- // section text was computed (Codex P2 finding, PR #764).
6438
- if (!this.isRecallSectionEnabled(sectionId)) return false;
6439
- const trimmed = content.trim();
6440
- if (trimmed.length === 0) return false;
6441
-
6442
- const maxChars = this.getRecallSectionMaxChars(sectionId);
6443
- let finalContent = trimmed;
6444
- if (maxChars === 0) return false;
6445
- if (typeof maxChars === "number" && finalContent.length > maxChars) {
6446
- finalContent = `${finalContent.slice(0, maxChars)}\n\n...(trimmed)\n`;
6447
- }
6448
-
6449
- const existing = sectionBuckets.get(sectionId) ?? [];
6450
- existing.push(finalContent);
6451
- sectionBuckets.set(sectionId, existing);
6452
- return true;
6444
+ return this.recallSectionCoordinator.appendRecallSection(
6445
+ sectionBuckets,
6446
+ sectionId,
6447
+ content,
6448
+ );
6453
6449
  }
6454
6450
 
6455
6451
  private truncateRecallSectionToBudget(
6456
6452
  content: string,
6457
6453
  maxChars: number,
6458
6454
  ): string {
6459
- if (maxChars <= 0) return "";
6460
- if (content.length <= maxChars) return content;
6461
- const suffix = "\n\n...(memory context trimmed)";
6462
- if (maxChars <= suffix.length) {
6463
- return content.slice(0, maxChars);
6464
- }
6465
- return `${content.slice(0, maxChars - suffix.length)}${suffix}`;
6466
- }
6467
-
6468
- private protectedRecallSectionIds(
6469
- sectionBuckets: Map<string, string[]>,
6470
- ): Set<string> {
6471
- const protectedIds = new Set<string>();
6472
- if ((sectionBuckets.get("memories")?.length ?? 0) > 0) {
6473
- protectedIds.add("memories");
6474
- }
6475
- return protectedIds;
6476
- }
6477
-
6478
- private protectedRecallReservationChars(content: string): number {
6479
- const headingBoundary = content.indexOf("\n\n");
6480
- const headingChars =
6481
- headingBoundary >= 0 ? headingBoundary + 2 : Math.min(content.length, 24);
6482
- return Math.min(content.length, Math.max(headingChars, 24));
6483
- }
6484
-
6485
- private estimateReservedRecallBudget(
6486
- entries: Array<{ id: string; content: string }>,
6487
- startIndex: number,
6488
- protectedIds: Set<string>,
6489
- alreadyIncludedCount: number,
6490
- ): number {
6491
- const separatorLength = "\n\n---\n\n".length;
6492
- let reserved = 0;
6493
- let simulatedIncluded = alreadyIncludedCount;
6494
- for (let i = startIndex; i < entries.length; i += 1) {
6495
- const entry = entries[i];
6496
- if (!entry || !protectedIds.has(entry.id)) continue;
6497
- if (simulatedIncluded > 0) {
6498
- reserved += separatorLength;
6499
- }
6500
- reserved += this.protectedRecallReservationChars(entry.content);
6501
- simulatedIncluded += 1;
6502
- }
6503
- return reserved;
6455
+ return this.recallSectionCoordinator.truncateRecallSectionToBudget(
6456
+ content,
6457
+ maxChars,
6458
+ );
6504
6459
  }
6505
6460
 
6506
6461
  private getRecallBudgetChars(override?: number): number {
6507
- if (
6508
- typeof override === "number" &&
6509
- Number.isFinite(override) &&
6510
- override >= 0
6511
- ) {
6512
- return Math.floor(override);
6513
- }
6514
- const configuredBudget = this.config.recallBudgetChars;
6515
- if (
6516
- typeof configuredBudget === "number" &&
6517
- Number.isFinite(configuredBudget) &&
6518
- configuredBudget >= 0
6519
- ) {
6520
- return Math.floor(configuredBudget);
6521
- }
6522
- const tokenBudget = this.config.maxMemoryTokens;
6523
- if (
6524
- typeof tokenBudget === "number" &&
6525
- Number.isFinite(tokenBudget) &&
6526
- tokenBudget >= 0
6527
- ) {
6528
- return Math.floor(tokenBudget * 4);
6529
- }
6530
- return 0;
6462
+ return this.recallSectionCoordinator.getRecallBudgetChars(override);
6531
6463
  }
6532
6464
 
6533
6465
  private assembleRecallSections(
@@ -6540,89 +6472,13 @@ export class Orchestrator {
6540
6472
  truncated: boolean;
6541
6473
  finalChars: number;
6542
6474
  } {
6543
- const orderedEntries: Array<{ id: string; content: string }> = [];
6544
- const pipeline = Array.isArray(this.config.recallPipeline)
6545
- ? this.config.recallPipeline
6546
- : [];
6547
- const orderedIds = pipeline
6548
- .filter((entry) => entry.enabled !== false)
6549
- .map((entry) => entry.id);
6550
- const seen = new Set<string>();
6551
-
6552
- for (const id of orderedIds) {
6553
- const chunks = sectionBuckets.get(id);
6554
- if (!chunks || chunks.length === 0) continue;
6555
- orderedEntries.push({ id, content: chunks.join("\n\n") });
6556
- seen.add(id);
6557
- }
6558
-
6559
- for (const [id, chunks] of sectionBuckets.entries()) {
6560
- if (seen.has(id)) continue;
6561
- if (chunks.length === 0) continue;
6562
- orderedEntries.push({ id, content: chunks.join("\n\n") });
6563
- }
6475
+ return this.recallSectionCoordinator.assembleRecallSections(
6476
+ sectionBuckets,
6477
+ budgetOverride,
6478
+ );
6479
+ }
6564
6480
 
6565
- const budget = this.getRecallBudgetChars(budgetOverride);
6566
- if (budget === 0) {
6567
- return {
6568
- sections: [],
6569
- includedIds: [],
6570
- omittedIds: orderedEntries.map((entry) => entry.id),
6571
- truncated: orderedEntries.length > 0,
6572
- finalChars: 0,
6573
- };
6574
- }
6575
6481
 
6576
- const separator = "\n\n---\n\n";
6577
- const protectedIds = this.protectedRecallSectionIds(sectionBuckets);
6578
- const sections: string[] = [];
6579
- const includedIds: string[] = [];
6580
- const omittedIds: string[] = [];
6581
- let usedChars = 0;
6582
- let truncated = false;
6583
-
6584
- for (let index = 0; index < orderedEntries.length; index += 1) {
6585
- const entry = orderedEntries[index]!;
6586
- const separatorChars = sections.length > 0 ? separator.length : 0;
6587
- const reserve = protectedIds.has(entry.id)
6588
- ? 0
6589
- : this.estimateReservedRecallBudget(
6590
- orderedEntries,
6591
- index + 1,
6592
- protectedIds,
6593
- sections.length + 1,
6594
- );
6595
- const availableForEntry = budget - usedChars - separatorChars - reserve;
6596
- if (availableForEntry <= 0) {
6597
- omittedIds.push(entry.id);
6598
- truncated = true;
6599
- continue;
6600
- }
6601
- const finalContent = this.truncateRecallSectionToBudget(
6602
- entry.content,
6603
- availableForEntry,
6604
- );
6605
- if (!finalContent) {
6606
- omittedIds.push(entry.id);
6607
- truncated = true;
6608
- continue;
6609
- }
6610
- if (finalContent.length < entry.content.length) {
6611
- truncated = true;
6612
- }
6613
- sections.push(finalContent);
6614
- includedIds.push(entry.id);
6615
- usedChars += separatorChars + finalContent.length;
6616
- }
6617
-
6618
- return {
6619
- sections,
6620
- includedIds,
6621
- omittedIds,
6622
- truncated,
6623
- finalChars: usedChars,
6624
- };
6625
- }
6626
6482
 
6627
6483
  /**
6628
6484
  * Clock source for the shared post-retrieval assembly/enrichment budget. The
@@ -16946,18 +16802,7 @@ export class Orchestrator {
16946
16802
  includedSections?: string[];
16947
16803
  omittedSections?: string[];
16948
16804
  }): LastRecallBudgetSummary {
16949
- return {
16950
- requestedTopK: options.requestedTopK,
16951
- appliedTopK: options.recallResultLimit,
16952
- recallBudgetChars: this.getRecallBudgetChars(),
16953
- maxMemoryTokens: this.config.maxMemoryTokens,
16954
- qmdFetchLimit: options.qmdFetchLimit,
16955
- qmdHybridFetchLimit: options.qmdHybridFetchLimit,
16956
- finalContextChars: options.finalContextChars,
16957
- truncated: options.truncated,
16958
- includedSections: [...(options.includedSections ?? [])],
16959
- omittedSections: [...(options.omittedSections ?? [])],
16960
- };
16805
+ return this.recallSectionCoordinator.buildLastRecallBudgetSummary(options);
16961
16806
  }
16962
16807
 
16963
16808
  private collectLastRecallSources(
@@ -16969,16 +16814,10 @@ export class Orchestrator {
16969
16814
  | "cold_fallback"
16970
16815
  | "recent_scan",
16971
16816
  ): string[] {
16972
- const used = new Set<string>();
16973
- if (recallSource !== "none") {
16974
- used.add(recallSource);
16975
- }
16976
- for (const [sectionId, chunks] of sectionBuckets.entries()) {
16977
- if (chunks.length > 0) {
16978
- used.add(sectionId);
16979
- }
16980
- }
16981
- return [...used];
16817
+ return this.recallSectionCoordinator.collectLastRecallSources(
16818
+ sectionBuckets,
16819
+ recallSource,
16820
+ );
16982
16821
  }
16983
16822
 
16984
16823
  /**
@@ -18338,99 +18177,11 @@ export class Orchestrator {
18338
18177
  supersededCreated: string;
18339
18178
  supersededTags: string[];
18340
18179
  } | null> {
18341
- if (!this.isSearchAvailableForNamespaceRouting()) return null;
18342
-
18343
- // Search for similar memories
18344
- const results = await this.searchAcrossNamespaces({
18345
- query: content,
18346
- namespaces: [namespaceScope],
18347
- maxResults: 5,
18348
- mode: "search",
18349
- });
18350
-
18351
- for (const result of results) {
18352
- // Check similarity threshold
18353
- if (result.score < this.config.contradictionSimilarityThreshold) {
18354
- continue;
18355
- }
18356
-
18357
- // Get the existing memory
18358
- const memoryId = this.extractMemoryIdsFromResults([result])[0];
18359
- if (!memoryId) continue;
18360
-
18361
- const resultNamespace = this.namespaceFromPath(result.path);
18362
- if (resultNamespace !== namespaceScope) continue;
18363
- const resultStorage =
18364
- await this.storageRouter.storageFor(resultNamespace);
18365
- const existingMemory = await resultStorage.getMemoryById(memoryId);
18366
- if (!existingMemory) continue;
18367
-
18368
- // Skip memories already resolved or explicitly forgotten. Other
18369
- // non-active statuses remain valid contradiction candidates.
18370
- if (
18371
- existingMemory.frontmatter.status === "superseded" ||
18372
- existingMemory.frontmatter.status === "forgotten"
18373
- ) {
18374
- continue;
18375
- }
18376
-
18377
- // Verify contradiction with LLM
18378
- const verification = await this.extraction.verifyContradiction(
18379
- { content, category },
18380
- {
18381
- id: existingMemory.frontmatter.id,
18382
- content: existingMemory.content,
18383
- category: existingMemory.frontmatter.category,
18384
- created: existingMemory.frontmatter.created,
18385
- },
18386
- );
18387
-
18388
- if (!verification) continue;
18389
-
18390
- // Check if it's a real contradiction with high confidence
18391
- if (
18392
- verification.isContradiction &&
18393
- verification.confidence >= this.config.contradictionMinConfidence
18394
- ) {
18395
- // When the LLM says the existing memory is newer (whichIsNewer ===
18396
- // "first") the incoming fact is the stale one in both resolve modes —
18397
- // log and continue so the caller never marks contradictionDetected and
18398
- // the semantic-skip gate can discard the outdated write normally.
18399
- if (verification.whichIsNewer === "first") {
18400
- log.info(
18401
- `detected contradiction (confidence: ${verification.confidence}): ${existingMemory.frontmatter.id} vs new memory — existing is newer, incoming fact is stale`,
18402
- );
18403
- continue;
18404
- }
18405
-
18406
- // The new fact is newer than the existing one. When auto-resolve is
18407
- // enabled, the caller retires the old memory AFTER the new write lands
18408
- // and its tombstone status is known (#1645: defer auto-resolve until
18409
- // tombstone status is known — a tombstone-blocked new write must not
18410
- // retire the only active copy, leaving neither memory active). When
18411
- // disabled, the old memory stays active for manual review. The
18412
- // contradiction info is returned in both cases so the caller can apply
18413
- // the deferred retire post-write.
18414
-
18415
- // Return the contradiction info regardless of auto-resolve setting.
18416
- // The caller uses this to set `contradictionDetected=true` which
18417
- // prevents the semantic-skip guard from silently dropping a
18418
- // legitimately contradictory update (the regression this fixes).
18419
- log.info(
18420
- `detected contradiction (confidence: ${verification.confidence}): ${existingMemory.frontmatter.id} vs new memory${this.config.contradictionAutoResolve ? " (auto-resolved)" : " (queued for manual review)"}`,
18421
- );
18422
- return {
18423
- supersededId: existingMemory.frontmatter.id,
18424
- confidence: verification.confidence,
18425
- reason: verification.reasoning,
18426
- supersededPath: existingMemory.path,
18427
- supersededCreated: existingMemory.frontmatter.created,
18428
- supersededTags: existingMemory.frontmatter.tags ?? [],
18429
- };
18430
- }
18431
- }
18432
-
18433
- return null;
18180
+ return this.contradictionLinkingCoordinator.checkForContradiction(
18181
+ content,
18182
+ category,
18183
+ namespaceScope,
18184
+ );
18434
18185
  }
18435
18186
 
18436
18187
  /**
@@ -18453,49 +18204,12 @@ export class Orchestrator {
18453
18204
  newMemoryId: string,
18454
18205
  postWriteGuard: boolean,
18455
18206
  ): Promise<void> {
18456
- // #1645 yG2: clear the pre-write `supersedes` link from a blocked row so
18457
- // it doesn't claim to supersede a still-active memory (best-effort).
18458
- if (postWriteGuard && contradiction && this.config.contradictionAutoResolve) {
18459
- try {
18460
- const blockedRow = await storage.getMemoryById(newMemoryId);
18461
- if (blockedRow?.frontmatter?.supersedes) {
18462
- await storage.writeMemoryFrontmatter(blockedRow, { supersedes: undefined });
18463
- }
18464
- } catch (err) {
18465
- log.warn(
18466
- `contradiction auto-resolve supersedes clear failed for blocked ${newMemoryId}: ${err}`,
18467
- );
18468
- }
18469
- }
18470
- if (
18471
- !contradiction ||
18472
- !this.config.contradictionAutoResolve ||
18473
- postWriteGuard
18474
- ) {
18475
- return;
18476
- }
18477
- try {
18478
- await storage.supersedeMemory(
18479
- contradiction.supersededId,
18480
- newMemoryId,
18481
- contradiction.reason,
18482
- );
18483
- if (
18484
- resolveIndexingCapabilities(this.config).queryAwareIndexing &&
18485
- contradiction.supersededPath
18486
- ) {
18487
- deindexMemory(
18488
- this.config.memoryDir,
18489
- contradiction.supersededPath,
18490
- contradiction.supersededCreated,
18491
- contradiction.supersededTags,
18492
- );
18493
- }
18494
- } catch (err) {
18495
- log.warn(
18496
- `contradiction auto-resolve supersede failed for ${contradiction.supersededId}: ${err}`,
18497
- );
18498
- }
18207
+ return this.contradictionLinkingCoordinator.applyDeferredContradictionResolve(
18208
+ contradiction,
18209
+ storage,
18210
+ newMemoryId,
18211
+ postWriteGuard,
18212
+ );
18499
18213
  }
18500
18214
 
18501
18215
  // ---------------------------------------------------------------------------
@@ -18510,61 +18224,14 @@ export class Orchestrator {
18510
18224
  category: string,
18511
18225
  namespaceScope: string,
18512
18226
  ): Promise<MemoryLink[]> {
18513
- if (!this.isSearchAvailableForNamespaceRouting()) return [];
18514
-
18515
- // Search for related memories
18516
- const results = await this.searchAcrossNamespaces({
18517
- query: content,
18518
- namespaces: [namespaceScope],
18519
- maxResults: 5,
18520
- mode: "search",
18521
- });
18522
- if (results.length === 0) return [];
18523
-
18524
- // Get full memory details for candidates
18525
- const candidates: Array<{ id: string; content: string; category: string }> =
18526
- [];
18527
- for (const result of results) {
18528
- const memoryId = this.extractMemoryIdsFromResults([result])[0];
18529
- if (!memoryId) continue;
18530
-
18531
- const resultNamespace = this.namespaceFromPath(result.path);
18532
- if (resultNamespace !== namespaceScope) continue;
18533
- const resultStorage =
18534
- await this.storageRouter.storageFor(resultNamespace);
18535
- const memory = await resultStorage.getMemoryById(memoryId);
18536
- if (
18537
- memory &&
18538
- memory.frontmatter.status !== "superseded" &&
18539
- memory.frontmatter.status !== "forgotten"
18540
- ) {
18541
- candidates.push({
18542
- id: memory.frontmatter.id,
18543
- content: memory.content,
18544
- category: memory.frontmatter.category,
18545
- });
18546
- }
18547
- }
18548
-
18549
- if (candidates.length === 0) return [];
18550
-
18551
- // Ask LLM for link suggestions
18552
- const suggestions = await this.extraction.suggestLinks(
18553
- { content, category },
18554
- candidates,
18227
+ return this.contradictionLinkingCoordinator.suggestLinksForMemory(
18228
+ content,
18229
+ category,
18230
+ namespaceScope,
18555
18231
  );
18556
-
18557
- if (!suggestions || suggestions.links.length === 0) return [];
18558
-
18559
- // Convert to MemoryLink format
18560
- return suggestions.links.map((link) => ({
18561
- targetId: link.targetId,
18562
- linkType: link.linkType,
18563
- strength: link.strength,
18564
- reason: link.reason || undefined,
18565
- }));
18566
18232
  }
18567
18233
 
18234
+
18568
18235
  private async graphSeedPathRelativeToStorage(
18569
18236
  storage: StorageManager,
18570
18237
  result: QmdSearchResult,