@remnic/core 9.43.0 → 9.45.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 (258) hide show
  1. package/dist/access-admin-ops-surface.d.ts +5 -5
  2. package/dist/access-admin-ops-surface.js +42 -41
  3. package/dist/access-authorization-probe.d.ts +5 -5
  4. package/dist/access-authorization-probe.js +43 -42
  5. package/dist/access-boundary.d.ts +5 -5
  6. package/dist/access-boundary.js +42 -41
  7. package/dist/access-cli.js +100 -97
  8. package/dist/access-cli.js.map +1 -1
  9. package/dist/access-extraction-force-flush.d.ts +5 -5
  10. package/dist/access-extraction-force-flush.js +42 -41
  11. package/dist/access-http-lcm-compaction.d.ts +5 -5
  12. package/dist/access-http-lifecycle-flush.d.ts +5 -5
  13. package/dist/access-http-query.d.ts +8 -0
  14. package/dist/access-http-query.js +180 -0
  15. package/dist/access-http.d.ts +5 -5
  16. package/dist/access-http.js +51 -49
  17. package/dist/access-identity-continuity-surface.d.ts +4 -4
  18. package/dist/access-identity-continuity-surface.js +42 -41
  19. package/dist/access-lcm-surface.d.ts +5 -5
  20. package/dist/access-lcm-surface.js +42 -41
  21. package/dist/access-mcp.d.ts +5 -5
  22. package/dist/access-mcp.js +47 -46
  23. package/dist/access-namespace-preflight.js +42 -41
  24. package/dist/access-observe-write-surface.d.ts +5 -5
  25. package/dist/access-observe-write-surface.js +42 -41
  26. package/dist/access-operations-batch.js +44 -43
  27. package/dist/access-operations.d.ts +8 -8
  28. package/dist/access-operations.js +46 -45
  29. package/dist/access-recall-concurrency.d.ts +5 -5
  30. package/dist/access-recall-concurrency.js +42 -41
  31. package/dist/access-recall-response.d.ts +5 -5
  32. package/dist/access-recall-response.js +42 -41
  33. package/dist/access-recall-surface.d.ts +5 -5
  34. package/dist/access-recall-surface.js +42 -41
  35. package/dist/access-schema.d.ts +84 -84
  36. package/dist/access-schema.js +3 -3
  37. package/dist/{access-service-D1BkxwSf.d.ts → access-service-DBo88Dmm.d.ts} +14 -4
  38. package/dist/access-service-helpers.d.ts +5 -5
  39. package/dist/access-service.d.ts +5 -5
  40. package/dist/access-service.js +42 -41
  41. package/dist/access-surface-catalog.d.ts +5 -5
  42. package/dist/access-surface-catalog.js +5 -0
  43. package/dist/access-surface-catalog.js.map +1 -1
  44. package/dist/access-wearables-meetings-surface.d.ts +2 -2
  45. package/dist/{auto-sync-UPTUVE4X.js → auto-sync-5OE5QOZB.js} +3 -3
  46. package/dist/bootstrap.d.ts +4 -4
  47. package/dist/briefing.d.ts +1 -1
  48. package/dist/briefing.js +9 -8
  49. package/dist/buffer.d.ts +1 -1
  50. package/dist/buffer.js +6 -6
  51. package/dist/causal-behavior.js +2 -2
  52. package/dist/causal-chain.js +2 -2
  53. package/dist/causal-consolidation.js +13 -12
  54. package/dist/causal-consolidation.js.map +1 -1
  55. package/dist/causal-retrieval.js +2 -2
  56. package/dist/causal-trajectory-graph.js +2 -2
  57. package/dist/causal-trajectory.js +1 -1
  58. package/dist/{chunk-LEPOP46W.js → chunk-227UFSEQ.js} +4 -4
  59. package/dist/{chunk-CMENJQ6I.js → chunk-2QR2RRH6.js} +2 -2
  60. package/dist/{chunk-ZERSIPFC.js → chunk-3HKQOFOV.js} +22 -20
  61. package/dist/{chunk-ZERSIPFC.js.map → chunk-3HKQOFOV.js.map} +1 -1
  62. package/dist/{chunk-4DYBLQZC.js → chunk-3HLCRYBV.js} +3 -3
  63. package/dist/{chunk-L2DPF4DF.js → chunk-3SHB4YAW.js} +4 -4
  64. package/dist/{chunk-UV72DEZD.js → chunk-4B77XSG5.js} +5 -5
  65. package/dist/{chunk-GUQYMOPU.js → chunk-4LMA77JH.js} +5 -5
  66. package/dist/{chunk-Q53RLEW7.js → chunk-5SM35XZR.js} +2 -2
  67. package/dist/{chunk-YJHU5B3M.js → chunk-5YGO5VEH.js} +2 -2
  68. package/dist/{chunk-AX2J2LC4.js → chunk-5ZE7QHTK.js} +2 -2
  69. package/dist/{chunk-5QZEVMLY.js → chunk-65V4K4MT.js} +56 -38
  70. package/dist/chunk-65V4K4MT.js.map +1 -0
  71. package/dist/{chunk-YFHMW37V.js → chunk-6CZPDBJS.js} +5 -5
  72. package/dist/{chunk-BI6RE2ZS.js → chunk-6OLQJJYE.js} +2 -2
  73. package/dist/chunk-6UWB5PTR.js +413 -0
  74. package/dist/chunk-6UWB5PTR.js.map +1 -0
  75. package/dist/chunk-6ZYQ36IB.js +30 -0
  76. package/dist/chunk-6ZYQ36IB.js.map +1 -0
  77. package/dist/{chunk-GS5UVGQK.js → chunk-7JO6RVBI.js} +6 -6
  78. package/dist/{chunk-MBTPUVHZ.js → chunk-7PVFOFPJ.js} +2 -2
  79. package/dist/{chunk-KPJQTSRJ.js → chunk-C7EI7CA6.js} +2 -2
  80. package/dist/{chunk-NRV4Y3PM.js → chunk-CAGPP5NB.js} +1 -1
  81. package/dist/{chunk-NF3U3MPG.js → chunk-ECK75GDJ.js} +2 -2
  82. package/dist/{chunk-KDXD2AM6.js → chunk-FLBPATMZ.js} +44 -44
  83. package/dist/{chunk-OEXKYYVH.js → chunk-FVGQ5LIS.js} +6 -6
  84. package/dist/{chunk-AR2FSZBP.js → chunk-G24XIK6H.js} +2 -2
  85. package/dist/{chunk-5TOV3D6U.js → chunk-GBJJUPNV.js} +6 -6
  86. package/dist/{chunk-UP67AFRN.js → chunk-GOPWZYZH.js} +29 -29
  87. package/dist/chunk-GOPWZYZH.js.map +1 -0
  88. package/dist/{chunk-EPQ76W5T.js → chunk-GQBZ7EVF.js} +2 -2
  89. package/dist/{chunk-BGXHVOBI.js → chunk-HLPD7B7P.js} +2 -2
  90. package/dist/{chunk-KQAFEZQX.js → chunk-IPLYGWQF.js} +5 -5
  91. package/dist/{chunk-JDXDA5OO.js → chunk-J4OKD6QX.js} +2 -2
  92. package/dist/{chunk-LZ5JKQCS.js → chunk-JZ7SSAQ5.js} +3 -3
  93. package/dist/chunk-K6OTW3TP.js +24 -0
  94. package/dist/chunk-K6OTW3TP.js.map +1 -0
  95. package/dist/{chunk-EHKDORQN.js → chunk-NVRYW264.js} +9 -9
  96. package/dist/{chunk-MU7ZHSZE.js → chunk-PO5LSKQO.js} +2 -2
  97. package/dist/{chunk-ONHRRJZM.js → chunk-QJAQNXWI.js} +6 -6
  98. package/dist/{chunk-WGCTFGLW.js → chunk-QQ3NDJOM.js} +3 -3
  99. package/dist/{chunk-BEQOZOYZ.js → chunk-RVLJEII5.js} +30 -511
  100. package/dist/chunk-RVLJEII5.js.map +1 -0
  101. package/dist/chunk-S5SLVSVY.js +517 -0
  102. package/dist/chunk-S5SLVSVY.js.map +1 -0
  103. package/dist/{chunk-QY66HJ4X.js → chunk-SS7YWVPF.js} +5 -5
  104. package/dist/{chunk-ZVVASRUT.js → chunk-U5G66ORD.js} +90 -88
  105. package/dist/chunk-U5G66ORD.js.map +1 -0
  106. package/dist/{chunk-JYIFGGEM.js → chunk-UZGJFIIG.js} +2 -2
  107. package/dist/{chunk-NHRNYJPJ.js → chunk-VCGPO2VD.js} +7 -7
  108. package/dist/{chunk-F2KMAFEB.js → chunk-VRYJSKOM.js} +2 -2
  109. package/dist/{chunk-HNZKVLAN.js → chunk-W6ROK2KU.js} +2 -2
  110. package/dist/{chunk-SEUSFKNS.js → chunk-WC4SPYHX.js} +14 -14
  111. package/dist/{chunk-MSXWUXFE.js → chunk-WG2PI44B.js} +2 -2
  112. package/dist/{chunk-4VXGRIH6.js → chunk-WUNIWKY4.js} +5 -5
  113. package/dist/{chunk-3C2TGBDB.js → chunk-XFQRFWVS.js} +2 -2
  114. package/dist/{chunk-5N26WBPQ.js → chunk-XMZV27S5.js} +5 -5
  115. package/dist/{chunk-JGXXPDM2.js → chunk-YQQK7W7T.js} +3 -3
  116. package/dist/{chunk-3F2LKUMU.js → chunk-ZAB5PG65.js} +2 -2
  117. package/dist/{chunk-MVW234LO.js → chunk-ZPJJE7MF.js} +2 -2
  118. package/dist/{chunk-6GIMMNVK.js → chunk-ZS5UZU5M.js} +4 -4
  119. package/dist/{cli-IUhV-lmk.d.ts → cli-DQ4VhjqX.d.ts} +3 -3
  120. package/dist/cli.d.ts +6 -6
  121. package/dist/cli.js +69 -67
  122. package/dist/compounding/engine.d.ts +1 -1
  123. package/dist/compounding/engine.js +9 -8
  124. package/dist/connectors/codex-materialize-runner.js +9 -8
  125. package/dist/connectors/index.js +9 -8
  126. package/dist/consolidation-provenance-check.d.ts +1 -1
  127. package/dist/consolidation-undo.d.ts +1 -1
  128. package/dist/contradiction/index.d.ts +1 -1
  129. package/dist/convergence-refresh.d.ts +24 -0
  130. package/dist/convergence-refresh.js +75 -0
  131. package/dist/convergence-refresh.js.map +1 -0
  132. package/dist/conversation-index/backend.js +2 -2
  133. package/dist/corpus-watermark.js +20 -19
  134. package/dist/entity-retrieval.d.ts +1 -1
  135. package/dist/entity-retrieval.js +9 -8
  136. package/dist/explicit-capture.d.ts +4 -4
  137. package/dist/explicit-capture.js +4 -3
  138. package/dist/extraction.js +15 -14
  139. package/dist/{graph-edge-decay-Z6ENALU2.js → graph-edge-decay-GF3ZSGSP.js} +4 -4
  140. package/dist/graph-edge-decay-GF3ZSGSP.js.map +1 -0
  141. package/dist/graph-snapshot.js +3 -3
  142. package/dist/graph.js +2 -2
  143. package/dist/index.d.ts +398 -398
  144. package/dist/index.js +161 -158
  145. package/dist/lcm/index.js +3 -3
  146. package/dist/maintenance/memory-governance.js +10 -9
  147. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +1 -1
  148. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +9 -8
  149. package/dist/maintenance/rebuild-memory-projection.d.ts +1 -1
  150. package/dist/maintenance/rebuild-memory-projection.js +11 -10
  151. package/dist/{maintenance-DVBLXkFw.d.ts → maintenance-_RV38GlE.d.ts} +1 -1
  152. package/dist/mcp-memory-inspector-app.d.ts +5 -5
  153. package/dist/memory-worth-outcomes.d.ts +1 -1
  154. package/dist/namespaces/migrate.d.ts +1 -1
  155. package/dist/namespaces/migrate.js +19 -18
  156. package/dist/namespaces/search.js +9 -9
  157. package/dist/namespaces/storage.d.ts +1 -1
  158. package/dist/namespaces/storage.js +9 -8
  159. package/dist/offline-sync-impression-drain.js +4 -4
  160. package/dist/operator-doctor-corpus.js +21 -20
  161. package/dist/operator-toolkit.d.ts +1 -1
  162. package/dist/operator-toolkit.js +30 -29
  163. package/dist/orchestration/compression-guideline-coordinator.d.ts +1 -1
  164. package/dist/orchestration/maintenance.d.ts +2 -2
  165. package/dist/orchestration/maintenance.js +16 -15
  166. package/dist/{orchestrator-fYTncnLy.d.ts → orchestrator-B2ecFpRO.d.ts} +4 -4
  167. package/dist/orchestrator.d.ts +4 -4
  168. package/dist/orchestrator.js +101 -98
  169. package/dist/qmd.js +4 -4
  170. package/dist/reconcile/manifest.d.ts +33 -0
  171. package/dist/reconcile/manifest.js +248 -0
  172. package/dist/reconcile/manifest.js.map +1 -0
  173. package/dist/reconcile/plan.d.ts +1 -1
  174. package/dist/reconcile/plan.js +8 -404
  175. package/dist/reconcile/plan.js.map +1 -1
  176. package/dist/resume-bundles.js +1 -1
  177. package/dist/schemas.d.ts +76 -76
  178. package/dist/search/factory.js +8 -8
  179. package/dist/search/index.js +14 -14
  180. package/dist/semantic-consolidation.js +11 -10
  181. package/dist/semantic-rule-promotion.js +9 -8
  182. package/dist/semantic-rule-verifier.js +10 -9
  183. package/dist/{service-CLuMO-pa.d.ts → service-DW06sY3P.d.ts} +1 -1
  184. package/dist/shared-context/manager.d.ts +8 -8
  185. package/dist/source-agent-qualifier.js +14 -13
  186. package/dist/{storage-Blr71GpS.d.ts → storage-qRIQPA6F.d.ts} +12 -0
  187. package/dist/storage.d.ts +1 -1
  188. package/dist/storage.js +8 -7
  189. package/dist/temporal-supersession.d.ts +1 -1
  190. package/dist/tier-migration.d.ts +1 -1
  191. package/dist/transfer/autodetect.js +1 -1
  192. package/dist/transfer/backup.js +1 -1
  193. package/dist/transfer/capsule-export.js +2 -2
  194. package/dist/transfer/types.d.ts +66 -66
  195. package/dist/verified-recall.js +10 -9
  196. package/package.json +12 -2
  197. package/src/access-http-query.ts +25 -0
  198. package/src/access-http.test.ts +136 -0
  199. package/src/access-http.ts +26 -26
  200. package/src/access-service-offline-file-content.test.ts +40 -0
  201. package/src/access-service.ts +34 -0
  202. package/src/access-surface-catalog.ts +5 -0
  203. package/src/convergence-refresh.ts +28 -0
  204. package/src/orchestrator-convergence-refresh.test.ts +114 -0
  205. package/src/orchestrator.ts +5 -4
  206. package/src/reconcile/manifest.test.ts +261 -0
  207. package/src/reconcile/manifest.ts +278 -0
  208. package/src/reconcile/plan.ts +1 -0
  209. package/src/storage/content-hash-index.ts +26 -0
  210. package/dist/chunk-5QZEVMLY.js.map +0 -1
  211. package/dist/chunk-BEQOZOYZ.js.map +0 -1
  212. package/dist/chunk-UP67AFRN.js.map +0 -1
  213. package/dist/chunk-ZVVASRUT.js.map +0 -1
  214. /package/dist/{graph-edge-decay-Z6ENALU2.js.map → access-http-query.js.map} +0 -0
  215. /package/dist/{auto-sync-UPTUVE4X.js.map → auto-sync-5OE5QOZB.js.map} +0 -0
  216. /package/dist/{chunk-LEPOP46W.js.map → chunk-227UFSEQ.js.map} +0 -0
  217. /package/dist/{chunk-CMENJQ6I.js.map → chunk-2QR2RRH6.js.map} +0 -0
  218. /package/dist/{chunk-4DYBLQZC.js.map → chunk-3HLCRYBV.js.map} +0 -0
  219. /package/dist/{chunk-L2DPF4DF.js.map → chunk-3SHB4YAW.js.map} +0 -0
  220. /package/dist/{chunk-UV72DEZD.js.map → chunk-4B77XSG5.js.map} +0 -0
  221. /package/dist/{chunk-GUQYMOPU.js.map → chunk-4LMA77JH.js.map} +0 -0
  222. /package/dist/{chunk-Q53RLEW7.js.map → chunk-5SM35XZR.js.map} +0 -0
  223. /package/dist/{chunk-YJHU5B3M.js.map → chunk-5YGO5VEH.js.map} +0 -0
  224. /package/dist/{chunk-AX2J2LC4.js.map → chunk-5ZE7QHTK.js.map} +0 -0
  225. /package/dist/{chunk-YFHMW37V.js.map → chunk-6CZPDBJS.js.map} +0 -0
  226. /package/dist/{chunk-BI6RE2ZS.js.map → chunk-6OLQJJYE.js.map} +0 -0
  227. /package/dist/{chunk-GS5UVGQK.js.map → chunk-7JO6RVBI.js.map} +0 -0
  228. /package/dist/{chunk-MBTPUVHZ.js.map → chunk-7PVFOFPJ.js.map} +0 -0
  229. /package/dist/{chunk-KPJQTSRJ.js.map → chunk-C7EI7CA6.js.map} +0 -0
  230. /package/dist/{chunk-NRV4Y3PM.js.map → chunk-CAGPP5NB.js.map} +0 -0
  231. /package/dist/{chunk-NF3U3MPG.js.map → chunk-ECK75GDJ.js.map} +0 -0
  232. /package/dist/{chunk-KDXD2AM6.js.map → chunk-FLBPATMZ.js.map} +0 -0
  233. /package/dist/{chunk-OEXKYYVH.js.map → chunk-FVGQ5LIS.js.map} +0 -0
  234. /package/dist/{chunk-AR2FSZBP.js.map → chunk-G24XIK6H.js.map} +0 -0
  235. /package/dist/{chunk-5TOV3D6U.js.map → chunk-GBJJUPNV.js.map} +0 -0
  236. /package/dist/{chunk-EPQ76W5T.js.map → chunk-GQBZ7EVF.js.map} +0 -0
  237. /package/dist/{chunk-BGXHVOBI.js.map → chunk-HLPD7B7P.js.map} +0 -0
  238. /package/dist/{chunk-KQAFEZQX.js.map → chunk-IPLYGWQF.js.map} +0 -0
  239. /package/dist/{chunk-JDXDA5OO.js.map → chunk-J4OKD6QX.js.map} +0 -0
  240. /package/dist/{chunk-LZ5JKQCS.js.map → chunk-JZ7SSAQ5.js.map} +0 -0
  241. /package/dist/{chunk-EHKDORQN.js.map → chunk-NVRYW264.js.map} +0 -0
  242. /package/dist/{chunk-MU7ZHSZE.js.map → chunk-PO5LSKQO.js.map} +0 -0
  243. /package/dist/{chunk-ONHRRJZM.js.map → chunk-QJAQNXWI.js.map} +0 -0
  244. /package/dist/{chunk-WGCTFGLW.js.map → chunk-QQ3NDJOM.js.map} +0 -0
  245. /package/dist/{chunk-QY66HJ4X.js.map → chunk-SS7YWVPF.js.map} +0 -0
  246. /package/dist/{chunk-JYIFGGEM.js.map → chunk-UZGJFIIG.js.map} +0 -0
  247. /package/dist/{chunk-NHRNYJPJ.js.map → chunk-VCGPO2VD.js.map} +0 -0
  248. /package/dist/{chunk-F2KMAFEB.js.map → chunk-VRYJSKOM.js.map} +0 -0
  249. /package/dist/{chunk-HNZKVLAN.js.map → chunk-W6ROK2KU.js.map} +0 -0
  250. /package/dist/{chunk-SEUSFKNS.js.map → chunk-WC4SPYHX.js.map} +0 -0
  251. /package/dist/{chunk-MSXWUXFE.js.map → chunk-WG2PI44B.js.map} +0 -0
  252. /package/dist/{chunk-4VXGRIH6.js.map → chunk-WUNIWKY4.js.map} +0 -0
  253. /package/dist/{chunk-3C2TGBDB.js.map → chunk-XFQRFWVS.js.map} +0 -0
  254. /package/dist/{chunk-5N26WBPQ.js.map → chunk-XMZV27S5.js.map} +0 -0
  255. /package/dist/{chunk-JGXXPDM2.js.map → chunk-YQQK7W7T.js.map} +0 -0
  256. /package/dist/{chunk-3F2LKUMU.js.map → chunk-ZAB5PG65.js.map} +0 -0
  257. /package/dist/{chunk-MVW234LO.js.map → chunk-ZPJJE7MF.js.map} +0 -0
  258. /package/dist/{chunk-6GIMMNVK.js.map → chunk-ZS5UZU5M.js.map} +0 -0
@@ -1,3 +1,7 @@
1
+ import {
2
+ CONTENT_HASH_INDEX_RETRY_MAX_DELAY_MS,
3
+ ContentHashIndex
4
+ } from "./chunk-S5SLVSVY.js";
1
5
  import {
2
6
  markProjectedMemoryPathInvalid
3
7
  } from "./chunk-3CSX3ETE.js";
@@ -9,14 +13,7 @@ import {
9
13
  withHeldFileLock
10
14
  } from "./chunk-FFAZ2XFU.js";
11
15
  import {
12
- computeContentHash,
13
- normalizeContent
14
- } from "./chunk-W5H6ZRPT.js";
15
- import {
16
- SecureStoreLockedError,
17
- readMaybeEncryptedFile,
18
16
  readMaybeEncryptedFileFromChunks,
19
- writeMaybeEncryptedFile,
20
17
  writeMaybeEncryptedFileFromChunks
21
18
  } from "./chunk-5TFP4CUL.js";
22
19
  import {
@@ -29,486 +26,11 @@ import {
29
26
  log
30
27
  } from "./chunk-3WCASNQZ.js";
31
28
 
32
- // src/storage/content-hash-index.ts
33
- import { mkdir, stat } from "fs/promises";
34
- import path from "path";
35
- var CONTENT_HASH_INDEX_LOCK_STALE_MS = 3e4;
36
- var CONTENT_HASH_INDEX_RETRY_MAX_ATTEMPTS = 5;
37
- var CONTENT_HASH_INDEX_RETRY_BASE_MS = 500;
38
- var CONTENT_HASH_INDEX_RETRY_MAX_DELAY_MS = 5e3;
39
- var FactHashIndexNotAuthoritativeError = class extends Error {
40
- constructor(stateDir) {
41
- super(
42
- `fact-hash index is not authoritative: the cross-process rebuild lock for ${stateDir} could not be acquired within the bounded retry budget`
43
- );
44
- this.name = "FactHashIndexNotAuthoritativeError";
45
- }
46
- };
47
- var ContentHashIndex = class _ContentHashIndex {
48
- hashes = /* @__PURE__ */ new Set();
49
- dirty = false;
50
- /**
51
- * Hashes explicitly removed since the last successful save (issue #1909 review
52
- * round 8 thread 3). Tracked separately so `saveMergingWithDisk` can be
53
- * removal-AWARE: under the file lock it reads the latest on-disk set, DROPS
54
- * these, then unions our additions — so a removal batch cannot resurrect a
55
- * hash (union alone would) and cannot clobber a concurrent extraction's
56
- * appended hash (blind overwrite would). Consumed + cleared by every save.
57
- */
58
- removed = /* @__PURE__ */ new Set();
59
- /**
60
- * Hashes added by THIS instance since the last successful save (issue #1909
61
- * review round 9 finding 3). Tracked separately from the loaded snapshot so a
62
- * reconciling save publishes `(on-disk \ removed) ∪ added` — it re-applies only
63
- * OUR additions, never the stale loaded entries. Without this, seeding the
64
- * merge from `this.hashes` (loaded ∪ added) would resurrect a hash a peer
65
- * removed on disk while this instance held a stale snapshot.
66
- */
67
- added = /* @__PURE__ */ new Set();
68
- filePath;
69
- secureStoreKeyProvider;
70
- secureStoreWriteKeyProvider;
71
- memoryDir;
72
- lockOptions;
73
- /**
74
- * Deferred reconcile-save durable-retry state (issue #1909 / PR #2016). At
75
- * most ONE retry is ever armed (`reconcileRetryTimer` is the reentrancy guard)
76
- * so successive timed-out saves cannot stack duplicate/parallel retries.
77
- * `reconcileRetryBarrier` resolves when the chain settles (published or gave
78
- * up) — awaited by tests and any caller wanting the eventual result.
79
- */
80
- reconcileRetryTimer = null;
81
- reconcileRetryAttempts = 0;
82
- reconcileRetryBarrier = null;
83
- reconcileRetryResolve = null;
84
- /**
85
- * On-disk fingerprint captured at the last point THIS instance's in-memory
86
- * set matched disk — after `load()`, `save()`, or a reconcile publish. A peer
87
- * process that advances the durable index changes its file generation even
88
- * when byte size and mtime collide, so the freshness check remains safe
89
- * without an O(file-size) read on the hot path.
90
- */
91
- lastSyncedFingerprint = null;
92
- constructor(stateDir, secureStoreKeyProvider = () => null, secureStoreWriteKeyProvider = secureStoreKeyProvider, memoryDir = path.dirname(stateDir), lockOptions = {}) {
93
- this.filePath = path.join(stateDir, "fact-hashes.txt");
94
- this.secureStoreKeyProvider = secureStoreKeyProvider;
95
- this.secureStoreWriteKeyProvider = secureStoreWriteKeyProvider;
96
- this.memoryDir = memoryDir;
97
- this.lockOptions = lockOptions;
98
- }
99
- /** Load existing hashes from disk. Safe to call multiple times. */
100
- async load() {
101
- try {
102
- const raw = await readMaybeEncryptedFile(this.filePath, this.secureStoreKeyProvider(), this.memoryDir);
103
- for (const line of raw.split("\n")) {
104
- const trimmed = line.trim();
105
- if (trimmed.length > 0) {
106
- this.hashes.add(trimmed);
107
- }
108
- }
109
- log.debug(`content-hash index: loaded ${this.hashes.size} hashes`);
110
- } catch (err) {
111
- if (err instanceof SecureStoreLockedError) throw err;
112
- if (!isErrnoCode(err, "ENOENT")) throw err;
113
- log.debug("content-hash index: no existing index \u2014 starting fresh");
114
- }
115
- await this.captureSyncedFingerprint();
116
- }
117
- /** Cheap `stat` of the durable index file; null when it does not exist yet. */
118
- async statIndexFile() {
119
- try {
120
- const s = await stat(this.filePath);
121
- return {
122
- mtimeMs: s.mtimeMs,
123
- size: s.size,
124
- dev: s.dev,
125
- ino: s.ino,
126
- ctimeMs: s.ctimeMs,
127
- birthtimeMs: s.birthtimeMs
128
- };
129
- } catch (err) {
130
- if (isErrnoCode(err, "ENOENT")) return null;
131
- throw err;
132
- }
133
- }
134
- /** Record the current on-disk fingerprint as this instance's synced baseline. */
135
- async captureSyncedFingerprint() {
136
- try {
137
- this.lastSyncedFingerprint = await this.statIndexFile();
138
- } catch (err) {
139
- this.lastSyncedFingerprint = null;
140
- log.debug(`content-hash index: could not fingerprint ${this.filePath}: ${err}`);
141
- }
142
- }
143
- /**
144
- * True when the durable index file is unchanged since this instance last
145
- * synced it (load / save / reconcile). False when a peer advanced it, when
146
- * the file appeared or vanished, or when freshness cannot be established
147
- * (stat error) — the caller then treats the in-memory snapshot as
148
- * non-authoritative and confirms a dedup miss against the durable corpus.
149
- * The stat includes file identity and generation metadata so same-size,
150
- * same-mtime atomic replacements are detected without reading the file body.
151
- */
152
- async isDiskFingerprintCurrent() {
153
- let current;
154
- try {
155
- current = await this.statIndexFile();
156
- } catch {
157
- return false;
158
- }
159
- const last = this.lastSyncedFingerprint;
160
- if (last === null || current === null) {
161
- return last === null && current === null;
162
- }
163
- return current.mtimeMs === last.mtimeMs && current.size === last.size && current.dev === last.dev && current.ino === last.ino && current.ctimeMs === last.ctimeMs && current.birthtimeMs === last.birthtimeMs;
164
- }
165
- /** Check if content already exists in the index. */
166
- has(content) {
167
- return this.hashes.has(_ContentHashIndex.computeHash(content));
168
- }
169
- /** Add content hash to the index. */
170
- add(content) {
171
- const hash = _ContentHashIndex.computeHash(content);
172
- this.removed.delete(hash);
173
- this.hashes.add(hash);
174
- this.added.add(hash);
175
- this.dirty = true;
176
- }
177
- get size() {
178
- return this.hashes.size;
179
- }
180
- /** Clear all loaded hashes so the next save rewrites the index from scratch. */
181
- clear() {
182
- if (this.hashes.size > 0) {
183
- this.hashes.clear();
184
- }
185
- this.added.clear();
186
- this.removed.clear();
187
- this.cancelReconcileRetry();
188
- this.dirty = true;
189
- }
190
- /** Persist index to disk if changed (plain whole-file overwrite). */
191
- async save() {
192
- if (!this.dirty) return;
193
- await mkdir(path.dirname(this.filePath), { recursive: true });
194
- const publishedAdded = new Set(this.added);
195
- const publishedRemoved = new Set(this.removed);
196
- const serialized = [...this.hashes].join("\n") + "\n";
197
- await writeMaybeEncryptedFile(
198
- this.filePath,
199
- serialized,
200
- this.secureStoreWriteKeyProvider(),
201
- {},
202
- this.memoryDir
203
- );
204
- for (const h of publishedAdded) this.added.delete(h);
205
- for (const h of publishedRemoved) this.removed.delete(h);
206
- this.dirty = this.added.size > 0 || this.removed.size > 0;
207
- await this.captureSyncedFingerprint();
208
- if (this.dirty) {
209
- this.scheduleReconcileRetry();
210
- } else {
211
- this.cancelReconcileRetry();
212
- }
213
- log.debug(`content-hash index: saved ${this.hashes.size} hashes`);
214
- }
215
- /**
216
- * Persist the index by RECONCILING with the latest on-disk state under a
217
- * cross-process lock (issue #1909). Used by the extraction-persist batch save
218
- * for BOTH append and removal batches, so appends and removals to the same
219
- * index serialize against each other:
220
- * final = (on-disk \ this.removed) ∪ this.added
221
- * Note it re-applies only OUR local additions (`added`), NOT the loaded
222
- * snapshot (review round 9 finding 3): seeding from `this.hashes` would
223
- * resurrect a hash a peer removed on disk while we held a stale snapshot. This
224
- * preserves a concurrent writer's appended hashes (a blind overwrite would
225
- * drop them), never resurrects a removed hash, and never loses our additions.
226
- *
227
- * Hardening:
228
- * - Dirty short-circuit (round 7 finding 3): when this instance neither added
229
- * nor removed anything this run, skip the O(file) read+rewrite entirely.
230
- * - Cross-process lock (round 7 finding 2): serialize the read→reconcile→write
231
- * window on a per-file advisory lock. If the lock is NOT acquired (timeout),
232
- * do NOT publish (round 9 finding 2): keep `dirty` set AND schedule a bounded
233
- * durable background retry (PR #2016) that keeps re-attempting the locked
234
- * publish until the deferred additions land — never an unlocked write that
235
- * could clobber a peer, and never a silent "batch save complete" that leaves
236
- * the addition in this process's memory only.
237
- */
238
- async saveMergingWithDisk() {
239
- if (!this.dirty) return;
240
- await mkdir(path.dirname(this.filePath), { recursive: true });
241
- const publish = async () => {
242
- const publishedAdded = new Set(this.added);
243
- const publishedRemoved = new Set(this.removed);
244
- const merged = new Set(publishedAdded);
245
- try {
246
- const raw = await readMaybeEncryptedFile(
247
- this.filePath,
248
- this.secureStoreKeyProvider(),
249
- this.memoryDir
250
- );
251
- for (const line of raw.split("\n")) {
252
- const trimmed = line.trim();
253
- if (trimmed.length > 0 && !publishedRemoved.has(trimmed)) merged.add(trimmed);
254
- }
255
- } catch (err) {
256
- if (err instanceof SecureStoreLockedError) throw err;
257
- if (!isErrnoCode(err, "ENOENT")) throw err;
258
- }
259
- await mkdir(path.dirname(this.filePath), { recursive: true });
260
- await writeMaybeEncryptedFile(
261
- this.filePath,
262
- [...merged].join("\n") + "\n",
263
- this.secureStoreWriteKeyProvider(),
264
- {},
265
- this.memoryDir
266
- );
267
- for (const h of publishedAdded) this.added.delete(h);
268
- for (const h of publishedRemoved) this.removed.delete(h);
269
- for (const h of this.added) merged.add(h);
270
- for (const h of this.removed) merged.delete(h);
271
- this.hashes = merged;
272
- this.dirty = this.added.size > 0 || this.removed.size > 0;
273
- await this.captureSyncedFingerprint();
274
- };
275
- await withHeldFileLock(
276
- `${this.filePath}.lock`,
277
- {
278
- staleMs: CONTENT_HASH_INDEX_LOCK_STALE_MS,
279
- ...this.lockOptions.maxWaitMs !== void 0 ? { maxWaitMs: this.lockOptions.maxWaitMs } : {},
280
- ...this.lockOptions.pollMs !== void 0 ? { pollMs: this.lockOptions.pollMs } : {}
281
- },
282
- async (acquired) => {
283
- if (!acquired) {
284
- log.warn(
285
- `content-hash index: lock not acquired for ${this.filePath}; deferring reconcile save (dirty retained, scheduling durable retry)`
286
- );
287
- this.scheduleReconcileRetry();
288
- return;
289
- }
290
- await publish();
291
- if (this.dirty) {
292
- this.scheduleReconcileRetry();
293
- } else {
294
- this.cancelReconcileRetry();
295
- }
296
- }
297
- );
298
- log.debug(`content-hash index: reconcile-saved ${this.hashes.size} hashes`);
299
- }
300
- /**
301
- * Rebuild-and-publish the index from an authoritative source (the durable
302
- * corpus) under the SAME per-file cross-process lock the reconciling
303
- * append/removal saves (`saveMergingWithDisk`) use (issue #1909 / PR #2016).
304
- * The `populate` callback runs WHILE the lock is held and MUST repopulate this
305
- * index from the corpus (`clear()` then `addByHash(...)` for every corpus
306
- * hash); the rebuilt set is then published with a plain overwrite that is now
307
- * serialized against every locked writer.
308
- *
309
- * This closes the finding where the previous unlocked clear→scan→save() could
310
- * overwrite a peer's newer lock-merged or deferred additions: a locked writer
311
- * that committed BEFORE the rebuild acquired the lock has its memory `.md` on
312
- * disk and is re-scanned; one that commits AFTER the rebuild releases
313
- * reconciles its additions on top of the freshly-published set. No union with
314
- * the raw on-disk file is performed, so the rebuild keeps its
315
- * garbage-collection property (orphaned hashes for deleted memories drop).
316
- *
317
- * Lock-acquisition failure is explicit and non-destructive: `populate` is NOT
318
- * run and nothing is written (never an unlocked overwrite). Returns true when
319
- * the rebuild was published under the lock, false when the lock timed out —
320
- * the caller keeps the index non-authoritative and retries on next use. Uses
321
- * the same non-reentrant file lock as the reconcile path, so it can never
322
- * deadlock with the deferred reconcile-retry: a concurrent locked writer (or a
323
- * fired retry) simply yields `acquired=false` after the bounded wait.
324
- */
325
- async rebuildUnderLock(populate) {
326
- await mkdir(path.dirname(this.filePath), { recursive: true });
327
- let published = false;
328
- await withHeldFileLock(
329
- `${this.filePath}.lock`,
330
- {
331
- staleMs: CONTENT_HASH_INDEX_LOCK_STALE_MS,
332
- ...this.lockOptions.maxWaitMs !== void 0 ? { maxWaitMs: this.lockOptions.maxWaitMs } : {},
333
- ...this.lockOptions.pollMs !== void 0 ? { pollMs: this.lockOptions.pollMs } : {}
334
- },
335
- async (acquired) => {
336
- if (!acquired) {
337
- log.warn(
338
- `content-hash index: lock not acquired for ${this.filePath}; deferring authoritative rebuild (index left non-authoritative, retried on next use)`
339
- );
340
- return;
341
- }
342
- await populate();
343
- await this.save();
344
- published = true;
345
- }
346
- );
347
- return published;
348
- }
349
- /**
350
- * True while a background durable reconcile-save retry is armed (PR #2016).
351
- * Test/introspection hook.
352
- */
353
- get hasPendingReconcileRetry() {
354
- return this.reconcileRetryTimer !== null;
355
- }
356
- /** True while this index has in-memory changes not yet published to disk. */
357
- get hasPendingChanges() {
358
- return this.dirty;
359
- }
360
- /**
361
- * Resolve once any armed background reconcile-save retry chain has settled —
362
- * either it published the deferred additions, or it exhausted its bounded
363
- * attempts and fell back to the corpus-rebuild safety net. Resolves
364
- * immediately when nothing is armed. Lets a caller (or a test) await the
365
- * eventual durability outcome of a lock-timed-out save.
366
- */
367
- async whenReconcileRetrySettled() {
368
- await (this.reconcileRetryBarrier ?? Promise.resolve());
369
- }
370
- /**
371
- * Drive any deferred lock-timeout reconcile save to completion INLINE at a
372
- * lifecycle boundary (PR #2016 finding 3). The background retry timer is
373
- * `unref`'d so it never keeps a long-lived daemon alive — but a short-lived
374
- * writer (a one-shot CLI) can exit before it fires, leaving a durable fact
375
- * `.md` whose hash never reached `fact-hashes.txt` for peers that already
376
- * built their in-memory index. `orchestrator.destroy()` calls this so the
377
- * addition publishes before the process exits; long-lived hosts only reach it
378
- * at their own shutdown, so their in-flight retries keep running in the
379
- * background until then. Bounded by the same attempt ceiling as the background
380
- * retry; a permanently contended lock falls back to the corpus-rebuild-on-
381
- * restart safety net (the fact `.md` is already durable). No deadlock: each
382
- * attempt is the same non-reentrant, bounded-wait file lock.
383
- */
384
- async flushReconcileRetry() {
385
- if (!this.dirty) return;
386
- const maxAttempts = this.lockOptions.retryMaxAttempts ?? CONTENT_HASH_INDEX_RETRY_MAX_ATTEMPTS;
387
- const baseMs = this.lockOptions.retryBaseMs ?? CONTENT_HASH_INDEX_RETRY_BASE_MS;
388
- for (let attempt = 0; this.dirty && attempt < maxAttempts; attempt += 1) {
389
- if (this.reconcileRetryTimer) {
390
- clearTimeout(this.reconcileRetryTimer);
391
- this.reconcileRetryTimer = null;
392
- }
393
- await this.saveMergingWithDisk();
394
- if (!this.dirty) break;
395
- if (attempt < maxAttempts - 1) {
396
- const wait = Math.min(baseMs * 2 ** attempt, CONTENT_HASH_INDEX_RETRY_MAX_DELAY_MS);
397
- await new Promise((resolve) => setTimeout(resolve, wait));
398
- }
399
- }
400
- if (this.reconcileRetryTimer) {
401
- clearTimeout(this.reconcileRetryTimer);
402
- this.reconcileRetryTimer = null;
403
- }
404
- this.reconcileRetryAttempts = 0;
405
- this.settleReconcileRetry();
406
- }
407
- /**
408
- * Schedule ONE bounded, exponentially-backed-off background retry of the
409
- * deferred reconcile save (PR #2016). Reentrant-safe: an already-armed timer
410
- * short-circuits, so successive timed-out saves never stack duplicate retries.
411
- * When attempts are exhausted the chain settles without publishing — the
412
- * durable fact `.md` is on disk and a process restart rebuilds the index from
413
- * the corpus, so this degrades to that safety net, never a fatal failure.
414
- */
415
- scheduleReconcileRetry() {
416
- if (this.reconcileRetryTimer) return;
417
- const maxAttempts = this.lockOptions.retryMaxAttempts ?? CONTENT_HASH_INDEX_RETRY_MAX_ATTEMPTS;
418
- if (this.reconcileRetryAttempts >= maxAttempts) {
419
- log.warn(
420
- `content-hash index: exhausted ${maxAttempts} deferred reconcile-save retries for ${this.filePath}; ${this.added.size} addition(s) remain dirty in-memory (a process restart rebuilds the index from the durable corpus)`
421
- );
422
- this.reconcileRetryAttempts = 0;
423
- this.settleReconcileRetry();
424
- return;
425
- }
426
- if (!this.reconcileRetryBarrier) {
427
- this.reconcileRetryBarrier = new Promise((resolve) => {
428
- this.reconcileRetryResolve = resolve;
429
- });
430
- }
431
- const attempt = this.reconcileRetryAttempts + 1;
432
- const baseMs = this.lockOptions.retryBaseMs ?? CONTENT_HASH_INDEX_RETRY_BASE_MS;
433
- const delay = Math.min(baseMs * 2 ** (attempt - 1), CONTENT_HASH_INDEX_RETRY_MAX_DELAY_MS);
434
- this.reconcileRetryTimer = setTimeout(() => {
435
- this.reconcileRetryTimer = null;
436
- this.reconcileRetryAttempts = attempt;
437
- void this.saveMergingWithDisk().catch((err) => {
438
- log.warn(`content-hash index: deferred reconcile-save retry failed for ${this.filePath}: ${err}`);
439
- }).finally(() => {
440
- if (this.dirty && !this.reconcileRetryTimer) this.settleReconcileRetry();
441
- });
442
- }, delay);
443
- this.reconcileRetryTimer.unref?.();
444
- }
445
- /** Cancel any armed reconcile-save retry and settle the barrier (a publish landed). */
446
- cancelReconcileRetry() {
447
- if (this.reconcileRetryTimer) {
448
- clearTimeout(this.reconcileRetryTimer);
449
- this.reconcileRetryTimer = null;
450
- }
451
- this.reconcileRetryAttempts = 0;
452
- this.settleReconcileRetry();
453
- }
454
- /** Resolve and clear the retry barrier if one is outstanding. */
455
- settleReconcileRetry() {
456
- const resolve = this.reconcileRetryResolve;
457
- this.reconcileRetryBarrier = null;
458
- this.reconcileRetryResolve = null;
459
- resolve?.();
460
- }
461
- /** Remove a hash from the index (used when archiving/deleting). */
462
- remove(content) {
463
- const hash = _ContentHashIndex.computeHash(content);
464
- this.added.delete(hash);
465
- this.removed.add(hash);
466
- this.hashes.delete(hash);
467
- this.dirty = true;
468
- }
469
- /**
470
- * Remove a pre-computed SHA-256 hash directly from the index without
471
- * re-hashing. Use this when the caller already holds the stored hash
472
- * (e.g. `memory.frontmatter.contentHash`) to avoid the double-hash bug
473
- * where `remove(hash)` would compute `hash(hash)` and never match the
474
- * entry.
475
- */
476
- removeByHash(hash) {
477
- this.added.delete(hash);
478
- this.removed.add(hash);
479
- this.hashes.delete(hash);
480
- this.dirty = true;
481
- }
482
- /**
483
- * Add a pre-computed SHA-256 hash directly to the index without re-hashing.
484
- * Use this when the caller already holds the stored hash
485
- * (e.g. `memory.frontmatter.contentHash`) so that the index records the raw
486
- * content hash rather than re-hashing the citation-annotated body.
487
- *
488
- * @internal Only called from `StorageManager.ensureFactHashIndexAuthoritative`.
489
- * Not part of the public API — prefer `add(content)` for external callers.
490
- */
491
- addByHash(hash) {
492
- this.removed.delete(hash);
493
- this.hashes.add(hash);
494
- this.added.add(hash);
495
- this.dirty = true;
496
- }
497
- /** Normalize content (delegates to content-hash.ts for a single source of truth). */
498
- static normalizeContent(content) {
499
- return normalizeContent(content);
500
- }
501
- /** Compute SHA-256 hash (delegates to content-hash.ts for a single source of truth). */
502
- static computeHash(content) {
503
- return computeContentHash(content);
504
- }
505
- };
506
-
507
29
  // src/storage/tombstone-blocked-capture-mutation.ts
508
30
  import { AsyncLocalStorage } from "async_hooks";
509
31
  import { createHash } from "crypto";
510
- import { mkdir as mkdir2 } from "fs/promises";
511
- import path2 from "path";
32
+ import { mkdir } from "fs/promises";
33
+ import path from "path";
512
34
  var TOMBSTONE_CAPTURE_WRITE_LOCK_STALE_MS = 6e4;
513
35
  var CAPTURE_WRITE_LOCK_MAX_ATTEMPTS = 3;
514
36
  var CAPTURE_WRITE_LOCK_RETRY_BASE_MS = 25;
@@ -538,10 +60,10 @@ var TombstoneBlockedCaptureWriteLock = class {
538
60
  context = new AsyncLocalStorage();
539
61
  captureWriteLockPathForHash(identityHash) {
540
62
  const filename = identityHash.length === 0 ? "explicit-capture-write.lock" : `explicit-capture-write-${identityHash}.lock`;
541
- return path2.join(this.options.stateDir, "tombstone-blocked-capture", filename);
63
+ return path.join(this.options.stateDir, "tombstone-blocked-capture", filename);
542
64
  }
543
65
  async withSingleCaptureWriteLock(lockPath, task) {
544
- await mkdir2(path2.dirname(lockPath), { recursive: true });
66
+ await mkdir(path.dirname(lockPath), { recursive: true });
545
67
  const retry = /* @__PURE__ */ Symbol("retry");
546
68
  const permanentFailure = /* @__PURE__ */ Symbol("permanent-failure");
547
69
  const runWithHeldFileLock = this.options.withHeldFileLock ?? withHeldFileLock;
@@ -693,14 +215,14 @@ async function runTombstoneBlockedChunkMutation(mutation) {
693
215
  // src/storage/tombstone-blocked-capture-sync.ts
694
216
  import { createHash as createHash2, randomUUID as randomUUID2 } from "crypto";
695
217
  import { unlink as unlink2 } from "fs/promises";
696
- import path4 from "path";
218
+ import path3 from "path";
697
219
  import { isDeepStrictEqual } from "util";
698
220
 
699
221
  // src/storage/tombstone-blocked-capture-index.ts
700
222
  import { execFile } from "child_process";
701
223
  import { randomUUID } from "crypto";
702
- import { mkdir as mkdir3, readFile, readdir, rename, stat as stat2, unlink, writeFile } from "fs/promises";
703
- import path3 from "path";
224
+ import { mkdir as mkdir2, readFile, readdir, rename, stat, unlink, writeFile } from "fs/promises";
225
+ import path2 from "path";
704
226
  import { promisify } from "util";
705
227
  var REBUILD_MAX_ATTEMPTS = 3;
706
228
  var execFileAsync = promisify(execFile);
@@ -722,7 +244,7 @@ var TombstoneBlockedCaptureIndex = class {
722
244
  }
723
245
  createIndex() {
724
246
  return new ContentHashIndex(
725
- path3.join(this.options.stateDir, "tombstone-blocked-capture"),
247
+ path2.join(this.options.stateDir, "tombstone-blocked-capture"),
726
248
  this.options.secureStoreKeyProvider,
727
249
  this.options.secureStoreWriteKeyProvider,
728
250
  this.options.memoryDir,
@@ -730,17 +252,17 @@ var TombstoneBlockedCaptureIndex = class {
730
252
  );
731
253
  }
732
254
  indexPath() {
733
- return path3.join(this.options.stateDir, "tombstone-blocked-capture", "fact-hashes.txt");
255
+ return path2.join(this.options.stateDir, "tombstone-blocked-capture", "fact-hashes.txt");
734
256
  }
735
257
  rebuildMarkerPath() {
736
- return path3.join(this.options.stateDir, "tombstone-blocked-capture", "rebuild-required");
258
+ return path2.join(this.options.stateDir, "tombstone-blocked-capture", "rebuild-required");
737
259
  }
738
260
  async readRebuildMarkers() {
739
261
  try {
740
262
  const entries = (await readdir(this.rebuildMarkerPath())).filter((entry) => !entry.startsWith("."));
741
263
  return (await Promise.all(
742
264
  entries.map(async (entry) => {
743
- const markerPath = path3.join(this.rebuildMarkerPath(), entry);
265
+ const markerPath = path2.join(this.rebuildMarkerPath(), entry);
744
266
  try {
745
267
  const raw = (await readFile(markerPath, "utf8")).trim();
746
268
  if (raw === "committed") return { path: markerPath, committed: true };
@@ -760,10 +282,10 @@ var TombstoneBlockedCaptureIndex = class {
760
282
  }
761
283
  const state = value.state;
762
284
  if (state !== "pending" && state !== "committed") malformed = true;
763
- const markerStat = await stat2(markerPath).catch(() => null);
285
+ const markerStat = await stat(markerPath).catch(() => null);
764
286
  const createdAt = typeof value.createdAt === "number" && Number.isFinite(value.createdAt) ? value.createdAt : markerStat?.mtimeMs;
765
287
  if (typeof value.pid !== "number" || !Number.isInteger(value.pid)) malformed = true;
766
- const ownerId = typeof value.ownerId === "string" && value.ownerId.length > 0 ? value.ownerId : path3.basename(markerPath);
288
+ const ownerId = typeof value.ownerId === "string" && value.ownerId.length > 0 ? value.ownerId : path2.basename(markerPath);
767
289
  if (typeof value.ownerId !== "string" || value.ownerId.length === 0) malformed = true;
768
290
  const processStartedAtMs = typeof value.processStartedAtMs === "number" && Number.isFinite(value.processStartedAtMs) && value.processStartedAtMs > 0 ? value.processStartedAtMs : void 0;
769
291
  return {
@@ -855,9 +377,9 @@ var TombstoneBlockedCaptureIndex = class {
855
377
  }
856
378
  async markRebuildRequired(committed = false) {
857
379
  const markerDir = this.rebuildMarkerPath();
858
- await mkdir3(markerDir, { recursive: true });
380
+ await mkdir2(markerDir, { recursive: true });
859
381
  const ownerId = randomUUID();
860
- const markerPath = path3.join(markerDir, ownerId);
382
+ const markerPath = path2.join(markerDir, ownerId);
861
383
  await this.writeMarkerAtomically(
862
384
  markerPath,
863
385
  `${JSON.stringify({
@@ -877,7 +399,7 @@ var TombstoneBlockedCaptureIndex = class {
877
399
  `${JSON.stringify({
878
400
  state: "committed",
879
401
  pid: process.pid,
880
- ownerId: path3.basename(markerPath),
402
+ ownerId: path2.basename(markerPath),
881
403
  createdAt: Date.now(),
882
404
  processStartedAtMs: MARKER_PROCESS_STARTED_AT_MS
883
405
  })}
@@ -919,7 +441,7 @@ var TombstoneBlockedCaptureIndex = class {
919
441
  }
920
442
  async hasPersistedIndexOrMarkers() {
921
443
  try {
922
- await stat2(this.indexPath());
444
+ await stat(this.indexPath());
923
445
  return true;
924
446
  } catch (err) {
925
447
  if (!isErrnoCode(err, "ENOENT")) throw err;
@@ -936,7 +458,7 @@ var TombstoneBlockedCaptureIndex = class {
936
458
  const clearableRebuildMarkers = await this.getClearableRebuildMarkerPaths(rebuildMarkers);
937
459
  let persisted = true;
938
460
  try {
939
- await stat2(this.indexPath());
461
+ await stat(this.indexPath());
940
462
  if (rebuildMarkers.length > 0) persisted = false;
941
463
  } catch (err) {
942
464
  if (isErrnoCode(err, "ENOENT")) persisted = false;
@@ -1121,8 +643,8 @@ var TombstoneBlockedCaptureIndex = class {
1121
643
  await this.failOpen("writeMemoryFrontmatter", () => this.sync(before, { ...before, frontmatter }, rebuildMarker));
1122
644
  }
1123
645
  shouldRebuildAfterInvalidationForPath(filePath) {
1124
- const relative = path3.relative(path3.resolve(this.options.memoryDir), path3.resolve(filePath));
1125
- const category = relative.split(path3.sep)[0];
646
+ const relative = path2.relative(path2.resolve(this.options.memoryDir), path2.resolve(filePath));
647
+ const category = relative.split(path2.sep)[0];
1126
648
  return category === "cold" || RECALL_FALLBACK_DIRS.includes(category);
1127
649
  }
1128
650
  };
@@ -1383,11 +905,11 @@ var TombstoneBlockedCaptureIndexHost = class {
1383
905
  this.invalidateAllMemoriesCache();
1384
906
  this.invalidateKnowledgeIndexCache();
1385
907
  this.markFactHashIndexNotAuthoritative();
1386
- if (filePath.includes(`${path4.sep}cold${path4.sep}`)) {
908
+ if (filePath.includes(`${path3.sep}cold${path3.sep}`)) {
1387
909
  this.invalidateColdMemoriesCache();
1388
910
  }
1389
911
  await this.rebuildTombstoneBlockedCaptureAfterInvalidationForPath(filePath, ownedMarker);
1390
- if (filePath.includes(`${path4.sep}artifacts${path4.sep}`)) {
912
+ if (filePath.includes(`${path3.sep}artifacts${path3.sep}`)) {
1391
913
  this.bumpArtifactWriteVersion();
1392
914
  }
1393
915
  this.bumpMemoryStatusVersion();
@@ -1483,7 +1005,7 @@ var TombstoneBlockedCaptureIndexHost = class {
1483
1005
  const memoryDir = this.tombstoneBlockedCaptureIndexOptions().memoryDir;
1484
1006
  markProjectedMemoryPathInvalid(memoryDir, current.frontmatter.id);
1485
1007
  this.invalidateAllMemoriesCache();
1486
- if (current.path.includes(`${path4.sep}cold${path4.sep}`)) {
1008
+ if (current.path.includes(`${path3.sep}cold${path3.sep}`)) {
1487
1009
  this.invalidateColdMemoriesCache();
1488
1010
  }
1489
1011
  await this.rebuildTombstoneBlockedCaptureAfterInvalidation(rebuildMarker);
@@ -1601,7 +1123,7 @@ var TombstoneBlockedCaptureIndexHost = class {
1601
1123
  return { after, chunks: replay };
1602
1124
  }
1603
1125
  const options = this.tombstoneBlockedCaptureIndexOptions();
1604
- const stagePath = path4.join(
1126
+ const stagePath = path3.join(
1605
1127
  options.stateDir,
1606
1128
  "tombstone-blocked-capture",
1607
1129
  "offline-sync-staging",
@@ -1738,7 +1260,7 @@ var TombstoneBlockedCaptureIndexHost = class {
1738
1260
  */
1739
1261
  async requestSyncReconcileIfMemoryPath(target) {
1740
1262
  const stateDir = this.tombstoneBlockedCaptureIndexOptions().stateDir;
1741
- if (!pathMayCarryEntityRefs(path4.dirname(stateDir), target)) return;
1263
+ if (!pathMayCarryEntityRefs(path3.dirname(stateDir), target)) return;
1742
1264
  await requestEntityCanonicalIdReconcile(stateDir);
1743
1265
  }
1744
1266
  async deleteOfflineSyncFile(filePath) {
@@ -1774,13 +1296,10 @@ var TombstoneBlockedCaptureIndexHost = class {
1774
1296
  };
1775
1297
 
1776
1298
  export {
1777
- CONTENT_HASH_INDEX_RETRY_MAX_DELAY_MS,
1778
- FactHashIndexNotAuthoritativeError,
1779
- ContentHashIndex,
1780
1299
  isTombstoneBlockedCaptureWriteLockBusy,
1781
1300
  normalizeExplicitCaptureContent,
1782
1301
  buildExplicitCaptureDedupKey,
1783
1302
  parseTombstoneBlockedOfflineSyncMemory,
1784
1303
  TombstoneBlockedCaptureIndexHost
1785
1304
  };
1786
- //# sourceMappingURL=chunk-BEQOZOYZ.js.map
1305
+ //# sourceMappingURL=chunk-RVLJEII5.js.map