@remnic/core 9.3.733 → 9.3.735

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 (304) hide show
  1. package/dist/access-boundary.d.ts +13 -11
  2. package/dist/access-boundary.js +9 -9
  3. package/dist/access-cli.js +26 -24
  4. package/dist/access-cli.js.map +1 -1
  5. package/dist/access-http.d.ts +13 -11
  6. package/dist/access-http.js +14 -14
  7. package/dist/access-mcp.d.ts +13 -11
  8. package/dist/access-mcp.js +13 -13
  9. package/dist/access-operations-batch.js +11 -11
  10. package/dist/access-operations.d.ts +13 -11
  11. package/dist/access-operations.js +12 -12
  12. package/dist/access-schema.d.ts +4 -4
  13. package/dist/{access-service-Byoe3HsT.d.ts → access-service-CVx7mmvK.d.ts} +4 -4
  14. package/dist/access-service.d.ts +13 -11
  15. package/dist/access-service.js +8 -8
  16. package/dist/access-surface-catalog.d.ts +13 -11
  17. package/dist/action-confidence.d.ts +1 -1
  18. package/dist/active-memory-bridge.d.ts +1 -1
  19. package/dist/active-memory-bridge.js +3 -2
  20. package/dist/active-recall.d.ts +1 -1
  21. package/dist/behavior-learner.d.ts +1 -1
  22. package/dist/behavior-signals.d.ts +1 -1
  23. package/dist/bootstrap.d.ts +12 -10
  24. package/dist/briefing.d.ts +1 -1
  25. package/dist/buffer-surprise-report.d.ts +1 -1
  26. package/dist/buffer.d.ts +1 -1
  27. package/dist/calibration.d.ts +1 -1
  28. package/dist/capabilities.d.ts +196 -2
  29. package/dist/capabilities.js +21 -3
  30. package/dist/{catalog-DM1nk7cM.d.ts → catalog-BVhDEUhT.d.ts} +2 -2
  31. package/dist/causal-behavior.d.ts +1 -1
  32. package/dist/causal-consolidation.d.ts +1 -1
  33. package/dist/causal-trajectory-graph.d.ts +1 -1
  34. package/dist/{chunk-CX77GNMB.js → chunk-2T2N7ISV.js} +6 -3
  35. package/dist/chunk-2T2N7ISV.js.map +1 -0
  36. package/dist/{chunk-HHNSLPX7.js → chunk-5BOQNB2K.js} +10 -9
  37. package/dist/chunk-5BOQNB2K.js.map +1 -0
  38. package/dist/{chunk-QZHF4BWN.js → chunk-AAIHDIMD.js} +6 -6
  39. package/dist/{chunk-H3MB3F62.js → chunk-AB2E5DCN.js} +4 -3
  40. package/dist/chunk-AB2E5DCN.js.map +1 -0
  41. package/dist/{chunk-KSJCXXOU.js → chunk-AE7NTZ75.js} +6 -3
  42. package/dist/chunk-AE7NTZ75.js.map +1 -0
  43. package/dist/{chunk-OTQE66IX.js → chunk-AESC5OQJ.js} +6 -3
  44. package/dist/chunk-AESC5OQJ.js.map +1 -0
  45. package/dist/{chunk-FFUCCKPN.js → chunk-BXPG5AVX.js} +10 -7
  46. package/dist/chunk-BXPG5AVX.js.map +1 -0
  47. package/dist/{chunk-P3VJCTVE.js → chunk-CHJIWG2H.js} +4 -3
  48. package/dist/chunk-CHJIWG2H.js.map +1 -0
  49. package/dist/{chunk-FYWUNVFZ.js → chunk-E4LYJ7PY.js} +6 -6
  50. package/dist/{chunk-NIZQH6AU.js → chunk-FF36YNKY.js} +8 -7
  51. package/dist/chunk-FF36YNKY.js.map +1 -0
  52. package/dist/{chunk-OUITHS6V.js → chunk-FLCYY5JX.js} +801 -711
  53. package/dist/chunk-FLCYY5JX.js.map +1 -0
  54. package/dist/{chunk-PLBIPT6I.js → chunk-FLPKEMSO.js} +7 -4
  55. package/dist/chunk-FLPKEMSO.js.map +1 -0
  56. package/dist/{chunk-6TUWSUUD.js → chunk-G54IDCD3.js} +59 -53
  57. package/dist/chunk-G54IDCD3.js.map +1 -0
  58. package/dist/{chunk-J6BH2OBA.js → chunk-GB2FZOWB.js} +8 -5
  59. package/dist/chunk-GB2FZOWB.js.map +1 -0
  60. package/dist/{chunk-CGPHMNL4.js → chunk-GYICIICQ.js} +10 -6
  61. package/dist/chunk-GYICIICQ.js.map +1 -0
  62. package/dist/{chunk-DKT3X5C3.js → chunk-HFXZIF3V.js} +7 -4
  63. package/dist/chunk-HFXZIF3V.js.map +1 -0
  64. package/dist/{chunk-646B5ERJ.js → chunk-HLPYL6LC.js} +71 -65
  65. package/dist/chunk-HLPYL6LC.js.map +1 -0
  66. package/dist/{chunk-ZVHRSR2R.js → chunk-IPI45Q4S.js} +6 -3
  67. package/dist/chunk-IPI45Q4S.js.map +1 -0
  68. package/dist/{chunk-24D66MMN.js → chunk-IX4L7E5G.js} +7 -4
  69. package/dist/chunk-IX4L7E5G.js.map +1 -0
  70. package/dist/{chunk-SYX73XD7.js → chunk-IXGXALRV.js} +10 -7
  71. package/dist/chunk-IXGXALRV.js.map +1 -0
  72. package/dist/{chunk-ESF7TRYJ.js → chunk-JWDE7OVJ.js} +79 -2
  73. package/dist/chunk-JWDE7OVJ.js.map +1 -0
  74. package/dist/{chunk-GGL34GCW.js → chunk-K3Y2SJTN.js} +7 -4
  75. package/dist/chunk-K3Y2SJTN.js.map +1 -0
  76. package/dist/{chunk-PMAQRUN4.js → chunk-NDKW67ER.js} +5 -2
  77. package/dist/chunk-NDKW67ER.js.map +1 -0
  78. package/dist/{chunk-ZQUAVZNG.js → chunk-NNJKEAP2.js} +7 -4
  79. package/dist/chunk-NNJKEAP2.js.map +1 -0
  80. package/dist/{chunk-UZYLX7M6.js → chunk-OYHYBHHI.js} +9 -6
  81. package/dist/chunk-OYHYBHHI.js.map +1 -0
  82. package/dist/{chunk-NOU77OHX.js → chunk-P6VLG7KE.js} +2 -2
  83. package/dist/{chunk-O4ZIBPIW.js → chunk-QNTLWH3T.js} +3 -3
  84. package/dist/{chunk-LUCARK4W.js → chunk-UO6MPN77.js} +37 -35
  85. package/dist/chunk-UO6MPN77.js.map +1 -0
  86. package/dist/{chunk-HJWQJUKQ.js → chunk-VOEVVIP3.js} +3 -3
  87. package/dist/{chunk-KQYGNGON.js → chunk-ZBZ4XULO.js} +6 -3
  88. package/dist/chunk-ZBZ4XULO.js.map +1 -0
  89. package/dist/{cli-Dt-tuiYH.d.ts → cli-Cx5Mxwk7.d.ts} +3 -3
  90. package/dist/cli.d.ts +14 -12
  91. package/dist/cli.js +20 -20
  92. package/dist/compounding/engine.d.ts +3 -2
  93. package/dist/compounding/engine.js +2 -1
  94. package/dist/compounding/preference-consolidator.d.ts +1 -1
  95. package/dist/compression-optimizer.d.ts +1 -1
  96. package/dist/config.d.ts +1 -1
  97. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  98. package/dist/connectors/codex-materialize.d.ts +1 -1
  99. package/dist/connectors/index.d.ts +1 -1
  100. package/dist/consolidation-provenance-check.d.ts +1 -1
  101. package/dist/consolidation-undo.d.ts +1 -1
  102. package/dist/contradiction/index.d.ts +2 -2
  103. package/dist/contradiction/index.js +2 -1
  104. package/dist/{contradiction-scan-HWGEOUDS.js → contradiction-scan-2B4AE4TI.js} +3 -2
  105. package/dist/conversation-index/backend.d.ts +1 -1
  106. package/dist/conversation-index/chunker.d.ts +1 -1
  107. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  108. package/dist/conversation-index/indexer.d.ts +1 -1
  109. package/dist/conversation-index/search.d.ts +1 -1
  110. package/dist/day-summary.d.ts +1 -1
  111. package/dist/delinearize.d.ts +1 -1
  112. package/dist/direct-answer-wiring.d.ts +1 -1
  113. package/dist/direct-answer.d.ts +1 -1
  114. package/dist/embedding-fallback.d.ts +1 -1
  115. package/dist/embedding-fallback.js +2 -2
  116. package/dist/enrichment/index.d.ts +1 -1
  117. package/dist/entity-retrieval.d.ts +1 -1
  118. package/dist/entity-retrieval.js +2 -1
  119. package/dist/entity-schema.d.ts +1 -1
  120. package/dist/explicit-capture.d.ts +12 -10
  121. package/dist/explicit-capture.js +2 -1
  122. package/dist/extraction-faithfulness.d.ts +1 -1
  123. package/dist/extraction-judge-telemetry.d.ts +1 -1
  124. package/dist/extraction-judge-training.d.ts +1 -1
  125. package/dist/extraction-judge.d.ts +1 -1
  126. package/dist/extraction.d.ts +1 -1
  127. package/dist/extraction.js +3 -3
  128. package/dist/fallback-llm.d.ts +1 -1
  129. package/dist/{first-start-migration-OOR57AYR.js → first-start-migration-2RQYDIZ7.js} +10 -8
  130. package/dist/first-start-migration-2RQYDIZ7.js.map +1 -0
  131. package/dist/graph-dashboard-diff.d.ts +1 -1
  132. package/dist/graph-dashboard-key.d.ts +1 -1
  133. package/dist/graph-dashboard-parser.d.ts +1 -1
  134. package/dist/graph-edge-reinforcement.d.ts +1 -1
  135. package/dist/graph-snapshot.d.ts +1 -1
  136. package/dist/graph.d.ts +1 -1
  137. package/dist/identity-continuity.d.ts +1 -1
  138. package/dist/importance.d.ts +1 -1
  139. package/dist/index.d.ts +12 -12
  140. package/dist/index.js +44 -44
  141. package/dist/intent.d.ts +1 -1
  142. package/dist/lcm/engine.d.ts +1 -1
  143. package/dist/lcm/index.d.ts +1 -1
  144. package/dist/lcm/tools.d.ts +1 -1
  145. package/dist/lifecycle.d.ts +1 -1
  146. package/dist/live-connectors-runner.d.ts +1 -1
  147. package/dist/local-llm.d.ts +1 -1
  148. package/dist/local-llm.js +2 -1
  149. package/dist/local-model-endpoint.d.ts +1 -1
  150. package/dist/maintenance/memory-governance.d.ts +1 -1
  151. package/dist/mcp-memory-inspector-app.d.ts +13 -11
  152. package/dist/memory-action-policy.d.ts +1 -1
  153. package/dist/memory-cache.d.ts +1 -1
  154. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  155. package/dist/memory-projection-store.d.ts +1 -1
  156. package/dist/memory-provenance.d.ts +1 -1
  157. package/dist/memory-worth-outcomes.d.ts +1 -1
  158. package/dist/models-json.d.ts +1 -1
  159. package/dist/namespaces/migrate.d.ts +2 -2
  160. package/dist/namespaces/migrate.js +6 -6
  161. package/dist/namespaces/principal.d.ts +1 -1
  162. package/dist/namespaces/principal.js +2 -1
  163. package/dist/namespaces/search.d.ts +1 -1
  164. package/dist/namespaces/search.js +4 -4
  165. package/dist/namespaces/storage.d.ts +2 -2
  166. package/dist/namespaces/storage.js +2 -1
  167. package/dist/native-knowledge.d.ts +1 -1
  168. package/dist/operator-toolkit.d.ts +1 -1
  169. package/dist/operator-toolkit.js +11 -11
  170. package/dist/orchestration/compression-guideline-coordinator.d.ts +1 -1
  171. package/dist/orchestration/compression-guideline-coordinator.js +2 -1
  172. package/dist/orchestration/maintenance.d.ts +2 -2
  173. package/dist/orchestration/maintenance.js +6 -5
  174. package/dist/{orchestrator-B4KjaOtY.d.ts → orchestrator-oF0cceBX.d.ts} +143 -18
  175. package/dist/orchestrator.d.ts +8 -6
  176. package/dist/orchestrator.js +21 -19
  177. package/dist/patterns-cli.d.ts +1 -1
  178. package/dist/policy-runtime.d.ts +1 -1
  179. package/dist/provenance.d.ts +1 -1
  180. package/dist/qmd-recall-cache.d.ts +1 -1
  181. package/dist/qmd.d.ts +1 -1
  182. package/dist/recall-disclosure-escalation.d.ts +1 -1
  183. package/dist/recall-explain-renderer.d.ts +1 -1
  184. package/dist/recall-planner-llm.d.ts +1 -1
  185. package/dist/recall-state.d.ts +1 -1
  186. package/dist/recall-tag-filter.d.ts +1 -1
  187. package/dist/recall-xray-cli.d.ts +1 -1
  188. package/dist/recall-xray-renderer.d.ts +1 -1
  189. package/dist/recall-xray.d.ts +1 -1
  190. package/dist/resolve-auth-token.d.ts +1 -1
  191. package/dist/retrieval-agents.d.ts +1 -1
  192. package/dist/retrieval-tiers.d.ts +1 -1
  193. package/dist/routing/engine.d.ts +1 -1
  194. package/dist/routing/store.d.ts +1 -1
  195. package/dist/schemas.d.ts +2 -2
  196. package/dist/search/embed-helper.d.ts +1 -1
  197. package/dist/search/embed-helper.js +2 -2
  198. package/dist/search/factory.d.ts +1 -1
  199. package/dist/search/factory.js +3 -3
  200. package/dist/search/index.d.ts +1 -1
  201. package/dist/search/index.js +3 -3
  202. package/dist/search/lancedb-backend.d.ts +1 -1
  203. package/dist/search/meilisearch-backend.d.ts +1 -1
  204. package/dist/search/noop-backend.d.ts +1 -1
  205. package/dist/search/orama-backend.d.ts +1 -1
  206. package/dist/search/port.d.ts +1 -1
  207. package/dist/search/remote-backend.d.ts +1 -1
  208. package/dist/{semantic-SLAa_prH.d.ts → semantic-DJR8_DMQ.d.ts} +1 -1
  209. package/dist/{semantic-consolidation-CstTvHPo.d.ts → semantic-consolidation-DKGbufYO.d.ts} +1 -1
  210. package/dist/semantic-consolidation.d.ts +2 -2
  211. package/dist/semantic-rule-verifier.d.ts +1 -1
  212. package/dist/session-observer-bands.d.ts +1 -1
  213. package/dist/session-observer-state.d.ts +1 -1
  214. package/dist/shared-context/manager.d.ts +3 -3
  215. package/dist/signal.d.ts +1 -1
  216. package/dist/storage.d.ts +1 -1
  217. package/dist/summarizer.d.ts +1 -1
  218. package/dist/summarizer.js +3 -2
  219. package/dist/summary-snapshot.d.ts +1 -1
  220. package/dist/temporal-supersession.d.ts +1 -1
  221. package/dist/temporal-validity.d.ts +1 -1
  222. package/dist/threading.d.ts +1 -1
  223. package/dist/tier-migration.d.ts +1 -1
  224. package/dist/tier-routing.d.ts +1 -1
  225. package/dist/{tier-stats-3LYQ3VV5.js → tier-stats-KPDIISG7.js} +8 -4
  226. package/dist/tier-stats-KPDIISG7.js.map +1 -0
  227. package/dist/topics.d.ts +1 -1
  228. package/dist/transcript.d.ts +1 -1
  229. package/dist/transfer/types.d.ts +30 -30
  230. package/dist/trust-score-stage.d.ts +1 -1
  231. package/dist/trust-score.d.ts +1 -1
  232. package/dist/{types-VkxElCHR.d.ts → types-C7UCxpuO.d.ts} +1 -1
  233. package/dist/types.d.ts +1 -1
  234. package/dist/utility-runtime.d.ts +1 -1
  235. package/package.json +2 -2
  236. package/src/access-service.ts +61 -56
  237. package/src/active-memory-bridge.ts +2 -1
  238. package/src/admin/admin-surfaces.ts +2 -1
  239. package/src/capabilities.test.ts +375 -0
  240. package/src/capabilities.ts +403 -0
  241. package/src/cli/creation-ledger-commands.ts +2 -2
  242. package/src/cli/research-status-commands.ts +13 -13
  243. package/src/cli.ts +29 -25
  244. package/src/compounding/engine.ts +4 -3
  245. package/src/contradiction/contradiction-scan.ts +4 -3
  246. package/src/embedding-fallback.ts +5 -2
  247. package/src/entity-retrieval.ts +3 -2
  248. package/src/explicit-capture.ts +2 -1
  249. package/src/extraction.ts +6 -3
  250. package/src/local-llm.ts +4 -3
  251. package/src/maintenance/first-start-migration.ts +8 -5
  252. package/src/maintenance/namespace-maintenance-fanout.ts +2 -1
  253. package/src/maintenance/namespace-planner.ts +4 -3
  254. package/src/maintenance/tier-stats.ts +4 -3
  255. package/src/namespaces/catalog.ts +2 -1
  256. package/src/namespaces/migrate.ts +2 -1
  257. package/src/namespaces/principal.ts +6 -5
  258. package/src/namespaces/scope-profiles.ts +2 -1
  259. package/src/namespaces/search.ts +2 -1
  260. package/src/namespaces/storage.ts +4 -3
  261. package/src/operator-toolkit.ts +27 -26
  262. package/src/orchestration/compression-guideline-coordinator.ts +7 -6
  263. package/src/orchestration/lifecycle-policy-coordinator.ts +504 -0
  264. package/src/orchestration/maintenance.ts +8 -4
  265. package/src/orchestration/semantic-consolidation-coordinator.ts +454 -0
  266. package/src/orchestration/tier-migration-coordinator.ts +5 -4
  267. package/src/orchestrator.ts +106 -800
  268. package/src/scopes/scope-plan.ts +3 -2
  269. package/src/search/embed-helper.ts +5 -2
  270. package/src/search/factory.ts +9 -6
  271. package/src/summarizer.ts +3 -2
  272. package/dist/chunk-24D66MMN.js.map +0 -1
  273. package/dist/chunk-646B5ERJ.js.map +0 -1
  274. package/dist/chunk-6TUWSUUD.js.map +0 -1
  275. package/dist/chunk-CGPHMNL4.js.map +0 -1
  276. package/dist/chunk-CX77GNMB.js.map +0 -1
  277. package/dist/chunk-DKT3X5C3.js.map +0 -1
  278. package/dist/chunk-ESF7TRYJ.js.map +0 -1
  279. package/dist/chunk-FFUCCKPN.js.map +0 -1
  280. package/dist/chunk-GGL34GCW.js.map +0 -1
  281. package/dist/chunk-H3MB3F62.js.map +0 -1
  282. package/dist/chunk-HHNSLPX7.js.map +0 -1
  283. package/dist/chunk-J6BH2OBA.js.map +0 -1
  284. package/dist/chunk-KQYGNGON.js.map +0 -1
  285. package/dist/chunk-KSJCXXOU.js.map +0 -1
  286. package/dist/chunk-LUCARK4W.js.map +0 -1
  287. package/dist/chunk-NIZQH6AU.js.map +0 -1
  288. package/dist/chunk-OTQE66IX.js.map +0 -1
  289. package/dist/chunk-OUITHS6V.js.map +0 -1
  290. package/dist/chunk-P3VJCTVE.js.map +0 -1
  291. package/dist/chunk-PLBIPT6I.js.map +0 -1
  292. package/dist/chunk-PMAQRUN4.js.map +0 -1
  293. package/dist/chunk-SYX73XD7.js.map +0 -1
  294. package/dist/chunk-UZYLX7M6.js.map +0 -1
  295. package/dist/chunk-ZQUAVZNG.js.map +0 -1
  296. package/dist/chunk-ZVHRSR2R.js.map +0 -1
  297. package/dist/first-start-migration-OOR57AYR.js.map +0 -1
  298. package/dist/tier-stats-3LYQ3VV5.js.map +0 -1
  299. /package/dist/{chunk-QZHF4BWN.js.map → chunk-AAIHDIMD.js.map} +0 -0
  300. /package/dist/{chunk-FYWUNVFZ.js.map → chunk-E4LYJ7PY.js.map} +0 -0
  301. /package/dist/{chunk-NOU77OHX.js.map → chunk-P6VLG7KE.js.map} +0 -0
  302. /package/dist/{chunk-O4ZIBPIW.js.map → chunk-QNTLWH3T.js.map} +0 -0
  303. /package/dist/{chunk-HJWQJUKQ.js.map → chunk-VOEVVIP3.js.map} +0 -0
  304. /package/dist/{contradiction-scan-HWGEOUDS.js.map → contradiction-scan-2B4AE4TI.js.map} +0 -0
@@ -24,6 +24,7 @@
24
24
  */
25
25
 
26
26
  import { createHash } from "node:crypto";
27
+ import { resolveCompressionCapabilities } from "../capabilities.js";
27
28
 
28
29
  // StorageManager type comes from the package barrel (type-only) so this
29
30
  // module does not add a direct storage.ts import (#1533 ratchet).
@@ -103,7 +104,7 @@ export class CompressionGuidelineCoordinator {
103
104
  ? draftState
104
105
  : activeState;
105
106
 
106
- if (!this.config.compressionGuidelineLearningEnabled) {
107
+ if (!resolveCompressionCapabilities(this.config).compressionGuidelineLearning) {
107
108
  return {
108
109
  enabled: false,
109
110
  dryRun,
@@ -152,7 +153,7 @@ export class CompressionGuidelineCoordinator {
152
153
  }
153
154
  const refinedCandidate =
154
155
  await refineCompressionGuidelineCandidateSemantically(candidate, {
155
- enabled: this.config.compressionGuidelineSemanticRefinementEnabled,
156
+ enabled: resolveCompressionCapabilities(this.config).compressionGuidelineSemanticRefinement,
156
157
  timeoutMs: this.config.compressionGuidelineSemanticTimeoutMs,
157
158
  runRefinement: async (baseline) => {
158
159
  const prompt = [
@@ -241,7 +242,7 @@ export class CompressionGuidelineCoordinator {
241
242
  | "guideline_version_mismatch"
242
243
  | "draft_changed";
243
244
  }> {
244
- if (!this.config.compressionGuidelineLearningEnabled) {
245
+ if (!resolveCompressionCapabilities(this.config).compressionGuidelineLearning) {
245
246
  return {
246
247
  enabled: false,
247
248
  activated: false,
@@ -312,7 +313,7 @@ export class CompressionGuidelineCoordinator {
312
313
 
313
314
  /** Consolidation-time hook: recompute the draft from recent events. */
314
315
  async runCompressionGuidelineLearningPass(): Promise<void> {
315
- if (!this.config.compressionGuidelineLearningEnabled) return;
316
+ if (!resolveCompressionCapabilities(this.config).compressionGuidelineLearning) return;
316
317
  try {
317
318
  const result = await this.optimizeCompressionGuidelines({
318
319
  dryRun: false,
@@ -328,8 +329,8 @@ export class CompressionGuidelineCoordinator {
328
329
 
329
330
  /** Recall-time hook: surface active guidelines as a recall section. */
330
331
  async buildCompressionGuidelineRecallSection(): Promise<string | null> {
331
- if (!this.config.contextCompressionActionsEnabled) return null;
332
- if (!this.config.compressionGuidelineLearningEnabled) return null;
332
+ if (!resolveCompressionCapabilities(this.config).contextCompressionActions) return null;
333
+ if (!resolveCompressionCapabilities(this.config).compressionGuidelineLearning) return null;
333
334
 
334
335
  const state = await this.storage
335
336
  .readCompressionGuidelineOptimizerState()
@@ -0,0 +1,504 @@
1
+ /**
2
+ * Lifecycle-policy coordinator — extracted from the orchestrator
3
+ * (issue #1526, seam 6).
4
+ *
5
+ * Owns the deterministic memory-lifecycle pipeline: heat/decay scoring
6
+ * (`runLifecyclePolicyPass`), fact archival (`runFactArchival`),
7
+ * summarization (`runSummarization`), and topic extraction
8
+ * (`runTopicExtraction`). Also owns the action-outcome prior builder
9
+ * (`buildLifecycleActionPriors` / `actionOutcomePriorDelta`) that feeds
10
+ * the lifecycle transition decider.
11
+ *
12
+ * The orchestrator constructs one instance and delegates the internal
13
+ * entrypoints to it. The public wrapper (`runLifecyclePolicyNow`)
14
+ * remains on the orchestrator as a thin pass-through. Storage is the
15
+ * orchestrator's stable `this.storage` (or a per-namespace override
16
+ * passed via options); the extraction engine, embedding-fallback, and
17
+ * content-hash callbacks arrive as deps so the orchestrator keeps
18
+ * ownership of gateway routing and cross-subsystem persistence.
19
+ *
20
+ * Behavior-preserving move from orchestrator.ts. No logic changes — the
21
+ * orchestrator keeps thin delegating methods so existing call sites
22
+ * and tests that exercise the public API continue to work.
23
+ */
24
+
25
+ import {
26
+ decideLifecycleTransition,
27
+ resolveLifecycleState,
28
+ type LifecycleSignals,
29
+ } from "../lifecycle.js";
30
+ import type { LifecycleState } from "../types.js";
31
+ import {
32
+ resolveIndexingCapabilities,
33
+ resolveMemoryLifecycleCapabilities,
34
+ resolveCreationMemoryCapabilities,
35
+ } from "../capabilities.js";
36
+ import { isActiveMemoryStatus } from "../memory-lifecycle-ledger-utils.js";
37
+ import { deindexMemory } from "../temporal-index.js";
38
+ import { extractTopics } from "../topics.js";
39
+ import { log } from "../logger.js";
40
+ import path from "node:path";
41
+ import { mkdir, writeFile } from "node:fs/promises";
42
+ import type { StorageManager } from "../index.js";
43
+ import type { ExtractionEngine } from "../extraction.js";
44
+ import type { EmbeddingFallback } from "../embedding-fallback.js";
45
+ import type {
46
+ PluginConfig,
47
+ MemoryFile,
48
+ MemoryActionEvent,
49
+ MemorySummary,
50
+ } from "../types.js";
51
+
52
+ /** Dependencies injected by the orchestrator. All stable references or
53
+ * live accessors. */
54
+ export interface LifecyclePolicyCoordinatorDeps {
55
+ config: PluginConfig;
56
+ /** Live accessor: the orchestrator's storage manager (stable post-ctor). */
57
+ getStorage: () => StorageManager;
58
+ /** The extraction engine — used for summarization. */
59
+ extraction: ExtractionEngine;
60
+ /** The embedding-fallback manager used for index cleanup on archival. */
61
+ embeddingFallback: EmbeddingFallback;
62
+ /** Effective lifecycle thresholds (promote/stale/archive). Delegated to
63
+ * the orchestrator which owns runtime-policy-values overlay. */
64
+ getEffectiveLifecycleThresholds: () => {
65
+ promoteHeatThreshold: number;
66
+ staleDecayThreshold: number;
67
+ archiveDecayThreshold: number;
68
+ };
69
+ /** Remove a memory's content-hash entry from the storage-scoped index.
70
+ * Delegated to the orchestrator which owns the per-storage index map. */
71
+ removeContentHashForMemory: (
72
+ targetStorage: StorageManager,
73
+ memory: MemoryFile,
74
+ context: string,
75
+ ) => Promise<void>;
76
+ /** Persist all dirty content-hash indexes to disk. */
77
+ saveContentHashIndexes: () => Promise<void>;
78
+ }
79
+
80
+ /**
81
+ * Coordinates the memory-lifecycle policy pipeline. Holds no mutable
82
+ * state of its own — all persistence flows through the injected storage
83
+ * managers and callbacks.
84
+ */
85
+ export class LifecyclePolicyCoordinator {
86
+ constructor(
87
+ private readonly deps: LifecyclePolicyCoordinatorDeps,
88
+ ) {}
89
+
90
+ private get config(): PluginConfig {
91
+ return this.deps.config;
92
+ }
93
+
94
+ // -------------------------------------------------------------------------
95
+ // Action-outcome priors (feeds lifecycle transition decisions)
96
+ // -------------------------------------------------------------------------
97
+
98
+ actionOutcomePriorDelta(event: MemoryActionEvent): number {
99
+ if (event.outcome === "failed") return -0.3;
100
+ if (event.policyDecision === "deny") return -0.22;
101
+ if (event.policyDecision === "defer") return -0.14;
102
+ if (event.outcome === "skipped") return -0.1;
103
+
104
+ if (event.outcome !== "applied") return 0;
105
+ switch (event.action) {
106
+ case "store_episode":
107
+ case "store_note":
108
+ case "update_note":
109
+ return 0.08;
110
+ case "create_artifact":
111
+ case "summarize_node":
112
+ case "link_graph":
113
+ return 0.04;
114
+ case "discard":
115
+ return -0.03;
116
+ default:
117
+ return 0;
118
+ }
119
+ }
120
+
121
+ async buildLifecycleActionPriors(
122
+ storage: StorageManager = this.deps.getStorage(),
123
+ ): Promise<Map<string, number>> {
124
+ const events = await storage.readMemoryActionEvents(1200);
125
+ if (events.length === 0) return new Map<string, number>();
126
+
127
+ const nowMs = Date.now();
128
+ const windowMs = 14 * 24 * 60 * 60 * 1000;
129
+ const byMemory = new Map<
130
+ string,
131
+ Array<{ weightedDelta: number; weight: number }>
132
+ >();
133
+
134
+ for (const event of events) {
135
+ if (
136
+ typeof event.memoryId !== "string" ||
137
+ event.memoryId.trim().length === 0
138
+ )
139
+ continue;
140
+ const ts = Date.parse(event.timestamp);
141
+ if (!Number.isFinite(ts)) continue;
142
+ const ageMs = nowMs - ts;
143
+ if (ageMs < 0 || ageMs > windowMs) continue;
144
+
145
+ const delta = this.actionOutcomePriorDelta(event);
146
+ if (delta === 0) continue;
147
+
148
+ const recencyWeight = Math.max(0.2, 1 - ageMs / windowMs);
149
+ const list = byMemory.get(event.memoryId) ?? [];
150
+ if (list.length >= 8) list.shift();
151
+ list.push({
152
+ weightedDelta: delta * recencyWeight,
153
+ weight: recencyWeight,
154
+ });
155
+ byMemory.set(event.memoryId, list);
156
+ }
157
+
158
+ const out = new Map<string, number>();
159
+ for (const [memoryId, deltas] of byMemory.entries()) {
160
+ if (deltas.length === 0) continue;
161
+ const weightedSum = deltas.reduce(
162
+ (sum, item) => sum + item.weightedDelta,
163
+ 0,
164
+ );
165
+ const weightTotal = deltas.reduce((sum, item) => sum + item.weight, 0);
166
+ if (weightTotal <= 0) continue;
167
+ const score = weightedSum / weightTotal;
168
+ out.set(memoryId, Math.max(-0.25, Math.min(0.15, score)));
169
+ }
170
+ return out;
171
+ }
172
+
173
+ // -------------------------------------------------------------------------
174
+ // Lifecycle policy pass (heat/decay scoring + transition)
175
+ // -------------------------------------------------------------------------
176
+
177
+ async runLifecyclePolicyPass(
178
+ allMemories: MemoryFile[],
179
+ storage: StorageManager = this.deps.getStorage(),
180
+ ): Promise<number> {
181
+ const now = new Date();
182
+ const nowIso = now.toISOString();
183
+ const countsByState: Record<LifecycleState, number> = {
184
+ candidate: 0,
185
+ validated: 0,
186
+ active: 0,
187
+ stale: 0,
188
+ archived: 0,
189
+ };
190
+ const transitionCounts: Record<string, number> = {};
191
+ let updatedCount = 0;
192
+ let disputedCount = 0;
193
+ let evaluatedCount = 0;
194
+ const lifecycleCaps = resolveMemoryLifecycleCapabilities(this.config);
195
+
196
+ const thresholds = this.deps.getEffectiveLifecycleThresholds();
197
+ const policy = {
198
+ promoteHeatThreshold: thresholds.promoteHeatThreshold,
199
+ staleDecayThreshold: thresholds.staleDecayThreshold,
200
+ archiveDecayThreshold: thresholds.archiveDecayThreshold,
201
+ protectedCategories: this.config.lifecycleProtectedCategories,
202
+ };
203
+ const actionPriors = await this.buildLifecycleActionPriors(storage);
204
+
205
+ for (const memory of allMemories) {
206
+ if (
207
+ memory.frontmatter.status === "superseded" ||
208
+ memory.frontmatter.status === "forgotten"
209
+ ) {
210
+ continue;
211
+ }
212
+ evaluatedCount += 1;
213
+ const currentState = resolveLifecycleState(memory.frontmatter);
214
+ const actionPriorScore = actionPriors.get(memory.frontmatter.id);
215
+ const signals: LifecycleSignals | undefined =
216
+ typeof actionPriorScore === "number" &&
217
+ Number.isFinite(actionPriorScore)
218
+ ? { actionPriorScore }
219
+ : undefined;
220
+ const decision = decideLifecycleTransition(memory, policy, now, signals);
221
+ const nextState: LifecycleState =
222
+ memory.frontmatter.status === "archived"
223
+ ? "archived"
224
+ : decision.nextState;
225
+
226
+ countsByState[nextState] += 1;
227
+ if (memory.frontmatter.verificationState === "disputed") {
228
+ disputedCount += 1;
229
+ }
230
+ if (nextState !== currentState) {
231
+ const key = `${currentState}->${nextState}`;
232
+ transitionCounts[key] = (transitionCounts[key] ?? 0) + 1;
233
+ }
234
+
235
+ const prevHeat = memory.frontmatter.heatScore;
236
+ const prevDecay = memory.frontmatter.decayScore;
237
+ const scoreDelta =
238
+ Math.abs((prevHeat ?? -1) - decision.heatScore) +
239
+ Math.abs((prevDecay ?? -1) - decision.decayScore);
240
+ const shouldPersist =
241
+ memory.frontmatter.lifecycleState !== nextState ||
242
+ memory.frontmatter.heatScore === undefined ||
243
+ memory.frontmatter.decayScore === undefined ||
244
+ memory.frontmatter.lastValidatedAt === undefined ||
245
+ scoreDelta >= 0.01;
246
+
247
+ if (!shouldPersist) continue;
248
+
249
+ const wrote = await storage.writeMemoryFrontmatter(memory, {
250
+ lifecycleState: nextState,
251
+ heatScore: decision.heatScore,
252
+ decayScore: decision.decayScore,
253
+ lastValidatedAt: nowIso,
254
+ });
255
+ if (wrote) updatedCount += 1;
256
+ }
257
+
258
+ // Report how many memories had frontmatter rewritten so callers can record a
259
+ // catalog write touch for lifecycle-only passes (codex NR-tS).
260
+ if (!lifecycleCaps.lifecycleMetrics) return updatedCount;
261
+
262
+ const total = evaluatedCount;
263
+ const metrics = {
264
+ generatedAt: nowIso,
265
+ memoriesEvaluated: total,
266
+ memoriesUpdated: updatedCount,
267
+ countsByLifecycleState: countsByState,
268
+ transitionCounts,
269
+ staleRatio: total > 0 ? countsByState.stale / total : 0,
270
+ disputedRatio: total > 0 ? disputedCount / total : 0,
271
+ policy: {
272
+ promoteHeatThreshold: thresholds.promoteHeatThreshold,
273
+ staleDecayThreshold: thresholds.staleDecayThreshold,
274
+ archiveDecayThreshold: thresholds.archiveDecayThreshold,
275
+ protectedCategories: this.config.lifecycleProtectedCategories,
276
+ },
277
+ };
278
+ const metricsPath = path.join(
279
+ storage.dir,
280
+ "state",
281
+ "lifecycle-metrics.json",
282
+ );
283
+ await mkdir(path.dirname(metricsPath), { recursive: true });
284
+ await writeFile(metricsPath, JSON.stringify(metrics, null, 2), "utf-8");
285
+ return updatedCount;
286
+ }
287
+
288
+ // -------------------------------------------------------------------------
289
+ // Fact archival
290
+ // -------------------------------------------------------------------------
291
+
292
+ /**
293
+ * Archive old, low-importance, rarely-accessed facts (v6.0).
294
+ * Moves eligible facts from facts/ to archive/YYYY-MM-DD/.
295
+ * Returns the number of archived facts.
296
+ */
297
+ async runFactArchival(
298
+ allMemories: MemoryFile[],
299
+ ): Promise<number> {
300
+ const storage = this.deps.getStorage();
301
+ const now = Date.now();
302
+ const ageCutoffMs = this.config.factArchivalAgeDays * 24 * 60 * 60 * 1000;
303
+ const protectedCategories = new Set(
304
+ this.config.factArchivalProtectedCategories,
305
+ );
306
+ let archivedCount = 0;
307
+
308
+ for (const memory of allMemories) {
309
+ const fm = memory.frontmatter;
310
+
311
+ // Skip already-archived or superseded
312
+ if (fm.status && fm.status !== "active") continue;
313
+
314
+ // Skip protected categories
315
+ if (protectedCategories.has(fm.category)) continue;
316
+
317
+ // Skip corrections (always keep)
318
+ if (fm.category === "correction") continue;
319
+
320
+ // Check age requirement
321
+ const createdMs = new Date(fm.created).getTime();
322
+ if (now - createdMs < ageCutoffMs) continue;
323
+
324
+ // Check importance (only archive low-importance facts)
325
+ const importanceScore = fm.importance?.score ?? 0.5;
326
+ if (importanceScore >= this.config.factArchivalMaxImportance) continue;
327
+
328
+ // Check access count
329
+ const accessCount = fm.accessCount ?? 0;
330
+ if (accessCount > this.config.factArchivalMaxAccessCount) continue;
331
+
332
+ // All criteria met — archive
333
+ const result = await storage.archiveMemory(memory);
334
+ if (result) {
335
+ // Remove from the same storage-scoped content-hash index since it is
336
+ // no longer in hot search.
337
+ await this.deps.removeContentHashForMemory(
338
+ storage,
339
+ memory,
340
+ "fact-archival",
341
+ );
342
+ await this.deps.embeddingFallback.removeFromIndex(memory.frontmatter.id);
343
+ if (
344
+ resolveIndexingCapabilities(this.config).queryAwareIndexing &&
345
+ memory.path &&
346
+ memory.frontmatter?.created
347
+ ) {
348
+ deindexMemory(
349
+ this.config.memoryDir,
350
+ memory.path,
351
+ memory.frontmatter.created,
352
+ memory.frontmatter.tags ?? [],
353
+ );
354
+ }
355
+ archivedCount++;
356
+ }
357
+ }
358
+
359
+ // Save hash indexes if we removed any entries.
360
+ if (archivedCount > 0) {
361
+ await this.deps.saveContentHashIndexes().catch((err) =>
362
+ log.warn(`content-hash index save failed during archival: ${err}`),
363
+ );
364
+ }
365
+
366
+ return archivedCount;
367
+ }
368
+
369
+ // -------------------------------------------------------------------------
370
+ // Summarization (Phase 4A)
371
+ // -------------------------------------------------------------------------
372
+
373
+ /**
374
+ * Run memory summarization if memory count exceeds threshold (Phase 4A).
375
+ */
376
+ async runSummarization(
377
+ allMemories: MemoryFile[],
378
+ ): Promise<void> {
379
+ const storage = this.deps.getStorage();
380
+ // Only active memories count toward the threshold
381
+ const activeMemories = allMemories.filter(
382
+ (m) => isActiveMemoryStatus(m.frontmatter.status),
383
+ );
384
+
385
+ if (activeMemories.length < this.config.summarizationTriggerCount) {
386
+ return;
387
+ }
388
+
389
+ log.info(
390
+ `memory count (${activeMemories.length}) exceeds threshold (${this.config.summarizationTriggerCount}) — running summarization`,
391
+ );
392
+
393
+ // Sort by creation date, oldest first
394
+ const sorted = activeMemories.sort(
395
+ (a, b) =>
396
+ new Date(a.frontmatter.created).getTime() -
397
+ new Date(b.frontmatter.created).getTime(),
398
+ );
399
+
400
+ // Keep recent memories, with explicit zero handling so `slice(-0)` does not
401
+ // accidentally keep every memory out of the summarization candidate set.
402
+ const recentToKeep = Math.max(0, this.config.summarizationRecentToKeep);
403
+ const toSummarize = recentToKeep > 0 ? sorted.slice(0, -recentToKeep) : sorted;
404
+
405
+ // Filter candidates for summarization
406
+ const candidates = toSummarize.filter((m) => {
407
+ // Skip if protected by entity reference
408
+ if (m.frontmatter.entityRef) return false;
409
+
410
+ // Skip if protected by tag
411
+ const protectedTags = this.config.summarizationProtectedTags;
412
+ if (m.frontmatter.tags.some((t) => protectedTags.includes(t)))
413
+ return false;
414
+
415
+ // Skip if importance is above threshold
416
+ const importance = m.frontmatter.importance?.score ?? 0.5;
417
+ if (importance >= this.config.summarizationImportanceThreshold)
418
+ return false;
419
+
420
+ return true;
421
+ });
422
+
423
+ if (candidates.length < 50) {
424
+ log.debug(
425
+ `only ${candidates.length} candidates for summarization — skipping`,
426
+ );
427
+ return;
428
+ }
429
+
430
+ // Summarize in batches of 50
431
+ const batchSize = 50;
432
+ for (let i = 0; i < candidates.length; i += batchSize) {
433
+ const batch = candidates.slice(i, i + batchSize);
434
+ const batchData = batch.map((m) => ({
435
+ id: m.frontmatter.id,
436
+ content: m.content,
437
+ category: m.frontmatter.category,
438
+ created: m.frontmatter.created,
439
+ }));
440
+
441
+ const result = await this.deps.extraction.summarizeMemories(batchData);
442
+ if (!result) continue;
443
+
444
+ // Create summary
445
+ const summary: MemorySummary = {
446
+ id: `summary-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`,
447
+ createdAt: new Date().toISOString(),
448
+ timeRangeStart: batch[0].frontmatter.created,
449
+ timeRangeEnd: batch[batch.length - 1].frontmatter.created,
450
+ summaryText: result.summaryText,
451
+ keyFacts: result.keyFacts,
452
+ keyEntities: result.keyEntities,
453
+ sourceEpisodeIds: batch.map((m) => m.frontmatter.id),
454
+ };
455
+
456
+ await storage.writeSummary(summary);
457
+
458
+ // Archive source memories
459
+ const archived = await storage.archiveMemories(
460
+ batch.map((m) => m.frontmatter.id),
461
+ summary.id,
462
+ );
463
+
464
+ // Catalog write touch (issue #1499 sweep): summarization writes a durable
465
+ // summary and then rewrites source-memory archive status, bypassing the
466
+ // extraction write path. Record the touch after both mutations complete so
467
+ // `lastWriteAt` covers the final archived-state write.
468
+ // #1522: catalog touch handled at the storage chokepoint.
469
+
470
+ log.info(
471
+ `created summary ${summary.id} from ${batch.length} memories, archived ${archived}`,
472
+ );
473
+ }
474
+ }
475
+
476
+ // -------------------------------------------------------------------------
477
+ // Topic extraction (Phase 4B)
478
+ // -------------------------------------------------------------------------
479
+
480
+ /**
481
+ * Run topic extraction on all memories (Phase 4B).
482
+ */
483
+ async runTopicExtraction(
484
+ allMemories: MemoryFile[],
485
+ ): Promise<void> {
486
+ const storage = this.deps.getStorage();
487
+ // Only extract from active memories
488
+ const activeMemories = allMemories.filter(
489
+ (m) => isActiveMemoryStatus(m.frontmatter.status),
490
+ );
491
+
492
+ if (activeMemories.length === 0) return;
493
+
494
+ const topics = extractTopics(
495
+ activeMemories,
496
+ this.config.topicExtractionTopN,
497
+ );
498
+ await storage.saveTopics(topics);
499
+
500
+ log.debug(
501
+ `extracted ${topics.length} topics from ${activeMemories.length} memories`,
502
+ );
503
+ }
504
+ }
@@ -19,6 +19,10 @@
19
19
  * `orchestrator.requestQmdMaintenance` etc. continue to work.
20
20
  */
21
21
 
22
+ import {
23
+ resolveNamespaceCapabilities,
24
+ resolveQmdCapabilities,
25
+ } from "../capabilities.js";
22
26
  import { existsSync } from "node:fs";
23
27
  import path from "node:path";
24
28
 
@@ -403,7 +407,7 @@ export class MaintenanceScheduler {
403
407
  /** Internal: queue a debounced QMD maintenance pass. */
404
408
  private requestQmdMaintenance(): void {
405
409
  if (!this.deps.getQmd().isAvailable()) return;
406
- if (!this.deps.config.qmdMaintenanceEnabled) return;
410
+ if (!resolveQmdCapabilities(this.deps.config).qmdMaintenance) return;
407
411
 
408
412
  this.qmdMaintenancePending = true;
409
413
  if (this.qmdMaintenanceTimer) return;
@@ -437,7 +441,7 @@ export class MaintenanceScheduler {
437
441
  this.qmdMaintenancePending = false;
438
442
 
439
443
  try {
440
- if (this.deps.config.namespacesEnabled) {
444
+ if (resolveNamespaceCapabilities(this.deps.config).namespaces) {
441
445
  // Include cataloged dynamic namespaces, not just the configured set
442
446
  // (NGnei), but run through the namespace-aware maintenance planner so
443
447
  // each namespace is budgeted, lock-protected, and status-recorded
@@ -446,7 +450,7 @@ export class MaintenanceScheduler {
446
450
  const now = Date.now();
447
451
  const lastEmbedAtByNamespace = this.lastQmdEmbedAtMsByNamespace;
448
452
  const dueEmbedNamespaces = (namespaces: string[]): string[] => {
449
- if (!this.deps.config.qmdAutoEmbedEnabled) return [];
453
+ if (!resolveQmdCapabilities(this.deps.config).qmdAutoEmbed) return [];
450
454
  return namespaces.filter(
451
455
  (namespace) =>
452
456
  now - (lastEmbedAtByNamespace.get(namespace) ?? 0) >=
@@ -514,7 +518,7 @@ export class MaintenanceScheduler {
514
518
  await this.deps.getQmd().update();
515
519
  const now = Date.now();
516
520
  if (
517
- this.deps.config.qmdAutoEmbedEnabled &&
521
+ resolveQmdCapabilities(this.deps.config).qmdAutoEmbed &&
518
522
  now - this.lastQmdEmbedAtMs >= this.deps.config.qmdEmbedMinIntervalMs
519
523
  ) {
520
524
  await this.deps.getQmd().embed();