chainlesschain 0.163.7 → 0.164.0
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/package.json +5 -1
- package/scripts/macos-mcp-launcher-build.mjs +317 -0
- package/scripts/macos-mcp-launcher-postinstall.sh +54 -0
- package/scripts/macos-mcp-launcher-preinstall.sh +61 -0
- package/src/assets/web-panel/assets/{AIOps-axqQfwv8.js → AIOps-D2MEn7fI.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-DV-Ro0By.js → ActionButton-lCW_4Gf0.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-Bt72WEVu.js → Analytics-Bs7i-nsS.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-BtepG55E.js → AppLayout-CK7B6S_j.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-B7KaJ7S_.js → Artifacts-C8ILjpyo.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-FNFaUg7A.js → Audit-Bb9cNaWc.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-DFb6J2wQ.js → BackgroundAgents-sC9ooXIf.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-CC7YBhyj.js → Backup-D-DrsplT.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-RkgTNVtj.js → BaseInput-uCNZpwSK.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-hHEmGZy-.js → Chat-CsDK1uE9.js} +6 -6
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-CAP9YhHv.js → ChatBubbleRenderer-OqSDt50w.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-z5wXOQP1.js → Checkbox-JhTXM1-K.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-DVaDJnxy.js → Codegen-BbzZLnyD.js} +1 -1
- package/src/assets/web-panel/assets/{Col-CJmaRDR5.js → Col-D4VW4m4j.js} +1 -1
- package/src/assets/web-panel/assets/{Community-DF29_2bI.js → Community-BXrYawxV.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-DtkQkBzn.js → Compact-DCihGy1u.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-xoHDxp7I.js → Compliance-DlyZ-lk8.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-BUm-R7ht.js → Cowork-DvGZrhbO.js} +2 -2
- package/src/assets/web-panel/assets/{Cron-Cgl14ZkB.js → Cron-DUncZi8h.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-BNcbmoqh.js → Crosschain-C_hLuUcm.js} +1 -1
- package/src/assets/web-panel/assets/{DID-Bwja0Zo9.js → DID-b6YSUqxr.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-Bk5XjEdJ.js → Dashboard-uvM15Cfb.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-Ci36Oitq.js → Dropdown-D1-Nd4qY.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer--U04ZN4q.js → EmailListRenderer-8ApvL6Zc.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-B2gNPR2s.js → FamilyGuardDashboard-LYJt8811.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-C4KghYn7.js → Federation-BbI3HGpv.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-QL7x_Q_0.js → FormItemContext-DSoEKuFu.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-F3Ryltwm.js → GenericCardRenderer-B0S9OWd5.js} +1 -1
- package/src/assets/web-panel/assets/{Git-2HassK5k.js → Git-DIs9Zhf3.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-DoBIp7oe.js → Governance-jzZXrxcl.js} +1 -1
- package/src/assets/web-panel/assets/{Inference--W01QhZ-.js → Inference-JUPjf2ZI.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-DmvwqGpT.js → KnowledgeGraph-DxnfJvlP.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-BBJ4yAel.js → Logs-iXiz8BEE.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-BLCZMzhJ.js → MarkdownRenderer-GmB6DOr6.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-D5lNngSI.js → Marketplace-Y3Xch312.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-CkEVOMKH.js → McpTools-D7kGGbO7.js} +4 -4
- package/src/assets/web-panel/assets/{Memory-B1Ow1xVE.js → Memory-Do_hVxzh.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-SgYbUfb6.js → MobileBridge-CtrR0Tas.js} +1 -1
- package/src/assets/web-panel/assets/MobileProjects-BL0Czcoj.js +1 -0
- package/src/assets/web-panel/assets/{Mtc-DcTXSSma.js → Mtc-qo5QCTGd.js} +2 -2
- package/src/assets/web-panel/assets/{MtcAudit-Dt3WG4oj.js → MtcAudit-cq5mnjYj.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-B9B38UZx.js → Multisig-Bq0MAQHw.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-B0S4GGvG.js → NLProgramming-DdWE6Vi2.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-DZ5U58Ng.js → Notes-BxMBFcIp.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-PjL5ZW34.js → NotificationSettings-RTrAcbUe.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-DrAX2ESt.js → OrderTableRenderer-DJbpGqzT.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-Cv1GYs-c.js → Organization-SQzIPdqC.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-Bbkp_PL3.js → Overflow-02yECh22.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-BD8QUgoZ.js → P2P-BNg4pNCM.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-BO-2PeaB.js → PdhVaultBrowser-BxPJZsD3.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-D_OPVa02.js → Permissions-CLnDnPAz.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-mh-pEmaB.js → PersonalDataHub-C5m0AjGf.js} +4 -4
- package/src/assets/web-panel/assets/{Pipeline-6JC2EDdb.js → Pipeline-VwOf5Dhv.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-CUshzUAG.js → Privacy-CC0W2hZd.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-Cs2Aalri.js → ProjectInit-Dz893Bob.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-1ak49tcj.js → ProjectSettings-CxQkvl0k.js} +2 -2
- package/src/assets/web-panel/assets/Projects-DDAjkUkT.js +1 -0
- package/src/assets/web-panel/assets/{Providers-CXXxvafH.js → Providers-DeB9IkxK.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-PTcDsF58.js → QrScannerModal-OCeoaswn.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-CDwucrJw.js → QuickAsk-DenotaAj.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-CJlLVRXR.js → Recommend-Cies_jjI.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-DlN-ETsO.js → RemoteSession-Dxzl5n2T.js} +3 -3
- package/src/assets/web-panel/assets/{Reputation-DI23LR6m.js → Reputation-CW0mvxgZ.js} +1 -1
- package/src/assets/web-panel/assets/{Row-Cl7UQMrM.js → Row-SEd32qZU.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-CexHNfh8.js → RssFeed-BSwnJ3Lm.js} +3 -3
- package/src/assets/web-panel/assets/{Search-BneBWvRN.js → Search-xe2m8bkC.js} +1 -1
- package/src/assets/web-panel/assets/{Security-DX7Phgrp.js → Security-Mq2F9Nro.js} +4 -4
- package/src/assets/web-panel/assets/{Services-BWXO8Mte.js → Services-BKGw2V3P.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-DCyOjKPJ.js → Skeleton-DW95-Rxf.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-CXqERsTB.js → Skills-CHgChCv_.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-bhbrbz8E.js → Sla-tKh6k3R7.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-3IPU0HBZ.js → SpeechSettings-D6UL3dA5.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-DBNTQLbM.js → SyncSettings-D0Fw8fVL.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-quP0bkN-.js → Tasks-20x1GB3D.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-BouWmgho.js → Templates-DJ-lts-a.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-qv0D9s7z.js → Tenant-BFdGpbs7.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-BxvbE8BB.js → Terminal-Xpx61vHL.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-D-IeLnJ2.js → TimelineRenderer-C6UIvyZQ.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-CFMKKyVG.js → Tokens-Dellq08f.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-L8as3UuJ.js → Trigger-VKw8d0J-.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-MxmA4VZG.js → Trust-DNftdKT5.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-C0VvJYRi.js → UkeySign-DX9VAKJI.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-Bf5QZj8N.js → VideoEditing-B2h3jO8q.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-BIJ9riRz.js → Wallet-CjGkof7f.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-B8p9Mhkw.js → WebAuthn-2Zfcu55P.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-BVsuaPen.js → WorkflowEditor-B9eZ8UxZ.js} +1 -1
- package/src/assets/web-panel/assets/{chat-BfkjoKpV.js → chat-CQNfD-YO.js} +1 -1
- package/src/assets/web-panel/assets/{colors-DeAlsWK8.js → colors-D4usyFT2.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-Cs97bz5j.js → compact-item-s4TpjvjX.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-BqbG60LH.js → createContext-BRCSvYxj.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-DKJjSWRn.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-i_RY0b1X.js → hasIn-AdkUbkV-.js} +1 -1
- package/src/assets/web-panel/assets/{index-BOVkf1K3.js → index--00U6vXZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-B-3tEpTc.js → index-B2V-eKfK.js} +1 -1
- package/src/assets/web-panel/assets/{index-D2B4VPyP.js → index-B4JJCfQ2.js} +1 -1
- package/src/assets/web-panel/assets/{index-BkBi5TmC.js → index-BIoG5yYf.js} +1 -1
- package/src/assets/web-panel/assets/{index-79V_zv1s.js → index-BMcimU-2.js} +1 -1
- package/src/assets/web-panel/assets/{index-U4f5izHz.js → index-BPhkFZ1I.js} +1 -1
- package/src/assets/web-panel/assets/{index-DiSkx4UB.js → index-BQ3DXBtD.js} +3 -3
- package/src/assets/web-panel/assets/{index-dIHr4B_u.js → index-Bad4VNvz.js} +1 -1
- package/src/assets/web-panel/assets/{index-CIG8fQ2_.js → index-BgiXR_-_.js} +1 -1
- package/src/assets/web-panel/assets/{index-DqBgBpgp.js → index-BtobShro.js} +1 -1
- package/src/assets/web-panel/assets/{index-ZxO_-E8a.js → index-Bw2MEnUk.js} +1 -1
- package/src/assets/web-panel/assets/{index-DUUrv141.js → index-C1mJtE6q.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bm7lLR4c.js → index-C484EJiS.js} +1 -1
- package/src/assets/web-panel/assets/{index-COdGA-8n.js → index-C5KAQFPQ.js} +1 -1
- package/src/assets/web-panel/assets/index-C61cnl3K.js +1 -0
- package/src/assets/web-panel/assets/{index-CED2PL_y.js → index-C7Y8Aluc.js} +1 -1
- package/src/assets/web-panel/assets/{index-YXgLng0K.js → index-CCsM_Ybx.js} +1 -1
- package/src/assets/web-panel/assets/{index-0-agYlWL.js → index-CJCFe2Qf.js} +1 -1
- package/src/assets/web-panel/assets/{index-B5UkyA3c.js → index-CJVEOa4i.js} +1 -1
- package/src/assets/web-panel/assets/{index-B1CbOH1i.js → index-CJdQrZth.js} +1 -1
- package/src/assets/web-panel/assets/{index-s1opAL-M.js → index-CKC1t3Ic.js} +1 -1
- package/src/assets/web-panel/assets/{index-yObj1O4n.js → index-CQhAVU5t.js} +1 -1
- package/src/assets/web-panel/assets/{index-CgsqdnRV.js → index-CYdoQsa1.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dk7-v4hP.js → index-Cduu2Hhr.js} +1 -1
- package/src/assets/web-panel/assets/{index-B-JVTrpr.js → index-CkwiSLhU.js} +1 -1
- package/src/assets/web-panel/assets/{index-CeWoNHau.js → index-Cvyt-zhm.js} +1 -1
- package/src/assets/web-panel/assets/{index-CE2VtTlp.js → index-D2GjI2oe.js} +1 -1
- package/src/assets/web-panel/assets/index-D4XFHxBr.js +1 -0
- package/src/assets/web-panel/assets/{index-DmbfhJUP.js → index-DARsAyUp.js} +1 -1
- package/src/assets/web-panel/assets/{index-BESLFt4q.js → index-DVKfQ0Ux.js} +1 -1
- package/src/assets/web-panel/assets/{index-PT_5sBMA.js → index-DZT36ZYq.js} +1 -1
- package/src/assets/web-panel/assets/{index-gyFpvL7l.js → index-D_XBHopw.js} +1 -1
- package/src/assets/web-panel/assets/{index-BYUVuwKt.js → index-DdCB70SS.js} +1 -1
- package/src/assets/web-panel/assets/{index-BcUXAB2s.js → index-DzRjHxEv.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dk2qouAz.js → index-MMN9V6JF.js} +1 -1
- package/src/assets/web-panel/assets/{index-D9evtvg2.js → index-RfMr79MW.js} +1 -1
- package/src/assets/web-panel/assets/{index-BuLQobzW.js → index-_IRVsV9X.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cf3WCLmy.js → index-nXyk8GZ9.js} +1 -1
- package/src/assets/web-panel/assets/{index-CG3PRyAL.js → index-s_buFMEG.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-C9h9yKL3.js → initDefaultProps-Blmpk7HL.js} +1 -1
- package/src/assets/web-panel/assets/{motion-BvmLsPdu.js → motion-DPBJMv1n.js} +1 -1
- package/src/assets/web-panel/assets/{move-CoL4ekU1.js → move-ButdzCM7.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-C4pMy6xV.js → mtc-parser-cyRC_QCe.js} +1 -1
- package/src/assets/web-panel/assets/{omit-DPuJfNxx.js → omit-1epSV7hz.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-D0KEeaK2.js → pickAttrs-DuPY8xJs.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-BpkyINxt.js → placementArrow-6XZqarhe.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-DQI_wOq8.js → responsiveObserve-B40pXBWM.js} +1 -1
- package/src/assets/web-panel/assets/{slide-DYfdDiRg.js → slide-jbZ9Wu4n.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-B5dtvb0D.js → statusUtils-BKQQcVy4.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-CF310mSj.js → styleChecker-NiKfWjUT.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-D1Qp4BLp.js → useFlexGapSupport-bQUCvPeb.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-C7_iyvJK.js → useFs-CUGji7ph.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-DZUt_fIm.js → usePersonalDataHub-4veyN2N2.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-D3dsi0lZ.js → vnode-1-nLug-Z.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-WdbOlvdQ.js → zoom-dhCeRDMo.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-help-index.json +6 -6
- package/src/commands/automation.js +103 -1
- package/src/commands/cowork.js +174 -19
- package/src/commands/permissions.js +240 -16
- package/src/commands/plugin.js +1293 -56
- package/src/commands/session-location.js +276 -0
- package/src/commands/session.js +2 -0
- package/src/commands/team-merge-review.js +937 -0
- package/src/commands/team.js +2 -0
- package/src/data/changelog.json +27 -1
- package/src/gateways/ws/action-protocol.js +35 -10
- package/src/gateways/ws/remote-session-protocol.js +24 -1
- package/src/gateways/ws/ws-agent-handler.js +12 -0
- package/src/gateways/ws/ws-server.js +48 -12
- package/src/harness/jsonl-session-store.js +341 -24
- package/src/harness/mcp-client.js +8 -1
- package/src/harness/remote-session-audit.js +1 -0
- package/src/harness/remote-session-crypto.js +210 -2
- package/src/harness/remote-session-registry.js +159 -6
- package/src/harness/session-list-index.js +233 -14
- package/src/lib/agent-authority.js +6 -0
- package/src/lib/agent-schedule-store.js +139 -28
- package/src/lib/agent-team/team-merge-review-store.js +765 -0
- package/src/lib/agent-team/team-merge-review-transaction.js +1223 -0
- package/src/lib/agent-team/team-merge-review.js +1847 -0
- package/src/lib/automation-center-incidents.js +314 -0
- package/src/lib/automation-center-runtime.js +448 -0
- package/src/lib/automation-center.js +182 -38
- package/src/lib/automation-engine.js +41 -0
- package/src/lib/automation-execution-authority.js +241 -12
- package/src/lib/automation-execution-incident.js +737 -0
- package/src/lib/background-agent-keeper-client.js +248 -0
- package/src/lib/background-agent-keeper-protocol.js +147 -0
- package/src/lib/background-agent-supervisor.js +520 -40
- package/src/lib/background-interaction-resolver.js +12 -0
- package/src/lib/background-turn-bootstrap-protocol.js +126 -0
- package/src/lib/cowork-cron.js +85 -14
- package/src/lib/cowork-workflow.js +336 -16
- package/src/lib/dynamic-workflow-facade.js +648 -0
- package/src/lib/execution-location-contract.js +551 -0
- package/src/lib/execution-location-runtime.js +130 -0
- package/src/lib/ide-context.js +94 -6
- package/src/lib/mcp-stdio-package-materialization.js +166 -14
- package/src/lib/packer/pkg-config-generator.js +2 -0
- package/src/lib/permission-authority.js +77 -0
- package/src/lib/permission-side-effect-center.js +495 -0
- package/src/lib/plugin-runtime/install.js +514 -13
- package/src/lib/plugin-runtime/marketplace-artifact-readback.js +900 -0
- package/src/lib/plugin-runtime/marketplace-catalog.js +1181 -0
- package/src/lib/plugin-runtime/marketplace-impact.js +408 -0
- package/src/lib/plugin-runtime/marketplace-remote-artifacts.js +1567 -0
- package/src/lib/plugin-security.js +60 -3
- package/src/lib/process-execution-broker/index.js +1095 -57
- package/src/lib/process-execution-broker/linux-bwrap-descriptor-launch.js +375 -0
- package/src/lib/process-execution-broker/linux-generic-bwrap-runtime.js +90 -16
- package/src/lib/process-execution-broker/linux-generic-bwrap.js +159 -18
- package/src/lib/process-execution-broker/macos-mcp-launcher-contract.js +278 -0
- package/src/lib/process-execution-broker/macos-mcp-launcher-protocol.json +23 -0
- package/src/lib/process-execution-broker/macos-mcp-launcher.c +1497 -0
- package/src/lib/process-execution-broker/mcp-fd-entry-bootstrap.js +37 -0
- package/src/lib/process-execution-broker/platform-sandbox.js +2330 -279
- 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 +50 -4
- package/src/lib/public-ide-capability-manifest.js +3 -0
- package/src/lib/remote-approval-bridge.js +123 -17
- package/src/lib/remote-membership-authority.js +632 -0
- package/src/lib/remote-membership-coordinator.js +2409 -0
- package/src/lib/remote-membership-host-store.js +1750 -0
- package/src/lib/scheduler-kernel/agenda-adapter.js +17 -7
- package/src/lib/scheduler-kernel/automation-adapter.js +105 -11
- package/src/lib/scheduler-kernel/automation-event-adapter.js +87 -11
- package/src/lib/scheduler-kernel/contract.js +91 -0
- package/src/lib/scheduler-kernel/cowork-cron-adapter.js +12 -1
- package/src/lib/scheduler-kernel/loop-adapter.js +7 -1
- package/src/lib/scheduler-kernel/routine-adapter.js +7 -1
- package/src/lib/scheduler-kernel/runtime-control-capabilities.js +31 -0
- package/src/lib/scheduler-kernel/runtime.js +176 -3
- package/src/lib/scheduler-kernel/store.js +1253 -45
- package/src/lib/scoped-permission-store.js +369 -0
- package/src/lib/session-anti-rollback-anchor.js +262 -5
- package/src/lib/sub-agent-context.js +4 -0
- package/src/lib/workflow-definition-contract.js +149 -0
- package/src/repl/agent-repl.js +41 -7
- package/src/repl/chat-repl.js +2 -0
- package/src/repl/clipboard-image.js +735 -16
- package/src/repl/ide-status.js +1 -1
- package/src/repl/prompt-interactions.js +59 -6
- package/src/runtime/agent-core.js +93 -3
- package/src/runtime/headless-runner.js +30 -25
- package/src/runtime/headless-stream.js +32 -25
- package/src/runtime/mcp-config.js +81 -10
- package/src/workers/background-agent-keeper.js +498 -0
- package/src/workers/background-agent-worker.js +358 -13
- package/src/workers/background-turn-bootstrap.js +143 -0
- package/src/assets/web-panel/assets/MobileProjects-BWdOvQAj.js +0 -1
- package/src/assets/web-panel/assets/Projects-BV4oApsm.js +0 -1
- package/src/assets/web-panel/assets/devWarning-DPty0mGN.js +0 -1
- package/src/assets/web-panel/assets/index-Bt7g0Vq_.js +0 -1
- package/src/assets/web-panel/assets/index-ChVT0p9u.js +0 -1
|
@@ -12,6 +12,14 @@ import {
|
|
|
12
12
|
buildAutomationCenterProjection,
|
|
13
13
|
runAutomationCenterAction,
|
|
14
14
|
} from "../lib/automation-center.js";
|
|
15
|
+
import {
|
|
16
|
+
automationCenterIncidentActionErrorEnvelope,
|
|
17
|
+
runAutomationCenterIncidentAction,
|
|
18
|
+
} from "../lib/automation-center-incidents.js";
|
|
19
|
+
import {
|
|
20
|
+
automationCenterRuntimeActionErrorEnvelope,
|
|
21
|
+
runAutomationCenterRuntimeAction,
|
|
22
|
+
} from "../lib/automation-center-runtime.js";
|
|
15
23
|
import {
|
|
16
24
|
createAutomationCenterRoutine,
|
|
17
25
|
editAutomationCenterRoutine,
|
|
@@ -22,6 +30,7 @@ import { parseJsonOption } from "../lib/parse-json-option.js";
|
|
|
22
30
|
import { AutomationSchedulerBridge } from "../lib/scheduler-kernel/automation-adapter.js";
|
|
23
31
|
import { AutomationEventDispatcher } from "../lib/scheduler-kernel/automation-event-adapter.js";
|
|
24
32
|
import { openSchedulerStore } from "../lib/scheduler-kernel/store.js";
|
|
33
|
+
import { resolveAutomationCenterRuntimeControl } from "../lib/scheduler-kernel/runtime-control-capabilities.js";
|
|
25
34
|
import {
|
|
26
35
|
RoutineSchedulerBridge,
|
|
27
36
|
routineBridgeRunId,
|
|
@@ -288,7 +297,8 @@ export function registerAutomationCommand(program) {
|
|
|
288
297
|
if (
|
|
289
298
|
actionCommand &&
|
|
290
299
|
(actionCommand.name().endsWith("-v2") ||
|
|
291
|
-
actionCommand.name().startsWith("center-routine-")
|
|
300
|
+
actionCommand.name().startsWith("center-routine-") ||
|
|
301
|
+
actionCommand.name() === "center-runtime-action")
|
|
292
302
|
)
|
|
293
303
|
return;
|
|
294
304
|
const db = await _prepare(thisCommand);
|
|
@@ -446,9 +456,13 @@ function _wire(root) {
|
|
|
446
456
|
.option("--json", "Output as JSON")
|
|
447
457
|
.action(async (opts, cmd) => {
|
|
448
458
|
const db = _dbFromCtx(cmd);
|
|
459
|
+
let schedulerStore;
|
|
449
460
|
try {
|
|
461
|
+
schedulerStore = openSchedulerStore();
|
|
450
462
|
const projection = buildAutomationCenterProjection(db, {
|
|
451
463
|
limit: Number(opts.limit),
|
|
464
|
+
schedulerStore,
|
|
465
|
+
runtimeCapabilityForKind: resolveAutomationCenterRuntimeControl,
|
|
452
466
|
});
|
|
453
467
|
if (opts.json) console.log(JSON.stringify(projection, null, 2));
|
|
454
468
|
else {
|
|
@@ -465,6 +479,94 @@ function _wire(root) {
|
|
|
465
479
|
logger.error(e.message);
|
|
466
480
|
process.exitCode = 1;
|
|
467
481
|
} finally {
|
|
482
|
+
schedulerStore?.close();
|
|
483
|
+
await shutdown();
|
|
484
|
+
}
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
root
|
|
488
|
+
.command("center-runtime-action <occurrenceId> <pause|resume>")
|
|
489
|
+
.description("Pause or resume one exact fenced scheduler occurrence")
|
|
490
|
+
.requiredOption(
|
|
491
|
+
"--expected-fence <fence>",
|
|
492
|
+
"Exact scheduler fence shown by center-projection",
|
|
493
|
+
)
|
|
494
|
+
.requiredOption(
|
|
495
|
+
"--expected-control-revision <revision>",
|
|
496
|
+
"Exact runtime-control revision shown by center-projection",
|
|
497
|
+
)
|
|
498
|
+
.option("--json", "Output as JSON")
|
|
499
|
+
.action(async (occurrenceId, action, opts) => {
|
|
500
|
+
let schedulerStore;
|
|
501
|
+
try {
|
|
502
|
+
schedulerStore = openSchedulerStore();
|
|
503
|
+
const result = runAutomationCenterRuntimeAction(schedulerStore, {
|
|
504
|
+
capabilityForKind: resolveAutomationCenterRuntimeControl,
|
|
505
|
+
occurrenceId,
|
|
506
|
+
action,
|
|
507
|
+
expectedFence: Number(opts.expectedFence),
|
|
508
|
+
expectedControlRevision: Number(opts.expectedControlRevision),
|
|
509
|
+
});
|
|
510
|
+
if (opts.json) console.log(JSON.stringify(result, null, 2));
|
|
511
|
+
else logger.success(`${occurrenceId} ${action} completed`);
|
|
512
|
+
} catch (error) {
|
|
513
|
+
if (opts.json) {
|
|
514
|
+
console.log(
|
|
515
|
+
JSON.stringify(
|
|
516
|
+
automationCenterRuntimeActionErrorEnvelope(error, {
|
|
517
|
+
occurrenceId,
|
|
518
|
+
action,
|
|
519
|
+
}),
|
|
520
|
+
null,
|
|
521
|
+
2,
|
|
522
|
+
),
|
|
523
|
+
);
|
|
524
|
+
} else logger.error(error.message);
|
|
525
|
+
process.exitCode = 1;
|
|
526
|
+
} finally {
|
|
527
|
+
schedulerStore?.close();
|
|
528
|
+
await shutdown();
|
|
529
|
+
}
|
|
530
|
+
});
|
|
531
|
+
|
|
532
|
+
root
|
|
533
|
+
.command("center-incident-action <incidentId> <retry|cancel>")
|
|
534
|
+
.description("Retry or cancel a revision-gated Automation Center incident")
|
|
535
|
+
.requiredOption(
|
|
536
|
+
"--expected-revision <revision>",
|
|
537
|
+
"Exact incident revision shown by center-projection",
|
|
538
|
+
)
|
|
539
|
+
.option("--json", "Output as JSON")
|
|
540
|
+
.action(async (incidentId, action, opts, cmd) => {
|
|
541
|
+
const db = _dbFromCtx(cmd);
|
|
542
|
+
let schedulerStore;
|
|
543
|
+
try {
|
|
544
|
+
// Cancellation is incident-local. Retry alone needs the scheduler's
|
|
545
|
+
// dead-letter evidence and owns this short-lived handle.
|
|
546
|
+
if (action === "retry") schedulerStore = openSchedulerStore();
|
|
547
|
+
const result = runAutomationCenterIncidentAction(db, schedulerStore, {
|
|
548
|
+
incidentId,
|
|
549
|
+
action,
|
|
550
|
+
expectedRevision: opts.expectedRevision,
|
|
551
|
+
});
|
|
552
|
+
if (opts.json) console.log(JSON.stringify(result, null, 2));
|
|
553
|
+
else logger.success(`${incidentId} ${action} completed`);
|
|
554
|
+
} catch (error) {
|
|
555
|
+
if (opts.json) {
|
|
556
|
+
console.log(
|
|
557
|
+
JSON.stringify(
|
|
558
|
+
automationCenterIncidentActionErrorEnvelope(error, {
|
|
559
|
+
incidentId,
|
|
560
|
+
action,
|
|
561
|
+
}),
|
|
562
|
+
null,
|
|
563
|
+
2,
|
|
564
|
+
),
|
|
565
|
+
);
|
|
566
|
+
} else logger.error(error.message);
|
|
567
|
+
process.exitCode = 1;
|
|
568
|
+
} finally {
|
|
569
|
+
schedulerStore?.close();
|
|
468
570
|
await shutdown();
|
|
469
571
|
}
|
|
470
572
|
});
|
package/src/commands/cowork.js
CHANGED
|
@@ -9,6 +9,14 @@ import fs from "fs";
|
|
|
9
9
|
import path from "path";
|
|
10
10
|
import { logger } from "../lib/logger.js";
|
|
11
11
|
|
|
12
|
+
async function loadCoworkWorkflowRecord(cwd, id, definitionDigest) {
|
|
13
|
+
const { getWorkflowRecord, getWorkflowVersion } =
|
|
14
|
+
await import("../lib/cowork-workflow.js");
|
|
15
|
+
return definitionDigest
|
|
16
|
+
? getWorkflowVersion(cwd, id, definitionDigest)
|
|
17
|
+
: getWorkflowRecord(cwd, id);
|
|
18
|
+
}
|
|
19
|
+
|
|
12
20
|
export function registerCoworkCommand(program) {
|
|
13
21
|
const cowork = program
|
|
14
22
|
.command("cowork")
|
|
@@ -799,6 +807,145 @@ export function registerCoworkCommand(program) {
|
|
|
799
807
|
console.log(JSON.stringify(wf, null, 2));
|
|
800
808
|
});
|
|
801
809
|
|
|
810
|
+
workflow
|
|
811
|
+
.command("versions <id>")
|
|
812
|
+
.description("List immutable saved definition versions")
|
|
813
|
+
.option("--json", "Machine-readable JSON output")
|
|
814
|
+
.action(async (id, options) => {
|
|
815
|
+
try {
|
|
816
|
+
const { listWorkflowVersions } =
|
|
817
|
+
await import("../lib/cowork-workflow.js");
|
|
818
|
+
const versions = listWorkflowVersions(process.cwd(), id);
|
|
819
|
+
if (options.json) {
|
|
820
|
+
console.log(JSON.stringify(versions, null, 2));
|
|
821
|
+
return;
|
|
822
|
+
}
|
|
823
|
+
if (versions.length === 0) {
|
|
824
|
+
logger.log(chalk.gray(`No versioned definitions found for '${id}'.`));
|
|
825
|
+
return;
|
|
826
|
+
}
|
|
827
|
+
logger.log(chalk.bold(`${versions.length} immutable version(s):`));
|
|
828
|
+
for (const version of versions) {
|
|
829
|
+
logger.log(` ${version.definitionDigest} ${version.name}`);
|
|
830
|
+
}
|
|
831
|
+
} catch (err) {
|
|
832
|
+
logger.error(err.message);
|
|
833
|
+
process.exitCode = 1;
|
|
834
|
+
}
|
|
835
|
+
});
|
|
836
|
+
|
|
837
|
+
workflow
|
|
838
|
+
.command("manifest <id>")
|
|
839
|
+
.description(
|
|
840
|
+
"Project a versioned, digest-bound workflow definition and DAG plan",
|
|
841
|
+
)
|
|
842
|
+
.option(
|
|
843
|
+
"--definition-digest <sha256>",
|
|
844
|
+
"Inspect an immutable saved definition version",
|
|
845
|
+
)
|
|
846
|
+
.option("--json", "Machine-readable JSON output")
|
|
847
|
+
.action(async (id, options) => {
|
|
848
|
+
try {
|
|
849
|
+
const [{ createDynamicWorkflowManifest }, record] = await Promise.all([
|
|
850
|
+
import("../lib/dynamic-workflow-facade.js"),
|
|
851
|
+
loadCoworkWorkflowRecord(process.cwd(), id, options.definitionDigest),
|
|
852
|
+
]);
|
|
853
|
+
if (!record) {
|
|
854
|
+
logger.error(`Workflow not found: ${id}`);
|
|
855
|
+
process.exitCode = 1;
|
|
856
|
+
return;
|
|
857
|
+
}
|
|
858
|
+
const projected = createDynamicWorkflowManifest(record.definition);
|
|
859
|
+
const manifest = Object.freeze({
|
|
860
|
+
...projected,
|
|
861
|
+
definitionAuthority: Object.freeze({
|
|
862
|
+
status: record.status,
|
|
863
|
+
recordSchema: record.recordSchema,
|
|
864
|
+
definitionSchema: record.definitionSchema,
|
|
865
|
+
definitionDigest: record.definitionDigest,
|
|
866
|
+
}),
|
|
867
|
+
});
|
|
868
|
+
if (options.json) {
|
|
869
|
+
console.log(JSON.stringify(manifest, null, 2));
|
|
870
|
+
return;
|
|
871
|
+
}
|
|
872
|
+
logger.log(chalk.bold(`${manifest.definition.name}`));
|
|
873
|
+
logger.log(` schema: ${manifest.schema}`);
|
|
874
|
+
logger.log(` digest: ${manifest.definitionDigest}`);
|
|
875
|
+
logger.log(` authority: ${record.status}`);
|
|
876
|
+
logger.log(` adapter: ${manifest.adapter}`);
|
|
877
|
+
logger.log(` plan: ${manifest.plan.mode}`);
|
|
878
|
+
logger.log(
|
|
879
|
+
` task calls: ${manifest.plan.worstCaseTaskCalls ?? "unknown"}`,
|
|
880
|
+
);
|
|
881
|
+
logger.log(
|
|
882
|
+
` resumable: ${manifest.runtimeClaims.durablePauseResume ? "yes" : "no"}`,
|
|
883
|
+
);
|
|
884
|
+
} catch (err) {
|
|
885
|
+
logger.error(err.message);
|
|
886
|
+
process.exitCode = 1;
|
|
887
|
+
}
|
|
888
|
+
});
|
|
889
|
+
|
|
890
|
+
workflow
|
|
891
|
+
.command("preflight <id>")
|
|
892
|
+
.description(
|
|
893
|
+
"Evaluate capability, permission, sandbox, scale, and cost gates",
|
|
894
|
+
)
|
|
895
|
+
.option(
|
|
896
|
+
"--definition-digest <sha256>",
|
|
897
|
+
"Preflight an immutable saved definition version",
|
|
898
|
+
)
|
|
899
|
+
.option("--max-parallel <n>", "Requested maximum parallel steps", "4")
|
|
900
|
+
.option("--json", "Machine-readable JSON output")
|
|
901
|
+
.action(async (id, options) => {
|
|
902
|
+
try {
|
|
903
|
+
const [
|
|
904
|
+
{ buildDynamicWorkflowPreflight },
|
|
905
|
+
{ captureAmbientExecutionLocation },
|
|
906
|
+
record,
|
|
907
|
+
] = await Promise.all([
|
|
908
|
+
import("../lib/dynamic-workflow-facade.js"),
|
|
909
|
+
import("../lib/execution-location-runtime.js"),
|
|
910
|
+
loadCoworkWorkflowRecord(process.cwd(), id, options.definitionDigest),
|
|
911
|
+
]);
|
|
912
|
+
if (!record) {
|
|
913
|
+
logger.error(`Workflow not found: ${id}`);
|
|
914
|
+
process.exitCode = 1;
|
|
915
|
+
return;
|
|
916
|
+
}
|
|
917
|
+
const preflight = buildDynamicWorkflowPreflight({
|
|
918
|
+
workflow: record.definition,
|
|
919
|
+
definitionAuthority: record,
|
|
920
|
+
executionLocation: captureAmbientExecutionLocation(),
|
|
921
|
+
maxParallel: options.maxParallel,
|
|
922
|
+
});
|
|
923
|
+
if (options.json) {
|
|
924
|
+
console.log(JSON.stringify(preflight, null, 2));
|
|
925
|
+
} else {
|
|
926
|
+
const color = preflight.allowed ? chalk.green : chalk.red;
|
|
927
|
+
logger.log(color(preflight.allowed ? "READY" : "BLOCKED"));
|
|
928
|
+
logger.log(` definition: ${preflight.definition.definitionDigest}`);
|
|
929
|
+
logger.log(
|
|
930
|
+
` task calls: ${preflight.scale.worstCaseTaskCalls ?? "unknown"}`,
|
|
931
|
+
);
|
|
932
|
+
logger.log(
|
|
933
|
+
` tokens/USD: ${preflight.cost.projectedTokens ?? "unknown"} / ${preflight.cost.projectedUsd ?? "unknown"}`,
|
|
934
|
+
);
|
|
935
|
+
for (const blocker of preflight.blockers) {
|
|
936
|
+
logger.log(chalk.red(` blocker: ${blocker}`));
|
|
937
|
+
}
|
|
938
|
+
for (const warning of preflight.warnings) {
|
|
939
|
+
logger.log(chalk.yellow(` warning: ${warning}`));
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
process.exitCode = preflight.allowed ? 0 : 2;
|
|
943
|
+
} catch (err) {
|
|
944
|
+
logger.error(err.message);
|
|
945
|
+
process.exitCode = 1;
|
|
946
|
+
}
|
|
947
|
+
});
|
|
948
|
+
|
|
802
949
|
workflow
|
|
803
950
|
.command("add <file>")
|
|
804
951
|
.description("Add a workflow from a JSON definition file")
|
|
@@ -832,6 +979,10 @@ export function registerCoworkCommand(program) {
|
|
|
832
979
|
workflow
|
|
833
980
|
.command("run <id>")
|
|
834
981
|
.description("Execute a saved workflow end-to-end")
|
|
982
|
+
.option(
|
|
983
|
+
"--definition-digest <sha256>",
|
|
984
|
+
"Replay an immutable saved definition version",
|
|
985
|
+
)
|
|
835
986
|
.option("--continue-on-error", "Keep running after a step fails", false)
|
|
836
987
|
.option("--max-parallel <n>", "Max parallel steps per batch", "4")
|
|
837
988
|
.option(
|
|
@@ -840,28 +991,32 @@ export function registerCoworkCommand(program) {
|
|
|
840
991
|
false,
|
|
841
992
|
)
|
|
842
993
|
.action(async (id, options) => {
|
|
843
|
-
const [
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
import("../lib/cowork-task-runner.js"),
|
|
849
|
-
]);
|
|
850
|
-
const wf = getWorkflow(process.cwd(), id);
|
|
851
|
-
if (!wf) {
|
|
852
|
-
logger.error(`Workflow not found: ${id}`);
|
|
853
|
-
process.exit(1);
|
|
854
|
-
}
|
|
855
|
-
wfDeps.runTask = runCoworkTask;
|
|
856
|
-
|
|
857
|
-
logger.log(
|
|
858
|
-
chalk.bold(
|
|
859
|
-
`\nExecuting workflow '${wf.name}' (${wf.steps.length} steps)...`,
|
|
860
|
-
),
|
|
861
|
-
);
|
|
994
|
+
const [{ executeWorkflow, _deps: wfDeps }, { runCoworkTask }] =
|
|
995
|
+
await Promise.all([
|
|
996
|
+
import("../lib/cowork-workflow.js"),
|
|
997
|
+
import("../lib/cowork-task-runner.js"),
|
|
998
|
+
]);
|
|
862
999
|
try {
|
|
1000
|
+
const record = await loadCoworkWorkflowRecord(
|
|
1001
|
+
process.cwd(),
|
|
1002
|
+
id,
|
|
1003
|
+
options.definitionDigest,
|
|
1004
|
+
);
|
|
1005
|
+
if (!record) {
|
|
1006
|
+
logger.error(`Workflow not found: ${id}`);
|
|
1007
|
+
process.exitCode = 1;
|
|
1008
|
+
return;
|
|
1009
|
+
}
|
|
1010
|
+
const wf = record.definition;
|
|
1011
|
+
wfDeps.runTask = runCoworkTask;
|
|
1012
|
+
logger.log(
|
|
1013
|
+
chalk.bold(
|
|
1014
|
+
`\nExecuting workflow '${wf.name}' (${wf.steps.length} steps, ${record.definitionDigest})...`,
|
|
1015
|
+
),
|
|
1016
|
+
);
|
|
863
1017
|
const result = await executeWorkflow({
|
|
864
1018
|
workflow: wf,
|
|
1019
|
+
definitionDigest: record.definitionDigest,
|
|
865
1020
|
cwd: process.cwd(),
|
|
866
1021
|
maxParallel: parseInt(options.maxParallel, 10) || 4,
|
|
867
1022
|
continueOnError: !!options.continueOnError,
|
|
@@ -3,15 +3,18 @@
|
|
|
3
3
|
* permission ruleset (Claude-Code `permissions.{allow,ask,deny}` parity).
|
|
4
4
|
*
|
|
5
5
|
* cc permissions list [--json] merged ruleset + source file
|
|
6
|
+
* cc permissions activity [--session <id>] actual resources/effects/recovery
|
|
6
7
|
* cc permissions test <tool> <args...> dry-run: which rule decides?
|
|
7
8
|
* cc permissions add <allow|ask|deny> <rule> append a rule to a settings file
|
|
8
9
|
* cc permissions allow|ask|deny <rule> convenience aliases for add
|
|
10
|
+
* cc permissions scoped <decision> <rule> add a workspace-bound TTL rule
|
|
11
|
+
* cc permissions revoke <id> --revision <n> CAS-revoke a scoped rule
|
|
9
12
|
* [--local | --user] (default target: project)
|
|
10
13
|
*
|
|
11
|
-
* The ruleset is loaded by
|
|
12
|
-
* evaluated by permission-rules (deny > ask > allow).
|
|
13
|
-
* and
|
|
14
|
-
*
|
|
14
|
+
* The ruleset is loaded by the shared permission authority resolver and
|
|
15
|
+
* evaluated by permission-rules (deny > ask > allow). Scoped mutations are
|
|
16
|
+
* CLI-owned and live outside the repository; IDE clients call this surface
|
|
17
|
+
* instead of editing authority files directly.
|
|
15
18
|
*/
|
|
16
19
|
|
|
17
20
|
import chalk from "chalk";
|
|
@@ -24,7 +27,37 @@ const KIND_COLOR = {
|
|
|
24
27
|
};
|
|
25
28
|
|
|
26
29
|
const RUNTIME_ADVISORY =
|
|
27
|
-
"
|
|
30
|
+
"permission rules are enforced by Agent Core; scoped rules are refreshed before every tool call, while managed host policy and ApprovalGate still apply.";
|
|
31
|
+
|
|
32
|
+
const DURATION_UNITS = Object.freeze({
|
|
33
|
+
s: 1000,
|
|
34
|
+
m: 60 * 1000,
|
|
35
|
+
h: 60 * 60 * 1000,
|
|
36
|
+
d: 24 * 60 * 60 * 1000,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
function parseDurationMs(value) {
|
|
40
|
+
const match = String(value || "")
|
|
41
|
+
.trim()
|
|
42
|
+
.toLowerCase()
|
|
43
|
+
.match(/^(\d+)(s|m|h|d)$/);
|
|
44
|
+
if (!match) {
|
|
45
|
+
throw new Error("duration must be an integer followed by s, m, h, or d");
|
|
46
|
+
}
|
|
47
|
+
const duration = Number(match[1]) * DURATION_UNITS[match[2]];
|
|
48
|
+
if (!Number.isSafeInteger(duration) || duration < 1000) {
|
|
49
|
+
throw new Error("duration must be at least 1s and within the safe range");
|
|
50
|
+
}
|
|
51
|
+
return duration;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function parseNonNegativeInteger(value, label) {
|
|
55
|
+
const number = Number(value);
|
|
56
|
+
if (!Number.isSafeInteger(number) || number < 0) {
|
|
57
|
+
throw new Error(`${label} must be a non-negative integer`);
|
|
58
|
+
}
|
|
59
|
+
return number;
|
|
60
|
+
}
|
|
28
61
|
|
|
29
62
|
function printRuntimeAdvisory() {
|
|
30
63
|
logger.log(chalk.yellow(RUNTIME_ADVISORY));
|
|
@@ -49,7 +82,12 @@ function buildArgs(tool, positional, rulesMod) {
|
|
|
49
82
|
return {};
|
|
50
83
|
}
|
|
51
84
|
|
|
52
|
-
async function persistPermissionRule(
|
|
85
|
+
async function persistPermissionRule(
|
|
86
|
+
decision,
|
|
87
|
+
rule,
|
|
88
|
+
options,
|
|
89
|
+
operation = "add",
|
|
90
|
+
) {
|
|
53
91
|
try {
|
|
54
92
|
const kind = String(decision || "").toLowerCase();
|
|
55
93
|
if (!["allow", "ask", "deny"].includes(kind)) {
|
|
@@ -110,11 +148,13 @@ export function registerPermissionsCommand(program) {
|
|
|
110
148
|
.option("--settings <file>", "Also merge an explicit settings file")
|
|
111
149
|
.action(async (options) => {
|
|
112
150
|
try {
|
|
113
|
-
const {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
151
|
+
const { loadPermissionAuthority } =
|
|
152
|
+
await import("../lib/permission-authority.js");
|
|
153
|
+
const { rules, sources, files, managed, managedFile, scoped } =
|
|
154
|
+
loadPermissionAuthority({
|
|
155
|
+
cwd: process.cwd(),
|
|
156
|
+
settingsFile: options.settings,
|
|
157
|
+
});
|
|
118
158
|
if (options.json) {
|
|
119
159
|
console.log(
|
|
120
160
|
JSON.stringify(
|
|
@@ -124,8 +164,9 @@ export function registerPermissionsCommand(program) {
|
|
|
124
164
|
files,
|
|
125
165
|
managed,
|
|
126
166
|
managedFile,
|
|
167
|
+
scoped,
|
|
127
168
|
enforcement: {
|
|
128
|
-
status: "
|
|
169
|
+
status: "enforced",
|
|
129
170
|
note: RUNTIME_ADVISORY,
|
|
130
171
|
},
|
|
131
172
|
},
|
|
@@ -144,7 +185,7 @@ export function registerPermissionsCommand(program) {
|
|
|
144
185
|
"(or create .claude/settings.json with a permissions block)",
|
|
145
186
|
),
|
|
146
187
|
);
|
|
147
|
-
return;
|
|
188
|
+
if (!scoped?.rules?.length) return;
|
|
148
189
|
}
|
|
149
190
|
for (const kind of ["deny", "ask", "allow"]) {
|
|
150
191
|
if (rules[kind].length === 0) continue;
|
|
@@ -191,6 +232,17 @@ export function registerPermissionsCommand(program) {
|
|
|
191
232
|
);
|
|
192
233
|
}
|
|
193
234
|
}
|
|
235
|
+
if (scoped?.rules?.length) {
|
|
236
|
+
logger.log(chalk.bold("\nworkspace-scoped rules"));
|
|
237
|
+
for (const record of scoped.rules) {
|
|
238
|
+
const status = record.effectiveStatus || record.status;
|
|
239
|
+
const color = status === "active" ? chalk.green : chalk.gray;
|
|
240
|
+
logger.log(
|
|
241
|
+
` ${color(status.padEnd(28))} ${record.id} r${record.revision} ${record.decision} ${record.rule}`,
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
logger.log(chalk.dim(` authority: ${scoped.file}`));
|
|
245
|
+
}
|
|
194
246
|
} catch (err) {
|
|
195
247
|
logger.error(chalk.red(`permissions list failed: ${err.message}`));
|
|
196
248
|
process.exitCode = 1;
|
|
@@ -246,6 +298,82 @@ export function registerPermissionsCommand(program) {
|
|
|
246
298
|
}
|
|
247
299
|
});
|
|
248
300
|
|
|
301
|
+
// ── activity ──────────────────────────────────────────────────────────
|
|
302
|
+
cmd
|
|
303
|
+
.command("activity")
|
|
304
|
+
.description(
|
|
305
|
+
"Show actual resource, side-effect, permission, and recovery evidence",
|
|
306
|
+
)
|
|
307
|
+
.option("-s, --session <id>", "Persisted CLI session", "default")
|
|
308
|
+
.option("-n, --limit <n>", "Maximum side-effect records", "50")
|
|
309
|
+
.option("--json", "Output the versioned center projection as JSON")
|
|
310
|
+
.action(async (options) => {
|
|
311
|
+
try {
|
|
312
|
+
const sessionId = String(options.session || "default").trim();
|
|
313
|
+
const limit = Math.max(
|
|
314
|
+
1,
|
|
315
|
+
Math.min(100, parseNonNegativeInteger(options.limit, "limit")),
|
|
316
|
+
);
|
|
317
|
+
const { loadSideEffectLedger } =
|
|
318
|
+
await import("../lib/side-effect-ledger-store.js");
|
|
319
|
+
const { loadTurnBindingLog } =
|
|
320
|
+
await import("../lib/turn-binding-store.js");
|
|
321
|
+
const { loadMcpLedgerRecovery } =
|
|
322
|
+
await import("../lib/mcp-call-ledger-store.js");
|
|
323
|
+
const { sessionExists } =
|
|
324
|
+
await import("../harness/jsonl-session-store.js");
|
|
325
|
+
const { buildPermissionSideEffectCenter } =
|
|
326
|
+
await import("../lib/permission-side-effect-center.js");
|
|
327
|
+
const mcpRecords = sessionExists(sessionId)
|
|
328
|
+
? loadMcpLedgerRecovery(sessionId).records
|
|
329
|
+
: [];
|
|
330
|
+
const projection = buildPermissionSideEffectCenter({
|
|
331
|
+
sessionId,
|
|
332
|
+
operations: loadSideEffectLedger(sessionId).list(),
|
|
333
|
+
mcpRecords,
|
|
334
|
+
turns: loadTurnBindingLog(sessionId).list(),
|
|
335
|
+
limit,
|
|
336
|
+
});
|
|
337
|
+
if (options.json) {
|
|
338
|
+
console.log(JSON.stringify(projection, null, 2));
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
if (projection.entries.length === 0) {
|
|
342
|
+
logger.log(
|
|
343
|
+
chalk.gray(`No side-effect evidence for session ${sessionId}.`),
|
|
344
|
+
);
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
logger.log(
|
|
348
|
+
chalk.bold(
|
|
349
|
+
`${projection.entries.length} actual side effect(s) · ${projection.summary.irreversible} irreversible · ${projection.summary.inspect} need inspection`,
|
|
350
|
+
),
|
|
351
|
+
);
|
|
352
|
+
for (const entry of projection.entries) {
|
|
353
|
+
const coverage =
|
|
354
|
+
entry.recovery.coverage === "full"
|
|
355
|
+
? chalk.green(entry.recovery.coverage)
|
|
356
|
+
: entry.recovery.coverage === "partial"
|
|
357
|
+
? chalk.yellow(entry.recovery.coverage)
|
|
358
|
+
: chalk.red(entry.recovery.coverage);
|
|
359
|
+
logger.log(
|
|
360
|
+
`${chalk.cyan(entry.tool)} ${entry.kind} ${entry.state} · recovery ${coverage}/${entry.recovery.action}`,
|
|
361
|
+
);
|
|
362
|
+
for (const [kind, values] of Object.entries(entry.resources)) {
|
|
363
|
+
if (values.length) {
|
|
364
|
+
logger.log(chalk.gray(` ${kind}: ${values.join(", ")}`));
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
for (const warning of entry.unresolvedResources) {
|
|
368
|
+
logger.log(chalk.yellow(` unresolved: ${warning}`));
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
} catch (err) {
|
|
372
|
+
logger.error(chalk.red(`permissions activity failed: ${err.message}`));
|
|
373
|
+
process.exitCode = 1;
|
|
374
|
+
}
|
|
375
|
+
});
|
|
376
|
+
|
|
249
377
|
// ── test (dry-run) ─────────────────────────────────────────────────────
|
|
250
378
|
cmd
|
|
251
379
|
.command("test <tool> [args...]")
|
|
@@ -256,13 +384,14 @@ export function registerPermissionsCommand(program) {
|
|
|
256
384
|
.option("--settings <file>", "Also merge an explicit settings file")
|
|
257
385
|
.action(async (tool, args, options) => {
|
|
258
386
|
try {
|
|
259
|
-
const {
|
|
260
|
-
|
|
387
|
+
const { ruleSource } = await import("../lib/settings-loader.cjs");
|
|
388
|
+
const { loadPermissionAuthority } =
|
|
389
|
+
await import("../lib/permission-authority.js");
|
|
261
390
|
// .cjs default-export interop: module.exports surfaces as `.default`.
|
|
262
391
|
const rulesMod = await import("../lib/permission-rules.cjs");
|
|
263
392
|
const mod = rulesMod.default || rulesMod;
|
|
264
393
|
|
|
265
|
-
const { rules, sources } =
|
|
394
|
+
const { rules, sources } = loadPermissionAuthority({
|
|
266
395
|
cwd: process.cwd(),
|
|
267
396
|
settingsFile: options.settings,
|
|
268
397
|
});
|
|
@@ -392,4 +521,99 @@ export function registerPermissionsCommand(program) {
|
|
|
392
521
|
await persistPermissionRule(decision, rule, options, decision);
|
|
393
522
|
});
|
|
394
523
|
}
|
|
524
|
+
|
|
525
|
+
cmd
|
|
526
|
+
.command("scoped <decision> <rule>")
|
|
527
|
+
.description(
|
|
528
|
+
"Create a workspace-bound, expiring rule in the CLI security store",
|
|
529
|
+
)
|
|
530
|
+
.requiredOption(
|
|
531
|
+
"--expires-in <duration>",
|
|
532
|
+
"TTL such as 30s, 15m, 2h, or 1d",
|
|
533
|
+
)
|
|
534
|
+
.option("--reason <text>", "Human-readable reason for the grant")
|
|
535
|
+
.option(
|
|
536
|
+
"--expected-generation <n>",
|
|
537
|
+
"Create only if the store generation still matches",
|
|
538
|
+
)
|
|
539
|
+
.option("--json", "Output as JSON")
|
|
540
|
+
.action(async (decision, rule, options) => {
|
|
541
|
+
try {
|
|
542
|
+
const ttlMs = parseDurationMs(options.expiresIn);
|
|
543
|
+
const expectedGeneration =
|
|
544
|
+
options.expectedGeneration === undefined
|
|
545
|
+
? null
|
|
546
|
+
: parseNonNegativeInteger(
|
|
547
|
+
options.expectedGeneration,
|
|
548
|
+
"expected generation",
|
|
549
|
+
);
|
|
550
|
+
const { ScopedPermissionStore } =
|
|
551
|
+
await import("../lib/scoped-permission-store.js");
|
|
552
|
+
const store = new ScopedPermissionStore({ cwd: process.cwd() });
|
|
553
|
+
const record = store.add({
|
|
554
|
+
decision,
|
|
555
|
+
rule,
|
|
556
|
+
expiresAt: Date.now() + ttlMs,
|
|
557
|
+
reason: options.reason || "",
|
|
558
|
+
expectedGeneration,
|
|
559
|
+
});
|
|
560
|
+
if (options.json) {
|
|
561
|
+
console.log(
|
|
562
|
+
JSON.stringify(
|
|
563
|
+
{
|
|
564
|
+
record,
|
|
565
|
+
authority: {
|
|
566
|
+
file: store.filePath,
|
|
567
|
+
workspace: store.workspace,
|
|
568
|
+
},
|
|
569
|
+
},
|
|
570
|
+
null,
|
|
571
|
+
2,
|
|
572
|
+
),
|
|
573
|
+
);
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
576
|
+
logger.log(
|
|
577
|
+
`${KIND_COLOR[record.decision].bold("✓ scoped " + record.decision)} ${record.rule}`,
|
|
578
|
+
);
|
|
579
|
+
logger.log(
|
|
580
|
+
chalk.gray(
|
|
581
|
+
` ${record.id} r${record.revision}; expires ${new Date(record.expiresAt).toISOString()}`,
|
|
582
|
+
),
|
|
583
|
+
);
|
|
584
|
+
} catch (err) {
|
|
585
|
+
logger.error(chalk.red(`permissions scoped failed: ${err.message}`));
|
|
586
|
+
process.exitCode = 1;
|
|
587
|
+
}
|
|
588
|
+
});
|
|
589
|
+
|
|
590
|
+
cmd
|
|
591
|
+
.command("revoke <id>")
|
|
592
|
+
.description("Revoke a workspace-scoped rule with revision CAS")
|
|
593
|
+
.requiredOption("--revision <n>", "Expected record revision")
|
|
594
|
+
.option("--json", "Output as JSON")
|
|
595
|
+
.action(async (id, options) => {
|
|
596
|
+
try {
|
|
597
|
+
const expectedRevision = parseNonNegativeInteger(
|
|
598
|
+
options.revision,
|
|
599
|
+
"revision",
|
|
600
|
+
);
|
|
601
|
+
const { ScopedPermissionStore } =
|
|
602
|
+
await import("../lib/scoped-permission-store.js");
|
|
603
|
+
const store = new ScopedPermissionStore({ cwd: process.cwd() });
|
|
604
|
+
const record = store.revoke({ id, expectedRevision });
|
|
605
|
+
if (options.json) {
|
|
606
|
+
console.log(JSON.stringify({ record }, null, 2));
|
|
607
|
+
return;
|
|
608
|
+
}
|
|
609
|
+
logger.log(
|
|
610
|
+
chalk.green(
|
|
611
|
+
`Revoked ${record.id} at revision ${record.revision} (${record.rule})`,
|
|
612
|
+
),
|
|
613
|
+
);
|
|
614
|
+
} catch (err) {
|
|
615
|
+
logger.error(chalk.red(`permissions revoke failed: ${err.message}`));
|
|
616
|
+
process.exitCode = 1;
|
|
617
|
+
}
|
|
618
|
+
});
|
|
395
619
|
}
|