@remnic/core 9.25.7 → 9.27.0

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 (238) hide show
  1. package/dist/access-admin-ops-surface.d.ts +5 -5
  2. package/dist/access-admin-ops-surface.js +41 -41
  3. package/dist/access-audit.js +2 -2
  4. package/dist/access-authorization-probe.d.ts +5 -5
  5. package/dist/access-authorization-probe.js +42 -42
  6. package/dist/access-boundary.d.ts +5 -5
  7. package/dist/access-boundary.js +41 -41
  8. package/dist/access-cli.js +98 -97
  9. package/dist/access-cli.js.map +1 -1
  10. package/dist/access-http-lcm-compaction.d.ts +130 -0
  11. package/dist/access-http-lcm-compaction.js +10 -0
  12. package/dist/access-http.d.ts +5 -5
  13. package/dist/access-http.js +53 -52
  14. package/dist/access-identity-continuity-surface.d.ts +4 -4
  15. package/dist/access-identity-continuity-surface.js +41 -41
  16. package/dist/access-lcm-surface.d.ts +5 -5
  17. package/dist/access-lcm-surface.js +41 -41
  18. package/dist/access-mcp.d.ts +5 -5
  19. package/dist/access-mcp.js +47 -47
  20. package/dist/access-namespace-preflight.js +41 -41
  21. package/dist/access-observe-write-surface.d.ts +5 -5
  22. package/dist/access-observe-write-surface.js +41 -41
  23. package/dist/access-operations-batch.js +43 -43
  24. package/dist/access-operations.d.ts +8 -8
  25. package/dist/access-operations.js +45 -45
  26. package/dist/access-recall-concurrency.d.ts +5 -5
  27. package/dist/access-recall-concurrency.js +41 -41
  28. package/dist/access-recall-response.d.ts +5 -5
  29. package/dist/access-recall-response.js +41 -41
  30. package/dist/access-recall-surface.d.ts +5 -5
  31. package/dist/access-recall-surface.js +41 -41
  32. package/dist/access-schema.d.ts +92 -77
  33. package/dist/access-schema.js +8 -8
  34. package/dist/{access-service-CIdWkP6J.d.ts → access-service-B4-Fu9x2.d.ts} +4 -4
  35. package/dist/access-service.d.ts +5 -5
  36. package/dist/access-service.js +41 -41
  37. package/dist/access-surface-catalog.d.ts +5 -5
  38. package/dist/access-wearables-meetings-surface.d.ts +2 -2
  39. package/dist/adapters/index.js +7 -7
  40. package/dist/adapters/registry.js +3 -3
  41. package/dist/{auto-sync-5OE5QOZB.js → auto-sync-UPTUVE4X.js} +3 -3
  42. package/dist/bootstrap.d.ts +4 -4
  43. package/dist/briefing.d.ts +1 -1
  44. package/dist/briefing.js +5 -5
  45. package/dist/buffer.d.ts +1 -1
  46. package/dist/{capsule-crypto-7FJQINUR.js → capsule-crypto-YO5QJ6L3.js} +2 -2
  47. package/dist/capsule-crypto-YO5QJ6L3.js.map +1 -0
  48. package/dist/causal-behavior.js +2 -2
  49. package/dist/causal-chain.js +2 -2
  50. package/dist/causal-consolidation.js +11 -11
  51. package/dist/causal-retrieval.js +2 -2
  52. package/dist/causal-trajectory.js +1 -1
  53. package/dist/{chunk-JBPKEARU.js → chunk-2QSZNTDO.js} +7 -7
  54. package/dist/{chunk-UMFLAACL.js → chunk-2RAC4JIG.js} +9 -9
  55. package/dist/{chunk-OIE242WM.js → chunk-4MJZTF42.js} +3 -3
  56. package/dist/chunk-4Z4XNEWZ.js +86 -0
  57. package/dist/chunk-4Z4XNEWZ.js.map +1 -0
  58. package/dist/{chunk-IR4LGIH6.js → chunk-5BRT4Z2I.js} +2 -2
  59. package/dist/{chunk-2PHX3I5C.js → chunk-6NNNURLK.js} +8 -8
  60. package/dist/{chunk-BLAKS3CP.js → chunk-77CNV7DY.js} +4 -4
  61. package/dist/{chunk-TVVEYCNW.js → chunk-7K5Q6COX.js} +4 -4
  62. package/dist/{chunk-227UFSEQ.js → chunk-7RZJWZ46.js} +5 -5
  63. package/dist/{chunk-7CPOZH6Y.js → chunk-AJ7QCSIS.js} +2 -2
  64. package/dist/{chunk-TPYZ727G.js → chunk-BHLN7L7M.js} +6 -6
  65. package/dist/{chunk-WIGBTWXA.js → chunk-BNGPHGVZ.js} +2 -2
  66. package/dist/{chunk-2NLLXCJG.js → chunk-BXLOS5AJ.js} +2 -2
  67. package/dist/{chunk-PS5OG75R.js → chunk-CI26JDZA.js} +2 -2
  68. package/dist/{chunk-K4DP5KZA.js → chunk-CIQXI47W.js} +684 -22
  69. package/dist/chunk-CIQXI47W.js.map +1 -0
  70. package/dist/{chunk-X7Y7WX73.js → chunk-DQEMWVMT.js} +1 -1
  71. package/dist/{chunk-W33DEUKR.js → chunk-EOLC6EXV.js} +2 -2
  72. package/dist/{chunk-UOURUMBN.js → chunk-EUSLKI4X.js} +2 -2
  73. package/dist/{chunk-ZPUFQGUF.js → chunk-EYJSW2RV.js} +5 -5
  74. package/dist/{chunk-3CHQZVAL.js → chunk-FRVTCCGD.js} +5 -5
  75. package/dist/{chunk-AQ2ZQYDI.js → chunk-HEXSNYJD.js} +6 -6
  76. package/dist/{chunk-E5A6C4A5.js → chunk-HORJVJ6K.js} +48 -48
  77. package/dist/{chunk-3UOSVTFR.js → chunk-JCVQV6QX.js} +11 -11
  78. package/dist/{chunk-37VPMR4E.js → chunk-JDOJZTFF.js} +6 -6
  79. package/dist/{chunk-P25IPRXP.js → chunk-KGTD2KZJ.js} +28 -8
  80. package/dist/chunk-KGTD2KZJ.js.map +1 -0
  81. package/dist/{chunk-WSEA52RI.js → chunk-MEBQFQ26.js} +2 -2
  82. package/dist/{chunk-G6MGAE36.js → chunk-MG6MNSP4.js} +5 -5
  83. package/dist/{chunk-BL4JHZSO.js → chunk-NUWMZIYZ.js} +40 -40
  84. package/dist/{chunk-ES36HTSC.js → chunk-PTN6UAUA.js} +4 -4
  85. package/dist/{chunk-KZVPTJNZ.js → chunk-RGJBM7Z3.js} +75 -75
  86. package/dist/{chunk-7IGWPXVC.js → chunk-RNY3BO35.js} +2 -2
  87. package/dist/{chunk-JA4HEXV7.js → chunk-RPA2RX5P.js} +2 -2
  88. package/dist/{chunk-32XTXKIA.js → chunk-RSYJV25N.js} +22 -14
  89. package/dist/chunk-RSYJV25N.js.map +1 -0
  90. package/dist/{chunk-S2BBISHU.js → chunk-RYHWZ52A.js} +4 -4
  91. package/dist/{chunk-ZN4UZWMT.js → chunk-SK3EYPKC.js} +2 -2
  92. package/dist/{chunk-BUK2FXOL.js → chunk-TKBDJTXG.js} +4 -4
  93. package/dist/{chunk-D7MAWMMK.js → chunk-U3TH5Q2Q.js} +2 -2
  94. package/dist/{chunk-SSYBI43M.js → chunk-UT3OQPFA.js} +6 -6
  95. package/dist/{chunk-4B77XSG5.js → chunk-UV72DEZD.js} +5 -5
  96. package/dist/{chunk-KQAFEZQX.js → chunk-VDX2J7OX.js} +2 -2
  97. package/dist/{chunk-NRV4Y3PM.js → chunk-W4FBGYGK.js} +1 -1
  98. package/dist/{chunk-5J7HJ7RT.js → chunk-WEAO45M4.js} +2 -2
  99. package/dist/{chunk-MU7ZHSZE.js → chunk-WZFAPHIK.js} +2 -2
  100. package/dist/{chunk-NY6W6CJW.js → chunk-XKO7BM2C.js} +2 -2
  101. package/dist/{chunk-7KXQ44PA.js → chunk-XQ4EH6DI.js} +5 -5
  102. package/dist/{chunk-EZ25VE3G.js → chunk-YNDLCWXS.js} +4 -4
  103. package/dist/{chunk-VPSAVXHM.js → chunk-YSGBD3QN.js} +7 -7
  104. package/dist/{cli-Da5kesWC.d.ts → cli-Bz7X7dGx.d.ts} +3 -3
  105. package/dist/cli.d.ts +6 -6
  106. package/dist/cli.js +75 -74
  107. package/dist/compounding/engine.d.ts +1 -1
  108. package/dist/compounding/engine.js +5 -5
  109. package/dist/connectors/codex-materialize-runner.js +5 -5
  110. package/dist/connectors/index.js +5 -5
  111. package/dist/consolidation-provenance-check.d.ts +1 -1
  112. package/dist/consolidation-undo.d.ts +1 -1
  113. package/dist/contradiction/index.d.ts +1 -1
  114. package/dist/conversation-index/backend.js +2 -2
  115. package/dist/corpus-watermark.js +16 -16
  116. package/dist/dashboard-runtime.js +2 -2
  117. package/dist/entity-retrieval.d.ts +1 -1
  118. package/dist/entity-retrieval.js +5 -5
  119. package/dist/explicit-capture.d.ts +4 -4
  120. package/dist/extraction.js +3 -3
  121. package/dist/{first-start-migration-BKNGOFED.js → first-start-migration-LEXL3XYL.js} +4 -4
  122. package/dist/index.d.ts +398 -398
  123. package/dist/index.js +177 -176
  124. package/dist/lcm/engine.js +3 -3
  125. package/dist/lcm/index.js +9 -9
  126. package/dist/maintenance/memory-governance.js +6 -6
  127. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +1 -1
  128. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +5 -5
  129. package/dist/maintenance/rebuild-memory-projection.d.ts +1 -1
  130. package/dist/maintenance/rebuild-memory-projection.js +7 -7
  131. package/dist/{maintenance-DD22oIx9.d.ts → maintenance-DgnD2z8S.d.ts} +1 -1
  132. package/dist/mcp-memory-inspector-app.d.ts +5 -5
  133. package/dist/memory-worth-outcomes.d.ts +1 -1
  134. package/dist/namespaces/migrate.d.ts +1 -1
  135. package/dist/namespaces/migrate.js +15 -15
  136. package/dist/namespaces/search.js +9 -9
  137. package/dist/namespaces/storage.d.ts +1 -1
  138. package/dist/namespaces/storage.js +5 -5
  139. package/dist/operator-doctor-corpus.js +17 -17
  140. package/dist/operator-toolkit.d.ts +1 -1
  141. package/dist/operator-toolkit.js +28 -28
  142. package/dist/orchestration/compression-guideline-coordinator.d.ts +1 -1
  143. package/dist/orchestration/maintenance.d.ts +2 -2
  144. package/dist/orchestration/maintenance.js +11 -11
  145. package/dist/{orchestrator-CFJ_TG6D.d.ts → orchestrator-rIHmHpv1.d.ts} +3 -3
  146. package/dist/orchestrator.d.ts +4 -4
  147. package/dist/orchestrator.js +98 -97
  148. package/dist/resume-bundles.js +1 -1
  149. package/dist/schemas.d.ts +76 -76
  150. package/dist/search/factory.js +8 -8
  151. package/dist/search/index.js +13 -13
  152. package/dist/search/lancedb-backend.js +2 -2
  153. package/dist/search/meilisearch-backend.js +2 -2
  154. package/dist/search/orama-backend.js +2 -2
  155. package/dist/semantic-consolidation.js +7 -7
  156. package/dist/semantic-rule-promotion.js +5 -5
  157. package/dist/semantic-rule-verifier.js +6 -6
  158. package/dist/{service-Z8uzoAST.d.ts → service-cTvil7D_.d.ts} +1 -1
  159. package/dist/session-namespace-bindings.d.ts +27 -0
  160. package/dist/session-namespace-bindings.js +243 -0
  161. package/dist/session-namespace-bindings.js.map +1 -0
  162. package/dist/shared-context/manager.d.ts +8 -8
  163. package/dist/{storage-BZVMn8yJ.d.ts → storage-C9ibpTme.d.ts} +0 -3
  164. package/dist/storage.d.ts +1 -1
  165. package/dist/storage.js +4 -4
  166. package/dist/temporal-supersession.d.ts +1 -1
  167. package/dist/testing/lifecycle-matrix.d.ts +100 -0
  168. package/dist/testing/lifecycle-matrix.js +149 -0
  169. package/dist/testing/lifecycle-matrix.js.map +1 -0
  170. package/dist/tier-migration.d.ts +1 -1
  171. package/dist/transfer/backup.js +4 -4
  172. package/dist/transfer/capsule-export.js +4 -4
  173. package/dist/transfer/capsule-import.js +3 -3
  174. package/dist/transfer/types.d.ts +66 -66
  175. package/dist/verified-recall.js +6 -6
  176. package/package.json +22 -2
  177. package/src/access-http-lcm-compaction.ts +116 -0
  178. package/src/access-http.test.ts +218 -0
  179. package/src/access-http.ts +8 -8
  180. package/src/access-schema-pi.test.ts +9 -0
  181. package/src/access-schema.ts +29 -4
  182. package/src/access-surface-catalog.test.ts +1 -0
  183. package/src/session-namespace-bindings.test.ts +358 -0
  184. package/src/session-namespace-bindings.ts +301 -0
  185. package/src/storage/profile-header.ts +897 -0
  186. package/src/storage-profile-timestamp.test.ts +3290 -0
  187. package/src/storage.ts +5 -8
  188. package/src/testing/lifecycle-matrix.ts +17 -7
  189. package/src/testing/subjects/profile-header-write.test.ts +71 -0
  190. package/dist/chunk-32XTXKIA.js.map +0 -1
  191. package/dist/chunk-K4DP5KZA.js.map +0 -1
  192. package/dist/chunk-P25IPRXP.js.map +0 -1
  193. /package/dist/{capsule-crypto-7FJQINUR.js.map → access-http-lcm-compaction.js.map} +0 -0
  194. /package/dist/{auto-sync-5OE5QOZB.js.map → auto-sync-UPTUVE4X.js.map} +0 -0
  195. /package/dist/{chunk-JBPKEARU.js.map → chunk-2QSZNTDO.js.map} +0 -0
  196. /package/dist/{chunk-UMFLAACL.js.map → chunk-2RAC4JIG.js.map} +0 -0
  197. /package/dist/{chunk-OIE242WM.js.map → chunk-4MJZTF42.js.map} +0 -0
  198. /package/dist/{chunk-IR4LGIH6.js.map → chunk-5BRT4Z2I.js.map} +0 -0
  199. /package/dist/{chunk-2PHX3I5C.js.map → chunk-6NNNURLK.js.map} +0 -0
  200. /package/dist/{chunk-BLAKS3CP.js.map → chunk-77CNV7DY.js.map} +0 -0
  201. /package/dist/{chunk-TVVEYCNW.js.map → chunk-7K5Q6COX.js.map} +0 -0
  202. /package/dist/{chunk-227UFSEQ.js.map → chunk-7RZJWZ46.js.map} +0 -0
  203. /package/dist/{chunk-7CPOZH6Y.js.map → chunk-AJ7QCSIS.js.map} +0 -0
  204. /package/dist/{chunk-TPYZ727G.js.map → chunk-BHLN7L7M.js.map} +0 -0
  205. /package/dist/{chunk-WIGBTWXA.js.map → chunk-BNGPHGVZ.js.map} +0 -0
  206. /package/dist/{chunk-2NLLXCJG.js.map → chunk-BXLOS5AJ.js.map} +0 -0
  207. /package/dist/{chunk-PS5OG75R.js.map → chunk-CI26JDZA.js.map} +0 -0
  208. /package/dist/{chunk-X7Y7WX73.js.map → chunk-DQEMWVMT.js.map} +0 -0
  209. /package/dist/{chunk-W33DEUKR.js.map → chunk-EOLC6EXV.js.map} +0 -0
  210. /package/dist/{chunk-UOURUMBN.js.map → chunk-EUSLKI4X.js.map} +0 -0
  211. /package/dist/{chunk-ZPUFQGUF.js.map → chunk-EYJSW2RV.js.map} +0 -0
  212. /package/dist/{chunk-3CHQZVAL.js.map → chunk-FRVTCCGD.js.map} +0 -0
  213. /package/dist/{chunk-AQ2ZQYDI.js.map → chunk-HEXSNYJD.js.map} +0 -0
  214. /package/dist/{chunk-E5A6C4A5.js.map → chunk-HORJVJ6K.js.map} +0 -0
  215. /package/dist/{chunk-3UOSVTFR.js.map → chunk-JCVQV6QX.js.map} +0 -0
  216. /package/dist/{chunk-37VPMR4E.js.map → chunk-JDOJZTFF.js.map} +0 -0
  217. /package/dist/{chunk-WSEA52RI.js.map → chunk-MEBQFQ26.js.map} +0 -0
  218. /package/dist/{chunk-G6MGAE36.js.map → chunk-MG6MNSP4.js.map} +0 -0
  219. /package/dist/{chunk-BL4JHZSO.js.map → chunk-NUWMZIYZ.js.map} +0 -0
  220. /package/dist/{chunk-ES36HTSC.js.map → chunk-PTN6UAUA.js.map} +0 -0
  221. /package/dist/{chunk-KZVPTJNZ.js.map → chunk-RGJBM7Z3.js.map} +0 -0
  222. /package/dist/{chunk-7IGWPXVC.js.map → chunk-RNY3BO35.js.map} +0 -0
  223. /package/dist/{chunk-JA4HEXV7.js.map → chunk-RPA2RX5P.js.map} +0 -0
  224. /package/dist/{chunk-S2BBISHU.js.map → chunk-RYHWZ52A.js.map} +0 -0
  225. /package/dist/{chunk-ZN4UZWMT.js.map → chunk-SK3EYPKC.js.map} +0 -0
  226. /package/dist/{chunk-BUK2FXOL.js.map → chunk-TKBDJTXG.js.map} +0 -0
  227. /package/dist/{chunk-D7MAWMMK.js.map → chunk-U3TH5Q2Q.js.map} +0 -0
  228. /package/dist/{chunk-SSYBI43M.js.map → chunk-UT3OQPFA.js.map} +0 -0
  229. /package/dist/{chunk-4B77XSG5.js.map → chunk-UV72DEZD.js.map} +0 -0
  230. /package/dist/{chunk-KQAFEZQX.js.map → chunk-VDX2J7OX.js.map} +0 -0
  231. /package/dist/{chunk-NRV4Y3PM.js.map → chunk-W4FBGYGK.js.map} +0 -0
  232. /package/dist/{chunk-5J7HJ7RT.js.map → chunk-WEAO45M4.js.map} +0 -0
  233. /package/dist/{chunk-MU7ZHSZE.js.map → chunk-WZFAPHIK.js.map} +0 -0
  234. /package/dist/{chunk-NY6W6CJW.js.map → chunk-XKO7BM2C.js.map} +0 -0
  235. /package/dist/{chunk-7KXQ44PA.js.map → chunk-XQ4EH6DI.js.map} +0 -0
  236. /package/dist/{chunk-EZ25VE3G.js.map → chunk-YNDLCWXS.js.map} +0 -0
  237. /package/dist/{chunk-VPSAVXHM.js.map → chunk-YSGBD3QN.js.map} +0 -0
  238. /package/dist/{first-start-migration-BKNGOFED.js.map → first-start-migration-LEXL3XYL.js.map} +0 -0
@@ -1,17 +1,16 @@
1
1
  import {
2
2
  compareVerifiedEpisodeResults,
3
3
  searchVerifiedEpisodes
4
- } from "./chunk-SSYBI43M.js";
4
+ } from "./chunk-UT3OQPFA.js";
5
5
  import "./chunk-B7RWBZXW.js";
6
- import "./chunk-ZBJMUXZH.js";
7
- import "./chunk-K4DP5KZA.js";
8
- import "./chunk-2QMKMVHH.js";
6
+ import "./chunk-CIQXI47W.js";
9
7
  import "./chunk-UHVXE24Y.js";
8
+ import "./chunk-2QMKMVHH.js";
10
9
  import "./chunk-DEBHXHJR.js";
11
10
  import "./chunk-DNHVPZOD.js";
12
11
  import "./chunk-6CIAGZ6X.js";
13
- import "./chunk-J6A3CX5N.js";
14
12
  import "./chunk-HKF5VASQ.js";
13
+ import "./chunk-J6A3CX5N.js";
15
14
  import "./chunk-V25OWXAC.js";
16
15
  import "./chunk-XKGPIWGI.js";
17
16
  import "./chunk-EGGE52UU.js";
@@ -28,12 +27,12 @@ import "./chunk-R3DJVOSM.js";
28
27
  import "./chunk-BT7NVCML.js";
29
28
  import "./chunk-JYIJNNN3.js";
30
29
  import "./chunk-AAD2ZS6P.js";
31
- import "./chunk-W5H6ZRPT.js";
32
30
  import "./chunk-5VQJBH2G.js";
33
31
  import "./chunk-AITCS2RC.js";
34
32
  import "./chunk-XMMESCPD.js";
35
33
  import "./chunk-42JKGUFJ.js";
36
34
  import "./chunk-PDJTHRAW.js";
35
+ import "./chunk-W5H6ZRPT.js";
37
36
  import "./chunk-G7D6GZ5J.js";
38
37
  import "./chunk-C23BYTJV.js";
39
38
  import "./chunk-QIEUU4UK.js";
@@ -49,6 +48,7 @@ import "./chunk-EYIEWJNI.js";
49
48
  import "./chunk-JUC24CTX.js";
50
49
  import "./chunk-6MKAMLQL.js";
51
50
  import "./chunk-JAKIDQB2.js";
51
+ import "./chunk-ZBJMUXZH.js";
52
52
  import "./chunk-BJMBJZ2Y.js";
53
53
  import "./chunk-UKJAGEXH.js";
54
54
  import "./chunk-FP2373TW.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remnic/core",
3
- "version": "9.25.7",
3
+ "version": "9.27.0",
4
4
  "description": "Framework-agnostic Remnic memory engine — orchestrator, storage, extraction, search, trust zones",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -2420,6 +2420,26 @@
2420
2420
  "remnic-source": "./src/session-integrity.ts",
2421
2421
  "import": "./dist/session-integrity.js"
2422
2422
  },
2423
+ "./session-namespace-bindings": {
2424
+ "types": "./dist/session-namespace-bindings.d.ts",
2425
+ "remnic-source": "./src/session-namespace-bindings.ts",
2426
+ "import": "./dist/session-namespace-bindings.js"
2427
+ },
2428
+ "./session-namespace-bindings.js": {
2429
+ "types": "./dist/session-namespace-bindings.d.ts",
2430
+ "remnic-source": "./src/session-namespace-bindings.ts",
2431
+ "import": "./dist/session-namespace-bindings.js"
2432
+ },
2433
+ "./testing/lifecycle-matrix": {
2434
+ "types": "./dist/testing/lifecycle-matrix.d.ts",
2435
+ "remnic-source": "./src/testing/lifecycle-matrix.ts",
2436
+ "import": "./dist/testing/lifecycle-matrix.js"
2437
+ },
2438
+ "./testing/lifecycle-matrix.js": {
2439
+ "types": "./dist/testing/lifecycle-matrix.d.ts",
2440
+ "remnic-source": "./src/testing/lifecycle-matrix.ts",
2441
+ "import": "./dist/testing/lifecycle-matrix.js"
2442
+ },
2423
2443
  "./session-observer-bands": {
2424
2444
  "types": "./dist/session-observer-bands.d.ts",
2425
2445
  "remnic-source": "./src/session-observer-bands.ts",
@@ -3056,7 +3076,7 @@
3056
3076
  "core"
3057
3077
  ],
3058
3078
  "peerDependencies": {
3059
- "@remnic/coding-graph": "^9.25.7"
3079
+ "@remnic/coding-graph": "^9.27.0"
3060
3080
  },
3061
3081
  "peerDependenciesMeta": {
3062
3082
  "@remnic/coding-graph": {
@@ -0,0 +1,116 @@
1
+ import type { ServerResponse } from "node:http";
2
+
3
+ import type { LcmCompactionFlushRequest } from "./access-schema.js";
4
+ import type { EngramAccessLcmCompactionFlushResponse, EngramAccessService } from "./access-service.js";
5
+
6
+ type LcmCompactionService = Pick<EngramAccessService, "lcmCompactionFlush">;
7
+ type JsonResponder = (res: ServerResponse, status: number, payload: unknown) => void;
8
+
9
+ export interface LcmCompactionFlushHttpOptions {
10
+ body: LcmCompactionFlushRequest;
11
+ service: LcmCompactionService;
12
+ response: ServerResponse;
13
+ ensureWriteRateLimitAvailable: () => void;
14
+ recordWriteRateLimitHit: () => void;
15
+ resolveNamespace: (namespace?: string) => string | undefined;
16
+ defaultNamespace?: string;
17
+ resolveRequestPrincipal: () => string | undefined;
18
+ respondJson: JsonResponder;
19
+ }
20
+
21
+ export function respondLcmCompactionCapabilitiesHttp(response: ServerResponse): void {
22
+ response.statusCode = 200;
23
+ response.setHeader("content-type", "application/json; charset=utf-8");
24
+ response.end(JSON.stringify({ lcmCompactionFlushBatch: true }, null, 2));
25
+ }
26
+
27
+ export async function handleLcmCompactionFlushHttp({
28
+ body,
29
+ service,
30
+ response,
31
+ ensureWriteRateLimitAvailable,
32
+ recordWriteRateLimitHit,
33
+ resolveNamespace,
34
+ defaultNamespace,
35
+ resolveRequestPrincipal,
36
+ respondJson,
37
+ }: LcmCompactionFlushHttpOptions): Promise<void> {
38
+ ensureWriteRateLimitAvailable();
39
+ const requestedNamespaces = body.namespaces;
40
+ if (requestedNamespaces === undefined) {
41
+ const result = await service.lcmCompactionFlush({
42
+ sessionKey: body.sessionKey,
43
+ namespace: resolveNamespace(body.namespace),
44
+ authenticatedPrincipal: resolveRequestPrincipal(),
45
+ });
46
+ recordWriteRateLimitHit();
47
+ respondJson(response, 200, result);
48
+ return;
49
+ }
50
+ const resolutionOutcomes = await Promise.allSettled(
51
+ requestedNamespaces.map(async (requestedNamespace) => {
52
+ const namespace = resolveNamespace(requestedNamespace);
53
+ return {
54
+ requestedNamespace,
55
+ namespace,
56
+ effectiveNamespace: namespace ?? defaultNamespace ?? "",
57
+ };
58
+ })
59
+ );
60
+ const uniqueResolvedNamespaces: Array<{
61
+ requestedNamespace: string;
62
+ namespace: string | undefined;
63
+ effectiveNamespace: string;
64
+ }> = [];
65
+ const queuedEffectiveNamespaces = new Set<string>();
66
+ for (const outcome of resolutionOutcomes) {
67
+ if (outcome.status === "fulfilled" && !queuedEffectiveNamespaces.has(outcome.value.effectiveNamespace)) {
68
+ queuedEffectiveNamespaces.add(outcome.value.effectiveNamespace);
69
+ uniqueResolvedNamespaces.push(outcome.value);
70
+ }
71
+ }
72
+ const serviceOutcomes = await Promise.allSettled(
73
+ uniqueResolvedNamespaces.map(({ namespace }) =>
74
+ service.lcmCompactionFlush({
75
+ sessionKey: body.sessionKey,
76
+ namespace,
77
+ authenticatedPrincipal: resolveRequestPrincipal(),
78
+ })
79
+ )
80
+ );
81
+ const serviceOutcomesByEffectiveNamespace = new Map<
82
+ string,
83
+ PromiseSettledResult<EngramAccessLcmCompactionFlushResponse>
84
+ >();
85
+ for (const [index, resolved] of uniqueResolvedNamespaces.entries()) {
86
+ const serviceOutcome = serviceOutcomes[index];
87
+ if (serviceOutcome !== undefined) {
88
+ serviceOutcomesByEffectiveNamespace.set(resolved.effectiveNamespace, serviceOutcome);
89
+ }
90
+ }
91
+ type BatchResult =
92
+ | {
93
+ requestedNamespace: string;
94
+ status: "fulfilled";
95
+ result: EngramAccessLcmCompactionFlushResponse;
96
+ }
97
+ | { requestedNamespace: string; status: "rejected" };
98
+ const results: BatchResult[] = resolutionOutcomes.map((outcome, index) => {
99
+ const requestedNamespace = requestedNamespaces[index] ?? "";
100
+ if (outcome.status === "rejected") {
101
+ return { status: "rejected", requestedNamespace };
102
+ }
103
+ const serviceOutcome = serviceOutcomesByEffectiveNamespace.get(outcome.value.effectiveNamespace);
104
+ return serviceOutcome?.status === "fulfilled"
105
+ ? { status: "fulfilled", requestedNamespace, result: serviceOutcome.value }
106
+ : { status: "rejected", requestedNamespace };
107
+ });
108
+ recordWriteRateLimitHit();
109
+ respondJson(response, 200, {
110
+ enabled: results.every((result) => result.status === "fulfilled" && result.result.enabled !== false),
111
+ flushed: results.every((result) => result.status === "fulfilled" && result.result.flushed !== false),
112
+ sessionKey: body.sessionKey,
113
+ namespaces: requestedNamespaces,
114
+ results: results.map(({ requestedNamespace, ...result }) => ({ ...result, namespace: requestedNamespace })),
115
+ });
116
+ }
@@ -108,6 +108,224 @@ test("HTTP memory browse rejects malformed pagination and sort query values", as
108
108
  }
109
109
  });
110
110
 
111
+ test("HTTP batch LCM flush isolates namespace failures and charges one write quota", async () => {
112
+ const calls: Array<{ namespace?: string; sessionKey: string; authenticatedPrincipal?: string }> = [];
113
+ const service = {
114
+ lcmCompactionFlush: async (request: {
115
+ namespace?: string;
116
+ sessionKey: string;
117
+ authenticatedPrincipal?: string;
118
+ }) => {
119
+ calls.push(request);
120
+ if (request.namespace === "team-b") throw new Error("team-b flush failed");
121
+ return { enabled: true, flushed: true };
122
+ },
123
+ } as unknown as EngramAccessService;
124
+ const server = new EngramAccessHttpServer({
125
+ service,
126
+ port: 0,
127
+ authToken: "test-token",
128
+ adminConsoleEnabled: false,
129
+ writeRateLimitMaxRequests: 1,
130
+ });
131
+
132
+ const status = await server.start();
133
+ try {
134
+ const response = await fetch(`http://127.0.0.1:${status.port}/engram/v1/lcm/compaction/flush`, {
135
+ method: "POST",
136
+ headers: {
137
+ authorization: "Bearer test-token",
138
+ "content-type": "application/json",
139
+ },
140
+ body: JSON.stringify({
141
+ sessionKey: "batch-session",
142
+ namespaces: ["team-a", "team-b"],
143
+ }),
144
+ });
145
+ assert.equal(response.status, 200);
146
+ assert.deepEqual(await response.json(), {
147
+ enabled: false,
148
+ flushed: false,
149
+ sessionKey: "batch-session",
150
+ namespaces: ["team-a", "team-b"],
151
+ results: [
152
+ {
153
+ status: "fulfilled",
154
+ namespace: "team-a",
155
+ result: { enabled: true, flushed: true },
156
+ },
157
+ { status: "rejected", namespace: "team-b" },
158
+ ],
159
+ });
160
+ assert.deepEqual(calls, [
161
+ {
162
+ sessionKey: "batch-session",
163
+ namespace: "team-a",
164
+ authenticatedPrincipal: undefined,
165
+ },
166
+ {
167
+ sessionKey: "batch-session",
168
+ namespace: "team-b",
169
+ authenticatedPrincipal: undefined,
170
+ },
171
+ ]);
172
+
173
+ const conflicting = await fetch(`http://127.0.0.1:${status.port}/engram/v1/lcm/compaction/flush`, {
174
+ method: "POST",
175
+ headers: {
176
+ authorization: "Bearer test-token",
177
+ "content-type": "application/json",
178
+ },
179
+ body: JSON.stringify({
180
+ sessionKey: "batch-session",
181
+ namespace: "team-a",
182
+ namespaces: ["team-b"],
183
+ }),
184
+ });
185
+ assert.equal(conflicting.status, 400);
186
+ assert.equal(calls.length, 2, "conflicting namespace forms must fail before dispatch");
187
+
188
+ const rateLimited = await fetch(`http://127.0.0.1:${status.port}/engram/v1/lcm/compaction/flush`, {
189
+ method: "POST",
190
+ headers: {
191
+ authorization: "Bearer test-token",
192
+ "content-type": "application/json",
193
+ },
194
+ body: JSON.stringify({
195
+ sessionKey: "batch-session",
196
+ namespaces: ["team-a"],
197
+ }),
198
+ });
199
+ assert.equal(rateLimited.status, 429);
200
+ assert.equal(calls.length, 2, "a batch consumes one write quota unit");
201
+ } finally {
202
+ await server.stop();
203
+ }
204
+ });
205
+
206
+ test("HTTP batch LCM flush deduplicates aliases after effective namespace resolution", async () => {
207
+ const calls: Array<{ namespace?: string; sessionKey: string; authenticatedPrincipal?: string }> = [];
208
+ const service = {
209
+ configRef: parseConfig({ namespacesEnabled: true, defaultNamespace: "default" }),
210
+ lcmCompactionFlush: async (request: {
211
+ namespace?: string;
212
+ sessionKey: string;
213
+ authenticatedPrincipal?: string;
214
+ }) => {
215
+ calls.push(request);
216
+ return { enabled: true, flushed: true };
217
+ },
218
+ } as unknown as EngramAccessService;
219
+ const server = new EngramAccessHttpServer({
220
+ service,
221
+ port: 0,
222
+ authToken: "test-token",
223
+ adminConsoleEnabled: false,
224
+ });
225
+
226
+ const status = await server.start();
227
+ try {
228
+ const response = await fetch(`http://127.0.0.1:${status.port}/engram/v1/lcm/compaction/flush`, {
229
+ method: "POST",
230
+ headers: {
231
+ authorization: "Bearer test-token",
232
+ "content-type": "application/json",
233
+ },
234
+ body: JSON.stringify({
235
+ sessionKey: "effective-namespace-session",
236
+ namespaces: ["", "default"],
237
+ }),
238
+ });
239
+ assert.equal(response.status, 200);
240
+ assert.deepEqual(await response.json(), {
241
+ enabled: true,
242
+ flushed: true,
243
+ sessionKey: "effective-namespace-session",
244
+ namespaces: ["", "default"],
245
+ results: [
246
+ {
247
+ status: "fulfilled",
248
+ namespace: "",
249
+ result: { enabled: true, flushed: true },
250
+ },
251
+ {
252
+ status: "fulfilled",
253
+ namespace: "default",
254
+ result: { enabled: true, flushed: true },
255
+ },
256
+ ],
257
+ });
258
+ assert.deepEqual(calls, [
259
+ {
260
+ sessionKey: "effective-namespace-session",
261
+ namespace: undefined,
262
+ authenticatedPrincipal: undefined,
263
+ },
264
+ ]);
265
+ } finally {
266
+ await server.stop();
267
+ }
268
+ });
269
+
270
+
271
+ test("HTTP batch LCM flush isolates per-namespace authorization failures", async () => {
272
+ const calls: string[] = [];
273
+ const service = {
274
+ lcmCompactionFlush: async (request: { namespace?: string }) => {
275
+ calls.push(request.namespace ?? "");
276
+ return { enabled: true, flushed: true };
277
+ },
278
+ } as unknown as EngramAccessService;
279
+ const server = new EngramAccessHttpServer({
280
+ service,
281
+ port: 0,
282
+ authToken: "unused-token",
283
+ authTokenEntriesGetter: () => [
284
+ {
285
+ token: "scoped-token",
286
+ capabilities: {
287
+ version: 1,
288
+ ops: ["lcm_compaction_flush"],
289
+ namespaces: ["team-a"],
290
+ },
291
+ },
292
+ ],
293
+ adminConsoleEnabled: false,
294
+ });
295
+
296
+ const status = await server.start();
297
+ try {
298
+ const response = await fetch(`http://127.0.0.1:${status.port}/engram/v1/lcm/compaction/flush`, {
299
+ method: "POST",
300
+ headers: {
301
+ authorization: "Bearer scoped-token",
302
+ "content-type": "application/json",
303
+ },
304
+ body: JSON.stringify({
305
+ sessionKey: "authorized-batch-session",
306
+ namespaces: ["team-a", "team-b"],
307
+ }),
308
+ });
309
+ assert.equal(response.status, 200);
310
+ assert.deepEqual(await response.json(), {
311
+ enabled: false,
312
+ flushed: false,
313
+ sessionKey: "authorized-batch-session",
314
+ namespaces: ["team-a", "team-b"],
315
+ results: [
316
+ {
317
+ status: "fulfilled",
318
+ namespace: "team-a",
319
+ result: { enabled: true, flushed: true },
320
+ },
321
+ { status: "rejected", namespace: "team-b" },
322
+ ],
323
+ });
324
+ assert.deepEqual(calls, ["team-a"]);
325
+ } finally {
326
+ await server.stop();
327
+ }
328
+ });
111
329
  test("HTTP admin console assets are public but API routes require bearer authentication", async () => {
112
330
  const service = {} as EngramAccessService;
113
331
  const server = new EngramAccessHttpServer({
@@ -40,6 +40,7 @@ import { projectTagProjectId } from "./coding/coding-namespace.js";
40
40
  import { getOperation, type OperationName } from "./access-boundary.js";
41
41
  import { authorizationProbeNamespaces, probeOperationAuthorization } from "./access-authorization-probe.js";
42
42
  import { resolveQueryNamespaceWritablePreflight } from "./access-namespace-preflight.js";
43
+ import * as lcm from "./access-http-lcm-compaction.js";
43
44
  import {
44
45
  assertOperationAllowed,
45
46
  capabilityAllowsOp,
@@ -889,7 +890,7 @@ export class EngramAccessHttpServer {
889
890
  this.respondJson(res, 200, await this.service.health());
890
891
  return;
891
892
  }
892
-
893
+ if (req.method === "GET" && pathname === "/engram/v1/capabilities") return lcm.respondLcmCompactionCapabilitiesHttp(res);
893
894
  if (req.method === "GET" && pathname === "/engram/v1/authorization") {
894
895
  res.setHeader("cache-control", "no-store");
895
896
  const probe = probeOperationAuthorization(tokenCapabilityStore.getStore(), parsed.searchParams.getAll("op"));
@@ -1674,14 +1675,13 @@ export class EngramAccessHttpServer {
1674
1675
  ) {
1675
1676
  this.enforceTokenOp("lcm_compaction_flush"); // boundary dispatch (issue #1525)
1676
1677
  const body = await this.readValidatedBody(req, "lcmCompactionFlush");
1677
- this.ensureWriteRateLimitAvailable(req);
1678
- const response = await this.service.lcmCompactionFlush({
1679
- sessionKey: body.sessionKey,
1680
- namespace: this.resolveNamespace(req, body.namespace),
1681
- authenticatedPrincipal: this.resolveRequestPrincipal(req),
1678
+ await lcm.handleLcmCompactionFlushHttp({
1679
+ body, service: this.service,
1680
+ response: res, ensureWriteRateLimitAvailable: () => this.ensureWriteRateLimitAvailable(req),
1681
+ recordWriteRateLimitHit: () => this.recordWriteRateLimitHit(req),
1682
+ resolveNamespace: (namespace) => this.resolveNamespace(req, namespace), defaultNamespace: this.service.configRef?.defaultNamespace,
1683
+ resolveRequestPrincipal: () => this.resolveRequestPrincipal(req), respondJson: this.respondJson.bind(this),
1682
1684
  });
1683
- this.recordWriteRateLimitHit(req);
1684
- this.respondJson(res, 200, response);
1685
1685
  return;
1686
1686
  }
1687
1687
 
@@ -49,6 +49,15 @@ test("LCM compaction schemas validate Pi extension requests", () => {
49
49
  assert.equal(record.success, true);
50
50
  });
51
51
 
52
+ test("LCM compaction flush rejects duplicate namespace batches", () => {
53
+ const result = validateRequest("lcmCompactionFlush", {
54
+ sessionKey: "pi:session",
55
+ namespaces: ["work", "work"],
56
+ });
57
+
58
+ assert.equal(result.success, false);
59
+ });
60
+
52
61
  test("LCM compaction record rejects invalid token counts", () => {
53
62
  const result = validateRequest("lcmCompactionRecord", {
54
63
  sessionKey: "pi:session",
@@ -331,10 +331,35 @@ export const lcmSearchRequestSchema = z.object({
331
331
  limit: z.number().int().min(1).max(100).optional(),
332
332
  });
333
333
 
334
- export const lcmCompactionFlushRequestSchema = z.object({
335
- sessionKey: z.string().trim().min(1, "sessionKey is required").max(512),
336
- namespace: namespaceSchema,
337
- });
334
+ export const lcmCompactionFlushRequestSchema = z
335
+ .object({
336
+ sessionKey: z.string().trim().min(1, "sessionKey is required").max(512),
337
+ namespace: namespaceSchema,
338
+ /**
339
+ * Optional multi-namespace flush used by delegate lifecycle replay. The
340
+ * server handles the whole list as one quota-counted write.
341
+ */
342
+ namespaces: z.array(z.string().trim().max(256)).min(1).max(64).optional(),
343
+ })
344
+ .superRefine((value, ctx) => {
345
+ if (value.namespace !== undefined && value.namespaces !== undefined) {
346
+ ctx.addIssue({
347
+ code: z.ZodIssueCode.custom,
348
+ message: "namespace and namespaces are mutually exclusive",
349
+ path: ["namespaces"],
350
+ });
351
+ }
352
+ if (
353
+ value.namespaces !== undefined &&
354
+ new Set(value.namespaces).size !== value.namespaces.length
355
+ ) {
356
+ ctx.addIssue({
357
+ code: z.ZodIssueCode.custom,
358
+ message: "namespaces must not contain duplicates",
359
+ path: ["namespaces"],
360
+ });
361
+ }
362
+ });
338
363
 
339
364
  export const lcmCompactionRecordRequestSchema = z.object({
340
365
  sessionKey: z.string().trim().min(1, "sessionKey is required").max(512),
@@ -534,6 +534,7 @@ test("HTTP handler source routes match the catalog (static completeness)", () =>
534
534
 
535
535
  const INFRA = [
536
536
  /^\/engram\/v1\/health$/,
537
+ /^\/engram\/v1\/capabilities$/,
537
538
  /^\/engram\/v1\/authorization$/,
538
539
  /^\/engram\/v1\/admin\//,
539
540
  /^\/engram\/ui/,