chainlesschain 0.163.3 → 0.163.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. package/package.json +3 -2
  2. package/scripts/command-lifecycle-report.mjs +330 -38
  3. package/src/assets/web-panel/assets/{AIOps-DIY6KxV-.js → AIOps-Cv2EE1Zy.js} +1 -1
  4. package/src/assets/web-panel/assets/{ActionButton-BXH0muPt.js → ActionButton-CcpxMLuW.js} +1 -1
  5. package/src/assets/web-panel/assets/{Analytics-D39w8vmg.js → Analytics-DE8mJoMI.js} +3 -3
  6. package/src/assets/web-panel/assets/{AppLayout-CUU1zvLs.js → AppLayout-DKn9dk9L.js} +5 -5
  7. package/src/assets/web-panel/assets/{Artifacts-D8azHO3T.js → Artifacts-Cp3mG3Py.js} +1 -1
  8. package/src/assets/web-panel/assets/{Audit-D0tAwXTg.js → Audit-zvsQfF2C.js} +1 -1
  9. package/src/assets/web-panel/assets/{BackgroundAgents-C29mhJll.js → BackgroundAgents-Bi85SsjN.js} +1 -1
  10. package/src/assets/web-panel/assets/{Backup-D6Aa1Gro.js → Backup-Cw47Dj6s.js} +1 -1
  11. package/src/assets/web-panel/assets/{BaseInput-B1uoHbPQ.js → BaseInput-C5Ip2afH.js} +1 -1
  12. package/src/assets/web-panel/assets/{Chat-Bs4DLOR5.js → Chat-C0iAFkJv.js} +5 -5
  13. package/src/assets/web-panel/assets/{ChatBubbleRenderer-DUYIBSle.js → ChatBubbleRenderer-BV9Wv7wO.js} +1 -1
  14. package/src/assets/web-panel/assets/{Checkbox-CNcBPEa4.js → Checkbox-3KZZCiAF.js} +1 -1
  15. package/src/assets/web-panel/assets/{Codegen-CIY89763.js → Codegen-C8OMbBAz.js} +1 -1
  16. package/src/assets/web-panel/assets/{Col-CsPYFmgo.js → Col-B-MB84LJ.js} +1 -1
  17. package/src/assets/web-panel/assets/{Community-BBocEge4.js → Community-DpR7Dxao.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compact-TQ8Ux0Lf.js → Compact-CyDtz0OS.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compliance-DfBsZTft.js → Compliance-5tiRa2An.js} +1 -1
  20. package/src/assets/web-panel/assets/{Cowork-Cg-I6FVH.js → Cowork-DnQaKZ5x.js} +4 -4
  21. package/src/assets/web-panel/assets/{Cron-DTQzfRTp.js → Cron-BaWfoEDf.js} +2 -2
  22. package/src/assets/web-panel/assets/{Crosschain-DGxEKGpR.js → Crosschain-Bu0HoHhb.js} +1 -1
  23. package/src/assets/web-panel/assets/{DID-DLZ1RDSr.js → DID-31zk8upX.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dashboard-XneICKNI.js → Dashboard-BmVne-e2.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dropdown-BRU00J1-.js → Dropdown-B4PkoOWd.js} +1 -1
  26. package/src/assets/web-panel/assets/{EmailListRenderer-BzCbJuAy.js → EmailListRenderer-BZ6tyFtI.js} +1 -1
  27. package/src/assets/web-panel/assets/{FamilyGuardDashboard-D7BRyNBG.js → FamilyGuardDashboard-Osozn4Ds.js} +1 -1
  28. package/src/assets/web-panel/assets/{Federation-D9DeFIhW.js → Federation-DaH8TOAP.js} +1 -1
  29. package/src/assets/web-panel/assets/{FormItemContext-6rAtA9Ko.js → FormItemContext-tbU0uwis.js} +1 -1
  30. package/src/assets/web-panel/assets/{GenericCardRenderer-8Hqy80pU.js → GenericCardRenderer-Df8LQBrL.js} +1 -1
  31. package/src/assets/web-panel/assets/{Git-Cmvkj1rt.js → Git-DsMB6-14.js} +2 -2
  32. package/src/assets/web-panel/assets/{Governance-BRiQUjjw.js → Governance-BnH0dZzd.js} +1 -1
  33. package/src/assets/web-panel/assets/{Inference-CKN_EzVf.js → Inference-DhnN1N_P.js} +1 -1
  34. package/src/assets/web-panel/assets/{KnowledgeGraph-BCDHwpwQ.js → KnowledgeGraph-DnNshAgn.js} +1 -1
  35. package/src/assets/web-panel/assets/{Logs-DK9ovhaB.js → Logs-BmBFX3_N.js} +2 -2
  36. package/src/assets/web-panel/assets/{MarkdownRenderer-D53pHiHy.js → MarkdownRenderer-DCslfQU3.js} +1 -1
  37. package/src/assets/web-panel/assets/{Marketplace-BILPGakp.js → Marketplace-CPEgWDc3.js} +1 -1
  38. package/src/assets/web-panel/assets/{McpTools-DTVCOr9-.js → McpTools-C36qjgF9.js} +5 -5
  39. package/src/assets/web-panel/assets/{Memory-Hzc1iow4.js → Memory-tNHvrgqN.js} +2 -2
  40. package/src/assets/web-panel/assets/{MobileBridge-GXfgnGYV.js → MobileBridge-Xaf6cKjc.js} +1 -1
  41. package/src/assets/web-panel/assets/{MobileProjects-B-3TJWsS.js → MobileProjects-D2E5TTeO.js} +1 -1
  42. package/src/assets/web-panel/assets/{Mtc-DwSJMWtK.js → Mtc-D4AJ2dwV.js} +4 -4
  43. package/src/assets/web-panel/assets/{MtcAudit-D2uxf-DA.js → MtcAudit-Df-gtn2_.js} +4 -4
  44. package/src/assets/web-panel/assets/{Multisig-DG6kbKK0.js → Multisig-DTCHLWld.js} +3 -3
  45. package/src/assets/web-panel/assets/{NLProgramming-f5p49EDU.js → NLProgramming-DruZ_1Jb.js} +1 -1
  46. package/src/assets/web-panel/assets/{Notes-FUgHyzSD.js → Notes-Dx3pdGDs.js} +4 -4
  47. package/src/assets/web-panel/assets/{NotificationSettings-DCHGee7e.js → NotificationSettings-Bi3L69oL.js} +1 -1
  48. package/src/assets/web-panel/assets/{OrderTableRenderer-Dm6LlIoa.js → OrderTableRenderer-BHY33m7C.js} +1 -1
  49. package/src/assets/web-panel/assets/{Organization-BawA7qAg.js → Organization-BG2ZVEV-.js} +4 -4
  50. package/src/assets/web-panel/assets/{Overflow-D6a5wZU1.js → Overflow-Viwtg4Mn.js} +1 -1
  51. package/src/assets/web-panel/assets/{P2P-K8WavwnA.js → P2P-Clm_yc1Z.js} +2 -2
  52. package/src/assets/web-panel/assets/{PdhVaultBrowser-4JAJYaqx.js → PdhVaultBrowser-NKmmDiOw.js} +5 -5
  53. package/src/assets/web-panel/assets/{Permissions-BDWvi8PD.js → Permissions-DIL8u9Nk.js} +4 -4
  54. package/src/assets/web-panel/assets/{PersonalDataHub-DF_K4E9i.js → PersonalDataHub-B-jM4wt-.js} +4 -4
  55. package/src/assets/web-panel/assets/{Pipeline-BYeZlesI.js → Pipeline-627I__H5.js} +1 -1
  56. package/src/assets/web-panel/assets/{Privacy-BIHlgnIc.js → Privacy-2DN2qrkW.js} +1 -1
  57. package/src/assets/web-panel/assets/{ProjectInit-Cvf-6B5P.js → ProjectInit-CN4wC0sF.js} +2 -2
  58. package/src/assets/web-panel/assets/{ProjectSettings-CnwfJrRz.js → ProjectSettings-K35vsh5H.js} +2 -2
  59. package/src/assets/web-panel/assets/Projects-B_wQadhX.js +1 -0
  60. package/src/assets/web-panel/assets/{Providers-CxC7JuYv.js → Providers-MckaQUhQ.js} +1 -1
  61. package/src/assets/web-panel/assets/{QrScannerModal-VLf3gAfL.js → QrScannerModal-BS3mtA_O.js} +1 -1
  62. package/src/assets/web-panel/assets/{QuickAsk-B5vGjRiF.js → QuickAsk-BHp_nofL.js} +1 -1
  63. package/src/assets/web-panel/assets/{Recommend--UW4iYs-.js → Recommend-DlmnPuZj.js} +1 -1
  64. package/src/assets/web-panel/assets/{RemoteSession-DMSPcfKR.js → RemoteSession-tsyFbvpy.js} +2 -2
  65. package/src/assets/web-panel/assets/{Reputation-kQXlEHmj.js → Reputation-Ba1iWv2D.js} +1 -1
  66. package/src/assets/web-panel/assets/{Row-CxGu3pit.js → Row-NnlGC--f.js} +1 -1
  67. package/src/assets/web-panel/assets/{RssFeed-Bi5lo8MZ.js → RssFeed-CjThSIRv.js} +3 -3
  68. package/src/assets/web-panel/assets/{Search-Cq_H5RTh.js → Search-CojUyC5x.js} +1 -1
  69. package/src/assets/web-panel/assets/{Security-YFbmkaQS.js → Security-c-sxeJEc.js} +3 -3
  70. package/src/assets/web-panel/assets/{Services-DLOGdaLm.js → Services-CtcKEEmF.js} +2 -2
  71. package/src/assets/web-panel/assets/{Skeleton-CteIxb3D.js → Skeleton-CIBBXflN.js} +1 -1
  72. package/src/assets/web-panel/assets/{Skills-CccopaIZ.js → Skills-D1XOOK9n.js} +1 -1
  73. package/src/assets/web-panel/assets/{Sla-AzfEQKX1.js → Sla-hRfEp5Sn.js} +1 -1
  74. package/src/assets/web-panel/assets/{SpeechSettings-ekGo5l77.js → SpeechSettings-Dexb1f_6.js} +1 -1
  75. package/src/assets/web-panel/assets/{SyncSettings-BmZmAgYH.js → SyncSettings-BJsSFGYy.js} +2 -2
  76. package/src/assets/web-panel/assets/{Tasks-D7q3Z4uL.js → Tasks-CfSZ8A1L.js} +1 -1
  77. package/src/assets/web-panel/assets/{Templates-CX1Tgeka.js → Templates-idDf47W-.js} +1 -1
  78. package/src/assets/web-panel/assets/{Tenant-Zc59jF4i.js → Tenant-C-UsX6w6.js} +1 -1
  79. package/src/assets/web-panel/assets/{Terminal-CXOD7y83.js → Terminal-BgJtX5n1.js} +2 -2
  80. package/src/assets/web-panel/assets/{TimelineRenderer-B1aBHPBo.js → TimelineRenderer-DP0BLKTl.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tokens-zALlOq_U.js → Tokens-LwCzqETp.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trigger-CQfJMXaq.js → Trigger-D_9tVch0.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trust-BU0RcM-w.js → Trust-BH2UlEWh.js} +1 -1
  84. package/src/assets/web-panel/assets/{UkeySign-IFZ3HsbH.js → UkeySign-CIpD0nYb.js} +1 -1
  85. package/src/assets/web-panel/assets/{VideoEditing-BzslgW0v.js → VideoEditing-9ShhYxK_.js} +1 -1
  86. package/src/assets/web-panel/assets/{Wallet-BZAcQNS6.js → Wallet-C7afGNIG.js} +4 -4
  87. package/src/assets/web-panel/assets/{WebAuthn-CBK1DMi0.js → WebAuthn-bUKn6i5R.js} +3 -3
  88. package/src/assets/web-panel/assets/{WorkflowEditor-BlMTPzO-.js → WorkflowEditor-CxgQaGyp.js} +1 -1
  89. package/src/assets/web-panel/assets/{chat-B51-8QVn.js → chat-DMVkmJwx.js} +1 -1
  90. package/src/assets/web-panel/assets/{colors-504RTByU.js → colors-CDzQh5nS.js} +1 -1
  91. package/src/assets/web-panel/assets/{compact-item-C-GP6IQM.js → compact-item-C51kEF4D.js} +1 -1
  92. package/src/assets/web-panel/assets/{createContext-DOkIj7ID.js → createContext-BTk9bXBn.js} +1 -1
  93. package/src/assets/web-panel/assets/devWarning-CdwPwYj8.js +1 -0
  94. package/src/assets/web-panel/assets/{hasIn-DN7V-_FW.js → hasIn-CMje33rb.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-CKTfZyfU.js → index-0Auljb10.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-D9LyiN-L.js → index-B0-zMtKA.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-DEMPUVa3.js → index-BAfY7m7i.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-Bkxhaeta.js → index-BBz9LIMS.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-7jIqHbzw.js → index-BCRvG9lq.js} +1 -1
  100. package/src/assets/web-panel/assets/index-BEeOdfEe.js +1 -0
  101. package/src/assets/web-panel/assets/index-BTe0TOu6.js +1 -0
  102. package/src/assets/web-panel/assets/{index-P2mfY27Z.js → index-BTlsE8Df.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-DAOpQvl_.js → index-BVePe_Rf.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-CYopNjcJ.js → index-BW4F5YDF.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-B_vGU-Js.js → index-BXQBPLyE.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-kt_5rfcZ.js → index-BeEaAEIp.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-Cao5DZy7.js → index-BtlEqHLP.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-DA2f1UV3.js → index-BzCkNylB.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-B2-x9bS8.js → index-C1oZQmAA.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-D1phyca8.js → index-C1oZReaY.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-FcV8J_Qz.js → index-C4rQCS8T.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-C3TSohzc.js → index-C5IWTMVl.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-CySTJKeq.js → index-CCLj9hcD.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-C9_48OzU.js → index-CDLkNkLj.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-so8eIIxF.js → index-Cd0hmPxD.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-CX78k-qf.js → index-CfC-piWZ.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-DE-hmI2l.js → index-CtM8OT_7.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-kAqQXfP6.js → index-CvSeVzqe.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-C0k_Nqg9.js → index-CwGPwjUu.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-CP2A226L.js → index-CypsfcEq.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-CfiEM64n.js → index-D9rC-fGW.js} +3 -3
  122. package/src/assets/web-panel/assets/{index-yYTQZypF.js → index-DJfnCuMq.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-f4Bo4KXm.js → index-DRG-aqOs.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-By6u5IV1.js → index-DRLQyp2A.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-ConjaJro.js → index-DgivOKHA.js} +1 -1
  126. package/src/assets/web-panel/assets/{index--n-ZciV3.js → index-DpcrFxMI.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-CqcLo5WV.js → index-DqU9njjT.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-CUhQpiYv.js → index-Ld_4mFmC.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-C4DV_5uA.js → index-OS-vfbTA.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-DaA__-q1.js → index-h31MwrME.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-BFIFJ5Dr.js → index-hg_emBsi.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-C8UltbXK.js → index-togc_uYn.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-et5JIPHO.js → index-x53Vf7la.js} +1 -1
  134. package/src/assets/web-panel/assets/{initDefaultProps-CPYEIdpV.js → initDefaultProps-vrA8K-ac.js} +1 -1
  135. package/src/assets/web-panel/assets/{motion-Cjim9pxs.js → motion-ByEzwIAl.js} +1 -1
  136. package/src/assets/web-panel/assets/{move-DuU-cgz3.js → move-Ck4AWjw-.js} +1 -1
  137. package/src/assets/web-panel/assets/{mtc-parser-DJHNAkta.js → mtc-parser-6p0l9SrB.js} +1 -1
  138. package/src/assets/web-panel/assets/{omit-DSQBgdBj.js → omit-B1CUPQ6R.js} +1 -1
  139. package/src/assets/web-panel/assets/{pickAttrs-CTmT_j5m.js → pickAttrs-B1STg1iW.js} +1 -1
  140. package/src/assets/web-panel/assets/{placementArrow-Lfm6v-r4.js → placementArrow-DTTllkBV.js} +1 -1
  141. package/src/assets/web-panel/assets/{responsiveObserve-CgrcPcDi.js → responsiveObserve-AIrrCfBb.js} +1 -1
  142. package/src/assets/web-panel/assets/{slide-CuE3110i.js → slide-C_fPMjdR.js} +1 -1
  143. package/src/assets/web-panel/assets/{statusUtils-DiK5nbpf.js → statusUtils-D5ow2yIP.js} +1 -1
  144. package/src/assets/web-panel/assets/{styleChecker-DPEJdQaZ.js → styleChecker-Dy3hEA--.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFlexGapSupport-CnnodGmp.js → useFlexGapSupport-WfzcfSh4.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFs-DWF84Yav.js → useFs-CKSejfas.js} +1 -1
  147. package/src/assets/web-panel/assets/{usePersonalDataHub-a5b5Dw2f.js → usePersonalDataHub-od3zpPBN.js} +1 -1
  148. package/src/assets/web-panel/assets/{vnode-DAluzXOq.js → vnode-DRD_2DFA.js} +1 -1
  149. package/src/assets/web-panel/assets/{zoom-Dokg7uAZ.js → zoom-DmNrEtgf.js} +1 -1
  150. package/src/assets/web-panel/index.html +1 -1
  151. package/src/command-help-index.json +1 -1
  152. package/src/commands/agenda.js +52 -6
  153. package/src/commands/artifacts.js +98 -0
  154. package/src/commands/cowork.js +24 -12
  155. package/src/commands/mcp.js +1 -1
  156. package/src/commands/review.js +221 -22
  157. package/src/commands/routine.js +40 -10
  158. package/src/commands/session-mcp-recovery.js +5 -5
  159. package/src/data/changelog.json +27 -1
  160. package/src/gateways/ws/ws-agent-handler.js +492 -14
  161. package/src/harness/jsonl-session-store.js +39 -1
  162. package/src/harness/mcp-client.js +172 -29
  163. package/src/harness/prompt-compressor.js +24 -0
  164. package/src/harness/provider-backed-compaction.js +205 -0
  165. package/src/lib/agent-schedule-store.js +197 -4
  166. package/src/lib/app-preview.js +3 -0
  167. package/src/lib/command-lifecycle-report.js +1340 -145
  168. package/src/lib/cowork-cron.js +243 -25
  169. package/src/lib/delivery-coordinator.js +30 -5
  170. package/src/lib/delivery-production-adapter.js +1777 -0
  171. package/src/lib/delivery-production-runner.js +240 -0
  172. package/src/lib/durable-security-store.js +29 -17
  173. package/src/lib/execution-trace/trace-context.cjs +179 -0
  174. package/src/lib/execution-trace/trace-context.js +8 -175
  175. package/src/lib/mcp-call-ledger-store.js +58 -6
  176. package/src/lib/mcp-host-recovery-runtime.js +2 -0
  177. package/src/lib/mcp-ledger-recovery-admission.js +39 -3
  178. package/src/lib/mcp-recovery-adjudication.js +256 -19
  179. package/src/lib/mcp-sandbox-policy.js +29 -0
  180. package/src/lib/mcp-stdio-capsule-builder-worker.cjs +495 -0
  181. package/src/lib/mcp-stdio-executable-identity.js +33 -2
  182. package/src/lib/mcp-stdio-immutable-vfs-resolver.cjs +830 -0
  183. package/src/lib/mcp-stdio-package-materialization.js +721 -333
  184. package/src/lib/micro-compact.js +11 -5
  185. package/src/lib/observability/index.js +2 -0
  186. package/src/lib/observability/otlp-exporter.js +2 -2
  187. package/src/lib/packer/pack-update-applier.js +8 -1
  188. package/src/lib/packer/pkg-config-generator.js +34 -0
  189. package/src/lib/process-execution-broker/index.js +48 -8
  190. package/src/lib/process-execution-broker/platform-sandbox.js +82 -1
  191. package/src/lib/routine-store.js +76 -3
  192. package/src/lib/scheduler-kernel/agenda-adapter.js +542 -0
  193. package/src/lib/scheduler-kernel/contract.js +315 -0
  194. package/src/lib/scheduler-kernel/cowork-cron-adapter.js +774 -0
  195. package/src/lib/scheduler-kernel/routine-adapter.js +517 -0
  196. package/src/lib/scheduler-kernel/runtime.js +527 -0
  197. package/src/lib/scheduler-kernel/store.js +1455 -0
  198. package/src/lib/session-host-lease.js +403 -30
  199. package/src/lib/session-message-provenance.js +4 -1
  200. package/src/lib/session-persistence-failure.js +4 -1
  201. package/src/lib/sub-agent-context.js +8 -0
  202. package/src/repl/agent-repl.js +309 -43
  203. package/src/runtime/agent-core.js +1079 -105
  204. package/src/runtime/headless-runner.js +260 -166
  205. package/src/runtime/headless-stream.js +254 -25
  206. package/src/assets/web-panel/assets/Projects-b-jPXzF4.js +0 -1
  207. package/src/assets/web-panel/assets/devWarning-kB0nCNwN.js +0 -1
  208. package/src/assets/web-panel/assets/index-Bya64sZE.js +0 -1
  209. package/src/assets/web-panel/assets/index-D_FWpDZM.js +0 -1
@@ -168,6 +168,34 @@ function hasLiveExecutionLease(entry, now) {
168
168
  return Number(entry.executionLease?.expiresAt) > Number(now);
169
169
  }
170
170
 
171
+ function agendaStoreError(code, message, { retryable = false, retryAt } = {}) {
172
+ const error = new Error(message);
173
+ error.code = code;
174
+ error.retryable = retryable;
175
+ if (retryAt !== undefined) error.retryAt = retryAt;
176
+ return error;
177
+ }
178
+
179
+ function applyScheduledAgentSuccess(entry, atMs) {
180
+ if (entry.kind === "wakeup") {
181
+ entry.status = "fired";
182
+ entry.firedAt = atMs;
183
+ return;
184
+ }
185
+ if (entry.kind === "cron") {
186
+ entry.lastRunAt = atMs;
187
+ entry.runs = (entry.runs || 0) + 1;
188
+ const next = nextCronTime(entry.cron, atMs);
189
+ if (next == null) entry.status = "exhausted";
190
+ else entry.nextAt = next;
191
+ return;
192
+ }
193
+ throw agendaStoreError(
194
+ "AGENDA_SCHEDULER_KIND_UNSUPPORTED",
195
+ `Scheduler execution is not supported for agenda kind: ${entry.kind}`,
196
+ );
197
+ }
198
+
171
199
  /** Statuses an entry can never leave — safe to prune. */
172
200
  export const TERMINAL_STATUSES = Object.freeze([
173
201
  "fired",
@@ -499,6 +527,11 @@ export class AgentScheduleStore {
499
527
  return out;
500
528
  }
501
529
 
530
+ get(id) {
531
+ if (typeof id !== "string" || id.length === 0) return null;
532
+ return this.list().find((entry) => entry.id === id) || null;
533
+ }
534
+
502
535
  /** Entries whose time has come (pending wakeup / active cron|monitor). */
503
536
  due(kind = null, atMs = null) {
504
537
  const now = atMs != null ? atMs : this._now();
@@ -524,16 +557,20 @@ export class AgentScheduleStore {
524
557
  * lease expires. This is deliberately separate from `due()` for backwards
525
558
  * compatibility with read-only callers and injected test stores.
526
559
  */
527
- claimDue(atMs = null, leaseMs = 120000) {
560
+ claimDue(atMs = null, leaseMs = 120000, kind = null) {
528
561
  const now = atMs != null ? Number(atMs) : this._now();
529
562
  const ttl = Math.max(1000, Number(leaseMs) || 120000);
563
+ const kinds = kind == null ? SCHEDULE_KINDS : [kind];
564
+ if (kinds.some((value) => !SCHEDULE_KINDS.includes(value))) {
565
+ throw new Error(`unknown schedule kind: ${kind}`);
566
+ }
530
567
  this._ensureDir();
531
568
  return withFileLock(
532
569
  path.join(this.dir, ".agenda-claims"),
533
570
  () => {
534
571
  const claimed = [];
535
- for (const kind of SCHEDULE_KINDS) {
536
- const entries = this._readAll(kind);
572
+ for (const scheduleKind of kinds) {
573
+ const entries = this._readAll(scheduleKind);
537
574
  let changed = false;
538
575
  for (const entry of entries) {
539
576
  if (!isSchedulableStatus(entry) || isEntryExpired(entry, now))
@@ -552,7 +589,7 @@ export class AgentScheduleStore {
552
589
  });
553
590
  changed = true;
554
591
  }
555
- if (changed) this._writeAll(kind, entries);
592
+ if (changed) this._writeAll(scheduleKind, entries);
556
593
  }
557
594
  return claimed;
558
595
  },
@@ -571,6 +608,162 @@ export class AgentScheduleStore {
571
608
  return null;
572
609
  }
573
610
 
611
+ /**
612
+ * Bind a scheduler claim to the legacy Agenda entry before agent execution.
613
+ * The same lock used by legacy `claimDue()` prevents an old/new driver from
614
+ * starting the entry concurrently during migration.
615
+ */
616
+ bindSchedulerExecution(
617
+ id,
618
+ { occurrenceId, snapshotDigest, attempt, atMs = null } = {},
619
+ ) {
620
+ const now = atMs != null ? Number(atMs) : this._now();
621
+ if (typeof occurrenceId !== "string" || occurrenceId.length === 0) {
622
+ throw agendaStoreError(
623
+ "AGENDA_SCHEDULER_BINDING_INVALID",
624
+ "Agenda scheduler occurrenceId is required",
625
+ );
626
+ }
627
+ if (typeof snapshotDigest !== "string" || snapshotDigest.length === 0) {
628
+ throw agendaStoreError(
629
+ "AGENDA_SCHEDULER_BINDING_INVALID",
630
+ "Agenda scheduler snapshotDigest is required",
631
+ );
632
+ }
633
+ if (!Number.isSafeInteger(attempt) || attempt < 1) {
634
+ throw agendaStoreError(
635
+ "AGENDA_SCHEDULER_BINDING_INVALID",
636
+ "Agenda scheduler attempt must be a positive integer",
637
+ );
638
+ }
639
+ this._ensureDir();
640
+ return withFileLock(
641
+ path.join(this.dir, ".agenda-claims"),
642
+ () => {
643
+ for (const kind of ["wakeup", "cron"]) {
644
+ const entries = this._readAll(kind);
645
+ const entry = entries.find((candidate) => candidate.id === id);
646
+ if (!entry) continue;
647
+ const prior = entry.schedulerExecution;
648
+ if (prior?.status === "running") {
649
+ throw agendaStoreError(
650
+ "AGENDA_SCHEDULER_OUTCOME_UNKNOWN",
651
+ `Agenda scheduler execution outcome is unknown: ${id}`,
652
+ );
653
+ }
654
+ if (
655
+ prior?.status === "succeeded" &&
656
+ prior.occurrenceId === occurrenceId &&
657
+ prior.snapshotDigest === snapshotDigest
658
+ ) {
659
+ return entry;
660
+ }
661
+ if (hasLiveExecutionLease(entry, now)) {
662
+ throw agendaStoreError(
663
+ "AGENDA_SCHEDULER_LEGACY_CLAIM_ACTIVE",
664
+ `Agenda entry is already claimed by a legacy runner: ${id}`,
665
+ {
666
+ retryable: true,
667
+ retryAt: Number(entry.executionLease.expiresAt),
668
+ },
669
+ );
670
+ }
671
+ entry.schedulerExecution = {
672
+ occurrenceId,
673
+ snapshotDigest,
674
+ attempt,
675
+ status: "running",
676
+ startedAt: now,
677
+ };
678
+ // Fence an older CLI that only understands the legacy claim field.
679
+ // Terminal scheduler evidence clears this lease; an outcome-unknown
680
+ // execution intentionally keeps it non-expiring until adjudicated so
681
+ // an old runner cannot duplicate an uncertain agent side effect.
682
+ entry.executionLease = {
683
+ owner: `scheduler:${occurrenceId}:${attempt}`,
684
+ claimedAt: now,
685
+ expiresAt: Number.MAX_SAFE_INTEGER,
686
+ };
687
+ this._writeAll(kind, entries);
688
+ return entry;
689
+ }
690
+ throw agendaStoreError(
691
+ "AGENDA_SCHEDULER_ENTRY_NOT_FOUND",
692
+ `Agenda entry does not exist: ${id}`,
693
+ );
694
+ },
695
+ { failIfUnavailable: true },
696
+ );
697
+ }
698
+
699
+ /**
700
+ * Atomically publish scheduler evidence and the legacy wakeup/cron state.
701
+ * A successful cron advances exactly once in the same JSONL replacement that
702
+ * records terminal evidence; failures keep the entry schedulable for the
703
+ * scheduler kernel's bounded retry policy.
704
+ */
705
+ completeSchedulerExecution(
706
+ id,
707
+ {
708
+ occurrenceId,
709
+ snapshotDigest,
710
+ attempt,
711
+ outcome,
712
+ result = null,
713
+ error = null,
714
+ atMs = null,
715
+ } = {},
716
+ ) {
717
+ if (!["succeeded", "failed"].includes(outcome)) {
718
+ throw agendaStoreError(
719
+ "AGENDA_SCHEDULER_OUTCOME_INVALID",
720
+ "Agenda scheduler outcome must be succeeded or failed",
721
+ );
722
+ }
723
+ const now = atMs != null ? Number(atMs) : this._now();
724
+ this._ensureDir();
725
+ return withFileLock(
726
+ path.join(this.dir, ".agenda-claims"),
727
+ () => {
728
+ for (const kind of ["wakeup", "cron"]) {
729
+ const entries = this._readAll(kind);
730
+ const entry = entries.find((candidate) => candidate.id === id);
731
+ if (!entry) continue;
732
+ const evidence = entry.schedulerExecution;
733
+ if (
734
+ !evidence ||
735
+ evidence.occurrenceId !== occurrenceId ||
736
+ evidence.snapshotDigest !== snapshotDigest ||
737
+ evidence.attempt !== attempt ||
738
+ evidence.status !== "running"
739
+ ) {
740
+ throw agendaStoreError(
741
+ "AGENDA_SCHEDULER_BINDING_MISMATCH",
742
+ `Agenda scheduler evidence does not match the active claim: ${id}`,
743
+ );
744
+ }
745
+ if (outcome === "succeeded") {
746
+ applyScheduledAgentSuccess(entry, now);
747
+ }
748
+ entry.schedulerExecution = {
749
+ ...evidence,
750
+ status: outcome,
751
+ endedAt: now,
752
+ ...(outcome === "succeeded" ? { result } : { error }),
753
+ };
754
+ delete entry.executionLease;
755
+ this._writeAll(kind, entries);
756
+ return entry;
757
+ }
758
+ throw agendaStoreError(
759
+ "AGENDA_SCHEDULER_ENTRY_NOT_FOUND",
760
+ `Agenda entry does not exist: ${id}`,
761
+ );
762
+ },
763
+ { failIfUnavailable: true },
764
+ );
765
+ }
766
+
574
767
  /**
575
768
  * Retire every schedulable entry whose `expiresAt` has passed (status →
576
769
  * "expired", stamping `expiredAt`), across all kinds, so it never fires again.
@@ -311,6 +311,9 @@ export function buildEvidenceArtifact(kind, data = {}) {
311
311
  ...base,
312
312
  // The image bytes/path are opaque to this layer; only metadata here.
313
313
  ref: d.ref == null ? null : String(d.ref),
314
+ digest: /^sha256:[0-9a-f]{64}$/iu.test(String(d.digest || ""))
315
+ ? String(d.digest).toLowerCase()
316
+ : null,
314
317
  width: Number.isFinite(Number(d.width)) ? Number(d.width) : null,
315
318
  height: Number.isFinite(Number(d.height)) ? Number(d.height) : null,
316
319
  };