@remnic/core 9.3.752 → 9.3.753

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 (303) 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 +22 -22
  5. package/dist/access-cli.js +72 -72
  6. package/dist/access-http.d.ts +5 -5
  7. package/dist/access-http.js +30 -30
  8. package/dist/access-mcp.d.ts +5 -5
  9. package/dist/access-mcp.js +27 -27
  10. package/dist/access-operations-batch.js +24 -24
  11. package/dist/access-operations.d.ts +11 -11
  12. package/dist/access-operations.js +26 -26
  13. package/dist/access-recall-surface.d.ts +5 -5
  14. package/dist/access-recall-surface.js +21 -21
  15. package/dist/access-schema.d.ts +116 -116
  16. package/dist/access-schema.js +3 -3
  17. package/dist/{access-service-C2cOHQvg.d.ts → access-service-MitduesD.d.ts} +72 -96
  18. package/dist/access-service.d.ts +5 -5
  19. package/dist/access-service.js +25 -21
  20. package/dist/access-surface-catalog.d.ts +5 -5
  21. package/dist/action-confidence.d.ts +1 -1
  22. package/dist/active-memory-bridge.d.ts +1 -1
  23. package/dist/active-recall.d.ts +1 -1
  24. package/dist/active-recall.js +5 -5
  25. package/dist/adapters/index.js +4 -4
  26. package/dist/adapters/registry.js +2 -2
  27. package/dist/behavior-learner.d.ts +1 -1
  28. package/dist/behavior-signals.d.ts +1 -1
  29. package/dist/bootstrap.d.ts +4 -4
  30. package/dist/briefing.d.ts +3 -3
  31. package/dist/briefing.js +8 -8
  32. package/dist/buffer-surprise-report.d.ts +1 -1
  33. package/dist/buffer.d.ts +3 -3
  34. package/dist/buffer.js +2 -2
  35. package/dist/calibration.d.ts +1 -1
  36. package/dist/capabilities.d.ts +1 -1
  37. package/dist/{catalog-D_FvzTM0.d.ts → catalog-BEmNVRN0.d.ts} +1 -1
  38. package/dist/causal-behavior.d.ts +1 -1
  39. package/dist/causal-consolidation.d.ts +1 -1
  40. package/dist/causal-consolidation.js +11 -11
  41. package/dist/causal-trajectory-graph.d.ts +1 -1
  42. package/dist/{chunk-J2JB6BHT.js → chunk-243P7YYV.js} +8 -8
  43. package/dist/{chunk-YGNQG4Q6.js → chunk-34THARMH.js} +10 -10
  44. package/dist/{chunk-UFNQKZV7.js → chunk-3HGZX26P.js} +20 -20
  45. package/dist/{chunk-2U4E34Y3.js → chunk-3ZIKDH6C.js} +4 -4
  46. package/dist/{chunk-5JAT4ZJD.js → chunk-4DLFJJOQ.js} +4 -4
  47. package/dist/{chunk-BIAMJUUJ.js → chunk-5QANTTY2.js} +4 -4
  48. package/dist/{chunk-JBPKEARU.js → chunk-AU7Q3LSC.js} +4 -4
  49. package/dist/{chunk-L3VSTJ2V.js → chunk-AXBRVBT6.js} +2 -2
  50. package/dist/{chunk-V4ZPLQLC.js → chunk-BWOEYBRB.js} +2 -2
  51. package/dist/{chunk-2DPCAW2T.js → chunk-C3IHRWIC.js} +8 -8
  52. package/dist/{chunk-MW7UUXTA.js → chunk-DBSMLRTO.js} +5 -5
  53. package/dist/{chunk-OVMLS7TN.js → chunk-DKIZ4BUQ.js} +14 -14
  54. package/dist/{chunk-RBYV3WSB.js → chunk-DS4QM6I7.js} +4 -4
  55. package/dist/{chunk-IBPEVGP5.js → chunk-E3MRYDUQ.js} +2 -2
  56. package/dist/{chunk-MTN2G4DT.js → chunk-E6LENGYV.js} +2 -2
  57. package/dist/{chunk-K5CWCJKJ.js → chunk-EEO4YWQ7.js} +10 -10
  58. package/dist/{chunk-KFNG72W7.js → chunk-GWGWBK5Y.js} +2 -2
  59. package/dist/{chunk-5DXUE7GB.js → chunk-HAZVVOYT.js} +2 -2
  60. package/dist/{chunk-R7TGDLV3.js → chunk-HM6UJPPO.js} +4 -4
  61. package/dist/{chunk-C4LNKQ3M.js → chunk-ITLJATQI.js} +5 -5
  62. package/dist/{chunk-MEPWWSTD.js → chunk-JES2O5Q6.js} +4 -4
  63. package/dist/{chunk-SC5AEZLU.js → chunk-JGPURIEH.js} +9 -9
  64. package/dist/{chunk-33NX5BLR.js → chunk-JRZV3767.js} +4 -4
  65. package/dist/{chunk-IQWFWSCP.js → chunk-JZ7P26GF.js} +4 -4
  66. package/dist/{chunk-XKAOT4ZB.js → chunk-K5LLP4CY.js} +4 -4
  67. package/dist/{chunk-JNKSFIAY.js → chunk-KY4WOZ3P.js} +53 -53
  68. package/dist/{chunk-6ROCH5JV.js → chunk-KYHGLDFU.js} +8 -8
  69. package/dist/{chunk-RRRZ3CLN.js → chunk-LOPZ2DWR.js} +4 -4
  70. package/dist/{chunk-MLDAD27I.js → chunk-LZ73Y56P.js} +5 -5
  71. package/dist/{chunk-FEELYTRT.js → chunk-N3VE7OCY.js} +5 -5
  72. package/dist/{chunk-OKOF7ITI.js → chunk-OSMBC3JU.js} +6 -6
  73. package/dist/{chunk-FLVL4L3L.js → chunk-OUXPVWTZ.js} +5 -5
  74. package/dist/{chunk-QMMCMV2L.js → chunk-OZMBT7N3.js} +6 -6
  75. package/dist/{chunk-VQL22SHO.js → chunk-PN5AMCK2.js} +96 -96
  76. package/dist/{chunk-GFGYHLON.js → chunk-QIRZI3C3.js} +2 -2
  77. package/dist/{chunk-QRM3K3XT.js → chunk-RNWWAS5V.js} +5 -5
  78. package/dist/{chunk-DC5OBZS3.js → chunk-TVISHYL5.js} +2 -2
  79. package/dist/{chunk-S5UYWK3O.js → chunk-VVSV2QVY.js} +6 -6
  80. package/dist/{chunk-GECEETQ3.js → chunk-W3M34XT4.js} +4 -4
  81. package/dist/{chunk-FXRFFYWD.js → chunk-WIWPSQYU.js} +4 -4
  82. package/dist/{chunk-KT2VQLP7.js → chunk-XOPLMSVV.js} +8 -8
  83. package/dist/{chunk-JHZ3LEM7.js → chunk-YNBEHUZH.js} +2 -2
  84. package/dist/{chunk-VX2RYM2K.js → chunk-ZECLLIMX.js} +811 -744
  85. package/dist/chunk-ZECLLIMX.js.map +1 -0
  86. package/dist/{chunk-67JRXV6Z.js → chunk-ZIFPFKB2.js} +5 -5
  87. package/dist/{chunk-ZGGI3COG.js → chunk-ZMHDSIEX.js} +9 -9
  88. package/dist/{cli-DFUU9WYu.d.ts → cli-DqonYBZ0.d.ts} +3 -3
  89. package/dist/cli.d.ts +6 -6
  90. package/dist/cli.js +47 -47
  91. package/dist/compounding/engine.d.ts +3 -3
  92. package/dist/compounding/engine.js +10 -10
  93. package/dist/compounding/preference-consolidator.d.ts +1 -1
  94. package/dist/compression-optimizer.d.ts +1 -1
  95. package/dist/config.d.ts +1 -1
  96. package/dist/config.js +2 -2
  97. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  98. package/dist/connectors/codex-materialize-runner.js +9 -9
  99. package/dist/connectors/codex-materialize.d.ts +1 -1
  100. package/dist/connectors/index.d.ts +1 -1
  101. package/dist/connectors/index.js +11 -11
  102. package/dist/consolidation-provenance-check.d.ts +1 -1
  103. package/dist/consolidation-undo.d.ts +1 -1
  104. package/dist/contradiction/index.d.ts +1 -1
  105. package/dist/contradiction/index.js +2 -2
  106. package/dist/{contradiction-scan-KO4WWCS4.js → contradiction-scan-2SODRNUF.js} +3 -3
  107. package/dist/contradiction-scan-2SODRNUF.js.map +1 -0
  108. package/dist/conversation-index/backend.d.ts +1 -1
  109. package/dist/conversation-index/chunker.d.ts +1 -1
  110. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  111. package/dist/conversation-index/indexer.d.ts +1 -1
  112. package/dist/conversation-index/search.d.ts +1 -1
  113. package/dist/day-summary.d.ts +1 -1
  114. package/dist/day-summary.js +2 -2
  115. package/dist/delinearize.d.ts +1 -1
  116. package/dist/direct-answer-wiring.d.ts +1 -1
  117. package/dist/direct-answer.d.ts +1 -1
  118. package/dist/embedding-fallback.d.ts +1 -1
  119. package/dist/embedding-fallback.js +2 -2
  120. package/dist/enrichment/index.d.ts +1 -1
  121. package/dist/entity-retrieval.d.ts +1 -1
  122. package/dist/entity-retrieval.js +9 -9
  123. package/dist/entity-schema.d.ts +1 -1
  124. package/dist/explicit-capture.d.ts +6 -6
  125. package/dist/explicit-capture.js +2 -2
  126. package/dist/extraction-faithfulness.d.ts +1 -1
  127. package/dist/extraction-judge-telemetry.d.ts +1 -1
  128. package/dist/extraction-judge-training.d.ts +1 -1
  129. package/dist/extraction-judge.d.ts +1 -1
  130. package/dist/extraction.d.ts +1 -1
  131. package/dist/extraction.js +5 -5
  132. package/dist/fallback-llm.d.ts +1 -1
  133. package/dist/{first-start-migration-4I3VDSYS.js → first-start-migration-DY6YCRC2.js} +2 -2
  134. package/dist/{forget-WYLR4ZFV.js → forget-OEE5OELK.js} +2 -2
  135. package/dist/graph-dashboard-diff.d.ts +1 -1
  136. package/dist/graph-dashboard-key.d.ts +1 -1
  137. package/dist/graph-dashboard-parser.d.ts +1 -1
  138. package/dist/graph-edge-reinforcement.d.ts +1 -1
  139. package/dist/graph-snapshot.d.ts +1 -1
  140. package/dist/graph.d.ts +1 -1
  141. package/dist/identity-continuity.d.ts +1 -1
  142. package/dist/importance.d.ts +1 -1
  143. package/dist/index.d.ts +1284 -1284
  144. package/dist/index.js +102 -102
  145. package/dist/intent.d.ts +1 -1
  146. package/dist/lcm/engine.d.ts +1 -1
  147. package/dist/lcm/engine.js +2 -2
  148. package/dist/lcm/index.d.ts +1 -1
  149. package/dist/lcm/index.js +5 -5
  150. package/dist/lcm/tools.d.ts +1 -1
  151. package/dist/lifecycle.d.ts +1 -1
  152. package/dist/live-connectors-runner.d.ts +1 -1
  153. package/dist/local-llm.d.ts +1 -1
  154. package/dist/local-llm.js +2 -2
  155. package/dist/local-model-endpoint.d.ts +1 -1
  156. package/dist/maintenance/memory-governance.d.ts +1 -1
  157. package/dist/maintenance/memory-governance.js +8 -8
  158. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +8 -8
  159. package/dist/maintenance/rebuild-memory-projection.js +9 -9
  160. package/dist/mcp-memory-inspector-app.d.ts +5 -5
  161. package/dist/memory-action-policy.d.ts +1 -1
  162. package/dist/memory-cache.d.ts +1 -1
  163. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  164. package/dist/memory-projection-store.d.ts +1 -1
  165. package/dist/memory-provenance.d.ts +1 -1
  166. package/dist/memory-worth-outcomes.d.ts +1 -1
  167. package/dist/models-json.d.ts +1 -1
  168. package/dist/namespaces/migrate.d.ts +2 -2
  169. package/dist/namespaces/migrate.js +14 -14
  170. package/dist/namespaces/principal.d.ts +1 -1
  171. package/dist/namespaces/search.d.ts +1 -1
  172. package/dist/namespaces/search.js +4 -4
  173. package/dist/namespaces/storage.d.ts +2 -2
  174. package/dist/namespaces/storage.js +10 -10
  175. package/dist/native-knowledge.d.ts +1 -1
  176. package/dist/operator-toolkit.d.ts +1 -1
  177. package/dist/operator-toolkit.js +20 -20
  178. package/dist/orchestration/compression-guideline-coordinator.d.ts +1 -1
  179. package/dist/orchestration/compression-guideline-coordinator.js +2 -2
  180. package/dist/orchestration/maintenance.d.ts +2 -2
  181. package/dist/orchestration/maintenance.js +14 -14
  182. package/dist/{orchestrator-BhxMxtQJ.d.ts → orchestrator-D7ZGOQLX.d.ts} +77 -77
  183. package/dist/orchestrator.d.ts +4 -4
  184. package/dist/orchestrator.js +72 -72
  185. package/dist/patterns-cli.d.ts +1 -1
  186. package/dist/policy-runtime.d.ts +1 -1
  187. package/dist/provenance.d.ts +1 -1
  188. package/dist/qmd-recall-cache.d.ts +1 -1
  189. package/dist/qmd.d.ts +1 -1
  190. package/dist/recall-disclosure-escalation.d.ts +1 -1
  191. package/dist/recall-explain-renderer.d.ts +1 -1
  192. package/dist/recall-planner-llm.d.ts +1 -1
  193. package/dist/recall-state.d.ts +1 -1
  194. package/dist/recall-tag-filter.d.ts +1 -1
  195. package/dist/recall-xray-cli.d.ts +1 -1
  196. package/dist/recall-xray-renderer.d.ts +1 -1
  197. package/dist/recall-xray.d.ts +1 -1
  198. package/dist/resolve-auth-token.d.ts +1 -1
  199. package/dist/resume-bundles.js +2 -2
  200. package/dist/retrieval-agents.d.ts +1 -1
  201. package/dist/retrieval-tiers.d.ts +1 -1
  202. package/dist/routing/engine.d.ts +1 -1
  203. package/dist/routing/store.d.ts +1 -1
  204. package/dist/routing/store.js +2 -2
  205. package/dist/schemas.d.ts +122 -122
  206. package/dist/search/embed-helper.d.ts +1 -1
  207. package/dist/search/embed-helper.js +2 -2
  208. package/dist/search/factory.d.ts +1 -1
  209. package/dist/search/factory.js +3 -3
  210. package/dist/search/index.d.ts +1 -1
  211. package/dist/search/index.js +3 -3
  212. package/dist/search/lancedb-backend.d.ts +1 -1
  213. package/dist/search/meilisearch-backend.d.ts +1 -1
  214. package/dist/search/noop-backend.d.ts +1 -1
  215. package/dist/search/orama-backend.d.ts +1 -1
  216. package/dist/search/port.d.ts +1 -1
  217. package/dist/search/remote-backend.d.ts +1 -1
  218. package/dist/{semantic-consolidation-BrsoFeMP.d.ts → semantic-consolidation-7Sndms2M.d.ts} +1 -1
  219. package/dist/semantic-consolidation.d.ts +2 -2
  220. package/dist/semantic-consolidation.js +11 -11
  221. package/dist/semantic-rule-promotion.js +8 -8
  222. package/dist/semantic-rule-verifier.d.ts +1 -1
  223. package/dist/semantic-rule-verifier.js +8 -8
  224. package/dist/session-observer-bands.d.ts +1 -1
  225. package/dist/session-observer-state.d.ts +1 -1
  226. package/dist/shared-context/manager.d.ts +9 -9
  227. package/dist/shared-context/manager.js +2 -2
  228. package/dist/signal.d.ts +1 -1
  229. package/dist/storage.d.ts +1 -1
  230. package/dist/storage.js +7 -7
  231. package/dist/summarizer.d.ts +1 -1
  232. package/dist/summarizer.js +3 -3
  233. package/dist/summary-snapshot.d.ts +1 -1
  234. package/dist/temporal-supersession.d.ts +1 -1
  235. package/dist/temporal-validity.d.ts +1 -1
  236. package/dist/threading.d.ts +1 -1
  237. package/dist/tier-migration.d.ts +1 -1
  238. package/dist/tier-routing.d.ts +1 -1
  239. package/dist/{tier-stats-5XF4UBRQ.js → tier-stats-TG6GUZ6N.js} +4 -4
  240. package/dist/topics.d.ts +1 -1
  241. package/dist/transcript.d.ts +1 -1
  242. package/dist/transfer/autodetect.js +1 -1
  243. package/dist/transfer/backup.js +1 -1
  244. package/dist/transfer/capsule-export.js +2 -2
  245. package/dist/transfer/types.d.ts +110 -110
  246. package/dist/trust-score-stage.d.ts +1 -1
  247. package/dist/trust-score.d.ts +1 -1
  248. package/dist/{types-BfI4uJeb.d.ts → types-DTEFxFuL.d.ts} +1 -1
  249. package/dist/types.d.ts +1 -1
  250. package/dist/utility-runtime.d.ts +1 -1
  251. package/dist/verified-recall.js +8 -8
  252. package/package.json +2 -2
  253. package/src/access-admin-ops-surface.ts +828 -0
  254. package/src/access-service.ts +41 -698
  255. package/dist/chunk-VX2RYM2K.js.map +0 -1
  256. /package/dist/{contradiction-scan-KO4WWCS4.js.map → access-admin-ops-surface.js.map} +0 -0
  257. /package/dist/{chunk-J2JB6BHT.js.map → chunk-243P7YYV.js.map} +0 -0
  258. /package/dist/{chunk-YGNQG4Q6.js.map → chunk-34THARMH.js.map} +0 -0
  259. /package/dist/{chunk-UFNQKZV7.js.map → chunk-3HGZX26P.js.map} +0 -0
  260. /package/dist/{chunk-2U4E34Y3.js.map → chunk-3ZIKDH6C.js.map} +0 -0
  261. /package/dist/{chunk-5JAT4ZJD.js.map → chunk-4DLFJJOQ.js.map} +0 -0
  262. /package/dist/{chunk-BIAMJUUJ.js.map → chunk-5QANTTY2.js.map} +0 -0
  263. /package/dist/{chunk-JBPKEARU.js.map → chunk-AU7Q3LSC.js.map} +0 -0
  264. /package/dist/{chunk-L3VSTJ2V.js.map → chunk-AXBRVBT6.js.map} +0 -0
  265. /package/dist/{chunk-V4ZPLQLC.js.map → chunk-BWOEYBRB.js.map} +0 -0
  266. /package/dist/{chunk-2DPCAW2T.js.map → chunk-C3IHRWIC.js.map} +0 -0
  267. /package/dist/{chunk-MW7UUXTA.js.map → chunk-DBSMLRTO.js.map} +0 -0
  268. /package/dist/{chunk-OVMLS7TN.js.map → chunk-DKIZ4BUQ.js.map} +0 -0
  269. /package/dist/{chunk-RBYV3WSB.js.map → chunk-DS4QM6I7.js.map} +0 -0
  270. /package/dist/{chunk-IBPEVGP5.js.map → chunk-E3MRYDUQ.js.map} +0 -0
  271. /package/dist/{chunk-MTN2G4DT.js.map → chunk-E6LENGYV.js.map} +0 -0
  272. /package/dist/{chunk-K5CWCJKJ.js.map → chunk-EEO4YWQ7.js.map} +0 -0
  273. /package/dist/{chunk-KFNG72W7.js.map → chunk-GWGWBK5Y.js.map} +0 -0
  274. /package/dist/{chunk-5DXUE7GB.js.map → chunk-HAZVVOYT.js.map} +0 -0
  275. /package/dist/{chunk-R7TGDLV3.js.map → chunk-HM6UJPPO.js.map} +0 -0
  276. /package/dist/{chunk-C4LNKQ3M.js.map → chunk-ITLJATQI.js.map} +0 -0
  277. /package/dist/{chunk-MEPWWSTD.js.map → chunk-JES2O5Q6.js.map} +0 -0
  278. /package/dist/{chunk-SC5AEZLU.js.map → chunk-JGPURIEH.js.map} +0 -0
  279. /package/dist/{chunk-33NX5BLR.js.map → chunk-JRZV3767.js.map} +0 -0
  280. /package/dist/{chunk-IQWFWSCP.js.map → chunk-JZ7P26GF.js.map} +0 -0
  281. /package/dist/{chunk-XKAOT4ZB.js.map → chunk-K5LLP4CY.js.map} +0 -0
  282. /package/dist/{chunk-JNKSFIAY.js.map → chunk-KY4WOZ3P.js.map} +0 -0
  283. /package/dist/{chunk-6ROCH5JV.js.map → chunk-KYHGLDFU.js.map} +0 -0
  284. /package/dist/{chunk-RRRZ3CLN.js.map → chunk-LOPZ2DWR.js.map} +0 -0
  285. /package/dist/{chunk-MLDAD27I.js.map → chunk-LZ73Y56P.js.map} +0 -0
  286. /package/dist/{chunk-FEELYTRT.js.map → chunk-N3VE7OCY.js.map} +0 -0
  287. /package/dist/{chunk-OKOF7ITI.js.map → chunk-OSMBC3JU.js.map} +0 -0
  288. /package/dist/{chunk-FLVL4L3L.js.map → chunk-OUXPVWTZ.js.map} +0 -0
  289. /package/dist/{chunk-QMMCMV2L.js.map → chunk-OZMBT7N3.js.map} +0 -0
  290. /package/dist/{chunk-VQL22SHO.js.map → chunk-PN5AMCK2.js.map} +0 -0
  291. /package/dist/{chunk-GFGYHLON.js.map → chunk-QIRZI3C3.js.map} +0 -0
  292. /package/dist/{chunk-QRM3K3XT.js.map → chunk-RNWWAS5V.js.map} +0 -0
  293. /package/dist/{chunk-DC5OBZS3.js.map → chunk-TVISHYL5.js.map} +0 -0
  294. /package/dist/{chunk-S5UYWK3O.js.map → chunk-VVSV2QVY.js.map} +0 -0
  295. /package/dist/{chunk-GECEETQ3.js.map → chunk-W3M34XT4.js.map} +0 -0
  296. /package/dist/{chunk-FXRFFYWD.js.map → chunk-WIWPSQYU.js.map} +0 -0
  297. /package/dist/{chunk-KT2VQLP7.js.map → chunk-XOPLMSVV.js.map} +0 -0
  298. /package/dist/{chunk-JHZ3LEM7.js.map → chunk-YNBEHUZH.js.map} +0 -0
  299. /package/dist/{chunk-67JRXV6Z.js.map → chunk-ZIFPFKB2.js.map} +0 -0
  300. /package/dist/{chunk-ZGGI3COG.js.map → chunk-ZMHDSIEX.js.map} +0 -0
  301. /package/dist/{first-start-migration-4I3VDSYS.js.map → first-start-migration-DY6YCRC2.js.map} +0 -0
  302. /package/dist/{forget-WYLR4ZFV.js.map → forget-OEE5OELK.js.map} +0 -0
  303. /package/dist/{tier-stats-5XF4UBRQ.js.map → tier-stats-TG6GUZ6N.js.map} +0 -0
@@ -251,6 +251,7 @@ import {
251
251
  import { formatProfileTraceAscii } from "./profiling.js";
252
252
  import { resolveAccessSetupCapabilities, resolveGraphConstructionCapabilities, resolveIndexingCapabilities } from "./capabilities.js";
253
253
  import { resolveRecallEnhancementCapabilities } from "./capabilities.js";
254
+ import { AccessAdminOpsSurface } from "./access-admin-ops-surface.js";
254
255
  import { AccessRecallSurface } from "./access-recall-surface.js";
255
256
  import { selfDeps } from "./orchestration/self-deps.js";
256
257
 
@@ -302,12 +303,12 @@ function qmdResultPathCandidates(
302
303
  return [...candidates];
303
304
  }
304
305
 
305
- type AccessProfilingReportRequest = {
306
+ export type AccessProfilingReportRequest = {
306
307
  format?: string;
307
308
  limit?: number;
308
309
  };
309
310
 
310
- type AccessProfilingReportResponse = {
311
+ export type AccessProfilingReportResponse = {
311
312
  enabled: boolean;
312
313
  format?: "ascii" | "json";
313
314
  report?: string;
@@ -860,7 +861,7 @@ export interface EngramAccessOfflineSyncApplyResponse extends OfflineSyncApplyCh
860
861
  export type EngramAccessActionConfidenceRequest = ActionConfidenceInput;
861
862
  export type EngramAccessActionConfidenceResponse = ActionConfidenceResult;
862
863
 
863
- async function buildProjectedGovernanceProposedActions(
864
+ export async function buildProjectedGovernanceProposedActions(
864
865
  storage: Awaited<ReturnType<Orchestrator["getStorage"]>>,
865
866
  projected: NonNullable<Awaited<ReturnType<Awaited<ReturnType<Orchestrator["getStorage"]>>["getProjectedGovernanceRecord"]>>>,
866
867
  ): Promise<Awaited<ReturnType<typeof readMemoryGovernanceRunArtifact>>["appliedActions"]> {
@@ -879,7 +880,7 @@ async function buildProjectedGovernanceProposedActions(
879
880
  return buildProposedActions(reviewQueue, memories);
880
881
  }
881
882
 
882
- function hasGroupedGovernanceActions(
883
+ export function hasGroupedGovernanceActions(
883
884
  grouped?: Awaited<ReturnType<typeof readMemoryGovernanceRunArtifact>>["transitionReport"]["proposed"],
884
885
  ): boolean {
885
886
  if (!grouped) return false;
@@ -1307,6 +1308,18 @@ export class EngramAccessService {
1307
1308
  private readonly budget: CrossNamespaceBudget;
1308
1309
  private readonly auditAdapter: AccessAuditAdapter | null;
1309
1310
 
1311
+ /** AccessAdminOpsSurface (access-service decomposition). Lazy; selfDeps live wiring. */
1312
+ private _accessAdminOpsSurface: AccessAdminOpsSurface | undefined;
1313
+
1314
+ private get accessAdminOpsSurface(): AccessAdminOpsSurface {
1315
+ if (!this._accessAdminOpsSurface) {
1316
+ this._accessAdminOpsSurface = new AccessAdminOpsSurface(
1317
+ selfDeps<ConstructorParameters<typeof AccessAdminOpsSurface>[0]>(this),
1318
+ );
1319
+ }
1320
+ return this._accessAdminOpsSurface;
1321
+ }
1322
+
1310
1323
  /** AccessRecallSurface (access-service decomposition). Lazy; selfDeps live wiring. */
1311
1324
  private _accessRecallSurface: AccessRecallSurface | undefined;
1312
1325
 
@@ -3835,97 +3848,11 @@ export class EngramAccessService {
3835
3848
  }
3836
3849
 
3837
3850
  async reviewQueue(runId?: string, namespace?: string, principal?: string): Promise<EngramAccessReviewQueueResponse> {
3838
- const resolvedNamespace = this.resolveReadableNamespace(namespace, principal);
3839
- const storage = await this.orchestrator.getStorage(resolvedNamespace);
3840
- const projected = await storage.getProjectedGovernanceRecord();
3841
- if (projected && (!runId || projected.runId === runId.trim())) {
3842
- const projectedAppliedActions = projected.appliedActionRows.map((row) => ({
3843
- action: row.action,
3844
- memoryId: row.memoryId,
3845
- reasonCode: row.reasonCode,
3846
- beforeStatus: row.beforeStatus,
3847
- afterStatus: row.afterStatus,
3848
- originalPath: row.originalPath,
3849
- currentPath: row.currentPath,
3850
- })) as Awaited<
3851
- ReturnType<typeof readMemoryGovernanceRunArtifact>
3852
- >["appliedActions"];
3853
- const projectedProposedActions = await buildProjectedGovernanceProposedActions(storage, projected);
3854
- const projectedArtifact = await (async () => {
3855
- try {
3856
- return await readMemoryGovernanceRunArtifact(storage.dir, projected.runId);
3857
- } catch {
3858
- return null;
3859
- }
3860
- })();
3861
- const metrics = projected.metrics as Awaited<ReturnType<typeof readMemoryGovernanceRunArtifact>>["metrics"];
3862
- const fallbackTransitionReport = {
3863
- proposed: groupActionsByStatus(projectedProposedActions),
3864
- applied: groupActionsByStatus(projectedAppliedActions),
3865
- };
3866
- const transitionReport = projectedArtifact?.transitionReport
3867
- ? {
3868
- proposed:
3869
- hasGroupedGovernanceActions(projectedArtifact.transitionReport.proposed) || projectedProposedActions.length === 0
3870
- ? projectedArtifact.transitionReport.proposed
3871
- : fallbackTransitionReport.proposed,
3872
- applied:
3873
- hasGroupedGovernanceActions(projectedArtifact.transitionReport.applied) || projectedAppliedActions.length === 0
3874
- ? projectedArtifact.transitionReport.applied
3875
- : fallbackTransitionReport.applied,
3876
- }
3877
- : fallbackTransitionReport;
3878
- const qualityScore = projectedArtifact?.qualityScore ?? metrics?.qualityScore ?? buildQualityScore(metrics?.reviewReasons ?? {
3879
- exact_duplicate: 0,
3880
- semantic_duplicate_candidate: 0,
3881
- disputed_memory: 0,
3882
- speculative_low_confidence: 0,
3883
- archive_candidate: 0,
3884
- explicit_capture_review: 0,
3885
- malformed_import: 0,
3886
- });
3887
- const effectiveMetrics = metrics ? { ...metrics, qualityScore: metrics.qualityScore ?? qualityScore } : metrics;
3888
-
3889
- return {
3890
- found: true,
3891
- namespace: resolvedNamespace,
3892
- runId: projected.runId,
3893
- summary: projected.summary as Awaited<ReturnType<typeof readMemoryGovernanceRunArtifact>>["summary"],
3894
- metrics: effectiveMetrics,
3895
- qualityScore,
3896
- reviewQueue: projected.reviewQueueRows.map((row) => ({
3897
- entryId: row.entryId,
3898
- memoryId: row.memoryId,
3899
- path: row.path,
3900
- reasonCode: row.reasonCode,
3901
- severity: row.severity,
3902
- suggestedAction: row.suggestedAction,
3903
- suggestedStatus: row.suggestedStatus,
3904
- relatedMemoryIds: row.relatedMemoryIds,
3905
- })) as Awaited<
3906
- ReturnType<typeof readMemoryGovernanceRunArtifact>
3907
- >["reviewQueue"],
3908
- appliedActions: projectedAppliedActions,
3909
- transitionReport,
3910
- report: projected.report,
3911
- };
3912
- }
3913
-
3914
- const resolvedRunId = runId?.trim() || (await listMemoryGovernanceRuns(storage.dir))[0];
3915
- if (!resolvedRunId) return { found: false, namespace: resolvedNamespace };
3916
- const artifact = await readMemoryGovernanceRunArtifact(storage.dir, resolvedRunId);
3917
- return {
3918
- found: true,
3919
- namespace: resolvedNamespace,
3920
- runId: resolvedRunId,
3921
- summary: artifact.summary,
3922
- metrics: artifact.metrics,
3923
- qualityScore: artifact.qualityScore,
3924
- reviewQueue: artifact.reviewQueue,
3925
- appliedActions: artifact.appliedActions,
3926
- transitionReport: artifact.transitionReport,
3927
- report: artifact.report,
3928
- };
3851
+ return this.accessAdminOpsSurface.reviewQueue(
3852
+ runId,
3853
+ namespace,
3854
+ principal,
3855
+ );
3929
3856
  }
3930
3857
 
3931
3858
  async maintenance(namespace?: string, principal?: string): Promise<EngramAccessMaintenanceResponse> {
@@ -4010,56 +3937,10 @@ export class EngramAccessService {
4010
3937
  summaryPath: string;
4011
3938
  reportPath: string;
4012
3939
  }> {
4013
- const deepSleep = this.orchestrator.config.dreamsPhases.deepSleep;
4014
- if (deepSleep.enabled === false && deepSleep.enabledExplicitlySet === true) {
4015
- throw new Error("memory governance is disabled by dreams.phases.deepSleep.enabled=false");
4016
- }
4017
- const resolvedNamespace = this.writableNamespaceFor(
4018
- request.namespace,
4019
- undefined,
4020
- request.authenticatedPrincipal ?? principal,
3940
+ return this.accessAdminOpsSurface.governanceRun(
3941
+ request,
3942
+ principal,
4021
3943
  );
4022
- const storage = await this.orchestrator.getStorage(resolvedNamespace);
4023
- const mode = request.mode === "apply" ? "apply" : "shadow";
4024
- const boundedBatchSize =
4025
- typeof request.batchSize === "number" && Number.isFinite(request.batchSize)
4026
- ? Math.max(1, Math.floor(request.batchSize))
4027
- : undefined;
4028
- const result = await runMemoryGovernance({
4029
- memoryDir: storage.dir,
4030
- mode,
4031
- recentDays:
4032
- typeof request.recentDays === "number" && Number.isFinite(request.recentDays)
4033
- ? Math.max(1, Math.floor(request.recentDays))
4034
- : undefined,
4035
- maxMemories:
4036
- typeof request.maxMemories === "number" && Number.isFinite(request.maxMemories)
4037
- ? Math.max(1, Math.floor(request.maxMemories))
4038
- : undefined,
4039
- batchSize: boundedBatchSize,
4040
- });
4041
- if (mode === "apply") {
4042
- try {
4043
- await this.orchestrator.processEntitySynthesisQueue(
4044
- resolvedNamespace,
4045
- Math.min(boundedBatchSize ?? 5, 5),
4046
- );
4047
- } catch (error) {
4048
- log.debug(`governanceRun: entity synthesis refresh failed after governance apply: ${error}`);
4049
- }
4050
- }
4051
-
4052
- return {
4053
- namespace: resolvedNamespace,
4054
- runId: result.runId,
4055
- traceId: result.traceId,
4056
- mode: result.mode,
4057
- reviewQueueCount: result.reviewQueue.length,
4058
- proposedActionCount: result.proposedActions.length,
4059
- appliedActionCount: result.appliedActions.length,
4060
- summaryPath: result.summaryPath,
4061
- reportPath: result.reportPath,
4062
- };
4063
3944
  }
4064
3945
 
4065
3946
  async procedureMiningRun(
@@ -4225,160 +4106,17 @@ export class EngramAccessService {
4225
4106
  reason?: string;
4226
4107
  retryAfterMs?: number;
4227
4108
  }> {
4228
- if (!resolveIndexingCapabilities(this.orchestrator.config).conversationIndex) {
4229
- return {
4230
- enabled: false,
4231
- sessions: 0,
4232
- chunks: 0,
4233
- skipped: 0,
4234
- skippedSessionKeys: [],
4235
- embeddedRuns: 0,
4236
- reason: "disabled",
4237
- };
4238
- }
4239
-
4240
- const hours =
4241
- typeof request.hours === "number" && Number.isFinite(request.hours)
4242
- ? Math.max(1, Math.floor(request.hours))
4243
- : 24;
4244
-
4245
- let sessionKey: string | undefined;
4246
- if (request.sessionKey !== undefined) {
4247
- if (typeof request.sessionKey !== "string" || request.sessionKey.trim().length === 0) {
4248
- throw new EngramAccessInputError("sessionKey must be a non-empty string when provided");
4249
- }
4250
- sessionKey = request.sessionKey.trim();
4251
- }
4252
-
4253
- if (sessionKey) {
4254
- const result = await this.orchestrator.updateConversationIndex(
4255
- sessionKey,
4256
- hours,
4257
- { embed: request.embed },
4258
- );
4259
- return {
4260
- enabled: true,
4261
- sessionKey,
4262
- sessions: 1,
4263
- chunks: result.chunks,
4264
- skipped: result.skipped ? 1 : 0,
4265
- skippedSessionKeys: result.skipped ? [sessionKey] : [],
4266
- embeddedRuns: result.embedded ? 1 : 0,
4267
- reason: result.reason,
4268
- retryAfterMs: result.retryAfterMs,
4269
- };
4270
- }
4271
-
4272
- const sessionKeys = await this.orchestrator.transcript.listSessionKeys();
4273
- let chunks = 0;
4274
- let skipped = 0;
4275
- const skippedSessionKeys: string[] = [];
4276
- let embeddedRuns = 0;
4277
-
4278
- for (const sessionKey of sessionKeys) {
4279
- const result = await this.orchestrator.updateConversationIndex(
4280
- sessionKey,
4281
- hours,
4282
- { embed: request.embed },
4283
- );
4284
- chunks += result.chunks;
4285
- if (result.skipped) {
4286
- skipped += 1;
4287
- skippedSessionKeys.push(sessionKey);
4288
- }
4289
- if (result.embedded) {
4290
- embeddedRuns += 1;
4291
- }
4292
- }
4293
-
4294
- return {
4295
- enabled: true,
4296
- sessions: sessionKeys.length,
4297
- chunks,
4298
- skipped,
4299
- skippedSessionKeys,
4300
- embeddedRuns,
4301
- };
4109
+ return this.accessAdminOpsSurface.conversationIndexUpdate(
4110
+ request,
4111
+ );
4302
4112
  }
4303
4113
 
4304
4114
  async profilingReport(
4305
4115
  request: AccessProfilingReportRequest = {},
4306
4116
  ): Promise<AccessProfilingReportResponse> {
4307
- const profiler = this.orchestrator.profiler;
4308
- if (!profiler.isEnabled) {
4309
- return {
4310
- enabled: false,
4311
- reason: "disabled",
4312
- message: "Profiling is disabled. Set profilingEnabled: true in your plugin config to enable.",
4313
- };
4314
- }
4315
-
4316
- const format = request.format ?? "ascii";
4317
- if (format !== "ascii" && format !== "json") {
4318
- throw new EngramAccessInputError("format must be one of: ascii, json");
4319
- }
4320
-
4321
- const limit = request.limit ?? 5;
4322
- if (!Number.isInteger(limit) || limit < 1 || limit > 20) {
4323
- throw new EngramAccessInputError("limit must be an integer between 1 and 20");
4324
- }
4325
-
4326
- const traces = profiler.getRecentTraces(limit);
4327
- const stats = profiler.getStats();
4328
- const bottleneck = profiler.identifyBottleneck();
4329
-
4330
- if (format === "json") {
4331
- return {
4332
- enabled: true,
4333
- format,
4334
- traces,
4335
- stats,
4336
- bottleneck,
4337
- };
4338
- }
4339
-
4340
- const lines: string[] = [];
4341
- lines.push("Engram Profiling Report");
4342
- lines.push("=".repeat(60));
4343
- lines.push("");
4344
-
4345
- type BucketEntry = { count: number; avgMs: number; p50Ms: number; p95Ms: number; maxMs: number };
4346
- const allBuckets: Array<[string, Record<string, BucketEntry>]> = [
4347
- ["byKind", stats.byKind],
4348
- ["bySpan", stats.bySpan],
4349
- ];
4350
- const hasStats = allBuckets.some(([, entries]) => Object.keys(entries).length > 0);
4351
- if (hasStats) {
4352
- lines.push("Aggregate Stats (all retained traces):");
4353
- for (const [bucket, entries] of allBuckets) {
4354
- for (const [key, summary] of Object.entries(entries)) {
4355
- lines.push(
4356
- ` ${bucket}/${key}: avg=${summary.avgMs}ms p50=${summary.p50Ms}ms p95=${summary.p95Ms}ms max=${summary.maxMs}ms (n=${summary.count})`,
4357
- );
4358
- }
4359
- }
4360
- lines.push("");
4361
- }
4362
-
4363
- if (bottleneck) {
4364
- lines.push(`Bottleneck: ${bottleneck}`);
4365
- lines.push("");
4366
- }
4367
-
4368
- if (traces.length === 0) {
4369
- lines.push("No traces recorded yet. Trigger a recall or extraction to see timing data.");
4370
- } else {
4371
- for (const trace of traces) {
4372
- lines.push(formatProfileTraceAscii(trace));
4373
- lines.push("");
4374
- }
4375
- }
4376
-
4377
- return {
4378
- enabled: true,
4379
- format,
4380
- report: lines.join("\n"),
4381
- };
4117
+ return this.accessAdminOpsSurface.profilingReport(
4118
+ request,
4119
+ );
4382
4120
  }
4383
4121
 
4384
4122
  async trustZoneStatus(namespace?: string, principal?: string): Promise<EngramAccessTrustZoneStatusResponse> {
@@ -6316,134 +6054,14 @@ export class EngramAccessService {
6316
6054
  return { explanation };
6317
6055
  }
6318
6056
 
6319
- /**
6320
- * Read-only graph snapshot for the admin pane (issue #691 PR 2/5).
6321
- *
6322
- * Reads adjacency from the JSONL edge store written by `GraphIndex` and
6323
- * resolves node metadata via the namespaced storage manager. Namespace
6324
- * resolution mirrors the read-side path used by `recall` /
6325
- * `procedureStats`, so multi-principal deployments can't leak edges from
6326
- * a peer namespace (CLAUDE.md rule 42).
6327
- */
6328
6057
  async graphSnapshot(
6329
6058
  request: GraphSnapshotRequest & { namespace?: string },
6330
6059
  authenticatedPrincipal?: string,
6331
6060
  ): Promise<GraphSnapshotResponse> {
6332
- const namespace = this.resolveReadableNamespace(
6333
- request.namespace,
6061
+ return this.accessAdminOpsSurface.graphSnapshot(
6062
+ request,
6334
6063
  authenticatedPrincipal,
6335
6064
  );
6336
- const storage = await this.orchestrator.getStorage(namespace);
6337
- const cfg = this.orchestrator.config;
6338
- const graphCaps = resolveGraphConstructionCapabilities(cfg);
6339
- // Canonicalize the storage root once — through `realpath` so that any
6340
- // symlink in the namespace root path itself is resolved before we
6341
- // compare children against it. This is required because
6342
- // `GraphEdge.from` / `to` are JSONL-parsed strings — a malformed edge
6343
- // with an absolute path, a `..` segment, OR a symlink that resolves
6344
- // to a file outside the namespace would otherwise read a memory file
6345
- // from a peer namespace, leaking metadata across tenants
6346
- // (codex P1 + follow-up on PR #734; CLAUDE.md rule 42).
6347
- let namespaceRootReal: string;
6348
- try {
6349
- namespaceRootReal = await nodeFs.realpath(storage.dir);
6350
- } catch {
6351
- // If the namespace root itself doesn't exist on disk yet (fresh
6352
- // install with no memories), fall back to the lexical resolve so
6353
- // the snapshot can still return an empty result rather than
6354
- // throwing. No symlink can resolve through a missing path, so
6355
- // this fallback is safe — every candidate we see will fail the
6356
- // realpath step below and surface as `null`.
6357
- namespaceRootReal = nodePath.resolve(storage.dir);
6358
- }
6359
- const namespaceRootWithSep = namespaceRootReal.endsWith(nodePath.sep)
6360
- ? namespaceRootReal
6361
- : namespaceRootReal + nodePath.sep;
6362
- const loadNode = async (relPath: string): Promise<GraphSnapshotNodeMetadata | null> => {
6363
- // `GraphEdge.from` / `to` are storage-relative paths; resolve against
6364
- // the namespaced storage root so the metadata read honors namespace
6365
- // boundaries even when the same memory id exists in multiple
6366
- // namespaces.
6367
- //
6368
- // Three-stage guard:
6369
- // 1. Reject absolute paths up front — only relative endpoints are
6370
- // ever produced by the writer, so anything else is malformed.
6371
- // 2. Lexical containment check on the resolved path. This catches
6372
- // `..` traversals before we touch the filesystem.
6373
- // 3. `fs.realpath` containment check — resolves symlinks so an
6374
- // in-namespace path that *points* at an out-of-namespace file
6375
- // is still rejected. Without this step a symlinked endpoint
6376
- // could leak a peer namespace's frontmatter.
6377
- // Bad paths surface a length-only warning (never echo the offending
6378
- // segments — those would themselves cross namespace boundaries
6379
- // through the log surface) and fall through to a `null` metadata
6380
- // result.
6381
- if (nodePath.isAbsolute(relPath)) {
6382
- log.warn(
6383
- `graphSnapshot: rejected absolute edge endpoint (len=${relPath.length}) `
6384
- + `outside namespace root`,
6385
- );
6386
- return null;
6387
- }
6388
- const candidate = nodePath.resolve(namespaceRootReal, relPath);
6389
- if (candidate !== namespaceRootReal && !candidate.startsWith(namespaceRootWithSep)) {
6390
- log.warn(
6391
- `graphSnapshot: rejected traversing edge endpoint (len=${relPath.length}) `
6392
- + `outside namespace root`,
6393
- );
6394
- return null;
6395
- }
6396
- let canonical: string;
6397
- try {
6398
- canonical = await nodeFs.realpath(candidate);
6399
- } catch {
6400
- // Missing file — `readMemoryByPath` will return null too. We
6401
- // intentionally still call it so callers see a consistent
6402
- // "unknown" result rather than special-casing missing edges.
6403
- canonical = candidate;
6404
- }
6405
- if (canonical !== namespaceRootReal && !canonical.startsWith(namespaceRootWithSep)) {
6406
- log.warn(
6407
- `graphSnapshot: rejected symlinked edge endpoint (len=${relPath.length}) `
6408
- + `that resolved outside namespace root`,
6409
- );
6410
- return null;
6411
- }
6412
- // Both `canonical` (realpath of candidate) and `namespaceRootReal`
6413
- // (realpath of storage.dir) are fully resolved here, so the
6414
- // containment check above is comparing apples-to-apples even when
6415
- // storage.dir (= storage.baseDir) is itself a symlink to the real
6416
- // directory. Pass `canonical` — not the pre-realpath `candidate` —
6417
- // so the storage read also uses the stable real path.
6418
- const memory = await storage.readMemoryByPath(canonical);
6419
- if (!memory) return null;
6420
- const fm = memory.frontmatter;
6421
- return {
6422
- category: fm.category ?? "unknown",
6423
- label: fm.id ?? nodePath.basename(canonical, nodePath.extname(canonical)),
6424
- updated: fm.updated,
6425
- };
6426
- };
6427
- // Use the realpath-resolved namespace root for the edge-file read so
6428
- // the JSONL location is stable whether storage.dir is a direct path
6429
- // or a symlink. namespaceRootReal was computed via `fs.realpath`
6430
- // above; using it here keeps both the graph-file I/O and the loadNode
6431
- // containment check on the same resolved base path.
6432
- return buildGraphSnapshot({
6433
- memoryDir: namespaceRootReal,
6434
- graphConfig: {
6435
- entityGraph: graphCaps.entityGraph,
6436
- timeGraph: graphCaps.timeGraph,
6437
- causalGraph: graphCaps.causalGraph,
6438
- },
6439
- request: {
6440
- limit: request.limit,
6441
- since: request.since,
6442
- focusNodeId: request.focusNodeId,
6443
- categories: request.categories,
6444
- },
6445
- loadNode,
6446
- });
6447
6065
  }
6448
6066
 
6449
6067
  async memoryFeedback(request: {
@@ -7140,108 +6758,13 @@ export class EngramAccessService {
7140
6758
  });
7141
6759
  }
7142
6760
 
7143
- /**
7144
- * List capsule archives in the namespace-scoped capsule store.
7145
- *
7146
- * MCP uses this access-layer method instead of reading arbitrary paths so
7147
- * capsule discovery remains bound to the same namespace ACLs as export and
7148
- * import.
7149
- */
7150
6761
  async capsuleList(options?: {
7151
6762
  namespace?: string;
7152
6763
  principal?: string;
7153
6764
  }): Promise<EngramAccessCapsuleListResponse> {
7154
- const resolvedNamespace = this.resolveReadableNamespace(options?.namespace, options?.principal);
7155
- const storage = await this.orchestrator.getStorage(resolvedNamespace);
7156
- const capsulesDir = defaultCapsulesDir(storage.dir);
7157
- let dirEntries: import("node:fs").Dirent[];
7158
- try {
7159
- const capsulesDirStat = await nodeFs.lstat(capsulesDir);
7160
- if (capsulesDirStat.isSymbolicLink()) {
7161
- throw new EngramAccessInputError("capsule list failed: capsule store directory must not be a symlink");
7162
- }
7163
- if (!capsulesDirStat.isDirectory()) {
7164
- throw new EngramAccessInputError("capsule list failed: capsule store path must be a directory");
7165
- }
7166
- dirEntries = await nodeFs.readdir(capsulesDir, { withFileTypes: true });
7167
- } catch (err) {
7168
- const code = typeof err === "object" && err !== null && "code" in err
7169
- ? (err as { code?: unknown }).code
7170
- : undefined;
7171
- if (code === "ENOENT") {
7172
- return { namespace: resolvedNamespace, capsulesDir, capsules: [] };
7173
- }
7174
- throw err;
7175
- }
7176
-
7177
- const archiveNames = dirEntries
7178
- .filter(
7179
- (entry) =>
7180
- entry.isFile() &&
7181
- (entry.name.endsWith(".capsule.json.gz") ||
7182
- entry.name.endsWith(".capsule.json.gz.enc")),
7183
- )
7184
- .map((entry) => entry.name)
7185
- .sort();
7186
-
7187
- const capsules: CapsuleListEntry[] = [];
7188
- for (const archiveName of archiveNames) {
7189
- const archivePath = nodePath.join(capsulesDir, archiveName);
7190
- const id = archiveName
7191
- .replace(/\.capsule\.json\.gz\.enc$/, "")
7192
- .replace(/\.capsule\.json\.gz$/, "");
7193
- const manifestPath = nodePath.join(capsulesDir, `${id}.manifest.json`);
7194
-
7195
- let createdAt: string | null = null;
7196
- let pluginVersion: string | null = null;
7197
- let fileCount: number | null = null;
7198
- let description: string | null = null;
7199
- let manifestPathOrNull: string | null = manifestPath;
7200
-
7201
- try {
7202
- const manifestStat = await nodeFs.lstat(manifestPath);
7203
- if (manifestStat.isSymbolicLink() || !manifestStat.isFile()) {
7204
- capsules.push({
7205
- id,
7206
- archivePath,
7207
- manifestPath: manifestPathOrNull,
7208
- createdAt,
7209
- pluginVersion,
7210
- fileCount,
7211
- description,
7212
- });
7213
- continue;
7214
- }
7215
- const raw = await nodeFs.readFile(manifestPath, "utf-8");
7216
- const sidecar = JSON.parse(raw) as Record<string, unknown>;
7217
- createdAt = typeof sidecar.createdAt === "string" ? sidecar.createdAt : null;
7218
- pluginVersion = typeof sidecar.pluginVersion === "string" ? sidecar.pluginVersion : null;
7219
- fileCount = Array.isArray(sidecar.files) ? sidecar.files.length : null;
7220
- const capsule = sidecar.capsule as Record<string, unknown> | undefined;
7221
- description = capsule && typeof capsule.description === "string"
7222
- ? capsule.description
7223
- : null;
7224
- } catch (err) {
7225
- const code = typeof err === "object" && err !== null && "code" in err
7226
- ? (err as { code?: unknown }).code
7227
- : undefined;
7228
- if (code === "ENOENT") {
7229
- manifestPathOrNull = null;
7230
- }
7231
- }
7232
-
7233
- capsules.push({
7234
- id,
7235
- archivePath,
7236
- manifestPath: manifestPathOrNull,
7237
- createdAt,
7238
- pluginVersion,
7239
- fileCount,
7240
- description,
7241
- });
7242
- }
7243
-
7244
- return { namespace: resolvedNamespace, capsulesDir, capsules };
6765
+ return this.accessAdminOpsSurface.capsuleList(
6766
+ options,
6767
+ );
7245
6768
  }
7246
6769
 
7247
6770
  /**
@@ -7484,87 +7007,15 @@ export class EngramAccessService {
7484
7007
  return getDreamsStatus(storage.dir, windowHours);
7485
7008
  }
7486
7009
 
7487
- /**
7488
- * Manually invoke a single Dreams phase pass (PR 4/4).
7489
- *
7490
- * Deep-sleep delegates to memory governance (shadow → dry-run, apply → live).
7491
- * Light-sleep and REM scan the observation ledger and memory corpus
7492
- * respectively, returning the same telemetry shape as a scheduled run.
7493
- */
7494
7010
  async dreamsRun(options: {
7495
7011
  phase: import("./types.js").DreamsPhase;
7496
7012
  dryRun?: boolean;
7497
7013
  namespace?: string;
7498
7014
  authenticatedPrincipal?: string;
7499
7015
  }): Promise<import("./types.js").DreamsRunResult> {
7500
- const { runDreamsPhase } = await import("./maintenance/dreams-ledger.js");
7501
- const validPhases = ["lightSleep", "rem", "deepSleep"];
7502
- if (!validPhases.includes(options.phase)) {
7503
- throw new EngramAccessInputError(
7504
- `Invalid phase: ${String(options.phase)}. Must be one of: ${validPhases.join(", ")}`,
7505
- );
7506
- }
7507
- const deepSleep = this.orchestrator.config.dreamsPhases.deepSleep;
7508
- if (
7509
- options.phase === "deepSleep" &&
7510
- deepSleep.enabled === false &&
7511
- deepSleep.enabledExplicitlySet === true
7512
- ) {
7513
- throw new EngramAccessInputError(
7514
- "memory governance is disabled by dreams.phases.deepSleep.enabled=false",
7515
- );
7516
- }
7517
- const dryRun = options.dryRun === true;
7518
- const resolvedNamespace = this.writableNamespaceFor(
7519
- options.namespace,
7520
- undefined,
7521
- options.authenticatedPrincipal,
7522
- );
7523
- const storage = await this.orchestrator.getStorage(resolvedNamespace);
7524
- const memoryDir = storage.dir;
7525
- const phaseRunner = dryRun || options.phase === "deepSleep"
7526
- ? undefined
7527
- : async (_opts: { memoryDir: string; phase: "lightSleep" | "rem" }) => {
7528
- if (_opts.phase === "lightSleep") {
7529
- const result = await this.orchestrator.runLifecyclePolicyNow(storage);
7530
- return {
7531
- itemsProcessed: result.memoriesAssessed,
7532
- notes: `scored ${result.memoriesAssessed} memories`,
7533
- };
7534
- }
7535
- const result = await this.orchestrator.runSemanticConsolidationNow({
7536
- dryRun: false,
7537
- storage,
7538
- });
7539
- const itemsProcessed = result.clusters.reduce(
7540
- (sum, cluster) => sum + cluster.memories.length,
7541
- 0,
7542
- );
7543
- return {
7544
- itemsProcessed,
7545
- notes: `REM consolidation found ${result.clustersFound} clusters`,
7546
- };
7547
- };
7548
- const governanceRunner = options.phase === "deepSleep"
7549
- ? async (_opts: { memoryDir: string; dryRun: boolean }) => {
7550
- return this.orchestrator.runDeepSleepGovernanceNow({
7551
- storage,
7552
- dryRun: _opts.dryRun,
7553
- });
7554
- }
7555
- : undefined;
7556
- const result = await runDreamsPhase(
7557
- { memoryDir, phase: options.phase, dryRun },
7558
- governanceRunner,
7559
- phaseRunner,
7016
+ return this.accessAdminOpsSurface.dreamsRun(
7017
+ options,
7560
7018
  );
7561
- return {
7562
- phase: result.phase,
7563
- dryRun: result.dryRun,
7564
- durationMs: result.durationMs,
7565
- itemsProcessed: result.itemsProcessed,
7566
- notes: result.notes,
7567
- };
7568
7019
  }
7569
7020
 
7570
7021
  // ---------------------------------------------------------------------------
@@ -7723,12 +7174,6 @@ export class EngramAccessService {
7723
7174
  return redactSensitive(result);
7724
7175
  }
7725
7176
 
7726
- /**
7727
- * Manually promote a memory into one or more authorized targets. Requires
7728
- * a non-empty reason (audit-logged). Reuses the scope-profile promotion
7729
- * resolution and `canWriteNamespace` gate — there is no dashboard-only
7730
- * write path.
7731
- */
7732
7177
  async adminPromoteMemory(request: {
7733
7178
  sourceMemoryId: string;
7734
7179
  namespace?: string;
@@ -7738,111 +7183,9 @@ export class EngramAccessService {
7738
7183
  reason: string;
7739
7184
  actor?: never; // ignored — actor is derived from the authenticated principal
7740
7185
  }) {
7741
- const config = this.orchestrator.config;
7742
- const namespacesEnabled = resolveNamespaceCapabilities(config).namespaces === true;
7743
- // Fix OdCl3: when no namespace is supplied, resolve the source via the
7744
- // scope plan (principal self / scope-profile write layer / coding overlay)
7745
- // instead of falling through to config.defaultNamespace. This matches the
7746
- // runtime observe/write path.
7747
- let sourceNamespace: string;
7748
- if (request.namespace) {
7749
- sourceNamespace = this.resolveReadableNamespace(
7750
- request.namespace,
7751
- request.principal,
7752
- );
7753
- } else {
7754
- const codingContext = request.sessionKey
7755
- ? this.orchestrator.getCodingContextForSession(request.sessionKey) ?? null
7756
- : null;
7757
- const plan = resolveScopePlan({
7758
- config,
7759
- sessionKey: request.sessionKey,
7760
- principalOverride: request.principal,
7761
- codingContext,
7762
- namespacesEnabled,
7763
- });
7764
- sourceNamespace = this.resolveReadableNamespace(
7765
- plan.baseNamespace,
7766
- request.principal,
7767
- );
7768
- }
7769
- // Fix OdB0c: thread coding context into the scope-profile plan so
7770
- // userProject/teamProject promotion targets resolve for project-scoped
7771
- // sessions (previously hard-coded to null).
7772
- const codingContext = request.sessionKey
7773
- ? this.orchestrator.getCodingContextForSession(request.sessionKey) ?? null
7774
- : null;
7775
- const codingOverlay = codingContext
7776
- ? resolveCodingNamespaceOverlay(
7777
- codingContext,
7778
- config.codingMode,
7779
- config.defaultNamespace,
7780
- )
7781
- : null;
7782
- const scopeProfilePlan = resolveScopeProfilePlan({
7783
- config,
7784
- principal: request.principal,
7785
- codingContext,
7786
- codingOverlay,
7787
- });
7788
- const storage: PromotionStorageProvider = {
7789
- readMemory: async (namespace, memoryId) => {
7790
- const resolved = await this.orchestrator.getStorage(namespace);
7791
- const memory = await resolved.getMemoryById(memoryId);
7792
- if (!memory) return null;
7793
- return {
7794
- category: memory.frontmatter.category,
7795
- content: memory.content,
7796
- frontmatter: memory.frontmatter,
7797
- };
7798
- },
7799
- writePromotedMemory: async (namespace, memory) => {
7800
- const resolved = await this.orchestrator.getStorage(namespace);
7801
- const { id, tombstoneBlocked } = await resolved.writeMemory(
7802
- memory.category,
7803
- memory.content,
7804
- {
7805
- confidence: memory.confidence,
7806
- tags: memory.tags,
7807
- entityRef: memory.entityRef,
7808
- source: `admin-promotion:${memory.sourceNamespace}:${memory.reason.slice(0, 120)}`,
7809
- lineage: memory.lineage,
7810
- sourceMemoryId: memory.sourceMemoryId,
7811
- actor: memory.actor,
7812
- validAt: memory.validAt,
7813
- },
7814
- );
7815
- // #1645: a tombstone-blocked promotion lands pending_review (no active
7816
- // copy in the target). Report it as a failed promotion so the admin
7817
- // sees an honest result — the content is queued for review, not
7818
- // actively promoted. promoteMemory's catch block sanitizes this into
7819
- // a generic "promotion write failed" audit entry.
7820
- if (tombstoneBlocked) {
7821
- throw new Error(
7822
- "target namespace tombstone-blocked the promoted content (pending_review)",
7823
- );
7824
- }
7825
- return id;
7826
- },
7827
- };
7828
- try {
7829
- return await promoteMemory({
7830
- config,
7831
- sourceMemoryId: request.sourceMemoryId,
7832
- sourceNamespace,
7833
- principal: request.principal,
7834
- targets: request.targets,
7835
- reason: request.reason,
7836
- actor: request.principal ?? "admin-console",
7837
- storage,
7838
- scopeProfilePlan,
7839
- });
7840
- } catch (err) {
7841
- if (err instanceof AdminPromotionError) {
7842
- throw new EngramAccessInputError(err.message);
7843
- }
7844
- throw err;
7845
- }
7186
+ return this.accessAdminOpsSurface.adminPromoteMemory(
7187
+ request,
7188
+ );
7846
7189
  }
7847
7190
  }
7848
7191