@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
@@ -7,10 +7,13 @@ import {
7
7
  } from "./chunk-OZECYVGI.js";
8
8
  import {
9
9
  CompressionGuidelineCoordinator
10
- } from "./chunk-SYX73XD7.js";
10
+ } from "./chunk-IXGXALRV.js";
11
11
  import {
12
12
  MaintenanceScheduler
13
- } from "./chunk-CGPHMNL4.js";
13
+ } from "./chunk-GYICIICQ.js";
14
+ import {
15
+ runPeerProfileReasoner
16
+ } from "./chunk-I74SUMNI.js";
14
17
  import {
15
18
  migrateFromEngram
16
19
  } from "./chunk-7HYPN2GC.js";
@@ -26,7 +29,7 @@ import {
26
29
  import {
27
30
  CompoundingEngine,
28
31
  defaultTierMigrationCycleBudget
29
- } from "./chunk-ZVHRSR2R.js";
32
+ } from "./chunk-IPI45Q4S.js";
30
33
  import {
31
34
  SharedContextManager
32
35
  } from "./chunk-UFS7OXGL.js";
@@ -60,7 +63,7 @@ import {
60
63
  } from "./chunk-UHGBNIOS.js";
61
64
  import {
62
65
  HourlySummarizer
63
- } from "./chunk-DKT3X5C3.js";
66
+ } from "./chunk-HFXZIF3V.js";
64
67
  import {
65
68
  buildTargetedFactRecallSection,
66
69
  shouldRecallTargetedFactEvidence
@@ -157,7 +160,7 @@ import {
157
160
  } from "./chunk-LTHVM4XN.js";
158
161
  import {
159
162
  ExtractionEngine
160
- } from "./chunk-NIZQH6AU.js";
163
+ } from "./chunk-FF36YNKY.js";
161
164
  import {
162
165
  parseMemoryActionEligibilityContext
163
166
  } from "./chunk-5GSUBCZM.js";
@@ -166,7 +169,7 @@ import {
166
169
  } from "./chunk-PWFWCGOO.js";
167
170
  import {
168
171
  LocalLlmClient
169
- } from "./chunk-24D66MMN.js";
172
+ } from "./chunk-IX4L7E5G.js";
170
173
  import {
171
174
  buildFocusedListRecallSection,
172
175
  shouldRecallFocusedListEvidence
@@ -190,12 +193,12 @@ import {
190
193
  } from "./chunk-Q6IP2ARR.js";
191
194
  import {
192
195
  EmbeddingFallback
193
- } from "./chunk-P3VJCTVE.js";
196
+ } from "./chunk-CHJIWG2H.js";
194
197
  import {
195
198
  buildEntityRecallSection,
196
199
  entityRecentTranscriptLookbackHours,
197
200
  readRecentEntityTranscriptEntries
198
- } from "./chunk-OTQE66IX.js";
201
+ } from "./chunk-AESC5OQJ.js";
199
202
  import {
200
203
  RoutingRulesStore
201
204
  } from "./chunk-WIWPSQYU.js";
@@ -225,14 +228,14 @@ import {
225
228
  import {
226
229
  runNamespaceMaintenanceFanout,
227
230
  summarizeNamespaceMaintenanceHealth
228
- } from "./chunk-KSJCXXOU.js";
231
+ } from "./chunk-AE7NTZ75.js";
229
232
  import {
230
233
  NamespaceCatalog,
231
234
  planNamespaceMaintenance
232
- } from "./chunk-FFUCCKPN.js";
235
+ } from "./chunk-BXPG5AVX.js";
233
236
  import {
234
237
  NamespaceStorageRouter
235
- } from "./chunk-ZQUAVZNG.js";
238
+ } from "./chunk-NNJKEAP2.js";
236
239
  import {
237
240
  searchHarmonicRetrieval
238
241
  } from "./chunk-AV5ZEH4M.js";
@@ -330,14 +333,14 @@ import {
330
333
  resolveNamespaceFromStorageDir,
331
334
  resolveScopePlan,
332
335
  resolveScopeProfilePlan
333
- } from "./chunk-J6BH2OBA.js";
336
+ } from "./chunk-GB2FZOWB.js";
334
337
  import {
335
338
  NamespaceSearchRouter
336
- } from "./chunk-KQYGNGON.js";
339
+ } from "./chunk-ZBZ4XULO.js";
337
340
  import {
338
341
  createConversationIndexRuntime,
339
342
  createSearchBackend
340
- } from "./chunk-HHNSLPX7.js";
343
+ } from "./chunk-5BOQNB2K.js";
341
344
  import {
342
345
  NoopSearchBackend
343
346
  } from "./chunk-CYEPCZN5.js";
@@ -360,14 +363,7 @@ import {
360
363
  } from "./chunk-QDW3E4RD.js";
361
364
  import {
362
365
  shouldSkipImplicitExtraction
363
- } from "./chunk-PMAQRUN4.js";
364
- import {
365
- resolveCapabilities,
366
- resolveCreationMemoryCapabilities,
367
- resolveGraphConstructionCapabilities,
368
- resolveIndexingCapabilities,
369
- resolveMemoryLifecycleCapabilities
370
- } from "./chunk-ESF7TRYJ.js";
366
+ } from "./chunk-NDKW67ER.js";
371
367
  import {
372
368
  searchCausalTrajectories
373
369
  } from "./chunk-SQNED75R.js";
@@ -469,7 +465,23 @@ import {
469
465
  defaultNamespaceForPrincipal,
470
466
  recallNamespacesForPrincipal,
471
467
  resolvePrincipal
472
- } from "./chunk-UZYLX7M6.js";
468
+ } from "./chunk-OYHYBHHI.js";
469
+ import {
470
+ resolveCapabilities,
471
+ resolveCompressionCapabilities,
472
+ resolveCreationMemoryCapabilities,
473
+ resolveEvalCapabilities,
474
+ resolveGraphConstructionCapabilities,
475
+ resolveIdentityContinuityCapabilities,
476
+ resolveIndexingCapabilities,
477
+ resolveLocalLlmCapabilities,
478
+ resolveMemoryLifecycleCapabilities,
479
+ resolveNamespaceCapabilities,
480
+ resolveObjectiveStateCapabilities,
481
+ resolveQmdCapabilities,
482
+ resolveSecurityCapabilities,
483
+ resolveUtilityLearningCapabilities
484
+ } from "./chunk-JWDE7OVJ.js";
473
485
  import {
474
486
  isSafeRouteNamespace,
475
487
  selectRouteRule
@@ -494,19 +506,19 @@ import {
494
506
  } from "./chunk-PVGDJXVK.js";
495
507
 
496
508
  // src/orchestrator.ts
497
- import path3 from "path";
509
+ import path4 from "path";
498
510
  import os2 from "os";
499
511
  import { createHash, randomBytes } from "crypto";
500
512
  import { existsSync, readFileSync } from "fs";
501
513
  import {
502
514
  lstat,
503
- mkdir as mkdir2,
515
+ mkdir as mkdir3,
504
516
  readdir,
505
517
  readFile as readFile2,
506
518
  realpath,
507
519
  stat,
508
520
  unlink,
509
- writeFile as writeFile2
521
+ writeFile as writeFile3
510
522
  } from "fs/promises";
511
523
 
512
524
  // src/procedural/procedure-recall.ts
@@ -587,7 +599,7 @@ var TierMigrationCoordinator = class {
587
599
  const { config, tierMigrationStatus } = this.deps;
588
600
  const dryRun = options?.dryRun === true;
589
601
  const persistSkipped = options?.force === true || trigger === "manual";
590
- if (!config.qmdTierMigrationEnabled && options?.force !== true) {
602
+ if (!resolveQmdCapabilities(config).qmdTierMigration && options?.force !== true) {
591
603
  const skipped = {
592
604
  trigger,
593
605
  scanned: 0,
@@ -601,7 +613,7 @@ var TierMigrationCoordinator = class {
601
613
  if (persistSkipped) await tierMigrationStatus.recordCycle(skipped);
602
614
  return skipped;
603
615
  }
604
- if (trigger === "maintenance" && !config.qmdTierAutoBackfillEnabled && options?.force !== true) {
616
+ if (trigger === "maintenance" && !resolveQmdCapabilities(config).qmdTierAutoBackfill && options?.force !== true) {
605
617
  const skipped = {
606
618
  trigger,
607
619
  scanned: 0,
@@ -649,7 +661,7 @@ var TierMigrationCoordinator = class {
649
661
  }
650
662
  const policy = applyUtilityPromotionRuntimePolicy(
651
663
  {
652
- enabled: config.qmdTierMigrationEnabled,
664
+ enabled: resolveQmdCapabilities(config).qmdTierMigration,
653
665
  demotionMinAgeDays: config.qmdTierDemotionMinAgeDays,
654
666
  demotionValueThreshold: config.qmdTierDemotionValueThreshold,
655
667
  promotionValueThreshold: config.qmdTierPromotionValueThreshold
@@ -684,7 +696,7 @@ var TierMigrationCoordinator = class {
684
696
  qmd: this.deps.getQmd(),
685
697
  hotCollection: config.qmdCollection,
686
698
  coldCollection: config.qmdColdCollection ?? `${config.qmdCollection}-cold`,
687
- autoEmbed: config.qmdAutoEmbedEnabled
699
+ autoEmbed: resolveQmdCapabilities(config).qmdAutoEmbed
688
700
  });
689
701
  let migrated = 0;
690
702
  let promoted = 0;
@@ -867,8 +879,560 @@ var ExtractionQueueCoordinator = class {
867
879
  * drain — used by the flush deadline test to simulate a busy queue and
868
880
  * assert a queued task's deadline expires while it waits.
869
881
  */
870
- setProcessingForTest(value) {
871
- this.processing = value;
882
+ setProcessingForTest(value) {
883
+ this.processing = value;
884
+ }
885
+ };
886
+
887
+ // src/orchestration/semantic-consolidation-coordinator.ts
888
+ var SemanticConsolidationCoordinator = class {
889
+ constructor(deps) {
890
+ this.deps = deps;
891
+ }
892
+ deps;
893
+ get config() {
894
+ return this.deps.config;
895
+ }
896
+ async runSemanticConsolidation(options) {
897
+ const targetStorage = options?.storage ?? this.deps.getStorage();
898
+ const result = {
899
+ clustersFound: 0,
900
+ memoriesConsolidated: 0,
901
+ memoriesArchived: 0,
902
+ errors: 0,
903
+ clusters: []
904
+ };
905
+ if (!this.config.semanticConsolidationEnabled && !options?.force) {
906
+ log.debug("[semantic-consolidation] disabled in config");
907
+ return result;
908
+ }
909
+ log.info("[semantic-consolidation] starting run");
910
+ const allMemories = await targetStorage.readAllMemories();
911
+ if (allMemories.length < 10) {
912
+ log.debug("[semantic-consolidation] too few memories, skipping");
913
+ return result;
914
+ }
915
+ const threshold = options?.thresholdOverride ?? this.config.semanticConsolidationThreshold;
916
+ const clusters = findSimilarClusters(allMemories, {
917
+ threshold,
918
+ minClusterSize: this.config.semanticConsolidationMinClusterSize,
919
+ excludeCategories: this.config.semanticConsolidationExcludeCategories,
920
+ maxPerRun: this.config.semanticConsolidationMaxPerRun
921
+ });
922
+ result.clustersFound = clusters.length;
923
+ result.clusters = clusters;
924
+ if (clusters.length === 0) {
925
+ log.info("[semantic-consolidation] no clusters found");
926
+ return result;
927
+ }
928
+ log.info(`[semantic-consolidation] found ${clusters.length} cluster(s)`);
929
+ if (options?.dryRun) {
930
+ log.info(
931
+ "[semantic-consolidation] dry run \u2014 skipping LLM synthesis and archival"
932
+ );
933
+ return result;
934
+ }
935
+ const useGateway = this.config.modelSource === "gateway";
936
+ const modelSetting = this.config.semanticConsolidationModel;
937
+ if (modelSetting === "fast" && this.deps.getFastLlm() && !useGateway) {
938
+ log.info("[semantic-consolidation] using fast local LLM for synthesis");
939
+ }
940
+ const gatewayChainOptions = !useGateway ? {} : modelSetting === "fast" ? this.config.fastGatewayAgentId ? { agentId: this.config.fastGatewayAgentId } : this.config.gatewayAgentId ? { agentId: this.config.gatewayAgentId } : {} : gatewayTaskChainOptions(this.config);
941
+ const llm = new FallbackLlmClient(
942
+ this.config.gatewayConfig,
943
+ fallbackLlmRuntimeContextFromConfig(this.config)
944
+ );
945
+ if (!llm.isAvailable(gatewayChainOptions) && !(modelSetting === "fast" && this.deps.getFastLlm() && !useGateway)) {
946
+ log.warn(
947
+ "[semantic-consolidation] no LLM available \u2014 skipping synthesis"
948
+ );
949
+ return result;
950
+ }
951
+ let extensionsBlock = "";
952
+ try {
953
+ extensionsBlock = await buildExtensionsBlockForConsolidation(this.config);
954
+ } catch (err) {
955
+ log.warn(`[semantic-consolidation] extension discovery failed (non-fatal): ${err instanceof Error ? err.message : String(err)}`);
956
+ }
957
+ for (const cluster of clusters) {
958
+ let canonicalWriteCompleted = false;
959
+ try {
960
+ const operatorAwareEnabled = this.config.operatorAwareConsolidationEnabled === true;
961
+ let prompt = operatorAwareEnabled ? buildOperatorAwareConsolidationPrompt(cluster) : buildConsolidationPrompt(cluster);
962
+ if (extensionsBlock.length > 0) {
963
+ prompt += "\n\n" + extensionsBlock;
964
+ }
965
+ const messages = [
966
+ {
967
+ role: "system",
968
+ content: operatorAwareEnabled ? 'You are a memory consolidation system. Return ONLY a JSON object with two keys, "operator" and "output". The "operator" value MUST be one of the exact strings "merge", "update", or "split" \u2014 never a pipe-separated placeholder, never prose. The "output" value is the canonical memory text.' : "You are a memory consolidation system. Output only the consolidated memory text."
969
+ },
970
+ { role: "user", content: prompt }
971
+ ];
972
+ const llmOpts = { temperature: 0.2, maxTokens: 2e3 };
973
+ let response = null;
974
+ if (useGateway) {
975
+ response = await llm.chatCompletion(messages, { ...llmOpts, ...gatewayChainOptions });
976
+ } else if (modelSetting === "fast" && this.deps.getFastLlm()) {
977
+ const fastResult = await this.deps.getFastLlm().chatCompletion(messages, {
978
+ operation: "semantic-consolidation",
979
+ maxTokens: llmOpts.maxTokens,
980
+ temperature: llmOpts.temperature,
981
+ priority: "background",
982
+ forceDisableThinking: true
983
+ });
984
+ response = fastResult ? { content: fastResult.content } : null;
985
+ } else {
986
+ response = await llm.chatCompletion(messages, llmOpts);
987
+ }
988
+ if (!response?.content) {
989
+ log.warn(
990
+ `[semantic-consolidation] empty LLM response for cluster in "${cluster.category}"`
991
+ );
992
+ result.errors++;
993
+ continue;
994
+ }
995
+ let canonicalContent;
996
+ let operator;
997
+ if (operatorAwareEnabled) {
998
+ const parsed = parseOperatorAwareConsolidationResponse(
999
+ response.content,
1000
+ cluster
1001
+ );
1002
+ canonicalContent = parsed.output;
1003
+ operator = parsed.operator;
1004
+ } else {
1005
+ canonicalContent = parseConsolidationResponse(response.content);
1006
+ operator = chooseConsolidationOperator(cluster);
1007
+ }
1008
+ cluster.canonicalContent = canonicalContent;
1009
+ const sorted = [...cluster.memories].sort(
1010
+ (a, b) => new Date(b.frontmatter.created).getTime() - new Date(a.frontmatter.created).getTime()
1011
+ );
1012
+ const newest = sorted[0];
1013
+ const lineageIds = cluster.memories.map((m) => m.frontmatter.id);
1014
+ const derivedFromEntries = [];
1015
+ for (const m of cluster.memories) {
1016
+ if (!m.path) continue;
1017
+ const entry = await targetStorage.snapshotForProvenance(m.path);
1018
+ if (entry) derivedFromEntries.push(entry);
1019
+ }
1020
+ const { id: canonicalId, tombstoneBlocked: canonicalBlocked } = await targetStorage.writeMemory(
1021
+ newest.frontmatter.category,
1022
+ canonicalContent,
1023
+ {
1024
+ actor: "semantic-consolidation",
1025
+ confidence: newest.frontmatter.confidence,
1026
+ tags: [
1027
+ ...new Set(
1028
+ cluster.memories.flatMap((m) => m.frontmatter.tags ?? [])
1029
+ )
1030
+ ],
1031
+ source: "semantic-consolidation",
1032
+ lineage: lineageIds,
1033
+ derivedFrom: derivedFromEntries.length > 0 ? derivedFromEntries : void 0,
1034
+ derivedVia: operator
1035
+ }
1036
+ );
1037
+ if (canonicalBlocked) {
1038
+ log.info(`[semantic-consolidation] cluster in "${cluster.category}" tombstone-blocked \u2014 keeping ${cluster.memories.length} source(s) active (pending_review ${canonicalId})`);
1039
+ continue;
1040
+ }
1041
+ canonicalWriteCompleted = true;
1042
+ result.memoriesConsolidated++;
1043
+ for (const m of cluster.memories) {
1044
+ const archiveResult = await targetStorage.archiveMemory(m, {
1045
+ actor: "semantic-consolidation",
1046
+ reasonCode: "semantic-consolidation",
1047
+ relatedMemoryIds: [canonicalId]
1048
+ });
1049
+ if (archiveResult) {
1050
+ await this.deps.removeContentHashForMemory(
1051
+ targetStorage,
1052
+ m,
1053
+ "semantic-consolidation"
1054
+ );
1055
+ try {
1056
+ await this.deps.embeddingFallback.removeFromIndex(m.frontmatter.id);
1057
+ if (resolveIndexingCapabilities(this.config).queryAwareIndexing && m.path && m.frontmatter?.created) {
1058
+ deindexMemory(
1059
+ targetStorage.dir,
1060
+ m.path,
1061
+ m.frontmatter.created,
1062
+ m.frontmatter.tags ?? []
1063
+ );
1064
+ }
1065
+ } catch (cleanupErr) {
1066
+ log.warn(
1067
+ `[semantic-consolidation] index cleanup failed (non-fatal): ${cleanupErr}`
1068
+ );
1069
+ }
1070
+ result.memoriesArchived++;
1071
+ }
1072
+ }
1073
+ log.info(
1074
+ `[semantic-consolidation] consolidated ${cluster.memories.length} memories \u2192 ${canonicalId}`
1075
+ );
1076
+ } catch (err) {
1077
+ log.warn(
1078
+ `[semantic-consolidation] cluster processing failed: ${err instanceof Error ? err.message : String(err)}`
1079
+ );
1080
+ result.errors++;
1081
+ } finally {
1082
+ if (canonicalWriteCompleted) {
1083
+ }
1084
+ }
1085
+ }
1086
+ if (result.memoriesArchived > 0) {
1087
+ await this.deps.saveContentHashIndexes().catch(
1088
+ (err) => log.warn(
1089
+ `[semantic-consolidation] content-hash index save failed: ${err}`
1090
+ )
1091
+ );
1092
+ }
1093
+ log.info(
1094
+ `[semantic-consolidation] complete: clusters=${result.clustersFound}, consolidated=${result.memoriesConsolidated}, archived=${result.memoriesArchived}, errors=${result.errors}`
1095
+ );
1096
+ try {
1097
+ await materializeAfterSemanticConsolidation({
1098
+ config: this.config,
1099
+ memoryDir: targetStorage.dir
1100
+ });
1101
+ } catch (err) {
1102
+ log.warn(
1103
+ `[semantic-consolidation] Codex materialize post-hook failed (non-fatal): ${err instanceof Error ? err.message : String(err)}`
1104
+ );
1105
+ }
1106
+ if (this.config.peerProfileReasonerEnabled) {
1107
+ try {
1108
+ const peerLlm = new FallbackLlmClient(
1109
+ this.config.gatewayConfig,
1110
+ fallbackLlmRuntimeContextFromConfig(this.config)
1111
+ );
1112
+ const peerResult = await runPeerProfileReasoner({
1113
+ memoryDir: targetStorage.dir,
1114
+ enabled: true,
1115
+ llm: peerLlm,
1116
+ model: this.config.peerProfileReasonerModel,
1117
+ minInteractions: this.config.peerProfileReasonerMinInteractions,
1118
+ maxFieldsPerRun: this.config.peerProfileReasonerMaxFieldsPerRun,
1119
+ log: {
1120
+ debug: (msg) => log.debug(msg),
1121
+ info: (msg) => log.info(msg),
1122
+ warn: (msg) => log.warn(msg)
1123
+ }
1124
+ });
1125
+ log.info(
1126
+ `[peer-profile-reasoner] complete: peers=${peerResult.peersConsidered}, processed=${peerResult.peersProcessed}, fields=${peerResult.fieldsApplied}`
1127
+ );
1128
+ } catch (err) {
1129
+ log.warn(
1130
+ `[peer-profile-reasoner] post-consolidation hook failed (non-fatal): ${err instanceof Error ? err.message : String(err)}`
1131
+ );
1132
+ }
1133
+ }
1134
+ return result;
1135
+ }
1136
+ };
1137
+
1138
+ // src/orchestration/lifecycle-policy-coordinator.ts
1139
+ import path2 from "path";
1140
+ import { mkdir, writeFile } from "fs/promises";
1141
+ var LifecyclePolicyCoordinator = class {
1142
+ constructor(deps) {
1143
+ this.deps = deps;
1144
+ }
1145
+ deps;
1146
+ get config() {
1147
+ return this.deps.config;
1148
+ }
1149
+ // -------------------------------------------------------------------------
1150
+ // Action-outcome priors (feeds lifecycle transition decisions)
1151
+ // -------------------------------------------------------------------------
1152
+ actionOutcomePriorDelta(event) {
1153
+ if (event.outcome === "failed") return -0.3;
1154
+ if (event.policyDecision === "deny") return -0.22;
1155
+ if (event.policyDecision === "defer") return -0.14;
1156
+ if (event.outcome === "skipped") return -0.1;
1157
+ if (event.outcome !== "applied") return 0;
1158
+ switch (event.action) {
1159
+ case "store_episode":
1160
+ case "store_note":
1161
+ case "update_note":
1162
+ return 0.08;
1163
+ case "create_artifact":
1164
+ case "summarize_node":
1165
+ case "link_graph":
1166
+ return 0.04;
1167
+ case "discard":
1168
+ return -0.03;
1169
+ default:
1170
+ return 0;
1171
+ }
1172
+ }
1173
+ async buildLifecycleActionPriors(storage = this.deps.getStorage()) {
1174
+ const events = await storage.readMemoryActionEvents(1200);
1175
+ if (events.length === 0) return /* @__PURE__ */ new Map();
1176
+ const nowMs = Date.now();
1177
+ const windowMs = 14 * 24 * 60 * 60 * 1e3;
1178
+ const byMemory = /* @__PURE__ */ new Map();
1179
+ for (const event of events) {
1180
+ if (typeof event.memoryId !== "string" || event.memoryId.trim().length === 0)
1181
+ continue;
1182
+ const ts = Date.parse(event.timestamp);
1183
+ if (!Number.isFinite(ts)) continue;
1184
+ const ageMs = nowMs - ts;
1185
+ if (ageMs < 0 || ageMs > windowMs) continue;
1186
+ const delta = this.actionOutcomePriorDelta(event);
1187
+ if (delta === 0) continue;
1188
+ const recencyWeight = Math.max(0.2, 1 - ageMs / windowMs);
1189
+ const list = byMemory.get(event.memoryId) ?? [];
1190
+ if (list.length >= 8) list.shift();
1191
+ list.push({
1192
+ weightedDelta: delta * recencyWeight,
1193
+ weight: recencyWeight
1194
+ });
1195
+ byMemory.set(event.memoryId, list);
1196
+ }
1197
+ const out = /* @__PURE__ */ new Map();
1198
+ for (const [memoryId, deltas] of byMemory.entries()) {
1199
+ if (deltas.length === 0) continue;
1200
+ const weightedSum = deltas.reduce(
1201
+ (sum, item) => sum + item.weightedDelta,
1202
+ 0
1203
+ );
1204
+ const weightTotal = deltas.reduce((sum, item) => sum + item.weight, 0);
1205
+ if (weightTotal <= 0) continue;
1206
+ const score = weightedSum / weightTotal;
1207
+ out.set(memoryId, Math.max(-0.25, Math.min(0.15, score)));
1208
+ }
1209
+ return out;
1210
+ }
1211
+ // -------------------------------------------------------------------------
1212
+ // Lifecycle policy pass (heat/decay scoring + transition)
1213
+ // -------------------------------------------------------------------------
1214
+ async runLifecyclePolicyPass(allMemories, storage = this.deps.getStorage()) {
1215
+ const now = /* @__PURE__ */ new Date();
1216
+ const nowIso = now.toISOString();
1217
+ const countsByState = {
1218
+ candidate: 0,
1219
+ validated: 0,
1220
+ active: 0,
1221
+ stale: 0,
1222
+ archived: 0
1223
+ };
1224
+ const transitionCounts = {};
1225
+ let updatedCount = 0;
1226
+ let disputedCount = 0;
1227
+ let evaluatedCount = 0;
1228
+ const lifecycleCaps = resolveMemoryLifecycleCapabilities(this.config);
1229
+ const thresholds = this.deps.getEffectiveLifecycleThresholds();
1230
+ const policy = {
1231
+ promoteHeatThreshold: thresholds.promoteHeatThreshold,
1232
+ staleDecayThreshold: thresholds.staleDecayThreshold,
1233
+ archiveDecayThreshold: thresholds.archiveDecayThreshold,
1234
+ protectedCategories: this.config.lifecycleProtectedCategories
1235
+ };
1236
+ const actionPriors = await this.buildLifecycleActionPriors(storage);
1237
+ for (const memory of allMemories) {
1238
+ if (memory.frontmatter.status === "superseded" || memory.frontmatter.status === "forgotten") {
1239
+ continue;
1240
+ }
1241
+ evaluatedCount += 1;
1242
+ const currentState = resolveLifecycleState(memory.frontmatter);
1243
+ const actionPriorScore = actionPriors.get(memory.frontmatter.id);
1244
+ const signals = typeof actionPriorScore === "number" && Number.isFinite(actionPriorScore) ? { actionPriorScore } : void 0;
1245
+ const decision = decideLifecycleTransition(memory, policy, now, signals);
1246
+ const nextState = memory.frontmatter.status === "archived" ? "archived" : decision.nextState;
1247
+ countsByState[nextState] += 1;
1248
+ if (memory.frontmatter.verificationState === "disputed") {
1249
+ disputedCount += 1;
1250
+ }
1251
+ if (nextState !== currentState) {
1252
+ const key = `${currentState}->${nextState}`;
1253
+ transitionCounts[key] = (transitionCounts[key] ?? 0) + 1;
1254
+ }
1255
+ const prevHeat = memory.frontmatter.heatScore;
1256
+ const prevDecay = memory.frontmatter.decayScore;
1257
+ const scoreDelta = Math.abs((prevHeat ?? -1) - decision.heatScore) + Math.abs((prevDecay ?? -1) - decision.decayScore);
1258
+ const shouldPersist = memory.frontmatter.lifecycleState !== nextState || memory.frontmatter.heatScore === void 0 || memory.frontmatter.decayScore === void 0 || memory.frontmatter.lastValidatedAt === void 0 || scoreDelta >= 0.01;
1259
+ if (!shouldPersist) continue;
1260
+ const wrote = await storage.writeMemoryFrontmatter(memory, {
1261
+ lifecycleState: nextState,
1262
+ heatScore: decision.heatScore,
1263
+ decayScore: decision.decayScore,
1264
+ lastValidatedAt: nowIso
1265
+ });
1266
+ if (wrote) updatedCount += 1;
1267
+ }
1268
+ if (!lifecycleCaps.lifecycleMetrics) return updatedCount;
1269
+ const total = evaluatedCount;
1270
+ const metrics = {
1271
+ generatedAt: nowIso,
1272
+ memoriesEvaluated: total,
1273
+ memoriesUpdated: updatedCount,
1274
+ countsByLifecycleState: countsByState,
1275
+ transitionCounts,
1276
+ staleRatio: total > 0 ? countsByState.stale / total : 0,
1277
+ disputedRatio: total > 0 ? disputedCount / total : 0,
1278
+ policy: {
1279
+ promoteHeatThreshold: thresholds.promoteHeatThreshold,
1280
+ staleDecayThreshold: thresholds.staleDecayThreshold,
1281
+ archiveDecayThreshold: thresholds.archiveDecayThreshold,
1282
+ protectedCategories: this.config.lifecycleProtectedCategories
1283
+ }
1284
+ };
1285
+ const metricsPath = path2.join(
1286
+ storage.dir,
1287
+ "state",
1288
+ "lifecycle-metrics.json"
1289
+ );
1290
+ await mkdir(path2.dirname(metricsPath), { recursive: true });
1291
+ await writeFile(metricsPath, JSON.stringify(metrics, null, 2), "utf-8");
1292
+ return updatedCount;
1293
+ }
1294
+ // -------------------------------------------------------------------------
1295
+ // Fact archival
1296
+ // -------------------------------------------------------------------------
1297
+ /**
1298
+ * Archive old, low-importance, rarely-accessed facts (v6.0).
1299
+ * Moves eligible facts from facts/ to archive/YYYY-MM-DD/.
1300
+ * Returns the number of archived facts.
1301
+ */
1302
+ async runFactArchival(allMemories) {
1303
+ const storage = this.deps.getStorage();
1304
+ const now = Date.now();
1305
+ const ageCutoffMs = this.config.factArchivalAgeDays * 24 * 60 * 60 * 1e3;
1306
+ const protectedCategories = new Set(
1307
+ this.config.factArchivalProtectedCategories
1308
+ );
1309
+ let archivedCount = 0;
1310
+ for (const memory of allMemories) {
1311
+ const fm = memory.frontmatter;
1312
+ if (fm.status && fm.status !== "active") continue;
1313
+ if (protectedCategories.has(fm.category)) continue;
1314
+ if (fm.category === "correction") continue;
1315
+ const createdMs = new Date(fm.created).getTime();
1316
+ if (now - createdMs < ageCutoffMs) continue;
1317
+ const importanceScore = fm.importance?.score ?? 0.5;
1318
+ if (importanceScore >= this.config.factArchivalMaxImportance) continue;
1319
+ const accessCount = fm.accessCount ?? 0;
1320
+ if (accessCount > this.config.factArchivalMaxAccessCount) continue;
1321
+ const result = await storage.archiveMemory(memory);
1322
+ if (result) {
1323
+ await this.deps.removeContentHashForMemory(
1324
+ storage,
1325
+ memory,
1326
+ "fact-archival"
1327
+ );
1328
+ await this.deps.embeddingFallback.removeFromIndex(memory.frontmatter.id);
1329
+ if (resolveIndexingCapabilities(this.config).queryAwareIndexing && memory.path && memory.frontmatter?.created) {
1330
+ deindexMemory(
1331
+ this.config.memoryDir,
1332
+ memory.path,
1333
+ memory.frontmatter.created,
1334
+ memory.frontmatter.tags ?? []
1335
+ );
1336
+ }
1337
+ archivedCount++;
1338
+ }
1339
+ }
1340
+ if (archivedCount > 0) {
1341
+ await this.deps.saveContentHashIndexes().catch(
1342
+ (err) => log.warn(`content-hash index save failed during archival: ${err}`)
1343
+ );
1344
+ }
1345
+ return archivedCount;
1346
+ }
1347
+ // -------------------------------------------------------------------------
1348
+ // Summarization (Phase 4A)
1349
+ // -------------------------------------------------------------------------
1350
+ /**
1351
+ * Run memory summarization if memory count exceeds threshold (Phase 4A).
1352
+ */
1353
+ async runSummarization(allMemories) {
1354
+ const storage = this.deps.getStorage();
1355
+ const activeMemories = allMemories.filter(
1356
+ (m) => isActiveMemoryStatus(m.frontmatter.status)
1357
+ );
1358
+ if (activeMemories.length < this.config.summarizationTriggerCount) {
1359
+ return;
1360
+ }
1361
+ log.info(
1362
+ `memory count (${activeMemories.length}) exceeds threshold (${this.config.summarizationTriggerCount}) \u2014 running summarization`
1363
+ );
1364
+ const sorted = activeMemories.sort(
1365
+ (a, b) => new Date(a.frontmatter.created).getTime() - new Date(b.frontmatter.created).getTime()
1366
+ );
1367
+ const recentToKeep = Math.max(0, this.config.summarizationRecentToKeep);
1368
+ const toSummarize = recentToKeep > 0 ? sorted.slice(0, -recentToKeep) : sorted;
1369
+ const candidates = toSummarize.filter((m) => {
1370
+ if (m.frontmatter.entityRef) return false;
1371
+ const protectedTags = this.config.summarizationProtectedTags;
1372
+ if (m.frontmatter.tags.some((t) => protectedTags.includes(t)))
1373
+ return false;
1374
+ const importance = m.frontmatter.importance?.score ?? 0.5;
1375
+ if (importance >= this.config.summarizationImportanceThreshold)
1376
+ return false;
1377
+ return true;
1378
+ });
1379
+ if (candidates.length < 50) {
1380
+ log.debug(
1381
+ `only ${candidates.length} candidates for summarization \u2014 skipping`
1382
+ );
1383
+ return;
1384
+ }
1385
+ const batchSize = 50;
1386
+ for (let i = 0; i < candidates.length; i += batchSize) {
1387
+ const batch = candidates.slice(i, i + batchSize);
1388
+ const batchData = batch.map((m) => ({
1389
+ id: m.frontmatter.id,
1390
+ content: m.content,
1391
+ category: m.frontmatter.category,
1392
+ created: m.frontmatter.created
1393
+ }));
1394
+ const result = await this.deps.extraction.summarizeMemories(batchData);
1395
+ if (!result) continue;
1396
+ const summary = {
1397
+ id: `summary-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`,
1398
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
1399
+ timeRangeStart: batch[0].frontmatter.created,
1400
+ timeRangeEnd: batch[batch.length - 1].frontmatter.created,
1401
+ summaryText: result.summaryText,
1402
+ keyFacts: result.keyFacts,
1403
+ keyEntities: result.keyEntities,
1404
+ sourceEpisodeIds: batch.map((m) => m.frontmatter.id)
1405
+ };
1406
+ await storage.writeSummary(summary);
1407
+ const archived = await storage.archiveMemories(
1408
+ batch.map((m) => m.frontmatter.id),
1409
+ summary.id
1410
+ );
1411
+ log.info(
1412
+ `created summary ${summary.id} from ${batch.length} memories, archived ${archived}`
1413
+ );
1414
+ }
1415
+ }
1416
+ // -------------------------------------------------------------------------
1417
+ // Topic extraction (Phase 4B)
1418
+ // -------------------------------------------------------------------------
1419
+ /**
1420
+ * Run topic extraction on all memories (Phase 4B).
1421
+ */
1422
+ async runTopicExtraction(allMemories) {
1423
+ const storage = this.deps.getStorage();
1424
+ const activeMemories = allMemories.filter(
1425
+ (m) => isActiveMemoryStatus(m.frontmatter.status)
1426
+ );
1427
+ if (activeMemories.length === 0) return;
1428
+ const topics = extractTopics(
1429
+ activeMemories,
1430
+ this.config.topicExtractionTopN
1431
+ );
1432
+ await storage.saveTopics(topics);
1433
+ log.debug(
1434
+ `extracted ${topics.length} topics from ${activeMemories.length} memories`
1435
+ );
872
1436
  }
873
1437
  };
874
1438
 
@@ -1204,8 +1768,8 @@ function generateResolverDocument(taxonomy) {
1204
1768
  }
1205
1769
 
1206
1770
  // src/taxonomy/taxonomy-loader.ts
1207
- import { readFile, mkdir, writeFile } from "fs/promises";
1208
- import path2 from "path";
1771
+ import { readFile, mkdir as mkdir2, writeFile as writeFile2 } from "fs/promises";
1772
+ import path3 from "path";
1209
1773
  var TAXONOMY_DIR = ".taxonomy";
1210
1774
  var TAXONOMY_FILE = "taxonomy.json";
1211
1775
  var MAX_SLUG_LENGTH = 32;
@@ -1303,7 +1867,7 @@ function validateTaxonomy(taxonomy) {
1303
1867
  }
1304
1868
  }
1305
1869
  async function loadTaxonomy(memoryDir) {
1306
- const taxonomyPath = path2.join(memoryDir, TAXONOMY_DIR, TAXONOMY_FILE);
1870
+ const taxonomyPath = path3.join(memoryDir, TAXONOMY_DIR, TAXONOMY_FILE);
1307
1871
  let raw;
1308
1872
  try {
1309
1873
  raw = await readFile(taxonomyPath, "utf-8");
@@ -1353,16 +1917,16 @@ async function loadTaxonomy(memoryDir) {
1353
1917
  }
1354
1918
  async function saveTaxonomy(memoryDir, taxonomy) {
1355
1919
  validateTaxonomy(taxonomy);
1356
- const dir = path2.join(memoryDir, TAXONOMY_DIR);
1357
- await mkdir(dir, { recursive: true });
1358
- const filePath = path2.join(dir, TAXONOMY_FILE);
1359
- await writeFile(filePath, JSON.stringify(taxonomy, null, 2) + "\n", "utf-8");
1920
+ const dir = path3.join(memoryDir, TAXONOMY_DIR);
1921
+ await mkdir2(dir, { recursive: true });
1922
+ const filePath = path3.join(dir, TAXONOMY_FILE);
1923
+ await writeFile2(filePath, JSON.stringify(taxonomy, null, 2) + "\n", "utf-8");
1360
1924
  }
1361
1925
  function getTaxonomyDir(memoryDir) {
1362
- return path2.join(memoryDir, TAXONOMY_DIR);
1926
+ return path3.join(memoryDir, TAXONOMY_DIR);
1363
1927
  }
1364
1928
  function getTaxonomyFilePath(memoryDir) {
1365
- return path2.join(memoryDir, TAXONOMY_DIR, TAXONOMY_FILE);
1929
+ return path3.join(memoryDir, TAXONOMY_DIR, TAXONOMY_FILE);
1366
1930
  }
1367
1931
 
1368
1932
  // src/wearables/registry.ts
@@ -2328,7 +2892,7 @@ async function raceRecallAbort(promise, signal, message = "recall aborted") {
2328
2892
  }
2329
2893
  }
2330
2894
  function qmdCollectionPathParts(resultPath) {
2331
- if (!resultPath || path3.isAbsolute(resultPath)) return null;
2895
+ if (!resultPath || path4.isAbsolute(resultPath)) return null;
2332
2896
  const normalized = resultPath.replace(/\\/g, "/").replace(/^\/+/, "");
2333
2897
  const slashIndex = normalized.indexOf("/");
2334
2898
  if (slashIndex <= 0 || slashIndex >= normalized.length - 1) return null;
@@ -2341,9 +2905,9 @@ function qmdCollectionPathParts(resultPath) {
2341
2905
  }
2342
2906
  function qmdResultPathCandidates(storageDir, resultPath) {
2343
2907
  const candidates = /* @__PURE__ */ new Set();
2344
- const storageRoot = path3.resolve(storageDir);
2908
+ const storageRoot = path4.resolve(storageDir);
2345
2909
  const addCandidate = (candidate) => {
2346
- const resolved = path3.resolve(candidate);
2910
+ const resolved = path4.resolve(candidate);
2347
2911
  if (isPathInsideStorageRoot(storageRoot, resolved)) {
2348
2912
  candidates.add(resolved);
2349
2913
  }
@@ -2351,12 +2915,12 @@ function qmdResultPathCandidates(storageDir, resultPath) {
2351
2915
  const addRelativeCandidates = (relativePath) => {
2352
2916
  const normalized = relativePath.replace(/\\/g, "/").replace(/^\/+/, "");
2353
2917
  if (!normalized) return;
2354
- addCandidate(path3.join(storageRoot, normalized));
2918
+ addCandidate(path4.join(storageRoot, normalized));
2355
2919
  if (/^\d{4}-\d{2}-\d{2}\//.test(normalized)) {
2356
- addCandidate(path3.join(storageRoot, "facts", normalized));
2920
+ addCandidate(path4.join(storageRoot, "facts", normalized));
2357
2921
  }
2358
2922
  };
2359
- if (path3.isAbsolute(resultPath)) {
2923
+ if (path4.isAbsolute(resultPath)) {
2360
2924
  addCandidate(resultPath);
2361
2925
  } else {
2362
2926
  addRelativeCandidates(resultPath);
@@ -2473,7 +3037,7 @@ async function qmdStartupCollectionCheckWithTimeout(promise, controller, label)
2473
3037
  return await Promise.race([checkedPromise, timeoutPromise]);
2474
3038
  }
2475
3039
  function defaultWorkspaceDir() {
2476
- return path3.join(os2.homedir(), ".openclaw", "workspace");
3040
+ return path4.join(os2.homedir(), ".openclaw", "workspace");
2477
3041
  }
2478
3042
  function sanitizeSessionKeyForFilename(sessionKey) {
2479
3043
  const readable = sessionKey.replace(/[^a-zA-Z0-9._-]/g, "_");
@@ -2766,11 +3330,11 @@ function mergeGraphExpandedResults(primary, expanded) {
2766
3330
  return Array.from(mergedByPath.values());
2767
3331
  }
2768
3332
  function graphPathRelativeToStorage(storageDir, candidatePath) {
2769
- const absolutePath = path3.isAbsolute(candidatePath) ? candidatePath : path3.resolve(storageDir, candidatePath);
2770
- const rel = path3.relative(storageDir, absolutePath);
3333
+ const absolutePath = path4.isAbsolute(candidatePath) ? candidatePath : path4.resolve(storageDir, candidatePath);
3334
+ const rel = path4.relative(storageDir, absolutePath);
2771
3335
  if (!rel || rel === ".") return null;
2772
3336
  if (rel.startsWith("..")) return null;
2773
- return rel.split(path3.sep).join("/");
3337
+ return rel.split(path4.sep).join("/");
2774
3338
  }
2775
3339
  function normalizeGraphActivationScore(score) {
2776
3340
  const bounded = Number.isFinite(score) && score > 0 ? score : 0;
@@ -2915,7 +3479,7 @@ function buildMemoryPathById(allMemsForGraph, storageDir) {
2915
3479
  for (const mem of allMemsForGraph ?? []) {
2916
3480
  const id = mem.frontmatter.id;
2917
3481
  if (!id) continue;
2918
- pathById.set(id, path3.relative(storageDir, mem.path));
3482
+ pathById.set(id, path4.relative(storageDir, mem.path));
2919
3483
  }
2920
3484
  return pathById;
2921
3485
  }
@@ -2923,7 +3487,7 @@ function appendMemoryToGraphContext(options) {
2923
3487
  if (!Array.isArray(options.allMemsForGraph)) return;
2924
3488
  const nowIso = (/* @__PURE__ */ new Date()).toISOString();
2925
3489
  options.allMemsForGraph.push({
2926
- path: path3.join(options.storageDir, options.memoryRelPath),
3490
+ path: path4.join(options.storageDir, options.memoryRelPath),
2927
3491
  content: options.content,
2928
3492
  frontmatter: {
2929
3493
  id: options.memoryId,
@@ -2943,16 +3507,16 @@ function resolvePersistedMemoryRelativePath(options) {
2943
3507
  const persisted = options.pathById.get(options.memoryId);
2944
3508
  if (persisted) return persisted;
2945
3509
  if (options.category === "correction") {
2946
- return path3.join("corrections", `${options.memoryId}.md`);
3510
+ return path4.join("corrections", `${options.memoryId}.md`);
2947
3511
  }
2948
3512
  const subtree = categoryDirName(options.category);
2949
3513
  const idParts = options.memoryId.split("-");
2950
3514
  const maybeTimestamp = Number(idParts[1]);
2951
3515
  if (Number.isFinite(maybeTimestamp) && maybeTimestamp > 0) {
2952
3516
  const day = new Date(maybeTimestamp).toISOString().slice(0, 10);
2953
- return path3.join(subtree, day, `${options.memoryId}.md`);
3517
+ return path4.join(subtree, day, `${options.memoryId}.md`);
2954
3518
  }
2955
- return path3.join(subtree, `${options.memoryId}.md`);
3519
+ return path4.join(subtree, `${options.memoryId}.md`);
2956
3520
  }
2957
3521
  var Orchestrator = class _Orchestrator {
2958
3522
  storage;
@@ -3031,6 +3595,8 @@ var Orchestrator = class _Orchestrator {
3031
3595
  tierMigrationStatus;
3032
3596
  tierMigrationCoordinator;
3033
3597
  compressionGuidelineCoordinator;
3598
+ semanticConsolidationCoordinator;
3599
+ lifecyclePolicyCoordinator;
3034
3600
  /**
3035
3601
  * In-memory X-ray snapshot from the most recent `recall()` call that
3036
3602
  * was invoked with `xrayCapture: true` (issue #570 PR 1). Scope is
@@ -3324,7 +3890,7 @@ var Orchestrator = class _Orchestrator {
3324
3890
  * @internal
3325
3891
  */
3326
3892
  applyCodingNamespaceOverlay(sessionKey, baseNamespace) {
3327
- if (!this.config.namespacesEnabled) return baseNamespace;
3893
+ if (!resolveNamespaceCapabilities(this.config).namespaces) return baseNamespace;
3328
3894
  const codingContext = this.getCodingContextForSession(sessionKey);
3329
3895
  const overlay = resolveCodingNamespaceOverlay(codingContext, this.config.codingMode, this.config.defaultNamespace);
3330
3896
  if (!overlay) return baseNamespace;
@@ -3392,7 +3958,7 @@ var Orchestrator = class _Orchestrator {
3392
3958
  * @internal
3393
3959
  */
3394
3960
  applyCodingRecallOverlay(sessionKey) {
3395
- if (!this.config.namespacesEnabled) return null;
3961
+ if (!resolveNamespaceCapabilities(this.config).namespaces) return null;
3396
3962
  const codingContext = this.getCodingContextForSession(sessionKey);
3397
3963
  const overlay = resolveCodingNamespaceOverlay(codingContext, this.config.codingMode, this.config.defaultNamespace);
3398
3964
  if (!overlay) return null;
@@ -3406,13 +3972,13 @@ var Orchestrator = class _Orchestrator {
3406
3972
  return getConfiguredNamespaces(this.config);
3407
3973
  }
3408
3974
  rememberNamespaceStorageDirHint(namespace, storageDir) {
3409
- if (!this.config.namespacesEnabled || !storageDir) return;
3975
+ if (!resolveNamespaceCapabilities(this.config).namespaces || !storageDir) return;
3410
3976
  const ns = normalizeNamespaceIdentity(namespace);
3411
3977
  if (!ns) return;
3412
3978
  const defaultNs = normalizeNamespaceIdentity(this.config.defaultNamespace);
3413
3979
  if (ns !== defaultNs && !isSafeRouteNamespace(ns)) return;
3414
3980
  if (!this.storageDirMatchesNamespaceHint(ns, storageDir)) return;
3415
- const resolvedStorageDir = path3.resolve(storageDir);
3981
+ const resolvedStorageDir = path4.resolve(storageDir);
3416
3982
  let hints = this.namespaceStorageDirHints.get(resolvedStorageDir);
3417
3983
  if (!hints) {
3418
3984
  hints = /* @__PURE__ */ new Set();
@@ -3423,21 +3989,21 @@ var Orchestrator = class _Orchestrator {
3423
3989
  storageDirMatchesNamespaceHint(namespace, storageDir) {
3424
3990
  const ns = normalizeNamespaceIdentity(namespace);
3425
3991
  if (!ns) return false;
3426
- const resolvedStorageDir = path3.resolve(storageDir);
3427
- const resolvedMemoryDir = path3.resolve(this.config.memoryDir);
3992
+ const resolvedStorageDir = path4.resolve(storageDir);
3993
+ const resolvedMemoryDir = path4.resolve(this.config.memoryDir);
3428
3994
  const defaultNs = normalizeNamespaceIdentity(this.config.defaultNamespace);
3429
3995
  if (resolvedStorageDir === resolvedMemoryDir) return ns === defaultNs;
3430
- const resolvedNamespacesDir = path3.join(resolvedMemoryDir, "namespaces");
3996
+ const resolvedNamespacesDir = path4.join(resolvedMemoryDir, "namespaces");
3431
3997
  if (!isPathInsideStorageRoot(resolvedNamespacesDir, resolvedStorageDir)) return false;
3432
- const rawRoot = path3.resolve(resolvedNamespacesDir, ns);
3433
- const tokenRoot = path3.resolve(resolvedNamespacesDir, namespaceIdentityToken(ns));
3998
+ const rawRoot = path4.resolve(resolvedNamespacesDir, ns);
3999
+ const tokenRoot = path4.resolve(resolvedNamespacesDir, namespaceIdentityToken(ns));
3434
4000
  return resolvedStorageDir === rawRoot || resolvedStorageDir === tokenRoot;
3435
4001
  }
3436
4002
  namespaceStorageDirHintOwnershipRank(record, resolvedStorageDir, configured) {
3437
- if (resolvedStorageDir === path3.resolve(this.config.memoryDir)) {
4003
+ if (resolvedStorageDir === path4.resolve(this.config.memoryDir)) {
3438
4004
  return record.namespace === normalizeNamespaceIdentity(this.config.defaultNamespace) ? 0 : 3;
3439
4005
  }
3440
- const leaf = path3.basename(resolvedStorageDir);
4006
+ const leaf = path4.basename(resolvedStorageDir);
3441
4007
  const tokenOwnsRoot = namespaceIdentityToken(record.namespace) === leaf;
3442
4008
  if (tokenOwnsRoot && configured.has(record.namespace)) return 0;
3443
4009
  if (record.namespace === leaf) return 1;
@@ -3465,7 +4031,7 @@ var Orchestrator = class _Orchestrator {
3465
4031
  loadNamespaceStorageDirHintsFromCatalog() {
3466
4032
  if (this.namespaceStorageDirHintsLoaded || !this.namespaceCatalog.enabled) return;
3467
4033
  this.namespaceStorageDirHintsLoaded = true;
3468
- const catalogPath = path3.join(this.config.memoryDir, "state", "namespaces.jsonl");
4034
+ const catalogPath = path4.join(this.config.memoryDir, "state", "namespaces.jsonl");
3469
4035
  if (!existsSync(catalogPath)) return;
3470
4036
  let body;
3471
4037
  try {
@@ -3502,7 +4068,7 @@ var Orchestrator = class _Orchestrator {
3502
4068
  if (!this.storageDirMatchesNamespaceHint(record.namespace, record.storageDir)) {
3503
4069
  continue;
3504
4070
  }
3505
- const resolvedStorageDir = path3.resolve(record.storageDir);
4071
+ const resolvedStorageDir = path4.resolve(record.storageDir);
3506
4072
  const current = preferredByStorageDir.get(resolvedStorageDir);
3507
4073
  preferredByStorageDir.set(
3508
4074
  resolvedStorageDir,
@@ -3557,8 +4123,8 @@ var Orchestrator = class _Orchestrator {
3557
4123
  return summarizeNamespaceMaintenanceHealth(this.config);
3558
4124
  }
3559
4125
  buildConfiguredQmdSearchOptions(queryText) {
3560
- const intentHint = this.config.qmdIntentHintsEnabled ? buildQmdIntentHint(inferIntentFromText(queryText)) : void 0;
3561
- const explain = this.config.qmdExplainEnabled === true;
4126
+ const intentHint = resolveQmdCapabilities(this.config).qmdIntentHints ? buildQmdIntentHint(inferIntentFromText(queryText)) : void 0;
4127
+ const explain = resolveQmdCapabilities(this.config).qmdExplain === true;
3562
4128
  const searchOptions = {};
3563
4129
  if (intentHint) {
3564
4130
  searchOptions.intent = intentHint;
@@ -3569,15 +4135,15 @@ var Orchestrator = class _Orchestrator {
3569
4135
  return Object.keys(searchOptions).length > 0 ? searchOptions : void 0;
3570
4136
  }
3571
4137
  async searchAcrossNamespaces(options) {
3572
- if (this.config.namespacesEnabled && options.namespaces !== void 0 && options.namespaces.length === 0) {
4138
+ if (resolveNamespaceCapabilities(this.config).namespaces && options.namespaces !== void 0 && options.namespaces.length === 0) {
3573
4139
  return [];
3574
4140
  }
3575
- const namespaces = this.config.namespacesEnabled ? Array.from(
4141
+ const namespaces = resolveNamespaceCapabilities(this.config).namespaces ? Array.from(
3576
4142
  new Set(
3577
4143
  (options.namespaces?.length ? options.namespaces : this.configuredNamespaceList()).map((value) => value.trim()).filter(Boolean)
3578
4144
  )
3579
4145
  ) : [this.config.defaultNamespace];
3580
- if (!this.config.namespacesEnabled) {
4146
+ if (!resolveNamespaceCapabilities(this.config).namespaces) {
3581
4147
  switch (options.mode) {
3582
4148
  case "hybrid":
3583
4149
  return await this.qmd.hybridSearch(
@@ -3623,7 +4189,7 @@ var Orchestrator = class _Orchestrator {
3623
4189
  return await this.namespaceSearchRouter.healthForNamespace(namespace, execution);
3624
4190
  }
3625
4191
  isSearchAvailableForNamespaceRouting() {
3626
- if (this.config.namespacesEnabled) return true;
4192
+ if (resolveNamespaceCapabilities(this.config).namespaces) return true;
3627
4193
  return this.qmd.isAvailable();
3628
4194
  }
3629
4195
  invalidateLiveContentHashIndex() {
@@ -3766,7 +4332,7 @@ var Orchestrator = class _Orchestrator {
3766
4332
  this.config = config;
3767
4333
  this.profiler = new ProfilingCollector({
3768
4334
  enabled: config.profilingEnabled,
3769
- storageDir: config.profilingStorageDir || path3.join(config.memoryDir, "profiling"),
4335
+ storageDir: config.profilingStorageDir || path4.join(config.memoryDir, "profiling"),
3770
4336
  maxTraces: config.profilingMaxTraces
3771
4337
  });
3772
4338
  this.namespaceCatalog = new NamespaceCatalog(config);
@@ -3835,7 +4401,7 @@ var Orchestrator = class _Orchestrator {
3835
4401
  this.compounding = config.compoundingEnabled ? new CompoundingEngine(config, this.storage) : void 0;
3836
4402
  this.buffer = new SmartBuffer(config, this.storage);
3837
4403
  this.transcript = new TranscriptManager(config);
3838
- this.conversationIndexDir = path3.join(
4404
+ this.conversationIndexDir = path4.join(
3839
4405
  config.memoryDir,
3840
4406
  "conversation-index",
3841
4407
  "chunks"
@@ -3891,6 +4457,14 @@ var Orchestrator = class _Orchestrator {
3891
4457
  client.disableThinking = true;
3892
4458
  return client;
3893
4459
  })() : this.localLlm;
4460
+ this.semanticConsolidationCoordinator = new SemanticConsolidationCoordinator({
4461
+ config,
4462
+ getStorage: () => this.storage,
4463
+ getFastLlm: () => this.fastLlm,
4464
+ embeddingFallback: this.embeddingFallback,
4465
+ removeContentHashForMemory: (targetStorage, memory, context) => this.removeContentHashForMemory(targetStorage, memory, context),
4466
+ saveContentHashIndexes: () => this.saveContentHashIndexes()
4467
+ });
3894
4468
  this._fastGatewayLlm = config.modelSource === "gateway" ? new FallbackLlmClient(
3895
4469
  config.gatewayConfig,
3896
4470
  fallbackLlmRuntimeContextFromConfig(config)
@@ -3907,8 +4481,17 @@ var Orchestrator = class _Orchestrator {
3907
4481
  config.gatewayConfig,
3908
4482
  this.modelRegistry
3909
4483
  );
4484
+ this.lifecyclePolicyCoordinator = new LifecyclePolicyCoordinator({
4485
+ config,
4486
+ getStorage: () => this.storage,
4487
+ extraction: this.extraction,
4488
+ embeddingFallback: this.embeddingFallback,
4489
+ getEffectiveLifecycleThresholds: () => this.effectiveLifecycleThresholds(),
4490
+ removeContentHashForMemory: (targetStorage, memory, context) => this.removeContentHashForMemory(targetStorage, memory, context),
4491
+ saveContentHashIndexes: () => this.saveContentHashIndexes()
4492
+ });
3910
4493
  this.threading = new ThreadingManager(
3911
- path3.join(config.memoryDir, "threads"),
4494
+ path4.join(config.memoryDir, "threads"),
3912
4495
  config.threadingGapMinutes
3913
4496
  );
3914
4497
  const lifecycleCaps = resolveMemoryLifecycleCapabilities(config);
@@ -4003,7 +4586,7 @@ var Orchestrator = class _Orchestrator {
4003
4586
  };
4004
4587
  }
4005
4588
  routeEngineOptions() {
4006
- const allowedNamespaces = this.config.namespacesEnabled ? Array.from(
4589
+ const allowedNamespaces = resolveNamespaceCapabilities(this.config).namespaces ? Array.from(
4007
4590
  /* @__PURE__ */ new Set([
4008
4591
  this.config.defaultNamespace,
4009
4592
  this.config.sharedNamespace,
@@ -4143,7 +4726,7 @@ var Orchestrator = class _Orchestrator {
4143
4726
  get briefingChainFollowupGenerator() {
4144
4727
  const chainAvailable = this.config.modelSource === "gateway" ? this._fastGatewayLlm?.isAvailable(
4145
4728
  this.config.fastGatewayAgentId || this.config.gatewayAgentId || void 0
4146
- ) === true : this.config.localLlmEnabled;
4729
+ ) === true : resolveLocalLlmCapabilities(this.config).localLlm;
4147
4730
  if (!chainAvailable) return void 0;
4148
4731
  return buildChainFollowupGenerator(this.fastLlmForRerank);
4149
4732
  }
@@ -4158,7 +4741,7 @@ var Orchestrator = class _Orchestrator {
4158
4741
  });
4159
4742
  await this.storage.ensureDirectories();
4160
4743
  await this.storage.loadAliases();
4161
- if (this.config.namespacesEnabled) {
4744
+ if (resolveNamespaceCapabilities(this.config).namespaces) {
4162
4745
  const namespaces = /* @__PURE__ */ new Set([
4163
4746
  this.config.defaultNamespace,
4164
4747
  this.config.sharedNamespace,
@@ -4199,8 +4782,8 @@ var Orchestrator = class _Orchestrator {
4199
4782
  this.runtimePolicyValues = await this.policyRuntime.loadRuntimeValues();
4200
4783
  this.utilityRuntimeValues = await loadUtilityRuntimeValues({
4201
4784
  memoryDir: this.config.memoryDir,
4202
- memoryUtilityLearningEnabled: this.config.memoryUtilityLearningEnabled,
4203
- promotionByOutcomeEnabled: this.config.promotionByOutcomeEnabled
4785
+ memoryUtilityLearningEnabled: resolveUtilityLearningCapabilities(this.config).memoryUtilityLearning,
4786
+ promotionByOutcomeEnabled: resolveUtilityLearningCapabilities(this.config).promotionByOutcome
4204
4787
  });
4205
4788
  if (this.config.factDeduplicationEnabled) {
4206
4789
  this.contentHashIndex = this.storage.createContentHashIndex();
@@ -4231,7 +4814,7 @@ var Orchestrator = class _Orchestrator {
4231
4814
  const files = await readdir(wsDir).catch(() => []);
4232
4815
  for (const f of files) {
4233
4816
  if (!f.startsWith(".compaction-reset-signal-")) continue;
4234
- const fp = path3.join(wsDir, f);
4817
+ const fp = path4.join(wsDir, f);
4235
4818
  const s = await stat(fp).catch(() => null);
4236
4819
  if (s && Date.now() - s.mtimeMs >= COMPACTION_SIGNAL_MAX_AGE_MS) {
4237
4820
  await unlink(fp).catch(() => {
@@ -4247,12 +4830,12 @@ var Orchestrator = class _Orchestrator {
4247
4830
  const available = await this.qmd.probe();
4248
4831
  if (available) {
4249
4832
  log.info(`Search backend: available ${this.qmd.debugStatus()}`);
4250
- const namespaces = this.config.namespacesEnabled ? await this.maintenanceNamespaces() : [this.config.defaultNamespace];
4833
+ const namespaces = resolveNamespaceCapabilities(this.config).namespaces ? await this.maintenanceNamespaces() : [this.config.defaultNamespace];
4251
4834
  const states = await Promise.all(
4252
4835
  namespaces.map(async (namespace) => {
4253
4836
  const collectionCheckAbort = new AbortController();
4254
4837
  const state = await qmdStartupCollectionCheckWithTimeout(
4255
- this.config.namespacesEnabled ? this.namespaceSearchRouter.ensureNamespaceCollection(
4838
+ resolveNamespaceCapabilities(this.config).namespaces ? this.namespaceSearchRouter.ensureNamespaceCollection(
4256
4839
  namespace,
4257
4840
  { signal: collectionCheckAbort.signal }
4258
4841
  ) : this.qmd.ensureCollection(
@@ -4327,10 +4910,10 @@ var Orchestrator = class _Orchestrator {
4327
4910
  }
4328
4911
  async deferredInitialize(signal) {
4329
4912
  const lifecycleCaps = resolveMemoryLifecycleCapabilities(this.config);
4330
- if (this.qmd.isAvailable() && this.config.qmdMaintenanceEnabled) {
4913
+ if (this.qmd.isAvailable() && resolveQmdCapabilities(this.config).qmdMaintenance) {
4331
4914
  try {
4332
4915
  log.info("QMD startup sync: updating index to match current disk state");
4333
- if (this.config.namespacesEnabled) {
4916
+ if (resolveNamespaceCapabilities(this.config).namespaces) {
4334
4917
  await this.namespaceSearchRouter.updateNamespaces(
4335
4918
  await this.maintenanceNamespaces(),
4336
4919
  { signal }
@@ -4414,7 +4997,7 @@ var Orchestrator = class _Orchestrator {
4414
4997
  }
4415
4998
  }
4416
4999
  if (signal.aborted) return;
4417
- if (this.config.localLlmEnabled) {
5000
+ if (resolveLocalLlmCapabilities(this.config).localLlm) {
4418
5001
  try {
4419
5002
  await this.validateLocalLlmModel();
4420
5003
  } catch (err) {
@@ -4424,9 +5007,9 @@ var Orchestrator = class _Orchestrator {
4424
5007
  if (signal.aborted) return;
4425
5008
  await this.maintenanceScheduler.autoRegisterCrons(signal);
4426
5009
  if (signal.aborted) return;
4427
- if (lifecycleCaps.lifecyclePolicy && this.config.qmdTierMigrationEnabled) {
5010
+ if (lifecycleCaps.lifecyclePolicy && resolveQmdCapabilities(this.config).qmdTierMigration) {
4428
5011
  try {
4429
- const { runFirstStartMigration } = await import("./first-start-migration-OOR57AYR.js");
5012
+ const { runFirstStartMigration } = await import("./first-start-migration-2RQYDIZ7.js");
4430
5013
  const result = await runFirstStartMigration({
4431
5014
  storage: this.storage,
4432
5015
  config: this.config,
@@ -4500,14 +5083,14 @@ var Orchestrator = class _Orchestrator {
4500
5083
  return false;
4501
5084
  }
4502
5085
  log.info(`startupSearchSync: backend now available ${this.qmd.debugStatus()}`);
4503
- if (this.config.namespacesEnabled) {
5086
+ if (resolveNamespaceCapabilities(this.config).namespaces) {
4504
5087
  this.namespaceSearchRouter.clearCache();
4505
5088
  }
4506
- const namespaces = this.config.namespacesEnabled ? await this.maintenanceNamespaces() : [this.config.defaultNamespace];
5089
+ const namespaces = resolveNamespaceCapabilities(this.config).namespaces ? await this.maintenanceNamespaces() : [this.config.defaultNamespace];
4507
5090
  const states = await Promise.all(
4508
5091
  namespaces.map(async (namespace) => ({
4509
5092
  namespace,
4510
- state: this.config.namespacesEnabled ? await this.namespaceSearchRouter.ensureNamespaceCollection(namespace, { signal }) : await this.qmd.ensureCollection(this.config.memoryDir, this.config.qmdCollection, { signal })
5093
+ state: resolveNamespaceCapabilities(this.config).namespaces ? await this.namespaceSearchRouter.ensureNamespaceCollection(namespace, { signal }) : await this.qmd.ensureCollection(this.config.memoryDir, this.config.qmdCollection, { signal })
4511
5094
  }))
4512
5095
  );
4513
5096
  if (signal?.aborted) {
@@ -4524,7 +5107,7 @@ var Orchestrator = class _Orchestrator {
4524
5107
  log.warn("startupSearchSync: search collection missing; disabling search (fallback retrieval remains enabled)");
4525
5108
  return false;
4526
5109
  }
4527
- if (this.config.qmdMaintenanceEnabled) {
5110
+ if (resolveQmdCapabilities(this.config).qmdMaintenance) {
4528
5111
  try {
4529
5112
  const failTsBefore = "lastUpdateFailedAtMs" in this.qmd ? this.qmd.lastUpdateFailedAtMs : null;
4530
5113
  const hasRunTs = "lastUpdateRanAtMs" in this.qmd;
@@ -4533,7 +5116,7 @@ var Orchestrator = class _Orchestrator {
4533
5116
  }
4534
5117
  log.info("startupSearchSync: updating index to match current disk state");
4535
5118
  let namespacesUpdated = 0;
4536
- if (this.config.namespacesEnabled) {
5119
+ if (resolveNamespaceCapabilities(this.config).namespaces) {
4537
5120
  namespacesUpdated = await this.namespaceSearchRouter.updateNamespaces(
4538
5121
  namespaces,
4539
5122
  { signal }
@@ -4551,7 +5134,7 @@ var Orchestrator = class _Orchestrator {
4551
5134
  log.warn("startupSearchSync: update silently failed (detected via fail timestamp)");
4552
5135
  return false;
4553
5136
  }
4554
- if (this.config.namespacesEnabled) {
5137
+ if (resolveNamespaceCapabilities(this.config).namespaces) {
4555
5138
  if (namespacesUpdated === 0) {
4556
5139
  log.warn("startupSearchSync: no namespace backends were eligible for update (all unavailable or collections missing)");
4557
5140
  return false;
@@ -4740,15 +5323,15 @@ ${doc.content}` : doc.content,
4740
5323
  this.lastFileHygieneRunAtMs = now;
4741
5324
  if (hygiene.rotateEnabled) {
4742
5325
  for (const rel of hygiene.rotatePaths) {
4743
- const abs = path3.isAbsolute(rel) ? rel : path3.join(this.config.workspaceDir, rel);
5326
+ const abs = path4.isAbsolute(rel) ? rel : path4.join(this.config.workspaceDir, rel);
4744
5327
  try {
4745
5328
  const raw = await readFile2(abs, "utf-8");
4746
5329
  if (raw.length > hygiene.rotateMaxBytes) {
4747
- const archiveDir = path3.join(
5330
+ const archiveDir = path4.join(
4748
5331
  this.config.workspaceDir,
4749
5332
  hygiene.archiveDir
4750
5333
  );
4751
- const base = path3.basename(abs);
5334
+ const base = path4.basename(abs);
4752
5335
  const prefix = base.toUpperCase().replace(/\.MD$/i, "").replace(/[^A-Z0-9]+/g, "-") || "FILE";
4753
5336
  const { newContent } = await rotateMarkdownFileToArchive({
4754
5337
  filePath: abs,
@@ -4756,7 +5339,7 @@ ${doc.content}` : doc.content,
4756
5339
  archivePrefix: prefix,
4757
5340
  keepTailChars: hygiene.rotateKeepTailChars
4758
5341
  });
4759
- await writeFile2(abs, newContent, "utf-8");
5342
+ await writeFile3(abs, newContent, "utf-8");
4760
5343
  }
4761
5344
  } catch {
4762
5345
  }
@@ -4773,8 +5356,8 @@ ${doc.content}` : doc.content,
4773
5356
  log.warn(w.message);
4774
5357
  }
4775
5358
  if (hygiene.warningsLogEnabled && warnings.length > 0) {
4776
- const fp = path3.join(this.config.memoryDir, hygiene.warningsLogPath);
4777
- await mkdir2(path3.dirname(fp), { recursive: true });
5359
+ const fp = path4.join(this.config.memoryDir, hygiene.warningsLogPath);
5360
+ await mkdir3(path4.dirname(fp), { recursive: true });
4778
5361
  const stamp = (/* @__PURE__ */ new Date()).toISOString();
4779
5362
  const block = `
4780
5363
 
@@ -4787,7 +5370,7 @@ ${doc.content}` : doc.content,
4787
5370
  } catch {
4788
5371
  existing = "# Engram File Hygiene Warnings\n";
4789
5372
  }
4790
- await writeFile2(fp, existing + block, "utf-8");
5373
+ await writeFile3(fp, existing + block, "utf-8");
4791
5374
  }
4792
5375
  }
4793
5376
  }
@@ -4825,253 +5408,18 @@ ${doc.content}` : doc.content,
4825
5408
  this.storageDirNamespace(targetStorage.dir),
4826
5409
  5
4827
5410
  );
4828
- } catch (error) {
4829
- log.debug(`deep-sleep governance: entity synthesis refresh failed after apply: ${error}`);
4830
- }
4831
- }
4832
- return summarizeGovernanceResultForDreams(govResult, options?.dryRun === true);
4833
- }
4834
- async runSemanticConsolidation(options) {
4835
- const targetStorage = options?.storage ?? this.storage;
4836
- const result = {
4837
- clustersFound: 0,
4838
- memoriesConsolidated: 0,
4839
- memoriesArchived: 0,
4840
- errors: 0,
4841
- clusters: []
4842
- };
4843
- if (!this.config.semanticConsolidationEnabled && !options?.force) {
4844
- log.debug("[semantic-consolidation] disabled in config");
4845
- return result;
4846
- }
4847
- log.info("[semantic-consolidation] starting run");
4848
- const allMemories = await targetStorage.readAllMemories();
4849
- if (allMemories.length < 10) {
4850
- log.debug("[semantic-consolidation] too few memories, skipping");
4851
- return result;
4852
- }
4853
- const threshold = options?.thresholdOverride ?? this.config.semanticConsolidationThreshold;
4854
- const clusters = findSimilarClusters(allMemories, {
4855
- threshold,
4856
- minClusterSize: this.config.semanticConsolidationMinClusterSize,
4857
- excludeCategories: this.config.semanticConsolidationExcludeCategories,
4858
- maxPerRun: this.config.semanticConsolidationMaxPerRun
4859
- });
4860
- result.clustersFound = clusters.length;
4861
- result.clusters = clusters;
4862
- if (clusters.length === 0) {
4863
- log.info("[semantic-consolidation] no clusters found");
4864
- return result;
4865
- }
4866
- log.info(`[semantic-consolidation] found ${clusters.length} cluster(s)`);
4867
- if (options?.dryRun) {
4868
- log.info(
4869
- "[semantic-consolidation] dry run \u2014 skipping LLM synthesis and archival"
4870
- );
4871
- return result;
4872
- }
4873
- const { FallbackLlmClient: FallbackLlmClient2, gatewayTaskChainOptions: gatewayTaskChainOptions2 } = await import("./fallback-llm.js");
4874
- const useGateway = this.config.modelSource === "gateway";
4875
- const modelSetting = this.config.semanticConsolidationModel;
4876
- if (modelSetting === "fast" && this.fastLlm && !useGateway) {
4877
- log.info("[semantic-consolidation] using fast local LLM for synthesis");
4878
- }
4879
- const gatewayChainOptions = !useGateway ? {} : modelSetting === "fast" ? this.config.fastGatewayAgentId ? { agentId: this.config.fastGatewayAgentId } : this.config.gatewayAgentId ? { agentId: this.config.gatewayAgentId } : {} : gatewayTaskChainOptions2(this.config);
4880
- const llm = new FallbackLlmClient2(
4881
- this.config.gatewayConfig,
4882
- fallbackLlmRuntimeContextFromConfig(this.config)
4883
- );
4884
- if (!llm.isAvailable(gatewayChainOptions) && !(modelSetting === "fast" && this.fastLlm && !useGateway)) {
4885
- log.warn(
4886
- "[semantic-consolidation] no LLM available \u2014 skipping synthesis"
4887
- );
4888
- return result;
4889
- }
4890
- let extensionsBlock = "";
4891
- try {
4892
- extensionsBlock = await buildExtensionsBlockForConsolidation(this.config);
4893
- } catch (err) {
4894
- log.warn(`[semantic-consolidation] extension discovery failed (non-fatal): ${err instanceof Error ? err.message : String(err)}`);
4895
- }
4896
- for (const cluster of clusters) {
4897
- let canonicalWriteCompleted = false;
4898
- try {
4899
- const operatorAwareEnabled = this.config.operatorAwareConsolidationEnabled === true;
4900
- let prompt = operatorAwareEnabled ? buildOperatorAwareConsolidationPrompt(cluster) : buildConsolidationPrompt(cluster);
4901
- if (extensionsBlock.length > 0) {
4902
- prompt += "\n\n" + extensionsBlock;
4903
- }
4904
- const messages = [
4905
- {
4906
- role: "system",
4907
- content: operatorAwareEnabled ? 'You are a memory consolidation system. Return ONLY a JSON object with two keys, "operator" and "output". The "operator" value MUST be one of the exact strings "merge", "update", or "split" \u2014 never a pipe-separated placeholder, never prose. The "output" value is the canonical memory text.' : "You are a memory consolidation system. Output only the consolidated memory text."
4908
- },
4909
- { role: "user", content: prompt }
4910
- ];
4911
- const llmOpts = { temperature: 0.2, maxTokens: 2e3 };
4912
- let response = null;
4913
- if (useGateway) {
4914
- response = await llm.chatCompletion(messages, { ...llmOpts, ...gatewayChainOptions });
4915
- } else if (modelSetting === "fast" && this.fastLlm) {
4916
- const fastResult = await this.fastLlm.chatCompletion(messages, {
4917
- operation: "semantic-consolidation",
4918
- maxTokens: llmOpts.maxTokens,
4919
- temperature: llmOpts.temperature,
4920
- priority: "background",
4921
- forceDisableThinking: true
4922
- });
4923
- response = fastResult ? { content: fastResult.content } : null;
4924
- } else {
4925
- response = await llm.chatCompletion(messages, llmOpts);
4926
- }
4927
- if (!response?.content) {
4928
- log.warn(
4929
- `[semantic-consolidation] empty LLM response for cluster in "${cluster.category}"`
4930
- );
4931
- result.errors++;
4932
- continue;
4933
- }
4934
- let canonicalContent;
4935
- let operator;
4936
- if (operatorAwareEnabled) {
4937
- const parsed = parseOperatorAwareConsolidationResponse(
4938
- response.content,
4939
- cluster
4940
- );
4941
- canonicalContent = parsed.output;
4942
- operator = parsed.operator;
4943
- } else {
4944
- canonicalContent = parseConsolidationResponse(response.content);
4945
- operator = chooseConsolidationOperator(cluster);
4946
- }
4947
- cluster.canonicalContent = canonicalContent;
4948
- const sorted = [...cluster.memories].sort(
4949
- (a, b) => new Date(b.frontmatter.created).getTime() - new Date(a.frontmatter.created).getTime()
4950
- );
4951
- const newest = sorted[0];
4952
- const lineageIds = cluster.memories.map((m) => m.frontmatter.id);
4953
- const derivedFromEntries = [];
4954
- for (const m of cluster.memories) {
4955
- if (!m.path) continue;
4956
- const entry = await targetStorage.snapshotForProvenance(m.path);
4957
- if (entry) derivedFromEntries.push(entry);
4958
- }
4959
- const { id: canonicalId, tombstoneBlocked: canonicalBlocked } = await targetStorage.writeMemory(
4960
- newest.frontmatter.category,
4961
- canonicalContent,
4962
- {
4963
- actor: "semantic-consolidation",
4964
- confidence: newest.frontmatter.confidence,
4965
- tags: [
4966
- ...new Set(
4967
- cluster.memories.flatMap((m) => m.frontmatter.tags ?? [])
4968
- )
4969
- ],
4970
- source: "semantic-consolidation",
4971
- lineage: lineageIds,
4972
- derivedFrom: derivedFromEntries.length > 0 ? derivedFromEntries : void 0,
4973
- derivedVia: operator
4974
- }
4975
- );
4976
- if (canonicalBlocked) {
4977
- log.info(`[semantic-consolidation] cluster in "${cluster.category}" tombstone-blocked \u2014 keeping ${cluster.memories.length} source(s) active (pending_review ${canonicalId})`);
4978
- continue;
4979
- }
4980
- canonicalWriteCompleted = true;
4981
- result.memoriesConsolidated++;
4982
- for (const m of cluster.memories) {
4983
- const archiveResult = await targetStorage.archiveMemory(m, {
4984
- actor: "semantic-consolidation",
4985
- reasonCode: "semantic-consolidation",
4986
- relatedMemoryIds: [canonicalId]
4987
- });
4988
- if (archiveResult) {
4989
- await this.removeContentHashForMemory(
4990
- targetStorage,
4991
- m,
4992
- "semantic-consolidation"
4993
- );
4994
- try {
4995
- await this.embeddingFallback.removeFromIndex(m.frontmatter.id);
4996
- if (resolveIndexingCapabilities(this.config).queryAwareIndexing && m.path && m.frontmatter?.created) {
4997
- deindexMemory(
4998
- targetStorage.dir,
4999
- m.path,
5000
- m.frontmatter.created,
5001
- m.frontmatter.tags ?? []
5002
- );
5003
- }
5004
- } catch (cleanupErr) {
5005
- log.warn(
5006
- `[semantic-consolidation] index cleanup failed (non-fatal): ${cleanupErr}`
5007
- );
5008
- }
5009
- result.memoriesArchived++;
5010
- }
5011
- }
5012
- log.info(
5013
- `[semantic-consolidation] consolidated ${cluster.memories.length} memories \u2192 ${canonicalId}`
5014
- );
5015
- } catch (err) {
5016
- log.warn(
5017
- `[semantic-consolidation] cluster processing failed: ${err instanceof Error ? err.message : String(err)}`
5018
- );
5019
- result.errors++;
5020
- } finally {
5021
- if (canonicalWriteCompleted) {
5022
- }
5023
- }
5024
- }
5025
- if (result.memoriesArchived > 0) {
5026
- await this.saveContentHashIndexes().catch(
5027
- (err) => log.warn(
5028
- `[semantic-consolidation] content-hash index save failed: ${err}`
5029
- )
5030
- );
5031
- }
5032
- log.info(
5033
- `[semantic-consolidation] complete: clusters=${result.clustersFound}, consolidated=${result.memoriesConsolidated}, archived=${result.memoriesArchived}, errors=${result.errors}`
5034
- );
5035
- try {
5036
- await materializeAfterSemanticConsolidation({
5037
- config: this.config,
5038
- memoryDir: targetStorage.dir
5039
- });
5040
- } catch (err) {
5041
- log.warn(
5042
- `[semantic-consolidation] Codex materialize post-hook failed (non-fatal): ${err instanceof Error ? err.message : String(err)}`
5043
- );
5044
- }
5045
- if (this.config.peerProfileReasonerEnabled) {
5046
- try {
5047
- const { runPeerProfileReasoner } = await import("./peers/index.js");
5048
- const llm2 = new FallbackLlmClient2(
5049
- this.config.gatewayConfig,
5050
- fallbackLlmRuntimeContextFromConfig(this.config)
5051
- );
5052
- const peerResult = await runPeerProfileReasoner({
5053
- memoryDir: targetStorage.dir,
5054
- enabled: true,
5055
- llm: llm2,
5056
- model: this.config.peerProfileReasonerModel,
5057
- minInteractions: this.config.peerProfileReasonerMinInteractions,
5058
- maxFieldsPerRun: this.config.peerProfileReasonerMaxFieldsPerRun,
5059
- log: {
5060
- debug: (msg) => log.debug(msg),
5061
- info: (msg) => log.info(msg),
5062
- warn: (msg) => log.warn(msg)
5063
- }
5064
- });
5065
- log.info(
5066
- `[peer-profile-reasoner] complete: peers=${peerResult.peersConsidered}, processed=${peerResult.peersProcessed}, fields=${peerResult.fieldsApplied}`
5067
- );
5068
- } catch (err) {
5069
- log.warn(
5070
- `[peer-profile-reasoner] post-consolidation hook failed (non-fatal): ${err instanceof Error ? err.message : String(err)}`
5071
- );
5411
+ } catch (error) {
5412
+ log.debug(`deep-sleep governance: entity synthesis refresh failed after apply: ${error}`);
5072
5413
  }
5073
5414
  }
5074
- return result;
5415
+ return summarizeGovernanceResultForDreams(govResult, options?.dryRun === true);
5416
+ }
5417
+ // Issue #1526 (seam 5): semantic consolidation moved to
5418
+ // SemanticConsolidationCoordinator. Thin delegation keeps all
5419
+ // call sites (runConsolidation, runSemanticConsolidationNow,
5420
+ // runSemanticConsolidationFanout) stable.
5421
+ async runSemanticConsolidation(options) {
5422
+ return this.semanticConsolidationCoordinator.runSemanticConsolidation(options);
5075
5423
  }
5076
5424
  async waitForExtractionIdle(timeoutMs = 6e4) {
5077
5425
  return this.extractionQueueCoordinator.waitForIdle(timeoutMs);
@@ -5255,7 +5603,7 @@ ${evidenceText}`
5255
5603
  for (const categoryDir of RECALL_FALLBACK_DIRS) {
5256
5604
  if (memoryRootReal === null) break;
5257
5605
  for (const date of datesToScan) {
5258
- const dateDir = path3.join(storage.dir, categoryDir, date);
5606
+ const dateDir = path4.join(storage.dir, categoryDir, date);
5259
5607
  try {
5260
5608
  const dirStat = await lstat(dateDir);
5261
5609
  if (dirStat.isSymbolicLink() || !dirStat.isDirectory()) continue;
@@ -5264,7 +5612,7 @@ ${evidenceText}`
5264
5612
  for (const entry of entries) {
5265
5613
  if (entry.isSymbolicLink()) continue;
5266
5614
  if (!entry.name.endsWith(".md")) continue;
5267
- const fullPath = path3.join(dateDir, entry.name);
5615
+ const fullPath = path4.join(dateDir, entry.name);
5268
5616
  try {
5269
5617
  assertPathInsideRoot(memoryRootReal, await realpath(fullPath), fullPath);
5270
5618
  const raw = await readFile2(fullPath, "utf-8");
@@ -5286,7 +5634,7 @@ ${evidenceText}`
5286
5634
  facts.push({
5287
5635
  path: fullPath,
5288
5636
  frontmatter: {
5289
- id: fm.id || path3.basename(entry.name, ".md"),
5637
+ id: fm.id || path4.basename(entry.name, ".md"),
5290
5638
  category: fm.category || "fact",
5291
5639
  created,
5292
5640
  updated: fm.updated || created,
@@ -5309,13 +5657,13 @@ ${evidenceText}`
5309
5657
  return a.frontmatter.created < b.frontmatter.created ? -1 : 1;
5310
5658
  });
5311
5659
  const hourlySummaries = [];
5312
- const hourlyBaseDir = path3.join(storage.dir, "summaries", "hourly");
5660
+ const hourlyBaseDir = path4.join(storage.dir, "summaries", "hourly");
5313
5661
  try {
5314
5662
  const sessionKeys = await readdir(hourlyBaseDir, { withFileTypes: true });
5315
5663
  for (const sk of sessionKeys) {
5316
5664
  if (!sk.isDirectory()) continue;
5317
5665
  for (const date of datesToScan) {
5318
- const summaryFile = path3.join(hourlyBaseDir, sk.name, `${date}.md`);
5666
+ const summaryFile = path4.join(hourlyBaseDir, sk.name, `${date}.md`);
5319
5667
  try {
5320
5668
  const raw = await readFile2(summaryFile, "utf-8");
5321
5669
  const filtered = filterHourlySummaryMarkdownForLocalDay(
@@ -5363,7 +5711,7 @@ ${evidenceText}`
5363
5711
  action: event.action,
5364
5712
  eligibility,
5365
5713
  options: {
5366
- actionsEnabled: this.config.contextCompressionActionsEnabled,
5714
+ actionsEnabled: resolveCompressionCapabilities(this.config).contextCompressionActions,
5367
5715
  maxCompressionTokensPerHour: this.config.maxCompressionTokensPerHour
5368
5716
  }
5369
5717
  });
@@ -5419,7 +5767,7 @@ ${evidenceText}`
5419
5767
  }
5420
5768
  async getLastGraphRecallSnapshot(namespace) {
5421
5769
  const storage = await this.getStorage(namespace);
5422
- const snapshotPath = path3.join(
5770
+ const snapshotPath = path4.join(
5423
5771
  storage.dir,
5424
5772
  "state",
5425
5773
  "last_graph_recall.json"
@@ -5458,7 +5806,7 @@ ${evidenceText}`
5458
5806
  }
5459
5807
  async getLastIntentSnapshot(namespace) {
5460
5808
  const storage = await this.getStorage(namespace);
5461
- const snapshotPath = path3.join(storage.dir, "state", "last_intent.json");
5809
+ const snapshotPath = path4.join(storage.dir, "state", "last_intent.json");
5462
5810
  try {
5463
5811
  const raw = await readFile2(snapshotPath, "utf-8");
5464
5812
  const parsed = JSON.parse(raw);
@@ -5491,7 +5839,7 @@ ${evidenceText}`
5491
5839
  }
5492
5840
  async getLastQmdRecallSnapshot(namespace) {
5493
5841
  const storage = await this.getStorage(namespace);
5494
- const snapshotPath = path3.join(
5842
+ const snapshotPath = path4.join(
5495
5843
  storage.dir,
5496
5844
  "state",
5497
5845
  "last_qmd_recall.json"
@@ -5644,7 +5992,7 @@ ${r.snippet.trim()}
5644
5992
  const entries = await readdir(dir, { withFileTypes: true });
5645
5993
  let total = 0;
5646
5994
  for (const entry of entries) {
5647
- const fullPath = path3.join(dir, entry.name);
5995
+ const fullPath = path4.join(dir, entry.name);
5648
5996
  if (entry.isDirectory()) {
5649
5997
  total += await this.countConversationChunkDocs(fullPath);
5650
5998
  continue;
@@ -5872,7 +6220,7 @@ ${r.snippet.trim()}
5872
6220
  options.abortSignal?.addEventListener("abort", onAbort, { once: true });
5873
6221
  }
5874
6222
  const principal = typeof options.principalOverride === "string" && options.principalOverride.length > 0 ? options.principalOverride : resolvePrincipal(sessionKey, this.config);
5875
- const namespacesEnabled = this.config.namespacesEnabled;
6223
+ const namespacesEnabled = resolveNamespaceCapabilities(this.config).namespaces;
5876
6224
  if (namespacesEnabled && !principal) {
5877
6225
  throw new Error("authentication required: namespaces are enabled and no principal was supplied");
5878
6226
  }
@@ -6213,7 +6561,7 @@ ${r.snippet.trim()}
6213
6561
  const scoped = /* @__PURE__ */ new Set();
6214
6562
  for (const memoryPath of paths) {
6215
6563
  if (!memoryPath || isArtifactMemoryPath(memoryPath)) continue;
6216
- if (this.config.namespacesEnabled && !recallNamespaces.includes(this.namespaceFromPath(memoryPath))) {
6564
+ if (resolveNamespaceCapabilities(this.config).namespaces && !recallNamespaces.includes(this.namespaceFromPath(memoryPath))) {
6217
6565
  continue;
6218
6566
  }
6219
6567
  scoped.add(memoryPath);
@@ -6296,7 +6644,7 @@ ${r.snippet.trim()}
6296
6644
  const tokens = Array.from(new Set(tokenizeRecallQuery(query)));
6297
6645
  const memories = (await Promise.all(
6298
6646
  Array.from(candidatePaths).map(async (memoryPath) => {
6299
- const namespace = this.config.namespacesEnabled ? this.namespaceFromPath(memoryPath) : this.config.defaultNamespace;
6647
+ const namespace = resolveNamespaceCapabilities(this.config).namespaces ? this.namespaceFromPath(memoryPath) : this.config.defaultNamespace;
6300
6648
  const storage = await this.storageRouter.storageFor(namespace);
6301
6649
  return await storage.readMemoryByPath(memoryPath);
6302
6650
  })
@@ -6550,7 +6898,7 @@ ${r.snippet.trim()}
6550
6898
  resolvedPath = resolvedCold.result.path;
6551
6899
  resolvedResult = resolvedCold.result;
6552
6900
  }
6553
- if (!path3.isAbsolute(resolvedPath)) {
6901
+ if (!path4.isAbsolute(resolvedPath)) {
6554
6902
  resolvedAmbiguousSeeds.set(result.path, null);
6555
6903
  return null;
6556
6904
  }
@@ -6575,7 +6923,7 @@ ${r.snippet.trim()}
6575
6923
  }
6576
6924
  continue;
6577
6925
  }
6578
- if (path3.isAbsolute(result.path)) {
6926
+ if (path4.isAbsolute(result.path)) {
6579
6927
  const resolved = await resolveAmbiguousSeedOwner(result, null);
6580
6928
  if (resolved) {
6581
6929
  addResultForNamespace(resolved.namespace, resolved.result);
@@ -6618,7 +6966,7 @@ ${r.snippet.trim()}
6618
6966
  0
6619
6967
  );
6620
6968
  seedPaths.push(
6621
- ...seedRelativePaths.map((rel) => path3.join(storage.dir, rel))
6969
+ ...seedRelativePaths.map((rel) => path4.join(storage.dir, rel))
6622
6970
  );
6623
6971
  const seedSet = new Set(seedRelativePaths);
6624
6972
  const expanded = await this.graphIndexFor(storage).spreadingActivation(
@@ -6634,7 +6982,7 @@ ${r.snippet.trim()}
6634
6982
  for (const candidate of expanded.slice(0, perNamespaceExpandedCap)) {
6635
6983
  if (deadlineExpired()) break;
6636
6984
  if (seedSet.has(candidate.path)) continue;
6637
- const memoryPath = path3.resolve(storage.dir, candidate.path);
6985
+ const memoryPath = path4.resolve(storage.dir, candidate.path);
6638
6986
  const memory = await storage.readMemoryByPath(memoryPath);
6639
6987
  if (deadlineExpired()) break;
6640
6988
  if (!memory) continue;
@@ -6659,7 +7007,7 @@ ${r.snippet.trim()}
6659
7007
  path: memory.path,
6660
7008
  score,
6661
7009
  namespace,
6662
- seed: path3.resolve(storage.dir, candidate.seed),
7010
+ seed: path4.resolve(storage.dir, candidate.seed),
6663
7011
  hopDepth: candidate.hopDepth,
6664
7012
  decayedWeight: candidate.decayedWeight,
6665
7013
  graphType: candidate.graphType,
@@ -6680,12 +7028,12 @@ ${r.snippet.trim()}
6680
7028
  }
6681
7029
  async recordLastGraphRecallSnapshot(options) {
6682
7030
  try {
6683
- const snapshotPath = path3.join(
7031
+ const snapshotPath = path4.join(
6684
7032
  options.storage.dir,
6685
7033
  "state",
6686
7034
  "last_graph_recall.json"
6687
7035
  );
6688
- await mkdir2(path3.dirname(snapshotPath), { recursive: true });
7036
+ await mkdir3(path4.dirname(snapshotPath), { recursive: true });
6689
7037
  const now = (/* @__PURE__ */ new Date()).toISOString();
6690
7038
  const totalSeedCount = options.seedPaths.length;
6691
7039
  const totalExpandedCount = options.expandedPaths.length;
@@ -6712,20 +7060,20 @@ ${r.snippet.trim()}
6712
7060
  finalResults: (options.finalResults ?? []).slice(0, 64),
6713
7061
  shadowComparison: options.shadowComparison
6714
7062
  };
6715
- await writeFile2(snapshotPath, JSON.stringify(payload, null, 2), "utf-8");
7063
+ await writeFile3(snapshotPath, JSON.stringify(payload, null, 2), "utf-8");
6716
7064
  } catch (err) {
6717
7065
  log.debug(`last graph recall write failed: ${err}`);
6718
7066
  }
6719
7067
  }
6720
7068
  async recordLastIntentSnapshot(options) {
6721
7069
  try {
6722
- const snapshotPath = path3.join(
7070
+ const snapshotPath = path4.join(
6723
7071
  options.storage.dir,
6724
7072
  "state",
6725
7073
  "last_intent.json"
6726
7074
  );
6727
- await mkdir2(path3.dirname(snapshotPath), { recursive: true });
6728
- await writeFile2(
7075
+ await mkdir3(path4.dirname(snapshotPath), { recursive: true });
7076
+ await writeFile3(
6729
7077
  snapshotPath,
6730
7078
  JSON.stringify(options.snapshot, null, 2),
6731
7079
  "utf-8"
@@ -6736,13 +7084,13 @@ ${r.snippet.trim()}
6736
7084
  }
6737
7085
  async recordLastQmdRecallSnapshot(options) {
6738
7086
  try {
6739
- const snapshotPath = path3.join(
7087
+ const snapshotPath = path4.join(
6740
7088
  options.storage.dir,
6741
7089
  "state",
6742
7090
  "last_qmd_recall.json"
6743
7091
  );
6744
- await mkdir2(path3.dirname(snapshotPath), { recursive: true });
6745
- await writeFile2(
7092
+ await mkdir3(path4.dirname(snapshotPath), { recursive: true });
7093
+ await writeFile3(
6746
7094
  snapshotPath,
6747
7095
  JSON.stringify(options.snapshot, null, 2),
6748
7096
  "utf-8"
@@ -6756,9 +7104,9 @@ ${r.snippet.trim()}
6756
7104
  const stateDir = await this.resolveStateDirForNamespace(
6757
7105
  options.namespace
6758
7106
  );
6759
- const snapshotPath = path3.join(stateDir, "last_intent.json");
6760
- await mkdir2(path3.dirname(snapshotPath), { recursive: true });
6761
- await writeFile2(
7107
+ const snapshotPath = path4.join(stateDir, "last_intent.json");
7108
+ await mkdir3(path4.dirname(snapshotPath), { recursive: true });
7109
+ await writeFile3(
6762
7110
  snapshotPath,
6763
7111
  JSON.stringify(options.snapshot, null, 2),
6764
7112
  "utf-8"
@@ -6768,13 +7116,13 @@ ${r.snippet.trim()}
6768
7116
  }
6769
7117
  }
6770
7118
  async resolveStateDirForNamespace(namespace) {
6771
- if (!this.config.namespacesEnabled) {
6772
- return path3.join(this.config.memoryDir, "state");
7119
+ if (!resolveNamespaceCapabilities(this.config).namespaces) {
7120
+ return path4.join(this.config.memoryDir, "state");
6773
7121
  }
6774
7122
  if (namespace !== this.config.defaultNamespace) {
6775
- return path3.join(this.config.memoryDir, "namespaces", namespace, "state");
7123
+ return path4.join(this.config.memoryDir, "namespaces", namespace, "state");
6776
7124
  }
6777
- const candidate = path3.join(
7125
+ const candidate = path4.join(
6778
7126
  this.config.memoryDir,
6779
7127
  "namespaces",
6780
7128
  this.config.defaultNamespace
@@ -6782,11 +7130,11 @@ ${r.snippet.trim()}
6782
7130
  try {
6783
7131
  const candidateStat = await stat(candidate);
6784
7132
  if (candidateStat.isDirectory()) {
6785
- return path3.join(candidate, "state");
7133
+ return path4.join(candidate, "state");
6786
7134
  }
6787
7135
  } catch {
6788
7136
  }
6789
- return path3.join(this.config.memoryDir, "state");
7137
+ return path4.join(this.config.memoryDir, "state");
6790
7138
  }
6791
7139
  buildGraphRecallRankedResults(results, sourceLabelResolver, limit = 64) {
6792
7140
  return results.slice(0, limit).map((result) => ({
@@ -6984,7 +7332,7 @@ ${r.snippet.trim()}
6984
7332
  }
6985
7333
  const timings = {};
6986
7334
  const profileTraceId = this.profiler.startTrace("recall", sessionKey, {
6987
- qmdEnabled: this.config.qmdEnabled,
7335
+ qmdEnabled: resolveQmdCapabilities(this.config).qmd,
6988
7336
  rerankEnabled: caps.rerank,
6989
7337
  parallelRetrieval: caps.parallelRetrieval
6990
7338
  });
@@ -7141,7 +7489,7 @@ ${r.snippet.trim()}
7141
7489
  );
7142
7490
  const embeddingFetchLimit = computedFetchLimit;
7143
7491
  const principal = typeof options.principalOverride === "string" && options.principalOverride.length > 0 ? options.principalOverride : resolvePrincipal(sessionKey, this.config);
7144
- const namespacesEnabled = this.config.namespacesEnabled;
7492
+ const namespacesEnabled = resolveNamespaceCapabilities(this.config).namespaces;
7145
7493
  if (namespacesEnabled && !principal) {
7146
7494
  throw new Error("authentication required: namespaces are enabled and no principal was supplied");
7147
7495
  }
@@ -7188,7 +7536,7 @@ ${r.snippet.trim()}
7188
7536
  const graphExpandedResultPaths = /* @__PURE__ */ new Set();
7189
7537
  const graphSourceLabelsForPath = (resultPath) => {
7190
7538
  const labels = [];
7191
- const normalizedPath = resultPath.split(path3.sep).join("/");
7539
+ const normalizedPath = resultPath.split(path4.sep).join("/");
7192
7540
  const isEntityPath = normalizedPath.startsWith("entities/") || normalizedPath.includes("/entities/");
7193
7541
  if (graphBaselinePaths.has(resultPath)) labels.push("baseline");
7194
7542
  if (graphExpandedResultPaths.has(resultPath))
@@ -7317,7 +7665,7 @@ ${r.snippet.trim()}
7317
7665
  retrievalQueryLength: retrievalQuery.length,
7318
7666
  recallMode,
7319
7667
  recallResultLimit,
7320
- qmdEnabled: this.config.qmdEnabled,
7668
+ qmdEnabled: resolveQmdCapabilities(this.config).qmd,
7321
7669
  qmdAvailable: this.qmd.isAvailable(),
7322
7670
  recallNamespaces: [],
7323
7671
  source: recallSource,
@@ -7338,7 +7686,7 @@ ${r.snippet.trim()}
7338
7686
  profileStorageNamespaces.map((namespace) => this.storageRouter.storageFor(namespace))
7339
7687
  );
7340
7688
  const emptyProfileStorage = new Proxy(
7341
- { dir: path3.join(this.config.memoryDir, ".empty-scope-profile") },
7689
+ { dir: path4.join(this.config.memoryDir, ".empty-scope-profile") },
7342
7690
  {
7343
7691
  get(target, prop) {
7344
7692
  if (prop in target) return target[prop];
@@ -7622,7 +7970,7 @@ ${lines.join("\n\n")}`;
7622
7970
  const identityContinuityPromise = (async () => {
7623
7971
  if (!this.isRecallSectionEnabled(
7624
7972
  "identity-continuity",
7625
- this.config.identityContinuityEnabled === true
7973
+ resolveIdentityContinuityCapabilities(this.config).identityContinuity === true
7626
7974
  ))
7627
7975
  return null;
7628
7976
  const t0 = Date.now();
@@ -7820,9 +8168,9 @@ ${rows.join("\n")}
7820
8168
  })();
7821
8169
  const objectiveStatePromise = (async () => {
7822
8170
  const t0 = Date.now();
7823
- if (!this.config.objectiveStateMemoryEnabled || !this.config.objectiveStateRecallEnabled || !this.isRecallSectionEnabled(
8171
+ if (!resolveObjectiveStateCapabilities(this.config).objectiveStateMemory || !resolveObjectiveStateCapabilities(this.config).objectiveStateRecall || !this.isRecallSectionEnabled(
7824
8172
  "objective-state",
7825
- this.config.objectiveStateRecallEnabled === true
8173
+ resolveObjectiveStateCapabilities(this.config).objectiveStateRecall === true
7826
8174
  )) {
7827
8175
  recordRecallSectionMetric({
7828
8176
  section: "objectiveState",
@@ -7850,13 +8198,13 @@ ${rows.join("\n")}
7850
8198
  }
7851
8199
  const objectiveStateSearches = await Promise.all(
7852
8200
  recallNamespaces.map(async (namespace) => {
7853
- const storage = this.config.namespacesEnabled ? await this.getStorage(namespace) : null;
8201
+ const storage = resolveNamespaceCapabilities(this.config).namespaces ? await this.getStorage(namespace) : null;
7854
8202
  return searchObjectiveStateSnapshots({
7855
- memoryDir: this.config.namespacesEnabled ? storage.dir : this.config.memoryDir,
8203
+ memoryDir: resolveNamespaceCapabilities(this.config).namespaces ? storage.dir : this.config.memoryDir,
7856
8204
  objectiveStateStoreDir: objectiveStateStoreOverrideForNamespace({
7857
8205
  memoryDir: this.config.memoryDir,
7858
8206
  configuredStoreDir: this.config.objectiveStateStoreDir,
7859
- namespacesEnabled: this.config.namespacesEnabled,
8207
+ namespacesEnabled: resolveNamespaceCapabilities(this.config).namespaces,
7860
8208
  namespace
7861
8209
  }),
7862
8210
  query: retrievalQuery,
@@ -8041,9 +8389,9 @@ ${rows.join("\n")}
8041
8389
  })();
8042
8390
  const trustZonePromise = (async () => {
8043
8391
  const t0 = Date.now();
8044
- if (!this.config.trustZonesEnabled || !this.config.trustZoneRecallEnabled || !this.isRecallSectionEnabled(
8392
+ if (!resolveSecurityCapabilities(this.config).trustZones || !resolveSecurityCapabilities(this.config).trustZoneRecall || !this.isRecallSectionEnabled(
8045
8393
  "trust-zones",
8046
- this.config.trustZoneRecallEnabled === true
8394
+ resolveSecurityCapabilities(this.config).trustZoneRecall === true
8047
8395
  )) {
8048
8396
  recordRecallSectionMetric({
8049
8397
  section: "trustZones",
@@ -8612,7 +8960,7 @@ ${rows.join("\n")}
8612
8960
  qmdFetchLimit,
8613
8961
  qmdHybridFetchLimit,
8614
8962
  {
8615
- namespacesEnabled: this.config.namespacesEnabled,
8963
+ namespacesEnabled: resolveNamespaceCapabilities(this.config).namespaces,
8616
8964
  recallNamespaces,
8617
8965
  resolveNamespace: (p) => this.namespaceFromPath(p),
8618
8966
  queryAwarePrefilter,
@@ -8814,11 +9162,11 @@ ${formatted}`;
8814
9162
  if (!this.config.compactionResetEnabled) return null;
8815
9163
  const workspaceDir = compactionWorkspaceDir || this.config.workspaceDir || defaultWorkspaceDir();
8816
9164
  const safeSessionKey = sanitizeSessionKeyForFilename(effectiveSessionKey);
8817
- const signalPath = path3.join(
9165
+ const signalPath = path4.join(
8818
9166
  workspaceDir,
8819
9167
  `.compaction-reset-signal-${safeSessionKey}`
8820
9168
  );
8821
- const bootPath = path3.join(workspaceDir, "BOOT.md");
9169
+ const bootPath = path4.join(workspaceDir, "BOOT.md");
8822
9170
  try {
8823
9171
  const signalStat = await stat(signalPath).catch(() => null);
8824
9172
  if (!signalStat) return null;
@@ -8945,7 +9293,7 @@ ${formatted}`;
8945
9293
  workspaceDir: this.config.workspaceDir,
8946
9294
  memoryDir: this.config.memoryDir,
8947
9295
  config: this.config.nativeKnowledge,
8948
- recallNamespaces: this.config.namespacesEnabled ? recallNamespaces : void 0,
9296
+ recallNamespaces: resolveNamespaceCapabilities(this.config).namespaces ? recallNamespaces : void 0,
8949
9297
  defaultNamespace: this.config.defaultNamespace,
8950
9298
  abortSignal: nativeKnowledgeAbort.signal
8951
9299
  }).catch(() => []);
@@ -9700,7 +10048,7 @@ ${tmtNode.summary}`
9700
10048
  []
9701
10049
  );
9702
10050
  let memoryResults = memoryResultsRaw;
9703
- if (this.config.namespacesEnabled) {
10051
+ if (resolveNamespaceCapabilities(this.config).namespaces) {
9704
10052
  memoryResults = memoryResults.filter(
9705
10053
  (r) => recallNamespaces.includes(this.namespaceFromPath(r.path))
9706
10054
  );
@@ -9983,7 +10331,7 @@ ${tmtNode.summary}`
9983
10331
  const scopedCandidates = filterRecallCandidates(
9984
10332
  prefilteredEmbeddingResults,
9985
10333
  {
9986
- namespacesEnabled: this.config.namespacesEnabled,
10334
+ namespacesEnabled: resolveNamespaceCapabilities(this.config).namespaces,
9987
10335
  recallNamespaces,
9988
10336
  resolveNamespace: (p) => this.namespaceFromPath(p),
9989
10337
  limit: embeddingFetchLimit
@@ -10144,7 +10492,7 @@ ${tmtNode.summary}`
10144
10492
  const scopedCandidates = filterRecallCandidates(
10145
10493
  prefilteredEmbeddingResults,
10146
10494
  {
10147
- namespacesEnabled: this.config.namespacesEnabled,
10495
+ namespacesEnabled: resolveNamespaceCapabilities(this.config).namespaces,
10148
10496
  recallNamespaces,
10149
10497
  resolveNamespace: (p) => this.namespaceFromPath(p),
10150
10498
  limit: embeddingFetchLimit
@@ -10503,7 +10851,7 @@ ${tmtNode.summary}`
10503
10851
  });
10504
10852
  if (this.isRecallSectionEnabled(
10505
10853
  "compression-guidelines",
10506
- this.config.compressionGuidelineLearningEnabled === true
10854
+ resolveCompressionCapabilities(this.config).compressionGuidelineLearning === true
10507
10855
  )) {
10508
10856
  const compressionGuidelineSection = await this.buildCompressionGuidelineRecallSection();
10509
10857
  if (compressionGuidelineSection) {
@@ -10809,7 +11157,7 @@ _Context: ${topQuestion.context}_`
10809
11157
  retrievalQueryLength: retrievalQuery.length,
10810
11158
  recallMode,
10811
11159
  recallResultLimit,
10812
- qmdEnabled: this.config.qmdEnabled,
11160
+ qmdEnabled: resolveQmdCapabilities(this.config).qmd,
10813
11161
  qmdAvailable: this.qmd.isAvailable(),
10814
11162
  recallNamespaces,
10815
11163
  source: recallSource,
@@ -11982,7 +12330,7 @@ ${normalized}`).digest("hex");
11982
12330
  const profileAllowsSharedWrites = !scopeProfileWritePlan || Boolean(
11983
12331
  scopeProfileWritePlan.profile.readOrder.includes("serverShared") && scopeProfileWritePlan.readNamespaces.includes(this.config.sharedNamespace) && sharedProfileLayer?.readable && sharedProfileLayer.writable && sharedPromotionTarget?.authorized
11984
12332
  );
11985
- const namespacesEnabled = this.config.namespacesEnabled;
12333
+ const namespacesEnabled = resolveNamespaceCapabilities(this.config).namespaces;
11986
12334
  const profileAutoPromotionAllows = (category, confidence) => {
11987
12335
  if (!scopeProfileWritePlan) return false;
11988
12336
  const actualTier = confidenceTier(confidence);
@@ -12010,7 +12358,7 @@ ${normalized}`).digest("hex");
12010
12358
  return scopeProfileWritePlan.profile.autoPromote.targets.includes("serverShared") && profileAutoPromotionAllows(category, confidence);
12011
12359
  };
12012
12360
  const shouldPromoteToShared = (targetStorage, category, confidence) => {
12013
- if (!this.config.namespacesEnabled || !profileAllowsSharedWrites || !sharedAutoPromotionAllows(category, confidence))
12361
+ if (!resolveNamespaceCapabilities(this.config).namespaces || !profileAllowsSharedWrites || !sharedAutoPromotionAllows(category, confidence))
12014
12362
  return false;
12015
12363
  if (this.storageDirNamespace(targetStorage.dir) === this.config.sharedNamespace)
12016
12364
  return false;
@@ -13420,7 +13768,7 @@ ${normalized}`).digest("hex");
13420
13768
  const allMems = allMemsForGraph ?? [];
13421
13769
  for (const m of allMems) {
13422
13770
  if (m.frontmatter.entityRef === entityRef) {
13423
- const rel = path3.relative(storage.dir, m.path);
13771
+ const rel = path4.relative(storage.dir, m.path);
13424
13772
  if (rel !== memoryRelPath) entitySiblings.push(rel);
13425
13773
  }
13426
13774
  }
@@ -13485,7 +13833,7 @@ ${normalized}`).digest("hex");
13485
13833
  const needsFullRebuild = !indexesExist(this.config.memoryDir);
13486
13834
  if (!needsFullRebuild && persistedIds.length === 0) return;
13487
13835
  try {
13488
- const allMemories = needsFullRebuild && this.config.namespacesEnabled ? await this.readAllMemoriesForNamespaces(
13836
+ const allMemories = needsFullRebuild && resolveNamespaceCapabilities(this.config).namespaces ? await this.readAllMemoriesForNamespaces(
13489
13837
  Array.from(
13490
13838
  /* @__PURE__ */ new Set([
13491
13839
  this.config.defaultNamespace,
@@ -13744,7 +14092,7 @@ ${normalized}`).digest("hex");
13744
14092
  }
13745
14093
  if (this.config.semanticConsolidationEnabled) {
13746
14094
  try {
13747
- const stateFilePath = path3.join(
14095
+ const stateFilePath = path4.join(
13748
14096
  this.config.memoryDir,
13749
14097
  "state",
13750
14098
  "semantic-consolidation-last-run.json"
@@ -13792,9 +14140,9 @@ ${normalized}`).digest("hex");
13792
14140
  );
13793
14141
  }
13794
14142
  if (semResult.errors === 0 || semResult.memoriesArchived > 0) {
13795
- const stateDir = path3.join(this.config.memoryDir, "state");
13796
- await mkdir2(stateDir, { recursive: true });
13797
- await writeFile2(
14143
+ const stateDir = path4.join(this.config.memoryDir, "state");
14144
+ await mkdir3(stateDir, { recursive: true });
14145
+ await writeFile3(
13798
14146
  stateFilePath,
13799
14147
  JSON.stringify({ lastRunAt: (/* @__PURE__ */ new Date()).toISOString() }),
13800
14148
  "utf-8"
@@ -13919,65 +14267,6 @@ ${texts.map((t, i) => `[${i + 1}] ${t}`).join("\n\n")}`;
13919
14267
  async buildCompressionGuidelineRecallSection() {
13920
14268
  return this.compressionGuidelineCoordinator.buildCompressionGuidelineRecallSection();
13921
14269
  }
13922
- actionOutcomePriorDelta(event) {
13923
- if (event.outcome === "failed") return -0.3;
13924
- if (event.policyDecision === "deny") return -0.22;
13925
- if (event.policyDecision === "defer") return -0.14;
13926
- if (event.outcome === "skipped") return -0.1;
13927
- if (event.outcome !== "applied") return 0;
13928
- switch (event.action) {
13929
- case "store_episode":
13930
- case "store_note":
13931
- case "update_note":
13932
- return 0.08;
13933
- case "create_artifact":
13934
- case "summarize_node":
13935
- case "link_graph":
13936
- return 0.04;
13937
- case "discard":
13938
- return -0.03;
13939
- default:
13940
- return 0;
13941
- }
13942
- }
13943
- async buildLifecycleActionPriors(storage = this.storage) {
13944
- const events = await storage.readMemoryActionEvents(1200);
13945
- if (events.length === 0) return /* @__PURE__ */ new Map();
13946
- const nowMs = Date.now();
13947
- const windowMs = 14 * 24 * 60 * 60 * 1e3;
13948
- const byMemory = /* @__PURE__ */ new Map();
13949
- for (const event of events) {
13950
- if (typeof event.memoryId !== "string" || event.memoryId.trim().length === 0)
13951
- continue;
13952
- const ts = Date.parse(event.timestamp);
13953
- if (!Number.isFinite(ts)) continue;
13954
- const ageMs = nowMs - ts;
13955
- if (ageMs < 0 || ageMs > windowMs) continue;
13956
- const delta = this.actionOutcomePriorDelta(event);
13957
- if (delta === 0) continue;
13958
- const recencyWeight = Math.max(0.2, 1 - ageMs / windowMs);
13959
- const list = byMemory.get(event.memoryId) ?? [];
13960
- if (list.length >= 8) list.shift();
13961
- list.push({
13962
- weightedDelta: delta * recencyWeight,
13963
- weight: recencyWeight
13964
- });
13965
- byMemory.set(event.memoryId, list);
13966
- }
13967
- const out = /* @__PURE__ */ new Map();
13968
- for (const [memoryId, deltas] of byMemory.entries()) {
13969
- if (deltas.length === 0) continue;
13970
- const weightedSum = deltas.reduce(
13971
- (sum, item) => sum + item.weightedDelta,
13972
- 0
13973
- );
13974
- const weightTotal = deltas.reduce((sum, item) => sum + item.weight, 0);
13975
- if (weightTotal <= 0) continue;
13976
- const score = weightedSum / weightTotal;
13977
- out.set(memoryId, Math.max(-0.25, Math.min(0.15, score)));
13978
- }
13979
- return out;
13980
- }
13981
14270
  async recordScheduledDreamsPhaseRun(phase, itemsProcessed, notes, timing = {}) {
13982
14271
  try {
13983
14272
  const { recordDreamsPhaseRun } = await import("./dreams-ledger-6UODQOX6.js");
@@ -14001,223 +14290,24 @@ ${texts.map((t, i) => `[${i + 1}] ${t}`).join("\n\n")}`;
14001
14290
  return { memoriesAssessed: lifecycleCorpus.length };
14002
14291
  }
14003
14292
  async runLifecyclePolicyPass(allMemories, storage = this.storage) {
14004
- const now = /* @__PURE__ */ new Date();
14005
- const nowIso = now.toISOString();
14006
- const countsByState = {
14007
- candidate: 0,
14008
- validated: 0,
14009
- active: 0,
14010
- stale: 0,
14011
- archived: 0
14012
- };
14013
- const transitionCounts = {};
14014
- let updatedCount = 0;
14015
- let disputedCount = 0;
14016
- let evaluatedCount = 0;
14017
- const lifecycleCaps = resolveMemoryLifecycleCapabilities(this.config);
14018
- const thresholds = this.effectiveLifecycleThresholds();
14019
- const policy = {
14020
- promoteHeatThreshold: thresholds.promoteHeatThreshold,
14021
- staleDecayThreshold: thresholds.staleDecayThreshold,
14022
- archiveDecayThreshold: thresholds.archiveDecayThreshold,
14023
- protectedCategories: this.config.lifecycleProtectedCategories
14024
- };
14025
- const actionPriors = await this.buildLifecycleActionPriors(storage);
14026
- for (const memory of allMemories) {
14027
- if (memory.frontmatter.status === "superseded" || memory.frontmatter.status === "forgotten") {
14028
- continue;
14029
- }
14030
- evaluatedCount += 1;
14031
- const currentState = resolveLifecycleState(memory.frontmatter);
14032
- const actionPriorScore = actionPriors.get(memory.frontmatter.id);
14033
- const signals = typeof actionPriorScore === "number" && Number.isFinite(actionPriorScore) ? { actionPriorScore } : void 0;
14034
- const decision = decideLifecycleTransition(memory, policy, now, signals);
14035
- const nextState = memory.frontmatter.status === "archived" ? "archived" : decision.nextState;
14036
- countsByState[nextState] += 1;
14037
- if (memory.frontmatter.verificationState === "disputed") {
14038
- disputedCount += 1;
14039
- }
14040
- if (nextState !== currentState) {
14041
- const key = `${currentState}->${nextState}`;
14042
- transitionCounts[key] = (transitionCounts[key] ?? 0) + 1;
14043
- }
14044
- const prevHeat = memory.frontmatter.heatScore;
14045
- const prevDecay = memory.frontmatter.decayScore;
14046
- const scoreDelta = Math.abs((prevHeat ?? -1) - decision.heatScore) + Math.abs((prevDecay ?? -1) - decision.decayScore);
14047
- const shouldPersist = memory.frontmatter.lifecycleState !== nextState || memory.frontmatter.heatScore === void 0 || memory.frontmatter.decayScore === void 0 || memory.frontmatter.lastValidatedAt === void 0 || scoreDelta >= 0.01;
14048
- if (!shouldPersist) continue;
14049
- const wrote = await storage.writeMemoryFrontmatter(memory, {
14050
- lifecycleState: nextState,
14051
- heatScore: decision.heatScore,
14052
- decayScore: decision.decayScore,
14053
- lastValidatedAt: nowIso
14054
- });
14055
- if (wrote) updatedCount += 1;
14056
- }
14057
- if (!lifecycleCaps.lifecycleMetrics) return updatedCount;
14058
- const total = evaluatedCount;
14059
- const metrics = {
14060
- generatedAt: nowIso,
14061
- memoriesEvaluated: total,
14062
- memoriesUpdated: updatedCount,
14063
- countsByLifecycleState: countsByState,
14064
- transitionCounts,
14065
- staleRatio: total > 0 ? countsByState.stale / total : 0,
14066
- disputedRatio: total > 0 ? disputedCount / total : 0,
14067
- policy: {
14068
- promoteHeatThreshold: thresholds.promoteHeatThreshold,
14069
- staleDecayThreshold: thresholds.staleDecayThreshold,
14070
- archiveDecayThreshold: thresholds.archiveDecayThreshold,
14071
- protectedCategories: this.config.lifecycleProtectedCategories
14072
- }
14073
- };
14074
- const metricsPath = path3.join(
14075
- storage.dir,
14076
- "state",
14077
- "lifecycle-metrics.json"
14078
- );
14079
- await mkdir2(path3.dirname(metricsPath), { recursive: true });
14080
- await writeFile2(metricsPath, JSON.stringify(metrics, null, 2), "utf-8");
14081
- return updatedCount;
14293
+ return this.lifecyclePolicyCoordinator.runLifecyclePolicyPass(allMemories, storage);
14082
14294
  }
14083
- /**
14084
- * Archive old, low-importance, rarely-accessed facts (v6.0).
14085
- * Moves eligible facts from facts/ to archive/YYYY-MM-DD/.
14086
- * Returns the number of archived facts.
14087
- */
14088
14295
  async runFactArchival(allMemories) {
14089
- const now = Date.now();
14090
- const ageCutoffMs = this.config.factArchivalAgeDays * 24 * 60 * 60 * 1e3;
14091
- const protectedCategories = new Set(
14092
- this.config.factArchivalProtectedCategories
14093
- );
14094
- let archivedCount = 0;
14095
- for (const memory of allMemories) {
14096
- const fm = memory.frontmatter;
14097
- if (fm.status && fm.status !== "active") continue;
14098
- if (protectedCategories.has(fm.category)) continue;
14099
- if (fm.category === "correction") continue;
14100
- const createdMs = new Date(fm.created).getTime();
14101
- if (now - createdMs < ageCutoffMs) continue;
14102
- const importanceScore = fm.importance?.score ?? 0.5;
14103
- if (importanceScore >= this.config.factArchivalMaxImportance) continue;
14104
- const accessCount = fm.accessCount ?? 0;
14105
- if (accessCount > this.config.factArchivalMaxAccessCount) continue;
14106
- const result = await this.storage.archiveMemory(memory);
14107
- if (result) {
14108
- await this.removeContentHashForMemory(
14109
- this.storage,
14110
- memory,
14111
- "fact-archival"
14112
- );
14113
- await this.embeddingFallback.removeFromIndex(memory.frontmatter.id);
14114
- if (resolveIndexingCapabilities(this.config).queryAwareIndexing && memory.path && memory.frontmatter?.created) {
14115
- deindexMemory(
14116
- this.config.memoryDir,
14117
- memory.path,
14118
- memory.frontmatter.created,
14119
- memory.frontmatter.tags ?? []
14120
- );
14121
- }
14122
- archivedCount++;
14123
- }
14124
- }
14125
- if (archivedCount > 0) {
14126
- await this.saveContentHashIndexes().catch(
14127
- (err) => log.warn(`content-hash index save failed during archival: ${err}`)
14128
- );
14129
- }
14130
- return archivedCount;
14296
+ return this.lifecyclePolicyCoordinator.runFactArchival(allMemories);
14131
14297
  }
14132
- /**
14133
- * Run memory summarization if memory count exceeds threshold (Phase 4A).
14134
- */
14135
14298
  async runSummarization(allMemories) {
14136
- const activeMemories = allMemories.filter(
14137
- (m) => isActiveMemoryStatus(m.frontmatter.status)
14138
- );
14139
- if (activeMemories.length < this.config.summarizationTriggerCount) {
14140
- return;
14141
- }
14142
- log.info(
14143
- `memory count (${activeMemories.length}) exceeds threshold (${this.config.summarizationTriggerCount}) \u2014 running summarization`
14144
- );
14145
- const sorted = activeMemories.sort(
14146
- (a, b) => new Date(a.frontmatter.created).getTime() - new Date(b.frontmatter.created).getTime()
14147
- );
14148
- const recentToKeep = Math.max(0, this.config.summarizationRecentToKeep);
14149
- const toSummarize = recentToKeep > 0 ? sorted.slice(0, -recentToKeep) : sorted;
14150
- const candidates = toSummarize.filter((m) => {
14151
- if (m.frontmatter.entityRef) return false;
14152
- const protectedTags = this.config.summarizationProtectedTags;
14153
- if (m.frontmatter.tags.some((t) => protectedTags.includes(t)))
14154
- return false;
14155
- const importance = m.frontmatter.importance?.score ?? 0.5;
14156
- if (importance >= this.config.summarizationImportanceThreshold)
14157
- return false;
14158
- return true;
14159
- });
14160
- if (candidates.length < 50) {
14161
- log.debug(
14162
- `only ${candidates.length} candidates for summarization \u2014 skipping`
14163
- );
14164
- return;
14165
- }
14166
- const batchSize = 50;
14167
- for (let i = 0; i < candidates.length; i += batchSize) {
14168
- const batch = candidates.slice(i, i + batchSize);
14169
- const batchData = batch.map((m) => ({
14170
- id: m.frontmatter.id,
14171
- content: m.content,
14172
- category: m.frontmatter.category,
14173
- created: m.frontmatter.created
14174
- }));
14175
- const result = await this.extraction.summarizeMemories(batchData);
14176
- if (!result) continue;
14177
- const summary = {
14178
- id: `summary-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`,
14179
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
14180
- timeRangeStart: batch[0].frontmatter.created,
14181
- timeRangeEnd: batch[batch.length - 1].frontmatter.created,
14182
- summaryText: result.summaryText,
14183
- keyFacts: result.keyFacts,
14184
- keyEntities: result.keyEntities,
14185
- sourceEpisodeIds: batch.map((m) => m.frontmatter.id)
14186
- };
14187
- await this.storage.writeSummary(summary);
14188
- const archived = await this.storage.archiveMemories(
14189
- batch.map((m) => m.frontmatter.id),
14190
- summary.id
14191
- );
14192
- log.info(
14193
- `created summary ${summary.id} from ${batch.length} memories, archived ${archived}`
14194
- );
14195
- }
14299
+ return this.lifecyclePolicyCoordinator.runSummarization(allMemories);
14196
14300
  }
14197
- /**
14198
- * Run topic extraction on all memories (Phase 4B).
14199
- */
14200
14301
  async runTopicExtraction(allMemories) {
14201
- const activeMemories = allMemories.filter(
14202
- (m) => isActiveMemoryStatus(m.frontmatter.status)
14203
- );
14204
- if (activeMemories.length === 0) return;
14205
- const topics = extractTopics(
14206
- activeMemories,
14207
- this.config.topicExtractionTopN
14208
- );
14209
- await this.storage.saveTopics(topics);
14210
- log.debug(
14211
- `extracted ${topics.length} topics from ${activeMemories.length} memories`
14212
- );
14302
+ return this.lifecyclePolicyCoordinator.runTopicExtraction(allMemories);
14213
14303
  }
14214
14304
  /** Threshold (bytes) at which IDENTITY.md reflections get auto-consolidated */
14215
14305
  static IDENTITY_CONSOLIDATE_THRESHOLD = 8e3;
14216
14306
  async autoConsolidateIdentity() {
14217
- const namespaces = this.config.namespacesEnabled ? await this.maintenanceNamespaces() : [this.config.defaultNamespace];
14307
+ const namespaces = resolveNamespaceCapabilities(this.config).namespaces ? await this.maintenanceNamespaces() : [this.config.defaultNamespace];
14218
14308
  for (const namespace of namespaces) {
14219
14309
  const storage = await this.storageRouter.storageFor(namespace);
14220
- const identityNamespace = this.config.namespacesEnabled && namespace !== this.config.defaultNamespace ? namespace : void 0;
14310
+ const identityNamespace = resolveNamespaceCapabilities(this.config).namespaces && namespace !== this.config.defaultNamespace ? namespace : void 0;
14221
14311
  const reflectionsContent = await storage.readIdentityReflections() ?? "";
14222
14312
  const existingIdentity = await storage.readIdentity(
14223
14313
  this.config.workspaceDir,
@@ -14486,7 +14576,7 @@ ${lines.join("\n\n")}`;
14486
14576
  return { text: `${content.slice(0, headroom)}${suffix}`, truncated: true };
14487
14577
  }
14488
14578
  async buildIdentityContinuitySection(options) {
14489
- if (!this.config.identityContinuityEnabled) return null;
14579
+ if (!resolveIdentityContinuityCapabilities(this.config).identityContinuity) return null;
14490
14580
  if (this.config.identityMaxInjectChars <= 0) return null;
14491
14581
  const resolved = resolveEffectiveIdentityInjectionMode({
14492
14582
  configuredMode: this.config.identityInjectionMode,
@@ -14557,7 +14647,7 @@ ${lines.join("\n\n")}`;
14557
14647
  }
14558
14648
  }
14559
14649
  queueEvalShadowRecall(record) {
14560
- if (!this.config.evalHarnessEnabled || !this.config.evalShadowModeEnabled)
14650
+ if (!resolveEvalCapabilities(this.config).evalHarness || !resolveEvalCapabilities(this.config).evalShadowMode)
14561
14651
  return;
14562
14652
  this.evalShadowWriteChain = this.evalShadowWriteChain.catch(() => void 0).then(async () => {
14563
14653
  try {
@@ -14619,13 +14709,13 @@ ${lines.join("\n\n")}`;
14619
14709
  const seenStorageDirs = /* @__PURE__ */ new Set();
14620
14710
  const addStorage = (storage) => {
14621
14711
  const storageDir = storageDirFor(storage);
14622
- const storageKey = storageDir ? path3.resolve(storageDir) : `storage-without-dir-${storages.length}`;
14712
+ const storageKey = storageDir ? path4.resolve(storageDir) : `storage-without-dir-${storages.length}`;
14623
14713
  if (seenStorageDirs.has(storageKey)) return;
14624
14714
  seenStorageDirs.add(storageKey);
14625
14715
  storages.push(storage);
14626
14716
  };
14627
14717
  const fallbackNamespace = fallbackStorageDir !== null ? this.storageDirNamespace(fallbackStorageDir) : this.config.defaultNamespace;
14628
- if (recallNamespaces.length === 0 || !this.config.namespacesEnabled || recallNamespaces.includes(fallbackNamespace)) {
14718
+ if (recallNamespaces.length === 0 || !resolveNamespaceCapabilities(this.config).namespaces || recallNamespaces.includes(fallbackNamespace)) {
14629
14719
  addStorage(fallbackStorage);
14630
14720
  }
14631
14721
  if (recallNamespaces.length > 0) {
@@ -14649,7 +14739,7 @@ ${lines.join("\n\n")}`;
14649
14739
  continue;
14650
14740
  }
14651
14741
  try {
14652
- const coldRoot = path3.join(storageDir, "cold");
14742
+ const coldRoot = path4.join(storageDir, "cold");
14653
14743
  for (const candidate of qmdResultPathCandidates(
14654
14744
  coldRoot,
14655
14745
  parts.relativePath
@@ -14690,7 +14780,7 @@ ${lines.join("\n\n")}`;
14690
14780
  return null;
14691
14781
  }
14692
14782
  }
14693
- if (path3.isAbsolute(resultPath)) {
14783
+ if (path4.isAbsolute(resultPath)) {
14694
14784
  if (!fallbackStorageDir) {
14695
14785
  return await fallbackStorage.readMemoryByPath(resultPath);
14696
14786
  }
@@ -14729,14 +14819,14 @@ ${lines.join("\n\n")}`;
14729
14819
  );
14730
14820
  if (!memory) return null;
14731
14821
  let ownerNamespace = null;
14732
- if (path3.isAbsolute(memory.path)) {
14822
+ if (path4.isAbsolute(memory.path)) {
14733
14823
  const ownerStorage = await this.storageForAbsoluteQmdResultPath(
14734
14824
  memory.path,
14735
14825
  fallbackStorage,
14736
14826
  recallNamespaces
14737
14827
  );
14738
14828
  ownerNamespace = ownerStorage?.namespace ?? null;
14739
- if (!ownerNamespace && this.config.namespacesEnabled) return null;
14829
+ if (!ownerNamespace && resolveNamespaceCapabilities(this.config).namespaces) return null;
14740
14830
  }
14741
14831
  ownerNamespace ??= this.namespaceFromPath(memory.path);
14742
14832
  if (recallNamespaces.length > 0 && !recallNamespaces.includes(ownerNamespace)) {
@@ -14753,16 +14843,16 @@ ${lines.join("\n\n")}`;
14753
14843
  };
14754
14844
  }
14755
14845
  async storageForAbsoluteQmdResultPath(resultPath, fallbackStorage, recallNamespaces = []) {
14756
- const resolvedPath = path3.resolve(resultPath);
14757
- const memoryRoot = path3.resolve(this.config.memoryDir);
14758
- const namespacesRoot = path3.join(memoryRoot, "namespaces");
14846
+ const resolvedPath = path4.resolve(resultPath);
14847
+ const memoryRoot = path4.resolve(this.config.memoryDir);
14848
+ const namespacesRoot = path4.join(memoryRoot, "namespaces");
14759
14849
  const fallbackStorageDir = typeof fallbackStorage.dir === "string" && fallbackStorage.dir ? fallbackStorage.dir : null;
14760
14850
  const matches = [];
14761
14851
  const seenDirs = /* @__PURE__ */ new Set();
14762
14852
  const maybeAddStorage = (storage, namespace) => {
14763
14853
  const storageDir = typeof storage.dir === "string" && storage.dir ? storage.dir : null;
14764
14854
  if (!storageDir) return;
14765
- const candidateRoot = path3.resolve(storageDir);
14855
+ const candidateRoot = path4.resolve(storageDir);
14766
14856
  if (seenDirs.has(candidateRoot)) return;
14767
14857
  if (!isPathInsideStorageRoot(candidateRoot, resolvedPath)) return;
14768
14858
  if (candidateRoot === memoryRoot && isPathInsideStorageRoot(namespacesRoot, resolvedPath)) {
@@ -14780,7 +14870,7 @@ ${lines.join("\n\n")}`;
14780
14870
  candidateNamespaces.add(ns);
14781
14871
  }
14782
14872
  if (isPathInsideStorageRoot(namespacesRoot, resolvedPath)) {
14783
- const relativeToNamespaces = path3.relative(namespacesRoot, resolvedPath);
14873
+ const relativeToNamespaces = path4.relative(namespacesRoot, resolvedPath);
14784
14874
  const [namespaceSegment] = relativeToNamespaces.split(/[\\/]/);
14785
14875
  if (namespaceSegment) {
14786
14876
  candidateNamespaces.add(
@@ -14825,7 +14915,7 @@ ${lines.join("\n\n")}`;
14825
14915
  nsMap = buildMemoryWorthCounterMap(memories);
14826
14916
  this.memoryWorthCounterCache.set(ns, { at: nowMs, counters: nsMap });
14827
14917
  }
14828
- for (const [path4, c] of nsMap) counters.set(path4, c);
14918
+ for (const [path5, c] of nsMap) counters.set(path5, c);
14829
14919
  } catch (err) {
14830
14920
  log.debug("memory-worth: failed to read namespace, skipping", {
14831
14921
  namespace: ns,
@@ -14908,7 +14998,7 @@ ${lines.join("\n\n")}`;
14908
14998
  namespaces,
14909
14999
  {
14910
15000
  readNamespaceMemories: async (ns) => (await this.getStorage(ns)).readAllMemories(),
14911
- readMemoryFrontmatter: async (path4) => {
15001
+ readMemoryFrontmatter: async (path5) => {
14912
15002
  if (!fallbackReader) {
14913
15003
  for (const ns of namespaces) {
14914
15004
  try {
@@ -14919,7 +15009,7 @@ ${lines.join("\n\n")}`;
14919
15009
  }
14920
15010
  }
14921
15011
  if (!fallbackReader) return null;
14922
- const memory = await this.readQmdResultMemory(path4, fallbackReader, namespaces);
15012
+ const memory = await this.readQmdResultMemory(path5, fallbackReader, namespaces);
14923
15013
  return memory ? memory.frontmatter : null;
14924
15014
  }
14925
15015
  },
@@ -15088,13 +15178,13 @@ ${lines.join("\n\n")}`;
15088
15178
  * so facts from non-default namespaces can't cross-match.
15089
15179
  */
15090
15180
  semanticDedupScopeFor(targetStorage) {
15091
- if (!this.config.namespacesEnabled) return {};
15092
- const memoryDir = path3.resolve(this.config.memoryDir);
15093
- const storageDir = path3.resolve(targetStorage.dir);
15181
+ if (!resolveNamespaceCapabilities(this.config).namespaces) return {};
15182
+ const memoryDir = path4.resolve(this.config.memoryDir);
15183
+ const storageDir = path4.resolve(targetStorage.dir);
15094
15184
  if (storageDir === memoryDir) {
15095
15185
  return { pathExcludePrefixes: ["namespaces/"] };
15096
15186
  }
15097
- let rel = path3.relative(memoryDir, storageDir);
15187
+ let rel = path4.relative(memoryDir, storageDir);
15098
15188
  if (!rel || rel.startsWith("..")) {
15099
15189
  log.debug(
15100
15190
  `semantic dedup: target storage dir ${storageDir} is outside memoryDir ${memoryDir}; scoping lookup to absolute path prefix`
@@ -15113,7 +15203,7 @@ ${lines.join("\n\n")}`;
15113
15203
  if (hits.length === 0) return [];
15114
15204
  const results = [];
15115
15205
  for (const hit of hits) {
15116
- const fullPath = path3.isAbsolute(hit.path) ? hit.path : path3.join(this.config.memoryDir, hit.path);
15206
+ const fullPath = path4.isAbsolute(hit.path) ? hit.path : path4.join(this.config.memoryDir, hit.path);
15117
15207
  const memory = await this.storage.readMemoryByPath(fullPath);
15118
15208
  if (!memory) continue;
15119
15209
  results.push({
@@ -15221,7 +15311,7 @@ ${lines.join("\n\n")}`;
15221
15311
  if (timeoutHandle) clearTimeout(timeoutHandle);
15222
15312
  }
15223
15313
  };
15224
- const coldQmdEnabled = this.config.qmdColdTierEnabled === true;
15314
+ const coldQmdEnabled = resolveQmdCapabilities(this.config).qmdColdTier === true;
15225
15315
  const coldCollection = this.config.qmdColdCollection ?? "openclaw-engram-cold";
15226
15316
  const coldMaxResults = this.config.qmdColdMaxResults ?? this.config.qmdMaxResults;
15227
15317
  let longTerm = [];
@@ -15256,7 +15346,7 @@ ${lines.join("\n\n")}`;
15256
15346
  coldFetchLimit,
15257
15347
  coldHybridLimit,
15258
15348
  {
15259
- namespacesEnabled: this.config.namespacesEnabled,
15349
+ namespacesEnabled: resolveNamespaceCapabilities(this.config).namespaces,
15260
15350
  recallNamespaces: options.recallNamespaces,
15261
15351
  resolveNamespace: (p) => this.namespaceFromPath(p),
15262
15352
  collection: coldCollection,
@@ -15302,7 +15392,7 @@ ${lines.join("\n\n")}`;
15302
15392
  }
15303
15393
  if (longTerm.length === 0) return [];
15304
15394
  let results = longTerm;
15305
- if (this.config.namespacesEnabled) {
15395
+ if (resolveNamespaceCapabilities(this.config).namespaces) {
15306
15396
  const recallRoots = [];
15307
15397
  const seenRecallRoots = /* @__PURE__ */ new Set();
15308
15398
  for (const namespace of options.recallNamespaces) {
@@ -15310,7 +15400,7 @@ ${lines.join("\n\n")}`;
15310
15400
  const storage = await this.storageRouter.storageFor(namespace);
15311
15401
  const storageDir = typeof storage.dir === "string" && storage.dir ? storage.dir : null;
15312
15402
  if (!storageDir) continue;
15313
- const recallRoot = path3.resolve(storageDir);
15403
+ const recallRoot = path4.resolve(storageDir);
15314
15404
  if (seenRecallRoots.has(recallRoot)) continue;
15315
15405
  seenRecallRoots.add(recallRoot);
15316
15406
  recallRoots.push(recallRoot);
@@ -15334,8 +15424,8 @@ ${lines.join("\n\n")}`;
15334
15424
  if (resolvedCold) scopedResults.push(resolvedCold.result);
15335
15425
  continue;
15336
15426
  }
15337
- if (path3.isAbsolute(result.path)) {
15338
- const resolvedPath = path3.resolve(result.path);
15427
+ if (path4.isAbsolute(result.path)) {
15428
+ const resolvedPath = path4.resolve(result.path);
15339
15429
  if (recallRoots.some(
15340
15430
  (recallRoot) => isPathInsideStorageRoot(recallRoot, resolvedPath)
15341
15431
  )) {
@@ -15351,8 +15441,8 @@ ${lines.join("\n\n")}`;
15351
15441
  }
15352
15442
  results = results.filter((r) => !isArtifactMemoryPath(r.path));
15353
15443
  if (results.length === 0) return [];
15354
- const isFullModeGraphAssist = this.config.qmdTierParityGraphEnabled && graphCaps.multiGraphMemory && caps.graphAssistInFullMode && options.recallMode === "full" && results.length >= Math.max(1, this.config.graphAssistMinSeedResults ?? 3);
15355
- const shouldRunGraphExpansion = this.config.qmdTierParityGraphEnabled && (options.recallMode === "graph_mode" || isFullModeGraphAssist);
15444
+ const isFullModeGraphAssist = resolveQmdCapabilities(this.config).qmdTierParityGraph && graphCaps.multiGraphMemory && caps.graphAssistInFullMode && options.recallMode === "full" && results.length >= Math.max(1, this.config.graphAssistMinSeedResults ?? 3);
15445
+ const shouldRunGraphExpansion = resolveQmdCapabilities(this.config).qmdTierParityGraph && (options.recallMode === "graph_mode" || isFullModeGraphAssist);
15356
15446
  if (shouldRunGraphExpansion) {
15357
15447
  const { merged } = await this.expandResultsViaGraph({
15358
15448
  memoryResults: results,
@@ -15513,7 +15603,7 @@ ${lines.join("\n\n")}`;
15513
15603
  async flushAccessTracking() {
15514
15604
  if (this.accessTrackingBuffer.size === 0) return;
15515
15605
  const entries = [];
15516
- const namespaces = this.config.namespacesEnabled ? Array.from(
15606
+ const namespaces = resolveNamespaceCapabilities(this.config).namespaces ? Array.from(
15517
15607
  /* @__PURE__ */ new Set([
15518
15608
  this.config.defaultNamespace,
15519
15609
  this.config.sharedNamespace,
@@ -16169,7 +16259,7 @@ ${lines.join("\n\n")}`;
16169
16259
  return resolved;
16170
16260
  }
16171
16261
  namespaceFromPath(p) {
16172
- if (!this.config.namespacesEnabled) return this.config.defaultNamespace;
16262
+ if (!resolveNamespaceCapabilities(this.config).namespaces) return this.config.defaultNamespace;
16173
16263
  const parts = qmdCollectionPathParts(p);
16174
16264
  const collectionNamespace = parts ? this.qmdCollectionNamespaceFromPrefix(parts.collection) : null;
16175
16265
  if (collectionNamespace) return collectionNamespace;
@@ -16270,4 +16360,4 @@ export {
16270
16360
  resolvePersistedMemoryRelativePath,
16271
16361
  Orchestrator
16272
16362
  };
16273
- //# sourceMappingURL=chunk-OUITHS6V.js.map
16363
+ //# sourceMappingURL=chunk-FLCYY5JX.js.map