@remnic/core 9.3.752 → 9.3.754

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 (331) hide show
  1. package/dist/access-admin-ops-surface.d.ts +194 -0
  2. package/dist/access-admin-ops-surface.js +128 -0
  3. package/dist/access-boundary.d.ts +5 -5
  4. package/dist/access-boundary.js +37 -37
  5. package/dist/access-cli.js +109 -109
  6. package/dist/access-http.d.ts +5 -5
  7. package/dist/access-http.js +46 -46
  8. package/dist/access-lcm-surface.d.ts +188 -0
  9. package/dist/access-lcm-surface.js +128 -0
  10. package/dist/access-lcm-surface.js.map +1 -0
  11. package/dist/access-mcp.d.ts +5 -5
  12. package/dist/access-mcp.js +42 -42
  13. package/dist/access-operations-batch.js +39 -39
  14. package/dist/access-operations.d.ts +8 -8
  15. package/dist/access-operations.js +41 -41
  16. package/dist/access-recall-surface.d.ts +5 -5
  17. package/dist/access-recall-surface.js +36 -36
  18. package/dist/access-schema.d.ts +54 -54
  19. package/dist/access-schema.js +5 -5
  20. package/dist/{access-service-C2cOHQvg.d.ts → access-service-DKRV1zxh.d.ts} +75 -159
  21. package/dist/access-service.d.ts +5 -5
  22. package/dist/access-service.js +40 -36
  23. package/dist/access-surface-catalog.d.ts +5 -5
  24. package/dist/action-confidence.d.ts +1 -1
  25. package/dist/active-memory-bridge.d.ts +1 -1
  26. package/dist/active-recall.d.ts +1 -1
  27. package/dist/active-recall.js +5 -5
  28. package/dist/adapters/index.js +7 -7
  29. package/dist/adapters/registry.js +3 -3
  30. package/dist/{auto-sync-IEBKPGAM.js → auto-sync-G4YKBPOU.js} +5 -5
  31. package/dist/behavior-learner.d.ts +1 -1
  32. package/dist/behavior-signals.d.ts +1 -1
  33. package/dist/bootstrap.d.ts +4 -4
  34. package/dist/briefing.d.ts +3 -3
  35. package/dist/briefing.js +13 -13
  36. package/dist/buffer-surprise-report.d.ts +1 -1
  37. package/dist/buffer.d.ts +3 -3
  38. package/dist/buffer.js +2 -2
  39. package/dist/calibration.d.ts +1 -1
  40. package/dist/calibration.js +2 -2
  41. package/dist/capabilities.d.ts +1 -1
  42. package/dist/{catalog-D_FvzTM0.d.ts → catalog-BEmNVRN0.d.ts} +1 -1
  43. package/dist/causal-behavior.d.ts +1 -1
  44. package/dist/causal-consolidation.d.ts +1 -1
  45. package/dist/causal-consolidation.js +16 -16
  46. package/dist/causal-trajectory-graph.d.ts +1 -1
  47. package/dist/{chunk-5DXUE7GB.js → chunk-24463PIV.js} +2 -2
  48. package/dist/{chunk-2DPCAW2T.js → chunk-2MHCWXX6.js} +8 -8
  49. package/dist/{chunk-KFNG72W7.js → chunk-2MR3MFQB.js} +6 -6
  50. package/dist/{chunk-YTU7WKYN.js → chunk-2OZ2JEUP.js} +2 -2
  51. package/dist/{chunk-JBPKEARU.js → chunk-2QSZNTDO.js} +7 -7
  52. package/dist/{chunk-EHYB325U.js → chunk-3DOD6ICJ.js} +2 -2
  53. package/dist/{chunk-5JAT4ZJD.js → chunk-4DLFJJOQ.js} +4 -4
  54. package/dist/{chunk-JNKSFIAY.js → chunk-4DVYRPLL.js} +76 -76
  55. package/dist/{chunk-VUA4S7P6.js → chunk-5J4OL7TJ.js} +4 -4
  56. package/dist/{chunk-BIAMJUUJ.js → chunk-5QANTTY2.js} +4 -4
  57. package/dist/{chunk-K5CWCJKJ.js → chunk-7AL5WNPW.js} +10 -10
  58. package/dist/{chunk-V4ZPLQLC.js → chunk-7CAJLUNW.js} +2 -2
  59. package/dist/{chunk-MEPWWSTD.js → chunk-BERWPOXU.js} +4 -4
  60. package/dist/{chunk-UFNQKZV7.js → chunk-BQ6J6P3K.js} +23 -23
  61. package/dist/{chunk-KT2VQLP7.js → chunk-CJ276MDI.js} +8 -8
  62. package/dist/{chunk-DC5OBZS3.js → chunk-COZEVVXZ.js} +2 -2
  63. package/dist/{chunk-67JRXV6Z.js → chunk-CXCZ4LAI.js} +5 -5
  64. package/dist/{chunk-MW7UUXTA.js → chunk-DBSMLRTO.js} +5 -5
  65. package/dist/{chunk-RBYV3WSB.js → chunk-DS4QM6I7.js} +4 -4
  66. package/dist/{chunk-MLDAD27I.js → chunk-G7LCG56O.js} +8 -8
  67. package/dist/{chunk-IBPEVGP5.js → chunk-GAH5755F.js} +2 -2
  68. package/dist/{chunk-SC5AEZLU.js → chunk-GPFXPC2V.js} +10 -10
  69. package/dist/{chunk-R7TGDLV3.js → chunk-HM6UJPPO.js} +4 -4
  70. package/dist/{chunk-2U4E34Y3.js → chunk-JBO6UBIE.js} +4 -4
  71. package/dist/{chunk-33NX5BLR.js → chunk-JRZV3767.js} +4 -4
  72. package/dist/{chunk-IQWFWSCP.js → chunk-JZ7P26GF.js} +4 -4
  73. package/dist/{chunk-XKAOT4ZB.js → chunk-K5LLP4CY.js} +4 -4
  74. package/dist/{chunk-JHZ3LEM7.js → chunk-KURUULFF.js} +2 -2
  75. package/dist/{chunk-VX2RYM2K.js → chunk-L4AS7TIG.js} +5644 -5529
  76. package/dist/chunk-L4AS7TIG.js.map +1 -0
  77. package/dist/{chunk-LQ6JI4VH.js → chunk-LD53WPMU.js} +4 -4
  78. package/dist/{chunk-RRRZ3CLN.js → chunk-LOPZ2DWR.js} +4 -4
  79. package/dist/{chunk-GFGYHLON.js → chunk-OH66EBCS.js} +2 -2
  80. package/dist/{chunk-OKOF7ITI.js → chunk-OSMBC3JU.js} +6 -6
  81. package/dist/{chunk-QMMCMV2L.js → chunk-PJQMISPD.js} +7 -7
  82. package/dist/{chunk-VQL22SHO.js → chunk-PYVZKEZZ.js} +130 -130
  83. package/dist/{chunk-DCWIQFNA.js → chunk-T422SYM6.js} +5 -5
  84. package/dist/{chunk-5CEJH5ZN.js → chunk-TAPSNIMA.js} +4 -4
  85. package/dist/{chunk-3NN73CM7.js → chunk-TH7WMHVK.js} +2 -2
  86. package/dist/{chunk-YGNQG4Q6.js → chunk-THZ4WR5L.js} +19 -19
  87. package/dist/{chunk-MTN2G4DT.js → chunk-TIFF32QK.js} +2 -2
  88. package/dist/{chunk-QRM3K3XT.js → chunk-TJATYB3F.js} +14 -14
  89. package/dist/{chunk-6ROCH5JV.js → chunk-TXALJRYO.js} +8 -8
  90. package/dist/{chunk-OVMLS7TN.js → chunk-U2SMR57B.js} +10 -10
  91. package/dist/{chunk-S5UYWK3O.js → chunk-V4C4SFZB.js} +6 -6
  92. package/dist/{chunk-L3VSTJ2V.js → chunk-VSU2NZGC.js} +2 -2
  93. package/dist/{chunk-GECEETQ3.js → chunk-W3M34XT4.js} +4 -4
  94. package/dist/{chunk-FXRFFYWD.js → chunk-WIWPSQYU.js} +4 -4
  95. package/dist/{chunk-FEELYTRT.js → chunk-WS6GLJ7P.js} +5 -5
  96. package/dist/{chunk-C4LNKQ3M.js → chunk-WUVUTOUV.js} +5 -5
  97. package/dist/{chunk-WRFKZEO6.js → chunk-YQGHW5ML.js} +4 -4
  98. package/dist/{chunk-J2JB6BHT.js → chunk-YRBXBHU7.js} +8 -8
  99. package/dist/{chunk-ZGGI3COG.js → chunk-ZJMSTFOR.js} +9 -9
  100. package/dist/{cli-DFUU9WYu.d.ts → cli-D-xw8Sp1.d.ts} +3 -3
  101. package/dist/cli.d.ts +6 -6
  102. package/dist/cli.js +73 -73
  103. package/dist/compounding/engine.d.ts +3 -3
  104. package/dist/compounding/engine.js +15 -15
  105. package/dist/compounding/preference-consolidator.d.ts +1 -1
  106. package/dist/compression-optimizer.d.ts +1 -1
  107. package/dist/config.d.ts +1 -1
  108. package/dist/config.js +2 -2
  109. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  110. package/dist/connectors/codex-materialize-runner.js +14 -14
  111. package/dist/connectors/codex-materialize.d.ts +1 -1
  112. package/dist/connectors/index.d.ts +1 -1
  113. package/dist/connectors/index.js +16 -16
  114. package/dist/consolidation-provenance-check.d.ts +1 -1
  115. package/dist/consolidation-undo.d.ts +1 -1
  116. package/dist/contradiction/index.d.ts +1 -1
  117. package/dist/contradiction/index.js +2 -2
  118. package/dist/{contradiction-scan-KO4WWCS4.js → contradiction-scan-2SODRNUF.js} +3 -3
  119. package/dist/contradiction-scan-2SODRNUF.js.map +1 -0
  120. package/dist/conversation-index/backend.d.ts +1 -1
  121. package/dist/conversation-index/backend.js +2 -2
  122. package/dist/conversation-index/chunker.d.ts +1 -1
  123. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  124. package/dist/conversation-index/indexer.d.ts +1 -1
  125. package/dist/conversation-index/search.d.ts +1 -1
  126. package/dist/day-summary.d.ts +1 -1
  127. package/dist/day-summary.js +2 -2
  128. package/dist/delinearize.d.ts +1 -1
  129. package/dist/direct-answer-wiring.d.ts +1 -1
  130. package/dist/direct-answer.d.ts +1 -1
  131. package/dist/embedding-fallback.d.ts +1 -1
  132. package/dist/embedding-fallback.js +2 -2
  133. package/dist/enrichment/index.d.ts +1 -1
  134. package/dist/entity-retrieval.d.ts +1 -1
  135. package/dist/entity-retrieval.js +14 -14
  136. package/dist/entity-schema.d.ts +1 -1
  137. package/dist/explicit-capture.d.ts +6 -6
  138. package/dist/explicit-capture.js +2 -2
  139. package/dist/extraction-faithfulness.d.ts +1 -1
  140. package/dist/extraction-faithfulness.js +3 -3
  141. package/dist/extraction-judge-telemetry.d.ts +1 -1
  142. package/dist/extraction-judge-training.d.ts +1 -1
  143. package/dist/extraction-judge.d.ts +1 -1
  144. package/dist/extraction-judge.js +3 -3
  145. package/dist/extraction.d.ts +1 -1
  146. package/dist/extraction.js +7 -7
  147. package/dist/fallback-llm.d.ts +1 -1
  148. package/dist/fallback-llm.js +2 -2
  149. package/dist/{first-start-migration-4I3VDSYS.js → first-start-migration-DY6YCRC2.js} +2 -2
  150. package/dist/{forget-WYLR4ZFV.js → forget-OEE5OELK.js} +2 -2
  151. package/dist/graph-dashboard-diff.d.ts +1 -1
  152. package/dist/graph-dashboard-key.d.ts +1 -1
  153. package/dist/graph-dashboard-parser.d.ts +1 -1
  154. package/dist/graph-edge-reinforcement.d.ts +1 -1
  155. package/dist/graph-snapshot.d.ts +1 -1
  156. package/dist/graph.d.ts +1 -1
  157. package/dist/identity-continuity.d.ts +1 -1
  158. package/dist/importance.d.ts +1 -1
  159. package/dist/index.d.ts +1284 -1284
  160. package/dist/index.js +204 -204
  161. package/dist/intent.d.ts +1 -1
  162. package/dist/lcm/engine.d.ts +1 -1
  163. package/dist/lcm/engine.js +3 -3
  164. package/dist/lcm/index.d.ts +1 -1
  165. package/dist/lcm/index.js +8 -8
  166. package/dist/lcm/tools.d.ts +1 -1
  167. package/dist/lifecycle.d.ts +1 -1
  168. package/dist/live-connectors-runner.d.ts +1 -1
  169. package/dist/local-llm.d.ts +1 -1
  170. package/dist/local-llm.js +2 -2
  171. package/dist/local-model-endpoint.d.ts +1 -1
  172. package/dist/maintenance/memory-governance.d.ts +1 -1
  173. package/dist/maintenance/memory-governance.js +13 -13
  174. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +13 -13
  175. package/dist/maintenance/rebuild-memory-projection.js +14 -14
  176. package/dist/mcp-memory-inspector-app.d.ts +5 -5
  177. package/dist/memory-action-policy.d.ts +1 -1
  178. package/dist/memory-cache.d.ts +1 -1
  179. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  180. package/dist/memory-projection-store.d.ts +1 -1
  181. package/dist/memory-provenance.d.ts +1 -1
  182. package/dist/memory-worth-outcomes.d.ts +1 -1
  183. package/dist/models-json.d.ts +1 -1
  184. package/dist/namespaces/migrate.d.ts +2 -2
  185. package/dist/namespaces/migrate.js +26 -26
  186. package/dist/namespaces/principal.d.ts +1 -1
  187. package/dist/namespaces/search.d.ts +1 -1
  188. package/dist/namespaces/search.js +11 -11
  189. package/dist/namespaces/storage.d.ts +2 -2
  190. package/dist/namespaces/storage.js +15 -15
  191. package/dist/native-knowledge.d.ts +1 -1
  192. package/dist/operator-toolkit.d.ts +1 -1
  193. package/dist/operator-toolkit.js +33 -33
  194. package/dist/orchestration/compression-guideline-coordinator.d.ts +1 -1
  195. package/dist/orchestration/compression-guideline-coordinator.js +2 -2
  196. package/dist/orchestration/maintenance.d.ts +2 -2
  197. package/dist/orchestration/maintenance.js +19 -19
  198. package/dist/{orchestrator-BhxMxtQJ.d.ts → orchestrator-D7ZGOQLX.d.ts} +77 -77
  199. package/dist/orchestrator.d.ts +4 -4
  200. package/dist/orchestrator.js +109 -109
  201. package/dist/patterns-cli.d.ts +1 -1
  202. package/dist/policy-runtime.d.ts +1 -1
  203. package/dist/provenance.d.ts +1 -1
  204. package/dist/qmd-recall-cache.d.ts +1 -1
  205. package/dist/qmd.d.ts +1 -1
  206. package/dist/recall-disclosure-escalation.d.ts +1 -1
  207. package/dist/recall-explain-renderer.d.ts +1 -1
  208. package/dist/recall-planner-llm.d.ts +1 -1
  209. package/dist/recall-planner-llm.js +2 -2
  210. package/dist/recall-state.d.ts +1 -1
  211. package/dist/recall-tag-filter.d.ts +1 -1
  212. package/dist/recall-xray-cli.d.ts +1 -1
  213. package/dist/recall-xray-renderer.d.ts +1 -1
  214. package/dist/recall-xray.d.ts +1 -1
  215. package/dist/resolve-auth-token.d.ts +1 -1
  216. package/dist/resume-bundles.js +2 -2
  217. package/dist/retrieval-agents.d.ts +1 -1
  218. package/dist/retrieval-tiers.d.ts +1 -1
  219. package/dist/routing/engine.d.ts +1 -1
  220. package/dist/routing/store.d.ts +1 -1
  221. package/dist/routing/store.js +2 -2
  222. package/dist/schemas.d.ts +42 -42
  223. package/dist/search/embed-helper.d.ts +1 -1
  224. package/dist/search/embed-helper.js +2 -2
  225. package/dist/search/factory.d.ts +1 -1
  226. package/dist/search/factory.js +10 -10
  227. package/dist/search/index.d.ts +1 -1
  228. package/dist/search/index.js +14 -14
  229. package/dist/search/lancedb-backend.d.ts +1 -1
  230. package/dist/search/lancedb-backend.js +2 -2
  231. package/dist/search/meilisearch-backend.d.ts +1 -1
  232. package/dist/search/meilisearch-backend.js +2 -2
  233. package/dist/search/noop-backend.d.ts +1 -1
  234. package/dist/search/orama-backend.d.ts +1 -1
  235. package/dist/search/orama-backend.js +2 -2
  236. package/dist/search/port.d.ts +1 -1
  237. package/dist/search/remote-backend.d.ts +1 -1
  238. package/dist/{semantic-consolidation-BrsoFeMP.d.ts → semantic-consolidation-7Sndms2M.d.ts} +1 -1
  239. package/dist/semantic-consolidation.d.ts +2 -2
  240. package/dist/semantic-consolidation.js +16 -16
  241. package/dist/semantic-rule-promotion.js +13 -13
  242. package/dist/semantic-rule-verifier.d.ts +1 -1
  243. package/dist/semantic-rule-verifier.js +13 -13
  244. package/dist/session-observer-bands.d.ts +1 -1
  245. package/dist/session-observer-state.d.ts +1 -1
  246. package/dist/shared-context/manager.d.ts +1 -1
  247. package/dist/shared-context/manager.js +2 -2
  248. package/dist/signal.d.ts +1 -1
  249. package/dist/storage.d.ts +1 -1
  250. package/dist/storage.js +12 -12
  251. package/dist/summarizer.d.ts +1 -1
  252. package/dist/summarizer.js +5 -5
  253. package/dist/summary-snapshot.d.ts +1 -1
  254. package/dist/temporal-supersession.d.ts +1 -1
  255. package/dist/temporal-validity.d.ts +1 -1
  256. package/dist/threading.d.ts +1 -1
  257. package/dist/tier-migration.d.ts +1 -1
  258. package/dist/tier-routing.d.ts +1 -1
  259. package/dist/{tier-stats-5XF4UBRQ.js → tier-stats-TG6GUZ6N.js} +4 -4
  260. package/dist/topics.d.ts +1 -1
  261. package/dist/transcript.d.ts +1 -1
  262. package/dist/transfer/backup.js +1 -1
  263. package/dist/transfer/capsule-export.js +1 -1
  264. package/dist/transfer/types.d.ts +44 -44
  265. package/dist/trust-score-stage.d.ts +1 -1
  266. package/dist/trust-score.d.ts +1 -1
  267. package/dist/{types-BfI4uJeb.d.ts → types-DTEFxFuL.d.ts} +1 -1
  268. package/dist/types.d.ts +1 -1
  269. package/dist/utility-runtime.d.ts +1 -1
  270. package/dist/verified-recall.js +13 -13
  271. package/package.json +2 -2
  272. package/src/access-admin-ops-surface.ts +828 -0
  273. package/src/access-lcm-surface.ts +517 -0
  274. package/src/access-service.ts +62 -1115
  275. package/dist/chunk-VX2RYM2K.js.map +0 -1
  276. /package/dist/{contradiction-scan-KO4WWCS4.js.map → access-admin-ops-surface.js.map} +0 -0
  277. /package/dist/{auto-sync-IEBKPGAM.js.map → auto-sync-G4YKBPOU.js.map} +0 -0
  278. /package/dist/{chunk-5DXUE7GB.js.map → chunk-24463PIV.js.map} +0 -0
  279. /package/dist/{chunk-2DPCAW2T.js.map → chunk-2MHCWXX6.js.map} +0 -0
  280. /package/dist/{chunk-KFNG72W7.js.map → chunk-2MR3MFQB.js.map} +0 -0
  281. /package/dist/{chunk-YTU7WKYN.js.map → chunk-2OZ2JEUP.js.map} +0 -0
  282. /package/dist/{chunk-JBPKEARU.js.map → chunk-2QSZNTDO.js.map} +0 -0
  283. /package/dist/{chunk-EHYB325U.js.map → chunk-3DOD6ICJ.js.map} +0 -0
  284. /package/dist/{chunk-5JAT4ZJD.js.map → chunk-4DLFJJOQ.js.map} +0 -0
  285. /package/dist/{chunk-JNKSFIAY.js.map → chunk-4DVYRPLL.js.map} +0 -0
  286. /package/dist/{chunk-VUA4S7P6.js.map → chunk-5J4OL7TJ.js.map} +0 -0
  287. /package/dist/{chunk-BIAMJUUJ.js.map → chunk-5QANTTY2.js.map} +0 -0
  288. /package/dist/{chunk-K5CWCJKJ.js.map → chunk-7AL5WNPW.js.map} +0 -0
  289. /package/dist/{chunk-V4ZPLQLC.js.map → chunk-7CAJLUNW.js.map} +0 -0
  290. /package/dist/{chunk-MEPWWSTD.js.map → chunk-BERWPOXU.js.map} +0 -0
  291. /package/dist/{chunk-UFNQKZV7.js.map → chunk-BQ6J6P3K.js.map} +0 -0
  292. /package/dist/{chunk-KT2VQLP7.js.map → chunk-CJ276MDI.js.map} +0 -0
  293. /package/dist/{chunk-DC5OBZS3.js.map → chunk-COZEVVXZ.js.map} +0 -0
  294. /package/dist/{chunk-67JRXV6Z.js.map → chunk-CXCZ4LAI.js.map} +0 -0
  295. /package/dist/{chunk-MW7UUXTA.js.map → chunk-DBSMLRTO.js.map} +0 -0
  296. /package/dist/{chunk-RBYV3WSB.js.map → chunk-DS4QM6I7.js.map} +0 -0
  297. /package/dist/{chunk-MLDAD27I.js.map → chunk-G7LCG56O.js.map} +0 -0
  298. /package/dist/{chunk-IBPEVGP5.js.map → chunk-GAH5755F.js.map} +0 -0
  299. /package/dist/{chunk-SC5AEZLU.js.map → chunk-GPFXPC2V.js.map} +0 -0
  300. /package/dist/{chunk-R7TGDLV3.js.map → chunk-HM6UJPPO.js.map} +0 -0
  301. /package/dist/{chunk-2U4E34Y3.js.map → chunk-JBO6UBIE.js.map} +0 -0
  302. /package/dist/{chunk-33NX5BLR.js.map → chunk-JRZV3767.js.map} +0 -0
  303. /package/dist/{chunk-IQWFWSCP.js.map → chunk-JZ7P26GF.js.map} +0 -0
  304. /package/dist/{chunk-XKAOT4ZB.js.map → chunk-K5LLP4CY.js.map} +0 -0
  305. /package/dist/{chunk-JHZ3LEM7.js.map → chunk-KURUULFF.js.map} +0 -0
  306. /package/dist/{chunk-LQ6JI4VH.js.map → chunk-LD53WPMU.js.map} +0 -0
  307. /package/dist/{chunk-RRRZ3CLN.js.map → chunk-LOPZ2DWR.js.map} +0 -0
  308. /package/dist/{chunk-GFGYHLON.js.map → chunk-OH66EBCS.js.map} +0 -0
  309. /package/dist/{chunk-OKOF7ITI.js.map → chunk-OSMBC3JU.js.map} +0 -0
  310. /package/dist/{chunk-QMMCMV2L.js.map → chunk-PJQMISPD.js.map} +0 -0
  311. /package/dist/{chunk-VQL22SHO.js.map → chunk-PYVZKEZZ.js.map} +0 -0
  312. /package/dist/{chunk-DCWIQFNA.js.map → chunk-T422SYM6.js.map} +0 -0
  313. /package/dist/{chunk-5CEJH5ZN.js.map → chunk-TAPSNIMA.js.map} +0 -0
  314. /package/dist/{chunk-3NN73CM7.js.map → chunk-TH7WMHVK.js.map} +0 -0
  315. /package/dist/{chunk-YGNQG4Q6.js.map → chunk-THZ4WR5L.js.map} +0 -0
  316. /package/dist/{chunk-MTN2G4DT.js.map → chunk-TIFF32QK.js.map} +0 -0
  317. /package/dist/{chunk-QRM3K3XT.js.map → chunk-TJATYB3F.js.map} +0 -0
  318. /package/dist/{chunk-6ROCH5JV.js.map → chunk-TXALJRYO.js.map} +0 -0
  319. /package/dist/{chunk-OVMLS7TN.js.map → chunk-U2SMR57B.js.map} +0 -0
  320. /package/dist/{chunk-S5UYWK3O.js.map → chunk-V4C4SFZB.js.map} +0 -0
  321. /package/dist/{chunk-L3VSTJ2V.js.map → chunk-VSU2NZGC.js.map} +0 -0
  322. /package/dist/{chunk-GECEETQ3.js.map → chunk-W3M34XT4.js.map} +0 -0
  323. /package/dist/{chunk-FXRFFYWD.js.map → chunk-WIWPSQYU.js.map} +0 -0
  324. /package/dist/{chunk-FEELYTRT.js.map → chunk-WS6GLJ7P.js.map} +0 -0
  325. /package/dist/{chunk-C4LNKQ3M.js.map → chunk-WUVUTOUV.js.map} +0 -0
  326. /package/dist/{chunk-WRFKZEO6.js.map → chunk-YQGHW5ML.js.map} +0 -0
  327. /package/dist/{chunk-J2JB6BHT.js.map → chunk-YRBXBHU7.js.map} +0 -0
  328. /package/dist/{chunk-ZGGI3COG.js.map → chunk-ZJMSTFOR.js.map} +0 -0
  329. /package/dist/{first-start-migration-4I3VDSYS.js.map → first-start-migration-DY6YCRC2.js.map} +0 -0
  330. /package/dist/{forget-WYLR4ZFV.js.map → forget-OEE5OELK.js.map} +0 -0
  331. /package/dist/{tier-stats-5XF4UBRQ.js.map → tier-stats-TG6GUZ6N.js.map} +0 -0
@@ -0,0 +1,828 @@
1
+ /**
2
+ * Access admin/ops read-surface (extracted from access-service.ts;
3
+ * god-file decomposition, #1526 playbook: verbatim move + live selfDeps
4
+ * wiring).
5
+ *
6
+ * Owns the operator-facing read/maintenance surfaces of the access
7
+ * layer: review queue listing, governance runs, conversation-index
8
+ * updates, profiling reports, graph snapshots, capsule listing, dreams
9
+ * pipeline runs, and admin memory promotion.
10
+ */
11
+
12
+ import * as nodeFs from "node:fs/promises";
13
+ import * as nodePath from "node:path";
14
+ import { AdminPromotionError, type MemoryPromotionTargetKind, type PromotionStorageProvider, promoteMemory } from "./admin/admin-surfaces.js";
15
+ import { resolveGraphConstructionCapabilities, resolveIndexingCapabilities, resolveNamespaceCapabilities } from "./capabilities.js";
16
+ import { type CapsuleListEntry, defaultCapsulesDir } from "./capsule-cli.js";
17
+ import { resolveCodingNamespaceOverlay } from "./coding/coding-namespace.js";
18
+ import { type GraphSnapshotNodeMetadata, type GraphSnapshotRequest, type GraphSnapshotResponse, buildGraphSnapshot } from "./graph-snapshot.js";
19
+ import { log } from "./logger.js";
20
+ import { buildQualityScore, groupActionsByStatus, listMemoryGovernanceRuns, readMemoryGovernanceRunArtifact, runMemoryGovernance } from "./maintenance/memory-governance.js";
21
+ import { resolveScopeProfilePlan } from "./namespaces/scope-profiles.js";
22
+ import type { Orchestrator } from "./orchestrator.js";
23
+ import { formatProfileTraceAscii } from "./profiling.js";
24
+ import { resolveScopePlan } from "./scopes/scope-plan.js";
25
+ import {
26
+ EngramAccessInputError,
27
+ buildProjectedGovernanceProposedActions,
28
+ hasGroupedGovernanceActions,
29
+ type AccessProfilingReportRequest,
30
+ type AccessProfilingReportResponse,
31
+ type EngramAccessCapsuleListResponse,
32
+ type EngramAccessReviewQueueResponse,
33
+ } from "./access-service.js";
34
+
35
+ export interface AccessAdminOpsSurfaceDeps {
36
+ readonly orchestrator: Orchestrator;
37
+ resolveReadableNamespace(namespace: string | undefined, principal?: string): string;
38
+ writableNamespaceFor(
39
+ namespace: string | undefined,
40
+ sessionKey: string | undefined,
41
+ authenticatedPrincipal?: string,
42
+ ): string;
43
+ }
44
+
45
+ export class AccessAdminOpsSurface {
46
+ constructor(
47
+ private readonly deps: AccessAdminOpsSurfaceDeps,
48
+ ) {}
49
+
50
+ async reviewQueue(runId?: string, namespace?: string, principal?: string): Promise<EngramAccessReviewQueueResponse> {
51
+ const resolvedNamespace = this.deps.resolveReadableNamespace(namespace, principal);
52
+ const storage = await this.deps.orchestrator.getStorage(resolvedNamespace);
53
+ const projected = await storage.getProjectedGovernanceRecord();
54
+ if (projected && (!runId || projected.runId === runId.trim())) {
55
+ const projectedAppliedActions = projected.appliedActionRows.map((row) => ({
56
+ action: row.action,
57
+ memoryId: row.memoryId,
58
+ reasonCode: row.reasonCode,
59
+ beforeStatus: row.beforeStatus,
60
+ afterStatus: row.afterStatus,
61
+ originalPath: row.originalPath,
62
+ currentPath: row.currentPath,
63
+ })) as Awaited<
64
+ ReturnType<typeof readMemoryGovernanceRunArtifact>
65
+ >["appliedActions"];
66
+ const projectedProposedActions = await buildProjectedGovernanceProposedActions(storage, projected);
67
+ const projectedArtifact = await (async () => {
68
+ try {
69
+ return await readMemoryGovernanceRunArtifact(storage.dir, projected.runId);
70
+ } catch {
71
+ return null;
72
+ }
73
+ })();
74
+ const metrics = projected.metrics as Awaited<ReturnType<typeof readMemoryGovernanceRunArtifact>>["metrics"];
75
+ const fallbackTransitionReport = {
76
+ proposed: groupActionsByStatus(projectedProposedActions),
77
+ applied: groupActionsByStatus(projectedAppliedActions),
78
+ };
79
+ const transitionReport = projectedArtifact?.transitionReport
80
+ ? {
81
+ proposed:
82
+ hasGroupedGovernanceActions(projectedArtifact.transitionReport.proposed) || projectedProposedActions.length === 0
83
+ ? projectedArtifact.transitionReport.proposed
84
+ : fallbackTransitionReport.proposed,
85
+ applied:
86
+ hasGroupedGovernanceActions(projectedArtifact.transitionReport.applied) || projectedAppliedActions.length === 0
87
+ ? projectedArtifact.transitionReport.applied
88
+ : fallbackTransitionReport.applied,
89
+ }
90
+ : fallbackTransitionReport;
91
+ const qualityScore = projectedArtifact?.qualityScore ?? metrics?.qualityScore ?? buildQualityScore(metrics?.reviewReasons ?? {
92
+ exact_duplicate: 0,
93
+ semantic_duplicate_candidate: 0,
94
+ disputed_memory: 0,
95
+ speculative_low_confidence: 0,
96
+ archive_candidate: 0,
97
+ explicit_capture_review: 0,
98
+ malformed_import: 0,
99
+ });
100
+ const effectiveMetrics = metrics ? { ...metrics, qualityScore: metrics.qualityScore ?? qualityScore } : metrics;
101
+
102
+ return {
103
+ found: true,
104
+ namespace: resolvedNamespace,
105
+ runId: projected.runId,
106
+ summary: projected.summary as Awaited<ReturnType<typeof readMemoryGovernanceRunArtifact>>["summary"],
107
+ metrics: effectiveMetrics,
108
+ qualityScore,
109
+ reviewQueue: projected.reviewQueueRows.map((row) => ({
110
+ entryId: row.entryId,
111
+ memoryId: row.memoryId,
112
+ path: row.path,
113
+ reasonCode: row.reasonCode,
114
+ severity: row.severity,
115
+ suggestedAction: row.suggestedAction,
116
+ suggestedStatus: row.suggestedStatus,
117
+ relatedMemoryIds: row.relatedMemoryIds,
118
+ })) as Awaited<
119
+ ReturnType<typeof readMemoryGovernanceRunArtifact>
120
+ >["reviewQueue"],
121
+ appliedActions: projectedAppliedActions,
122
+ transitionReport,
123
+ report: projected.report,
124
+ };
125
+ }
126
+
127
+ const resolvedRunId = runId?.trim() || (await listMemoryGovernanceRuns(storage.dir))[0];
128
+ if (!resolvedRunId) return { found: false, namespace: resolvedNamespace };
129
+ const artifact = await readMemoryGovernanceRunArtifact(storage.dir, resolvedRunId);
130
+ return {
131
+ found: true,
132
+ namespace: resolvedNamespace,
133
+ runId: resolvedRunId,
134
+ summary: artifact.summary,
135
+ metrics: artifact.metrics,
136
+ qualityScore: artifact.qualityScore,
137
+ reviewQueue: artifact.reviewQueue,
138
+ appliedActions: artifact.appliedActions,
139
+ transitionReport: artifact.transitionReport,
140
+ report: artifact.report,
141
+ };
142
+ }
143
+
144
+ async governanceRun(
145
+ request: {
146
+ namespace?: string;
147
+ mode?: "shadow" | "apply";
148
+ recentDays?: number;
149
+ maxMemories?: number;
150
+ batchSize?: number;
151
+ authenticatedPrincipal?: string;
152
+ },
153
+ principal?: string,
154
+ ): Promise<{
155
+ namespace: string;
156
+ runId: string;
157
+ traceId: string;
158
+ mode: "shadow" | "apply";
159
+ reviewQueueCount: number;
160
+ proposedActionCount: number;
161
+ appliedActionCount: number;
162
+ summaryPath: string;
163
+ reportPath: string;
164
+ }> {
165
+ const deepSleep = this.deps.orchestrator.config.dreamsPhases.deepSleep;
166
+ if (deepSleep.enabled === false && deepSleep.enabledExplicitlySet === true) {
167
+ throw new Error("memory governance is disabled by dreams.phases.deepSleep.enabled=false");
168
+ }
169
+ const resolvedNamespace = this.deps.writableNamespaceFor(
170
+ request.namespace,
171
+ undefined,
172
+ request.authenticatedPrincipal ?? principal,
173
+ );
174
+ const storage = await this.deps.orchestrator.getStorage(resolvedNamespace);
175
+ const mode = request.mode === "apply" ? "apply" : "shadow";
176
+ const boundedBatchSize =
177
+ typeof request.batchSize === "number" && Number.isFinite(request.batchSize)
178
+ ? Math.max(1, Math.floor(request.batchSize))
179
+ : undefined;
180
+ const result = await runMemoryGovernance({
181
+ memoryDir: storage.dir,
182
+ mode,
183
+ recentDays:
184
+ typeof request.recentDays === "number" && Number.isFinite(request.recentDays)
185
+ ? Math.max(1, Math.floor(request.recentDays))
186
+ : undefined,
187
+ maxMemories:
188
+ typeof request.maxMemories === "number" && Number.isFinite(request.maxMemories)
189
+ ? Math.max(1, Math.floor(request.maxMemories))
190
+ : undefined,
191
+ batchSize: boundedBatchSize,
192
+ });
193
+ if (mode === "apply") {
194
+ try {
195
+ await this.deps.orchestrator.processEntitySynthesisQueue(
196
+ resolvedNamespace,
197
+ Math.min(boundedBatchSize ?? 5, 5),
198
+ );
199
+ } catch (error) {
200
+ log.debug(`governanceRun: entity synthesis refresh failed after governance apply: ${error}`);
201
+ }
202
+ }
203
+
204
+ return {
205
+ namespace: resolvedNamespace,
206
+ runId: result.runId,
207
+ traceId: result.traceId,
208
+ mode: result.mode,
209
+ reviewQueueCount: result.reviewQueue.length,
210
+ proposedActionCount: result.proposedActions.length,
211
+ appliedActionCount: result.appliedActions.length,
212
+ summaryPath: result.summaryPath,
213
+ reportPath: result.reportPath,
214
+ };
215
+ }
216
+
217
+ async conversationIndexUpdate(
218
+ request: {
219
+ sessionKey?: string;
220
+ hours?: number;
221
+ embed?: boolean;
222
+ } = {},
223
+ ): Promise<{
224
+ enabled: boolean;
225
+ sessionKey?: string;
226
+ sessions: number;
227
+ chunks: number;
228
+ skipped: number;
229
+ skippedSessionKeys: string[];
230
+ embeddedRuns: number;
231
+ reason?: string;
232
+ retryAfterMs?: number;
233
+ }> {
234
+ if (!resolveIndexingCapabilities(this.deps.orchestrator.config).conversationIndex) {
235
+ return {
236
+ enabled: false,
237
+ sessions: 0,
238
+ chunks: 0,
239
+ skipped: 0,
240
+ skippedSessionKeys: [],
241
+ embeddedRuns: 0,
242
+ reason: "disabled",
243
+ };
244
+ }
245
+
246
+ const hours =
247
+ typeof request.hours === "number" && Number.isFinite(request.hours)
248
+ ? Math.max(1, Math.floor(request.hours))
249
+ : 24;
250
+
251
+ let sessionKey: string | undefined;
252
+ if (request.sessionKey !== undefined) {
253
+ if (typeof request.sessionKey !== "string" || request.sessionKey.trim().length === 0) {
254
+ throw new EngramAccessInputError("sessionKey must be a non-empty string when provided");
255
+ }
256
+ sessionKey = request.sessionKey.trim();
257
+ }
258
+
259
+ if (sessionKey) {
260
+ const result = await this.deps.orchestrator.updateConversationIndex(
261
+ sessionKey,
262
+ hours,
263
+ { embed: request.embed },
264
+ );
265
+ return {
266
+ enabled: true,
267
+ sessionKey,
268
+ sessions: 1,
269
+ chunks: result.chunks,
270
+ skipped: result.skipped ? 1 : 0,
271
+ skippedSessionKeys: result.skipped ? [sessionKey] : [],
272
+ embeddedRuns: result.embedded ? 1 : 0,
273
+ reason: result.reason,
274
+ retryAfterMs: result.retryAfterMs,
275
+ };
276
+ }
277
+
278
+ const sessionKeys = await this.deps.orchestrator.transcript.listSessionKeys();
279
+ let chunks = 0;
280
+ let skipped = 0;
281
+ const skippedSessionKeys: string[] = [];
282
+ let embeddedRuns = 0;
283
+
284
+ for (const sessionKey of sessionKeys) {
285
+ const result = await this.deps.orchestrator.updateConversationIndex(
286
+ sessionKey,
287
+ hours,
288
+ { embed: request.embed },
289
+ );
290
+ chunks += result.chunks;
291
+ if (result.skipped) {
292
+ skipped += 1;
293
+ skippedSessionKeys.push(sessionKey);
294
+ }
295
+ if (result.embedded) {
296
+ embeddedRuns += 1;
297
+ }
298
+ }
299
+
300
+ return {
301
+ enabled: true,
302
+ sessions: sessionKeys.length,
303
+ chunks,
304
+ skipped,
305
+ skippedSessionKeys,
306
+ embeddedRuns,
307
+ };
308
+ }
309
+
310
+ async profilingReport(
311
+ request: AccessProfilingReportRequest = {},
312
+ ): Promise<AccessProfilingReportResponse> {
313
+ const profiler = this.deps.orchestrator.profiler;
314
+ if (!profiler.isEnabled) {
315
+ return {
316
+ enabled: false,
317
+ reason: "disabled",
318
+ message: "Profiling is disabled. Set profilingEnabled: true in your plugin config to enable.",
319
+ };
320
+ }
321
+
322
+ const format = request.format ?? "ascii";
323
+ if (format !== "ascii" && format !== "json") {
324
+ throw new EngramAccessInputError("format must be one of: ascii, json");
325
+ }
326
+
327
+ const limit = request.limit ?? 5;
328
+ if (!Number.isInteger(limit) || limit < 1 || limit > 20) {
329
+ throw new EngramAccessInputError("limit must be an integer between 1 and 20");
330
+ }
331
+
332
+ const traces = profiler.getRecentTraces(limit);
333
+ const stats = profiler.getStats();
334
+ const bottleneck = profiler.identifyBottleneck();
335
+
336
+ if (format === "json") {
337
+ return {
338
+ enabled: true,
339
+ format,
340
+ traces,
341
+ stats,
342
+ bottleneck,
343
+ };
344
+ }
345
+
346
+ const lines: string[] = [];
347
+ lines.push("Engram Profiling Report");
348
+ lines.push("=".repeat(60));
349
+ lines.push("");
350
+
351
+ type BucketEntry = { count: number; avgMs: number; p50Ms: number; p95Ms: number; maxMs: number };
352
+ const allBuckets: Array<[string, Record<string, BucketEntry>]> = [
353
+ ["byKind", stats.byKind],
354
+ ["bySpan", stats.bySpan],
355
+ ];
356
+ const hasStats = allBuckets.some(([, entries]) => Object.keys(entries).length > 0);
357
+ if (hasStats) {
358
+ lines.push("Aggregate Stats (all retained traces):");
359
+ for (const [bucket, entries] of allBuckets) {
360
+ for (const [key, summary] of Object.entries(entries)) {
361
+ lines.push(
362
+ ` ${bucket}/${key}: avg=${summary.avgMs}ms p50=${summary.p50Ms}ms p95=${summary.p95Ms}ms max=${summary.maxMs}ms (n=${summary.count})`,
363
+ );
364
+ }
365
+ }
366
+ lines.push("");
367
+ }
368
+
369
+ if (bottleneck) {
370
+ lines.push(`Bottleneck: ${bottleneck}`);
371
+ lines.push("");
372
+ }
373
+
374
+ if (traces.length === 0) {
375
+ lines.push("No traces recorded yet. Trigger a recall or extraction to see timing data.");
376
+ } else {
377
+ for (const trace of traces) {
378
+ lines.push(formatProfileTraceAscii(trace));
379
+ lines.push("");
380
+ }
381
+ }
382
+
383
+ return {
384
+ enabled: true,
385
+ format,
386
+ report: lines.join("\n"),
387
+ };
388
+ }
389
+
390
+ /**
391
+ * Read-only graph snapshot for the admin pane (issue #691 PR 2/5).
392
+ *
393
+ * Reads adjacency from the JSONL edge store written by `GraphIndex` and
394
+ * resolves node metadata via the namespaced storage manager. Namespace
395
+ * resolution mirrors the read-side path used by `recall` /
396
+ * `procedureStats`, so multi-principal deployments can't leak edges from
397
+ * a peer namespace (CLAUDE.md rule 42).
398
+ */
399
+ async graphSnapshot(
400
+ request: GraphSnapshotRequest & { namespace?: string },
401
+ authenticatedPrincipal?: string,
402
+ ): Promise<GraphSnapshotResponse> {
403
+ const namespace = this.deps.resolveReadableNamespace(
404
+ request.namespace,
405
+ authenticatedPrincipal,
406
+ );
407
+ const storage = await this.deps.orchestrator.getStorage(namespace);
408
+ const cfg = this.deps.orchestrator.config;
409
+ const graphCaps = resolveGraphConstructionCapabilities(cfg);
410
+ // Canonicalize the storage root once — through `realpath` so that any
411
+ // symlink in the namespace root path itself is resolved before we
412
+ // compare children against it. This is required because
413
+ // `GraphEdge.from` / `to` are JSONL-parsed strings — a malformed edge
414
+ // with an absolute path, a `..` segment, OR a symlink that resolves
415
+ // to a file outside the namespace would otherwise read a memory file
416
+ // from a peer namespace, leaking metadata across tenants
417
+ // (codex P1 + follow-up on PR #734; CLAUDE.md rule 42).
418
+ let namespaceRootReal: string;
419
+ try {
420
+ namespaceRootReal = await nodeFs.realpath(storage.dir);
421
+ } catch {
422
+ // If the namespace root itself doesn't exist on disk yet (fresh
423
+ // install with no memories), fall back to the lexical resolve so
424
+ // the snapshot can still return an empty result rather than
425
+ // throwing. No symlink can resolve through a missing path, so
426
+ // this fallback is safe — every candidate we see will fail the
427
+ // realpath step below and surface as `null`.
428
+ namespaceRootReal = nodePath.resolve(storage.dir);
429
+ }
430
+ const namespaceRootWithSep = namespaceRootReal.endsWith(nodePath.sep)
431
+ ? namespaceRootReal
432
+ : namespaceRootReal + nodePath.sep;
433
+ const loadNode = async (relPath: string): Promise<GraphSnapshotNodeMetadata | null> => {
434
+ // `GraphEdge.from` / `to` are storage-relative paths; resolve against
435
+ // the namespaced storage root so the metadata read honors namespace
436
+ // boundaries even when the same memory id exists in multiple
437
+ // namespaces.
438
+ //
439
+ // Three-stage guard:
440
+ // 1. Reject absolute paths up front — only relative endpoints are
441
+ // ever produced by the writer, so anything else is malformed.
442
+ // 2. Lexical containment check on the resolved path. This catches
443
+ // `..` traversals before we touch the filesystem.
444
+ // 3. `fs.realpath` containment check — resolves symlinks so an
445
+ // in-namespace path that *points* at an out-of-namespace file
446
+ // is still rejected. Without this step a symlinked endpoint
447
+ // could leak a peer namespace's frontmatter.
448
+ // Bad paths surface a length-only warning (never echo the offending
449
+ // segments — those would themselves cross namespace boundaries
450
+ // through the log surface) and fall through to a `null` metadata
451
+ // result.
452
+ if (nodePath.isAbsolute(relPath)) {
453
+ log.warn(
454
+ `graphSnapshot: rejected absolute edge endpoint (len=${relPath.length}) `
455
+ + `outside namespace root`,
456
+ );
457
+ return null;
458
+ }
459
+ const candidate = nodePath.resolve(namespaceRootReal, relPath);
460
+ if (candidate !== namespaceRootReal && !candidate.startsWith(namespaceRootWithSep)) {
461
+ log.warn(
462
+ `graphSnapshot: rejected traversing edge endpoint (len=${relPath.length}) `
463
+ + `outside namespace root`,
464
+ );
465
+ return null;
466
+ }
467
+ let canonical: string;
468
+ try {
469
+ canonical = await nodeFs.realpath(candidate);
470
+ } catch {
471
+ // Missing file — `readMemoryByPath` will return null too. We
472
+ // intentionally still call it so callers see a consistent
473
+ // "unknown" result rather than special-casing missing edges.
474
+ canonical = candidate;
475
+ }
476
+ if (canonical !== namespaceRootReal && !canonical.startsWith(namespaceRootWithSep)) {
477
+ log.warn(
478
+ `graphSnapshot: rejected symlinked edge endpoint (len=${relPath.length}) `
479
+ + `that resolved outside namespace root`,
480
+ );
481
+ return null;
482
+ }
483
+ // Both `canonical` (realpath of candidate) and `namespaceRootReal`
484
+ // (realpath of storage.dir) are fully resolved here, so the
485
+ // containment check above is comparing apples-to-apples even when
486
+ // storage.dir (= storage.baseDir) is itself a symlink to the real
487
+ // directory. Pass `canonical` — not the pre-realpath `candidate` —
488
+ // so the storage read also uses the stable real path.
489
+ const memory = await storage.readMemoryByPath(canonical);
490
+ if (!memory) return null;
491
+ const fm = memory.frontmatter;
492
+ return {
493
+ category: fm.category ?? "unknown",
494
+ label: fm.id ?? nodePath.basename(canonical, nodePath.extname(canonical)),
495
+ updated: fm.updated,
496
+ };
497
+ };
498
+ // Use the realpath-resolved namespace root for the edge-file read so
499
+ // the JSONL location is stable whether storage.dir is a direct path
500
+ // or a symlink. namespaceRootReal was computed via `fs.realpath`
501
+ // above; using it here keeps both the graph-file I/O and the loadNode
502
+ // containment check on the same resolved base path.
503
+ return buildGraphSnapshot({
504
+ memoryDir: namespaceRootReal,
505
+ graphConfig: {
506
+ entityGraph: graphCaps.entityGraph,
507
+ timeGraph: graphCaps.timeGraph,
508
+ causalGraph: graphCaps.causalGraph,
509
+ },
510
+ request: {
511
+ limit: request.limit,
512
+ since: request.since,
513
+ focusNodeId: request.focusNodeId,
514
+ categories: request.categories,
515
+ },
516
+ loadNode,
517
+ });
518
+ }
519
+
520
+ /**
521
+ * List capsule archives in the namespace-scoped capsule store.
522
+ *
523
+ * MCP uses this access-layer method instead of reading arbitrary paths so
524
+ * capsule discovery remains bound to the same namespace ACLs as export and
525
+ * import.
526
+ */
527
+ async capsuleList(options?: {
528
+ namespace?: string;
529
+ principal?: string;
530
+ }): Promise<EngramAccessCapsuleListResponse> {
531
+ const resolvedNamespace = this.deps.resolveReadableNamespace(options?.namespace, options?.principal);
532
+ const storage = await this.deps.orchestrator.getStorage(resolvedNamespace);
533
+ const capsulesDir = defaultCapsulesDir(storage.dir);
534
+ let dirEntries: import("node:fs").Dirent[];
535
+ try {
536
+ const capsulesDirStat = await nodeFs.lstat(capsulesDir);
537
+ if (capsulesDirStat.isSymbolicLink()) {
538
+ throw new EngramAccessInputError("capsule list failed: capsule store directory must not be a symlink");
539
+ }
540
+ if (!capsulesDirStat.isDirectory()) {
541
+ throw new EngramAccessInputError("capsule list failed: capsule store path must be a directory");
542
+ }
543
+ dirEntries = await nodeFs.readdir(capsulesDir, { withFileTypes: true });
544
+ } catch (err) {
545
+ const code = typeof err === "object" && err !== null && "code" in err
546
+ ? (err as { code?: unknown }).code
547
+ : undefined;
548
+ if (code === "ENOENT") {
549
+ return { namespace: resolvedNamespace, capsulesDir, capsules: [] };
550
+ }
551
+ throw err;
552
+ }
553
+
554
+ const archiveNames = dirEntries
555
+ .filter(
556
+ (entry) =>
557
+ entry.isFile() &&
558
+ (entry.name.endsWith(".capsule.json.gz") ||
559
+ entry.name.endsWith(".capsule.json.gz.enc")),
560
+ )
561
+ .map((entry) => entry.name)
562
+ .sort();
563
+
564
+ const capsules: CapsuleListEntry[] = [];
565
+ for (const archiveName of archiveNames) {
566
+ const archivePath = nodePath.join(capsulesDir, archiveName);
567
+ const id = archiveName
568
+ .replace(/\.capsule\.json\.gz\.enc$/, "")
569
+ .replace(/\.capsule\.json\.gz$/, "");
570
+ const manifestPath = nodePath.join(capsulesDir, `${id}.manifest.json`);
571
+
572
+ let createdAt: string | null = null;
573
+ let pluginVersion: string | null = null;
574
+ let fileCount: number | null = null;
575
+ let description: string | null = null;
576
+ let manifestPathOrNull: string | null = manifestPath;
577
+
578
+ try {
579
+ const manifestStat = await nodeFs.lstat(manifestPath);
580
+ if (manifestStat.isSymbolicLink() || !manifestStat.isFile()) {
581
+ capsules.push({
582
+ id,
583
+ archivePath,
584
+ manifestPath: manifestPathOrNull,
585
+ createdAt,
586
+ pluginVersion,
587
+ fileCount,
588
+ description,
589
+ });
590
+ continue;
591
+ }
592
+ const raw = await nodeFs.readFile(manifestPath, "utf-8");
593
+ const sidecar = JSON.parse(raw) as Record<string, unknown>;
594
+ createdAt = typeof sidecar.createdAt === "string" ? sidecar.createdAt : null;
595
+ pluginVersion = typeof sidecar.pluginVersion === "string" ? sidecar.pluginVersion : null;
596
+ fileCount = Array.isArray(sidecar.files) ? sidecar.files.length : null;
597
+ const capsule = sidecar.capsule as Record<string, unknown> | undefined;
598
+ description = capsule && typeof capsule.description === "string"
599
+ ? capsule.description
600
+ : null;
601
+ } catch (err) {
602
+ const code = typeof err === "object" && err !== null && "code" in err
603
+ ? (err as { code?: unknown }).code
604
+ : undefined;
605
+ if (code === "ENOENT") {
606
+ manifestPathOrNull = null;
607
+ }
608
+ }
609
+
610
+ capsules.push({
611
+ id,
612
+ archivePath,
613
+ manifestPath: manifestPathOrNull,
614
+ createdAt,
615
+ pluginVersion,
616
+ fileCount,
617
+ description,
618
+ });
619
+ }
620
+
621
+ return { namespace: resolvedNamespace, capsulesDir, capsules };
622
+ }
623
+
624
+ /**
625
+ * Manually invoke a single Dreams phase pass (PR 4/4).
626
+ *
627
+ * Deep-sleep delegates to memory governance (shadow → dry-run, apply → live).
628
+ * Light-sleep and REM scan the observation ledger and memory corpus
629
+ * respectively, returning the same telemetry shape as a scheduled run.
630
+ */
631
+ async dreamsRun(options: {
632
+ phase: import("./types.js").DreamsPhase;
633
+ dryRun?: boolean;
634
+ namespace?: string;
635
+ authenticatedPrincipal?: string;
636
+ }): Promise<import("./types.js").DreamsRunResult> {
637
+ const { runDreamsPhase } = await import("./maintenance/dreams-ledger.js");
638
+ const validPhases = ["lightSleep", "rem", "deepSleep"];
639
+ if (!validPhases.includes(options.phase)) {
640
+ throw new EngramAccessInputError(
641
+ `Invalid phase: ${String(options.phase)}. Must be one of: ${validPhases.join(", ")}`,
642
+ );
643
+ }
644
+ const deepSleep = this.deps.orchestrator.config.dreamsPhases.deepSleep;
645
+ if (
646
+ options.phase === "deepSleep" &&
647
+ deepSleep.enabled === false &&
648
+ deepSleep.enabledExplicitlySet === true
649
+ ) {
650
+ throw new EngramAccessInputError(
651
+ "memory governance is disabled by dreams.phases.deepSleep.enabled=false",
652
+ );
653
+ }
654
+ const dryRun = options.dryRun === true;
655
+ const resolvedNamespace = this.deps.writableNamespaceFor(
656
+ options.namespace,
657
+ undefined,
658
+ options.authenticatedPrincipal,
659
+ );
660
+ const storage = await this.deps.orchestrator.getStorage(resolvedNamespace);
661
+ const memoryDir = storage.dir;
662
+ const phaseRunner = dryRun || options.phase === "deepSleep"
663
+ ? undefined
664
+ : async (_opts: { memoryDir: string; phase: "lightSleep" | "rem" }) => {
665
+ if (_opts.phase === "lightSleep") {
666
+ const result = await this.deps.orchestrator.runLifecyclePolicyNow(storage);
667
+ return {
668
+ itemsProcessed: result.memoriesAssessed,
669
+ notes: `scored ${result.memoriesAssessed} memories`,
670
+ };
671
+ }
672
+ const result = await this.deps.orchestrator.runSemanticConsolidationNow({
673
+ dryRun: false,
674
+ storage,
675
+ });
676
+ const itemsProcessed = result.clusters.reduce(
677
+ (sum, cluster) => sum + cluster.memories.length,
678
+ 0,
679
+ );
680
+ return {
681
+ itemsProcessed,
682
+ notes: `REM consolidation found ${result.clustersFound} clusters`,
683
+ };
684
+ };
685
+ const governanceRunner = options.phase === "deepSleep"
686
+ ? async (_opts: { memoryDir: string; dryRun: boolean }) => {
687
+ return this.deps.orchestrator.runDeepSleepGovernanceNow({
688
+ storage,
689
+ dryRun: _opts.dryRun,
690
+ });
691
+ }
692
+ : undefined;
693
+ const result = await runDreamsPhase(
694
+ { memoryDir, phase: options.phase, dryRun },
695
+ governanceRunner,
696
+ phaseRunner,
697
+ );
698
+ return {
699
+ phase: result.phase,
700
+ dryRun: result.dryRun,
701
+ durationMs: result.durationMs,
702
+ itemsProcessed: result.itemsProcessed,
703
+ notes: result.notes,
704
+ };
705
+ }
706
+
707
+ /**
708
+ * Manually promote a memory into one or more authorized targets. Requires
709
+ * a non-empty reason (audit-logged). Reuses the scope-profile promotion
710
+ * resolution and `canWriteNamespace` gate — there is no dashboard-only
711
+ * write path.
712
+ */
713
+ async adminPromoteMemory(request: {
714
+ sourceMemoryId: string;
715
+ namespace?: string;
716
+ principal?: string;
717
+ sessionKey?: string;
718
+ targets: ReadonlyArray<{ kind: MemoryPromotionTargetKind; namespace?: string }>;
719
+ reason: string;
720
+ actor?: never; // ignored — actor is derived from the authenticated principal
721
+ }) {
722
+ const config = this.deps.orchestrator.config;
723
+ const namespacesEnabled = resolveNamespaceCapabilities(config).namespaces === true;
724
+ // Fix OdCl3: when no namespace is supplied, resolve the source via the
725
+ // scope plan (principal self / scope-profile write layer / coding overlay)
726
+ // instead of falling through to config.defaultNamespace. This matches the
727
+ // runtime observe/write path.
728
+ let sourceNamespace: string;
729
+ if (request.namespace) {
730
+ sourceNamespace = this.deps.resolveReadableNamespace(
731
+ request.namespace,
732
+ request.principal,
733
+ );
734
+ } else {
735
+ const codingContext = request.sessionKey
736
+ ? this.deps.orchestrator.getCodingContextForSession(request.sessionKey) ?? null
737
+ : null;
738
+ const plan = resolveScopePlan({
739
+ config,
740
+ sessionKey: request.sessionKey,
741
+ principalOverride: request.principal,
742
+ codingContext,
743
+ namespacesEnabled,
744
+ });
745
+ sourceNamespace = this.deps.resolveReadableNamespace(
746
+ plan.baseNamespace,
747
+ request.principal,
748
+ );
749
+ }
750
+ // Fix OdB0c: thread coding context into the scope-profile plan so
751
+ // userProject/teamProject promotion targets resolve for project-scoped
752
+ // sessions (previously hard-coded to null).
753
+ const codingContext = request.sessionKey
754
+ ? this.deps.orchestrator.getCodingContextForSession(request.sessionKey) ?? null
755
+ : null;
756
+ const codingOverlay = codingContext
757
+ ? resolveCodingNamespaceOverlay(
758
+ codingContext,
759
+ config.codingMode,
760
+ config.defaultNamespace,
761
+ )
762
+ : null;
763
+ const scopeProfilePlan = resolveScopeProfilePlan({
764
+ config,
765
+ principal: request.principal,
766
+ codingContext,
767
+ codingOverlay,
768
+ });
769
+ const storage: PromotionStorageProvider = {
770
+ readMemory: async (namespace, memoryId) => {
771
+ const resolved = await this.deps.orchestrator.getStorage(namespace);
772
+ const memory = await resolved.getMemoryById(memoryId);
773
+ if (!memory) return null;
774
+ return {
775
+ category: memory.frontmatter.category,
776
+ content: memory.content,
777
+ frontmatter: memory.frontmatter,
778
+ };
779
+ },
780
+ writePromotedMemory: async (namespace, memory) => {
781
+ const resolved = await this.deps.orchestrator.getStorage(namespace);
782
+ const { id, tombstoneBlocked } = await resolved.writeMemory(
783
+ memory.category,
784
+ memory.content,
785
+ {
786
+ confidence: memory.confidence,
787
+ tags: memory.tags,
788
+ entityRef: memory.entityRef,
789
+ source: `admin-promotion:${memory.sourceNamespace}:${memory.reason.slice(0, 120)}`,
790
+ lineage: memory.lineage,
791
+ sourceMemoryId: memory.sourceMemoryId,
792
+ actor: memory.actor,
793
+ validAt: memory.validAt,
794
+ },
795
+ );
796
+ // #1645: a tombstone-blocked promotion lands pending_review (no active
797
+ // copy in the target). Report it as a failed promotion so the admin
798
+ // sees an honest result — the content is queued for review, not
799
+ // actively promoted. promoteMemory's catch block sanitizes this into
800
+ // a generic "promotion write failed" audit entry.
801
+ if (tombstoneBlocked) {
802
+ throw new Error(
803
+ "target namespace tombstone-blocked the promoted content (pending_review)",
804
+ );
805
+ }
806
+ return id;
807
+ },
808
+ };
809
+ try {
810
+ return await promoteMemory({
811
+ config,
812
+ sourceMemoryId: request.sourceMemoryId,
813
+ sourceNamespace,
814
+ principal: request.principal,
815
+ targets: request.targets,
816
+ reason: request.reason,
817
+ actor: request.principal ?? "admin-console",
818
+ storage,
819
+ scopeProfilePlan,
820
+ });
821
+ } catch (err) {
822
+ if (err instanceof AdminPromotionError) {
823
+ throw new EngramAccessInputError(err.message);
824
+ }
825
+ throw err;
826
+ }
827
+ }
828
+ }