chainlesschain 0.162.181 → 0.162.183
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 +2 -1
- package/scripts/build-windows-sandbox-helper.ps1 +163 -0
- package/src/assets/web-panel/assets/{AIOps-cq0dwbnf.js → AIOps-BapS7lz4.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-CvcgGl3w.js → ActionButton-CXYdXEUI.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-hM2-jFqg.js → Analytics-CKR5Lexn.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-B9_Gsd_g.js → AppLayout-DATVUOXB.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-B7bu52Og.js → Artifacts-vb_0ZlV1.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-DThfDgqB.js → Audit-BI1l9GWt.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-DjlFiD4v.js → BackgroundAgents-BFXbaUEf.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-CK9xJKnG.js → Backup-DEYBJJ6H.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-DEiSU8K8.js → BaseInput-COdzeO0M.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-CpT96czj.js → Chat-oSN6sfM5.js} +6 -6
- package/src/assets/web-panel/assets/ChatBubbleRenderer-CI_jT0ru.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-C1GfDnO0.js → Checkbox-BezEa4tm.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-3DAKgiLx.js → Codegen-CNEL0Ife.js} +1 -1
- package/src/assets/web-panel/assets/{Col-74cOwZU1.js → Col-Bf2Y2Bn1.js} +1 -1
- package/src/assets/web-panel/assets/{Community-tn9Kkz9j.js → Community-BfUlu4Hc.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-BcoXH7m4.js → Compact-BN4xWP9e.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-DIPGUBgi.js → Compliance-Bt6BKmEP.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-doD5_91c.js → Cowork-DKLp8YxO.js} +2 -2
- package/src/assets/web-panel/assets/{Cron-C-IDvubz.js → Cron-o7Hhw6ky.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-CdcCoBdj.js → Crosschain-DaNXWJIw.js} +1 -1
- package/src/assets/web-panel/assets/{DID-DdH5aMMA.js → DID-B-Qa2mha.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-DHLA4mm0.js → Dashboard-CMX0Qnxw.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-dEeCt7Md.js → Dropdown-BLuLyRu_.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-BMaecFv9.js → EmailListRenderer-CFBAeMij.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-DUaUukTN.js → FamilyGuardDashboard-DWzXQ67V.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-CMBE0_rp.js → Federation-DB1QSLgr.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-PG-JDbXq.js → FormItemContext-C-OKCToP.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-Bcb0p88m.js → GenericCardRenderer-DMJFtFZf.js} +1 -1
- package/src/assets/web-panel/assets/{Git-Bgv15myB.js → Git-DsGSujOV.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-DB8YTArI.js → Governance-B0iS9NEW.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-BQMwCWaS.js → Inference-CH004H7c.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-B1_ZziiB.js → KnowledgeGraph-Q9MTQ83c.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-DovEEnt_.js → Logs-B_fyjZK9.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-D201OL4T.js → MarkdownRenderer-C0o4FtpD.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-BlCXSpyB.js → Marketplace-BIStF9d1.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-CsCR09Wj.js → McpTools-pGfal768.js} +5 -5
- package/src/assets/web-panel/assets/{Memory-CBVRLKno.js → Memory-xbNqpIqB.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-C9OIafgA.js → MobileBridge-B5EQGrIK.js} +1 -1
- package/src/assets/web-panel/assets/MobileProjects-VTc3gT1y.js +1 -0
- package/src/assets/web-panel/assets/{Mtc-vE-HdvLj.js → Mtc-a_rmfxJH.js} +4 -4
- package/src/assets/web-panel/assets/{MtcAudit-CPLaekCd.js → MtcAudit-BmKuofUr.js} +4 -4
- package/src/assets/web-panel/assets/{Multisig-C_UP9C2o.js → Multisig-BQbJ-CAN.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-2nODJcU1.js → NLProgramming-JtPJKX25.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-BhE-SJGu.js → Notes-ZFKznTSG.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-D21q7BNU.js → NotificationSettings-B6aHRBBR.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-0b62GYOD.js → OrderTableRenderer-DdcsOqEz.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-CEqmw_sb.js → Organization-BFDTAUgS.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-MW-gMDO_.js → Overflow-0FoTfbWH.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-CY0hjI_G.js → P2P-CWd90etw.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-BbWh7Man.js → PdhVaultBrowser-DtCGC-W-.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-ChqEA_4Q.js → Permissions-CvQ7nr7T.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-B3YrbYfD.js → PersonalDataHub-rdNPcR-Z.js} +5 -5
- package/src/assets/web-panel/assets/{Pipeline-B8WBhhlW.js → Pipeline-CmrfiNOs.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-Cmb0PXNx.js → Privacy-D7ep1h_t.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-hF6zW3Nz.js → ProjectInit-C0xKINHS.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-BFSVfpW0.js → ProjectSettings-AOmZFp-F.js} +2 -2
- package/src/assets/web-panel/assets/Projects-BWHSkXZP.js +1 -0
- package/src/assets/web-panel/assets/{Providers-B8yux8Dx.js → Providers-Cb7JCTPL.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-N76cQluO.js → QrScannerModal-BDMehcXC.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-ClvZ0KYR.js → QuickAsk-BF6_1nvx.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-B-GfgBpT.js → Recommend-BHfT-A28.js} +1 -1
- package/src/assets/web-panel/assets/RemoteSession-B6EEf8hh.js +5 -0
- package/src/assets/web-panel/assets/{Reputation-DJIZzQeG.js → Reputation-CsWHLEcj.js} +1 -1
- package/src/assets/web-panel/assets/{Row-COzxu_bb.js → Row-D6srnWhm.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-CoYsJQuE.js → RssFeed-Xhr-KyVd.js} +3 -3
- package/src/assets/web-panel/assets/{Search-DC77Mq9S.js → Search-vIbIJvwL.js} +1 -1
- package/src/assets/web-panel/assets/{Security-Loy2EdMO.js → Security-Bzi5Aiko.js} +4 -4
- package/src/assets/web-panel/assets/{Services-GUD07Eu0.js → Services-BHtVX52P.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-DWzkptYU.js → Skeleton-C0R8B2jf.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-CEDn1r-Z.js → Skills-DtT6rWOX.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-ub_k4pXh.js → Sla-0B37mxVU.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-D7HLX9CA.js → SpeechSettings-0V2jE1Bs.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-DbwOvl6m.js → SyncSettings-CYedRzaj.js} +2 -2
- package/src/assets/web-panel/assets/Tasks-D-R1x8vm.js +1 -0
- package/src/assets/web-panel/assets/{Templates-BNVeIhud.js → Templates-BKoHztGT.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-PS9AzhXU.js → Tenant--17nwVNZ.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-Cgb4eLB_.js → Terminal-Dnkos7vW.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-CrmXMOkg.js → TimelineRenderer-C5jx4AE3.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-DD-VDHw1.js → Tokens-DYJKYa9t.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-BsoN_n-n.js → Trigger-DChpWiQ9.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-n8LmN4ZV.js → Trust-DfWG52EA.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-C9_7MImA.js → UkeySign-CMugYcyA.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-DyBteNgn.js → VideoEditing-BOSmrHAd.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-BS5ixeXI.js → Wallet-D5g3k3Sa.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-spc4UImU.js → WebAuthn-D-7u4Mkc.js} +3 -3
- package/src/assets/web-panel/assets/{WorkflowEditor-D7iVvaBO.js → WorkflowEditor-CFzZMSUJ.js} +1 -1
- package/src/assets/web-panel/assets/{chat-6CmBkHrL.js → chat-VbR6l6mc.js} +1 -1
- package/src/assets/web-panel/assets/{colors-BGoCLkxI.js → colors-BSZn8EDS.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-fYZBetMO.js → compact-item-y74obMEq.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-BeM-1UVj.js → createContext-C326bjex.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-D3Bho_6u.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-CE7ZuEnV.js → hasIn-D_INJQT_.js} +1 -1
- package/src/assets/web-panel/assets/{index-ukg99D1V.js → index-4PIeTM--.js} +1 -1
- package/src/assets/web-panel/assets/{index-B2U-ObMq.js → index-4eyH-eC2.js} +1 -1
- package/src/assets/web-panel/assets/index-5iAFwYx1.js +1 -0
- package/src/assets/web-panel/assets/{index-CRLjEP1H.js → index-9PIVuXqo.js} +1 -1
- package/src/assets/web-panel/assets/{index-BfPL-m46.js → index-B7SrC-On.js} +1 -1
- package/src/assets/web-panel/assets/{index--lap6cf7.js → index-BJi3UqBt.js} +1 -1
- package/src/assets/web-panel/assets/{index-B3CDgvNW.js → index-BY8-nCgs.js} +1 -1
- package/src/assets/web-panel/assets/index-BfnB7LPx.js +1 -0
- package/src/assets/web-panel/assets/{index-De0quFDw.js → index-Bfw2hf2s.js} +1 -1
- package/src/assets/web-panel/assets/{index-BunaQCa0.js → index-BjcWKg1S.js} +1 -1
- package/src/assets/web-panel/assets/{index-BsMfoaeo.js → index-BnSfnSMP.js} +1 -1
- package/src/assets/web-panel/assets/{index-C0v6YKKO.js → index-Bnua8IX3.js} +1 -1
- package/src/assets/web-panel/assets/{index-C4SJVjs4.js → index-C-ZCaUJc.js} +1 -1
- package/src/assets/web-panel/assets/{index-BNZDILcO.js → index-C2NyllnW.js} +1 -1
- package/src/assets/web-panel/assets/{index-YjcumOZ4.js → index-C327pLbw.js} +1 -1
- package/src/assets/web-panel/assets/{index-CRnUE8Cb.js → index-CMHqs3Jb.js} +1 -1
- package/src/assets/web-panel/assets/{index-CIpVrf5P.js → index-CfLJ42kv.js} +1 -1
- package/src/assets/web-panel/assets/{index-BEVm0lCS.js → index-Cr3uuz0C.js} +3 -3
- package/src/assets/web-panel/assets/{index-Dw1PyYPm.js → index-CsovTpx9.js} +1 -1
- package/src/assets/web-panel/assets/{index-lJBjB1QX.js → index-CzE53HiB.js} +1 -1
- package/src/assets/web-panel/assets/{index-CpIGIB85.js → index-DBkzrpiL.js} +1 -1
- package/src/assets/web-panel/assets/{index-DoXk5KJ8.js → index-DNMxIsDg.js} +1 -1
- package/src/assets/web-panel/assets/{index-DsvfrESp.js → index-DUU2606o.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cip8emOQ.js → index-DdyjrCAu.js} +1 -1
- package/src/assets/web-panel/assets/{index-ATcSr_2O.js → index-DkH1JvEt.js} +1 -1
- package/src/assets/web-panel/assets/{index-BV551878.js → index-Dlxh9D8D.js} +1 -1
- package/src/assets/web-panel/assets/{index-BU_2qiDk.js → index-DuIkfnTF.js} +1 -1
- package/src/assets/web-panel/assets/{index-zb7rVOhV.js → index-DwHSZLXg.js} +1 -1
- package/src/assets/web-panel/assets/{index-MtOuq2i6.js → index-E_v1ZCTP.js} +1 -1
- package/src/assets/web-panel/assets/{index-B8BsdNV_.js → index-FQBsuExX.js} +1 -1
- package/src/assets/web-panel/assets/{index-WUrJ6S1j.js → index-GA80ir_u.js} +1 -1
- package/src/assets/web-panel/assets/{index-RMZ8a7Yt.js → index-IZAWt0H8.js} +1 -1
- package/src/assets/web-panel/assets/{index-D1r9tT3J.js → index-Iw0FfqUz.js} +1 -1
- package/src/assets/web-panel/assets/{index-BowH1eLQ.js → index-KF9Zmqln.js} +1 -1
- package/src/assets/web-panel/assets/{index-Puq6Luf1.js → index-abmn_8Yz.js} +1 -1
- package/src/assets/web-panel/assets/{index-QIpnpZgz.js → index-gINyI1rh.js} +1 -1
- package/src/assets/web-panel/assets/{index-C9Y3k0HI.js → index-jYaogFE8.js} +1 -1
- package/src/assets/web-panel/assets/{index-B4wiTEOM.js → index-nSn2-C4N.js} +1 -1
- package/src/assets/web-panel/assets/{index-DT3zPSVX.js → index-qMA4GYdQ.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-CYHMs1ag.js → initDefaultProps-DI0Zaf8-.js} +1 -1
- package/src/assets/web-panel/assets/{motion-DDB2Ffk5.js → motion-BZDKSy3Z.js} +1 -1
- package/src/assets/web-panel/assets/{move-Bg3cD-dX.js → move-DsIW01Vp.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-B5nedjTS.js → mtc-parser-CohkDhsf.js} +1 -1
- package/src/assets/web-panel/assets/{omit-BHyuUILu.js → omit-DpiN5rzg.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-C9YQnEN9.js → pickAttrs-qbuqni3y.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-DBUFYUe7.js → placementArrow-mBky6714.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-nBs2Obnk.js → responsiveObserve-Bas3eQ2K.js} +1 -1
- package/src/assets/web-panel/assets/{slide-DkCEaXNU.js → slide-CBx_SKoK.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-aqE1Wi6U.js → statusUtils-BlYguJSV.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-CN5bhfHB.js → styleChecker-BCYQmRGv.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-B_oX_kvJ.js → useFlexGapSupport-Dp5dybLM.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-rCuXHeme.js → useFs-DHAMBgA2.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-DZR9Abyd.js → usePersonalDataHub-W6jsSw76.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-ConCYQlX.js → vnode-BkI6aayc.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-CUdDxG5M.js → zoom-C_IMGueq.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/agenda.js +115 -3
- package/src/commands/agent.js +15 -0
- package/src/commands/background-session.js +49 -0
- package/src/commands/plugin.js +235 -23
- package/src/commands/session.js +13 -0
- package/src/data/changelog.json +26 -0
- package/src/gateways/terminal/PtyManager.js +45 -4
- package/src/gateways/ws/ws-server.js +10 -1
- package/src/harness/background-task-manager.js +70 -2
- package/src/harness/jsonl-session-store.js +6 -4
- package/src/harness/worktree-isolator.js +14 -3
- package/src/lib/agent-core.js +1 -0
- package/src/lib/agent-schedule-store.js +45 -22
- package/src/lib/agent-team/team-runner.js +19 -1
- package/src/lib/background-agent-supervisor.js +49 -0
- package/src/lib/hook-runner.js +6 -2
- package/src/lib/packer/pkg-config-generator.js +3 -1
- package/src/lib/plugin-runtime/bin.js +1148 -70
- package/src/lib/plugin-runtime/install.js +226 -7
- package/src/lib/plugin-runtime/manifest.js +68 -12
- package/src/lib/plugin-runtime/scopes.js +33 -12
- package/src/lib/plugin-usage-attribution.js +44 -0
- package/src/lib/process-execution-broker/index.js +626 -48
- package/src/lib/process-execution-broker/platform-sandbox.js +4971 -266
- 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 +3856 -0
- package/src/lib/repl-bang-memorize.js +67 -10
- package/src/lib/session-usage.js +77 -0
- package/src/lib/slash-commands.js +27 -4
- package/src/repl/agent-repl.js +10 -9
- package/src/runtime/agent-core.js +376 -52
- package/src/runtime/agent-runtime.js +13 -1
- package/src/runtime/headless-runner.js +13 -4
- package/src/runtime/headless-stream.js +20 -1
- package/src/runtime/mcp-config.js +15 -5
- package/src/assets/web-panel/assets/ChatBubbleRenderer-BKPPNmZI.js +0 -1
- package/src/assets/web-panel/assets/MobileProjects-D_zoJ8Xs.js +0 -1
- package/src/assets/web-panel/assets/Projects-DAWkVFkc.js +0 -1
- package/src/assets/web-panel/assets/RemoteSession-mlglCdQi.js +0 -5
- package/src/assets/web-panel/assets/Tasks-CBQzoAu5.js +0 -1
- package/src/assets/web-panel/assets/devWarning-BzPwHnw8.js +0 -1
- package/src/assets/web-panel/assets/index-DacrAdc-.js +0 -1
- package/src/assets/web-panel/assets/index-EHzNJozo.js +0 -1
- package/src/lib/process-execution-broker/windows-sandbox.ps1 +0 -999
package/src/commands/agent.js
CHANGED
|
@@ -757,6 +757,12 @@ export function registerAgentCommand(program) {
|
|
|
757
757
|
process.stderr.write(
|
|
758
758
|
"--permission-prompt-tool requires --mcp-config (the tool must come from a loaded MCP server).\n",
|
|
759
759
|
);
|
|
760
|
+
// Complete worktree cleanup while the async command action is still
|
|
761
|
+
// running. Windows hosted runners do not reliably permit the exit
|
|
762
|
+
// handler to start the synchronous git subprocesses needed to remove
|
|
763
|
+
// the linked worktree, so the exit hook remains only a last-resort
|
|
764
|
+
// fallback for unexpected termination paths.
|
|
765
|
+
await _finishWorktree();
|
|
760
766
|
process.exit(1);
|
|
761
767
|
}
|
|
762
768
|
|
|
@@ -1125,6 +1131,15 @@ export function registerAgentCommand(program) {
|
|
|
1125
1131
|
title: prompt.slice(0, 100),
|
|
1126
1132
|
followUpArgv,
|
|
1127
1133
|
worktree: _worktree,
|
|
1134
|
+
governance: {
|
|
1135
|
+
permissionMode: options.permissionMode || "default",
|
|
1136
|
+
resourceBudget: {
|
|
1137
|
+
maxTurns: options.maxTurns
|
|
1138
|
+
? parseInt(options.maxTurns, 10)
|
|
1139
|
+
: null,
|
|
1140
|
+
maxCostUsd,
|
|
1141
|
+
},
|
|
1142
|
+
},
|
|
1128
1143
|
});
|
|
1129
1144
|
if (_worktree) {
|
|
1130
1145
|
// Ownership moves to the persisted background session only after
|
|
@@ -2,6 +2,7 @@ import { existsSync, readFileSync } from "node:fs";
|
|
|
2
2
|
import chalk from "chalk";
|
|
3
3
|
import { logger } from "../lib/logger.js";
|
|
4
4
|
import { readPrLinkLedger } from "../lib/pr-link-ledger.js";
|
|
5
|
+
import { loadSideEffectLedger } from "../lib/side-effect-ledger-store.js";
|
|
5
6
|
import executionBroker from "../lib/process-execution-broker/index.js";
|
|
6
7
|
|
|
7
8
|
function formatAge(ms) {
|
|
@@ -74,6 +75,21 @@ export function formatBackgroundAgentDetails(
|
|
|
74
75
|
lines.push(` branch: ${session.branch || "-"}`);
|
|
75
76
|
lines.push(` baseSha: ${session.baseSha || "-"}`);
|
|
76
77
|
}
|
|
78
|
+
if (session.governance) {
|
|
79
|
+
const governance = session.governance;
|
|
80
|
+
const budget = governance.resourceBudget || {};
|
|
81
|
+
lines.push(` owner: ${governance.owner || "-"}`);
|
|
82
|
+
lines.push(` permissionMode: ${governance.permissionMode || "default"}`);
|
|
83
|
+
lines.push(
|
|
84
|
+
` budget: turns=${budget.maxTurns || "unlimited"} costUsd=${budget.maxCostUsd || "unlimited"}`,
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
if (session.sideEffects) {
|
|
88
|
+
const effects = session.sideEffects;
|
|
89
|
+
lines.push(
|
|
90
|
+
` sideEffects: total=${effects.total || 0} unsettled=${effects.unsettled || 0} unknown=${effects.unknown || 0}`,
|
|
91
|
+
);
|
|
92
|
+
}
|
|
77
93
|
if (session.phase) lines.push(` phase: ${session.phase}`);
|
|
78
94
|
if (session.pr?.number) {
|
|
79
95
|
lines.push(
|
|
@@ -101,6 +117,27 @@ export function formatBackgroundAgentDetails(
|
|
|
101
117
|
return lines.join("\n");
|
|
102
118
|
}
|
|
103
119
|
|
|
120
|
+
export function summarizeSideEffects(ledger) {
|
|
121
|
+
const ops =
|
|
122
|
+
ledger && typeof ledger.list === "function"
|
|
123
|
+
? ledger.list()
|
|
124
|
+
: Array.isArray(ledger?.ops)
|
|
125
|
+
? ledger.ops
|
|
126
|
+
: [];
|
|
127
|
+
const count = (state) => ops.filter((op) => op?.state === state).length;
|
|
128
|
+
return {
|
|
129
|
+
total: ops.length,
|
|
130
|
+
prepared: count("prepared"),
|
|
131
|
+
started: count("started"),
|
|
132
|
+
committed: count("committed"),
|
|
133
|
+
failed: count("failed"),
|
|
134
|
+
unknown: count("unknown"),
|
|
135
|
+
unsettled: ops.filter(
|
|
136
|
+
(op) => op?.state === "prepared" || op?.state === "started",
|
|
137
|
+
).length,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
104
141
|
function parseLines(value, fallback) {
|
|
105
142
|
const n = Number(value);
|
|
106
143
|
return Number.isFinite(n) && n > 0 ? Math.floor(n) : fallback;
|
|
@@ -447,6 +484,18 @@ async function runDashboardView(options = {}) {
|
|
|
447
484
|
} catch {
|
|
448
485
|
/* PR decoration is cosmetic */
|
|
449
486
|
}
|
|
487
|
+
for (const s of sessions) {
|
|
488
|
+
if (!s.sessionId) continue;
|
|
489
|
+
try {
|
|
490
|
+
s.sideEffects = summarizeSideEffects(
|
|
491
|
+
loadSideEffectLedger(s.sessionId, {
|
|
492
|
+
failIfUnavailable: false,
|
|
493
|
+
}),
|
|
494
|
+
);
|
|
495
|
+
} catch {
|
|
496
|
+
/* side-effect decoration is cosmetic */
|
|
497
|
+
}
|
|
498
|
+
}
|
|
450
499
|
return sessions;
|
|
451
500
|
};
|
|
452
501
|
|
package/src/commands/plugin.js
CHANGED
|
@@ -20,10 +20,8 @@ import {
|
|
|
20
20
|
removePlugin,
|
|
21
21
|
updatePlugin,
|
|
22
22
|
getPluginSettings,
|
|
23
|
-
setPluginSetting,
|
|
24
23
|
searchRegistry,
|
|
25
24
|
listRegistry,
|
|
26
|
-
registerInMarketplace,
|
|
27
25
|
getPluginSummary,
|
|
28
26
|
installPluginSkills,
|
|
29
27
|
removePluginSkills,
|
|
@@ -404,8 +402,28 @@ export function registerPluginCommand(program) {
|
|
|
404
402
|
.command("enable")
|
|
405
403
|
.description("Enable a plugin")
|
|
406
404
|
.argument("<name>", "Plugin name")
|
|
407
|
-
.
|
|
405
|
+
.option(
|
|
406
|
+
"--scope <scope>",
|
|
407
|
+
"Enable the unified-runtime install at this scope (user|project|local)",
|
|
408
|
+
)
|
|
409
|
+
.option("--json", "Output unified-runtime result as JSON")
|
|
410
|
+
.action(async (name, options) => {
|
|
408
411
|
try {
|
|
412
|
+
if (options.scope) {
|
|
413
|
+
const { setPluginEnabled } =
|
|
414
|
+
await import("../lib/plugin-runtime/install.js");
|
|
415
|
+
const result = setPluginEnabled(name, true, {
|
|
416
|
+
scope: options.scope,
|
|
417
|
+
cwd: process.cwd(),
|
|
418
|
+
});
|
|
419
|
+
if (options.json) console.log(JSON.stringify(result, null, 2));
|
|
420
|
+
else {
|
|
421
|
+
logger.success(
|
|
422
|
+
`Enabled ${name} (${options.scope} scope). Reload active plugin sessions to apply the change.`,
|
|
423
|
+
);
|
|
424
|
+
}
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
409
427
|
enforcePluginPolicy(
|
|
410
428
|
{ name, action: "enable" },
|
|
411
429
|
loadPluginManagedPolicy(),
|
|
@@ -436,8 +454,28 @@ export function registerPluginCommand(program) {
|
|
|
436
454
|
.command("disable")
|
|
437
455
|
.description("Disable a plugin")
|
|
438
456
|
.argument("<name>", "Plugin name")
|
|
439
|
-
.
|
|
457
|
+
.option(
|
|
458
|
+
"--scope <scope>",
|
|
459
|
+
"Disable the unified-runtime install at this scope (user|project|local)",
|
|
460
|
+
)
|
|
461
|
+
.option("--json", "Output unified-runtime result as JSON")
|
|
462
|
+
.action(async (name, options) => {
|
|
440
463
|
try {
|
|
464
|
+
if (options.scope) {
|
|
465
|
+
const { setPluginEnabled } =
|
|
466
|
+
await import("../lib/plugin-runtime/install.js");
|
|
467
|
+
const result = setPluginEnabled(name, false, {
|
|
468
|
+
scope: options.scope,
|
|
469
|
+
cwd: process.cwd(),
|
|
470
|
+
});
|
|
471
|
+
if (options.json) console.log(JSON.stringify(result, null, 2));
|
|
472
|
+
else {
|
|
473
|
+
logger.success(
|
|
474
|
+
`Disabled ${name} (${options.scope} scope). Reload active plugin sessions to apply the change.`,
|
|
475
|
+
);
|
|
476
|
+
}
|
|
477
|
+
return;
|
|
478
|
+
}
|
|
441
479
|
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
442
480
|
if (!ctx.db) {
|
|
443
481
|
logger.error("Database not available");
|
|
@@ -860,6 +898,7 @@ export function registerPluginCommand(program) {
|
|
|
860
898
|
// plugin name) resolves to a git source the installer already handles.
|
|
861
899
|
let installSource = source;
|
|
862
900
|
let integritySha = null;
|
|
901
|
+
let sourceMetadata = null;
|
|
863
902
|
const { isRemoteSource, resolveRemoteSource } =
|
|
864
903
|
await import("../lib/plugin-runtime/remote-source.js");
|
|
865
904
|
if (options.registry || isRemoteSource(source)) {
|
|
@@ -883,6 +922,19 @@ export function registerPluginCommand(program) {
|
|
|
883
922
|
});
|
|
884
923
|
installSource = resolved.source;
|
|
885
924
|
integritySha = resolved.sha256;
|
|
925
|
+
sourceMetadata = {
|
|
926
|
+
type: "registry",
|
|
927
|
+
source: url,
|
|
928
|
+
registry: url,
|
|
929
|
+
package: name || source,
|
|
930
|
+
resolvedSource: resolved.source,
|
|
931
|
+
ref:
|
|
932
|
+
(typeof resolved.source === "string" &&
|
|
933
|
+
resolved.source.includes("#") &&
|
|
934
|
+
resolved.source.slice(resolved.source.indexOf("#") + 1)) ||
|
|
935
|
+
null,
|
|
936
|
+
offline: resolved.fromCache === true,
|
|
937
|
+
};
|
|
886
938
|
if (resolved.fromCache) {
|
|
887
939
|
logger.warn(
|
|
888
940
|
chalk.yellow(
|
|
@@ -897,13 +949,31 @@ export function registerPluginCommand(program) {
|
|
|
897
949
|
}
|
|
898
950
|
}
|
|
899
951
|
|
|
952
|
+
let managed = null;
|
|
953
|
+
try {
|
|
954
|
+
managed = loadPluginManagedPolicy();
|
|
955
|
+
} catch (err) {
|
|
956
|
+
logger.error(`Managed plugin policy is invalid: ${err.message}`);
|
|
957
|
+
process.exitCode = 1;
|
|
958
|
+
return;
|
|
959
|
+
}
|
|
960
|
+
const requiresManagedSignature =
|
|
961
|
+
managed?.requireSignedPlugins === true ||
|
|
962
|
+
managed?.requireSignedPlugins === "require";
|
|
900
963
|
const signature =
|
|
901
|
-
options.sha256 ||
|
|
964
|
+
options.sha256 ||
|
|
965
|
+
options.signature ||
|
|
966
|
+
options.publicKey ||
|
|
967
|
+
integritySha ||
|
|
968
|
+
requiresManagedSignature
|
|
902
969
|
? {
|
|
903
970
|
sha256: options.sha256 || integritySha,
|
|
904
971
|
signatureFile: options.signature,
|
|
905
972
|
publicKeyFile: options.publicKey,
|
|
906
|
-
requireSignature:
|
|
973
|
+
requireSignature:
|
|
974
|
+
Boolean(options.signature) || requiresManagedSignature,
|
|
975
|
+
trustedKeySha256: managed?.trustedPluginKeySha256 || null,
|
|
976
|
+
requireTrustedKey: requiresManagedSignature,
|
|
907
977
|
}
|
|
908
978
|
: null;
|
|
909
979
|
try {
|
|
@@ -912,6 +982,9 @@ export function registerPluginCommand(program) {
|
|
|
912
982
|
cwd: process.cwd(),
|
|
913
983
|
force: options.force === true,
|
|
914
984
|
signature,
|
|
985
|
+
sourceMetadata,
|
|
986
|
+
managedPolicy: managed,
|
|
987
|
+
policySource: options.registry || source,
|
|
915
988
|
});
|
|
916
989
|
const capNotice = await resolvePluginCapabilityNotice(
|
|
917
990
|
res.name,
|
|
@@ -1060,8 +1133,21 @@ export function registerPluginCommand(program) {
|
|
|
1060
1133
|
const trust = isPluginTrusted(r)
|
|
1061
1134
|
? chalk.green("trusted")
|
|
1062
1135
|
: chalk.yellow("untrusted");
|
|
1136
|
+
const state =
|
|
1137
|
+
r.enabled === false
|
|
1138
|
+
? chalk.yellow("disabled")
|
|
1139
|
+
: chalk.green("enabled");
|
|
1140
|
+
const signed = r.integrity?.signature?.verified
|
|
1141
|
+
? chalk.green("signed")
|
|
1142
|
+
: chalk.gray("unsigned");
|
|
1143
|
+
const policy =
|
|
1144
|
+
r.policy?.allowed === false
|
|
1145
|
+
? chalk.red("policy-blocked")
|
|
1146
|
+
: r.policy?.managed
|
|
1147
|
+
? chalk.cyan("managed")
|
|
1148
|
+
: "";
|
|
1063
1149
|
logger.log(
|
|
1064
|
-
` ${ok} ${chalk.cyan(r.name)} v${r.version} ${chalk.gray(`[${r.scope}]`)} ${trust}`,
|
|
1150
|
+
` ${ok} ${chalk.cyan(r.name)} v${r.version} ${chalk.gray(`[${r.scope}]`)} ${state} ${trust} ${signed}${policy ? ` ${policy}` : ""}`,
|
|
1065
1151
|
);
|
|
1066
1152
|
}
|
|
1067
1153
|
});
|
|
@@ -1456,22 +1542,162 @@ export function registerPluginCommand(program) {
|
|
|
1456
1542
|
plugin
|
|
1457
1543
|
.command("upgrade <source>")
|
|
1458
1544
|
.description(
|
|
1459
|
-
"Update a runtime plugin from its
|
|
1545
|
+
"Update a runtime plugin from its pinned local, git, or registry source; repoints .active",
|
|
1460
1546
|
)
|
|
1461
1547
|
.option("--scope <scope>", `Scope to update in (${SCOPES})`, "user")
|
|
1462
1548
|
.option("--force", "Reinstall even if the version is unchanged")
|
|
1549
|
+
.option("--sha256 <hex>", "Expected SHA-256 of the manifest file")
|
|
1550
|
+
.option("--signature <path>", "Detached Ed25519 signature of the manifest")
|
|
1551
|
+
.option("--public-key <path>", "Public key for signature verification")
|
|
1552
|
+
.option(
|
|
1553
|
+
"--registry <url>",
|
|
1554
|
+
"Resolve <source> as a plugin NAME in this registry URL",
|
|
1555
|
+
)
|
|
1556
|
+
.option(
|
|
1557
|
+
"--name <plugin>",
|
|
1558
|
+
"Plugin name to select from a multi-plugin registry",
|
|
1559
|
+
)
|
|
1560
|
+
.option("--token <token>", "Bearer token for a private registry")
|
|
1561
|
+
.option(
|
|
1562
|
+
"--allow-insecure-registry",
|
|
1563
|
+
"Allow a plain-HTTP registry URL (MITM risk — trusted networks only)",
|
|
1564
|
+
)
|
|
1463
1565
|
.option(
|
|
1464
1566
|
"--grant-capabilities",
|
|
1465
1567
|
"Grant any newly declared capabilities during the upgrade (no separate consent step)",
|
|
1466
1568
|
)
|
|
1569
|
+
.option("--json", "Output as JSON")
|
|
1467
1570
|
.action(async (source, options) => {
|
|
1468
1571
|
const { updatePlugin } = await import("../lib/plugin-runtime/install.js");
|
|
1572
|
+
let installSource = source;
|
|
1573
|
+
let integritySha = null;
|
|
1574
|
+
let sourceMetadata = null;
|
|
1575
|
+
const { isRemoteSource, resolveRemoteSource } =
|
|
1576
|
+
await import("../lib/plugin-runtime/remote-source.js");
|
|
1577
|
+
if (options.registry || isRemoteSource(source)) {
|
|
1578
|
+
const url = options.registry || source;
|
|
1579
|
+
const name = options.registry ? source : options.name;
|
|
1580
|
+
let config = null;
|
|
1581
|
+
try {
|
|
1582
|
+
const cm = await import("../lib/config-manager.js");
|
|
1583
|
+
config = cm.loadConfig();
|
|
1584
|
+
} catch {
|
|
1585
|
+
config = null;
|
|
1586
|
+
}
|
|
1587
|
+
try {
|
|
1588
|
+
const resolved = await resolveRemoteSource(url, {
|
|
1589
|
+
name,
|
|
1590
|
+
token: options.token,
|
|
1591
|
+
config,
|
|
1592
|
+
allowInsecure: options.allowInsecureRegistry === true,
|
|
1593
|
+
});
|
|
1594
|
+
installSource = resolved.source;
|
|
1595
|
+
integritySha = resolved.sha256;
|
|
1596
|
+
sourceMetadata = {
|
|
1597
|
+
type: "registry",
|
|
1598
|
+
source: url,
|
|
1599
|
+
registry: url,
|
|
1600
|
+
package: name || source,
|
|
1601
|
+
resolvedSource: resolved.source,
|
|
1602
|
+
ref:
|
|
1603
|
+
(typeof resolved.source === "string" &&
|
|
1604
|
+
resolved.source.includes("#") &&
|
|
1605
|
+
resolved.source.slice(resolved.source.indexOf("#") + 1)) ||
|
|
1606
|
+
null,
|
|
1607
|
+
offline: resolved.fromCache === true,
|
|
1608
|
+
};
|
|
1609
|
+
if (resolved.fromCache && !options.json) {
|
|
1610
|
+
logger.warn(
|
|
1611
|
+
chalk.yellow(
|
|
1612
|
+
" ⚠ registry unreachable — using cached copy (offline)",
|
|
1613
|
+
),
|
|
1614
|
+
);
|
|
1615
|
+
}
|
|
1616
|
+
} catch (err) {
|
|
1617
|
+
logger.error(`Registry resolution failed: ${err.message}`);
|
|
1618
|
+
process.exitCode = 1;
|
|
1619
|
+
return;
|
|
1620
|
+
}
|
|
1621
|
+
}
|
|
1622
|
+
|
|
1623
|
+
let managed = null;
|
|
1469
1624
|
try {
|
|
1470
|
-
|
|
1625
|
+
managed = loadPluginManagedPolicy();
|
|
1626
|
+
} catch (err) {
|
|
1627
|
+
logger.error(`Managed plugin policy is invalid: ${err.message}`);
|
|
1628
|
+
process.exitCode = 1;
|
|
1629
|
+
return;
|
|
1630
|
+
}
|
|
1631
|
+
const requiresManagedSignature =
|
|
1632
|
+
managed?.requireSignedPlugins === true ||
|
|
1633
|
+
managed?.requireSignedPlugins === "require";
|
|
1634
|
+
const signature =
|
|
1635
|
+
options.sha256 ||
|
|
1636
|
+
options.signature ||
|
|
1637
|
+
options.publicKey ||
|
|
1638
|
+
integritySha ||
|
|
1639
|
+
requiresManagedSignature
|
|
1640
|
+
? {
|
|
1641
|
+
sha256: options.sha256 || integritySha,
|
|
1642
|
+
signatureFile: options.signature,
|
|
1643
|
+
publicKeyFile: options.publicKey,
|
|
1644
|
+
requireSignature:
|
|
1645
|
+
Boolean(options.signature) || requiresManagedSignature,
|
|
1646
|
+
trustedKeySha256: managed?.trustedPluginKeySha256 || null,
|
|
1647
|
+
requireTrustedKey: requiresManagedSignature,
|
|
1648
|
+
}
|
|
1649
|
+
: null;
|
|
1650
|
+
try {
|
|
1651
|
+
const res = updatePlugin(installSource, {
|
|
1471
1652
|
scope: options.scope,
|
|
1472
1653
|
cwd: process.cwd(),
|
|
1473
1654
|
force: options.force,
|
|
1655
|
+
signature,
|
|
1656
|
+
sourceMetadata,
|
|
1657
|
+
managedPolicy: managed,
|
|
1658
|
+
policySource: options.registry || source,
|
|
1474
1659
|
});
|
|
1660
|
+
const upgradeNotice = await resolvePluginCapabilityNotice(
|
|
1661
|
+
res.name,
|
|
1662
|
+
options.scope,
|
|
1663
|
+
process.cwd(),
|
|
1664
|
+
);
|
|
1665
|
+
if (res.updated || res.reinstalled)
|
|
1666
|
+
await auditPluginInstall(
|
|
1667
|
+
"upgrade",
|
|
1668
|
+
{ ...res, scope: options.scope },
|
|
1669
|
+
installSource,
|
|
1670
|
+
upgradeNotice,
|
|
1671
|
+
);
|
|
1672
|
+
|
|
1673
|
+
if (options.json) {
|
|
1674
|
+
let capabilitiesGranted = false;
|
|
1675
|
+
if (
|
|
1676
|
+
options.grantCapabilities &&
|
|
1677
|
+
upgradeNotice &&
|
|
1678
|
+
!upgradeNotice.consented
|
|
1679
|
+
) {
|
|
1680
|
+
capabilitiesGranted = await grantInstalledPluginCapabilities(
|
|
1681
|
+
res.name,
|
|
1682
|
+
options.scope,
|
|
1683
|
+
process.cwd(),
|
|
1684
|
+
);
|
|
1685
|
+
}
|
|
1686
|
+
console.log(
|
|
1687
|
+
JSON.stringify(
|
|
1688
|
+
{
|
|
1689
|
+
...res,
|
|
1690
|
+
scope: options.scope,
|
|
1691
|
+
capabilities: upgradeNotice,
|
|
1692
|
+
capabilitiesGranted,
|
|
1693
|
+
},
|
|
1694
|
+
null,
|
|
1695
|
+
2,
|
|
1696
|
+
),
|
|
1697
|
+
);
|
|
1698
|
+
return;
|
|
1699
|
+
}
|
|
1700
|
+
|
|
1475
1701
|
if (res.updated) {
|
|
1476
1702
|
logger.success(
|
|
1477
1703
|
`Updated ${res.name}: ${res.previousVersion ? `v${res.previousVersion} → ` : ""}v${res.version} (${options.scope} scope)`,
|
|
@@ -1489,20 +1715,6 @@ export function registerPluginCommand(program) {
|
|
|
1489
1715
|
// upgrade that adds a capability shows a `⚠ capability consent required`
|
|
1490
1716
|
// notice diffed against the prior consent, then either auto-grants
|
|
1491
1717
|
// (--grant-capabilities) or blocks interactively to re-consent now.
|
|
1492
|
-
const upgradeNotice = await resolvePluginCapabilityNotice(
|
|
1493
|
-
res.name,
|
|
1494
|
-
options.scope,
|
|
1495
|
-
process.cwd(),
|
|
1496
|
-
);
|
|
1497
|
-
// Only a version that actually landed on disk is an install; an
|
|
1498
|
-
// already-up-to-date no-op fetched nothing new to run.
|
|
1499
|
-
if (res.updated || res.reinstalled)
|
|
1500
|
-
await auditPluginInstall(
|
|
1501
|
-
"upgrade",
|
|
1502
|
-
{ ...res, scope: options.scope },
|
|
1503
|
-
source,
|
|
1504
|
-
upgradeNotice,
|
|
1505
|
-
);
|
|
1506
1718
|
await applyCapabilityConsentGate(
|
|
1507
1719
|
res.name,
|
|
1508
1720
|
options.scope,
|
package/src/commands/session.js
CHANGED
|
@@ -1333,6 +1333,7 @@ export function registerSessionCommand(program) {
|
|
|
1333
1333
|
"subagent",
|
|
1334
1334
|
"tool",
|
|
1335
1335
|
"mcp",
|
|
1336
|
+
"plugin",
|
|
1336
1337
|
"model",
|
|
1337
1338
|
];
|
|
1338
1339
|
|
|
@@ -1403,6 +1404,18 @@ export function registerSessionCommand(program) {
|
|
|
1403
1404
|
);
|
|
1404
1405
|
return;
|
|
1405
1406
|
}
|
|
1407
|
+
case "plugin": {
|
|
1408
|
+
const rows = a.tools?.byPlugin || [];
|
|
1409
|
+
if (rows.length === 0) return empty("plugin-attributed tool calls");
|
|
1410
|
+
for (const r of rows)
|
|
1411
|
+
toolRow(`${r.plugin}${r.version ? `@${r.version}` : ""}`, r);
|
|
1412
|
+
logger.log(
|
|
1413
|
+
chalk.gray(
|
|
1414
|
+
" turnTokens = tokens of turns that used the plugin (approximation; do not sum across rows)",
|
|
1415
|
+
),
|
|
1416
|
+
);
|
|
1417
|
+
return;
|
|
1418
|
+
}
|
|
1406
1419
|
default:
|
|
1407
1420
|
break;
|
|
1408
1421
|
}
|
package/src/data/changelog.json
CHANGED
|
@@ -1,6 +1,32 @@
|
|
|
1
1
|
{
|
|
2
2
|
"source": "CHANGELOG.md",
|
|
3
3
|
"releases": [
|
|
4
|
+
{
|
|
5
|
+
"productVersion": null,
|
|
6
|
+
"cliVersion": "0.162.183",
|
|
7
|
+
"cliVersions": ["0.4.74", "0.37.35", "0.162.182", "0.162.183"],
|
|
8
|
+
"date": "2026-07-27",
|
|
9
|
+
"title": "",
|
|
10
|
+
"sections": [
|
|
11
|
+
{
|
|
12
|
+
"heading": "Added — cc CLI 0.162.183 + IDE quality, plugin, and worktree governance",
|
|
13
|
+
"body": "> `chainlesschain` **0.162.182 → 0.162.183**, VS Code\n> **0.37.34 → 0.37.35**, and JetBrains **0.4.73 → 0.4.74** (2026-07-27).\n> `@chainlesschain/personal-data-hub` remains **0.4.57** and\n> `@chainlesschain/agent-sdk` remains **0.1.7**.\n\n- **IDE-native quality context**: both IDE bridges negotiate bounded\n `cc-ide-quality/v1` test-result, coverage, and debugger snapshots with\n Context v2 freshness metadata; VS Code notebook execution now carries its\n real notebook context.\n- **Installation Doctor depth**: VS Code and JetBrains report Node/Java\n availability plus managed-CLI and plugin-registry offline recovery state,\n without probing executables from an untrusted workspace directory.\n- **Plugin lifecycle and supply-chain UI**: scoped enable/disable, source-aware\n upgrades, live-session reload, signature/SBOM summaries, managed-policy\n provenance, and sanitized registry/Git/local source metadata stay governed\n by the CLI runtime.\n- **Plugin usage attribution**: compact transcripts and usage reports now\n attribute plugin-bin and plugin-provided MCP calls by plugin/version without\n persisting tool arguments.\n- **Supervised worktree tasks**: IDE-created isolated tasks run as background\n worktree agents and display canonical lifecycle, owner/session, permission\n mode, resource budget, and bounded side-effect counts. Team and batch rows\n remain explicitly unmanaged until they expose equivalent durable state.\n- **Release validation**: publication remains gated on the exact release\n commit passing CLI CI, CLI Strict Sandbox, background reconnect E2E, packaged\n VSIX Extension Host gates, JetBrains unit/build/Remote Robot gates, and\n public marketplace readback."
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"productVersion": null,
|
|
19
|
+
"cliVersion": "0.162.182",
|
|
20
|
+
"cliVersions": ["0.162.181", "0.162.182"],
|
|
21
|
+
"date": "2026-07-27",
|
|
22
|
+
"title": "",
|
|
23
|
+
"sections": [
|
|
24
|
+
{
|
|
25
|
+
"heading": "Fixed — cc CLI 0.162.182: attested native plugin sandbox closure",
|
|
26
|
+
"body": "> `chainlesschain` **0.162.181 → 0.162.182** (2026-07-27).\n> CLI-only release; `@chainlesschain/personal-data-hub` remains **0.4.57**\n> and `@chainlesschain/agent-sdk` remains **0.1.7**.\n\n- **One-shot native plugin execution contracts**: policy-bearing native plugin\n bins must preserve the resolver-issued target, literal argv, plugin root, and\n executable identity through the process broker. Replayed, copied, stale, or\n asynchronous contracts fail closed before a target process is started.\n- **Linux strong boundary completion**: strict native launches accept only\n attested static ELF executables for the current architecture, reject dynamic\n loaders and malformed program headers, pin the plugin tree through file\n descriptors, and enter the fixed bubblewrap filesystem/network policy\n without exposing a mutable host path.\n- **Cross-platform identity hardening**: Windows AppContainer launches retain\n attested target handles, while platform adapters revalidate executable and\n plugin identities across probe, spawn, IPC, and detached launch boundaries.\n- **Release validation gate**: the exact release commit must pass `CLI CI` and\n `CLI Strict Sandbox` on their configured Ubuntu, Windows, and macOS runners;\n local tests are supplementary and cannot authorize publication."
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
},
|
|
4
30
|
{
|
|
5
31
|
"productVersion": null,
|
|
6
32
|
"cliVersion": "0.162.181",
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* PtyManager — ESM mirror of `desktop-app-vue/src/main/terminal/PtyManager.js`.
|
|
3
3
|
*
|
|
4
|
-
* Keep
|
|
5
|
-
* process; this one targets `cc ui` (Node ESM)
|
|
6
|
-
*
|
|
4
|
+
* Keep their protocol and session behavior in sync. The desktop copy targets
|
|
5
|
+
* Electron's CJS main process; this one targets `cc ui` (Node ESM), whose host
|
|
6
|
+
* injects its own trusted workspace-policy resolver.
|
|
7
7
|
*
|
|
8
8
|
* Design notes — see docs/design/Android_Remote_Terminal_Plan_A.md §4:
|
|
9
9
|
* - node-pty loaded lazily so the module loads without the native
|
|
@@ -44,6 +44,24 @@ function resolveShellCmd(shell) {
|
|
|
44
44
|
return shell;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
function validatePinnedSandboxPolicy(policy) {
|
|
48
|
+
if (policy == null) return null;
|
|
49
|
+
if (
|
|
50
|
+
typeof policy !== "object" ||
|
|
51
|
+
Array.isArray(policy) ||
|
|
52
|
+
typeof policy.then === "function" ||
|
|
53
|
+
!Array.isArray(policy.requiredBoundaries) ||
|
|
54
|
+
policy.requiredBoundaries.length === 0 ||
|
|
55
|
+
!Object.isFrozen(policy) ||
|
|
56
|
+
!Object.isFrozen(policy.requiredBoundaries)
|
|
57
|
+
) {
|
|
58
|
+
const error = new TypeError("invalid_pty_sandbox_policy");
|
|
59
|
+
error.code = "ERR_PTY_SANDBOX_POLICY_INVALID";
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
return policy;
|
|
63
|
+
}
|
|
64
|
+
|
|
47
65
|
class PtySession {
|
|
48
66
|
constructor({ id, shell, cwd, cols, rows, proc, createdAt, ringBuffer }) {
|
|
49
67
|
this.id = id;
|
|
@@ -65,6 +83,16 @@ export class PtyManager extends EventEmitter {
|
|
|
65
83
|
constructor(opts = {}) {
|
|
66
84
|
super();
|
|
67
85
|
this.config = { ...DEFAULT_CONFIG, ...(opts.config || {}) };
|
|
86
|
+
const resolveSandboxPolicy =
|
|
87
|
+
opts.resolveSandboxPolicy ?? opts._deps?.resolveSandboxPolicy ?? null;
|
|
88
|
+
if (
|
|
89
|
+
resolveSandboxPolicy !== null &&
|
|
90
|
+
typeof resolveSandboxPolicy !== "function"
|
|
91
|
+
) {
|
|
92
|
+
throw new TypeError("resolveSandboxPolicy must be a function or null");
|
|
93
|
+
}
|
|
94
|
+
this._policyCwd = opts.policyCwd || process.cwd();
|
|
95
|
+
this._resolveSandboxPolicy = resolveSandboxPolicy;
|
|
68
96
|
this._deps = {
|
|
69
97
|
loadNodePty: opts._deps?.loadNodePty || (() => require("node-pty")),
|
|
70
98
|
spawnPty: opts._deps?.spawnPty || null,
|
|
@@ -92,6 +120,19 @@ export class PtyManager extends EventEmitter {
|
|
|
92
120
|
throw new Error("shell_not_allowed");
|
|
93
121
|
}
|
|
94
122
|
|
|
123
|
+
const cwd = req.cwd || this.config.defaultCwd || process.cwd();
|
|
124
|
+
// A remote cwd may discover a stricter policy, but it must never replace
|
|
125
|
+
// the fixed workspace root supplied by the host. Resolve and validate the
|
|
126
|
+
// pinned policy before loading node-pty or allocating a native terminal.
|
|
127
|
+
const sandboxPolicy = this._resolveSandboxPolicy
|
|
128
|
+
? validatePinnedSandboxPolicy(
|
|
129
|
+
this._resolveSandboxPolicy({
|
|
130
|
+
workspaceCwd: this._policyCwd,
|
|
131
|
+
executionCwd: cwd,
|
|
132
|
+
}),
|
|
133
|
+
)
|
|
134
|
+
: null;
|
|
135
|
+
|
|
95
136
|
let pty;
|
|
96
137
|
try {
|
|
97
138
|
pty = this._deps.loadNodePty();
|
|
@@ -101,7 +142,6 @@ export class PtyManager extends EventEmitter {
|
|
|
101
142
|
throw err;
|
|
102
143
|
}
|
|
103
144
|
|
|
104
|
-
const cwd = req.cwd || this.config.defaultCwd || process.cwd();
|
|
105
145
|
const cols = Number.isFinite(req.cols) ? req.cols : 80;
|
|
106
146
|
const rows = Number.isFinite(req.rows) ? req.rows : 24;
|
|
107
147
|
const cmd = resolveShellCmd(shell);
|
|
@@ -123,6 +163,7 @@ export class PtyManager extends EventEmitter {
|
|
|
123
163
|
origin: "terminal:pty",
|
|
124
164
|
policy: "allow",
|
|
125
165
|
scope: "terminal",
|
|
166
|
+
...(sandboxPolicy ? { sandboxPolicy } : {}),
|
|
126
167
|
});
|
|
127
168
|
|
|
128
169
|
const sessionId = randomUUID();
|
|
@@ -114,6 +114,7 @@ import {
|
|
|
114
114
|
handleArtifactShow,
|
|
115
115
|
} from "./artifact-protocol.js";
|
|
116
116
|
import { executionBroker } from "../../lib/process-execution-broker/index.js";
|
|
117
|
+
import { collectWorkspacePluginBinSandboxPolicy } from "../../lib/plugin-runtime/bin.js";
|
|
117
118
|
|
|
118
119
|
export const _deps = {
|
|
119
120
|
spawn: (...args) => executionBroker.spawn(...args),
|
|
@@ -1215,7 +1216,15 @@ export class ChainlessChainWSServer extends EventEmitter {
|
|
|
1215
1216
|
if (this._taskManager) return this._taskManager;
|
|
1216
1217
|
const { BackgroundTaskManager } =
|
|
1217
1218
|
await import("../../harness/background-task-manager.js");
|
|
1218
|
-
this._taskManager = new BackgroundTaskManager({
|
|
1219
|
+
this._taskManager = new BackgroundTaskManager({
|
|
1220
|
+
recoverOnStart: true,
|
|
1221
|
+
policyCwd: this.projectRoot,
|
|
1222
|
+
resolveSandboxPolicy: ({ workspaceCwd, executionCwd }) =>
|
|
1223
|
+
collectWorkspacePluginBinSandboxPolicy({
|
|
1224
|
+
workspaceCwd,
|
|
1225
|
+
executionCwd,
|
|
1226
|
+
}),
|
|
1227
|
+
});
|
|
1219
1228
|
this._subscribeTaskNotifications();
|
|
1220
1229
|
return this._taskManager;
|
|
1221
1230
|
}
|