@remnic/core 9.69.46 → 9.69.48

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 (601) hide show
  1. package/dist/access-admin-ops-surface.d.ts +15 -14
  2. package/dist/access-admin-ops-surface.js +43 -42
  3. package/dist/access-authorization-probe.d.ts +15 -14
  4. package/dist/access-authorization-probe.js +44 -43
  5. package/dist/access-boundary.d.ts +15 -14
  6. package/dist/access-boundary.js +43 -42
  7. package/dist/access-cli.js +120 -115
  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 +15 -14
  11. package/dist/access-extraction-force-flush.js +43 -42
  12. package/dist/access-health-types.d.ts +1 -1
  13. package/dist/access-http-briefing.d.ts +15 -14
  14. package/dist/access-http-briefing.js +44 -43
  15. package/dist/access-http-lcm-compaction.d.ts +15 -14
  16. package/dist/access-http-lifecycle-flush.d.ts +15 -14
  17. package/dist/access-http-offline-stream.d.ts +15 -14
  18. package/dist/access-http-query.d.ts +2 -2
  19. package/dist/access-http-query.js +45 -44
  20. package/dist/access-http.d.ts +16 -15
  21. package/dist/access-http.js +68 -64
  22. package/dist/access-identity-continuity-surface.d.ts +11 -11
  23. package/dist/access-identity-continuity-surface.js +43 -42
  24. package/dist/access-lcm-surface.d.ts +15 -14
  25. package/dist/access-lcm-surface.js +43 -42
  26. package/dist/access-mcp-output-schemas.js +1 -1
  27. package/dist/access-mcp-shared-context-tools.d.ts +15 -14
  28. package/dist/access-mcp.d.ts +15 -14
  29. package/dist/access-mcp.js +56 -53
  30. package/dist/access-memory-search-fanout.d.ts +2 -2
  31. package/dist/{access-namespace-preflight-DDnsN22V.d.ts → access-namespace-preflight-CetF9ziA.d.ts} +1 -1
  32. package/dist/access-namespace-preflight.d.ts +3 -3
  33. package/dist/access-namespace-preflight.js +43 -42
  34. package/dist/access-observe-transcript.d.ts +11 -11
  35. package/dist/access-observe-write-category.d.ts +3 -3
  36. package/dist/access-observe-write-category.js +4 -4
  37. package/dist/access-observe-write-surface.d.ts +15 -14
  38. package/dist/access-observe-write-surface.js +43 -42
  39. package/dist/access-offline-manifest.d.ts +11 -11
  40. package/dist/access-offline-manifest.js +2 -2
  41. package/dist/access-operations-batch.js +45 -44
  42. package/dist/access-operations.d.ts +16 -15
  43. package/dist/access-operations.js +52 -50
  44. package/dist/access-recall-concurrency.d.ts +15 -14
  45. package/dist/access-recall-concurrency.js +43 -42
  46. package/dist/access-recall-response.d.ts +15 -14
  47. package/dist/access-recall-response.js +43 -42
  48. package/dist/access-recall-surface.d.ts +15 -14
  49. package/dist/access-recall-surface.js +43 -42
  50. package/dist/access-schema.d.ts +114 -114
  51. package/dist/access-schema.js +3 -3
  52. package/dist/{access-service-DGynYlbE.d.ts → access-service-DUkTWyZS.d.ts} +77 -74
  53. package/dist/access-service-helpers.d.ts +15 -14
  54. package/dist/access-service.d.ts +15 -14
  55. package/dist/access-service.js +43 -42
  56. package/dist/access-surface-catalog.d.ts +15 -14
  57. package/dist/access-surface-catalog.js +51 -44
  58. package/dist/access-surface-catalog.js.map +1 -1
  59. package/dist/access-wearables-meetings-surface.d.ts +4 -4
  60. package/dist/action-confidence.d.ts +1 -1
  61. package/dist/active-memory-bridge.d.ts +1 -1
  62. package/dist/active-recall.d.ts +1 -1
  63. package/dist/active-recall.js +3 -2
  64. package/dist/active-recall.js.map +1 -1
  65. package/dist/activity/digest.d.ts +1 -1
  66. package/dist/adapters/index.js +4 -4
  67. package/dist/adapters/registry.js +2 -2
  68. package/dist/ambient-provenance.d.ts +1 -1
  69. package/dist/artifact-search.d.ts +1 -1
  70. package/dist/background-generation.d.ts +1 -1
  71. package/dist/behavior-learner.d.ts +1 -1
  72. package/dist/behavior-signals.d.ts +1 -1
  73. package/dist/bootstrap.d.ts +11 -11
  74. package/dist/briefing-window.d.ts +2 -2
  75. package/dist/briefing.d.ts +2 -2
  76. package/dist/briefing.js +13 -13
  77. package/dist/buffer-surprise-report.d.ts +1 -1
  78. package/dist/buffer-turn-helpers.d.ts +1 -1
  79. package/dist/buffer.d.ts +2 -2
  80. package/dist/buffer.js +5 -5
  81. package/dist/bulk-import/index.d.ts +3 -3
  82. package/dist/calibration.d.ts +1 -1
  83. package/dist/capabilities.d.ts +1 -1
  84. package/dist/{catalog-Dl2hYqpS.d.ts → catalog-Bns9zpl3.d.ts} +1 -1
  85. package/dist/causal-behavior.d.ts +1 -1
  86. package/dist/causal-consolidation.d.ts +1 -1
  87. package/dist/causal-consolidation.js +14 -14
  88. package/dist/causal-trajectory-graph.d.ts +1 -1
  89. package/dist/{chunk-N46SNYMC.js → chunk-2B2RHLHI.js} +2 -2
  90. package/dist/{chunk-F5V7KRQS.js → chunk-2WMXZYMS.js} +2 -2
  91. package/dist/{chunk-KF57IQFX.js → chunk-32ZBIGID.js} +19 -15
  92. package/dist/chunk-32ZBIGID.js.map +1 -0
  93. package/dist/{chunk-ORQ7AZMU.js → chunk-3RKVSECD.js} +8 -8
  94. package/dist/{chunk-3NYM6JA4.js → chunk-4LPIVP77.js} +2 -2
  95. package/dist/{chunk-PW4HTWXL.js → chunk-55XWRL6F.js} +2 -2
  96. package/dist/{chunk-GGY7WKMB.js → chunk-5KBI2MOC.js} +1 -1
  97. package/dist/{chunk-IXMWTNNY.js → chunk-6A6HSXWV.js} +2 -2
  98. package/dist/{chunk-P7S7BVBJ.js → chunk-7DU2F7LM.js} +3 -3
  99. package/dist/{chunk-4HTQ76O4.js → chunk-7SJCSDQ3.js} +2 -2
  100. package/dist/{chunk-U4ESGVZ2.js → chunk-7YUX52XZ.js} +3 -3
  101. package/dist/{chunk-FMEP2RB5.js → chunk-B4WI7OF2.js} +2 -2
  102. package/dist/{chunk-EUP4AXIW.js → chunk-B6VDWDFN.js} +2 -2
  103. package/dist/{chunk-UOREPQ3C.js → chunk-BIXELUIR.js} +2 -2
  104. package/dist/{chunk-GYYLZOSO.js → chunk-BMBAA2M5.js} +13 -6
  105. package/dist/chunk-BMBAA2M5.js.map +1 -0
  106. package/dist/{chunk-AYZHHMTK.js → chunk-BNX2TUSF.js} +2 -2
  107. package/dist/{chunk-5ZXGH2ZL.js → chunk-BXOPUJ3W.js} +2 -2
  108. package/dist/{chunk-TE6B2UU6.js → chunk-CD7VTZIG.js} +2 -2
  109. package/dist/{chunk-EC5SVM6H.js → chunk-DE4ZGH2N.js} +2 -2
  110. package/dist/{chunk-YFVIA5A6.js → chunk-DRLZB3CN.js} +2 -2
  111. package/dist/{chunk-SRRZZHA5.js → chunk-EGOWY342.js} +2 -2
  112. package/dist/chunk-EIB4FJVR.js +46 -0
  113. package/dist/chunk-EIB4FJVR.js.map +1 -0
  114. package/dist/{chunk-W44T2KHG.js → chunk-EWBDJQ5Y.js} +3 -3
  115. package/dist/{chunk-JMBTNVMW.js → chunk-FGRJJBFO.js} +2 -2
  116. package/dist/{chunk-F3TURDFG.js → chunk-FPB5LQWW.js} +4 -1
  117. package/dist/{chunk-F3TURDFG.js.map → chunk-FPB5LQWW.js.map} +1 -1
  118. package/dist/{chunk-WGZHSQDV.js → chunk-G2XZFGYN.js} +4 -4
  119. package/dist/{chunk-CFIHVWYZ.js → chunk-GGROFIYX.js} +2 -2
  120. package/dist/{chunk-XLZZLUWL.js → chunk-HG74GEVY.js} +2 -2
  121. package/dist/chunk-HMDYSGY6.js +54 -0
  122. package/dist/chunk-HMDYSGY6.js.map +1 -0
  123. package/dist/{chunk-WUUGE7QC.js → chunk-HS75MCQF.js} +4 -4
  124. package/dist/{chunk-DO6R3LIE.js → chunk-I6IJDTRP.js} +2 -2
  125. package/dist/{chunk-7ZNJN5WZ.js → chunk-IHOXK2I6.js} +55 -6
  126. package/dist/chunk-IHOXK2I6.js.map +1 -0
  127. package/dist/{chunk-2NKY7OC6.js → chunk-IMJPJY7V.js} +2 -2
  128. package/dist/{chunk-TZ44E732.js → chunk-IO7K7GES.js} +2 -2
  129. package/dist/{chunk-7BNB7KHB.js → chunk-JIURESYF.js} +7 -7
  130. package/dist/{chunk-AYP2FZFA.js → chunk-JUOJGZPV.js} +2 -2
  131. package/dist/{chunk-4XTSKGLX.js → chunk-JYXLW22X.js} +3 -3
  132. package/dist/{chunk-HXDXR2FH.js → chunk-KPYMORPQ.js} +41 -31
  133. package/dist/chunk-KPYMORPQ.js.map +1 -0
  134. package/dist/{chunk-IPLYGWQF.js → chunk-KQAFEZQX.js} +5 -5
  135. package/dist/{chunk-AN2O4KZY.js → chunk-KVIMQAER.js} +2 -2
  136. package/dist/chunk-LI4APB6M.js +218 -0
  137. package/dist/chunk-LI4APB6M.js.map +1 -0
  138. package/dist/{chunk-VGRVJ6Z6.js → chunk-LIAM7U2J.js} +2 -2
  139. package/dist/{chunk-S3SND7SO.js → chunk-LIDJWAQV.js} +2 -2
  140. package/dist/{chunk-T5NI5K46.js → chunk-LYMJ36UI.js} +2 -2
  141. package/dist/{chunk-UGGOQKO6.js → chunk-MKJFPIVG.js} +93 -51
  142. package/dist/chunk-MKJFPIVG.js.map +1 -0
  143. package/dist/{chunk-UEJY6ZTQ.js → chunk-MKLDZNBD.js} +2 -2
  144. package/dist/{chunk-QUFJ3NJE.js → chunk-MNG536IS.js} +20 -20
  145. package/dist/{chunk-SW42MMAH.js → chunk-MQT3WP3F.js} +2 -2
  146. package/dist/{chunk-5EHPB6RL.js → chunk-MUNR43V3.js} +2 -2
  147. package/dist/{chunk-OV7GJ4KW.js → chunk-NNFB4CU4.js} +2 -2
  148. package/dist/{chunk-47C6DF43.js → chunk-OS4JVTHR.js} +3 -3
  149. package/dist/{chunk-W6YDAIVB.js → chunk-OSTXIFZW.js} +13 -2
  150. package/dist/chunk-OSTXIFZW.js.map +1 -0
  151. package/dist/chunk-P3YNEMYY.js +212 -0
  152. package/dist/chunk-P3YNEMYY.js.map +1 -0
  153. package/dist/{chunk-JOP7W24J.js → chunk-PA67GXYJ.js} +8 -8
  154. package/dist/{chunk-FSH6KRKO.js → chunk-PPJLJD2D.js} +2 -2
  155. package/dist/{chunk-AG6PANBG.js → chunk-PXJ6HE2W.js} +11 -11
  156. package/dist/{chunk-DDBLZJRV.js → chunk-QB4VXCFN.js} +2 -2
  157. package/dist/{chunk-L63M2PE4.js → chunk-QGAKUOKU.js} +2 -2
  158. package/dist/{chunk-YUQPUK6H.js → chunk-QLCMOHRE.js} +2 -2
  159. package/dist/{chunk-Q4AUIFUA.js → chunk-QMWKENNK.js} +4 -4
  160. package/dist/{chunk-66QOUYNS.js → chunk-R32AEEU3.js} +174 -57
  161. package/dist/chunk-R32AEEU3.js.map +1 -0
  162. package/dist/{chunk-TNQR7N52.js → chunk-S3YM4SZQ.js} +2 -1
  163. package/dist/chunk-S3YM4SZQ.js.map +1 -0
  164. package/dist/{chunk-RW4QNB4J.js → chunk-S45INSV3.js} +3 -1
  165. package/dist/{chunk-RW4QNB4J.js.map → chunk-S45INSV3.js.map} +1 -1
  166. package/dist/{chunk-EEHQY7ER.js → chunk-SK6HEQTW.js} +2 -2
  167. package/dist/{chunk-PGAB2V53.js → chunk-SMBWBEE7.js} +2 -2
  168. package/dist/{chunk-62NYUFNH.js → chunk-SS33RR4F.js} +8 -8
  169. package/dist/{chunk-4ECS33D4.js → chunk-T3T5HTZZ.js} +2 -2
  170. package/dist/{chunk-KG2OOAFF.js → chunk-TQSCR5DU.js} +6 -6
  171. package/dist/{chunk-D5DTZBTV.js → chunk-TW4MXM7H.js} +6 -6
  172. package/dist/chunk-TW4MXM7H.js.map +1 -0
  173. package/dist/{chunk-AS2NOPDM.js → chunk-V7IONNTJ.js} +2 -2
  174. package/dist/{chunk-HYWPUYLO.js → chunk-VV5GCNKG.js} +2 -2
  175. package/dist/{chunk-Y3XHIWVP.js → chunk-WL3PGPGU.js} +2 -2
  176. package/dist/{chunk-3UQIS2GC.js → chunk-WNMVUWI7.js} +2 -2
  177. package/dist/{chunk-66YUOI53.js → chunk-WQW6KPVC.js} +1 -1
  178. package/dist/chunk-WQW6KPVC.js.map +1 -0
  179. package/dist/{chunk-2AV75BJW.js → chunk-WVI43D54.js} +24 -1
  180. package/dist/chunk-WVI43D54.js.map +1 -0
  181. package/dist/{chunk-WOBMSMUK.js → chunk-WYU66IVZ.js} +3 -3
  182. package/dist/{chunk-A7GQBJP5.js → chunk-X2NFFBTO.js} +4 -4
  183. package/dist/{chunk-CWMMKFO7.js → chunk-XEHLYA5Z.js} +3 -3
  184. package/dist/{chunk-JIWZVOQM.js → chunk-XKHRNAK7.js} +2 -2
  185. package/dist/{chunk-VW5TGNJN.js → chunk-XXLH6KFO.js} +2 -2
  186. package/dist/chunk-XYGINDIJ.js +74 -0
  187. package/dist/chunk-XYGINDIJ.js.map +1 -0
  188. package/dist/{chunk-J5OXWG66.js → chunk-XZUHXKM3.js} +2 -2
  189. package/dist/{chunk-K4KE5MYE.js → chunk-Y5VT7BIT.js} +2 -2
  190. package/dist/{chunk-S7KDHFF2.js → chunk-YXWMZAAN.js} +2 -2
  191. package/dist/{chunk-EAZ3YZKN.js → chunk-ZEIJQ4I3.js} +2 -2
  192. package/dist/{cli-Cik3H7q1.d.ts → cli-Bbndoc6k.d.ts} +5 -5
  193. package/dist/cli.d.ts +17 -16
  194. package/dist/cli.js +90 -85
  195. package/dist/coding/export-okf-codegraph.d.ts +1 -1
  196. package/dist/coding/export-okf-codegraph.js +12 -12
  197. package/dist/coding/pre-action-gate.d.ts +1 -1
  198. package/dist/compounding/engine.d.ts +2 -2
  199. package/dist/compounding/engine.js +13 -13
  200. package/dist/compounding/preference-consolidator.d.ts +1 -1
  201. package/dist/compression-optimizer.d.ts +1 -1
  202. package/dist/config.d.ts +1 -1
  203. package/dist/config.js +3 -2
  204. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  205. package/dist/connectors/codex-materialize-runner.js +13 -13
  206. package/dist/connectors/codex-materialize.d.ts +1 -1
  207. package/dist/connectors/index.d.ts +1 -1
  208. package/dist/connectors/index.js +13 -13
  209. package/dist/consolidation-provenance-check.d.ts +2 -2
  210. package/dist/consolidation-undo.d.ts +2 -2
  211. package/dist/contradiction/index.d.ts +4 -4
  212. package/dist/converge-config.d.ts +1 -1
  213. package/dist/convergence-refresh.d.ts +2 -2
  214. package/dist/convergence-refresh.js +15 -15
  215. package/dist/conversation-index/backend.d.ts +1 -1
  216. package/dist/conversation-index/chunker.d.ts +1 -1
  217. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  218. package/dist/conversation-index/indexer.d.ts +1 -1
  219. package/dist/conversation-index/search.d.ts +1 -1
  220. package/dist/corpus-watermark.d.ts +1 -1
  221. package/dist/corpus-watermark.js +15 -15
  222. package/dist/cross-lingual-recall.d.ts +1 -1
  223. package/dist/day-summary.d.ts +1 -1
  224. package/dist/deep-recall-http-glue.d.ts +15 -14
  225. package/dist/deep-recall-http-glue.js +4 -4
  226. package/dist/deep-recall-mcp-tools.d.ts +15 -14
  227. package/dist/deep-recall-policy-llm.d.ts +2 -2
  228. package/dist/deep-recall-seeds.d.ts +1 -1
  229. package/dist/deep-recall.js +2 -2
  230. package/dist/delinearize.d.ts +1 -1
  231. package/dist/dependency-propagation-config.d.ts +1 -1
  232. package/dist/{dependency-propagation-delivery-BXaUoVUf.d.ts → dependency-propagation-delivery-B-LvcDaq.d.ts} +1 -1
  233. package/dist/direct-answer-wiring.d.ts +1 -1
  234. package/dist/direct-answer.d.ts +1 -1
  235. package/dist/embedding-fallback.d.ts +1 -1
  236. package/dist/enrichment/index.d.ts +1 -1
  237. package/dist/entity-origin-fields.d.ts +1 -1
  238. package/dist/entity-retrieval.d.ts +2 -2
  239. package/dist/entity-retrieval.js +14 -14
  240. package/dist/entity-schema.d.ts +1 -1
  241. package/dist/episodic-context.d.ts +1 -1
  242. package/dist/eval-trajectory-contracts.d.ts +1 -1
  243. package/dist/eval-trajectory-store.d.ts +1 -1
  244. package/dist/eval-trajectory.d.ts +1 -1
  245. package/dist/explicit-capture.d.ts +11 -11
  246. package/dist/external-wiki-access.d.ts +15 -14
  247. package/dist/external-wiki-access.js +44 -43
  248. package/dist/external-wiki-collection-registration.d.ts +1 -1
  249. package/dist/external-wiki-collection.d.ts +1 -1
  250. package/dist/external-wiki-mcp-tools.d.ts +15 -14
  251. package/dist/extraction-error-classification.d.ts +1 -1
  252. package/dist/extraction-evidence-class.d.ts +142 -0
  253. package/dist/extraction-evidence-class.js +113 -0
  254. package/dist/extraction-evidence-class.js.map +1 -0
  255. package/dist/extraction-faithfulness.d.ts +2 -2
  256. package/dist/extraction-judge-telemetry.d.ts +2 -2
  257. package/dist/extraction-judge-training.d.ts +2 -2
  258. package/dist/extraction-judge.d.ts +2 -2
  259. package/dist/extraction-liveness.d.ts +1 -1
  260. package/dist/extraction-normalization.d.ts +1 -1
  261. package/dist/extraction-prompt.d.ts +1 -1
  262. package/dist/extraction-source-grounding-rules.d.ts +1 -1
  263. package/dist/extraction-source-grounding.d.ts +1 -1
  264. package/dist/extraction-source-grounding.js +2 -2
  265. package/dist/extraction-span-config.d.ts +1 -1
  266. package/dist/extraction-span-materialize.d.ts +1 -1
  267. package/dist/extraction-span-wire.d.ts +1 -1
  268. package/dist/extraction.d.ts +2 -2
  269. package/dist/extraction.js +21 -21
  270. package/dist/fallback-llm-codex-subscription.d.ts +1 -1
  271. package/dist/fallback-llm.d.ts +1 -1
  272. package/dist/{generic-recall-paths-BkVVEoeO.d.ts → generic-recall-paths-Bfc7zigS.d.ts} +1 -1
  273. package/dist/graph-append-error.d.ts +1 -1
  274. package/dist/graph-dashboard-diff.d.ts +1 -1
  275. package/dist/graph-dashboard-key.d.ts +1 -1
  276. package/dist/graph-dashboard-parser.d.ts +1 -1
  277. package/dist/graph-edge-reinforcement.d.ts +1 -1
  278. package/dist/graph-jsonl.d.ts +1 -1
  279. package/dist/graph-path-reconstruction.d.ts +1 -1
  280. package/dist/graph-path-scoring.d.ts +1 -1
  281. package/dist/graph-snapshot.d.ts +1 -1
  282. package/dist/graph.d.ts +1 -1
  283. package/dist/harmonic-retrieval.js +1 -1
  284. package/dist/importance.d.ts +1 -1
  285. package/dist/importers/index.d.ts +1 -1
  286. package/dist/importers/test-utils.d.ts +1 -1
  287. package/dist/in-flight-reads.d.ts +1 -1
  288. package/dist/{index-Zb6SUV4R.d.ts → index-C7IA1DxB.d.ts} +3 -3
  289. package/dist/index.d.ts +798 -707
  290. package/dist/index.js +184 -134
  291. package/dist/intent.d.ts +1 -1
  292. package/dist/lcm/engine.d.ts +1 -1
  293. package/dist/lcm/engine.js +2 -2
  294. package/dist/lcm/index.d.ts +1 -1
  295. package/dist/lcm/index.js +7 -7
  296. package/dist/lcm/tools.d.ts +1 -1
  297. package/dist/lifecycle.d.ts +1 -1
  298. package/dist/live-connectors-runner.d.ts +1 -1
  299. package/dist/{local-llm-DdrhmecM.d.ts → local-llm-DH4tWtck.d.ts} +1 -1
  300. package/dist/local-llm-helpers.d.ts +2 -2
  301. package/dist/local-llm.d.ts +2 -2
  302. package/dist/local-llm.js +2 -2
  303. package/dist/local-model-endpoint.d.ts +1 -1
  304. package/dist/location/index.d.ts +5 -5
  305. package/dist/location/index.js +15 -15
  306. package/dist/maintenance/memory-governance.d.ts +1 -1
  307. package/dist/maintenance/memory-governance.js +13 -13
  308. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
  309. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +13 -13
  310. package/dist/maintenance/rebuild-memory-projection.d.ts +2 -2
  311. package/dist/maintenance/rebuild-memory-projection.js +14 -14
  312. package/dist/{maintenance-Du_VRvVg.d.ts → maintenance-n6yeTQhR.d.ts} +4 -4
  313. package/dist/mcp-memory-inspector-app.d.ts +15 -14
  314. package/dist/mcp-read-only-tools.js +1 -1
  315. package/dist/memory-action-policy.d.ts +1 -1
  316. package/dist/memory-browse-http-glue.d.ts +170 -0
  317. package/dist/memory-browse-http-glue.js +9 -0
  318. package/dist/memory-browse-http-glue.js.map +1 -0
  319. package/dist/memory-browse-mcp-tools.d.ts +160 -0
  320. package/dist/memory-browse-mcp-tools.js +8 -0
  321. package/dist/memory-browse-mcp-tools.js.map +1 -0
  322. package/dist/memory-browse-operations.d.ts +2 -0
  323. package/dist/memory-browse-operations.js +246 -0
  324. package/dist/memory-browse-operations.js.map +1 -0
  325. package/dist/memory-browse.d.ts +113 -0
  326. package/dist/memory-browse.js +49 -0
  327. package/dist/memory-browse.js.map +1 -0
  328. package/dist/memory-cache.d.ts +1 -1
  329. package/dist/memory-controller.d.ts +1 -1
  330. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  331. package/dist/memory-projection-store.d.ts +1 -1
  332. package/dist/memory-provenance.d.ts +1 -1
  333. package/dist/memory-snapshot.d.ts +1 -1
  334. package/dist/memory-subject-cli.d.ts +15 -14
  335. package/dist/memory-subject.d.ts +15 -14
  336. package/dist/memory-worth-outcomes.d.ts +2 -2
  337. package/dist/models-json.d.ts +1 -1
  338. package/dist/namespaces/migrate.d.ts +3 -3
  339. package/dist/namespaces/migrate.js +14 -14
  340. package/dist/namespaces/principal.d.ts +1 -1
  341. package/dist/namespaces/search.d.ts +1 -1
  342. package/dist/namespaces/search.js +6 -6
  343. package/dist/namespaces/storage.d.ts +3 -3
  344. package/dist/namespaces/storage.js +13 -13
  345. package/dist/native-knowledge.d.ts +1 -1
  346. package/dist/offline-sync-impression-drain.d.ts +1 -1
  347. package/dist/operator-doctor-corpus.d.ts +1 -1
  348. package/dist/operator-doctor-corpus.js +16 -16
  349. package/dist/operator-doctor-replica.d.ts +1 -1
  350. package/dist/operator-toolkit.d.ts +3 -3
  351. package/dist/operator-toolkit.js +23 -22
  352. package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
  353. package/dist/orchestration/maintenance.d.ts +4 -4
  354. package/dist/orchestration/maintenance.js +23 -23
  355. package/dist/{orchestrator-D9U3Zgjp.d.ts → orchestrator-Cirjo3ZB.d.ts} +10 -10
  356. package/dist/orchestrator.d.ts +11 -11
  357. package/dist/orchestrator.js +122 -117
  358. package/dist/patterns-cli.d.ts +1 -1
  359. package/dist/{pipeline-4lqKJZ_0.d.ts → pipeline-DK79FrgH.d.ts} +1 -1
  360. package/dist/policy-runtime.d.ts +1 -1
  361. package/dist/proactive-contention.d.ts +2 -2
  362. package/dist/provenance.d.ts +77 -2
  363. package/dist/provenance.js +7 -3
  364. package/dist/{public-http-AabioFLh.d.ts → public-http-DaHHhWRR.d.ts} +1 -1
  365. package/dist/{qmd-DnoWaXKb.d.ts → qmd-BT0ErlRS.d.ts} +1 -1
  366. package/dist/qmd-preflight.d.ts +2 -2
  367. package/dist/qmd-recall-cache.d.ts +1 -1
  368. package/dist/qmd.d.ts +2 -2
  369. package/dist/qmd.js +4 -4
  370. package/dist/recall-concurrency-config.d.ts +1 -1
  371. package/dist/recall-context-composition.d.ts +43 -3
  372. package/dist/recall-context-composition.js +5 -1
  373. package/dist/recall-disclosure-escalation.d.ts +1 -1
  374. package/dist/recall-explain-renderer.d.ts +1 -1
  375. package/dist/recall-explain-renderer.js +3 -3
  376. package/dist/recall-memory-map.d.ts +1 -1
  377. package/dist/recall-navigate-access.d.ts +1 -1
  378. package/dist/recall-navigate-access.js +2 -2
  379. package/dist/recall-navigate-disclosure.d.ts +1 -1
  380. package/dist/recall-navigate-disclosure.js +2 -2
  381. package/dist/recall-navigate.d.ts +1 -1
  382. package/dist/recall-navigate.js +2 -2
  383. package/dist/recall-navigation-http-glue.d.ts +15 -14
  384. package/dist/recall-navigation-mcp-tools.d.ts +15 -14
  385. package/dist/recall-navigation-operations.js +44 -43
  386. package/dist/recall-navigation-renderer.d.ts +1 -1
  387. package/dist/recall-navigation.d.ts +1 -1
  388. package/dist/recall-navigation.js +43 -42
  389. package/dist/recall-planner-llm.d.ts +1 -1
  390. package/dist/recall-state-view-admission.d.ts +2 -2
  391. package/dist/recall-state-view-admission.js +5 -5
  392. package/dist/recall-state-view-anchors.d.ts +1 -1
  393. package/dist/recall-state.d.ts +1 -1
  394. package/dist/recall-tag-filter.d.ts +1 -1
  395. package/dist/recall-timings.d.ts +1 -1
  396. package/dist/recall-xray-cli.d.ts +1 -1
  397. package/dist/recall-xray-cli.js +4 -4
  398. package/dist/recall-xray-renderer.d.ts +1 -1
  399. package/dist/recall-xray-renderer.js +3 -3
  400. package/dist/recall-xray.d.ts +1 -1
  401. package/dist/recall-xray.js +2 -2
  402. package/dist/reconcile/cursor.d.ts +1 -1
  403. package/dist/reconcile/manifest.d.ts +4 -1
  404. package/dist/reconcile/manifest.js +1 -1
  405. package/dist/reconcile/plan.d.ts +1 -1
  406. package/dist/replay/normalizers/chatgpt.d.ts +1 -1
  407. package/dist/replay/normalizers/claude.d.ts +1 -1
  408. package/dist/replay/normalizers/openclaw.d.ts +1 -1
  409. package/dist/replay/normalizers/shared.d.ts +1 -1
  410. package/dist/replay/runner.d.ts +1 -1
  411. package/dist/replay/types.d.ts +1 -1
  412. package/dist/replica-divergence.d.ts +1 -1
  413. package/dist/replica-peers-config.d.ts +1 -1
  414. package/dist/resolve-auth-token.d.ts +1 -1
  415. package/dist/resume-bundles.js +4 -3
  416. package/dist/retrieval-agents.d.ts +2 -2
  417. package/dist/retrieval-tiers.d.ts +1 -1
  418. package/dist/routing/engine.d.ts +1 -1
  419. package/dist/routing/store.d.ts +1 -1
  420. package/dist/salvage-envelope.d.ts +1 -1
  421. package/dist/schemas.d.ts +160 -160
  422. package/dist/{scope-profiles-crazXegZ.d.ts → scope-profiles-BgPQx9iE.d.ts} +1 -1
  423. package/dist/search/embed-helper.d.ts +1 -1
  424. package/dist/search/factory.d.ts +1 -1
  425. package/dist/search/factory.js +5 -5
  426. package/dist/search/index.d.ts +1 -1
  427. package/dist/search/index.js +9 -9
  428. package/dist/search/lancedb-backend.d.ts +1 -1
  429. package/dist/search/meilisearch-backend.d.ts +1 -1
  430. package/dist/search/noop-backend.d.ts +1 -1
  431. package/dist/search/orama-backend.d.ts +1 -1
  432. package/dist/search/port.d.ts +1 -1
  433. package/dist/search/remote-backend.d.ts +1 -1
  434. package/dist/{semantic-consolidation-B09JI9WM.d.ts → semantic-consolidation-BrAWKVcm.d.ts} +1 -1
  435. package/dist/semantic-consolidation.d.ts +2 -2
  436. package/dist/semantic-consolidation.js +14 -14
  437. package/dist/semantic-rule-promotion.js +13 -13
  438. package/dist/semantic-rule-verifier.d.ts +1 -1
  439. package/dist/semantic-rule-verifier.js +13 -13
  440. package/dist/{service-ByjbCuj7.d.ts → service-CqHOTg87.d.ts} +2 -2
  441. package/dist/session-observer-bands.d.ts +1 -1
  442. package/dist/session-observer-state.d.ts +1 -1
  443. package/dist/shared-context/manager.d.ts +7 -7
  444. package/dist/signal.d.ts +1 -1
  445. package/dist/source-agent-qualifier.d.ts +1 -1
  446. package/dist/source-agent-qualifier.js +17 -17
  447. package/dist/standing-memory-block.d.ts +77 -0
  448. package/dist/standing-memory-block.js +40 -0
  449. package/dist/standing-memory-block.js.map +1 -0
  450. package/dist/standup/build.js +13 -13
  451. package/dist/{storage-CbdF077z.d.ts → storage-mD2YQ8_2.d.ts} +1 -1
  452. package/dist/storage.d.ts +2 -2
  453. package/dist/storage.js +12 -12
  454. package/dist/subject-config.d.ts +1 -1
  455. package/dist/summarizer.d.ts +1 -1
  456. package/dist/summarizer.js +3 -3
  457. package/dist/summary-snapshot.d.ts +1 -1
  458. package/dist/support-passport/index.d.ts +18 -17
  459. package/dist/support-passport/index.js +46 -45
  460. package/dist/{tagging-CF7DNV7_.d.ts → tagging-CiAVA-ID.d.ts} +2 -2
  461. package/dist/temporal-supersession.d.ts +2 -2
  462. package/dist/temporal-timeline-recall.d.ts +1 -1
  463. package/dist/temporal-timeline-recall.js +2 -2
  464. package/dist/temporal-validity.d.ts +1 -1
  465. package/dist/threading.d.ts +1 -1
  466. package/dist/tier-migration.d.ts +2 -2
  467. package/dist/tier-routing.d.ts +1 -1
  468. package/dist/topics.d.ts +1 -1
  469. package/dist/transcript.d.ts +1 -1
  470. package/dist/transfer/autodetect.js +1 -1
  471. package/dist/transfer/backup.js +1 -1
  472. package/dist/transfer/capsule-export.js +2 -2
  473. package/dist/transfer/export-okf.d.ts +1 -1
  474. package/dist/transfer/export-okf.js +13 -13
  475. package/dist/transfer/types.d.ts +78 -78
  476. package/dist/trust-score-stage.d.ts +1 -1
  477. package/dist/trust-score.d.ts +1 -1
  478. package/dist/{types-nmhnJpxx.d.ts → types-DgDaoY61.d.ts} +6 -0
  479. package/dist/types.d.ts +1 -1
  480. package/dist/types.js +1 -1
  481. package/dist/utility-runtime.d.ts +1 -1
  482. package/dist/verified-recall.js +13 -13
  483. package/dist/who-knows-cli.d.ts +15 -14
  484. package/dist/who-knows-cli.js +14 -14
  485. package/dist/who-knows.d.ts +15 -14
  486. package/dist/who-knows.js +13 -13
  487. package/dist/write-envelope.d.ts +1 -1
  488. package/package.json +2 -2
  489. package/src/access-boundary.ts +3 -0
  490. package/src/access-http.ts +2 -2
  491. package/src/access-mcp-output-schemas.ts +25 -0
  492. package/src/access-mcp.ts +3 -3
  493. package/src/access-operations.ts +2 -0
  494. package/src/access-service.ts +6 -1
  495. package/src/access-surface-catalog.test.ts +20 -0
  496. package/src/access-surface-catalog.ts +6 -0
  497. package/src/activity/timeline/index.ts +1 -0
  498. package/src/activity/timeline/journal-recap.test.ts +17 -0
  499. package/src/activity/timeline/journal-recap.ts +19 -6
  500. package/src/activity/timeline/recap-export-range.test.ts +289 -0
  501. package/src/activity/timeline/recap-export-range.ts +169 -0
  502. package/src/activity/timeline/recap-export.test.ts +73 -1
  503. package/src/activity/timeline/recap-export.ts +57 -4
  504. package/src/cli/memory-browse-commands.ts +77 -0
  505. package/src/cli.ts +2 -2
  506. package/src/config.ts +11 -0
  507. package/src/extraction-evidence-class.test.ts +355 -0
  508. package/src/extraction-evidence-class.ts +241 -0
  509. package/src/index.ts +1 -0
  510. package/src/mcp-read-only-tools.ts +3 -0
  511. package/src/memory-browse-http-glue.ts +93 -0
  512. package/src/memory-browse-mcp-tools.ts +57 -0
  513. package/src/memory-browse-operations.ts +88 -0
  514. package/src/memory-browse-surface.test.ts +500 -0
  515. package/src/memory-browse.ts +316 -0
  516. package/src/provenance.ts +3 -3
  517. package/src/recall-context-composition.test.ts +66 -0
  518. package/src/recall-context-composition.ts +102 -2
  519. package/src/reconcile/manifest.test.ts +27 -0
  520. package/src/reconcile/manifest.ts +7 -0
  521. package/src/standing-memory-block.test.ts +262 -0
  522. package/src/standing-memory-block.ts +331 -0
  523. package/src/types.ts +6 -0
  524. package/dist/chunk-2AV75BJW.js.map +0 -1
  525. package/dist/chunk-66QOUYNS.js.map +0 -1
  526. package/dist/chunk-66YUOI53.js.map +0 -1
  527. package/dist/chunk-7ZNJN5WZ.js.map +0 -1
  528. package/dist/chunk-D5DTZBTV.js.map +0 -1
  529. package/dist/chunk-GYYLZOSO.js.map +0 -1
  530. package/dist/chunk-HXDXR2FH.js.map +0 -1
  531. package/dist/chunk-KF57IQFX.js.map +0 -1
  532. package/dist/chunk-TNQR7N52.js.map +0 -1
  533. package/dist/chunk-UGGOQKO6.js.map +0 -1
  534. package/dist/chunk-W6YDAIVB.js.map +0 -1
  535. /package/dist/{chunk-N46SNYMC.js.map → chunk-2B2RHLHI.js.map} +0 -0
  536. /package/dist/{chunk-F5V7KRQS.js.map → chunk-2WMXZYMS.js.map} +0 -0
  537. /package/dist/{chunk-ORQ7AZMU.js.map → chunk-3RKVSECD.js.map} +0 -0
  538. /package/dist/{chunk-3NYM6JA4.js.map → chunk-4LPIVP77.js.map} +0 -0
  539. /package/dist/{chunk-PW4HTWXL.js.map → chunk-55XWRL6F.js.map} +0 -0
  540. /package/dist/{chunk-GGY7WKMB.js.map → chunk-5KBI2MOC.js.map} +0 -0
  541. /package/dist/{chunk-IXMWTNNY.js.map → chunk-6A6HSXWV.js.map} +0 -0
  542. /package/dist/{chunk-P7S7BVBJ.js.map → chunk-7DU2F7LM.js.map} +0 -0
  543. /package/dist/{chunk-4HTQ76O4.js.map → chunk-7SJCSDQ3.js.map} +0 -0
  544. /package/dist/{chunk-U4ESGVZ2.js.map → chunk-7YUX52XZ.js.map} +0 -0
  545. /package/dist/{chunk-FMEP2RB5.js.map → chunk-B4WI7OF2.js.map} +0 -0
  546. /package/dist/{chunk-EUP4AXIW.js.map → chunk-B6VDWDFN.js.map} +0 -0
  547. /package/dist/{chunk-UOREPQ3C.js.map → chunk-BIXELUIR.js.map} +0 -0
  548. /package/dist/{chunk-AYZHHMTK.js.map → chunk-BNX2TUSF.js.map} +0 -0
  549. /package/dist/{chunk-5ZXGH2ZL.js.map → chunk-BXOPUJ3W.js.map} +0 -0
  550. /package/dist/{chunk-TE6B2UU6.js.map → chunk-CD7VTZIG.js.map} +0 -0
  551. /package/dist/{chunk-EC5SVM6H.js.map → chunk-DE4ZGH2N.js.map} +0 -0
  552. /package/dist/{chunk-YFVIA5A6.js.map → chunk-DRLZB3CN.js.map} +0 -0
  553. /package/dist/{chunk-SRRZZHA5.js.map → chunk-EGOWY342.js.map} +0 -0
  554. /package/dist/{chunk-W44T2KHG.js.map → chunk-EWBDJQ5Y.js.map} +0 -0
  555. /package/dist/{chunk-JMBTNVMW.js.map → chunk-FGRJJBFO.js.map} +0 -0
  556. /package/dist/{chunk-WGZHSQDV.js.map → chunk-G2XZFGYN.js.map} +0 -0
  557. /package/dist/{chunk-CFIHVWYZ.js.map → chunk-GGROFIYX.js.map} +0 -0
  558. /package/dist/{chunk-XLZZLUWL.js.map → chunk-HG74GEVY.js.map} +0 -0
  559. /package/dist/{chunk-WUUGE7QC.js.map → chunk-HS75MCQF.js.map} +0 -0
  560. /package/dist/{chunk-DO6R3LIE.js.map → chunk-I6IJDTRP.js.map} +0 -0
  561. /package/dist/{chunk-2NKY7OC6.js.map → chunk-IMJPJY7V.js.map} +0 -0
  562. /package/dist/{chunk-TZ44E732.js.map → chunk-IO7K7GES.js.map} +0 -0
  563. /package/dist/{chunk-7BNB7KHB.js.map → chunk-JIURESYF.js.map} +0 -0
  564. /package/dist/{chunk-AYP2FZFA.js.map → chunk-JUOJGZPV.js.map} +0 -0
  565. /package/dist/{chunk-4XTSKGLX.js.map → chunk-JYXLW22X.js.map} +0 -0
  566. /package/dist/{chunk-IPLYGWQF.js.map → chunk-KQAFEZQX.js.map} +0 -0
  567. /package/dist/{chunk-AN2O4KZY.js.map → chunk-KVIMQAER.js.map} +0 -0
  568. /package/dist/{chunk-VGRVJ6Z6.js.map → chunk-LIAM7U2J.js.map} +0 -0
  569. /package/dist/{chunk-S3SND7SO.js.map → chunk-LIDJWAQV.js.map} +0 -0
  570. /package/dist/{chunk-T5NI5K46.js.map → chunk-LYMJ36UI.js.map} +0 -0
  571. /package/dist/{chunk-UEJY6ZTQ.js.map → chunk-MKLDZNBD.js.map} +0 -0
  572. /package/dist/{chunk-QUFJ3NJE.js.map → chunk-MNG536IS.js.map} +0 -0
  573. /package/dist/{chunk-SW42MMAH.js.map → chunk-MQT3WP3F.js.map} +0 -0
  574. /package/dist/{chunk-5EHPB6RL.js.map → chunk-MUNR43V3.js.map} +0 -0
  575. /package/dist/{chunk-OV7GJ4KW.js.map → chunk-NNFB4CU4.js.map} +0 -0
  576. /package/dist/{chunk-47C6DF43.js.map → chunk-OS4JVTHR.js.map} +0 -0
  577. /package/dist/{chunk-JOP7W24J.js.map → chunk-PA67GXYJ.js.map} +0 -0
  578. /package/dist/{chunk-FSH6KRKO.js.map → chunk-PPJLJD2D.js.map} +0 -0
  579. /package/dist/{chunk-AG6PANBG.js.map → chunk-PXJ6HE2W.js.map} +0 -0
  580. /package/dist/{chunk-DDBLZJRV.js.map → chunk-QB4VXCFN.js.map} +0 -0
  581. /package/dist/{chunk-L63M2PE4.js.map → chunk-QGAKUOKU.js.map} +0 -0
  582. /package/dist/{chunk-YUQPUK6H.js.map → chunk-QLCMOHRE.js.map} +0 -0
  583. /package/dist/{chunk-Q4AUIFUA.js.map → chunk-QMWKENNK.js.map} +0 -0
  584. /package/dist/{chunk-EEHQY7ER.js.map → chunk-SK6HEQTW.js.map} +0 -0
  585. /package/dist/{chunk-PGAB2V53.js.map → chunk-SMBWBEE7.js.map} +0 -0
  586. /package/dist/{chunk-62NYUFNH.js.map → chunk-SS33RR4F.js.map} +0 -0
  587. /package/dist/{chunk-4ECS33D4.js.map → chunk-T3T5HTZZ.js.map} +0 -0
  588. /package/dist/{chunk-KG2OOAFF.js.map → chunk-TQSCR5DU.js.map} +0 -0
  589. /package/dist/{chunk-AS2NOPDM.js.map → chunk-V7IONNTJ.js.map} +0 -0
  590. /package/dist/{chunk-HYWPUYLO.js.map → chunk-VV5GCNKG.js.map} +0 -0
  591. /package/dist/{chunk-Y3XHIWVP.js.map → chunk-WL3PGPGU.js.map} +0 -0
  592. /package/dist/{chunk-3UQIS2GC.js.map → chunk-WNMVUWI7.js.map} +0 -0
  593. /package/dist/{chunk-WOBMSMUK.js.map → chunk-WYU66IVZ.js.map} +0 -0
  594. /package/dist/{chunk-A7GQBJP5.js.map → chunk-X2NFFBTO.js.map} +0 -0
  595. /package/dist/{chunk-CWMMKFO7.js.map → chunk-XEHLYA5Z.js.map} +0 -0
  596. /package/dist/{chunk-JIWZVOQM.js.map → chunk-XKHRNAK7.js.map} +0 -0
  597. /package/dist/{chunk-VW5TGNJN.js.map → chunk-XXLH6KFO.js.map} +0 -0
  598. /package/dist/{chunk-J5OXWG66.js.map → chunk-XZUHXKM3.js.map} +0 -0
  599. /package/dist/{chunk-K4KE5MYE.js.map → chunk-Y5VT7BIT.js.map} +0 -0
  600. /package/dist/{chunk-S7KDHFF2.js.map → chunk-YXWMZAAN.js.map} +0 -0
  601. /package/dist/{chunk-EAZ3YZKN.js.map → chunk-ZEIJQ4I3.js.map} +0 -0
@@ -0,0 +1,316 @@
1
+ /**
2
+ * Memory-store browse verbs (issue #2978) — deterministic `ls` / `tree` /
3
+ * `find` over ONE resolved namespace's memory store, so an agent can see
4
+ * what exists instead of guessing ids at an opaque search box.
5
+ *
6
+ * Scope rules (all existing contracts, no new ones):
7
+ * - Every call resolves through the caller's `resolveReadableNamespace`
8
+ * (read/write path symmetry) and ONE storage instance — browse never
9
+ * enumerates across namespaces.
10
+ * - Only the recall corpus is browsable: a path's top segment must be a
11
+ * `RECALL_FALLBACK_DIRS` category AND survive
12
+ * `isGenericRecallExcludedPath`. Derived stores (`artifacts/`,
13
+ * `meetings/` records, wearables day stores, `state/`, ...) are
14
+ * indistinguishable from missing paths — `not_found`, never listed.
15
+ * - Support-passport private memories are filtered exactly like
16
+ * `memoryBrowse` (the paginated list): their names never appear.
17
+ * - Output is deterministically sorted (plain code-point order, no
18
+ * locale) and entry-capped so a huge store cannot blow the response.
19
+ *
20
+ * `ponytail:` the index is rebuilt from `readAllMemories()` per call —
21
+ * O(corpus) per browse. Fine at agent cadence; swap for a cached directory
22
+ * index if browsing ever sits on a hot path.
23
+ */
24
+
25
+ import { toMemoryPathRel } from "./memory-lifecycle-ledger-utils.js";
26
+ import { normalizeProjectionPreview } from "./memory-projection-format.js";
27
+ import { isGenericRecallExcludedPath } from "./orchestration/generic-recall-paths.js";
28
+ import { isSupportPassportPrivateMemory } from "./support-passport/card-projection.js";
29
+ import { RECALL_FALLBACK_DIRS } from "./utils/category-dir.js";
30
+ import type { MemoryFile } from "./types.js";
31
+
32
+ /** Browse reads touch only these storage members. */
33
+ export interface MemoryBrowseStorage {
34
+ readonly dir: string;
35
+ readAllMemories(): Promise<MemoryFile[]>;
36
+ }
37
+
38
+ /** Injected seams; the service supplies live wiring, tests supply doubles. */
39
+ export interface MemoryBrowseDeps {
40
+ readonly resolveReadableNamespace: (namespace: string | undefined, principal?: string) => string;
41
+ readonly getStorage: (namespace: string) => Promise<MemoryBrowseStorage>;
42
+ }
43
+
44
+ export type BrowseVerb = "ls" | "tree" | "find";
45
+
46
+ export interface MemoryStoreBrowseRequest {
47
+ readonly verb: BrowseVerb;
48
+ /** ls/tree: directory relative to the store root ("" or "/" = root). */
49
+ readonly path?: string;
50
+ /** tree: expansion depth, 1..MAX_TREE_DEPTH (default 1). */
51
+ readonly depth?: number;
52
+ /** find: glob (`*` wildcard) or substring matched against path and name. */
53
+ readonly pattern?: string;
54
+ readonly namespace?: string;
55
+ readonly authenticatedPrincipal?: string;
56
+ }
57
+
58
+ export interface MemoryBrowseEntry {
59
+ /** Store-relative path with forward slashes; dirs carry no trailing slash. */
60
+ readonly path: string;
61
+ readonly kind: "dir" | "file";
62
+ readonly name: string;
63
+ /** Files: first content line (180-char preview). Dirs: empty. */
64
+ readonly description: string;
65
+ /** Dirs: recursive memory count beneath. Files: 1. */
66
+ readonly count: number;
67
+ /** 0-based depth relative to the browse root (tree nests; ls/find are 0). */
68
+ readonly depth: number;
69
+ }
70
+
71
+ export type MemoryBrowseError = "invalid_path" | "not_found" | "invalid_depth" | "invalid_pattern";
72
+
73
+ export type MemoryStoreBrowseResult =
74
+ | {
75
+ ok: true;
76
+ verb: BrowseVerb;
77
+ namespace: string;
78
+ path: string;
79
+ total: number;
80
+ entries: MemoryBrowseEntry[];
81
+ truncated: boolean;
82
+ rendered: string;
83
+ }
84
+ | {
85
+ ok: false;
86
+ verb: BrowseVerb;
87
+ path: string;
88
+ error: MemoryBrowseError;
89
+ message: string;
90
+ rendered: string;
91
+ };
92
+
93
+ export const MAX_LS_ENTRIES = 200;
94
+ export const MAX_TREE_ENTRIES = 400;
95
+ export const MAX_TREE_DEPTH = 4;
96
+ export const MAX_FIND_ENTRIES = 200;
97
+ const MAX_PATH_CHARS = 512;
98
+ const MAX_PATTERN_CHARS = 256;
99
+
100
+ const BROWSABLE_ROOTS: Record<string, true> = Object.fromEntries(RECALL_FALLBACK_DIRS.map((dir) => [dir, true]));
101
+
102
+ /** The recall-corpus visibility rule shared by every browse code path. */
103
+ function isBrowsableMemoryPath(relPath: string): boolean {
104
+ if (!relPath.endsWith(".md")) return false;
105
+ const top = relPath.split("/")[0] ?? "";
106
+ return BROWSABLE_ROOTS[top] === true && !isGenericRecallExcludedPath(relPath);
107
+ }
108
+
109
+ /**
110
+ * Normalize a caller-supplied store path. Returns "" for the root. Throws
111
+ * `Error` on absolute paths, `..`/`.` segments, backslashes, control
112
+ * characters, or oversize input — never reinterpreted (pattern 39).
113
+ */
114
+ export function sanitizeBrowsePath(raw: string | undefined): string {
115
+ const trimmed = (raw ?? "").trim();
116
+ if (trimmed === "" || trimmed === "/") return "";
117
+ if (trimmed.length > MAX_PATH_CHARS) throw new Error("path is too long");
118
+ if (trimmed.includes("\\")) throw new Error("path must use '/' separators");
119
+ const segments = trimmed.split("/");
120
+ for (const segment of segments) {
121
+ if (segment === "") throw new Error("path has an empty segment");
122
+ if (segment === "." || segment === "..") throw new Error("path must not contain '.' or '..' segments");
123
+ for (const ch of segment) {
124
+ const code = ch.charCodeAt(0);
125
+ if (code < 0x20 || code === 0x7f) throw new Error("path has control characters");
126
+ }
127
+ }
128
+ return segments.join("/");
129
+ }
130
+
131
+ /** Escape every regex metacharacter in a glob segment. */
132
+ function segmentRegex(segment: string): RegExp {
133
+ const source = `^${segment.split("*").map((part) => part.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join(".*")}$`;
134
+ return new RegExp(source, "i");
135
+ }
136
+
137
+ /**
138
+ * `*` glob (one segment per pattern segment, `find -name` semantics — `*`
139
+ * never crosses `/`) or case-insensitive substring over path and name.
140
+ */
141
+ export function browsePatternMatches(pattern: string, relPath: string): boolean {
142
+ const segments = relPath.split("/");
143
+ const name = segments[segments.length - 1] ?? "";
144
+ const patternSegments = pattern.split("/");
145
+ if (patternSegments.length === 1) {
146
+ const single = patternSegments[0]!;
147
+ if (single.includes("*")) return segmentRegex(single).test(name);
148
+ const needle = single.toLowerCase();
149
+ return relPath.toLowerCase().includes(needle) || name.toLowerCase().includes(needle);
150
+ }
151
+ if (patternSegments.length !== segments.length) return false;
152
+ return patternSegments.every((segment, index) => segmentRegex(segment).test(segments[index]!));
153
+ }
154
+
155
+ interface DirNode {
156
+ readonly subdirs: Map<string, DirNode>;
157
+ readonly files: Map<string, MemoryFile>;
158
+ count: number;
159
+ }
160
+
161
+ function emptyNode(): DirNode {
162
+ return { subdirs: new Map(), files: new Map(), count: 0 };
163
+ }
164
+
165
+ /** Directory index over the browsable corpus: root "" holds category dirs. */
166
+ function buildIndex(memories: readonly MemoryFile[], dir: string): DirNode {
167
+ const root = emptyNode();
168
+ for (const memory of memories) {
169
+ const rel = toMemoryPathRel(dir, memory.path);
170
+ if (!isBrowsableMemoryPath(rel)) continue;
171
+ const segments = rel.split("/");
172
+ let node = root;
173
+ node.count += 1;
174
+ for (let index = 0; index < segments.length - 1; index += 1) {
175
+ const name = segments[index]!;
176
+ let child = node.subdirs.get(name);
177
+ if (child === undefined) {
178
+ child = emptyNode();
179
+ node.subdirs.set(name, child);
180
+ }
181
+ node = child;
182
+ node.count += 1;
183
+ }
184
+ node.files.set(segments[segments.length - 1]!, memory);
185
+ }
186
+ return root;
187
+ }
188
+
189
+ function byPath(left: { path: string }, right: { path: string }): number {
190
+ return left.path < right.path ? -1 : left.path > right.path ? 1 : 0;
191
+ }
192
+
193
+ function dirEntries(node: DirNode, dirPath: string): MemoryBrowseEntry[] {
194
+ const prefix = dirPath === "" ? "" : `${dirPath}/`;
195
+ const entries: MemoryBrowseEntry[] = [];
196
+ for (const [name, child] of node.subdirs) {
197
+ entries.push({ path: `${prefix}${name}`, kind: "dir", name, description: "", count: child.count, depth: 0 });
198
+ }
199
+ for (const [name, memory] of node.files) {
200
+ entries.push({
201
+ path: `${prefix}${name}`,
202
+ kind: "file",
203
+ name,
204
+ description: normalizeProjectionPreview(memory.content),
205
+ count: 1,
206
+ depth: 0,
207
+ });
208
+ }
209
+ return entries.sort(byPath);
210
+ }
211
+
212
+ function renderEntries(verb: BrowseVerb, namespace: string, browsePath: string, entries: readonly MemoryBrowseEntry[]): string {
213
+ const lines = [`${verb} ${namespace}:${browsePath === "" ? "/" : browsePath}`];
214
+ for (const entry of entries) {
215
+ const indent = " ".repeat(entry.depth);
216
+ if (entry.kind === "dir") {
217
+ lines.push(`${indent}${entry.path}/ (${entry.count} memories)`);
218
+ } else {
219
+ const description = entry.description.length > 0 ? ` — ${entry.description}` : "";
220
+ lines.push(`${indent}${entry.path}${description}`);
221
+ }
222
+ }
223
+ return lines.join("\n");
224
+ }
225
+
226
+ function refusal(verb: BrowseVerb, browsePath: string, error: MemoryBrowseError, message: string): MemoryStoreBrowseResult {
227
+ return { ok: false, verb, path: browsePath, error, message, rendered: `browse ${verb} failed: ${error} — ${message}` };
228
+ }
229
+
230
+ /** Run one browse verb. Malformed input throws `Error`; typed refusals return in-band. */
231
+ export async function runMemoryBrowse(
232
+ deps: MemoryBrowseDeps,
233
+ request: MemoryStoreBrowseRequest,
234
+ ): Promise<MemoryStoreBrowseResult> {
235
+ const namespace = deps.resolveReadableNamespace(request.namespace, request.authenticatedPrincipal);
236
+ const storage = await deps.getStorage(namespace);
237
+ const memories = (await storage.readAllMemories()).filter((memory) => !isSupportPassportPrivateMemory(memory));
238
+
239
+ if (request.verb === "find") {
240
+ const pattern = (request.pattern ?? "").trim();
241
+ if (pattern.length === 0) return refusal(request.verb, "", "invalid_pattern", "pattern is required");
242
+ if (pattern.length > MAX_PATTERN_CHARS) {
243
+ return refusal(request.verb, "", "invalid_pattern", "pattern is too long");
244
+ }
245
+ const hits: MemoryBrowseEntry[] = [];
246
+ let truncated = false;
247
+ let total = 0;
248
+ for (const memory of memories) {
249
+ const rel = toMemoryPathRel(storage.dir, memory.path);
250
+ if (!isBrowsableMemoryPath(rel)) continue;
251
+ if (!browsePatternMatches(pattern, rel)) continue;
252
+ total += 1;
253
+ if (hits.length >= MAX_FIND_ENTRIES) {
254
+ truncated = true;
255
+ break;
256
+ }
257
+ hits.push({
258
+ path: rel,
259
+ kind: "file",
260
+ name: rel.split("/").pop() ?? rel,
261
+ description: normalizeProjectionPreview(memory.content),
262
+ count: 1,
263
+ depth: 0,
264
+ });
265
+ }
266
+ hits.sort(byPath);
267
+ return { ok: true, verb: "find", namespace, path: "", total, entries: hits, truncated, rendered: renderEntries("find", namespace, "", hits) };
268
+ }
269
+
270
+ let browsePath: string;
271
+ try {
272
+ browsePath = sanitizeBrowsePath(request.path);
273
+ } catch (err) {
274
+ return refusal(request.verb, request.path ?? "", "invalid_path", err instanceof Error ? err.message : String(err));
275
+ }
276
+ const root = buildIndex(memories, storage.dir);
277
+ let node: DirNode | undefined = root;
278
+ for (const segment of browsePath === "" ? [] : browsePath.split("/")) {
279
+ node = node?.subdirs.get(segment);
280
+ if (node === undefined) break;
281
+ }
282
+ // Invisible-by-design stores resolve as not_found, indistinguishable from
283
+ // a missing path: the index only ever contains browsable corpus paths.
284
+ if (node === undefined) {
285
+ return refusal(request.verb, browsePath, "not_found", `no browsable store path: ${browsePath}`);
286
+ }
287
+
288
+ if (request.verb === "ls") {
289
+ const all = dirEntries(node, browsePath);
290
+ const truncated = all.length > MAX_LS_ENTRIES;
291
+ const entries = all.slice(0, MAX_LS_ENTRIES);
292
+ return { ok: true, verb: "ls", namespace, path: browsePath, total: all.length, entries, truncated, rendered: renderEntries("ls", namespace, browsePath, entries) };
293
+ }
294
+
295
+ if (request.depth !== undefined && (!Number.isInteger(request.depth) || request.depth < 1 || request.depth > MAX_TREE_DEPTH)) {
296
+ return refusal(request.verb, browsePath, "invalid_depth", `depth must be an integer between 1 and ${MAX_TREE_DEPTH}`);
297
+ }
298
+ const depth = request.depth ?? 1;
299
+ const entries: MemoryBrowseEntry[] = [];
300
+ let truncated = false;
301
+ const walk = (current: DirNode, currentPath: string, currentDepth: number): void => {
302
+ for (const entry of dirEntries(current, currentPath)) {
303
+ if (entries.length >= MAX_TREE_ENTRIES) {
304
+ truncated = true;
305
+ return;
306
+ }
307
+ entries.push({ ...entry, depth: currentDepth });
308
+ if (entry.kind === "dir" && currentDepth < depth - 1) {
309
+ walk(current.subdirs.get(entry.name)!, entry.path, currentDepth + 1);
310
+ if (truncated) return;
311
+ }
312
+ }
313
+ };
314
+ walk(node, browsePath, 0);
315
+ return { ok: true, verb: "tree", namespace, path: browsePath, total: entries.length, entries, truncated, rendered: renderEntries("tree", namespace, browsePath, entries) };
316
+ }
package/src/provenance.ts CHANGED
@@ -652,11 +652,11 @@ function casefold(s: string): string {
652
652
  * this as a verified match and record a source without offsets (cursor
653
653
  * thread Ocver — "Normalized match drops verified provenance").
654
654
  */
655
- type LocateQuoteResult =
655
+ export type LocateQuoteResult =
656
656
  | { matched: false }
657
657
  | { matched: true; offsets?: { charStart: number; charEnd: number } };
658
658
 
659
- function locateQuoteOffsets(quote: string, text: string): LocateQuoteResult {
659
+ export function locateQuoteOffsets(quote: string, text: string): LocateQuoteResult {
660
660
  // 1. Exact substring match (handles unicode, curly quotes, emoji verbatim).
661
661
  const exactIdx = text.indexOf(quote);
662
662
  if (exactIdx >= 0) {
@@ -769,7 +769,7 @@ function locateQuoteOffsets(quote: string, text: string): LocateQuoteResult {
769
769
  * original meaning (chatgpt-codex-connector thread 4xA — limiting role-prefix
770
770
  * stripping to actual prompt labels).
771
771
  */
772
- function stripLeadingRolePrefix(quote: string): string {
772
+ export function stripLeadingRolePrefix(quote: string): string {
773
773
  return quote.replace(/^\s*\[(?:context\s+)?(?:user|assistant)\]\s+/i, "");
774
774
  }
775
775
 
@@ -2,6 +2,9 @@ import assert from "node:assert/strict";
2
2
  import test from "node:test";
3
3
 
4
4
  import {
5
+ boundRecallContextComposition,
6
+ composeMissingMemoryContext,
7
+ composeRecallContext,
5
8
  formatCuriosityFooter,
6
9
  renderMemoryContextPrompt,
7
10
  selectCuriosityQuestion,
@@ -88,3 +91,66 @@ test("renderMemoryContextPrompt caps context before its footer deterministically
88
91
  assert.ok(rendered);
89
92
  assert.equal(rendered.body, "ab\n\n---\n\nfooter");
90
93
  });
94
+
95
+ test("#2972 healthy recall carries no degradation marker", () => {
96
+ const composition = boundRecallContextComposition({
97
+ context: "A remembered deployment decision.",
98
+ maxChars: 512,
99
+ });
100
+
101
+ assert.equal("degradation" in composition, false);
102
+ assert.ok(!JSON.stringify(composition).includes("degradation"));
103
+ });
104
+
105
+ test("#2972 budget-clipped context is marked degraded, not silently cut", () => {
106
+ const composition = boundRecallContextComposition({
107
+ context: "x".repeat(100),
108
+ maxChars: 20,
109
+ });
110
+
111
+ assert.equal(composition.degradation?.state, "degraded");
112
+ assert.equal(composition.degradation?.reason, "budget-clipped");
113
+ assert.equal(composition.degradation?.budget?.fullChars, 100);
114
+ assert.ok(
115
+ (composition.degradation?.budget?.deliveredChars ?? 0) <
116
+ (composition.degradation?.budget?.fullChars ?? 0),
117
+ );
118
+ });
119
+
120
+ test("#2972 a fitting compact context is preferred over clipping the tail", () => {
121
+ const composition = boundRecallContextComposition({
122
+ context: "full-form entry one\n\nfull-form entry two",
123
+ compactContext: "entry one\nentry two",
124
+ maxChars: 30,
125
+ });
126
+
127
+ assert.equal(composition.context, "entry one\nentry two");
128
+ assert.equal(composition.degradation?.state, "degraded");
129
+ assert.equal(composition.degradation?.reason, "budget-compacted");
130
+ assert.equal(composition.degradation?.budget?.deliveredChars, 19);
131
+ });
132
+
133
+ test("#2972 a compact form that is not shallower than the full context is ignored", () => {
134
+ const composition = boundRecallContextComposition({
135
+ context: "x".repeat(50),
136
+ compactContext: "y".repeat(60),
137
+ maxChars: 10,
138
+ });
139
+
140
+ assert.equal(composition.degradation?.reason, "budget-clipped");
141
+ });
142
+
143
+ test("#2972 backend failure yields an explicit missing note, never an empty string", () => {
144
+ const composition = composeMissingMemoryContext({ detail: "backend_unavailable" });
145
+ const body = composeRecallContext(composition);
146
+
147
+ assert.ok(body.length > 0);
148
+ assert.match(body, /memory context unavailable/i);
149
+ assert.equal(composition.degradation?.state, "missing");
150
+ assert.equal(composition.degradation?.reason, "backend-unavailable");
151
+ assert.equal(composition.degradation?.detail, "backend_unavailable");
152
+
153
+ const rendered = renderMemoryContextPrompt({ ...composition, maxChars: 512 });
154
+ assert.ok(rendered);
155
+ assert.match(rendered.body, /memory context unavailable/i);
156
+ });
@@ -35,6 +35,33 @@ const TRIM_MARKER = "\n\n...(memory context trimmed)";
35
35
  export interface RecallContextComposition {
36
36
  context: string;
37
37
  footer?: string;
38
+ /**
39
+ * Machine-readable degradation marker (#2972). Absent on a healthy
40
+ * recall so the healthy wire shape stays byte-stable. Budget warnings
41
+ * ride here — never inside the injected text — so the block stays
42
+ * cache-stable while degradation stays inspectable.
43
+ */
44
+ degradation?: RecallContextDegradation;
45
+ }
46
+
47
+ export type RecallDegradationState = "complete" | "degraded" | "missing";
48
+
49
+ export type RecallDegradationReason =
50
+ | "budget-clipped"
51
+ | "budget-compacted"
52
+ | "backend-unavailable";
53
+
54
+ export interface RecallContextDegradation {
55
+ state: RecallDegradationState;
56
+ reason: RecallDegradationReason;
57
+ /** Operator-facing detail (e.g. a SearchDegradation code). */
58
+ detail?: string;
59
+ /** Budget accounting, present on budget-driven degradation. */
60
+ budget?: {
61
+ contextBudget: number;
62
+ fullChars: number;
63
+ deliveredChars: number;
64
+ };
38
65
  }
39
66
 
40
67
  export interface CuriosityQuestion {
@@ -53,6 +80,14 @@ export interface RenderedMemoryContextPrompt {
53
80
 
54
81
  export interface RenderMemoryContextPromptInput extends RecallContextComposition {
55
82
  maxChars: number;
83
+ /**
84
+ * Pre-rendered shallow form of every entry (#2972). When the full
85
+ * context exceeds budget, a fitting compact form is delivered instead
86
+ * of clipping the tail — breadth-complete-but-shallow over
87
+ * deep-but-amputated. Ignored unless strictly shorter than the full
88
+ * context and within budget.
89
+ */
90
+ compactContext?: string;
56
91
  }
57
92
 
58
93
  function trimText(value: string | undefined): string {
@@ -96,14 +131,77 @@ export function boundRecallContextComposition({
96
131
  context: rawContext,
97
132
  footer: rawFooter,
98
133
  maxChars,
134
+ compactContext: rawCompactContext,
99
135
  }: RenderMemoryContextPromptInput): RecallContextComposition {
100
136
  if (!Number.isFinite(maxChars) || maxChars <= 0) return { context: "" };
101
137
 
102
138
  const limit = Math.floor(maxChars);
103
139
  const footer = trimText(rawFooter);
104
- const context = truncateToBudget(trimText(rawContext), contextBudgetForFooter(limit, footer));
140
+ const contextBudget = contextBudgetForFooter(limit, footer);
141
+ const fullContext = trimText(rawContext);
142
+ let context = fullContext;
143
+ let degradation: RecallContextDegradation | undefined;
144
+ if (fullContext.length > contextBudget) {
145
+ const compactContext = trimText(rawCompactContext);
146
+ if (
147
+ compactContext.length > 0 &&
148
+ compactContext.length <= contextBudget &&
149
+ compactContext.length < fullContext.length
150
+ ) {
151
+ context = compactContext;
152
+ degradation = {
153
+ state: "degraded",
154
+ reason: "budget-compacted",
155
+ budget: {
156
+ contextBudget,
157
+ fullChars: fullContext.length,
158
+ deliveredChars: compactContext.length,
159
+ },
160
+ };
161
+ } else {
162
+ context = truncateToBudget(fullContext, contextBudget);
163
+ degradation = {
164
+ state: "degraded",
165
+ reason: "budget-clipped",
166
+ budget: {
167
+ contextBudget,
168
+ fullChars: fullContext.length,
169
+ deliveredChars: context.length,
170
+ },
171
+ };
172
+ }
173
+ }
174
+ // Footer truncation is fixed overhead, not lost memory content; the
175
+ // degradation contract covers the recall context only.
105
176
  const boundedFooter = footer.length > limit ? truncateToBudget(footer, limit) : footer;
106
- return { context, ...(boundedFooter ? { footer: boundedFooter } : {}) };
177
+ return {
178
+ context,
179
+ ...(boundedFooter ? { footer: boundedFooter } : {}),
180
+ ...(degradation ? { degradation } : {}),
181
+ };
182
+ }
183
+
184
+ export const MEMORY_CONTEXT_UNAVAILABLE_NOTE =
185
+ "Memory context unavailable for this turn: recall failed. " +
186
+ "This means the memory backend could not be queried — it does not mean " +
187
+ "no relevant memories exist.";
188
+
189
+ /**
190
+ * Missing state (#2972): a failed recall path composes this INSTEAD of an
191
+ * empty or silently truncated context, so "backend failed" is never
192
+ * indistinguishable from "no relevant memories" (the injection-side twin
193
+ * of Review-Prevention rule 22). Replace the bounded composition with
194
+ * this result on failure; do not run it back through bounding.
195
+ */
196
+ export function composeMissingMemoryContext(input: { detail?: string } = {}): RecallContextComposition {
197
+ return {
198
+ context: MEMORY_CONTEXT_UNAVAILABLE_NOTE,
199
+ degradation: {
200
+ state: "missing",
201
+ reason: "backend-unavailable",
202
+ ...(input.detail ? { detail: input.detail } : {}),
203
+ },
204
+ };
107
205
  }
108
206
  export function composeRecallContext(composition: RecallContextComposition): string {
109
207
  const context = trimText(composition.context);
@@ -117,11 +215,13 @@ export function renderMemoryContextPrompt({
117
215
  context: rawContext,
118
216
  footer: rawFooter,
119
217
  maxChars,
218
+ compactContext: rawCompactContext,
120
219
  }: RenderMemoryContextPromptInput): RenderedMemoryContextPrompt | null {
121
220
  const bounded = boundRecallContextComposition({
122
221
  context: rawContext,
123
222
  footer: rawFooter,
124
223
  maxChars,
224
+ compactContext: rawCompactContext,
125
225
  });
126
226
  const body = composeRecallContext(bounded);
127
227
  if (body.length === 0) return null;
@@ -39,6 +39,33 @@ test("peer manifest revision includes the citation-template fingerprint", () =>
39
39
  assert.equal(peerManifestRevision("{{source}}"), custom);
40
40
  });
41
41
 
42
+ test("buildReconcileManifest stops scheduling read batches once the signal aborts (#2954)", async () => {
43
+ const controller = new AbortController();
44
+ let reads = 0;
45
+ const stub = Buffer.from("stub");
46
+ // 120 files = three 50-file read batches; the abort lands inside batch 1.
47
+ const files = Array.from({ length: 120 }, (_, i) => ({
48
+ path: `facts/batch-abort-${i}.md`,
49
+ sha256: createHash("sha256").update(String(i)).digest("hex"),
50
+ }));
51
+ await assert.rejects(
52
+ buildReconcileManifest({
53
+ files,
54
+ parseMemory: parseFrontmatter,
55
+ signal: controller.signal,
56
+ readFile: async () => {
57
+ reads += 1;
58
+ if (reads === 1) controller.abort();
59
+ return stub;
60
+ },
61
+ }),
62
+ (error: unknown) => (error as Error)?.name === "AbortError"
63
+ );
64
+ // Batch 1 was already in flight when the abort landed, so exactly its 50
65
+ // reads ran; batches 2 and 3 must never be scheduled.
66
+ assert.equal(reads, 50);
67
+ });
68
+
42
69
  test("reconcile manifest keeps file identity separate from canonical semantic identity", async () => {
43
70
  const content = "The deployment uses a durable queue with an enrichment suffix.";
44
71
  const semanticHash = ContentHashIndex.computeHash("The deployment uses a durable queue.");
@@ -82,6 +82,9 @@ export interface BuildReconcileManifestOptions {
82
82
  parseMemory: ReconcileMemoryParser;
83
83
  cachedFiles?: Iterable<ReconcileManifestFile>;
84
84
  citationTemplate?: string;
85
+ /** Cancellation (#2954): checked between read batches so an aborted run
86
+ * stops scheduling new file reads instead of walking the whole corpus. */
87
+ signal?: AbortSignal;
85
88
  }
86
89
 
87
90
  const SHA256_PATTERN = /^[a-f0-9]{64}$/i;
@@ -287,6 +290,10 @@ export async function buildReconcileManifest(options: BuildReconcileManifestOpti
287
290
  }
288
291
  }
289
292
  for (let i = 0; i < uncached.length; i += MANIFEST_BUILD_BATCH_SIZE) {
293
+ // Between batches, not within one: an abort mid-batch lets the in-flight
294
+ // reads settle (their own fetch signal does the aborting) and stops the
295
+ // NEXT batch from ever being scheduled.
296
+ options.signal?.throwIfAborted();
290
297
  const batch = uncached.slice(i, i + MANIFEST_BUILD_BATCH_SIZE);
291
298
  const results = await Promise.all(
292
299
  batch.map(({ file }) =>