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
@@ -16,7 +16,8 @@
16
16
  "graph_effect_receipts",
17
17
  "deterministic_trace",
18
18
  "agent_stream_events",
19
- "agent_stream_payloads"
19
+ "agent_stream_payloads",
20
+ "unified_policy_decision"
20
21
  ]
21
22
  },
22
23
  "oneOf": [
@@ -1626,6 +1627,26 @@
1626
1627
  }
1627
1628
  }
1628
1629
  },
1630
+ "HumanTaskDecision": {
1631
+ "type": "object",
1632
+ "additionalProperties": false,
1633
+ "required": [
1634
+ "actorId",
1635
+ "decision",
1636
+ "decidedAt"
1637
+ ],
1638
+ "properties": {
1639
+ "actorId": {
1640
+ "$ref": "#/$defs/Identifier"
1641
+ },
1642
+ "decision": {
1643
+ "$ref": "#/$defs/ApprovalDecision"
1644
+ },
1645
+ "decidedAt": {
1646
+ "$ref": "#/$defs/Timestamp"
1647
+ }
1648
+ }
1649
+ },
1629
1650
  "HumanTask": {
1630
1651
  "type": "object",
1631
1652
  "additionalProperties": false,
@@ -1659,6 +1680,12 @@
1659
1680
  "operationDigest": {
1660
1681
  "$ref": "#/$defs/Digest"
1661
1682
  },
1683
+ "operation": {
1684
+ "$ref": "#/$defs/JsonValue"
1685
+ },
1686
+ "authorityDigest": {
1687
+ "$ref": "#/$defs/Digest"
1688
+ },
1662
1689
  "status": {
1663
1690
  "enum": [
1664
1691
  "open",
@@ -1668,6 +1695,21 @@
1668
1695
  "expired"
1669
1696
  ]
1670
1697
  },
1698
+ "quorum": {
1699
+ "type": "integer",
1700
+ "minimum": 1,
1701
+ "maximum": 64
1702
+ },
1703
+ "separationOfDuties": {
1704
+ "type": "boolean"
1705
+ },
1706
+ "decisions": {
1707
+ "type": "array",
1708
+ "maxItems": 64,
1709
+ "items": {
1710
+ "$ref": "#/$defs/HumanTaskDecision"
1711
+ }
1712
+ },
1671
1713
  "claimActorId": {
1672
1714
  "anyOf": [
1673
1715
  {
@@ -1688,12 +1730,32 @@
1688
1730
  }
1689
1731
  ]
1690
1732
  },
1733
+ "claimExpiresAt": {
1734
+ "anyOf": [
1735
+ {
1736
+ "$ref": "#/$defs/Timestamp"
1737
+ },
1738
+ {
1739
+ "type": "null"
1740
+ }
1741
+ ]
1742
+ },
1691
1743
  "nonce": {
1692
1744
  "$ref": "#/$defs/Identifier"
1693
1745
  },
1694
1746
  "expiresAt": {
1695
1747
  "$ref": "#/$defs/Timestamp"
1696
1748
  },
1749
+ "createdAt": {
1750
+ "$ref": "#/$defs/Timestamp"
1751
+ },
1752
+ "updatedAt": {
1753
+ "$ref": "#/$defs/Timestamp"
1754
+ },
1755
+ "reason": {
1756
+ "type": "string",
1757
+ "maxLength": 1024
1758
+ },
1697
1759
  "decision": {
1698
1760
  "anyOf": [
1699
1761
  {
@@ -1822,7 +1884,8 @@
1822
1884
  "token_usage",
1823
1885
  "tool_result",
1824
1886
  "tool_use",
1825
- "user"
1887
+ "user",
1888
+ "policy_decision"
1826
1889
  ]
1827
1890
  },
1828
1891
  "AgentStreamEventEnvelope": {
@@ -2444,6 +2507,85 @@
2444
2507
  }
2445
2508
  }
2446
2509
  },
2510
+ "AgentPolicyDecisionStreamEvent": {
2511
+ "type": "object",
2512
+ "required": [
2513
+ "type",
2514
+ "schema_version",
2515
+ "decision_id",
2516
+ "source",
2517
+ "decision",
2518
+ "policy_digest"
2519
+ ],
2520
+ "properties": {
2521
+ "type": {
2522
+ "const": "policy_decision"
2523
+ },
2524
+ "schema_version": {
2525
+ "const": 1
2526
+ },
2527
+ "decision_id": {
2528
+ "type": "string",
2529
+ "minLength": 1,
2530
+ "maxLength": 160
2531
+ },
2532
+ "source": {
2533
+ "enum": [
2534
+ "hook",
2535
+ "tool"
2536
+ ]
2537
+ },
2538
+ "decision": {
2539
+ "enum": [
2540
+ "allow",
2541
+ "ask",
2542
+ "deny"
2543
+ ]
2544
+ },
2545
+ "session_id": {
2546
+ "type": "string",
2547
+ "maxLength": 160
2548
+ },
2549
+ "turn_id": {
2550
+ "type": "string",
2551
+ "maxLength": 160
2552
+ },
2553
+ "tool_use_id": {
2554
+ "type": "string",
2555
+ "maxLength": 160
2556
+ },
2557
+ "tool": {
2558
+ "type": "string",
2559
+ "maxLength": 256
2560
+ },
2561
+ "hook_event": {
2562
+ "type": "string",
2563
+ "maxLength": 96
2564
+ },
2565
+ "via": {
2566
+ "type": "string",
2567
+ "maxLength": 120
2568
+ },
2569
+ "rule": {
2570
+ "type": "string",
2571
+ "maxLength": 256
2572
+ },
2573
+ "reason": {
2574
+ "type": "string",
2575
+ "maxLength": 512
2576
+ },
2577
+ "chain": {
2578
+ "type": "array",
2579
+ "maxItems": 8,
2580
+ "items": {
2581
+ "$ref": "#/$defs/JsonValue"
2582
+ }
2583
+ },
2584
+ "policy_digest": {
2585
+ "$ref": "#/$defs/Digest"
2586
+ }
2587
+ }
2588
+ },
2447
2589
  "AgentQuestionRequestStreamEvent": {
2448
2590
  "type": "object",
2449
2591
  "required": [
@@ -3276,6 +3418,9 @@
3276
3418
  },
3277
3419
  {
3278
3420
  "$ref": "#/$defs/AgentUserStreamEvent"
3421
+ },
3422
+ {
3423
+ "$ref": "#/$defs/AgentPolicyDecisionStreamEvent"
3279
3424
  }
3280
3425
  ]
3281
3426
  },
@@ -3394,6 +3539,7 @@
3394
3539
  "graph/compile",
3395
3540
  "graph/run",
3396
3541
  "graph/status",
3542
+ "graph/history",
3397
3543
  "graph/cancel",
3398
3544
  "graph/reconcile"
3399
3545
  ]
@@ -28,6 +28,8 @@ import { createHash, randomUUID } from "node:crypto";
28
28
 
29
29
  export const DEFAULT_LEASE_TTL_MS = 60000;
30
30
  export const DEFAULT_MAX_ATTEMPTS = 3;
31
+ export const DEFAULT_QUEUE_WAIT_SLO_MS = 10_000;
32
+ export const DEFAULT_AGING_WINDOW_MS = 2_500;
31
33
  export const ADJUDICATION_DECISIONS = Object.freeze({
32
34
  RETRY: "retry",
33
35
  ACCEPT: "accept",
@@ -154,11 +156,21 @@ export class TaskLeaseRegistry {
154
156
  now = () => Date.now(),
155
157
  defaultTtlMs = DEFAULT_LEASE_TTL_MS,
156
158
  maxAttempts = DEFAULT_MAX_ATTEMPTS,
159
+ queueWaitSloMs = DEFAULT_QUEUE_WAIT_SLO_MS,
160
+ agingWindowMs = DEFAULT_AGING_WINDOW_MS,
157
161
  leaseEpoch = randomUUID(),
158
162
  } = {}) {
159
163
  this._now = typeof now === "function" ? now : () => now;
160
164
  this.defaultTtlMs = defaultTtlMs > 0 ? defaultTtlMs : DEFAULT_LEASE_TTL_MS;
161
165
  this.maxAttempts = maxAttempts > 0 ? maxAttempts : DEFAULT_MAX_ATTEMPTS;
166
+ this.queueWaitSloMs =
167
+ Number.isFinite(queueWaitSloMs) && queueWaitSloMs > 0
168
+ ? Math.floor(queueWaitSloMs)
169
+ : DEFAULT_QUEUE_WAIT_SLO_MS;
170
+ this.agingWindowMs =
171
+ Number.isFinite(agingWindowMs) && agingWindowMs > 0
172
+ ? Math.floor(agingWindowMs)
173
+ : DEFAULT_AGING_WINDOW_MS;
162
174
  this._leaseEpoch = String(leaseEpoch || randomUUID());
163
175
  this._leaseSequence = 0;
164
176
  this._tasks = new SharedTaskList({ groupId, now: this._now });
@@ -175,6 +187,11 @@ export class TaskLeaseRegistry {
175
187
  ["low", new Set()],
176
188
  ]);
177
189
  this._leasedKeys = new Set();
190
+ this._priorityInheritanceCache = null;
191
+ // The ready timestamp is part of the durable scheduler contract. Restarts
192
+ // must not reset a task's queue-wait clock and thereby reintroduce
193
+ // starvation under a sustained high-priority stream.
194
+ this._readySinceByKey = new Map();
178
195
  }
179
196
 
180
197
  /**
@@ -300,6 +317,7 @@ export class TaskLeaseRegistry {
300
317
  }
301
318
  dependents.add(key);
302
319
  }
320
+ this._priorityInheritanceCache = null;
303
321
  this._enqueueIfReady(key);
304
322
  return { ok: true, key, id: created.id };
305
323
  }
@@ -326,6 +344,8 @@ export class TaskLeaseRegistry {
326
344
  lease: lease ? { ...lease } : null,
327
345
  assignee: t.assignee,
328
346
  createdBy: t.createdBy ?? null,
347
+ createdAt: t.createdAt,
348
+ updatedAt: t.updatedAt,
329
349
  rev: t.rev,
330
350
  // Full metadata is exposed so executors can read user payload
331
351
  // (e.g. a task's shell `command` or agent `prompt`) — it carries the
@@ -403,12 +423,75 @@ export class TaskLeaseRegistry {
403
423
  this._requeueExpiredLeases(now);
404
424
  const excluded =
405
425
  excludeKeys instanceof Set ? excludeKeys : new Set(excludeKeys || []);
426
+ let selected = null;
406
427
  for (const priority of ["high", "normal", "low"]) {
407
428
  for (const key of this._readyByPriority.get(priority)) {
408
- if (!excluded.has(key)) return key;
429
+ if (excluded.has(key)) continue;
430
+ const scheduling = this.schedulingPriority(key, { now });
431
+ const bothUrgent =
432
+ scheduling.sloUrgent && selected?.scheduling?.sloUrgent;
433
+ if (
434
+ !selected ||
435
+ (bothUrgent &&
436
+ scheduling.queueWaitMs > selected.scheduling.queueWaitMs) ||
437
+ (!bothUrgent &&
438
+ (scheduling.total > selected.scheduling.total ||
439
+ (scheduling.total === selected.scheduling.total &&
440
+ scheduling.queueWaitMs > selected.scheduling.queueWaitMs)))
441
+ ) {
442
+ selected = { key, scheduling };
443
+ }
444
+ // FIFO inside one priority class is sufficient: later members cannot
445
+ // have waited longer than the first non-excluded member.
446
+ break;
409
447
  }
410
448
  }
411
- return null;
449
+ return selected?.key || null;
450
+ }
451
+
452
+ /**
453
+ * Explain the effective scheduling priority for one task.
454
+ *
455
+ * A blocked high-priority descendant donates its priority transitively to
456
+ * the dependency that can unblock it. Ready tasks also age, and once they
457
+ * consume 75% of the declared queue-wait SLO they enter an urgent band that
458
+ * outranks newly arriving work. This makes the SLO enforceable rather than
459
+ * leaving aging as telemetry-only decoration.
460
+ */
461
+ schedulingPriority(key, { now = this._now() } = {}) {
462
+ const task = this.getTask(key);
463
+ if (!task) return null;
464
+ const base = this._priorityScore(task.priority);
465
+ const readySince = this._readySinceByKey.get(key);
466
+ const queueWaitMs = Math.max(
467
+ 0,
468
+ Number(now) -
469
+ Number(
470
+ readySince ??
471
+ task.createdAt ??
472
+ (Number.isFinite(now) ? Number(now) : 0),
473
+ ),
474
+ );
475
+ const inheritance = this._priorityInheritanceFor(key);
476
+ const donatedBase = Math.max(base, inheritance.donatedBase);
477
+ const criticalPathBoost = inheritance.criticalPathBoost;
478
+ const aging = Math.min(1000, Math.floor(queueWaitMs / this.agingWindowMs));
479
+ const sloUrgent = queueWaitMs >= Math.floor(this.queueWaitSloMs * 0.75);
480
+ const sloBoost = sloUrgent ? 10_000 : 0;
481
+ return Object.freeze({
482
+ base,
483
+ donation: Math.max(0, donatedBase - base),
484
+ aging,
485
+ criticalPathBoost,
486
+ sloBoost,
487
+ sloUrgent,
488
+ total: donatedBase + aging + Math.min(1000, criticalPathBoost) + sloBoost,
489
+ queueWaitMs,
490
+ queueWaitSloMs: this.queueWaitSloMs,
491
+ readySince: Number(readySince ?? task.createdAt ?? now),
492
+ queueWaitDeadlineAt:
493
+ Number(readySince ?? task.createdAt ?? now) + this.queueWaitSloMs,
494
+ });
412
495
  }
413
496
 
414
497
  /**
@@ -1871,6 +1954,9 @@ export class TaskLeaseRegistry {
1871
1954
  registry: {
1872
1955
  defaultTtlMs: this.defaultTtlMs,
1873
1956
  maxAttempts: this.maxAttempts,
1957
+ queueWaitSloMs: this.queueWaitSloMs,
1958
+ agingWindowMs: this.agingWindowMs,
1959
+ readySinceByKey: Array.from(this._readySinceByKey.entries()),
1874
1960
  byKey: Array.from(this._byKey.entries()),
1875
1961
  },
1876
1962
  tasks: this._tasks.snapshot(),
@@ -1882,9 +1968,12 @@ export class TaskLeaseRegistry {
1882
1968
  now,
1883
1969
  defaultTtlMs: snapshot?.registry?.defaultTtlMs,
1884
1970
  maxAttempts: snapshot?.registry?.maxAttempts,
1971
+ queueWaitSloMs: snapshot?.registry?.queueWaitSloMs,
1972
+ agingWindowMs: snapshot?.registry?.agingWindowMs,
1885
1973
  });
1886
1974
  reg._tasks = SharedTaskList.restore(snapshot.tasks, { now: reg._now });
1887
1975
  reg._byKey = new Map(snapshot?.registry?.byKey || []);
1976
+ reg._readySinceByKey = new Map(snapshot?.registry?.readySinceByKey || []);
1888
1977
  reg._rebuildIndexes();
1889
1978
  return reg;
1890
1979
  }
@@ -1899,6 +1988,7 @@ export class TaskLeaseRegistry {
1899
1988
  patch,
1900
1989
  actor: patch.assignee,
1901
1990
  });
1991
+ if (patch.status !== undefined) this._priorityInheritanceCache = null;
1902
1992
  return true;
1903
1993
  } catch {
1904
1994
  // ConcurrencyError (rev changed under us) — caller re-reads and retries.
@@ -1970,8 +2060,72 @@ export class TaskLeaseRegistry {
1970
2060
  : "normal";
1971
2061
  }
1972
2062
 
1973
- _removeReady(key) {
2063
+ _priorityScore(priority) {
2064
+ return priority === "high" ? 2 : priority === "low" ? 0 : 1;
2065
+ }
2066
+
2067
+ _priorityInheritanceFor(key) {
2068
+ if (!this._priorityInheritanceCache) {
2069
+ const keys = [...this._byKey.keys()];
2070
+ const indegree = new Map(
2071
+ keys.map((candidate) => [
2072
+ candidate,
2073
+ (this._depsByKey.get(candidate) || []).filter((dependency) =>
2074
+ this._byKey.has(dependency),
2075
+ ).length,
2076
+ ]),
2077
+ );
2078
+ const ready = keys.filter((candidate) => indegree.get(candidate) === 0);
2079
+ const order = [];
2080
+ for (let index = 0; index < ready.length; index += 1) {
2081
+ const candidate = ready[index];
2082
+ order.push(candidate);
2083
+ for (const dependent of this._dependentsByKey.get(candidate) || []) {
2084
+ if (!indegree.has(dependent)) continue;
2085
+ indegree.set(dependent, indegree.get(dependent) - 1);
2086
+ if (indegree.get(dependent) === 0) ready.push(dependent);
2087
+ }
2088
+ }
2089
+ const inherited = new Map();
2090
+ for (const candidate of order.reverse()) {
2091
+ const task = this.getTask(candidate);
2092
+ let donatedBase = this._priorityScore(task?.priority);
2093
+ let criticalPathBoost = 0;
2094
+ for (const dependent of this._dependentsByKey.get(candidate) || []) {
2095
+ const dependentTask = this.getTask(dependent);
2096
+ if (
2097
+ !dependentTask ||
2098
+ [TASK_STATUS.COMPLETED, TASK_STATUS.CANCELLED].includes(
2099
+ dependentTask.status,
2100
+ )
2101
+ ) {
2102
+ continue;
2103
+ }
2104
+ const child = inherited.get(dependent) || {
2105
+ donatedBase: this._priorityScore(dependentTask.priority),
2106
+ criticalPathBoost: 0,
2107
+ };
2108
+ donatedBase = Math.max(donatedBase, child.donatedBase);
2109
+ criticalPathBoost = Math.max(
2110
+ criticalPathBoost,
2111
+ child.criticalPathBoost + 1,
2112
+ );
2113
+ }
2114
+ inherited.set(candidate, { donatedBase, criticalPathBoost });
2115
+ }
2116
+ this._priorityInheritanceCache = inherited;
2117
+ }
2118
+ return (
2119
+ this._priorityInheritanceCache.get(key) || {
2120
+ donatedBase: this._priorityScore(this.getTask(key)?.priority),
2121
+ criticalPathBoost: 0,
2122
+ }
2123
+ );
2124
+ }
2125
+
2126
+ _removeReady(key, { clearWait = true } = {}) {
1974
2127
  for (const queue of this._readyByPriority.values()) queue.delete(key);
2128
+ if (clearWait) this._readySinceByKey.delete(key);
1975
2129
  }
1976
2130
 
1977
2131
  _dependenciesCompleted(key) {
@@ -2012,6 +2166,9 @@ export class TaskLeaseRegistry {
2012
2166
  return false;
2013
2167
  }
2014
2168
  this._leasedKeys.delete(key);
2169
+ if (!this._readySinceByKey.has(key)) {
2170
+ this._readySinceByKey.set(key, Number(now));
2171
+ }
2015
2172
  this._readyByPriority.get(this._priorityFor(task)).add(key);
2016
2173
  return true;
2017
2174
  }
@@ -2027,6 +2184,7 @@ export class TaskLeaseRegistry {
2027
2184
  }
2028
2185
 
2029
2186
  _rebuildIndexes() {
2187
+ const restoredReadySince = new Map(this._readySinceByKey || []);
2030
2188
  this._depsByKey = new Map();
2031
2189
  this._dependentsByKey = new Map();
2032
2190
  this._readyByPriority = new Map([
@@ -2035,6 +2193,8 @@ export class TaskLeaseRegistry {
2035
2193
  ["low", new Set()],
2036
2194
  ]);
2037
2195
  this._leasedKeys = new Set();
2196
+ this._readySinceByKey = restoredReadySince;
2197
+ this._priorityInheritanceCache = null;
2038
2198
  for (const task of this._tasks.list()) {
2039
2199
  const key = task.metadata?.key;
2040
2200
  const dependencies = task.metadata?.dependsOn || [];
@@ -2053,5 +2213,14 @@ export class TaskLeaseRegistry {
2053
2213
  }
2054
2214
  const now = this._now();
2055
2215
  for (const key of this._byKey.keys()) this._enqueueIfReady(key, now);
2216
+ for (const priority of ["high", "normal", "low"]) {
2217
+ const ordered = [...this._readyByPriority.get(priority)].sort(
2218
+ (left, right) =>
2219
+ (this._readySinceByKey.get(left) || 0) -
2220
+ (this._readySinceByKey.get(right) || 0) ||
2221
+ left.localeCompare(right),
2222
+ );
2223
+ this._readyByPriority.set(priority, new Set(ordered));
2224
+ }
2056
2225
  }
2057
2226
  }
@@ -211,6 +211,7 @@ export class TeamRunner {
211
211
  this._workerCount = 1;
212
212
  this._claimControllers = new Set();
213
213
  this._claimsByKey = new Map();
214
+ this._scopeDonations = new Map();
214
215
  this._handoffTransfers = new Map();
215
216
  this._handoffExpiryTimers = new Map();
216
217
  this._wallTimer = null;
@@ -224,6 +225,53 @@ export class TeamRunner {
224
225
  }
225
226
  }
226
227
 
228
+ /** Wake idle workers after a producer durably appends new tasks. */
229
+ notifyWorkAvailable() {
230
+ this._signalProgress();
231
+ }
232
+
233
+ /** Current dependency/aging priority plus scope-wait donations. */
234
+ priorityContext(key) {
235
+ return Object.freeze({
236
+ scheduling:
237
+ this.registry.schedulingPriority?.(key, { now: this._now() }) || null,
238
+ scopeDonations: Object.freeze(
239
+ [...(this._scopeDonations.get(key) || [])].map((entry) =>
240
+ Object.freeze({ ...entry }),
241
+ ),
242
+ ),
243
+ });
244
+ }
245
+
246
+ _recordScopeDonation(waiterKey, conflicts) {
247
+ const scheduling =
248
+ this.registry.schedulingPriority?.(waiterKey, { now: this._now() }) ||
249
+ null;
250
+ for (const conflict of conflicts || []) {
251
+ const holderKey = conflict?.key;
252
+ if (!holderKey || !this._activeKeys.has(holderKey)) continue;
253
+ const current = this._scopeDonations.get(holderKey) || [];
254
+ const previous = current.find((entry) => entry.waiterKey === waiterKey);
255
+ const donation = {
256
+ holderKey,
257
+ waiterKey,
258
+ waiterPriority: scheduling,
259
+ observedAt: this._now(),
260
+ };
261
+ if (
262
+ previous &&
263
+ Number(previous.waiterPriority?.total || 0) >=
264
+ Number(scheduling?.total || 0)
265
+ ) {
266
+ continue;
267
+ }
268
+ const next = current.filter((entry) => entry.waiterKey !== waiterKey);
269
+ next.push(donation);
270
+ this._scopeDonations.set(holderKey, next);
271
+ this._emit("task:priority-donated", donation);
272
+ }
273
+ }
274
+
227
275
  /**
228
276
  * Track a teammate's lifecycle state (idle / running / failed / shutdown) and
229
277
  * emit a `teammate:state` event on every transition. `lost` is set on resume
@@ -1620,6 +1668,8 @@ export class TeamRunner {
1620
1668
  this._setState(holder, "shutdown", { reason: "no-more-work" });
1621
1669
  return; // no claimable + nothing in flight → this worker is finished
1622
1670
  }
1671
+ const schedulingPriority =
1672
+ this.registry.schedulingPriority?.(key, { now: this._now() }) || null;
1623
1673
  const acq = this.registry.acquire(key, { holder, ttlMs: this.ttlMs });
1624
1674
  if (!acq.ok) {
1625
1675
  if (
@@ -1736,6 +1786,7 @@ export class TeamRunner {
1736
1786
  budgetReservation,
1737
1787
  sessionWork,
1738
1788
  );
1789
+ claim.schedulingPriority = schedulingPriority;
1739
1790
  } catch (error) {
1740
1791
  this._reservedExecutions = Math.max(0, this._reservedExecutions - 1);
1741
1792
  this.registry.release(key, {
@@ -2257,6 +2308,7 @@ export class TeamRunner {
2257
2308
  this._setFatal(error, { phase: "scope-validation", key });
2258
2309
  return null;
2259
2310
  }
2311
+ this._recordScopeDonation(key, check.conflicts);
2260
2312
  excluded.add(key);
2261
2313
  }
2262
2314
  return null;
@@ -2312,6 +2364,7 @@ export class TeamRunner {
2312
2364
  _releaseScope(holder, key) {
2313
2365
  if (!this.scopeLock) return;
2314
2366
  const released = this.scopeLock.release(key);
2367
+ this._scopeDonations.delete(key);
2315
2368
  if (released?.ok) {
2316
2369
  this._emit("task:scope-released", {
2317
2370
  key,
@@ -2330,7 +2383,12 @@ export class TeamRunner {
2330
2383
  this._inFlight++;
2331
2384
  this._maxInFlight = Math.max(this._maxInFlight, this._inFlight);
2332
2385
  this._setState(holder, "running", { key, sessionTaskKey });
2333
- this._emit("task:claimed", { key, holder, attempts: task.attempts });
2386
+ this._emit("task:claimed", {
2387
+ key,
2388
+ holder,
2389
+ attempts: task.attempts,
2390
+ schedulingPriority: claim.schedulingPriority || null,
2391
+ });
2334
2392
  const renew = () => this._renewClaim(claim);
2335
2393
  // A teammate-scoped messaging handle: post to a peer / broadcast, and read
2336
2394
  // its own inbox (direct messages + unseen broadcasts).
@@ -2471,6 +2529,7 @@ export class TeamRunner {
2471
2529
  task,
2472
2530
  holder,
2473
2531
  renew,
2532
+ priorityContext: () => this.priorityContext(key),
2474
2533
  inbox,
2475
2534
  sendMessage,
2476
2535
  messageAuthority,