@remnic/core 9.52.2 → 9.54.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (429) hide show
  1. package/dist/access-admin-ops-surface.d.ts +11 -11
  2. package/dist/access-admin-ops-surface.js +22 -22
  3. package/dist/access-authorization-probe.d.ts +11 -11
  4. package/dist/access-authorization-probe.js +23 -23
  5. package/dist/access-boundary.d.ts +11 -11
  6. package/dist/access-boundary.js +22 -22
  7. package/dist/access-cli.js +55 -55
  8. package/dist/access-coding-context-resolution.d.ts +1 -1
  9. package/dist/access-extraction-force-flush.d.ts +11 -11
  10. package/dist/access-extraction-force-flush.js +22 -22
  11. package/dist/access-health-types.d.ts +1 -1
  12. package/dist/access-http-lcm-compaction.d.ts +11 -11
  13. package/dist/access-http-lifecycle-flush.d.ts +11 -11
  14. package/dist/access-http-offline-stream.d.ts +11 -11
  15. package/dist/access-http-query.js +22 -22
  16. package/dist/access-http.d.ts +11 -11
  17. package/dist/access-http.js +29 -29
  18. package/dist/access-identity-continuity-surface.d.ts +9 -9
  19. package/dist/access-identity-continuity-surface.js +22 -22
  20. package/dist/access-lcm-surface.d.ts +11 -11
  21. package/dist/access-lcm-surface.js +22 -22
  22. package/dist/access-mcp.d.ts +11 -11
  23. package/dist/access-mcp.js +27 -27
  24. package/dist/access-memory-search-fanout.d.ts +2 -2
  25. package/dist/{access-namespace-preflight-Ds6CGlCP.d.ts → access-namespace-preflight-C7n4tgWC.d.ts} +1 -1
  26. package/dist/access-namespace-preflight.d.ts +3 -3
  27. package/dist/access-namespace-preflight.js +22 -22
  28. package/dist/access-observe-write-surface.d.ts +11 -11
  29. package/dist/access-observe-write-surface.js +22 -22
  30. package/dist/access-offline-manifest.d.ts +9 -9
  31. package/dist/access-offline-manifest.js +8 -4
  32. package/dist/access-operations-batch.js +24 -24
  33. package/dist/access-operations.d.ts +14 -14
  34. package/dist/access-operations.js +26 -26
  35. package/dist/access-recall-concurrency.d.ts +11 -11
  36. package/dist/access-recall-concurrency.js +22 -22
  37. package/dist/access-recall-response.d.ts +11 -11
  38. package/dist/access-recall-response.js +22 -22
  39. package/dist/access-recall-surface.d.ts +11 -11
  40. package/dist/access-recall-surface.js +22 -22
  41. package/dist/access-schema.d.ts +88 -88
  42. package/dist/{access-service-Cbk3bNbD.d.ts → access-service-CXvbxLK-.d.ts} +7 -7
  43. package/dist/access-service-helpers.d.ts +11 -11
  44. package/dist/access-service.d.ts +11 -11
  45. package/dist/access-service.js +22 -22
  46. package/dist/access-surface-catalog.d.ts +11 -11
  47. package/dist/access-wearables-meetings-surface.d.ts +3 -3
  48. package/dist/action-confidence.d.ts +1 -1
  49. package/dist/active-memory-bridge.d.ts +1 -1
  50. package/dist/active-recall.d.ts +1 -1
  51. package/dist/active-recall.js +5 -5
  52. package/dist/ambient-provenance.d.ts +1 -1
  53. package/dist/artifact-search.d.ts +1 -1
  54. package/dist/{auto-sync-QFQGOEO2.js → auto-sync-TDHLZPVP.js} +7 -7
  55. package/dist/behavior-learner.d.ts +1 -1
  56. package/dist/behavior-signals.d.ts +1 -1
  57. package/dist/bootstrap.d.ts +9 -9
  58. package/dist/briefing.d.ts +2 -2
  59. package/dist/briefing.js +12 -12
  60. package/dist/buffer-surprise-report.d.ts +1 -1
  61. package/dist/buffer-turn-helpers.d.ts +1 -1
  62. package/dist/buffer.d.ts +2 -2
  63. package/dist/bulk-import/index.d.ts +3 -3
  64. package/dist/calibration.d.ts +1 -1
  65. package/dist/capabilities.d.ts +1 -1
  66. package/dist/{catalog-D3B4RDy1.d.ts → catalog-BOOxl-I2.d.ts} +1 -1
  67. package/dist/causal-behavior.d.ts +1 -1
  68. package/dist/causal-consolidation.d.ts +1 -1
  69. package/dist/causal-consolidation.js +13 -13
  70. package/dist/causal-trajectory-graph.d.ts +1 -1
  71. package/dist/{chunk-MLXZD4WM.js → chunk-2GFK22OZ.js} +2 -2
  72. package/dist/{chunk-RANKJI5T.js → chunk-3JLPGJ43.js} +2 -2
  73. package/dist/{chunk-O5FFBO2M.js → chunk-47P3RYZP.js} +70 -8
  74. package/dist/{chunk-O5FFBO2M.js.map → chunk-47P3RYZP.js.map} +1 -1
  75. package/dist/{chunk-X7XEDOSL.js → chunk-4IIFL7GC.js} +8 -8
  76. package/dist/chunk-5FVVY2EB.js +27 -0
  77. package/dist/chunk-5FVVY2EB.js.map +1 -0
  78. package/dist/{chunk-GXSOUIA4.js → chunk-5WQMORU5.js} +4 -4
  79. package/dist/{chunk-J272WKX2.js → chunk-6HPHEFXT.js} +2 -2
  80. package/dist/{chunk-B6LZ4IBH.js → chunk-6LAPLZOS.js} +2 -2
  81. package/dist/{chunk-WD5B5AIE.js → chunk-6R4G7N4S.js} +118 -173
  82. package/dist/chunk-6R4G7N4S.js.map +1 -0
  83. package/dist/{chunk-VXCNQYTC.js → chunk-APPFNGX6.js} +2 -2
  84. package/dist/{chunk-GXFSQ6SD.js → chunk-C4ZNGVK3.js} +2 -2
  85. package/dist/{chunk-JSEJH2YQ.js → chunk-CGVHPCP2.js} +2 -2
  86. package/dist/{chunk-BQIFZ2MP.js → chunk-CX5SW2EW.js} +41 -24
  87. package/dist/chunk-CX5SW2EW.js.map +1 -0
  88. package/dist/{chunk-RMHMUUBW.js → chunk-CYF6WVE7.js} +105 -49
  89. package/dist/{chunk-RMHMUUBW.js.map → chunk-CYF6WVE7.js.map} +1 -1
  90. package/dist/{chunk-TEMSWHQD.js → chunk-DZD576ZU.js} +5 -5
  91. package/dist/{chunk-AMTEYNYK.js → chunk-EVWWT3KE.js} +4 -4
  92. package/dist/{chunk-P2KBDJJ6.js → chunk-G2LUMAUF.js} +4 -3
  93. package/dist/{chunk-P2KBDJJ6.js.map → chunk-G2LUMAUF.js.map} +1 -1
  94. package/dist/{chunk-AXIDQG5A.js → chunk-G4T7L557.js} +5 -5
  95. package/dist/{chunk-7M6NYQWB.js → chunk-G7Z6EENO.js} +4 -4
  96. package/dist/{chunk-IARXXZU4.js → chunk-HOIRB77A.js} +99 -20
  97. package/dist/chunk-HOIRB77A.js.map +1 -0
  98. package/dist/{chunk-NDAH7BJ5.js → chunk-HVP33QVW.js} +103 -6
  99. package/dist/chunk-HVP33QVW.js.map +1 -0
  100. package/dist/{chunk-YXKVLYXU.js → chunk-HWRD23DW.js} +2 -2
  101. package/dist/{chunk-SOEN6KCF.js → chunk-IBKR2TFR.js} +2 -2
  102. package/dist/{chunk-R3DJVOSM.js → chunk-JDSVLVCG.js} +8 -1
  103. package/dist/chunk-JDSVLVCG.js.map +1 -0
  104. package/dist/{chunk-F4EU6VUC.js → chunk-JDZPNCMA.js} +2 -2
  105. package/dist/{chunk-D5YOZ66N.js → chunk-JV5YUBIZ.js} +20 -20
  106. package/dist/{chunk-DLG5V6ND.js → chunk-K4QS7LXU.js} +4 -7
  107. package/dist/chunk-K4QS7LXU.js.map +1 -0
  108. package/dist/{chunk-BAKXNQ3C.js → chunk-KRTY3ENI.js} +2 -2
  109. package/dist/{chunk-NK5RGJ65.js → chunk-L4DLLKPN.js} +2 -2
  110. package/dist/{chunk-VFSAWRMZ.js → chunk-LJS7KUPV.js} +2 -2
  111. package/dist/{chunk-JJRVPWFY.js → chunk-MLPTFODV.js} +166 -37
  112. package/dist/chunk-MLPTFODV.js.map +1 -0
  113. package/dist/{chunk-NOEMGE56.js → chunk-NH5IR2WM.js} +2 -2
  114. package/dist/{chunk-5V6IXHPI.js → chunk-NSVDUN76.js} +2 -2
  115. package/dist/{chunk-W7Y5JDVB.js → chunk-PDDTI7IC.js} +4 -4
  116. package/dist/{chunk-QINJITDS.js → chunk-PX2LSHYM.js} +2 -2
  117. package/dist/{chunk-HDIUYMSB.js → chunk-QWGE2PUH.js} +6 -6
  118. package/dist/{chunk-X57M2Q4I.js → chunk-RDJRFDJY.js} +3 -3
  119. package/dist/{chunk-RYLEDKQ2.js → chunk-RUMNY5DT.js} +3 -3
  120. package/dist/{chunk-BKIFTXHR.js → chunk-RZ4XGKOJ.js} +2 -2
  121. package/dist/{chunk-66SE3BNH.js → chunk-SUPEYLH2.js} +2 -2
  122. package/dist/{chunk-BF6SXNQJ.js → chunk-T2JHZWH6.js} +20 -20
  123. package/dist/{chunk-VHFXP27N.js → chunk-THPPCISA.js} +60 -23
  124. package/dist/chunk-THPPCISA.js.map +1 -0
  125. package/dist/{chunk-QPOHMO6M.js → chunk-UES4BHA2.js} +2 -2
  126. package/dist/{chunk-XAPMEU3K.js → chunk-UU7TRFNE.js} +2 -2
  127. package/dist/{chunk-QBSFOKY6.js → chunk-VOELBUS4.js} +4 -4
  128. package/dist/{chunk-2LY6GIIE.js → chunk-WDBX6VER.js} +2 -2
  129. package/dist/{chunk-BMEYMKWX.js → chunk-WM65LU67.js} +2 -2
  130. package/dist/{chunk-WLRD2TXF.js → chunk-WOPA3SGI.js} +4 -4
  131. package/dist/{chunk-5UZ6UCOZ.js → chunk-XUAMCLY4.js} +3 -3
  132. package/dist/{chunk-7HXZJAID.js → chunk-YGLY6QFV.js} +3 -3
  133. package/dist/{chunk-2OIQDTDC.js → chunk-ZPJ4QSGP.js} +2 -2
  134. package/dist/{chunk-3OY7KXHM.js → chunk-ZYLC7NFO.js} +3 -3
  135. package/dist/{cli-DMAFI0qt.d.ts → cli-DVUFIa5E.d.ts} +5 -5
  136. package/dist/cli.d.ts +13 -13
  137. package/dist/cli.js +42 -42
  138. package/dist/coding/pre-action-gate.d.ts +1 -1
  139. package/dist/compounding/engine.d.ts +2 -2
  140. package/dist/compounding/engine.js +13 -13
  141. package/dist/compounding/preference-consolidator.d.ts +1 -1
  142. package/dist/compression-optimizer.d.ts +1 -1
  143. package/dist/config.d.ts +1 -1
  144. package/dist/config.js +5 -5
  145. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  146. package/dist/connectors/codex-materialize-runner.js +12 -12
  147. package/dist/connectors/codex-materialize.d.ts +1 -1
  148. package/dist/connectors/index.d.ts +1 -1
  149. package/dist/connectors/index.js +12 -12
  150. package/dist/consolidation-provenance-check.d.ts +2 -2
  151. package/dist/consolidation-undo.d.ts +2 -2
  152. package/dist/content-hash.d.ts +12 -2
  153. package/dist/content-hash.js +9 -3
  154. package/dist/contradiction/index.d.ts +2 -2
  155. package/dist/contradiction/index.js +3 -3
  156. package/dist/converge-config.d.ts +1 -1
  157. package/dist/convergence-refresh.d.ts +2 -2
  158. package/dist/convergence-refresh.js +14 -14
  159. package/dist/conversation-index/backend.d.ts +1 -1
  160. package/dist/conversation-index/chunker.d.ts +1 -1
  161. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  162. package/dist/conversation-index/indexer.d.ts +1 -1
  163. package/dist/conversation-index/search.d.ts +1 -1
  164. package/dist/corpus-watermark.d.ts +1 -1
  165. package/dist/corpus-watermark.js +14 -14
  166. package/dist/day-summary.d.ts +1 -1
  167. package/dist/delinearize.d.ts +1 -1
  168. package/dist/dependency-propagation-config.d.ts +1 -1
  169. package/dist/{dependency-propagation-delivery-D63r24pH.d.ts → dependency-propagation-delivery-XzF76C9n.d.ts} +1 -1
  170. package/dist/direct-answer-wiring.d.ts +1 -1
  171. package/dist/direct-answer.d.ts +1 -1
  172. package/dist/embedding-fallback.d.ts +1 -1
  173. package/dist/enrichment/index.d.ts +1 -1
  174. package/dist/entity-retrieval.d.ts +2 -2
  175. package/dist/entity-retrieval.js +12 -12
  176. package/dist/entity-schema.d.ts +1 -1
  177. package/dist/explicit-capture.d.ts +9 -9
  178. package/dist/explicit-capture.js +8 -8
  179. package/dist/external-wiki-access.d.ts +11 -11
  180. package/dist/external-wiki-access.js +23 -23
  181. package/dist/external-wiki-collection-registration.d.ts +1 -1
  182. package/dist/external-wiki-collection.d.ts +1 -1
  183. package/dist/external-wiki-mcp-tools.d.ts +11 -11
  184. package/dist/extraction-error-classification.d.ts +1 -1
  185. package/dist/extraction-faithfulness.d.ts +1 -1
  186. package/dist/extraction-judge-telemetry.d.ts +1 -1
  187. package/dist/extraction-judge-training.d.ts +1 -1
  188. package/dist/extraction-judge.d.ts +1 -1
  189. package/dist/extraction-liveness.d.ts +1 -1
  190. package/dist/extraction-normalization.d.ts +1 -1
  191. package/dist/extraction-normalization.js +2 -2
  192. package/dist/extraction-prompt.d.ts +1 -1
  193. package/dist/extraction-source-grounding-rules.d.ts +1 -1
  194. package/dist/extraction-source-grounding.d.ts +1 -1
  195. package/dist/extraction-source-grounding.js +3 -3
  196. package/dist/extraction.d.ts +1 -1
  197. package/dist/extraction.js +16 -16
  198. package/dist/fallback-llm.d.ts +1 -1
  199. package/dist/{forget-HDS4N6CG.js → forget-EHGGJZLX.js} +3 -2
  200. package/dist/{forget-HDS4N6CG.js.map → forget-EHGGJZLX.js.map} +1 -1
  201. package/dist/graph-dashboard-diff.d.ts +1 -1
  202. package/dist/graph-dashboard-key.d.ts +1 -1
  203. package/dist/graph-dashboard-parser.d.ts +1 -1
  204. package/dist/graph-edge-reinforcement.d.ts +1 -1
  205. package/dist/graph-path-reconstruction.d.ts +1 -1
  206. package/dist/graph-path-scoring.d.ts +1 -1
  207. package/dist/graph-snapshot.d.ts +1 -1
  208. package/dist/graph.d.ts +1 -1
  209. package/dist/harmonic-construction.js +2 -2
  210. package/dist/harmonic-retrieval.js +4 -4
  211. package/dist/importance.d.ts +1 -1
  212. package/dist/importers/index.d.ts +1 -1
  213. package/dist/in-flight-reads.d.ts +1 -1
  214. package/dist/index.d.ts +777 -705
  215. package/dist/index.js +77 -67
  216. package/dist/intent.d.ts +1 -1
  217. package/dist/lcm/engine.d.ts +1 -1
  218. package/dist/lcm/index.d.ts +1 -1
  219. package/dist/lcm/tools.d.ts +1 -1
  220. package/dist/lifecycle.d.ts +1 -1
  221. package/dist/live-connectors-runner.d.ts +1 -1
  222. package/dist/local-llm.d.ts +1 -1
  223. package/dist/local-model-endpoint.d.ts +1 -1
  224. package/dist/maintenance/memory-governance.d.ts +1 -1
  225. package/dist/maintenance/memory-governance.js +12 -12
  226. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
  227. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +12 -12
  228. package/dist/maintenance/rebuild-memory-projection.d.ts +2 -2
  229. package/dist/maintenance/rebuild-memory-projection.js +13 -13
  230. package/dist/{maintenance-kBII2qUI.d.ts → maintenance-BJzNIKBE.d.ts} +3 -3
  231. package/dist/mcp-memory-inspector-app.d.ts +11 -11
  232. package/dist/memory-action-policy.d.ts +1 -1
  233. package/dist/memory-cache.d.ts +1 -1
  234. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  235. package/dist/memory-projection-store.d.ts +1 -1
  236. package/dist/memory-provenance.d.ts +1 -1
  237. package/dist/memory-snapshot.d.ts +1 -1
  238. package/dist/memory-worth-outcomes.d.ts +2 -2
  239. package/dist/models-json.d.ts +1 -1
  240. package/dist/namespaces/migrate.d.ts +3 -3
  241. package/dist/namespaces/migrate.js +13 -13
  242. package/dist/namespaces/principal.d.ts +1 -1
  243. package/dist/namespaces/search.d.ts +1 -1
  244. package/dist/namespaces/storage.d.ts +3 -3
  245. package/dist/namespaces/storage.js +12 -12
  246. package/dist/native-knowledge.d.ts +1 -1
  247. package/dist/offline-sync-impression-drain.d.ts +1 -1
  248. package/dist/operator-doctor-corpus.d.ts +1 -1
  249. package/dist/operator-doctor-corpus.js +15 -15
  250. package/dist/operator-doctor-replica.d.ts +1 -1
  251. package/dist/operator-toolkit.d.ts +3 -3
  252. package/dist/operator-toolkit.js +21 -21
  253. package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
  254. package/dist/orchestration/maintenance.d.ts +4 -4
  255. package/dist/orchestration/maintenance.js +17 -17
  256. package/dist/{orchestrator-DHy5LtTy.d.ts → orchestrator-BiXgBJBQ.d.ts} +8 -8
  257. package/dist/orchestrator.d.ts +9 -9
  258. package/dist/orchestrator.js +55 -55
  259. package/dist/patterns-cli.d.ts +1 -1
  260. package/dist/{pipeline-D21Rs6gW.d.ts → pipeline-sz_dcuLg.d.ts} +1 -1
  261. package/dist/policy-runtime.d.ts +1 -1
  262. package/dist/proactive-contention.d.ts +1 -1
  263. package/dist/provenance.d.ts +1 -1
  264. package/dist/provenance.js +2 -2
  265. package/dist/{qmd-Dhle1P4X.d.ts → qmd-eAWObK4M.d.ts} +1 -1
  266. package/dist/qmd-preflight.d.ts +2 -2
  267. package/dist/qmd-recall-cache.d.ts +1 -1
  268. package/dist/qmd.d.ts +2 -2
  269. package/dist/recall-concurrency-config.d.ts +1 -1
  270. package/dist/recall-disclosure-escalation.d.ts +1 -1
  271. package/dist/recall-explain-renderer.d.ts +1 -1
  272. package/dist/recall-memory-map.d.ts +1 -1
  273. package/dist/recall-planner-llm.d.ts +1 -1
  274. package/dist/recall-state.d.ts +1 -1
  275. package/dist/recall-tag-filter.d.ts +1 -1
  276. package/dist/recall-timings.d.ts +1 -1
  277. package/dist/recall-xray-cli.d.ts +1 -1
  278. package/dist/recall-xray-renderer.d.ts +1 -1
  279. package/dist/recall-xray.d.ts +1 -1
  280. package/dist/reconcile/cursor.d.ts +1 -1
  281. package/dist/reconcile/manifest.d.ts +4 -2
  282. package/dist/reconcile/manifest.js +7 -3
  283. package/dist/reconcile/plan.d.ts +1 -1
  284. package/dist/replay/normalizers/chatgpt.d.ts +1 -1
  285. package/dist/replay/normalizers/claude.d.ts +1 -1
  286. package/dist/replay/normalizers/openclaw.d.ts +1 -1
  287. package/dist/replay/normalizers/shared.d.ts +1 -1
  288. package/dist/replay/runner.d.ts +1 -1
  289. package/dist/replay/types.d.ts +1 -1
  290. package/dist/replica-divergence.d.ts +1 -1
  291. package/dist/replica-peers-config.d.ts +1 -1
  292. package/dist/{resolution-MDPNOEG6.js → resolution-MMOD5WC4.js} +4 -4
  293. package/dist/resolve-auth-token.d.ts +1 -1
  294. package/dist/resume-bundles.js +6 -6
  295. package/dist/retrieval-agents.d.ts +2 -2
  296. package/dist/retrieval-tiers.d.ts +1 -1
  297. package/dist/routing/engine.d.ts +1 -1
  298. package/dist/routing/store.d.ts +1 -1
  299. package/dist/salvage-envelope.d.ts +1 -1
  300. package/dist/salvage-envelope.js +3 -3
  301. package/dist/schemas.d.ts +138 -138
  302. package/dist/{scope-profiles-NzGPDXLn.d.ts → scope-profiles-BBQsXuyj.d.ts} +1 -1
  303. package/dist/search/embed-helper.d.ts +1 -1
  304. package/dist/search/factory.d.ts +1 -1
  305. package/dist/search/index.d.ts +1 -1
  306. package/dist/search/lancedb-backend.d.ts +1 -1
  307. package/dist/search/meilisearch-backend.d.ts +1 -1
  308. package/dist/search/noop-backend.d.ts +1 -1
  309. package/dist/search/orama-backend.d.ts +1 -1
  310. package/dist/search/port.d.ts +1 -1
  311. package/dist/search/remote-backend.d.ts +1 -1
  312. package/dist/{semantic-consolidation-DLDKvyy5.d.ts → semantic-consolidation-HD8RkzVA.d.ts} +1 -1
  313. package/dist/semantic-consolidation.d.ts +2 -2
  314. package/dist/semantic-consolidation.js +13 -13
  315. package/dist/semantic-rule-promotion.js +12 -12
  316. package/dist/semantic-rule-verifier.d.ts +1 -1
  317. package/dist/semantic-rule-verifier.js +12 -12
  318. package/dist/{service-PT2_z7xm.d.ts → service-DIrtHHEg.d.ts} +2 -2
  319. package/dist/session-observer-bands.d.ts +1 -1
  320. package/dist/session-observer-state.d.ts +1 -1
  321. package/dist/shared-context/manager.d.ts +9 -9
  322. package/dist/signal.d.ts +1 -1
  323. package/dist/source-agent-qualifier.d.ts +1 -1
  324. package/dist/source-agent-qualifier.js +14 -14
  325. package/dist/{storage-BmVudhk4.d.ts → storage-DqCzXi56.d.ts} +37 -33
  326. package/dist/storage.d.ts +2 -2
  327. package/dist/storage.js +14 -14
  328. package/dist/structured-attributes.d.ts +3 -1
  329. package/dist/structured-attributes.js +3 -1
  330. package/dist/summarizer.d.ts +1 -1
  331. package/dist/summary-snapshot.d.ts +1 -1
  332. package/dist/temporal-supersession.d.ts +2 -2
  333. package/dist/temporal-timeline-recall.d.ts +1 -1
  334. package/dist/temporal-validity.d.ts +1 -1
  335. package/dist/threading.d.ts +1 -1
  336. package/dist/tier-migration.d.ts +2 -2
  337. package/dist/tier-routing.d.ts +1 -1
  338. package/dist/topics.d.ts +1 -1
  339. package/dist/transcript.d.ts +1 -1
  340. package/dist/transfer/types.d.ts +66 -66
  341. package/dist/trust-score-stage.d.ts +1 -1
  342. package/dist/trust-score.d.ts +1 -1
  343. package/dist/{types-CkiDUorT.d.ts → types-d_j4vC6N.d.ts} +26 -1
  344. package/dist/types.d.ts +1 -1
  345. package/dist/utility-runtime.d.ts +1 -1
  346. package/dist/verified-recall.js +12 -12
  347. package/dist/write-envelope.d.ts +1 -1
  348. package/dist/write-envelope.js +2 -2
  349. package/package.json +2 -2
  350. package/src/access-offline-manifest.ts +1 -0
  351. package/src/access-service-offline-file-content.test.ts +1 -0
  352. package/src/content-hash.ts +34 -1
  353. package/src/dedup/index.test.ts +56 -38
  354. package/src/dedup/index.ts +85 -38
  355. package/src/lifecycle/tombstones.test.ts +763 -16
  356. package/src/lifecycle/tombstones.ts +217 -50
  357. package/src/reconcile/manifest.test.ts +158 -1
  358. package/src/reconcile/manifest.ts +76 -22
  359. package/src/storage/content-hash-index.ts +56 -40
  360. package/src/storage/entity-ref-repair.ts +3 -3
  361. package/src/storage/memory-read-store.ts +9 -0
  362. package/src/storage/tombstone-blocked-capture-index.ts +4 -9
  363. package/src/storage-contract/content-hash.test.ts +13 -0
  364. package/src/storage-fact-hash-index-defer.test.ts +1 -1
  365. package/src/storage.ts +107 -93
  366. package/src/structured-attributes.ts +11 -0
  367. package/src/wearables/cleanup.test.ts +71 -0
  368. package/src/wearables/cleanup.ts +163 -16
  369. package/src/wearables/config.test.ts +62 -0
  370. package/src/wearables/config.ts +99 -5
  371. package/src/wearables/index.ts +10 -0
  372. package/src/wearables/pipeline.test.ts +36 -0
  373. package/src/wearables/pipeline.ts +18 -3
  374. package/src/wearables/redaction.test.ts +156 -0
  375. package/src/wearables/redaction.ts +102 -10
  376. package/src/wearables/text-language.ts +146 -0
  377. package/src/wearables/types.ts +26 -0
  378. package/dist/chunk-BQIFZ2MP.js.map +0 -1
  379. package/dist/chunk-DLG5V6ND.js.map +0 -1
  380. package/dist/chunk-IARXXZU4.js.map +0 -1
  381. package/dist/chunk-JJRVPWFY.js.map +0 -1
  382. package/dist/chunk-NDAH7BJ5.js.map +0 -1
  383. package/dist/chunk-R3DJVOSM.js.map +0 -1
  384. package/dist/chunk-VHFXP27N.js.map +0 -1
  385. package/dist/chunk-W5H6ZRPT.js +0 -14
  386. package/dist/chunk-W5H6ZRPT.js.map +0 -1
  387. package/dist/chunk-WD5B5AIE.js.map +0 -1
  388. /package/dist/{auto-sync-QFQGOEO2.js.map → auto-sync-TDHLZPVP.js.map} +0 -0
  389. /package/dist/{chunk-MLXZD4WM.js.map → chunk-2GFK22OZ.js.map} +0 -0
  390. /package/dist/{chunk-RANKJI5T.js.map → chunk-3JLPGJ43.js.map} +0 -0
  391. /package/dist/{chunk-X7XEDOSL.js.map → chunk-4IIFL7GC.js.map} +0 -0
  392. /package/dist/{chunk-GXSOUIA4.js.map → chunk-5WQMORU5.js.map} +0 -0
  393. /package/dist/{chunk-J272WKX2.js.map → chunk-6HPHEFXT.js.map} +0 -0
  394. /package/dist/{chunk-B6LZ4IBH.js.map → chunk-6LAPLZOS.js.map} +0 -0
  395. /package/dist/{chunk-VXCNQYTC.js.map → chunk-APPFNGX6.js.map} +0 -0
  396. /package/dist/{chunk-GXFSQ6SD.js.map → chunk-C4ZNGVK3.js.map} +0 -0
  397. /package/dist/{chunk-JSEJH2YQ.js.map → chunk-CGVHPCP2.js.map} +0 -0
  398. /package/dist/{chunk-TEMSWHQD.js.map → chunk-DZD576ZU.js.map} +0 -0
  399. /package/dist/{chunk-AMTEYNYK.js.map → chunk-EVWWT3KE.js.map} +0 -0
  400. /package/dist/{chunk-AXIDQG5A.js.map → chunk-G4T7L557.js.map} +0 -0
  401. /package/dist/{chunk-7M6NYQWB.js.map → chunk-G7Z6EENO.js.map} +0 -0
  402. /package/dist/{chunk-YXKVLYXU.js.map → chunk-HWRD23DW.js.map} +0 -0
  403. /package/dist/{chunk-SOEN6KCF.js.map → chunk-IBKR2TFR.js.map} +0 -0
  404. /package/dist/{chunk-F4EU6VUC.js.map → chunk-JDZPNCMA.js.map} +0 -0
  405. /package/dist/{chunk-D5YOZ66N.js.map → chunk-JV5YUBIZ.js.map} +0 -0
  406. /package/dist/{chunk-BAKXNQ3C.js.map → chunk-KRTY3ENI.js.map} +0 -0
  407. /package/dist/{chunk-NK5RGJ65.js.map → chunk-L4DLLKPN.js.map} +0 -0
  408. /package/dist/{chunk-VFSAWRMZ.js.map → chunk-LJS7KUPV.js.map} +0 -0
  409. /package/dist/{chunk-NOEMGE56.js.map → chunk-NH5IR2WM.js.map} +0 -0
  410. /package/dist/{chunk-5V6IXHPI.js.map → chunk-NSVDUN76.js.map} +0 -0
  411. /package/dist/{chunk-W7Y5JDVB.js.map → chunk-PDDTI7IC.js.map} +0 -0
  412. /package/dist/{chunk-QINJITDS.js.map → chunk-PX2LSHYM.js.map} +0 -0
  413. /package/dist/{chunk-HDIUYMSB.js.map → chunk-QWGE2PUH.js.map} +0 -0
  414. /package/dist/{chunk-X57M2Q4I.js.map → chunk-RDJRFDJY.js.map} +0 -0
  415. /package/dist/{chunk-RYLEDKQ2.js.map → chunk-RUMNY5DT.js.map} +0 -0
  416. /package/dist/{chunk-BKIFTXHR.js.map → chunk-RZ4XGKOJ.js.map} +0 -0
  417. /package/dist/{chunk-66SE3BNH.js.map → chunk-SUPEYLH2.js.map} +0 -0
  418. /package/dist/{chunk-BF6SXNQJ.js.map → chunk-T2JHZWH6.js.map} +0 -0
  419. /package/dist/{chunk-QPOHMO6M.js.map → chunk-UES4BHA2.js.map} +0 -0
  420. /package/dist/{chunk-XAPMEU3K.js.map → chunk-UU7TRFNE.js.map} +0 -0
  421. /package/dist/{chunk-QBSFOKY6.js.map → chunk-VOELBUS4.js.map} +0 -0
  422. /package/dist/{chunk-2LY6GIIE.js.map → chunk-WDBX6VER.js.map} +0 -0
  423. /package/dist/{chunk-BMEYMKWX.js.map → chunk-WM65LU67.js.map} +0 -0
  424. /package/dist/{chunk-WLRD2TXF.js.map → chunk-WOPA3SGI.js.map} +0 -0
  425. /package/dist/{chunk-5UZ6UCOZ.js.map → chunk-XUAMCLY4.js.map} +0 -0
  426. /package/dist/{chunk-7HXZJAID.js.map → chunk-YGLY6QFV.js.map} +0 -0
  427. /package/dist/{chunk-2OIQDTDC.js.map → chunk-ZPJ4QSGP.js.map} +0 -0
  428. /package/dist/{chunk-3OY7KXHM.js.map → chunk-ZYLC7NFO.js.map} +0 -0
  429. /package/dist/{resolution-MDPNOEG6.js.map → resolution-MMOD5WC4.js.map} +0 -0
@@ -110,6 +110,55 @@ async function saveCorrectionsFile(memoryDir, rules) {
110
110
  }
111
111
  }
112
112
 
113
+ // src/wearables/text-language.ts
114
+ var PREFIXABLE_EDGE_CHAR = /[\p{Script=Latin}\p{Script=Cyrillic}\p{Script=Greek}\p{Script=Arabic}\p{Script=Hebrew}\p{Script=Hangul}\p{N}]/u;
115
+ var SUFFIXABLE_EDGE_CHAR = /[\p{Script=Latin}\p{Script=Cyrillic}\p{Script=Greek}\p{Script=Arabic}\p{Script=Hebrew}\p{N}\p{M}]/u;
116
+ var PROCLITIC_EDGE_CHAR = /[\p{Script=Arabic}\p{Script=Hebrew}]/u;
117
+ var PROCLITIC_LETTERS = "\u0648\u0641\u0628\u0643\u0644\u0633\u05D4\u05D5\u05DB\u05DC\u05DE\u05E9\u05D1";
118
+ var BOUNDARY_LOOKBEHIND = "(?<![\\p{L}\\p{M}\\p{N}])";
119
+ var BOUNDARY_LOOKAHEAD = "(?![\\p{L}\\p{M}\\p{N}])";
120
+ var PROCLITIC_LOOKBEHIND = `(?:${BOUNDARY_LOOKBEHIND}|(?<=${BOUNDARY_LOOKBEHIND}[${PROCLITIC_LETTERS}]))`;
121
+ var HAS_KANA = /[\p{Script=Hiragana}\p{Script=Katakana}]/u;
122
+ var HAS_HAN = /\p{Script=Han}/u;
123
+ var HAS_HANGUL = /\p{Script=Hangul}/u;
124
+ var HAS_ARABIC = /\p{Script=Arabic}/u;
125
+ var HAS_CYRILLIC = /\p{Script=Cyrillic}/u;
126
+ function foldForMatching(text) {
127
+ return text.normalize("NFC").replace(/[\u0131\u0130I]/g, "i");
128
+ }
129
+ function detectScriptHints(text) {
130
+ const hints = ["latin"];
131
+ if (HAS_KANA.test(text)) hints.push("japanese");
132
+ else if (HAS_HAN.test(text)) hints.push("han");
133
+ if (HAS_HANGUL.test(text)) hints.push("korean");
134
+ if (HAS_ARABIC.test(text)) hints.push("arabic");
135
+ if (HAS_CYRILLIC.test(text)) hints.push("cyrillic");
136
+ return hints;
137
+ }
138
+ function escapeRegExp2(value) {
139
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
140
+ }
141
+ function buildPhraseMatcher(phrases) {
142
+ const parts = [];
143
+ const seen = /* @__PURE__ */ new Set();
144
+ for (const raw of phrases) {
145
+ if (typeof raw !== "string") continue;
146
+ const phrase = foldForMatching(raw.trim());
147
+ if (phrase.length === 0) continue;
148
+ const key = phrase.toLowerCase();
149
+ if (seen.has(key)) continue;
150
+ seen.add(key);
151
+ const characters = Array.from(phrase);
152
+ const body = phrase.split(/\s+/).map((word) => escapeRegExp2(word)).join("\\s+");
153
+ const first = characters[0];
154
+ const lead = PROCLITIC_EDGE_CHAR.test(first) ? PROCLITIC_LOOKBEHIND : PREFIXABLE_EDGE_CHAR.test(first) ? BOUNDARY_LOOKBEHIND : "";
155
+ const tail = SUFFIXABLE_EDGE_CHAR.test(characters[characters.length - 1]) ? BOUNDARY_LOOKAHEAD : "";
156
+ parts.push(`${lead}${body}${tail}`);
157
+ }
158
+ if (parts.length === 0) return null;
159
+ return new RegExp(parts.join("|"), "iu");
160
+ }
161
+
113
162
  // src/wearables/redaction.ts
114
163
  var REDACTION_PLACEHOLDER = "[redacted]";
115
164
  var BUILT_IN_PATTERNS = [
@@ -163,14 +212,57 @@ function compileRedactionPatterns(patterns) {
163
212
  }
164
213
  });
165
214
  }
166
- var OFF_THE_RECORD = /\boff\s+the\s+record\b/i;
167
- var BACK_ON_THE_RECORD = /\b(?:back\s+)?on\s+the\s+record\b/i;
168
- function applyOffTheRecord(conversation) {
215
+ var BUILT_IN_OFF_THE_RECORD_START = [
216
+ "off the record",
217
+ "fuera de registro",
218
+ "extraoficialmente",
219
+ "fora de registro",
220
+ "fora do registro",
221
+ "hors micro",
222
+ "nicht f\xFCrs protokoll",
223
+ "nicht f\xFCr das protokoll",
224
+ "fuori registro",
225
+ "\u30AA\u30D5\u30EC\u30B3",
226
+ "\uC624\uD504\uB354\uB808\uCF54\uB4DC",
227
+ "\u4E0D\u8981\u8BB0\u5F55",
228
+ "\u043D\u0435 \u0434\u043B\u044F \u043F\u0440\u043E\u0442\u043E\u043A\u043E\u043B\u0430",
229
+ "\u0628\u062F\u0648\u0646 \u062A\u0633\u062C\u064A\u0644"
230
+ ];
231
+ var BUILT_IN_OFF_THE_RECORD_END = [
232
+ "back on the record",
233
+ "on the record",
234
+ "de nuevo en registro",
235
+ "de volta ao registro",
236
+ "wieder f\xFCrs protokoll",
237
+ "wieder f\xFCr das protokoll",
238
+ "\u30AA\u30F3\u30EC\u30B3",
239
+ "\uC628\uB354\uB808\uCF54\uB4DC"
240
+ ];
241
+ function compileOffTheRecordMarkers(settings) {
242
+ const useBuiltIns = settings?.useBuiltIns !== false;
243
+ const start = [
244
+ ...useBuiltIns ? BUILT_IN_OFF_THE_RECORD_START : [],
245
+ ...settings?.start ?? []
246
+ ];
247
+ const end = [
248
+ ...useBuiltIns ? BUILT_IN_OFF_THE_RECORD_END : [],
249
+ ...settings?.end ?? []
250
+ ];
251
+ return {
252
+ start: buildPhraseMatcher(start),
253
+ end: buildPhraseMatcher(end)
254
+ };
255
+ }
256
+ function applyOffTheRecord(conversation, markers = compileOffTheRecordMarkers()) {
257
+ if (!markers.start) {
258
+ return { conversation, droppedSegments: 0 };
259
+ }
169
260
  let offRecord = false;
170
261
  let droppedSegments = 0;
171
262
  const segments = [];
172
263
  for (const segment of conversation.segments) {
173
- if (!offRecord && OFF_THE_RECORD.test(segment.text)) {
264
+ const probe = foldForMatching(segment.text);
265
+ if (!offRecord && markers.start.test(probe)) {
174
266
  offRecord = true;
175
267
  segments.push({
176
268
  ...segment,
@@ -179,7 +271,7 @@ function applyOffTheRecord(conversation) {
179
271
  continue;
180
272
  }
181
273
  if (offRecord) {
182
- if (BACK_ON_THE_RECORD.test(segment.text)) {
274
+ if (markers.end?.test(probe)) {
183
275
  offRecord = false;
184
276
  segments.push({
185
277
  ...segment,
@@ -205,9 +297,14 @@ export {
205
297
  correctionsFilePath,
206
298
  loadCorrectionsFile,
207
299
  saveCorrectionsFile,
300
+ detectScriptHints,
301
+ buildPhraseMatcher,
208
302
  REDACTION_PLACEHOLDER,
209
303
  redactText,
210
304
  compileRedactionPatterns,
305
+ BUILT_IN_OFF_THE_RECORD_START,
306
+ BUILT_IN_OFF_THE_RECORD_END,
307
+ compileOffTheRecordMarkers,
211
308
  applyOffTheRecord
212
309
  };
213
- //# sourceMappingURL=chunk-NDAH7BJ5.js.map
310
+ //# sourceMappingURL=chunk-HVP33QVW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/wearables/corrections.ts","../src/wearables/text-language.ts","../src/wearables/redaction.ts"],"sourcesContent":["/**\n * Wearable transcript corrections — user-specific replacement rules.\n *\n * ASR engines consistently mishear the same proper nouns for the same\n * person (\"remnick\" for \"Remnic\", a colleague's name, product jargon).\n * Rules come from two places, merged at sync time:\n *\n * 1. `wearables.corrections` in plugin config (declarative, versioned\n * with the operator's config).\n * 2. A CLI-managed rules file at `state/wearables/corrections.json`\n * (added interactively via `remnic wearables corrections add`).\n *\n * Literal rules are regex-escaped before compilation and replacements\n * are applied via a function (never a replacement string) so `$` in\n * either side can't corrupt output.\n */\n\nimport { promises as fsPromises } from \"node:fs\";\nimport * as path from \"node:path\";\n\nimport type { WearableCorrectionRule } from \"./types.js\";\n\nexport interface CompiledCorrectionRule {\n rule: WearableCorrectionRule;\n pattern: RegExp;\n}\n\nexport interface CorrectionApplication {\n text: string;\n applied: number;\n}\n\n/** Hard cap on rule pattern length (bounds hostile/pathological regexes). */\nconst MAX_PATTERN_LENGTH = 256;\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\n/**\n * Validate and compile a correction rule. Throws a descriptive error on\n * invalid input (empty match, regex that doesn't compile, regex that\n * matches the empty string) — callers surface this at config parse or\n * CLI time rather than skipping the rule silently.\n */\nexport function compileCorrectionRule(\n rule: WearableCorrectionRule,\n label: string,\n): CompiledCorrectionRule {\n if (typeof rule.match !== \"string\" || rule.match.length === 0) {\n throw new Error(`${label}: match must be a non-empty string`);\n }\n if (rule.match.length > MAX_PATTERN_LENGTH) {\n throw new Error(\n `${label}: match exceeds ${MAX_PATTERN_LENGTH} characters — correction patterns must stay short`,\n );\n }\n if (typeof rule.replace !== \"string\") {\n throw new Error(`${label}: replace must be a string`);\n }\n const flags = rule.caseInsensitive === false ? \"g\" : \"gi\";\n let pattern: RegExp;\n if (rule.regex === true) {\n try {\n // Operator-supplied regexes are the documented feature here\n // (rules live in the operator's own config / state file, never in\n // request input); the length cap above bounds pathological\n // patterns. CodeQL js/regex-injection is dismissed by design for\n // this site.\n pattern = new RegExp(rule.match, flags);\n } catch (err) {\n throw new Error(\n `${label}: match is not a valid regular expression: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n } else {\n // Literal rules match on word boundaries when both edges of the\n // match are word characters, so \"remnick\" doesn't fire inside\n // \"remnickson\" unless the user opts into regex mode.\n const escaped = escapeRegExp(rule.match);\n const leading = /^[\\p{L}\\p{N}_]/u.test(rule.match) ? \"\\\\b\" : \"\";\n const trailing = /[\\p{L}\\p{N}_]$/u.test(rule.match) ? \"\\\\b\" : \"\";\n pattern = new RegExp(`${leading}${escaped}${trailing}`, flags);\n }\n if (pattern.test(\"\")) {\n throw new Error(\n `${label}: pattern matches the empty string and would corrupt every transcript`,\n );\n }\n pattern.lastIndex = 0;\n return { rule, pattern };\n}\n\n/** Compile a rule list, labeling errors with their index. */\nexport function compileCorrectionRules(\n rules: WearableCorrectionRule[],\n labelPrefix: string,\n): CompiledCorrectionRule[] {\n return rules.map((rule, index) =>\n compileCorrectionRule(rule, `${labelPrefix}[${index}]`),\n );\n}\n\n/** Apply every applicable rule to a piece of transcript text. */\nexport function applyCorrections(\n text: string,\n rules: CompiledCorrectionRule[],\n sourceId: string,\n): CorrectionApplication {\n let applied = 0;\n let result = text;\n for (const { rule, pattern } of rules) {\n if (\n Array.isArray(rule.sources) &&\n rule.sources.length > 0 &&\n !rule.sources.includes(sourceId)\n ) {\n continue;\n }\n pattern.lastIndex = 0;\n result = result.replace(pattern, () => {\n applied += 1;\n // Replacement via function: `$` in rule.replace stays literal.\n return rule.replace;\n });\n }\n return { text: result, applied };\n}\n\n// ---------------------------------------------------------------------------\n// CLI-managed rules file\n// ---------------------------------------------------------------------------\n\ninterface CorrectionsFileShape {\n version: 1;\n rules: WearableCorrectionRule[];\n}\n\nexport function correctionsFilePath(memoryDir: string): string {\n return path.join(memoryDir, \"state\", \"wearables\", \"corrections.json\");\n}\n\n/**\n * Load CLI-managed correction rules. A missing file means no rules; a\n * malformed file throws (operators should know their corrections are\n * not being applied rather than silently losing them).\n */\nexport async function loadCorrectionsFile(\n memoryDir: string,\n): Promise<WearableCorrectionRule[]> {\n const filePath = correctionsFilePath(memoryDir);\n let raw: string;\n try {\n raw = await fsPromises.readFile(filePath, \"utf-8\");\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return [];\n throw err;\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (err) {\n throw new Error(\n `wearables corrections file is not valid JSON (state/wearables/corrections.json): ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n if (\n typeof parsed !== \"object\" ||\n parsed === null ||\n Array.isArray(parsed) ||\n !Array.isArray((parsed as CorrectionsFileShape).rules)\n ) {\n throw new Error(\n 'wearables corrections file has an unexpected shape (state/wearables/corrections.json); expected {\"version\":1,\"rules\":[...]}',\n );\n }\n const rules = (parsed as CorrectionsFileShape).rules;\n // Validate every persisted rule up front so a hand-edited bad rule\n // fails at load with its index, not mid-sync.\n compileCorrectionRules(rules, \"state corrections\");\n return rules;\n}\n\n/** Persist CLI-managed rules atomically (temp file + rename). */\nexport async function saveCorrectionsFile(\n memoryDir: string,\n rules: WearableCorrectionRule[],\n): Promise<void> {\n compileCorrectionRules(rules, \"state corrections\");\n const filePath = correctionsFilePath(memoryDir);\n await fsPromises.mkdir(path.dirname(filePath), { recursive: true });\n const payload: CorrectionsFileShape = { version: 1, rules };\n const tmpPath = `${filePath}.tmp-${process.pid}-${Date.now().toString(36)}`;\n await fsPromises.writeFile(\n tmpPath,\n `${JSON.stringify(payload, null, 2)}\\n`,\n \"utf-8\",\n );\n try {\n await fsPromises.rename(tmpPath, filePath);\n } catch (err) {\n // Clean up the temp file on rename failure; the original (if any)\n // is untouched.\n await fsPromises.unlink(tmpPath).catch(() => undefined);\n throw err;\n }\n}\n","/**\n * Script-aware text helpers shared by wearable cleanup and redaction.\n *\n * Both features were written for space-delimited English. A spoken\n * marker phrase or a filler token in Japanese, Korean, Chinese, Arabic,\n * or Russian never matched, so a privacy feature silently did nothing\n * (issue #2196). These helpers make phrase matching correct for scripts\n * that do not separate words with spaces.\n */\n\n/** Coarse script class used to select built-in token sets. */\nexport type ScriptHint =\n | \"latin\"\n | \"japanese\"\n | \"han\"\n | \"korean\"\n | \"arabic\"\n | \"cyrillic\";\n\n/**\n * Whether a phrase edge needs a word boundary is decided per EDGE and per\n * script, because scripts attach material at different ends.\n *\n * Leading edge: guarded for every script that spaces its words, so a\n * marker cannot match at the tail of a longer word — Korean `기록` must\n * not fire inside `신기록`, Arabic `خاص` must not fire inside `أشخاص`.\n * Arabic and Hebrew additionally write single-letter proclitics (`و`,\n * `ف`, `ב`, `ל`) with no space, so their guard admits ONE such letter\n * when that letter itself starts a word: `وبدون تسجيل` still reaches the\n * built-in `بدون تسجيل`.\n *\n * Trailing edge: guarded for the space-delimited scripts, so `بدون تسجيل`\n * does not match inside `بدون تسجيلات`. Hangul is excluded — Korean\n * particles attach to the END of a word, and guarding there would stop\n * `기록을` from matching `기록`.\n *\n * Han and Kana running text has no boundary at either end: requiring one\n * is the bug that made every non-Latin marker unreachable.\n */\nconst PREFIXABLE_EDGE_CHAR =\n /[\\p{Script=Latin}\\p{Script=Cyrillic}\\p{Script=Greek}\\p{Script=Arabic}\\p{Script=Hebrew}\\p{Script=Hangul}\\p{N}]/u;\nconst SUFFIXABLE_EDGE_CHAR =\n /[\\p{Script=Latin}\\p{Script=Cyrillic}\\p{Script=Greek}\\p{Script=Arabic}\\p{Script=Hebrew}\\p{N}\\p{M}]/u;\nconst PROCLITIC_EDGE_CHAR = /[\\p{Script=Arabic}\\p{Script=Hebrew}]/u;\n\n/**\n * Single-letter proclitics that attach to the following word in Arabic\n * and Hebrew. Kept to the unambiguous conjunctions and prepositions;\n * a longer prefix is a different word, not a clitic.\n */\nconst PROCLITIC_LETTERS = \"وفبكلسהוכלמשב\";\n\n/**\n * Combining marks count as word characters. Without `\\p{M}` a decomposed\n * `café` (base `e` plus U+0301) would let the phrase `cafe` match its\n * prefix and elide a span nobody marked.\n */\nconst BOUNDARY_LOOKBEHIND = \"(?<![\\\\p{L}\\\\p{M}\\\\p{N}])\";\nconst BOUNDARY_LOOKAHEAD = \"(?![\\\\p{L}\\\\p{M}\\\\p{N}])\";\n/** Word start, or exactly one word-initial proclitic before the phrase. */\nconst PROCLITIC_LOOKBEHIND = `(?:${BOUNDARY_LOOKBEHIND}|(?<=${BOUNDARY_LOOKBEHIND}[${PROCLITIC_LETTERS}]))`;\n\nconst HAS_KANA = /[\\p{Script=Hiragana}\\p{Script=Katakana}]/u;\nconst HAS_HAN = /\\p{Script=Han}/u;\nconst HAS_HANGUL = /\\p{Script=Hangul}/u;\nconst HAS_ARABIC = /\\p{Script=Arabic}/u;\nconst HAS_CYRILLIC = /\\p{Script=Cyrillic}/u;\n\n/**\n * Normalize text for phrase matching: NFC, then fold the Turkic dotted and\n * dotless I onto plain `i`.\n *\n * JavaScript's `/iu` folding is locale-independent, so it equates `i` with\n * `I` but never `ı` with `I` or `i` with `İ`. A Turkish marker such as\n * `kayıt dışı` would therefore miss an uppercase `KAYIT DIŞI` transcript and\n * leave the span on the record. Both sides of the comparison run through\n * this, so the fold cannot make one side drift from the other.\n */\nexport function foldForMatching(text: string): string {\n return text.normalize(\"NFC\").replace(/[\\u0131\\u0130I]/g, \"i\");\n}\n\n/**\n * Report which script-specific token sets apply to `text`.\n *\n * `latin` is always present: transcripts mix scripts freely, and the\n * Latin filler tokens are whole-token matches that cannot fire inside\n * non-Latin text. Japanese wins over Han when kana are present, because\n * Japanese text also contains Han characters.\n */\nexport function detectScriptHints(text: string): ScriptHint[] {\n const hints: ScriptHint[] = [\"latin\"];\n if (HAS_KANA.test(text)) hints.push(\"japanese\");\n else if (HAS_HAN.test(text)) hints.push(\"han\");\n if (HAS_HANGUL.test(text)) hints.push(\"korean\");\n if (HAS_ARABIC.test(text)) hints.push(\"arabic\");\n if (HAS_CYRILLIC.test(text)) hints.push(\"cyrillic\");\n return hints;\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\n/**\n * Compile `phrases` into one case-insensitive matcher, or `null` when\n * no usable phrase remains.\n *\n * Internal whitespace matches any whitespace run, so a transcript that\n * breaks a phrase across a line still matches. Letter boundaries are\n * added per edge, and only when that edge is a space-delimited script.\n */\nexport function buildPhraseMatcher(\n phrases: readonly string[],\n): RegExp | null {\n const parts: string[] = [];\n const seen = new Set<string>();\n for (const raw of phrases) {\n if (typeof raw !== \"string\") continue;\n // Folded on both sides (the tester folds its input too): an ASR that\n // emits decomposed or Turkic-uppercase text would otherwise never match\n // its marker, and the span would be persisted (issue #2196).\n const phrase = foldForMatching(raw.trim());\n if (phrase.length === 0) continue;\n const key = phrase.toLowerCase();\n if (seen.has(key)) continue;\n seen.add(key);\n const characters = Array.from(phrase);\n const body = phrase\n .split(/\\s+/)\n .map((word) => escapeRegExp(word))\n .join(\"\\\\s+\");\n const first = characters[0];\n const lead = PROCLITIC_EDGE_CHAR.test(first)\n ? PROCLITIC_LOOKBEHIND\n : PREFIXABLE_EDGE_CHAR.test(first)\n ? BOUNDARY_LOOKBEHIND\n : \"\";\n const tail = SUFFIXABLE_EDGE_CHAR.test(characters[characters.length - 1])\n ? BOUNDARY_LOOKAHEAD\n : \"\";\n parts.push(`${lead}${body}${tail}`);\n }\n if (parts.length === 0) return null;\n return new RegExp(parts.join(\"|\"), \"iu\");\n}\n","/**\n * Wearable transcript redaction — privacy guard applied before any\n * transcript text is persisted or fed to extraction.\n *\n * Always-on recorders capture things nobody intended to store: card\n * numbers read aloud, SSNs dictated to a pharmacy line. Built-in\n * patterns cover the unambiguous, high-sensitivity cases; users can add\n * their own regexes via `wearables.redactionPatterns` (validated at\n * config parse — invalid patterns are rejected loudly, never ignored).\n *\n * All built-in patterns are simple linear scans (no nested quantifiers)\n * to stay safely outside polynomial-ReDoS territory.\n */\n\nimport { buildPhraseMatcher, foldForMatching } from \"./text-language.js\";\nimport type {\n OffTheRecordMarkerSettings,\n WearableConversation,\n} from \"./types.js\";\n\nexport const REDACTION_PLACEHOLDER = \"[redacted]\";\n\n/**\n * Built-in patterns. Conservative by design — false positives erase\n * real transcript content, so each pattern targets formats that are\n * near-certain PII:\n * - US SSN with separators (123-45-6789). Bare 9-digit runs are NOT\n * matched (too many false positives: ids, tracking numbers).\n * - Payment-card-like runs: 13–19 digits in groups separated by\n * spaces/dashes (4111 1111 1111 1111) or contiguous 15–16 digits.\n */\nconst BUILT_IN_PATTERNS: RegExp[] = [\n /\\b\\d{3}-\\d{2}-\\d{4}\\b/g,\n // Starts and ENDS on a digit so a trailing separator is never\n // consumed (replacing it would glue the placeholder to the next word).\n /\\b\\d(?:[ -]?\\d){12,18}\\b/g,\n];\n\n/** Minimum digit count before a digit-run is treated as a card number. */\nconst CARD_MIN_DIGITS = 13;\n\nexport interface RedactionResult {\n text: string;\n redactions: number;\n}\n\nexport function redactText(\n text: string,\n userPatterns: RegExp[],\n): RedactionResult {\n let redactions = 0;\n let result = text;\n\n // SSN pattern first (more specific than the digit-run pattern).\n result = result.replace(BUILT_IN_PATTERNS[0], () => {\n redactions += 1;\n return REDACTION_PLACEHOLDER;\n });\n\n // Digit-run pattern with a post-match digit-count check so short\n // grouped numbers (\"call 555 0125 today\") survive.\n result = result.replace(BUILT_IN_PATTERNS[1], (match) => {\n const digits = match.replace(/\\D/g, \"\");\n if (digits.length < CARD_MIN_DIGITS || digits.length > 19) {\n return match;\n }\n redactions += 1;\n return REDACTION_PLACEHOLDER;\n });\n\n for (const pattern of userPatterns) {\n result = result.replace(pattern, () => {\n redactions += 1;\n return REDACTION_PLACEHOLDER;\n });\n }\n\n return { text: result, redactions };\n}\n\n/**\n * Compile user-supplied redaction patterns. Throws with a descriptive\n * message on the first invalid pattern — config parsing surfaces this\n * to the operator instead of silently skipping the rule.\n */\nexport function compileRedactionPatterns(patterns: string[]): RegExp[] {\n return patterns.map((pattern, index) => {\n if (typeof pattern !== \"string\" || pattern.trim().length === 0) {\n throw new Error(\n `wearables.redactionPatterns[${index}] must be a non-empty string`,\n );\n }\n if (pattern.length > 256) {\n throw new Error(\n `wearables.redactionPatterns[${index}] exceeds 256 characters — redaction patterns must stay short`,\n );\n }\n try {\n // Operator-supplied regexes from the operator's own config —\n // length-capped above; never request input.\n return new RegExp(pattern, \"gi\");\n } catch (err) {\n throw new Error(\n `wearables.redactionPatterns[${index}] is not a valid regular expression: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n });\n}\n\n/**\n * Built-in phrases that BEGIN an off-the-record span.\n *\n * Conservative by design: a false positive elides real transcript\n * content. Every phrase is a fixed multi-word expression, or a loanword\n * that only means \"off the record\" (issue #2196). Operators extend this\n * list through `wearables.offTheRecordMarkers.start`.\n */\nexport const BUILT_IN_OFF_THE_RECORD_START: readonly string[] = [\n \"off the record\",\n \"fuera de registro\",\n \"extraoficialmente\",\n \"fora de registro\",\n \"fora do registro\",\n \"hors micro\",\n \"nicht fürs protokoll\",\n \"nicht für das protokoll\",\n \"fuori registro\",\n \"オフレコ\",\n \"오프더레코드\",\n \"不要记录\",\n \"не для протокола\",\n \"بدون تسجيل\",\n];\n\n/**\n * Built-in phrases that END an off-the-record span.\n *\n * Shorter than the start list on purpose. A start phrase with no\n * matching end phrase elides through the end of the conversation, which\n * is the fail-closed direction; an over-eager end phrase would leak. So\n * a language only appears here when the phrase is unambiguous.\n */\nexport const BUILT_IN_OFF_THE_RECORD_END: readonly string[] = [\n \"back on the record\",\n \"on the record\",\n \"de nuevo en registro\",\n \"de volta ao registro\",\n \"wieder fürs protokoll\",\n \"wieder für das protokoll\",\n \"オンレコ\",\n \"온더레코드\",\n];\n\n/**\n * Loose form of the parsed `OffTheRecordMarkerSettings`: callers that\n * only override one field pass a partial, so every property is\n * optional and read-only here.\n */\nexport type OffTheRecordMarkerInput = {\n readonly [K in keyof OffTheRecordMarkerSettings]?: K extends \"useBuiltIns\"\n ? boolean\n : readonly string[];\n};\n\nexport interface CompiledOffTheRecordMarkers {\n start: RegExp | null;\n end: RegExp | null;\n}\n\n/**\n * Compile marker settings into matchers. Omitting `settings` yields the\n * built-in lists, so callers that never configured markers keep the\n * previous behavior plus the new languages.\n */\nexport function compileOffTheRecordMarkers(\n settings?: OffTheRecordMarkerInput,\n): CompiledOffTheRecordMarkers {\n const useBuiltIns = settings?.useBuiltIns !== false;\n const start = [\n ...(useBuiltIns ? BUILT_IN_OFF_THE_RECORD_START : []),\n ...(settings?.start ?? []),\n ];\n const end = [\n ...(useBuiltIns ? BUILT_IN_OFF_THE_RECORD_END : []),\n ...(settings?.end ?? []),\n ];\n return {\n start: buildPhraseMatcher(start),\n end: buildPhraseMatcher(end),\n };\n}\n\nexport interface OffTheRecordResult {\n conversation: WearableConversation;\n droppedSegments: number;\n}\n\n/**\n * Drop segments between a spoken off-the-record marker and the next\n * back-on-the-record marker (or conversation end). The marker segments\n * themselves are kept, with the off-record span replaced by a visible\n * placeholder so the transcript shows that content was elided by\n * request rather than lost.\n */\nexport function applyOffTheRecord(\n conversation: WearableConversation,\n markers: CompiledOffTheRecordMarkers = compileOffTheRecordMarkers(),\n): OffTheRecordResult {\n if (!markers.start) {\n return { conversation, droppedSegments: 0 };\n }\n let offRecord = false;\n let droppedSegments = 0;\n const segments = [];\n for (const segment of conversation.segments) {\n // Matched folded, stored as written: the transcript keeps the ASR's own\n // bytes while a decomposed or Turkic-uppercase spelling still reaches\n // the marker.\n const probe = foldForMatching(segment.text);\n if (!offRecord && markers.start.test(probe)) {\n offRecord = true;\n segments.push({\n ...segment,\n text: \"[off the record — segment elided]\",\n });\n continue;\n }\n if (offRecord) {\n if (markers.end?.test(probe)) {\n offRecord = false;\n segments.push({\n ...segment,\n text: \"[back on the record]\",\n });\n } else {\n droppedSegments += 1;\n }\n continue;\n }\n segments.push(segment);\n }\n return {\n conversation: { ...conversation, segments },\n droppedSegments,\n };\n}\n"],"mappings":"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","names":["escapeRegExp"]}
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-KJTKLXTH.js";
4
4
  import {
5
5
  StorageManager
6
- } from "./chunk-WD5B5AIE.js";
6
+ } from "./chunk-6R4G7N4S.js";
7
7
  import {
8
8
  copyExistingFileToBackup,
9
9
  writeFileAtomically
@@ -260,4 +260,4 @@ export {
260
260
  backupExistingLedger,
261
261
  rebuildMemoryLifecycleLedger
262
262
  };
263
- //# sourceMappingURL=chunk-YXKVLYXU.js.map
263
+ //# sourceMappingURL=chunk-HWRD23DW.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  applyExtractionSourceGrounding
3
- } from "./chunk-NK5RGJ65.js";
3
+ } from "./chunk-L4DLLKPN.js";
4
4
  import {
5
5
  CONNECTOR_LABEL_MAX_LENGTH,
6
6
  knownConnectorIds
@@ -108,4 +108,4 @@ export {
108
108
  renderExtractionConversation,
109
109
  applyGroundingWithConnector
110
110
  };
111
- //# sourceMappingURL=chunk-SOEN6KCF.js.map
111
+ //# sourceMappingURL=chunk-IBKR2TFR.js.map
@@ -13,6 +13,12 @@ function stripAttributesSuffix(content) {
13
13
  if (inner.includes("]") || inner.includes("\n")) return content.trim();
14
14
  return trimmed.slice(0, markerIndex).trim();
15
15
  }
16
+ function storedContentIdentityCandidates(content, stripCitation) {
17
+ const fullBody = content.trim();
18
+ const bodyWithoutAttributes = stripAttributesSuffix(fullBody);
19
+ const rawBody = stripCitation(bodyWithoutAttributes);
20
+ return [.../* @__PURE__ */ new Set([rawBody, bodyWithoutAttributes, fullBody])];
21
+ }
16
22
  function normalizeAttributePairs(pairs) {
17
23
  return Object.entries(pairs).map(([k, v]) => [k.trim().toLowerCase(), v.trim()]).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => `${k}: ${v}`).join("; ");
18
24
  }
@@ -28,7 +34,8 @@ function assemblePersistedBody(content, structuredAttributes) {
28
34
 
29
35
  export {
30
36
  stripAttributesSuffix,
37
+ storedContentIdentityCandidates,
31
38
  normalizeAttributePairs,
32
39
  assemblePersistedBody
33
40
  };
34
- //# sourceMappingURL=chunk-R3DJVOSM.js.map
41
+ //# sourceMappingURL=chunk-JDSVLVCG.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/structured-attributes.ts"],"sourcesContent":["/**\n * Shared helpers for the `\\n[Attributes: …]` enrichment suffix that\n * `writeMemory` appends to a stored body when `structuredAttributes` are\n * present.\n *\n * Extracted here (out of `storage.ts`) so every reader — the storage\n * manager, the wearable service, and the coding surfaces — strips the suffix\n * with ONE definition. Previously `coding/architecture-surfaces.ts` carried a\n * weaker local copy that only checked the trailing `]`, which could truncate\n * card markdown that legitimately ends in a `[Attributes: …]` line (cursor\n * review: duplicate attribute suffix stripper).\n *\n * String operations, not regex — CodeQL `js/polynomial-redos` flags\n * suffix-anchored patterns over library-supplied content.\n */\n\nimport { sanitizeMemoryContent } from \"./sanitize.js\";\n\n/**\n * Remove the `[Attributes: …]` suffix `writeMemory` appends to the stored\n * body when structuredAttributes are present, yielding the raw fact/card text\n * for content comparison or client display. Inverse companion of\n * `normalizeAttributePairs` enrichment in `storage.ts`.\n *\n * Returns the stripped (trimmed) body when the marker opens the final\n * non-empty line and its inner payload contains no premature `]` or newline\n * (mirrors the exact shape `normalizeAttributePairs` emits). Otherwise\n * returns the trimmed input unchanged — never truncates legitimate content.\n */\nexport function stripAttributesSuffix(content: string): string {\n const trimmed = content.trimEnd();\n if (!trimmed.endsWith(\"]\")) return content.trim();\n const marker = \"\\n[Attributes: \";\n const markerIndex = trimmed.lastIndexOf(marker);\n if (markerIndex === -1) return content.trim();\n // The block must be the FINAL line and contain no \"]\" before the\n // closing bracket (mirrors the shape normalizeAttributePairs emits).\n const inner = trimmed.slice(markerIndex + marker.length, -1);\n if (inner.includes(\"]\") || inner.includes(\"\\n\")) return content.trim();\n return trimmed.slice(0, markerIndex).trim();\n}\n\n/** Return stored-body identity forms, from raw semantic content to full body. */\nexport function storedContentIdentityCandidates(\n content: string,\n stripCitation: (value: string) => string,\n): string[] {\n const fullBody = content.trim();\n const bodyWithoutAttributes = stripAttributesSuffix(fullBody);\n const rawBody = stripCitation(bodyWithoutAttributes);\n return [...new Set([rawBody, bodyWithoutAttributes, fullBody])];\n}\n// ---------------------------------------------------------------------------\n// Persisted-body assembly (issue #1989 PR2)\n// ---------------------------------------------------------------------------\n//\n// `writeMemory` historically enriched content with the attribute suffix and\n// then sanitized the COMBINED body inline. That assembly is the persisted\n// form both the file body and write-idempotency fingerprints must agree on\n// (AGENTS.md §13), so it lives here — shared by `StorageManager.writeMemory`\n// and `composeMemoryEnvelope` — instead of existing twice.\n\n/**\n * Canonical `key: value; …` rendering of structured attributes. Keys are\n * trimmed + lowercased, values trimmed, pairs sorted by normalized key.\n * Moved verbatim from `storage.ts` (which re-exports it for API stability);\n * used at the write path, the dedup-lookup path, and envelope assembly.\n */\nexport function normalizeAttributePairs(pairs: Record<string, string>): string {\n return Object.entries(pairs)\n .map(([k, v]) => [k.trim().toLowerCase(), v.trim()] as [string, string])\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([k, v]) => `${k}: ${v}`)\n .join(\"; \");\n}\n\nexport interface AssembledPersistBody {\n /** The exact body persistence writes: enriched then sanitized. */\n text: string;\n /** False when sanitization redacted injection-bearing text. */\n clean: boolean;\n /** Matched injection pattern sources (for the storage warn log). */\n violations: string[];\n}\n\n/**\n * Assemble the persisted body exactly as `writeMemory` does: append the\n * normalized attribute suffix when attributes are present, then sanitize the\n * combined result. ONE definition — byte-identity between the legacy write\n * path and the sealed-envelope path is structural, not tested-by-hope.\n */\nexport function assemblePersistedBody(\n content: string,\n structuredAttributes?: Record<string, string>,\n): AssembledPersistBody {\n let enriched = content;\n if (structuredAttributes && Object.keys(structuredAttributes).length > 0) {\n enriched = `${content}\\n[Attributes: ${normalizeAttributePairs(structuredAttributes)}]`;\n }\n const sanitized = sanitizeMemoryContent(enriched);\n return { text: sanitized.text, clean: sanitized.clean, violations: sanitized.violations };\n}\n"],"mappings":";;;;;AA6BO,SAAS,sBAAsB,SAAyB;AAC7D,QAAM,UAAU,QAAQ,QAAQ;AAChC,MAAI,CAAC,QAAQ,SAAS,GAAG,EAAG,QAAO,QAAQ,KAAK;AAChD,QAAM,SAAS;AACf,QAAM,cAAc,QAAQ,YAAY,MAAM;AAC9C,MAAI,gBAAgB,GAAI,QAAO,QAAQ,KAAK;AAG5C,QAAM,QAAQ,QAAQ,MAAM,cAAc,OAAO,QAAQ,EAAE;AAC3D,MAAI,MAAM,SAAS,GAAG,KAAK,MAAM,SAAS,IAAI,EAAG,QAAO,QAAQ,KAAK;AACrE,SAAO,QAAQ,MAAM,GAAG,WAAW,EAAE,KAAK;AAC5C;AAGO,SAAS,gCACd,SACA,eACU;AACV,QAAM,WAAW,QAAQ,KAAK;AAC9B,QAAM,wBAAwB,sBAAsB,QAAQ;AAC5D,QAAM,UAAU,cAAc,qBAAqB;AACnD,SAAO,CAAC,GAAG,oBAAI,IAAI,CAAC,SAAS,uBAAuB,QAAQ,CAAC,CAAC;AAChE;AAiBO,SAAS,wBAAwB,OAAuC;AAC7E,SAAO,OAAO,QAAQ,KAAK,EACxB,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,YAAY,GAAG,EAAE,KAAK,CAAC,CAAqB,EACtE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,EACrC,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,EAAE,EAC5B,KAAK,IAAI;AACd;AAiBO,SAAS,sBACd,SACA,sBACsB;AACtB,MAAI,WAAW;AACf,MAAI,wBAAwB,OAAO,KAAK,oBAAoB,EAAE,SAAS,GAAG;AACxE,eAAW,GAAG,OAAO;AAAA,eAAkB,wBAAwB,oBAAoB,CAAC;AAAA,EACtF;AACA,QAAM,YAAY,sBAAsB,QAAQ;AAChD,SAAO,EAAE,MAAM,UAAU,MAAM,OAAO,UAAU,OAAO,YAAY,UAAU,WAAW;AAC1F;","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  StorageManager
3
- } from "./chunk-WD5B5AIE.js";
3
+ } from "./chunk-6R4G7N4S.js";
4
4
  import {
5
5
  normalizeEntityName
6
6
  } from "./chunk-YXZG5TVN.js";
@@ -958,4 +958,4 @@ export {
958
958
  resolveBriefingSaveDir,
959
959
  briefingFilename
960
960
  };
961
- //# sourceMappingURL=chunk-F4EU6VUC.js.map
961
+ //# sourceMappingURL=chunk-JDZPNCMA.js.map
@@ -54,7 +54,7 @@ import {
54
54
  } from "./chunk-IIFFC3RL.js";
55
55
  import {
56
56
  rebuildMemoryLifecycleLedger
57
- } from "./chunk-YXKVLYXU.js";
57
+ } from "./chunk-HWRD23DW.js";
58
58
  import {
59
59
  rebuildObservations
60
60
  } from "./chunk-DQTCGVFK.js";
@@ -80,21 +80,21 @@ import {
80
80
  } from "./chunk-6FC3IZ26.js";
81
81
  import {
82
82
  searchVerifiedEpisodes
83
- } from "./chunk-J272WKX2.js";
83
+ } from "./chunk-6HPHEFXT.js";
84
84
  import {
85
85
  ThreadingManager
86
86
  } from "./chunk-OJP3N7UK.js";
87
87
  import {
88
88
  promoteSemanticRuleFromMemory
89
- } from "./chunk-X57M2Q4I.js";
89
+ } from "./chunk-RDJRFDJY.js";
90
90
  import {
91
91
  searchVerifiedSemanticRules
92
- } from "./chunk-VFSAWRMZ.js";
92
+ } from "./chunk-LJS7KUPV.js";
93
93
  import {
94
94
  buildResumeBundleFromState,
95
95
  getResumeBundleStatus,
96
96
  recordResumeBundle
97
- } from "./chunk-XAPMEU3K.js";
97
+ } from "./chunk-UU7TRFNE.js";
98
98
  import {
99
99
  getWorkProductLedgerStatus,
100
100
  recordWorkProductLedgerEntry,
@@ -127,7 +127,7 @@ import {
127
127
  runOperatorInventory,
128
128
  runOperatorRepair,
129
129
  runOperatorSetup
130
- } from "./chunk-X7XEDOSL.js";
130
+ } from "./chunk-4IIFL7GC.js";
131
131
  import {
132
132
  analyzeSessionIntegrity,
133
133
  applySessionRepair,
@@ -152,7 +152,7 @@ import {
152
152
  } from "./chunk-6GUG4YNM.js";
153
153
  import {
154
154
  searchHarmonicRetrieval
155
- } from "./chunk-W7Y5JDVB.js";
155
+ } from "./chunk-PDDTI7IC.js";
156
156
  import {
157
157
  rescoreMemoryImportance
158
158
  } from "./chunk-JXS5PDQ7.js";
@@ -169,7 +169,7 @@ import {
169
169
  rebuildMemoryProjection,
170
170
  repairMemoryProjection,
171
171
  verifyMemoryProjection
172
- } from "./chunk-5UZ6UCOZ.js";
172
+ } from "./chunk-XUAMCLY4.js";
173
173
  import {
174
174
  getCueAnchorStoreStatus
175
175
  } from "./chunk-ACPCA4NO.js";
@@ -196,11 +196,11 @@ import {
196
196
  } from "./chunk-UQ7RN5HK.js";
197
197
  import {
198
198
  parseConfig
199
- } from "./chunk-O5FFBO2M.js";
199
+ } from "./chunk-47P3RYZP.js";
200
200
  import {
201
201
  EngramAccessHttpServer,
202
202
  MeetingsInputError
203
- } from "./chunk-HDIUYMSB.js";
203
+ } from "./chunk-QWGE2PUH.js";
204
204
  import {
205
205
  WearablesInputError
206
206
  } from "./chunk-V7IZKJI3.js";
@@ -213,13 +213,13 @@ import {
213
213
  createProductionChatLlmAdapter,
214
214
  loadChatSession,
215
215
  sessionBelongsToPrincipal
216
- } from "./chunk-QINJITDS.js";
216
+ } from "./chunk-PX2LSHYM.js";
217
217
  import {
218
218
  getAbstractionNodeStoreStatus
219
219
  } from "./chunk-DJUKBGAD.js";
220
220
  import {
221
221
  EngramAccessService
222
- } from "./chunk-BF6SXNQJ.js";
222
+ } from "./chunk-T2JHZWH6.js";
223
223
  import {
224
224
  WorkStorage
225
225
  } from "./chunk-GDB4J2H3.js";
@@ -239,7 +239,7 @@ import {
239
239
  } from "./chunk-QT2FRYI4.js";
240
240
  import {
241
241
  readAggregateExtractionWatermark
242
- } from "./chunk-JSEJH2YQ.js";
242
+ } from "./chunk-CGVHPCP2.js";
243
243
  import {
244
244
  getObjectiveStateStoreStatus
245
245
  } from "./chunk-HTP6XRUI.js";
@@ -248,15 +248,15 @@ import {
248
248
  readMemoryGovernanceRunArtifact,
249
249
  restoreMemoryGovernanceRun,
250
250
  runMemoryGovernance
251
- } from "./chunk-B6LZ4IBH.js";
251
+ } from "./chunk-6LAPLZOS.js";
252
252
  import {
253
253
  listNamespaces,
254
254
  runNamespaceMigration,
255
255
  verifyNamespaces
256
- } from "./chunk-RANKJI5T.js";
256
+ } from "./chunk-3JLPGJ43.js";
257
257
  import {
258
258
  resolveNamespaceChildRoot
259
- } from "./chunk-NOEMGE56.js";
259
+ } from "./chunk-NH5IR2WM.js";
260
260
  import {
261
261
  getCausalTrajectoryStoreStatus
262
262
  } from "./chunk-AHZOMHWN.js";
@@ -265,7 +265,7 @@ import {
265
265
  } from "./chunk-BIJAWZYW.js";
266
266
  import {
267
267
  meetingIdDate
268
- } from "./chunk-WD5B5AIE.js";
268
+ } from "./chunk-6R4G7N4S.js";
269
269
  import {
270
270
  isValidTranscriptDate
271
271
  } from "./chunk-UHVXE24Y.js";
@@ -4025,7 +4025,7 @@ function registerCli(api, orchestrator, registerOptions = {}) {
4025
4025
  const idArg = typeof args[0] === "string" ? args[0] : "";
4026
4026
  const options = args[1] ?? {};
4027
4027
  const reason = typeof options.reason === "string" && options.reason.trim().length > 0 ? options.reason.trim() : void 0;
4028
- const { forgetMemory } = await import("./forget-HDS4N6CG.js");
4028
+ const { forgetMemory } = await import("./forget-EHGGJZLX.js");
4029
4029
  try {
4030
4030
  const result = await forgetMemory(orchestrator.storage, {
4031
4031
  id: idArg,
@@ -7230,7 +7230,7 @@ Semantic consolidation complete. clusters=${result.clustersFound}, consolidated=
7230
7230
  console.error("--verb is required. Must be one of: keep-a, keep-b, merge, both-valid, needs-more-context");
7231
7231
  process.exit(1);
7232
7232
  }
7233
- const { isValidResolutionVerb, executeResolution } = await import("./resolution-MDPNOEG6.js");
7233
+ const { isValidResolutionVerb, executeResolution } = await import("./resolution-MMOD5WC4.js");
7234
7234
  if (!isValidResolutionVerb(verb)) {
7235
7235
  console.error(`Invalid verb: ${verb}. Must be one of: keep-a, keep-b, merge, both-valid, needs-more-context`);
7236
7236
  process.exit(1);
@@ -7989,4 +7989,4 @@ export {
7989
7989
  listMemoryMarkdownFilePaths,
7990
7990
  registerCli
7991
7991
  };
7992
- //# sourceMappingURL=chunk-D5YOZ66N.js.map
7992
+ //# sourceMappingURL=chunk-JV5YUBIZ.js.map
@@ -9,7 +9,7 @@ import {
9
9
  import {
10
10
  CONTENT_HASH_INDEX_RETRY_MAX_DELAY_MS,
11
11
  ContentHashIndex
12
- } from "./chunk-BQIFZ2MP.js";
12
+ } from "./chunk-CX5SW2EW.js";
13
13
  import {
14
14
  markProjectedMemoryPathInvalid
15
15
  } from "./chunk-3CSX3ETE.js";
@@ -460,7 +460,7 @@ var TombstoneBlockedCaptureIndex = class {
460
460
  await index.load();
461
461
  const rebuildMarkers = await this.getRebuildMarkers();
462
462
  const clearableRebuildMarkers = await this.getClearableRebuildMarkerPaths(rebuildMarkers);
463
- let persisted = true;
463
+ let persisted = !index.requiresFormatMigration;
464
464
  try {
465
465
  await stat(this.indexPath());
466
466
  if (rebuildMarkers.length > 0) persisted = false;
@@ -616,10 +616,7 @@ var TombstoneBlockedCaptureIndex = class {
616
616
  if (rebuildMarker) await this.markRebuildCommitted(rebuildMarker);
617
617
  const rebuilt = await this.rebuild(await this.getIndex());
618
618
  if (rebuilt) {
619
- await this.clearRebuildRequired([
620
- ...clearableExistingMarkers,
621
- marker
622
- ]);
619
+ await this.clearRebuildRequired([...clearableExistingMarkers, marker]);
623
620
  }
624
621
  await this.setAuthoritative(rebuilt);
625
622
  }
@@ -1377,4 +1374,4 @@ export {
1377
1374
  parseTombstoneBlockedOfflineSyncMemory,
1378
1375
  TombstoneBlockedCaptureIndexHost
1379
1376
  };
1380
- //# sourceMappingURL=chunk-DLG5V6ND.js.map
1377
+ //# sourceMappingURL=chunk-K4QS7LXU.js.map