chainlesschain 0.163.7 → 0.164.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 (252) hide show
  1. package/package.json +5 -1
  2. package/scripts/macos-mcp-launcher-build.mjs +317 -0
  3. package/scripts/macos-mcp-launcher-postinstall.sh +54 -0
  4. package/scripts/macos-mcp-launcher-preinstall.sh +61 -0
  5. package/src/assets/web-panel/assets/{AIOps-axqQfwv8.js → AIOps-D2MEn7fI.js} +1 -1
  6. package/src/assets/web-panel/assets/{ActionButton-DV-Ro0By.js → ActionButton-lCW_4Gf0.js} +1 -1
  7. package/src/assets/web-panel/assets/{Analytics-Bt72WEVu.js → Analytics-Bs7i-nsS.js} +3 -3
  8. package/src/assets/web-panel/assets/{AppLayout-BtepG55E.js → AppLayout-CK7B6S_j.js} +5 -5
  9. package/src/assets/web-panel/assets/{Artifacts-B7KaJ7S_.js → Artifacts-C8ILjpyo.js} +1 -1
  10. package/src/assets/web-panel/assets/{Audit-FNFaUg7A.js → Audit-Bb9cNaWc.js} +1 -1
  11. package/src/assets/web-panel/assets/{BackgroundAgents-DFb6J2wQ.js → BackgroundAgents-sC9ooXIf.js} +1 -1
  12. package/src/assets/web-panel/assets/{Backup-CC7YBhyj.js → Backup-D-DrsplT.js} +1 -1
  13. package/src/assets/web-panel/assets/{BaseInput-RkgTNVtj.js → BaseInput-uCNZpwSK.js} +1 -1
  14. package/src/assets/web-panel/assets/{Chat-hHEmGZy-.js → Chat-CsDK1uE9.js} +6 -6
  15. package/src/assets/web-panel/assets/{ChatBubbleRenderer-CAP9YhHv.js → ChatBubbleRenderer-OqSDt50w.js} +1 -1
  16. package/src/assets/web-panel/assets/{Checkbox-z5wXOQP1.js → Checkbox-JhTXM1-K.js} +1 -1
  17. package/src/assets/web-panel/assets/{Codegen-DVaDJnxy.js → Codegen-BbzZLnyD.js} +1 -1
  18. package/src/assets/web-panel/assets/{Col-CJmaRDR5.js → Col-D4VW4m4j.js} +1 -1
  19. package/src/assets/web-panel/assets/{Community-DF29_2bI.js → Community-BXrYawxV.js} +1 -1
  20. package/src/assets/web-panel/assets/{Compact-DtkQkBzn.js → Compact-DCihGy1u.js} +1 -1
  21. package/src/assets/web-panel/assets/{Compliance-xoHDxp7I.js → Compliance-DlyZ-lk8.js} +1 -1
  22. package/src/assets/web-panel/assets/{Cowork-BUm-R7ht.js → Cowork-DvGZrhbO.js} +2 -2
  23. package/src/assets/web-panel/assets/{Cron-Cgl14ZkB.js → Cron-DUncZi8h.js} +2 -2
  24. package/src/assets/web-panel/assets/{Crosschain-BNcbmoqh.js → Crosschain-C_hLuUcm.js} +1 -1
  25. package/src/assets/web-panel/assets/{DID-Bwja0Zo9.js → DID-b6YSUqxr.js} +2 -2
  26. package/src/assets/web-panel/assets/{Dashboard-Bk5XjEdJ.js → Dashboard-uvM15Cfb.js} +2 -2
  27. package/src/assets/web-panel/assets/{Dropdown-Ci36Oitq.js → Dropdown-D1-Nd4qY.js} +1 -1
  28. package/src/assets/web-panel/assets/{EmailListRenderer--U04ZN4q.js → EmailListRenderer-8ApvL6Zc.js} +1 -1
  29. package/src/assets/web-panel/assets/{FamilyGuardDashboard-B2gNPR2s.js → FamilyGuardDashboard-LYJt8811.js} +1 -1
  30. package/src/assets/web-panel/assets/{Federation-C4KghYn7.js → Federation-BbI3HGpv.js} +1 -1
  31. package/src/assets/web-panel/assets/{FormItemContext-QL7x_Q_0.js → FormItemContext-DSoEKuFu.js} +1 -1
  32. package/src/assets/web-panel/assets/{GenericCardRenderer-F3Ryltwm.js → GenericCardRenderer-B0S9OWd5.js} +1 -1
  33. package/src/assets/web-panel/assets/{Git-2HassK5k.js → Git-DIs9Zhf3.js} +2 -2
  34. package/src/assets/web-panel/assets/{Governance-DoBIp7oe.js → Governance-jzZXrxcl.js} +1 -1
  35. package/src/assets/web-panel/assets/{Inference--W01QhZ-.js → Inference-JUPjf2ZI.js} +1 -1
  36. package/src/assets/web-panel/assets/{KnowledgeGraph-DmvwqGpT.js → KnowledgeGraph-DxnfJvlP.js} +1 -1
  37. package/src/assets/web-panel/assets/{Logs-BBJ4yAel.js → Logs-iXiz8BEE.js} +2 -2
  38. package/src/assets/web-panel/assets/{MarkdownRenderer-BLCZMzhJ.js → MarkdownRenderer-GmB6DOr6.js} +1 -1
  39. package/src/assets/web-panel/assets/{Marketplace-D5lNngSI.js → Marketplace-Y3Xch312.js} +1 -1
  40. package/src/assets/web-panel/assets/{McpTools-CkEVOMKH.js → McpTools-D7kGGbO7.js} +4 -4
  41. package/src/assets/web-panel/assets/{Memory-B1Ow1xVE.js → Memory-Do_hVxzh.js} +2 -2
  42. package/src/assets/web-panel/assets/{MobileBridge-SgYbUfb6.js → MobileBridge-CtrR0Tas.js} +1 -1
  43. package/src/assets/web-panel/assets/MobileProjects-BL0Czcoj.js +1 -0
  44. package/src/assets/web-panel/assets/{Mtc-DcTXSSma.js → Mtc-qo5QCTGd.js} +2 -2
  45. package/src/assets/web-panel/assets/{MtcAudit-Dt3WG4oj.js → MtcAudit-cq5mnjYj.js} +2 -2
  46. package/src/assets/web-panel/assets/{Multisig-B9B38UZx.js → Multisig-Bq0MAQHw.js} +3 -3
  47. package/src/assets/web-panel/assets/{NLProgramming-B0S4GGvG.js → NLProgramming-DdWE6Vi2.js} +1 -1
  48. package/src/assets/web-panel/assets/{Notes-DZ5U58Ng.js → Notes-BxMBFcIp.js} +3 -3
  49. package/src/assets/web-panel/assets/{NotificationSettings-PjL5ZW34.js → NotificationSettings-RTrAcbUe.js} +1 -1
  50. package/src/assets/web-panel/assets/{OrderTableRenderer-DrAX2ESt.js → OrderTableRenderer-DJbpGqzT.js} +1 -1
  51. package/src/assets/web-panel/assets/{Organization-Cv1GYs-c.js → Organization-SQzIPdqC.js} +4 -4
  52. package/src/assets/web-panel/assets/{Overflow-Bbkp_PL3.js → Overflow-02yECh22.js} +1 -1
  53. package/src/assets/web-panel/assets/{P2P-BD8QUgoZ.js → P2P-BNg4pNCM.js} +2 -2
  54. package/src/assets/web-panel/assets/{PdhVaultBrowser-BO-2PeaB.js → PdhVaultBrowser-BxPJZsD3.js} +3 -3
  55. package/src/assets/web-panel/assets/{Permissions-D_OPVa02.js → Permissions-CLnDnPAz.js} +4 -4
  56. package/src/assets/web-panel/assets/{PersonalDataHub-mh-pEmaB.js → PersonalDataHub-C5m0AjGf.js} +4 -4
  57. package/src/assets/web-panel/assets/{Pipeline-6JC2EDdb.js → Pipeline-VwOf5Dhv.js} +1 -1
  58. package/src/assets/web-panel/assets/{Privacy-CUshzUAG.js → Privacy-CC0W2hZd.js} +1 -1
  59. package/src/assets/web-panel/assets/{ProjectInit-Cs2Aalri.js → ProjectInit-Dz893Bob.js} +2 -2
  60. package/src/assets/web-panel/assets/{ProjectSettings-1ak49tcj.js → ProjectSettings-CxQkvl0k.js} +2 -2
  61. package/src/assets/web-panel/assets/Projects-DDAjkUkT.js +1 -0
  62. package/src/assets/web-panel/assets/{Providers-CXXxvafH.js → Providers-DeB9IkxK.js} +1 -1
  63. package/src/assets/web-panel/assets/{QrScannerModal-PTcDsF58.js → QrScannerModal-OCeoaswn.js} +1 -1
  64. package/src/assets/web-panel/assets/{QuickAsk-CDwucrJw.js → QuickAsk-DenotaAj.js} +1 -1
  65. package/src/assets/web-panel/assets/{Recommend-CJlLVRXR.js → Recommend-Cies_jjI.js} +1 -1
  66. package/src/assets/web-panel/assets/{RemoteSession-DlN-ETsO.js → RemoteSession-Dxzl5n2T.js} +3 -3
  67. package/src/assets/web-panel/assets/{Reputation-DI23LR6m.js → Reputation-CW0mvxgZ.js} +1 -1
  68. package/src/assets/web-panel/assets/{Row-Cl7UQMrM.js → Row-SEd32qZU.js} +1 -1
  69. package/src/assets/web-panel/assets/{RssFeed-CexHNfh8.js → RssFeed-BSwnJ3Lm.js} +3 -3
  70. package/src/assets/web-panel/assets/{Search-BneBWvRN.js → Search-xe2m8bkC.js} +1 -1
  71. package/src/assets/web-panel/assets/{Security-DX7Phgrp.js → Security-Mq2F9Nro.js} +4 -4
  72. package/src/assets/web-panel/assets/{Services-BWXO8Mte.js → Services-BKGw2V3P.js} +2 -2
  73. package/src/assets/web-panel/assets/{Skeleton-DCyOjKPJ.js → Skeleton-DW95-Rxf.js} +1 -1
  74. package/src/assets/web-panel/assets/{Skills-CXqERsTB.js → Skills-CHgChCv_.js} +1 -1
  75. package/src/assets/web-panel/assets/{Sla-bhbrbz8E.js → Sla-tKh6k3R7.js} +1 -1
  76. package/src/assets/web-panel/assets/{SpeechSettings-3IPU0HBZ.js → SpeechSettings-D6UL3dA5.js} +1 -1
  77. package/src/assets/web-panel/assets/{SyncSettings-DBNTQLbM.js → SyncSettings-D0Fw8fVL.js} +2 -2
  78. package/src/assets/web-panel/assets/{Tasks-quP0bkN-.js → Tasks-20x1GB3D.js} +1 -1
  79. package/src/assets/web-panel/assets/{Templates-BouWmgho.js → Templates-DJ-lts-a.js} +1 -1
  80. package/src/assets/web-panel/assets/{Tenant-qv0D9s7z.js → Tenant-BFdGpbs7.js} +1 -1
  81. package/src/assets/web-panel/assets/{Terminal-BxvbE8BB.js → Terminal-Xpx61vHL.js} +2 -2
  82. package/src/assets/web-panel/assets/{TimelineRenderer-D-IeLnJ2.js → TimelineRenderer-C6UIvyZQ.js} +1 -1
  83. package/src/assets/web-panel/assets/{Tokens-CFMKKyVG.js → Tokens-Dellq08f.js} +1 -1
  84. package/src/assets/web-panel/assets/{Trigger-L8as3UuJ.js → Trigger-VKw8d0J-.js} +1 -1
  85. package/src/assets/web-panel/assets/{Trust-MxmA4VZG.js → Trust-DNftdKT5.js} +1 -1
  86. package/src/assets/web-panel/assets/{UkeySign-C0VvJYRi.js → UkeySign-DX9VAKJI.js} +1 -1
  87. package/src/assets/web-panel/assets/{VideoEditing-Bf5QZj8N.js → VideoEditing-B2h3jO8q.js} +1 -1
  88. package/src/assets/web-panel/assets/{Wallet-BIJ9riRz.js → Wallet-CjGkof7f.js} +4 -4
  89. package/src/assets/web-panel/assets/{WebAuthn-B8p9Mhkw.js → WebAuthn-2Zfcu55P.js} +4 -4
  90. package/src/assets/web-panel/assets/{WorkflowEditor-BVsuaPen.js → WorkflowEditor-B9eZ8UxZ.js} +1 -1
  91. package/src/assets/web-panel/assets/{chat-BfkjoKpV.js → chat-CQNfD-YO.js} +1 -1
  92. package/src/assets/web-panel/assets/{colors-DeAlsWK8.js → colors-D4usyFT2.js} +1 -1
  93. package/src/assets/web-panel/assets/{compact-item-Cs97bz5j.js → compact-item-s4TpjvjX.js} +1 -1
  94. package/src/assets/web-panel/assets/{createContext-BqbG60LH.js → createContext-BRCSvYxj.js} +1 -1
  95. package/src/assets/web-panel/assets/devWarning-DKJjSWRn.js +1 -0
  96. package/src/assets/web-panel/assets/{hasIn-i_RY0b1X.js → hasIn-AdkUbkV-.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-BOVkf1K3.js → index--00U6vXZ.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-B-3tEpTc.js → index-B2V-eKfK.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-D2B4VPyP.js → index-B4JJCfQ2.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-BkBi5TmC.js → index-BIoG5yYf.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-79V_zv1s.js → index-BMcimU-2.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-U4f5izHz.js → index-BPhkFZ1I.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-DiSkx4UB.js → index-BQ3DXBtD.js} +3 -3
  104. package/src/assets/web-panel/assets/{index-dIHr4B_u.js → index-Bad4VNvz.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-CIG8fQ2_.js → index-BgiXR_-_.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-DqBgBpgp.js → index-BtobShro.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-ZxO_-E8a.js → index-Bw2MEnUk.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-DUUrv141.js → index-C1mJtE6q.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-Bm7lLR4c.js → index-C484EJiS.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-COdGA-8n.js → index-C5KAQFPQ.js} +1 -1
  111. package/src/assets/web-panel/assets/index-C61cnl3K.js +1 -0
  112. package/src/assets/web-panel/assets/{index-CED2PL_y.js → index-C7Y8Aluc.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-YXgLng0K.js → index-CCsM_Ybx.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-0-agYlWL.js → index-CJCFe2Qf.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-B5UkyA3c.js → index-CJVEOa4i.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-B1CbOH1i.js → index-CJdQrZth.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-s1opAL-M.js → index-CKC1t3Ic.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-yObj1O4n.js → index-CQhAVU5t.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-CgsqdnRV.js → index-CYdoQsa1.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-Dk7-v4hP.js → index-Cduu2Hhr.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-B-JVTrpr.js → index-CkwiSLhU.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-CeWoNHau.js → index-Cvyt-zhm.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-CE2VtTlp.js → index-D2GjI2oe.js} +1 -1
  124. package/src/assets/web-panel/assets/index-D4XFHxBr.js +1 -0
  125. package/src/assets/web-panel/assets/{index-DmbfhJUP.js → index-DARsAyUp.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-BESLFt4q.js → index-DVKfQ0Ux.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-PT_5sBMA.js → index-DZT36ZYq.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-gyFpvL7l.js → index-D_XBHopw.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-BYUVuwKt.js → index-DdCB70SS.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-BcUXAB2s.js → index-DzRjHxEv.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-Dk2qouAz.js → index-MMN9V6JF.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-D9evtvg2.js → index-RfMr79MW.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-BuLQobzW.js → index-_IRVsV9X.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-Cf3WCLmy.js → index-nXyk8GZ9.js} +1 -1
  135. package/src/assets/web-panel/assets/{index-CG3PRyAL.js → index-s_buFMEG.js} +1 -1
  136. package/src/assets/web-panel/assets/{initDefaultProps-C9h9yKL3.js → initDefaultProps-Blmpk7HL.js} +1 -1
  137. package/src/assets/web-panel/assets/{motion-BvmLsPdu.js → motion-DPBJMv1n.js} +1 -1
  138. package/src/assets/web-panel/assets/{move-CoL4ekU1.js → move-ButdzCM7.js} +1 -1
  139. package/src/assets/web-panel/assets/{mtc-parser-C4pMy6xV.js → mtc-parser-cyRC_QCe.js} +1 -1
  140. package/src/assets/web-panel/assets/{omit-DPuJfNxx.js → omit-1epSV7hz.js} +1 -1
  141. package/src/assets/web-panel/assets/{pickAttrs-D0KEeaK2.js → pickAttrs-DuPY8xJs.js} +1 -1
  142. package/src/assets/web-panel/assets/{placementArrow-BpkyINxt.js → placementArrow-6XZqarhe.js} +1 -1
  143. package/src/assets/web-panel/assets/{responsiveObserve-DQI_wOq8.js → responsiveObserve-B40pXBWM.js} +1 -1
  144. package/src/assets/web-panel/assets/{slide-DYfdDiRg.js → slide-jbZ9Wu4n.js} +1 -1
  145. package/src/assets/web-panel/assets/{statusUtils-B5dtvb0D.js → statusUtils-BKQQcVy4.js} +1 -1
  146. package/src/assets/web-panel/assets/{styleChecker-CF310mSj.js → styleChecker-NiKfWjUT.js} +1 -1
  147. package/src/assets/web-panel/assets/{useFlexGapSupport-D1Qp4BLp.js → useFlexGapSupport-bQUCvPeb.js} +1 -1
  148. package/src/assets/web-panel/assets/{useFs-C7_iyvJK.js → useFs-CUGji7ph.js} +1 -1
  149. package/src/assets/web-panel/assets/{usePersonalDataHub-DZUt_fIm.js → usePersonalDataHub-4veyN2N2.js} +1 -1
  150. package/src/assets/web-panel/assets/{vnode-D3dsi0lZ.js → vnode-1-nLug-Z.js} +1 -1
  151. package/src/assets/web-panel/assets/{zoom-WdbOlvdQ.js → zoom-dhCeRDMo.js} +1 -1
  152. package/src/assets/web-panel/index.html +1 -1
  153. package/src/command-help-index.json +6 -6
  154. package/src/commands/automation.js +103 -1
  155. package/src/commands/cowork.js +174 -19
  156. package/src/commands/permissions.js +240 -16
  157. package/src/commands/plugin.js +1293 -56
  158. package/src/commands/session-location.js +276 -0
  159. package/src/commands/session.js +2 -0
  160. package/src/commands/team-merge-review.js +937 -0
  161. package/src/commands/team.js +2 -0
  162. package/src/data/changelog.json +27 -1
  163. package/src/gateways/ws/action-protocol.js +35 -10
  164. package/src/gateways/ws/remote-session-protocol.js +24 -1
  165. package/src/gateways/ws/ws-agent-handler.js +12 -0
  166. package/src/gateways/ws/ws-server.js +48 -12
  167. package/src/harness/jsonl-session-store.js +341 -24
  168. package/src/harness/mcp-client.js +8 -1
  169. package/src/harness/remote-session-audit.js +1 -0
  170. package/src/harness/remote-session-crypto.js +210 -2
  171. package/src/harness/remote-session-registry.js +159 -6
  172. package/src/harness/session-list-index.js +233 -14
  173. package/src/lib/agent-authority.js +6 -0
  174. package/src/lib/agent-schedule-store.js +139 -28
  175. package/src/lib/agent-team/team-merge-review-store.js +765 -0
  176. package/src/lib/agent-team/team-merge-review-transaction.js +1223 -0
  177. package/src/lib/agent-team/team-merge-review.js +1847 -0
  178. package/src/lib/automation-center-incidents.js +314 -0
  179. package/src/lib/automation-center-runtime.js +448 -0
  180. package/src/lib/automation-center.js +182 -38
  181. package/src/lib/automation-engine.js +41 -0
  182. package/src/lib/automation-execution-authority.js +241 -12
  183. package/src/lib/automation-execution-incident.js +737 -0
  184. package/src/lib/background-agent-keeper-client.js +248 -0
  185. package/src/lib/background-agent-keeper-protocol.js +147 -0
  186. package/src/lib/background-agent-supervisor.js +520 -40
  187. package/src/lib/background-interaction-resolver.js +12 -0
  188. package/src/lib/background-turn-bootstrap-protocol.js +126 -0
  189. package/src/lib/cowork-cron.js +85 -14
  190. package/src/lib/cowork-workflow.js +336 -16
  191. package/src/lib/dynamic-workflow-facade.js +648 -0
  192. package/src/lib/execution-location-contract.js +551 -0
  193. package/src/lib/execution-location-runtime.js +130 -0
  194. package/src/lib/ide-context.js +94 -6
  195. package/src/lib/mcp-stdio-package-materialization.js +166 -14
  196. package/src/lib/packer/pkg-config-generator.js +2 -0
  197. package/src/lib/permission-authority.js +77 -0
  198. package/src/lib/permission-side-effect-center.js +495 -0
  199. package/src/lib/plugin-runtime/install.js +514 -13
  200. package/src/lib/plugin-runtime/marketplace-artifact-readback.js +900 -0
  201. package/src/lib/plugin-runtime/marketplace-catalog.js +1181 -0
  202. package/src/lib/plugin-runtime/marketplace-impact.js +408 -0
  203. package/src/lib/plugin-runtime/marketplace-remote-artifacts.js +1567 -0
  204. package/src/lib/plugin-security.js +60 -3
  205. package/src/lib/process-execution-broker/index.js +1095 -57
  206. package/src/lib/process-execution-broker/linux-bwrap-descriptor-launch.js +375 -0
  207. package/src/lib/process-execution-broker/linux-generic-bwrap-runtime.js +90 -16
  208. package/src/lib/process-execution-broker/linux-generic-bwrap.js +159 -18
  209. package/src/lib/process-execution-broker/macos-mcp-launcher-contract.js +278 -0
  210. package/src/lib/process-execution-broker/macos-mcp-launcher-protocol.json +23 -0
  211. package/src/lib/process-execution-broker/macos-mcp-launcher.c +1497 -0
  212. package/src/lib/process-execution-broker/mcp-fd-entry-bootstrap.js +37 -0
  213. package/src/lib/process-execution-broker/platform-sandbox.js +2330 -279
  214. package/src/lib/process-execution-broker/windows-sandbox-helper.dll +0 -0
  215. package/src/lib/process-execution-broker/windows-sandbox-helper.exe +0 -0
  216. package/src/lib/process-execution-broker/windows-sandbox.cs +50 -4
  217. package/src/lib/public-ide-capability-manifest.js +3 -0
  218. package/src/lib/remote-approval-bridge.js +123 -17
  219. package/src/lib/remote-membership-authority.js +632 -0
  220. package/src/lib/remote-membership-coordinator.js +2409 -0
  221. package/src/lib/remote-membership-host-store.js +1750 -0
  222. package/src/lib/scheduler-kernel/agenda-adapter.js +17 -7
  223. package/src/lib/scheduler-kernel/automation-adapter.js +105 -11
  224. package/src/lib/scheduler-kernel/automation-event-adapter.js +87 -11
  225. package/src/lib/scheduler-kernel/contract.js +91 -0
  226. package/src/lib/scheduler-kernel/cowork-cron-adapter.js +12 -1
  227. package/src/lib/scheduler-kernel/loop-adapter.js +7 -1
  228. package/src/lib/scheduler-kernel/routine-adapter.js +7 -1
  229. package/src/lib/scheduler-kernel/runtime-control-capabilities.js +31 -0
  230. package/src/lib/scheduler-kernel/runtime.js +176 -3
  231. package/src/lib/scheduler-kernel/store.js +1253 -45
  232. package/src/lib/scoped-permission-store.js +369 -0
  233. package/src/lib/session-anti-rollback-anchor.js +262 -5
  234. package/src/lib/sub-agent-context.js +4 -0
  235. package/src/lib/workflow-definition-contract.js +149 -0
  236. package/src/repl/agent-repl.js +41 -7
  237. package/src/repl/chat-repl.js +2 -0
  238. package/src/repl/clipboard-image.js +735 -16
  239. package/src/repl/ide-status.js +1 -1
  240. package/src/repl/prompt-interactions.js +59 -6
  241. package/src/runtime/agent-core.js +93 -3
  242. package/src/runtime/headless-runner.js +30 -25
  243. package/src/runtime/headless-stream.js +32 -25
  244. package/src/runtime/mcp-config.js +81 -10
  245. package/src/workers/background-agent-keeper.js +498 -0
  246. package/src/workers/background-agent-worker.js +358 -13
  247. package/src/workers/background-turn-bootstrap.js +143 -0
  248. package/src/assets/web-panel/assets/MobileProjects-BWdOvQAj.js +0 -1
  249. package/src/assets/web-panel/assets/Projects-BV4oApsm.js +0 -1
  250. package/src/assets/web-panel/assets/devWarning-DPty0mGN.js +0 -1
  251. package/src/assets/web-panel/assets/index-Bt7g0Vq_.js +0 -1
  252. package/src/assets/web-panel/assets/index-ChVT0p9u.js +0 -1
@@ -9,14 +9,23 @@
9
9
 
10
10
  import {
11
11
  appendFileSync,
12
+ closeSync,
13
+ constants as fsConstants,
12
14
  existsSync,
15
+ fstatSync,
16
+ fsyncSync,
17
+ lstatSync,
18
+ openSync,
13
19
  readFileSync,
20
+ renameSync,
14
21
  rmSync,
15
22
  writeFileSync,
16
23
  } from "node:fs";
17
- import { join } from "node:path";
24
+ import { randomUUID } from "node:crypto";
25
+ import { basename, dirname, join } from "node:path";
18
26
  import { iterateFileLinesReverseSync } from "../lib/file-lines.js";
19
27
  import { ensurePrivateFile } from "../lib/secure-fs.js";
28
+ import { isAffectedWindowsZeroDeviceStatRuntime } from "../lib/secure-file-identity.js";
20
29
 
21
30
  export const SESSION_INDEX_SCHEMA = 2;
22
31
  export const SESSION_INDEX_FILE = ".sessions-index-v2.ndjson";
@@ -31,6 +40,14 @@ export const SESSION_GENERATION_AUTHORITY_SCHEMA =
31
40
  // Keeping the injection immediately around the production sidecar/journal
32
41
  // boundary makes that gate deterministic without replacing either write.
33
42
  export const _sessionScaleFaultHooks = Object.seal({
43
+ afterMetaTempFsync: null,
44
+ afterMetaRename: null,
45
+ afterMetaDirectoryFsync: null,
46
+ afterTombstoneTempFsync: null,
47
+ afterTombstoneRename: null,
48
+ afterTombstoneDirectoryFsync: null,
49
+ afterTombstoneRemoval: null,
50
+ afterTombstoneRemovalDirectoryFsync: null,
34
51
  afterMetaSnapshot: null,
35
52
  });
36
53
 
@@ -40,6 +57,157 @@ function runSessionScaleFaultHook(name, payload) {
40
57
  if (typeof hook === "function") hook(payload);
41
58
  }
42
59
 
60
+ function annotateSnapshotFailure(
61
+ cause,
62
+ { targetPath, renamed, directorySynced },
63
+ ) {
64
+ const error = cause instanceof Error ? cause : new Error(String(cause));
65
+ if (!error.commitState) {
66
+ // Before rename the public snapshot is unchanged. POSIX needs the parent
67
+ // directory fsync to make the rename durable; Windows exposes no usable
68
+ // directory fsync through Node, so a flushed atomic rename is its complete
69
+ // host boundary. A hook after that boundary models response loss.
70
+ error.commitState = !renamed
71
+ ? "not-committed"
72
+ : directorySynced
73
+ ? "committed"
74
+ : "unknown";
75
+ }
76
+ if (!error.persistenceTarget) error.persistenceTarget = targetPath;
77
+ return error;
78
+ }
79
+
80
+ function syncParentDirectory(targetPath) {
81
+ if (process.platform === "win32") return false;
82
+ let descriptor = null;
83
+ try {
84
+ const flags =
85
+ fsConstants.O_RDONLY |
86
+ Number(fsConstants.O_DIRECTORY ?? 0) |
87
+ Number(fsConstants.O_NOFOLLOW ?? 0);
88
+ descriptor = openSync(dirname(targetPath), flags);
89
+ if (!fstatSync(descriptor).isDirectory()) {
90
+ throw new Error("Session snapshot parent is not a directory");
91
+ }
92
+ fsyncSync(descriptor);
93
+ return true;
94
+ } finally {
95
+ if (descriptor !== null) closeSync(descriptor);
96
+ }
97
+ }
98
+
99
+ function assertSnapshotPathMatchesDescriptor(
100
+ filePath,
101
+ descriptorStats,
102
+ serialized,
103
+ ) {
104
+ const published = lstatSync(filePath, { bigint: true });
105
+ const usefulIdentity =
106
+ descriptorStats.dev !== 0n ||
107
+ descriptorStats.ino !== 0n ||
108
+ published.dev !== 0n ||
109
+ published.ino !== 0n;
110
+ const deviceMatches =
111
+ String(descriptorStats.dev) === String(published.dev) ||
112
+ (isAffectedWindowsZeroDeviceStatRuntime() &&
113
+ String(descriptorStats.dev) !== "0" &&
114
+ String(published.dev) === "0");
115
+ const identityMatches =
116
+ deviceMatches &&
117
+ String(descriptorStats.ino) === String(published.ino) &&
118
+ String(descriptorStats.mode) === String(published.mode);
119
+ const expectedBytes = BigInt(Buffer.byteLength(serialized, "utf8"));
120
+ if (
121
+ published.isSymbolicLink() ||
122
+ !published.isFile() ||
123
+ (usefulIdentity && !identityMatches) ||
124
+ descriptorStats.size !== expectedBytes ||
125
+ published.size !== expectedBytes ||
126
+ readFileSync(filePath, "utf8") !== serialized
127
+ ) {
128
+ throw new Error(
129
+ "Session snapshot path no longer identifies the flushed payload",
130
+ );
131
+ }
132
+ }
133
+
134
+ /**
135
+ * Publish one authority snapshot without ever exposing a partial JSON file.
136
+ * The temporary file lives beside the destination so rename remains atomic.
137
+ * Activity ordering is intentionally outside this helper: that journal is a
138
+ * rebuildable cache and must not be confused with the durable snapshot.
139
+ */
140
+ function writeSnapshotDurably(
141
+ filePath,
142
+ serialized,
143
+ { kind, sessionId, status, afterTempFsync, afterRename, afterDirectoryFsync },
144
+ ) {
145
+ const temporaryPath = join(
146
+ dirname(filePath),
147
+ `.${basename(filePath)}.${process.pid}.${randomUUID()}.tmp`,
148
+ );
149
+ const payload = Object.freeze({
150
+ kind,
151
+ sessionId,
152
+ status,
153
+ targetPath: filePath,
154
+ temporaryPath,
155
+ });
156
+ let descriptor = null;
157
+ let descriptorStats = null;
158
+ let renamed = false;
159
+ let directorySynced = process.platform === "win32";
160
+ try {
161
+ descriptor = openSync(temporaryPath, "wx", 0o600);
162
+ writeFileSync(descriptor, serialized, "utf8");
163
+ ensurePrivateFile(temporaryPath);
164
+ fsyncSync(descriptor);
165
+ descriptorStats = fstatSync(descriptor, { bigint: true });
166
+ runSessionScaleFaultHook(afterTempFsync, payload);
167
+ assertSnapshotPathMatchesDescriptor(
168
+ temporaryPath,
169
+ descriptorStats,
170
+ serialized,
171
+ );
172
+
173
+ // Both files are in the same directory; rename atomically replaces an old
174
+ // snapshot or publishes a first generation without a partial target.
175
+ // The temp already has the final owner-only permissions before publication.
176
+ renameSync(temporaryPath, filePath);
177
+ renamed = true;
178
+ assertSnapshotPathMatchesDescriptor(filePath, descriptorStats, serialized);
179
+ closeSync(descriptor);
180
+ descriptor = null;
181
+ runSessionScaleFaultHook(afterRename, payload);
182
+ if (process.platform !== "win32") {
183
+ directorySynced = syncParentDirectory(filePath);
184
+ runSessionScaleFaultHook(afterDirectoryFsync, payload);
185
+ }
186
+ } catch (cause) {
187
+ throw annotateSnapshotFailure(cause, {
188
+ targetPath: filePath,
189
+ renamed,
190
+ directorySynced,
191
+ });
192
+ } finally {
193
+ if (descriptor !== null) {
194
+ try {
195
+ closeSync(descriptor);
196
+ } catch {
197
+ // Preserve the persistence failure that stopped publication.
198
+ }
199
+ }
200
+ if (!renamed) {
201
+ try {
202
+ rmSync(temporaryPath, { force: true });
203
+ } catch {
204
+ // A crash may leave an ignored same-directory temp file. Never replace
205
+ // the original persistence failure with best-effort cleanup failure.
206
+ }
207
+ }
208
+ }
209
+ }
210
+
43
211
  export function sessionMetaPath(dir, sessionId) {
44
212
  return join(dir, `${sessionId}.meta.json`);
45
213
  }
@@ -189,6 +357,7 @@ function writeMetaSnapshot(dir, meta) {
189
357
  // that publication fails. Remove it only after a live generation snapshot
190
358
  // commits, so crashes can cause an extra candidate read but never hide a
191
359
  // successfully committed tombstone.
360
+ let tombstonePublished = false;
192
361
  if (meta.deleted === true) {
193
362
  const generation = normalizeSessionGenerationAuthority(meta.generation);
194
363
  const marker = {
@@ -206,21 +375,71 @@ function writeMetaSnapshot(dir, meta) {
206
375
  Number(meta.deleted_at_ms || meta.updated_at_ms) || 0,
207
376
  ),
208
377
  };
209
- writeFileSync(tombstoneMarker, `${JSON.stringify(marker)}\n`, {
210
- encoding: "utf8",
211
- mode: 0o600,
378
+ writeSnapshotDurably(tombstoneMarker, `${JSON.stringify(marker)}\n`, {
379
+ kind: "tombstone",
380
+ sessionId: meta.id,
381
+ status: "deleted",
382
+ afterTempFsync: "afterTombstoneTempFsync",
383
+ afterRename: "afterTombstoneRename",
384
+ afterDirectoryFsync: "afterTombstoneDirectoryFsync",
212
385
  });
213
- ensurePrivateFile(tombstoneMarker);
386
+ tombstonePublished = true;
387
+ }
388
+ try {
389
+ writeSnapshotDurably(filePath, `${JSON.stringify(meta)}\n`, {
390
+ kind: "meta",
391
+ sessionId: meta.id,
392
+ status: meta.deleted === true ? "deleted" : "live",
393
+ afterTempFsync: "afterMetaTempFsync",
394
+ afterRename: "afterMetaRename",
395
+ afterDirectoryFsync: "afterMetaDirectoryFsync",
396
+ });
397
+ } catch (cause) {
398
+ // A durable marker is already a conservative deletion fence. If the meta
399
+ // publication then fails, the composite mutation is partial/unknown even
400
+ // when the old meta path itself was left byte-for-byte unchanged.
401
+ if (tombstonePublished && cause?.commitState === "not-committed") {
402
+ cause.commitState = "unknown";
403
+ }
404
+ throw cause;
405
+ }
406
+
407
+ if (meta.deleted !== true && existsSync(tombstoneMarker)) {
408
+ const payload = Object.freeze({
409
+ kind: "tombstone-removal",
410
+ sessionId: meta.id,
411
+ status: "live",
412
+ targetPath: tombstoneMarker,
413
+ parentDirectory: dirname(tombstoneMarker),
414
+ });
415
+ let removed = false;
416
+ let directorySynced = process.platform === "win32";
417
+ try {
418
+ rmSync(tombstoneMarker, { force: true });
419
+ removed = true;
420
+ runSessionScaleFaultHook("afterTombstoneRemoval", payload);
421
+ if (process.platform !== "win32") {
422
+ directorySynced = syncParentDirectory(tombstoneMarker);
423
+ runSessionScaleFaultHook(
424
+ "afterTombstoneRemovalDirectoryFsync",
425
+ payload,
426
+ );
427
+ }
428
+ } catch (cause) {
429
+ const error = cause instanceof Error ? cause : new Error(String(cause));
430
+ if (!error.commitState) {
431
+ // The live meta was already durably published. Retaining the marker is
432
+ // fail-closed; removing it without a POSIX directory barrier is an
433
+ // unknown publication, while a post-barrier hook is response loss.
434
+ error.commitState =
435
+ removed && directorySynced ? "committed" : "unknown";
436
+ }
437
+ if (!error.persistenceTarget) {
438
+ error.persistenceTarget = tombstoneMarker;
439
+ }
440
+ throw error;
441
+ }
214
442
  }
215
- // The owning transcript lock serializes this derived snapshot. It need not
216
- // use a second temp+rename protocol: interruption can only corrupt a cache,
217
- // which readSessionMeta rejects and rebuildSessionMeta regenerates.
218
- writeFileSync(filePath, `${JSON.stringify(meta)}\n`, {
219
- encoding: "utf8",
220
- mode: 0o600,
221
- });
222
- ensurePrivateFile(filePath);
223
- if (meta.deleted !== true) rmSync(tombstoneMarker, { force: true });
224
443
  }
225
444
 
226
445
  /**
@@ -266,6 +266,12 @@ export function describeAuthorityChain(envelope = {}) {
266
266
  const parts = [`origin=${envelope.origin || "unknown"}`];
267
267
  if (envelope.principalId) parts.push(`principal=${envelope.principalId}`);
268
268
  if (envelope.sessionId) parts.push(`session=${envelope.sessionId}`);
269
+ if (envelope.remoteSessionId)
270
+ parts.push(`remote-session=${envelope.remoteSessionId}`);
271
+ if (envelope.sessionEpoch)
272
+ parts.push(`session-epoch=${envelope.sessionEpoch}`);
273
+ if (envelope.membershipEpoch)
274
+ parts.push(`membership-epoch=${envelope.membershipEpoch}`);
269
275
  if (envelope.parentAgentId) parts.push(`parent=${envelope.parentAgentId}`);
270
276
  if (envelope.correlationId) parts.push(`corr=${envelope.correlationId}`);
271
277
  parts.push(`authority=${authorityForOrigin(envelope.origin, envelope)}`);
@@ -258,6 +258,21 @@ function agendaStoreError(code, message, { retryable = false, retryAt } = {}) {
258
258
  return error;
259
259
  }
260
260
 
261
+ function agendaPersistenceError(
262
+ code,
263
+ message,
264
+ cause,
265
+ { filePath, commitState } = {},
266
+ ) {
267
+ const error = new Error(message, { cause });
268
+ error.name = "AgendaScheduleStoreError";
269
+ error.code = code;
270
+ error.filePath = filePath;
271
+ if (typeof cause?.code === "string") error.fsCode = cause.code;
272
+ if (commitState) error.commitState = commitState;
273
+ return error;
274
+ }
275
+
261
276
  function applyScheduledAgentSuccess(entry, atMs) {
262
277
  if (entry.kind === "wakeup") {
263
278
  entry.status = "fired";
@@ -666,9 +681,16 @@ export function previousCronTime(expr, fromMs, options = {}) {
666
681
  // ─── store ───────────────────────────────────────────────────────────────
667
682
 
668
683
  export class AgentScheduleStore {
669
- constructor({ dir = null, now = () => Date.now() } = {}) {
684
+ constructor({
685
+ dir = null,
686
+ now = () => Date.now(),
687
+ fileSystem = fs,
688
+ platform = process.platform,
689
+ } = {}) {
670
690
  this.dir = dir || agentScheduleDir();
671
691
  this._now = typeof now === "function" ? now : () => now;
692
+ this._fs = fileSystem;
693
+ this._platform = platform;
672
694
  }
673
695
 
674
696
  _file(kind) {
@@ -676,37 +698,124 @@ export class AgentScheduleStore {
676
698
  }
677
699
 
678
700
  _ensureDir() {
679
- fs.mkdirSync(this.dir, { recursive: true, mode: 0o700 });
701
+ this._fs.mkdirSync(this.dir, { recursive: true, mode: 0o700 });
680
702
  }
681
703
 
682
- _readAll(kind) {
704
+ _readAll(kind, { failOnMalformed = false } = {}) {
705
+ const filePath = this._file(kind);
683
706
  let raw;
684
707
  try {
685
- raw = fs.readFileSync(this._file(kind), "utf-8");
686
- } catch {
687
- return [];
708
+ raw = this._fs.readFileSync(filePath, "utf-8");
709
+ } catch (cause) {
710
+ if (cause?.code === "ENOENT") return [];
711
+ throw agendaPersistenceError(
712
+ "AGENDA_SCHEDULE_STORE_READ_FAILED",
713
+ `Agenda schedule store read failed (${filePath})`,
714
+ cause,
715
+ { filePath },
716
+ );
688
717
  }
689
718
  const entries = [];
719
+ let lineNumber = 0;
690
720
  for (const line of raw.split("\n")) {
721
+ lineNumber += 1;
691
722
  const trimmed = line.trim();
692
723
  if (!trimmed) continue;
693
724
  try {
694
- entries.push(JSON.parse(trimmed));
695
- } catch {
725
+ const entry = JSON.parse(trimmed);
726
+ if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
727
+ throw new TypeError("schedule entry must be an object");
728
+ }
729
+ entries.push(entry);
730
+ } catch (cause) {
731
+ if (failOnMalformed) {
732
+ throw agendaPersistenceError(
733
+ "AGENDA_SCHEDULE_STORE_MALFORMED",
734
+ `Agenda schedule store contains malformed JSONL (${filePath}:${lineNumber})`,
735
+ cause,
736
+ { filePath },
737
+ );
738
+ }
696
739
  // Skip a corrupt line rather than throwing — one bad append must not
697
- // poison the whole store (per-row resilience, like the JSON.parse sweep).
740
+ // poison advisory reads. Authoritative mutations opt into strict mode
741
+ // so they never replace a store after silently dropping durable rows.
698
742
  }
699
743
  }
700
744
  return entries;
701
745
  }
702
746
 
703
747
  _writeAll(kind, entries) {
704
- this._ensureDir();
748
+ const filePath = this._file(kind);
705
749
  const body = entries.map((entry) => JSON.stringify(entry)).join("\n");
706
- fs.writeFileSync(this._file(kind), body ? body + "\n" : "", {
707
- encoding: "utf-8",
708
- mode: 0o600,
709
- });
750
+ const contents = Buffer.from(body ? `${body}\n` : "", "utf8");
751
+ const temporaryPath = path.join(
752
+ this.dir,
753
+ `.${path.basename(filePath)}.${process.pid}.${randomUUID()}.tmp`,
754
+ );
755
+ let descriptor = null;
756
+ let renamed = false;
757
+
758
+ try {
759
+ this._ensureDir();
760
+ descriptor = this._fs.openSync(temporaryPath, "wx", 0o600);
761
+ let offset = 0;
762
+ while (offset < contents.length) {
763
+ const written = this._fs.writeSync(
764
+ descriptor,
765
+ contents,
766
+ offset,
767
+ contents.length - offset,
768
+ null,
769
+ );
770
+ if (!Number.isSafeInteger(written) || written <= 0) {
771
+ const cause = new Error("write returned no progress");
772
+ cause.code = "EIO";
773
+ throw cause;
774
+ }
775
+ offset += written;
776
+ }
777
+ this._fs.fsyncSync(descriptor);
778
+ this._fs.closeSync(descriptor);
779
+ descriptor = null;
780
+ this._fs.renameSync(temporaryPath, filePath);
781
+ renamed = true;
782
+
783
+ if (this._platform !== "win32") {
784
+ const directoryDescriptor = this._fs.openSync(this.dir, "r");
785
+ try {
786
+ this._fs.fsyncSync(directoryDescriptor);
787
+ } finally {
788
+ this._fs.closeSync(directoryDescriptor);
789
+ }
790
+ }
791
+ } catch (cause) {
792
+ if (descriptor !== null) {
793
+ try {
794
+ this._fs.closeSync(descriptor);
795
+ } catch {
796
+ // Preserve the original persistence failure.
797
+ }
798
+ }
799
+ if (!renamed) {
800
+ try {
801
+ this._fs.unlinkSync(temporaryPath);
802
+ } catch {
803
+ // Best-effort orphan cleanup; the authoritative file is untouched.
804
+ }
805
+ }
806
+ throw agendaPersistenceError(
807
+ "AGENDA_SCHEDULE_STORE_WRITE_FAILED",
808
+ `Agenda schedule store write failed (${filePath})`,
809
+ cause,
810
+ {
811
+ filePath,
812
+ // A failure before rename leaves the old generation authoritative.
813
+ // A directory-fsync failure after rename makes crash durability
814
+ // unknowable even though an immediate read sees the new generation.
815
+ commitState: renamed ? "unknown" : "not-committed",
816
+ },
817
+ );
818
+ }
710
819
  }
711
820
 
712
821
  // ── create ──────────────────────────────────────────────────────────────
@@ -741,7 +850,7 @@ export class AgentScheduleStore {
741
850
  createdAt: now,
742
851
  status: "pending",
743
852
  };
744
- const entries = this._readAll("wakeup");
853
+ const entries = this._readAll("wakeup", { failOnMalformed: true });
745
854
  entries.push(entry);
746
855
  this._writeAll("wakeup", entries);
747
856
  return entry;
@@ -786,7 +895,7 @@ export class AgentScheduleStore {
786
895
  runs: 0,
787
896
  status: "active",
788
897
  };
789
- const entries = this._readAll("cron");
898
+ const entries = this._readAll("cron", { failOnMalformed: true });
790
899
  entries.push(entry);
791
900
  this._writeAll("cron", entries);
792
901
  return entry;
@@ -882,7 +991,7 @@ export class AgentScheduleStore {
882
991
  checks: 0,
883
992
  status: "active",
884
993
  };
885
- const entries = this._readAll("monitor");
994
+ const entries = this._readAll("monitor", { failOnMalformed: true });
886
995
  entries.push(entry);
887
996
  this._writeAll("monitor", entries);
888
997
  return entry;
@@ -917,7 +1026,7 @@ export class AgentScheduleStore {
917
1026
  path.join(this.dir, ".agenda-claims"),
918
1027
  () => {
919
1028
  for (const kind of SCHEDULE_KINDS) {
920
- const entries = this._readAll(kind);
1029
+ const entries = this._readAll(kind, { failOnMalformed: true });
921
1030
  const entry = entries.find((candidate) => candidate.id === id);
922
1031
  if (!entry) continue;
923
1032
  if (!isSchedulableStatus(entry)) {
@@ -993,7 +1102,7 @@ export class AgentScheduleStore {
993
1102
  path.join(this.dir, ".agenda-claims"),
994
1103
  () => {
995
1104
  for (const kind of SCHEDULE_KINDS) {
996
- const entries = this._readAll(kind);
1105
+ const entries = this._readAll(kind, { failOnMalformed: true });
997
1106
  const entry = entries.find((candidate) => candidate.id === id);
998
1107
  if (!entry) continue;
999
1108
  const prior = entry.schedulerMigration;
@@ -1079,7 +1188,7 @@ export class AgentScheduleStore {
1079
1188
  path.join(this.dir, ".agenda-claims"),
1080
1189
  () => {
1081
1190
  for (const kind of SCHEDULE_KINDS) {
1082
- const entries = this._readAll(kind);
1191
+ const entries = this._readAll(kind, { failOnMalformed: true });
1083
1192
  const entry = entries.find((candidate) => candidate.id === id);
1084
1193
  if (!entry) continue;
1085
1194
  const migration = entry.schedulerMigration;
@@ -1171,7 +1280,9 @@ export class AgentScheduleStore {
1171
1280
  () => {
1172
1281
  const claimed = [];
1173
1282
  for (const scheduleKind of kinds) {
1174
- const entries = this._readAll(scheduleKind);
1283
+ const entries = this._readAll(scheduleKind, {
1284
+ failOnMalformed: true,
1285
+ });
1175
1286
  let changed = false;
1176
1287
  for (const entry of entries) {
1177
1288
  if (!isSchedulableStatus(entry) || isEntryExpired(entry, now))
@@ -1242,7 +1353,7 @@ export class AgentScheduleStore {
1242
1353
  path.join(this.dir, ".agenda-claims"),
1243
1354
  () => {
1244
1355
  for (const kind of SCHEDULE_KINDS) {
1245
- const entries = this._readAll(kind);
1356
+ const entries = this._readAll(kind, { failOnMalformed: true });
1246
1357
  const entry = entries.find((candidate) => candidate.id === id);
1247
1358
  if (!entry) continue;
1248
1359
  const prior = entry.schedulerExecution;
@@ -1330,7 +1441,7 @@ export class AgentScheduleStore {
1330
1441
  path.join(this.dir, ".agenda-claims"),
1331
1442
  () => {
1332
1443
  for (const kind of SCHEDULE_KINDS) {
1333
- const entries = this._readAll(kind);
1444
+ const entries = this._readAll(kind, { failOnMalformed: true });
1334
1445
  const entry = entries.find((candidate) => candidate.id === id);
1335
1446
  if (!entry) continue;
1336
1447
  const evidence = entry.schedulerExecution;
@@ -1408,7 +1519,7 @@ export class AgentScheduleStore {
1408
1519
  path.join(this.dir, ".agenda-claims"),
1409
1520
  () => {
1410
1521
  for (const kind of SCHEDULE_KINDS) {
1411
- const entries = this._readAll(kind);
1522
+ const entries = this._readAll(kind, { failOnMalformed: true });
1412
1523
  const entry = entries.find((candidate) => candidate.id === id);
1413
1524
  if (!entry) continue;
1414
1525
  const evidence = entry.schedulerExecution;
@@ -1484,7 +1595,7 @@ export class AgentScheduleStore {
1484
1595
  const now = atMs != null ? atMs : this._now();
1485
1596
  const retired = [];
1486
1597
  for (const kind of SCHEDULE_KINDS) {
1487
- const entries = this._readAll(kind);
1598
+ const entries = this._readAll(kind, { failOnMalformed: true });
1488
1599
  let changed = false;
1489
1600
  for (const entry of entries) {
1490
1601
  if (isSchedulableStatus(entry) && isEntryExpired(entry, now)) {
@@ -1501,7 +1612,7 @@ export class AgentScheduleStore {
1501
1612
 
1502
1613
  cancel(id) {
1503
1614
  for (const kind of SCHEDULE_KINDS) {
1504
- const entries = this._readAll(kind);
1615
+ const entries = this._readAll(kind, { failOnMalformed: true });
1505
1616
  const idx = entries.findIndex((entry) => entry.id === id);
1506
1617
  if (idx >= 0) {
1507
1618
  const [removed] = entries.splice(idx, 1);
@@ -1522,7 +1633,7 @@ export class AgentScheduleStore {
1522
1633
  pruneTerminal({ before = Infinity } = {}) {
1523
1634
  const removed = [];
1524
1635
  for (const kind of SCHEDULE_KINDS) {
1525
- const entries = this._readAll(kind);
1636
+ const entries = this._readAll(kind, { failOnMalformed: true });
1526
1637
  const keep = entries.filter((entry) => {
1527
1638
  const prunable =
1528
1639
  TERMINAL_SET.has(entry.status) && terminalAt(entry) <= before;
@@ -1586,7 +1697,7 @@ export class AgentScheduleStore {
1586
1697
  }
1587
1698
 
1588
1699
  _mutate(kind, id, fn) {
1589
- const entries = this._readAll(kind);
1700
+ const entries = this._readAll(kind, { failOnMalformed: true });
1590
1701
  const entry = entries.find((e) => e.id === id);
1591
1702
  if (!entry) return null;
1592
1703
  fn(entry);