@remnic/core 9.69.47 → 9.69.49

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 (523) hide show
  1. package/dist/access-admin-ops-surface.d.ts +14 -14
  2. package/dist/access-admin-ops-surface.js +32 -30
  3. package/dist/access-authorization-probe.d.ts +14 -14
  4. package/dist/access-authorization-probe.js +33 -31
  5. package/dist/access-boundary.d.ts +14 -14
  6. package/dist/access-boundary.js +32 -30
  7. package/dist/access-cli.js +99 -98
  8. package/dist/access-cli.js.map +1 -1
  9. package/dist/access-coding-context-resolution.d.ts +1 -1
  10. package/dist/access-extraction-force-flush.d.ts +14 -14
  11. package/dist/access-extraction-force-flush.js +32 -30
  12. package/dist/access-health-types.d.ts +1 -1
  13. package/dist/access-http-briefing.d.ts +14 -14
  14. package/dist/access-http-briefing.js +33 -31
  15. package/dist/access-http-lcm-compaction.d.ts +14 -14
  16. package/dist/access-http-lifecycle-flush.d.ts +14 -14
  17. package/dist/access-http-offline-stream.d.ts +14 -14
  18. package/dist/access-http-query.d.ts +2 -2
  19. package/dist/access-http-query.js +34 -32
  20. package/dist/access-http.d.ts +15 -15
  21. package/dist/access-http.js +52 -50
  22. package/dist/access-identity-continuity-surface.d.ts +11 -11
  23. package/dist/access-identity-continuity-surface.js +32 -30
  24. package/dist/access-lcm-surface.d.ts +14 -14
  25. package/dist/access-lcm-surface.js +32 -30
  26. package/dist/access-mcp-shared-context-tools.d.ts +14 -14
  27. package/dist/access-mcp.d.ts +14 -14
  28. package/dist/access-mcp.js +42 -40
  29. package/dist/access-memory-search-fanout.d.ts +2 -2
  30. package/dist/{access-namespace-preflight-CetF9ziA.d.ts → access-namespace-preflight-DqRw_g-8.d.ts} +1 -1
  31. package/dist/access-namespace-preflight.d.ts +3 -3
  32. package/dist/access-namespace-preflight.js +32 -30
  33. package/dist/access-observe-transcript.d.ts +11 -11
  34. package/dist/access-observe-write-category.d.ts +3 -3
  35. package/dist/access-observe-write-surface.d.ts +14 -14
  36. package/dist/access-observe-write-surface.js +32 -30
  37. package/dist/access-offline-manifest.d.ts +11 -11
  38. package/dist/access-operations-batch.js +34 -32
  39. package/dist/access-operations.d.ts +14 -14
  40. package/dist/access-operations.js +41 -39
  41. package/dist/access-recall-concurrency.d.ts +14 -14
  42. package/dist/access-recall-concurrency.js +32 -30
  43. package/dist/access-recall-response.d.ts +14 -14
  44. package/dist/access-recall-response.js +32 -30
  45. package/dist/access-recall-surface.d.ts +14 -14
  46. package/dist/access-recall-surface.js +32 -30
  47. package/dist/access-schema.d.ts +114 -114
  48. package/dist/{access-service-BXYrJ3pO.d.ts → access-service-70VHaltr.d.ts} +73 -73
  49. package/dist/access-service-helpers.d.ts +14 -14
  50. package/dist/access-service.d.ts +14 -14
  51. package/dist/access-service.js +32 -30
  52. package/dist/access-surface-catalog.d.ts +14 -14
  53. package/dist/access-surface-catalog.js +34 -32
  54. package/dist/access-surface-catalog.js.map +1 -1
  55. package/dist/access-wearables-meetings-surface.d.ts +4 -4
  56. package/dist/action-confidence.d.ts +1 -1
  57. package/dist/active-memory-bridge.d.ts +1 -1
  58. package/dist/active-recall.d.ts +1 -1
  59. package/dist/active-recall.js +2 -2
  60. package/dist/activity/digest.d.ts +1 -1
  61. package/dist/adapters/index.js +4 -4
  62. package/dist/adapters/registry.js +2 -2
  63. package/dist/ambient-provenance.d.ts +1 -1
  64. package/dist/artifact-search.d.ts +1 -1
  65. package/dist/background-generation.d.ts +1 -1
  66. package/dist/behavior-learner.d.ts +1 -1
  67. package/dist/behavior-signals.d.ts +1 -1
  68. package/dist/bootstrap.d.ts +11 -11
  69. package/dist/briefing-window.d.ts +2 -2
  70. package/dist/briefing.d.ts +2 -2
  71. package/dist/briefing.js +11 -11
  72. package/dist/buffer-surprise-report.d.ts +1 -1
  73. package/dist/buffer-turn-helpers.d.ts +1 -1
  74. package/dist/buffer.d.ts +2 -2
  75. package/dist/buffer.js +5 -5
  76. package/dist/bulk-import/index.d.ts +3 -3
  77. package/dist/calibration.d.ts +1 -1
  78. package/dist/capabilities.d.ts +1 -1
  79. package/dist/{catalog-Bns9zpl3.d.ts → catalog-Byi9prz9.d.ts} +1 -1
  80. package/dist/causal-behavior.d.ts +1 -1
  81. package/dist/causal-consolidation.d.ts +1 -1
  82. package/dist/causal-consolidation.js +12 -12
  83. package/dist/causal-trajectory-graph.d.ts +1 -1
  84. package/dist/{chunk-DE4ZGH2N.js → chunk-2IVHOQRY.js} +8 -3
  85. package/dist/chunk-2IVHOQRY.js.map +1 -0
  86. package/dist/{chunk-MQT3WP3F.js → chunk-3MX4GWJO.js} +2 -2
  87. package/dist/{chunk-PXJ6HE2W.js → chunk-3RABJOGD.js} +2 -2
  88. package/dist/{chunk-V2XNMIAM.js → chunk-4WSR7MYV.js} +2 -2
  89. package/dist/{chunk-6A6HSXWV.js → chunk-5WIGM42T.js} +2 -2
  90. package/dist/{chunk-GGROFIYX.js → chunk-6DYCSSHN.js} +2 -2
  91. package/dist/{chunk-55XWRL6F.js → chunk-6VLOKESS.js} +2 -2
  92. package/dist/{chunk-OS4JVTHR.js → chunk-76RTJ533.js} +3 -3
  93. package/dist/{chunk-4LPIVP77.js → chunk-7VTQETLT.js} +2 -2
  94. package/dist/{chunk-X2NFFBTO.js → chunk-A7GQBJP5.js} +4 -4
  95. package/dist/{chunk-G2SJRFGP.js → chunk-AIKUSXIS.js} +6 -6
  96. package/dist/{chunk-MNG536IS.js → chunk-AJLQH4RO.js} +13 -13
  97. package/dist/{chunk-XEHLYA5Z.js → chunk-AOMVOC2E.js} +3 -3
  98. package/dist/{chunk-XXLH6KFO.js → chunk-BHXY5FXL.js} +2 -2
  99. package/dist/{chunk-PA67GXYJ.js → chunk-C3YEB7CR.js} +5 -5
  100. package/dist/{chunk-SK6HEQTW.js → chunk-DHTOYRDE.js} +2 -2
  101. package/dist/{chunk-WQW6KPVC.js → chunk-DNAD57VY.js} +1 -1
  102. package/dist/chunk-DNAD57VY.js.map +1 -0
  103. package/dist/{chunk-P3YNEMYY.js → chunk-E64HBW7M.js} +2 -2
  104. package/dist/{chunk-NMA7RQPR.js → chunk-EBLKS57G.js} +2 -2
  105. package/dist/{chunk-2QX65IEC.js → chunk-EHUUXLLA.js} +2 -2
  106. package/dist/{chunk-LYMJ36UI.js → chunk-EST3J4LX.js} +2 -2
  107. package/dist/{chunk-B6VDWDFN.js → chunk-EUP4AXIW.js} +2 -2
  108. package/dist/{chunk-XZUHXKM3.js → chunk-FLZJMXFV.js} +2 -2
  109. package/dist/{chunk-GXJSLNYO.js → chunk-FVRZDZ7J.js} +2 -2
  110. package/dist/{chunk-645WOU5I.js → chunk-H7BZBSP6.js} +4 -4
  111. package/dist/{chunk-2JFSQWFH.js → chunk-HIBNECBQ.js} +5 -5
  112. package/dist/{chunk-7ZNJN5WZ.js → chunk-IHOXK2I6.js} +55 -6
  113. package/dist/chunk-IHOXK2I6.js.map +1 -0
  114. package/dist/{chunk-QLCMOHRE.js → chunk-IIDXU2CY.js} +2 -2
  115. package/dist/{chunk-2NKY7OC6.js → chunk-IMJPJY7V.js} +2 -2
  116. package/dist/{chunk-JYXLW22X.js → chunk-JG4AP36X.js} +2 -2
  117. package/dist/{chunk-3RKVSECD.js → chunk-JI5Q6EOY.js} +7 -7
  118. package/dist/{chunk-XKHRNAK7.js → chunk-JIWZVOQM.js} +2 -2
  119. package/dist/{chunk-7YUX52XZ.js → chunk-JVM3CEGL.js} +3 -3
  120. package/dist/{chunk-QB4VXCFN.js → chunk-K26LFJE4.js} +2 -2
  121. package/dist/{chunk-Y5VT7BIT.js → chunk-K4KE5MYE.js} +2 -2
  122. package/dist/{chunk-TQSCR5DU.js → chunk-KG2OOAFF.js} +6 -6
  123. package/dist/{chunk-VV5GCNKG.js → chunk-KHLNIDWB.js} +2 -2
  124. package/dist/{chunk-LIAM7U2J.js → chunk-LE2UESGS.js} +2 -2
  125. package/dist/{chunk-YXWMZAAN.js → chunk-LLFMZYFS.js} +2 -2
  126. package/dist/{chunk-PPJLJD2D.js → chunk-LX32KV2C.js} +2 -2
  127. package/dist/{chunk-44BILQ7U.js → chunk-N57PUWUE.js} +39 -39
  128. package/dist/{chunk-V7IONNTJ.js → chunk-NDWBT2VV.js} +2 -2
  129. package/dist/{chunk-DRLZB3CN.js → chunk-OTGIAJQ2.js} +2 -2
  130. package/dist/{chunk-T3T5HTZZ.js → chunk-P36WML7L.js} +2 -2
  131. package/dist/{chunk-SJ7ZNUXB.js → chunk-PAQ7YGJY.js} +2 -2
  132. package/dist/{chunk-YOSLKZLZ.js → chunk-PSQRBCGR.js} +2 -2
  133. package/dist/{chunk-FGRJJBFO.js → chunk-PZHN7R35.js} +2 -2
  134. package/dist/{chunk-QMWKENNK.js → chunk-Q4AUIFUA.js} +4 -4
  135. package/dist/{chunk-CD7VTZIG.js → chunk-QQA6VTOY.js} +2 -2
  136. package/dist/{chunk-ROBGBT3D.js → chunk-RBHQA2UU.js} +50 -50
  137. package/dist/{chunk-HG74GEVY.js → chunk-RS53SDCA.js} +2 -2
  138. package/dist/{chunk-SS33RR4F.js → chunk-SKYYPVBW.js} +8 -8
  139. package/dist/{chunk-OSTXIFZW.js → chunk-SNOAFXKX.js} +38 -4
  140. package/dist/chunk-SNOAFXKX.js.map +1 -0
  141. package/dist/{chunk-EWBDJQ5Y.js → chunk-SYJZUVTN.js} +3 -3
  142. package/dist/{chunk-IO7K7GES.js → chunk-T3F2HWIG.js} +2 -2
  143. package/dist/{chunk-BMENHAJL.js → chunk-T3OLYUU6.js} +2 -2
  144. package/dist/{chunk-AS4YKT75.js → chunk-TUSY4KRE.js} +207 -44
  145. package/dist/chunk-TUSY4KRE.js.map +1 -0
  146. package/dist/{chunk-QGAKUOKU.js → chunk-U3ZRHNNG.js} +2 -2
  147. package/dist/{chunk-LIDJWAQV.js → chunk-UB4UVALS.js} +2 -2
  148. package/dist/chunk-UD6W67JM.js +260 -0
  149. package/dist/chunk-UD6W67JM.js.map +1 -0
  150. package/dist/{chunk-WYU66IVZ.js → chunk-UE7L4EDU.js} +3 -3
  151. package/dist/{chunk-I6IJDTRP.js → chunk-VBRS7Z3O.js} +2 -2
  152. package/dist/{chunk-EGOWY342.js → chunk-WGCASEEQ.js} +2 -2
  153. package/dist/{chunk-QKFYJVDG.js → chunk-WHSNLCRO.js} +2 -2
  154. package/dist/{chunk-JXLEQIJ7.js → chunk-XQFHKPNB.js} +7 -7
  155. package/dist/{chunk-NE45P3OF.js → chunk-YA5M7OC4.js} +2 -2
  156. package/dist/{chunk-WL3PGPGU.js → chunk-YKWWG3CM.js} +2 -2
  157. package/dist/{chunk-EZ25VE3G.js → chunk-YNDLCWXS.js} +4 -4
  158. package/dist/{chunk-MMQVWKFY.js → chunk-YOC3EEZH.js} +12 -12
  159. package/dist/{chunk-ZEIJQ4I3.js → chunk-Z2OKRO3E.js} +2 -2
  160. package/dist/{chunk-5KBI2MOC.js → chunk-ZDGSHXJU.js} +1 -1
  161. package/dist/{chunk-R4JTUTU6.js → chunk-ZYZW46HZ.js} +3 -3
  162. package/dist/{cli-B8YyIrPR.d.ts → cli-CdJiBilM.d.ts} +5 -5
  163. package/dist/cli.d.ts +16 -16
  164. package/dist/cli.js +71 -69
  165. package/dist/coding/export-okf-codegraph.d.ts +1 -1
  166. package/dist/coding/export-okf-codegraph.js +13 -13
  167. package/dist/coding/pre-action-gate.d.ts +1 -1
  168. package/dist/compounding/engine.d.ts +2 -2
  169. package/dist/compounding/engine.js +12 -12
  170. package/dist/compounding/preference-consolidator.d.ts +1 -1
  171. package/dist/compression-optimizer.d.ts +1 -1
  172. package/dist/config.d.ts +1 -1
  173. package/dist/config.js +2 -2
  174. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  175. package/dist/connectors/codex-materialize-runner.js +11 -11
  176. package/dist/connectors/codex-materialize.d.ts +1 -1
  177. package/dist/connectors/index.d.ts +1 -1
  178. package/dist/connectors/index.js +11 -11
  179. package/dist/consolidation-provenance-check.d.ts +2 -2
  180. package/dist/consolidation-undo.d.ts +2 -2
  181. package/dist/contradiction/index.d.ts +4 -4
  182. package/dist/converge-config.d.ts +1 -1
  183. package/dist/convergence-refresh.d.ts +2 -2
  184. package/dist/convergence-refresh.js +13 -13
  185. package/dist/conversation-index/backend.d.ts +1 -1
  186. package/dist/conversation-index/chunker.d.ts +1 -1
  187. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  188. package/dist/conversation-index/indexer.d.ts +1 -1
  189. package/dist/conversation-index/search.d.ts +1 -1
  190. package/dist/corpus-watermark.d.ts +1 -1
  191. package/dist/corpus-watermark.js +13 -13
  192. package/dist/cross-lingual-recall.d.ts +1 -1
  193. package/dist/dashboard-runtime.js +2 -2
  194. package/dist/day-summary.d.ts +1 -1
  195. package/dist/deep-recall-http-glue.d.ts +14 -14
  196. package/dist/deep-recall-mcp-tools.d.ts +14 -14
  197. package/dist/deep-recall-policy-llm.d.ts +2 -2
  198. package/dist/deep-recall-seeds.d.ts +1 -1
  199. package/dist/delinearize.d.ts +1 -1
  200. package/dist/dependency-propagation-config.d.ts +1 -1
  201. package/dist/{dependency-propagation-delivery-B-LvcDaq.d.ts → dependency-propagation-delivery-BgHy44WX.d.ts} +1 -1
  202. package/dist/direct-answer-wiring.d.ts +1 -1
  203. package/dist/direct-answer.d.ts +1 -1
  204. package/dist/directory-sidecars.d.ts +87 -0
  205. package/dist/directory-sidecars.js +22 -0
  206. package/dist/directory-sidecars.js.map +1 -0
  207. package/dist/embedding-fallback.d.ts +1 -1
  208. package/dist/enrichment/index.d.ts +1 -1
  209. package/dist/entity-origin-fields.d.ts +1 -1
  210. package/dist/entity-retrieval.d.ts +2 -2
  211. package/dist/entity-retrieval.js +13 -13
  212. package/dist/entity-schema.d.ts +1 -1
  213. package/dist/episodic-context.d.ts +1 -1
  214. package/dist/eval-trajectory-contracts.d.ts +1 -1
  215. package/dist/eval-trajectory-store.d.ts +1 -1
  216. package/dist/eval-trajectory.d.ts +1 -1
  217. package/dist/event-order-recall.js +2 -2
  218. package/dist/explicit-capture.d.ts +11 -11
  219. package/dist/external-wiki-access.d.ts +14 -14
  220. package/dist/external-wiki-access.js +33 -31
  221. package/dist/external-wiki-collection-registration.d.ts +1 -1
  222. package/dist/external-wiki-collection.d.ts +1 -1
  223. package/dist/external-wiki-mcp-tools.d.ts +14 -14
  224. package/dist/extraction-error-classification.d.ts +1 -1
  225. package/dist/extraction-evidence-class.d.ts +1 -1
  226. package/dist/extraction-faithfulness.d.ts +2 -2
  227. package/dist/extraction-judge-telemetry.d.ts +2 -2
  228. package/dist/extraction-judge-training.d.ts +2 -2
  229. package/dist/extraction-judge.d.ts +2 -2
  230. package/dist/extraction-liveness.d.ts +1 -1
  231. package/dist/extraction-normalization.d.ts +1 -1
  232. package/dist/extraction-prompt.d.ts +1 -1
  233. package/dist/extraction-source-grounding-rules.d.ts +1 -1
  234. package/dist/extraction-source-grounding.d.ts +1 -1
  235. package/dist/extraction-span-config.d.ts +1 -1
  236. package/dist/extraction-span-materialize.d.ts +1 -1
  237. package/dist/extraction-span-wire.d.ts +1 -1
  238. package/dist/extraction.d.ts +2 -2
  239. package/dist/extraction.js +15 -15
  240. package/dist/fallback-llm-codex-subscription.d.ts +1 -1
  241. package/dist/fallback-llm.d.ts +1 -1
  242. package/dist/{generic-recall-paths-Bfc7zigS.d.ts → generic-recall-paths-BoueWXYr.d.ts} +1 -1
  243. package/dist/graph-append-error.d.ts +1 -1
  244. package/dist/graph-dashboard-diff.d.ts +1 -1
  245. package/dist/graph-dashboard-key.d.ts +1 -1
  246. package/dist/graph-dashboard-parser.d.ts +1 -1
  247. package/dist/graph-edge-reinforcement.d.ts +1 -1
  248. package/dist/graph-jsonl.d.ts +1 -1
  249. package/dist/graph-path-reconstruction.d.ts +1 -1
  250. package/dist/graph-path-scoring.d.ts +1 -1
  251. package/dist/graph-snapshot.d.ts +1 -1
  252. package/dist/graph.d.ts +1 -1
  253. package/dist/harmonic-retrieval.js +1 -1
  254. package/dist/importance.d.ts +1 -1
  255. package/dist/importers/index.d.ts +1 -1
  256. package/dist/importers/test-utils.d.ts +1 -1
  257. package/dist/in-flight-reads.d.ts +1 -1
  258. package/dist/{index-C7IA1DxB.d.ts → index-cwbrXoxe.d.ts} +3 -3
  259. package/dist/index.d.ts +719 -719
  260. package/dist/index.js +132 -127
  261. package/dist/intent.d.ts +1 -1
  262. package/dist/lcm/engine.d.ts +1 -1
  263. package/dist/lcm/engine.js +2 -2
  264. package/dist/lcm/index.d.ts +1 -1
  265. package/dist/lcm/index.js +4 -4
  266. package/dist/lcm/tools.d.ts +1 -1
  267. package/dist/lifecycle.d.ts +1 -1
  268. package/dist/live-connectors-runner.d.ts +1 -1
  269. package/dist/{local-llm-DH4tWtck.d.ts → local-llm-B0vd_rp9.d.ts} +1 -1
  270. package/dist/local-llm-helpers.d.ts +2 -2
  271. package/dist/local-llm.d.ts +2 -2
  272. package/dist/local-model-endpoint.d.ts +1 -1
  273. package/dist/location/index.d.ts +5 -5
  274. package/dist/location/index.js +13 -13
  275. package/dist/maintenance/memory-governance.d.ts +1 -1
  276. package/dist/maintenance/memory-governance.js +11 -11
  277. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
  278. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +11 -11
  279. package/dist/maintenance/rebuild-memory-projection.d.ts +2 -2
  280. package/dist/maintenance/rebuild-memory-projection.js +12 -12
  281. package/dist/{maintenance-n6yeTQhR.d.ts → maintenance-DJgQkoLh.d.ts} +3 -3
  282. package/dist/mcp-memory-inspector-app.d.ts +14 -14
  283. package/dist/memory-action-policy.d.ts +1 -1
  284. package/dist/memory-browse-http-glue.d.ts +14 -14
  285. package/dist/memory-browse-mcp-tools.d.ts +14 -14
  286. package/dist/memory-browse-operations.js +33 -31
  287. package/dist/memory-browse.d.ts +1 -1
  288. package/dist/memory-browse.js +7 -5
  289. package/dist/memory-cache.d.ts +1 -1
  290. package/dist/memory-controller.d.ts +1 -1
  291. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  292. package/dist/memory-projection-store.d.ts +1 -1
  293. package/dist/memory-provenance.d.ts +1 -1
  294. package/dist/memory-snapshot.d.ts +1 -1
  295. package/dist/memory-subject-cli.d.ts +14 -14
  296. package/dist/memory-subject.d.ts +14 -14
  297. package/dist/memory-worth-outcomes.d.ts +2 -2
  298. package/dist/models-json.d.ts +1 -1
  299. package/dist/namespaces/migrate.d.ts +3 -3
  300. package/dist/namespaces/migrate.js +12 -12
  301. package/dist/namespaces/principal.d.ts +1 -1
  302. package/dist/namespaces/search.d.ts +1 -1
  303. package/dist/namespaces/search.js +6 -6
  304. package/dist/namespaces/storage.d.ts +3 -3
  305. package/dist/namespaces/storage.js +11 -11
  306. package/dist/native-knowledge.d.ts +1 -1
  307. package/dist/offline-sync-impression-drain.d.ts +1 -1
  308. package/dist/operator-doctor-corpus.d.ts +1 -1
  309. package/dist/operator-doctor-corpus.js +14 -14
  310. package/dist/operator-doctor-replica.d.ts +1 -1
  311. package/dist/operator-toolkit.d.ts +3 -3
  312. package/dist/operator-toolkit.js +21 -21
  313. package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
  314. package/dist/orchestration/maintenance.d.ts +4 -4
  315. package/dist/orchestration/maintenance.js +19 -19
  316. package/dist/{orchestrator-Cirjo3ZB.d.ts → orchestrator-Kx5zwNUm.d.ts} +10 -10
  317. package/dist/orchestrator.d.ts +11 -11
  318. package/dist/orchestrator.js +99 -98
  319. package/dist/patterns-cli.d.ts +1 -1
  320. package/dist/{pipeline-DK79FrgH.d.ts → pipeline-9SYxxign.d.ts} +1 -1
  321. package/dist/policy-runtime.d.ts +1 -1
  322. package/dist/proactive-contention.d.ts +2 -2
  323. package/dist/provenance.d.ts +1 -1
  324. package/dist/{public-http-VB85y0ZH.d.ts → public-http-Bvol6Jr4.d.ts} +1 -1
  325. package/dist/{qmd-BT0ErlRS.d.ts → qmd-DjwuG9Xa.d.ts} +1 -1
  326. package/dist/qmd-preflight.d.ts +2 -2
  327. package/dist/qmd-recall-cache.d.ts +1 -1
  328. package/dist/qmd.d.ts +2 -2
  329. package/dist/qmd.js +4 -4
  330. package/dist/recall-concurrency-config.d.ts +1 -1
  331. package/dist/recall-context-composition.d.ts +43 -3
  332. package/dist/recall-context-composition.js +5 -1
  333. package/dist/recall-disclosure-escalation.d.ts +1 -1
  334. package/dist/recall-explain-renderer.d.ts +1 -1
  335. package/dist/recall-explain-renderer.js +3 -3
  336. package/dist/recall-memory-map.d.ts +1 -1
  337. package/dist/recall-navigate-access.d.ts +1 -1
  338. package/dist/recall-navigate-access.js +2 -2
  339. package/dist/recall-navigate-disclosure.d.ts +1 -1
  340. package/dist/recall-navigate-disclosure.js +2 -2
  341. package/dist/recall-navigate.d.ts +1 -1
  342. package/dist/recall-navigate.js +2 -2
  343. package/dist/recall-navigation-http-glue.d.ts +14 -14
  344. package/dist/recall-navigation-mcp-tools.d.ts +14 -14
  345. package/dist/recall-navigation-operations.js +33 -31
  346. package/dist/recall-navigation-renderer.d.ts +1 -1
  347. package/dist/recall-navigation.d.ts +1 -1
  348. package/dist/recall-navigation.js +32 -30
  349. package/dist/recall-planner-llm.d.ts +1 -1
  350. package/dist/recall-state-view-admission.d.ts +2 -2
  351. package/dist/recall-state-view-admission.js +8 -5
  352. package/dist/recall-state-view-anchors.d.ts +1 -1
  353. package/dist/recall-state.d.ts +1 -1
  354. package/dist/recall-tag-filter.d.ts +1 -1
  355. package/dist/recall-timings.d.ts +1 -1
  356. package/dist/recall-xray-cli.d.ts +1 -1
  357. package/dist/recall-xray-cli.js +4 -4
  358. package/dist/recall-xray-renderer.d.ts +1 -1
  359. package/dist/recall-xray-renderer.js +3 -3
  360. package/dist/recall-xray.d.ts +1 -1
  361. package/dist/recall-xray.js +2 -2
  362. package/dist/reconcile/cursor.d.ts +1 -1
  363. package/dist/reconcile/manifest.d.ts +1 -1
  364. package/dist/reconcile/plan.d.ts +1 -1
  365. package/dist/replay/normalizers/chatgpt.d.ts +1 -1
  366. package/dist/replay/normalizers/claude.d.ts +1 -1
  367. package/dist/replay/normalizers/openclaw.d.ts +1 -1
  368. package/dist/replay/normalizers/shared.d.ts +1 -1
  369. package/dist/replay/runner.d.ts +1 -1
  370. package/dist/replay/types.d.ts +1 -1
  371. package/dist/replica-divergence.d.ts +1 -1
  372. package/dist/replica-peers-config.d.ts +1 -1
  373. package/dist/resolve-auth-token.d.ts +1 -1
  374. package/dist/resume-bundles.js +3 -3
  375. package/dist/retrieval-agents.d.ts +2 -2
  376. package/dist/retrieval-tiers.d.ts +1 -1
  377. package/dist/routing/engine.d.ts +1 -1
  378. package/dist/routing/store.d.ts +1 -1
  379. package/dist/salvage-envelope.d.ts +1 -1
  380. package/dist/schemas.d.ts +160 -160
  381. package/dist/{scope-profiles-BgPQx9iE.d.ts → scope-profiles-DPegZtRf.d.ts} +1 -1
  382. package/dist/search/embed-helper.d.ts +1 -1
  383. package/dist/search/factory.d.ts +1 -1
  384. package/dist/search/factory.js +5 -5
  385. package/dist/search/index.d.ts +1 -1
  386. package/dist/search/index.js +9 -9
  387. package/dist/search/lancedb-backend.d.ts +1 -1
  388. package/dist/search/meilisearch-backend.d.ts +1 -1
  389. package/dist/search/noop-backend.d.ts +1 -1
  390. package/dist/search/orama-backend.d.ts +1 -1
  391. package/dist/search/port.d.ts +1 -1
  392. package/dist/search/remote-backend.d.ts +1 -1
  393. package/dist/{semantic-consolidation-BrAWKVcm.d.ts → semantic-consolidation-DMzhKRYl.d.ts} +1 -1
  394. package/dist/semantic-consolidation.d.ts +2 -2
  395. package/dist/semantic-consolidation.js +12 -12
  396. package/dist/semantic-rule-promotion.js +11 -11
  397. package/dist/semantic-rule-verifier.d.ts +1 -1
  398. package/dist/semantic-rule-verifier.js +11 -11
  399. package/dist/{service-CqHOTg87.d.ts → service-E99KuPvi.d.ts} +2 -2
  400. package/dist/session-observer-bands.d.ts +1 -1
  401. package/dist/session-observer-state.d.ts +1 -1
  402. package/dist/shared-context/manager.d.ts +7 -7
  403. package/dist/signal.d.ts +1 -1
  404. package/dist/source-agent-qualifier.d.ts +1 -1
  405. package/dist/source-agent-qualifier.js +14 -14
  406. package/dist/standup/build.js +11 -11
  407. package/dist/{storage-mD2YQ8_2.d.ts → storage-BS7ux8F7.d.ts} +1 -1
  408. package/dist/storage.d.ts +2 -2
  409. package/dist/storage.js +10 -10
  410. package/dist/subject-config.d.ts +1 -1
  411. package/dist/summarizer.d.ts +1 -1
  412. package/dist/summary-snapshot.d.ts +1 -1
  413. package/dist/support-passport/index.d.ts +17 -17
  414. package/dist/support-passport/index.js +35 -33
  415. package/dist/{tagging-CiAVA-ID.d.ts → tagging-BhOEcSXP.d.ts} +2 -2
  416. package/dist/temporal-supersession.d.ts +2 -2
  417. package/dist/temporal-timeline-recall.d.ts +1 -1
  418. package/dist/temporal-timeline-recall.js +2 -2
  419. package/dist/temporal-validity.d.ts +1 -1
  420. package/dist/threading.d.ts +1 -1
  421. package/dist/tier-migration.d.ts +2 -2
  422. package/dist/tier-routing.d.ts +1 -1
  423. package/dist/topics.d.ts +1 -1
  424. package/dist/transcript.d.ts +1 -1
  425. package/dist/transfer/export-okf.d.ts +1 -1
  426. package/dist/transfer/export-okf.js +11 -11
  427. package/dist/transfer/types.d.ts +78 -78
  428. package/dist/trust-score-stage.d.ts +1 -1
  429. package/dist/trust-score.d.ts +1 -1
  430. package/dist/{types-DgDaoY61.d.ts → types-DQ2H8gAC.d.ts} +19 -0
  431. package/dist/types.d.ts +1 -1
  432. package/dist/types.js +1 -1
  433. package/dist/utility-runtime.d.ts +1 -1
  434. package/dist/verified-recall.js +11 -11
  435. package/dist/who-knows-cli.d.ts +14 -14
  436. package/dist/who-knows-cli.js +12 -12
  437. package/dist/who-knows.d.ts +14 -14
  438. package/dist/who-knows.js +11 -11
  439. package/dist/write-envelope.d.ts +1 -1
  440. package/package.json +2 -2
  441. package/src/config.ts +4 -0
  442. package/src/directory-sidecars.test.ts +268 -0
  443. package/src/directory-sidecars.ts +383 -0
  444. package/src/experience/session-experience-config.ts +51 -0
  445. package/src/experience/session-experience-lifecycle.test.ts +139 -0
  446. package/src/experience/session-experience.test.ts +233 -0
  447. package/src/experience/session-experience.ts +240 -0
  448. package/src/orchestration/generic-recall-paths.ts +5 -1
  449. package/src/orchestration/session-context.ts +50 -0
  450. package/src/recall-context-composition.test.ts +66 -0
  451. package/src/recall-context-composition.ts +102 -2
  452. package/src/types.ts +3 -0
  453. package/dist/chunk-7ZNJN5WZ.js.map +0 -1
  454. package/dist/chunk-AS4YKT75.js.map +0 -1
  455. package/dist/chunk-DE4ZGH2N.js.map +0 -1
  456. package/dist/chunk-OSTXIFZW.js.map +0 -1
  457. package/dist/chunk-WQW6KPVC.js.map +0 -1
  458. /package/dist/{chunk-MQT3WP3F.js.map → chunk-3MX4GWJO.js.map} +0 -0
  459. /package/dist/{chunk-PXJ6HE2W.js.map → chunk-3RABJOGD.js.map} +0 -0
  460. /package/dist/{chunk-V2XNMIAM.js.map → chunk-4WSR7MYV.js.map} +0 -0
  461. /package/dist/{chunk-6A6HSXWV.js.map → chunk-5WIGM42T.js.map} +0 -0
  462. /package/dist/{chunk-GGROFIYX.js.map → chunk-6DYCSSHN.js.map} +0 -0
  463. /package/dist/{chunk-55XWRL6F.js.map → chunk-6VLOKESS.js.map} +0 -0
  464. /package/dist/{chunk-OS4JVTHR.js.map → chunk-76RTJ533.js.map} +0 -0
  465. /package/dist/{chunk-4LPIVP77.js.map → chunk-7VTQETLT.js.map} +0 -0
  466. /package/dist/{chunk-X2NFFBTO.js.map → chunk-A7GQBJP5.js.map} +0 -0
  467. /package/dist/{chunk-G2SJRFGP.js.map → chunk-AIKUSXIS.js.map} +0 -0
  468. /package/dist/{chunk-MNG536IS.js.map → chunk-AJLQH4RO.js.map} +0 -0
  469. /package/dist/{chunk-XEHLYA5Z.js.map → chunk-AOMVOC2E.js.map} +0 -0
  470. /package/dist/{chunk-XXLH6KFO.js.map → chunk-BHXY5FXL.js.map} +0 -0
  471. /package/dist/{chunk-PA67GXYJ.js.map → chunk-C3YEB7CR.js.map} +0 -0
  472. /package/dist/{chunk-SK6HEQTW.js.map → chunk-DHTOYRDE.js.map} +0 -0
  473. /package/dist/{chunk-P3YNEMYY.js.map → chunk-E64HBW7M.js.map} +0 -0
  474. /package/dist/{chunk-NMA7RQPR.js.map → chunk-EBLKS57G.js.map} +0 -0
  475. /package/dist/{chunk-2QX65IEC.js.map → chunk-EHUUXLLA.js.map} +0 -0
  476. /package/dist/{chunk-LYMJ36UI.js.map → chunk-EST3J4LX.js.map} +0 -0
  477. /package/dist/{chunk-B6VDWDFN.js.map → chunk-EUP4AXIW.js.map} +0 -0
  478. /package/dist/{chunk-XZUHXKM3.js.map → chunk-FLZJMXFV.js.map} +0 -0
  479. /package/dist/{chunk-GXJSLNYO.js.map → chunk-FVRZDZ7J.js.map} +0 -0
  480. /package/dist/{chunk-645WOU5I.js.map → chunk-H7BZBSP6.js.map} +0 -0
  481. /package/dist/{chunk-2JFSQWFH.js.map → chunk-HIBNECBQ.js.map} +0 -0
  482. /package/dist/{chunk-QLCMOHRE.js.map → chunk-IIDXU2CY.js.map} +0 -0
  483. /package/dist/{chunk-2NKY7OC6.js.map → chunk-IMJPJY7V.js.map} +0 -0
  484. /package/dist/{chunk-JYXLW22X.js.map → chunk-JG4AP36X.js.map} +0 -0
  485. /package/dist/{chunk-3RKVSECD.js.map → chunk-JI5Q6EOY.js.map} +0 -0
  486. /package/dist/{chunk-XKHRNAK7.js.map → chunk-JIWZVOQM.js.map} +0 -0
  487. /package/dist/{chunk-7YUX52XZ.js.map → chunk-JVM3CEGL.js.map} +0 -0
  488. /package/dist/{chunk-QB4VXCFN.js.map → chunk-K26LFJE4.js.map} +0 -0
  489. /package/dist/{chunk-Y5VT7BIT.js.map → chunk-K4KE5MYE.js.map} +0 -0
  490. /package/dist/{chunk-TQSCR5DU.js.map → chunk-KG2OOAFF.js.map} +0 -0
  491. /package/dist/{chunk-VV5GCNKG.js.map → chunk-KHLNIDWB.js.map} +0 -0
  492. /package/dist/{chunk-LIAM7U2J.js.map → chunk-LE2UESGS.js.map} +0 -0
  493. /package/dist/{chunk-YXWMZAAN.js.map → chunk-LLFMZYFS.js.map} +0 -0
  494. /package/dist/{chunk-PPJLJD2D.js.map → chunk-LX32KV2C.js.map} +0 -0
  495. /package/dist/{chunk-44BILQ7U.js.map → chunk-N57PUWUE.js.map} +0 -0
  496. /package/dist/{chunk-V7IONNTJ.js.map → chunk-NDWBT2VV.js.map} +0 -0
  497. /package/dist/{chunk-DRLZB3CN.js.map → chunk-OTGIAJQ2.js.map} +0 -0
  498. /package/dist/{chunk-T3T5HTZZ.js.map → chunk-P36WML7L.js.map} +0 -0
  499. /package/dist/{chunk-SJ7ZNUXB.js.map → chunk-PAQ7YGJY.js.map} +0 -0
  500. /package/dist/{chunk-YOSLKZLZ.js.map → chunk-PSQRBCGR.js.map} +0 -0
  501. /package/dist/{chunk-FGRJJBFO.js.map → chunk-PZHN7R35.js.map} +0 -0
  502. /package/dist/{chunk-QMWKENNK.js.map → chunk-Q4AUIFUA.js.map} +0 -0
  503. /package/dist/{chunk-CD7VTZIG.js.map → chunk-QQA6VTOY.js.map} +0 -0
  504. /package/dist/{chunk-ROBGBT3D.js.map → chunk-RBHQA2UU.js.map} +0 -0
  505. /package/dist/{chunk-HG74GEVY.js.map → chunk-RS53SDCA.js.map} +0 -0
  506. /package/dist/{chunk-SS33RR4F.js.map → chunk-SKYYPVBW.js.map} +0 -0
  507. /package/dist/{chunk-EWBDJQ5Y.js.map → chunk-SYJZUVTN.js.map} +0 -0
  508. /package/dist/{chunk-IO7K7GES.js.map → chunk-T3F2HWIG.js.map} +0 -0
  509. /package/dist/{chunk-BMENHAJL.js.map → chunk-T3OLYUU6.js.map} +0 -0
  510. /package/dist/{chunk-QGAKUOKU.js.map → chunk-U3ZRHNNG.js.map} +0 -0
  511. /package/dist/{chunk-LIDJWAQV.js.map → chunk-UB4UVALS.js.map} +0 -0
  512. /package/dist/{chunk-WYU66IVZ.js.map → chunk-UE7L4EDU.js.map} +0 -0
  513. /package/dist/{chunk-I6IJDTRP.js.map → chunk-VBRS7Z3O.js.map} +0 -0
  514. /package/dist/{chunk-EGOWY342.js.map → chunk-WGCASEEQ.js.map} +0 -0
  515. /package/dist/{chunk-QKFYJVDG.js.map → chunk-WHSNLCRO.js.map} +0 -0
  516. /package/dist/{chunk-JXLEQIJ7.js.map → chunk-XQFHKPNB.js.map} +0 -0
  517. /package/dist/{chunk-NE45P3OF.js.map → chunk-YA5M7OC4.js.map} +0 -0
  518. /package/dist/{chunk-WL3PGPGU.js.map → chunk-YKWWG3CM.js.map} +0 -0
  519. /package/dist/{chunk-EZ25VE3G.js.map → chunk-YNDLCWXS.js.map} +0 -0
  520. /package/dist/{chunk-MMQVWKFY.js.map → chunk-YOC3EEZH.js.map} +0 -0
  521. /package/dist/{chunk-ZEIJQ4I3.js.map → chunk-Z2OKRO3E.js.map} +0 -0
  522. /package/dist/{chunk-5KBI2MOC.js.map → chunk-ZDGSHXJU.js.map} +0 -0
  523. /package/dist/{chunk-R4JTUTU6.js.map → chunk-ZYZW46HZ.js.map} +0 -0
@@ -0,0 +1,383 @@
1
+ /**
2
+ * @remnic/core — per-directory abstract/overview sidecars (issue #2977).
3
+ *
4
+ * One derived `overview.md` per memory directory (category roots and every
5
+ * directory beneath them, including `namespaces/<ns>/` subtrees), rendered
6
+ * bottom-up from existing memory content:
7
+ *
8
+ * - the ABSTRACT is a single line (<=256 chars) composed from child titles;
9
+ * - the OVERVIEW body lists one preview line per child memory and embeds
10
+ * each child DIRECTORY's abstract, so a parent summarizes its subtree
11
+ * without embedding full child overviews.
12
+ *
13
+ * Determinism: no LLM, no embeddings. Content is assembled with the same
14
+ * preview machinery the OKF index files use (`normalizeProjectionPreview`).
15
+ *
16
+ * Invalidation: each sidecar stores a content-free fingerprint of its subtree
17
+ * (child name|size|mtime for files, recursive fingerprints for child dirs).
18
+ * Any add/edit/delete anywhere below a directory changes its fingerprint, so
19
+ * `loadDirectorySidecar` can detect staleness with `readdir`+`stat` alone and
20
+ * refresh without reading child memory files first. Eager regeneration runs
21
+ * through {@link runDirectorySidecarMaintenance}; lazy refresh on read covers
22
+ * direct-write paths that bypass scheduled maintenance (Gotcha #43).
23
+ *
24
+ * Isolation: sidecars are derived artifacts, excluded from generic recall via
25
+ * `isGenericRecallExcludedPath` (basename match, the same tradeoff OKF makes
26
+ * for `index.md`/`log.md`) while staying full-text searchable. Files at the
27
+ * sidecar path WITHOUT the marker are user content: never overwritten, never
28
+ * removed.
29
+ */
30
+
31
+ import { createHash } from "node:crypto";
32
+ import { lstatSync, readFileSync, readdirSync, statSync, unlinkSync } from "node:fs";
33
+ import path from "node:path";
34
+
35
+ import { writeFileAtomically } from "./maintenance/atomic-file.js";
36
+ import { normalizeProjectionPreview } from "./memory-projection-format.js";
37
+ import { OKF_RESERVED_BASENAMES } from "./okf/type-mapping.js";
38
+ import { RECALL_FALLBACK_DIRS } from "./utils/category-dir.js";
39
+
40
+ export const DIRECTORY_SIDECAR_BASENAME = "overview.md";
41
+ export const DIRECTORY_SIDECAR_MARKER = "<!-- remnic-directory-sidecar -->";
42
+
43
+ const ABSTRACT_MAX_CHARS = 256;
44
+ const OVERVIEW_MAX_CHARS = 4000;
45
+ const DEFAULT_QUERY_LIMIT = 5;
46
+
47
+ /** Basenames never treated as child memories (ours plus OKF's reserved ones). */
48
+ const RESERVED_CHILD_BASENAMES: Readonly<Record<string, true>> = Object.freeze({
49
+ ...OKF_RESERVED_BASENAMES,
50
+ [DIRECTORY_SIDECAR_BASENAME]: true,
51
+ });
52
+
53
+ export interface DirectorySidecar {
54
+ /** Absolute directory the sidecar describes. */
55
+ readonly dir: string;
56
+ /** Single-line L0 abstract (<=256 chars). */
57
+ readonly abstract: string;
58
+ /** Abstract plus the per-child preview body (<=4000 chars). */
59
+ readonly overview: string;
60
+ /** Number of memory `.md` children in this directory. */
61
+ readonly childCount: number;
62
+ /** False when the stored fingerprint no longer matches the subtree. */
63
+ readonly fresh: boolean;
64
+ }
65
+
66
+ export interface DirectorySidecarMatch extends DirectorySidecar {
67
+ readonly score: number;
68
+ }
69
+
70
+ export interface DirectorySidecarReport {
71
+ written: string[];
72
+ removed: string[];
73
+ }
74
+
75
+ interface ParsedSidecar {
76
+ abstract: string;
77
+ overview: string;
78
+ childCount: number;
79
+ fingerprint: string;
80
+ }
81
+
82
+ function listEntries(dir: string) {
83
+ try {
84
+ return readdirSync(dir, { withFileTypes: true });
85
+ } catch {
86
+ return [];
87
+ }
88
+ }
89
+
90
+ /** Root check that refuses symlinks (fs-boundary rule, PRs #1938/#1999). */
91
+ function isRealDirectory(entryPath: string): boolean {
92
+ try {
93
+ const stats = lstatSync(entryPath);
94
+ return !stats.isSymbolicLink() && stats.isDirectory();
95
+ } catch {
96
+ return false;
97
+ }
98
+ }
99
+
100
+ function memoryChildren(dir: string): string[] {
101
+ // Dirent.isFile() is false for symlinks, so a linked memory never enters the corpus.
102
+ return listEntries(dir)
103
+ .filter((entry) => entry.isFile() && !RESERVED_CHILD_BASENAMES[entry.name] && entry.name.endsWith(".md"))
104
+ .map((entry) => entry.name)
105
+ .sort((a, b) => a.localeCompare(b));
106
+ }
107
+
108
+ function directoryChildren(dir: string): string[] {
109
+ // Dirent.isDirectory() is false for symlinks (fs-boundary rule, PRs #1938/#1999).
110
+ return listEntries(dir)
111
+ .filter((entry) => entry.isDirectory())
112
+ .map((entry) => entry.name)
113
+ .sort((a, b) => a.localeCompare(b));
114
+ }
115
+
116
+ /**
117
+ * Content-free subtree fingerprint: sha256 over sorted child descriptors.
118
+ * Files contribute `name|size|mtimeMs`; directories contribute their own
119
+ * recursive fingerprint, so any change below a directory invalidates every
120
+ * ancestor. Reads no file contents.
121
+ */
122
+ export function directoryFingerprint(dir: string): string {
123
+ const hash = createHash("sha256");
124
+ for (const name of memoryChildren(dir)) {
125
+ try {
126
+ const stats = statSync(path.join(dir, name));
127
+ hash.update(`f|${name}|${stats.size}|${Math.trunc(stats.mtimeMs)}\n`);
128
+ } catch {
129
+ hash.update(`f|${name}|missing\n`);
130
+ }
131
+ }
132
+ for (const name of directoryChildren(dir)) {
133
+ hash.update(`d|${name}|${directoryFingerprint(path.join(dir, name))}\n`);
134
+ }
135
+ return hash.digest("hex");
136
+ }
137
+
138
+ function readFileOrNull(target: string): string | null {
139
+ try {
140
+ return readFileSync(target, "utf8");
141
+ } catch {
142
+ return null;
143
+ }
144
+ }
145
+
146
+ function parseSidecar(content: string): ParsedSidecar | null {
147
+ if (!content.startsWith(DIRECTORY_SIDECAR_MARKER)) return null;
148
+ const fingerprint = /^fingerprint: ([0-9a-f]{64})$/m.exec(content)?.[1];
149
+ if (!fingerprint) return null;
150
+ const abstract = /^## Abstract\n([^\n]+)$/m.exec(content)?.[1] ?? "";
151
+ const overviewStart = content.indexOf("## Abstract");
152
+ const overview =
153
+ overviewStart === -1 ? "" : content.slice(overviewStart, overviewStart + OVERVIEW_MAX_CHARS).trim();
154
+ // The `* name — preview` child bullets are the rendered child count.
155
+ const childCount = (content.match(/^\* .+$/gm) ?? []).length;
156
+ return { abstract, overview, childCount, fingerprint };
157
+ }
158
+
159
+ function sidecarPath(dir: string): string {
160
+ return path.join(dir, DIRECTORY_SIDECAR_BASENAME);
161
+ }
162
+
163
+ function renderSidecar(dir: string, fingerprint: string, childAbstracts: Map<string, string>): string | null {
164
+ const children = memoryChildren(dir);
165
+ const childDirs = directoryChildren(dir).filter((name) => childAbstracts.has(path.join(dir, name)));
166
+ if (children.length === 0 && childDirs.length === 0) return null;
167
+
168
+ const previews = children.map((name) => {
169
+ try {
170
+ return normalizeProjectionPreview(readFileSync(path.join(dir, name), "utf8"), 120);
171
+ } catch {
172
+ return "";
173
+ }
174
+ });
175
+ const titles = children.map(
176
+ (name, index) => previews[index].split(" ").slice(0, 8).join(" ") || name.replace(/\.md$/, ""),
177
+ );
178
+ const abstract = normalizeProjectionPreview(
179
+ `${path.basename(dir)}/ — ${children.length} memories: ${titles.slice(0, 5).join(" · ")}`,
180
+ ABSTRACT_MAX_CHARS,
181
+ );
182
+
183
+ const lines = [
184
+ DIRECTORY_SIDECAR_MARKER,
185
+ `fingerprint: ${fingerprint}`,
186
+ `# ${path.basename(dir)}/ overview`,
187
+ "",
188
+ "## Abstract",
189
+ abstract,
190
+ "",
191
+ "## Children",
192
+ ];
193
+ for (const [index, name] of children.entries()) {
194
+ lines.push(`* ${name} — ${previews[index]}`);
195
+ }
196
+ for (const name of childDirs) {
197
+ lines.push(`### ${name}/`);
198
+ lines.push(childAbstracts.get(path.join(dir, name)) ?? "");
199
+ }
200
+ lines.push("");
201
+ return lines.join("\n");
202
+ }
203
+
204
+ /** Scope roots whose category subtrees carry sidecars: the memory root plus every namespace root. */
205
+ function scopeRoots(memoryDir: string): string[] {
206
+ const roots = [memoryDir];
207
+ const namespacesRoot = path.join(memoryDir, "namespaces");
208
+ for (const entry of listEntries(namespacesRoot)) {
209
+ if (entry.isDirectory() && isRealDirectory(path.join(namespacesRoot, entry.name))) {
210
+ roots.push(path.join(namespacesRoot, entry.name));
211
+ }
212
+ }
213
+ return roots;
214
+ }
215
+
216
+ /**
217
+ * Every directory that should carry a sidecar, deepest first (post-order) so
218
+ * parents render after their children and can embed child abstracts.
219
+ */
220
+ function collectSidecarDirs(scopeRoot: string): string[] {
221
+ const dirs: string[] = [];
222
+ const walk = (dir: string, isCategoryRoot: boolean): boolean => {
223
+ let carries = memoryChildren(dir).length > 0;
224
+ for (const name of directoryChildren(dir)) {
225
+ carries = walk(path.join(dir, name), false) || carries;
226
+ }
227
+ // A directory that stopped carrying memories must still be visited so its
228
+ // orphaned sidecar can be pruned or rewritten (cache-invalidation completeness).
229
+ const hasSidecar = readFileOrNull(sidecarPath(dir))?.startsWith(DIRECTORY_SIDECAR_MARKER) === true;
230
+ if (isCategoryRoot || carries || hasSidecar) dirs.push(dir);
231
+ return carries;
232
+ };
233
+ for (const category of RECALL_FALLBACK_DIRS) {
234
+ const categoryDir = path.join(scopeRoot, category);
235
+ if (!isRealDirectory(categoryDir)) continue;
236
+ walk(categoryDir, true);
237
+ }
238
+ return dirs;
239
+ }
240
+
241
+ /**
242
+ * Regenerate directory sidecars incrementally. Unchanged sidecars are left
243
+ * untouched; emptied directories lose theirs; user files at the sidecar path
244
+ * (no marker) are never written or removed. With `enabled: false` every
245
+ * generated sidecar is removed — the OKF index-maintenance contract.
246
+ */
247
+ export async function runDirectorySidecarMaintenance(
248
+ memoryDir: string,
249
+ enabled: boolean,
250
+ ): Promise<DirectorySidecarReport> {
251
+ const written: string[] = [];
252
+ const removed: string[] = [];
253
+ for (const scope of scopeRoots(memoryDir)) {
254
+ const childAbstracts = new Map<string, string>();
255
+ for (const dir of collectSidecarDirs(scope)) {
256
+ const target = sidecarPath(dir);
257
+ const raw = readFileOrNull(target);
258
+ const existing = raw !== null && raw.startsWith(DIRECTORY_SIDECAR_MARKER) ? raw : null;
259
+ if (!enabled) {
260
+ if (existing !== null) {
261
+ unlinkSync(target);
262
+ removed.push(target);
263
+ }
264
+ continue;
265
+ }
266
+ const next = renderSidecar(dir, directoryFingerprint(dir), childAbstracts);
267
+ if (next === null) {
268
+ if (existing !== null) {
269
+ unlinkSync(target);
270
+ removed.push(target);
271
+ }
272
+ continue;
273
+ }
274
+ const parsedNext = parseSidecar(next);
275
+ if (parsedNext) childAbstracts.set(dir, parsedNext.abstract);
276
+ if (raw === next) continue;
277
+ if (existing === null && raw !== null) continue; // user-authored file: hands off
278
+ await writeFileAtomically(target, next);
279
+ written.push(target);
280
+ }
281
+ }
282
+ return { written, removed };
283
+ }
284
+
285
+ /**
286
+ * Read a directory's sidecar for retrieval. By default a stale sidecar is
287
+ * refreshed in place (child directories first), which is what makes direct
288
+ * writes that bypass maintenance still converge. With `{ refresh: false }`
289
+ * the stored sidecar is returned as-is with `fresh: false` so callers can
290
+ * observe staleness without writes.
291
+ */
292
+ export async function loadDirectorySidecar(
293
+ dir: string,
294
+ options: { refresh?: boolean } = {},
295
+ ): Promise<DirectorySidecar | null> {
296
+ const refresh = options.refresh !== false;
297
+ const target = sidecarPath(dir);
298
+ const stored = readFileOrNull(target);
299
+ const generated = stored !== null && stored.startsWith(DIRECTORY_SIDECAR_MARKER);
300
+ const parsed = generated ? parseSidecar(stored) : null;
301
+ const fingerprint = directoryFingerprint(dir);
302
+ if (parsed !== null && (parsed.fingerprint === fingerprint || !refresh)) {
303
+ return {
304
+ dir,
305
+ abstract: parsed.abstract,
306
+ overview: parsed.overview,
307
+ childCount: parsed.childCount,
308
+ fresh: parsed.fingerprint === fingerprint,
309
+ };
310
+ }
311
+ if (!refresh) return null;
312
+
313
+ // Refresh bottom-up so this directory's body embeds current child abstracts.
314
+ const childAbstracts = new Map<string, string>();
315
+ for (const name of directoryChildren(dir)) {
316
+ const child = await loadDirectorySidecar(path.join(dir, name));
317
+ if (child) childAbstracts.set(path.join(dir, name), child.abstract);
318
+ }
319
+ const next = renderSidecar(dir, directoryFingerprint(dir), childAbstracts);
320
+ if (next === null) {
321
+ if (generated) unlinkSync(target);
322
+ return null;
323
+ }
324
+ if (readFileOrNull(target) !== next) {
325
+ if (stored !== null && !generated) {
326
+ // User-authored file at the sidecar path: serve nothing rather than clobber it.
327
+ return null;
328
+ }
329
+ await writeFileAtomically(target, next);
330
+ }
331
+ const refreshed = parseSidecar(next);
332
+ return refreshed
333
+ ? {
334
+ dir,
335
+ abstract: refreshed.abstract,
336
+ overview: refreshed.overview,
337
+ childCount: refreshed.childCount,
338
+ fresh: true,
339
+ }
340
+ : null;
341
+ }
342
+
343
+ /**
344
+ * Overview-query primitive for hierarchical retrieval (layer 1 of #2977):
345
+ * score every sidecar's abstract (+3 per query term) and overview (+1 per
346
+ * term) lexically, then return the most specific matches — when both a
347
+ * directory and its descendant match, only the descendant is kept, matching
348
+ * the drill-down semantics the full retrieval mode will build on.
349
+ */
350
+ export async function findDirectorySidecarsForQuery(
351
+ memoryDir: string,
352
+ query: string,
353
+ options: { namespace?: string; limit?: number } = {},
354
+ ): Promise<DirectorySidecarMatch[]> {
355
+ const scope = options.namespace ? path.join(memoryDir, "namespaces", options.namespace) : memoryDir;
356
+ if (!isRealDirectory(scope)) return [];
357
+ const terms = query
358
+ .toLowerCase()
359
+ .split(/[^a-z0-9]+/)
360
+ .filter((term) => term.length >= 2);
361
+
362
+ const matches: DirectorySidecarMatch[] = [];
363
+ for (const root of scopeRoots(scope)) {
364
+ for (const dir of collectSidecarDirs(root)) {
365
+ const sidecar = await loadDirectorySidecar(dir);
366
+ if (!sidecar) continue;
367
+ const abstractLower = sidecar.abstract.toLowerCase();
368
+ const overviewLower = sidecar.overview.toLowerCase();
369
+ let score = 0;
370
+ for (const term of terms) {
371
+ if (abstractLower.includes(term)) score += 3;
372
+ else if (overviewLower.includes(term)) score += 1;
373
+ }
374
+ if (score > 0) matches.push({ ...sidecar, score });
375
+ }
376
+ }
377
+ matches.sort((a, b) => b.score - a.score || a.dir.localeCompare(b.dir));
378
+
379
+ const limit = options.limit ?? DEFAULT_QUERY_LIMIT;
380
+ return matches
381
+ .filter((candidate) => !matches.some((other) => other.dir.startsWith(`${candidate.dir}${path.sep}`)))
382
+ .slice(0, limit);
383
+ }
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Session-end experience extraction config (issue #2979) — the
3
+ * `sessionExperience` block.
4
+ *
5
+ * Parsed like `recallNavigation`: shape-validated, fail-closed on unknown
6
+ * keys, no silent clamping. Defaults OFF (a machine-generated memory write
7
+ * from the completed session must be an explicit operator opt-in); the
8
+ * `conservative` preset pins `enabled: false`.
9
+ */
10
+
11
+ import { coerceBool } from "../connectors/coerce.js";
12
+
13
+ export interface SessionExperienceConfig {
14
+ /**
15
+ * Master switch for session-end Situation/Approach/Reflection episode
16
+ * extraction. Default false.
17
+ */
18
+ enabled: boolean;
19
+ }
20
+
21
+ export const SESSION_EXPERIENCE_CONFIG_DEFAULTS: SessionExperienceConfig = {
22
+ enabled: false,
23
+ };
24
+
25
+ function parseFlag(src: Record<string, unknown>, key: string, fallback: boolean): boolean {
26
+ const value = src[key];
27
+ if (value === undefined || value === null) return fallback;
28
+ const coerced = coerceBool(value);
29
+ if (coerced === undefined) {
30
+ throw new Error(
31
+ `sessionExperience.${key} must be a boolean (or "true"/"false"/"1"/"0"); got ${JSON.stringify(value)}`,
32
+ );
33
+ }
34
+ return coerced;
35
+ }
36
+
37
+ export function parseSessionExperienceConfig(raw: unknown): SessionExperienceConfig {
38
+ if (raw === undefined || raw === null) return { ...SESSION_EXPERIENCE_CONFIG_DEFAULTS };
39
+ if (typeof raw !== "object" || Array.isArray(raw)) {
40
+ throw new Error(`sessionExperience must be an object; got ${JSON.stringify(raw)}`);
41
+ }
42
+ const src = raw as Record<string, unknown>;
43
+ const { enabled: _enabled, ...unknown } = src;
44
+ const unknownKey = Object.keys(unknown)[0];
45
+ if (unknownKey !== undefined) {
46
+ throw new Error(`sessionExperience contains unknown key ${JSON.stringify(unknownKey)}`);
47
+ }
48
+ return {
49
+ enabled: parseFlag(src, "enabled", SESSION_EXPERIENCE_CONFIG_DEFAULTS.enabled),
50
+ };
51
+ }
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Session-end experience extraction through the real flush lifecycle
3
+ * (issue #2979): `flushSession(reason: "session_end")` drains the buffer
4
+ * and then derives at most one agent-experience episode; `before_reset`
5
+ * must not write one; gate off must write nothing anywhere.
6
+ */
7
+ import assert from "node:assert/strict";
8
+ import { readFile } from "node:fs/promises";
9
+ import test from "node:test";
10
+
11
+ import { Orchestrator } from "../orchestrator.js";
12
+ import {
13
+ cleanupDir,
14
+ makeHarmonicLifecycleConfig,
15
+ markdownFilesUnder,
16
+ mkTempMemoryDir,
17
+ singleFactResult,
18
+ stubExtraction,
19
+ } from "../testing/orchestrator-lite.js";
20
+
21
+ async function sessionEndMemories(memoryDir: string): Promise<string[]> {
22
+ const matches: string[] = [];
23
+ for (const file of await markdownFilesUnder(`${memoryDir}/procedures`)) {
24
+ if ((await readFile(file, "utf8")).includes("Reflection: ")) matches.push(file);
25
+ }
26
+ return matches;
27
+ }
28
+
29
+ async function withOrchestrator(
30
+ label: string,
31
+ overrides: Record<string, unknown>,
32
+ run: (orchestrator: Orchestrator, memoryDir: string) => Promise<void>,
33
+ ): Promise<void> {
34
+ const memoryDir = await mkTempMemoryDir(label);
35
+ let orchestrator: Orchestrator | undefined;
36
+ try {
37
+ orchestrator = new Orchestrator(makeHarmonicLifecycleConfig(memoryDir, overrides));
38
+ stubExtraction(orchestrator, (turns) => singleFactResult("The harmonic probe fact persists."));
39
+ await run(orchestrator, memoryDir);
40
+ } finally {
41
+ await orchestrator?.destroy().catch(() => undefined);
42
+ await cleanupDir(memoryDir);
43
+ }
44
+ }
45
+
46
+ const SESSION = "session-end-experience";
47
+
48
+ const SUCCESS_TURNS: Array<[role: "user" | "assistant", content: string]> = [
49
+ ["user", "Fix the flaky payments integration test that times out after thirty seconds."],
50
+ ["assistant", "I will reproduce the timeout and inspect the payments test setup."],
51
+ ["assistant", "Added the missing await to the setup call. Verified: the payments test passes now."],
52
+ ];
53
+
54
+ test("session_end flush writes exactly one pending_review agent-experience episode", async () => {
55
+ await withOrchestrator(
56
+ "sx-e2e-on",
57
+ { sessionExperience: { enabled: true } },
58
+ async (orchestrator, memoryDir) => {
59
+ for (const [role, content] of SUCCESS_TURNS) {
60
+ await orchestrator.processTurn(role, content, SESSION);
61
+ }
62
+ await orchestrator.flushSession(SESSION, { reason: "session_end" });
63
+ const experiences = await sessionEndMemories(memoryDir);
64
+ assert.equal(experiences.length, 1, "one session = at most one experience episode");
65
+ const body = await readFile(experiences[0], "utf8");
66
+ assert.match(body, /Situation: Fix the flaky payments integration test/);
67
+ assert.match(body, /Approach: /);
68
+ assert.match(body, /Reflection: /);
69
+ assert.match(body, /status: pending_review/);
70
+ assert.match(body, /subject: agent/);
71
+ assert.match(body, /category: procedure/);
72
+ assert.match(body, /experience_session_hash/);
73
+ // A second session_end drain sees an empty buffer and must not duplicate.
74
+ await orchestrator.flushSession(SESSION, { reason: "session_end" });
75
+ assert.equal((await sessionEndMemories(memoryDir)).length, 1, "replay must not duplicate");
76
+ },
77
+ );
78
+ });
79
+
80
+ test("a failed session_end records the failure reflection", async () => {
81
+ await withOrchestrator(
82
+ "sx-e2e-fail",
83
+ { sessionExperience: { enabled: true } },
84
+ async (orchestrator, memoryDir) => {
85
+ await orchestrator.processTurn(
86
+ "user",
87
+ "Migrate the billing export job to the new queue library before the release cut.",
88
+ SESSION,
89
+ );
90
+ await orchestrator.processTurn(
91
+ "assistant",
92
+ "The migration failed: the new queue library cannot serialize the billing payload format.",
93
+ SESSION,
94
+ );
95
+ await orchestrator.flushSession(SESSION, { reason: "session_end" });
96
+ const experiences = await sessionEndMemories(memoryDir);
97
+ assert.equal(experiences.length, 1);
98
+ const body = await readFile(experiences[0], "utf8");
99
+ assert.match(body, /experience_outcome: failure|experience_outcome=failure/);
100
+ assert.match(body, /fail/i);
101
+ },
102
+ );
103
+ });
104
+
105
+ test("gate off (default): a session_end flush writes no experience anywhere", async () => {
106
+ await withOrchestrator("sx-e2e-off", {}, async (orchestrator, memoryDir) => {
107
+ for (const [role, content] of SUCCESS_TURNS) {
108
+ await orchestrator.processTurn(role, content, SESSION);
109
+ }
110
+ await orchestrator.flushSession(SESSION, { reason: "session_end" });
111
+ assert.equal((await sessionEndMemories(memoryDir)).length, 0, "gate off must write nothing");
112
+ for (const file of await markdownFilesUnder(memoryDir)) {
113
+ const body = await readFile(file, "utf8");
114
+ assert.doesNotMatch(
115
+ body,
116
+ /Reflection: /,
117
+ `no experience body may appear anywhere while gated off (saw ${file})`,
118
+ );
119
+ }
120
+ });
121
+ });
122
+
123
+ test("before_reset drains the buffer but writes no experience episode", async () => {
124
+ await withOrchestrator(
125
+ "sx-e2e-reset",
126
+ { sessionExperience: { enabled: true } },
127
+ async (orchestrator, memoryDir) => {
128
+ for (const [role, content] of SUCCESS_TURNS) {
129
+ await orchestrator.processTurn(role, content, SESSION);
130
+ }
131
+ await orchestrator.flushSession(SESSION, { reason: "before_reset" });
132
+ assert.equal(
133
+ (await sessionEndMemories(memoryDir)).length,
134
+ 0,
135
+ "experiences are session_end-only in v1",
136
+ );
137
+ },
138
+ );
139
+ });