chainlesschain 0.166.7 → 0.166.9

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 (187) hide show
  1. package/README.md +21 -0
  2. package/package.json +3 -1
  3. package/src/assets/web-panel/.build-hash +1 -1
  4. package/src/assets/web-panel/assets/{AIOps-BlrmQxa2.js → AIOps-DJvpifGx.js} +1 -1
  5. package/src/assets/web-panel/assets/{ActionButton-zyRyLITg.js → ActionButton-D2UhuF_A.js} +1 -1
  6. package/src/assets/web-panel/assets/{Analytics-DwGz7OGN.js → Analytics-C9ho9obu.js} +3 -3
  7. package/src/assets/web-panel/assets/{AppLayout-Dc-nj7Zd.js → AppLayout-BvRCpFK3.js} +5 -5
  8. package/src/assets/web-panel/assets/{Artifacts-7Hu3O73p.js → Artifacts-jxrySvpk.js} +1 -1
  9. package/src/assets/web-panel/assets/{Audit-Bnoe3-fR.js → Audit-ovEw0ZYl.js} +1 -1
  10. package/src/assets/web-panel/assets/{BackgroundAgents-BqYFrDKZ.js → BackgroundAgents-D7H5z6zS.js} +1 -1
  11. package/src/assets/web-panel/assets/{Backup-B3hwW1nz.js → Backup-BuXob8za.js} +1 -1
  12. package/src/assets/web-panel/assets/{BaseInput-XFVxLA4w.js → BaseInput-CtnszuQ2.js} +1 -1
  13. package/src/assets/web-panel/assets/{Chat-CWRDNw7e.js → Chat-B_mYE8fJ.js} +6 -6
  14. package/src/assets/web-panel/assets/{ChatBubbleRenderer-Bf30VM8G.js → ChatBubbleRenderer-DaiA6CsX.js} +1 -1
  15. package/src/assets/web-panel/assets/{Checkbox-kFeeBgac.js → Checkbox-ierdtcJD.js} +1 -1
  16. package/src/assets/web-panel/assets/{Codegen-CCxp8xoI.js → Codegen-3VKPJD_B.js} +1 -1
  17. package/src/assets/web-panel/assets/{Col-BLKZalle.js → Col-1EdMyf5P.js} +1 -1
  18. package/src/assets/web-panel/assets/{Community-DD0eWCez.js → Community-D6H7UA8K.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compact-CHqHWdy0.js → Compact-BBAZvYIm.js} +1 -1
  20. package/src/assets/web-panel/assets/{Compliance-Bw54uPiK.js → Compliance-CgsTrAoj.js} +1 -1
  21. package/src/assets/web-panel/assets/{Cowork-DZ13zKNJ.js → Cowork-tnZgLoTE.js} +3 -3
  22. package/src/assets/web-panel/assets/{Cron-Dlj5Jevg.js → Cron-CPpZw2Nh.js} +2 -2
  23. package/src/assets/web-panel/assets/{Crosschain-Nvz0aR0j.js → Crosschain-BymBcp5z.js} +1 -1
  24. package/src/assets/web-panel/assets/{DID-Ct89eUyY.js → DID-DKPxS_K1.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dashboard-BHUH5IAe.js → Dashboard-DvJhEmH9.js} +2 -2
  26. package/src/assets/web-panel/assets/{Dropdown-BhZG-PO7.js → Dropdown-b8iQyQIZ.js} +1 -1
  27. package/src/assets/web-panel/assets/{EmailListRenderer-ae4RVwwJ.js → EmailListRenderer--0-A-zKb.js} +1 -1
  28. package/src/assets/web-panel/assets/{FamilyGuardDashboard-AOcxLfLr.js → FamilyGuardDashboard-C12iDN06.js} +1 -1
  29. package/src/assets/web-panel/assets/{Federation-BK2PJQOF.js → Federation-BRhaE2Z8.js} +1 -1
  30. package/src/assets/web-panel/assets/{FormItemContext-C2n3xO2_.js → FormItemContext-C4dnq7yf.js} +1 -1
  31. package/src/assets/web-panel/assets/{GenericCardRenderer-DcyUVFZq.js → GenericCardRenderer-CGAdbR5n.js} +1 -1
  32. package/src/assets/web-panel/assets/{Git-tBae9Lt8.js → Git-4eA2fYzL.js} +2 -2
  33. package/src/assets/web-panel/assets/{Governance-DmNR3AP4.js → Governance-BJuY9Y-9.js} +1 -1
  34. package/src/assets/web-panel/assets/{Inference-CoseEigi.js → Inference-DZ5Dy4up.js} +1 -1
  35. package/src/assets/web-panel/assets/{KnowledgeGraph-Bdjd1sxr.js → KnowledgeGraph-BMTjRs4A.js} +1 -1
  36. package/src/assets/web-panel/assets/{Logs-CtlkKIcn.js → Logs-BKEeQEfJ.js} +2 -2
  37. package/src/assets/web-panel/assets/MarkdownRenderer-B05DgASC.js +1 -0
  38. package/src/assets/web-panel/assets/{Marketplace-BTYb7nEx.js → Marketplace-Dhho4fEg.js} +1 -1
  39. package/src/assets/web-panel/assets/{McpTools-D0iUdW3P.js → McpTools-BW6xxSlU.js} +2 -2
  40. package/src/assets/web-panel/assets/{Memory--gwI7w4Y.js → Memory-mPqlpSkq.js} +2 -2
  41. package/src/assets/web-panel/assets/{MobileBridge-JmFBi24T.js → MobileBridge-Cb9N_DQI.js} +1 -1
  42. package/src/assets/web-panel/assets/{MobileProjects-BK01cQRx.js → MobileProjects-BNs8tah_.js} +1 -1
  43. package/src/assets/web-panel/assets/{Mtc-u7avzyoO.js → Mtc-CaxBt8tn.js} +5 -5
  44. package/src/assets/web-panel/assets/{MtcAudit-gT3z5fo_.js → MtcAudit-DRPQbp3t.js} +2 -2
  45. package/src/assets/web-panel/assets/{Multisig-BIqZTz5n.js → Multisig-CRm-d8bK.js} +3 -3
  46. package/src/assets/web-panel/assets/{NLProgramming-DdhVfXYq.js → NLProgramming-BCCk3LPs.js} +1 -1
  47. package/src/assets/web-panel/assets/{Notes-CBlyUmY3.js → Notes-Cv8SN8gN.js} +3 -3
  48. package/src/assets/web-panel/assets/{NotificationSettings-DSyI26N3.js → NotificationSettings-CggIvTh5.js} +1 -1
  49. package/src/assets/web-panel/assets/{OrderTableRenderer-B7IEuNz4.js → OrderTableRenderer-BW3_bV12.js} +1 -1
  50. package/src/assets/web-panel/assets/{Organization-ozhi4kGS.js → Organization-BuRE-VCO.js} +4 -4
  51. package/src/assets/web-panel/assets/{Overflow-CBy57RVM.js → Overflow-DBrm1gju.js} +1 -1
  52. package/src/assets/web-panel/assets/{P2P-CA-ZRv77.js → P2P-CWVnDYgS.js} +2 -2
  53. package/src/assets/web-panel/assets/{PdhVaultBrowser-DOHc9zm8.js → PdhVaultBrowser-8RKUIpte.js} +3 -3
  54. package/src/assets/web-panel/assets/{Permissions-DiP632GP.js → Permissions-tDUAxogW.js} +4 -4
  55. package/src/assets/web-panel/assets/{PersonalDataHub-AnU8O-SS.js → PersonalDataHub-Dv2-CFis.js} +5 -5
  56. package/src/assets/web-panel/assets/{Pipeline-DDibOUaP.js → Pipeline-DM6kvFni.js} +1 -1
  57. package/src/assets/web-panel/assets/{Privacy-D421t36T.js → Privacy-DzK-yL0d.js} +1 -1
  58. package/src/assets/web-panel/assets/{ProjectInit-DR879ZPJ.js → ProjectInit-B5UrNpkj.js} +2 -2
  59. package/src/assets/web-panel/assets/{ProjectSettings-Ded8o6aY.js → ProjectSettings-CxJD43oW.js} +2 -2
  60. package/src/assets/web-panel/assets/Projects-Z2Orm8Ma.js +1 -0
  61. package/src/assets/web-panel/assets/{Providers-Boivuu-E.js → Providers-CYl4jRYK.js} +1 -1
  62. package/src/assets/web-panel/assets/{QrScannerModal-xKD_ntKp.js → QrScannerModal-DeH2T0fH.js} +1 -1
  63. package/src/assets/web-panel/assets/{QuickAsk-D3y_A6FV.js → QuickAsk-Bw9k_kTk.js} +1 -1
  64. package/src/assets/web-panel/assets/{Recommend-BjKM-YC2.js → Recommend-Bl_jGwoi.js} +1 -1
  65. package/src/assets/web-panel/assets/RemoteSession-d6u01Kq0.js +5 -0
  66. package/src/assets/web-panel/assets/{Reputation-Ci2GjH5p.js → Reputation-Ds_Dfr-k.js} +1 -1
  67. package/src/assets/web-panel/assets/{Row-B0-T2BSh.js → Row-BpQUQTNj.js} +1 -1
  68. package/src/assets/web-panel/assets/{RssFeed-Bet-ur-r.js → RssFeed-BatpZBGt.js} +2 -2
  69. package/src/assets/web-panel/assets/{Search-DWtRAS2R.js → Search-D7hOObzi.js} +1 -1
  70. package/src/assets/web-panel/assets/{Security-BDfu2Qn6.js → Security-dXQ4FKNt.js} +4 -4
  71. package/src/assets/web-panel/assets/{Services-CvJmvSMM.js → Services-D8wInGPa.js} +2 -2
  72. package/src/assets/web-panel/assets/{Skeleton-CEbrKpdC.js → Skeleton-DXQCoYpM.js} +1 -1
  73. package/src/assets/web-panel/assets/{Skills-CjVeiETf.js → Skills-D3oLRIVn.js} +1 -1
  74. package/src/assets/web-panel/assets/{Sla-Dibypxum.js → Sla-BmP4-LnJ.js} +1 -1
  75. package/src/assets/web-panel/assets/{SpeechSettings-XflYXp7a.js → SpeechSettings-DLj-xzro.js} +1 -1
  76. package/src/assets/web-panel/assets/{SyncSettings-ro1Ivx1E.js → SyncSettings-8KKaaRMr.js} +2 -2
  77. package/src/assets/web-panel/assets/{Tasks-CHq1qFbo.js → Tasks-GyK42I7C.js} +1 -1
  78. package/src/assets/web-panel/assets/{Templates-CRnUZxtZ.js → Templates-n1y_8UBG.js} +1 -1
  79. package/src/assets/web-panel/assets/{Tenant-jUX72JCA.js → Tenant-B39nBph8.js} +1 -1
  80. package/src/assets/web-panel/assets/{Terminal-BBhAs7pt.js → Terminal-DCQoOKXe.js} +2 -2
  81. package/src/assets/web-panel/assets/{TimelineRenderer-CD5M3RGp.js → TimelineRenderer-BkhbDfXk.js} +1 -1
  82. package/src/assets/web-panel/assets/{Tokens-sah3v0gu.js → Tokens-BeHIIU8D.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trigger-BNT3Uz3s.js → Trigger-BHvWXVOb.js} +1 -1
  84. package/src/assets/web-panel/assets/{Trust-BytMGPMo.js → Trust-y2WaOSto.js} +1 -1
  85. package/src/assets/web-panel/assets/{UkeySign-BkYVMRQs.js → UkeySign-DBFeJBzt.js} +1 -1
  86. package/src/assets/web-panel/assets/{VideoEditing-psvb5Q7Y.js → VideoEditing-BEOWitC-.js} +1 -1
  87. package/src/assets/web-panel/assets/{Wallet-PFQTW0MH.js → Wallet-BITedTe6.js} +4 -4
  88. package/src/assets/web-panel/assets/{WebAuthn-DgO-OwRT.js → WebAuthn-DMwlJVin.js} +5 -5
  89. package/src/assets/web-panel/assets/{WorkflowEditor-DL2l9VNl.js → WorkflowEditor-CKfGFEu1.js} +1 -1
  90. package/src/assets/web-panel/assets/{chat-C84akEzN.js → chat-DR6gnBGF.js} +1 -1
  91. package/src/assets/web-panel/assets/{colors-DzTWuQKP.js → colors-C_Hw5NCn.js} +1 -1
  92. package/src/assets/web-panel/assets/{compact-item-CR9LJQFv.js → compact-item-B8IPwsEu.js} +1 -1
  93. package/src/assets/web-panel/assets/{createContext-CTTov5Kn.js → createContext-D-u4JVnJ.js} +1 -1
  94. package/src/assets/web-panel/assets/devWarning-Cq6lSd_q.js +1 -0
  95. package/src/assets/web-panel/assets/{hasIn-DALj523o.js → hasIn-CZubdS4D.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-Be6Os5S8.js → index-11ASqx-A.js} +1 -1
  97. package/src/assets/web-panel/assets/index-BQ3213fz.js +1 -0
  98. package/src/assets/web-panel/assets/{index-CXaCRXN4.js → index-BXS6wYJZ.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-7ux_XohH.js → index-Bi21Etg4.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-CXTEpfGe.js → index-Bizm87cX.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-DH6OG-ci.js → index-Bv2132PO.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-CZhhFQi9.js → index-BzoFanEQ.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-B6QOJbSn.js → index-C25rOz7O.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-CunGDV0g.js → index-C2VmtNaQ.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-CmELknPe.js → index-Cbm8F0M2.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-DZER6Lj3.js → index-CfniPP5p.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-B2qpjU-D.js → index-Cg2bCeol.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-QW0EXx14.js → index-CiXkhOkY.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-C5eeMl_2.js → index-Cl5RpreD.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-s4CFyn-n.js → index-CqmLw8cs.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-eJcFleIV.js → index-Ctje8Vl3.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-3-XJoYgX.js → index-D1w96gg9.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-_8vetPbU.js → index-D47jt8ET.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-Cef0n4k_.js → index-DJ6pG79m.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-AXnERsyV.js → index-DTosx2Wu.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-DtW6Zr_i.js → index-DY6MHo9D.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-CNmTDXmf.js → index-DcFjRT-K.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-Dah8M4l2.js → index-DfnzrUxU.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-D0MqUnKO.js → index-DjRrqooR.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-CqUgXYIQ.js → index-DmRcgiYT.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-D9ScRFxz.js → index-DpjHpRoq.js} +3 -3
  122. package/src/assets/web-panel/assets/{index-DjE_ew7U.js → index-Dt-w3xQ7.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-W9axN_Ce.js → index-DuOU5apg.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-BDyt57zL.js → index-LvjAKDSl.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-hzzTITR9.js → index-_nL79NT8.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-BNaQt49r.js → index-auyNYjLo.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-DBIPnoTj.js → index-cVqbas5C.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-CnxjXIsK.js → index-ffe7bvqP.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-BHRXKiU1.js → index-idZKyADQ.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-D_Bg0LdK.js → index-k1Xa5iw1.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-BKNIzw0U.js → index-mYZJxGH6.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-DxdzSljS.js → index-rYBHSDcJ.js} +1 -1
  133. package/src/assets/web-panel/assets/index-vJagfET2.js +1 -0
  134. package/src/assets/web-panel/assets/{index-CjkPDSX4.js → index-xoNssgz_.js} +1 -1
  135. package/src/assets/web-panel/assets/{initDefaultProps-JuW8mFj7.js → initDefaultProps-lcU_dT2r.js} +1 -1
  136. package/src/assets/web-panel/assets/{motion-Cwb0HBve.js → motion-Dc7UNXZ1.js} +1 -1
  137. package/src/assets/web-panel/assets/{move-DHokzMgu.js → move-Cll8ZXaL.js} +1 -1
  138. package/src/assets/web-panel/assets/{mtc-parser-DX31y6QS.js → mtc-parser-CAb_yLIM.js} +1 -1
  139. package/src/assets/web-panel/assets/{omit-BCIUYDA6.js → omit-DurYMyTe.js} +1 -1
  140. package/src/assets/web-panel/assets/{pickAttrs-DMCj4EoZ.js → pickAttrs-BITQyOlw.js} +1 -1
  141. package/src/assets/web-panel/assets/{placementArrow-Dy5K-u1s.js → placementArrow-Dg1rH91i.js} +1 -1
  142. package/src/assets/web-panel/assets/{responsiveObserve-DkGeZu54.js → responsiveObserve-D_EWIeac.js} +1 -1
  143. package/src/assets/web-panel/assets/{slide-Dc5dyJdg.js → slide-lK4d3zsh.js} +1 -1
  144. package/src/assets/web-panel/assets/{statusUtils-DIUBjOaC.js → statusUtils-Bflq-Git.js} +1 -1
  145. package/src/assets/web-panel/assets/{styleChecker-DmyEOxm5.js → styleChecker-Ccp0I-wt.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFlexGapSupport-FRhakk1e.js → useFlexGapSupport-CYZbByYA.js} +1 -1
  147. package/src/assets/web-panel/assets/{useFs-clXyV1WQ.js → useFs-B_x0nxFD.js} +1 -1
  148. package/src/assets/web-panel/assets/{usePersonalDataHub-UF6DG41z.js → usePersonalDataHub-DW55rL85.js} +1 -1
  149. package/src/assets/web-panel/assets/{vnode-CoCt95G7.js → vnode-Ca6MH3W8.js} +1 -1
  150. package/src/assets/web-panel/assets/{zoom-yVWt-ENm.js → zoom-NdHelOog.js} +1 -1
  151. package/src/assets/web-panel/index.html +1 -1
  152. package/src/command-help-index.json +1 -1
  153. package/src/commands/orchestrate.js +61 -9
  154. package/src/data/changelog.json +34 -1
  155. package/src/gateways/ws/message-dispatcher.js +4 -0
  156. package/src/gateways/ws/session-protocol.js +89 -11
  157. package/src/gateways/ws/ws-agent-handler.js +65 -9
  158. package/src/gateways/ws/ws-approval-gate.js +181 -16
  159. package/src/gateways/ws/ws-server.js +16 -6
  160. package/src/generated/cc-agent-protocol.schema.json +148 -2
  161. package/src/lib/agent-team/task-lease.js +172 -3
  162. package/src/lib/agent-team/team-runner.js +60 -1
  163. package/src/lib/app-server/graph-runtime.js +326 -2
  164. package/src/lib/app-server/server.js +60 -0
  165. package/src/lib/approval-grant-ledger.js +69 -0
  166. package/src/lib/codex-app-server-adapter.js +11 -20
  167. package/src/lib/graph-kernel/compiler.js +66 -13
  168. package/src/lib/graph-kernel/cutover-authority-resolver.js +26 -0
  169. package/src/lib/graph-kernel/cutover-ledger.js +53 -11
  170. package/src/lib/graph-kernel/retirement-evidence.js +567 -0
  171. package/src/lib/graph-kernel/runtime.js +76 -14
  172. package/src/lib/interaction-adapter.js +61 -9
  173. package/src/lib/policy-decision-event.js +149 -0
  174. package/src/lib/process-execution-broker/platform-sandbox.js +15 -1
  175. package/src/lib/record-replay/index.js +1 -0
  176. package/src/lib/record-replay/playwright-ui-driver.js +327 -0
  177. package/src/lib/webhook-security.js +484 -36
  178. package/src/runtime/coding-agent-events.cjs +13 -11
  179. package/src/runtime/headless-runner.js +17 -1
  180. package/src/runtime/headless-stream.js +66 -3
  181. package/src/runtime/session-slash-commands.js +57 -6
  182. package/src/assets/web-panel/assets/MarkdownRenderer-CZsTBEQE.js +0 -1
  183. package/src/assets/web-panel/assets/Projects-BHPxiucB.js +0 -1
  184. package/src/assets/web-panel/assets/RemoteSession-CgqKMXG4.js +0 -5
  185. package/src/assets/web-panel/assets/devWarning-BOhvmlpc.js +0 -1
  186. package/src/assets/web-panel/assets/index-DDyMJexx.js +0 -1
  187. package/src/assets/web-panel/assets/index-btiojFYn.js +0 -1
@@ -4,6 +4,7 @@ import {
4
4
  compileGraphDefinition,
5
5
  executionAttemptId,
6
6
  graphDigest,
7
+ validateGraphDefinitionMigrationEvidence,
7
8
  writeScopesOverlap,
8
9
  } from "./compiler.js";
9
10
  import { GraphEventStore } from "./event-store.js";
@@ -356,6 +357,7 @@ function stateSnapshot(run) {
356
357
  version: 1,
357
358
  id: run.id,
358
359
  definition: run.compiled.definition,
360
+ definitionMigration: clone(run.definitionMigration),
359
361
  subgraphDefinitions: run.compiled.subgraphDefinitions,
360
362
  phase: run.phase,
361
363
  status: run.status,
@@ -404,6 +406,11 @@ function restoreState(run, snapshot, compiled = null) {
404
406
  subgraphs: persistedSubgraphRegistry(snapshot.subgraphDefinitions),
405
407
  allowUnresolvedSubgraphs: snapshot.subgraphDefinitions == null,
406
408
  });
409
+ run.definitionMigration = snapshot.definitionMigration
410
+ ? clone(
411
+ validateGraphDefinitionMigrationEvidence(snapshot.definitionMigration),
412
+ )
413
+ : clone(run.compiled.definitionMigration || null);
407
414
  run.phase = snapshot.phase;
408
415
  run.status = snapshot.status;
409
416
  run.graphRevision = snapshot.graphRevision;
@@ -475,12 +482,35 @@ function attemptProjection(attempt) {
475
482
  return Object.freeze(clone(attempt));
476
483
  }
477
484
 
485
+ function humanTaskProjection(task) {
486
+ const projected = clone(task);
487
+ if (
488
+ projected.claimExpiresAt == null &&
489
+ Number.isFinite(projected.claimExpiresAtMs)
490
+ ) {
491
+ projected.claimExpiresAt = nowIso(() => projected.claimExpiresAtMs);
492
+ }
493
+ delete projected.claimExpiresAtMs;
494
+ delete projected.expiresAtMs;
495
+ return Object.freeze(projected);
496
+ }
497
+
478
498
  function runProjection(run) {
479
499
  return Object.freeze({
480
500
  id: run.id,
481
501
  definitionId: run.compiled.definitionId,
482
502
  revision: run.compiled.revision,
483
503
  revisionDigest: run.revisionDigest,
504
+ definitionMigration: run.definitionMigration
505
+ ? Object.freeze({
506
+ schema: run.definitionMigration.schema,
507
+ fromVersion: run.definitionMigration.fromVersion,
508
+ toVersion: run.definitionMigration.toVersion,
509
+ revisionDigest: run.definitionMigration.revisionDigest,
510
+ rollbackDigest: run.definitionMigration.rollbackDigest,
511
+ backupAvailable: true,
512
+ })
513
+ : null,
484
514
  occurrenceRef: clone(run.occurrenceRef),
485
515
  phase: run.phase,
486
516
  status: run.status,
@@ -591,6 +621,7 @@ function buildRun(compiled, options, now, writerIdentity, writerLeaseTtlMs) {
591
621
  const run = {
592
622
  id,
593
623
  compiled,
624
+ definitionMigration: clone(compiled.definitionMigration || null),
594
625
  phase: "open",
595
626
  status: "running",
596
627
  graphRevision: compiled.revision,
@@ -963,6 +994,7 @@ function sweepExpirations(run, now) {
963
994
  task.status = "open";
964
995
  task.claimActorId = null;
965
996
  task.claimLeaseId = null;
997
+ task.claimExpiresAt = null;
966
998
  task.claimExpiresAtMs = null;
967
999
  task.updatedAt = nowIso(() => now);
968
1000
  changed = true;
@@ -1170,6 +1202,13 @@ function classifyQuiescence(run, now) {
1170
1202
  ) {
1171
1203
  return "running";
1172
1204
  }
1205
+ if (
1206
+ [...run.humanTasks.values()].some((task) =>
1207
+ ["open", "claimed"].includes(task.status),
1208
+ )
1209
+ ) {
1210
+ return "waiting_human";
1211
+ }
1173
1212
  if (
1174
1213
  [...run.attempts.values()].some((attempt) =>
1175
1214
  ACTIVE_ATTEMPT.has(attempt.status),
@@ -1191,13 +1230,6 @@ function classifyQuiescence(run, now) {
1191
1230
  ) {
1192
1231
  return "reconciliation_required";
1193
1232
  }
1194
- if (
1195
- [...run.humanTasks.values()].some((task) =>
1196
- ["open", "claimed"].includes(task.status),
1197
- )
1198
- ) {
1199
- return "waiting_human";
1200
- }
1201
1233
  if (
1202
1234
  [...run.messages.values()].some((message) =>
1203
1235
  ["admitted", "delivered", "read"].includes(message.status),
@@ -1582,6 +1614,19 @@ export class GraphKernel {
1582
1614
  );
1583
1615
  }
1584
1616
 
1617
+ humanTasks(runId) {
1618
+ const run = this._run(runId);
1619
+ return Object.freeze(
1620
+ [...run.humanTasks.values()]
1621
+ .sort(
1622
+ (left, right) =>
1623
+ left.createdAt.localeCompare(right.createdAt) ||
1624
+ left.id.localeCompare(right.id),
1625
+ )
1626
+ .map(humanTaskProjection),
1627
+ );
1628
+ }
1629
+
1585
1630
  registerAgent(runId, { agentId, capacity = 1, resident = true } = {}) {
1586
1631
  const run = this._run(runId);
1587
1632
  const id = safeIdentifier(agentId, "agentId");
@@ -4146,11 +4191,12 @@ export class GraphKernel {
4146
4191
  authorityDigest: run.authorityDigest,
4147
4192
  status: "open",
4148
4193
  nonce: safeIdentifier(nonce, "nonce"),
4149
- quorum: Math.max(1, Number(quorum) || 1),
4194
+ quorum: Math.min(64, Math.max(1, Math.trunc(Number(quorum)) || 1)),
4150
4195
  separationOfDuties: separationOfDuties === true,
4151
4196
  decisions: [],
4152
4197
  claimActorId: null,
4153
4198
  claimLeaseId: null,
4199
+ claimExpiresAt: null,
4154
4200
  claimExpiresAtMs: null,
4155
4201
  createdAt: nowIso(() => now),
4156
4202
  updatedAt: nowIso(() => now),
@@ -4160,7 +4206,7 @@ export class GraphKernel {
4160
4206
  };
4161
4207
  run.humanTasks.set(id, task);
4162
4208
  run.status = "waiting_human";
4163
- return Object.freeze(clone(task));
4209
+ return humanTaskProjection(task);
4164
4210
  },
4165
4211
  { idempotencyKey: `human-task:${id}` },
4166
4212
  );
@@ -4206,8 +4252,9 @@ export class GraphKernel {
4206
4252
  task.claimActorId = actor;
4207
4253
  task.claimLeaseId = safeIdentifier(claimLeaseId, "claimLeaseId");
4208
4254
  task.claimExpiresAtMs = now + finitePositive(ttlMs, 300_000);
4255
+ task.claimExpiresAt = nowIso(() => task.claimExpiresAtMs);
4209
4256
  task.updatedAt = nowIso(() => now);
4210
- return Object.freeze(clone(task));
4257
+ return humanTaskProjection(task);
4211
4258
  },
4212
4259
  );
4213
4260
  }
@@ -4312,11 +4359,15 @@ export class GraphKernel {
4312
4359
  task.status = "open";
4313
4360
  task.claimActorId = null;
4314
4361
  task.claimLeaseId = null;
4362
+ task.claimExpiresAt = null;
4315
4363
  task.claimExpiresAtMs = null;
4316
4364
  }
4317
4365
  task.updatedAt = nowIso(() => now);
4318
4366
  run.status = classifyQuiescence(run, now);
4319
- return Object.freeze(clone(task));
4367
+ if (TERMINAL_RUN.has(run.status)) {
4368
+ run.completedAt = nowIso(() => now);
4369
+ }
4370
+ return humanTaskProjection(task);
4320
4371
  },
4321
4372
  );
4322
4373
  }
@@ -4336,14 +4387,25 @@ export class GraphKernel {
4336
4387
  "human task is already terminal",
4337
4388
  );
4338
4389
  }
4390
+ const now = this.now();
4339
4391
  task.status = "cancelled";
4340
4392
  task.reason = String(reason).slice(0, 1024);
4341
- task.updatedAt = nowIso(this.now);
4393
+ task.updatedAt = nowIso(() => now);
4394
+ const attempt = run.attempts.get(task.attemptId);
4395
+ if (attempt && attempt.status === "waiting_human") {
4396
+ attempt.status = "cancelled";
4397
+ attempt.participationStatus = "human_cancelled";
4398
+ attempt.updatedAt = nowIso(() => now);
4399
+ }
4342
4400
  const state = run.nodeStates.get(task.nodeId);
4343
4401
  state.status = "cancelled";
4344
4402
  state.blockedRoot = task.id;
4345
- state.updatedAt = nowIso(this.now);
4346
- return Object.freeze(clone(task));
4403
+ state.updatedAt = nowIso(() => now);
4404
+ run.status = classifyQuiescence(run, now);
4405
+ if (TERMINAL_RUN.has(run.status)) {
4406
+ run.completedAt = nowIso(() => now);
4407
+ }
4408
+ return humanTaskProjection(task);
4347
4409
  },
4348
4410
  );
4349
4411
  }
@@ -205,6 +205,7 @@ export class WebSocketInteractionAdapter extends InteractionAdapter {
205
205
  // null (the default for plain questions) → no binding check, unchanged.
206
206
  binding: options.binding || null,
207
207
  bindingType: options.bindingType || null,
208
+ requireBinding: options.requireBinding === true,
208
209
  });
209
210
 
210
211
  if (approvalRequest) {
@@ -253,6 +254,7 @@ export class WebSocketInteractionAdapter extends InteractionAdapter {
253
254
  // Approval binding pass-through: a permission-gate producer supplies
254
255
  // it; plain questions never carry one (message stays byte-identical).
255
256
  ...(options.binding ? { binding: options.binding } : {}),
257
+ ...(options.requireBinding === true ? { requireBinding: true } : {}),
256
258
  },
257
259
  );
258
260
  }
@@ -290,6 +292,45 @@ export class WebSocketInteractionAdapter extends InteractionAdapter {
290
292
  return answer === "true" || answer === "yes" || answer === "y";
291
293
  }
292
294
 
295
+ /**
296
+ * Structured approval variant used by Desktop/WebSocket hosts. Unlike the
297
+ * legacy boolean askConfirm path, this preserves the canonical decision
298
+ * lifetime and requires the trusted host to echo the exact request binding.
299
+ */
300
+ async askApproval(question, options = {}) {
301
+ const {
302
+ binding = null,
303
+ default: dflt = false,
304
+ approval = {},
305
+ ...extra
306
+ } = options || {};
307
+ const answer = await this._ask(
308
+ "confirm",
309
+ question,
310
+ { default: dflt, approval, ...extra },
311
+ binding ? { binding, requireBinding: true } : {},
312
+ );
313
+ const candidate =
314
+ answer?.decision && typeof answer.decision === "object"
315
+ ? answer.decision
316
+ : answer;
317
+ if (
318
+ candidate &&
319
+ typeof candidate === "object" &&
320
+ [
321
+ "acceptOnce",
322
+ "acceptForTurn",
323
+ "acceptForSession",
324
+ "decline",
325
+ "cancel",
326
+ ].includes(candidate.kind)
327
+ ) {
328
+ return candidate;
329
+ }
330
+ if (answer === true) return { kind: "acceptOnce" };
331
+ return { kind: "decline" };
332
+ }
333
+
293
334
  /**
294
335
  * Agent-core AskUserQuestion transport for Desktop/WebSocket consumers.
295
336
  * It uses the same pending map and `session-answer` resolver as MCP
@@ -369,7 +410,7 @@ export class WebSocketInteractionAdapter extends InteractionAdapter {
369
410
  * Resolves the corresponding pending promise.
370
411
  */
371
412
  resolveAnswer(requestId, answer, binding = null) {
372
- this._resolvePending(requestId, answer, "question", binding);
413
+ return this._resolvePending(requestId, answer, "question", binding);
373
414
  }
374
415
 
375
416
  /**
@@ -441,7 +482,7 @@ export class WebSocketInteractionAdapter extends InteractionAdapter {
441
482
  }
442
483
 
443
484
  resolveHostTool(requestId, payload) {
444
- this._resolvePending(requestId, payload, "host-tool");
485
+ return this._resolvePending(requestId, payload, "host-tool");
445
486
  }
446
487
 
447
488
  rejectAllPending(reason = createAbortError("Interaction interrupted")) {
@@ -549,7 +590,7 @@ export class WebSocketInteractionAdapter extends InteractionAdapter {
549
590
  ) {
550
591
  const pending = this._pending.get(requestId);
551
592
  if (!pending) {
552
- return;
593
+ return Object.freeze({ settled: false, reason: "not_pending" });
553
594
  }
554
595
  // Kind guard: a question-answer must not settle a host-tool request (or
555
596
  // vice versa). On a mismatch, IGNORE the message — leave the request pending
@@ -559,7 +600,7 @@ export class WebSocketInteractionAdapter extends InteractionAdapter {
559
600
  // value). Backward-compatible: callers passing no expectedKind, and
560
601
  // pre-kind pending entries, behave exactly as before.
561
602
  if (expectedKind && pending.kind && pending.kind !== expectedKind) {
562
- return;
603
+ return Object.freeze({ settled: false, reason: "kind_mismatch" });
563
604
  }
564
605
 
565
606
  // Approval-binding guard (authority §"权限来源"): if this request was raised
@@ -572,17 +613,18 @@ export class WebSocketInteractionAdapter extends InteractionAdapter {
572
613
  pending.bindingType === "interaction" &&
573
614
  !sameInteractionBinding(pending.binding, incomingBinding)
574
615
  ) {
575
- return;
616
+ return Object.freeze({ settled: false, reason: "binding_mismatch" });
576
617
  }
577
618
 
578
619
  let effective = payload;
579
620
  if (
580
621
  pending.bindingType !== "interaction" &&
581
622
  pending.binding &&
582
- incomingBinding &&
583
- !verifyApprovalBinding(pending.binding, incomingBinding)
623
+ ((pending.requireBinding && !incomingBinding) ||
624
+ (incomingBinding &&
625
+ !verifyApprovalBinding(pending.binding, incomingBinding)))
584
626
  ) {
585
- effective = false;
627
+ effective = pending.requireBinding ? { kind: "decline" } : false;
586
628
  }
587
629
 
588
630
  this._pending.delete(requestId);
@@ -594,13 +636,23 @@ export class WebSocketInteractionAdapter extends InteractionAdapter {
594
636
  effective === true ||
595
637
  effective === "true" ||
596
638
  effective === "yes" ||
597
- effective === "y";
639
+ effective === "y" ||
640
+ ["acceptOnce", "acceptForTurn", "acceptForSession"].includes(
641
+ effective?.kind || effective?.decision?.kind,
642
+ );
598
643
  this._notifyPendingApproval("approval.settled", {
599
644
  requestId,
600
645
  reason: normalizedApproval ? "approved" : "denied",
601
646
  });
602
647
  }
603
648
  pending.resolve(effective);
649
+ return Object.freeze({
650
+ settled: true,
651
+ reason:
652
+ effective !== payload && pending.requireBinding
653
+ ? "binding_mismatch_denied"
654
+ : "resolved",
655
+ });
604
656
  }
605
657
  }
606
658
 
@@ -0,0 +1,149 @@
1
+ import { createHash } from "node:crypto";
2
+ import { redactSecrets } from "./secret-scan.js";
3
+
4
+ export const POLICY_DECISION_EVENT_VERSION = 1;
5
+
6
+ const MAX_CHAIN = 8;
7
+
8
+ function boundedText(value, max) {
9
+ if (value == null) return null;
10
+ let text;
11
+ if (typeof value === "string") {
12
+ text = value;
13
+ } else {
14
+ try {
15
+ text = JSON.stringify(value);
16
+ } catch {
17
+ text = String(value);
18
+ }
19
+ }
20
+ const redacted = redactSecrets(String(text));
21
+ return redacted.length > max
22
+ ? `${redacted.slice(0, Math.max(0, max - 1))}…`
23
+ : redacted;
24
+ }
25
+
26
+ function stableValue(value) {
27
+ if (Array.isArray(value)) return value.map(stableValue);
28
+ if (!value || typeof value !== "object") return value;
29
+ return Object.fromEntries(
30
+ Object.keys(value)
31
+ .filter((key) => value[key] !== undefined)
32
+ .sort()
33
+ .map((key) => [key, stableValue(value[key])]),
34
+ );
35
+ }
36
+
37
+ function digest(value) {
38
+ return `sha256:${createHash("sha256")
39
+ .update(JSON.stringify(stableValue(value)))
40
+ .digest("hex")}`;
41
+ }
42
+
43
+ function canonicalDecision(
44
+ value,
45
+ { blocked = false, requiresApproval = false } = {},
46
+ ) {
47
+ const normalized = String(value || "")
48
+ .trim()
49
+ .toLowerCase();
50
+ if (
51
+ blocked ||
52
+ ["block", "blocked", "deny", "denied", "decline", "cancel"].includes(
53
+ normalized,
54
+ )
55
+ ) {
56
+ return "deny";
57
+ }
58
+ if (
59
+ requiresApproval ||
60
+ ["ask", "confirm", "approval_required", "require_confirmation"].includes(
61
+ normalized,
62
+ )
63
+ ) {
64
+ return "ask";
65
+ }
66
+ return "allow";
67
+ }
68
+
69
+ function normalizeChain(value) {
70
+ if (!Array.isArray(value)) return [];
71
+ return value.slice(0, MAX_CHAIN).map((candidate) => {
72
+ const row =
73
+ candidate && typeof candidate === "object" && !Array.isArray(candidate)
74
+ ? candidate
75
+ : {};
76
+ return {
77
+ layer: boundedText(row.layer, 80),
78
+ outcome: boundedText(row.outcome, 80),
79
+ via: boundedText(row.via || row.source, 120),
80
+ rule: boundedText(row.rule, 256),
81
+ reason: boundedText(row.reason, 512),
82
+ };
83
+ });
84
+ }
85
+
86
+ function finalizePolicyDecision(value) {
87
+ const projection = Object.fromEntries(
88
+ Object.entries(value).filter(([, entry]) => entry !== undefined),
89
+ );
90
+ const policyDigest = digest(projection);
91
+ return Object.freeze({
92
+ type: "policy_decision",
93
+ schema_version: POLICY_DECISION_EVENT_VERSION,
94
+ decision_id:
95
+ boundedText(projection.decision_id, 160) ||
96
+ `policy:${policyDigest.slice("sha256:".length, "sha256:".length + 48)}`,
97
+ ...projection,
98
+ policy_digest: policyDigest,
99
+ });
100
+ }
101
+
102
+ export function projectHookPolicyDecision(event = {}) {
103
+ if (event?.type !== "hook_response") return null;
104
+ return finalizePolicyDecision({
105
+ source: "hook",
106
+ decision: canonicalDecision(event.decision, {
107
+ blocked: event.blocked === true || Boolean(event.error),
108
+ requiresApproval: event.requires_approval === true,
109
+ }),
110
+ session_id: boundedText(event.session_id, 160) || undefined,
111
+ turn_id: boundedText(event.turn_id, 160) || undefined,
112
+ tool_use_id: boundedText(event.tool_use_id, 160) || undefined,
113
+ tool: boundedText(event.tool || event.tool_name, 256) || undefined,
114
+ hook_event: boundedText(event.hook_event, 96) || undefined,
115
+ via: boundedText(
116
+ event.via || (event.hook_event ? `hook:${event.hook_event}` : "hook"),
117
+ 120,
118
+ ),
119
+ reason: event.error ? "hook_runtime_error" : undefined,
120
+ });
121
+ }
122
+
123
+ export function projectToolPolicyDecision(event = {}, context = {}) {
124
+ const permission =
125
+ event?.permission_decision &&
126
+ typeof event.permission_decision === "object" &&
127
+ !Array.isArray(event.permission_decision)
128
+ ? event.permission_decision
129
+ : null;
130
+ if (!permission) return null;
131
+ return finalizePolicyDecision({
132
+ decision_id:
133
+ boundedText(permission.id || event.permission_decision_id, 160) ||
134
+ undefined,
135
+ source: "tool",
136
+ decision: canonicalDecision(permission.decision),
137
+ session_id:
138
+ boundedText(context.sessionId || event.session_id, 160) || undefined,
139
+ turn_id: boundedText(context.turnId || event.turn_id, 160) || undefined,
140
+ tool_use_id:
141
+ boundedText(context.toolUseId || event.tool_use_id || event.id, 160) ||
142
+ undefined,
143
+ tool: boundedText(event.tool || permission.tool, 256) || undefined,
144
+ via: boundedText(permission.via, 120) || undefined,
145
+ rule: boundedText(permission.rule, 256) || undefined,
146
+ reason: boundedText(permission.reason, 512) || undefined,
147
+ chain: normalizeChain(permission.chain),
148
+ });
149
+ }
@@ -2208,7 +2208,7 @@ function cleanupWindowsTemporaryPath(
2208
2208
  }
2209
2209
  if (
2210
2210
  !expectedIdentity ||
2211
- !sameWindowsFileIdentity(inspected.identity, expectedIdentity)
2211
+ !sameWindowsFileObjectIdentity(inspected.identity, expectedIdentity)
2212
2212
  ) {
2213
2213
  return false;
2214
2214
  }
@@ -2719,6 +2719,20 @@ function sameWindowsFileIdentity(left, right) {
2719
2719
  );
2720
2720
  }
2721
2721
 
2722
+ // Cleanup is authorized by the stable file-object identity, not by metadata
2723
+ // that Windows may settle after the helper closes its last write handle. The
2724
+ // strict identity above remains authoritative while content is read or
2725
+ // attested; this cleanup-only comparison still rejects a same-path replacement
2726
+ // because that changes the inode/birth identity.
2727
+ function sameWindowsFileObjectIdentity(left, right) {
2728
+ return (
2729
+ left.dev === right.dev &&
2730
+ left.ino === right.ino &&
2731
+ left.mode === right.mode &&
2732
+ left.birthtimeNs === right.birthtimeNs
2733
+ );
2734
+ }
2735
+
2722
2736
  function inspectWindowsAdapterAssembly(runtime, assemblyPath) {
2723
2737
  const boundBefore = inspectWindowsAdapterBoundPath(
2724
2738
  runtime,
@@ -1 +1,2 @@
1
1
  export * from "./skill-recorder.js";
2
+ export * from "./playwright-ui-driver.js";