chainlesschain 0.162.188 → 0.162.193
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 +61 -11
- package/bin/chainlesschain.js +7 -52
- package/completions/_cc +209 -0
- package/completions/cc.bash +18 -0
- package/completions/cc.fish +13 -0
- package/completions/cc.ps1 +226 -0
- package/package.json +10 -2
- package/src/assets/web-panel/assets/{AIOps-Brr1LVcE.js → AIOps-DBLkaTje.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-DQU74DKG.js → ActionButton-BAy-Qebo.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-CYp9178y.js → Analytics-Dfb1Mlau.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-DW4SCYsW.js → AppLayout-BbFkN8m0.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-CYlD_ed1.js → Artifacts-kM4-cEEH.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-CWl1rZOi.js → Audit-BSQfYWf3.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-BOR-LPsa.js → BackgroundAgents-CWDbI_fG.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-DLpG7j1X.js → Backup-BxLPbq_Q.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-B35K9wdr.js → BaseInput-DuIbdrp6.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-CwUJb9gB.js → Chat-NEmjGahU.js} +5 -5
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-1v6aMS1m.js → ChatBubbleRenderer-DfJEo-5_.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-pi3-tPNW.js → Checkbox-CaoeG3Ns.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-FyNF35eL.js → Codegen-BFf_g3xY.js} +1 -1
- package/src/assets/web-panel/assets/{Col-tGt_JDEr.js → Col-CNOd8mdQ.js} +1 -1
- package/src/assets/web-panel/assets/{Community-CC7LonQX.js → Community-BhpDqz-i.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-BGXrHHjE.js → Compact-CQ42T7Z6.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-DSW0TBZ8.js → Compliance-DI5PcLMN.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-Bhk7rbvE.js → Cowork-wYYZe0wR.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-DxyiQ2NZ.js → Cron-Dlq03DD_.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-B2ZkxHok.js → Crosschain-BzqS8PP3.js} +1 -1
- package/src/assets/web-panel/assets/{DID-yOJV99eJ.js → DID-It55Yem7.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-CKsttz7D.js → Dashboard-9HkH6oxn.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-CVFldXSL.js → Dropdown-00e2YWRB.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-Bufv638J.js → EmailListRenderer-By-ugRDL.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-4ncjoIjL.js → FamilyGuardDashboard-C396yu5m.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-DsknEDoX.js → Federation-BME5sbZY.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-Cqe5jWXA.js → FormItemContext-B4TEZCr-.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-NAJaFKxc.js → GenericCardRenderer-_9CX9ieY.js} +1 -1
- package/src/assets/web-panel/assets/{Git-CszKQpnl.js → Git-BrS6WVSr.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-BXGodXi6.js → Governance-BMdCWnKF.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-CkoYuG2c.js → Inference-Bcp3vzcA.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-DFlEr_T0.js → KnowledgeGraph-DlLuqGY5.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-CVaENddA.js → Logs-D-W_6x09.js} +2 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-DElGPxCZ.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-CDlLT0fw.js → Marketplace-Dzn2guvI.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-DdwOyszN.js → McpTools-uPict-KL.js} +6 -6
- package/src/assets/web-panel/assets/{Memory-DKQnkKuG.js → Memory-BCw43kOb.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-DGseqlzJ.js → MobileBridge-DmV8Wv7F.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-COBbEOlj.js → MobileProjects-C-HaCmSM.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-O61Vwyli.js → Mtc-C6jxJ34Y.js} +5 -5
- package/src/assets/web-panel/assets/{MtcAudit-Dw2SyasS.js → MtcAudit-Za8ExwhQ.js} +5 -5
- package/src/assets/web-panel/assets/{Multisig-hSu_l8kf.js → Multisig-KKDbuEgb.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-CX1Epurr.js → NLProgramming-Dj97zbCk.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-R9xX8o8_.js → Notes-DBXvMraU.js} +4 -4
- package/src/assets/web-panel/assets/{NotificationSettings-jtSNLCuK.js → NotificationSettings-DOxITLYl.js} +1 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-7DVjZwMM.js +1 -0
- package/src/assets/web-panel/assets/{Organization-Pu2WO-U3.js → Organization-D1i73mjb.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-BjnqUyFp.js → Overflow-kW6Q3rvg.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-jjkvz44c.js → P2P-C-v_8p2v.js} +2 -2
- package/src/assets/web-panel/assets/PdhVaultBrowser-tUbbY64W.js +7 -0
- package/src/assets/web-panel/assets/{Permissions-D4yDpivd.js → Permissions-DkHxEZ58.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-0qsL6iH1.js → PersonalDataHub-DWuMPGrK.js} +5 -5
- package/src/assets/web-panel/assets/{Pipeline-Cx7Ybrk2.js → Pipeline-30IYXWWm.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-PbfR_M_V.js → Privacy-DZNQ4RrH.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-CyV6Gsub.js → ProjectInit-De2MCElf.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-C7KZ2Wdk.js → ProjectSettings-5uHk9wsC.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-DQDjO-yK.js → Projects-XjDfrFLb.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-DyFVBBMX.js → Providers-Bgwj6gcE.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-CzB1BC9_.js → QrScannerModal-gKql9umv.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-Bk636mC1.js → QuickAsk-BWvmwkh7.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-DoWxHIT3.js → Recommend-Uok4hZPd.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-oOVIv9wq.js → RemoteSession-DLJzTk9a.js} +3 -3
- package/src/assets/web-panel/assets/{Reputation-BucoReGG.js → Reputation-ZVwIPMSO.js} +1 -1
- package/src/assets/web-panel/assets/{Row-DzmOdJU7.js → Row-CN04HxWR.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-C1tK7KGU.js → RssFeed-BdSrEG4g.js} +3 -3
- package/src/assets/web-panel/assets/{Search-CSnInOqk.js → Search-5PwVd0IR.js} +1 -1
- package/src/assets/web-panel/assets/{Security-dlejr15l.js → Security-DdBo4zjN.js} +3 -3
- package/src/assets/web-panel/assets/{Services-BioPZuNh.js → Services-D3letU7M.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-DWMibwpC.js → Skeleton--Jb83f1v.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-BAAnx1B2.js → Skills-Bg-CulHX.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-jWNp4hNO.js → Sla-7QOa7S-X.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-y5kqKha-.js → SpeechSettings-DQwppjRw.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-B9GNsc3e.js → SyncSettings-dNPQGL-s.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-BDBYKRen.js → Tasks-Ggs-Z48q.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-DRiE5eaN.js → Templates-78TYHgRO.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-BGlAvExF.js → Tenant-xHwwv9vO.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-B8uzrbNY.js → Terminal-BJXSJfm4.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-Df48iveY.js → TimelineRenderer-fLbjRhJw.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-CcmHndN6.js → Tokens-oMSBSBmB.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-DPkWxmQ2.js → Trigger-CfnY_wX_.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-DTb5a5AV.js → Trust-AdyTgYKO.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-CBmg5vch.js → UkeySign-C5K_81dS.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-B0mZrz4O.js → VideoEditing-vcGVDqki.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-Bxs7_mpd.js → Wallet-hhOc3hlY.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-C8x3cMxU.js → WebAuthn-CVloC11s.js} +3 -3
- package/src/assets/web-panel/assets/{WorkflowEditor-DPrNznrP.js → WorkflowEditor-CYeE32R5.js} +1 -1
- package/src/assets/web-panel/assets/{chat-D3bYWu7S.js → chat-CNROR5bN.js} +1 -1
- package/src/assets/web-panel/assets/{colors-DY-PwMu4.js → colors-Cjx-cnwU.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-LDk10Kw6.js → compact-item-DOIfelvD.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-C-2MZnFq.js → createContext-DfA7UZ8u.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-ChcCBGs7.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-BQIBjcnB.js → hasIn-BMSCzcfM.js} +1 -1
- package/src/assets/web-panel/assets/{index-CQVb2dWp.js → index-5-HXgOX5.js} +1 -1
- package/src/assets/web-panel/assets/{index-BdXnYMCZ.js → index-AWg-0M1S.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cx6D_dx2.js → index-B4iYzpkL.js} +1 -1
- package/src/assets/web-panel/assets/{index-_HRO_cIu.js → index-B5Udeb_6.js} +1 -1
- package/src/assets/web-panel/assets/{index-DlRYqt3S.js → index-B7gf77CJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-BrnRO9yE.js → index-BEMwBBHk.js} +1 -1
- package/src/assets/web-panel/assets/{index-VCh5zNJo.js → index-BM1y_9hM.js} +1 -1
- package/src/assets/web-panel/assets/{index-BRI3ngNg.js → index-BUonmKSE.js} +1 -1
- package/src/assets/web-panel/assets/{index-C3GNvExG.js → index-BbQ2eQ8H.js} +1 -1
- package/src/assets/web-panel/assets/{index-DSvo_bp0.js → index-BemJ2u_E.js} +1 -1
- package/src/assets/web-panel/assets/{index-L6qixyLc.js → index-BolaOQxx.js} +1 -1
- package/src/assets/web-panel/assets/{index-BI4KgcYC.js → index-BxOk9vkG.js} +1 -1
- package/src/assets/web-panel/assets/{index-CY4KnaO9.js → index-By61ojUx.js} +1 -1
- package/src/assets/web-panel/assets/{index-L3smcoQX.js → index-C2K9SNVX.js} +1 -1
- package/src/assets/web-panel/assets/{index-BX2b9Orc.js → index-C3L5gdiD.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cz4b6Z_7.js → index-C7xn0Nub.js} +1 -1
- package/src/assets/web-panel/assets/{index-COG61sRv.js → index-CAnvhwg6.js} +1 -1
- package/src/assets/web-panel/assets/{index-C7FC8cP2.js → index-CEKMcOyU.js} +1 -1
- package/src/assets/web-panel/assets/{index-BN-xdSWZ.js → index-CNC5onm4.js} +1 -1
- package/src/assets/web-panel/assets/{index-DY2FIrmz.js → index-CVL27kXC.js} +1 -1
- package/src/assets/web-panel/assets/{index-CiTvBAr-.js → index-CVm1_i3t.js} +1 -1
- package/src/assets/web-panel/assets/{index-DhRt9cYJ.js → index-CdYBye8B.js} +1 -1
- package/src/assets/web-panel/assets/{index-B5pgtZnY.js → index-ClNMrqEY.js} +1 -1
- package/src/assets/web-panel/assets/{index-7xKu7Fns.js → index-Cs6l7uRu.js} +1 -1
- package/src/assets/web-panel/assets/{index-D4K1weKc.js → index-CshQbilz.js} +1 -1
- package/src/assets/web-panel/assets/{index-k7C_oDCO.js → index-Cyweh0Hy.js} +1 -1
- package/src/assets/web-panel/assets/{index-D3Oq-DLL.js → index-DBpWXFed.js} +3 -3
- package/src/assets/web-panel/assets/{index-DYyLJPlF.js → index-DHtpHZAQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dh-tkpKQ.js → index-DLmn0BoK.js} +1 -1
- package/src/assets/web-panel/assets/{index-8JC9BJa1.js → index-DPAWBrMf.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dd2Km97U.js → index-DjEsxO5h.js} +1 -1
- package/src/assets/web-panel/assets/{index-KFZO_lcx.js → index-FBc_CJBd.js} +1 -1
- package/src/assets/web-panel/assets/{index-DTIZpPtG.js → index-Icdoqmzt.js} +1 -1
- package/src/assets/web-panel/assets/index-Q2IajL54.js +1 -0
- package/src/assets/web-panel/assets/index-bRkHgOMc.js +1 -0
- package/src/assets/web-panel/assets/{index-lmm9p-jm.js → index-dCd8cSUq.js} +1 -1
- package/src/assets/web-panel/assets/{index-HasPt4-h.js → index-m2vG9gG_.js} +1 -1
- package/src/assets/web-panel/assets/{index-CaslYch6.js → index-mTpHoEzr.js} +1 -1
- package/src/assets/web-panel/assets/{index-CbR6ROOa.js → index-ti_lnTWl.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-zQPSHf2C.js → initDefaultProps-Bu8k7H1Y.js} +1 -1
- package/src/assets/web-panel/assets/{motion-CKCStGVk.js → motion-s3iVK41k.js} +1 -1
- package/src/assets/web-panel/assets/{move-BufVDGYF.js → move-B6B-E5Jz.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-DcaFxy5D.js → mtc-parser-BiYgTidA.js} +1 -1
- package/src/assets/web-panel/assets/{omit-EScpkGdo.js → omit-pU1RdUDA.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-72hG_qfT.js → pickAttrs-Cdoq_SeM.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-CMFWiH20.js → placementArrow-DIuvAn2K.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-DKQHS41p.js → responsiveObserve-8w16YR2D.js} +1 -1
- package/src/assets/web-panel/assets/{slide-QVAFHTIQ.js → slide-VZ01cZe3.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-DIz38e2G.js → statusUtils-lh8YMN8Z.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-zK5cyLby.js → styleChecker-CmDyreec.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-DhZngk62.js → useFlexGapSupport-hiJWMU5y.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-BvV2cvkg.js → useFs-Thnu-Iaj.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-CRmxb9l3.js → usePersonalDataHub-LBdOxjwY.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-CgQIbobP.js → vnode-Cg6lFY_X.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-D4XrrO0R.js → zoom-DVfsR1YO.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/cli-help.js +181 -0
- package/src/command-help-index.json +181 -0
- package/src/command-manifest.json +1107 -175
- package/src/command-surface-policy.js +197 -0
- package/src/commands/agent.js +98 -33
- package/src/commands/artifacts.js +400 -2
- package/src/commands/background-session.js +41 -3
- package/src/commands/checkpoint-managed.js +1059 -0
- package/src/commands/checkpoint-restore-recovery.js +1476 -0
- package/src/commands/checkpoint.js +950 -22
- package/src/commands/compact.js +101 -25
- package/src/commands/config.js +506 -20
- package/src/commands/doctor.js +4 -1
- package/src/commands/hub.js +1 -1
- package/src/commands/mcp.js +688 -24
- package/src/commands/pack.js +16 -2
- package/src/commands/plugin.js +20 -12
- package/src/commands/session-mcp-recovery.js +218 -0
- package/src/commands/session.js +470 -110
- package/src/commands/setup.js +36 -10
- package/src/commands/skill.js +181 -110
- package/src/commands/status.js +21 -5
- package/src/commands/team-distributed.js +3324 -0
- package/src/commands/team.js +1130 -74
- package/src/commands/update.js +68 -6
- package/src/constants.js +11 -0
- package/src/data/changelog.json +26 -0
- package/src/gateways/ws/action-protocol.js +10 -0
- package/src/gateways/ws/session-protocol.js +555 -27
- package/src/gateways/ws/ws-agent-handler.js +541 -14
- package/src/gateways/ws/ws-session-gateway.js +129 -22
- package/src/gateways/ws/ws-session-state.js +431 -0
- package/src/harness/background-task-manager.js +233 -36
- package/src/harness/jsonl-session-store.js +2551 -167
- package/src/harness/mcp-client.js +802 -61
- package/src/harness/prompt-compressor.js +227 -27
- package/src/harness/session-index.js +89 -38
- package/src/harness/session-list-index.js +254 -0
- package/src/harness/structured-handoff.js +410 -0
- package/src/lazy-dispatch.js +747 -84
- package/src/lib/__tests__/logger.test.js +50 -2
- package/src/lib/advisor-runtime.js +1047 -0
- package/src/lib/agent-core.js +2 -0
- package/src/lib/agent-sandbox.js +120 -26
- package/src/lib/agent-session-export.js +20 -0
- package/src/lib/agent-team/task-lease.js +271 -3
- package/src/lib/agent-team/team-adjudication.js +1501 -0
- package/src/lib/agent-team/team-budget.js +4 -1
- package/src/lib/agent-team/team-control-store.js +582 -0
- package/src/lib/agent-team/team-distributed-queue.js +5246 -0
- package/src/lib/agent-team/team-process-checkpoint.js +211 -0
- package/src/lib/agent-team/team-runner.js +543 -24
- package/src/lib/agent-team/team-worktree.js +1403 -95
- package/src/lib/artifact-store.js +131 -8
- package/src/lib/background-agent-supervisor.js +185 -13
- package/src/lib/background-interaction-journal.js +37 -9
- package/src/lib/background-launch-profile.js +1058 -0
- package/src/lib/checkpoint-restore-already-completed-controller.js +902 -0
- package/src/lib/checkpoint-restore-orchestrator.js +987 -0
- package/src/lib/checkpoint-restore-partial-rollback-controller.js +1953 -0
- package/src/lib/checkpoint-restore-recovery-controller.js +689 -0
- package/src/lib/checkpoint-restore-recovery.js +884 -0
- package/src/lib/checkpoint-restore-retention.js +126 -0
- package/src/lib/checkpoint-restore-saga.js +5079 -0
- package/src/lib/checkpoint-restore-session-recovery.js +1178 -0
- package/src/lib/checkpoint-restore-workspace-target-verifier.js +270 -0
- package/src/lib/checkpoint-store.js +1688 -97
- package/src/lib/checkpoint-timeline-authority.js +522 -0
- package/src/lib/checkpoint-timeline.js +642 -0
- package/src/lib/config-keys.js +18 -119
- package/src/lib/config-manager.js +446 -27
- package/src/lib/config-redaction.js +57 -0
- package/src/lib/config-schema.js +853 -0
- package/src/lib/cowork-mcp-tools.js +5 -0
- package/src/lib/cowork-task-runner.js +458 -63
- package/src/lib/delivery-coordinator.js +1234 -0
- package/src/lib/delivery-evidence.js +450 -0
- package/src/lib/doctor-checkup.js +199 -14
- package/src/lib/executable-path.js +34 -0
- package/src/lib/fatal-handler.js +16 -0
- package/src/lib/file-checkpoint.js +4909 -186
- package/src/lib/file-lines.js +125 -0
- package/src/lib/headless-config-command.js +16 -5
- package/src/lib/hook-runner.cjs +139 -38
- package/src/lib/hooks-v2-workspace-context.js +10 -0
- package/src/lib/impacted-gate-selector.js +424 -0
- package/src/lib/interaction-adapter.js +62 -0
- package/src/lib/jsonl-session-store.js +1 -35
- package/src/lib/logger.js +66 -14
- package/src/lib/managed-checkpoint-render.js +60 -0
- package/src/lib/managed-tool-checkpoint.js +194 -0
- package/src/lib/mcp-call-ledger-store.js +1069 -0
- package/src/lib/mcp-call-ledger.js +747 -0
- package/src/lib/mcp-client.js +5 -0
- package/src/lib/mcp-conflict-scheduler.js +468 -0
- package/src/lib/mcp-effect-contract.js +102 -0
- package/src/lib/mcp-headers-helper-trust.js +145 -0
- package/src/lib/mcp-headers-helper.js +616 -0
- package/src/lib/mcp-host-recovery-runtime.js +131 -0
- package/src/lib/mcp-ledger-recovery-admission.js +1065 -0
- package/src/lib/mcp-recovery-adjudication.js +443 -0
- package/src/lib/output-context.js +86 -0
- package/src/lib/packer/file-identity.js +170 -0
- package/src/lib/packer/index.js +3 -0
- package/src/lib/packer/native-update-state.js +277 -0
- package/src/lib/packer/pack-update-applier.js +1983 -136
- package/src/lib/packer/pack-update-checker.js +34 -0
- package/src/lib/packer/pack-update-downloader.js +875 -86
- package/src/lib/packer/pack-update-signature.js +86 -0
- package/src/lib/packer/pkg-config-generator.js +6 -0
- package/src/lib/paths.js +65 -10
- package/src/lib/plan-mode.js +831 -14
- package/src/lib/plan-persistence.js +540 -0
- package/src/lib/plugin-runtime/hooks.js +227 -69
- package/src/lib/plugin-runtime/plugin-options.js +189 -44
- package/src/lib/pr-automation-policy.js +146 -8
- package/src/lib/process-execution-broker/credential-agent.js +7 -0
- package/src/lib/process-execution-broker/index.js +491 -13
- package/src/lib/process-execution-broker/linux-generic-bwrap-runtime.js +28 -1
- package/src/lib/process-execution-broker/linux-generic-bwrap.js +28 -4
- package/src/lib/process-execution-broker/platform-sandbox.js +92 -70
- package/src/lib/process-execution-broker/windows-sandbox-helper.dll +0 -0
- package/src/lib/process-execution-broker/windows-sandbox-helper.exe +0 -0
- package/src/lib/process-execution-broker/windows-sandbox.cs +284 -19
- package/src/lib/process-execution-broker/workspace-transaction.js +4459 -0
- package/src/lib/project-instructions.js +165 -29
- package/src/lib/project-mcp-trust.js +67 -0
- package/src/lib/public-ide-capability-manifest.js +272 -0
- package/src/lib/public-ide-capability-validation.js +351 -0
- package/src/lib/secret-store.js +267 -43
- package/src/lib/secure-file-identity.js +433 -0
- package/src/lib/secure-fs.js +1089 -0
- package/src/lib/security-audit.js +58 -0
- package/src/lib/service-manager.js +34 -13
- package/src/lib/session-budget-runtime.js +1452 -0
- package/src/lib/session-host-snapshot.js +388 -0
- package/src/lib/session-message-provenance.js +429 -0
- package/src/lib/session-projection.js +804 -0
- package/src/lib/session-resource-budget.js +1495 -0
- package/src/lib/settings-hooks.cjs +138 -22
- package/src/lib/settings-loader.cjs +25 -2
- package/src/lib/side-effect-ledger-store.js +45 -23
- package/src/lib/skill-execution-identity.js +217 -0
- package/src/lib/skill-loader.js +299 -18
- package/src/lib/sub-agent-context.js +236 -28
- package/src/lib/sub-agent-registry.js +5 -0
- package/src/lib/subagent-contract.js +94 -0
- package/src/lib/todo-manager.js +185 -18
- package/src/lib/todo-persistence.js +417 -0
- package/src/lib/turn-binding-store.js +41 -23
- package/src/lib/turn-binding.js +160 -2
- package/src/lib/with-file-lock.js +165 -24
- package/src/lib/ws-chat-handler.js +21 -0
- package/src/program-base.js +18 -0
- package/src/repl/advisor-command.js +103 -0
- package/src/repl/agent-repl.js +2175 -146
- package/src/repl/btw-command.js +93 -10
- package/src/repl/clipboard-image.js +119 -0
- package/src/repl/config-summary.js +64 -108
- package/src/repl/prompt-editor.js +233 -0
- package/src/repl/prompt-interactions.js +344 -0
- package/src/repl/prompt-stash.js +354 -0
- package/src/repl/prompt-suggestions.js +312 -0
- package/src/repl/repl-keybindings.js +227 -0
- package/src/repl/session-recap.js +217 -0
- package/src/repl/slash-command-registry.js +22 -0
- package/src/repl/terminal-layout.js +88 -0
- package/src/runtime/agent-core.js +1630 -447
- package/src/runtime/coding-agent-contract-shared.cjs +13 -1
- package/src/runtime/coding-agent-managed-tool-policy.cjs +7 -2
- package/src/runtime/diagnostics.js +32 -13
- package/src/runtime/headless-runner.js +310 -118
- package/src/runtime/headless-stream.js +356 -95
- package/src/runtime/mcp-config.js +148 -14
- package/src/runtime/policies/agent-policy.js +14 -0
- package/src/runtime/status-diagnostics-lite.js +137 -0
- package/src/assets/web-panel/assets/MarkdownRenderer-7iWGwZ-r.js +0 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-BU2Yqq5H.js +0 -1
- package/src/assets/web-panel/assets/PdhVaultBrowser-69ca_WeR.js +0 -7
- package/src/assets/web-panel/assets/devWarning-B4dXIJqD.js +0 -1
- package/src/assets/web-panel/assets/index-C-C7DaG6.js +0 -1
- package/src/assets/web-panel/assets/index-DkfWzWtd.js +0 -1
package/src/lib/agent-core.js
CHANGED
|
@@ -50,9 +50,11 @@ export {
|
|
|
50
50
|
_anthropicThinkingParams,
|
|
51
51
|
_normalizeAnthropicResponse,
|
|
52
52
|
_resetFileFreshness,
|
|
53
|
+
_withPostEditDiagnostics,
|
|
53
54
|
_getSharedCodeIntel,
|
|
54
55
|
disposeSharedCodeIntel,
|
|
55
56
|
emitToolHookLifecycle,
|
|
56
57
|
emitToolBatchHookLifecycle,
|
|
58
|
+
buildSubAgentHandoffContext,
|
|
57
59
|
_resetSubtreeInstructionLoaders,
|
|
58
60
|
} from "../runtime/agent-core.js";
|
package/src/lib/agent-sandbox.js
CHANGED
|
@@ -5,6 +5,11 @@ import { proxyEnv } from "./sandbox-egress-proxy.js";
|
|
|
5
5
|
import executionBroker from "./process-execution-broker/index.js";
|
|
6
6
|
|
|
7
7
|
export const DEFAULT_SANDBOX_IMAGE = "node:22-bookworm-slim";
|
|
8
|
+
export const AGENT_SANDBOX_MODES = Object.freeze([
|
|
9
|
+
"off",
|
|
10
|
+
"workspace-write",
|
|
11
|
+
"strict",
|
|
12
|
+
]);
|
|
8
13
|
export const _deps = {
|
|
9
14
|
spawnSync: (...args) => executionBroker.spawnSync(...args),
|
|
10
15
|
};
|
|
@@ -82,8 +87,7 @@ function pathIsWithin(candidate, root) {
|
|
|
82
87
|
}
|
|
83
88
|
|
|
84
89
|
function normalizeWorkspaceRoots(entries, cwd) {
|
|
85
|
-
const roots =
|
|
86
|
-
Array.isArray(entries) && entries.length > 0 ? entries : [cwd];
|
|
90
|
+
const roots = Array.isArray(entries) && entries.length > 0 ? entries : [cwd];
|
|
87
91
|
return stringList(roots).map((entry) => path.resolve(cwd, entry));
|
|
88
92
|
}
|
|
89
93
|
|
|
@@ -142,9 +146,7 @@ export function resolveSandboxPolicyPath(
|
|
|
142
146
|
? normalizedPolicy.allowWrite
|
|
143
147
|
: normalizedPolicy.allowRead;
|
|
144
148
|
const policyDenies =
|
|
145
|
-
access === "write"
|
|
146
|
-
? normalizedPolicy.denyWrite
|
|
147
|
-
: normalizedPolicy.denyRead;
|
|
149
|
+
access === "write" ? normalizedPolicy.denyWrite : normalizedPolicy.denyRead;
|
|
148
150
|
const allowedInputs = [
|
|
149
151
|
...normalizeWorkspaceRoots(workspaceRoots, resolvedCwd),
|
|
150
152
|
...resolvePolicyPaths(policyAllows, resolvedCwd),
|
|
@@ -208,18 +210,112 @@ export function normalizeSandboxPolicy(settings = {}, cwd = process.cwd()) {
|
|
|
208
210
|
|
|
209
211
|
export function normalizeAgentSandbox(value, options = {}) {
|
|
210
212
|
const settings = options.settings || {};
|
|
211
|
-
|
|
212
|
-
|
|
213
|
+
const policyRequiresSandbox =
|
|
214
|
+
settings.requireSandbox === true ||
|
|
215
|
+
settings.allowUnsandboxedCommands === false;
|
|
216
|
+
if (!value && settings.enabled !== true && !policyRequiresSandbox)
|
|
217
|
+
return null;
|
|
218
|
+
if (value === false || settings.enabled === false) {
|
|
219
|
+
if (policyRequiresSandbox) {
|
|
220
|
+
const error = new Error(
|
|
221
|
+
"Sandbox disablement is prohibited by effective sandbox policy",
|
|
222
|
+
);
|
|
223
|
+
error.code = "CONFIG_SANDBOX_OFF_PROHIBITED";
|
|
224
|
+
throw error;
|
|
225
|
+
}
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
const effectiveSettings = policyRequiresSandbox
|
|
229
|
+
? {
|
|
230
|
+
...settings,
|
|
231
|
+
enabled: true,
|
|
232
|
+
failIfUnavailable: true,
|
|
233
|
+
allowUnsandboxedCommands: false,
|
|
234
|
+
}
|
|
235
|
+
: settings;
|
|
236
|
+
const managedNetworkDisabled = options.managedSettings?.network === false;
|
|
213
237
|
const image =
|
|
214
238
|
typeof value === "string" && value.trim() && value !== "true"
|
|
215
239
|
? value.trim()
|
|
216
240
|
: DEFAULT_SANDBOX_IMAGE;
|
|
217
241
|
return {
|
|
218
|
-
engine:
|
|
219
|
-
image:
|
|
242
|
+
engine: effectiveSettings.engine || "docker",
|
|
243
|
+
image: effectiveSettings.image || image,
|
|
220
244
|
cwd: path.resolve(options.cwd || process.cwd()),
|
|
221
|
-
network:
|
|
222
|
-
|
|
245
|
+
network: managedNetworkDisabled
|
|
246
|
+
? false
|
|
247
|
+
: options.network === true || effectiveSettings.network === true,
|
|
248
|
+
policy: normalizeSandboxPolicy(
|
|
249
|
+
effectiveSettings,
|
|
250
|
+
options.cwd || process.cwd(),
|
|
251
|
+
),
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Resolve the explicit public sandbox posture. Both isolation modes fail
|
|
257
|
+
* closed when the selected engine is unavailable; `strict` additionally
|
|
258
|
+
* forbids per-command unsandboxed escape hatches and network access.
|
|
259
|
+
*/
|
|
260
|
+
export function normalizeAgentSandboxMode(mode, value, options = {}) {
|
|
261
|
+
if (mode == null || mode === "") {
|
|
262
|
+
return normalizeAgentSandbox(value, options);
|
|
263
|
+
}
|
|
264
|
+
if (!AGENT_SANDBOX_MODES.includes(mode)) {
|
|
265
|
+
const error = new Error(
|
|
266
|
+
`Invalid sandbox mode "${mode}"; expected off, workspace-write, or strict`,
|
|
267
|
+
);
|
|
268
|
+
error.code = "CONFIG_SANDBOX_MODE_INVALID";
|
|
269
|
+
throw error;
|
|
270
|
+
}
|
|
271
|
+
const settings = { ...(options.settings || {}) };
|
|
272
|
+
if (mode === "off") {
|
|
273
|
+
const managedSettings = options.managedSettings || {};
|
|
274
|
+
if (
|
|
275
|
+
managedSettings.enabled === true ||
|
|
276
|
+
managedSettings.requireSandbox === true ||
|
|
277
|
+
managedSettings.allowUnsandboxedCommands === false ||
|
|
278
|
+
settings.requireSandbox === true ||
|
|
279
|
+
settings.allowUnsandboxedCommands === false
|
|
280
|
+
) {
|
|
281
|
+
const error = new Error(
|
|
282
|
+
"Sandbox mode off is prohibited by managed/effective sandbox policy",
|
|
283
|
+
);
|
|
284
|
+
error.code = "CONFIG_SANDBOX_OFF_PROHIBITED";
|
|
285
|
+
throw error;
|
|
286
|
+
}
|
|
287
|
+
return null;
|
|
288
|
+
}
|
|
289
|
+
settings.enabled = true;
|
|
290
|
+
settings.failIfUnavailable = true;
|
|
291
|
+
settings.allowUnsandboxedCommands = false;
|
|
292
|
+
if (mode === "strict") {
|
|
293
|
+
settings.network = false;
|
|
294
|
+
}
|
|
295
|
+
const sandbox = normalizeAgentSandbox(value || true, {
|
|
296
|
+
...options,
|
|
297
|
+
network: mode === "strict" ? false : options.network,
|
|
298
|
+
settings,
|
|
299
|
+
});
|
|
300
|
+
sandbox.mode = mode;
|
|
301
|
+
return sandbox;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Clamp an already-enabled sandbox to fail closed for safety-oriented run
|
|
306
|
+
* modes. This never turns isolation on implicitly; it only prevents a selected
|
|
307
|
+
* sandbox from degrading to bare host execution when its engine is missing.
|
|
308
|
+
*/
|
|
309
|
+
export function enforceSandboxFailClosed(sandbox, reason = "safe") {
|
|
310
|
+
if (!sandbox) return null;
|
|
311
|
+
return {
|
|
312
|
+
...sandbox,
|
|
313
|
+
failClosedReason: reason,
|
|
314
|
+
policy: {
|
|
315
|
+
...(sandbox.policy || {}),
|
|
316
|
+
allowUnsandboxedCommands: false,
|
|
317
|
+
failIfUnavailable: true,
|
|
318
|
+
},
|
|
223
319
|
};
|
|
224
320
|
}
|
|
225
321
|
|
|
@@ -229,21 +325,19 @@ export function executeSandboxedShell(command, sandbox, options = {}) {
|
|
|
229
325
|
}
|
|
230
326
|
const hostCwd = path.resolve(options.cwd || sandbox.cwd);
|
|
231
327
|
const policy = sandbox.policy || normalizeSandboxPolicy({}, hostCwd);
|
|
232
|
-
//
|
|
233
|
-
//
|
|
234
|
-
//
|
|
235
|
-
//
|
|
236
|
-
// rather than grant unrestricted access.
|
|
328
|
+
// Proxy environment variables are advisory: a child can clear them or open a
|
|
329
|
+
// raw socket. Until a backend can enforce egress below the process layer,
|
|
330
|
+
// domain-restricted networking must fail closed instead of granting the
|
|
331
|
+
// sandbox an unrestricted network namespace.
|
|
237
332
|
const egress = options.egressProxy || null;
|
|
238
333
|
if (
|
|
239
334
|
(policy.allowedDomains.length || policy.deniedDomains.length) &&
|
|
240
|
-
sandbox.network
|
|
241
|
-
!egress
|
|
335
|
+
sandbox.network
|
|
242
336
|
) {
|
|
243
337
|
return {
|
|
244
338
|
stdout: "",
|
|
245
339
|
stderr:
|
|
246
|
-
"Domain-restricted sandbox networking
|
|
340
|
+
"Domain-restricted sandbox networking has no non-bypassable backend enforcement; refusing unrestricted network access",
|
|
247
341
|
exitCode: 1,
|
|
248
342
|
failedToStart: true,
|
|
249
343
|
};
|
|
@@ -272,10 +366,8 @@ export function executeSandboxedShell(command, sandbox, options = {}) {
|
|
|
272
366
|
if (process.platform !== "win32" && process.getuid && process.getgid) {
|
|
273
367
|
args.push("--user", `${process.getuid()}:${process.getgid()}`);
|
|
274
368
|
}
|
|
275
|
-
//
|
|
276
|
-
//
|
|
277
|
-
// gateway on Linux via host-gateway); the caller builds `egress.env` with that
|
|
278
|
-
// hostname (proxyEnv(port, "host.docker.internal")).
|
|
369
|
+
// Proxy variables remain useful for unrestricted networking, but are not a
|
|
370
|
+
// security boundary. Domain-restricted requests have already failed closed.
|
|
279
371
|
if (egress && egress.port && sandbox.network) {
|
|
280
372
|
args.push("--add-host", "host.docker.internal:host-gateway");
|
|
281
373
|
const penv = proxyEnv(egress.port, "host.docker.internal");
|
|
@@ -348,8 +440,8 @@ function executeBubblewrapShell(command, sandbox, options, hostCwd, policy) {
|
|
|
348
440
|
for (const target of policy.denyWrite) args.push("--ro-bind", target, target);
|
|
349
441
|
for (const target of policy.denyRead) args.push("--tmpfs", target);
|
|
350
442
|
args.push("--", "sh", "-lc", String(command || ""));
|
|
351
|
-
// bwrap `--share-net` shares the host network namespace
|
|
352
|
-
//
|
|
443
|
+
// bwrap `--share-net` shares the host network namespace. Proxy variables are
|
|
444
|
+
// convenience only; domain-restricted requests have already failed closed.
|
|
353
445
|
const egress = options.egressProxy || null;
|
|
354
446
|
const bwrapEnv =
|
|
355
447
|
egress && egress.port && sandbox.network
|
|
@@ -459,7 +551,7 @@ export function assertSandboxAvailable(sandbox, deps = _deps) {
|
|
|
459
551
|
|
|
460
552
|
export function sandboxSummary(sandbox) {
|
|
461
553
|
if (!sandbox) return null;
|
|
462
|
-
|
|
554
|
+
const summary = {
|
|
463
555
|
engine: sandbox.engine,
|
|
464
556
|
image: sandbox.image,
|
|
465
557
|
isolationLevel: isolationLevel(sandbox),
|
|
@@ -474,4 +566,6 @@ export function sandboxSummary(sandbox) {
|
|
|
474
566
|
failIfUnavailable: sandbox.policy?.failIfUnavailable === true,
|
|
475
567
|
},
|
|
476
568
|
};
|
|
569
|
+
if (sandbox.mode) summary.mode = sandbox.mode;
|
|
570
|
+
return summary;
|
|
477
571
|
}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* Pure function over the event list (see jsonl-session-store.js appendEvent):
|
|
8
8
|
* { type, timestamp, data }
|
|
9
9
|
* types: session_start{title,provider,model} · user_message · assistant_message
|
|
10
|
+
* · ws_turn{requestId,user,assistant,outcome}
|
|
10
11
|
* · system · tool_call{tool,args} · tool_result{tool,result}
|
|
11
12
|
* · compact(stats) · token_usage{...}
|
|
12
13
|
*/
|
|
@@ -76,6 +77,25 @@ export function renderAgentSessionMarkdown(sessionId, events, opts = {}) {
|
|
|
76
77
|
L.push(asText(ev.data?.content));
|
|
77
78
|
L.push("");
|
|
78
79
|
break;
|
|
80
|
+
case "ws_turn":
|
|
81
|
+
if (
|
|
82
|
+
ev.data?.schemaVersion === 1 &&
|
|
83
|
+
ev.data?.outcome === "completed" &&
|
|
84
|
+
ev.data?.user?.role === "user" &&
|
|
85
|
+
ev.data?.assistant?.role === "assistant"
|
|
86
|
+
) {
|
|
87
|
+
users += 1;
|
|
88
|
+
assistants += 1;
|
|
89
|
+
L.push("## 👤 User");
|
|
90
|
+
L.push("");
|
|
91
|
+
L.push(asText(ev.data.user.content));
|
|
92
|
+
L.push("");
|
|
93
|
+
L.push("## 🤖 Assistant");
|
|
94
|
+
L.push("");
|
|
95
|
+
L.push(asText(ev.data.assistant.content));
|
|
96
|
+
L.push("");
|
|
97
|
+
}
|
|
98
|
+
break;
|
|
79
99
|
case "system":
|
|
80
100
|
L.push("## ⚙ System");
|
|
81
101
|
L.push("");
|
|
@@ -28,6 +28,11 @@ import { 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 ADJUDICATION_DECISIONS = Object.freeze({
|
|
32
|
+
RETRY: "retry",
|
|
33
|
+
ACCEPT: "accept",
|
|
34
|
+
CANCEL: "cancel",
|
|
35
|
+
});
|
|
31
36
|
|
|
32
37
|
export class TaskLeaseRegistry {
|
|
33
38
|
constructor({
|
|
@@ -423,7 +428,14 @@ export class TaskLeaseRegistry {
|
|
|
423
428
|
*/
|
|
424
429
|
fail(
|
|
425
430
|
key,
|
|
426
|
-
{
|
|
431
|
+
{
|
|
432
|
+
holder,
|
|
433
|
+
leaseId,
|
|
434
|
+
error = null,
|
|
435
|
+
retryable = true,
|
|
436
|
+
adjudication = null,
|
|
437
|
+
now = this._now(),
|
|
438
|
+
} = {},
|
|
427
439
|
) {
|
|
428
440
|
const id = this._byKey.get(key);
|
|
429
441
|
const task = id ? this._tasks.get(id) : null;
|
|
@@ -434,6 +446,23 @@ export class TaskLeaseRegistry {
|
|
|
434
446
|
}
|
|
435
447
|
const attempts = (task.metadata?.attempts || 0) + 1;
|
|
436
448
|
const willRetry = retryable !== false && attempts < this.maxAttempts;
|
|
449
|
+
const adjudicationRequest =
|
|
450
|
+
!willRetry && adjudication && typeof adjudication === "object"
|
|
451
|
+
? {
|
|
452
|
+
required: true,
|
|
453
|
+
code:
|
|
454
|
+
adjudication.code ||
|
|
455
|
+
"TEAM_TASK_SIDE_EFFECT_ADJUDICATION_REQUIRED",
|
|
456
|
+
reason:
|
|
457
|
+
adjudication.reason ||
|
|
458
|
+
(error ? String(error) : "task outcome requires adjudication"),
|
|
459
|
+
evidenceDigest: adjudication.evidenceDigest || null,
|
|
460
|
+
requestedAt: Number.isFinite(adjudication.requestedAt)
|
|
461
|
+
? adjudication.requestedAt
|
|
462
|
+
: now,
|
|
463
|
+
decision: null,
|
|
464
|
+
}
|
|
465
|
+
: task.metadata?.adjudication || null;
|
|
437
466
|
const ok = this._write(task, {
|
|
438
467
|
status: willRetry ? TASK_STATUS.PENDING : TASK_STATUS.CANCELLED,
|
|
439
468
|
assignee: null,
|
|
@@ -442,6 +471,7 @@ export class TaskLeaseRegistry {
|
|
|
442
471
|
lease: null,
|
|
443
472
|
attempts,
|
|
444
473
|
lastError: error ? String(error) : null,
|
|
474
|
+
...(adjudicationRequest ? { adjudication: adjudicationRequest } : {}),
|
|
445
475
|
},
|
|
446
476
|
});
|
|
447
477
|
if (!ok) return { ok: false, reason: "concurrent" };
|
|
@@ -529,6 +559,14 @@ export class TaskLeaseRegistry {
|
|
|
529
559
|
if (!candidate.retry) {
|
|
530
560
|
metadata.attempts = (fresh.metadata?.attempts || 0) + 1;
|
|
531
561
|
metadata.lastError = String(error);
|
|
562
|
+
metadata.adjudication = {
|
|
563
|
+
required: true,
|
|
564
|
+
code: "TEAM_TASK_ABANDONED_ADJUDICATION_REQUIRED",
|
|
565
|
+
reason: String(error),
|
|
566
|
+
evidenceDigest: null,
|
|
567
|
+
requestedAt: this._now(),
|
|
568
|
+
decision: null,
|
|
569
|
+
};
|
|
532
570
|
}
|
|
533
571
|
if (
|
|
534
572
|
this._write(fresh, {
|
|
@@ -550,6 +588,234 @@ export class TaskLeaseRegistry {
|
|
|
550
588
|
return { reclaimed, adjudicationRequired };
|
|
551
589
|
}
|
|
552
590
|
|
|
591
|
+
/**
|
|
592
|
+
* Resolve a fail-closed task after a durable human decision has been
|
|
593
|
+
* authenticated by the adjudication log.
|
|
594
|
+
*
|
|
595
|
+
* This is deliberately the only TaskLeaseRegistry operation allowed to move
|
|
596
|
+
* a CANCELLED task out of a terminal state. The generic SharedTaskList keeps
|
|
597
|
+
* its terminal-state invariant; this method performs a compare-by-revision
|
|
598
|
+
* replacement and records the exceptional transition in task history.
|
|
599
|
+
*/
|
|
600
|
+
resolveAdjudication(
|
|
601
|
+
key,
|
|
602
|
+
{
|
|
603
|
+
decision,
|
|
604
|
+
decisionId,
|
|
605
|
+
actor = "human",
|
|
606
|
+
reason = null,
|
|
607
|
+
evidenceDigest = null,
|
|
608
|
+
result = null,
|
|
609
|
+
now = this._now(),
|
|
610
|
+
} = {},
|
|
611
|
+
) {
|
|
612
|
+
const allowed = new Set(Object.values(ADJUDICATION_DECISIONS));
|
|
613
|
+
if (!allowed.has(decision)) {
|
|
614
|
+
return { ok: false, reason: "invalid_decision" };
|
|
615
|
+
}
|
|
616
|
+
if (!decisionId || typeof decisionId !== "string") {
|
|
617
|
+
return { ok: false, reason: "decision_id_required" };
|
|
618
|
+
}
|
|
619
|
+
const id = this._byKey.get(key);
|
|
620
|
+
const task = id ? this._tasks.get(id) : null;
|
|
621
|
+
if (!task) return { ok: false, reason: "not_found" };
|
|
622
|
+
const pending = task.metadata?.adjudication || null;
|
|
623
|
+
if (pending?.required !== true) {
|
|
624
|
+
const prior = pending?.decision || null;
|
|
625
|
+
if (prior?.id === decisionId && prior?.action === decision) {
|
|
626
|
+
return {
|
|
627
|
+
ok: true,
|
|
628
|
+
idempotent: true,
|
|
629
|
+
decision,
|
|
630
|
+
status: task.status,
|
|
631
|
+
};
|
|
632
|
+
}
|
|
633
|
+
return { ok: false, reason: "adjudication_not_required" };
|
|
634
|
+
}
|
|
635
|
+
if (task.status !== TASK_STATUS.CANCELLED) {
|
|
636
|
+
return { ok: false, reason: "invalid_task_state" };
|
|
637
|
+
}
|
|
638
|
+
if (pending.evidenceDigest && pending.evidenceDigest !== evidenceDigest) {
|
|
639
|
+
return { ok: false, reason: "evidence_mismatch" };
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
const status =
|
|
643
|
+
decision === ADJUDICATION_DECISIONS.RETRY
|
|
644
|
+
? TASK_STATUS.PENDING
|
|
645
|
+
: decision === ADJUDICATION_DECISIONS.ACCEPT
|
|
646
|
+
? TASK_STATUS.COMPLETED
|
|
647
|
+
: TASK_STATUS.CANCELLED;
|
|
648
|
+
const decidedAt = Number.isFinite(now) ? now : this._now();
|
|
649
|
+
const decisionRecord = {
|
|
650
|
+
id: decisionId,
|
|
651
|
+
action: decision,
|
|
652
|
+
actor: actor ? String(actor) : "human",
|
|
653
|
+
reason: reason == null ? null : String(reason),
|
|
654
|
+
evidenceDigest: evidenceDigest || pending.evidenceDigest || null,
|
|
655
|
+
decidedAt,
|
|
656
|
+
};
|
|
657
|
+
const snapshot = this._tasks.snapshot();
|
|
658
|
+
const stored = snapshot.tasks.find((candidate) => candidate.id === task.id);
|
|
659
|
+
if (!stored || stored.rev !== task.rev) {
|
|
660
|
+
return { ok: false, reason: "concurrent" };
|
|
661
|
+
}
|
|
662
|
+
stored.status = status;
|
|
663
|
+
stored.assignee = null;
|
|
664
|
+
stored.updatedAt = decidedAt;
|
|
665
|
+
stored.rev += 1;
|
|
666
|
+
stored.metadata = {
|
|
667
|
+
...stored.metadata,
|
|
668
|
+
lease: null,
|
|
669
|
+
...(decision === ADJUDICATION_DECISIONS.ACCEPT
|
|
670
|
+
? {
|
|
671
|
+
result: result ?? {
|
|
672
|
+
adjudicated: true,
|
|
673
|
+
decisionId,
|
|
674
|
+
},
|
|
675
|
+
}
|
|
676
|
+
: {}),
|
|
677
|
+
adjudication: {
|
|
678
|
+
...pending,
|
|
679
|
+
required: false,
|
|
680
|
+
decision: decisionRecord,
|
|
681
|
+
},
|
|
682
|
+
};
|
|
683
|
+
stored.history = [
|
|
684
|
+
...(stored.history || []),
|
|
685
|
+
{
|
|
686
|
+
ts: decidedAt,
|
|
687
|
+
actor: decisionRecord.actor,
|
|
688
|
+
action: "adjudicated",
|
|
689
|
+
changes: ["status", "assignee", "metadata"],
|
|
690
|
+
decision: decisionRecord.action,
|
|
691
|
+
decisionId,
|
|
692
|
+
},
|
|
693
|
+
];
|
|
694
|
+
this._tasks = SharedTaskList.restore(snapshot, { now: this._now });
|
|
695
|
+
this._rebuildIndexes();
|
|
696
|
+
if (status === TASK_STATUS.PENDING) {
|
|
697
|
+
this._enqueueIfReady(key, decidedAt);
|
|
698
|
+
} else if (status === TASK_STATUS.COMPLETED) {
|
|
699
|
+
for (const dependent of this._dependentsByKey.get(key) || []) {
|
|
700
|
+
this._enqueueIfReady(dependent, decidedAt);
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
return { ok: true, decision, status };
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
/**
|
|
707
|
+
* Force any recovery-ambiguous task into the fail-closed adjudication state.
|
|
708
|
+
* This exceptional transition is used only when durable collaboration
|
|
709
|
+
* evidence contradicts or weakens the registry snapshot.
|
|
710
|
+
*/
|
|
711
|
+
requireAdjudication(
|
|
712
|
+
key,
|
|
713
|
+
{
|
|
714
|
+
code = "TEAM_TASK_SIDE_EFFECT_ADJUDICATION_REQUIRED",
|
|
715
|
+
reason = "task outcome requires adjudication",
|
|
716
|
+
evidenceDigest = null,
|
|
717
|
+
now = this._now(),
|
|
718
|
+
} = {},
|
|
719
|
+
) {
|
|
720
|
+
const id = this._byKey.get(key);
|
|
721
|
+
const task = id ? this._tasks.get(id) : null;
|
|
722
|
+
if (!task) return { ok: false, reason: "not_found" };
|
|
723
|
+
if (task.metadata?.adjudication?.required === true) {
|
|
724
|
+
return { ok: true, idempotent: true };
|
|
725
|
+
}
|
|
726
|
+
const snapshot = this._tasks.snapshot();
|
|
727
|
+
const stored = snapshot.tasks.find((candidate) => candidate.id === task.id);
|
|
728
|
+
if (!stored || stored.rev !== task.rev) {
|
|
729
|
+
return { ok: false, reason: "concurrent" };
|
|
730
|
+
}
|
|
731
|
+
const requestedAt = Number.isFinite(now) ? now : this._now();
|
|
732
|
+
const priorStatus = stored.status;
|
|
733
|
+
stored.status = TASK_STATUS.CANCELLED;
|
|
734
|
+
stored.assignee = null;
|
|
735
|
+
stored.updatedAt = requestedAt;
|
|
736
|
+
stored.rev += 1;
|
|
737
|
+
stored.metadata = {
|
|
738
|
+
...stored.metadata,
|
|
739
|
+
lease: null,
|
|
740
|
+
lastError: String(reason),
|
|
741
|
+
adjudication: {
|
|
742
|
+
required: true,
|
|
743
|
+
code: String(code),
|
|
744
|
+
reason: String(reason),
|
|
745
|
+
evidenceDigest: evidenceDigest || null,
|
|
746
|
+
requestedAt,
|
|
747
|
+
priorStatus,
|
|
748
|
+
decision: null,
|
|
749
|
+
},
|
|
750
|
+
};
|
|
751
|
+
stored.history = [
|
|
752
|
+
...(stored.history || []),
|
|
753
|
+
{
|
|
754
|
+
ts: requestedAt,
|
|
755
|
+
actor: "recovery",
|
|
756
|
+
action: "adjudication-required",
|
|
757
|
+
changes: ["status", "assignee", "metadata"],
|
|
758
|
+
},
|
|
759
|
+
];
|
|
760
|
+
this._tasks = SharedTaskList.restore(snapshot, { now: this._now });
|
|
761
|
+
this._rebuildIndexes();
|
|
762
|
+
return { ok: true, priorStatus };
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
/** Bind a pending adjudication to its immutable durable case evidence. */
|
|
766
|
+
bindAdjudicationCase(key, { caseId, registryDigest, sideEffectDigest } = {}) {
|
|
767
|
+
const id = this._byKey.get(key);
|
|
768
|
+
const task = id ? this._tasks.get(id) : null;
|
|
769
|
+
if (!task) return { ok: false, reason: "not_found" };
|
|
770
|
+
const adjudication = task.metadata?.adjudication || null;
|
|
771
|
+
if (adjudication?.required !== true) {
|
|
772
|
+
return { ok: false, reason: "adjudication_not_required" };
|
|
773
|
+
}
|
|
774
|
+
for (const [name, value] of Object.entries({
|
|
775
|
+
caseId,
|
|
776
|
+
registryDigest,
|
|
777
|
+
sideEffectDigest,
|
|
778
|
+
})) {
|
|
779
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
780
|
+
return { ok: false, reason: `${name}_required` };
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
const current = adjudication.case || null;
|
|
784
|
+
if (current) {
|
|
785
|
+
if (
|
|
786
|
+
current.caseId === caseId &&
|
|
787
|
+
current.registryDigest === registryDigest &&
|
|
788
|
+
current.sideEffectDigest === sideEffectDigest
|
|
789
|
+
) {
|
|
790
|
+
return { ok: true, idempotent: true, case: { ...current } };
|
|
791
|
+
}
|
|
792
|
+
return { ok: false, reason: "case_binding_conflict" };
|
|
793
|
+
}
|
|
794
|
+
const binding = { caseId, registryDigest, sideEffectDigest };
|
|
795
|
+
const ok = this._write(task, {
|
|
796
|
+
metadata: {
|
|
797
|
+
...task.metadata,
|
|
798
|
+
adjudication: {
|
|
799
|
+
...adjudication,
|
|
800
|
+
case: binding,
|
|
801
|
+
},
|
|
802
|
+
},
|
|
803
|
+
});
|
|
804
|
+
return ok
|
|
805
|
+
? { ok: true, case: { ...binding } }
|
|
806
|
+
: { ok: false, reason: "concurrent" };
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
pendingAdjudications() {
|
|
810
|
+
return this.list()
|
|
811
|
+
.filter((task) => task.metadata?.adjudication?.required === true)
|
|
812
|
+
.map((task) => ({
|
|
813
|
+
key: task.key,
|
|
814
|
+
status: task.status,
|
|
815
|
+
...task.metadata.adjudication,
|
|
816
|
+
}));
|
|
817
|
+
}
|
|
818
|
+
|
|
553
819
|
stats({ now = this._now() } = {}) {
|
|
554
820
|
const base = this._tasks.stats();
|
|
555
821
|
let leased = 0;
|
|
@@ -566,6 +832,7 @@ export class TaskLeaseRegistry {
|
|
|
566
832
|
leased,
|
|
567
833
|
expiredLeases: expired,
|
|
568
834
|
claimable: this.claimable({ now }).length,
|
|
835
|
+
adjudicationRequired: this.pendingAdjudications().length,
|
|
569
836
|
};
|
|
570
837
|
}
|
|
571
838
|
|
|
@@ -575,8 +842,9 @@ export class TaskLeaseRegistry {
|
|
|
575
842
|
.list()
|
|
576
843
|
.every(
|
|
577
844
|
(t) =>
|
|
578
|
-
t.status === TASK_STATUS.COMPLETED ||
|
|
579
|
-
|
|
845
|
+
(t.status === TASK_STATUS.COMPLETED ||
|
|
846
|
+
t.status === TASK_STATUS.CANCELLED) &&
|
|
847
|
+
t.metadata?.adjudication?.required !== true,
|
|
580
848
|
);
|
|
581
849
|
}
|
|
582
850
|
|