chainlesschain 0.166.9 → 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 (232) hide show
  1. package/README.md +33 -0
  2. package/bin/chainlesschain.js +5 -0
  3. package/package.json +5 -2
  4. package/src/assets/web-panel/assets/{AIOps-DJvpifGx.js → AIOps-BN25cNOD.js} +1 -1
  5. package/src/assets/web-panel/assets/{ActionButton-D2UhuF_A.js → ActionButton-Da9IP-m5.js} +1 -1
  6. package/src/assets/web-panel/assets/{Analytics-C9ho9obu.js → Analytics-D7hkEvQm.js} +3 -3
  7. package/src/assets/web-panel/assets/{AppLayout-BvRCpFK3.js → AppLayout-CCV4Xnbc.js} +5 -5
  8. package/src/assets/web-panel/assets/{Artifacts-jxrySvpk.js → Artifacts-CVSnVJeA.js} +1 -1
  9. package/src/assets/web-panel/assets/{Audit-ovEw0ZYl.js → Audit-CuYdw5Ag.js} +1 -1
  10. package/src/assets/web-panel/assets/{BackgroundAgents-D7H5z6zS.js → BackgroundAgents-DZCnK-Tf.js} +1 -1
  11. package/src/assets/web-panel/assets/{Backup-BuXob8za.js → Backup-cV9FdpTy.js} +1 -1
  12. package/src/assets/web-panel/assets/{BaseInput-CtnszuQ2.js → BaseInput-BRnv6YSp.js} +1 -1
  13. package/src/assets/web-panel/assets/{Chat-B_mYE8fJ.js → Chat-Bw5w87P4.js} +6 -6
  14. package/src/assets/web-panel/assets/ChatBubbleRenderer-C0GjtUAw.js +1 -0
  15. package/src/assets/web-panel/assets/{Checkbox-ierdtcJD.js → Checkbox-DaoTqcdt.js} +1 -1
  16. package/src/assets/web-panel/assets/{Codegen-3VKPJD_B.js → Codegen-B4dYcEIi.js} +1 -1
  17. package/src/assets/web-panel/assets/{Col-1EdMyf5P.js → Col-mAhuOeuD.js} +1 -1
  18. package/src/assets/web-panel/assets/{Community-D6H7UA8K.js → Community-BK6KEdBk.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compact-BBAZvYIm.js → Compact-CCglmNu5.js} +1 -1
  20. package/src/assets/web-panel/assets/{Compliance-CgsTrAoj.js → Compliance-Cm8S4of7.js} +1 -1
  21. package/src/assets/web-panel/assets/{Cowork-tnZgLoTE.js → Cowork-Dhs1QLMe.js} +3 -3
  22. package/src/assets/web-panel/assets/{Cron-CPpZw2Nh.js → Cron-CLlhmXWk.js} +2 -2
  23. package/src/assets/web-panel/assets/{Crosschain-BymBcp5z.js → Crosschain-BnHVbaNs.js} +1 -1
  24. package/src/assets/web-panel/assets/{DID-DKPxS_K1.js → DID-UzQP9-0O.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dashboard-DvJhEmH9.js → Dashboard-CBdlPClz.js} +2 -2
  26. package/src/assets/web-panel/assets/{Dropdown-b8iQyQIZ.js → Dropdown-axIRPdq1.js} +1 -1
  27. package/src/assets/web-panel/assets/{EmailListRenderer--0-A-zKb.js → EmailListRenderer-DUalW5rx.js} +1 -1
  28. package/src/assets/web-panel/assets/{FamilyGuardDashboard-C12iDN06.js → FamilyGuardDashboard-Bl4W9luY.js} +1 -1
  29. package/src/assets/web-panel/assets/{Federation-BRhaE2Z8.js → Federation-C1yP-uEu.js} +1 -1
  30. package/src/assets/web-panel/assets/{FormItemContext-C4dnq7yf.js → FormItemContext-Xh6Ig5q8.js} +1 -1
  31. package/src/assets/web-panel/assets/{GenericCardRenderer-CGAdbR5n.js → GenericCardRenderer-C2cz3bt2.js} +1 -1
  32. package/src/assets/web-panel/assets/{Git-4eA2fYzL.js → Git-C_z63ixg.js} +2 -2
  33. package/src/assets/web-panel/assets/{Governance-BJuY9Y-9.js → Governance-BYqB33_3.js} +1 -1
  34. package/src/assets/web-panel/assets/{Inference-DZ5Dy4up.js → Inference-CEULuArm.js} +1 -1
  35. package/src/assets/web-panel/assets/{KnowledgeGraph-BMTjRs4A.js → KnowledgeGraph-fgMsu-0H.js} +1 -1
  36. package/src/assets/web-panel/assets/{Logs-BKEeQEfJ.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-Dhho4fEg.js → Marketplace-B8zyLiFe.js} +1 -1
  39. package/src/assets/web-panel/assets/{McpTools-BW6xxSlU.js → McpTools-BLAN2mWW.js} +3 -3
  40. package/src/assets/web-panel/assets/{Memory-mPqlpSkq.js → Memory-CrQcFM7u.js} +2 -2
  41. package/src/assets/web-panel/assets/{MobileBridge-Cb9N_DQI.js → MobileBridge-DVnyiiU-.js} +1 -1
  42. package/src/assets/web-panel/assets/{MobileProjects-BNs8tah_.js → MobileProjects-qjCME5OD.js} +1 -1
  43. package/src/assets/web-panel/assets/{Mtc-CaxBt8tn.js → Mtc-4JE3C3It.js} +2 -2
  44. package/src/assets/web-panel/assets/{MtcAudit-DRPQbp3t.js → MtcAudit-CjBuak9I.js} +5 -5
  45. package/src/assets/web-panel/assets/{Multisig-CRm-d8bK.js → Multisig-BtPcYQcC.js} +3 -3
  46. package/src/assets/web-panel/assets/{NLProgramming-BCCk3LPs.js → NLProgramming-Cx653_Ba.js} +1 -1
  47. package/src/assets/web-panel/assets/{Notes-Cv8SN8gN.js → Notes-CkuD3YzS.js} +4 -4
  48. package/src/assets/web-panel/assets/{NotificationSettings-CggIvTh5.js → NotificationSettings-BgNgU7HH.js} +1 -1
  49. package/src/assets/web-panel/assets/{OrderTableRenderer-BW3_bV12.js → OrderTableRenderer-BTC8W0a-.js} +1 -1
  50. package/src/assets/web-panel/assets/{Organization-BuRE-VCO.js → Organization-Dmd4Hjxz.js} +4 -4
  51. package/src/assets/web-panel/assets/{Overflow-DBrm1gju.js → Overflow-C_5DA-G0.js} +1 -1
  52. package/src/assets/web-panel/assets/{P2P-CWVnDYgS.js → P2P-uwslV4XC.js} +2 -2
  53. package/src/assets/web-panel/assets/{PdhVaultBrowser-8RKUIpte.js → PdhVaultBrowser-CuNgwVnX.js} +5 -5
  54. package/src/assets/web-panel/assets/{Permissions-tDUAxogW.js → Permissions-CJayVX9H.js} +4 -4
  55. package/src/assets/web-panel/assets/{PersonalDataHub-Dv2-CFis.js → PersonalDataHub-Cb05H5go.js} +4 -4
  56. package/src/assets/web-panel/assets/{Pipeline-DM6kvFni.js → Pipeline-BZlGKapZ.js} +1 -1
  57. package/src/assets/web-panel/assets/{Privacy-DzK-yL0d.js → Privacy-BIzZWYzd.js} +1 -1
  58. package/src/assets/web-panel/assets/{ProjectInit-B5UrNpkj.js → ProjectInit-vEYYyQXQ.js} +2 -2
  59. package/src/assets/web-panel/assets/{ProjectSettings-CxJD43oW.js → ProjectSettings-MZqTy5CC.js} +2 -2
  60. package/src/assets/web-panel/assets/Projects-CRARUOl8.js +1 -0
  61. package/src/assets/web-panel/assets/{Providers-CYl4jRYK.js → Providers-80VAK8PX.js} +1 -1
  62. package/src/assets/web-panel/assets/{QrScannerModal-DeH2T0fH.js → QrScannerModal-CzRSoIwK.js} +1 -1
  63. package/src/assets/web-panel/assets/{QuickAsk-Bw9k_kTk.js → QuickAsk-BpwQ2n4C.js} +1 -1
  64. package/src/assets/web-panel/assets/{Recommend-Bl_jGwoi.js → Recommend-BC03TZ79.js} +1 -1
  65. package/src/assets/web-panel/assets/{RemoteSession-d6u01Kq0.js → RemoteSession-DE59-jaa.js} +2 -2
  66. package/src/assets/web-panel/assets/{Reputation-Ds_Dfr-k.js → Reputation-DOHmeWyA.js} +1 -1
  67. package/src/assets/web-panel/assets/{Row-BpQUQTNj.js → Row-hc5RZl1D.js} +1 -1
  68. package/src/assets/web-panel/assets/{RssFeed-BatpZBGt.js → RssFeed-Cv5uMP7E.js} +3 -3
  69. package/src/assets/web-panel/assets/{Search-D7hOObzi.js → Search-qohu7Ug0.js} +1 -1
  70. package/src/assets/web-panel/assets/{Security-dXQ4FKNt.js → Security-drCPFWV5.js} +4 -4
  71. package/src/assets/web-panel/assets/{Services-D8wInGPa.js → Services-BAEgUeRy.js} +2 -2
  72. package/src/assets/web-panel/assets/{Skeleton-DXQCoYpM.js → Skeleton-CkJkKBlo.js} +1 -1
  73. package/src/assets/web-panel/assets/{Skills-D3oLRIVn.js → Skills-bMuKEpez.js} +1 -1
  74. package/src/assets/web-panel/assets/{Sla-BmP4-LnJ.js → Sla-DxWQVHRC.js} +1 -1
  75. package/src/assets/web-panel/assets/{SpeechSettings-DLj-xzro.js → SpeechSettings-BpS8idmV.js} +1 -1
  76. package/src/assets/web-panel/assets/{SyncSettings-8KKaaRMr.js → SyncSettings-BPBLlW5v.js} +2 -2
  77. package/src/assets/web-panel/assets/{Tasks-GyK42I7C.js → Tasks-C4SLEeUh.js} +1 -1
  78. package/src/assets/web-panel/assets/{Templates-n1y_8UBG.js → Templates-r-wfU39U.js} +1 -1
  79. package/src/assets/web-panel/assets/{Tenant-B39nBph8.js → Tenant-C7vjRmLN.js} +1 -1
  80. package/src/assets/web-panel/assets/{Terminal-DCQoOKXe.js → Terminal-DdzeFCV2.js} +2 -2
  81. package/src/assets/web-panel/assets/{TimelineRenderer-BkhbDfXk.js → TimelineRenderer-CYyWN2KD.js} +1 -1
  82. package/src/assets/web-panel/assets/{Tokens-BeHIIU8D.js → Tokens-D8A9osUg.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trigger-BHvWXVOb.js → Trigger-DBvrNlyS.js} +1 -1
  84. package/src/assets/web-panel/assets/{Trust-y2WaOSto.js → Trust-DBVAGc7o.js} +1 -1
  85. package/src/assets/web-panel/assets/{UkeySign-DBFeJBzt.js → UkeySign-C1vQUCRJ.js} +1 -1
  86. package/src/assets/web-panel/assets/{VideoEditing-BEOWitC-.js → VideoEditing-BKs4dah4.js} +1 -1
  87. package/src/assets/web-panel/assets/{Wallet-BITedTe6.js → Wallet-ByIuj3lD.js} +4 -4
  88. package/src/assets/web-panel/assets/{WebAuthn-DMwlJVin.js → WebAuthn-DYlAFCm9.js} +3 -3
  89. package/src/assets/web-panel/assets/{WorkflowEditor-CKfGFEu1.js → WorkflowEditor-Dwyadd0c.js} +1 -1
  90. package/src/assets/web-panel/assets/{chat-DR6gnBGF.js → chat-Bm2f3s08.js} +1 -1
  91. package/src/assets/web-panel/assets/{colors-C_Hw5NCn.js → colors-C8ORSh7V.js} +1 -1
  92. package/src/assets/web-panel/assets/{compact-item-B8IPwsEu.js → compact-item-1iVlnsM-.js} +1 -1
  93. package/src/assets/web-panel/assets/{createContext-D-u4JVnJ.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-CZubdS4D.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-C25rOz7O.js → index-B53c3diB.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-CfniPP5p.js → index-B59OWAs7.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-11ASqx-A.js → index-B8BrB0Ls.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-auyNYjLo.js → index-BC32_0xT.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-Ctje8Vl3.js → index-BC8Wb6cy.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-Cg2bCeol.js → index-BCOhTILd.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-D1w96gg9.js → index-BFniLMn9.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-k1Xa5iw1.js → index-BIvM-uAX.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-DuOU5apg.js → index-BK-RY0-7.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-D47jt8ET.js → index-BQL9r73Y.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-C2VmtNaQ.js → index-BVtnizyC.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-Bizm87cX.js → index-Bf1PlIHp.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-Dt-w3xQ7.js → index-Bgw4Y2rU.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-ffe7bvqP.js → index-BgwLNxmr.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-Cl5RpreD.js → index-C-J5-pGH.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-idZKyADQ.js → index-C-ZIHi42.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-LvjAKDSl.js → index-C3B1S-mW.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-DmRcgiYT.js → index-C5RfRciU.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-rYBHSDcJ.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-DcFjRT-K.js → index-CTfEmKK0.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-DjRrqooR.js → index-CfiHyVyl.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-DpjHpRoq.js → index-CkFvuAex.js} +3 -3
  120. package/src/assets/web-panel/assets/{index-BzoFanEQ.js → index-D98FXb0w.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-Cbm8F0M2.js → index-DDHk911Q.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-BXS6wYJZ.js → index-DJxtPFOh.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-DY6MHo9D.js → index-DVJ1uKf4.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-CiXkhOkY.js → index-Dcck8QfW.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-mYZJxGH6.js → index-DgUE51Pz.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-CqmLw8cs.js → index-Dsve5Gkv.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-xoNssgz_.js → index-DvedhJeM.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-DfnzrUxU.js → index-DwMdWKiF.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-Bi21Etg4.js → index-OcbzdRpT.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-DJ6pG79m.js → index-fPK6GFEg.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-_nL79NT8.js → index-geQinnns.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-DTosx2Wu.js → index-pHWA7bmM.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-cVqbas5C.js → index-reUHhuz8.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-Bv2132PO.js → index-tqTx5wXo.js} +1 -1
  135. package/src/assets/web-panel/assets/{initDefaultProps-lcU_dT2r.js → initDefaultProps-CuA-cpkL.js} +1 -1
  136. package/src/assets/web-panel/assets/{motion-Dc7UNXZ1.js → motion-CimmE_9b.js} +1 -1
  137. package/src/assets/web-panel/assets/{move-Cll8ZXaL.js → move-DlGlrltz.js} +1 -1
  138. package/src/assets/web-panel/assets/{mtc-parser-CAb_yLIM.js → mtc-parser-CK6BJQ07.js} +1 -1
  139. package/src/assets/web-panel/assets/{omit-DurYMyTe.js → omit-BKjBfZfB.js} +1 -1
  140. package/src/assets/web-panel/assets/{pickAttrs-BITQyOlw.js → pickAttrs-B2chVYw9.js} +1 -1
  141. package/src/assets/web-panel/assets/{placementArrow-Dg1rH91i.js → placementArrow-BW8aLJJ3.js} +1 -1
  142. package/src/assets/web-panel/assets/{responsiveObserve-D_EWIeac.js → responsiveObserve-dXlPl66S.js} +1 -1
  143. package/src/assets/web-panel/assets/{slide-lK4d3zsh.js → slide-hSa89S4G.js} +1 -1
  144. package/src/assets/web-panel/assets/{statusUtils-Bflq-Git.js → statusUtils-DM6KLt-s.js} +1 -1
  145. package/src/assets/web-panel/assets/{styleChecker-Ccp0I-wt.js → styleChecker-C9MQAK15.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFlexGapSupport-CYZbByYA.js → useFlexGapSupport-BpQDpP0z.js} +1 -1
  147. package/src/assets/web-panel/assets/{useFs-B_x0nxFD.js → useFs-C7rtRViA.js} +1 -1
  148. package/src/assets/web-panel/assets/{usePersonalDataHub-DW55rL85.js → usePersonalDataHub-Dm15xafq.js} +1 -1
  149. package/src/assets/web-panel/assets/{vnode-Ca6MH3W8.js → vnode-mEiEytw4.js} +1 -1
  150. package/src/assets/web-panel/assets/{zoom-NdHelOog.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 +41 -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/index.js +2 -0
  195. package/src/lib/graph-kernel/migration-saga.js +2 -2
  196. package/src/lib/graph-kernel/production-cutover-evidence.js +976 -0
  197. package/src/lib/graph-kernel/retirement-evidence.js +12 -4
  198. package/src/lib/hierarchical-memory.js +22 -0
  199. package/src/lib/hook-audit-store.js +170 -0
  200. package/src/lib/hook-event-bus.cjs +0 -0
  201. package/src/lib/hook-manager.js +25 -83
  202. package/src/lib/hook-runtime-adapters.js +233 -0
  203. package/src/lib/hook-runtime-contract.cjs +291 -0
  204. package/src/lib/hook-runtime-contract.js +21 -0
  205. package/src/lib/hook-trust.js +210 -0
  206. package/src/lib/hooks-v2-producers.js +52 -6
  207. package/src/lib/hooks-v2-runtime.js +443 -178
  208. package/src/lib/llm-pricing.js +10 -0
  209. package/src/lib/memory-manager.js +29 -4
  210. package/src/lib/model-context-window.js +52 -0
  211. package/src/lib/permanent-memory.js +17 -0
  212. package/src/lib/plan-mode.js +8 -4
  213. package/src/lib/process-execution-broker/index.js +208 -16
  214. package/src/lib/runtime-usage-ledger.js +20 -0
  215. package/src/lib/session-consolidator.js +59 -0
  216. package/src/lib/session-core-singletons.js +17 -4
  217. package/src/lib/session-hooks.js +29 -2
  218. package/src/lib/session-transcript-migration.js +188 -0
  219. package/src/lib/settings-hook-events.cjs +37 -401
  220. package/src/lib/settings-hook-events.js +210 -8
  221. package/src/lib/settings-hooks.cjs +42 -83
  222. package/src/lib/ws-session-manager.js +4 -1
  223. package/src/repl/agent-repl.js +186 -53
  224. package/src/runtime/agent-core.js +376 -350
  225. package/src/runtime/headless-runner.js +40 -33
  226. package/src/runtime/headless-stream.js +131 -30
  227. package/src/assets/web-panel/assets/ChatBubbleRenderer-DaiA6CsX.js +0 -1
  228. package/src/assets/web-panel/assets/MarkdownRenderer-B05DgASC.js +0 -1
  229. package/src/assets/web-panel/assets/Projects-Z2Orm8Ma.js +0 -1
  230. package/src/assets/web-panel/assets/devWarning-Cq6lSd_q.js +0 -1
  231. package/src/assets/web-panel/assets/index-BQ3213fz.js +0 -1
  232. package/src/assets/web-panel/assets/index-vJagfET2.js +0 -1
@@ -1,9 +1,20 @@
1
1
  import { createHash, randomUUID } from "node:crypto";
2
2
  import { BoundedAsyncQueue, QueueOverloadedError } from "./bounded-queue.js";
3
3
  import { CliAgentKernelAdapter } from "./cli-agent-kernel-adapter.js";
4
- import { JsonlRolloutStore } from "./rollout-store.js";
4
+ import { assertRolloutStore } from "./rollout-store.js";
5
+ import {
6
+ closeRolloutStore,
7
+ createRolloutStore,
8
+ } from "./rollout-store-factory.js";
5
9
  import { AppServerGraphRuntime } from "./graph-runtime.js";
6
10
  import { compileGraphDefinition } from "../graph-kernel/compiler.js";
11
+ import { createCliContextMemoryRuntime } from "../context-memory-kernel/runtime.js";
12
+ import {
13
+ contextPlanCreatedNotification,
14
+ memoryDeletionNotification,
15
+ memoryMutationNotification,
16
+ memoryRecalledNotification,
17
+ } from "./context-memory-notifications.js";
7
18
  import {
8
19
  APP_SERVER_MIN_PROTOCOL_VERSION,
9
20
  APP_SERVER_PROTOCOL_VERSION,
@@ -19,7 +30,6 @@ import {
19
30
  } from "./protocol.js";
20
31
 
21
32
  const TERMINAL_TURN_STATUSES = new Set(["completed", "failed", "interrupted"]);
22
-
23
33
  function stableValue(value) {
24
34
  if (Array.isArray(value)) return value.map(stableValue);
25
35
  if (!value || typeof value !== "object") return value;
@@ -96,13 +106,34 @@ function publicError(error) {
96
106
  ) {
97
107
  return new JsonRpcError(JSON_RPC_ERROR.CONFLICT, error.message);
98
108
  }
109
+ if (error?.code === "invalid_argument") {
110
+ return new JsonRpcError(
111
+ JSON_RPC_ERROR.INVALID_PARAMS,
112
+ error.message,
113
+ error.details || null,
114
+ );
115
+ }
116
+ if (
117
+ [
118
+ "revision_conflict",
119
+ "legacy_writer_fenced",
120
+ "scope_denied",
121
+ "replica_tombstone_fenced",
122
+ ].includes(error?.code)
123
+ ) {
124
+ return new JsonRpcError(
125
+ JSON_RPC_ERROR.CONFLICT,
126
+ error.message,
127
+ error.details || null,
128
+ );
129
+ }
99
130
  return error;
100
131
  }
101
132
 
102
133
  export class CcAppServer {
103
134
  constructor({
104
135
  send,
105
- store = new JsonlRolloutStore(),
136
+ store = null,
106
137
  kernel = new CliAgentKernelAdapter(),
107
138
  now = Date.now,
108
139
  createId = randomUUID,
@@ -113,22 +144,31 @@ export class CcAppServer {
113
144
  interruptSettlementMs = 30_000,
114
145
  transport = "stdio",
115
146
  graphRuntime = null,
147
+ contextMemoryRuntimeFactory = createCliContextMemoryRuntime,
116
148
  } = {}) {
117
149
  if (typeof send !== "function") {
118
150
  throw new TypeError("CcAppServer requires a send(message) function");
119
151
  }
152
+ const resolvedStore = assertRolloutStore(store || createRolloutStore(), {
153
+ requireList: true,
154
+ });
120
155
  this.send = send;
121
- this.store = store;
156
+ this.store = resolvedStore;
157
+ this._ownsStore = store == null;
122
158
  this.kernel = kernel;
123
159
  this.now = now;
124
160
  this.createId = createId;
125
161
  this.requestTimeoutMs = requestTimeoutMs;
126
162
  this.interruptSettlementMs = interruptSettlementMs;
127
163
  this.transport = transport === "websocket" ? "websocket" : "stdio";
164
+ if (typeof contextMemoryRuntimeFactory !== "function") {
165
+ throw new TypeError("contextMemoryRuntimeFactory must be a function");
166
+ }
167
+ this.contextMemoryRuntimeFactory = contextMemoryRuntimeFactory;
128
168
  this.graphRuntime =
129
169
  graphRuntime ||
130
170
  new AppServerGraphRuntime({
131
- rolloutStore: store,
171
+ rolloutStore: resolvedStore,
132
172
  now,
133
173
  createId,
134
174
  executeNode: (context) => this._executeGraphNode(context),
@@ -299,6 +339,13 @@ export class CcAppServer {
299
339
  "graph/history": () => this._graphHistory(message.params),
300
340
  "graph/cancel": () => this._graphCancel(message.params),
301
341
  "graph/reconcile": () => this._graphReconcile(message.params),
342
+ "context/plan": () => this._contextPlan(message.params),
343
+ "context/compact": () => this._contextCompact(message.params),
344
+ "memory/recall": () => this._memoryRecall(message.params),
345
+ "memory/propose": () => this._memoryPropose(message.params),
346
+ "memory/decide": () => this._memoryDecide(message.params),
347
+ "memory/delete": () => this._memoryDelete(message.params),
348
+ "memory/reconcile": () => this._memoryReconcile(message.params),
302
349
  };
303
350
  const handler = handlers[method];
304
351
  if (!handler) {
@@ -353,6 +400,132 @@ export class CcAppServer {
353
400
  });
354
401
  }
355
402
 
403
+ _contextMemoryRuntime(options = {}) {
404
+ const runtime = this.contextMemoryRuntimeFactory(options);
405
+ if (!runtime?.kernel) {
406
+ throw new Error("Context/Memory runtime factory returned no kernel");
407
+ }
408
+ return runtime;
409
+ }
410
+
411
+ async _contextPlan(rawParams) {
412
+ const params = requireObject(rawParams);
413
+ const runtime = this._contextMemoryRuntime({
414
+ scopeKey: `app-server:context:${params.sessionHead || "plan"}`,
415
+ });
416
+ try {
417
+ const plan = await runtime.kernel.planContext(params);
418
+ const notification = contextPlanCreatedNotification(plan);
419
+ await this._notify(notification.method, notification.params);
420
+ return plan;
421
+ } catch (error) {
422
+ await this._notify("context/event", {
423
+ type: "context.plan.rejected",
424
+ reason_code: safeId(error?.code, "context_plan_failed"),
425
+ });
426
+ throw error;
427
+ }
428
+ }
429
+
430
+ async _contextCompact(rawParams) {
431
+ const params = requireObject(rawParams);
432
+ const sessionId = requiredString(params.sessionId, "sessionId");
433
+ const operationId = requiredString(params.operationId, "operationId");
434
+ const runtime = this._contextMemoryRuntime({ sessionId });
435
+ await this._notify("context/event", {
436
+ type: "context.compaction.started",
437
+ operation_id: operationId,
438
+ session_id: sessionId,
439
+ });
440
+ try {
441
+ const receipt = await runtime.kernel.compactContext(params);
442
+ const type =
443
+ receipt.status === "reconciliation_required"
444
+ ? "context.compaction.reconciliation_required"
445
+ : ["committed", "degraded"].includes(receipt.status)
446
+ ? "context.compaction.committed"
447
+ : "context.compaction.aborted";
448
+ await this._notify("context/event", {
449
+ type,
450
+ operation_id: operationId,
451
+ session_id: sessionId,
452
+ ...(type === "context.compaction.aborted"
453
+ ? { reason_code: safeId(receipt.status, "compaction_aborted") }
454
+ : { receipt }),
455
+ });
456
+ return receipt;
457
+ } catch (error) {
458
+ await this._notify("context/event", {
459
+ type: "context.compaction.aborted",
460
+ operation_id: operationId,
461
+ session_id: sessionId,
462
+ reason_code: safeId(error?.code, "compaction_failed"),
463
+ });
464
+ throw error;
465
+ }
466
+ }
467
+
468
+ async _memoryRecall(rawParams) {
469
+ const params = requireObject(rawParams);
470
+ const runtime = this._contextMemoryRuntime({
471
+ scopeKey: "app-server:memory",
472
+ });
473
+ const result = await runtime.kernel.recallMemory(params);
474
+ const notification = memoryRecalledNotification(result);
475
+ await this._notify(notification.method, notification.params);
476
+ return result;
477
+ }
478
+
479
+ async _memoryPropose(rawParams) {
480
+ const params = requireObject(rawParams);
481
+ const runtime = this._contextMemoryRuntime({
482
+ scopeKey: "app-server:memory",
483
+ });
484
+ const mutation = await runtime.kernel.proposeMemory(params);
485
+ await this._notifyMemoryMutation(mutation);
486
+ return mutation;
487
+ }
488
+
489
+ async _memoryDecide(rawParams) {
490
+ const params = requireObject(rawParams);
491
+ const runtime = this._contextMemoryRuntime({
492
+ scopeKey: "app-server:memory",
493
+ });
494
+ const mutation = await runtime.kernel.decideMemory(params);
495
+ await this._notifyMemoryMutation(mutation);
496
+ return mutation;
497
+ }
498
+
499
+ async _notifyMemoryMutation(mutation) {
500
+ const notification = memoryMutationNotification(mutation);
501
+ if (!notification) return;
502
+ await this._notify(notification.method, notification.params);
503
+ }
504
+
505
+ async _memoryDelete(rawParams) {
506
+ const params = requireObject(rawParams);
507
+ const runtime = this._contextMemoryRuntime({
508
+ scopeKey: "app-server:memory",
509
+ });
510
+ const receipt = await runtime.kernel.deleteMemory(params);
511
+ const notification = memoryDeletionNotification(receipt);
512
+ await this._notify(notification.method, notification.params);
513
+ return receipt;
514
+ }
515
+
516
+ async _memoryReconcile(rawParams) {
517
+ const params = requireObject(rawParams);
518
+ const operationId = requiredString(params.operationId, "operationId");
519
+ const runtime = this._contextMemoryRuntime({
520
+ scopeKey: "app-server:memory",
521
+ });
522
+ const result = await runtime.kernel.reconcile(operationId);
523
+ const notification = memoryDeletionNotification(result, operationId);
524
+ if (notification)
525
+ await this._notify(notification.method, notification.params);
526
+ return result;
527
+ }
528
+
356
529
  _graphCompile(rawParams) {
357
530
  const params = requireObject(rawParams);
358
531
  const compiled = compileGraphDefinition(
@@ -1115,7 +1288,11 @@ export class CcAppServer {
1115
1288
  );
1116
1289
  }
1117
1290
  this.pendingClientRequests.clear();
1118
- await this.kernel.close?.();
1119
- await Promise.all(this.workers);
1291
+ try {
1292
+ await this.kernel.close?.();
1293
+ await Promise.all(this.workers);
1294
+ } finally {
1295
+ if (this._ownsStore) closeRolloutStore(this.store);
1296
+ }
1120
1297
  }
1121
1298
  }
@@ -6,17 +6,32 @@ import { createRequire } from "node:module";
6
6
  import {
7
7
  ROLLOUT_STORE_SCHEMA,
8
8
  ROLLOUT_STORE_VERSION,
9
+ migrateRolloutStore,
9
10
  _rolloutStoreInternals,
10
11
  } from "./rollout-store.js";
11
12
 
12
- const { buildRecord, canonicalJson, projectThread, verifyRecords } =
13
- _rolloutStoreInternals;
13
+ const {
14
+ assertExpectedHead,
15
+ buildRecord,
16
+ canonicalJson,
17
+ projectThread,
18
+ startPayload,
19
+ verifyRecords,
20
+ } = _rolloutStoreInternals;
14
21
 
15
22
  let DatabaseSync = null;
16
- try {
17
- ({ DatabaseSync } = createRequire(import.meta.url)("node:sqlite"));
18
- } catch {
19
- // node:sqlite is optional on the minimum supported Node 22.12 runtime.
23
+ let sqliteProbed = false;
24
+
25
+ function loadDatabaseSync() {
26
+ if (!sqliteProbed) {
27
+ sqliteProbed = true;
28
+ try {
29
+ ({ DatabaseSync } = createRequire(import.meta.url)("node:sqlite"));
30
+ } catch {
31
+ // node:sqlite is optional on the minimum supported Node 22.12 runtime.
32
+ }
33
+ }
34
+ return DatabaseSync;
20
35
  }
21
36
 
22
37
  function sqliteError(code, message, cause = null) {
@@ -40,7 +55,7 @@ function recordThreadId(input) {
40
55
  }
41
56
 
42
57
  export function sqliteRolloutStoreAvailable() {
43
- return typeof DatabaseSync === "function";
58
+ return typeof loadDatabaseSync() === "function";
44
59
  }
45
60
 
46
61
  export class SqliteRolloutStore {
@@ -50,13 +65,14 @@ export class SqliteRolloutStore {
50
65
  if (this.filename !== ":memory:") {
51
66
  fs.mkdirSync(path.dirname(this.filename), { recursive: true });
52
67
  }
53
- if (!database && !sqliteRolloutStoreAvailable()) {
68
+ const SqliteDatabase = database ? null : loadDatabaseSync();
69
+ if (!database && typeof SqliteDatabase !== "function") {
54
70
  throw sqliteError(
55
71
  "CC_ROLLOUT_SQLITE_UNAVAILABLE",
56
72
  "SQLite rollout storage requires a Node runtime with node:sqlite",
57
73
  );
58
74
  }
59
- this.db = database || new DatabaseSync(this.filename);
75
+ this.db = database || new SqliteDatabase(this.filename);
60
76
  this.db.exec("PRAGMA journal_mode = WAL");
61
77
  this.db.exec("PRAGMA synchronous = FULL");
62
78
  this.db.exec("PRAGMA foreign_keys = ON");
@@ -148,6 +164,7 @@ export class SqliteRolloutStore {
148
164
  title = null,
149
165
  parentThreadId = null,
150
166
  metadata = {},
167
+ timestamp: startedAt = null,
151
168
  } = {}) {
152
169
  const id = recordThreadId(threadId);
153
170
  return this._transaction(() => {
@@ -158,7 +175,8 @@ export class SqliteRolloutStore {
158
175
  threadId: id,
159
176
  eventType: "thread.started",
160
177
  idempotencyKey: `thread:${id}`,
161
- payload: { title, parentThreadId, metadata },
178
+ timestamp: startedAt || undefined,
179
+ payload: startPayload({ title, parentThreadId, metadata }),
162
180
  },
163
181
  null,
164
182
  this.now,
@@ -199,6 +217,7 @@ export class SqliteRolloutStore {
199
217
  }
200
218
  return clone(duplicate);
201
219
  }
220
+ assertExpectedHead(input, records);
202
221
  const record = buildRecord(input, records.at(-1), this.now);
203
222
  this.db
204
223
  .prepare(
@@ -237,7 +256,7 @@ export class SqliteRolloutStore {
237
256
  .map((threadId) => this.resume(threadId))
238
257
  .filter((thread) => includeArchived || thread.status !== "archived")
239
258
  .sort((left, right) => right.updatedAt.localeCompare(left.updatedAt))
240
- .slice(0, Math.max(1, Number(limit) || 100));
259
+ .slice(0, Math.max(1, Math.min(100_000, Number(limit) || 100)));
241
260
  }
242
261
 
243
262
  forkThread(sourceThreadId, { threadId = randomUUID(), title = null } = {}) {
@@ -261,6 +280,10 @@ export class SqliteRolloutStore {
261
280
  return this.resume(target.id);
262
281
  }
263
282
 
283
+ fork(sourceThreadId, options = {}) {
284
+ return this.forkThread(sourceThreadId, options);
285
+ }
286
+
264
287
  checkpoint(threadId, payload = {}) {
265
288
  return this.append({
266
289
  threadId,
@@ -271,13 +294,19 @@ export class SqliteRolloutStore {
271
294
  }
272
295
 
273
296
  compact(threadId, options = {}) {
297
+ if (typeof options.summary !== "string" || !options.summary.trim()) {
298
+ throw sqliteError(
299
+ "CC_ROLLOUT_INVALID_ARGUMENT",
300
+ "compaction summary is required",
301
+ );
302
+ }
274
303
  return this.append({
275
304
  threadId,
276
305
  eventType: "rollout.compacted",
277
306
  idempotencyKey: options.idempotencyKey || null,
278
307
  payload: {
279
- summary: String(options.summary || ""),
280
- retainedState: options.retainedState || {},
308
+ summary: options.summary,
309
+ retainedState: options.retainedState ?? {},
281
310
  },
282
311
  });
283
312
  }
@@ -292,11 +321,25 @@ export class SqliteRolloutStore {
292
321
  return this.resume(threadId);
293
322
  }
294
323
 
295
- migrate({ fromVersion = 1, toVersion = 1, dryRun = true } = {}) {
324
+ migrate({
325
+ fromVersion = 1,
326
+ toVersion = 1,
327
+ dryRun = true,
328
+ targetStore = null,
329
+ threadIds = null,
330
+ } = {}) {
331
+ if (targetStore) {
332
+ return migrateRolloutStore({
333
+ sourceStore: this,
334
+ targetStore,
335
+ threadIds,
336
+ dryRun,
337
+ });
338
+ }
296
339
  if (Number(fromVersion) !== 1 || Number(toVersion) !== 1) {
297
340
  throw sqliteError(
298
- "CC_ROLLOUT_VERSION_UNSUPPORTED",
299
- "SQLite rollout adapter currently supports schema v1 only",
341
+ "CC_ROLLOUT_MIGRATION_UNSUPPORTED",
342
+ `rollout migration ${fromVersion} -> ${toVersion} is unsupported`,
300
343
  );
301
344
  }
302
345
  return Object.freeze({
@@ -321,6 +321,12 @@ export function createAutoModeApprovalGate(inner, resolved, opts = {}) {
321
321
  clearSessionPolicy(sessionId) {
322
322
  return inner?.clearSessionPolicy?.(sessionId);
323
323
  },
324
+ awaitPersistence() {
325
+ return inner?.awaitPersistence?.();
326
+ },
327
+ hasPolicyStore() {
328
+ return inner?.hasPolicyStore?.() === true;
329
+ },
324
330
  setConfirmer(fn) {
325
331
  confirm = typeof fn === "function" ? fn : null;
326
332
  inner?.setConfirmer?.(fn);
@@ -360,6 +366,26 @@ export function createAutoModeApprovalGate(inner, resolved, opts = {}) {
360
366
  return inner?.createAuthorizationBinder?.() || null;
361
367
  },
362
368
  async decide(ctx = {}) {
369
+ const shouldCheckPersistence =
370
+ typeof inner?.awaitPersistence === "function" &&
371
+ (typeof inner?.hasPolicyStore !== "function" ||
372
+ inner.hasPolicyStore() === true);
373
+ if (shouldCheckPersistence) {
374
+ try {
375
+ await inner.awaitPersistence();
376
+ } catch (error) {
377
+ return {
378
+ decision: "deny",
379
+ via: "policy-store-error",
380
+ base: "deny",
381
+ policy: "auto-mode",
382
+ riskLevel: RISK_LEVELS.includes(ctx.riskLevel)
383
+ ? ctx.riskLevel
384
+ : "low",
385
+ error,
386
+ };
387
+ }
388
+ }
363
389
  if (!isActive()) return inner.decide(ctx);
364
390
  const riskLevel = RISK_LEVELS.includes(ctx.riskLevel)
365
391
  ? ctx.riskLevel
@@ -532,6 +532,11 @@ function modelUsageBoundaryIdentity(data, field) {
532
532
  ),
533
533
  model: boundedLabel(data.model, `${field} model`, MAX_MODEL_LENGTH),
534
534
  source: normalizedUsageSource(data.source, `${field} source`),
535
+ operationId: boundedLabel(
536
+ data.operationId,
537
+ `${field} operationId`,
538
+ MAX_ID_LENGTH,
539
+ ),
535
540
  };
536
541
  }
537
542
 
@@ -539,7 +544,8 @@ function sameModelUsageIdentity(left, right) {
539
544
  return (
540
545
  left.provider === right.provider &&
541
546
  left.model === right.model &&
542
- left.source === right.source
547
+ left.source === right.source &&
548
+ left.operationId === right.operationId
543
549
  );
544
550
  }
545
551
 
@@ -641,6 +647,11 @@ function strictUsage(event) {
641
647
  }
642
648
  return {
643
649
  callId,
650
+ operationId: boundedLabel(
651
+ data.operationId,
652
+ "session usage operationId",
653
+ MAX_ID_LENGTH,
654
+ ),
644
655
  provider: usageIdentity(
645
656
  data,
646
657
  raw,
@@ -1047,6 +1058,7 @@ export function createVerifiedSessionObservabilityProjection(
1047
1058
  provider: usage.provider,
1048
1059
  model: usage.model,
1049
1060
  source: usage.source,
1061
+ operationId: usage.operationId,
1050
1062
  };
1051
1063
  if (previous && !sameModelUsageIdentity(previous, identity)) {
1052
1064
  throw new Error(
@@ -0,0 +1,95 @@
1
+ import { createHash } from "node:crypto";
2
+ import {
3
+ ContextMemoryAuthorityRegistry,
4
+ CUTOVER_STAGES,
5
+ } from "@chainlesschain/context-memory-kernel";
6
+
7
+ const STAGE_ENV = "CHAINLESSCHAIN_CONTEXT_MEMORY_CLI_STAGE";
8
+ const OPT_IN_ENV = "CHAINLESSCHAIN_CONTEXT_MEMORY_CLI_OPT_IN";
9
+ const CANARY_PERCENT_ENV = "CHAINLESSCHAIN_CONTEXT_MEMORY_CLI_CANARY_PERCENT";
10
+
11
+ function boundedPercent(value, fallback) {
12
+ const parsed = Number(value);
13
+ if (!Number.isFinite(parsed)) return fallback;
14
+ return Math.max(0, Math.min(100, parsed));
15
+ }
16
+
17
+ function cohortBucket(scopeKey) {
18
+ const digest = createHash("sha256").update(scopeKey).digest();
19
+ return digest.readUInt32BE(0) % 10_000;
20
+ }
21
+
22
+ export function resolveCliContextMemoryCutover({
23
+ env = process.env,
24
+ scopeKey = "cli:global",
25
+ } = {}) {
26
+ const stage = env[STAGE_ENV] || "shadow";
27
+ if (!CUTOVER_STAGES.includes(stage)) {
28
+ const error = new Error(`Unsupported CLI Context/Memory stage: ${stage}`);
29
+ error.code = "CONTEXT_MEMORY_STAGE_INVALID";
30
+ throw error;
31
+ }
32
+ let canonical = false;
33
+ let reason = stage;
34
+ if (stage === "internal_canary") {
35
+ const percent = boundedPercent(env[CANARY_PERCENT_ENV], 1);
36
+ canonical = cohortBucket(scopeKey) < percent * 100;
37
+ reason = canonical ? "internal_canary_selected" : "internal_canary_control";
38
+ } else if (stage === "opt_in_canary") {
39
+ canonical = env[OPT_IN_ENV] === "1";
40
+ reason = canonical ? "explicit_opt_in" : "not_opted_in";
41
+ } else if (
42
+ ["canonical_default", "legacy_read_only", "retired"].includes(stage)
43
+ ) {
44
+ canonical = true;
45
+ }
46
+ return Object.freeze({
47
+ stage,
48
+ scopeKey,
49
+ mode: canonical ? "canonical" : "legacy",
50
+ canonical,
51
+ shadow: stage === "shadow",
52
+ // A selected canonical cohort must never run a second legacy writer. This
53
+ // also covers canonical_default; legacy_read_only/retired only tighten the
54
+ // corresponding read capability.
55
+ legacyWritable: !canonical,
56
+ legacyReadable: stage !== "retired",
57
+ reason,
58
+ cohortBucket: cohortBucket(scopeKey),
59
+ });
60
+ }
61
+
62
+ export function createCliAuthority({ decision, now = Date.now } = {}) {
63
+ if (!decision?.canonical) return { registry: null, writer: null };
64
+ const registry = new ContextMemoryAuthorityRegistry({ clock: now });
65
+ const writer = Object.freeze({
66
+ scopeKey: decision.scopeKey,
67
+ surface: "cli",
68
+ mode: "canonical",
69
+ writerId: "cli-context-memory-kernel",
70
+ generation: 1,
71
+ });
72
+ registry.bind({
73
+ ...writer,
74
+ stage: decision.stage,
75
+ leaseExpiresAt: new Date(Number(now()) + 5 * 60_000).toISOString(),
76
+ });
77
+ registry.assertWriter(writer);
78
+ return { registry, writer };
79
+ }
80
+
81
+ export function assertLegacyMutationAllowed(decision) {
82
+ if (decision?.legacyWritable) return;
83
+ const error = new Error(
84
+ `Legacy CLI Context/Memory mutations are fenced at ${decision?.stage || "unknown"}`,
85
+ );
86
+ error.code = "legacy_writer_fenced";
87
+ throw error;
88
+ }
89
+
90
+ export {
91
+ CANARY_PERCENT_ENV,
92
+ OPT_IN_ENV,
93
+ STAGE_ENV,
94
+ cohortBucket,
95
+ };