chainlesschain 0.166.10 → 0.166.13

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 (230) hide show
  1. package/README.md +33 -0
  2. package/bin/chainlesschain.js +5 -0
  3. package/package.json +4 -2
  4. package/src/assets/web-panel/assets/{AIOps-CLYBDAGv.js → AIOps-BN25cNOD.js} +1 -1
  5. package/src/assets/web-panel/assets/{ActionButton-CpeSttcu.js → ActionButton-Da9IP-m5.js} +1 -1
  6. package/src/assets/web-panel/assets/{Analytics-Ba1TNLG0.js → Analytics-D7hkEvQm.js} +3 -3
  7. package/src/assets/web-panel/assets/{AppLayout-xBy8EOeg.js → AppLayout-CCV4Xnbc.js} +5 -5
  8. package/src/assets/web-panel/assets/{Artifacts-CJ_3TFb8.js → Artifacts-CVSnVJeA.js} +1 -1
  9. package/src/assets/web-panel/assets/{Audit-DUATFCG3.js → Audit-CuYdw5Ag.js} +1 -1
  10. package/src/assets/web-panel/assets/{BackgroundAgents-BRXYPIGp.js → BackgroundAgents-DZCnK-Tf.js} +1 -1
  11. package/src/assets/web-panel/assets/{Backup-D8auLx7y.js → Backup-cV9FdpTy.js} +1 -1
  12. package/src/assets/web-panel/assets/{BaseInput-CBgdslQ3.js → BaseInput-BRnv6YSp.js} +1 -1
  13. package/src/assets/web-panel/assets/{Chat-B32LvAiE.js → Chat-Bw5w87P4.js} +5 -5
  14. package/src/assets/web-panel/assets/{ChatBubbleRenderer-CVfvAy-n.js → ChatBubbleRenderer-C0GjtUAw.js} +1 -1
  15. package/src/assets/web-panel/assets/{Checkbox-BwzBxOpC.js → Checkbox-DaoTqcdt.js} +1 -1
  16. package/src/assets/web-panel/assets/{Codegen-0U5vrg1H.js → Codegen-B4dYcEIi.js} +1 -1
  17. package/src/assets/web-panel/assets/{Col-dZ2i4aAj.js → Col-mAhuOeuD.js} +1 -1
  18. package/src/assets/web-panel/assets/{Community-UVvpLr8c.js → Community-BK6KEdBk.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compact-BDNEb1Bd.js → Compact-CCglmNu5.js} +1 -1
  20. package/src/assets/web-panel/assets/{Compliance-BrzQPxyS.js → Compliance-Cm8S4of7.js} +1 -1
  21. package/src/assets/web-panel/assets/{Cowork-BbgGsu-9.js → Cowork-Dhs1QLMe.js} +2 -2
  22. package/src/assets/web-panel/assets/{Cron-G321XPhp.js → Cron-CLlhmXWk.js} +2 -2
  23. package/src/assets/web-panel/assets/{Crosschain-CgLNUyMn.js → Crosschain-BnHVbaNs.js} +1 -1
  24. package/src/assets/web-panel/assets/{DID-BAfRj18q.js → DID-UzQP9-0O.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dashboard-BNIxA4TK.js → Dashboard-CBdlPClz.js} +2 -2
  26. package/src/assets/web-panel/assets/{Dropdown-BLAUmCAN.js → Dropdown-axIRPdq1.js} +1 -1
  27. package/src/assets/web-panel/assets/{EmailListRenderer-CsnhTW22.js → EmailListRenderer-DUalW5rx.js} +1 -1
  28. package/src/assets/web-panel/assets/{FamilyGuardDashboard-zcQ7Ip1n.js → FamilyGuardDashboard-Bl4W9luY.js} +1 -1
  29. package/src/assets/web-panel/assets/{Federation-KFwxodNU.js → Federation-C1yP-uEu.js} +1 -1
  30. package/src/assets/web-panel/assets/{FormItemContext-3CYRLEHG.js → FormItemContext-Xh6Ig5q8.js} +1 -1
  31. package/src/assets/web-panel/assets/{GenericCardRenderer-D3d9D8L9.js → GenericCardRenderer-C2cz3bt2.js} +1 -1
  32. package/src/assets/web-panel/assets/{Git-BJ202nJY.js → Git-C_z63ixg.js} +2 -2
  33. package/src/assets/web-panel/assets/{Governance-ClnnXVQ-.js → Governance-BYqB33_3.js} +1 -1
  34. package/src/assets/web-panel/assets/{Inference-DNU-PTkc.js → Inference-CEULuArm.js} +1 -1
  35. package/src/assets/web-panel/assets/{KnowledgeGraph-DJuinbuY.js → KnowledgeGraph-fgMsu-0H.js} +1 -1
  36. package/src/assets/web-panel/assets/{Logs-D4No-46s.js → Logs-DO9Hdcec.js} +2 -2
  37. package/src/assets/web-panel/assets/MarkdownRenderer-BkrK04xW.js +1 -0
  38. package/src/assets/web-panel/assets/{Marketplace-Ba-KqRN3.js → Marketplace-B8zyLiFe.js} +1 -1
  39. package/src/assets/web-panel/assets/{McpTools-DVoxnPgE.js → McpTools-BLAN2mWW.js} +3 -3
  40. package/src/assets/web-panel/assets/{Memory-D_C8gzAZ.js → Memory-CrQcFM7u.js} +2 -2
  41. package/src/assets/web-panel/assets/{MobileBridge-DnzTPcDH.js → MobileBridge-DVnyiiU-.js} +1 -1
  42. package/src/assets/web-panel/assets/MobileProjects-qjCME5OD.js +1 -0
  43. package/src/assets/web-panel/assets/{Mtc-CvEHmHId.js → Mtc-4JE3C3It.js} +2 -2
  44. package/src/assets/web-panel/assets/{MtcAudit-VNJmWqmv.js → MtcAudit-CjBuak9I.js} +5 -5
  45. package/src/assets/web-panel/assets/{Multisig-BO0x_Vsa.js → Multisig-BtPcYQcC.js} +3 -3
  46. package/src/assets/web-panel/assets/{NLProgramming-CM2gI1UY.js → NLProgramming-Cx653_Ba.js} +1 -1
  47. package/src/assets/web-panel/assets/{Notes-CMc1HsML.js → Notes-CkuD3YzS.js} +3 -3
  48. package/src/assets/web-panel/assets/{NotificationSettings-DGNmSKGM.js → NotificationSettings-BgNgU7HH.js} +1 -1
  49. package/src/assets/web-panel/assets/{OrderTableRenderer-Du-Kct3p.js → OrderTableRenderer-BTC8W0a-.js} +1 -1
  50. package/src/assets/web-panel/assets/{Organization-DRtRZjas.js → Organization-Dmd4Hjxz.js} +4 -4
  51. package/src/assets/web-panel/assets/{Overflow-Dp4OeWsn.js → Overflow-C_5DA-G0.js} +1 -1
  52. package/src/assets/web-panel/assets/{P2P-DXMJVls8.js → P2P-uwslV4XC.js} +2 -2
  53. package/src/assets/web-panel/assets/PdhVaultBrowser-CuNgwVnX.js +7 -0
  54. package/src/assets/web-panel/assets/{Permissions-D1Hbb51o.js → Permissions-CJayVX9H.js} +4 -4
  55. package/src/assets/web-panel/assets/{PersonalDataHub-BridiDhr.js → PersonalDataHub-Cb05H5go.js} +4 -4
  56. package/src/assets/web-panel/assets/{Pipeline-B4bUNCm1.js → Pipeline-BZlGKapZ.js} +1 -1
  57. package/src/assets/web-panel/assets/{Privacy-BTu_HEqK.js → Privacy-BIzZWYzd.js} +1 -1
  58. package/src/assets/web-panel/assets/{ProjectInit-SVtL2hnt.js → ProjectInit-vEYYyQXQ.js} +2 -2
  59. package/src/assets/web-panel/assets/{ProjectSettings-B2Sh7JZ2.js → ProjectSettings-MZqTy5CC.js} +2 -2
  60. package/src/assets/web-panel/assets/{Projects-BwU1xalW.js → Projects-CRARUOl8.js} +1 -1
  61. package/src/assets/web-panel/assets/{Providers-BWdWQSDw.js → Providers-80VAK8PX.js} +1 -1
  62. package/src/assets/web-panel/assets/{QrScannerModal-Brzc-Sxb.js → QrScannerModal-CzRSoIwK.js} +1 -1
  63. package/src/assets/web-panel/assets/{QuickAsk-DIBz7FCe.js → QuickAsk-BpwQ2n4C.js} +1 -1
  64. package/src/assets/web-panel/assets/{Recommend-CZ8RriIJ.js → Recommend-BC03TZ79.js} +1 -1
  65. package/src/assets/web-panel/assets/{RemoteSession-CM0KJQ3t.js → RemoteSession-DE59-jaa.js} +2 -2
  66. package/src/assets/web-panel/assets/{Reputation-D_wo8H0O.js → Reputation-DOHmeWyA.js} +1 -1
  67. package/src/assets/web-panel/assets/{Row-D1G1fD7N.js → Row-hc5RZl1D.js} +1 -1
  68. package/src/assets/web-panel/assets/{RssFeed-dKCVtA0K.js → RssFeed-Cv5uMP7E.js} +3 -3
  69. package/src/assets/web-panel/assets/{Search-Be1D61xo.js → Search-qohu7Ug0.js} +1 -1
  70. package/src/assets/web-panel/assets/{Security-IbNiR6OC.js → Security-drCPFWV5.js} +4 -4
  71. package/src/assets/web-panel/assets/{Services-nuHK8y8p.js → Services-BAEgUeRy.js} +2 -2
  72. package/src/assets/web-panel/assets/{Skeleton-DnM5jdnC.js → Skeleton-CkJkKBlo.js} +1 -1
  73. package/src/assets/web-panel/assets/{Skills-DCTdoq_q.js → Skills-bMuKEpez.js} +1 -1
  74. package/src/assets/web-panel/assets/{Sla-DlWun-Ui.js → Sla-DxWQVHRC.js} +1 -1
  75. package/src/assets/web-panel/assets/{SpeechSettings-C19kv2sd.js → SpeechSettings-BpS8idmV.js} +1 -1
  76. package/src/assets/web-panel/assets/{SyncSettings-CkQIR_Hu.js → SyncSettings-BPBLlW5v.js} +2 -2
  77. package/src/assets/web-panel/assets/{Tasks-DdbqOEbs.js → Tasks-C4SLEeUh.js} +1 -1
  78. package/src/assets/web-panel/assets/{Templates-B7GpIXeo.js → Templates-r-wfU39U.js} +1 -1
  79. package/src/assets/web-panel/assets/{Tenant-ByEstFhY.js → Tenant-C7vjRmLN.js} +1 -1
  80. package/src/assets/web-panel/assets/{Terminal-BKRVID1a.js → Terminal-DdzeFCV2.js} +2 -2
  81. package/src/assets/web-panel/assets/{TimelineRenderer-CNS3dHNv.js → TimelineRenderer-CYyWN2KD.js} +1 -1
  82. package/src/assets/web-panel/assets/{Tokens-BykqylCL.js → Tokens-D8A9osUg.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trigger-ByNxq51W.js → Trigger-DBvrNlyS.js} +1 -1
  84. package/src/assets/web-panel/assets/{Trust-BlrFsdaS.js → Trust-DBVAGc7o.js} +1 -1
  85. package/src/assets/web-panel/assets/{UkeySign-Dg26A-sd.js → UkeySign-C1vQUCRJ.js} +1 -1
  86. package/src/assets/web-panel/assets/{VideoEditing-C1wUxNn0.js → VideoEditing-BKs4dah4.js} +1 -1
  87. package/src/assets/web-panel/assets/{Wallet-OphEUzI4.js → Wallet-ByIuj3lD.js} +4 -4
  88. package/src/assets/web-panel/assets/{WebAuthn-_8lL08hF.js → WebAuthn-DYlAFCm9.js} +3 -3
  89. package/src/assets/web-panel/assets/{WorkflowEditor-BnTuIvnP.js → WorkflowEditor-Dwyadd0c.js} +1 -1
  90. package/src/assets/web-panel/assets/{chat-3N3VLQYr.js → chat-Bm2f3s08.js} +1 -1
  91. package/src/assets/web-panel/assets/{colors-Bo_G96gg.js → colors-C8ORSh7V.js} +1 -1
  92. package/src/assets/web-panel/assets/{compact-item-DjubfjI_.js → compact-item-1iVlnsM-.js} +1 -1
  93. package/src/assets/web-panel/assets/{createContext-Cx_HSLCk.js → createContext-CmqNyUSL.js} +1 -1
  94. package/src/assets/web-panel/assets/devWarning-B69RCDDH.js +1 -0
  95. package/src/assets/web-panel/assets/{hasIn-D5OjAOlA.js → hasIn-rUMaX3Ul.js} +1 -1
  96. package/src/assets/web-panel/assets/index-9biMQ-tw.js +1 -0
  97. package/src/assets/web-panel/assets/{index-Bj7S5IJw.js → index-B53c3diB.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-C-_Cy0k_.js → index-B59OWAs7.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-DaU60K3A.js → index-B8BrB0Ls.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-UnpsQ6A0.js → index-BC32_0xT.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-BScGr1BY.js → index-BC8Wb6cy.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-CC7RnaPP.js → index-BCOhTILd.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-DXJqa1-I.js → index-BFniLMn9.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-C-4sfa0l.js → index-BIvM-uAX.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-C8dPFFhy.js → index-BK-RY0-7.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-CVPDhmVH.js → index-BQL9r73Y.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-CqZq3zWr.js → index-BVtnizyC.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-C5IwN9q3.js → index-Bf1PlIHp.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-Cz5tQ5PY.js → index-Bgw4Y2rU.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-CmLwI-Y8.js → index-BgwLNxmr.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-Y-H7j25u.js → index-C-J5-pGH.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-ydnEPOzZ.js → index-C-ZIHi42.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-HioDjvUF.js → index-C3B1S-mW.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-CRKk1JPX.js → index-C5RfRciU.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-x7o-2T3S.js → index-CCEyz58d.js} +1 -1
  116. package/src/assets/web-panel/assets/index-COie87kl.js +1 -0
  117. package/src/assets/web-panel/assets/{index-BvYo09C0.js → index-CTfEmKK0.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-CCjq3g32.js → index-CfiHyVyl.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-3_CEBEEf.js → index-CkFvuAex.js} +3 -3
  120. package/src/assets/web-panel/assets/{index-EZr3bvz2.js → index-D98FXb0w.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-C4MAnkl5.js → index-DDHk911Q.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-BgPb37tI.js → index-DJxtPFOh.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-CNmsP0Xf.js → index-DVJ1uKf4.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-DBvZhdCb.js → index-Dcck8QfW.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-B905-Mcs.js → index-DgUE51Pz.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-DrVjatPe.js → index-Dsve5Gkv.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-uAcJUJkx.js → index-DvedhJeM.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-DD1zSPZH.js → index-DwMdWKiF.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-BxgIE4PD.js → index-OcbzdRpT.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-Ce8EWU6r.js → index-fPK6GFEg.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-DlcbE0sX.js → index-geQinnns.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-Dbdr8tVi.js → index-pHWA7bmM.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-DE4XtzMl.js → index-reUHhuz8.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-Q_vn0t8d.js → index-tqTx5wXo.js} +1 -1
  135. package/src/assets/web-panel/assets/{initDefaultProps-DurpENJY.js → initDefaultProps-CuA-cpkL.js} +1 -1
  136. package/src/assets/web-panel/assets/{motion-CIh-z-gR.js → motion-CimmE_9b.js} +1 -1
  137. package/src/assets/web-panel/assets/{move-Uc_yI2NA.js → move-DlGlrltz.js} +1 -1
  138. package/src/assets/web-panel/assets/{mtc-parser-DUevj5wz.js → mtc-parser-CK6BJQ07.js} +1 -1
  139. package/src/assets/web-panel/assets/{omit-85eMYyur.js → omit-BKjBfZfB.js} +1 -1
  140. package/src/assets/web-panel/assets/{pickAttrs-AuxDD20F.js → pickAttrs-B2chVYw9.js} +1 -1
  141. package/src/assets/web-panel/assets/{placementArrow-DOWn8dd1.js → placementArrow-BW8aLJJ3.js} +1 -1
  142. package/src/assets/web-panel/assets/{responsiveObserve-CPxTWodH.js → responsiveObserve-dXlPl66S.js} +1 -1
  143. package/src/assets/web-panel/assets/{slide-BqvbGPjx.js → slide-hSa89S4G.js} +1 -1
  144. package/src/assets/web-panel/assets/{statusUtils-BzXKkV8d.js → statusUtils-DM6KLt-s.js} +1 -1
  145. package/src/assets/web-panel/assets/{styleChecker-B2O7yRk3.js → styleChecker-C9MQAK15.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFlexGapSupport-DRWp7px1.js → useFlexGapSupport-BpQDpP0z.js} +1 -1
  147. package/src/assets/web-panel/assets/{useFs-Dp0V7sjM.js → useFs-C7rtRViA.js} +1 -1
  148. package/src/assets/web-panel/assets/{usePersonalDataHub-CyCrG3ql.js → usePersonalDataHub-Dm15xafq.js} +1 -1
  149. package/src/assets/web-panel/assets/{vnode-CXhoFpFo.js → vnode-mEiEytw4.js} +1 -1
  150. package/src/assets/web-panel/assets/{zoom-0z3mtwEg.js → zoom-DzPxflhY.js} +1 -1
  151. package/src/assets/web-panel/index.html +1 -1
  152. package/src/command-help-index.json +5 -5
  153. package/src/commands/agent.js +51 -20
  154. package/src/commands/compact.js +349 -3
  155. package/src/commands/context.js +72 -1
  156. package/src/commands/graph.js +26 -15
  157. package/src/commands/hmemory.js +21 -0
  158. package/src/commands/hook.js +256 -28
  159. package/src/commands/memory.js +209 -42
  160. package/src/commands/promcomp.js +17 -0
  161. package/src/commands/serve.js +94 -10
  162. package/src/commands/session.js +2 -3
  163. package/src/commands/team.js +7 -1
  164. package/src/data/changelog.json +28 -2
  165. package/src/gateways/ws/session-core-protocol.js +62 -3
  166. package/src/gateways/ws/session-protocol.js +123 -15
  167. package/src/gateways/ws/ws-agent-handler.js +157 -9
  168. package/src/gateways/ws/ws-session-gateway.js +204 -30
  169. package/src/generated/cc-agent-protocol.schema.json +2094 -4
  170. package/src/harness/prompt-compressor.js +5 -55
  171. package/src/lib/agent-sandbox.js +14 -4
  172. package/src/lib/agent-team/team-distributed-graph-bridge.js +3 -3
  173. package/src/lib/app-server/context-memory-notifications.js +54 -0
  174. package/src/lib/app-server/rollout-store-factory.js +115 -0
  175. package/src/lib/app-server/rollout-store.js +310 -23
  176. package/src/lib/app-server/server.js +184 -7
  177. package/src/lib/app-server/sqlite-rollout-store.js +59 -16
  178. package/src/lib/auto-mode-config.js +26 -0
  179. package/src/lib/causal-observability.js +13 -1
  180. package/src/lib/context-memory-kernel/authority.js +95 -0
  181. package/src/lib/context-memory-kernel/durable-memory-port.js +296 -0
  182. package/src/lib/context-memory-kernel/index.js +8 -0
  183. package/src/lib/context-memory-kernel/jsonl-session-context-port.js +232 -0
  184. package/src/lib/context-memory-kernel/live-compaction.js +375 -0
  185. package/src/lib/context-memory-kernel/memory-service.js +667 -0
  186. package/src/lib/context-memory-kernel/message-adapter.js +451 -0
  187. package/src/lib/context-memory-kernel/privacy-purge-port.js +244 -0
  188. package/src/lib/context-memory-kernel/provider-context.js +192 -0
  189. package/src/lib/context-memory-kernel/runtime.js +61 -0
  190. package/src/lib/direct-model-usage.js +22 -18
  191. package/src/lib/graph-kernel/cutover-authority-resolver.js +4 -5
  192. package/src/lib/graph-kernel/cutover-ledger.js +2 -2
  193. package/src/lib/graph-kernel/event-store.js +3 -5
  194. package/src/lib/graph-kernel/migration-saga.js +2 -2
  195. package/src/lib/graph-kernel/production-cutover-evidence.js +8 -1
  196. package/src/lib/hierarchical-memory.js +22 -0
  197. package/src/lib/hook-audit-store.js +170 -0
  198. package/src/lib/hook-event-bus.cjs +0 -0
  199. package/src/lib/hook-manager.js +25 -83
  200. package/src/lib/hook-runtime-adapters.js +233 -0
  201. package/src/lib/hook-runtime-contract.cjs +291 -0
  202. package/src/lib/hook-runtime-contract.js +21 -0
  203. package/src/lib/hook-trust.js +210 -0
  204. package/src/lib/hooks-v2-producers.js +52 -6
  205. package/src/lib/hooks-v2-runtime.js +443 -178
  206. package/src/lib/llm-pricing.js +10 -0
  207. package/src/lib/memory-manager.js +29 -4
  208. package/src/lib/model-context-window.js +52 -0
  209. package/src/lib/permanent-memory.js +17 -0
  210. package/src/lib/plan-mode.js +8 -4
  211. package/src/lib/process-execution-broker/index.js +208 -16
  212. package/src/lib/runtime-usage-ledger.js +20 -0
  213. package/src/lib/session-consolidator.js +59 -0
  214. package/src/lib/session-core-singletons.js +17 -4
  215. package/src/lib/session-hooks.js +29 -2
  216. package/src/lib/session-transcript-migration.js +188 -0
  217. package/src/lib/settings-hook-events.cjs +37 -401
  218. package/src/lib/settings-hook-events.js +210 -8
  219. package/src/lib/settings-hooks.cjs +42 -83
  220. package/src/lib/ws-session-manager.js +4 -1
  221. package/src/repl/agent-repl.js +186 -53
  222. package/src/runtime/agent-core.js +376 -350
  223. package/src/runtime/headless-runner.js +40 -33
  224. package/src/runtime/headless-stream.js +131 -30
  225. package/src/assets/web-panel/assets/MarkdownRenderer-Dt8hH_qA.js +0 -1
  226. package/src/assets/web-panel/assets/MobileProjects-Jg2dVUc-.js +0 -1
  227. package/src/assets/web-panel/assets/PdhVaultBrowser-0jYeVmyY.js +0 -7
  228. package/src/assets/web-panel/assets/devWarning-BX944k9E.js +0 -1
  229. package/src/assets/web-panel/assets/index-C_9Jt_SR.js +0 -1
  230. package/src/assets/web-panel/assets/index-DL2EFx7m.js +0 -1
@@ -0,0 +1,451 @@
1
+ import {
2
+ canonicalDigest,
3
+ canonicalJson,
4
+ normalizeContextItem,
5
+ } from "@chainlesschain/context-memory-kernel";
6
+ import {
7
+ getDurableSystemMessageProvenance,
8
+ markDurableSystemMessage,
9
+ } from "../session-message-provenance.js";
10
+
11
+ const MESSAGE_BUNDLE_SCHEMA = "chainlesschain.cli-context-message-bundle/v1";
12
+ const DEFAULT_ALLOWED_SINKS = Object.freeze(["*"]);
13
+ const TRUST_ORDER = Object.freeze([
14
+ "host",
15
+ "verified",
16
+ "user",
17
+ "external",
18
+ "untrusted",
19
+ ]);
20
+ const SENSITIVITY_ORDER = Object.freeze([
21
+ "public",
22
+ "internal",
23
+ "personal",
24
+ "secret",
25
+ "restricted",
26
+ ]);
27
+
28
+ function safeMessages(messages) {
29
+ if (!Array.isArray(messages)) return [];
30
+ return messages.filter(
31
+ (message) =>
32
+ message &&
33
+ typeof message === "object" &&
34
+ !Array.isArray(message) &&
35
+ typeof message.role === "string",
36
+ );
37
+ }
38
+
39
+ function toolCalls(message) {
40
+ return Array.isArray(message?.tool_calls)
41
+ ? message.tool_calls.filter(
42
+ (call) => call && typeof call === "object" && !Array.isArray(call),
43
+ )
44
+ : [];
45
+ }
46
+
47
+ function toolCallId(call) {
48
+ return typeof call?.id === "string" && call.id ? call.id : null;
49
+ }
50
+
51
+ function toolResultId(message) {
52
+ const value = message?.tool_call_id ?? message?.toolCallId;
53
+ return typeof value === "string" && value ? value : null;
54
+ }
55
+
56
+ function bundlePayload(messages) {
57
+ const durableSystemKinds = messages.map(
58
+ (message) => getDurableSystemMessageProvenance(message)?.kind || null,
59
+ );
60
+ return {
61
+ schema: MESSAGE_BUNDLE_SCHEMA,
62
+ messages,
63
+ durableSystemKinds,
64
+ };
65
+ }
66
+
67
+ function trustForBundle(messages) {
68
+ if (
69
+ messages.every(
70
+ (message) =>
71
+ message.role === "system" &&
72
+ getDurableSystemMessageProvenance(message),
73
+ )
74
+ ) {
75
+ return "verified";
76
+ }
77
+ if (messages.some((message) => message.role === "system")) {
78
+ return "untrusted";
79
+ }
80
+ if (messages.some((message) => message.role === "user")) return "user";
81
+ return "external";
82
+ }
83
+
84
+ function kindForBundle(messages, pendingTool) {
85
+ if (pendingTool) return "task-state";
86
+ if (messages.some((message) => message.role === "tool")) {
87
+ return "tool-evidence";
88
+ }
89
+ if (messages.every((message) => message.role === "system")) {
90
+ return "system-policy";
91
+ }
92
+ return "message";
93
+ }
94
+
95
+ function priorityForBundle(messages, sequence, pendingTool) {
96
+ if (pendingTool) return 900_000;
97
+ if (messages.every((message) => message.role === "system")) return 800_000;
98
+ const rolePriority = messages.some((message) => message.role === "user")
99
+ ? 500_000
100
+ : messages.some((message) => message.role === "tool")
101
+ ? 350_000
102
+ : 400_000;
103
+ return Math.min(999_999, rolePriority + Math.min(sequence, 99_999));
104
+ }
105
+
106
+ function createItem({
107
+ sessionId,
108
+ messages,
109
+ sequence,
110
+ pendingTool = false,
111
+ toolGroupId = null,
112
+ allowedSinks,
113
+ trustedSystemPolicy = false,
114
+ }) {
115
+ const payload = bundlePayload(messages);
116
+ const content = canonicalJson(payload);
117
+ const sourceDigest = canonicalDigest(
118
+ { sessionId, sequence, content },
119
+ "chainlesschain.cli-context-source/v1",
120
+ );
121
+ const item = {
122
+ schemaVersion: 1,
123
+ itemId: `cli-msg-${sourceDigest.slice(7, 39)}-${sequence}`,
124
+ kind: kindForBundle(messages, pendingTool),
125
+ scope: "session",
126
+ scopeId: sessionId,
127
+ sourceRef: {
128
+ store: "cli-jsonl-session",
129
+ id: `message-${sequence}`,
130
+ eventSequence: sequence,
131
+ digest: sourceDigest,
132
+ },
133
+ provenance: {
134
+ source: "cli-jsonl-session",
135
+ observedAt: new Date(sequence).toISOString(),
136
+ },
137
+ trust:
138
+ trustedSystemPolicy && messages.every((message) => message.role === "system")
139
+ ? "host"
140
+ : trustForBundle(messages),
141
+ sensitivity: "personal",
142
+ allowedSinks: allowedSinks || DEFAULT_ALLOWED_SINKS,
143
+ tokenEstimate: Math.max(1, Math.ceil(Buffer.byteLength(content, "utf8") / 4)),
144
+ priority: priorityForBundle(messages, sequence, pendingTool),
145
+ pinned: false,
146
+ createdAt: new Date(sequence).toISOString(),
147
+ content,
148
+ ...(pendingTool
149
+ ? {
150
+ binding: {
151
+ taskState: "waiting",
152
+ toolCallId: toolGroupId,
153
+ toolOutcome: "pending",
154
+ requiredForRecovery: true,
155
+ },
156
+ }
157
+ : {}),
158
+ };
159
+ return normalizeContextItem(item);
160
+ }
161
+
162
+ /**
163
+ * Project verified replay messages into canonical ContextItems. One assistant
164
+ * tool-call message and all immediately following results become a single
165
+ * indivisible item. The active, unanswered user turn is recovery-protected.
166
+ */
167
+ export function messagesToContextItems(messagesInput, options = {}) {
168
+ const messages = safeMessages(messagesInput);
169
+ const sessionId = String(options.sessionId || "").trim();
170
+ if (!sessionId) throw new TypeError("sessionId is required");
171
+ const allowedSinks = Array.isArray(options.allowedSinks)
172
+ ? [...options.allowedSinks]
173
+ : DEFAULT_ALLOWED_SINKS;
174
+ const items = [];
175
+ const trustedSystemIndexes = new Set(
176
+ Array.isArray(options.trustedSystemIndexes)
177
+ ? options.trustedSystemIndexes.filter(Number.isSafeInteger)
178
+ : [],
179
+ );
180
+
181
+ for (let index = 0; index < messages.length; index += 1) {
182
+ const message = messages[index];
183
+ const calls = message.role === "assistant" ? toolCalls(message) : [];
184
+ if (calls.length > 0) {
185
+ const ids = calls.map(toolCallId).filter(Boolean);
186
+ const expected = new Set(ids);
187
+ const bundle = [message];
188
+ const seen = new Set();
189
+ let cursor = index + 1;
190
+ while (cursor < messages.length && messages[cursor]?.role === "tool") {
191
+ const result = messages[cursor];
192
+ const resultId = toolResultId(result);
193
+ if (!resultId || !expected.has(resultId)) break;
194
+ bundle.push(result);
195
+ seen.add(resultId);
196
+ cursor += 1;
197
+ }
198
+ const pending = ids.length !== calls.length || seen.size !== expected.size;
199
+ const groupDigest = canonicalDigest(
200
+ { sessionId, index, ids: [...expected].sort() },
201
+ "chainlesschain.cli-tool-group/v1",
202
+ );
203
+ items.push(
204
+ createItem({
205
+ sessionId,
206
+ messages: bundle,
207
+ sequence: index,
208
+ pendingTool: pending,
209
+ toolGroupId: `tool-group-${groupDigest.slice(7, 39)}`,
210
+ allowedSinks,
211
+ }),
212
+ );
213
+ index = cursor - 1;
214
+ continue;
215
+ }
216
+
217
+ if (message.role === "tool") {
218
+ const orphanDigest = canonicalDigest(
219
+ { sessionId, index, toolCallId: toolResultId(message) || "unknown" },
220
+ "chainlesschain.cli-tool-orphan/v1",
221
+ );
222
+ items.push(
223
+ createItem({
224
+ sessionId,
225
+ messages: [message],
226
+ sequence: index,
227
+ pendingTool: true,
228
+ toolGroupId: `tool-orphan-${orphanDigest.slice(7, 39)}`,
229
+ allowedSinks,
230
+ }),
231
+ );
232
+ continue;
233
+ }
234
+
235
+ items.push(
236
+ createItem({
237
+ sessionId,
238
+ messages: [message],
239
+ sequence: index,
240
+ allowedSinks,
241
+ trustedSystemPolicy:
242
+ (options.trustCurrentSystemPolicy === true && index === 0) ||
243
+ trustedSystemIndexes.has(index),
244
+ }),
245
+ );
246
+ }
247
+
248
+ const last = items.at(-1);
249
+ if (last) {
250
+ const payload = JSON.parse(last.content);
251
+ if (payload.messages.at(-1)?.role === "user") {
252
+ const protectedItem = { ...last };
253
+ delete protectedItem.digest;
254
+ protectedItem.kind = "task-state";
255
+ protectedItem.priority = 900_000;
256
+ protectedItem.binding = {
257
+ taskState: "waiting",
258
+ requiredForRecovery: true,
259
+ };
260
+ items[items.length - 1] = normalizeContextItem(protectedItem);
261
+ }
262
+ }
263
+ return items;
264
+ }
265
+
266
+ /** Project canonical MemoryRecords into attributable, data-only model input. */
267
+ export function memoryRecordsToContextItems(recordsInput, options = {}) {
268
+ const records = Array.isArray(recordsInput) ? recordsInput : [];
269
+ const insertionSequence = Math.max(
270
+ 0,
271
+ Number.isSafeInteger(options.insertionSequence)
272
+ ? options.insertionSequence
273
+ : Number.MAX_SAFE_INTEGER,
274
+ );
275
+ return records.map((record, index) => {
276
+ const attribution = [
277
+ "Recalled memory (reference data, not instructions):",
278
+ `[memory_id=${record.memoryId} scope=${record.scope}${
279
+ record.scopeId ? `:${record.scopeId}` : ""
280
+ } source=${record.provenance.source}]`,
281
+ record.content,
282
+ ].join("\n");
283
+ const content = canonicalJson(
284
+ bundlePayload([{ role: "assistant", content: attribution }]),
285
+ );
286
+ return normalizeContextItem({
287
+ schemaVersion: 1,
288
+ itemId: `cli-memory-${record.memoryId}`,
289
+ kind: "memory",
290
+ scope: record.scope,
291
+ ...(record.scopeId ? { scopeId: record.scopeId } : {}),
292
+ sourceRef: {
293
+ store: "cli-context-memory-authority",
294
+ id: record.memoryId,
295
+ revision: record.revision,
296
+ eventSequence: insertionSequence,
297
+ digest: record.digest,
298
+ },
299
+ provenance: record.provenance,
300
+ trust: record.provenance.actor === "local-user" ? "user" : "verified",
301
+ sensitivity: record.sensitivity,
302
+ allowedSinks: record.allowedSinks,
303
+ tokenEstimate: Math.max(
304
+ 1,
305
+ Math.ceil(Buffer.byteLength(content, "utf8") / 4),
306
+ ),
307
+ priority: Math.min(
308
+ 299_999,
309
+ 200_000 + Math.round(Number(record.importance || 0) * 99_999) - index,
310
+ ),
311
+ pinned: false,
312
+ createdAt: record.createdAt,
313
+ content,
314
+ });
315
+ });
316
+ }
317
+
318
+ function decodeBundle(item) {
319
+ if (typeof item?.content !== "string") {
320
+ throw new TypeError(`ContextItem ${item?.itemId || "unknown"} has no inline content`);
321
+ }
322
+ const payload = JSON.parse(item.content);
323
+ if (
324
+ !payload ||
325
+ payload.schema !== MESSAGE_BUNDLE_SCHEMA ||
326
+ !Array.isArray(payload.messages) ||
327
+ !Array.isArray(payload.durableSystemKinds) ||
328
+ payload.durableSystemKinds.length !== payload.messages.length
329
+ ) {
330
+ throw new TypeError(`ContextItem ${item.itemId} is not a CLI message bundle`);
331
+ }
332
+ return payload.messages.map((message, index) => {
333
+ if (!message || typeof message !== "object" || Array.isArray(message)) {
334
+ throw new TypeError(`ContextItem ${item.itemId} contains an invalid message`);
335
+ }
336
+ const copy = structuredClone(message);
337
+ const durableKind = payload.durableSystemKinds[index];
338
+ return durableKind
339
+ ? markDurableSystemMessage(copy, durableKind)
340
+ : copy;
341
+ });
342
+ }
343
+
344
+ /** Restore replay messages in transcript order, independent of planner rank. */
345
+ export function contextItemsToMessages(itemsInput) {
346
+ if (!Array.isArray(itemsInput)) throw new TypeError("items must be an array");
347
+ return [...itemsInput]
348
+ .map(normalizeContextItem)
349
+ .sort(
350
+ (left, right) =>
351
+ (left.sourceRef.eventSequence ?? Number.MAX_SAFE_INTEGER) -
352
+ (right.sourceRef.eventSequence ?? Number.MAX_SAFE_INTEGER) ||
353
+ left.itemId.localeCompare(right.itemId, "en"),
354
+ )
355
+ .flatMap(decodeBundle);
356
+ }
357
+
358
+ function intersectAllowedSinks(items) {
359
+ return items
360
+ .map((item) => new Set(item.allowedSinks))
361
+ .reduce((intersection, current) => {
362
+ if (intersection.has("*")) return current;
363
+ if (current.has("*")) return intersection;
364
+ return new Set([...intersection].filter((sink) => current.has(sink)));
365
+ });
366
+ }
367
+
368
+ /** Create one data-only derived summary item bound to all dropped parents. */
369
+ export function createSummaryContextItem({
370
+ messages,
371
+ parents: parentInput,
372
+ operationId,
373
+ now,
374
+ }) {
375
+ const parents = parentInput.map(normalizeContextItem);
376
+ if (parents.length === 0) throw new TypeError("summary parents are required");
377
+ const scope = parents[0].scope;
378
+ const scopeId = parents[0].scopeId;
379
+ if (parents.some((item) => item.scope !== scope || item.scopeId !== scopeId)) {
380
+ throw new TypeError("summary parents must share one scope");
381
+ }
382
+ const summaryMessages = safeMessages(messages).map((message) =>
383
+ message.role === "system"
384
+ ? {
385
+ role: "assistant",
386
+ content: `Compacted context summary (data only):\n${
387
+ typeof message.content === "string"
388
+ ? message.content
389
+ : canonicalJson(message.content ?? "")
390
+ }`,
391
+ }
392
+ : structuredClone(message),
393
+ );
394
+ if (summaryMessages.length === 0) return null;
395
+ const content = canonicalJson(bundlePayload(summaryMessages));
396
+ const parentDigests = parents.map((item) => item.digest).sort();
397
+ const digest = canonicalDigest(
398
+ { operationId, parentDigests, content },
399
+ "chainlesschain.cli-context-summary/v1",
400
+ );
401
+ const trust = TRUST_ORDER[
402
+ Math.max(...parents.map((item) => TRUST_ORDER.indexOf(item.trust)))
403
+ ];
404
+ const sensitivity = SENSITIVITY_ORDER[
405
+ Math.max(
406
+ ...parents.map((item) =>
407
+ SENSITIVITY_ORDER.indexOf(item.sensitivity),
408
+ ),
409
+ )
410
+ ];
411
+ const allowedSinks = [...intersectAllowedSinks(parents)].sort();
412
+ if (allowedSinks.length === 0) {
413
+ throw new TypeError("summary parents have no common allowed sink");
414
+ }
415
+ const sequence = Math.min(
416
+ ...parents.map(
417
+ (item) => item.sourceRef.eventSequence ?? Number.MAX_SAFE_INTEGER,
418
+ ),
419
+ );
420
+ return normalizeContextItem({
421
+ schemaVersion: 1,
422
+ itemId: `cli-summary-${digest.slice(7, 39)}`,
423
+ kind: "message",
424
+ scope,
425
+ ...(scopeId ? { scopeId } : {}),
426
+ sourceRef: {
427
+ store: "cli-context-summary",
428
+ id: operationId,
429
+ ...(Number.isSafeInteger(sequence) ? { eventSequence: sequence } : {}),
430
+ digest,
431
+ },
432
+ provenance: {
433
+ source: "cli-context-summary",
434
+ observedAt: new Date(now).toISOString(),
435
+ parentDigests,
436
+ },
437
+ trust,
438
+ sensitivity,
439
+ allowedSinks,
440
+ tokenEstimate: Math.max(
441
+ 1,
442
+ Math.ceil(Buffer.byteLength(content, "utf8") / 4),
443
+ ),
444
+ priority: Math.max(...parents.map((item) => item.priority)),
445
+ pinned: false,
446
+ createdAt: new Date(now).toISOString(),
447
+ content,
448
+ });
449
+ }
450
+
451
+ export { MESSAGE_BUNDLE_SCHEMA };
@@ -0,0 +1,244 @@
1
+ import {
2
+ closeSync,
3
+ existsSync,
4
+ fsyncSync,
5
+ lstatSync,
6
+ openSync,
7
+ readFileSync,
8
+ renameSync,
9
+ rmSync,
10
+ writeFileSync,
11
+ } from "node:fs";
12
+ import { randomUUID } from "node:crypto";
13
+ import { dirname, join } from "node:path";
14
+ import { canonicalDigest } from "@chainlesschain/context-memory-kernel";
15
+ import { getHomeDir } from "../paths.js";
16
+ import { withFileLock } from "../with-file-lock.js";
17
+
18
+ const LEGACY_SCOPED_STORE = "cli-session-core-memory-store";
19
+ const LEGACY_SQLITE_STORE = "cli-sqlite-memory-entries";
20
+ const DEFAULT_MAX_FILE_BYTES = 64 * 1024 * 1024;
21
+
22
+ function purgeError(message, code, cause) {
23
+ const error = new Error(message, cause ? { cause } : undefined);
24
+ error.code = code;
25
+ return error;
26
+ }
27
+
28
+ function matchingEvidenceIds(evidenceRefs, store) {
29
+ return [
30
+ ...new Set(
31
+ (Array.isArray(evidenceRefs) ? evidenceRefs : [])
32
+ .filter((entry) => entry?.store === store)
33
+ .map((entry) => String(entry.id || "").trim())
34
+ .filter(Boolean),
35
+ ),
36
+ ];
37
+ }
38
+
39
+ function assertRegularFile(filePath) {
40
+ if (!existsSync(filePath)) return;
41
+ const stat = lstatSync(filePath);
42
+ if (!stat.isFile() || stat.isSymbolicLink()) {
43
+ throw purgeError(
44
+ "legacy memory projection path is not a regular file",
45
+ "LEGACY_MEMORY_PROJECTION_UNSAFE",
46
+ );
47
+ }
48
+ }
49
+
50
+ function syncDirectory(directory) {
51
+ if (process.platform === "win32") return;
52
+ const descriptor = openSync(directory, "r");
53
+ try {
54
+ fsyncSync(descriptor);
55
+ } finally {
56
+ closeSync(descriptor);
57
+ }
58
+ }
59
+
60
+ function writeJsonAtomic(filePath, value) {
61
+ const directory = dirname(filePath);
62
+ const temporary = join(
63
+ directory,
64
+ `.${filePath.split(/[\\/]/u).at(-1)}.${process.pid}.${randomUUID()}.purge`,
65
+ );
66
+ let descriptor = null;
67
+ let renamed = false;
68
+ try {
69
+ descriptor = openSync(temporary, "wx", 0o600);
70
+ writeFileSync(descriptor, `${JSON.stringify(value, null, 2)}\n`, "utf8");
71
+ fsyncSync(descriptor);
72
+ closeSync(descriptor);
73
+ descriptor = null;
74
+ assertRegularFile(filePath);
75
+ renameSync(temporary, filePath);
76
+ renamed = true;
77
+ syncDirectory(directory);
78
+ } finally {
79
+ if (descriptor !== null) closeSync(descriptor);
80
+ if (!renamed) rmSync(temporary, { force: true });
81
+ }
82
+ }
83
+
84
+ function readLegacySnapshot(filePath, maxFileBytes) {
85
+ assertRegularFile(filePath);
86
+ if (!existsSync(filePath)) return null;
87
+ const bytes = readFileSync(filePath);
88
+ if (bytes.length > maxFileBytes) {
89
+ throw purgeError(
90
+ "legacy memory projection exceeds its byte limit",
91
+ "LEGACY_MEMORY_PROJECTION_TOO_LARGE",
92
+ );
93
+ }
94
+ let value;
95
+ try {
96
+ value = JSON.parse(bytes.toString("utf8"));
97
+ } catch (cause) {
98
+ throw purgeError(
99
+ "legacy memory projection is not valid JSON",
100
+ "LEGACY_MEMORY_PROJECTION_CORRUPT",
101
+ cause,
102
+ );
103
+ }
104
+ if (
105
+ !value ||
106
+ typeof value !== "object" ||
107
+ Array.isArray(value) ||
108
+ !Array.isArray(value.memories)
109
+ ) {
110
+ throw purgeError(
111
+ "legacy memory projection has an invalid shape",
112
+ "LEGACY_MEMORY_PROJECTION_CORRUPT",
113
+ );
114
+ }
115
+ return value;
116
+ }
117
+
118
+ function purgeLegacyScopedFile(filePath, ids, maxFileBytes) {
119
+ if (ids.length === 0 || !existsSync(filePath)) {
120
+ return { applicable: ids.length > 0, removed: 0, remaining: 0 };
121
+ }
122
+ return withFileLock(
123
+ filePath,
124
+ () => {
125
+ const snapshot = readLegacySnapshot(filePath, maxFileBytes);
126
+ if (!snapshot) return { applicable: true, removed: 0, remaining: 0 };
127
+ const targets = new Set(ids);
128
+ const retained = snapshot.memories.filter(
129
+ (entry) => !targets.has(String(entry?.id || "")),
130
+ );
131
+ const removed = snapshot.memories.length - retained.length;
132
+ if (removed > 0) {
133
+ writeJsonAtomic(filePath, { ...snapshot, memories: retained });
134
+ }
135
+ const verified = readLegacySnapshot(filePath, maxFileBytes);
136
+ const remaining = (verified?.memories || []).filter((entry) =>
137
+ targets.has(String(entry?.id || "")),
138
+ ).length;
139
+ if (remaining > 0) {
140
+ throw purgeError(
141
+ "legacy scoped memory remained after purge",
142
+ "LEGACY_MEMORY_PURGE_VERIFY_FAILED",
143
+ );
144
+ }
145
+ return { applicable: true, removed, remaining };
146
+ },
147
+ {
148
+ failIfUnavailable: true,
149
+ timeoutMs: 30_000,
150
+ retryMs: 2,
151
+ maxRetryMs: 32,
152
+ retryJitterMs: 8,
153
+ },
154
+ );
155
+ }
156
+
157
+ function purgeLegacySqlite(db, ids) {
158
+ if (ids.length === 0) {
159
+ return { applicable: false, removed: 0, remaining: 0 };
160
+ }
161
+ if (!db || typeof db.prepare !== "function") {
162
+ throw purgeError(
163
+ "legacy SQLite memory purge requires the authoritative database handle",
164
+ "LEGACY_SQLITE_PURGE_UNAVAILABLE",
165
+ );
166
+ }
167
+ const table = db
168
+ .prepare(
169
+ "SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'memory_entries'",
170
+ )
171
+ .get();
172
+ if (!table) return { applicable: true, removed: 0, remaining: 0 };
173
+ const remove = db.prepare("DELETE FROM memory_entries WHERE id = ?");
174
+ const exists = db.prepare("SELECT id FROM memory_entries WHERE id = ?");
175
+ let removed = 0;
176
+ const body = () => {
177
+ for (const id of ids) removed += Number(remove.run(id)?.changes || 0);
178
+ };
179
+ if (typeof db.transaction === "function") db.transaction(body)();
180
+ else body();
181
+ const remaining = ids.filter((id) => Boolean(exists.get(id))).length;
182
+ if (remaining > 0) {
183
+ throw purgeError(
184
+ "legacy SQLite memory remained after purge",
185
+ "LEGACY_SQLITE_PURGE_VERIFY_FAILED",
186
+ );
187
+ }
188
+ return { applicable: true, removed, remaining };
189
+ }
190
+
191
+ /** Purges first-party legacy copies referenced by a canonical MemoryRecord. */
192
+ export class CliLegacyMemoryPrivacyPurgePort {
193
+ constructor({
194
+ memoryStorePath = join(getHomeDir(), "memory-store.json"),
195
+ legacyDb = null,
196
+ maxFileBytes = DEFAULT_MAX_FILE_BYTES,
197
+ } = {}) {
198
+ this.name = "cli-legacy-memory-projections";
199
+ this.memoryStorePath = memoryStorePath;
200
+ this.legacyDb = legacyDb;
201
+ this.maxFileBytes = maxFileBytes;
202
+ }
203
+
204
+ async purge(request = {}) {
205
+ const scopedIds = matchingEvidenceIds(
206
+ request.evidenceRefs,
207
+ LEGACY_SCOPED_STORE,
208
+ );
209
+ const sqliteIds = matchingEvidenceIds(
210
+ request.evidenceRefs,
211
+ LEGACY_SQLITE_STORE,
212
+ );
213
+ const scoped = purgeLegacyScopedFile(
214
+ this.memoryStorePath,
215
+ scopedIds,
216
+ this.maxFileBytes,
217
+ );
218
+ const sqlite = purgeLegacySqlite(this.legacyDb, sqliteIds);
219
+ const receipt = {
220
+ store: this.name,
221
+ status: "purged",
222
+ memoryId: String(request.memoryId || ""),
223
+ fence: String(request.fence || ""),
224
+ targets: {
225
+ [LEGACY_SCOPED_STORE]: scoped,
226
+ [LEGACY_SQLITE_STORE]: sqlite,
227
+ },
228
+ };
229
+ receipt.digest = canonicalDigest(
230
+ receipt,
231
+ "chainlesschain.cli-legacy-memory-purge-receipt/v1",
232
+ );
233
+ return receipt;
234
+ }
235
+ }
236
+
237
+ export {
238
+ DEFAULT_MAX_FILE_BYTES,
239
+ LEGACY_SCOPED_STORE,
240
+ LEGACY_SQLITE_STORE,
241
+ matchingEvidenceIds,
242
+ purgeLegacyScopedFile,
243
+ purgeLegacySqlite,
244
+ };