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.
- package/README.md +21 -0
- package/package.json +3 -1
- package/src/assets/web-panel/.build-hash +1 -1
- package/src/assets/web-panel/assets/{AIOps-BlrmQxa2.js → AIOps-DJvpifGx.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-zyRyLITg.js → ActionButton-D2UhuF_A.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-DwGz7OGN.js → Analytics-C9ho9obu.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-Dc-nj7Zd.js → AppLayout-BvRCpFK3.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-7Hu3O73p.js → Artifacts-jxrySvpk.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-Bnoe3-fR.js → Audit-ovEw0ZYl.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-BqYFrDKZ.js → BackgroundAgents-D7H5z6zS.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-B3hwW1nz.js → Backup-BuXob8za.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-XFVxLA4w.js → BaseInput-CtnszuQ2.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-CWRDNw7e.js → Chat-B_mYE8fJ.js} +6 -6
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-Bf30VM8G.js → ChatBubbleRenderer-DaiA6CsX.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-kFeeBgac.js → Checkbox-ierdtcJD.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-CCxp8xoI.js → Codegen-3VKPJD_B.js} +1 -1
- package/src/assets/web-panel/assets/{Col-BLKZalle.js → Col-1EdMyf5P.js} +1 -1
- package/src/assets/web-panel/assets/{Community-DD0eWCez.js → Community-D6H7UA8K.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-CHqHWdy0.js → Compact-BBAZvYIm.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-Bw54uPiK.js → Compliance-CgsTrAoj.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-DZ13zKNJ.js → Cowork-tnZgLoTE.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-Dlj5Jevg.js → Cron-CPpZw2Nh.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-Nvz0aR0j.js → Crosschain-BymBcp5z.js} +1 -1
- package/src/assets/web-panel/assets/{DID-Ct89eUyY.js → DID-DKPxS_K1.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-BHUH5IAe.js → Dashboard-DvJhEmH9.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-BhZG-PO7.js → Dropdown-b8iQyQIZ.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-ae4RVwwJ.js → EmailListRenderer--0-A-zKb.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-AOcxLfLr.js → FamilyGuardDashboard-C12iDN06.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-BK2PJQOF.js → Federation-BRhaE2Z8.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-C2n3xO2_.js → FormItemContext-C4dnq7yf.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-DcyUVFZq.js → GenericCardRenderer-CGAdbR5n.js} +1 -1
- package/src/assets/web-panel/assets/{Git-tBae9Lt8.js → Git-4eA2fYzL.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-DmNR3AP4.js → Governance-BJuY9Y-9.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-CoseEigi.js → Inference-DZ5Dy4up.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-Bdjd1sxr.js → KnowledgeGraph-BMTjRs4A.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-CtlkKIcn.js → Logs-BKEeQEfJ.js} +2 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-B05DgASC.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-BTYb7nEx.js → Marketplace-Dhho4fEg.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-D0iUdW3P.js → McpTools-BW6xxSlU.js} +2 -2
- package/src/assets/web-panel/assets/{Memory--gwI7w4Y.js → Memory-mPqlpSkq.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-JmFBi24T.js → MobileBridge-Cb9N_DQI.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-BK01cQRx.js → MobileProjects-BNs8tah_.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-u7avzyoO.js → Mtc-CaxBt8tn.js} +5 -5
- package/src/assets/web-panel/assets/{MtcAudit-gT3z5fo_.js → MtcAudit-DRPQbp3t.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-BIqZTz5n.js → Multisig-CRm-d8bK.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-DdhVfXYq.js → NLProgramming-BCCk3LPs.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-CBlyUmY3.js → Notes-Cv8SN8gN.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-DSyI26N3.js → NotificationSettings-CggIvTh5.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-B7IEuNz4.js → OrderTableRenderer-BW3_bV12.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-ozhi4kGS.js → Organization-BuRE-VCO.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-CBy57RVM.js → Overflow-DBrm1gju.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-CA-ZRv77.js → P2P-CWVnDYgS.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-DOHc9zm8.js → PdhVaultBrowser-8RKUIpte.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-DiP632GP.js → Permissions-tDUAxogW.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-AnU8O-SS.js → PersonalDataHub-Dv2-CFis.js} +5 -5
- package/src/assets/web-panel/assets/{Pipeline-DDibOUaP.js → Pipeline-DM6kvFni.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-D421t36T.js → Privacy-DzK-yL0d.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-DR879ZPJ.js → ProjectInit-B5UrNpkj.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-Ded8o6aY.js → ProjectSettings-CxJD43oW.js} +2 -2
- package/src/assets/web-panel/assets/Projects-Z2Orm8Ma.js +1 -0
- package/src/assets/web-panel/assets/{Providers-Boivuu-E.js → Providers-CYl4jRYK.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-xKD_ntKp.js → QrScannerModal-DeH2T0fH.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-D3y_A6FV.js → QuickAsk-Bw9k_kTk.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-BjKM-YC2.js → Recommend-Bl_jGwoi.js} +1 -1
- package/src/assets/web-panel/assets/RemoteSession-d6u01Kq0.js +5 -0
- package/src/assets/web-panel/assets/{Reputation-Ci2GjH5p.js → Reputation-Ds_Dfr-k.js} +1 -1
- package/src/assets/web-panel/assets/{Row-B0-T2BSh.js → Row-BpQUQTNj.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-Bet-ur-r.js → RssFeed-BatpZBGt.js} +2 -2
- package/src/assets/web-panel/assets/{Search-DWtRAS2R.js → Search-D7hOObzi.js} +1 -1
- package/src/assets/web-panel/assets/{Security-BDfu2Qn6.js → Security-dXQ4FKNt.js} +4 -4
- package/src/assets/web-panel/assets/{Services-CvJmvSMM.js → Services-D8wInGPa.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-CEbrKpdC.js → Skeleton-DXQCoYpM.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-CjVeiETf.js → Skills-D3oLRIVn.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-Dibypxum.js → Sla-BmP4-LnJ.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-XflYXp7a.js → SpeechSettings-DLj-xzro.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-ro1Ivx1E.js → SyncSettings-8KKaaRMr.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-CHq1qFbo.js → Tasks-GyK42I7C.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-CRnUZxtZ.js → Templates-n1y_8UBG.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-jUX72JCA.js → Tenant-B39nBph8.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-BBhAs7pt.js → Terminal-DCQoOKXe.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-CD5M3RGp.js → TimelineRenderer-BkhbDfXk.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-sah3v0gu.js → Tokens-BeHIIU8D.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-BNT3Uz3s.js → Trigger-BHvWXVOb.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-BytMGPMo.js → Trust-y2WaOSto.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-BkYVMRQs.js → UkeySign-DBFeJBzt.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-psvb5Q7Y.js → VideoEditing-BEOWitC-.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-PFQTW0MH.js → Wallet-BITedTe6.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-DgO-OwRT.js → WebAuthn-DMwlJVin.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-DL2l9VNl.js → WorkflowEditor-CKfGFEu1.js} +1 -1
- package/src/assets/web-panel/assets/{chat-C84akEzN.js → chat-DR6gnBGF.js} +1 -1
- package/src/assets/web-panel/assets/{colors-DzTWuQKP.js → colors-C_Hw5NCn.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-CR9LJQFv.js → compact-item-B8IPwsEu.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-CTTov5Kn.js → createContext-D-u4JVnJ.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-Cq6lSd_q.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-DALj523o.js → hasIn-CZubdS4D.js} +1 -1
- package/src/assets/web-panel/assets/{index-Be6Os5S8.js → index-11ASqx-A.js} +1 -1
- package/src/assets/web-panel/assets/index-BQ3213fz.js +1 -0
- package/src/assets/web-panel/assets/{index-CXaCRXN4.js → index-BXS6wYJZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-7ux_XohH.js → index-Bi21Etg4.js} +1 -1
- package/src/assets/web-panel/assets/{index-CXTEpfGe.js → index-Bizm87cX.js} +1 -1
- package/src/assets/web-panel/assets/{index-DH6OG-ci.js → index-Bv2132PO.js} +1 -1
- package/src/assets/web-panel/assets/{index-CZhhFQi9.js → index-BzoFanEQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-B6QOJbSn.js → index-C25rOz7O.js} +1 -1
- package/src/assets/web-panel/assets/{index-CunGDV0g.js → index-C2VmtNaQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-CmELknPe.js → index-Cbm8F0M2.js} +1 -1
- package/src/assets/web-panel/assets/{index-DZER6Lj3.js → index-CfniPP5p.js} +1 -1
- package/src/assets/web-panel/assets/{index-B2qpjU-D.js → index-Cg2bCeol.js} +1 -1
- package/src/assets/web-panel/assets/{index-QW0EXx14.js → index-CiXkhOkY.js} +1 -1
- package/src/assets/web-panel/assets/{index-C5eeMl_2.js → index-Cl5RpreD.js} +1 -1
- package/src/assets/web-panel/assets/{index-s4CFyn-n.js → index-CqmLw8cs.js} +1 -1
- package/src/assets/web-panel/assets/{index-eJcFleIV.js → index-Ctje8Vl3.js} +1 -1
- package/src/assets/web-panel/assets/{index-3-XJoYgX.js → index-D1w96gg9.js} +1 -1
- package/src/assets/web-panel/assets/{index-_8vetPbU.js → index-D47jt8ET.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cef0n4k_.js → index-DJ6pG79m.js} +1 -1
- package/src/assets/web-panel/assets/{index-AXnERsyV.js → index-DTosx2Wu.js} +1 -1
- package/src/assets/web-panel/assets/{index-DtW6Zr_i.js → index-DY6MHo9D.js} +1 -1
- package/src/assets/web-panel/assets/{index-CNmTDXmf.js → index-DcFjRT-K.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dah8M4l2.js → index-DfnzrUxU.js} +1 -1
- package/src/assets/web-panel/assets/{index-D0MqUnKO.js → index-DjRrqooR.js} +1 -1
- package/src/assets/web-panel/assets/{index-CqUgXYIQ.js → index-DmRcgiYT.js} +1 -1
- package/src/assets/web-panel/assets/{index-D9ScRFxz.js → index-DpjHpRoq.js} +3 -3
- package/src/assets/web-panel/assets/{index-DjE_ew7U.js → index-Dt-w3xQ7.js} +1 -1
- package/src/assets/web-panel/assets/{index-W9axN_Ce.js → index-DuOU5apg.js} +1 -1
- package/src/assets/web-panel/assets/{index-BDyt57zL.js → index-LvjAKDSl.js} +1 -1
- package/src/assets/web-panel/assets/{index-hzzTITR9.js → index-_nL79NT8.js} +1 -1
- package/src/assets/web-panel/assets/{index-BNaQt49r.js → index-auyNYjLo.js} +1 -1
- package/src/assets/web-panel/assets/{index-DBIPnoTj.js → index-cVqbas5C.js} +1 -1
- package/src/assets/web-panel/assets/{index-CnxjXIsK.js → index-ffe7bvqP.js} +1 -1
- package/src/assets/web-panel/assets/{index-BHRXKiU1.js → index-idZKyADQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-D_Bg0LdK.js → index-k1Xa5iw1.js} +1 -1
- package/src/assets/web-panel/assets/{index-BKNIzw0U.js → index-mYZJxGH6.js} +1 -1
- package/src/assets/web-panel/assets/{index-DxdzSljS.js → index-rYBHSDcJ.js} +1 -1
- package/src/assets/web-panel/assets/index-vJagfET2.js +1 -0
- package/src/assets/web-panel/assets/{index-CjkPDSX4.js → index-xoNssgz_.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-JuW8mFj7.js → initDefaultProps-lcU_dT2r.js} +1 -1
- package/src/assets/web-panel/assets/{motion-Cwb0HBve.js → motion-Dc7UNXZ1.js} +1 -1
- package/src/assets/web-panel/assets/{move-DHokzMgu.js → move-Cll8ZXaL.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-DX31y6QS.js → mtc-parser-CAb_yLIM.js} +1 -1
- package/src/assets/web-panel/assets/{omit-BCIUYDA6.js → omit-DurYMyTe.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-DMCj4EoZ.js → pickAttrs-BITQyOlw.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-Dy5K-u1s.js → placementArrow-Dg1rH91i.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-DkGeZu54.js → responsiveObserve-D_EWIeac.js} +1 -1
- package/src/assets/web-panel/assets/{slide-Dc5dyJdg.js → slide-lK4d3zsh.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-DIUBjOaC.js → statusUtils-Bflq-Git.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-DmyEOxm5.js → styleChecker-Ccp0I-wt.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-FRhakk1e.js → useFlexGapSupport-CYZbByYA.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-clXyV1WQ.js → useFs-B_x0nxFD.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-UF6DG41z.js → usePersonalDataHub-DW55rL85.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-CoCt95G7.js → vnode-Ca6MH3W8.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-yVWt-ENm.js → zoom-NdHelOog.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-help-index.json +1 -1
- package/src/commands/orchestrate.js +61 -9
- package/src/data/changelog.json +34 -1
- package/src/gateways/ws/message-dispatcher.js +4 -0
- package/src/gateways/ws/session-protocol.js +89 -11
- package/src/gateways/ws/ws-agent-handler.js +65 -9
- package/src/gateways/ws/ws-approval-gate.js +181 -16
- package/src/gateways/ws/ws-server.js +16 -6
- package/src/generated/cc-agent-protocol.schema.json +148 -2
- package/src/lib/agent-team/task-lease.js +172 -3
- package/src/lib/agent-team/team-runner.js +60 -1
- package/src/lib/app-server/graph-runtime.js +326 -2
- package/src/lib/app-server/server.js +60 -0
- package/src/lib/approval-grant-ledger.js +69 -0
- package/src/lib/codex-app-server-adapter.js +11 -20
- package/src/lib/graph-kernel/compiler.js +66 -13
- package/src/lib/graph-kernel/cutover-authority-resolver.js +26 -0
- package/src/lib/graph-kernel/cutover-ledger.js +53 -11
- package/src/lib/graph-kernel/retirement-evidence.js +567 -0
- package/src/lib/graph-kernel/runtime.js +76 -14
- package/src/lib/interaction-adapter.js +61 -9
- package/src/lib/policy-decision-event.js +149 -0
- package/src/lib/process-execution-broker/platform-sandbox.js +15 -1
- package/src/lib/record-replay/index.js +1 -0
- package/src/lib/record-replay/playwright-ui-driver.js +327 -0
- package/src/lib/webhook-security.js +484 -36
- package/src/runtime/coding-agent-events.cjs +13 -11
- package/src/runtime/headless-runner.js +17 -1
- package/src/runtime/headless-stream.js +66 -3
- package/src/runtime/session-slash-commands.js +57 -6
- package/src/assets/web-panel/assets/MarkdownRenderer-CZsTBEQE.js +0 -1
- package/src/assets/web-panel/assets/Projects-BHPxiucB.js +0 -1
- package/src/assets/web-panel/assets/RemoteSession-CgqKMXG4.js +0 -5
- package/src/assets/web-panel/assets/devWarning-BOhvmlpc.js +0 -1
- package/src/assets/web-panel/assets/index-DDyMJexx.js +0 -1
- 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 (
|
|
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
|
-
|
|
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", {
|
|
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,
|