@remnic/core 9.48.1 → 9.49.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (240) hide show
  1. package/dist/access-admin-ops-surface.d.ts +6 -5
  2. package/dist/access-admin-ops-surface.js +27 -26
  3. package/dist/access-audit.js +2 -2
  4. package/dist/access-authorization-probe.d.ts +6 -5
  5. package/dist/access-authorization-probe.js +28 -27
  6. package/dist/access-boundary.d.ts +6 -5
  7. package/dist/access-boundary.js +27 -26
  8. package/dist/access-cli.js +64 -63
  9. package/dist/access-cli.js.map +1 -1
  10. package/dist/access-extraction-force-flush.d.ts +6 -5
  11. package/dist/access-extraction-force-flush.js +27 -26
  12. package/dist/access-http-lcm-compaction.d.ts +6 -5
  13. package/dist/access-http-lifecycle-flush.d.ts +6 -5
  14. package/dist/access-http-offline-stream.d.ts +6 -5
  15. package/dist/access-http-query.js +27 -26
  16. package/dist/access-http.d.ts +6 -5
  17. package/dist/access-http.js +35 -34
  18. package/dist/access-identity-continuity-surface.d.ts +5 -4
  19. package/dist/access-identity-continuity-surface.js +27 -26
  20. package/dist/access-lcm-surface.d.ts +6 -5
  21. package/dist/access-lcm-surface.js +27 -26
  22. package/dist/access-mcp.d.ts +6 -5
  23. package/dist/access-mcp.js +33 -32
  24. package/dist/access-namespace-preflight.js +27 -26
  25. package/dist/access-observe-write-surface.d.ts +6 -5
  26. package/dist/access-observe-write-surface.js +27 -26
  27. package/dist/access-offline-manifest.d.ts +5 -4
  28. package/dist/access-operations-batch.js +29 -28
  29. package/dist/access-operations.d.ts +6 -5
  30. package/dist/access-operations.js +32 -31
  31. package/dist/access-recall-concurrency.d.ts +6 -5
  32. package/dist/access-recall-concurrency.js +27 -26
  33. package/dist/access-recall-response.d.ts +6 -5
  34. package/dist/access-recall-response.js +27 -26
  35. package/dist/access-recall-surface.d.ts +6 -5
  36. package/dist/access-recall-surface.js +27 -26
  37. package/dist/access-schema.js +3 -3
  38. package/dist/{access-service-andNjwfD.d.ts → access-service-DvXOzCrM.d.ts} +3 -3
  39. package/dist/access-service-helpers.d.ts +6 -5
  40. package/dist/access-service.d.ts +6 -5
  41. package/dist/access-service.js +27 -26
  42. package/dist/access-surface-catalog.d.ts +6 -5
  43. package/dist/access-wearables-meetings-surface.d.ts +3 -2
  44. package/dist/bootstrap.d.ts +5 -4
  45. package/dist/briefing.d.ts +2 -1
  46. package/dist/briefing.js +7 -6
  47. package/dist/buffer.d.ts +2 -1
  48. package/dist/{capsule-crypto-7FJQINUR.js → capsule-crypto-YO5QJ6L3.js} +2 -2
  49. package/dist/{capsule-merge-Q6AR3XL7.js → capsule-merge-6GFHWECG.js} +4 -4
  50. package/dist/causal-consolidation.js +8 -7
  51. package/dist/causal-consolidation.js.map +1 -1
  52. package/dist/{chunk-FMCHFSZF.js → chunk-2RIWJUSQ.js} +6 -6
  53. package/dist/{chunk-S55OAS5P.js → chunk-2VHLLPTX.js} +4 -4
  54. package/dist/{chunk-GWHPQOUC.js → chunk-3R6D33UF.js} +2 -2
  55. package/dist/{chunk-PELT6ADC.js → chunk-5AGR7SAI.js} +3 -3
  56. package/dist/chunk-5GINB5LC.js +13 -0
  57. package/dist/chunk-5GINB5LC.js.map +1 -0
  58. package/dist/{chunk-FJ2ND6CZ.js → chunk-5JRC6BYS.js} +10 -10
  59. package/dist/{chunk-A2TFK5PG.js → chunk-ABR2HEJO.js} +2 -2
  60. package/dist/{chunk-NXUJRXSF.js → chunk-B6KGGRUL.js} +2 -2
  61. package/dist/{chunk-PRVJH7CY.js → chunk-BMCHFWGX.js} +2 -2
  62. package/dist/{chunk-2NLLXCJG.js → chunk-BXLOS5AJ.js} +2 -2
  63. package/dist/{chunk-ANCC3JJH.js → chunk-C3KVFJH5.js} +2 -2
  64. package/dist/{chunk-JYPO7L3G.js → chunk-CNQQMB67.js} +2 -2
  65. package/dist/{chunk-X7Y7WX73.js → chunk-DQEMWVMT.js} +1 -1
  66. package/dist/{chunk-2EJNXE53.js → chunk-ENEA47UC.js} +2 -2
  67. package/dist/{chunk-PLCZD3LG.js → chunk-EY64JLOM.js} +66 -31
  68. package/dist/chunk-EY64JLOM.js.map +1 -0
  69. package/dist/{chunk-4WBGZYZZ.js → chunk-EYAIZBLM.js} +4 -4
  70. package/dist/chunk-EYAIZBLM.js.map +1 -0
  71. package/dist/{chunk-YNDLCWXS.js → chunk-EZ25VE3G.js} +4 -4
  72. package/dist/{chunk-HAYSYUAB.js → chunk-FMXJ555A.js} +2 -2
  73. package/dist/{chunk-VANZKHTN.js → chunk-G5OB4XZX.js} +4 -4
  74. package/dist/{chunk-DUEEQCTT.js → chunk-I3YHVVT4.js} +2 -2
  75. package/dist/{chunk-3JUYWPFJ.js → chunk-I4TQST3L.js} +2 -2
  76. package/dist/{chunk-HIDEBEAN.js → chunk-IPBNC77A.js} +8 -8
  77. package/dist/{chunk-45OTV7FZ.js → chunk-IXPKESVP.js} +11 -11
  78. package/dist/{chunk-KSGEGHYA.js → chunk-IZANPXMV.js} +34 -34
  79. package/dist/{chunk-IP3DHDU2.js → chunk-JFLOOTXU.js} +3 -3
  80. package/dist/{chunk-XL3TATMJ.js → chunk-JHMAYABJ.js} +4 -4
  81. package/dist/{chunk-HRMEYQRO.js → chunk-JXZ7NLYH.js} +2 -2
  82. package/dist/{chunk-53AJILXF.js → chunk-K7VKAHFE.js} +4 -4
  83. package/dist/{chunk-IJ7HK452.js → chunk-KMAP7SNQ.js} +2 -2
  84. package/dist/{chunk-D5NGH2EW.js → chunk-L6DCVUCA.js} +2 -2
  85. package/dist/{chunk-M4DMO67I.js → chunk-LQL7ARIC.js} +3 -3
  86. package/dist/{chunk-3NDN5P55.js → chunk-MXPB6PJQ.js} +2 -2
  87. package/dist/{chunk-RSPSHRZA.js → chunk-MZZR3J6M.js} +2 -2
  88. package/dist/{chunk-YLHM5BQQ.js → chunk-OLX2HJFW.js} +4 -4
  89. package/dist/{chunk-NIS256NW.js → chunk-QKD65RGL.js} +2 -2
  90. package/dist/{chunk-A4JMGKCD.js → chunk-R5IGA2NH.js} +4 -4
  91. package/dist/chunk-RBOJCG4T.js +77 -0
  92. package/dist/chunk-RBOJCG4T.js.map +1 -0
  93. package/dist/{chunk-7YKVM5H3.js → chunk-RHTO4HTL.js} +2 -2
  94. package/dist/{chunk-GD7UPIBG.js → chunk-RJV6Q2FT.js} +2 -2
  95. package/dist/{chunk-5L7PTX2Q.js → chunk-SHDZNSK4.js} +2 -2
  96. package/dist/{chunk-WOEVJKKQ.js → chunk-SMPVHGHG.js} +3 -3
  97. package/dist/{chunk-7K5Q6COX.js → chunk-TVVEYCNW.js} +4 -4
  98. package/dist/{chunk-52I3YZZ6.js → chunk-ULWHRQEQ.js} +2 -2
  99. package/dist/{chunk-KQAFEZQX.js → chunk-VDX2J7OX.js} +2 -2
  100. package/dist/{chunk-2P3GQVM2.js → chunk-YQIVWS7Y.js} +50 -41
  101. package/dist/chunk-YQIVWS7Y.js.map +1 -0
  102. package/dist/{chunk-G2RBWVFQ.js → chunk-Z4U6U3M3.js} +2 -2
  103. package/dist/{chunk-EZNXW27Q.js → chunk-Z5UC3OKB.js} +6 -6
  104. package/dist/{cli-p_WmVo2h.d.ts → cli-PyAUaozE.d.ts} +3 -3
  105. package/dist/cli.d.ts +7 -6
  106. package/dist/cli.js +52 -51
  107. package/dist/compounding/engine.d.ts +2 -1
  108. package/dist/compounding/engine.js +7 -6
  109. package/dist/connectors/codex-materialize-runner.js +7 -6
  110. package/dist/connectors/index.js +7 -6
  111. package/dist/consolidation-provenance-check.d.ts +2 -1
  112. package/dist/consolidation-provenance-check.js +4 -4
  113. package/dist/consolidation-undo.d.ts +2 -1
  114. package/dist/consolidation-undo.js +3 -3
  115. package/dist/contradiction/index.d.ts +2 -1
  116. package/dist/convergence-refresh.d.ts +2 -1
  117. package/dist/convergence-refresh.js +9 -8
  118. package/dist/corpus-read-cancellation.d.ts +38 -0
  119. package/dist/corpus-read-cancellation.js +9 -0
  120. package/dist/corpus-read-cancellation.js.map +1 -0
  121. package/dist/corpus-watermark.js +16 -15
  122. package/dist/dashboard-runtime.js +2 -2
  123. package/dist/entity-retrieval.d.ts +2 -1
  124. package/dist/entity-retrieval.js +7 -6
  125. package/dist/explicit-capture.d.ts +5 -4
  126. package/dist/external-wiki-access.d.ts +6 -5
  127. package/dist/external-wiki-access.js +28 -27
  128. package/dist/external-wiki-mcp-tools.d.ts +6 -5
  129. package/dist/extraction.js +8 -7
  130. package/dist/in-flight-reads.d.ts +46 -2
  131. package/dist/in-flight-reads.js +5 -3
  132. package/dist/index.d.ts +11 -10
  133. package/dist/index.js +68 -67
  134. package/dist/lcm/index.js +3 -3
  135. package/dist/maintenance/memory-governance.js +7 -6
  136. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -1
  137. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +7 -6
  138. package/dist/maintenance/rebuild-memory-projection.d.ts +2 -1
  139. package/dist/maintenance/rebuild-memory-projection.js +8 -7
  140. package/dist/{maintenance-BfcuwfJS.d.ts → maintenance-j7sfNQdK.d.ts} +1 -1
  141. package/dist/mcp-memory-inspector-app.d.ts +6 -5
  142. package/dist/memory-corpus-version.js +2 -2
  143. package/dist/memory-worth-outcomes.d.ts +2 -1
  144. package/dist/namespaces/migrate.d.ts +2 -1
  145. package/dist/namespaces/migrate.js +15 -14
  146. package/dist/namespaces/search.js +7 -7
  147. package/dist/namespaces/storage.d.ts +2 -1
  148. package/dist/namespaces/storage.js +7 -6
  149. package/dist/operator-doctor-corpus.js +17 -16
  150. package/dist/operator-toolkit.d.ts +2 -1
  151. package/dist/operator-toolkit.js +22 -21
  152. package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -1
  153. package/dist/orchestration/maintenance.d.ts +3 -2
  154. package/dist/orchestration/maintenance.js +12 -11
  155. package/dist/{orchestrator-B7nLo4z1.d.ts → orchestrator-Haa9xVPV.d.ts} +3 -3
  156. package/dist/orchestrator.d.ts +5 -4
  157. package/dist/orchestrator.js +64 -63
  158. package/dist/page-versioning.js +3 -3
  159. package/dist/search/factory.js +6 -6
  160. package/dist/search/index.js +11 -11
  161. package/dist/search/lancedb-backend.js +2 -2
  162. package/dist/search/meilisearch-backend.js +2 -2
  163. package/dist/search/orama-backend.js +2 -2
  164. package/dist/semantic-consolidation.js +8 -7
  165. package/dist/semantic-rule-promotion.js +7 -6
  166. package/dist/semantic-rule-verifier.js +7 -6
  167. package/dist/{service-B5W5IYCx.d.ts → service-Da_BI4S8.d.ts} +1 -1
  168. package/dist/source-agent-qualifier.js +7 -6
  169. package/dist/{storage-COL907QF.d.ts → storage-D1apCiCS.d.ts} +4 -3
  170. package/dist/storage.d.ts +2 -1
  171. package/dist/storage.js +6 -5
  172. package/dist/temporal-supersession.d.ts +2 -1
  173. package/dist/tier-migration.d.ts +2 -1
  174. package/dist/transfer/backup.js +2 -2
  175. package/dist/transfer/capsule-export.js +2 -2
  176. package/dist/transfer/capsule-import.js +5 -5
  177. package/dist/verified-recall.js +7 -6
  178. package/package.json +2 -2
  179. package/src/corpus-read-cancellation.ts +42 -0
  180. package/src/entity-retrieval.ts +4 -4
  181. package/src/in-flight-reads.ts +119 -6
  182. package/src/orchestration/namespace-read-fanout.ts +13 -2
  183. package/src/orchestration/recall-internal-deps.ts +2 -0
  184. package/src/orchestration/recall-internal.ts +4 -1
  185. package/src/orchestration/recall-search-pipeline.ts +2 -0
  186. package/src/orchestration/recall-search-prefilter.ts +5 -1
  187. package/src/orchestrator.ts +5 -5
  188. package/src/storage/entity-store.ts +9 -2
  189. package/src/storage/memory-read-store.ts +33 -4
  190. package/src/storage-contract/corpus-read-cancellation.test.ts +408 -0
  191. package/src/storage.ts +61 -19
  192. package/dist/chunk-2P3GQVM2.js.map +0 -1
  193. package/dist/chunk-4WBGZYZZ.js.map +0 -1
  194. package/dist/chunk-PDJTHRAW.js +0 -36
  195. package/dist/chunk-PDJTHRAW.js.map +0 -1
  196. package/dist/chunk-PLCZD3LG.js.map +0 -1
  197. /package/dist/{capsule-crypto-7FJQINUR.js.map → capsule-crypto-YO5QJ6L3.js.map} +0 -0
  198. /package/dist/{capsule-merge-Q6AR3XL7.js.map → capsule-merge-6GFHWECG.js.map} +0 -0
  199. /package/dist/{chunk-FMCHFSZF.js.map → chunk-2RIWJUSQ.js.map} +0 -0
  200. /package/dist/{chunk-S55OAS5P.js.map → chunk-2VHLLPTX.js.map} +0 -0
  201. /package/dist/{chunk-GWHPQOUC.js.map → chunk-3R6D33UF.js.map} +0 -0
  202. /package/dist/{chunk-PELT6ADC.js.map → chunk-5AGR7SAI.js.map} +0 -0
  203. /package/dist/{chunk-FJ2ND6CZ.js.map → chunk-5JRC6BYS.js.map} +0 -0
  204. /package/dist/{chunk-A2TFK5PG.js.map → chunk-ABR2HEJO.js.map} +0 -0
  205. /package/dist/{chunk-NXUJRXSF.js.map → chunk-B6KGGRUL.js.map} +0 -0
  206. /package/dist/{chunk-PRVJH7CY.js.map → chunk-BMCHFWGX.js.map} +0 -0
  207. /package/dist/{chunk-2NLLXCJG.js.map → chunk-BXLOS5AJ.js.map} +0 -0
  208. /package/dist/{chunk-ANCC3JJH.js.map → chunk-C3KVFJH5.js.map} +0 -0
  209. /package/dist/{chunk-JYPO7L3G.js.map → chunk-CNQQMB67.js.map} +0 -0
  210. /package/dist/{chunk-X7Y7WX73.js.map → chunk-DQEMWVMT.js.map} +0 -0
  211. /package/dist/{chunk-2EJNXE53.js.map → chunk-ENEA47UC.js.map} +0 -0
  212. /package/dist/{chunk-YNDLCWXS.js.map → chunk-EZ25VE3G.js.map} +0 -0
  213. /package/dist/{chunk-HAYSYUAB.js.map → chunk-FMXJ555A.js.map} +0 -0
  214. /package/dist/{chunk-VANZKHTN.js.map → chunk-G5OB4XZX.js.map} +0 -0
  215. /package/dist/{chunk-DUEEQCTT.js.map → chunk-I3YHVVT4.js.map} +0 -0
  216. /package/dist/{chunk-3JUYWPFJ.js.map → chunk-I4TQST3L.js.map} +0 -0
  217. /package/dist/{chunk-HIDEBEAN.js.map → chunk-IPBNC77A.js.map} +0 -0
  218. /package/dist/{chunk-45OTV7FZ.js.map → chunk-IXPKESVP.js.map} +0 -0
  219. /package/dist/{chunk-KSGEGHYA.js.map → chunk-IZANPXMV.js.map} +0 -0
  220. /package/dist/{chunk-IP3DHDU2.js.map → chunk-JFLOOTXU.js.map} +0 -0
  221. /package/dist/{chunk-XL3TATMJ.js.map → chunk-JHMAYABJ.js.map} +0 -0
  222. /package/dist/{chunk-HRMEYQRO.js.map → chunk-JXZ7NLYH.js.map} +0 -0
  223. /package/dist/{chunk-53AJILXF.js.map → chunk-K7VKAHFE.js.map} +0 -0
  224. /package/dist/{chunk-IJ7HK452.js.map → chunk-KMAP7SNQ.js.map} +0 -0
  225. /package/dist/{chunk-D5NGH2EW.js.map → chunk-L6DCVUCA.js.map} +0 -0
  226. /package/dist/{chunk-M4DMO67I.js.map → chunk-LQL7ARIC.js.map} +0 -0
  227. /package/dist/{chunk-3NDN5P55.js.map → chunk-MXPB6PJQ.js.map} +0 -0
  228. /package/dist/{chunk-RSPSHRZA.js.map → chunk-MZZR3J6M.js.map} +0 -0
  229. /package/dist/{chunk-YLHM5BQQ.js.map → chunk-OLX2HJFW.js.map} +0 -0
  230. /package/dist/{chunk-NIS256NW.js.map → chunk-QKD65RGL.js.map} +0 -0
  231. /package/dist/{chunk-A4JMGKCD.js.map → chunk-R5IGA2NH.js.map} +0 -0
  232. /package/dist/{chunk-7YKVM5H3.js.map → chunk-RHTO4HTL.js.map} +0 -0
  233. /package/dist/{chunk-GD7UPIBG.js.map → chunk-RJV6Q2FT.js.map} +0 -0
  234. /package/dist/{chunk-5L7PTX2Q.js.map → chunk-SHDZNSK4.js.map} +0 -0
  235. /package/dist/{chunk-WOEVJKKQ.js.map → chunk-SMPVHGHG.js.map} +0 -0
  236. /package/dist/{chunk-7K5Q6COX.js.map → chunk-TVVEYCNW.js.map} +0 -0
  237. /package/dist/{chunk-52I3YZZ6.js.map → chunk-ULWHRQEQ.js.map} +0 -0
  238. /package/dist/{chunk-KQAFEZQX.js.map → chunk-VDX2J7OX.js.map} +0 -0
  239. /package/dist/{chunk-G2RBWVFQ.js.map → chunk-Z4U6U3M3.js.map} +0 -0
  240. /package/dist/{chunk-EZNXW27Q.js.map → chunk-Z5UC3OKB.js.map} +0 -0
package/dist/storage.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import './types-D_Au9qJO.js';
2
+ import './corpus-read-cancellation.js';
2
3
  import './artifact-search.js';
3
- export { C as ContentHashIndex, t as ContentHashIndexLockOptions, u as FactHashIndexNotAuthoritativeError, v as MemoryLifecycleEventWriteOptions, M as MemoryWriteResult, R as ReextractJobRequest, w as SealedWriteExtras, S as StorageManager, W as WriteMemoryOptions, x as buildEntitySchemaCacheKey, y as compareEntityTimestamps, z as compileEntityFacts, A as countEntityStructuredFacts, B as fingerprintEntityStructuredFacts, D as isEntitySynthesisStale, E as isValidBufferSurpriseEvent, G as normalizeFrontmatterForPath, H as normalizeStructuredSectionFacts, p as parseEntityFile, I as parseFrontmatter, J as parseFrontmatterStringValue, s as serializeEntityFile } from './storage-COL907QF.js';
4
+ export { C as ContentHashIndex, t as ContentHashIndexLockOptions, u as FactHashIndexNotAuthoritativeError, v as MemoryLifecycleEventWriteOptions, M as MemoryWriteResult, R as ReextractJobRequest, w as SealedWriteExtras, S as StorageManager, W as WriteMemoryOptions, x as buildEntitySchemaCacheKey, y as compareEntityTimestamps, z as compileEntityFacts, A as countEntityStructuredFacts, B as fingerprintEntityStructuredFacts, D as isEntitySynthesisStale, E as isValidBufferSurpriseEvent, G as normalizeFrontmatterForPath, H as normalizeStructuredSectionFacts, p as parseEntityFile, I as parseFrontmatter, J as parseFrontmatterStringValue, s as serializeEntityFile } from './storage-D1apCiCS.js';
4
5
  export { normalizeEntityName } from './entity-id-normalization.js';
5
6
  import './page-versioning.js';
6
7
  import './consolidation-operator.js';
package/dist/storage.js CHANGED
@@ -13,16 +13,16 @@ import {
13
13
  parseFrontmatter,
14
14
  parseFrontmatterStringValue,
15
15
  serializeEntityFile
16
- } from "./chunk-PLCZD3LG.js";
16
+ } from "./chunk-EY64JLOM.js";
17
17
  import "./chunk-UHVXE24Y.js";
18
18
  import "./chunk-ENTCVTQR.js";
19
19
  import "./chunk-SXIMQLGV.js";
20
20
  import "./chunk-S2V7RUCL.js";
21
21
  import "./chunk-J6A3CX5N.js";
22
22
  import "./chunk-3S63QIFQ.js";
23
+ import "./chunk-SCU65EZI.js";
23
24
  import "./chunk-WRJVB3C2.js";
24
25
  import "./chunk-S2HLHAZ4.js";
25
- import "./chunk-SCU65EZI.js";
26
26
  import "./chunk-DM2T26WE.js";
27
27
  import "./chunk-LDXUBPMO.js";
28
28
  import "./chunk-JYIJNNN3.js";
@@ -37,10 +37,11 @@ import "./chunk-BT7NVCML.js";
37
37
  import {
38
38
  normalizeEntityName
39
39
  } from "./chunk-YXZG5TVN.js";
40
+ import "./chunk-5GINB5LC.js";
40
41
  import "./chunk-G7D6GZ5J.js";
41
- import "./chunk-7YKVM5H3.js";
42
- import "./chunk-IJ7HK452.js";
43
- import "./chunk-PDJTHRAW.js";
42
+ import "./chunk-RHTO4HTL.js";
43
+ import "./chunk-KMAP7SNQ.js";
44
+ import "./chunk-RBOJCG4T.js";
44
45
  import "./chunk-NZBZ7IS2.js";
45
46
  import "./chunk-DNHVPZOD.js";
46
47
  import "./chunk-6CIAGZ6X.js";
@@ -1,10 +1,11 @@
1
1
  import { l as MemoryFrontmatter } from './types-D_Au9qJO.js';
2
- import { S as StorageManager } from './storage-COL907QF.js';
2
+ import { S as StorageManager } from './storage-D1apCiCS.js';
3
3
  import './message-parts/index.js';
4
4
  import './bounded-jsonl-state.js';
5
5
  import './operator-doctor-types.js';
6
6
  import './external-wiki-config.js';
7
7
  import './types-continuity.js';
8
+ import './corpus-read-cancellation.js';
8
9
  import './artifact-search.js';
9
10
  import './entity-id-normalization.js';
10
11
  import './page-versioning.js';
@@ -1,5 +1,5 @@
1
1
  import { M as MemoryFile } from './types-D_Au9qJO.js';
2
- import { S as StorageManager } from './storage-COL907QF.js';
2
+ import { S as StorageManager } from './storage-D1apCiCS.js';
3
3
  import { MemoryTier } from './tier-routing.js';
4
4
  import { SearchBackend } from './search/port.js';
5
5
  import './message-parts/index.js';
@@ -7,6 +7,7 @@ import './bounded-jsonl-state.js';
7
7
  import './operator-doctor-types.js';
8
8
  import './external-wiki-config.js';
9
9
  import './types-continuity.js';
10
+ import './corpus-read-cancellation.js';
10
11
  import './artifact-search.js';
11
12
  import './entity-id-normalization.js';
12
13
  import './page-versioning.js';
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  backupMemoryDir
3
- } from "../chunk-2NLLXCJG.js";
3
+ } from "../chunk-BXLOS5AJ.js";
4
4
  import "../chunk-765K3SAT.js";
5
- import "../chunk-X7Y7WX73.js";
5
+ import "../chunk-DQEMWVMT.js";
6
6
  import "../chunk-J4EB7DNW.js";
7
7
  import "../chunk-BJMBJZ2Y.js";
8
8
  import "../chunk-UKJAGEXH.js";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  exportCapsule,
3
3
  isValidCapsuleSince
4
- } from "../chunk-KQAFEZQX.js";
4
+ } from "../chunk-VDX2J7OX.js";
5
5
  import "../chunk-WEHSQBFR.js";
6
- import "../chunk-X7Y7WX73.js";
6
+ import "../chunk-DQEMWVMT.js";
7
7
  import "../chunk-J4EB7DNW.js";
8
8
  import "../chunk-BJMBJZ2Y.js";
9
9
  import "../chunk-UKJAGEXH.js";
@@ -1,16 +1,16 @@
1
1
  import {
2
2
  importCapsule
3
- } from "../chunk-A4JMGKCD.js";
4
- import "../chunk-7YKVM5H3.js";
5
- import "../chunk-IJ7HK452.js";
6
- import "../chunk-PDJTHRAW.js";
3
+ } from "../chunk-R5IGA2NH.js";
4
+ import "../chunk-RHTO4HTL.js";
5
+ import "../chunk-KMAP7SNQ.js";
6
+ import "../chunk-RBOJCG4T.js";
7
7
  import "../chunk-NZBZ7IS2.js";
8
8
  import "../chunk-DNHVPZOD.js";
9
9
  import "../chunk-6CIAGZ6X.js";
10
10
  import "../chunk-XMMESCPD.js";
11
11
  import "../chunk-42JKGUFJ.js";
12
12
  import "../chunk-WEHSQBFR.js";
13
- import "../chunk-X7Y7WX73.js";
13
+ import "../chunk-DQEMWVMT.js";
14
14
  import "../chunk-BJMBJZ2Y.js";
15
15
  import "../chunk-UKJAGEXH.js";
16
16
  import "../chunk-FP2373TW.js";
@@ -1,18 +1,18 @@
1
1
  import {
2
2
  compareVerifiedEpisodeResults,
3
3
  searchVerifiedEpisodes
4
- } from "./chunk-GD7UPIBG.js";
4
+ } from "./chunk-RJV6Q2FT.js";
5
5
  import "./chunk-B7RWBZXW.js";
6
- import "./chunk-PLCZD3LG.js";
6
+ import "./chunk-EY64JLOM.js";
7
7
  import "./chunk-UHVXE24Y.js";
8
8
  import "./chunk-ENTCVTQR.js";
9
9
  import "./chunk-SXIMQLGV.js";
10
10
  import "./chunk-S2V7RUCL.js";
11
11
  import "./chunk-J6A3CX5N.js";
12
12
  import "./chunk-3S63QIFQ.js";
13
+ import "./chunk-SCU65EZI.js";
13
14
  import "./chunk-WRJVB3C2.js";
14
15
  import "./chunk-S2HLHAZ4.js";
15
- import "./chunk-SCU65EZI.js";
16
16
  import "./chunk-DM2T26WE.js";
17
17
  import "./chunk-LDXUBPMO.js";
18
18
  import "./chunk-JYIJNNN3.js";
@@ -22,10 +22,11 @@ import "./chunk-CGASUJVP.js";
22
22
  import "./chunk-R3DJVOSM.js";
23
23
  import "./chunk-BT7NVCML.js";
24
24
  import "./chunk-YXZG5TVN.js";
25
+ import "./chunk-5GINB5LC.js";
25
26
  import "./chunk-G7D6GZ5J.js";
26
- import "./chunk-7YKVM5H3.js";
27
- import "./chunk-IJ7HK452.js";
28
- import "./chunk-PDJTHRAW.js";
27
+ import "./chunk-RHTO4HTL.js";
28
+ import "./chunk-KMAP7SNQ.js";
29
+ import "./chunk-RBOJCG4T.js";
29
30
  import "./chunk-NZBZ7IS2.js";
30
31
  import "./chunk-DNHVPZOD.js";
31
32
  import "./chunk-6CIAGZ6X.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remnic/core",
3
- "version": "9.48.1",
3
+ "version": "9.49.0",
4
4
  "description": "Framework-agnostic Remnic memory engine — orchestrator, storage, extraction, search, trust zones",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -3096,7 +3096,7 @@
3096
3096
  "core"
3097
3097
  ],
3098
3098
  "peerDependencies": {
3099
- "@remnic/coding-graph": "^9.48.1"
3099
+ "@remnic/coding-graph": "^9.49.0"
3100
3100
  },
3101
3101
  "peerDependenciesMeta": {
3102
3102
  "@remnic/coding-graph": {
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Cancellation contract for the shared full-corpus read primitives (issue #2307).
3
+ *
4
+ * `readAllArtifactsCached`, `readAllEntityFiles`, `readAllMemories`, and the
5
+ * artifact source-status snapshot each walk and parse an entire memory tree. Issue
6
+ * #2291 bounded the recall providers that call them, so a timed-out recall returns
7
+ * on time — but the scan underneath kept running, and for the primitives without
8
+ * in-flight coalescing every abandoned request started another one. On a large or
9
+ * network-mounted store those pile up into sustained I/O no live request needs.
10
+ *
11
+ * The mechanism is a plain optional parameter, not ambient async context: these
12
+ * primitives have dozens of callers across extraction, maintenance, wearables, and
13
+ * coding surfaces, and an ambient signal would silently attach a request's
14
+ * cancellation to background work that merely shares its async context. An
15
+ * explicit parameter is greppable, and a caller that does not opt in behaves
16
+ * exactly as before.
17
+ *
18
+ * Two invariants bind every implementation:
19
+ *
20
+ * 1. **Checked before the cache lookup.** A caller that has already given up gets
21
+ * an `AbortError`, warm cache or not — the same contract the recall providers
22
+ * follow, so cancellation never depends on cache state.
23
+ * 2. **A cancelled read never publishes.** Every checkpoint throws, so control
24
+ * leaves before the cache write. A partial corpus must never be cached, or
25
+ * served, as if it were complete.
26
+ */
27
+
28
+ import { throwIfAborted } from "./abort-error.js";
29
+
30
+ export interface CorpusReadOptions {
31
+ /**
32
+ * Stops the read at its next directory, batch, or attempt boundary. A single
33
+ * in-flight file read is not interrupted; the boundaries are what bound the
34
+ * work, and on a tree large enough to matter there are thousands of them.
35
+ */
36
+ abortSignal?: AbortSignal;
37
+ }
38
+
39
+ /** Stop a corpus read at a scan boundary when its caller has given up. */
40
+ export function checkCorpusReadAbort(options?: CorpusReadOptions): void {
41
+ throwIfAborted(options?.abortSignal, "corpus read aborted");
42
+ }
@@ -550,12 +550,12 @@ async function buildEntityMentionIndex(
550
550
  const entityStatusVersionBefore = shouldPersistIndex ? storage.getMemoryStatusVersion() : undefined;
551
551
  const [previousIndex, entityFileSets, memorySets, nativeChunks] = await Promise.all([
552
552
  shouldPersistIndex ? readEntityIndexState(storage) : Promise.resolve(null),
553
- Promise.all(storages.map((scopedStorage) => scopedStorage.readAllEntityFiles())),
554
- Promise.all(storages.map((scopedStorage) => scopedStorage.readAllMemories())),
553
+ Promise.all(storages.map((scopedStorage) => scopedStorage.readAllEntityFiles({ abortSignal }))),
554
+ Promise.all(storages.map((scopedStorage) => scopedStorage.readAllMemories({ abortSignal }))),
555
555
  nativeChunksOverride ? Promise.resolve(nativeChunksOverride) : readNativeChunks(config, recallNamespaces),
556
556
  ]);
557
- // The bulk reads above cannot be interrupted mid-flight; stop before spending
558
- // the (larger) indexing pass over their results.
557
+ // The bulk reads now stop at their own scan boundaries (issue #2307); this
558
+ // checkpoint still guards the (larger) indexing pass over their results.
559
559
  checkEntityRecallAbort(abortSignal);
560
560
  // Pair each entity with the storage that owns it (#1534): canonical ids must
561
561
  // reflect that store's aliases and historical migration mappings, never another
@@ -14,8 +14,20 @@ import type { MemoryFile } from "./types.js";
14
14
  * an unlocked manager's decrypted scan must NOT be handed to a locked or
15
15
  * differently-keyed manager for the same dir — that would bypass the keyId
16
16
  * isolation getCachedMemories enforces. Locked/plaintext stores use keyId "".
17
+ *
18
+ * Since issue #2307 the registry also owns the scan's CANCELLATION, because
19
+ * whether a shared scan may be cancelled is purely a question of who is still
20
+ * attached to it — see `beginCoalescedScan`.
17
21
  */
18
- const inFlightReadsByKey = new Map<string, Promise<MemoryFile[]>>();
22
+ type InFlightEntry = {
23
+ read: Promise<MemoryFile[]>;
24
+ /** Readers still awaiting this scan. At zero the scan has no reason to finish. */
25
+ waiters: number;
26
+ /** Withdraw the slot and abort the scan. Absent for an uncancellable scan. */
27
+ cancel?: () => void;
28
+ };
29
+
30
+ const inFlightReadsByKey = new Map<string, InFlightEntry>();
19
31
 
20
32
  const DIR_SEP = "\u0000";
21
33
 
@@ -23,12 +35,113 @@ function composeKey(baseDir: string, keyId: string): string {
23
35
  return `${baseDir}${DIR_SEP}${keyId}`;
24
36
  }
25
37
 
26
- export function getInFlightRead(baseDir: string, keyId = ""): Promise<MemoryFile[]> | undefined {
27
- return inFlightReadsByKey.get(composeKey(baseDir, keyId));
38
+ /**
39
+ * A reader's attachment to a shared scan. `leave()` is idempotent per reader and
40
+ * must be called when that reader stops waiting — because its own signal fired, or
41
+ * because the scan settled.
42
+ */
43
+ export interface CoalescedScanWaiter {
44
+ leave(): void;
45
+ }
46
+
47
+ /**
48
+ * Cancellation lifecycle for a coalesced corpus scan (issue #2307).
49
+ *
50
+ * The rule is reference counting, not ownership: **the scan is cancelled when its
51
+ * LAST waiter leaves, and never before.** One reader can therefore not cancel work
52
+ * another still needs, and two readers that both give up do not leave a full disk
53
+ * scan running for nobody — which was the abandoned I/O this whole change exists to
54
+ * remove.
55
+ *
56
+ * On the last leave the slot is withdrawn from the registry BEFORE the controller
57
+ * fires, so a reader arriving later cannot attach to a promise already doomed to
58
+ * reject with an `AbortError` it never asked for; it starts a fresh scan instead.
59
+ */
60
+ export interface CoalescedScan extends CoalescedScanWaiter {
61
+ /** The signal the shared scan itself observes. */
62
+ readonly scanSignal: AbortSignal;
63
+ /** Publish the scan to the registry and arm cancellation. */
64
+ arm(read: Promise<MemoryFile[]>): void;
65
+ }
66
+
67
+ /** Build the per-reader `leave` closure: decrement once, cancel at zero. */
68
+ function trackWaiter(entry: InFlightEntry, callerSignal?: AbortSignal): CoalescedScanWaiter {
69
+ let left = false;
70
+ const leave = () => {
71
+ if (left) return;
72
+ left = true;
73
+ callerSignal?.removeEventListener("abort", onAbort);
74
+ entry.waiters -= 1;
75
+ if (entry.waiters <= 0) entry.cancel?.();
76
+ };
77
+ // Named so the listener can be removed again; `once` alone would leak the
78
+ // reference for a reader that leaves normally.
79
+ function onAbort() {
80
+ leave();
81
+ }
82
+ callerSignal?.addEventListener("abort", onAbort, { once: true });
83
+ return { leave };
28
84
  }
29
85
 
30
- export function setInFlightRead(baseDir: string, keyId: string, read: Promise<MemoryFile[]>): void {
31
- inFlightReadsByKey.set(composeKey(baseDir, keyId), read);
86
+ /**
87
+ * Attach to an existing scan for (baseDir, keyId), or `undefined` when none is in
88
+ * flight. The caller MUST `leave()` once it stops awaiting the returned promise.
89
+ */
90
+ export function attachInFlightReader(
91
+ baseDir: string,
92
+ keyId = "",
93
+ callerSignal?: AbortSignal,
94
+ ): { read: Promise<MemoryFile[]>; waiter: CoalescedScanWaiter } | undefined {
95
+ const entry = inFlightReadsByKey.get(composeKey(baseDir, keyId));
96
+ if (entry === undefined) return undefined;
97
+ entry.waiters += 1;
98
+ return { read: entry.read, waiter: trackWaiter(entry, callerSignal) };
99
+ }
100
+
101
+ /** Start a cancellable coalesced scan as its first waiter. */
102
+ export function beginCoalescedScan(
103
+ baseDir: string,
104
+ keyId: string,
105
+ callerSignal?: AbortSignal,
106
+ ): CoalescedScan {
107
+ const controller = new AbortController();
108
+ let waiter: CoalescedScanWaiter | undefined;
109
+ return {
110
+ scanSignal: controller.signal,
111
+ arm(read: Promise<MemoryFile[]>): void {
112
+ // `waiters: 1` IS the starter; trackWaiter only builds its leave closure
113
+ // (attaching readers do their own increment).
114
+ const entry: InFlightEntry = {
115
+ read,
116
+ waiters: 1,
117
+ cancel: () => {
118
+ deleteInFlightRead(baseDir, keyId, read);
119
+ controller.abort();
120
+ },
121
+ };
122
+ inFlightReadsByKey.set(composeKey(baseDir, keyId), entry);
123
+ waiter = trackWaiter(entry, callerSignal);
124
+ },
125
+ leave(): void {
126
+ waiter?.leave();
127
+ },
128
+ };
129
+ }
130
+
131
+ /**
132
+ * Register a scan promise directly, with no cancellation attached.
133
+ *
134
+ * For callers that own a promise rather than a scan they can abort — tests that
135
+ * seed a stale in-flight read, and any future producer outside `beginCoalescedScan`.
136
+ * The entry has no `cancel`, so waiters leaving is a no-op: an externally-owned
137
+ * promise is not this module's to abort.
138
+ */
139
+ export function setInFlightRead(
140
+ baseDir: string,
141
+ keyId: string,
142
+ read: Promise<MemoryFile[]>,
143
+ ): void {
144
+ inFlightReadsByKey.set(composeKey(baseDir, keyId), { read, waiters: 1 });
32
145
  }
33
146
 
34
147
  /**
@@ -41,7 +154,7 @@ export function deleteInFlightRead(
41
154
  expected?: Promise<MemoryFile[]>,
42
155
  ): void {
43
156
  const key = composeKey(baseDir, keyId);
44
- if (expected === undefined || inFlightReadsByKey.get(key) === expected) {
157
+ if (expected === undefined || inFlightReadsByKey.get(key)?.read === expected) {
45
158
  inFlightReadsByKey.delete(key);
46
159
  }
47
160
  }
@@ -27,6 +27,7 @@ import { mergeArtifactRecallCandidates, tokenizeRecallQuery } from "./orchestrat
27
27
  import { qmdCollectionPathParts } from "./qmd-result-resolver.js";
28
28
  import { qmdCollectionNamespaceFromPrefix as computeQmdCollectionNamespaceFromPrefix } from "./orchestrator-namespace-scope.js";
29
29
  import { resolveNamespaceFromStorageDir } from "../scopes/scope-plan.js";
30
+ import { checkCorpusReadAbort, type CorpusReadOptions } from "../corpus-read-cancellation.js";
30
31
  import type { ArtifactRecallOptions } from "./recall-search-prefilter.js";
31
32
  import type { SearchBackend, SearchExecutionOptions, SearchQueryOptions } from "../search/port.js";
32
33
  import type { MemoryFile, PluginConfig, QmdSearchResult } from "../types.js";
@@ -247,7 +248,9 @@ export class NamespaceReadFanoutCoordinator {
247
248
  async resolveArtifactSourceStatuses(
248
249
  storage: StorageManager,
249
250
  sourceIds: string[],
251
+ options?: CorpusReadOptions,
250
252
  ): Promise<Map<string, "active" | "superseded" | "archived" | "missing">> {
253
+ checkCorpusReadAbort(options);
251
254
  const currentStatusVersion = storage.getMemoryStatusVersion();
252
255
  const cached = this.deps.artifactSourceStatusCache.get(storage);
253
256
  let snapshot = cached;
@@ -266,8 +269,15 @@ export class NamespaceReadFanoutCoordinator {
266
269
  let latestVersionAfter = storage.getMemoryStatusVersion();
267
270
 
268
271
  for (let attempt = 0; attempt < MAX_STABLE_READ_ATTEMPTS; attempt += 1) {
272
+ // Each attempt is a full corpus read; an abandoned caller must not buy a
273
+ // second or third one (issue #2307).
274
+ checkCorpusReadAbort(options);
269
275
  const versionBefore = storage.getMemoryStatusVersion();
270
- const allMemories = await storage.readAllMemories();
276
+ const allMemories = await storage.readAllMemories(options);
277
+ // An abort landing between the read and the publish below would otherwise
278
+ // cache and return a snapshot to a caller that had already cancelled
279
+ // (issue #2307 review).
280
+ checkCorpusReadAbort(options);
271
281
  const versionAfter = storage.getMemoryStatusVersion();
272
282
  latestVersionAfter = versionAfter;
273
283
  latestStatuses = new Map(
@@ -467,12 +477,13 @@ export class NamespaceReadFanoutCoordinator {
467
477
 
468
478
  async readAllMemoriesForNamespaces(
469
479
  namespaces: string[],
480
+ options?: CorpusReadOptions,
470
481
  ): Promise<MemoryFile[]> {
471
482
  const uniq = Array.from(new Set(namespaces.filter(Boolean)));
472
483
  const lists = await Promise.all(
473
484
  uniq.map(async (ns) => {
474
485
  const sm = await this.deps.storageRouter.storageFor(ns);
475
- return sm.readAllMemories();
486
+ return sm.readAllMemories(options);
476
487
  }),
477
488
  );
478
489
  return lists.flat();
@@ -17,6 +17,7 @@ import type { NamespaceCatalog } from "../namespaces/catalog.js";
17
17
  import type { NamespaceStorageRouter } from "../namespaces/storage.js";
18
18
  import type { ObjectiveStateSearchResult } from "../objective-state.js";
19
19
  import type { IntentDebugSnapshot, QmdRecallSnapshot, QueryAwarePrefilter } from "../orchestrator.js";
20
+ import type { CorpusReadOptions } from "../corpus-read-cancellation.js";
20
21
  import type { ProfilingCollector } from "../profiling.js";
21
22
  import type { GraphRecallExpandedEntry, LastRecallBudgetSummary, LastRecallStore, RecallHandleHistoryStore } from "../recall-state.js";
22
23
  import type { RecallXraySnapshot } from "../recall-xray.js";
@@ -335,6 +336,7 @@ export interface RecallInternalDeps {
335
336
  ): void;
336
337
  readAllMemoriesForNamespaces(
337
338
  namespaces: string[],
339
+ options?: CorpusReadOptions,
338
340
  ): Promise<MemoryFile[]>;
339
341
  recallArtifactsAcrossNamespaces(
340
342
  prompt: string,
@@ -4414,7 +4414,10 @@ export class RecallInternalCoordinator {
4414
4414
  } else {
4415
4415
  const memories = await awaitAssemblyStep(
4416
4416
  "recent-memory-read",
4417
- () => this.deps.readAllMemoriesForNamespaces(recallNamespaces),
4417
+ (stepSignal) =>
4418
+ this.deps.readAllMemoriesForNamespaces(recallNamespaces, {
4419
+ abortSignal: stepSignal,
4420
+ }),
4418
4421
  [] as MemoryFile[],
4419
4422
  );
4420
4423
  if (memories.length > 0) {
@@ -34,6 +34,7 @@ import { RerankCache, rerankLocalOrNoop, reorderByRankedKeys } from "../rerank.j
34
34
  import type { SearchBackend, SearchDegradation, SearchExecutionOptions, SearchQueryOptions } from "../search/port.js";
35
35
  import { SecureStoreLockedError } from "../secure-store/index.js";
36
36
  import { isPathInsideStorageRoot } from "../storage-paths.js";
37
+ import type { CorpusReadOptions } from "../corpus-read-cancellation.js";
37
38
  import { extractTagsFromPrompt, isTemporalQuery, queryByDateRangeAsync, queryByTagsAsync, readIndexSnapshotAsync, recencyWindowFromPrompt } from "../temporal-index.js";
38
39
  import {
39
40
  buildQueryAwarePrefilter as buildQueryAwarePrefilterHelper,
@@ -206,6 +207,7 @@ export interface RecallSearchPipelineDeps {
206
207
  resolveArtifactSourceStatuses(
207
208
  storage: StorageManager,
208
209
  sourceIds: string[],
210
+ options?: CorpusReadOptions,
209
211
  ): Promise<Map<string, "active" | "superseded" | "archived" | "missing">>;
210
212
  resolveColdQmdResultForRecall(
211
213
  result: QmdSearchResult,
@@ -1,6 +1,7 @@
1
1
  import path from "node:path";
2
2
  import { resolveIndexingCapabilities, resolveMemoryLifecycleCapabilities } from "../capabilities.js";
3
3
  import type { EmbeddingFallback } from "../embedding-fallback.js";
4
+ import type { CorpusReadOptions } from "../corpus-read-cancellation.js";
4
5
  import type { StorageManager } from "../index.js";
5
6
  import type { NamespaceStorageRouter } from "../namespaces/storage.js";
6
7
  import {
@@ -27,6 +28,7 @@ export interface PrefilterAndArtifactDeps {
27
28
  resolveArtifactSourceStatuses(
28
29
  storage: StorageManager,
29
30
  sourceIds: string[],
31
+ options?: CorpusReadOptions,
30
32
  ): Promise<Map<string, "active" | "superseded" | "archived" | "missing">>;
31
33
  scopeQueryAwarePaths(
32
34
  paths: Set<string> | null,
@@ -84,7 +86,9 @@ export async function fetchActiveArtifactsForNamespace(
84
86
  throwIfRecallAborted(options.abortSignal);
85
87
  const sourceStatus =
86
88
  sourceIds.length > 0
87
- ? await deps.resolveArtifactSourceStatuses(storage, sourceIds)
89
+ ? await deps.resolveArtifactSourceStatuses(storage, sourceIds, {
90
+ abortSignal: options.abortSignal,
91
+ })
88
92
  : new Map<string, "active" | "superseded" | "archived" | "missing">();
89
93
 
90
94
  const filtered: MemoryFile[] = [];
@@ -121,6 +121,7 @@ import { ExtractionPersistCoordinator } from "./orchestration/extraction-persist
121
121
  import { RecallInternalCoordinator } from "./orchestration/recall-internal.js";
122
122
  import { RecallSearchPipelineCoordinator } from "./orchestration/recall-search-pipeline.js";
123
123
  import type { ArtifactRecallOptions } from "./orchestration/recall-search-prefilter.js";
124
+ import type { CorpusReadOptions } from "./corpus-read-cancellation.js";
124
125
  import { TurnIngestionCoordinator, type TurnIngestionOptions } from "./orchestration/turn-ingestion.js";
125
126
  import { RecallIntrospectionCoordinator } from "./orchestration/recall-introspection.js";
126
127
  import { OrchestratorInitCoordinator } from "./orchestration/orchestrator-init.js";
@@ -1872,10 +1873,10 @@ export class Orchestrator {
1872
1873
  private async resolveArtifactSourceStatuses(
1873
1874
  storage: StorageManager,
1874
1875
  sourceIds: string[],
1876
+ options?: CorpusReadOptions,
1875
1877
  ): Promise<Map<string, "active" | "superseded" | "archived" | "missing">> {
1876
1878
  return this.namespaceReadFanoutCoordinator.resolveArtifactSourceStatuses(
1877
- storage,
1878
- sourceIds,
1879
+ storage, sourceIds, options,
1879
1880
  );
1880
1881
  }
1881
1882
 
@@ -3970,9 +3971,8 @@ export class Orchestrator {
3970
3971
 
3971
3972
  private async readAllMemoriesForNamespaces(
3972
3973
  namespaces: string[],
3974
+ options?: CorpusReadOptions,
3973
3975
  ): Promise<MemoryFile[]> {
3974
- return this.namespaceReadFanoutCoordinator.readAllMemoriesForNamespaces(
3975
- namespaces,
3976
- );
3976
+ return this.namespaceReadFanoutCoordinator.readAllMemoriesForNamespaces(namespaces, options);
3977
3977
  }
3978
3978
  }
@@ -12,6 +12,7 @@
12
12
 
13
13
  import { readdir, unlink } from "node:fs/promises";
14
14
  import path from "node:path";
15
+ import { checkCorpusReadAbort, type CorpusReadOptions } from "../corpus-read-cancellation.js";
15
16
  import { normalizeEntityStructuredSection, sortStructuredSectionsBySchema } from "../entity-schema.js";
16
17
  import { withEntityCanonicalMutationLock } from "./entity-canonical-id-lock.js";
17
18
  import { log } from "../logger.js";
@@ -482,7 +483,8 @@ export class EntityStore {
482
483
  * Read all entity files and return lightweight EntityFile objects.
483
484
  * Parsing is fast (~50-100ms for ~1,800 files) since entity files are small.
484
485
  */
485
- async readAllEntityFiles(): Promise<EntityFile[]> {
486
+ async readAllEntityFiles(options?: CorpusReadOptions): Promise<EntityFile[]> {
487
+ checkCorpusReadAbort(options);
486
488
  const currentVersion = this.deps.getMemoryStatusVersion();
487
489
  const cacheKey = [
488
490
  this.deps.getEntityCacheSecureStoreKey(),
@@ -503,6 +505,9 @@ export class EntityStore {
503
505
  const BATCH_SIZE = 100;
504
506
  const entities: EntityFile[] = [];
505
507
  for (let i = 0; i < mdFiles.length; i += BATCH_SIZE) {
508
+ // Per batch, so an abandoned caller stops within one batch of I/O instead
509
+ // of reading every entity file for a result nobody awaits (issue #2307).
510
+ checkCorpusReadAbort(options);
506
511
  const batch = mdFiles.slice(i, i + BATCH_SIZE);
507
512
  const results = await Promise.all(
508
513
  batch.map(async (entry) => {
@@ -519,7 +524,9 @@ export class EntityStore {
519
524
  if (content !== null) entities.push(parseEntityFile(content, this.deps.entitySchemas));
520
525
  }
521
526
  }
522
-
527
+ // A signal that fired during the last batch's await would otherwise publish
528
+ // and return as if uncancelled (issue #2307 review).
529
+ checkCorpusReadAbort(options);
523
530
  setCachedEntities(this.deps.baseDir, entities, currentVersion, cacheKey);
524
531
  return entities;
525
532
  } catch (err) {