@remnic/core 9.7.8 → 9.7.10

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 (406) hide show
  1. package/dist/access-admin-ops-surface.d.ts +6 -6
  2. package/dist/access-admin-ops-surface.js +32 -30
  3. package/dist/access-audit.js +2 -2
  4. package/dist/access-boundary.d.ts +6 -6
  5. package/dist/access-boundary.js +33 -31
  6. package/dist/access-cli.js +92 -90
  7. package/dist/access-cli.js.map +1 -1
  8. package/dist/access-http.d.ts +6 -6
  9. package/dist/access-http.js +40 -38
  10. package/dist/access-identity-continuity-surface.d.ts +5 -5
  11. package/dist/access-identity-continuity-surface.js +32 -30
  12. package/dist/access-lcm-surface.d.ts +6 -6
  13. package/dist/access-lcm-surface.js +32 -30
  14. package/dist/access-mcp.d.ts +6 -6
  15. package/dist/access-mcp.js +37 -35
  16. package/dist/access-observe-write-surface.d.ts +6 -6
  17. package/dist/access-observe-write-surface.js +32 -30
  18. package/dist/access-operations-batch.js +35 -33
  19. package/dist/access-operations.d.ts +9 -9
  20. package/dist/access-operations.js +36 -34
  21. package/dist/access-recall-surface.d.ts +6 -6
  22. package/dist/access-recall-surface.js +32 -30
  23. package/dist/access-schema.d.ts +64 -64
  24. package/dist/{access-service-CxDZXTKt.d.ts → access-service-DSuzikHQ.d.ts} +4 -4
  25. package/dist/access-service.d.ts +6 -6
  26. package/dist/access-service.js +32 -30
  27. package/dist/access-surface-catalog.d.ts +6 -6
  28. package/dist/action-confidence.d.ts +1 -1
  29. package/dist/active-memory-bridge.d.ts +1 -1
  30. package/dist/active-recall.d.ts +1 -1
  31. package/dist/active-recall.js +1 -1
  32. package/dist/adapters/index.js +4 -4
  33. package/dist/adapters/registry.js +2 -2
  34. package/dist/{auto-sync-676N6N6Y.js → auto-sync-AAMTVZMK.js} +5 -5
  35. package/dist/behavior-learner.d.ts +1 -1
  36. package/dist/behavior-signals.d.ts +1 -1
  37. package/dist/bootstrap.d.ts +5 -5
  38. package/dist/briefing.d.ts +2 -2
  39. package/dist/briefing.js +15 -13
  40. package/dist/buffer-surprise-report.d.ts +1 -1
  41. package/dist/buffer.d.ts +2 -2
  42. package/dist/bulk-import/index.d.ts +3 -3
  43. package/dist/calibration.d.ts +1 -1
  44. package/dist/calibration.js +2 -2
  45. package/dist/capabilities.d.ts +1 -1
  46. package/dist/{capsule-merge-GK5E647P.js → capsule-merge-Z2HUO6IK.js} +10 -2
  47. package/dist/capsule-merge-Z2HUO6IK.js.map +1 -0
  48. package/dist/{catalog-DzU9HowE.d.ts → catalog-BNwjACa5.d.ts} +1 -1
  49. package/dist/causal-behavior.d.ts +1 -1
  50. package/dist/causal-consolidation.d.ts +1 -1
  51. package/dist/causal-consolidation.js +16 -14
  52. package/dist/causal-consolidation.js.map +1 -1
  53. package/dist/causal-trajectory-graph.d.ts +1 -1
  54. package/dist/{chunk-HHAA35A3.js → chunk-2VN4JAX7.js} +548 -161
  55. package/dist/chunk-2VN4JAX7.js.map +1 -0
  56. package/dist/{chunk-CNWC274T.js → chunk-3OQ4IZJN.js} +28 -28
  57. package/dist/{chunk-JO5AT6QT.js → chunk-3ZVFLMFQ.js} +1 -1
  58. package/dist/chunk-3ZVFLMFQ.js.map +1 -0
  59. package/dist/{chunk-7XH7VJN4.js → chunk-5S7Z5SHA.js} +2 -2
  60. package/dist/{chunk-WKE4VXSZ.js → chunk-673NPXE3.js} +2 -2
  61. package/dist/{chunk-Q6JPMCPO.js → chunk-7CKS4AXY.js} +63 -58
  62. package/dist/chunk-7CKS4AXY.js.map +1 -0
  63. package/dist/{chunk-UHGHTOR5.js → chunk-7EX4YOKH.js} +7 -7
  64. package/dist/{chunk-TVVEYCNW.js → chunk-7K5Q6COX.js} +4 -4
  65. package/dist/{chunk-EJCVMPIM.js → chunk-7LMEY5KZ.js} +15 -1
  66. package/dist/chunk-7LMEY5KZ.js.map +1 -0
  67. package/dist/{chunk-3F4N4WDH.js → chunk-AHLPZ2SF.js} +2 -2
  68. package/dist/{chunk-6C35R7P4.js → chunk-DJCKXI4M.js} +2 -2
  69. package/dist/{chunk-AD2KK5MT.js → chunk-DLWYAN6A.js} +9 -3
  70. package/dist/chunk-DLWYAN6A.js.map +1 -0
  71. package/dist/{chunk-TVRPRFUB.js → chunk-EQF5763Z.js} +9 -7
  72. package/dist/chunk-EQF5763Z.js.map +1 -0
  73. package/dist/{chunk-FYKIEOG6.js → chunk-FNJX2O6G.js} +3 -3
  74. package/dist/{chunk-DQPPRXFO.js → chunk-HQ7QZJM5.js} +2 -2
  75. package/dist/{chunk-RKNJBZ55.js → chunk-JBPKEARU.js} +4 -4
  76. package/dist/{chunk-KIPLG7S7.js → chunk-JKLJ6A7W.js} +2 -2
  77. package/dist/{chunk-O3BZ6PFY.js → chunk-JZM5QUTE.js} +2 -2
  78. package/dist/{chunk-KTOH7EJE.js → chunk-KXLRMM35.js} +312 -48
  79. package/dist/chunk-KXLRMM35.js.map +1 -0
  80. package/dist/{chunk-ZUFJ7ZTR.js → chunk-L4H6MQ7I.js} +6 -2
  81. package/dist/chunk-L4H6MQ7I.js.map +1 -0
  82. package/dist/{chunk-SYNYI4ZM.js → chunk-L5HJQC36.js} +2 -2
  83. package/dist/{chunk-VXMWDXIJ.js → chunk-LC7OODWZ.js} +2 -2
  84. package/dist/{chunk-ZW6OKHVX.js → chunk-LQKITFGB.js} +2 -2
  85. package/dist/{chunk-TZJVTH3F.js → chunk-MXRMNKSY.js} +14 -14
  86. package/dist/{chunk-GL3SMLMZ.js → chunk-N3LWQJ6Y.js} +150 -119
  87. package/dist/chunk-N3LWQJ6Y.js.map +1 -0
  88. package/dist/{chunk-M5QKGHCR.js → chunk-OC35KQIN.js} +6 -2
  89. package/dist/chunk-OC35KQIN.js.map +1 -0
  90. package/dist/chunk-OKUEZOGW.js +27 -0
  91. package/dist/chunk-OKUEZOGW.js.map +1 -0
  92. package/dist/{chunk-PKGWJFNR.js → chunk-OVMS3DCB.js} +2 -2
  93. package/dist/chunk-PDJTHRAW.js +36 -0
  94. package/dist/chunk-PDJTHRAW.js.map +1 -0
  95. package/dist/{chunk-LRGSLV7M.js → chunk-PYHOAXTI.js} +4 -4
  96. package/dist/{chunk-NMMKRVUF.js → chunk-QVALQE4P.js} +6 -6
  97. package/dist/{chunk-FXGC5UUH.js → chunk-RT7IP3D3.js} +2 -2
  98. package/dist/{chunk-AH3M6F4X.js → chunk-SBFDL2EQ.js} +2 -2
  99. package/dist/{chunk-UYZUJ4EB.js → chunk-SECMZACR.js} +2 -2
  100. package/dist/{chunk-HXDKC3BI.js → chunk-TGBJ2OMK.js} +2 -2
  101. package/dist/{chunk-DE6ENYLG.js → chunk-TXLGHDHS.js} +2 -2
  102. package/dist/{chunk-74MJH7I3.js → chunk-U4KHQTJ6.js} +12 -3
  103. package/dist/chunk-U4KHQTJ6.js.map +1 -0
  104. package/dist/{chunk-CRFTLUWT.js → chunk-UTDA43TB.js} +2 -2
  105. package/dist/{chunk-GKCCHHZK.js → chunk-UXKMMNJD.js} +4 -4
  106. package/dist/{chunk-57INMZ6F.js → chunk-UZRIKUFS.js} +2 -2
  107. package/dist/{chunk-2FSHROYK.js → chunk-V53GJUSL.js} +8 -8
  108. package/dist/{chunk-LKT755LP.js → chunk-VA4WSW54.js} +2 -2
  109. package/dist/{chunk-ZHKD4EZM.js → chunk-VCEH5UYS.js} +3 -3
  110. package/dist/{chunk-CHVU4RE5.js → chunk-VDLMAJXS.js} +3 -3
  111. package/dist/{chunk-XFTPUXCE.js → chunk-VRAD2FGO.js} +10 -10
  112. package/dist/{chunk-VF4XKTX3.js → chunk-VZ5OJE4X.js} +10 -2
  113. package/dist/chunk-VZ5OJE4X.js.map +1 -0
  114. package/dist/{chunk-UVIQHSS7.js → chunk-WUDBMLC6.js} +9 -3
  115. package/dist/chunk-WUDBMLC6.js.map +1 -0
  116. package/dist/{chunk-AWJ2FHCF.js → chunk-X47LWMKA.js} +49 -21
  117. package/dist/chunk-X47LWMKA.js.map +1 -0
  118. package/dist/{chunk-VMGMY2AI.js → chunk-XF4KOVDK.js} +8 -8
  119. package/dist/{chunk-VMGMY2AI.js.map → chunk-XF4KOVDK.js.map} +1 -1
  120. package/dist/{chunk-T7VNN3ZM.js → chunk-XVLEGMJI.js} +2 -2
  121. package/dist/{chunk-R2SJDIPO.js → chunk-YLTG6BO4.js} +9 -7
  122. package/dist/chunk-YLTG6BO4.js.map +1 -0
  123. package/dist/{chunk-QDCJNRKK.js → chunk-YXOAQAH2.js} +3 -3
  124. package/dist/{cli-BqyGVyOe.d.ts → cli-DACyuK8-.d.ts} +5 -5
  125. package/dist/cli.d.ts +8 -8
  126. package/dist/cli.js +66 -64
  127. package/dist/compounding/engine.d.ts +2 -2
  128. package/dist/compounding/engine.js +15 -13
  129. package/dist/compounding/preference-consolidator.d.ts +1 -1
  130. package/dist/compression-optimizer.d.ts +1 -1
  131. package/dist/config.d.ts +1 -1
  132. package/dist/config.js +1 -1
  133. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  134. package/dist/connectors/codex-materialize-runner.js +15 -13
  135. package/dist/connectors/codex-materialize.d.ts +1 -1
  136. package/dist/connectors/index.d.ts +1 -1
  137. package/dist/connectors/index.js +15 -13
  138. package/dist/consolidation-provenance-check.d.ts +2 -2
  139. package/dist/consolidation-provenance-check.js +6 -2
  140. package/dist/consolidation-undo.d.ts +2 -2
  141. package/dist/consolidation-undo.js +8 -1
  142. package/dist/consolidation-undo.js.map +1 -1
  143. package/dist/contradiction/index.d.ts +2 -2
  144. package/dist/conversation-index/backend.d.ts +1 -1
  145. package/dist/conversation-index/chunker.d.ts +1 -1
  146. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  147. package/dist/conversation-index/indexer.d.ts +1 -1
  148. package/dist/conversation-index/search.d.ts +1 -1
  149. package/dist/day-summary.d.ts +1 -1
  150. package/dist/delinearize.d.ts +1 -1
  151. package/dist/direct-answer-wiring.d.ts +1 -1
  152. package/dist/direct-answer.d.ts +1 -1
  153. package/dist/embedding-fallback.d.ts +1 -1
  154. package/dist/enrichment/index.d.ts +1 -1
  155. package/dist/entity-retrieval.d.ts +2 -2
  156. package/dist/entity-retrieval.js +15 -13
  157. package/dist/entity-schema.d.ts +1 -1
  158. package/dist/explicit-capture.d.ts +5 -5
  159. package/dist/extraction-faithfulness.d.ts +1 -1
  160. package/dist/extraction-faithfulness.js +3 -3
  161. package/dist/extraction-judge-telemetry.d.ts +1 -1
  162. package/dist/extraction-judge-training.d.ts +1 -1
  163. package/dist/extraction-judge.d.ts +1 -1
  164. package/dist/extraction-judge.js +3 -3
  165. package/dist/extraction.d.ts +1 -1
  166. package/dist/extraction.js +3 -3
  167. package/dist/fallback-llm.d.ts +1 -1
  168. package/dist/fallback-llm.js +2 -2
  169. package/dist/{forget-KHF7A44H.js → forget-CQCLB5LB.js} +2 -2
  170. package/dist/graph-dashboard-diff.d.ts +1 -1
  171. package/dist/graph-dashboard-key.d.ts +1 -1
  172. package/dist/graph-dashboard-parser.d.ts +1 -1
  173. package/dist/graph-edge-reinforcement.d.ts +1 -1
  174. package/dist/graph-snapshot.d.ts +1 -1
  175. package/dist/graph.d.ts +1 -1
  176. package/dist/identity-continuity.d.ts +1 -1
  177. package/dist/importance.d.ts +1 -1
  178. package/dist/importers/index.d.ts +1 -1
  179. package/dist/in-flight-reads.d.ts +19 -0
  180. package/dist/in-flight-reads.js +16 -0
  181. package/dist/in-flight-reads.js.map +1 -0
  182. package/dist/index.d.ts +13 -13
  183. package/dist/index.js +116 -114
  184. package/dist/intent.d.ts +1 -1
  185. package/dist/lcm/engine.d.ts +1 -1
  186. package/dist/lcm/engine.js +4 -4
  187. package/dist/lcm/index.d.ts +1 -1
  188. package/dist/lcm/index.js +13 -13
  189. package/dist/lcm/tools.d.ts +1 -1
  190. package/dist/lifecycle.d.ts +1 -1
  191. package/dist/live-connectors-runner.d.ts +1 -1
  192. package/dist/local-llm.d.ts +1 -1
  193. package/dist/local-model-endpoint.d.ts +1 -1
  194. package/dist/maintenance/memory-governance.d.ts +1 -1
  195. package/dist/maintenance/memory-governance.js +15 -13
  196. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +15 -13
  197. package/dist/maintenance/rebuild-memory-projection.js +16 -14
  198. package/dist/mcp-memory-inspector-app.d.ts +6 -6
  199. package/dist/memory-action-policy.d.ts +1 -1
  200. package/dist/memory-cache.d.ts +24 -13
  201. package/dist/memory-cache.js +3 -1
  202. package/dist/memory-corpus-version.d.ts +19 -0
  203. package/dist/memory-corpus-version.js +13 -0
  204. package/dist/memory-corpus-version.js.map +1 -0
  205. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  206. package/dist/memory-projection-store.d.ts +1 -1
  207. package/dist/memory-provenance.d.ts +1 -1
  208. package/dist/memory-worth-outcomes.d.ts +2 -2
  209. package/dist/models-json.d.ts +1 -1
  210. package/dist/namespaces/migrate.d.ts +3 -3
  211. package/dist/namespaces/migrate.js +22 -20
  212. package/dist/namespaces/principal.d.ts +1 -1
  213. package/dist/namespaces/search.d.ts +1 -1
  214. package/dist/namespaces/search.js +7 -7
  215. package/dist/namespaces/storage.d.ts +3 -3
  216. package/dist/namespaces/storage.js +15 -13
  217. package/dist/native-knowledge.d.ts +1 -1
  218. package/dist/operator-toolkit.d.ts +2 -2
  219. package/dist/operator-toolkit.js +27 -25
  220. package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
  221. package/dist/orchestration/maintenance.d.ts +2 -2
  222. package/dist/orchestration/maintenance.js +17 -15
  223. package/dist/{orchestrator-37Cx7yyw.d.ts → orchestrator-D83AvrPf.d.ts} +4 -4
  224. package/dist/orchestrator.d.ts +5 -5
  225. package/dist/orchestrator.js +92 -90
  226. package/dist/page-versioning.js +5 -1
  227. package/dist/patterns-cli.d.ts +1 -1
  228. package/dist/{pipeline-C6onljHc.d.ts → pipeline-BSqGpYl1.d.ts} +1 -1
  229. package/dist/policy-runtime.d.ts +1 -1
  230. package/dist/provenance.d.ts +1 -1
  231. package/dist/{qmd-J08G7MEm.d.ts → qmd-CutnpRVe.d.ts} +1 -1
  232. package/dist/qmd-preflight.d.ts +2 -2
  233. package/dist/qmd-recall-cache.d.ts +1 -1
  234. package/dist/qmd.d.ts +2 -2
  235. package/dist/qmd.js +2 -2
  236. package/dist/recall-disclosure-escalation.d.ts +1 -1
  237. package/dist/recall-explain-renderer.d.ts +1 -1
  238. package/dist/recall-explain-renderer.js +3 -3
  239. package/dist/recall-planner-llm.d.ts +1 -1
  240. package/dist/recall-planner-llm.js +2 -2
  241. package/dist/recall-state.d.ts +1 -1
  242. package/dist/recall-tag-filter.d.ts +1 -1
  243. package/dist/recall-timings.d.ts +1 -1
  244. package/dist/recall-xray-cli.d.ts +1 -1
  245. package/dist/recall-xray-cli.js +4 -4
  246. package/dist/recall-xray-renderer.d.ts +1 -1
  247. package/dist/recall-xray-renderer.js +3 -3
  248. package/dist/recall-xray.d.ts +1 -1
  249. package/dist/recall-xray.js +2 -2
  250. package/dist/replay/normalizers/chatgpt.d.ts +1 -1
  251. package/dist/replay/normalizers/claude.d.ts +1 -1
  252. package/dist/replay/normalizers/openclaw.d.ts +1 -1
  253. package/dist/replay/normalizers/shared.d.ts +1 -1
  254. package/dist/replay/runner.d.ts +1 -1
  255. package/dist/replay/types.d.ts +1 -1
  256. package/dist/resolve-auth-token.d.ts +1 -1
  257. package/dist/resume-bundles.js +2 -2
  258. package/dist/retrieval-agents.d.ts +2 -2
  259. package/dist/retrieval-agents.js +2 -2
  260. package/dist/retrieval-tiers.d.ts +1 -1
  261. package/dist/routing/engine.d.ts +1 -1
  262. package/dist/routing/store.d.ts +1 -1
  263. package/dist/schemas.d.ts +52 -52
  264. package/dist/search/embed-helper.d.ts +1 -1
  265. package/dist/search/factory.d.ts +1 -1
  266. package/dist/search/factory.js +6 -6
  267. package/dist/search/index.d.ts +1 -1
  268. package/dist/search/index.js +12 -12
  269. package/dist/search/lancedb-backend.d.ts +1 -1
  270. package/dist/search/meilisearch-backend.d.ts +1 -1
  271. package/dist/search/noop-backend.d.ts +1 -1
  272. package/dist/search/orama-backend.d.ts +1 -1
  273. package/dist/search/port.d.ts +1 -1
  274. package/dist/search/remote-backend.d.ts +1 -1
  275. package/dist/{semantic-consolidation-BFtoVosl.d.ts → semantic-consolidation-btIVRC4l.d.ts} +1 -1
  276. package/dist/semantic-consolidation.d.ts +2 -2
  277. package/dist/semantic-consolidation.js +16 -14
  278. package/dist/semantic-rule-promotion.js +15 -13
  279. package/dist/semantic-rule-verifier.d.ts +5 -1
  280. package/dist/semantic-rule-verifier.js +15 -13
  281. package/dist/session-observer-bands.d.ts +1 -1
  282. package/dist/session-observer-state.d.ts +1 -1
  283. package/dist/shared-context/manager.d.ts +9 -9
  284. package/dist/signal.d.ts +1 -1
  285. package/dist/{storage-CXjwBr69.d.ts → storage-BVv_Mqa0.d.ts} +133 -3
  286. package/dist/storage.d.ts +2 -2
  287. package/dist/storage.js +14 -12
  288. package/dist/summarizer.d.ts +1 -1
  289. package/dist/summarizer.js +3 -3
  290. package/dist/summary-snapshot.d.ts +1 -1
  291. package/dist/temporal-index-compat.d.ts +1 -0
  292. package/dist/temporal-index-compat.js +16 -0
  293. package/dist/temporal-index-compat.js.map +1 -0
  294. package/dist/temporal-index.d.ts +58 -7
  295. package/dist/temporal-index.js +23 -3
  296. package/dist/temporal-supersession.d.ts +2 -2
  297. package/dist/temporal-timeline-recall.d.ts +1 -1
  298. package/dist/temporal-validity.d.ts +1 -1
  299. package/dist/threading.d.ts +1 -1
  300. package/dist/tier-migration.d.ts +2 -2
  301. package/dist/tier-routing.d.ts +1 -1
  302. package/dist/topics.d.ts +1 -1
  303. package/dist/transcript.d.ts +1 -1
  304. package/dist/transfer/capsule-import.js +6 -2
  305. package/dist/transfer/import-sqlite.js +2 -2
  306. package/dist/transfer/types.d.ts +66 -66
  307. package/dist/trust-score-stage.d.ts +1 -1
  308. package/dist/trust-score.d.ts +1 -1
  309. package/dist/{types-DpxqC8dI.d.ts → types-Cmkz7csa.d.ts} +27 -0
  310. package/dist/types.d.ts +1 -1
  311. package/dist/types.js +1 -1
  312. package/dist/utility-runtime.d.ts +1 -1
  313. package/dist/verified-recall.d.ts +4 -0
  314. package/dist/verified-recall.js +15 -13
  315. package/package.json +12 -2
  316. package/src/binary-lifecycle/pipeline.ts +22 -0
  317. package/src/cli.ts +8 -0
  318. package/src/compounding/engine.ts +9 -1
  319. package/src/config.ts +14 -0
  320. package/src/consolidation-undo.ts +8 -0
  321. package/src/curation/index.ts +9 -0
  322. package/src/in-flight-reads.ts +63 -0
  323. package/src/maintenance/memory-governance.ts +6 -0
  324. package/src/memory-cache-hot.test.ts +131 -0
  325. package/src/memory-cache.ts +146 -22
  326. package/src/memory-corpus-version.ts +45 -0
  327. package/src/namespaces/storage.ts +20 -1
  328. package/src/operator-toolkit.ts +7 -1
  329. package/src/orchestration/consolidation-run.ts +5 -5
  330. package/src/orchestration/contradiction-linking-coordinator.ts +2 -2
  331. package/src/orchestration/lifecycle-policy-coordinator.ts +2 -2
  332. package/src/orchestration/persistence-index.ts +6 -6
  333. package/src/orchestration/recall-internal.ts +6 -3
  334. package/src/orchestration/recall-search-pipeline.ts +36 -21
  335. package/src/orchestration/semantic-consolidation-coordinator.ts +2 -2
  336. package/src/orchestrator.ts +25 -5
  337. package/src/page-versioning.ts +14 -1
  338. package/src/provenance-frontmatter.test.ts +6 -0
  339. package/src/review/index.ts +16 -8
  340. package/src/semantic-rule-promotion.ts +9 -1
  341. package/src/semantic-rule-verifier.ts +19 -6
  342. package/src/spaces/index.ts +10 -0
  343. package/src/storage/memory-read-store.ts +9 -2
  344. package/src/storage-contract/cache-coherence.test.ts +242 -0
  345. package/src/storage-contract/namespace-routing.test.ts +26 -1
  346. package/src/storage.ts +513 -31
  347. package/src/temporal-index-compat.ts +311 -0
  348. package/src/temporal-index.test.ts +273 -22
  349. package/src/temporal-index.ts +427 -178
  350. package/src/transfer/capsule-cache-coherence.test.ts +107 -0
  351. package/src/transfer/capsule-import.ts +8 -0
  352. package/src/transfer/capsule-merge.ts +7 -0
  353. package/src/types.ts +27 -0
  354. package/src/verified-recall.ts +20 -6
  355. package/dist/capsule-merge-GK5E647P.js.map +0 -1
  356. package/dist/chunk-74MJH7I3.js.map +0 -1
  357. package/dist/chunk-AD2KK5MT.js.map +0 -1
  358. package/dist/chunk-AWJ2FHCF.js.map +0 -1
  359. package/dist/chunk-EJCVMPIM.js.map +0 -1
  360. package/dist/chunk-GL3SMLMZ.js.map +0 -1
  361. package/dist/chunk-HHAA35A3.js.map +0 -1
  362. package/dist/chunk-JO5AT6QT.js.map +0 -1
  363. package/dist/chunk-KTOH7EJE.js.map +0 -1
  364. package/dist/chunk-M5QKGHCR.js.map +0 -1
  365. package/dist/chunk-Q6JPMCPO.js.map +0 -1
  366. package/dist/chunk-R2SJDIPO.js.map +0 -1
  367. package/dist/chunk-TVRPRFUB.js.map +0 -1
  368. package/dist/chunk-UVIQHSS7.js.map +0 -1
  369. package/dist/chunk-VF4XKTX3.js.map +0 -1
  370. package/dist/chunk-ZUFJ7ZTR.js.map +0 -1
  371. /package/dist/{auto-sync-676N6N6Y.js.map → auto-sync-AAMTVZMK.js.map} +0 -0
  372. /package/dist/{chunk-CNWC274T.js.map → chunk-3OQ4IZJN.js.map} +0 -0
  373. /package/dist/{chunk-7XH7VJN4.js.map → chunk-5S7Z5SHA.js.map} +0 -0
  374. /package/dist/{chunk-WKE4VXSZ.js.map → chunk-673NPXE3.js.map} +0 -0
  375. /package/dist/{chunk-UHGHTOR5.js.map → chunk-7EX4YOKH.js.map} +0 -0
  376. /package/dist/{chunk-TVVEYCNW.js.map → chunk-7K5Q6COX.js.map} +0 -0
  377. /package/dist/{chunk-3F4N4WDH.js.map → chunk-AHLPZ2SF.js.map} +0 -0
  378. /package/dist/{chunk-6C35R7P4.js.map → chunk-DJCKXI4M.js.map} +0 -0
  379. /package/dist/{chunk-FYKIEOG6.js.map → chunk-FNJX2O6G.js.map} +0 -0
  380. /package/dist/{chunk-DQPPRXFO.js.map → chunk-HQ7QZJM5.js.map} +0 -0
  381. /package/dist/{chunk-RKNJBZ55.js.map → chunk-JBPKEARU.js.map} +0 -0
  382. /package/dist/{chunk-KIPLG7S7.js.map → chunk-JKLJ6A7W.js.map} +0 -0
  383. /package/dist/{chunk-O3BZ6PFY.js.map → chunk-JZM5QUTE.js.map} +0 -0
  384. /package/dist/{chunk-SYNYI4ZM.js.map → chunk-L5HJQC36.js.map} +0 -0
  385. /package/dist/{chunk-VXMWDXIJ.js.map → chunk-LC7OODWZ.js.map} +0 -0
  386. /package/dist/{chunk-ZW6OKHVX.js.map → chunk-LQKITFGB.js.map} +0 -0
  387. /package/dist/{chunk-TZJVTH3F.js.map → chunk-MXRMNKSY.js.map} +0 -0
  388. /package/dist/{chunk-PKGWJFNR.js.map → chunk-OVMS3DCB.js.map} +0 -0
  389. /package/dist/{chunk-LRGSLV7M.js.map → chunk-PYHOAXTI.js.map} +0 -0
  390. /package/dist/{chunk-NMMKRVUF.js.map → chunk-QVALQE4P.js.map} +0 -0
  391. /package/dist/{chunk-FXGC5UUH.js.map → chunk-RT7IP3D3.js.map} +0 -0
  392. /package/dist/{chunk-AH3M6F4X.js.map → chunk-SBFDL2EQ.js.map} +0 -0
  393. /package/dist/{chunk-UYZUJ4EB.js.map → chunk-SECMZACR.js.map} +0 -0
  394. /package/dist/{chunk-HXDKC3BI.js.map → chunk-TGBJ2OMK.js.map} +0 -0
  395. /package/dist/{chunk-DE6ENYLG.js.map → chunk-TXLGHDHS.js.map} +0 -0
  396. /package/dist/{chunk-CRFTLUWT.js.map → chunk-UTDA43TB.js.map} +0 -0
  397. /package/dist/{chunk-GKCCHHZK.js.map → chunk-UXKMMNJD.js.map} +0 -0
  398. /package/dist/{chunk-57INMZ6F.js.map → chunk-UZRIKUFS.js.map} +0 -0
  399. /package/dist/{chunk-2FSHROYK.js.map → chunk-V53GJUSL.js.map} +0 -0
  400. /package/dist/{chunk-LKT755LP.js.map → chunk-VA4WSW54.js.map} +0 -0
  401. /package/dist/{chunk-ZHKD4EZM.js.map → chunk-VCEH5UYS.js.map} +0 -0
  402. /package/dist/{chunk-CHVU4RE5.js.map → chunk-VDLMAJXS.js.map} +0 -0
  403. /package/dist/{chunk-XFTPUXCE.js.map → chunk-VRAD2FGO.js.map} +0 -0
  404. /package/dist/{chunk-T7VNN3ZM.js.map → chunk-XVLEGMJI.js.map} +0 -0
  405. /package/dist/{chunk-QDCJNRKK.js.map → chunk-YXOAQAH2.js.map} +0 -0
  406. /package/dist/{forget-KHF7A44H.js.map → forget-CQCLB5LB.js.map} +0 -0
@@ -1,8 +1,17 @@
1
- // src/temporal-index.ts
1
+ // src/temporal-index-compat.ts
2
2
  import { execFileSync } from "child_process";
3
+ import * as crypto2 from "crypto";
4
+ import * as fs2 from "fs";
5
+ import * as path2 from "path";
6
+
7
+ // src/temporal-index.ts
8
+ import { execFile } from "child_process";
3
9
  import * as crypto from "crypto";
4
10
  import * as fs from "fs";
5
11
  import * as path from "path";
12
+ import { setTimeout as delay } from "timers/promises";
13
+ import { promisify } from "util";
14
+ var execFileAsync = promisify(execFile);
6
15
  var INDEX_VERSION = 2;
7
16
  var TEMPORAL_INDEX_FILE = "index_time.json";
8
17
  var TAG_INDEX_FILE = "index_tags.json";
@@ -10,8 +19,14 @@ var TAG_INDEX_VERSION = 2;
10
19
  var INDEX_LOCK_STALE_MS = 6e4;
11
20
  var INDEX_LOCK_POLL_MS = 10;
12
21
  var INDEX_PROCESS_START_TOLERANCE_MS = 2e3;
13
- var INDEX_LOCK_SLEEP = new Int32Array(new SharedArrayBuffer(4));
14
22
  var INDEX_PROCESS_STARTED_AT_MS = Date.now() - process.uptime() * 1e3;
23
+ var parsedIndexCache = /* @__PURE__ */ new Map();
24
+ var writeChains = /* @__PURE__ */ new Map();
25
+ var opChains = /* @__PURE__ */ new Map();
26
+ var indexReadObserverForTest;
27
+ function setIndexReadObserverForTest(observer) {
28
+ indexReadObserverForTest = observer;
29
+ }
15
30
  function stateDir(memoryDir) {
16
31
  return path.join(memoryDir, "state");
17
32
  }
@@ -21,20 +36,73 @@ function temporalIndexPath(memoryDir) {
21
36
  function tagIndexPath(memoryDir) {
22
37
  return path.join(stateDir(memoryDir), TAG_INDEX_FILE);
23
38
  }
24
- function ensureStateDir(memoryDir) {
25
- const dir = stateDir(memoryDir);
26
- fs.mkdirSync(dir, { recursive: true });
39
+ async function ensureStateDir(memoryDir) {
40
+ await fs.promises.mkdir(stateDir(memoryDir), { recursive: true });
41
+ }
42
+ function identityFromStat(stat) {
43
+ return {
44
+ size: stat.size,
45
+ mtimeMs: stat.mtimeMs,
46
+ ctimeMs: stat.ctimeMs,
47
+ ino: stat.ino
48
+ };
49
+ }
50
+ function identityEquals(left, right) {
51
+ return left.size === right.size && left.mtimeMs === right.mtimeMs && left.ctimeMs === right.ctimeMs && left.ino === right.ino;
27
52
  }
28
- function readJsonSafe(filePath, fallback) {
53
+ async function loadIndexCached(filePath, normalize, hasCurrentSchema) {
54
+ let handle;
29
55
  try {
30
- const raw = fs.readFileSync(filePath, "utf8");
31
- return JSON.parse(raw);
56
+ handle = await fs.promises.open(filePath, "r");
57
+ } catch (error) {
58
+ return error?.code === "ENOENT" ? { kind: "missing" } : { kind: "invalid" };
59
+ }
60
+ try {
61
+ const identity = identityFromStat(await handle.stat());
62
+ const cached = parsedIndexCache.get(filePath);
63
+ if (cached && identityEquals(cached.identity, identity)) {
64
+ return { kind: "ok", index: cached.index, currentSchema: cached.currentSchema };
65
+ }
66
+ indexReadObserverForTest?.();
67
+ const parsed = JSON.parse(await handle.readFile("utf8"));
68
+ const index = normalize(parsed);
69
+ const currentSchema = hasCurrentSchema(parsed);
70
+ parsedIndexCache.set(filePath, { identity, index, currentSchema });
71
+ return { kind: "ok", index, currentSchema };
32
72
  } catch {
33
- return fallback;
73
+ parsedIndexCache.delete(filePath);
74
+ return { kind: "invalid" };
75
+ } finally {
76
+ await handle.close().catch(() => void 0);
34
77
  }
35
78
  }
36
- function sleepSync(ms) {
37
- Atomics.wait(INDEX_LOCK_SLEEP, 0, 0, ms);
79
+ function withPathMutex(filePath, update) {
80
+ const previous = writeChains.get(filePath) ?? Promise.resolve();
81
+ const run = previous.then(update, update);
82
+ const tail = run.then(() => void 0, () => void 0);
83
+ writeChains.set(filePath, tail);
84
+ void tail.then(() => {
85
+ if (writeChains.get(filePath) === tail) writeChains.delete(filePath);
86
+ });
87
+ return run;
88
+ }
89
+ function withMemoryDirMutex(memoryDir, op) {
90
+ const previous = opChains.get(memoryDir) ?? Promise.resolve();
91
+ const run = previous.then(op, op);
92
+ const tail = run.then(() => void 0, () => void 0);
93
+ opChains.set(memoryDir, tail);
94
+ void tail.then(() => {
95
+ if (opChains.get(memoryDir) === tail) opChains.delete(memoryDir);
96
+ });
97
+ return run;
98
+ }
99
+ async function primeCacheAfterWrite(filePath, index, isCurrentSchema) {
100
+ try {
101
+ const identity = identityFromStat(await fs.promises.stat(filePath));
102
+ parsedIndexCache.set(filePath, { identity, index, currentSchema: isCurrentSchema() });
103
+ } catch {
104
+ parsedIndexCache.delete(filePath);
105
+ }
38
106
  }
39
107
  function uniqueTempPath(filePath) {
40
108
  const dir = path.dirname(filePath);
@@ -45,9 +113,9 @@ function uniqueTempPath(filePath) {
45
113
  function lockOwnerPath(lockDir) {
46
114
  return path.join(lockDir, "owner.json");
47
115
  }
48
- function writeIndexLockOwner(lockDir) {
116
+ async function writeIndexLockOwner(lockDir) {
49
117
  try {
50
- fs.writeFileSync(
118
+ await fs.promises.writeFile(
51
119
  lockOwnerPath(lockDir),
52
120
  JSON.stringify({
53
121
  pid: process.pid,
@@ -62,9 +130,9 @@ function writeIndexLockOwner(lockDir) {
62
130
  } catch {
63
131
  }
64
132
  }
65
- function readIndexLockOwner(lockDir) {
133
+ async function readIndexLockOwner(lockDir) {
66
134
  try {
67
- const parsed = JSON.parse(fs.readFileSync(lockOwnerPath(lockDir), "utf8"));
135
+ const parsed = JSON.parse(await fs.promises.readFile(lockOwnerPath(lockDir), "utf8"));
68
136
  if (!(typeof parsed.pid === "number" && Number.isInteger(parsed.pid) && parsed.pid > 0)) return null;
69
137
  const owner = { pid: parsed.pid };
70
138
  if ("createdAt" in parsed && typeof parsed.createdAt === "string" && parsed.createdAt.length > 0) {
@@ -88,13 +156,13 @@ function processIsAlive(pid) {
88
156
  return code === "EPERM";
89
157
  }
90
158
  }
91
- function readProcessStartedAtMs(pid) {
159
+ async function readProcessStartedAtMs(pid) {
92
160
  try {
93
- const output = execFileSync("ps", ["-p", String(pid), "-o", "lstart="], {
161
+ const { stdout } = await execFileAsync("ps", ["-p", String(pid), "-o", "lstart="], {
94
162
  encoding: "utf8",
95
- stdio: ["ignore", "pipe", "ignore"],
96
163
  timeout: 1e3
97
- }).trim();
164
+ });
165
+ const output = stdout.trim();
98
166
  if (!output) return null;
99
167
  const startedAtMs = Date.parse(output);
100
168
  return Number.isFinite(startedAtMs) ? startedAtMs : null;
@@ -102,10 +170,10 @@ function readProcessStartedAtMs(pid) {
102
170
  return null;
103
171
  }
104
172
  }
105
- function lockOwnerIsRunning(owner) {
173
+ async function lockOwnerIsRunning(owner) {
106
174
  if (!processIsAlive(owner.pid)) return false;
107
175
  if (owner.processStartedAtMs === void 0) return true;
108
- const runningStartedAtMs = readProcessStartedAtMs(owner.pid);
176
+ const runningStartedAtMs = await readProcessStartedAtMs(owner.pid);
109
177
  if (runningStartedAtMs === null) return true;
110
178
  return runningStartedAtMs <= owner.processStartedAtMs + INDEX_PROCESS_START_TOLERANCE_MS;
111
179
  }
@@ -114,76 +182,79 @@ function lockIsFresh(lockInfo, owner) {
114
182
  const referenceMs = Number.isFinite(ownerCreatedAtMs) ? ownerCreatedAtMs : lockInfo.mtimeMs;
115
183
  return Date.now() - referenceMs < INDEX_LOCK_STALE_MS;
116
184
  }
117
- function removeAbandonedIndexLock(lockDir) {
185
+ async function removeAbandonedIndexLock(lockDir) {
118
186
  try {
119
- const info = fs.lstatSync(lockDir);
187
+ const info = await fs.promises.lstat(lockDir);
120
188
  if (info.isSymbolicLink()) return "blocked";
121
189
  if (!info.isDirectory()) {
122
- fs.rmSync(lockDir, { force: true });
190
+ await fs.promises.rm(lockDir, { force: true });
123
191
  return "removed";
124
192
  }
125
- const owner = readIndexLockOwner(lockDir);
193
+ const owner = await readIndexLockOwner(lockDir);
126
194
  if (owner !== null) {
127
- if (lockOwnerIsRunning(owner)) return "wait";
195
+ if (await lockOwnerIsRunning(owner)) return "wait";
128
196
  }
129
197
  if (owner === null && lockIsFresh(info, null)) return "wait";
130
- fs.rmSync(lockDir, { recursive: true, force: true });
198
+ await fs.promises.rm(lockDir, { recursive: true, force: true });
131
199
  return "removed";
132
200
  } catch (error) {
133
201
  if (error?.code === "ENOENT") return "removed";
134
202
  return "blocked";
135
203
  }
136
204
  }
137
- function withIndexFileLock(filePath, update) {
205
+ async function withIndexFileLock(filePath, update) {
138
206
  const lockDir = `${filePath}.lock.d`;
139
207
  let acquired = false;
140
208
  while (!acquired) {
141
209
  try {
142
- fs.mkdirSync(lockDir);
143
- writeIndexLockOwner(lockDir);
210
+ await fs.promises.mkdir(lockDir);
211
+ await writeIndexLockOwner(lockDir);
144
212
  acquired = true;
145
213
  } catch (error) {
146
214
  const code = error?.code;
147
215
  if (code === "ENOENT") {
148
216
  try {
149
- fs.mkdirSync(path.dirname(lockDir), { recursive: true });
217
+ await fs.promises.mkdir(path.dirname(lockDir), { recursive: true });
150
218
  } catch {
151
- return;
219
+ return void 0;
152
220
  }
153
- sleepSync(INDEX_LOCK_POLL_MS);
221
+ await delay(INDEX_LOCK_POLL_MS);
154
222
  continue;
155
223
  }
156
- if (code !== "EEXIST") return;
157
- const cleanupResult = removeAbandonedIndexLock(lockDir);
158
- if (cleanupResult === "blocked") return;
159
- sleepSync(INDEX_LOCK_POLL_MS);
224
+ if (code !== "EEXIST") return void 0;
225
+ const cleanupResult = await removeAbandonedIndexLock(lockDir);
226
+ if (cleanupResult === "blocked") return void 0;
227
+ await delay(INDEX_LOCK_POLL_MS);
160
228
  }
161
229
  }
230
+ let result;
162
231
  try {
163
- update();
232
+ result = await update();
164
233
  } finally {
165
234
  try {
166
- fs.rmSync(lockDir, { recursive: true, force: true });
235
+ await fs.promises.rm(lockDir, { recursive: true, force: true });
167
236
  } catch {
168
237
  }
169
238
  }
239
+ return result;
170
240
  }
171
- function writeJsonAtomic(filePath, data) {
172
- const payload = JSON.stringify(data, null, 2);
241
+ async function writeJsonAtomic(filePath, data) {
242
+ const payload = JSON.stringify(data);
173
243
  for (let attempt = 0; attempt < 3; attempt += 1) {
174
244
  const tmp = uniqueTempPath(filePath);
175
245
  try {
176
- fs.writeFileSync(tmp, payload, "utf8");
177
- fs.renameSync(tmp, filePath);
178
- return;
246
+ await fs.promises.writeFile(tmp, payload, "utf8");
247
+ await fs.promises.rename(tmp, filePath);
248
+ return true;
179
249
  } catch {
180
250
  try {
181
- fs.unlinkSync(tmp);
251
+ await fs.promises.unlink(tmp);
182
252
  } catch {
183
253
  }
184
- sleepSync(INDEX_LOCK_POLL_MS);
254
+ await delay(INDEX_LOCK_POLL_MS);
185
255
  }
186
256
  }
257
+ return false;
187
258
  }
188
259
  function emptyTemporalIndex() {
189
260
  return { version: INDEX_VERSION, dates: {}, events: {} };
@@ -200,22 +271,49 @@ function normalizeTemporalIndex(raw) {
200
271
  ...typeof raw.lastRebuildAt === "string" ? { lastRebuildAt: raw.lastRebuildAt } : {}
201
272
  };
202
273
  }
203
- function updateTemporalIndex(memoryDir, update) {
274
+ function hasCurrentTemporalIndexSchema(raw) {
275
+ return isRecord(raw) && raw.version === INDEX_VERSION && isRecord(raw.dates) && isRecord(raw.events);
276
+ }
277
+ async function updateTemporalIndex(memoryDir, update) {
204
278
  const indexPath = temporalIndexPath(memoryDir);
205
- withIndexFileLock(indexPath, () => {
206
- const index = normalizeTemporalIndex(readJsonSafe(indexPath, emptyTemporalIndex()));
207
- update(index);
208
- writeJsonAtomic(indexPath, index);
279
+ return withPathMutex(indexPath, async () => {
280
+ const ok = await withIndexFileLock(indexPath, async () => {
281
+ const loaded = await loadIndexCached(
282
+ indexPath,
283
+ (raw) => normalizeTemporalIndex(raw),
284
+ hasCurrentTemporalIndexSchema
285
+ );
286
+ const index = structuredClone(loaded.kind === "ok" ? loaded.index : emptyTemporalIndex());
287
+ update(index);
288
+ if (await writeJsonAtomic(indexPath, index)) {
289
+ await primeCacheAfterWrite(indexPath, index, () => hasCurrentTemporalIndexSchema(index));
290
+ return true;
291
+ }
292
+ parsedIndexCache.delete(indexPath);
293
+ return false;
294
+ });
295
+ return ok === true;
209
296
  });
210
297
  }
211
- function updateTagIndex(memoryDir, update) {
298
+ async function updateTagIndex(memoryDir, update) {
212
299
  const indexPath = tagIndexPath(memoryDir);
213
- withIndexFileLock(indexPath, () => {
214
- const index = normalizeTagIndex(
215
- readJsonSafe(indexPath, { version: TAG_INDEX_VERSION, tags: {}, aliases: {} })
216
- );
217
- update(index);
218
- writeJsonAtomic(indexPath, index);
300
+ await withPathMutex(indexPath, async () => {
301
+ await withIndexFileLock(indexPath, async () => {
302
+ const loaded = await loadIndexCached(
303
+ indexPath,
304
+ (raw) => normalizeTagIndex(raw),
305
+ () => true
306
+ );
307
+ const index = structuredClone(
308
+ loaded.kind === "ok" ? loaded.index : { version: TAG_INDEX_VERSION, tags: {}, aliases: {} }
309
+ );
310
+ update(index);
311
+ if (await writeJsonAtomic(indexPath, index)) {
312
+ await primeCacheAfterWrite(indexPath, index, () => true);
313
+ } else {
314
+ parsedIndexCache.delete(indexPath);
315
+ }
316
+ });
219
317
  });
220
318
  }
221
319
  function isoDateFromTimestamp(isoString) {
@@ -487,104 +585,159 @@ function expandCanonicalTags(index, rawTags) {
487
585
  function aliasPhrase(alias) {
488
586
  return alias.replace(/\//g, " ").replace(/-/g, " ").replace(/\s+/g, " ").trim();
489
587
  }
490
- function promptContainsAlias(prompt, alias) {
491
- const phrase = aliasPhrase(alias);
492
- if (!phrase) return false;
493
- const normalizedPrompt = ` ${normalizeAliasKey(prompt)} `;
494
- return normalizedPrompt.includes(` ${phrase} `);
588
+ function applyTemporalIndexCompatibilityMutation(raw, mutation) {
589
+ const index = structuredClone(normalizeTemporalIndex(raw));
590
+ if (mutation.kind === "clear") {
591
+ return emptyTemporalIndex();
592
+ }
593
+ if (mutation.kind === "index") index.version = INDEX_VERSION;
594
+ for (const entry of mutation.entries) {
595
+ const dateKey = isoDateFromTimestamp(entry.createdAt);
596
+ if (mutation.kind === "index") {
597
+ removePathFromAllSets(index.dates, entry.path);
598
+ addPathToSet(index.dates, dateKey, entry.path);
599
+ index.events[entry.path] = temporalEventFromEntry(entry);
600
+ } else {
601
+ removePathFromSet(index.dates, dateKey, entry.path);
602
+ delete index.events[entry.path];
603
+ }
604
+ }
605
+ return index;
495
606
  }
496
- function indexMemory(memoryDir, memoryPath, createdAt, tags, temporal = {}) {
607
+ function applyTagIndexCompatibilityMutation(raw, mutation) {
608
+ const index = structuredClone(normalizeTagIndex(raw));
609
+ if (mutation.kind === "clear") {
610
+ return { version: TAG_INDEX_VERSION, tags: {}, aliases: {} };
611
+ }
612
+ for (const entry of mutation.entries) {
613
+ if (mutation.kind === "index") {
614
+ removePathFromAllTagEntries(index, entry.path);
615
+ for (const tag of entry.tags) {
616
+ if (tag && typeof tag === "string") addTagGraphEntry(index, tag, entry.path);
617
+ }
618
+ } else {
619
+ for (const tag of entry.tags) {
620
+ if (tag && typeof tag === "string") removeTagGraphEntry(index, tag, entry.path);
621
+ }
622
+ }
623
+ }
624
+ return index;
625
+ }
626
+ function hasCurrentTemporalIndexSchemaForCompatibility(raw) {
627
+ return hasCurrentTemporalIndexSchema(raw);
628
+ }
629
+ async function indexMemoryAsync(memoryDir, memoryPath, createdAt, tags, temporal = {}) {
497
630
  try {
498
- ensureStateDir(memoryDir);
631
+ await ensureStateDir(memoryDir);
499
632
  const dateKey = isoDateFromTimestamp(createdAt);
500
- updateTemporalIndex(memoryDir, (index) => {
501
- index.version = INDEX_VERSION;
502
- removePathFromAllSets(index.dates, memoryPath);
503
- addPathToSet(index.dates, dateKey, memoryPath);
504
- index.events[memoryPath] = temporalEventFromEntry({
505
- path: memoryPath,
506
- createdAt,
507
- tags,
508
- ...temporal
633
+ await withMemoryDirMutex(memoryDir, async () => {
634
+ const temporalOk = await updateTemporalIndex(memoryDir, (index) => {
635
+ index.version = INDEX_VERSION;
636
+ removePathFromAllSets(index.dates, memoryPath);
637
+ addPathToSet(index.dates, dateKey, memoryPath);
638
+ index.events[memoryPath] = temporalEventFromEntry({
639
+ path: memoryPath,
640
+ createdAt,
641
+ tags,
642
+ ...temporal
643
+ });
509
644
  });
510
- });
511
- updateTagIndex(memoryDir, (index) => {
512
- removePathFromAllTagEntries(index, memoryPath);
513
- for (const tag of tags) {
514
- if (tag && typeof tag === "string") {
515
- addTagGraphEntry(index, tag, memoryPath);
516
- }
645
+ if (temporalOk) {
646
+ await updateTagIndex(memoryDir, (index) => {
647
+ removePathFromAllTagEntries(index, memoryPath);
648
+ for (const tag of tags) {
649
+ if (tag && typeof tag === "string") {
650
+ addTagGraphEntry(index, tag, memoryPath);
651
+ }
652
+ }
653
+ });
517
654
  }
518
655
  });
519
656
  } catch {
520
657
  }
521
658
  }
522
- function deindexMemory(memoryDir, memoryPath, createdAt, tags) {
659
+ async function deindexMemoryAsync(memoryDir, memoryPath, createdAt, tags) {
523
660
  try {
524
- ensureStateDir(memoryDir);
661
+ await ensureStateDir(memoryDir);
525
662
  const dateKey = isoDateFromTimestamp(createdAt);
526
- updateTemporalIndex(memoryDir, (index) => {
527
- removePathFromSet(index.dates, dateKey, memoryPath);
528
- delete index.events[memoryPath];
529
- });
530
- updateTagIndex(memoryDir, (index) => {
531
- for (const tag of tags) {
532
- if (tag && typeof tag === "string") {
533
- removeTagGraphEntry(index, tag, memoryPath);
534
- }
663
+ await withMemoryDirMutex(memoryDir, async () => {
664
+ const temporalOk = await updateTemporalIndex(memoryDir, (index) => {
665
+ removePathFromSet(index.dates, dateKey, memoryPath);
666
+ delete index.events[memoryPath];
667
+ });
668
+ if (temporalOk) {
669
+ await updateTagIndex(memoryDir, (index) => {
670
+ for (const tag of tags) {
671
+ if (tag && typeof tag === "string") {
672
+ removeTagGraphEntry(index, tag, memoryPath);
673
+ }
674
+ }
675
+ });
535
676
  }
536
677
  });
537
678
  } catch {
538
679
  }
539
680
  }
540
- function clearIndexes(memoryDir) {
681
+ async function clearIndexesAsync(memoryDir) {
541
682
  try {
542
- ensureStateDir(memoryDir);
543
- updateTemporalIndex(memoryDir, (index) => {
544
- index.version = INDEX_VERSION;
545
- index.lastRebuildAt = void 0;
546
- index.dates = {};
547
- index.events = {};
548
- });
549
- updateTagIndex(memoryDir, (index) => {
550
- index.version = TAG_INDEX_VERSION;
551
- index.lastRebuildAt = void 0;
552
- index.tags = {};
553
- index.aliases = {};
683
+ await ensureStateDir(memoryDir);
684
+ await withMemoryDirMutex(memoryDir, async () => {
685
+ const temporalOk = await updateTemporalIndex(memoryDir, (index) => {
686
+ index.version = INDEX_VERSION;
687
+ index.lastRebuildAt = void 0;
688
+ index.dates = {};
689
+ index.events = {};
690
+ });
691
+ if (temporalOk) {
692
+ await updateTagIndex(memoryDir, (index) => {
693
+ index.version = TAG_INDEX_VERSION;
694
+ index.lastRebuildAt = void 0;
695
+ index.tags = {};
696
+ index.aliases = {};
697
+ });
698
+ }
554
699
  });
555
700
  } catch {
556
701
  }
557
702
  }
558
- function indexesExist(memoryDir) {
703
+ async function indexesExistAsync(memoryDir) {
559
704
  try {
560
- if (!fs.existsSync(tagIndexPath(memoryDir))) return false;
561
- const raw = JSON.parse(fs.readFileSync(temporalIndexPath(memoryDir), "utf8"));
562
- return isRecord(raw) && raw.version === INDEX_VERSION && isRecord(raw.dates) && isRecord(raw.events);
705
+ await fs.promises.access(tagIndexPath(memoryDir));
706
+ const loaded = await loadIndexCached(
707
+ temporalIndexPath(memoryDir),
708
+ (raw) => normalizeTemporalIndex(raw),
709
+ hasCurrentTemporalIndexSchema
710
+ );
711
+ return loaded.kind === "ok" && loaded.currentSchema;
563
712
  } catch {
564
713
  return false;
565
714
  }
566
715
  }
567
- function indexMemoriesBatch(memoryDir, entries) {
716
+ async function indexMemoriesBatchAsync(memoryDir, entries) {
568
717
  if (entries.length === 0) return;
569
718
  try {
570
- ensureStateDir(memoryDir);
571
- updateTemporalIndex(memoryDir, (index) => {
572
- index.version = INDEX_VERSION;
573
- for (const entry of entries) {
574
- const dateKey = isoDateFromTimestamp(entry.createdAt);
575
- removePathFromAllSets(index.dates, entry.path);
576
- addPathToSet(index.dates, dateKey, entry.path);
577
- index.events[entry.path] = temporalEventFromEntry(entry);
578
- }
579
- });
580
- updateTagIndex(memoryDir, (index) => {
581
- for (const entry of entries) {
582
- removePathFromAllTagEntries(index, entry.path);
583
- for (const tag of entry.tags) {
584
- if (tag && typeof tag === "string") {
585
- addTagGraphEntry(index, tag, entry.path);
586
- }
719
+ await ensureStateDir(memoryDir);
720
+ await withMemoryDirMutex(memoryDir, async () => {
721
+ const temporalOk = await updateTemporalIndex(memoryDir, (index) => {
722
+ index.version = INDEX_VERSION;
723
+ for (const entry of entries) {
724
+ const dateKey = isoDateFromTimestamp(entry.createdAt);
725
+ removePathFromAllSets(index.dates, entry.path);
726
+ addPathToSet(index.dates, dateKey, entry.path);
727
+ index.events[entry.path] = temporalEventFromEntry(entry);
587
728
  }
729
+ });
730
+ if (temporalOk) {
731
+ await updateTagIndex(memoryDir, (index) => {
732
+ for (const entry of entries) {
733
+ removePathFromAllTagEntries(index, entry.path);
734
+ for (const tag of entry.tags) {
735
+ if (tag && typeof tag === "string") {
736
+ addTagGraphEntry(index, tag, entry.path);
737
+ }
738
+ }
739
+ }
740
+ });
588
741
  }
589
742
  });
590
743
  } catch {
@@ -593,18 +746,13 @@ function indexMemoriesBatch(memoryDir, entries) {
593
746
  async function queryByDateRangeAsync(memoryDir, fromDate, toDate) {
594
747
  try {
595
748
  const tPath = temporalIndexPath(memoryDir);
596
- let raw;
597
- try {
598
- raw = await fs.promises.readFile(tPath, "utf8");
599
- } catch {
600
- return null;
601
- }
602
- let tIndex;
603
- try {
604
- tIndex = normalizeTemporalIndex(JSON.parse(raw));
605
- } catch {
606
- tIndex = emptyTemporalIndex();
607
- }
749
+ const loaded = await loadIndexCached(
750
+ tPath,
751
+ (raw) => normalizeTemporalIndex(raw),
752
+ hasCurrentTemporalIndexSchema
753
+ );
754
+ if (loaded.kind === "missing") return null;
755
+ const tIndex = loaded.kind === "ok" ? loaded.index : emptyTemporalIndex();
608
756
  const end = toDate ?? new Date(Date.now() + 864e5).toISOString().slice(0, 10);
609
757
  const results = /* @__PURE__ */ new Set();
610
758
  for (const [date, paths] of Object.entries(tIndex.dates)) {
@@ -621,10 +769,13 @@ async function queryByDateRangeAsync(memoryDir, fromDate, toDate) {
621
769
  }
622
770
  async function queryTemporalTimelineAsync(memoryDir, options = {}) {
623
771
  try {
624
- const raw = await fs.promises.readFile(temporalIndexPath(memoryDir), "utf8");
625
- const parsed = JSON.parse(raw);
626
- if (!isRecord(parsed) || parsed.version !== INDEX_VERSION || !isRecord(parsed.dates) || !isRecord(parsed.events)) return null;
627
- const index = normalizeTemporalIndex(parsed);
772
+ const loaded = await loadIndexCached(
773
+ temporalIndexPath(memoryDir),
774
+ (raw) => normalizeTemporalIndex(raw),
775
+ hasCurrentTemporalIndexSchema
776
+ );
777
+ if (loaded.kind !== "ok" || !loaded.currentSchema) return null;
778
+ const index = loaded.index;
628
779
  const chronology = Object.values(index.events).filter(
629
780
  (event) => typeof event?.path === "string" && event.path.length > 0 && normalizedIsoTimestamp(event.eventAt) !== void 0
630
781
  ).map((event) => ({
@@ -664,19 +815,13 @@ async function queryByTagsAsync(memoryDir, tags) {
664
815
  if (tags.length === 0) return null;
665
816
  try {
666
817
  const gPath = tagIndexPath(memoryDir);
667
- let raw;
668
- try {
669
- raw = await fs.promises.readFile(gPath, "utf8");
670
- } catch {
671
- return null;
672
- }
673
- let gIndex;
674
- try {
675
- gIndex = normalizeTagIndex(JSON.parse(raw));
676
- } catch {
677
- return null;
678
- }
679
- return queryByTagsFromIndex(gIndex, tags);
818
+ const loaded = await loadIndexCached(
819
+ gPath,
820
+ (raw) => normalizeTagIndex(raw),
821
+ () => true
822
+ );
823
+ if (loaded.kind !== "ok") return null;
824
+ return queryByTagsFromIndex(loaded.index, tags);
680
825
  } catch {
681
826
  return null;
682
827
  }
@@ -705,16 +850,28 @@ function extractTagsFromPrompt(prompt) {
705
850
  async function resolvePromptTagPrefilterAsync(memoryDir, prompt) {
706
851
  const explicitTags = extractTagsFromPrompt(prompt);
707
852
  try {
708
- const raw = await fs.promises.readFile(tagIndexPath(memoryDir), "utf8");
709
- const tagIndex = normalizeTagIndex(JSON.parse(raw));
853
+ const loaded = await loadIndexCached(
854
+ tagIndexPath(memoryDir),
855
+ (raw) => normalizeTagIndex(raw),
856
+ () => true
857
+ );
858
+ if (loaded.kind !== "ok") {
859
+ return { matchedTags: explicitTags, expandedTags: explicitTags, paths: null };
860
+ }
861
+ const tagIndex = loaded.index;
710
862
  const matched = new Set(explicitTags);
863
+ const normalizedPrompt = ` ${normalizeAliasKey(prompt)} `;
864
+ const containsAlias = (alias) => {
865
+ const phrase = aliasPhrase(alias);
866
+ return phrase.length > 0 && normalizedPrompt.includes(` ${phrase} `);
867
+ };
711
868
  for (const canonical of Object.keys(tagIndex.tags)) {
712
- if (promptContainsAlias(prompt, canonical)) {
869
+ if (containsAlias(canonical)) {
713
870
  matched.add(canonical);
714
871
  }
715
872
  }
716
873
  for (const [alias, canonicals] of Object.entries(tagIndex.aliases ?? {})) {
717
- if (!promptContainsAlias(prompt, alias)) continue;
874
+ if (!containsAlias(alias)) continue;
718
875
  for (const canonical of canonicals) {
719
876
  matched.add(canonical);
720
877
  }
@@ -737,6 +894,9 @@ async function resolvePromptTagPrefilterAsync(memoryDir, prompt) {
737
894
  return { matchedTags: explicitTags, expandedTags: explicitTags, paths: null };
738
895
  }
739
896
  }
897
+ function readIndexSnapshotAsync(memoryDir, read) {
898
+ return withMemoryDirMutex(memoryDir, read);
899
+ }
740
900
  function isTemporalQuery(prompt) {
741
901
  return /\b(today|yesterday|this week|last week|this month|last month|recent(?:ly)?|lately|just now|earlier today|this morning|last night|last year|this year|\d+ days? ago|\d+ hours? ago|\d+ weeks? ago|\d+ months? ago|(?:in |on |during |since |before |after )?(?:january|february|march|april|may|june|july|august|september|october|november|december)(?:\s+\d{1,4})?|\d{4}-\d{2}-\d{2}|\d{1,2}\/\d{1,2}\/\d{2,4}|(?:spring|summer|fall|autumn|winter)\s+\d{4}|on the \d{1,2}(?:st|nd|rd|th)?|last (?:monday|tuesday|wednesday|thursday|friday|saturday|sunday))\b/i.test(
742
902
  prompt
@@ -934,19 +1094,246 @@ function recencyWindowBoundsFromPrompt(prompt, nowMs = Date.now()) {
934
1094
  return { fromDate, toDate };
935
1095
  }
936
1096
 
1097
+ // src/temporal-index-compat.ts
1098
+ var TEMPORAL_INDEX_FILE2 = "index_time.json";
1099
+ var TAG_INDEX_FILE2 = "index_tags.json";
1100
+ var INDEX_LOCK_STALE_MS2 = 6e4;
1101
+ var SYNC_INDEX_LOCK_BOUND_MS = 1500;
1102
+ var INDEX_LOCK_POLL_MS2 = 10;
1103
+ var INDEX_PROCESS_START_TOLERANCE_MS2 = 2e3;
1104
+ var INDEX_LOCK_SLEEP = new Int32Array(new SharedArrayBuffer(4));
1105
+ var INDEX_PROCESS_STARTED_AT_MS2 = Date.now() - process.uptime() * 1e3;
1106
+ function stateDir2(memoryDir) {
1107
+ return path2.join(memoryDir, "state");
1108
+ }
1109
+ function temporalIndexPath2(memoryDir) {
1110
+ return path2.join(stateDir2(memoryDir), TEMPORAL_INDEX_FILE2);
1111
+ }
1112
+ function tagIndexPath2(memoryDir) {
1113
+ return path2.join(stateDir2(memoryDir), TAG_INDEX_FILE2);
1114
+ }
1115
+ function sleepSync(ms) {
1116
+ Atomics.wait(INDEX_LOCK_SLEEP, 0, 0, ms);
1117
+ }
1118
+ function uniqueTempPath2(filePath) {
1119
+ const nonce = crypto2.randomBytes(6).toString("hex");
1120
+ return path2.join(
1121
+ path2.dirname(filePath),
1122
+ `.${path2.basename(filePath)}.${process.pid}.${Date.now()}.${nonce}.tmp`
1123
+ );
1124
+ }
1125
+ function lockOwnerPath2(lockDir) {
1126
+ return path2.join(lockDir, "owner.json");
1127
+ }
1128
+ function writeIndexLockOwner2(lockDir) {
1129
+ try {
1130
+ fs2.writeFileSync(
1131
+ lockOwnerPath2(lockDir),
1132
+ JSON.stringify({
1133
+ pid: process.pid,
1134
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
1135
+ processStartedAtMs: INDEX_PROCESS_STARTED_AT_MS2
1136
+ }),
1137
+ { encoding: "utf8", flag: "wx" }
1138
+ );
1139
+ } catch {
1140
+ }
1141
+ }
1142
+ function readIndexLockOwner2(lockDir) {
1143
+ try {
1144
+ const parsed = JSON.parse(fs2.readFileSync(lockOwnerPath2(lockDir), "utf8"));
1145
+ if (!(typeof parsed.pid === "number" && Number.isInteger(parsed.pid) && parsed.pid > 0)) return null;
1146
+ return {
1147
+ pid: parsed.pid,
1148
+ ...typeof parsed.createdAt === "string" && parsed.createdAt.length > 0 ? { createdAt: parsed.createdAt } : {},
1149
+ ...typeof parsed.processStartedAtMs === "number" && Number.isFinite(parsed.processStartedAtMs) && parsed.processStartedAtMs > 0 ? { processStartedAtMs: parsed.processStartedAtMs } : {}
1150
+ };
1151
+ } catch {
1152
+ return null;
1153
+ }
1154
+ }
1155
+ function processIsAlive2(pid) {
1156
+ try {
1157
+ process.kill(pid, 0);
1158
+ return true;
1159
+ } catch (error) {
1160
+ return error?.code === "EPERM";
1161
+ }
1162
+ }
1163
+ function readProcessStartedAtMs2(pid) {
1164
+ try {
1165
+ const output = execFileSync("ps", ["-p", String(pid), "-o", "lstart="], {
1166
+ encoding: "utf8",
1167
+ stdio: ["ignore", "pipe", "ignore"],
1168
+ timeout: 1e3
1169
+ }).trim();
1170
+ if (!output) return null;
1171
+ const startedAtMs = Date.parse(output);
1172
+ return Number.isFinite(startedAtMs) ? startedAtMs : null;
1173
+ } catch {
1174
+ return null;
1175
+ }
1176
+ }
1177
+ function lockOwnerIsRunning2(owner) {
1178
+ if (!processIsAlive2(owner.pid)) return false;
1179
+ if (owner.processStartedAtMs === void 0) return true;
1180
+ const runningStartedAtMs = readProcessStartedAtMs2(owner.pid);
1181
+ if (runningStartedAtMs === null) return true;
1182
+ return runningStartedAtMs <= owner.processStartedAtMs + INDEX_PROCESS_START_TOLERANCE_MS2;
1183
+ }
1184
+ function lockIsFresh2(lockInfo, owner) {
1185
+ const ownerCreatedAtMs = owner?.createdAt ? Date.parse(owner.createdAt) : Number.NaN;
1186
+ const referenceMs = Number.isFinite(ownerCreatedAtMs) ? ownerCreatedAtMs : lockInfo.mtimeMs;
1187
+ return Date.now() - referenceMs < INDEX_LOCK_STALE_MS2;
1188
+ }
1189
+ function removeAbandonedIndexLock2(lockDir) {
1190
+ try {
1191
+ const info = fs2.lstatSync(lockDir);
1192
+ if (info.isSymbolicLink()) return "blocked";
1193
+ if (!info.isDirectory()) {
1194
+ fs2.rmSync(lockDir, { force: true });
1195
+ return "removed";
1196
+ }
1197
+ const owner = readIndexLockOwner2(lockDir);
1198
+ if (owner && lockOwnerIsRunning2(owner)) return "wait";
1199
+ if (!owner && lockIsFresh2(info, null)) return "wait";
1200
+ fs2.rmSync(lockDir, { recursive: true, force: true });
1201
+ return "removed";
1202
+ } catch (error) {
1203
+ return error?.code === "ENOENT" ? "removed" : "blocked";
1204
+ }
1205
+ }
1206
+ function withIndexFileLock2(filePath, update) {
1207
+ const lockDir = `${filePath}.lock.d`;
1208
+ const maxAttempts = Math.max(1, Math.ceil(SYNC_INDEX_LOCK_BOUND_MS / INDEX_LOCK_POLL_MS2));
1209
+ let acquired = false;
1210
+ for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
1211
+ try {
1212
+ fs2.mkdirSync(lockDir);
1213
+ writeIndexLockOwner2(lockDir);
1214
+ acquired = true;
1215
+ break;
1216
+ } catch (error) {
1217
+ const code = error?.code;
1218
+ if (code === "ENOENT") {
1219
+ try {
1220
+ fs2.mkdirSync(path2.dirname(lockDir), { recursive: true });
1221
+ } catch {
1222
+ return;
1223
+ }
1224
+ sleepSync(INDEX_LOCK_POLL_MS2);
1225
+ continue;
1226
+ }
1227
+ if (code !== "EEXIST") return;
1228
+ if (removeAbandonedIndexLock2(lockDir) === "blocked") return;
1229
+ sleepSync(INDEX_LOCK_POLL_MS2);
1230
+ }
1231
+ }
1232
+ if (!acquired) return;
1233
+ try {
1234
+ update();
1235
+ } finally {
1236
+ try {
1237
+ fs2.rmSync(lockDir, { recursive: true, force: true });
1238
+ } catch {
1239
+ }
1240
+ }
1241
+ }
1242
+ function readJson(filePath) {
1243
+ try {
1244
+ return JSON.parse(fs2.readFileSync(filePath, "utf8"));
1245
+ } catch {
1246
+ return null;
1247
+ }
1248
+ }
1249
+ function writeJsonAtomic2(filePath, value) {
1250
+ const payload = JSON.stringify(value);
1251
+ for (let attempt = 0; attempt < 3; attempt += 1) {
1252
+ const tempPath = uniqueTempPath2(filePath);
1253
+ try {
1254
+ fs2.writeFileSync(tempPath, payload, "utf8");
1255
+ fs2.renameSync(tempPath, filePath);
1256
+ return;
1257
+ } catch {
1258
+ try {
1259
+ fs2.unlinkSync(tempPath);
1260
+ } catch {
1261
+ }
1262
+ sleepSync(INDEX_LOCK_POLL_MS2);
1263
+ }
1264
+ }
1265
+ }
1266
+ function applyMutation(memoryDir, mutation) {
1267
+ try {
1268
+ fs2.mkdirSync(stateDir2(memoryDir), { recursive: true });
1269
+ const temporalPath = temporalIndexPath2(memoryDir);
1270
+ const tagPath = tagIndexPath2(memoryDir);
1271
+ withIndexFileLock2(temporalPath, () => {
1272
+ withIndexFileLock2(tagPath, () => {
1273
+ writeJsonAtomic2(
1274
+ temporalPath,
1275
+ applyTemporalIndexCompatibilityMutation(readJson(temporalPath), mutation)
1276
+ );
1277
+ writeJsonAtomic2(
1278
+ tagPath,
1279
+ applyTagIndexCompatibilityMutation(readJson(tagPath), mutation)
1280
+ );
1281
+ });
1282
+ });
1283
+ } catch {
1284
+ }
1285
+ }
1286
+ function indexMemory(memoryDir, memoryPath, createdAt, tags, temporal = {}) {
1287
+ applyMutation(memoryDir, {
1288
+ kind: "index",
1289
+ entries: [{ path: memoryPath, createdAt, tags, ...temporal }]
1290
+ });
1291
+ }
1292
+ function deindexMemory(memoryDir, memoryPath, createdAt, tags) {
1293
+ applyMutation(memoryDir, {
1294
+ kind: "deindex",
1295
+ entries: [{ path: memoryPath, createdAt, tags }]
1296
+ });
1297
+ }
1298
+ function clearIndexes(memoryDir) {
1299
+ applyMutation(memoryDir, { kind: "clear" });
1300
+ }
1301
+ function indexesExist(memoryDir) {
1302
+ try {
1303
+ if (!fs2.existsSync(tagIndexPath2(memoryDir))) return false;
1304
+ return hasCurrentTemporalIndexSchemaForCompatibility(readJson(temporalIndexPath2(memoryDir)));
1305
+ } catch {
1306
+ return false;
1307
+ }
1308
+ }
1309
+ function indexMemoriesBatch(memoryDir, entries) {
1310
+ if (entries.length === 0) return;
1311
+ applyMutation(memoryDir, { kind: "index", entries });
1312
+ }
1313
+
937
1314
  export {
938
1315
  indexMemory,
939
1316
  deindexMemory,
940
1317
  clearIndexes,
941
1318
  indexesExist,
942
1319
  indexMemoriesBatch,
1320
+ setIndexReadObserverForTest,
1321
+ applyTemporalIndexCompatibilityMutation,
1322
+ applyTagIndexCompatibilityMutation,
1323
+ hasCurrentTemporalIndexSchemaForCompatibility,
1324
+ indexMemoryAsync,
1325
+ deindexMemoryAsync,
1326
+ clearIndexesAsync,
1327
+ indexesExistAsync,
1328
+ indexMemoriesBatchAsync,
943
1329
  queryByDateRangeAsync,
944
1330
  queryTemporalTimelineAsync,
945
1331
  queryByTagsAsync,
946
1332
  extractTagsFromPrompt,
947
1333
  resolvePromptTagPrefilterAsync,
1334
+ readIndexSnapshotAsync,
948
1335
  isTemporalQuery,
949
1336
  recencyWindowFromPrompt,
950
1337
  recencyWindowBoundsFromPrompt
951
1338
  };
952
- //# sourceMappingURL=chunk-HHAA35A3.js.map
1339
+ //# sourceMappingURL=chunk-2VN4JAX7.js.map