@remnic/core 9.54.4 → 9.54.5

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 (526) hide show
  1. package/dist/access-admin-ops-surface.d.ts +12 -11
  2. package/dist/access-admin-ops-surface.js +46 -44
  3. package/dist/access-authorization-probe.d.ts +12 -11
  4. package/dist/access-authorization-probe.js +47 -45
  5. package/dist/access-boundary.d.ts +12 -11
  6. package/dist/access-boundary.js +46 -44
  7. package/dist/access-cli.js +92 -90
  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 +12 -11
  11. package/dist/access-extraction-force-flush.js +46 -44
  12. package/dist/access-health-types.d.ts +1 -1
  13. package/dist/access-http-lcm-compaction.d.ts +12 -11
  14. package/dist/access-http-lifecycle-flush.d.ts +12 -11
  15. package/dist/access-http-offline-stream.d.ts +12 -11
  16. package/dist/access-http-query.js +46 -44
  17. package/dist/access-http.d.ts +12 -11
  18. package/dist/access-http.js +56 -54
  19. package/dist/access-identity-continuity-surface.d.ts +9 -9
  20. package/dist/access-identity-continuity-surface.js +46 -44
  21. package/dist/access-lcm-surface.d.ts +12 -11
  22. package/dist/access-lcm-surface.js +46 -44
  23. package/dist/access-mcp.d.ts +12 -11
  24. package/dist/access-mcp.js +52 -50
  25. package/dist/access-memory-search-fanout.d.ts +22 -2
  26. package/dist/access-memory-search-fanout.js +1 -1
  27. package/dist/{access-namespace-preflight-C7n4tgWC.d.ts → access-namespace-preflight-BdHlGd_T.d.ts} +1 -1
  28. package/dist/access-namespace-preflight.d.ts +3 -3
  29. package/dist/access-namespace-preflight.js +46 -44
  30. package/dist/access-observe-write-surface.d.ts +12 -11
  31. package/dist/access-observe-write-surface.js +46 -44
  32. package/dist/access-offline-manifest.d.ts +10 -9
  33. package/dist/access-offline-manifest.js +12 -10
  34. package/dist/access-operations-batch.js +48 -46
  35. package/dist/access-operations.d.ts +15 -14
  36. package/dist/access-operations.js +51 -49
  37. package/dist/access-recall-concurrency.d.ts +12 -11
  38. package/dist/access-recall-concurrency.js +46 -44
  39. package/dist/access-recall-response.d.ts +12 -11
  40. package/dist/access-recall-response.js +46 -44
  41. package/dist/access-recall-surface.d.ts +12 -11
  42. package/dist/access-recall-surface.js +46 -44
  43. package/dist/access-schema.d.ts +90 -90
  44. package/dist/access-schema.js +3 -2
  45. package/dist/{access-service-CXvbxLK-.d.ts → access-service-DL7X9hrg.d.ts} +7 -7
  46. package/dist/access-service-helpers.d.ts +12 -11
  47. package/dist/access-service.d.ts +12 -11
  48. package/dist/access-service.js +46 -44
  49. package/dist/access-surface-catalog.d.ts +12 -11
  50. package/dist/access-wearables-meetings-surface.d.ts +3 -3
  51. package/dist/action-confidence.d.ts +1 -1
  52. package/dist/active-memory-bridge.d.ts +13 -1
  53. package/dist/active-memory-bridge.js +6 -1
  54. package/dist/active-recall.d.ts +1 -1
  55. package/dist/active-recall.js +3 -2
  56. package/dist/active-recall.js.map +1 -1
  57. package/dist/adapters/index.js +4 -4
  58. package/dist/adapters/registry.js +2 -2
  59. package/dist/ambient-provenance.d.ts +1 -1
  60. package/dist/artifact-search.d.ts +1 -1
  61. package/dist/behavior-learner.d.ts +1 -1
  62. package/dist/behavior-signals.d.ts +1 -1
  63. package/dist/bootstrap.d.ts +9 -9
  64. package/dist/briefing.d.ts +2 -2
  65. package/dist/briefing.js +30 -9
  66. package/dist/buffer-surprise-report.d.ts +1 -1
  67. package/dist/buffer-turn-helpers.d.ts +1 -1
  68. package/dist/buffer.d.ts +2 -2
  69. package/dist/buffer.js +3 -3
  70. package/dist/bulk-import/index.d.ts +3 -3
  71. package/dist/calibration.d.ts +1 -1
  72. package/dist/capabilities.d.ts +1 -1
  73. package/dist/{catalog-BOOxl-I2.d.ts → catalog-B90is4d8.d.ts} +1 -1
  74. package/dist/causal-behavior.d.ts +1 -1
  75. package/dist/causal-consolidation.d.ts +1 -1
  76. package/dist/causal-consolidation.js +31 -10
  77. package/dist/causal-consolidation.js.map +1 -1
  78. package/dist/causal-trajectory-graph.d.ts +1 -1
  79. package/dist/{chunk-6LAPLZOS.js → chunk-2DD6ZHOM.js} +8 -3
  80. package/dist/chunk-2DD6ZHOM.js.map +1 -0
  81. package/dist/{chunk-47P3RYZP.js → chunk-2INWPC6E.js} +2 -2
  82. package/dist/{chunk-3CSX3ETE.js → chunk-2LWQSV6A.js} +23 -11
  83. package/dist/chunk-2LWQSV6A.js.map +1 -0
  84. package/dist/{chunk-7BZOBA5J.js → chunk-2PNXOQ4P.js} +69 -11
  85. package/dist/chunk-2PNXOQ4P.js.map +1 -0
  86. package/dist/{chunk-WOPA3SGI.js → chunk-3OTSVCPK.js} +8 -8
  87. package/dist/{chunk-PX2LSHYM.js → chunk-3SXLD5T3.js} +3 -3
  88. package/dist/{chunk-T2JHZWH6.js → chunk-3WGI7F4V.js} +237 -93
  89. package/dist/chunk-3WGI7F4V.js.map +1 -0
  90. package/dist/{chunk-C4ZNGVK3.js → chunk-5JKUSBMX.js} +2 -2
  91. package/dist/{chunk-S75M5ZRK.js → chunk-6LEIWWAF.js} +16 -1
  92. package/dist/chunk-6LEIWWAF.js.map +1 -0
  93. package/dist/{chunk-MAXVH44E.js → chunk-6NNNURLK.js} +4 -4
  94. package/dist/{chunk-LJS7KUPV.js → chunk-6PZGKGAO.js} +2 -2
  95. package/dist/{chunk-YN6ASZUG.js → chunk-6QPI2ITJ.js} +5 -5
  96. package/dist/{chunk-CYF6WVE7.js → chunk-7HG7MGAP.js} +2688 -496
  97. package/dist/chunk-7HG7MGAP.js.map +1 -0
  98. package/dist/{chunk-CGVHPCP2.js → chunk-7Q7JWLQ4.js} +2 -2
  99. package/dist/{chunk-227UFSEQ.js → chunk-7RZJWZ46.js} +5 -5
  100. package/dist/{chunk-JBPKEARU.js → chunk-AU7Q3LSC.js} +4 -4
  101. package/dist/{chunk-PDDTI7IC.js → chunk-B4T3FQMT.js} +1 -1
  102. package/dist/{chunk-UU3G6GUP.js → chunk-BIF4SHMD.js} +1 -1
  103. package/dist/{chunk-UU3G6GUP.js.map → chunk-BIF4SHMD.js.map} +1 -1
  104. package/dist/{chunk-APPFNGX6.js → chunk-BSXGTDVJ.js} +2 -2
  105. package/dist/{chunk-4IIFL7GC.js → chunk-CLKBV3Z3.js} +10 -10
  106. package/dist/{chunk-ZYLC7NFO.js → chunk-CSY44OKU.js} +4 -4
  107. package/dist/{chunk-HLYR2TQL.js → chunk-CUTFSLSD.js} +2 -2
  108. package/dist/{chunk-RDJRFDJY.js → chunk-DBY26JJJ.js} +2 -2
  109. package/dist/{chunk-QWGE2PUH.js → chunk-DDA55IVB.js} +10 -10
  110. package/dist/{chunk-VMMQDEN5.js → chunk-DN2IDKI5.js} +2 -2
  111. package/dist/{chunk-2GFK22OZ.js → chunk-DOOWFDWN.js} +2 -2
  112. package/dist/{chunk-7FGL6CGA.js → chunk-DVYRD4HY.js} +2 -2
  113. package/dist/{chunk-YGLY6QFV.js → chunk-F2Y6I74C.js} +2 -2
  114. package/dist/{chunk-UU7TRFNE.js → chunk-FFEBSFVT.js} +2 -2
  115. package/dist/chunk-HNDIND7P.js +331 -0
  116. package/dist/chunk-HNDIND7P.js.map +1 -0
  117. package/dist/{chunk-NIS256NW.js → chunk-JKW663ZN.js} +2 -2
  118. package/dist/{chunk-G7A5HLUS.js → chunk-KJH6W2I7.js} +2 -2
  119. package/dist/{chunk-IXEBUYO4.js → chunk-KM55SMLG.js} +11 -2
  120. package/dist/{chunk-IXEBUYO4.js.map → chunk-KM55SMLG.js.map} +1 -1
  121. package/dist/{chunk-G2LUMAUF.js → chunk-L7RTUEDG.js} +12 -5
  122. package/dist/chunk-L7RTUEDG.js.map +1 -0
  123. package/dist/chunk-LC2BDILZ.js +57 -0
  124. package/dist/chunk-LC2BDILZ.js.map +1 -0
  125. package/dist/{chunk-JV5YUBIZ.js → chunk-LC3FD4BV.js} +52 -46
  126. package/dist/chunk-LC3FD4BV.js.map +1 -0
  127. package/dist/{chunk-HWRD23DW.js → chunk-LVKYLMSM.js} +3 -3
  128. package/dist/{chunk-RUMNY5DT.js → chunk-MRGJZ75M.js} +6 -2
  129. package/dist/chunk-MRGJZ75M.js.map +1 -0
  130. package/dist/{chunk-ZMYDYNI4.js → chunk-N7CXQ5TA.js} +4 -4
  131. package/dist/{chunk-3JLPGJ43.js → chunk-NGT35IGQ.js} +5 -5
  132. package/dist/{chunk-GUKBW4HL.js → chunk-NQMSEB5D.js} +6 -6
  133. package/dist/{chunk-WRJVB3C2.js → chunk-PO7NXBG2.js} +2 -2
  134. package/dist/{chunk-WM65LU67.js → chunk-QOQQMVR2.js} +2 -2
  135. package/dist/{chunk-QHFV6VNU.js → chunk-QPAQSG3F.js} +2 -2
  136. package/dist/{chunk-UTRO5UJU.js → chunk-QPW3PAIH.js} +5 -1
  137. package/dist/chunk-QPW3PAIH.js.map +1 -0
  138. package/dist/{chunk-6R4G7N4S.js → chunk-QQXWFDRD.js} +128 -74
  139. package/dist/chunk-QQXWFDRD.js.map +1 -0
  140. package/dist/{chunk-UES4BHA2.js → chunk-QTO6BMQZ.js} +2 -2
  141. package/dist/{chunk-THPPCISA.js → chunk-RBII7637.js} +5 -5
  142. package/dist/{chunk-QT2FRYI4.js → chunk-RG426DJO.js} +2 -2
  143. package/dist/{chunk-XUAMCLY4.js → chunk-TKFGFDPJ.js} +17 -13
  144. package/dist/chunk-TKFGFDPJ.js.map +1 -0
  145. package/dist/{chunk-VKXWK44Q.js → chunk-TY6MKIWP.js} +3 -3
  146. package/dist/{chunk-AZM4CCAC.js → chunk-UWJNKGBA.js} +5 -5
  147. package/dist/{chunk-JDZPNCMA.js → chunk-UYOXFFEY.js} +6 -3
  148. package/dist/chunk-UYOXFFEY.js.map +1 -0
  149. package/dist/{chunk-ZPJ4QSGP.js → chunk-VTU5IEKY.js} +2 -2
  150. package/dist/{chunk-RZ4XGKOJ.js → chunk-VYQ4URQB.js} +8 -8
  151. package/dist/{chunk-WDBX6VER.js → chunk-VZRFGJCH.js} +5 -5
  152. package/dist/{chunk-IBKR2TFR.js → chunk-WM5LD6AT.js} +2 -2
  153. package/dist/{chunk-K4QS7LXU.js → chunk-WZWZRZ2V.js} +2 -2
  154. package/dist/{chunk-G4T7L557.js → chunk-XKAR4RF6.js} +2 -2
  155. package/dist/{chunk-DZD576ZU.js → chunk-XSV2YDCJ.js} +2 -2
  156. package/dist/{chunk-G7Z6EENO.js → chunk-YDWPYDML.js} +4 -4
  157. package/dist/{chunk-6HPHEFXT.js → chunk-YKZLOPTC.js} +2 -2
  158. package/dist/{chunk-NH5IR2WM.js → chunk-YR65W7BV.js} +6 -2
  159. package/dist/chunk-YR65W7BV.js.map +1 -0
  160. package/dist/{chunk-GYPQL6XN.js → chunk-Z4N7SVVF.js} +35 -47
  161. package/dist/chunk-Z4N7SVVF.js.map +1 -0
  162. package/dist/{cli-DVUFIa5E.d.ts → cli-jfuZXixq.d.ts} +5 -5
  163. package/dist/cli.d.ts +14 -13
  164. package/dist/cli.js +74 -72
  165. package/dist/coding/pre-action-gate.d.ts +1 -1
  166. package/dist/compounding/engine.d.ts +2 -2
  167. package/dist/compounding/engine.js +30 -9
  168. package/dist/compounding/preference-consolidator.d.ts +1 -1
  169. package/dist/compression-optimizer.d.ts +1 -1
  170. package/dist/config.d.ts +1 -1
  171. package/dist/config.js +3 -2
  172. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  173. package/dist/connectors/codex-materialize-runner.js +30 -9
  174. package/dist/connectors/codex-materialize.d.ts +1 -1
  175. package/dist/connectors/index.d.ts +1 -1
  176. package/dist/connectors/index.js +29 -9
  177. package/dist/consolidation-provenance-check.d.ts +2 -2
  178. package/dist/consolidation-undo.d.ts +2 -2
  179. package/dist/contradiction/index.d.ts +2 -2
  180. package/dist/contradiction/index.js +3 -1
  181. package/dist/contradiction-scan-KCADHXPE.js +20 -0
  182. package/dist/converge-config.d.ts +1 -1
  183. package/dist/convergence-refresh.d.ts +2 -2
  184. package/dist/convergence-refresh.js +32 -11
  185. package/dist/conversation-index/backend.d.ts +1 -1
  186. package/dist/conversation-index/backend.js +2 -2
  187. package/dist/conversation-index/chunker.d.ts +1 -1
  188. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  189. package/dist/conversation-index/indexer.d.ts +1 -1
  190. package/dist/conversation-index/search.d.ts +1 -1
  191. package/dist/corpus-watermark.d.ts +1 -1
  192. package/dist/corpus-watermark.js +21 -20
  193. package/dist/day-summary.d.ts +1 -1
  194. package/dist/delinearize.d.ts +1 -1
  195. package/dist/dependency-propagation-config.d.ts +1 -1
  196. package/dist/{dependency-propagation-delivery-XzF76C9n.d.ts → dependency-propagation-delivery-CTDuAVJc.d.ts} +1 -1
  197. package/dist/direct-answer-wiring.d.ts +1 -1
  198. package/dist/direct-answer.d.ts +1 -1
  199. package/dist/embedding-fallback.d.ts +1 -1
  200. package/dist/enrichment/index.d.ts +1 -1
  201. package/dist/entity-retrieval.d.ts +2 -2
  202. package/dist/entity-retrieval.js +30 -9
  203. package/dist/entity-schema.d.ts +1 -1
  204. package/dist/explicit-capture.d.ts +9 -9
  205. package/dist/explicit-capture.js +6 -4
  206. package/dist/external-wiki-access.d.ts +12 -11
  207. package/dist/external-wiki-access.js +47 -45
  208. package/dist/external-wiki-collection-registration.d.ts +1 -1
  209. package/dist/external-wiki-collection.d.ts +1 -1
  210. package/dist/external-wiki-mcp-tools.d.ts +12 -11
  211. package/dist/extraction-error-classification.d.ts +1 -1
  212. package/dist/extraction-faithfulness.d.ts +1 -1
  213. package/dist/extraction-judge-telemetry.d.ts +1 -1
  214. package/dist/extraction-judge-training.d.ts +1 -1
  215. package/dist/extraction-judge.d.ts +1 -1
  216. package/dist/extraction-liveness.d.ts +1 -1
  217. package/dist/extraction-normalization.d.ts +1 -1
  218. package/dist/extraction-prompt.d.ts +1 -1
  219. package/dist/extraction-source-grounding-rules.d.ts +1 -1
  220. package/dist/extraction-source-grounding.d.ts +1 -1
  221. package/dist/extraction.d.ts +1 -1
  222. package/dist/extraction.js +29 -13
  223. package/dist/fallback-llm.d.ts +1 -1
  224. package/dist/{first-start-migration-626C5554.js → first-start-migration-LMMZFLKK.js} +13 -5
  225. package/dist/first-start-migration-LMMZFLKK.js.map +1 -0
  226. package/dist/graph-dashboard-diff.d.ts +1 -1
  227. package/dist/graph-dashboard-key.d.ts +1 -1
  228. package/dist/graph-dashboard-parser.d.ts +1 -1
  229. package/dist/graph-edge-reinforcement.d.ts +1 -1
  230. package/dist/graph-path-reconstruction.d.ts +1 -1
  231. package/dist/graph-path-scoring.d.ts +1 -1
  232. package/dist/graph-snapshot.d.ts +1 -1
  233. package/dist/graph.d.ts +1 -1
  234. package/dist/harmonic-retrieval.js +1 -1
  235. package/dist/importance.d.ts +1 -1
  236. package/dist/importers/index.d.ts +1 -1
  237. package/dist/in-flight-reads.d.ts +1 -1
  238. package/dist/index.d.ts +1439 -716
  239. package/dist/index.js +207 -121
  240. package/dist/intent.d.ts +1 -1
  241. package/dist/lcm/engine.d.ts +1 -1
  242. package/dist/lcm/engine.js +2 -2
  243. package/dist/lcm/index.d.ts +1 -1
  244. package/dist/lcm/index.js +5 -5
  245. package/dist/lcm/tools.d.ts +1 -1
  246. package/dist/lifecycle.d.ts +1 -1
  247. package/dist/live-connectors-runner.d.ts +1 -1
  248. package/dist/local-llm.d.ts +1 -1
  249. package/dist/local-model-endpoint.d.ts +1 -1
  250. package/dist/maintenance/memory-governance.d.ts +1 -1
  251. package/dist/maintenance/memory-governance.js +30 -9
  252. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
  253. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +30 -9
  254. package/dist/maintenance/rebuild-memory-projection.d.ts +2 -2
  255. package/dist/maintenance/rebuild-memory-projection.js +31 -10
  256. package/dist/{maintenance-BJzNIKBE.d.ts → maintenance-heMZSq7G.d.ts} +3 -3
  257. package/dist/mcp-memory-inspector-app.d.ts +12 -11
  258. package/dist/memory-action-policy.d.ts +1 -1
  259. package/dist/memory-cache.d.ts +1 -1
  260. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  261. package/dist/memory-projection-mutations.js +2 -2
  262. package/dist/memory-projection-store.d.ts +6 -2
  263. package/dist/memory-projection-store.js +1 -1
  264. package/dist/memory-provenance.d.ts +1 -1
  265. package/dist/memory-snapshot.d.ts +1 -1
  266. package/dist/memory-worth-outcomes.d.ts +2 -2
  267. package/dist/models-json.d.ts +1 -1
  268. package/dist/namespaces/migrate.d.ts +3 -3
  269. package/dist/namespaces/migrate.js +20 -19
  270. package/dist/namespaces/principal.d.ts +1 -1
  271. package/dist/namespaces/search.d.ts +1 -1
  272. package/dist/namespaces/search.js +6 -6
  273. package/dist/namespaces/storage.d.ts +3 -3
  274. package/dist/namespaces/storage.js +30 -9
  275. package/dist/native-knowledge.d.ts +1 -1
  276. package/dist/offline-sync-file-io.d.ts +20 -0
  277. package/dist/offline-sync-file-io.js +18 -0
  278. package/dist/offline-sync-file-io.js.map +1 -0
  279. package/dist/offline-sync-impression-drain.d.ts +1 -1
  280. package/dist/offline-sync-impression-drain.js +5 -5
  281. package/dist/offline-sync.d.ts +8 -6
  282. package/dist/offline-sync.js +2 -1
  283. package/dist/operator-doctor-corpus.d.ts +1 -1
  284. package/dist/operator-doctor-corpus.js +22 -21
  285. package/dist/operator-doctor-replica.d.ts +1 -1
  286. package/dist/operator-toolkit.d.ts +3 -3
  287. package/dist/operator-toolkit.js +34 -32
  288. package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
  289. package/dist/orchestration/maintenance.d.ts +4 -4
  290. package/dist/orchestration/maintenance.js +35 -15
  291. package/dist/{orchestrator-BiXgBJBQ.d.ts → orchestrator-BQQPsSjs.d.ts} +11 -8
  292. package/dist/orchestrator.d.ts +9 -9
  293. package/dist/orchestrator.js +93 -91
  294. package/dist/patterns-cli.d.ts +1 -1
  295. package/dist/{pipeline-sz_dcuLg.d.ts → pipeline-DFfmsnGk.d.ts} +1 -1
  296. package/dist/policy-runtime.d.ts +1 -1
  297. package/dist/proactive-contention.d.ts +1 -1
  298. package/dist/provenance.d.ts +1 -1
  299. package/dist/{purge-533FZLS4.js → purge-GB7PZHT2.js} +2 -2
  300. package/dist/{qmd-eAWObK4M.d.ts → qmd-BF5bcVRs.d.ts} +1 -1
  301. package/dist/qmd-preflight.d.ts +2 -2
  302. package/dist/qmd-recall-cache.d.ts +1 -1
  303. package/dist/qmd.d.ts +2 -2
  304. package/dist/recall-concurrency-config.d.ts +1 -1
  305. package/dist/recall-disclosure-escalation.d.ts +1 -1
  306. package/dist/recall-explain-renderer.d.ts +1 -1
  307. package/dist/recall-explain-renderer.js +3 -3
  308. package/dist/recall-memory-map.d.ts +1 -1
  309. package/dist/recall-planner-llm.d.ts +1 -1
  310. package/dist/recall-state.d.ts +1 -1
  311. package/dist/recall-tag-filter.d.ts +1 -1
  312. package/dist/recall-timings.d.ts +1 -1
  313. package/dist/recall-xray-cli.d.ts +1 -1
  314. package/dist/recall-xray-cli.js +4 -4
  315. package/dist/recall-xray-renderer.d.ts +1 -1
  316. package/dist/recall-xray-renderer.js +3 -3
  317. package/dist/recall-xray.d.ts +1 -1
  318. package/dist/recall-xray.js +2 -2
  319. package/dist/reconcile/cursor.d.ts +2 -1
  320. package/dist/reconcile/manifest.d.ts +2 -1
  321. package/dist/reconcile/manifest.js +6 -5
  322. package/dist/reconcile/plan.d.ts +2 -1
  323. package/dist/reconcile/plan.js +3 -2
  324. package/dist/replay/normalizers/chatgpt.d.ts +1 -1
  325. package/dist/replay/normalizers/claude.d.ts +1 -1
  326. package/dist/replay/normalizers/openclaw.d.ts +1 -1
  327. package/dist/replay/normalizers/shared.d.ts +1 -1
  328. package/dist/replay/runner.d.ts +1 -1
  329. package/dist/replay/types.d.ts +1 -1
  330. package/dist/replica-divergence.d.ts +1 -1
  331. package/dist/replica-peers-config.d.ts +1 -1
  332. package/dist/resolve-auth-token.d.ts +1 -1
  333. package/dist/resume-bundles.js +4 -3
  334. package/dist/retrieval-agents.d.ts +2 -2
  335. package/dist/retrieval-tiers.d.ts +1 -1
  336. package/dist/routing/engine.d.ts +1 -1
  337. package/dist/routing/store.d.ts +1 -1
  338. package/dist/salvage-envelope.d.ts +1 -1
  339. package/dist/schemas.d.ts +138 -138
  340. package/dist/{scope-profiles-BBQsXuyj.d.ts → scope-profiles-CbUOsE_E.d.ts} +1 -1
  341. package/dist/search/embed-helper.d.ts +1 -1
  342. package/dist/search/factory.d.ts +1 -1
  343. package/dist/search/factory.js +4 -4
  344. package/dist/search/index.d.ts +1 -1
  345. package/dist/search/index.js +6 -6
  346. package/dist/search/lancedb-backend.d.ts +1 -1
  347. package/dist/search/meilisearch-backend.d.ts +1 -1
  348. package/dist/search/noop-backend.d.ts +1 -1
  349. package/dist/search/orama-backend.d.ts +1 -1
  350. package/dist/search/port.d.ts +1 -1
  351. package/dist/search/remote-backend.d.ts +1 -1
  352. package/dist/{semantic-consolidation-HD8RkzVA.d.ts → semantic-consolidation-DAB3xdKM.d.ts} +1 -1
  353. package/dist/semantic-consolidation.d.ts +2 -2
  354. package/dist/semantic-consolidation.js +31 -10
  355. package/dist/semantic-rule-promotion.js +30 -9
  356. package/dist/semantic-rule-verifier.d.ts +1 -1
  357. package/dist/semantic-rule-verifier.js +30 -9
  358. package/dist/{service-DIrtHHEg.d.ts → service-DGKg2O6r.d.ts} +2 -2
  359. package/dist/session-observer-bands.d.ts +1 -1
  360. package/dist/session-observer-state.d.ts +1 -1
  361. package/dist/shared-context/manager.d.ts +9 -9
  362. package/dist/signal.d.ts +1 -1
  363. package/dist/source-agent-qualifier.d.ts +1 -1
  364. package/dist/source-agent-qualifier.js +28 -12
  365. package/dist/{storage-DqCzXi56.d.ts → storage-CC1jKcWg.d.ts} +46 -13
  366. package/dist/storage.d.ts +2 -2
  367. package/dist/storage.js +30 -9
  368. package/dist/summarizer.d.ts +1 -1
  369. package/dist/summary-snapshot.d.ts +1 -1
  370. package/dist/temporal-supersession.d.ts +2 -2
  371. package/dist/temporal-timeline-recall.d.ts +1 -1
  372. package/dist/temporal-validity.d.ts +1 -1
  373. package/dist/threading.d.ts +1 -1
  374. package/dist/tier-migration.d.ts +2 -2
  375. package/dist/tier-routing.d.ts +2 -2
  376. package/dist/tier-routing.js +7 -1
  377. package/dist/{tier-stats-2JCZYEF7.js → tier-stats-JDN6HRNT.js} +8 -2
  378. package/dist/{tier-stats-2JCZYEF7.js.map → tier-stats-JDN6HRNT.js.map} +1 -1
  379. package/dist/topics.d.ts +1 -1
  380. package/dist/transcript.d.ts +1 -1
  381. package/dist/transfer/types.d.ts +66 -66
  382. package/dist/trust-score-stage.d.ts +1 -1
  383. package/dist/trust-score.d.ts +1 -1
  384. package/dist/{types-d_j4vC6N.d.ts → types-BnQza1y8.d.ts} +2 -1
  385. package/dist/types.d.ts +1 -1
  386. package/dist/types.js +1 -1
  387. package/dist/utility-runtime.d.ts +2 -2
  388. package/dist/verified-recall.js +30 -9
  389. package/dist/write-envelope.d.ts +1 -1
  390. package/package.json +2 -2
  391. package/src/access-http.test.ts +31 -0
  392. package/src/access-memory-search-fanout.ts +24 -1
  393. package/src/access-offline-manifest.ts +5 -0
  394. package/src/access-service-namespace.test.ts +14 -0
  395. package/src/access-service-observe-scope.test.ts +2 -0
  396. package/src/access-service-offline-file-content.test.ts +211 -0
  397. package/src/access-service.ts +20 -43
  398. package/src/active-memory-bridge.test.ts +151 -0
  399. package/src/active-memory-bridge.ts +87 -11
  400. package/src/briefing.test.ts +38 -0
  401. package/src/briefing.ts +3 -3
  402. package/src/cli.ts +6 -1
  403. package/src/connectors/codex-materialize-runner.ts +2 -0
  404. package/src/contradiction/contradiction-scan.ts +2 -0
  405. package/src/contradiction/contradiction.test.ts +42 -0
  406. package/src/correction/correction-access-wiring.ts +8 -2
  407. package/src/correction/correction-storage-integration.test.ts +7 -0
  408. package/src/explicit-capture.test.ts +24 -0
  409. package/src/explicit-capture.ts +2 -0
  410. package/src/index.ts +3 -0
  411. package/src/maintenance/first-start-migration.ts +2 -1
  412. package/src/maintenance/memory-governance.test.ts +25 -0
  413. package/src/maintenance/memory-governance.ts +4 -1
  414. package/src/maintenance/pattern-reinforcement.test.ts +20 -0
  415. package/src/maintenance/pattern-reinforcement.ts +2 -1
  416. package/src/maintenance/rebuild-memory-projection.ts +8 -8
  417. package/src/memory-projection-store.ts +25 -27
  418. package/src/offline-sync-file-io.ts +68 -0
  419. package/src/offline-sync.ts +43 -57
  420. package/src/orchestration/consolidation-run.ts +5 -4
  421. package/src/orchestration/contradiction-linking-coordinator.ts +7 -0
  422. package/src/orchestration/contradiction-localization.integration.test.ts +115 -0
  423. package/src/orchestration/lifecycle-policy-coordinator.ts +2 -1
  424. package/src/orchestration/qmd-result-resolver.test.ts +215 -14
  425. package/src/orchestration/qmd-result-resolver.ts +142 -82
  426. package/src/orchestration/recall-search-pipeline.test.ts +41 -0
  427. package/src/orchestration/recall-search-pipeline.ts +12 -0
  428. package/src/orchestration/semantic-consolidation-coordinator.ts +2 -1
  429. package/src/orchestration/tier-migration-coordinator.ts +23 -56
  430. package/src/orchestration/workspace-ops.test.ts +37 -0
  431. package/src/orchestration/workspace-ops.ts +5 -29
  432. package/src/orchestrator.ts +7 -8
  433. package/src/storage/supersession-audit.ts +7 -1
  434. package/src/storage/supersession-side-effects.ts +17 -5
  435. package/src/storage.ts +18 -19
  436. package/src/support-passport/card-projection.test.ts +129 -0
  437. package/src/support-passport/card-projection.ts +287 -0
  438. package/src/support-passport/card-service.test.ts +2462 -0
  439. package/src/support-passport/card-service.ts +1042 -0
  440. package/src/support-passport/contracts.test.ts +143 -0
  441. package/src/support-passport/contracts.ts +136 -0
  442. package/src/support-passport/errors.ts +24 -0
  443. package/src/support-passport/grant-contracts.ts +139 -0
  444. package/src/support-passport/grant-service-cache.test.ts +148 -0
  445. package/src/support-passport/grant-service-cancellation.test.ts +81 -0
  446. package/src/support-passport/grant-service.test.ts +2882 -0
  447. package/src/support-passport/grant-service.ts +364 -0
  448. package/src/support-passport/grant-store-commit-hook.test.ts +123 -0
  449. package/src/support-passport/grant-store-order.test.ts +60 -0
  450. package/src/support-passport/grant-store-path-safety.test.ts +30 -0
  451. package/src/support-passport/grant-store-recovery.test.ts +448 -0
  452. package/src/support-passport/grant-store.ts +902 -0
  453. package/src/support-passport/index.ts +7 -0
  454. package/src/support-passport/offline-sync-guard.ts +230 -0
  455. package/src/support-passport/owner-lock.ts +53 -0
  456. package/src/support-passport/private-file.ts +371 -0
  457. package/src/tier-routing.ts +28 -17
  458. package/src/training-export/converter.test.ts +24 -0
  459. package/src/training-export/converter.ts +2 -0
  460. package/src/types.ts +1 -1
  461. package/src/wearables/service.test.ts +13 -0
  462. package/src/wearables/service.ts +2 -0
  463. package/dist/chunk-3CSX3ETE.js.map +0 -1
  464. package/dist/chunk-6LAPLZOS.js.map +0 -1
  465. package/dist/chunk-6R4G7N4S.js.map +0 -1
  466. package/dist/chunk-7BZOBA5J.js.map +0 -1
  467. package/dist/chunk-CYF6WVE7.js.map +0 -1
  468. package/dist/chunk-G2LUMAUF.js.map +0 -1
  469. package/dist/chunk-GYPQL6XN.js.map +0 -1
  470. package/dist/chunk-JDZPNCMA.js.map +0 -1
  471. package/dist/chunk-JV5YUBIZ.js.map +0 -1
  472. package/dist/chunk-NH5IR2WM.js.map +0 -1
  473. package/dist/chunk-RUMNY5DT.js.map +0 -1
  474. package/dist/chunk-S75M5ZRK.js.map +0 -1
  475. package/dist/chunk-T2JHZWH6.js.map +0 -1
  476. package/dist/chunk-UTRO5UJU.js.map +0 -1
  477. package/dist/chunk-XUAMCLY4.js.map +0 -1
  478. package/dist/contradiction-scan-HYLIRMJ2.js +0 -14
  479. package/dist/first-start-migration-626C5554.js.map +0 -1
  480. /package/dist/{chunk-47P3RYZP.js.map → chunk-2INWPC6E.js.map} +0 -0
  481. /package/dist/{chunk-WOPA3SGI.js.map → chunk-3OTSVCPK.js.map} +0 -0
  482. /package/dist/{chunk-PX2LSHYM.js.map → chunk-3SXLD5T3.js.map} +0 -0
  483. /package/dist/{chunk-C4ZNGVK3.js.map → chunk-5JKUSBMX.js.map} +0 -0
  484. /package/dist/{chunk-MAXVH44E.js.map → chunk-6NNNURLK.js.map} +0 -0
  485. /package/dist/{chunk-LJS7KUPV.js.map → chunk-6PZGKGAO.js.map} +0 -0
  486. /package/dist/{chunk-YN6ASZUG.js.map → chunk-6QPI2ITJ.js.map} +0 -0
  487. /package/dist/{chunk-CGVHPCP2.js.map → chunk-7Q7JWLQ4.js.map} +0 -0
  488. /package/dist/{chunk-227UFSEQ.js.map → chunk-7RZJWZ46.js.map} +0 -0
  489. /package/dist/{chunk-JBPKEARU.js.map → chunk-AU7Q3LSC.js.map} +0 -0
  490. /package/dist/{chunk-PDDTI7IC.js.map → chunk-B4T3FQMT.js.map} +0 -0
  491. /package/dist/{chunk-APPFNGX6.js.map → chunk-BSXGTDVJ.js.map} +0 -0
  492. /package/dist/{chunk-4IIFL7GC.js.map → chunk-CLKBV3Z3.js.map} +0 -0
  493. /package/dist/{chunk-ZYLC7NFO.js.map → chunk-CSY44OKU.js.map} +0 -0
  494. /package/dist/{chunk-HLYR2TQL.js.map → chunk-CUTFSLSD.js.map} +0 -0
  495. /package/dist/{chunk-RDJRFDJY.js.map → chunk-DBY26JJJ.js.map} +0 -0
  496. /package/dist/{chunk-QWGE2PUH.js.map → chunk-DDA55IVB.js.map} +0 -0
  497. /package/dist/{chunk-VMMQDEN5.js.map → chunk-DN2IDKI5.js.map} +0 -0
  498. /package/dist/{chunk-2GFK22OZ.js.map → chunk-DOOWFDWN.js.map} +0 -0
  499. /package/dist/{chunk-7FGL6CGA.js.map → chunk-DVYRD4HY.js.map} +0 -0
  500. /package/dist/{chunk-YGLY6QFV.js.map → chunk-F2Y6I74C.js.map} +0 -0
  501. /package/dist/{chunk-UU7TRFNE.js.map → chunk-FFEBSFVT.js.map} +0 -0
  502. /package/dist/{chunk-NIS256NW.js.map → chunk-JKW663ZN.js.map} +0 -0
  503. /package/dist/{chunk-G7A5HLUS.js.map → chunk-KJH6W2I7.js.map} +0 -0
  504. /package/dist/{chunk-HWRD23DW.js.map → chunk-LVKYLMSM.js.map} +0 -0
  505. /package/dist/{chunk-ZMYDYNI4.js.map → chunk-N7CXQ5TA.js.map} +0 -0
  506. /package/dist/{chunk-3JLPGJ43.js.map → chunk-NGT35IGQ.js.map} +0 -0
  507. /package/dist/{chunk-GUKBW4HL.js.map → chunk-NQMSEB5D.js.map} +0 -0
  508. /package/dist/{chunk-WRJVB3C2.js.map → chunk-PO7NXBG2.js.map} +0 -0
  509. /package/dist/{chunk-WM65LU67.js.map → chunk-QOQQMVR2.js.map} +0 -0
  510. /package/dist/{chunk-QHFV6VNU.js.map → chunk-QPAQSG3F.js.map} +0 -0
  511. /package/dist/{chunk-UES4BHA2.js.map → chunk-QTO6BMQZ.js.map} +0 -0
  512. /package/dist/{chunk-THPPCISA.js.map → chunk-RBII7637.js.map} +0 -0
  513. /package/dist/{chunk-QT2FRYI4.js.map → chunk-RG426DJO.js.map} +0 -0
  514. /package/dist/{chunk-VKXWK44Q.js.map → chunk-TY6MKIWP.js.map} +0 -0
  515. /package/dist/{chunk-AZM4CCAC.js.map → chunk-UWJNKGBA.js.map} +0 -0
  516. /package/dist/{chunk-ZPJ4QSGP.js.map → chunk-VTU5IEKY.js.map} +0 -0
  517. /package/dist/{chunk-RZ4XGKOJ.js.map → chunk-VYQ4URQB.js.map} +0 -0
  518. /package/dist/{chunk-WDBX6VER.js.map → chunk-VZRFGJCH.js.map} +0 -0
  519. /package/dist/{chunk-IBKR2TFR.js.map → chunk-WM5LD6AT.js.map} +0 -0
  520. /package/dist/{chunk-K4QS7LXU.js.map → chunk-WZWZRZ2V.js.map} +0 -0
  521. /package/dist/{chunk-G4T7L557.js.map → chunk-XKAR4RF6.js.map} +0 -0
  522. /package/dist/{chunk-DZD576ZU.js.map → chunk-XSV2YDCJ.js.map} +0 -0
  523. /package/dist/{chunk-G7Z6EENO.js.map → chunk-YDWPYDML.js.map} +0 -0
  524. /package/dist/{chunk-6HPHEFXT.js.map → chunk-YKZLOPTC.js.map} +0 -0
  525. /package/dist/{contradiction-scan-HYLIRMJ2.js.map → contradiction-scan-KCADHXPE.js.map} +0 -0
  526. /package/dist/{purge-533FZLS4.js.map → purge-GB7PZHT2.js.map} +0 -0
@@ -7,22 +7,22 @@ import {
7
7
  syncWearableSource,
8
8
  wearableSourceLabel
9
9
  } from "./chunk-HOIRB77A.js";
10
+ import {
11
+ runPeerProfileReasoner
12
+ } from "./chunk-I74SUMNI.js";
10
13
  import {
11
14
  CompressionGuidelineCoordinator
12
15
  } from "./chunk-6LKEUCEM.js";
13
16
  import {
14
17
  ActivityStore,
15
18
  MaintenanceScheduler
16
- } from "./chunk-WOPA3SGI.js";
17
- import {
18
- runPeerProfileReasoner
19
- } from "./chunk-I74SUMNI.js";
19
+ } from "./chunk-3OTSVCPK.js";
20
20
  import {
21
21
  migrateFromEngram
22
22
  } from "./chunk-7HYPN2GC.js";
23
23
  import {
24
24
  LcmEngine
25
- } from "./chunk-MAXVH44E.js";
25
+ } from "./chunk-6NNNURLK.js";
26
26
  import {
27
27
  chunkTranscriptEntries
28
28
  } from "./chunk-TECVW3JP.js";
@@ -32,7 +32,7 @@ import {
32
32
  import {
33
33
  CompoundingEngine,
34
34
  defaultTierMigrationCycleBudget
35
- } from "./chunk-YGLY6QFV.js";
35
+ } from "./chunk-F2Y6I74C.js";
36
36
  import {
37
37
  SharedContextManager
38
38
  } from "./chunk-M23RF3LJ.js";
@@ -41,6 +41,9 @@ import {
41
41
  applyUtilityRankingRuntimeDelta,
42
42
  loadUtilityRuntimeValues
43
43
  } from "./chunk-SEF4IOFE.js";
44
+ import {
45
+ decideTierTransition
46
+ } from "./chunk-6LEIWWAF.js";
44
47
  import {
45
48
  TmtBuilder
46
49
  } from "./chunk-ECZU5BJH.js";
@@ -56,9 +59,6 @@ import {
56
59
  import {
57
60
  TierMigrationExecutor
58
61
  } from "./chunk-YRFAYOFQ.js";
59
- import {
60
- decideTierTransition
61
- } from "./chunk-S75M5ZRK.js";
62
62
  import {
63
63
  HourlySummarizer
64
64
  } from "./chunk-LLJMAULE.js";
@@ -69,18 +69,6 @@ import {
69
69
  import {
70
70
  SessionObserverState
71
71
  } from "./chunk-QFN4U7AG.js";
72
- import {
73
- applyRuntimeRetrievalPolicy
74
- } from "./chunk-5IZL4DCV.js";
75
- import {
76
- RerankCache,
77
- reorderByRankedKeys,
78
- rerankLocalOrNoop
79
- } from "./chunk-LUDXM7MD.js";
80
- import {
81
- buildResponseGuidanceRecallSection,
82
- shouldRecallResponseGuidance
83
- } from "./chunk-6TCXIRP5.js";
84
72
  import {
85
73
  mergeWithAgentResults,
86
74
  runDirectAgent,
@@ -103,11 +91,23 @@ import {
103
91
  resolvePromptTagPrefilterAsync
104
92
  } from "./chunk-ZOKZIR5K.js";
105
93
  import {
106
- findUnresolvedEntityRefs
107
- } from "./chunk-X7XN6YU4.js";
94
+ applyRuntimeRetrievalPolicy
95
+ } from "./chunk-5IZL4DCV.js";
108
96
  import {
109
97
  RelevanceStore
110
98
  } from "./chunk-KATEWTQJ.js";
99
+ import {
100
+ RerankCache,
101
+ reorderByRankedKeys,
102
+ rerankLocalOrNoop
103
+ } from "./chunk-LUDXM7MD.js";
104
+ import {
105
+ buildResponseGuidanceRecallSection,
106
+ shouldRecallResponseGuidance
107
+ } from "./chunk-6TCXIRP5.js";
108
+ import {
109
+ findUnresolvedEntityRefs
110
+ } from "./chunk-X7XN6YU4.js";
111
111
  import {
112
112
  dedupeResultsByNamespace,
113
113
  hasMemoryForResult,
@@ -163,7 +163,7 @@ import {
163
163
  } from "./chunk-OH7QLI6W.js";
164
164
  import {
165
165
  ExtractionEngine
166
- } from "./chunk-G4T7L557.js";
166
+ } from "./chunk-XKAR4RF6.js";
167
167
  import {
168
168
  parseMemoryActionEligibilityContext
169
169
  } from "./chunk-WFLBP5GC.js";
@@ -190,7 +190,7 @@ import {
190
190
  buildEntityRecallSection,
191
191
  entityRecentTranscriptLookbackHours,
192
192
  readRecentEntityTranscriptEntries
193
- } from "./chunk-DZD576ZU.js";
193
+ } from "./chunk-XSV2YDCJ.js";
194
194
  import {
195
195
  buildEventOrderRecallSection,
196
196
  shouldRecallEventOrderEvidence
@@ -207,7 +207,7 @@ import {
207
207
  } from "./chunk-YK6BDDHP.js";
208
208
  import {
209
209
  refreshConvergedNamespaces
210
- } from "./chunk-C4ZNGVK3.js";
210
+ } from "./chunk-5JKUSBMX.js";
211
211
  import {
212
212
  formatDaySummaryMemories
213
213
  } from "./chunk-RPSYDM6C.js";
@@ -216,7 +216,7 @@ import {
216
216
  ensureBuiltInWearableConnectors,
217
217
  getWearableConnector,
218
218
  listWearableConnectors
219
- } from "./chunk-JV5YUBIZ.js";
219
+ } from "./chunk-LC3FD4BV.js";
220
220
  import {
221
221
  normalizeReplaySessionKey
222
222
  } from "./chunk-AJVLDJU6.js";
@@ -226,34 +226,34 @@ import {
226
226
  import {
227
227
  compareVerifiedEpisodeResults,
228
228
  searchVerifiedEpisodes
229
- } from "./chunk-6HPHEFXT.js";
229
+ } from "./chunk-YKZLOPTC.js";
230
230
  import {
231
231
  ThreadingManager
232
232
  } from "./chunk-OJP3N7UK.js";
233
233
  import {
234
234
  compareVerifiedSemanticRuleResults,
235
235
  searchVerifiedSemanticRules
236
- } from "./chunk-LJS7KUPV.js";
236
+ } from "./chunk-6PZGKGAO.js";
237
237
  import {
238
238
  searchWorkProductLedgerEntries
239
239
  } from "./chunk-WT6UL3UA.js";
240
240
  import {
241
241
  TranscriptManager
242
242
  } from "./chunk-HYQJQGD3.js";
243
- import {
244
- PolicyRuntimeManager
245
- } from "./chunk-33JBK2XP.js";
246
243
  import {
247
244
  runNamespaceMaintenanceFanout,
248
245
  summarizeNamespaceMaintenanceHealth
249
- } from "./chunk-4IIFL7GC.js";
246
+ } from "./chunk-CLKBV3Z3.js";
250
247
  import {
251
248
  NamespaceCatalog,
252
249
  planNamespaceMaintenance
253
- } from "./chunk-RZ4XGKOJ.js";
250
+ } from "./chunk-VYQ4URQB.js";
251
+ import {
252
+ PolicyRuntimeManager
253
+ } from "./chunk-33JBK2XP.js";
254
254
  import {
255
255
  searchHarmonicRetrieval
256
- } from "./chunk-PDDTI7IC.js";
256
+ } from "./chunk-B4T3FQMT.js";
257
257
  import {
258
258
  isAboveImportanceThreshold,
259
259
  scoreImportance
@@ -285,7 +285,7 @@ import {
285
285
  materializeAfterSemanticConsolidation,
286
286
  parseConsolidationResponse,
287
287
  parseOperatorAwareConsolidationResponse
288
- } from "./chunk-WM65LU67.js";
288
+ } from "./chunk-QOQQMVR2.js";
289
289
  import {
290
290
  BootstrapEngine
291
291
  } from "./chunk-MYVPLJOO.js";
@@ -300,13 +300,13 @@ import {
300
300
  } from "./chunk-UQ7RN5HK.js";
301
301
  import {
302
302
  SmartBuffer
303
- } from "./chunk-HLYR2TQL.js";
303
+ } from "./chunk-CUTFSLSD.js";
304
304
  import {
305
305
  isDisagreementPrompt
306
306
  } from "./chunk-H3FZVNRN.js";
307
307
  import {
308
308
  detectMeetings
309
- } from "./chunk-47P3RYZP.js";
309
+ } from "./chunk-2INWPC6E.js";
310
310
  import {
311
311
  compileCorrectionRule,
312
312
  correctionsFilePath,
@@ -331,7 +331,7 @@ import {
331
331
  } from "./chunk-KD3QD3A5.js";
332
332
  import {
333
333
  MeetingsInputError
334
- } from "./chunk-QWGE2PUH.js";
334
+ } from "./chunk-DDA55IVB.js";
335
335
  import {
336
336
  WearablesInputError,
337
337
  describeErrorForOperator
@@ -352,13 +352,17 @@ import {
352
352
  filterRecallCandidates,
353
353
  isGenericRecallExcludedPath,
354
354
  isTopLevelArchivePath
355
- } from "./chunk-T2JHZWH6.js";
355
+ } from "./chunk-3WGI7F4V.js";
356
356
  import {
357
357
  importCapsule
358
358
  } from "./chunk-QYN5PXDZ.js";
359
359
  import {
360
360
  isCodingGraphInstalled
361
361
  } from "./chunk-VQ7B2Q6M.js";
362
+ import {
363
+ listTrustZoneRecords,
364
+ searchTrustZoneRecords
365
+ } from "./chunk-KQS72GCR.js";
362
366
  import {
363
367
  applyTrustScoreStage,
364
368
  buildTrustSignalsForRerank,
@@ -366,10 +370,6 @@ import {
366
370
  trustResultFor,
367
371
  trustResultKey
368
372
  } from "./chunk-GNVZQ5JN.js";
369
- import {
370
- listTrustZoneRecords,
371
- searchTrustZoneRecords
372
- } from "./chunk-KQS72GCR.js";
373
373
  import {
374
374
  boundRecallContextComposition,
375
375
  composeRecallContext,
@@ -379,7 +379,7 @@ import {
379
379
  } from "./chunk-AHVEHR6K.js";
380
380
  import {
381
381
  buildXraySnapshot
382
- } from "./chunk-QHFV6VNU.js";
382
+ } from "./chunk-QPAQSG3F.js";
383
383
  import {
384
384
  objectiveStateStoreOverrideForNamespace,
385
385
  searchObjectiveStateSnapshots
@@ -396,25 +396,10 @@ import {
396
396
  } from "./chunk-QDW3E4RD.js";
397
397
  import {
398
398
  shouldSkipImplicitExtraction
399
- } from "./chunk-RUMNY5DT.js";
400
- import {
401
- NamespaceSearchRouter,
402
- namespaceCollectionName
403
- } from "./chunk-VMMQDEN5.js";
404
- import {
405
- createConversationIndexRuntime,
406
- createSearchBackend,
407
- isSearchBackendEnabled
408
- } from "./chunk-AZM4CCAC.js";
409
- import {
410
- NoopSearchBackend
411
- } from "./chunk-CYEPCZN5.js";
399
+ } from "./chunk-MRGJZ75M.js";
412
400
  import {
413
401
  NamespaceStorageRouter
414
- } from "./chunk-WDBX6VER.js";
415
- import {
416
- writeConversationChunks
417
- } from "./chunk-72A4L5JJ.js";
402
+ } from "./chunk-VZRFGJCH.js";
418
403
  import {
419
404
  searchCausalTrajectories
420
405
  } from "./chunk-AHZOMHWN.js";
@@ -423,7 +408,7 @@ import {
423
408
  } from "./chunk-BIJAWZYW.js";
424
409
  import {
425
410
  buildChainFollowupGenerator
426
- } from "./chunk-JDZPNCMA.js";
411
+ } from "./chunk-UYOXFFEY.js";
427
412
  import {
428
413
  QmdResultResolver,
429
414
  StorageManager,
@@ -442,7 +427,7 @@ import {
442
427
  reconstructFusionInputs,
443
428
  selfDeps,
444
429
  serializeFusionDay
445
- } from "./chunk-6R4G7N4S.js";
430
+ } from "./chunk-QQXWFDRD.js";
446
431
  import {
447
432
  bodyIsEscaped,
448
433
  decodeTranscriptBody,
@@ -456,6 +441,21 @@ import {
456
441
  import {
457
442
  buildRetiredFactTombstoneInputs
458
443
  } from "./chunk-MLPTFODV.js";
444
+ import {
445
+ NamespaceSearchRouter,
446
+ namespaceCollectionName
447
+ } from "./chunk-DN2IDKI5.js";
448
+ import {
449
+ createConversationIndexRuntime,
450
+ createSearchBackend,
451
+ isSearchBackendEnabled
452
+ } from "./chunk-UWJNKGBA.js";
453
+ import {
454
+ NoopSearchBackend
455
+ } from "./chunk-CYEPCZN5.js";
456
+ import {
457
+ writeConversationChunks
458
+ } from "./chunk-72A4L5JJ.js";
459
459
  import {
460
460
  canRecallToolScopedMemory,
461
461
  shouldPromoteGlobalFactToShared,
@@ -463,7 +463,7 @@ import {
463
463
  } from "./chunk-S2V7RUCL.js";
464
464
  import {
465
465
  confidenceTier
466
- } from "./chunk-UU3G6GUP.js";
466
+ } from "./chunk-BIF4SHMD.js";
467
467
  import {
468
468
  lintWorkspaceFiles,
469
469
  rotateMarkdownFileToArchive
@@ -554,7 +554,7 @@ import {
554
554
  throwIfRecallAborted,
555
555
  tokenizeRecallQuery,
556
556
  utcDateKeysForLocalDay
557
- } from "./chunk-ZMYDYNI4.js";
557
+ } from "./chunk-N7CXQ5TA.js";
558
558
  import {
559
559
  inferIntentFromText,
560
560
  intentCompatibilityScore,
@@ -597,17 +597,12 @@ import {
597
597
  getConfiguredNamespaces,
598
598
  resolveNamespaceFromStorageDir,
599
599
  resolveScopePlan
600
- } from "./chunk-YN6ASZUG.js";
600
+ } from "./chunk-6QPI2ITJ.js";
601
601
  import {
602
602
  attachCitation,
603
603
  hasCitationForTemplate,
604
604
  stripCitationForTemplate
605
605
  } from "./chunk-J6A3CX5N.js";
606
- import {
607
- namespaceIdentityFromToken,
608
- namespaceIdentityToken,
609
- normalizeNamespaceIdentity
610
- } from "./chunk-EGGE52UU.js";
611
606
  import {
612
607
  assertPathInsideRoot
613
608
  } from "./chunk-GCASGYIO.js";
@@ -619,6 +614,34 @@ import {
619
614
  import {
620
615
  ContentHashIndex
621
616
  } from "./chunk-CX5SW2EW.js";
617
+ import {
618
+ serializeMutations,
619
+ withHeldFileLock
620
+ } from "./chunk-FFAZ2XFU.js";
621
+ import {
622
+ SUPPORT_PASSPORT_ATTRIBUTE_KEYS,
623
+ SUPPORT_PASSPORT_CARD_TAG,
624
+ SupportPassportCardCategorySchema,
625
+ SupportPassportCardListSchema,
626
+ SupportPassportCardMutationInputSchema,
627
+ SupportPassportListCardsInputSchema,
628
+ SupportPassportManualDraftInputSchema,
629
+ SupportPassportMemoryIdSchema,
630
+ SupportPassportNamespaceSchema,
631
+ SupportPassportReplaceCardInputSchema,
632
+ computeSupportPassportCardRevision,
633
+ computeSupportPassportOwnerKey,
634
+ decodeSupportPassportNamespaceAttributes,
635
+ encodeSupportPassportNamespaceAttributes,
636
+ excludeSupportPassportPrivateMemories,
637
+ isSupportPassportPrivateMemory,
638
+ projectSupportPassportCard
639
+ } from "./chunk-HNDIND7P.js";
640
+ import {
641
+ namespaceIdentityFromToken,
642
+ namespaceIdentityToken,
643
+ normalizeNamespaceIdentity
644
+ } from "./chunk-EGGE52UU.js";
622
645
  import {
623
646
  normalizeAttributePairs,
624
647
  stripAttributesSuffix
@@ -636,6 +659,9 @@ import {
636
659
  assertIsDirectoryNotSymlink,
637
660
  assertRealpathInsideRoot
638
661
  } from "./chunk-GCGJW34D.js";
662
+ import {
663
+ parseIsoOffsetTimestamp
664
+ } from "./chunk-P7FMDTKL.js";
639
665
  import {
640
666
  canReadNamespace,
641
667
  defaultNamespaceForPrincipal,
@@ -811,23 +837,12 @@ var TierMigrationCoordinator = class {
811
837
  );
812
838
  this.inFlight = true;
813
839
  try {
814
- const coldStorage = this.deps.createColdStorage(
815
- path.join(storage.dir, "cold")
816
- );
817
- const [hotMemories, coldMemories] = await Promise.all([
818
- storage.readAllMemories(),
819
- coldStorage.readAllMemories()
820
- ]);
840
+ const coldStorage = this.deps.createColdStorage(path.join(storage.dir, "cold"));
841
+ const [hotMemories, coldMemories] = await Promise.all([storage.readAllMemories(), coldStorage.readAllMemories()]);
821
842
  const now = /* @__PURE__ */ new Date();
822
843
  const scanLimit = Math.max(0, Math.floor(budget.scanLimit));
823
- const hotScanLimit = Math.min(
824
- hotMemories.length,
825
- Math.ceil(scanLimit * 0.75)
826
- );
827
- const coldScanLimit = Math.min(
828
- coldMemories.length,
829
- Math.max(0, scanLimit - hotScanLimit)
830
- );
844
+ const hotScanLimit = Math.min(hotMemories.length, Math.ceil(scanLimit * 0.75));
845
+ const coldScanLimit = Math.min(coldMemories.length, Math.max(0, scanLimit - hotScanLimit));
831
846
  const toTimestamp = (memory) => Date.parse(memory.frontmatter.updated ?? memory.frontmatter.created);
832
847
  const hotCandidates = hotMemories.map((memory) => ({ memory, tier: "hot" })).sort((a, b) => toTimestamp(a.memory) - toTimestamp(b.memory)).slice(0, hotScanLimit);
833
848
  const coldCandidates = coldMemories.map((memory) => ({ memory, tier: "cold" })).sort((a, b) => toTimestamp(b.memory) - toTimestamp(a.memory)).slice(0, coldScanLimit);
@@ -844,12 +859,7 @@ var TierMigrationCoordinator = class {
844
859
  let demoted = 0;
845
860
  for (const candidate of candidates) {
846
861
  if (migrated >= limit) break;
847
- const decision = decideTierTransition(
848
- candidate.memory,
849
- candidate.tier,
850
- policy,
851
- now
852
- );
862
+ const decision = decideTierTransition(candidate.memory, candidate.tier, policy, now);
853
863
  if (!decision.changed) continue;
854
864
  if (!dryRun) {
855
865
  const res = await migration.migrateMemory({
@@ -1067,7 +1077,7 @@ var SemanticConsolidationCoordinator = class {
1067
1077
  return result;
1068
1078
  }
1069
1079
  log.info("[semantic-consolidation] starting run");
1070
- const allMemories = await targetStorage.readAllMemories();
1080
+ const allMemories = excludeSupportPassportPrivateMemories(await targetStorage.readAllMemories());
1071
1081
  if (allMemories.length < 10) {
1072
1082
  log.debug("[semantic-consolidation] too few memories, skipping");
1073
1083
  return result;
@@ -1415,7 +1425,7 @@ var LifecyclePolicyCoordinator = class {
1415
1425
  protectedCategories: this.config.lifecycleProtectedCategories
1416
1426
  };
1417
1427
  const actionPriors = await this.buildLifecycleActionPriors(storage);
1418
- for (const memory of allMemories) {
1428
+ for (const memory of excludeSupportPassportPrivateMemories(allMemories)) {
1419
1429
  if (memory.frontmatter.status === "superseded" || memory.frontmatter.status === "forgotten") {
1420
1430
  continue;
1421
1431
  }
@@ -2226,7 +2236,7 @@ var RecallRerankCoordinator = class _RecallRerankCoordinator {
2226
2236
  namespaces,
2227
2237
  {
2228
2238
  readNamespaceMemories: async (ns) => (await this.getStorage(ns)).readAllMemories(),
2229
- readMemoryFrontmatter: async (path35, preferredNamespace) => {
2239
+ readMemoryFrontmatter: async (path38, preferredNamespace) => {
2230
2240
  if (!fallbackReader) {
2231
2241
  for (const ns of namespaces) {
2232
2242
  try {
@@ -2238,7 +2248,7 @@ var RecallRerankCoordinator = class _RecallRerankCoordinator {
2238
2248
  }
2239
2249
  if (!fallbackReader) return null;
2240
2250
  const memory = await this.readQmdResultMemory(
2241
- path35,
2251
+ path38,
2242
2252
  fallbackReader,
2243
2253
  namespaces,
2244
2254
  preferredNamespace
@@ -3107,6 +3117,7 @@ var ContradictionLinkingCoordinator = class {
3107
3117
  const resultStorage2 = await this.storageForNamespace(resultNamespace);
3108
3118
  const existingMemory = await resultStorage2.getMemoryById(memoryId);
3109
3119
  if (!existingMemory) continue;
3120
+ if (isSupportPassportPrivateMemory(existingMemory)) continue;
3110
3121
  if (inferLocalizationMemoryStatus(existingMemory, resultStorage2.dir) !== "active") continue;
3111
3122
  const verification = await this.getExtraction().verifyContradiction(
3112
3123
  { content, category },
@@ -3156,6 +3167,9 @@ var ContradictionLinkingCoordinator = class {
3156
3167
  ]);
3157
3168
  anchorSnapshot = mergeMemorySnapshots(hot, cold, resultStorage.dir);
3158
3169
  }
3170
+ anchorSnapshot = anchorSnapshot?.filter(
3171
+ (memory) => !isSupportPassportPrivateMemory(memory)
3172
+ );
3159
3173
  const anchorMemoryById = anchorSnapshot ? new Map(anchorSnapshot.map((memory) => [memory.frontmatter.id, memory])) : void 0;
3160
3174
  const candidates = await localizeUpdateCandidates(
3161
3175
  {
@@ -3182,7 +3196,7 @@ var ContradictionLinkingCoordinator = class {
3182
3196
  if (!memoryId) continue;
3183
3197
  if (this.namespaceFromPath(result.path) !== namespaceScope) continue;
3184
3198
  const existingMemory = anchorMemoryById?.get(memoryId) ?? await resultStorage.getMemoryById(memoryId);
3185
- if (!existingMemory || inferLocalizationMemoryStatus(existingMemory, resultStorage.dir) !== "active") continue;
3199
+ if (!existingMemory || isSupportPassportPrivateMemory(existingMemory) || inferLocalizationMemoryStatus(existingMemory, resultStorage.dir) !== "active") continue;
3186
3200
  hits.push({
3187
3201
  id: memoryId,
3188
3202
  content: existingMemory.content,
@@ -3203,7 +3217,7 @@ var ContradictionLinkingCoordinator = class {
3203
3217
  );
3204
3218
  for (const candidate of candidates) {
3205
3219
  const existingMemory = anchorMemoryById?.get(candidate.id) ?? await resultStorage.getMemoryById(candidate.id);
3206
- if (!existingMemory || inferLocalizationMemoryStatus(existingMemory, resultStorage.dir) !== "active") continue;
3220
+ if (!existingMemory || isSupportPassportPrivateMemory(existingMemory) || inferLocalizationMemoryStatus(existingMemory, resultStorage.dir) !== "active") continue;
3207
3221
  const verification = await this.getExtraction().verifyContradiction(
3208
3222
  { content, category },
3209
3223
  {
@@ -3949,7 +3963,7 @@ var ConsolidationRunCoordinator = class {
3949
3963
  await this.deps.flushAccessTracking();
3950
3964
  }
3951
3965
  await this.pruneHarmonicStores(storage);
3952
- let allMemories = await storage.readAllMemories();
3966
+ let allMemories = excludeSupportPassportPrivateMemories(await storage.readAllMemories());
3953
3967
  if (allMemories.length < 5) {
3954
3968
  return { memoriesProcessed: allMemories.length, merged, invalidated };
3955
3969
  }
@@ -4228,7 +4242,7 @@ var ConsolidationRunCoordinator = class {
4228
4242
  const deepSleepStartedAt = (/* @__PURE__ */ new Date()).toISOString();
4229
4243
  const tierMigration = await this.deps.tierMigrationCoordinator.runCycle(storage, "maintenance");
4230
4244
  if (tierMigration.migrated > 0) memoryItemMutated = true;
4231
- allMemories = await storage.readAllMemories();
4245
+ allMemories = excludeSupportPassportPrivateMemories(await storage.readAllMemories());
4232
4246
  if (resolveRecallEnhancementCapabilities(config).factArchival) {
4233
4247
  const archived = await this.deps.lifecyclePolicyCoordinator.runFactArchival(allMemories);
4234
4248
  if (archived > 0) {
@@ -4248,7 +4262,7 @@ var ConsolidationRunCoordinator = class {
4248
4262
  } catch (err) {
4249
4263
  log.warn(`deep-sleep maintenance pass failed (ignored): ${err}`);
4250
4264
  try {
4251
- allMemories = await storage.readAllMemories();
4265
+ allMemories = excludeSupportPassportPrivateMemories(await storage.readAllMemories());
4252
4266
  } catch (readErr) {
4253
4267
  log.warn(`deep-sleep maintenance recovery read failed: ${readErr}`);
4254
4268
  throw err;
@@ -4282,7 +4296,7 @@ var ConsolidationRunCoordinator = class {
4282
4296
  const semResult = await this.deps.semanticConsolidationCoordinator.runSemanticConsolidation();
4283
4297
  let remItemsProcessed = allMemories.length;
4284
4298
  try {
4285
- allMemories = await storage.readAllMemories();
4299
+ allMemories = excludeSupportPassportPrivateMemories(await storage.readAllMemories());
4286
4300
  remItemsProcessed = allMemories.length;
4287
4301
  } catch (err) {
4288
4302
  log.warn(
@@ -13158,6 +13172,7 @@ var RecallSearchPipelineCoordinator = class {
13158
13172
  let forgottenFilteredCount = 0;
13159
13173
  let blockedPathFilteredCount = 0;
13160
13174
  let connectorPartitionFilteredCount = 0;
13175
+ let supportPassportFilteredCount = 0;
13161
13176
  const filtered = [];
13162
13177
  for (const r of results) {
13163
13178
  if (options?.blockedPaths && resultHasKey(options.blockedPaths, r)) {
@@ -13177,6 +13192,10 @@ var RecallSearchPipelineCoordinator = class {
13177
13192
  forgottenFilteredCount += 1;
13178
13193
  continue;
13179
13194
  }
13195
+ if (isSupportPassportPrivateMemory(memory)) {
13196
+ supportPassportFilteredCount += 1;
13197
+ continue;
13198
+ }
13180
13199
  if (options?.allowLifecycleFiltered !== true && shouldFilterLifecycleRecallCandidate(memory.frontmatter, {
13181
13200
  lifecyclePolicyEnabled: lifecycleCaps.lifecyclePolicy,
13182
13201
  lifecycleFilterStaleEnabled: lifecycleCaps.lifecycleFilterStale
@@ -13228,6 +13247,11 @@ var RecallSearchPipelineCoordinator = class {
13228
13247
  `connector partition filter removed ${connectorPartitionFilteredCount} tool-scoped candidates from recall`
13229
13248
  );
13230
13249
  }
13250
+ if (supportPassportFilteredCount > 0) {
13251
+ log.debug(
13252
+ `support passport filter removed ${supportPassportFilteredCount} owner-controlled records from generic recall`
13253
+ );
13254
+ }
13231
13255
  if (lifecycleFilteredCount > 0) {
13232
13256
  log.debug(
13233
13257
  `lifecycle retrieval filter removed ${lifecycleFilteredCount} stale/archived candidates`
@@ -15019,7 +15043,7 @@ var OrchestratorInitCoordinator = class {
15019
15043
  if (signal.aborted) return;
15020
15044
  if (lifecycleCaps.lifecyclePolicy && resolveQmdCapabilities(this.deps.config).qmdTierMigration) {
15021
15045
  try {
15022
- const { runFirstStartMigration } = await import("./first-start-migration-626C5554.js");
15046
+ const { runFirstStartMigration } = await import("./first-start-migration-LMMZFLKK.js");
15023
15047
  const result = await runFirstStartMigration({
15024
15048
  storage: this.deps.storage,
15025
15049
  config: this.deps.config,
@@ -15560,7 +15584,7 @@ async function runPatternReinforcement(storage, options) {
15560
15584
  if (targetCategories.size === 0) {
15561
15585
  return emptyResult2();
15562
15586
  }
15563
- const memories = await storage.readAllMemories();
15587
+ const memories = excludeSupportPassportPrivateMemories(await storage.readAllMemories());
15564
15588
  const eligible = memories.filter((m) => {
15565
15589
  if (!targetCategories.has(m.frontmatter.category)) return false;
15566
15590
  const status = m.frontmatter.status ?? ACTIVE_STATUS2;
@@ -15832,6 +15856,7 @@ Install it alongside Remnic:
15832
15856
  const memories = await storage.readAllMemories();
15833
15857
  const support = [];
15834
15858
  for (const memory of memories) {
15859
+ if (isSupportPassportPrivateMemory(memory)) continue;
15835
15860
  const status = inferMemoryStatus(
15836
15861
  memory.frontmatter,
15837
15862
  memory.path
@@ -17600,36 +17625,13 @@ var WorkspaceOpsCoordinator = class {
17600
17625
  const fullPath = path17.join(dateDir, entry.name);
17601
17626
  try {
17602
17627
  assertPathInsideRoot(memoryRootReal, await realpath2(fullPath), fullPath);
17603
- const raw = await readFile6(fullPath, "utf-8");
17604
- const fmMatch = raw.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
17605
- if (!fmMatch) continue;
17606
- const fmBlock = fmMatch[1];
17607
- const content = fmMatch[2].trim();
17608
- const fm = {};
17609
- for (const line of fmBlock.split("\n")) {
17610
- const colonIdx = line.indexOf(":");
17611
- if (colonIdx === -1) continue;
17612
- fm[line.slice(0, colonIdx).trim()] = line.slice(colonIdx + 1).trim();
17613
- }
17614
- const created = fm.created || "unknown";
17615
- const createdAt = parseFiniteDate(created);
17628
+ const memory = await storage.readMemoryByPath(fullPath);
17629
+ if (!memory || isSupportPassportPrivateMemory(memory)) continue;
17630
+ const createdAt = parseFiniteDate(memory.frontmatter.created);
17616
17631
  if (createdAt && formatDateInTimeZone(createdAt, timeZone) !== targetLocalDate) {
17617
17632
  continue;
17618
17633
  }
17619
- facts.push({
17620
- path: fullPath,
17621
- frontmatter: {
17622
- id: fm.id || path17.basename(entry.name, ".md"),
17623
- category: fm.category || "fact",
17624
- created,
17625
- updated: fm.updated || created,
17626
- source: fm.source || "unknown",
17627
- confidence: parseFloat(fm.confidence || "0.8"),
17628
- confidenceTier: fm.confidenceTier || "implied",
17629
- tags: []
17630
- },
17631
- content
17632
- });
17634
+ facts.push(memory);
17633
17635
  } catch {
17634
17636
  }
17635
17637
  }
@@ -19190,6 +19192,13 @@ var Orchestrator = class {
19190
19192
  const ns = typeof namespace === "string" && namespace.trim().length > 0 ? namespace.trim() : this.config.defaultNamespace;
19191
19193
  return this.storageRouter.storageFor(ns);
19192
19194
  }
19195
+ filterPrivateSearchResults = (results, namespaces = [], preserveUnresolved = false, visibilityCache) => this.qmdResultResolver.filterPrivateSearchResults(
19196
+ results,
19197
+ this.storage,
19198
+ namespaces,
19199
+ preserveUnresolved,
19200
+ visibilityCache
19201
+ );
19193
19202
  configuredNamespaceList() {
19194
19203
  return getConfiguredNamespaces(this.config);
19195
19204
  }
@@ -20833,12 +20842,6 @@ ${doc.content}` : doc.content,
20833
20842
  return match ? match[1] : null;
20834
20843
  }).filter((id) => id !== null);
20835
20844
  }
20836
- // ---------------------------------------------------------------------------
20837
- // Contradiction Detection (Phase 2B)
20838
- // ---------------------------------------------------------------------------
20839
- // ---------------------------------------------------------------------------
20840
- // Feedback (v2.2)
20841
- // ---------------------------------------------------------------------------
20842
20845
  async recordMemoryFeedback(memoryId, vote, note) {
20843
20846
  await this.relevance.record(memoryId, vote, note);
20844
20847
  }
@@ -20967,127 +20970,2301 @@ ${doc.content}` : doc.content,
20967
20970
  }
20968
20971
  };
20969
20972
 
20970
- // src/relay/mission-fixture.ts
20971
- var RELAY_DEMO_MISSION_ID = "checkout-token-recovery";
20972
- var RELAY_DEMO_NAMESPACE = "relay-build-week";
20973
- var sourceEvidence = {
20974
- kind: "source",
20975
- id: "source-checkout-contract",
20976
- label: "Checkout token contract",
20977
- locator: "fixture://checkout-service/src/token-policy.ts",
20978
- capture: "fixture"
20979
- };
20980
- var testEvidence = {
20981
- kind: "test",
20982
- id: "test-checkout-contract",
20983
- label: "Checkout integration contract",
20984
- locator: "fixture://checkout-service/test/token-policy.test.ts",
20985
- capture: "fixture"
20986
- };
20987
- var approvalEvidence = {
20988
- kind: "approval",
20989
- id: "approval-build-week-operator",
20990
- label: "Human approval receipt",
20991
- locator: "fixture://relay/approvals/correction-token-refresh.json",
20992
- capture: "fixture"
20993
- };
20994
- var correctionEvidence = {
20995
- kind: "correction",
20996
- id: "correction-token-refresh",
20997
- label: "Applied Remnic correction",
20998
- locator: "fixture://remnic/corrections/correction-token-refresh.json",
20999
- capture: "fixture"
20973
+ // src/support-passport/errors.ts
20974
+ var SupportPassportError = class extends Error {
20975
+ code;
20976
+ status;
20977
+ constructor(code, message, status) {
20978
+ super(message);
20979
+ this.name = "SupportPassportError";
20980
+ this.code = code;
20981
+ this.status = status;
20982
+ }
21000
20983
  };
21001
- function at(second) {
21002
- return `2026-07-17T18:00:${String(second).padStart(2, "0")}.000Z`;
20984
+
20985
+ // src/support-passport/owner-lock.ts
20986
+ import { createHash as createHash9 } from "crypto";
20987
+ import path21 from "path";
20988
+ var CARD_MUTATION_LOCK_STALE_MS = 6e4;
20989
+ var CARD_MUTATION_LOCK_MAX_WAIT_MS = 3e4;
20990
+ function computeSupportPassportOwnerLockKey(namespace, principal) {
20991
+ return createHash9("sha256").update(JSON.stringify([namespace, principal])).digest("hex");
20992
+ }
20993
+ function supportPassportOwnerLockPath(storage, scope) {
20994
+ const ownerLockKey = scope.ownerKey ?? computeSupportPassportOwnerLockKey(scope.namespace, scope.principal);
20995
+ if (!/^[a-f0-9]{64}$/.test(ownerLockKey)) {
20996
+ throw new SupportPassportError("card_data_invalid", "The support passport owner scope is invalid.", 500);
20997
+ }
20998
+ return path21.join(storage.dir, "state", `support-passport-cards-${ownerLockKey}.lock`);
20999
+ }
21000
+ async function withSupportPassportOwnerLock(storage, scope, task) {
21001
+ const lockPath = supportPassportOwnerLockPath(storage, scope);
21002
+ return await serializeMutations(
21003
+ lockPath,
21004
+ () => withHeldFileLock(
21005
+ lockPath,
21006
+ { staleMs: CARD_MUTATION_LOCK_STALE_MS, maxWaitMs: CARD_MUTATION_LOCK_MAX_WAIT_MS },
21007
+ async (acquired, lock) => {
21008
+ if (!acquired) {
21009
+ throw new SupportPassportError("storage_conflict", "The support passport is busy. Try again.", 409);
21010
+ }
21011
+ return await task(lock);
21012
+ }
21013
+ )
21014
+ );
21003
21015
  }
21004
- function createRelayMissionFixture() {
21005
- return [
21006
- {
21007
- occurredAt: at(0),
21008
- idempotencyKey: "fixture-001",
21009
- payload: {
21010
- kind: "mission_started",
21011
- title: "The checkout token split",
21012
- objective: "Resolve a conflicting token refresh policy and prove a cold agent acts on it.",
21013
- runMode: "fixture",
21014
- evidence: [sourceEvidence]
21016
+ async function requireSupportPassportOwnerLock(lock) {
21017
+ if (await lock.refresh()) return;
21018
+ throw new SupportPassportError("storage_conflict", "The support passport changed during the request.", 409);
21019
+ }
21020
+
21021
+ // src/support-passport/card-service.ts
21022
+ var OWNER_VISIBLE_STATUSES = /* @__PURE__ */ new Set(["pending_review", "active"]);
21023
+ var MAX_OWNER_VISIBLE_CARDS = 100;
21024
+ function invalidInput() {
21025
+ return new SupportPassportError("invalid_input", "The support card request is invalid.", 400);
21026
+ }
21027
+ function isStorageConflict(error) {
21028
+ return error instanceof SupportPassportError && error.code === "storage_conflict";
21029
+ }
21030
+ var SupportPassportCardService = class {
21031
+ resolveOwner;
21032
+ now;
21033
+ constructor(dependencies) {
21034
+ this.resolveOwner = dependencies.resolveOwner;
21035
+ this.now = dependencies.now ?? (() => /* @__PURE__ */ new Date());
21036
+ }
21037
+ async listCards(input) {
21038
+ const parsed = SupportPassportListCardsInputSchema.safeParse(input);
21039
+ if (!parsed.success) throw invalidInput();
21040
+ const { principal, namespace, storage } = await this.resolveOwnerScope(parsed.data.principal);
21041
+ return await withSupportPassportOwnerLock(storage, { namespace, principal }, async (lock) => {
21042
+ const stored = await this.readStoredCards(storage, lock, principal, namespace);
21043
+ const cards = this.ownerVisibleCards(stored).sort((a, b) => a.order - b.order || a.card.cardId.localeCompare(b.card.cardId)).map((item) => item.card);
21044
+ const output = SupportPassportCardListSchema.safeParse(cards);
21045
+ if (!output.success) {
21046
+ throw new SupportPassportError("card_data_invalid", "The support card data is invalid.", 500);
21047
+ }
21048
+ return output.data;
21049
+ });
21050
+ }
21051
+ async createManualDraft(input) {
21052
+ const parsed = SupportPassportManualDraftInputSchema.safeParse(input);
21053
+ if (!parsed.success) throw invalidInput();
21054
+ const { principal, namespace, storage } = await this.resolveOwnerScope(parsed.data.principal);
21055
+ return await withSupportPassportOwnerLock(
21056
+ storage,
21057
+ { namespace, principal },
21058
+ (lock) => this.createDraft(
21059
+ storage,
21060
+ {
21061
+ title: parsed.data.title,
21062
+ statement: parsed.data.statement,
21063
+ category: parsed.data.category,
21064
+ reviewBy: parsed.data.reviewBy,
21065
+ sourceMemoryIds: []
21066
+ },
21067
+ lock,
21068
+ principal,
21069
+ namespace
21070
+ )
21071
+ );
21072
+ }
21073
+ async replaceCard(input) {
21074
+ const parsed = SupportPassportReplaceCardInputSchema.safeParse(input);
21075
+ if (!parsed.success) throw invalidInput();
21076
+ const { principal, namespace, storage } = await this.resolveOwnerScope(parsed.data.principal);
21077
+ return await withSupportPassportOwnerLock(storage, { namespace, principal }, async (lock) => {
21078
+ const loadedPrior = await this.requireCard(storage, parsed.data.cardId, namespace, principal);
21079
+ const storedCards = await this.readProjectedCards(storage, namespace, principal);
21080
+ const interruptedReplacements = storedCards.filter(
21081
+ (item) => item.card.status === "pending_review" && (item.replacesDraftId === loadedPrior.card.cardId || item.memory.frontmatter.supersedes === loadedPrior.card.cardId)
21082
+ );
21083
+ if (interruptedReplacements.length > 1) {
21084
+ throw new SupportPassportError(
21085
+ "storage_conflict",
21086
+ "Multiple support card edits already completed. Reload the support passport.",
21087
+ 409
21088
+ );
21015
21089
  }
21016
- },
21017
- {
21018
- occurredAt: at(2),
21019
- idempotencyKey: "fixture-002",
21020
- payload: {
21021
- kind: "agent_status",
21022
- agentId: "agent-atlas",
21023
- sessionId: "session-atlas",
21024
- label: "Atlas",
21025
- role: "Checkout implementation",
21026
- status: "working",
21027
- evidence: [sourceEvidence]
21090
+ const [interruptedReplacement] = interruptedReplacements;
21091
+ if (interruptedReplacement) {
21092
+ if (interruptedReplacement.replacedRevision !== parsed.data.expectedRevision) {
21093
+ throw new SupportPassportError("revision_conflict", "The support card changed after it was loaded.", 409);
21094
+ }
21095
+ const matchesRetry = interruptedReplacement.card.title === parsed.data.title && interruptedReplacement.card.statement === parsed.data.statement && interruptedReplacement.card.category === parsed.data.category && interruptedReplacement.card.reviewBy === parsed.data.reviewBy;
21096
+ if (!matchesRetry) {
21097
+ throw new SupportPassportError(
21098
+ "storage_conflict",
21099
+ "A different support card edit already completed. Reload the support passport.",
21100
+ 409
21101
+ );
21102
+ }
21103
+ if (!interruptedReplacement.draftReplacementPrepared) return interruptedReplacement.card;
21104
+ const recovered = await this.recoverReplacementTransition(
21105
+ storage,
21106
+ interruptedReplacement.memory,
21107
+ lock,
21108
+ principal,
21109
+ namespace
21110
+ );
21111
+ return this.projectRequiredCard(recovered, namespace, principal).card;
21028
21112
  }
21029
- },
21030
- {
21031
- occurredAt: at(3),
21032
- idempotencyKey: "fixture-003",
21033
- payload: {
21034
- kind: "agent_status",
21035
- agentId: "agent-nova",
21036
- sessionId: "session-nova",
21037
- label: "Nova",
21038
- role: "Integration verification",
21039
- status: "working",
21040
- evidence: [testEvidence]
21113
+ this.requireRevision(loadedPrior, parsed.data.expectedRevision);
21114
+ await this.readStoredCards(storage, lock, principal, namespace);
21115
+ const refreshedPrior = await this.requireCard(storage, parsed.data.cardId, namespace, principal);
21116
+ this.requireRevision(refreshedPrior, parsed.data.expectedRevision);
21117
+ const recoveredMemory = await this.recoverReplacementTransition(
21118
+ storage,
21119
+ refreshedPrior.memory,
21120
+ lock,
21121
+ principal,
21122
+ namespace
21123
+ );
21124
+ const prior = this.projectRequiredCard(recoveredMemory, namespace, principal);
21125
+ if (prior.card.status !== "active" && prior.card.status !== "pending_review") {
21126
+ throw new SupportPassportError(
21127
+ "invalid_card_status",
21128
+ "Only a draft or approved support card can be edited.",
21129
+ 409
21130
+ );
21041
21131
  }
21042
- },
21043
- {
21044
- occurredAt: at(6),
21045
- idempotencyKey: "fixture-004",
21046
- payload: {
21047
- kind: "agent_output",
21048
- agentId: "agent-atlas",
21049
- sessionId: "session-atlas",
21050
- outputId: "output-atlas-policy",
21051
- summary: "Implemented a new token for every checkout retry.",
21052
- evidence: [
21053
- {
21054
- kind: "agent_output",
21055
- id: "output-atlas-policy",
21056
- label: "Atlas one-shot output",
21057
- locator: "fixture://codex/atlas/final-output.txt",
21058
- capture: "fixture"
21059
- }
21060
- ]
21132
+ const replacement = await this.createDraft(
21133
+ storage,
21134
+ {
21135
+ title: parsed.data.title,
21136
+ statement: parsed.data.statement,
21137
+ category: parsed.data.category,
21138
+ reviewBy: parsed.data.reviewBy,
21139
+ sourceMemoryIds: prior.sourceMemoryIds,
21140
+ supersedes: prior.card.status === "active" ? prior.card.cardId : prior.memory.frontmatter.supersedes,
21141
+ replacesDraftId: prior.card.status === "pending_review" ? prior.card.cardId : void 0,
21142
+ replacedRevision: prior.card.revision,
21143
+ order: prior.order,
21144
+ draftReplacementPrepared: prior.card.status === "pending_review"
21145
+ },
21146
+ lock,
21147
+ principal,
21148
+ namespace
21149
+ );
21150
+ if (prior.card.status === "active") return replacement;
21151
+ const replacedAt = this.now().toISOString();
21152
+ await this.requireOwnerLock(lock);
21153
+ const rejected = await storage.writeMemoryFrontmatterIfUnchanged(
21154
+ prior.memory,
21155
+ { status: "rejected", updated: replacedAt },
21156
+ { actor: principal, reasonCode: "owner-replaced-draft" }
21157
+ );
21158
+ if (rejected) {
21159
+ return await this.finishPreparedDraftReplacement(storage, replacement.cardId, lock, principal, namespace);
21061
21160
  }
21062
- },
21063
- {
21064
- occurredAt: at(7),
21065
- idempotencyKey: "fixture-005",
21066
- payload: {
21067
- kind: "belief_observed",
21068
- agentId: "agent-atlas",
21069
- sessionId: "session-atlas",
21070
- beliefId: "belief-new-token-every-request",
21071
- decisionId: "decision-new-token-every-request",
21072
- statement: "Mint a new checkout token for every request and retry.",
21073
- confidence: 0.91,
21074
- evidence: [
21075
- {
21076
- kind: "memory",
21077
- id: "memory-stale-token-policy",
21078
- label: "Stale project decision",
21079
- locator: "fixture://remnic/memories/memory-stale-token-policy.md",
21080
- capture: "fixture"
21081
- }
21082
- ]
21161
+ const currentPrior = await storage.getMemoryById(prior.card.cardId);
21162
+ const currentPriorCard = currentPrior ? this.projectOwnedCard(currentPrior, namespace, principal) : null;
21163
+ if (currentPriorCard?.card.status === "rejected") {
21164
+ return await this.finishPreparedDraftReplacement(storage, replacement.cardId, lock, principal, namespace);
21083
21165
  }
21084
- },
21085
- {
21086
- occurredAt: at(9),
21087
- idempotencyKey: "fixture-006",
21088
- payload: {
21089
- kind: "agent_output",
21090
- agentId: "agent-nova",
21166
+ await this.rejectCreatedDraft(
21167
+ storage,
21168
+ replacement.cardId,
21169
+ "draft-replacement-failed",
21170
+ lock,
21171
+ principal,
21172
+ namespace
21173
+ );
21174
+ throw new SupportPassportError("storage_conflict", "The support card changed before it was edited.", 409);
21175
+ });
21176
+ }
21177
+ async approveCard(input) {
21178
+ const parsed = SupportPassportCardMutationInputSchema.safeParse(input);
21179
+ if (!parsed.success) throw invalidInput();
21180
+ const { principal, namespace, storage } = await this.resolveOwnerScope(parsed.data.principal);
21181
+ return await withSupportPassportOwnerLock(storage, { namespace, principal }, async (lock) => {
21182
+ const loadedCard = await this.requireCard(storage, parsed.data.cardId, namespace, principal);
21183
+ this.requireRevision(loadedCard, parsed.data.expectedRevision);
21184
+ this.requireStatus(loadedCard, "pending_review");
21185
+ const recoveredMemory = await this.recoverReplacementTransition(
21186
+ storage,
21187
+ loadedCard.memory,
21188
+ lock,
21189
+ principal,
21190
+ namespace
21191
+ );
21192
+ const card = this.projectRequiredCard(recoveredMemory, namespace, principal);
21193
+ if (card.card.status === "active") return card.card;
21194
+ if (card.card.status === "rejected") {
21195
+ throw new SupportPassportError(
21196
+ "storage_conflict",
21197
+ "The support card was rejected while its replacement state was recovered.",
21198
+ 409
21199
+ );
21200
+ }
21201
+ this.requireStatus(card, "pending_review");
21202
+ await this.validatePriorForReplacement(storage, card, namespace, principal);
21203
+ const updatedAt = this.now().toISOString();
21204
+ await this.requireOwnerLock(lock);
21205
+ let approved;
21206
+ try {
21207
+ approved = await storage.writeMemoryFrontmatterIfUnchanged(
21208
+ card.memory,
21209
+ { status: "active", updated: updatedAt },
21210
+ { actor: principal, reasonCode: "owner-approved" }
21211
+ );
21212
+ } catch (error) {
21213
+ const current = await storage.getMemoryById(card.card.cardId);
21214
+ const currentCard = current ? this.projectOwnedCard(current, namespace, principal) : null;
21215
+ if (currentCard?.card.status === "active") {
21216
+ return await this.finishCommittedApproval(storage, currentCard, lock, principal, namespace);
21217
+ }
21218
+ throw error;
21219
+ }
21220
+ if (!approved) {
21221
+ const current = await storage.getMemoryById(card.card.cardId);
21222
+ const currentCard = current ? this.projectOwnedCard(current, namespace, principal) : null;
21223
+ if (currentCard?.card.status === "active") {
21224
+ return await this.finishCommittedApproval(storage, currentCard, lock, principal, namespace);
21225
+ }
21226
+ throw new SupportPassportError("storage_conflict", "The support card changed before approval.", 409);
21227
+ }
21228
+ const committedCard = {
21229
+ ...card.card,
21230
+ status: "active",
21231
+ updatedAt,
21232
+ revision: this.revisionFor(card.card, "active", updatedAt)
21233
+ };
21234
+ try {
21235
+ const current = await this.requireCard(storage, card.card.cardId, namespace, principal);
21236
+ return await this.finishCommittedApproval(storage, current, lock, principal, namespace);
21237
+ } catch (error) {
21238
+ if (isStorageConflict(error)) throw error;
21239
+ log.warn(
21240
+ `support passport could not finish replacement approval side effects: ${error instanceof Error ? error.message : String(error)}`
21241
+ );
21242
+ return committedCard;
21243
+ }
21244
+ });
21245
+ }
21246
+ async rejectCard(input) {
21247
+ return await this.changeStatus(input, "pending_review", "rejected");
21248
+ }
21249
+ async withdrawCard(input) {
21250
+ return await this.changeStatus(input, "active", "archived");
21251
+ }
21252
+ async createDraft(storage, input, lock, principal, namespace) {
21253
+ const now = this.now();
21254
+ const reviewBy = input.reviewBy ?? now.toISOString();
21255
+ const storedCards = await this.readStoredCards(storage, lock, principal, namespace);
21256
+ const visibleCards = this.ownerVisibleCards(storedCards);
21257
+ const replacesVisibleCard = visibleCards.some(
21258
+ (item) => input.replacesDraftId === item.card.cardId && item.card.status === "pending_review" || input.supersedes === item.card.cardId && item.card.status === "active"
21259
+ );
21260
+ if (visibleCards.length - (replacesVisibleCard ? 1 : 0) >= MAX_OWNER_VISIBLE_CARDS) {
21261
+ throw new SupportPassportError("invalid_input", "A support passport can contain at most 100 visible cards.", 400);
21262
+ }
21263
+ const maximumOrder = storedCards.reduce((maximum, card) => Math.max(maximum, card.order), -1);
21264
+ const order = input.order ?? maximumOrder + 1;
21265
+ if (!Number.isSafeInteger(order)) {
21266
+ throw new SupportPassportError("storage_conflict", "The support card order range is exhausted.", 409);
21267
+ }
21268
+ const envelope = composeMemoryEnvelope(
21269
+ {
21270
+ content: input.statement,
21271
+ category: "preference",
21272
+ tags: [SUPPORT_PASSPORT_CARD_TAG],
21273
+ structuredAttributes: {
21274
+ ...encodeSupportPassportNamespaceAttributes(namespace),
21275
+ [SUPPORT_PASSPORT_ATTRIBUTE_KEYS.owner]: computeSupportPassportOwnerKey(principal),
21276
+ [SUPPORT_PASSPORT_ATTRIBUTE_KEYS.title]: input.title,
21277
+ [SUPPORT_PASSPORT_ATTRIBUTE_KEYS.category]: input.category,
21278
+ [SUPPORT_PASSPORT_ATTRIBUTE_KEYS.order]: String(order),
21279
+ [SUPPORT_PASSPORT_ATTRIBUTE_KEYS.reviewBy]: reviewBy,
21280
+ [SUPPORT_PASSPORT_ATTRIBUTE_KEYS.sourceMemoryIds]: input.sourceMemoryIds.join(","),
21281
+ ...input.replacesDraftId ? { [SUPPORT_PASSPORT_ATTRIBUTE_KEYS.replacesDraftId]: input.replacesDraftId } : {},
21282
+ ...input.replacedRevision ? { [SUPPORT_PASSPORT_ATTRIBUTE_KEYS.replacedRevision]: input.replacedRevision } : {},
21283
+ ...input.draftReplacementPrepared ? { [SUPPORT_PASSPORT_ATTRIBUTE_KEYS.draftReplacementPrepared]: "true" } : {}
21284
+ },
21285
+ sourceReason: "support-passport"
21286
+ },
21287
+ { source: "support-passport", now: this.now }
21288
+ );
21289
+ if (envelope.sanitizeViolations.length > 0) throw invalidInput();
21290
+ await this.requireOwnerLock(lock);
21291
+ const written = await storage.writeSealedMemory(envelope, {
21292
+ actor: principal,
21293
+ status: "pending_review",
21294
+ lineage: input.sourceMemoryIds.length > 0 ? input.sourceMemoryIds : void 0,
21295
+ supersedes: input.supersedes
21296
+ });
21297
+ if (written.tombstoneBlocked) {
21298
+ throw new SupportPassportError("storage_conflict", "The support card needs memory review before use.", 409);
21299
+ }
21300
+ return this.projectRequiredCard(written.memory, namespace, principal).card;
21301
+ }
21302
+ async changeStatus(input, expectedStatus, nextStatus) {
21303
+ const parsed = SupportPassportCardMutationInputSchema.safeParse(input);
21304
+ if (!parsed.success) throw invalidInput();
21305
+ const { principal, namespace, storage } = await this.resolveOwnerScope(parsed.data.principal);
21306
+ return await withSupportPassportOwnerLock(storage, { namespace, principal }, async (lock) => {
21307
+ let card = await this.requireCard(storage, parsed.data.cardId, namespace, principal);
21308
+ this.requireRevision(card, parsed.data.expectedRevision);
21309
+ this.requireStatus(card, expectedStatus);
21310
+ if (expectedStatus === "pending_review" && nextStatus === "rejected") {
21311
+ await this.rejectPendingReplacementForPredecessor(storage, card, lock, principal, namespace);
21312
+ card = await this.requireCard(storage, card.card.cardId, namespace, principal);
21313
+ this.requireRevision(card, parsed.data.expectedRevision);
21314
+ this.requireStatus(card, expectedStatus);
21315
+ }
21316
+ if (expectedStatus === "pending_review" || expectedStatus === "active" && (card.replacesDraftId || card.memory.frontmatter.supersedes)) {
21317
+ card = this.projectRequiredCard(
21318
+ await this.recoverReplacementTransition(storage, card.memory, lock, principal, namespace, {
21319
+ rollbackConflictedApproval: expectedStatus !== "active"
21320
+ }),
21321
+ namespace,
21322
+ principal
21323
+ );
21324
+ }
21325
+ if (card.card.status === nextStatus) return card.card;
21326
+ this.requireStatus(card, expectedStatus);
21327
+ if (expectedStatus === "active" && nextStatus === "archived") {
21328
+ await this.rejectPendingReplacementForPredecessor(storage, card, lock, principal, namespace);
21329
+ card = await this.requireCard(storage, card.card.cardId, namespace, principal);
21330
+ this.requireRevision(card, parsed.data.expectedRevision);
21331
+ this.requireStatus(card, expectedStatus);
21332
+ }
21333
+ const updatedAt = this.now().toISOString();
21334
+ await this.requireOwnerLock(lock);
21335
+ const changed = await storage.writeMemoryFrontmatterIfUnchanged(
21336
+ card.memory,
21337
+ {
21338
+ status: nextStatus,
21339
+ updated: updatedAt,
21340
+ ...nextStatus === "archived" ? { archivedAt: updatedAt } : {}
21341
+ },
21342
+ { actor: principal, reasonCode: nextStatus === "archived" ? "owner-withdrew" : "owner-rejected" }
21343
+ );
21344
+ if (!changed)
21345
+ throw new SupportPassportError(
21346
+ "storage_conflict",
21347
+ "The support card changed before the request completed.",
21348
+ 409
21349
+ );
21350
+ return {
21351
+ ...card.card,
21352
+ status: nextStatus,
21353
+ updatedAt,
21354
+ revision: this.revisionFor(card.card, nextStatus, updatedAt)
21355
+ };
21356
+ });
21357
+ }
21358
+ revisionFor(card, status, updatedAt) {
21359
+ return computeSupportPassportCardRevision({
21360
+ cardId: card.cardId,
21361
+ title: card.title,
21362
+ statement: card.statement,
21363
+ category: card.category,
21364
+ status,
21365
+ updatedAt,
21366
+ reviewBy: card.reviewBy
21367
+ });
21368
+ }
21369
+ async resolveOwnerScope(principal) {
21370
+ const requestedPrincipal = SupportPassportListCardsInputSchema.safeParse({ principal });
21371
+ const owner = await this.resolveOwner(principal);
21372
+ const namespace = SupportPassportNamespaceSchema.safeParse(owner.namespace);
21373
+ const ownerPrincipal = SupportPassportListCardsInputSchema.safeParse({ principal: owner.principal });
21374
+ if (!requestedPrincipal.success || !namespace.success || !ownerPrincipal.success || ownerPrincipal.data.principal !== requestedPrincipal.data.principal) {
21375
+ throw new SupportPassportError("card_data_invalid", "The support passport owner scope is invalid.", 500);
21376
+ }
21377
+ return { ...owner, principal: ownerPrincipal.data.principal, namespace: namespace.data };
21378
+ }
21379
+ async rejectCreatedDraft(storage, cardId, reasonCode, lock, principal, namespace) {
21380
+ try {
21381
+ const current = await this.requireCard(storage, cardId, namespace, principal);
21382
+ await this.requireOwnerLock(lock);
21383
+ const rejected = await storage.writeMemoryFrontmatterIfUnchanged(
21384
+ current.memory,
21385
+ { status: "rejected", updated: this.now().toISOString() },
21386
+ { actor: principal, reasonCode }
21387
+ );
21388
+ if (!rejected) log.warn("support passport could not roll back a replacement draft");
21389
+ } catch (error) {
21390
+ log.warn(
21391
+ `support passport could not roll back a replacement draft: ${error instanceof Error ? error.message : String(error)}`
21392
+ );
21393
+ }
21394
+ }
21395
+ async requireCard(storage, cardId, namespace, principal) {
21396
+ const stored = await storage.getMemoryById(cardId);
21397
+ const card = stored ? this.projectOwnedCard(stored, namespace, principal) : null;
21398
+ if (!card) throw new SupportPassportError("card_not_found", "The support card was not found.", 404);
21399
+ return card;
21400
+ }
21401
+ projectRequiredCard(memory, namespace, principal) {
21402
+ const card = projectSupportPassportCard(memory);
21403
+ if (!card) throw new SupportPassportError("card_data_invalid", "The support card data is invalid.", 500);
21404
+ if (card.namespace !== namespace || card.owner !== computeSupportPassportOwnerKey(principal)) {
21405
+ throw new SupportPassportError("card_not_found", "The support card was not found.", 404);
21406
+ }
21407
+ return card;
21408
+ }
21409
+ projectOwnedCard(memory, namespace, principal) {
21410
+ const card = projectSupportPassportCard(memory);
21411
+ return card?.namespace === namespace && card.owner === computeSupportPassportOwnerKey(principal) ? card : null;
21412
+ }
21413
+ ownsMemory(memory, namespace, principal) {
21414
+ const attributes = memory.frontmatter.structuredAttributes;
21415
+ return attributes !== void 0 && decodeSupportPassportNamespaceAttributes(attributes) === namespace && attributes[SUPPORT_PASSPORT_ATTRIBUTE_KEYS.owner] === computeSupportPassportOwnerKey(principal);
21416
+ }
21417
+ async readProjectedCards(storage, namespace, principal) {
21418
+ const owner = computeSupportPassportOwnerKey(principal);
21419
+ const projected = (await storage.readAllMemories()).map(projectSupportPassportCard).filter((card) => card?.namespace === namespace && card.owner === owner);
21420
+ const ids = /* @__PURE__ */ new Set();
21421
+ for (const item of projected) {
21422
+ if (ids.has(item.card.cardId)) {
21423
+ throw new SupportPassportError("card_data_invalid", "Support card IDs must be unique.", 500);
21424
+ }
21425
+ ids.add(item.card.cardId);
21426
+ }
21427
+ return projected;
21428
+ }
21429
+ requireRevision(card, expectedRevision) {
21430
+ if (card.card.revision !== expectedRevision) {
21431
+ throw new SupportPassportError("revision_conflict", "The support card changed after it was loaded.", 409);
21432
+ }
21433
+ }
21434
+ requireStatus(card, status) {
21435
+ if (card.card.status !== status) {
21436
+ throw new SupportPassportError("invalid_card_status", `The support card must have status ${status}.`, 409);
21437
+ }
21438
+ }
21439
+ async readStoredCards(storage, lock, principal, namespace) {
21440
+ const initialVersion = storage.getCorpusScanVersion();
21441
+ const initial = await storage.readAllMemories();
21442
+ for (const memory of initial) {
21443
+ const card = this.projectOwnedCard(memory, namespace, principal);
21444
+ if (card) await this.recoverReplacementTransition(storage, memory, lock, principal, namespace);
21445
+ }
21446
+ const memories = storage.getCorpusScanVersion() === initialVersion ? initial : await storage.readAllMemories();
21447
+ const owner = computeSupportPassportOwnerKey(principal);
21448
+ const projected = memories.map(projectSupportPassportCard).filter((card) => card?.namespace === namespace && card.owner === owner);
21449
+ const ids = /* @__PURE__ */ new Set();
21450
+ for (const item of projected) {
21451
+ if (ids.has(item.card.cardId)) {
21452
+ throw new SupportPassportError("card_data_invalid", "Support card IDs must be unique.", 500);
21453
+ }
21454
+ ids.add(item.card.cardId);
21455
+ }
21456
+ return projected;
21457
+ }
21458
+ ownerVisibleCards(storedCards) {
21459
+ const visibleCards = storedCards.filter(
21460
+ (item) => OWNER_VISIBLE_STATUSES.has(item.card.status) && !item.draftReplacementPrepared
21461
+ );
21462
+ if (visibleCards.length <= MAX_OWNER_VISIBLE_CARDS) return visibleCards;
21463
+ const activeCardsWithPendingReplacements = new Set(
21464
+ visibleCards.filter((item) => item.card.status === "pending_review").map((item) => item.memory.frontmatter.supersedes).filter((cardId) => typeof cardId === "string")
21465
+ );
21466
+ return visibleCards.filter(
21467
+ (item) => item.card.status !== "active" || !activeCardsWithPendingReplacements.has(item.card.cardId)
21468
+ );
21469
+ }
21470
+ async preparePriorForReplacement(storage, replacement, lock, principal, namespace) {
21471
+ const priorId = replacement.memory.frontmatter.supersedes;
21472
+ if (!priorId) return null;
21473
+ const priorMemory = await storage.getMemoryById(priorId);
21474
+ const priorIsOwned = priorMemory ? this.ownsMemory(priorMemory, namespace, principal) : false;
21475
+ const alreadyRetired = priorIsOwned && priorMemory?.frontmatter.status === "superseded" && priorMemory.frontmatter.supersededBy === replacement.card.cardId;
21476
+ const prior = priorMemory && priorIsOwned && !alreadyRetired ? projectSupportPassportCard(priorMemory) : null;
21477
+ if (prior?.card.status === "rejected") return null;
21478
+ if (!priorMemory || !alreadyRetired && prior?.card.status !== "active") {
21479
+ throw new SupportPassportError("storage_conflict", "The prior support card changed before replacement.", 409);
21480
+ }
21481
+ if (alreadyRetired) return priorId;
21482
+ const retiredAt = this.now().toISOString();
21483
+ await this.requireOwnerLock(lock);
21484
+ const retired = await storage.writeMemoryFrontmatterIfUnchanged(
21485
+ priorMemory,
21486
+ {
21487
+ status: "superseded",
21488
+ supersededBy: replacement.card.cardId,
21489
+ supersededAt: retiredAt,
21490
+ supersessionCause: "direct",
21491
+ updated: retiredAt
21492
+ },
21493
+ {
21494
+ actor: principal,
21495
+ reasonCode: "support-passport-replacement-pending",
21496
+ relatedMemoryIds: [replacement.card.cardId]
21497
+ }
21498
+ );
21499
+ if (!retired) {
21500
+ throw new SupportPassportError("storage_conflict", "The prior support card changed before replacement.", 409);
21501
+ }
21502
+ return priorId;
21503
+ }
21504
+ async rejectPendingReplacementForPredecessor(storage, predecessor, lock, principal, namespace) {
21505
+ const storedCards = predecessor.card.status === "active" ? await this.readStoredCards(storage, lock, principal, namespace) : await this.readProjectedCards(storage, namespace, principal);
21506
+ const replacements = storedCards.filter((item) => {
21507
+ if (item.card.status !== "pending_review") return false;
21508
+ return predecessor.card.status === "pending_review" ? item.replacesDraftId === predecessor.card.cardId : item.memory.frontmatter.supersedes === predecessor.card.cardId;
21509
+ });
21510
+ if (replacements.length > 1) {
21511
+ throw new SupportPassportError(
21512
+ "storage_conflict",
21513
+ "Multiple support card edits target the card being withdrawn.",
21514
+ 409
21515
+ );
21516
+ }
21517
+ const [replacement] = replacements;
21518
+ if (!replacement) return;
21519
+ await this.requireOwnerLock(lock);
21520
+ const rejected = await storage.writeMemoryFrontmatterIfUnchanged(
21521
+ replacement.memory,
21522
+ { status: "rejected", updated: this.now().toISOString() },
21523
+ {
21524
+ actor: principal,
21525
+ reasonCode: predecessor.card.status === "pending_review" ? "source-draft-rejected" : "predecessor-withdrawn"
21526
+ }
21527
+ );
21528
+ if (rejected) return;
21529
+ const current = await storage.getMemoryById(replacement.card.cardId);
21530
+ const currentCard = current ? this.projectOwnedCard(current, namespace, principal) : null;
21531
+ if (currentCard?.card.status !== "rejected") {
21532
+ throw new SupportPassportError("storage_conflict", "The pending support card edit could not be cancelled.", 409);
21533
+ }
21534
+ }
21535
+ async validatePriorForReplacement(storage, replacement, namespace, principal) {
21536
+ const priorId = replacement.memory.frontmatter.supersedes;
21537
+ if (!priorId) return;
21538
+ const priorMemory = await storage.getMemoryById(priorId);
21539
+ const priorIsOwned = priorMemory ? this.ownsMemory(priorMemory, namespace, principal) : false;
21540
+ const alreadyRetired = priorIsOwned && priorMemory?.frontmatter.status === "superseded" && priorMemory.frontmatter.supersededBy === replacement.card.cardId;
21541
+ const prior = priorMemory && priorIsOwned && !alreadyRetired ? projectSupportPassportCard(priorMemory) : null;
21542
+ if (prior?.card.status === "rejected" || alreadyRetired) return;
21543
+ if (!priorMemory || prior?.card.status !== "active") {
21544
+ throw new SupportPassportError("storage_conflict", "The prior support card changed before replacement.", 409);
21545
+ }
21546
+ }
21547
+ async recoverReplacementTransition(storage, memory, lock, principal, namespace, options = {}) {
21548
+ const replacement = this.projectOwnedCard(memory, namespace, principal);
21549
+ if (replacement?.card.status !== "pending_review" && replacement?.card.status !== "active") return memory;
21550
+ if (!replacement.replacesDraftId && !memory.frontmatter.supersedes) return memory;
21551
+ if (replacement.card.status === "active" && memory.frontmatter.structuredAttributes?.[SUPPORT_PASSPORT_ATTRIBUTE_KEYS.replacementComplete] === "true") {
21552
+ return memory;
21553
+ }
21554
+ await this.recoverReplacedDraft(storage, replacement, lock, principal, namespace);
21555
+ const currentMemory = await storage.getMemoryById(replacement.card.cardId) ?? memory;
21556
+ const currentCard = this.projectOwnedCard(currentMemory, namespace, principal);
21557
+ if (currentCard?.card.status !== "pending_review" && currentCard?.card.status !== "active") {
21558
+ return currentMemory;
21559
+ }
21560
+ if (currentCard.card.status === "pending_review") {
21561
+ const priorId = currentMemory.frontmatter.supersedes;
21562
+ if (!priorId) return currentMemory;
21563
+ const prior = await storage.getMemoryById(priorId);
21564
+ if (prior && this.ownsMemory(prior, namespace, principal) && prior.frontmatter.status === "superseded" && prior.frontmatter.supersededBy === replacement.card.cardId) {
21565
+ await this.restorePriorAfterApprovalFailure(
21566
+ storage,
21567
+ priorId,
21568
+ replacement.card.cardId,
21569
+ lock,
21570
+ principal,
21571
+ namespace
21572
+ );
21573
+ }
21574
+ return await storage.getMemoryById(replacement.card.cardId) ?? currentMemory;
21575
+ }
21576
+ try {
21577
+ await this.completeReplacementAfterActivation(storage, currentCard, lock, principal, namespace);
21578
+ } catch (error) {
21579
+ if (!isStorageConflict(error)) throw error;
21580
+ if (options.rollbackConflictedApproval === false) throw error;
21581
+ await this.rollbackConflictedApproval(storage, currentCard.card.cardId, lock, principal, namespace);
21582
+ }
21583
+ return await storage.getMemoryById(replacement.card.cardId) ?? currentMemory;
21584
+ }
21585
+ async completeReplacementAfterActivation(storage, replacement, lock, principal, namespace) {
21586
+ const priorId = await this.preparePriorForReplacement(storage, replacement, lock, principal, namespace);
21587
+ if (priorId && !await this.completePriorRetirement(storage, priorId, replacement, lock, principal, namespace)) {
21588
+ throw new SupportPassportError("storage_conflict", "The prior support card changed before replacement.", 409);
21589
+ }
21590
+ await this.markReplacementComplete(storage, replacement.card.cardId, lock, principal, namespace);
21591
+ }
21592
+ async finishCommittedApproval(storage, replacement, lock, principal, namespace) {
21593
+ try {
21594
+ if (replacement.replacesDraftId || replacement.memory.frontmatter.supersedes) {
21595
+ await this.completeReplacementAfterActivation(storage, replacement, lock, principal, namespace);
21596
+ }
21597
+ } catch (error) {
21598
+ if (isStorageConflict(error)) {
21599
+ await this.rollbackConflictedApproval(storage, replacement.card.cardId, lock, principal, namespace);
21600
+ throw error;
21601
+ }
21602
+ log.warn(
21603
+ `support passport could not finish replacement approval side effects: ${error instanceof Error ? error.message : String(error)}`
21604
+ );
21605
+ }
21606
+ return replacement.card;
21607
+ }
21608
+ async rollbackConflictedApproval(storage, replacementId, lock, principal, namespace) {
21609
+ const replacement = await this.requireCard(storage, replacementId, namespace, principal);
21610
+ if (replacement.card.status !== "active") return;
21611
+ await this.requireOwnerLock(lock);
21612
+ const rolledBack = await storage.writeMemoryFrontmatterIfUnchanged(
21613
+ replacement.memory,
21614
+ { status: "pending_review", updated: this.now().toISOString() },
21615
+ { actor: principal, reasonCode: "replacement-predecessor-conflict" }
21616
+ );
21617
+ if (!rolledBack) {
21618
+ throw new SupportPassportError(
21619
+ "storage_conflict",
21620
+ "The replacement changed while its approval was rolled back.",
21621
+ 409
21622
+ );
21623
+ }
21624
+ const priorId = replacement.memory.frontmatter.supersedes;
21625
+ if (priorId) {
21626
+ await this.restorePriorAfterApprovalFailure(storage, priorId, replacementId, lock, principal, namespace);
21627
+ }
21628
+ }
21629
+ async completePriorRetirement(storage, priorId, replacement, lock, principal, namespace) {
21630
+ const replacementId = replacement.card.cardId;
21631
+ const prior = await storage.getMemoryById(priorId);
21632
+ if (!prior || !this.ownsMemory(prior, namespace, principal) || prior.frontmatter.status !== "superseded" || prior.frontmatter.supersededBy !== replacementId) {
21633
+ return false;
21634
+ }
21635
+ await this.requireOwnerLock(lock);
21636
+ const completed = await storage.supersedeMemory(
21637
+ priorId,
21638
+ replacementId,
21639
+ "support-passport-replacement",
21640
+ { supersessionCause: "direct" },
21641
+ {
21642
+ actor: principal,
21643
+ requireActive: true,
21644
+ acceptExactReplay: true,
21645
+ expectedSnapshot: prior,
21646
+ audit: {
21647
+ content: stripAttributesSuffix(prior.content),
21648
+ tags: ["supersession", "auto-resolved", "support-passport-audit"],
21649
+ structuredAttributes: {
21650
+ ...encodeSupportPassportNamespaceAttributes(namespace),
21651
+ [SUPPORT_PASSPORT_ATTRIBUTE_KEYS.owner]: computeSupportPassportOwnerKey(principal)
21652
+ },
21653
+ source: "support-passport"
21654
+ }
21655
+ }
21656
+ );
21657
+ if (!completed) log.warn("support passport could not complete replacement retirement side effects");
21658
+ return completed;
21659
+ }
21660
+ async recoverReplacedDraft(storage, replacement, lock, principal, namespace) {
21661
+ if (!replacement.replacesDraftId) return;
21662
+ const replacedDraft = await storage.getMemoryById(replacement.replacesDraftId);
21663
+ const projectedDraft = replacedDraft ? this.projectOwnedCard(replacedDraft, namespace, principal) : null;
21664
+ if (replacedDraft && projectedDraft?.card.status === "pending_review" && projectedDraft.card.revision === replacement.replacedRevision) {
21665
+ await this.requireOwnerLock(lock);
21666
+ const rejected = await storage.writeMemoryFrontmatterIfUnchanged(
21667
+ replacedDraft,
21668
+ { status: "rejected", updated: this.now().toISOString() },
21669
+ { actor: principal, reasonCode: "complete-draft-replacement" }
21670
+ );
21671
+ if (rejected) {
21672
+ await this.finishPreparedDraftReplacement(storage, replacement.card.cardId, lock, principal, namespace);
21673
+ return;
21674
+ }
21675
+ }
21676
+ const currentDraft = await storage.getMemoryById(replacement.replacesDraftId);
21677
+ if (currentDraft && this.ownsMemory(currentDraft, namespace, principal) && currentDraft.frontmatter.status === "rejected") {
21678
+ await this.finishPreparedDraftReplacement(storage, replacement.card.cardId, lock, principal, namespace);
21679
+ return;
21680
+ }
21681
+ if (currentDraft && this.ownsMemory(currentDraft, namespace, principal) && currentDraft.frontmatter.status === "pending_review") {
21682
+ throw new SupportPassportError("storage_conflict", "The replaced draft changed during recovery.", 409);
21683
+ }
21684
+ await this.rejectOrphanedReplacement(storage, replacement.card.cardId, lock, principal, namespace);
21685
+ }
21686
+ async finishPreparedDraftReplacement(storage, replacementId, lock, principal, namespace) {
21687
+ const replacement = await this.requireCard(storage, replacementId, namespace, principal);
21688
+ if (!replacement.draftReplacementPrepared) return replacement.card;
21689
+ const structuredAttributes = { ...replacement.memory.frontmatter.structuredAttributes };
21690
+ delete structuredAttributes[SUPPORT_PASSPORT_ATTRIBUTE_KEYS.draftReplacementPrepared];
21691
+ await this.requireOwnerLock(lock);
21692
+ const finished = await storage.writeMemoryFrontmatterIfUnchanged(
21693
+ replacement.memory,
21694
+ { structuredAttributes },
21695
+ { actor: principal, reasonCode: "draft-replacement-complete" }
21696
+ );
21697
+ if (finished) {
21698
+ return this.projectRequiredCard(
21699
+ { ...replacement.memory, frontmatter: { ...replacement.memory.frontmatter, structuredAttributes } },
21700
+ namespace,
21701
+ principal
21702
+ ).card;
21703
+ }
21704
+ const current = await this.requireCard(storage, replacementId, namespace, principal);
21705
+ if (!current.draftReplacementPrepared) return current.card;
21706
+ throw new SupportPassportError("storage_conflict", "The support card edit could not be completed.", 409);
21707
+ }
21708
+ async rejectOrphanedReplacement(storage, replacementId, lock, principal, namespace) {
21709
+ const currentReplacement = await this.requireCard(storage, replacementId, namespace, principal);
21710
+ if (currentReplacement.card.status === "rejected") return;
21711
+ this.requireStatus(currentReplacement, "pending_review");
21712
+ await this.requireOwnerLock(lock);
21713
+ const rejected = await storage.writeMemoryFrontmatterIfUnchanged(
21714
+ currentReplacement.memory,
21715
+ { status: "rejected", updated: this.now().toISOString() },
21716
+ { actor: principal, reasonCode: "replaced-draft-approved" }
21717
+ );
21718
+ if (rejected) return;
21719
+ const latest = await storage.getMemoryById(replacementId);
21720
+ if (latest?.frontmatter.status !== "rejected") {
21721
+ throw new SupportPassportError("storage_conflict", "The orphaned replacement could not be rejected.", 409);
21722
+ }
21723
+ }
21724
+ async restorePriorAfterApprovalFailure(storage, priorId, replacementId, lock, principal, namespace) {
21725
+ const replacement = await storage.getMemoryById(replacementId);
21726
+ if (replacement && !this.ownsMemory(replacement, namespace, principal)) {
21727
+ throw new SupportPassportError("storage_conflict", "The replacement support card changed ownership.", 409);
21728
+ }
21729
+ if (replacement?.frontmatter.status === "active") return;
21730
+ const prior = await storage.getMemoryById(priorId);
21731
+ if (prior && !this.ownsMemory(prior, namespace, principal)) {
21732
+ throw new SupportPassportError("storage_conflict", "The prior support card changed ownership.", 409);
21733
+ }
21734
+ if (prior?.frontmatter.status === "active" && prior.frontmatter.supersededBy === void 0) return;
21735
+ if (prior?.frontmatter.status !== "superseded" || prior.frontmatter.supersededBy !== replacementId) {
21736
+ throw new SupportPassportError("storage_conflict", "The prior support card could not be restored.", 409);
21737
+ }
21738
+ await this.requireOwnerLock(lock);
21739
+ const restored = await storage.writeMemoryFrontmatterIfUnchanged(
21740
+ prior,
21741
+ {
21742
+ status: "active",
21743
+ supersededBy: void 0,
21744
+ supersededAt: void 0,
21745
+ supersessionCause: void 0,
21746
+ invalidatedBy: void 0,
21747
+ updated: this.now().toISOString()
21748
+ },
21749
+ { actor: principal, reasonCode: "replacement-activation-failed" }
21750
+ );
21751
+ if (restored) return;
21752
+ const currentPrior = await storage.getMemoryById(priorId);
21753
+ if (currentPrior?.frontmatter.status === "active" && currentPrior.frontmatter.supersededBy === void 0) return;
21754
+ throw new SupportPassportError("storage_conflict", "The prior support card could not be restored.", 409);
21755
+ }
21756
+ async markReplacementComplete(storage, replacementId, lock, principal, namespace) {
21757
+ const replacement = await this.requireCard(storage, replacementId, namespace, principal);
21758
+ if (replacement.memory.frontmatter.structuredAttributes?.[SUPPORT_PASSPORT_ATTRIBUTE_KEYS.replacementComplete] === "true") {
21759
+ return;
21760
+ }
21761
+ await this.requireOwnerLock(lock);
21762
+ const marked = await storage.writeMemoryFrontmatterIfUnchanged(
21763
+ replacement.memory,
21764
+ {
21765
+ structuredAttributes: {
21766
+ ...replacement.memory.frontmatter.structuredAttributes,
21767
+ [SUPPORT_PASSPORT_ATTRIBUTE_KEYS.replacementComplete]: "true"
21768
+ }
21769
+ },
21770
+ { actor: principal, reasonCode: "replacement-side-effects-complete" }
21771
+ );
21772
+ if (!marked) log.warn("support passport could not mark replacement side effects complete");
21773
+ }
21774
+ async requireOwnerLock(lock) {
21775
+ if (await lock.refresh()) return;
21776
+ throw new SupportPassportError("storage_conflict", "The support passport lock changed. Try again.", 409);
21777
+ }
21778
+ };
21779
+
21780
+ // src/support-passport/grant-contracts.ts
21781
+ import { z } from "zod";
21782
+ var IsoTimestampSchema = z.string().datetime({ offset: true }).refine((value) => parseIsoOffsetTimestamp(value) !== null, "timestamp must be a real date");
21783
+ var RevisionSchema = z.string().regex(/^[a-f0-9]{64}$/);
21784
+ var GrantIdSchema = z.string().uuid().transform((value) => value.toLowerCase());
21785
+ var SupportPassportGrantCardRefSchema = z.object({
21786
+ cardId: SupportPassportMemoryIdSchema,
21787
+ revision: RevisionSchema
21788
+ }).strict();
21789
+ var SupportPassportGrantStateSchema = z.object({
21790
+ schemaVersion: z.literal(1),
21791
+ stateVersion: z.number().int().positive(),
21792
+ grantId: GrantIdSchema,
21793
+ namespace: SupportPassportNamespaceSchema,
21794
+ principalHash: RevisionSchema,
21795
+ ownerLockKey: RevisionSchema,
21796
+ secretHash: RevisionSchema,
21797
+ cards: z.array(SupportPassportGrantCardRefSchema).min(1).max(8),
21798
+ createdAt: IsoTimestampSchema,
21799
+ expiresAt: IsoTimestampSchema,
21800
+ revokedAt: IsoTimestampSchema.optional()
21801
+ }).strict().superRefine((grant, ctx) => {
21802
+ const ids = /* @__PURE__ */ new Set();
21803
+ for (const [index, card] of grant.cards.entries()) {
21804
+ if (ids.has(card.cardId)) {
21805
+ ctx.addIssue({
21806
+ code: z.ZodIssueCode.custom,
21807
+ message: "card IDs must be unique",
21808
+ path: ["cards", index, "cardId"]
21809
+ });
21810
+ }
21811
+ ids.add(card.cardId);
21812
+ }
21813
+ if (Date.parse(grant.expiresAt) <= Date.parse(grant.createdAt)) {
21814
+ ctx.addIssue({ code: z.ZodIssueCode.custom, message: "expiresAt must follow createdAt", path: ["expiresAt"] });
21815
+ }
21816
+ });
21817
+ var SupportPassportCreateGrantInputSchema = z.object({
21818
+ principal: z.string().trim().min(1).max(512),
21819
+ cards: z.array(SupportPassportGrantCardRefSchema).min(1).max(8),
21820
+ expiresAt: IsoTimestampSchema
21821
+ }).strict().superRefine((input, ctx) => {
21822
+ const ids = /* @__PURE__ */ new Set();
21823
+ for (const [index, card] of input.cards.entries()) {
21824
+ if (ids.has(card.cardId)) {
21825
+ ctx.addIssue({
21826
+ code: z.ZodIssueCode.custom,
21827
+ message: "card IDs must be unique",
21828
+ path: ["cards", index, "cardId"]
21829
+ });
21830
+ }
21831
+ ids.add(card.cardId);
21832
+ }
21833
+ });
21834
+ var SupportPassportOwnerGrantSchema = z.object({
21835
+ grantId: GrantIdSchema,
21836
+ stateVersion: z.number().int().positive(),
21837
+ cards: z.array(SupportPassportGrantCardRefSchema).min(1).max(8),
21838
+ createdAt: IsoTimestampSchema,
21839
+ expiresAt: IsoTimestampSchema,
21840
+ revokedAt: IsoTimestampSchema.optional(),
21841
+ status: z.enum(["active", "expired", "revoked"])
21842
+ }).strict();
21843
+ var SupportPassportCreatedGrantSchema = z.object({
21844
+ grant: SupportPassportOwnerGrantSchema,
21845
+ secret: z.string().regex(/^[A-Za-z0-9_-]{43}$/)
21846
+ }).strict();
21847
+ var SupportPassportPublicCardSchema = z.object({
21848
+ cardId: SupportPassportMemoryIdSchema,
21849
+ title: z.string().trim().min(1).max(80),
21850
+ statement: z.string().trim().min(1).max(500),
21851
+ category: SupportPassportCardCategorySchema,
21852
+ updatedAt: IsoTimestampSchema
21853
+ }).strict();
21854
+ var SupportPassportPublicGuideSchema = z.object({
21855
+ schemaVersion: z.literal(1),
21856
+ grantId: GrantIdSchema,
21857
+ expiresAt: IsoTimestampSchema,
21858
+ updatedAt: IsoTimestampSchema,
21859
+ cards: z.array(SupportPassportPublicCardSchema).min(1).max(8)
21860
+ }).strict();
21861
+ var SupportPassportRevokeGrantInputSchema = z.object({
21862
+ principal: z.string().trim().min(1).max(512),
21863
+ grantId: GrantIdSchema,
21864
+ expectedStateVersion: z.number().int().positive().optional()
21865
+ }).strict();
21866
+ var SupportPassportListGrantsInputSchema = z.object({
21867
+ principal: z.string().trim().min(1).max(512)
21868
+ }).strict();
21869
+
21870
+ // src/support-passport/grant-store.ts
21871
+ import { createHash as createHash10, randomBytes as randomBytes3, randomUUID as randomUUID3, timingSafeEqual } from "crypto";
21872
+ import { lstat as lstat4, open as open2, readdir as readdir4 } from "fs/promises";
21873
+ import path23 from "path";
21874
+
21875
+ // src/support-passport/private-file.ts
21876
+ import { randomUUID as randomUUID2 } from "crypto";
21877
+ import { constants as fsConstants } from "fs";
21878
+ import { lstat as lstat3, mkdir as mkdir7, open, rename, rm, stat as stat4 } from "fs/promises";
21879
+ import path22 from "path";
21880
+ var UNSUPPORTED_DIRECTORY_SYNC_ERRORS = /* @__PURE__ */ new Set(["EINVAL", "ENOSYS", "ENOTSUP", "EOPNOTSUPP"]);
21881
+ var NON_WRITABLE_ANCESTOR_SYNC_ERRORS = /* @__PURE__ */ new Set(["EROFS", "EPERM", "EACCES"]);
21882
+ function assertStableDirectory(before, opened, after, errorMessage) {
21883
+ if (before.isSymbolicLink() || !before.isDirectory() || after.isSymbolicLink() || !after.isDirectory() || before.dev !== opened.dev || before.ino !== opened.ino || after.dev !== opened.dev || after.ino !== opened.ino) {
21884
+ throw new Error(errorMessage);
21885
+ }
21886
+ }
21887
+ function assertStableRegularFile(before, opened, after, errorMessage) {
21888
+ if (before.isSymbolicLink() || !before.isFile() || after.isSymbolicLink() || !after.isFile() || before.dev !== opened.dev || before.ino !== opened.ino || after.dev !== opened.dev || after.ino !== opened.ino || opened.nlink !== 1) {
21889
+ throw new Error(errorMessage);
21890
+ }
21891
+ }
21892
+ function openFlags(...flags) {
21893
+ let combined = 0;
21894
+ for (const flag of flags) combined |= typeof flag === "number" ? flag : 0;
21895
+ return combined;
21896
+ }
21897
+ function assertContainedPath(trustedRoot, directory, errorMessage) {
21898
+ const relative = path22.relative(path22.resolve(trustedRoot), path22.resolve(directory));
21899
+ if (relative === ".." || relative.startsWith(`..${path22.sep}`) || path22.isAbsolute(relative)) {
21900
+ throw new Error(errorMessage);
21901
+ }
21902
+ }
21903
+ async function openDirectoryNoFollow(directory, errorMessage) {
21904
+ const before = await lstat3(directory);
21905
+ if (before.isSymbolicLink() || !before.isDirectory()) throw new Error(errorMessage);
21906
+ const handle = await open(
21907
+ directory,
21908
+ openFlags(fsConstants.O_RDONLY, fsConstants.O_DIRECTORY, fsConstants.O_NOFOLLOW)
21909
+ );
21910
+ try {
21911
+ const opened = await handle.stat();
21912
+ assertStableDirectory(before, opened, await lstat3(directory), errorMessage);
21913
+ return { before, opened, handle };
21914
+ } catch (error) {
21915
+ await handle.close().catch(() => void 0);
21916
+ throw error;
21917
+ }
21918
+ }
21919
+ async function closeDirectoryHandles(handles) {
21920
+ for (const handle of handles.reverse()) await handle.close().catch(() => void 0);
21921
+ }
21922
+ async function syncDirectoryHandle(handle) {
21923
+ try {
21924
+ await handle.sync();
21925
+ } catch (error) {
21926
+ const code = error.code;
21927
+ if (!UNSUPPORTED_DIRECTORY_SYNC_ERRORS.has(code ?? "")) throw error;
21928
+ }
21929
+ }
21930
+ async function resolvePrivateDirectoryPath(directory, handle, opened, errorMessage, platform = process.platform) {
21931
+ const descriptorRoot = requirePrivateFileDescriptorRoot(platform, errorMessage);
21932
+ const pinnedPath = path22.join(descriptorRoot, String(handle.fd));
21933
+ const metadata = await stat4(pinnedPath);
21934
+ if (!metadata.isDirectory() || metadata.dev !== opened.dev || metadata.ino !== opened.ino) {
21935
+ throw new Error(errorMessage);
21936
+ }
21937
+ return pinnedPath;
21938
+ }
21939
+ function requirePrivateFileDescriptorRoot(platform, errorMessage) {
21940
+ if (platform === "linux") return "/proc/self/fd";
21941
+ if (platform === "darwin" || platform === "freebsd" || platform === "openbsd") return "/dev/fd";
21942
+ throw new Error(errorMessage);
21943
+ }
21944
+ async function openStableDirectoryFromRoot(trustedRoot, directory, errorMessage, platform = process.platform) {
21945
+ const root = path22.resolve(trustedRoot);
21946
+ const target = path22.resolve(directory);
21947
+ assertContainedPath(root, target, errorMessage);
21948
+ requirePrivateFileDescriptorRoot(platform, errorMessage);
21949
+ const relative = path22.relative(root, target);
21950
+ const components = relative === "" ? [] : relative.split(path22.sep);
21951
+ const handles = [];
21952
+ let currentPath = root;
21953
+ try {
21954
+ let current = await openDirectoryNoFollow(root, errorMessage);
21955
+ handles.push(current.handle);
21956
+ for (const component of components) {
21957
+ const pinnedParent = await resolvePrivateDirectoryPath(currentPath, current.handle, current.opened, errorMessage);
21958
+ const child = await openDirectoryNoFollow(path22.join(pinnedParent, component), errorMessage);
21959
+ handles.push(child.handle);
21960
+ assertStableDirectory(current.before, current.opened, await lstat3(currentPath), errorMessage);
21961
+ currentPath = path22.join(currentPath, component);
21962
+ current = child;
21963
+ }
21964
+ assertStableDirectory(current.before, current.opened, await lstat3(target), errorMessage);
21965
+ return {
21966
+ ...current,
21967
+ handles,
21968
+ pinnedDirectory: await resolvePrivateDirectoryPath(
21969
+ target,
21970
+ current.handle,
21971
+ current.opened,
21972
+ errorMessage,
21973
+ platform
21974
+ )
21975
+ };
21976
+ } catch (error) {
21977
+ await closeDirectoryHandles(handles);
21978
+ throw error;
21979
+ }
21980
+ }
21981
+ async function ensurePrivateDirectoryNoFollow(trustedRoot, directory, errorMessage, syncVerifiedParent = syncDirectoryHandle, hardenExistingChildren = true, platform = process.platform) {
21982
+ const root = path22.resolve(trustedRoot);
21983
+ const target = path22.resolve(directory);
21984
+ assertContainedPath(root, target, errorMessage);
21985
+ const relative = path22.relative(root, target);
21986
+ requirePrivateFileDescriptorRoot(platform, errorMessage);
21987
+ const components = relative === "" ? [] : relative.split(path22.sep);
21988
+ const handles = [];
21989
+ let currentPath = root;
21990
+ try {
21991
+ let current = await openDirectoryNoFollow(root, errorMessage);
21992
+ handles.push(current.handle);
21993
+ for (const component of components) {
21994
+ const pinnedParent = await resolvePrivateDirectoryPath(currentPath, current.handle, current.opened, errorMessage);
21995
+ const childPath = path22.join(pinnedParent, component);
21996
+ let created = false;
21997
+ try {
21998
+ await mkdir7(childPath, { mode: 448 });
21999
+ created = true;
22000
+ } catch (error) {
22001
+ if (error.code !== "EEXIST") throw error;
22002
+ }
22003
+ await syncVerifiedParent(current.handle);
22004
+ const child = await openDirectoryNoFollow(childPath, errorMessage);
22005
+ handles.push(child.handle);
22006
+ if (created || hardenExistingChildren && (child.opened.mode & 511) !== 448) {
22007
+ await child.handle.chmod(448);
22008
+ }
22009
+ assertStableDirectory(current.before, current.opened, await lstat3(currentPath), errorMessage);
22010
+ currentPath = path22.join(currentPath, component);
22011
+ current = child;
22012
+ }
22013
+ assertStableDirectory(current.before, current.opened, await lstat3(target), errorMessage);
22014
+ } finally {
22015
+ await closeDirectoryHandles(handles);
22016
+ }
22017
+ }
22018
+ async function ensurePrivateDirectoryTreeNoFollow(directory, errorMessage, syncVerifiedParent = syncDirectoryHandle, platform = process.platform) {
22019
+ const target = path22.resolve(directory);
22020
+ const filesystemRoot = path22.parse(target).root;
22021
+ const rootMetadata = await stat4(filesystemRoot);
22022
+ await ensurePrivateDirectoryNoFollow(
22023
+ filesystemRoot,
22024
+ target,
22025
+ errorMessage,
22026
+ async (handle) => {
22027
+ try {
22028
+ await syncVerifiedParent(handle);
22029
+ } catch (error) {
22030
+ const code = error.code;
22031
+ const metadata = await handle.stat();
22032
+ if (metadata.ino === rootMetadata.ino && metadata.dev === rootMetadata.dev && NON_WRITABLE_ANCESTOR_SYNC_ERRORS.has(code ?? "")) {
22033
+ return;
22034
+ }
22035
+ throw error;
22036
+ }
22037
+ },
22038
+ false,
22039
+ platform
22040
+ );
22041
+ }
22042
+ async function withPrivateDirectoryNoFollow(trustedRoot, directory, errorMessage, task, platform = process.platform) {
22043
+ let directoryHandles = [];
22044
+ try {
22045
+ const stableDirectory = await openStableDirectoryFromRoot(trustedRoot, directory, errorMessage, platform);
22046
+ directoryHandles = stableDirectory.handles;
22047
+ const result = await task(stableDirectory.pinnedDirectory);
22048
+ assertStableDirectory(stableDirectory.before, stableDirectory.opened, await lstat3(directory), errorMessage);
22049
+ return result;
22050
+ } finally {
22051
+ await closeDirectoryHandles(directoryHandles);
22052
+ }
22053
+ }
22054
+ async function readPrivateFileNoFollow(directory, filePath, errorMessage, trustedRoot = directory, platform = process.platform) {
22055
+ if (path22.dirname(filePath) !== path22.resolve(directory)) throw new Error(errorMessage);
22056
+ const targetName = path22.basename(filePath);
22057
+ let directoryHandles = [];
22058
+ let fileHandle;
22059
+ try {
22060
+ const stableDirectory = await openStableDirectoryFromRoot(trustedRoot, directory, errorMessage, platform);
22061
+ directoryHandles = stableDirectory.handles;
22062
+ const pinnedDirectory = stableDirectory.pinnedDirectory;
22063
+ const targetPath = path22.join(pinnedDirectory, targetName);
22064
+ const before = await lstat3(targetPath);
22065
+ if (before.isSymbolicLink() || !before.isFile()) throw new Error(errorMessage);
22066
+ try {
22067
+ fileHandle = await open(targetPath, openFlags(fsConstants.O_RDONLY, fsConstants.O_NOFOLLOW));
22068
+ } catch (error) {
22069
+ if (error.code === "ELOOP") throw new Error(errorMessage);
22070
+ throw error;
22071
+ }
22072
+ const fileMetadata = await fileHandle.stat();
22073
+ assertStableRegularFile(before, fileMetadata, await lstat3(targetPath), errorMessage);
22074
+ assertStableDirectory(stableDirectory.before, stableDirectory.opened, await lstat3(directory), errorMessage);
22075
+ return await fileHandle.readFile("utf8");
22076
+ } finally {
22077
+ await fileHandle?.close().catch(() => void 0);
22078
+ await closeDirectoryHandles(directoryHandles);
22079
+ }
22080
+ }
22081
+ async function writePrivateFileAtomicallyNoFollow(directory, filePath, content, errorMessage, trustedRoot = directory, platform = process.platform) {
22082
+ if (path22.dirname(filePath) !== path22.resolve(directory)) throw new Error(errorMessage);
22083
+ const targetName = path22.basename(filePath);
22084
+ const tempName = `.${targetName}.${randomUUID2()}.tmp`;
22085
+ let tempPath;
22086
+ let directoryHandles = [];
22087
+ let fileHandle;
22088
+ try {
22089
+ const stableDirectory = await openStableDirectoryFromRoot(trustedRoot, directory, errorMessage, platform);
22090
+ directoryHandles = stableDirectory.handles;
22091
+ const pinnedDirectory = stableDirectory.pinnedDirectory;
22092
+ tempPath = path22.join(pinnedDirectory, tempName);
22093
+ const targetPath = path22.join(pinnedDirectory, targetName);
22094
+ try {
22095
+ fileHandle = await open(
22096
+ tempPath,
22097
+ openFlags(fsConstants.O_WRONLY, fsConstants.O_CREAT, fsConstants.O_EXCL, fsConstants.O_NOFOLLOW),
22098
+ 384
22099
+ );
22100
+ } catch (error) {
22101
+ if (error.code === "ELOOP") throw new Error(errorMessage);
22102
+ throw error;
22103
+ }
22104
+ const fileMetadata = await fileHandle.stat();
22105
+ const tempMetadata = await lstat3(tempPath);
22106
+ assertStableRegularFile(tempMetadata, fileMetadata, await lstat3(tempPath), errorMessage);
22107
+ assertStableDirectory(stableDirectory.before, stableDirectory.opened, await lstat3(directory), errorMessage);
22108
+ await fileHandle.chmod(384);
22109
+ await fileHandle.writeFile(content, "utf8");
22110
+ await fileHandle.sync();
22111
+ await fileHandle.close();
22112
+ fileHandle = void 0;
22113
+ assertStableDirectory(stableDirectory.before, stableDirectory.opened, await lstat3(directory), errorMessage);
22114
+ await rename(tempPath, targetPath);
22115
+ assertStableDirectory(stableDirectory.before, stableDirectory.opened, await lstat3(directory), errorMessage);
22116
+ if (stableDirectory.handle) await syncDirectoryHandle(stableDirectory.handle);
22117
+ } finally {
22118
+ await fileHandle?.close().catch(() => void 0);
22119
+ if (tempPath) await rm(tempPath, { force: true }).catch(() => void 0);
22120
+ await closeDirectoryHandles(directoryHandles);
22121
+ }
22122
+ }
22123
+ async function removePrivateFilesNoFollow(directory, fileNames, errorMessage, trustedRoot = directory, platform = process.platform) {
22124
+ if (fileNames.some(
22125
+ (fileName) => fileName.length === 0 || fileName === "." || fileName === ".." || path22.basename(fileName) !== fileName
22126
+ )) {
22127
+ throw new Error(errorMessage);
22128
+ }
22129
+ let directoryHandles = [];
22130
+ try {
22131
+ const stableDirectory = await openStableDirectoryFromRoot(trustedRoot, directory, errorMessage, platform);
22132
+ directoryHandles = stableDirectory.handles;
22133
+ const pinnedDirectory = stableDirectory.pinnedDirectory;
22134
+ for (const fileName of fileNames) {
22135
+ await rm(path22.join(pinnedDirectory, fileName), { force: true });
22136
+ }
22137
+ assertStableDirectory(stableDirectory.before, stableDirectory.opened, await lstat3(directory), errorMessage);
22138
+ if (stableDirectory.handle) await syncDirectoryHandle(stableDirectory.handle);
22139
+ } finally {
22140
+ await closeDirectoryHandles(directoryHandles);
22141
+ }
22142
+ }
22143
+
22144
+ // src/support-passport/grant-store.ts
22145
+ var GRANT_LOCK_STALE_MS = 3e4;
22146
+ var GRANT_LOCK_WAIT_MS = 5e3;
22147
+ var GRANT_LOCK_HEARTBEAT_MS = 1e4;
22148
+ var SAFE_GRANT_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
22149
+ var UUID_INPUT = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
22150
+ var SAFE_OWNER_INDEX_HASH = /^[0-9a-f]{64}$/;
22151
+ var UNSUPPORTED_DIRECTORY_SYNC_ERRORS2 = /* @__PURE__ */ new Set(["EINVAL", "ENOSYS", "ENOTSUP", "EOPNOTSUPP"]);
22152
+ var MAX_OWNER_GRANT_HISTORY = 100;
22153
+ var MAX_OWNER_INDEX_RECOVERY_ATTEMPTS = 3;
22154
+ var OwnerIndexLockLostError = class extends Error {
22155
+ constructor(cause) {
22156
+ super("support passport owner index lock was lost", { cause });
22157
+ this.name = "OwnerIndexLockLostError";
22158
+ }
22159
+ };
22160
+ var MalformedGrantStateError = class extends Error {
22161
+ constructor(message = "support passport grant state is invalid", cause) {
22162
+ super(message, { cause });
22163
+ this.name = "MalformedGrantStateError";
22164
+ }
22165
+ };
22166
+ function sha256(domain, value) {
22167
+ return createHash10("sha256").update(domain).update("\0").update(value).digest("hex");
22168
+ }
22169
+ function hashesMatch(left, right) {
22170
+ const leftBytes = Buffer.from(left, "hex");
22171
+ const rightBytes = Buffer.from(right, "hex");
22172
+ return leftBytes.length === 32 && rightBytes.length === 32 && timingSafeEqual(leftBytes, rightBytes);
22173
+ }
22174
+ function sameGrantState(left, right) {
22175
+ return JSON.stringify(left) === JSON.stringify(right);
22176
+ }
22177
+ function newestGrantFirst(left, right) {
22178
+ return Date.parse(right.createdAt) - Date.parse(left.createdAt) || left.grantId.localeCompare(right.grantId);
22179
+ }
22180
+ function grantNotFound() {
22181
+ return new SupportPassportError("grant_not_found", "The share link was not found.", 404);
22182
+ }
22183
+ function warnCommitNotificationFailure(error) {
22184
+ log.warn(`support passport commit notification failed: ${error instanceof Error ? error.message : String(error)}`);
22185
+ }
22186
+ function notifySupportPassportCommitted(callback) {
22187
+ try {
22188
+ const completion = callback?.();
22189
+ if (completion) void Promise.resolve(completion).catch(warnCommitNotificationFailure);
22190
+ } catch (error) {
22191
+ warnCommitNotificationFailure(error);
22192
+ }
22193
+ }
22194
+ function normalizeGrantId(grantId) {
22195
+ if (typeof grantId !== "string" || !UUID_INPUT.test(grantId)) throw grantNotFound();
22196
+ return grantId.toLowerCase();
22197
+ }
22198
+ function normalizeNamespace(namespace) {
22199
+ const parsed = SupportPassportNamespaceSchema.safeParse(namespace);
22200
+ if (!parsed.success) {
22201
+ throw new SupportPassportError("invalid_input", "The share link request is invalid.", 400);
22202
+ }
22203
+ return parsed.data;
22204
+ }
22205
+ function normalizePrincipal(principal) {
22206
+ const normalized = typeof principal === "string" ? principal.trim() : "";
22207
+ if (normalized.length < 1 || normalized.length > 512) {
22208
+ throw new SupportPassportError("invalid_input", "The share link request is invalid.", 400);
22209
+ }
22210
+ return normalized;
22211
+ }
22212
+ async function syncDirectoryForDurability(directory, openDirectory = async (target) => await open2(target, "r")) {
22213
+ let handle;
22214
+ try {
22215
+ handle = await openDirectory(directory);
22216
+ await handle.sync();
22217
+ } catch (error) {
22218
+ const code = error.code;
22219
+ if (!UNSUPPORTED_DIRECTORY_SYNC_ERRORS2.has(code ?? "")) throw error;
22220
+ } finally {
22221
+ await handle?.close().catch(() => void 0);
22222
+ }
22223
+ }
22224
+ var SupportPassportGrantStore = class {
22225
+ memoryDir;
22226
+ grantsDir;
22227
+ ownerIndexesDir;
22228
+ memoryRootReady;
22229
+ safeDirectoriesReady;
22230
+ now;
22231
+ makeSecret;
22232
+ makeGrantId;
22233
+ runWithHeldFileLock;
22234
+ syncDirectory;
22235
+ constructor(options) {
22236
+ this.memoryDir = path23.resolve(expandTildePath(options.memoryDir));
22237
+ this.grantsDir = path23.join(this.memoryDir, "state", "support-passport", "grants");
22238
+ this.ownerIndexesDir = path23.join(this.grantsDir, "owners");
22239
+ this.now = options.now ?? (() => /* @__PURE__ */ new Date());
22240
+ this.makeSecret = options.makeSecret ?? (() => randomBytes3(32));
22241
+ this.makeGrantId = options.makeGrantId ?? randomUUID3;
22242
+ this.runWithHeldFileLock = options.withHeldFileLock ?? withHeldFileLock;
22243
+ this.syncDirectory = options.syncDirectory ?? syncDirectoryForDurability;
22244
+ }
22245
+ async create(input, hooks = {}) {
22246
+ const mutationHooks = typeof hooks === "function" ? { beforeCommit: hooks } : hooks;
22247
+ const namespace = normalizeNamespace(input.namespace);
22248
+ const parsed = SupportPassportCreateGrantInputSchema.safeParse({
22249
+ principal: input.principal,
22250
+ cards: input.cards,
22251
+ expiresAt: input.expiresAt
22252
+ });
22253
+ if (!parsed.success) {
22254
+ throw new SupportPassportError("invalid_input", "The share link request is invalid.", 400);
22255
+ }
22256
+ const requestedAt = input.requestedAt ?? this.now();
22257
+ const durationMs = Date.parse(parsed.data.expiresAt) - requestedAt.getTime();
22258
+ if (!Number.isFinite(requestedAt.getTime()) || !Number.isFinite(durationMs) || durationMs < 3e5 || durationMs > 6048e5) {
22259
+ throw new SupportPassportError("invalid_input", "The share link request is invalid.", 400);
22260
+ }
22261
+ const principalHash = computeSupportPassportOwnerKey(parsed.data.principal);
22262
+ const ownerHash = this.ownerHash(namespace, principalHash);
22263
+ let committed;
22264
+ try {
22265
+ let finalized;
22266
+ try {
22267
+ finalized = await this.withOwnerIndexLock(ownerHash, async (lock) => {
22268
+ await this.requireAvailableOwnerGrantSlot(namespace, principalHash);
22269
+ committed = await this.withMutationLock(async (mutationLock) => {
22270
+ const secretBytes = this.makeSecret();
22271
+ if (!Buffer.isBuffer(secretBytes) || secretBytes.length !== 32) {
22272
+ throw new Error("SupportPassportGrantStore.makeSecret must return 32 bytes");
22273
+ }
22274
+ const rawGrantId = this.makeGrantId();
22275
+ if (!UUID_INPUT.test(rawGrantId)) {
22276
+ throw new Error("SupportPassportGrantStore.makeGrantId must return a UUID");
22277
+ }
22278
+ const grantId = rawGrantId.toLowerCase();
22279
+ const secret = secretBytes.toString("base64url");
22280
+ const createdAt = this.now();
22281
+ const createdAtMs = createdAt.getTime();
22282
+ const expiresAtMs = Date.parse(parsed.data.expiresAt);
22283
+ if (!Number.isFinite(createdAtMs) || requestedAt.getTime() > createdAtMs || expiresAtMs <= createdAtMs || expiresAtMs - createdAtMs > 6048e5) {
22284
+ throw new SupportPassportError("invalid_input", "The share link request is invalid.", 400);
22285
+ }
22286
+ const state = SupportPassportGrantStateSchema.parse({
22287
+ schemaVersion: 1,
22288
+ stateVersion: 1,
22289
+ grantId,
22290
+ namespace,
22291
+ principalHash,
22292
+ ownerLockKey: computeSupportPassportOwnerLockKey(namespace, parsed.data.principal),
22293
+ secretHash: sha256("support-passport-secret:v1", secret),
22294
+ cards: parsed.data.cards,
22295
+ createdAt: createdAt.toISOString(),
22296
+ expiresAt: parsed.data.expiresAt
22297
+ });
22298
+ await this.requireMutationLock(mutationLock);
22299
+ await mutationHooks.beforeCommit?.();
22300
+ await this.requireMutationLock(mutationLock);
22301
+ try {
22302
+ await this.writeState(state, true);
22303
+ } catch (error) {
22304
+ const persisted2 = await this.readState(state.grantId).catch(() => void 0);
22305
+ if (!persisted2 || !sameGrantState(persisted2, state)) throw error;
22306
+ try {
22307
+ await this.syncDirectory(this.grantsDir);
22308
+ } catch {
22309
+ await this.removeGrantStates([state.grantId]).catch(() => void 0);
22310
+ throw error;
22311
+ }
22312
+ }
22313
+ try {
22314
+ await this.writeOwnerMembership(state);
22315
+ } catch (error) {
22316
+ await this.removeStoredGrant(state).catch(() => void 0);
22317
+ throw error;
22318
+ }
22319
+ const persisted = { state, secret };
22320
+ committed = persisted;
22321
+ return persisted;
22322
+ });
22323
+ try {
22324
+ await this.addToOwnerIndex(committed.state, lock);
22325
+ } catch (error) {
22326
+ if (error instanceof OwnerIndexLockLostError) throw error;
22327
+ const indexed = await this.readOwnerIndexByHash(ownerHash).catch(() => void 0);
22328
+ if (!indexed?.includes(committed.state.grantId)) throw error;
22329
+ try {
22330
+ await this.syncDirectory(this.ownerIndexesDir);
22331
+ } catch {
22332
+ throw error;
22333
+ }
22334
+ await this.requireOwnerIndexLock(lock);
22335
+ }
22336
+ return committed;
22337
+ });
22338
+ } catch (error) {
22339
+ if (!(error instanceof OwnerIndexLockLostError) || !committed) throw error;
22340
+ finalized = await this.reconcileCreateAfterOwnerIndexLockLoss(committed);
22341
+ }
22342
+ notifySupportPassportCommitted(mutationHooks.onCommitted);
22343
+ return finalized;
22344
+ } catch (error) {
22345
+ if (committed) {
22346
+ await this.withGrantLock(committed.state.grantId, async (lock) => {
22347
+ await this.requireMutationLock(lock);
22348
+ await this.removeStoredGrant(committed.state);
22349
+ }).catch(() => void 0);
22350
+ }
22351
+ throw error;
22352
+ }
22353
+ }
22354
+ async authenticate(grantId, secret) {
22355
+ const normalizedGrantId = normalizeGrantId(grantId);
22356
+ if (typeof secret !== "string" || secret.length > 512) throw grantNotFound();
22357
+ let state;
22358
+ try {
22359
+ state = await this.readState(normalizedGrantId);
22360
+ } catch (error) {
22361
+ if (error.code === "ENOENT") throw grantNotFound();
22362
+ throw error;
22363
+ }
22364
+ const candidate = sha256("support-passport-secret:v1", secret);
22365
+ if (!hashesMatch(candidate, state.secretHash)) throw grantNotFound();
22366
+ if (state.revokedAt) {
22367
+ throw new SupportPassportError("grant_gone", "The share link is no longer active.", 410);
22368
+ }
22369
+ if (Date.parse(state.expiresAt) <= this.now().getTime()) {
22370
+ throw new SupportPassportError("grant_expired", "The share link has expired.", 410);
22371
+ }
22372
+ return state;
22373
+ }
22374
+ async withAuthenticatedGrant(grantId, secret, task, beforeReturn) {
22375
+ return await this.withGrantLock(grantId, async (lock) => {
22376
+ const state = await this.authenticate(grantId, secret);
22377
+ const result = await task(state);
22378
+ await this.requireMutationLock(lock);
22379
+ const finalState = await this.authenticate(grantId, secret);
22380
+ await this.requireMutationLock(lock);
22381
+ if (finalState.stateVersion !== state.stateVersion) {
22382
+ throw new SupportPassportError("grant_stale", "The shared support guide has changed.", 410);
22383
+ }
22384
+ this.requireActiveState(finalState);
22385
+ await beforeReturn?.(finalState);
22386
+ await this.requireMutationLock(lock);
22387
+ this.requireActiveState(finalState);
22388
+ return result;
22389
+ });
22390
+ }
22391
+ async listForOwner(namespace, principal) {
22392
+ const normalizedNamespace = normalizeNamespace(namespace);
22393
+ const principalHash = computeSupportPassportOwnerKey(normalizePrincipal(principal));
22394
+ const activeCutoff = this.now().getTime();
22395
+ const states = this.listedOwnerStates(
22396
+ await this.readOwnerMembershipStates(normalizedNamespace, principalHash),
22397
+ activeCutoff
22398
+ );
22399
+ return states.sort((a, b) => {
22400
+ const aActive = !a.revokedAt && Date.parse(a.expiresAt) > activeCutoff;
22401
+ const bActive = !b.revokedAt && Date.parse(b.expiresAt) > activeCutoff;
22402
+ if (aActive !== bActive) return aActive ? -1 : 1;
22403
+ return newestGrantFirst(a, b);
22404
+ });
22405
+ }
22406
+ async revoke(input, hooks = {}) {
22407
+ const mutationHooks = typeof hooks === "function" ? { beforeCommit: hooks } : hooks;
22408
+ const normalizedInput = { ...input, grantId: normalizeGrantId(input.grantId) };
22409
+ const namespace = normalizeNamespace(input.namespace);
22410
+ return await this.withGrantLock(normalizedInput.grantId, async (lock) => {
22411
+ let state;
22412
+ try {
22413
+ state = await this.readState(normalizedInput.grantId);
22414
+ } catch (error) {
22415
+ if (error.code === "ENOENT") throw grantNotFound();
22416
+ throw error;
22417
+ }
22418
+ const principalHash = computeSupportPassportOwnerKey(normalizePrincipal(input.principal));
22419
+ if (state.namespace !== namespace || !hashesMatch(state.principalHash, principalHash)) throw grantNotFound();
22420
+ if (state.revokedAt) {
22421
+ return state;
22422
+ }
22423
+ if (normalizedInput.expectedStateVersion !== void 0 && normalizedInput.expectedStateVersion !== state.stateVersion) {
22424
+ throw new SupportPassportError("state_conflict", "The share link changed after it was loaded.", 409);
22425
+ }
22426
+ const revoked = SupportPassportGrantStateSchema.parse({
22427
+ ...state,
22428
+ stateVersion: state.stateVersion + 1,
22429
+ revokedAt: this.now().toISOString()
22430
+ });
22431
+ await this.requireMutationLock(lock);
22432
+ await mutationHooks.beforeCommit?.();
22433
+ await this.requireMutationLock(lock);
22434
+ try {
22435
+ await this.writeState(revoked);
22436
+ } catch (error) {
22437
+ const persisted = await this.readState(revoked.grantId).catch(() => void 0);
22438
+ if (!persisted || !sameGrantState(persisted, revoked)) throw error;
22439
+ await this.syncDirectory(this.grantsDir);
22440
+ }
22441
+ notifySupportPassportCommitted(mutationHooks.onCommitted);
22442
+ return revoked;
22443
+ });
22444
+ }
22445
+ filePath(grantId) {
22446
+ const normalizedGrantId = normalizeGrantId(grantId);
22447
+ return path23.join(this.grantsDir, `${normalizedGrantId}.json`);
22448
+ }
22449
+ ownerIndexPath(ownerHash) {
22450
+ if (!SAFE_OWNER_INDEX_HASH.test(ownerHash)) throw new Error("support passport owner index hash is invalid");
22451
+ return path23.join(this.ownerIndexesDir, `${ownerHash}.json`);
22452
+ }
22453
+ ownerHash(namespace, principalHash) {
22454
+ return sha256("support-passport-owner-index:v1", `${namespace}\0${principalHash}`);
22455
+ }
22456
+ async addToOwnerIndex(state, lock) {
22457
+ const ownerHash = this.ownerHash(state.namespace, state.principalHash);
22458
+ const ownerStates = (await this.readOwnerMembershipStates(state.namespace, state.principalHash)).filter((item) => item.grantId !== state.grantId).sort(newestGrantFirst);
22459
+ const current = ownerStates.map((item) => item.grantId);
22460
+ let retained = current;
22461
+ const indexedStates = [...ownerStates];
22462
+ if (current.length >= MAX_OWNER_GRANT_HISTORY) {
22463
+ const expiryCutoff = this.now().getTime();
22464
+ const active = indexedStates.filter((item) => !item.revokedAt && Date.parse(item.expiresAt) > expiryCutoff);
22465
+ if (active.length >= MAX_OWNER_GRANT_HISTORY) {
22466
+ throw new SupportPassportError(
22467
+ "invalid_input",
22468
+ "A support passport can contain at most 100 active share links.",
22469
+ 400
22470
+ );
22471
+ }
22472
+ const inactive = indexedStates.filter((item) => item.revokedAt || Date.parse(item.expiresAt) <= expiryCutoff).sort(newestGrantFirst);
22473
+ retained = [
22474
+ ...active.map((item) => item.grantId),
22475
+ ...inactive.slice(0, MAX_OWNER_GRANT_HISTORY - active.length - 1).map((item) => item.grantId)
22476
+ ];
22477
+ }
22478
+ const grantIds = [...retained, state.grantId];
22479
+ const retainedIds = new Set(grantIds);
22480
+ const indexedStateById = new Map(indexedStates.map((indexedState) => [indexedState.grantId, indexedState]));
22481
+ const evictedGrantIds = current.filter((grantId) => !retainedIds.has(grantId));
22482
+ await this.writeOwnerIndexWhileLocked(ownerHash, grantIds, lock);
22483
+ try {
22484
+ for (const grantId of evictedGrantIds) {
22485
+ await this.withGrantLock(grantId, async (grantLock) => {
22486
+ await this.requireMutationLock(grantLock);
22487
+ const evictedState = indexedStateById.get(grantId);
22488
+ if (evictedState) await this.removeStoredGrant(evictedState);
22489
+ else await this.removeGrantStates([grantId]);
22490
+ });
22491
+ }
22492
+ } catch (error) {
22493
+ log.warn(
22494
+ `support passport could not remove inactive grant state: ${error instanceof Error ? error.message : String(error)}`
22495
+ );
22496
+ }
22497
+ }
22498
+ async removeGrantStates(grantIds) {
22499
+ if (grantIds.length === 0) return;
22500
+ for (const grantId of grantIds) {
22501
+ if (!SAFE_GRANT_ID.test(grantId)) throw grantNotFound();
22502
+ }
22503
+ await removePrivateFilesNoFollow(
22504
+ this.grantsDir,
22505
+ grantIds.map((grantId) => `${grantId}.json`),
22506
+ "support passport grant files must be regular files in a stable directory",
22507
+ path23.parse(this.memoryDir).root
22508
+ );
22509
+ }
22510
+ ownerMembershipDirectory(ownerHash) {
22511
+ if (!SAFE_OWNER_INDEX_HASH.test(ownerHash)) throw new Error("support passport owner index hash is invalid");
22512
+ return path23.join(this.ownerIndexesDir, ownerHash);
22513
+ }
22514
+ async ensureOwnerMembershipDirectory(ownerHash) {
22515
+ const directory = this.ownerMembershipDirectory(ownerHash);
22516
+ await ensurePrivateDirectoryTreeNoFollow(
22517
+ directory,
22518
+ "support passport owner membership must remain inside the memory directory"
22519
+ );
22520
+ return directory;
22521
+ }
22522
+ async writeOwnerMembership(state) {
22523
+ const ownerHash = this.ownerHash(state.namespace, state.principalHash);
22524
+ const directory = await this.ensureOwnerMembershipDirectory(ownerHash);
22525
+ await writePrivateFileAtomicallyNoFollow(
22526
+ directory,
22527
+ path23.join(directory, `${state.grantId}.json`),
22528
+ `${JSON.stringify({ schemaVersion: 1, grantId: state.grantId })}
22529
+ `,
22530
+ "support passport owner membership must be regular files in a stable directory",
22531
+ path23.parse(this.memoryDir).root
22532
+ );
22533
+ }
22534
+ async removeOwnerMembership(state) {
22535
+ const ownerHash = this.ownerHash(state.namespace, state.principalHash);
22536
+ const directory = await this.ensureOwnerMembershipDirectory(ownerHash);
22537
+ await removePrivateFilesNoFollow(
22538
+ directory,
22539
+ [`${state.grantId}.json`],
22540
+ "support passport owner membership must be regular files in a stable directory",
22541
+ path23.parse(this.memoryDir).root
22542
+ );
22543
+ }
22544
+ async removeStoredGrant(state) {
22545
+ await this.removeGrantStates([state.grantId]);
22546
+ await this.removeOwnerMembership(state);
22547
+ }
22548
+ async writeOwnerIndexWhileLocked(ownerHash, grantIds, lock) {
22549
+ await this.requireOwnerIndexLock(lock);
22550
+ await this.writeOwnerIndex(ownerHash, grantIds);
22551
+ await this.requireOwnerIndexLock(lock);
22552
+ }
22553
+ async reconcileCreateAfterOwnerIndexLockLoss(committed) {
22554
+ const ownerHash = this.ownerHash(committed.state.namespace, committed.state.principalHash);
22555
+ for (let attempt = 1; attempt <= MAX_OWNER_INDEX_RECOVERY_ATTEMPTS; attempt += 1) {
22556
+ try {
22557
+ return await this.withOwnerIndexLock(
22558
+ ownerHash,
22559
+ async (lock) => await this.reconcileCommittedGrant(committed, ownerHash, lock)
22560
+ );
22561
+ } catch (error) {
22562
+ if (!(error instanceof OwnerIndexLockLostError)) throw error;
22563
+ }
22564
+ }
22565
+ throw new SupportPassportError("storage_conflict", "The share link store changed during the request.", 409);
22566
+ }
22567
+ async reconcileCommittedGrant(committed, ownerHash, lock) {
22568
+ const persisted = await this.readState(committed.state.grantId).catch(() => void 0);
22569
+ if (!persisted || !sameGrantState(persisted, committed.state)) {
22570
+ throw new SupportPassportError("storage_conflict", "The share link store changed during the request.", 409);
22571
+ }
22572
+ const ownerStates = await this.readOwnerMembershipStates(committed.state.namespace, committed.state.principalHash);
22573
+ const committedIndex = ownerStates.findIndex((state) => state.grantId === committed.state.grantId);
22574
+ if (committedIndex === -1) ownerStates.push(committed.state);
22575
+ else ownerStates[committedIndex] = committed.state;
22576
+ const activeCutoff = this.now().getTime();
22577
+ const active = ownerStates.filter((state) => !state.revokedAt && Date.parse(state.expiresAt) > activeCutoff);
22578
+ if (active.length > MAX_OWNER_GRANT_HISTORY) {
22579
+ await this.withGrantLock(committed.state.grantId, async (grantLock) => {
22580
+ await this.requireMutationLock(grantLock);
22581
+ await this.removeStoredGrant(committed.state);
22582
+ });
22583
+ const committedIndex2 = ownerStates.findIndex((state) => state.grantId === committed.state.grantId);
22584
+ if (committedIndex2 !== -1) ownerStates.splice(committedIndex2, 1);
22585
+ }
22586
+ const retained = this.retainedOwnerStates(ownerStates, activeCutoff);
22587
+ await this.writeOwnerIndexWhileLocked(
22588
+ ownerHash,
22589
+ retained.map((state) => state.grantId),
22590
+ lock
22591
+ );
22592
+ const retainedIds = new Set(retained.map((state) => state.grantId));
22593
+ for (const state of ownerStates) {
22594
+ if (retainedIds.has(state.grantId)) continue;
22595
+ try {
22596
+ await this.withGrantLock(state.grantId, async (grantLock) => {
22597
+ await this.requireMutationLock(grantLock);
22598
+ await this.removeStoredGrant(state);
22599
+ });
22600
+ } catch (error) {
22601
+ log.warn(
22602
+ `support passport could not remove inactive grant state: ${error instanceof Error ? error.message : String(error)}`
22603
+ );
22604
+ }
22605
+ }
22606
+ if (active.length > MAX_OWNER_GRANT_HISTORY) {
22607
+ throw new SupportPassportError("storage_conflict", "The share link store changed during the request.", 409);
22608
+ }
22609
+ return committed;
22610
+ }
22611
+ retainedOwnerStates(states, activeCutoff) {
22612
+ const active = states.filter((state) => !state.revokedAt && Date.parse(state.expiresAt) > activeCutoff);
22613
+ if (active.length > MAX_OWNER_GRANT_HISTORY) {
22614
+ throw new SupportPassportError("storage_conflict", "The share link store contains too many active links.", 409);
22615
+ }
22616
+ const inactive = states.filter((state) => state.revokedAt || Date.parse(state.expiresAt) <= activeCutoff).sort(newestGrantFirst);
22617
+ return [...active, ...inactive.slice(0, MAX_OWNER_GRANT_HISTORY - active.length)];
22618
+ }
22619
+ listedOwnerStates(states, activeCutoff) {
22620
+ const active = states.filter((state) => !state.revokedAt && Date.parse(state.expiresAt) > activeCutoff);
22621
+ const inactive = states.filter((state) => state.revokedAt || Date.parse(state.expiresAt) <= activeCutoff).sort(newestGrantFirst);
22622
+ return [...active, ...inactive.slice(0, Math.max(0, MAX_OWNER_GRANT_HISTORY - active.length))];
22623
+ }
22624
+ async requireAvailableOwnerGrantSlot(namespace, principalHash) {
22625
+ const activeCutoff = this.now().getTime();
22626
+ const active = (await this.readOwnerMembershipStates(namespace, principalHash)).filter(
22627
+ (state) => !state.revokedAt && Date.parse(state.expiresAt) > activeCutoff
22628
+ );
22629
+ if (active.length >= MAX_OWNER_GRANT_HISTORY) {
22630
+ throw new SupportPassportError(
22631
+ "invalid_input",
22632
+ "A support passport can contain at most 100 active share links.",
22633
+ 400
22634
+ );
22635
+ }
22636
+ }
22637
+ async readOwnerMembershipStates(namespace, principalHash) {
22638
+ await this.ensureSafeDirectories();
22639
+ const ownerHash = this.ownerHash(namespace, principalHash);
22640
+ const directory = await this.ensureOwnerMembershipDirectory(ownerHash);
22641
+ const grantIds = await withPrivateDirectoryNoFollow(
22642
+ path23.parse(this.memoryDir).root,
22643
+ directory,
22644
+ "support passport owner membership must be regular files in a stable directory",
22645
+ async (pinnedDirectory) => {
22646
+ const entries = await readdir4(pinnedDirectory, { withFileTypes: true });
22647
+ return entries.filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -5)).filter((grantId) => SAFE_GRANT_ID.test(grantId));
22648
+ }
22649
+ );
22650
+ const ownerStates = [];
22651
+ for (const grantId of grantIds) {
22652
+ try {
22653
+ const state = await this.readState(grantId);
22654
+ if (state.namespace === namespace && hashesMatch(state.principalHash, principalHash)) {
22655
+ ownerStates.push(state);
22656
+ }
22657
+ } catch (error) {
22658
+ if (error.code === "ENOENT" || error instanceof MalformedGrantStateError) continue;
22659
+ throw error;
22660
+ }
22661
+ }
22662
+ return ownerStates;
22663
+ }
22664
+ async readOwnerIndexByHash(ownerHash) {
22665
+ await this.ensureSafeDirectories();
22666
+ const filePath = this.ownerIndexPath(ownerHash);
22667
+ let content;
22668
+ try {
22669
+ content = await readPrivateFileNoFollow(
22670
+ this.ownerIndexesDir,
22671
+ filePath,
22672
+ "support passport owner indexes must be regular files in a stable directory",
22673
+ path23.parse(this.memoryDir).root
22674
+ );
22675
+ } catch (error) {
22676
+ if (error.code === "ENOENT") return [];
22677
+ throw error;
22678
+ }
22679
+ const parsed = JSON.parse(content);
22680
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
22681
+ throw new Error("support passport owner index is invalid");
22682
+ }
22683
+ const record = parsed;
22684
+ const grantIds = record.grantIds;
22685
+ if (record.schemaVersion !== 1 || record.ownerHash !== ownerHash || !Array.isArray(grantIds)) {
22686
+ throw new Error("support passport owner index is invalid");
22687
+ }
22688
+ if (grantIds.some((grantId) => typeof grantId !== "string" || !SAFE_GRANT_ID.test(grantId))) {
22689
+ throw new Error("support passport owner index is invalid");
22690
+ }
22691
+ const uniqueGrantIds = new Set(grantIds);
22692
+ if (uniqueGrantIds.size !== grantIds.length || uniqueGrantIds.size > MAX_OWNER_GRANT_HISTORY) {
22693
+ throw new Error("support passport owner index is invalid");
22694
+ }
22695
+ return [...uniqueGrantIds];
22696
+ }
22697
+ async writeOwnerIndex(ownerHash, grantIds) {
22698
+ const filePath = this.ownerIndexPath(ownerHash);
22699
+ try {
22700
+ const metadata = await lstat4(filePath);
22701
+ if (metadata.isSymbolicLink() || !metadata.isFile()) {
22702
+ throw new Error("support passport owner indexes must be regular files");
22703
+ }
22704
+ } catch (error) {
22705
+ if (error.code !== "ENOENT") throw error;
22706
+ }
22707
+ await writePrivateFileAtomicallyNoFollow(
22708
+ this.ownerIndexesDir,
22709
+ filePath,
22710
+ `${JSON.stringify({ schemaVersion: 1, ownerHash, grantIds }, null, 2)}
22711
+ `,
22712
+ "support passport owner indexes must be regular files in a stable directory",
22713
+ path23.parse(this.memoryDir).root
22714
+ );
22715
+ }
22716
+ async readState(grantId) {
22717
+ await this.ensureSafeDirectories();
22718
+ const filePath = this.filePath(grantId);
22719
+ const content = await readPrivateFileNoFollow(
22720
+ this.grantsDir,
22721
+ filePath,
22722
+ "support passport grant files must be regular files in a stable directory",
22723
+ path23.parse(this.memoryDir).root
22724
+ );
22725
+ try {
22726
+ const state = SupportPassportGrantStateSchema.parse(JSON.parse(content));
22727
+ if (state.grantId !== grantId) {
22728
+ throw new MalformedGrantStateError("support passport grant ID must match its file name");
22729
+ }
22730
+ return state;
22731
+ } catch (error) {
22732
+ if (error instanceof MalformedGrantStateError) throw error;
22733
+ if (error instanceof SyntaxError || error.name === "ZodError") {
22734
+ throw new MalformedGrantStateError(void 0, error);
22735
+ }
22736
+ throw error;
22737
+ }
22738
+ }
22739
+ async writeState(state, requireAbsent = false) {
22740
+ const filePath = this.filePath(state.grantId);
22741
+ try {
22742
+ const metadata = await lstat4(filePath);
22743
+ if (metadata.isSymbolicLink() || !metadata.isFile())
22744
+ throw new Error("support passport grant files must be regular files");
22745
+ if (requireAbsent) {
22746
+ throw new SupportPassportError("storage_conflict", "A new share link could not be allocated.", 409);
22747
+ }
22748
+ } catch (error) {
22749
+ if (error.code !== "ENOENT") throw error;
22750
+ }
22751
+ await writePrivateFileAtomicallyNoFollow(
22752
+ this.grantsDir,
22753
+ filePath,
22754
+ `${JSON.stringify(state, null, 2)}
22755
+ `,
22756
+ "support passport grant files must be regular files in a stable directory",
22757
+ path23.parse(this.memoryDir).root
22758
+ );
22759
+ }
22760
+ async ensureSafeDirectories() {
22761
+ if (!this.safeDirectoriesReady) {
22762
+ this.safeDirectoriesReady = (async () => {
22763
+ await this.ensureMemoryRoot();
22764
+ await ensurePrivateDirectoryNoFollow(
22765
+ this.memoryDir,
22766
+ this.ownerIndexesDir,
22767
+ "support passport grant directories must remain inside the memory directory",
22768
+ void 0,
22769
+ true
22770
+ );
22771
+ })();
22772
+ }
22773
+ const currentAttempt = this.safeDirectoriesReady;
22774
+ try {
22775
+ await currentAttempt;
22776
+ } catch (error) {
22777
+ if (this.safeDirectoriesReady === currentAttempt) this.safeDirectoriesReady = void 0;
22778
+ throw error;
22779
+ }
22780
+ }
22781
+ async ensureMemoryRoot() {
22782
+ const configuredMemoryDir = this.memoryDir;
22783
+ if (!this.memoryRootReady) {
22784
+ this.memoryRootReady = (async () => {
22785
+ await ensurePrivateDirectoryTreeNoFollow(
22786
+ configuredMemoryDir,
22787
+ "support passport memory directory must be a stable directory",
22788
+ void 0
22789
+ );
22790
+ this.memoryDir = configuredMemoryDir;
22791
+ this.grantsDir = path23.join(configuredMemoryDir, "state", "support-passport", "grants");
22792
+ this.ownerIndexesDir = path23.join(this.grantsDir, "owners");
22793
+ })();
22794
+ }
22795
+ const currentAttempt = this.memoryRootReady;
22796
+ try {
22797
+ await currentAttempt;
22798
+ } catch (error) {
22799
+ if (this.memoryRootReady === currentAttempt) this.memoryRootReady = void 0;
22800
+ throw error;
22801
+ }
22802
+ }
22803
+ async withMutationLock(task) {
22804
+ await this.ensureSafeDirectories();
22805
+ return await withPrivateDirectoryNoFollow(
22806
+ path23.parse(this.memoryDir).root,
22807
+ this.grantsDir,
22808
+ "support passport grant lock directory must remain inside the memory directory",
22809
+ async (pinnedDirectory) => await this.withExclusiveLock(
22810
+ `support-passport-grants:${this.grantsDir}`,
22811
+ path23.join(pinnedDirectory, ".grants.lock"),
22812
+ task
22813
+ )
22814
+ );
22815
+ }
22816
+ async withGrantLock(grantId, task) {
22817
+ const normalizedGrantId = normalizeGrantId(grantId);
22818
+ await this.ensureSafeDirectories();
22819
+ return await withPrivateDirectoryNoFollow(
22820
+ path23.parse(this.memoryDir).root,
22821
+ this.grantsDir,
22822
+ "support passport grant lock directory must remain inside the memory directory",
22823
+ async (pinnedDirectory) => await this.withExclusiveLock(
22824
+ `support-passport-grant:${this.grantsDir}:${normalizedGrantId}`,
22825
+ path23.join(pinnedDirectory, `.${normalizedGrantId}.lock`),
22826
+ task
22827
+ )
22828
+ );
22829
+ }
22830
+ async withOwnerIndexLock(ownerHash, task) {
22831
+ await this.ensureSafeDirectories();
22832
+ return await withPrivateDirectoryNoFollow(
22833
+ path23.parse(this.memoryDir).root,
22834
+ this.ownerIndexesDir,
22835
+ "support passport owner lock directory must remain inside the memory directory",
22836
+ async (pinnedDirectory) => await this.withExclusiveLock(
22837
+ `support-passport-owner:${this.ownerIndexesDir}:${ownerHash}`,
22838
+ path23.join(pinnedDirectory, `.${ownerHash}.lock`),
22839
+ task
22840
+ )
22841
+ );
22842
+ }
22843
+ async withExclusiveLock(serializationKey, lockPath, task) {
22844
+ return await serializeMutations(
22845
+ serializationKey,
22846
+ () => this.runWithHeldFileLock(
22847
+ lockPath,
22848
+ {
22849
+ staleMs: GRANT_LOCK_STALE_MS,
22850
+ maxWaitMs: GRANT_LOCK_WAIT_MS,
22851
+ heartbeatMs: GRANT_LOCK_HEARTBEAT_MS
22852
+ },
22853
+ async (acquired, lock) => {
22854
+ if (!acquired) {
22855
+ throw new SupportPassportError("storage_conflict", "The share link store is busy. Try again.", 409);
22856
+ }
22857
+ return await task(lock);
22858
+ }
22859
+ )
22860
+ );
22861
+ }
22862
+ async requireMutationLock(lock) {
22863
+ if (await lock.refresh()) return;
22864
+ throw new SupportPassportError("storage_conflict", "The share link store changed during the request.", 409);
22865
+ }
22866
+ async requireOwnerIndexLock(lock) {
22867
+ try {
22868
+ await this.requireMutationLock(lock);
22869
+ } catch (error) {
22870
+ throw new OwnerIndexLockLostError(error);
22871
+ }
22872
+ }
22873
+ requireActiveState(state) {
22874
+ if (state.revokedAt) {
22875
+ throw new SupportPassportError("grant_gone", "The share link is no longer active.", 410);
22876
+ }
22877
+ if (Date.parse(state.expiresAt) <= this.now().getTime()) {
22878
+ throw new SupportPassportError("grant_expired", "The share link has expired.", 410);
22879
+ }
22880
+ }
22881
+ };
22882
+
22883
+ // src/support-passport/grant-service.ts
22884
+ function invalidInput2() {
22885
+ return new SupportPassportError("invalid_input", "The share link request is invalid.", 400);
22886
+ }
22887
+ var SupportPassportGrantService = class {
22888
+ grantStore;
22889
+ resolveOwner;
22890
+ resolveNamespace;
22891
+ now;
22892
+ constructor(dependencies) {
22893
+ this.grantStore = dependencies.grantStore;
22894
+ this.resolveOwner = dependencies.resolveOwner;
22895
+ this.resolveNamespace = dependencies.resolveNamespace;
22896
+ this.now = dependencies.now ?? (() => /* @__PURE__ */ new Date());
22897
+ }
22898
+ async createGrant(input, options = {}) {
22899
+ const requestedAt = this.now();
22900
+ const parsed = SupportPassportCreateGrantInputSchema.safeParse(input);
22901
+ if (!parsed.success) throw invalidInput2();
22902
+ const owner = await this.resolveOwnerScope(parsed.data.principal);
22903
+ return await withSupportPassportOwnerLock(
22904
+ owner.storage,
22905
+ { namespace: owner.namespace, principal: owner.principal },
22906
+ async (ownerLock) => {
22907
+ options.signal?.throwIfAborted();
22908
+ const ownerHash = computeSupportPassportOwnerKey(owner.principal);
22909
+ const cardsById = new Map(
22910
+ this.projectOwnedCards(
22911
+ await owner.storage.readAllMemories(),
22912
+ owner.namespace,
22913
+ ownerHash
22914
+ ).map((card) => [card.card.cardId, card])
22915
+ );
22916
+ for (const cardRef of parsed.data.cards) {
22917
+ const stored = cardsById.get(cardRef.cardId);
22918
+ if (!stored || stored.namespace !== owner.namespace || stored.owner !== ownerHash || stored.card.status !== "active") {
22919
+ throw new SupportPassportError("invalid_card_status", "Only approved support cards can be shared.", 409);
22920
+ }
22921
+ if (stored.card.revision !== cardRef.revision) {
22922
+ throw new SupportPassportError("revision_conflict", "A support card changed after it was selected.", 409);
22923
+ }
22924
+ if (!this.publicCard(stored.card).success) {
22925
+ throw new SupportPassportError("card_data_invalid", "The support card data is invalid.", 500);
22926
+ }
22927
+ }
22928
+ const created = await this.grantStore.create(
22929
+ {
22930
+ namespace: owner.namespace,
22931
+ principal: owner.principal,
22932
+ cards: parsed.data.cards,
22933
+ expiresAt: parsed.data.expiresAt,
22934
+ requestedAt
22935
+ },
22936
+ {
22937
+ beforeCommit: async () => {
22938
+ options.signal?.throwIfAborted();
22939
+ await requireSupportPassportOwnerLock(ownerLock);
22940
+ }
22941
+ }
22942
+ );
22943
+ try {
22944
+ await requireSupportPassportOwnerLock(ownerLock);
22945
+ } catch (error) {
22946
+ await this.revokeCommittedGrant(created, owner);
22947
+ throw error;
22948
+ }
22949
+ if (options.signal?.aborted) {
22950
+ await this.revokeCommittedGrant(created, owner);
22951
+ options.signal.throwIfAborted();
22952
+ }
22953
+ const output = SupportPassportCreatedGrantSchema.parse({
22954
+ grant: this.ownerGrant(created.state),
22955
+ secret: created.secret
22956
+ });
22957
+ notifySupportPassportCommitted(options.onCommitted);
22958
+ return output;
22959
+ }
22960
+ );
22961
+ }
22962
+ async listGrants(input) {
22963
+ const parsed = SupportPassportListGrantsInputSchema.safeParse(input);
22964
+ if (!parsed.success) throw invalidInput2();
22965
+ const owner = await this.resolveOwnerScope(parsed.data.principal);
22966
+ return (await this.grantStore.listForOwner(owner.namespace, owner.principal)).map(
22967
+ (state) => this.ownerGrant(state)
22968
+ );
22969
+ }
22970
+ async revokeGrant(input, options = {}) {
22971
+ const parsed = SupportPassportRevokeGrantInputSchema.safeParse(input);
22972
+ if (!parsed.success) throw invalidInput2();
22973
+ const owner = await this.resolveOwnerScope(parsed.data.principal);
22974
+ return await withSupportPassportOwnerLock(
22975
+ owner.storage,
22976
+ { namespace: owner.namespace, principal: owner.principal },
22977
+ async (ownerLock) => {
22978
+ options.signal?.throwIfAborted();
22979
+ const state = await this.grantStore.revoke(
22980
+ {
22981
+ grantId: parsed.data.grantId,
22982
+ namespace: owner.namespace,
22983
+ principal: owner.principal,
22984
+ expectedStateVersion: parsed.data.expectedStateVersion
22985
+ },
22986
+ {
22987
+ beforeCommit: async () => {
22988
+ options.signal?.throwIfAborted();
22989
+ await requireSupportPassportOwnerLock(ownerLock);
22990
+ }
22991
+ }
22992
+ );
22993
+ const output = this.ownerGrant(state);
22994
+ notifySupportPassportCommitted(options.onCommitted);
22995
+ return output;
22996
+ }
22997
+ );
22998
+ }
22999
+ async readGrant(input) {
23000
+ if (!input || typeof input.grantId !== "string" || typeof input.secret !== "string") {
23001
+ throw new SupportPassportError("grant_not_found", "The share link was not found.", 404);
23002
+ }
23003
+ return await this.readGrantAttempt(input);
23004
+ }
23005
+ async readGrantAttempt(input) {
23006
+ const initialState = await this.grantStore.authenticate(input.grantId, input.secret);
23007
+ const storage = await this.resolveNamespace(initialState.namespace);
23008
+ const initialSnapshot = await this.readStoredCardSnapshot(
23009
+ storage,
23010
+ initialState.namespace,
23011
+ initialState.principalHash
23012
+ );
23013
+ const cards = this.readGrantCards(initialSnapshot, initialState);
23014
+ const firstCard = cards[0];
23015
+ if (!firstCard) throw new SupportPassportError("grant_stale", "The shared support guide has changed.", 410);
23016
+ const updatedAt = cards.reduce((latest, card) => {
23017
+ return Date.parse(card.updatedAt) > Date.parse(latest) ? card.updatedAt : latest;
23018
+ }, firstCard.updatedAt);
23019
+ return await withSupportPassportOwnerLock(
23020
+ storage,
23021
+ { namespace: initialState.namespace, ownerKey: initialState.ownerLockKey },
23022
+ async (ownerLock) => {
23023
+ return await this.grantStore.withAuthenticatedGrant(
23024
+ input.grantId,
23025
+ input.secret,
23026
+ async (finalState) => {
23027
+ if (finalState.namespace !== initialState.namespace) {
23028
+ throw new SupportPassportError("grant_stale", "The shared support guide has changed.", 410);
23029
+ }
23030
+ await requireSupportPassportOwnerLock(ownerLock);
23031
+ const currentSnapshot = await this.readStoredCardSnapshot(
23032
+ storage,
23033
+ finalState.namespace,
23034
+ finalState.principalHash
23035
+ );
23036
+ const currentCards = this.readGrantCards(currentSnapshot, finalState);
23037
+ await requireSupportPassportOwnerLock(ownerLock);
23038
+ if (JSON.stringify(currentCards) !== JSON.stringify(cards)) {
23039
+ throw new SupportPassportError("grant_stale", "The shared support guide has changed.", 410);
23040
+ }
23041
+ return SupportPassportPublicGuideSchema.parse({
23042
+ schemaVersion: 1,
23043
+ grantId: finalState.grantId,
23044
+ expiresAt: finalState.expiresAt,
23045
+ updatedAt,
23046
+ cards
23047
+ });
23048
+ },
23049
+ async () => await requireSupportPassportOwnerLock(ownerLock)
23050
+ );
23051
+ }
23052
+ );
23053
+ }
23054
+ readGrantCards(snapshot, state) {
23055
+ return state.cards.map((cardRef) => {
23056
+ const stored = snapshot.cardsById.get(cardRef.cardId);
23057
+ if (!stored || stored.namespace !== state.namespace || stored.owner !== state.principalHash || stored.card.status !== "active" || stored.card.revision !== cardRef.revision) {
23058
+ throw new SupportPassportError("grant_stale", "The shared support guide has changed.", 410);
23059
+ }
23060
+ const publicCard = this.publicCard(stored.card);
23061
+ if (!publicCard.success) {
23062
+ throw new SupportPassportError("grant_stale", "The shared support guide has changed.", 410);
23063
+ }
23064
+ return publicCard.data;
23065
+ });
23066
+ }
23067
+ async readStoredCardSnapshot(storage, namespace, owner) {
23068
+ for (let attempt = 0; attempt < 3; attempt += 1) {
23069
+ const before = this.cardSnapshotVersion(storage);
23070
+ const memories = await storage.readAllMemories();
23071
+ const after = this.cardSnapshotVersion(storage);
23072
+ if (before !== after) continue;
23073
+ const cards = this.projectOwnedCards(memories, namespace, owner);
23074
+ const snapshot = {
23075
+ version: after,
23076
+ cardsById: new Map(cards.map((card) => [card.card.cardId, card]))
23077
+ };
23078
+ return snapshot;
23079
+ }
23080
+ throw new SupportPassportError("storage_conflict", "The support card list changed during review.", 409);
23081
+ }
23082
+ projectOwnedCards(memories, namespace, owner) {
23083
+ const cards = memories.map((memory) => projectSupportPassportCard(memory)).filter(
23084
+ (card) => card !== null && card.namespace === namespace && card.owner === owner
23085
+ );
23086
+ const cardIds = /* @__PURE__ */ new Set();
23087
+ for (const card of cards) {
23088
+ if (cardIds.has(card.card.cardId)) {
23089
+ throw new SupportPassportError("card_data_invalid", "Support card IDs must be unique.", 500);
23090
+ }
23091
+ cardIds.add(card.card.cardId);
23092
+ }
23093
+ return cards;
23094
+ }
23095
+ cardSnapshotVersion(storage) {
23096
+ return `${storage.getCorpusScanVersion()}:${storage.hotCacheKeyId()}`;
23097
+ }
23098
+ async revokeCommittedGrant(created, owner) {
23099
+ try {
23100
+ await this.grantStore.revoke({
23101
+ grantId: created.state.grantId,
23102
+ namespace: owner.namespace,
23103
+ principal: owner.principal,
23104
+ expectedStateVersion: created.state.stateVersion
23105
+ });
23106
+ } catch {
23107
+ throw new SupportPassportError(
23108
+ "storage_conflict",
23109
+ "A share link could not be stopped after owner access changed. Review the active share list.",
23110
+ 500
23111
+ );
23112
+ }
23113
+ }
23114
+ publicCard(card) {
23115
+ return SupportPassportPublicCardSchema.safeParse({
23116
+ cardId: card.cardId,
23117
+ title: card.title,
23118
+ statement: card.statement,
23119
+ category: card.category,
23120
+ updatedAt: card.updatedAt
23121
+ });
23122
+ }
23123
+ async resolveOwnerScope(principal) {
23124
+ const requestedPrincipal = SupportPassportListCardsInputSchema.safeParse({ principal });
23125
+ const owner = await this.resolveOwner(principal);
23126
+ const namespace = SupportPassportNamespaceSchema.safeParse(owner.namespace);
23127
+ const ownerPrincipal = SupportPassportListCardsInputSchema.safeParse({ principal: owner.principal });
23128
+ if (!requestedPrincipal.success || !namespace.success || !ownerPrincipal.success || ownerPrincipal.data.principal !== requestedPrincipal.data.principal) {
23129
+ throw new SupportPassportError("card_data_invalid", "The support passport owner scope is invalid.", 500);
23130
+ }
23131
+ return { ...owner, principal: ownerPrincipal.data.principal, namespace: namespace.data };
23132
+ }
23133
+ ownerGrant(state) {
23134
+ const status = state.revokedAt ? "revoked" : Date.parse(state.expiresAt) <= this.now().getTime() ? "expired" : "active";
23135
+ return SupportPassportOwnerGrantSchema.parse({
23136
+ grantId: state.grantId,
23137
+ stateVersion: state.stateVersion,
23138
+ cards: state.cards,
23139
+ createdAt: state.createdAt,
23140
+ expiresAt: state.expiresAt,
23141
+ revokedAt: state.revokedAt,
23142
+ status
23143
+ });
23144
+ }
23145
+ };
23146
+
23147
+ // src/relay/mission-fixture.ts
23148
+ var RELAY_DEMO_MISSION_ID = "checkout-token-recovery";
23149
+ var RELAY_DEMO_NAMESPACE = "relay-build-week";
23150
+ var sourceEvidence = {
23151
+ kind: "source",
23152
+ id: "source-checkout-contract",
23153
+ label: "Checkout token contract",
23154
+ locator: "fixture://checkout-service/src/token-policy.ts",
23155
+ capture: "fixture"
23156
+ };
23157
+ var testEvidence = {
23158
+ kind: "test",
23159
+ id: "test-checkout-contract",
23160
+ label: "Checkout integration contract",
23161
+ locator: "fixture://checkout-service/test/token-policy.test.ts",
23162
+ capture: "fixture"
23163
+ };
23164
+ var approvalEvidence = {
23165
+ kind: "approval",
23166
+ id: "approval-build-week-operator",
23167
+ label: "Human approval receipt",
23168
+ locator: "fixture://relay/approvals/correction-token-refresh.json",
23169
+ capture: "fixture"
23170
+ };
23171
+ var correctionEvidence = {
23172
+ kind: "correction",
23173
+ id: "correction-token-refresh",
23174
+ label: "Applied Remnic correction",
23175
+ locator: "fixture://remnic/corrections/correction-token-refresh.json",
23176
+ capture: "fixture"
23177
+ };
23178
+ function at(second) {
23179
+ return `2026-07-17T18:00:${String(second).padStart(2, "0")}.000Z`;
23180
+ }
23181
+ function createRelayMissionFixture() {
23182
+ return [
23183
+ {
23184
+ occurredAt: at(0),
23185
+ idempotencyKey: "fixture-001",
23186
+ payload: {
23187
+ kind: "mission_started",
23188
+ title: "The checkout token split",
23189
+ objective: "Resolve a conflicting token refresh policy and prove a cold agent acts on it.",
23190
+ runMode: "fixture",
23191
+ evidence: [sourceEvidence]
23192
+ }
23193
+ },
23194
+ {
23195
+ occurredAt: at(2),
23196
+ idempotencyKey: "fixture-002",
23197
+ payload: {
23198
+ kind: "agent_status",
23199
+ agentId: "agent-atlas",
23200
+ sessionId: "session-atlas",
23201
+ label: "Atlas",
23202
+ role: "Checkout implementation",
23203
+ status: "working",
23204
+ evidence: [sourceEvidence]
23205
+ }
23206
+ },
23207
+ {
23208
+ occurredAt: at(3),
23209
+ idempotencyKey: "fixture-003",
23210
+ payload: {
23211
+ kind: "agent_status",
23212
+ agentId: "agent-nova",
23213
+ sessionId: "session-nova",
23214
+ label: "Nova",
23215
+ role: "Integration verification",
23216
+ status: "working",
23217
+ evidence: [testEvidence]
23218
+ }
23219
+ },
23220
+ {
23221
+ occurredAt: at(6),
23222
+ idempotencyKey: "fixture-004",
23223
+ payload: {
23224
+ kind: "agent_output",
23225
+ agentId: "agent-atlas",
23226
+ sessionId: "session-atlas",
23227
+ outputId: "output-atlas-policy",
23228
+ summary: "Implemented a new token for every checkout retry.",
23229
+ evidence: [
23230
+ {
23231
+ kind: "agent_output",
23232
+ id: "output-atlas-policy",
23233
+ label: "Atlas one-shot output",
23234
+ locator: "fixture://codex/atlas/final-output.txt",
23235
+ capture: "fixture"
23236
+ }
23237
+ ]
23238
+ }
23239
+ },
23240
+ {
23241
+ occurredAt: at(7),
23242
+ idempotencyKey: "fixture-005",
23243
+ payload: {
23244
+ kind: "belief_observed",
23245
+ agentId: "agent-atlas",
23246
+ sessionId: "session-atlas",
23247
+ beliefId: "belief-new-token-every-request",
23248
+ decisionId: "decision-new-token-every-request",
23249
+ statement: "Mint a new checkout token for every request and retry.",
23250
+ confidence: 0.91,
23251
+ evidence: [
23252
+ {
23253
+ kind: "memory",
23254
+ id: "memory-stale-token-policy",
23255
+ label: "Stale project decision",
23256
+ locator: "fixture://remnic/memories/memory-stale-token-policy.md",
23257
+ capture: "fixture"
23258
+ }
23259
+ ]
23260
+ }
23261
+ },
23262
+ {
23263
+ occurredAt: at(9),
23264
+ idempotencyKey: "fixture-006",
23265
+ payload: {
23266
+ kind: "agent_output",
23267
+ agentId: "agent-nova",
21091
23268
  sessionId: "session-nova",
21092
23269
  outputId: "output-nova-policy",
21093
23270
  summary: "The contract requires one token per checkout session, refreshed only after expiry.",
@@ -21712,9 +23889,9 @@ function readStructuralSymbol(entry) {
21712
23889
  const rec = entry;
21713
23890
  const symbol = typeof rec.symbol === "string" ? rec.symbol.trim() : "";
21714
23891
  if (!symbol) return null;
21715
- const path35 = typeof rec.path === "string" && rec.path.length > 0 ? rec.path : void 0;
23892
+ const path38 = typeof rec.path === "string" && rec.path.length > 0 ? rec.path : void 0;
21716
23893
  const kind = typeof rec.kind === "string" && rec.kind.length > 0 ? rec.kind : void 0;
21717
- const item = path35 !== void 0 && kind !== void 0 ? { symbol, path: path35, kind } : path35 !== void 0 ? { symbol, path: path35 } : kind !== void 0 ? { symbol, kind } : { symbol };
23894
+ const item = path38 !== void 0 && kind !== void 0 ? { symbol, path: path38, kind } : path38 !== void 0 ? { symbol, path: path38 } : kind !== void 0 ? { symbol, kind } : { symbol };
21718
23895
  return item;
21719
23896
  }
21720
23897
  function classifySpawnError(err) {
@@ -21788,7 +23965,7 @@ var DEFAULT_GRACE_PERIOD_DAYS = 7;
21788
23965
 
21789
23966
  // src/binary-lifecycle/backend.ts
21790
23967
  import fsp from "fs/promises";
21791
- import path21 from "path";
23968
+ import path24 from "path";
21792
23969
  var FilesystemBackend = class {
21793
23970
  type = "filesystem";
21794
23971
  basePath;
@@ -21796,27 +23973,27 @@ var FilesystemBackend = class {
21796
23973
  if (!basePath || basePath.trim().length === 0) {
21797
23974
  throw new Error("FilesystemBackend requires a non-empty basePath");
21798
23975
  }
21799
- this.basePath = path21.resolve(basePath);
23976
+ this.basePath = path24.resolve(basePath);
21800
23977
  }
21801
23978
  resolveRemotePath(remotePath) {
21802
- const resolved = path21.isAbsolute(remotePath) ? path21.resolve(remotePath) : path21.resolve(this.basePath, remotePath);
21803
- const relative = path21.relative(this.basePath, resolved);
21804
- if (relative === ".." || relative.startsWith(`..${path21.sep}`) || path21.isAbsolute(relative)) {
23979
+ const resolved = path24.isAbsolute(remotePath) ? path24.resolve(remotePath) : path24.resolve(this.basePath, remotePath);
23980
+ const relative = path24.relative(this.basePath, resolved);
23981
+ if (relative === ".." || relative.startsWith(`..${path24.sep}`) || path24.isAbsolute(relative)) {
21805
23982
  throw new Error(`FilesystemBackend remotePath escapes basePath: ${JSON.stringify(remotePath)}`);
21806
23983
  }
21807
23984
  return resolved;
21808
23985
  }
21809
23986
  isInsideBase(candidate, realBase) {
21810
- const relative = path21.relative(realBase, candidate);
21811
- return relative === "" || relative !== ".." && !relative.startsWith(`..${path21.sep}`) && !path21.isAbsolute(relative);
23987
+ const relative = path24.relative(realBase, candidate);
23988
+ return relative === "" || relative !== ".." && !relative.startsWith(`..${path24.sep}`) && !path24.isAbsolute(relative);
21812
23989
  }
21813
23990
  async realBasePathIfExists() {
21814
23991
  try {
21815
- const stat5 = await fsp.lstat(this.basePath);
21816
- if (stat5.isSymbolicLink()) {
23992
+ const stat6 = await fsp.lstat(this.basePath);
23993
+ if (stat6.isSymbolicLink()) {
21817
23994
  throw new Error(`FilesystemBackend basePath must not be a symlink: ${this.basePath}`);
21818
23995
  }
21819
- if (!stat5.isDirectory()) {
23996
+ if (!stat6.isDirectory()) {
21820
23997
  throw new Error(`FilesystemBackend basePath must be a directory: ${this.basePath}`);
21821
23998
  }
21822
23999
  return await fsp.realpath(this.basePath);
@@ -21837,19 +24014,19 @@ var FilesystemBackend = class {
21837
24014
  }
21838
24015
  async ensureSafeParentDirectory(dest) {
21839
24016
  const realBase = await this.ensureBaseDirectory();
21840
- const destDir = path21.dirname(dest);
21841
- const relativeDir = path21.relative(this.basePath, destDir);
21842
- const segments = relativeDir === "" ? [] : relativeDir.split(path21.sep);
24017
+ const destDir = path24.dirname(dest);
24018
+ const relativeDir = path24.relative(this.basePath, destDir);
24019
+ const segments = relativeDir === "" ? [] : relativeDir.split(path24.sep);
21843
24020
  let current = this.basePath;
21844
24021
  for (const segment of segments) {
21845
24022
  if (segment === "." || segment === "") continue;
21846
- current = path21.join(current, segment);
24023
+ current = path24.join(current, segment);
21847
24024
  try {
21848
- const stat5 = await fsp.lstat(current);
21849
- if (stat5.isSymbolicLink()) {
24025
+ const stat6 = await fsp.lstat(current);
24026
+ if (stat6.isSymbolicLink()) {
21850
24027
  throw new Error(`FilesystemBackend remotePath traverses symlink: ${current}`);
21851
24028
  }
21852
- if (!stat5.isDirectory()) {
24029
+ if (!stat6.isDirectory()) {
21853
24030
  throw new Error(`FilesystemBackend remotePath parent is not a directory: ${current}`);
21854
24031
  }
21855
24032
  } catch (err) {
@@ -21871,26 +24048,26 @@ var FilesystemBackend = class {
21871
24048
  if (realBase === null) {
21872
24049
  return null;
21873
24050
  }
21874
- const destDir = path21.dirname(dest);
21875
- const relativeDir = path21.relative(this.basePath, destDir);
21876
- const segments = relativeDir === "" ? [] : relativeDir.split(path21.sep);
24051
+ const destDir = path24.dirname(dest);
24052
+ const relativeDir = path24.relative(this.basePath, destDir);
24053
+ const segments = relativeDir === "" ? [] : relativeDir.split(path24.sep);
21877
24054
  let current = this.basePath;
21878
24055
  for (const segment of segments) {
21879
24056
  if (segment === "." || segment === "") continue;
21880
- current = path21.join(current, segment);
21881
- let stat5;
24057
+ current = path24.join(current, segment);
24058
+ let stat6;
21882
24059
  try {
21883
- stat5 = await fsp.lstat(current);
24060
+ stat6 = await fsp.lstat(current);
21884
24061
  } catch (err) {
21885
24062
  if (err.code === "ENOENT") {
21886
24063
  return null;
21887
24064
  }
21888
24065
  throw err;
21889
24066
  }
21890
- if (stat5.isSymbolicLink()) {
24067
+ if (stat6.isSymbolicLink()) {
21891
24068
  throw new Error(`FilesystemBackend remotePath traverses symlink: ${current}`);
21892
24069
  }
21893
- if (!stat5.isDirectory()) {
24070
+ if (!stat6.isDirectory()) {
21894
24071
  return null;
21895
24072
  }
21896
24073
  }
@@ -21905,11 +24082,11 @@ var FilesystemBackend = class {
21905
24082
  throw new Error(`FilesystemBackend remotePath parent escapes basePath: ${JSON.stringify(remotePath)}`);
21906
24083
  }
21907
24084
  try {
21908
- const stat5 = await fsp.lstat(dest);
21909
- if (stat5.isSymbolicLink()) {
24085
+ const stat6 = await fsp.lstat(dest);
24086
+ if (stat6.isSymbolicLink()) {
21910
24087
  throw new Error(`FilesystemBackend remotePath points to symlink: ${dest}`);
21911
24088
  }
21912
- if (!stat5.isFile()) {
24089
+ if (!stat6.isFile()) {
21913
24090
  return null;
21914
24091
  }
21915
24092
  } catch (err) {
@@ -21925,14 +24102,14 @@ var FilesystemBackend = class {
21925
24102
  return dest;
21926
24103
  }
21927
24104
  async upload(localPath, remotePath) {
21928
- if (path21.isAbsolute(remotePath)) {
24105
+ if (path24.isAbsolute(remotePath)) {
21929
24106
  throw new Error(`FilesystemBackend upload remotePath must be relative: ${JSON.stringify(remotePath)}`);
21930
24107
  }
21931
24108
  const dest = this.resolveRemotePath(remotePath);
21932
24109
  const realBase = await this.ensureSafeParentDirectory(dest);
21933
24110
  try {
21934
- const stat5 = await fsp.lstat(dest);
21935
- if (stat5.isSymbolicLink()) {
24111
+ const stat6 = await fsp.lstat(dest);
24112
+ if (stat6.isSymbolicLink()) {
21936
24113
  throw new Error(`FilesystemBackend remotePath points to symlink: ${dest}`);
21937
24114
  }
21938
24115
  } catch (err) {
@@ -21998,7 +24175,7 @@ function createBackend(cfg) {
21998
24175
 
21999
24176
  // src/binary-lifecycle/scanner.ts
22000
24177
  import fsp2 from "fs/promises";
22001
- import path22 from "path";
24178
+ import path25 from "path";
22002
24179
  import crypto from "crypto";
22003
24180
  function matchesPatterns(filename, patterns) {
22004
24181
  const lower = filename.toLowerCase();
@@ -22023,8 +24200,8 @@ async function scanForBinaries(memoryDir, config, manifest) {
22023
24200
  return;
22024
24201
  }
22025
24202
  for (const entry of entries) {
22026
- const fullPath = path22.join(dir, entry.name);
22027
- const relativePath = path22.relative(memoryDir, fullPath).split(path22.sep).join("/");
24203
+ const fullPath = path25.join(dir, entry.name);
24204
+ const relativePath = path25.relative(memoryDir, fullPath).split(path25.sep).join("/");
22028
24205
  if (entry.isDirectory()) {
22029
24206
  if (entry.name === ".binary-lifecycle") continue;
22030
24207
  await walk(fullPath);
@@ -22033,12 +24210,12 @@ async function scanForBinaries(memoryDir, config, manifest) {
22033
24210
  if (!entry.isFile()) continue;
22034
24211
  if (!matchesPatterns(entry.name, config.scanPatterns)) continue;
22035
24212
  try {
22036
- const stat5 = await fsp2.stat(fullPath);
22037
- if (stat5.size > config.maxBinarySizeBytes) continue;
22038
- if (stat5.size === 0) continue;
24213
+ const stat6 = await fsp2.stat(fullPath);
24214
+ if (stat6.size > config.maxBinarySizeBytes) continue;
24215
+ if (stat6.size === 0) continue;
22039
24216
  const existing = tracked.get(relativePath);
22040
24217
  if (existing) {
22041
- if (existing.sizeBytes !== stat5.size) {
24218
+ if (existing.sizeBytes !== stat6.size) {
22042
24219
  results.push(relativePath);
22043
24220
  continue;
22044
24221
  }
@@ -22064,15 +24241,15 @@ async function hashFile(filePath) {
22064
24241
 
22065
24242
  // src/binary-lifecycle/manifest.ts
22066
24243
  import fsp3 from "fs/promises";
22067
- import path23 from "path";
24244
+ import path26 from "path";
22068
24245
  import crypto2 from "crypto";
22069
24246
  var MANIFEST_DIR = ".binary-lifecycle";
22070
24247
  var MANIFEST_FILE = "manifest.json";
22071
24248
  function manifestDir(memoryDir) {
22072
- return path23.join(memoryDir, MANIFEST_DIR);
24249
+ return path26.join(memoryDir, MANIFEST_DIR);
22073
24250
  }
22074
24251
  function manifestPath(memoryDir) {
22075
- return path23.join(memoryDir, MANIFEST_DIR, MANIFEST_FILE);
24252
+ return path26.join(memoryDir, MANIFEST_DIR, MANIFEST_FILE);
22076
24253
  }
22077
24254
  async function readManifest(memoryDir) {
22078
24255
  const filePath = manifestPath(memoryDir);
@@ -22124,13 +24301,13 @@ function emptyManifest() {
22124
24301
 
22125
24302
  // src/binary-lifecycle/pipeline.ts
22126
24303
  import fsp4 from "fs/promises";
22127
- import path24 from "path";
24304
+ import path27 from "path";
22128
24305
  import crypto3 from "crypto";
22129
24306
  var historicalIdCache = new HistoricalEntityCanonicalIdCache();
22130
24307
  function isRecallCorpusMarkdown(mdPath, memoryDir) {
22131
- const rel = path24.relative(memoryDir, mdPath);
22132
- if (rel.startsWith("..") || path24.isAbsolute(rel)) return false;
22133
- const top = rel.split(path24.sep)[0];
24308
+ const rel = path27.relative(memoryDir, mdPath);
24309
+ if (rel.startsWith("..") || path27.isAbsolute(rel)) return false;
24310
+ const top = rel.split(path27.sep)[0];
22134
24311
  return RECALL_FALLBACK_DIRS.includes(top);
22135
24312
  }
22136
24313
  async function hashFile2(filePath) {
@@ -22154,13 +24331,13 @@ function escapeRegex(s) {
22154
24331
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
22155
24332
  }
22156
24333
  function resolveManifestAssetPath(memoryDir, originalPath) {
22157
- if (originalPath.length === 0 || originalPath.includes("\0") || originalPath.includes("\\") || path24.isAbsolute(originalPath) || path24.win32.isAbsolute(originalPath)) {
24334
+ if (originalPath.length === 0 || originalPath.includes("\0") || originalPath.includes("\\") || path27.isAbsolute(originalPath) || path27.win32.isAbsolute(originalPath)) {
22158
24335
  return null;
22159
24336
  }
22160
- const memoryRoot = path24.resolve(memoryDir);
22161
- const fullPath = path24.resolve(memoryRoot, originalPath);
22162
- const relative = path24.relative(memoryRoot, fullPath);
22163
- if (relative === "" || relative === ".." || relative.startsWith(`..${path24.sep}`) || path24.isAbsolute(relative)) {
24337
+ const memoryRoot = path27.resolve(memoryDir);
24338
+ const fullPath = path27.resolve(memoryRoot, originalPath);
24339
+ const relative = path27.relative(memoryRoot, fullPath);
24340
+ if (relative === "" || relative === ".." || relative.startsWith(`..${path27.sep}`) || path27.isAbsolute(relative)) {
22164
24341
  return null;
22165
24342
  }
22166
24343
  return fullPath;
@@ -22171,7 +24348,7 @@ function validateBinaryLifecycleConfig(config) {
22171
24348
  }
22172
24349
  }
22173
24350
  function remotePathForAsset(backend, relPath) {
22174
- const normalized = relPath.split(path24.sep).join("/");
24351
+ const normalized = relPath.split(path27.sep).join("/");
22175
24352
  if (backend.type === "filesystem") {
22176
24353
  return `.binary-lifecycle/mirrors/${normalized}`;
22177
24354
  }
@@ -22184,11 +24361,11 @@ async function stageMirror(memoryDir, newPaths, backend, assets, log2, dryRun) {
22184
24361
  let mirrored = 0;
22185
24362
  const errors = [];
22186
24363
  for (const relPath of newPaths) {
22187
- const fullPath = path24.join(memoryDir, relPath);
24364
+ const fullPath = path27.join(memoryDir, relPath);
22188
24365
  try {
22189
- const stat5 = await fsp4.stat(fullPath);
24366
+ const stat6 = await fsp4.stat(fullPath);
22190
24367
  const contentHash = await hashFile2(fullPath);
22191
- const ext = path24.extname(relPath);
24368
+ const ext = path27.extname(relPath);
22192
24369
  const mimeType = guessMimeType(ext);
22193
24370
  const remotePath = remotePathForAsset(backend, relPath);
22194
24371
  let backendLocation = remotePath;
@@ -22201,7 +24378,7 @@ async function stageMirror(memoryDir, newPaths, backend, assets, log2, dryRun) {
22201
24378
  mirroredPath: backendLocation,
22202
24379
  ...redirectPath ? { redirectPath } : {},
22203
24380
  contentHash,
22204
- sizeBytes: stat5.size,
24381
+ sizeBytes: stat6.size,
22205
24382
  mimeType,
22206
24383
  mirroredAt: (/* @__PURE__ */ new Date()).toISOString(),
22207
24384
  status: "mirrored"
@@ -22214,7 +24391,7 @@ async function stageMirror(memoryDir, newPaths, backend, assets, log2, dryRun) {
22214
24391
  assets.push(record);
22215
24392
  }
22216
24393
  mirrored++;
22217
- log2.info(`[binary-lifecycle] mirrored: ${relPath} (${stat5.size} bytes)${dryRun ? " [dry-run]" : ""}`);
24394
+ log2.info(`[binary-lifecycle] mirrored: ${relPath} (${stat6.size} bytes)${dryRun ? " [dry-run]" : ""}`);
22218
24395
  } catch (err) {
22219
24396
  const msg = `mirror failed for ${relPath}: ${err instanceof Error ? err.message : String(err)}`;
22220
24397
  log2.error(`[binary-lifecycle] ${msg}`);
@@ -22248,8 +24425,8 @@ async function stageRedirect(memoryDir, assets, log2, dryRun, readMarkdownFile,
22248
24425
  const pattern = markdownReferencePattern(asset, assetAbsolute, mdPath);
22249
24426
  if (!pattern.test(content)) continue;
22250
24427
  pattern.lastIndex = 0;
22251
- const updated = content.replace(pattern, (_match, open, _target, close) => {
22252
- return `${open}${markdownTargetForAsset(asset)}${close}`;
24428
+ const updated = content.replace(pattern, (_match, open3, _target, close) => {
24429
+ return `${open3}${markdownTargetForAsset(asset)}${close}`;
22253
24430
  });
22254
24431
  updates.push({ mdPath, content: updated });
22255
24432
  } catch (err) {
@@ -22326,7 +24503,7 @@ async function stageRedirect(memoryDir, assets, log2, dryRun, readMarkdownFile,
22326
24503
  for (const update of updates) {
22327
24504
  try {
22328
24505
  await withRawEntityPageMutation(memoryDir, update.mdPath, async () => {
22329
- const stateDir = path24.join(memoryDir, "state");
24506
+ const stateDir = path27.join(memoryDir, "state");
22330
24507
  const kind = classifyEntityRefWritePath(memoryDir, update.mdPath);
22331
24508
  if (kind === "memory") {
22332
24509
  const idsAtWrite = historicalIdCache.get(stateDir);
@@ -22420,10 +24597,10 @@ async function countRemainingLocalReferences(memoryDir, asset, assetAbsolute, md
22420
24597
  return { remaining, errors };
22421
24598
  }
22422
24599
  function markdownReferencePattern(asset, assetAbsolute, mdPath) {
22423
- const mdDir = path24.dirname(mdPath);
24600
+ const mdDir = path27.dirname(mdPath);
22424
24601
  const candidates = /* @__PURE__ */ new Set();
22425
24602
  const addCandidate = (candidate) => {
22426
- const normalized = candidate.split(path24.sep).join("/");
24603
+ const normalized = candidate.split(path27.sep).join("/");
22427
24604
  if (normalized.length === 0) return;
22428
24605
  candidates.add(normalized);
22429
24606
  const isParentTraversal = normalized === ".." || normalized.startsWith("../");
@@ -22431,10 +24608,10 @@ function markdownReferencePattern(asset, assetAbsolute, mdPath) {
22431
24608
  candidates.add(`./${normalized}`);
22432
24609
  }
22433
24610
  };
22434
- addCandidate(path24.relative(mdDir, assetAbsolute));
22435
- const originalPath = asset.originalPath.split(path24.sep).join("/");
22436
- const originalAsFileRelative = path24.resolve(mdDir, ...originalPath.split("/"));
22437
- if (path24.resolve(originalAsFileRelative) === path24.resolve(assetAbsolute)) {
24611
+ addCandidate(path27.relative(mdDir, assetAbsolute));
24612
+ const originalPath = asset.originalPath.split(path27.sep).join("/");
24613
+ const originalAsFileRelative = path27.resolve(mdDir, ...originalPath.split("/"));
24614
+ if (path27.resolve(originalAsFileRelative) === path27.resolve(assetAbsolute)) {
22438
24615
  addCandidate(originalPath);
22439
24616
  }
22440
24617
  addCandidate(`/${originalPath}`);
@@ -22530,7 +24707,7 @@ async function findMarkdownFiles(dir) {
22530
24707
  return;
22531
24708
  }
22532
24709
  for (const entry of entries) {
22533
- const full = path24.join(current, entry.name);
24710
+ const full = path27.join(current, entry.name);
22534
24711
  if (entry.isDirectory()) {
22535
24712
  if (entry.name === ".binary-lifecycle") continue;
22536
24713
  await walk(full);
@@ -22605,7 +24782,7 @@ async function runBinaryLifecyclePipeline(memoryDir, config, backend, log2, opts
22605
24782
 
22606
24783
  // src/projection/index.ts
22607
24784
  import fs from "fs";
22608
- import path25 from "path";
24785
+ import path28 from "path";
22609
24786
  var VALID_PROJECTION_CATEGORIES = new Set(ALL_CATEGORY_KEYS);
22610
24787
  async function generateContextTree(options) {
22611
24788
  const startTime = Date.now();
@@ -22620,8 +24797,8 @@ async function generateContextTree(options) {
22620
24797
  let nodesGenerated = 0;
22621
24798
  let nodesSkipped = 0;
22622
24799
  const categoryCounts = {};
22623
- const resolvedMemoryDir = path25.resolve(memoryDir);
22624
- const resolvedOutputDir = path25.resolve(outputDir);
24800
+ const resolvedMemoryDir = path28.resolve(memoryDir);
24801
+ const resolvedOutputDir = path28.resolve(outputDir);
22625
24802
  const requestedCategories = validateProjectionCategories(filterCategories);
22626
24803
  const realMemoryDir = assertSafeMemoryRoot(resolvedMemoryDir);
22627
24804
  assertNotSymlink(resolvedOutputDir, "context tree outputDir");
@@ -22659,7 +24836,7 @@ async function generateContextTree(options) {
22659
24836
  }
22660
24837
  }
22661
24838
  if (includeEntities) {
22662
- const entitiesDir = path25.join(memoryDir, "entities");
24839
+ const entitiesDir = path28.join(memoryDir, "entities");
22663
24840
  if (fs.existsSync(entitiesDir)) {
22664
24841
  assertSafeInputRoot(realMemoryDir, entitiesDir, "entities root");
22665
24842
  categoryCounts["entity"] = 0;
@@ -22671,7 +24848,7 @@ async function generateContextTree(options) {
22671
24848
  continue;
22672
24849
  }
22673
24850
  const content = fs.readFileSync(filePath, "utf8");
22674
- const fileName = path25.basename(filePath, ".md");
24851
+ const fileName = path28.basename(filePath, ".md");
22675
24852
  const node = projectEntityNode(fileName, content);
22676
24853
  const outputPath = resolveContainedOutputPath(realOutputDir, "entities", `${fileName}.md`);
22677
24854
  writeProjectedContent(realOutputDir, outputPath, node.content);
@@ -22683,7 +24860,7 @@ async function generateContextTree(options) {
22683
24860
  }
22684
24861
  const shouldIncludeQuestions = includeQuestions && (requestedCategories === void 0 || requestedCategories.includes("question"));
22685
24862
  if (shouldIncludeQuestions) {
22686
- const questionsDir = path25.join(memoryDir, "questions");
24863
+ const questionsDir = path28.join(memoryDir, "questions");
22687
24864
  if (fs.existsSync(questionsDir)) {
22688
24865
  assertSafeInputRoot(realMemoryDir, questionsDir, "questions root");
22689
24866
  categoryCounts["question"] = 0;
@@ -22724,8 +24901,8 @@ async function generateContextTree(options) {
22724
24901
  };
22725
24902
  }
22726
24903
  function isPathInside(root, candidate) {
22727
- const relative = path25.relative(root, candidate);
22728
- return relative === "" || !relative.startsWith("..") && !path25.isAbsolute(relative);
24904
+ const relative = path28.relative(root, candidate);
24905
+ return relative === "" || !relative.startsWith("..") && !path28.isAbsolute(relative);
22729
24906
  }
22730
24907
  function assertNotSymlink(targetPath, label) {
22731
24908
  try {
@@ -22738,21 +24915,21 @@ function assertNotSymlink(targetPath, label) {
22738
24915
  }
22739
24916
  }
22740
24917
  function assertSafeMemoryRoot(targetPath) {
22741
- const stat5 = fs.lstatSync(targetPath);
22742
- if (stat5.isSymbolicLink()) {
24918
+ const stat6 = fs.lstatSync(targetPath);
24919
+ if (stat6.isSymbolicLink()) {
22743
24920
  throw new Error(`memoryDir must not be a symlink: ${targetPath}`);
22744
24921
  }
22745
- if (!stat5.isDirectory()) {
24922
+ if (!stat6.isDirectory()) {
22746
24923
  throw new Error(`memoryDir must be a directory: ${targetPath}`);
22747
24924
  }
22748
24925
  return fs.realpathSync(targetPath);
22749
24926
  }
22750
24927
  function assertSafeInputRoot(realMemoryDir, targetPath, label) {
22751
- const stat5 = fs.lstatSync(targetPath);
22752
- if (stat5.isSymbolicLink()) {
24928
+ const stat6 = fs.lstatSync(targetPath);
24929
+ if (stat6.isSymbolicLink()) {
22753
24930
  throw new Error(`${label} must not be a symlink: ${targetPath}`);
22754
24931
  }
22755
- if (!stat5.isDirectory()) {
24932
+ if (!stat6.isDirectory()) {
22756
24933
  throw new Error(`${label} must be a directory: ${targetPath}`);
22757
24934
  }
22758
24935
  const realTarget = fs.realpathSync(targetPath);
@@ -22762,15 +24939,15 @@ function assertSafeInputRoot(realMemoryDir, targetPath, label) {
22762
24939
  }
22763
24940
  function assertSafeOutputTarget(realOutputDir, outputPath) {
22764
24941
  let current = realOutputDir;
22765
- const relative = path25.relative(realOutputDir, outputPath);
22766
- if (relative.startsWith("..") || path25.isAbsolute(relative)) {
24942
+ const relative = path28.relative(realOutputDir, outputPath);
24943
+ if (relative.startsWith("..") || path28.isAbsolute(relative)) {
22767
24944
  throw new Error(`context tree output path escapes outputDir: ${outputPath}`);
22768
24945
  }
22769
- for (const segment of relative.split(path25.sep).filter(Boolean)) {
22770
- current = path25.join(current, segment);
24946
+ for (const segment of relative.split(path28.sep).filter(Boolean)) {
24947
+ current = path28.join(current, segment);
22771
24948
  try {
22772
- const stat5 = fs.lstatSync(current);
22773
- if (stat5.isSymbolicLink()) {
24949
+ const stat6 = fs.lstatSync(current);
24950
+ if (stat6.isSymbolicLink()) {
22774
24951
  throw new Error(`context tree output path contains symlink: ${current}`);
22775
24952
  }
22776
24953
  } catch (err) {
@@ -22797,17 +24974,17 @@ function validateProjectionCategories(categories) {
22797
24974
  return validated;
22798
24975
  }
22799
24976
  function resolveContainedOutputPath(outputRoot, ...segments) {
22800
- const resolved = path25.resolve(outputRoot, ...segments);
22801
- const relative = path25.relative(outputRoot, resolved);
22802
- if (relative === "" || !relative.startsWith("..") && !path25.isAbsolute(relative)) {
24977
+ const resolved = path28.resolve(outputRoot, ...segments);
24978
+ const relative = path28.relative(outputRoot, resolved);
24979
+ if (relative === "" || !relative.startsWith("..") && !path28.isAbsolute(relative)) {
22803
24980
  return resolved;
22804
24981
  }
22805
24982
  throw new Error(`context tree output path escapes outputDir: ${segments.join("/")}`);
22806
24983
  }
22807
24984
  function writeProjectedContent(realOutputDir, outputPath, generatedContent) {
22808
24985
  assertSafeOutputTarget(realOutputDir, outputPath);
22809
- fs.mkdirSync(path25.dirname(outputPath), { recursive: true });
22810
- const realParent = fs.realpathSync(path25.dirname(outputPath));
24986
+ fs.mkdirSync(path28.dirname(outputPath), { recursive: true });
24987
+ const realParent = fs.realpathSync(path28.dirname(outputPath));
22811
24988
  if (!isPathInside(realOutputDir, realParent)) {
22812
24989
  throw new Error(`context tree output path escapes outputDir: ${outputPath}`);
22813
24990
  }
@@ -22846,7 +25023,7 @@ function walkR(dir, realMemoryDir) {
22846
25023
  const results = [];
22847
25024
  function walk(directory) {
22848
25025
  for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
22849
- const fullPath = path25.join(directory, entry.name);
25026
+ const fullPath = path28.join(directory, entry.name);
22850
25027
  if (entry.isSymbolicLink()) {
22851
25028
  throw new Error(`context tree input path contains symlink: ${fullPath}`);
22852
25029
  }
@@ -22899,13 +25076,13 @@ function extractBody(content) {
22899
25076
  }
22900
25077
  function projectNode(filePath, category, fm, rawContent) {
22901
25078
  const body = extractBody(rawContent);
22902
- const fileName = path25.basename(filePath, ".md");
22903
- const dateDir = path25.basename(path25.dirname(filePath));
25079
+ const fileName = path28.basename(filePath, ".md");
25080
+ const dateDir = path28.basename(path28.dirname(filePath));
22904
25081
  let relPath;
22905
25082
  if (/^\d{4}-\d{2}-\d{2}$/.test(dateDir)) {
22906
- relPath = path25.join(category, dateDir, `${fileName}.md`);
25083
+ relPath = path28.join(category, dateDir, `${fileName}.md`);
22907
25084
  } else {
22908
- relPath = path25.join(category, `${fileName}.md`);
25085
+ relPath = path28.join(category, `${fileName}.md`);
22909
25086
  }
22910
25087
  const generatedAt = (/* @__PURE__ */ new Date()).toISOString();
22911
25088
  const md = `# ${fm.id}
@@ -22951,7 +25128,7 @@ function projectEntityNode(fileName, content) {
22951
25128
  ${content}
22952
25129
  `;
22953
25130
  return {
22954
- path: path25.join("entities", `${fileName}.md`),
25131
+ path: path28.join("entities", `${fileName}.md`),
22955
25132
  category: "entity",
22956
25133
  title: fileName,
22957
25134
  content: md,
@@ -23004,7 +25181,7 @@ function generateIndex(categoryCounts, outputDir) {
23004
25181
 
23005
25182
  // src/onboarding/index.ts
23006
25183
  import fs2 from "fs";
23007
- import path26 from "path";
25184
+ import path29 from "path";
23008
25185
  var LANGUAGE_RULES = [
23009
25186
  {
23010
25187
  language: "TypeScript",
@@ -23106,7 +25283,7 @@ function onboard(options) {
23106
25283
  maxDepth = 6,
23107
25284
  excludeDirs = []
23108
25285
  } = options;
23109
- const directory = path26.resolve(options.directory ?? process.cwd());
25286
+ const directory = path29.resolve(options.directory ?? process.cwd());
23110
25287
  let rootStat;
23111
25288
  try {
23112
25289
  rootStat = fs2.statSync(directory);
@@ -23148,7 +25325,7 @@ function walkDir(root, exclude, maxDepth) {
23148
25325
  }
23149
25326
  for (const entry of entries) {
23150
25327
  if (exclude.has(entry.name)) continue;
23151
- const fullPath = path26.join(dir, entry.name);
25328
+ const fullPath = path29.join(dir, entry.name);
23152
25329
  if (entry.isDirectory()) {
23153
25330
  walk(fullPath, depth + 1);
23154
25331
  } else if (entry.isFile()) {
@@ -23163,11 +25340,11 @@ function detectLanguages(files, root) {
23163
25340
  const results = [];
23164
25341
  const extCounts = /* @__PURE__ */ new Map();
23165
25342
  for (const f of files) {
23166
- const ext = path26.extname(f).toLowerCase();
25343
+ const ext = path29.extname(f).toLowerCase();
23167
25344
  if (ext) extCounts.set(ext, (extCounts.get(ext) ?? 0) + 1);
23168
25345
  }
23169
25346
  const rootFiles = new Set(
23170
- files.filter((f) => path26.dirname(f) === root).map((f) => path26.basename(f))
25347
+ files.filter((f) => path29.dirname(f) === root).map((f) => path29.basename(f))
23171
25348
  );
23172
25349
  for (const rule of LANGUAGE_RULES) {
23173
25350
  const evidence = [];
@@ -23211,7 +25388,7 @@ function detectLanguages(files, root) {
23211
25388
  }
23212
25389
  function detectShape(files, root) {
23213
25390
  const rootFiles = new Set(
23214
- files.filter((f) => path26.dirname(f) === root).map((f) => path26.basename(f))
25391
+ files.filter((f) => path29.dirname(f) === root).map((f) => path29.basename(f))
23215
25392
  );
23216
25393
  const rootDirs = /* @__PURE__ */ new Set();
23217
25394
  try {
@@ -23222,7 +25399,7 @@ function detectShape(files, root) {
23222
25399
  }
23223
25400
  const evidence = [];
23224
25401
  if (rootFiles.has("package.json")) {
23225
- const pkg = readJsonSafe(path26.join(root, "package.json"));
25402
+ const pkg = readJsonSafe(path29.join(root, "package.json"));
23226
25403
  if (pkg?.workspaces) {
23227
25404
  evidence.push("package.json has workspaces");
23228
25405
  return { shape: "monorepo", evidence };
@@ -23236,13 +25413,13 @@ function detectShape(files, root) {
23236
25413
  evidence.push("workspace manifest found");
23237
25414
  return { shape: "workspace", evidence };
23238
25415
  }
23239
- const cargoToml = readTomlWorkspace(path26.join(root, "Cargo.toml"));
25416
+ const cargoToml = readTomlWorkspace(path29.join(root, "Cargo.toml"));
23240
25417
  if (cargoToml) {
23241
25418
  evidence.push("Cargo.toml has workspace");
23242
25419
  return { shape: "workspace", evidence };
23243
25420
  }
23244
25421
  if (rootFiles.has("package.json")) {
23245
- const pkg = readJsonSafe(path26.join(root, "package.json"));
25422
+ const pkg = readJsonSafe(path29.join(root, "package.json"));
23246
25423
  if (pkg?.exports || pkg?.main) {
23247
25424
  if (pkg?.bin) {
23248
25425
  evidence.push("package.json has bin");
@@ -23276,8 +25453,8 @@ function discoverDocs(files, root) {
23276
25453
  { pattern: /^\.editorconfig$/i, kind: "config" }
23277
25454
  ];
23278
25455
  for (const filePath of files) {
23279
- const basename = path26.basename(filePath).toLowerCase();
23280
- const relPath = path26.relative(root, filePath);
25456
+ const basename = path29.basename(filePath).toLowerCase();
25457
+ const relPath = path29.relative(root, filePath);
23281
25458
  let kind;
23282
25459
  for (const { pattern, kind: k } of docPatterns) {
23283
25460
  if (pattern.test(basename)) {
@@ -23289,7 +25466,7 @@ function discoverDocs(files, root) {
23289
25466
  kind = "docs";
23290
25467
  }
23291
25468
  if (!kind && (basename.endsWith(".md") || basename.endsWith(".mdx"))) {
23292
- if (path26.dirname(relPath) === "." || isUnderDocsDir(relPath)) {
25469
+ if (path29.dirname(relPath) === "." || isUnderDocsDir(relPath)) {
23293
25470
  kind = "docs";
23294
25471
  }
23295
25472
  }
@@ -23310,7 +25487,7 @@ function discoverDocs(files, root) {
23310
25487
  return docs;
23311
25488
  }
23312
25489
  function isUnderDocsDir(relPath) {
23313
- const parts = relPath.split(path26.sep);
25490
+ const parts = relPath.split(path29.sep);
23314
25491
  return parts[0] === "docs" || parts[0] === "doc" || parts[0] === "documentation";
23315
25492
  }
23316
25493
  function buildPlan(languages, shape, docs, _root) {
@@ -23354,7 +25531,7 @@ function readTomlWorkspace(filePath) {
23354
25531
 
23355
25532
  // src/curation/index.ts
23356
25533
  import fs3 from "fs";
23357
- import path27 from "path";
25534
+ import path30 from "path";
23358
25535
  import crypto4 from "crypto";
23359
25536
  async function curate(options) {
23360
25537
  const startTime = Date.now();
@@ -23439,18 +25616,18 @@ async function curate(options) {
23439
25616
  };
23440
25617
  }
23441
25618
  function resolveTargets(targetPath) {
23442
- const stat5 = fs3.statSync(targetPath);
23443
- if (stat5.isFile()) return [targetPath];
25619
+ const stat6 = fs3.statSync(targetPath);
25620
+ if (stat6.isFile()) return [targetPath];
23444
25621
  const results = [];
23445
25622
  const extensions = /* @__PURE__ */ new Set([".md", ".txt", ".mdx", ".rst"]);
23446
25623
  function walk(dir) {
23447
25624
  for (const entry of fs3.readdirSync(dir, { withFileTypes: true })) {
23448
- const fullPath = path27.join(dir, entry.name);
25625
+ const fullPath = path30.join(dir, entry.name);
23449
25626
  if (entry.isDirectory()) {
23450
25627
  if (entry.name !== "node_modules" && entry.name !== ".git") {
23451
25628
  walk(fullPath);
23452
25629
  }
23453
- } else if (extensions.has(path27.extname(entry.name).toLowerCase())) {
25630
+ } else if (extensions.has(path30.extname(entry.name).toLowerCase())) {
23454
25631
  results.push(fullPath);
23455
25632
  }
23456
25633
  }
@@ -23459,12 +25636,12 @@ function resolveTargets(targetPath) {
23459
25636
  return results;
23460
25637
  }
23461
25638
  function resolveProvenanceRoot(targetPath) {
23462
- const resolvedTarget = path27.resolve(targetPath);
23463
- const stat5 = fs3.statSync(resolvedTarget);
23464
- return stat5.isFile() ? path27.dirname(resolvedTarget) : resolvedTarget;
25639
+ const resolvedTarget = path30.resolve(targetPath);
25640
+ const stat6 = fs3.statSync(resolvedTarget);
25641
+ return stat6.isFile() ? path30.dirname(resolvedTarget) : resolvedTarget;
23465
25642
  }
23466
25643
  function extractStatements(content, filePath, projectRoot, source, sourceFileHash, categoryOverride, confidence, entityRef, tags) {
23467
- const relativePath = path27.relative(projectRoot, path27.resolve(filePath)) || path27.basename(filePath);
25644
+ const relativePath = path30.relative(projectRoot, path30.resolve(filePath)) || path30.basename(filePath);
23468
25645
  const statements = [];
23469
25646
  const now = (/* @__PURE__ */ new Date()).toISOString();
23470
25647
  const paragraphs = content.split(/\n{2,}/).map((p) => p.trim()).filter((p) => p.length > 20 && p.length < 2e3);
@@ -23558,7 +25735,7 @@ function loadExistingMemories(memoryDir) {
23558
25735
  if (!fs3.existsSync(memoryDir)) return result;
23559
25736
  const dirs = ALL_CATEGORY_DIRS;
23560
25737
  for (const dir of dirs) {
23561
- const fullDir = path27.join(memoryDir, dir);
25738
+ const fullDir = path30.join(memoryDir, dir);
23562
25739
  if (!fs3.existsSync(fullDir)) continue;
23563
25740
  walkFiles(fullDir, (filePath) => {
23564
25741
  const content = readFileSafe(filePath);
@@ -23581,11 +25758,11 @@ function writeStatement(stmt, memoryDir) {
23581
25758
  const now = /* @__PURE__ */ new Date();
23582
25759
  const dateDir = now.toISOString().split("T")[0];
23583
25760
  const categoryDir = getCategoryDir(memoryDir, stmt.category);
23584
- const dir = path27.join(categoryDir, dateDir);
25761
+ const dir = path30.join(categoryDir, dateDir);
23585
25762
  fs3.mkdirSync(dir, { recursive: true });
23586
25763
  const fileName = `${stmt.category}-${Date.now()}-${stmt.id.slice(0, 8)}.md`;
23587
- const filePath = path27.join(dir, fileName);
23588
- const historicalIds = historicalIdCache2.get(path27.join(memoryDir, "state"));
25764
+ const filePath = path30.join(dir, fileName);
25765
+ const historicalIds = historicalIdCache2.get(path30.join(memoryDir, "state"));
23589
25766
  const rawBody = `${[
23590
25767
  "---",
23591
25768
  `id: ${stmt.id}`,
@@ -23608,7 +25785,7 @@ ${stmt.content}
23608
25785
  fs3.writeFileSync(filePath, body);
23609
25786
  try {
23610
25787
  repairContentAfterJournalMoveSync({
23611
- stateDir: path27.join(memoryDir, "state"),
25788
+ stateDir: path30.join(memoryDir, "state"),
23612
25789
  cache: historicalIdCache2,
23613
25790
  idsAtWrite: historicalIds,
23614
25791
  rawContent: rawBody,
@@ -23669,7 +25846,7 @@ function extractBody2(content) {
23669
25846
  }
23670
25847
  function walkFiles(dir, callback) {
23671
25848
  for (const entry of fs3.readdirSync(dir, { withFileTypes: true })) {
23672
- const fullPath = path27.join(dir, entry.name);
25849
+ const fullPath = path30.join(dir, entry.name);
23673
25850
  if (entry.isDirectory()) {
23674
25851
  walkFiles(fullPath, callback);
23675
25852
  } else if (entry.name.endsWith(".md")) {
@@ -23681,7 +25858,7 @@ function walkFiles(dir, callback) {
23681
25858
  // src/dedup/index.ts
23682
25859
  import crypto5 from "crypto";
23683
25860
  import fs4 from "fs";
23684
- import path28 from "path";
25861
+ import path31 from "path";
23685
25862
  var DEFAULT_DEDUP_THRESHOLD = 0.85;
23686
25863
  var DEFAULT_MAX_LOAD = 1e4;
23687
25864
  function normalizeThreshold(value, defaultValue) {
@@ -23875,7 +26052,7 @@ function loadMemories(memoryDir, categories, maxLoad = 1e4) {
23875
26052
  const memoryRootReal = fs4.realpathSync(memoryDir);
23876
26053
  for (const category of allCategories) {
23877
26054
  if (result.length >= maxLoad) break;
23878
- const dir = path28.join(memoryDir, category);
26055
+ const dir = path31.join(memoryDir, category);
23879
26056
  if (!fs4.existsSync(dir)) continue;
23880
26057
  const categoryStat = fs4.lstatSync(dir);
23881
26058
  if (categoryStat.isSymbolicLink()) {
@@ -23936,15 +26113,15 @@ function extractBody3(content) {
23936
26113
  return match ? match[1].trim() : content.trim();
23937
26114
  }
23938
26115
  function assertPathInsideRoot2(rootReal, targetReal, sourcePath) {
23939
- const rel = path28.relative(rootReal, targetReal);
23940
- if (rel === "" || !rel.startsWith("..") && !path28.isAbsolute(rel)) {
26116
+ const rel = path31.relative(rootReal, targetReal);
26117
+ if (rel === "" || !rel.startsWith("..") && !path31.isAbsolute(rel)) {
23941
26118
  return;
23942
26119
  }
23943
26120
  throw new Error(`Refusing to scan memory path outside root: ${sourcePath}`);
23944
26121
  }
23945
26122
  function walkMdFiles(dir, memoryRootReal, categoryRootReal, callback) {
23946
26123
  for (const entry of fs4.readdirSync(dir, { withFileTypes: true })) {
23947
- const fullPath = path28.join(dir, entry.name);
26124
+ const fullPath = path31.join(dir, entry.name);
23948
26125
  const entryStat = fs4.lstatSync(fullPath);
23949
26126
  if (entryStat.isSymbolicLink()) {
23950
26127
  throw new Error(`Refusing to scan symlinked memory path: ${fullPath}`);
@@ -23962,10 +26139,10 @@ function walkMdFiles(dir, memoryRootReal, categoryRootReal, callback) {
23962
26139
 
23963
26140
  // src/review/index.ts
23964
26141
  import fs5 from "fs";
23965
- import path29 from "path";
26142
+ import path32 from "path";
23966
26143
  var historicalIdCache3 = new HistoricalEntityCanonicalIdCache();
23967
26144
  function writeReviewFileCanonicalized(memoryDir, filePath, content) {
23968
- const stateDir = path29.join(memoryDir, "state");
26145
+ const stateDir = path32.join(memoryDir, "state");
23969
26146
  const idsAtWrite = historicalIdCache3.get(stateDir);
23970
26147
  let originalBytes = null;
23971
26148
  try {
@@ -23999,21 +26176,21 @@ function writeReviewFileCanonicalized(memoryDir, filePath, content) {
23999
26176
  var DEFAULT_CONFIDENCE_THRESHOLD = 0.7;
24000
26177
  function realMemoryRoot(memoryDir) {
24001
26178
  try {
24002
- const stat5 = fs5.lstatSync(memoryDir);
24003
- if (!stat5.isDirectory() || stat5.isSymbolicLink()) return null;
26179
+ const stat6 = fs5.lstatSync(memoryDir);
26180
+ if (!stat6.isDirectory() || stat6.isSymbolicLink()) return null;
24004
26181
  return fs5.realpathSync(memoryDir);
24005
26182
  } catch {
24006
26183
  return null;
24007
26184
  }
24008
26185
  }
24009
26186
  function isPathInside2(rootReal, candidateReal) {
24010
- const relative = path29.relative(rootReal, candidateReal);
24011
- return relative === "" || !!relative && !relative.startsWith("..") && !path29.isAbsolute(relative);
26187
+ const relative = path32.relative(rootReal, candidateReal);
26188
+ return relative === "" || !!relative && !relative.startsWith("..") && !path32.isAbsolute(relative);
24012
26189
  }
24013
26190
  function isSafeDirectory(rootReal, dir) {
24014
26191
  try {
24015
- const stat5 = fs5.lstatSync(dir);
24016
- if (!stat5.isDirectory() || stat5.isSymbolicLink()) return false;
26192
+ const stat6 = fs5.lstatSync(dir);
26193
+ if (!stat6.isDirectory() || stat6.isSymbolicLink()) return false;
24017
26194
  return isPathInside2(rootReal, fs5.realpathSync(dir));
24018
26195
  } catch {
24019
26196
  return false;
@@ -24051,7 +26228,7 @@ function listReviewItems(options) {
24051
26228
  if (filterReason && item.reviewReason !== filterReason) return;
24052
26229
  items.push(item);
24053
26230
  };
24054
- const suggestionsDir = path29.join(memoryDir, "suggestions");
26231
+ const suggestionsDir = path32.join(memoryDir, "suggestions");
24055
26232
  if (!isLimitReached() && fs5.existsSync(suggestionsDir) && isSafeDirectory(rootReal, suggestionsDir)) {
24056
26233
  walkMd(rootReal, suggestionsDir, (filePath, content) => {
24057
26234
  if (isLimitReached()) return true;
@@ -24072,7 +26249,7 @@ function listReviewItems(options) {
24072
26249
  return isLimitReached();
24073
26250
  });
24074
26251
  }
24075
- const reviewDir = path29.join(memoryDir, "review");
26252
+ const reviewDir = path32.join(memoryDir, "review");
24076
26253
  if (!isLimitReached() && fs5.existsSync(reviewDir) && isSafeDirectory(rootReal, reviewDir)) {
24077
26254
  walkMd(rootReal, reviewDir, (filePath, content) => {
24078
26255
  if (isLimitReached()) return true;
@@ -24097,7 +26274,7 @@ function listReviewItems(options) {
24097
26274
  const categories = ALL_CATEGORY_DIRS;
24098
26275
  for (const category of categories) {
24099
26276
  if (isLimitReached()) break;
24100
- const dir = path29.join(memoryDir, category);
26277
+ const dir = path32.join(memoryDir, category);
24101
26278
  if (!fs5.existsSync(dir) || !isSafeDirectory(rootReal, dir)) continue;
24102
26279
  walkMd(rootReal, dir, (filePath, content) => {
24103
26280
  if (isLimitReached()) return true;
@@ -24179,9 +26356,9 @@ function approveItem(memoryDir, itemId, options) {
24179
26356
  const targetDir = getCategoryDir(memoryDir, category);
24180
26357
  const dateDir = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
24181
26358
  ensureSafeDirectory(rootReal, targetDir);
24182
- const outputPath = path29.join(targetDir, dateDir, path29.basename(found.filePath));
24183
- ensureSafeDirectory(rootReal, path29.dirname(outputPath));
24184
- const reviewStateDir = path29.join(memoryDir, "state");
26359
+ const outputPath = path32.join(targetDir, dateDir, path32.basename(found.filePath));
26360
+ ensureSafeDirectory(rootReal, path32.dirname(outputPath));
26361
+ const reviewStateDir = path32.join(memoryDir, "state");
24185
26362
  const idsAtWrite = historicalIdCache3.get(reviewStateDir);
24186
26363
  const promotedWritten = canonicalizeEntityRefFrontmatter(updatedContent, idsAtWrite);
24187
26364
  const promotedPath = writeFileWithoutClobber(outputPath, promotedWritten, itemId);
@@ -24258,13 +26435,13 @@ function findReviewFileById(memoryDir, id, options = {}) {
24258
26435
  const rootReal = realMemoryRoot(memoryDir);
24259
26436
  if (!rootReal) return null;
24260
26437
  for (const loc of ["suggestions", "review"]) {
24261
- const dir = path29.join(memoryDir, loc);
26438
+ const dir = path32.join(memoryDir, loc);
24262
26439
  if (!fs5.existsSync(dir) || !isSafeDirectory(rootReal, dir)) continue;
24263
26440
  const found = findFileById(rootReal, dir, id);
24264
26441
  if (found) return { filePath: found, location: "queue" };
24265
26442
  }
24266
26443
  for (const category of ALL_CATEGORY_DIRS) {
24267
- const dir = path29.join(memoryDir, category);
26444
+ const dir = path32.join(memoryDir, category);
24268
26445
  if (!fs5.existsSync(dir) || !isSafeDirectory(rootReal, dir)) continue;
24269
26446
  const found = findFileById(rootReal, dir, id, (fm) => isLowConfidenceReviewCandidate(fm, options));
24270
26447
  if (found) return { filePath: found, location: "category" };
@@ -24340,10 +26517,10 @@ function readFileSafe3(filePath) {
24340
26517
  }
24341
26518
  }
24342
26519
  function writeFileWithoutClobber(basePath, content, discriminator) {
24343
- const parsed = path29.parse(basePath);
26520
+ const parsed = path32.parse(basePath);
24344
26521
  const safeDiscriminator = sanitizeFilePart(discriminator);
24345
26522
  for (let attempt = 0; attempt < 1e3; attempt++) {
24346
- const candidate = attempt === 0 ? basePath : path29.join(
26523
+ const candidate = attempt === 0 ? basePath : path32.join(
24347
26524
  parsed.dir,
24348
26525
  `${parsed.name}-${safeDiscriminator}${attempt === 1 ? "" : `-${attempt}`}${parsed.ext || ".md"}`
24349
26526
  );
@@ -24399,7 +26576,7 @@ function extractBody4(content) {
24399
26576
  function walkMd(rootReal, dir, callback) {
24400
26577
  if (!isSafeDirectory(rootReal, dir)) return false;
24401
26578
  for (const entry of fs5.readdirSync(dir, { withFileTypes: true })) {
24402
- const fullPath = path29.join(dir, entry.name);
26579
+ const fullPath = path32.join(dir, entry.name);
24403
26580
  if (entry.isSymbolicLink()) continue;
24404
26581
  if (entry.isDirectory()) {
24405
26582
  if (walkMd(rootReal, fullPath, callback)) return true;
@@ -24414,7 +26591,7 @@ function walkMdPaths(rootReal, dir) {
24414
26591
  const results = [];
24415
26592
  if (!isSafeDirectory(rootReal, dir)) return results;
24416
26593
  for (const entry of fs5.readdirSync(dir, { withFileTypes: true })) {
24417
- const fullPath = path29.join(dir, entry.name);
26594
+ const fullPath = path32.join(dir, entry.name);
24418
26595
  if (entry.isSymbolicLink()) continue;
24419
26596
  if (entry.isDirectory()) {
24420
26597
  results.push(...walkMdPaths(rootReal, fullPath));
@@ -24427,7 +26604,7 @@ function walkMdPaths(rootReal, dir) {
24427
26604
 
24428
26605
  // src/sync/index.ts
24429
26606
  import fs6 from "fs";
24430
- import path30 from "path";
26607
+ import path33 from "path";
24431
26608
  import crypto6 from "crypto";
24432
26609
  var DEFAULT_EXTENSIONS = /* @__PURE__ */ new Set([".md", ".txt", ".mdx", ".rst"]);
24433
26610
  var DEFAULT_EXCLUDE2 = /* @__PURE__ */ new Set([
@@ -24449,7 +26626,7 @@ function syncChanges(options) {
24449
26626
  } = options;
24450
26627
  const extSet = new Set(extensions);
24451
26628
  const excludeSet = /* @__PURE__ */ new Set([...DEFAULT_EXCLUDE2, ...excludeDirs]);
24452
- const stateFilePath = options.stateFile ?? path30.join(memoryDir, ".sync-state.json");
26629
+ const stateFilePath = options.stateFile ?? path33.join(memoryDir, ".sync-state.json");
24453
26630
  const prevState = loadState(stateFilePath);
24454
26631
  const currentFiles = scanFiles(sourceDir, extSet, excludeSet);
24455
26632
  const changes = computeDiff(currentFiles, prevState.fileHashes, sourceDir);
@@ -24465,7 +26642,7 @@ function syncChanges(options) {
24465
26642
  for (const [relPath, hash] of Object.entries(currentFiles)) {
24466
26643
  newState.fileHashes[relPath] = hash;
24467
26644
  }
24468
- fs6.mkdirSync(path30.dirname(stateFilePath), { recursive: true });
26645
+ fs6.mkdirSync(path33.dirname(stateFilePath), { recursive: true });
24469
26646
  fs6.writeFileSync(stateFilePath, JSON.stringify(newState, null, 2));
24470
26647
  }
24471
26648
  return {
@@ -24531,13 +26708,13 @@ function scanFiles(root, extensions, exclude) {
24531
26708
  }
24532
26709
  for (const entry of entries) {
24533
26710
  if (exclude.has(entry.name)) continue;
24534
- const fullPath = path30.join(dir, entry.name);
26711
+ const fullPath = path33.join(dir, entry.name);
24535
26712
  if (entry.isDirectory()) {
24536
26713
  walk(fullPath);
24537
26714
  } else if (entry.isFile()) {
24538
- const ext = path30.extname(entry.name).toLowerCase();
26715
+ const ext = path33.extname(entry.name).toLowerCase();
24539
26716
  if (!extensions.has(ext)) continue;
24540
- const relPath = path30.relative(root, fullPath);
26717
+ const relPath = path33.relative(root, fullPath);
24541
26718
  try {
24542
26719
  const content = fs6.readFileSync(fullPath, "utf8");
24543
26720
  result[relPath] = hashContent3(content);
@@ -24552,7 +26729,7 @@ function scanFiles(root, extensions, exclude) {
24552
26729
  function computeDiff(current, previous, sourceDir) {
24553
26730
  const changes = [];
24554
26731
  for (const [relPath, hash] of Object.entries(current)) {
24555
- const fullPath = path30.join(sourceDir, relPath);
26732
+ const fullPath = path33.join(sourceDir, relPath);
24556
26733
  if (!(relPath in previous)) {
24557
26734
  let size = 0;
24558
26735
  try {
@@ -24585,7 +26762,7 @@ function computeDiff(current, previous, sourceDir) {
24585
26762
  for (const relPath of Object.keys(previous)) {
24586
26763
  if (!(relPath in current)) {
24587
26764
  changes.push({
24588
- filePath: path30.join(sourceDir, relPath),
26765
+ filePath: path33.join(sourceDir, relPath),
24589
26766
  relativePath: relPath,
24590
26767
  type: "deleted",
24591
26768
  currentHash: "",
@@ -24615,21 +26792,21 @@ function hashContent3(content) {
24615
26792
  import { spawnSync } from "child_process";
24616
26793
  import crypto7 from "crypto";
24617
26794
  import fs7 from "fs";
24618
- import path31 from "path";
26795
+ import path34 from "path";
24619
26796
  var historicalIdCache4 = new HistoricalEntityCanonicalIdCache();
24620
26797
  var MANIFEST_VERSION = 1;
24621
26798
  var MANIFEST_LOCK_STALE_MS = 3e4;
24622
26799
  var MANIFEST_LOCK_TIMEOUT_MS = MANIFEST_LOCK_STALE_MS + 1e4;
24623
26800
  var MANIFEST_LOCK_SLEEP_MS = 20;
24624
26801
  function normalizeSpaceMemoryDir(memoryDir) {
24625
- return path31.resolve(memoryDir);
26802
+ return path34.resolve(memoryDir);
24626
26803
  }
24627
26804
  function getSpacesDir(baseDir) {
24628
26805
  const homeDir = baseDir ?? resolveHomeDir();
24629
- return path31.join(homeDir, ".config", "engram", "spaces");
26806
+ return path34.join(homeDir, ".config", "engram", "spaces");
24630
26807
  }
24631
26808
  function getManifestPath(baseDir) {
24632
- return path31.join(getSpacesDir(baseDir), "manifest.json");
26809
+ return path34.join(getSpacesDir(baseDir), "manifest.json");
24633
26810
  }
24634
26811
  function loadManifest(baseDir, memoryDirOverride) {
24635
26812
  if (fs7.existsSync(getManifestPath(baseDir))) {
@@ -24676,9 +26853,9 @@ function readManifestUnlocked(baseDir, memoryDirOverride, options = {}) {
24676
26853
  }
24677
26854
  function saveManifestUnlocked(manifest, baseDir) {
24678
26855
  const manifestPath2 = getManifestPath(baseDir);
24679
- const manifestDir2 = path31.dirname(manifestPath2);
26856
+ const manifestDir2 = path34.dirname(manifestPath2);
24680
26857
  fs7.mkdirSync(manifestDir2, { recursive: true });
24681
- const tempPath = path31.join(manifestDir2, `.manifest.${process.pid}.${Date.now()}.${crypto7.randomUUID()}.tmp`);
26858
+ const tempPath = path34.join(manifestDir2, `.manifest.${process.pid}.${Date.now()}.${crypto7.randomUUID()}.tmp`);
24682
26859
  try {
24683
26860
  fs7.writeFileSync(tempPath, `${JSON.stringify(manifest, null, 2)}
24684
26861
  `, { flag: "wx" });
@@ -24693,7 +26870,7 @@ function saveManifestUnlocked(manifest, baseDir) {
24693
26870
  }
24694
26871
  function withManifestLock(baseDir, operation) {
24695
26872
  const lockDir = `${getManifestPath(baseDir)}.lock`;
24696
- fs7.mkdirSync(path31.dirname(lockDir), { recursive: true });
26873
+ fs7.mkdirSync(path34.dirname(lockDir), { recursive: true });
24697
26874
  const lockOwner = acquireManifestLock(lockDir);
24698
26875
  try {
24699
26876
  return operation();
@@ -24719,7 +26896,7 @@ function acquireManifestLock(lockDir) {
24719
26896
  try {
24720
26897
  fs7.mkdirSync(lockDir, { recursive: false });
24721
26898
  try {
24722
- fs7.writeFileSync(path31.join(lockDir, "owner"), `${owner}
26899
+ fs7.writeFileSync(path34.join(lockDir, "owner"), `${owner}
24723
26900
  `, { flag: "wx" });
24724
26901
  } catch (error) {
24725
26902
  fs7.rmSync(lockDir, { recursive: true, force: true });
@@ -24749,7 +26926,7 @@ function acquireManifestLock(lockDir) {
24749
26926
  }
24750
26927
  function releaseManifestLock(lockDir, owner) {
24751
26928
  try {
24752
- const ownerPath = path31.join(lockDir, "owner");
26929
+ const ownerPath = path34.join(lockDir, "owner");
24753
26930
  if (fs7.readFileSync(ownerPath, "utf8").trim() === owner) {
24754
26931
  fs7.rmSync(lockDir, { recursive: true, force: true });
24755
26932
  }
@@ -24765,7 +26942,7 @@ function removeStaleManifestLock(lockDir) {
24765
26942
  try {
24766
26943
  fs7.mkdirSync(reclaimDir, { recursive: false });
24767
26944
  try {
24768
- fs7.writeFileSync(path31.join(reclaimDir, "owner"), `${reclaimOwner}
26945
+ fs7.writeFileSync(path34.join(reclaimDir, "owner"), `${reclaimOwner}
24769
26946
  `, { flag: "wx" });
24770
26947
  } catch (error) {
24771
26948
  fs7.rmSync(reclaimDir, { recursive: true, force: true });
@@ -24830,9 +27007,9 @@ function removeStaleManifestReclaimLock(reclaimDir) {
24830
27007
  fs7.rmSync(tombstoneDir, { recursive: true, force: true });
24831
27008
  }
24832
27009
  function readManifestLockSnapshot(lockDir) {
24833
- let stat5;
27010
+ let stat6;
24834
27011
  try {
24835
- stat5 = fs7.statSync(lockDir);
27012
+ stat6 = fs7.statSync(lockDir);
24836
27013
  } catch (error) {
24837
27014
  if (error.code === "ENOENT") {
24838
27015
  return void 0;
@@ -24840,11 +27017,11 @@ function readManifestLockSnapshot(lockDir) {
24840
27017
  throw error;
24841
27018
  }
24842
27019
  try {
24843
- const owner = fs7.readFileSync(path31.join(lockDir, "owner"), "utf8").trim();
24844
- return { mtimeMs: stat5.mtimeMs, owner };
27020
+ const owner = fs7.readFileSync(path34.join(lockDir, "owner"), "utf8").trim();
27021
+ return { mtimeMs: stat6.mtimeMs, owner };
24845
27022
  } catch (error) {
24846
27023
  if (error.code === "ENOENT") {
24847
- return { mtimeMs: stat5.mtimeMs };
27024
+ return { mtimeMs: stat6.mtimeMs };
24848
27025
  }
24849
27026
  throw error;
24850
27027
  }
@@ -24912,8 +27089,8 @@ function sleepSync(ms) {
24912
27089
  }
24913
27090
  function createPersonalSpace(baseDir, memoryDirOverride) {
24914
27091
  const homeDir = baseDir ?? resolveHomeDir();
24915
- const standalonePath = path31.join(homeDir, ".engram", "memory");
24916
- const openclawPath = path31.join(homeDir, ".openclaw", "workspace", "memory", "local");
27092
+ const standalonePath = path34.join(homeDir, ".engram", "memory");
27093
+ const openclawPath = path34.join(homeDir, ".openclaw", "workspace", "memory", "local");
24917
27094
  const memoryDir = memoryDirOverride ?? readEnvVar("REMNIC_MEMORY_DIR") ?? readEnvVar("ENGRAM_MEMORY_DIR") ?? (fs7.existsSync(standalonePath) ? standalonePath : fs7.existsSync(openclawPath) ? openclawPath : standalonePath);
24918
27095
  const normalizedMemoryDir = normalizeSpaceMemoryDir(memoryDir);
24919
27096
  const now = (/* @__PURE__ */ new Date()).toISOString();
@@ -24942,7 +27119,7 @@ function createSpace(options) {
24942
27119
  const id = options.name.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-");
24943
27120
  const now = (/* @__PURE__ */ new Date()).toISOString();
24944
27121
  const memoryDir = normalizeSpaceMemoryDir(
24945
- options.memoryDir ?? path31.join(getSpacesDir(options.baseDir), id, "memory")
27122
+ options.memoryDir ?? path34.join(getSpacesDir(options.baseDir), id, "memory")
24946
27123
  );
24947
27124
  const space = updateManifest(options.baseDir, (manifest) => {
24948
27125
  if (manifest.spaces.some((s) => s.id === id)) {
@@ -25163,14 +27340,14 @@ async function mergeSpaces(sourceSpaceId, targetSpaceId, options) {
25163
27340
  };
25164
27341
  }
25165
27342
  function getAuditLog(baseDir) {
25166
- const auditPath = path31.join(getSpacesDir(baseDir), "audit.jsonl");
27343
+ const auditPath = path34.join(getSpacesDir(baseDir), "audit.jsonl");
25167
27344
  if (!fs7.existsSync(auditPath)) return [];
25168
27345
  const lines = fs7.readFileSync(auditPath, "utf8").trim().split("\n");
25169
27346
  return lines.filter((l) => l.trim()).map((l) => JSON.parse(l));
25170
27347
  }
25171
27348
  function appendAudit(entry, baseDir) {
25172
- const auditPath = path31.join(getSpacesDir(baseDir), "audit.jsonl");
25173
- fs7.mkdirSync(path31.dirname(auditPath), { recursive: true });
27349
+ const auditPath = path34.join(getSpacesDir(baseDir), "audit.jsonl");
27350
+ fs7.mkdirSync(path34.dirname(auditPath), { recursive: true });
25174
27351
  const full = {
25175
27352
  id: crypto7.randomUUID(),
25176
27353
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
@@ -25191,11 +27368,11 @@ async function copyMemories(sourceDir, targetDir, options) {
25191
27368
  sourceFiles.filter((p) => {
25192
27369
  const rp = safeRealpath(p);
25193
27370
  if (!rp || !isPathInsideRoot(rp, sourceRoot)) return false;
25194
- const rel = path31.relative(sourceRoot, rp);
25195
- const mapped = path31.resolve(targetRoot, rel);
27371
+ const rel = path34.relative(sourceRoot, rp);
27372
+ const mapped = path34.resolve(targetRoot, rel);
25196
27373
  if (!isPathInsideRoot(mapped, targetRoot)) return false;
25197
27374
  return classifyEntityRefWritePath(targetRoot, mapped) === "entity";
25198
- }).map((p) => path31.basename(p, ".md"))
27375
+ }).map((p) => path34.basename(p, ".md"))
25199
27376
  );
25200
27377
  const firstEntityId = sourceEntityIds.values().next().value;
25201
27378
  if (firstEntityId === void 0) {
@@ -25203,7 +27380,7 @@ async function copyMemories(sourceDir, targetDir, options) {
25203
27380
  }
25204
27381
  return withRawEntityPageMutation(
25205
27382
  targetRoot,
25206
- path31.join(targetRoot, "entities", `${firstEntityId}.md`),
27383
+ path34.join(targetRoot, "entities", `${firstEntityId}.md`),
25207
27384
  async () => copyPreparedMemories(
25208
27385
  sourceFiles,
25209
27386
  sourceRoot,
@@ -25230,14 +27407,14 @@ function copyPreparedMemories(sourceFiles, sourceRoot, targetRoot, sourceEntityI
25230
27407
  continue;
25231
27408
  }
25232
27409
  const content = fs7.readFileSync(sourcePath, "utf8");
25233
- const relativePath = path31.relative(sourceRoot, sourceRealPath);
25234
- const targetPath = path31.resolve(targetRoot, relativePath);
27410
+ const relativePath = path34.relative(sourceRoot, sourceRealPath);
27411
+ const targetPath = path34.resolve(targetRoot, relativePath);
25235
27412
  if (!isPathInsideRoot(targetPath, targetRoot)) {
25236
27413
  skipped++;
25237
27414
  continue;
25238
27415
  }
25239
27416
  const targetKind = classifyEntityRefWritePath(targetRoot, targetPath);
25240
- const idsAtCompare = historicalIdCache4.get(path31.join(targetRoot, "state"));
27417
+ const idsAtCompare = historicalIdCache4.get(path34.join(targetRoot, "state"));
25241
27418
  const sourceRef = targetKind === "memory" ? readEntityRefFromFrontmatter(content) : null;
25242
27419
  const refHasSourceClaimant = sourceRef !== null && sourceEntityIds.has(sourceRef);
25243
27420
  const canonicalContent = targetKind === "memory" && !refHasSourceClaimant ? canonicalizeEntityRefFrontmatter(content, idsAtCompare) : content;
@@ -25264,7 +27441,7 @@ function copyPreparedMemories(sourceFiles, sourceRoot, targetRoot, sourceEntityI
25264
27441
  if (fs7.existsSync(targetPath) && !options?.force) {
25265
27442
  const targetContent = fs7.readFileSync(targetPath, "utf8");
25266
27443
  const targetHash = hashContent4(targetContent);
25267
- if (hashContent4(canonicalContent) === targetHash && historicalIdCache4.get(path31.join(targetRoot, "state")) === idsAtCompare) {
27444
+ if (hashContent4(canonicalContent) === targetHash && historicalIdCache4.get(path34.join(targetRoot, "state")) === idsAtCompare) {
25268
27445
  skipped++;
25269
27446
  continue;
25270
27447
  }
@@ -25280,13 +27457,13 @@ function copyPreparedMemories(sourceFiles, sourceRoot, targetRoot, sourceEntityI
25280
27457
  continue;
25281
27458
  }
25282
27459
  }
25283
- fs7.mkdirSync(path31.dirname(targetPath), { recursive: true });
25284
- const targetParentRealPath = safeRealpath(path31.dirname(targetPath));
27460
+ fs7.mkdirSync(path34.dirname(targetPath), { recursive: true });
27461
+ const targetParentRealPath = safeRealpath(path34.dirname(targetPath));
25285
27462
  if (!targetParentRealPath || !isPathInsideRoot(targetParentRealPath, targetRoot)) {
25286
27463
  skipped++;
25287
27464
  continue;
25288
27465
  }
25289
- const stateDir = path31.join(targetRoot, "state");
27466
+ const stateDir = path34.join(targetRoot, "state");
25290
27467
  if (targetKind === "memory" && !refHasSourceClaimant) {
25291
27468
  const idsAtWrite = historicalIdCache4.get(stateDir);
25292
27469
  const written = canonicalizeEntityRefFrontmatter(content, idsAtWrite);
@@ -25330,7 +27507,7 @@ function copyPreparedMemories(sourceFiles, sourceRoot, targetRoot, sourceEntityI
25330
27507
  bumpMemoryCorpusVersionForDir(targetRoot);
25331
27508
  }
25332
27509
  if (reconcileNeeded) {
25333
- requestEntityCanonicalIdReconcileSync(path31.join(targetRoot, "state"));
27510
+ requestEntityCanonicalIdReconcileSync(path34.join(targetRoot, "state"));
25334
27511
  }
25335
27512
  return { merged, conflicts, skipped };
25336
27513
  }
@@ -25341,7 +27518,7 @@ function walkMd2(dir) {
25341
27518
  const results = [];
25342
27519
  function walk(d) {
25343
27520
  for (const entry of fs7.readdirSync(d, { withFileTypes: true })) {
25344
- const fullPath = path31.join(d, entry.name);
27521
+ const fullPath = path34.join(d, entry.name);
25345
27522
  if (entry.isSymbolicLink()) {
25346
27523
  continue;
25347
27524
  }
@@ -25370,8 +27547,8 @@ function safeRealpath(filePath) {
25370
27547
  }
25371
27548
  }
25372
27549
  function isPathInsideRoot(candidatePath, rootPath) {
25373
- const relative = path31.relative(rootPath, candidatePath);
25374
- return relative === "" || !relative.startsWith("..") && !path31.isAbsolute(relative);
27550
+ const relative = path34.relative(rootPath, candidatePath);
27551
+ return relative === "" || !relative.startsWith("..") && !path34.isAbsolute(relative);
25375
27552
  }
25376
27553
  function parseSimpleFrontmatter(content) {
25377
27554
  const match = content.match(/^---\n([\s\S]*?)\n---/);
@@ -25492,7 +27669,7 @@ var REMNIC_RECALL_DECISION_RULES = `## When to Use Recall vs Direct Read
25492
27669
  // src/memory-extension/codex-publisher.ts
25493
27670
  import fs8 from "fs";
25494
27671
  import os from "os";
25495
- import path32 from "path";
27672
+ import path35 from "path";
25496
27673
  var REMNIC_EXTENSION_DIR_NAME = "remnic";
25497
27674
  function resolveEnvHome(env) {
25498
27675
  if (env === void 0) return resolveHomeDir();
@@ -25501,12 +27678,12 @@ function resolveEnvHome(env) {
25501
27678
  function expandTildeWithHome(input, homeDir) {
25502
27679
  if (input === "~") return homeDir;
25503
27680
  if (input.startsWith("~/") || input.startsWith("~\\")) {
25504
- return path32.join(homeDir, input.slice(2));
27681
+ return path35.join(homeDir, input.slice(2));
25505
27682
  }
25506
27683
  return input;
25507
27684
  }
25508
27685
  function normalizeHostRoot(input, homeDir) {
25509
- return path32.resolve(expandTildeWithHome(input.trim(), homeDir));
27686
+ return path35.resolve(expandTildeWithHome(input.trim(), homeDir));
25510
27687
  }
25511
27688
  var CodexMemoryExtensionPublisher = class {
25512
27689
  hostId = "codex";
@@ -25520,12 +27697,12 @@ var CodexMemoryExtensionPublisher = class {
25520
27697
  async resolveExtensionRoot(env) {
25521
27698
  const homeDir = resolveEnvHome(env);
25522
27699
  const codexHomeInput = env === void 0 ? readEnvVar("CODEX_HOME")?.trim() : env.CODEX_HOME?.trim();
25523
- const codexHome = codexHomeInput ? normalizeHostRoot(codexHomeInput, homeDir) : path32.resolve(homeDir, ".codex");
25524
- return path32.join(codexHome, "memories_extensions", REMNIC_EXTENSION_DIR_NAME);
27700
+ const codexHome = codexHomeInput ? normalizeHostRoot(codexHomeInput, homeDir) : path35.resolve(homeDir, ".codex");
27701
+ return path35.join(codexHome, "memories_extensions", REMNIC_EXTENSION_DIR_NAME);
25525
27702
  }
25526
27703
  async isHostAvailable() {
25527
27704
  try {
25528
- const home = readEnvVar("CODEX_HOME")?.trim() || path32.join(resolveHomeDir(), ".codex");
27705
+ const home = readEnvVar("CODEX_HOME")?.trim() || path35.join(resolveHomeDir(), ".codex");
25529
27706
  return fs8.existsSync(home);
25530
27707
  } catch {
25531
27708
  return false;
@@ -25576,7 +27753,7 @@ When running inside the Codex phase-2 consolidation sandbox:
25576
27753
  }
25577
27754
  async publish(ctx) {
25578
27755
  const extensionRoot = await this.resolveExtensionRoot();
25579
- const instructionsPath = path32.join(extensionRoot, "instructions.md");
27756
+ const instructionsPath = path35.join(extensionRoot, "instructions.md");
25580
27757
  const filesWritten = [];
25581
27758
  const skipped = [];
25582
27759
  ctx.log.info(`Publishing Codex memory extension to ${extensionRoot}`);
@@ -25950,9 +28127,9 @@ async function generateActivityMemories(date, digestBody, config, deps) {
25950
28127
  }
25951
28128
 
25952
28129
  // src/session-summaries/index.ts
25953
- import { createHash as createHash9 } from "crypto";
25954
- import { lstat as lstat3, mkdir as mkdir7, readFile as readFile7, readdir as readdir4, rename, rm, stat as stat4, writeFile as writeFile7 } from "fs/promises";
25955
- import path33 from "path";
28130
+ import { createHash as createHash11 } from "crypto";
28131
+ import { lstat as lstat5, mkdir as mkdir8, readFile as readFile7, readdir as readdir5, rename as rename2, rm as rm2, stat as stat5, writeFile as writeFile7 } from "fs/promises";
28132
+ import path36 from "path";
25956
28133
 
25957
28134
  // src/session-summaries/adapters.ts
25958
28135
  var VALID_ROLES = /* @__PURE__ */ new Set(["user", "assistant", "tool", "system", "other"]);
@@ -26452,28 +28629,28 @@ var DEFAULT_MAX_FILES = 5e3;
26452
28629
  var DEFAULT_MAX_SESSIONS = 500;
26453
28630
  var SUPPORTED_EXTENSIONS = /* @__PURE__ */ new Set([".json", ".jsonl"]);
26454
28631
  function shortHash(value, length = 16) {
26455
- return createHash9("sha256").update(value).digest("hex").slice(0, length);
28632
+ return createHash11("sha256").update(value).digest("hex").slice(0, length);
26456
28633
  }
26457
28634
  async function listTranscriptFiles(root, maxFiles) {
26458
28635
  const out = [];
26459
28636
  let truncated = false;
26460
- const entrySortKey = (entryName, isDirectory) => isDirectory ? `${entryName}${path33.sep}` : entryName;
28637
+ const entrySortKey = (entryName, isDirectory) => isDirectory ? `${entryName}${path36.sep}` : entryName;
26461
28638
  async function visit(dir) {
26462
28639
  if (truncated) return;
26463
- const entries = (await readdir4(dir, { withFileTypes: true })).sort(
28640
+ const entries = (await readdir5(dir, { withFileTypes: true })).sort(
26464
28641
  (a, b) => entrySortKey(a.name, a.isDirectory()).localeCompare(entrySortKey(b.name, b.isDirectory()))
26465
28642
  );
26466
28643
  for (const entry of entries) {
26467
28644
  if (truncated) return;
26468
28645
  if (entry.name.startsWith(".")) continue;
26469
28646
  if (entry.isSymbolicLink()) continue;
26470
- const fullPath = path33.join(dir, entry.name);
28647
+ const fullPath = path36.join(dir, entry.name);
26471
28648
  if (entry.isDirectory()) {
26472
28649
  await visit(fullPath);
26473
28650
  continue;
26474
28651
  }
26475
28652
  if (!entry.isFile()) continue;
26476
- const ext = path33.extname(entry.name).toLowerCase();
28653
+ const ext = path36.extname(entry.name).toLowerCase();
26477
28654
  if (!SUPPORTED_EXTENSIONS.has(ext)) continue;
26478
28655
  out.push(fullPath);
26479
28656
  if (out.length > maxFiles) {
@@ -26500,7 +28677,7 @@ function normalizeInputDir(inputDir) {
26500
28677
  if (typeof inputDir !== "string" || inputDir.trim().length === 0) {
26501
28678
  throw new Error("inputDir must be a non-empty string");
26502
28679
  }
26503
- return path33.resolve(expandTildePath(inputDir.trim()));
28680
+ return path36.resolve(expandTildePath(inputDir.trim()));
26504
28681
  }
26505
28682
  function initRoleCounts() {
26506
28683
  return {
@@ -26595,11 +28772,11 @@ function buildDraft(options) {
26595
28772
  }
26596
28773
  async function collectLocalSessionSummaries(options) {
26597
28774
  const inputDir = normalizeInputDir(options.inputDir);
26598
- const inputLstat = await lstat3(inputDir);
28775
+ const inputLstat = await lstat5(inputDir);
26599
28776
  if (inputLstat.isSymbolicLink()) {
26600
28777
  throw new Error(`inputDir must not be a symbolic link: ${options.inputDir}`);
26601
28778
  }
26602
- const inputStat = await stat4(inputDir);
28779
+ const inputStat = await stat5(inputDir);
26603
28780
  if (!inputStat.isDirectory()) {
26604
28781
  throw new Error(`inputDir must be a directory: ${options.inputDir}`);
26605
28782
  }
@@ -26657,11 +28834,11 @@ async function collectLocalSessionSummaries(options) {
26657
28834
  continue;
26658
28835
  }
26659
28836
  seenFileHashes.add(fileHash);
26660
- const fileExtension = path33.extname(filePath).toLowerCase();
28837
+ const fileExtension = path36.extname(filePath).toLowerCase();
26661
28838
  const parsed = await adapter.parseFile(
26662
28839
  {
26663
28840
  content,
26664
- fileName: path33.basename(filePath),
28841
+ fileName: path36.basename(filePath),
26665
28842
  fileExtension,
26666
28843
  fileRef: fileHash
26667
28844
  },
@@ -26717,7 +28894,7 @@ async function collectLocalSessionSummaries(options) {
26717
28894
  }
26718
28895
  async function readRedactionConfig(pathLike) {
26719
28896
  if (!pathLike) return void 0;
26720
- const raw = await readFile7(path33.resolve(expandTildePath(pathLike)), "utf-8");
28897
+ const raw = await readFile7(path36.resolve(expandTildePath(pathLike)), "utf-8");
26721
28898
  const parsed = JSON.parse(raw);
26722
28899
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
26723
28900
  throw new Error("redaction config must be a JSON object");
@@ -26730,21 +28907,21 @@ function toJsonl(drafts) {
26730
28907
  }
26731
28908
  function defaultDraftOutputPath(memoryDir, generatedAt) {
26732
28909
  const stamp = generatedAt.replace(/[:.]/g, "-");
26733
- return path33.join(
26734
- path33.resolve(expandTildePath(memoryDir)),
28910
+ return path36.join(
28911
+ path36.resolve(expandTildePath(memoryDir)),
26735
28912
  "state",
26736
28913
  "session-summary-drafts",
26737
28914
  `session-summaries-${stamp}.jsonl`
26738
28915
  );
26739
28916
  }
26740
28917
  async function writeDrafts(filePath, drafts) {
26741
- await mkdir7(path33.dirname(filePath), { recursive: true });
28918
+ await mkdir8(path36.dirname(filePath), { recursive: true });
26742
28919
  const tempPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
26743
28920
  try {
26744
28921
  await writeFile7(tempPath, toJsonl(drafts), "utf-8");
26745
- await rename(tempPath, filePath);
28922
+ await rename2(tempPath, filePath);
26746
28923
  } catch (error) {
26747
- await rm(tempPath, { force: true });
28924
+ await rm2(tempPath, { force: true });
26748
28925
  throw error;
26749
28926
  }
26750
28927
  }
@@ -26756,7 +28933,7 @@ async function runLocalSessionSummaryCliCommand(options) {
26756
28933
  });
26757
28934
  const wroteFiles = [];
26758
28935
  if (options.output) {
26759
- const outputPath = path33.resolve(expandTildePath(options.output));
28936
+ const outputPath = path36.resolve(expandTildePath(options.output));
26760
28937
  await writeDrafts(outputPath, report.drafts);
26761
28938
  wroteFiles.push(outputPath);
26762
28939
  }
@@ -26790,20 +28967,20 @@ async function runLocalSessionSummaryCliCommand(options) {
26790
28967
  }
26791
28968
 
26792
28969
  // src/transfer/capsule-fork.ts
26793
- import { lstat as lstat4, mkdir as mkdir8, readFile as readFile8, realpath as realpath3, writeFile as writeFile8 } from "fs/promises";
26794
- import path34 from "path";
28970
+ import { lstat as lstat6, mkdir as mkdir9, readFile as readFile8, realpath as realpath3, writeFile as writeFile8 } from "fs/promises";
28971
+ import path37 from "path";
26795
28972
  async function forkCapsule(opts) {
26796
28973
  validateForkId(opts.forkId);
26797
- const rootAbs = path34.resolve(opts.targetRoot);
28974
+ const rootAbs = path37.resolve(opts.targetRoot);
26798
28975
  await assertIsDirectoryNotSymlink(rootAbs, "forkCapsule", "targetRoot");
26799
- const forkDirAbs = path34.join(rootAbs, "forks", opts.forkId);
28976
+ const forkDirAbs = path37.join(rootAbs, "forks", opts.forkId);
26800
28977
  const forkEntryExists = await pathEntryExists(forkDirAbs);
26801
28978
  if (forkEntryExists) {
26802
28979
  throw new Error(
26803
28980
  `forkCapsule: fork path already exists \u2014 forkId "${opts.forkId}" is already in use at: ${forkDirAbs}`
26804
28981
  );
26805
28982
  }
26806
- const archiveAbs = path34.resolve(opts.sourceArchive);
28983
+ const archiveAbs = path37.resolve(opts.sourceArchive);
26807
28984
  const importResult = await importCapsule({
26808
28985
  archivePath: archiveAbs,
26809
28986
  root: rootAbs,
@@ -26825,10 +29002,10 @@ async function forkCapsule(opts) {
26825
29002
  importedRecords: importResult.imported.length,
26826
29003
  skippedRecords: importResult.skipped.length
26827
29004
  };
26828
- const lineagePath = path34.join(forkDirAbs, "lineage.json");
29005
+ const lineagePath = path37.join(forkDirAbs, "lineage.json");
26829
29006
  const rootReal = await realpath3(rootAbs);
26830
29007
  await assertRealpathInsideRoot(rootReal, lineagePath, `forks/${opts.forkId}/lineage.json`, "forkCapsule");
26831
- await mkdir8(path34.dirname(lineagePath), { recursive: true });
29008
+ await mkdir9(path37.dirname(lineagePath), { recursive: true });
26832
29009
  await writeFile8(lineagePath, JSON.stringify(lineage, null, 2) + "\n", "utf-8");
26833
29010
  return {
26834
29011
  archivePath: archiveAbs,
@@ -26842,11 +29019,11 @@ async function readForkLineage(targetRoot, forkId) {
26842
29019
  if (typeof forkId !== "string" || forkId.length === 0 || forkId.length > 64 || !CAPSULE_ID_PATTERN.test(forkId)) {
26843
29020
  return null;
26844
29021
  }
26845
- const rootAbs = path34.resolve(targetRoot);
29022
+ const rootAbs = path37.resolve(targetRoot);
26846
29023
  const rootReal = await realpath3(rootAbs).catch(() => rootAbs);
26847
- const lineagePath = path34.join(rootReal, "forks", forkId, "lineage.json");
26848
- const rel = path34.relative(rootReal, lineagePath);
26849
- if (rel.startsWith("..") || path34.isAbsolute(rel)) {
29024
+ const lineagePath = path37.join(rootReal, "forks", forkId, "lineage.json");
29025
+ const rel = path37.relative(rootReal, lineagePath);
29026
+ if (rel.startsWith("..") || path37.isAbsolute(rel)) {
26850
29027
  return null;
26851
29028
  }
26852
29029
  if (!await isLineagePathContained(rootReal, lineagePath)) {
@@ -26881,30 +29058,45 @@ function validateForkId(forkId) {
26881
29058
  }
26882
29059
  }
26883
29060
  async function pathEntryExists(absPath) {
26884
- const st = await lstat4(absPath).catch(() => null);
29061
+ const st = await lstat6(absPath).catch(() => null);
26885
29062
  return st !== null;
26886
29063
  }
26887
29064
  async function isLineagePathContained(rootReal, lineagePath) {
26888
29065
  let existing = lineagePath;
26889
29066
  const suffix = [];
26890
- while (existing !== path34.dirname(existing)) {
26891
- const st = await lstat4(existing).catch(() => null);
29067
+ while (existing !== path37.dirname(existing)) {
29068
+ const st = await lstat6(existing).catch(() => null);
26892
29069
  if (st !== null) break;
26893
- suffix.unshift(path34.basename(existing));
26894
- existing = path34.dirname(existing);
29070
+ suffix.unshift(path37.basename(existing));
29071
+ existing = path37.dirname(existing);
26895
29072
  }
26896
29073
  const existingReal = await realpath3(existing).catch(() => existing);
26897
- const targetReal = suffix.length > 0 ? path34.join(existingReal, ...suffix) : existingReal;
26898
- const rel = path34.relative(rootReal, targetReal);
29074
+ const targetReal = suffix.length > 0 ? path37.join(existingReal, ...suffix) : existingReal;
29075
+ const rel = path37.relative(rootReal, targetReal);
26899
29076
  if (rel === "") return true;
26900
29077
  if (rel === "..") return false;
26901
- if (rel.startsWith(`..${path34.sep}`)) return false;
26902
- if (path34.isAbsolute(rel)) return false;
29078
+ if (rel.startsWith(`..${path37.sep}`)) return false;
29079
+ if (path37.isAbsolute(rel)) return false;
26903
29080
  return true;
26904
29081
  }
26905
29082
 
26906
29083
  export {
26907
29084
  buildProcedureRecallSection,
29085
+ SupportPassportError,
29086
+ SupportPassportCardService,
29087
+ SupportPassportGrantCardRefSchema,
29088
+ SupportPassportGrantStateSchema,
29089
+ SupportPassportCreateGrantInputSchema,
29090
+ SupportPassportOwnerGrantSchema,
29091
+ SupportPassportCreatedGrantSchema,
29092
+ SupportPassportPublicCardSchema,
29093
+ SupportPassportPublicGuideSchema,
29094
+ SupportPassportRevokeGrantInputSchema,
29095
+ SupportPassportListGrantsInputSchema,
29096
+ notifySupportPassportCommitted,
29097
+ syncDirectoryForDurability,
29098
+ SupportPassportGrantStore,
29099
+ SupportPassportGrantService,
26908
29100
  RELAY_DEMO_MISSION_ID,
26909
29101
  RELAY_DEMO_NAMESPACE,
26910
29102
  createRelayMissionFixture,
@@ -27018,4 +29210,4 @@ export {
27018
29210
  blendGraphExpandedRecallScore,
27019
29211
  Orchestrator
27020
29212
  };
27021
- //# sourceMappingURL=chunk-CYF6WVE7.js.map
29213
+ //# sourceMappingURL=chunk-7HG7MGAP.js.map