chainlesschain 0.162.198 → 0.162.200
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/bin/chainlesschain.js +14 -6
- package/package.json +4 -1
- package/scripts/command-lifecycle-report.mjs +94 -0
- package/src/assets/web-panel/assets/{AIOps-CSN-D2xb.js → AIOps-DcQ0bWKy.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-CBSMlGzv.js → ActionButton-GecwfFPt.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-3yr3Nt2t.js → Analytics-CD6iSt9v.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-1b-o3lMH.js → AppLayout-CDEtuEYf.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-Dr8rJi17.js → Artifacts-DS3jAjeW.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-2V689HC2.js → Audit-CcSJA048.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-DIxkNrD_.js → BackgroundAgents-DRo9Morb.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-Pg6BcwrE.js → Backup-Vw5MrWft.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-CLUpqyfH.js → BaseInput-DNHIu823.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-qVS8rD4G.js → Chat-DvAsO8-b.js} +5 -5
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-ti49X12Q.js → ChatBubbleRenderer-9aDuObay.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-Bs9AaEay.js → Checkbox-CKCa7tvn.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-Dvc1mq8q.js → Codegen-CIFvZdaT.js} +1 -1
- package/src/assets/web-panel/assets/{Col-C4_biO7A.js → Col-C79yz7bK.js} +1 -1
- package/src/assets/web-panel/assets/{Community-al25XQUV.js → Community-DVvZskLJ.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-D-ZDB8M1.js → Compact-oaew61hV.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-6lIfDz1W.js → Compliance-DqA7wmRx.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-DdI48XMJ.js → Cowork-B-qGadxa.js} +2 -2
- package/src/assets/web-panel/assets/{Cron-DF5HZd2g.js → Cron-CUlCl4sS.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-DuxeSvt3.js → Crosschain-CNOlr9DU.js} +1 -1
- package/src/assets/web-panel/assets/{DID-B9yHkUTd.js → DID-DJqFCT_3.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-Z5EuI3IM.js → Dashboard-CznGpphf.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-vuRfO3dY.js → Dropdown-_cJw218E.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-QFLCc1uL.js → EmailListRenderer-Dr-1BZ9C.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-BZ7EXkFJ.js → FamilyGuardDashboard-Dxf4xtSk.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-DycIEg2s.js → Federation-DOiG3i_1.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-Ba0H_7yG.js → FormItemContext-BzbMcFB9.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer--JgSTK-C.js → GenericCardRenderer-VbBrYttP.js} +1 -1
- package/src/assets/web-panel/assets/{Git-DEvTbldE.js → Git-CLG8E6ED.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-BJIljy18.js → Governance-LGJQfk_q.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-CVyW3G3q.js → Inference-DlQKx9lF.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-v8-borge.js → KnowledgeGraph-DU8vEouV.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-BCdS7gGo.js → Logs-FZIQOdln.js} +2 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-BJNWIrbw.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-AN6tGA2B.js → Marketplace-C_xd-zZI.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-DGViXASN.js → McpTools-q-YktphS.js} +5 -5
- package/src/assets/web-panel/assets/{Memory-Bpvmx9X4.js → Memory-Cq9OhDin.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-CTP-DOTC.js → MobileBridge-B03_R98T.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-C8qfktxn.js → MobileProjects-DZrk-qmF.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-ndYr0M1s.js → Mtc-BidCKW28.js} +2 -2
- package/src/assets/web-panel/assets/{MtcAudit-Ci0-YK7W.js → MtcAudit-r-iaMVM7.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-BehSTFW7.js → Multisig-CgTUFvff.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-B91_YBLv.js → NLProgramming-B7NvzfAV.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-BQlJ0-gq.js → Notes-80CWNqJI.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-CDgYMjYK.js → NotificationSettings-0H6xdiY3.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-BJkSlKeH.js → OrderTableRenderer-CKP4AFWy.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-B-b3cWCp.js → Organization-B8sxCV_h.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-CILUL4nL.js → Overflow-CW9JBBhQ.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-BTCFBkF0.js → P2P-bdSQV7oZ.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-BAR6AUx5.js → PdhVaultBrowser-DQad42nW.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-RRf6HbWJ.js → Permissions-CueexxTR.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-BGTMiICa.js → PersonalDataHub-fqxflhR8.js} +6 -6
- package/src/assets/web-panel/assets/{Pipeline-945qY9YF.js → Pipeline-KFwwnIMC.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-DPZwI6lJ.js → Privacy-ClnD9buY.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-BPH2NRKc.js → ProjectInit-CZEz6sm3.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-BZCRNCvb.js → ProjectSettings-B6NzpmOI.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-BTI__tBt.js → Projects-DYyuwPCs.js} +1 -1
- package/src/assets/web-panel/assets/Providers-C3tz_jdh.js +1 -0
- package/src/assets/web-panel/assets/{QrScannerModal-N6rbqt1r.js → QrScannerModal-BzuOBbqB.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-DrwjPS7M.js → QuickAsk-CmNO9qSj.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-Cog9Wd99.js → Recommend-VJNj3_NF.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-DC9pynjM.js → RemoteSession-CrbdbSBF.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-D4th4gKS.js → Reputation-DTyMd45j.js} +1 -1
- package/src/assets/web-panel/assets/{Row-ogiWR6v9.js → Row-DHrQ-Icz.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-uYlk-2Oj.js → RssFeed-DqWxY9c5.js} +3 -3
- package/src/assets/web-panel/assets/{Search-DYzzwvtM.js → Search-ctF1Ks3J.js} +1 -1
- package/src/assets/web-panel/assets/{Security-Da7YOyX6.js → Security-BrQz8uo5.js} +4 -4
- package/src/assets/web-panel/assets/{Services-CLI1VM1X.js → Services-D4scVFar.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-DK77dzDC.js → Skeleton-oUScaOjv.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-C_z7Lmhl.js → Skills-CL-y0eLt.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-D6413Q8L.js → Sla-DQExhwXj.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-C07ydbj2.js → SpeechSettings-iNp_I7kN.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-DGOm2W22.js → SyncSettings-CTDlMo0A.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-Cr_PVyLM.js → Tasks-4kb8l3sc.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-BhL2mZ0t.js → Templates-BXcL9oXW.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-CPk5oyUr.js → Tenant-DLE8eS0D.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-ClhqUsqV.js → Terminal-DGpUZPPK.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-BCC7MV5a.js → TimelineRenderer-C1pWXGPC.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-DD1Jt4oO.js → Tokens-BYfbfqhZ.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-BCydFvN2.js → Trigger-K9YfLOCw.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-DDHT1noa.js → Trust-Ctkq77Hy.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-CWPZC7oI.js → UkeySign-C6_CSe9J.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-9Ea0nJR0.js → VideoEditing-Be3rpOWs.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-BjxhLxTf.js → Wallet-D0UIplxk.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-C6uCye67.js → WebAuthn-CF9bM9I3.js} +3 -3
- package/src/assets/web-panel/assets/{WorkflowEditor-d2g4reYo.js → WorkflowEditor-D0H1XVPY.js} +1 -1
- package/src/assets/web-panel/assets/{chat-frTc6ScX.js → chat-Cgzzbe0o.js} +1 -1
- package/src/assets/web-panel/assets/{colors-B5K6lG3v.js → colors-BwNxEVS0.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-Cdn46r8D.js → compact-item-D60Z4Hhs.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-DU1jqVQi.js → createContext-MFk58XB0.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-BJiw369i.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-DdNH-aW_.js → hasIn-CRj2SvGO.js} +1 -1
- package/src/assets/web-panel/assets/{index-DM5FmPZU.js → index--s45_1cb.js} +1 -1
- package/src/assets/web-panel/assets/{index-D4l82Me1.js → index--tquQ2ZG.js} +1 -1
- package/src/assets/web-panel/assets/{index-CQorP1Ng.js → index-1T1rhokn.js} +1 -1
- package/src/assets/web-panel/assets/{index-CHmkkdfT.js → index-B-M82_rx.js} +1 -1
- package/src/assets/web-panel/assets/{index-CGiwfwB9.js → index-BE_el1Zs.js} +1 -1
- package/src/assets/web-panel/assets/{index-BwlIxAmX.js → index-BhRkR7IO.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cj6P9Nst.js → index-Bo0y96-K.js} +1 -1
- package/src/assets/web-panel/assets/{index-BoFak7le.js → index-CJgu5JUK.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dca_i7H8.js → index-CLWwdebO.js} +1 -1
- package/src/assets/web-panel/assets/{index-BVLL-mq_.js → index-CNAK5QG_.js} +1 -1
- package/src/assets/web-panel/assets/{index-LaivuXyF.js → index-CQjJjPRD.js} +1 -1
- package/src/assets/web-panel/assets/{index-t_OBzIP4.js → index-CTDbAfae.js} +1 -1
- package/src/assets/web-panel/assets/{index-BcGwGIaR.js → index-CVI_9sRK.js} +1 -1
- package/src/assets/web-panel/assets/{index-D23xGYjM.js → index-CY14oMQK.js} +1 -1
- package/src/assets/web-panel/assets/{index-VDM2KKo9.js → index-CbiTJkZf.js} +1 -1
- package/src/assets/web-panel/assets/index-CiMouosn.js +1 -0
- package/src/assets/web-panel/assets/{index-32ajXmTb.js → index-CqWpxMqx.js} +1 -1
- package/src/assets/web-panel/assets/{index-PjAS0sIZ.js → index-CvB8lYUR.js} +1 -1
- package/src/assets/web-panel/assets/{index-7ehytj1K.js → index-D51XwtCY.js} +1 -1
- package/src/assets/web-panel/assets/{index-DtBCCkC4.js → index-D6HvK_1O.js} +1 -1
- package/src/assets/web-panel/assets/{index-Be4OtL-N.js → index-D9jVIwLJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-CUoNAmE8.js → index-DA4tE98u.js} +1 -1
- package/src/assets/web-panel/assets/{index-cYaWV4Mq.js → index-DBwOtXw0.js} +1 -1
- package/src/assets/web-panel/assets/{index-MM4Zz2OE.js → index-DKdNzTIb.js} +1 -1
- package/src/assets/web-panel/assets/{index-DIVyTmZ3.js → index-DRySdmvN.js} +1 -1
- package/src/assets/web-panel/assets/{index-CtRPi4YC.js → index-DWzyTev7.js} +1 -1
- package/src/assets/web-panel/assets/index-DXcKlwy7.js +1 -0
- package/src/assets/web-panel/assets/{index-kVO_MDm-.js → index-DYjs7jAP.js} +1 -1
- package/src/assets/web-panel/assets/{index-D4miNkWv.js → index-DbROzMBp.js} +1 -1
- package/src/assets/web-panel/assets/{index-yZRuZpwK.js → index-DhFtk5PR.js} +1 -1
- package/src/assets/web-panel/assets/{index-BXKhhx9V.js → index-Di2AbMLg.js} +1 -1
- package/src/assets/web-panel/assets/{index-BC4eGkar.js → index-DvmocQsM.js} +1 -1
- package/src/assets/web-panel/assets/{index-NmEXVjzt.js → index-Dw-o0zEF.js} +1 -1
- package/src/assets/web-panel/assets/{index-DRzBBdQ0.js → index-DysPoP38.js} +1 -1
- package/src/assets/web-panel/assets/{index-HjCvXHf5.js → index-LX9pJxm_.js} +1 -1
- package/src/assets/web-panel/assets/{index-gg3QPC3i.js → index-OI_fXWx0.js} +3 -3
- package/src/assets/web-panel/assets/{index-mgU3Q-lN.js → index-eDTOX8Xj.js} +1 -1
- package/src/assets/web-panel/assets/{index-D1qIC4GR.js → index-gWKDsTzF.js} +1 -1
- package/src/assets/web-panel/assets/{index-DftZuyA7.js → index-q_GDUVAA.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-DwLTRNdo.js → initDefaultProps-C61kZqEd.js} +1 -1
- package/src/assets/web-panel/assets/{motion-BchZDXnh.js → motion-DZnT5U1L.js} +1 -1
- package/src/assets/web-panel/assets/{move-e8M-zZFl.js → move-L8wzwbel.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-Ci40fQb3.js → mtc-parser-DLdYSejc.js} +1 -1
- package/src/assets/web-panel/assets/{omit-C7110_f2.js → omit-D53cbS59.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-skteMgnM.js → pickAttrs-Bbc5HPtu.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-MGZ-lh2B.js → placementArrow-BkvmO860.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-N4Sd7uy-.js → responsiveObserve-u2y1ryS1.js} +1 -1
- package/src/assets/web-panel/assets/{slide-C7HDGRaa.js → slide-BBqj7svU.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-BhRexlgy.js → statusUtils-GN0mqu2d.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-ChEoQkN2.js → styleChecker-BvwPKoBT.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-CDbG1s2Y.js → useFlexGapSupport-CCt8tnfY.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-CUIx0tcJ.js → useFs-DXAxl2SV.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-bkO7L7ec.js → usePersonalDataHub-DihlR2dj.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-B_ZvABIG.js → vnode-D7BOX2gi.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-D5shjpS8.js → zoom-CVbO-nL7.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-help-index.json +1 -1
- package/src/commands/mcp.js +119 -0
- package/src/commands/session-show.js +8 -10
- package/src/commands/session.js +60 -52
- package/src/data/changelog.json +27 -1
- package/src/gateways/ws/session-protocol.js +14 -4
- package/src/gateways/ws/ws-agent-handler.js +31 -0
- package/src/harness/jsonl-session-store.js +1147 -130
- package/src/harness/mcp-client.js +44 -11
- package/src/harness/session-index.js +80 -80
- package/src/harness/session-list-index.js +147 -2
- package/src/lib/background-interaction-journal.js +2 -2
- package/src/lib/command-lifecycle-report.js +516 -0
- package/src/lib/mcp-stdio-environment.js +48 -0
- package/src/lib/mcp-stdio-executable-identity.js +552 -17
- package/src/lib/mcp-stdio-package-materialization.js +1424 -0
- package/src/lib/packer/native-update-state.js +979 -1
- package/src/lib/packer/pack-update-applier.js +1050 -125
- package/src/lib/packer/pkg-config-generator.js +1 -0
- package/src/lib/paths.js +53 -0
- package/src/lib/process-execution-broker/index.js +180 -37
- package/src/lib/process-execution-broker/platform-sandbox.js +291 -24
- package/src/lib/recent-session.js +17 -17
- package/src/lib/secure-file-identity.js +47 -0
- package/src/lib/secure-fs.js +21 -2
- package/src/lib/session-anti-rollback-anchor.js +766 -0
- package/src/lib/session-host-lease.js +492 -0
- package/src/lib/session-persistence-failure.js +109 -0
- package/src/lib/session-picker.js +26 -3
- package/src/lib/session-search.js +25 -11
- package/src/lib/side-effect-ledger-store.js +2 -2
- package/src/lib/skill-execution-authority.js +13 -9
- package/src/lib/turn-binding-store.js +2 -2
- package/src/repl/agent-repl.js +309 -39
- package/src/runtime/agent-core.js +88 -5
- package/src/runtime/cleanup-deadline.js +143 -0
- package/src/runtime/headless-runner.js +357 -139
- package/src/runtime/headless-stream.js +207 -28
- package/src/runtime/output-backpressure.js +53 -0
- package/src/assets/web-panel/assets/MarkdownRenderer-CU-JB2Ns.js +0 -1
- package/src/assets/web-panel/assets/Providers-DDCf_nIw.js +0 -1
- package/src/assets/web-panel/assets/devWarning-CP-jEUyw.js +0 -1
- package/src/assets/web-panel/assets/index-CzrCHrFy.js +0 -1
- package/src/assets/web-panel/assets/index-OJsGskZw.js +0 -1
|
@@ -1813,6 +1813,11 @@ export async function executeTool(name, args, context = {}) {
|
|
|
1813
1813
|
typeof context.externalToolDescriptors === "object"
|
|
1814
1814
|
? context.externalToolDescriptors[name] || null
|
|
1815
1815
|
: null;
|
|
1816
|
+
const localToolExecutor =
|
|
1817
|
+
context.externalToolExecutors &&
|
|
1818
|
+
typeof context.externalToolExecutors === "object"
|
|
1819
|
+
? context.externalToolExecutors[name] || null
|
|
1820
|
+
: null;
|
|
1816
1821
|
const runtimeDescriptor =
|
|
1817
1822
|
getRuntimeToolDescriptor(name) || localToolDescriptor;
|
|
1818
1823
|
const admission = context.toolAdmission;
|
|
@@ -2086,6 +2091,69 @@ export async function executeTool(name, args, context = {}) {
|
|
|
2086
2091
|
ruleAllowed = true;
|
|
2087
2092
|
}
|
|
2088
2093
|
|
|
2094
|
+
// MCP annotations are peer-provided hints, never execution authority. A
|
|
2095
|
+
// server that claims readOnlyHint=true therefore still needs a request-level
|
|
2096
|
+
// approval unless the host independently authorized this exact tool as a
|
|
2097
|
+
// trusted read. An explicit settings allow can suppress the default prompt,
|
|
2098
|
+
// but it cannot suppress a host-owned `ask`/requiresConfirmation decision.
|
|
2099
|
+
// Plan mode has already applied its stricter hard ceiling above, so this gate
|
|
2100
|
+
// covers normal interactive/Auto execution without creating a Plan escape.
|
|
2101
|
+
if (localToolExecutor?.kind === "mcp") {
|
|
2102
|
+
const mcpEffectContract = mcpLedgerEffectContract(
|
|
2103
|
+
localToolDescriptor,
|
|
2104
|
+
hostToolPolicy,
|
|
2105
|
+
);
|
|
2106
|
+
const trustedHostRead =
|
|
2107
|
+
mcpEffectContract.effect === McpEffect.READ &&
|
|
2108
|
+
mcpEffectContract.trusted === true;
|
|
2109
|
+
const settingsAskWasConfirmed =
|
|
2110
|
+
settingsVerdict.decision === "ask" && ruleAllowed;
|
|
2111
|
+
const hostRequiresConfirmation =
|
|
2112
|
+
!settingsAskWasConfirmed &&
|
|
2113
|
+
(hostToolPolicy?.requiresConfirmation === true ||
|
|
2114
|
+
hostToolPolicy?.decision === "ask");
|
|
2115
|
+
const defaultRequiresConfirmation = !trustedHostRead && !ruleAllowed;
|
|
2116
|
+
|
|
2117
|
+
if (hostRequiresConfirmation || defaultRequiresConfirmation) {
|
|
2118
|
+
const approved = await requestInteractivePermission(
|
|
2119
|
+
name,
|
|
2120
|
+
args,
|
|
2121
|
+
context,
|
|
2122
|
+
cwd,
|
|
2123
|
+
{
|
|
2124
|
+
tool: name,
|
|
2125
|
+
args,
|
|
2126
|
+
rule: null,
|
|
2127
|
+
reason: hostRequiresConfirmation
|
|
2128
|
+
? "host policy requires confirmation for this MCP tool"
|
|
2129
|
+
: `MCP effect is ${mcpEffectContract.effect} and lacks a trusted host read authorization`,
|
|
2130
|
+
source: hostRequiresConfirmation
|
|
2131
|
+
? "host-managed MCP policy"
|
|
2132
|
+
: "MCP effect contract",
|
|
2133
|
+
mcpEffect: mcpEffectContract.effect,
|
|
2134
|
+
mcpTrusted: mcpEffectContract.trusted === true,
|
|
2135
|
+
},
|
|
2136
|
+
);
|
|
2137
|
+
if (!approved) {
|
|
2138
|
+
return {
|
|
2139
|
+
error: `[MCP Permission] Tool "${name}" requires confirmation because its effect is ${mcpEffectContract.effect} and it does not have an applicable trusted host read authorization — denied.`,
|
|
2140
|
+
policy: {
|
|
2141
|
+
decision: "ask",
|
|
2142
|
+
via: hostRequiresConfirmation
|
|
2143
|
+
? "host-mcp-policy"
|
|
2144
|
+
: "mcp-effect-contract",
|
|
2145
|
+
code: "CC_MCP_EFFECT_CONFIRMATION_REQUIRED",
|
|
2146
|
+
effect: mcpEffectContract.effect,
|
|
2147
|
+
trusted: mcpEffectContract.trusted === true,
|
|
2148
|
+
},
|
|
2149
|
+
};
|
|
2150
|
+
}
|
|
2151
|
+
// The approval is scoped to this request and also satisfies the later
|
|
2152
|
+
// generic external-tool/ApprovalGate prompt for the same invocation.
|
|
2153
|
+
ruleAllowed = true;
|
|
2154
|
+
}
|
|
2155
|
+
}
|
|
2156
|
+
|
|
2089
2157
|
// Sensitive-file write guard (Claude-Code 2.1.160 parity): shell startup
|
|
2090
2158
|
// files / PowerShell profiles / git+husky hooks execute code on the user's
|
|
2091
2159
|
// next shell or commit — even otherwise-permitted edit flows confirm first.
|
|
@@ -3319,11 +3387,18 @@ function mcpLedgerEffectContract(descriptor, hostPolicy) {
|
|
|
3319
3387
|
)
|
|
3320
3388
|
? descriptorContract.declaredEffect
|
|
3321
3389
|
: "unknown";
|
|
3390
|
+
// Host authority may raise an unknown/read declaration to a stricter effect,
|
|
3391
|
+
// but it may never downgrade the conservative peer risk floor. In
|
|
3392
|
+
// particular, an accidentally stale host `read` policy cannot turn a newly
|
|
3393
|
+
// declared write/destructive tool into a trusted read.
|
|
3322
3394
|
const effect =
|
|
3323
|
-
authorizedEffect
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3395
|
+
declaredEffect === "destructive" || authorizedEffect === "destructive"
|
|
3396
|
+
? "destructive"
|
|
3397
|
+
: declaredEffect === "write" || authorizedEffect === "write"
|
|
3398
|
+
? "write"
|
|
3399
|
+
: declaredEffect === "unknown"
|
|
3400
|
+
? "unknown"
|
|
3401
|
+
: authorizedEffect || "unknown";
|
|
3327
3402
|
const annotations = descriptorContract.annotations || {};
|
|
3328
3403
|
|
|
3329
3404
|
return {
|
|
@@ -3341,7 +3416,15 @@ function mcpLedgerEffectContract(descriptor, hostPolicy) {
|
|
|
3341
3416
|
: null,
|
|
3342
3417
|
trusted:
|
|
3343
3418
|
authorizedEffect != null &&
|
|
3344
|
-
(hostContract.trusted === true || hostPolicy?.sourceTrusted === true)
|
|
3419
|
+
(hostContract.trusted === true || hostPolicy?.sourceTrusted === true) &&
|
|
3420
|
+
// Trust is valid only when the host authorization is at least as strict
|
|
3421
|
+
// as the merged effect. A stale host `read` classification cannot lend
|
|
3422
|
+
// trust to a server that now declares write/destructive behavior.
|
|
3423
|
+
authorizedEffect === effect &&
|
|
3424
|
+
// Trusted-read execution/parallelism requires the intersection promised
|
|
3425
|
+
// by the roadmap: a server read declaration plus host authorization.
|
|
3426
|
+
// An unmarked tool stays untrusted even when a host policy predicts read.
|
|
3427
|
+
(effect !== "read" || declaredEffect === "read"),
|
|
3345
3428
|
source:
|
|
3346
3429
|
hostContract.provenance ||
|
|
3347
3430
|
descriptorContract.provenance ||
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { performance } from "node:perf_hooks";
|
|
2
|
+
|
|
3
|
+
const HOST_CLEANUP_DEADLINE_MS = 10_000;
|
|
4
|
+
const SAFE_ERROR_CODE = /^[A-Z][A-Z0-9_]{0,63}$/;
|
|
5
|
+
|
|
6
|
+
function projectedErrorCode(error) {
|
|
7
|
+
if (!error) return null;
|
|
8
|
+
return typeof error.code === "string" && SAFE_ERROR_CODE.test(error.code)
|
|
9
|
+
? error.code
|
|
10
|
+
: "CC_CLEANUP_STEP_FAILED";
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function normalizeCleanupDeadlineMs(value) {
|
|
14
|
+
return Number.isFinite(value) &&
|
|
15
|
+
value > 0 &&
|
|
16
|
+
value <= HOST_CLEANUP_DEADLINE_MS
|
|
17
|
+
? Math.max(1, Math.floor(value))
|
|
18
|
+
: HOST_CLEANUP_DEADLINE_MS;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function cleanupDeadlineError(report) {
|
|
22
|
+
const error = new Error(
|
|
23
|
+
`CLI cleanup exceeded the host deadline of ${report.timeoutMs} ms`,
|
|
24
|
+
);
|
|
25
|
+
error.code = "CC_CLEANUP_DEADLINE_EXCEEDED";
|
|
26
|
+
error.isCleanupDeadlineFailure = true;
|
|
27
|
+
error.timeoutMs = report.timeoutMs;
|
|
28
|
+
error.timedOutSteps = report.steps
|
|
29
|
+
.filter((step) => step.status === "timeout")
|
|
30
|
+
.map((step) => step.name);
|
|
31
|
+
error.cleanupReport = report;
|
|
32
|
+
return error;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* One host-owned absolute deadline shared by a cleanup sequence. Operations
|
|
37
|
+
* are invoked in order. If an operation consumes the remaining budget, later
|
|
38
|
+
* disposers are still invoked (and observed) but are not awaited, so one
|
|
39
|
+
* uncooperative adapter cannot prevent exhaustive teardown from starting.
|
|
40
|
+
*/
|
|
41
|
+
export function createCleanupDeadline(
|
|
42
|
+
{ timeoutMs, label = "cli-cleanup" } = {},
|
|
43
|
+
deps = {},
|
|
44
|
+
) {
|
|
45
|
+
// A wall-clock adjustment must never extend teardown past the host ceiling.
|
|
46
|
+
const now = deps.now || (() => performance.now());
|
|
47
|
+
const setTimer = deps.setTimeout || setTimeout;
|
|
48
|
+
const clearTimer = deps.clearTimeout || clearTimeout;
|
|
49
|
+
const normalizedTimeoutMs = normalizeCleanupDeadlineMs(timeoutMs);
|
|
50
|
+
let startedAt = null;
|
|
51
|
+
let deadlineAt = null;
|
|
52
|
+
let exhausted = false;
|
|
53
|
+
const steps = [];
|
|
54
|
+
|
|
55
|
+
const ensureStarted = () => {
|
|
56
|
+
if (startedAt !== null) return;
|
|
57
|
+
startedAt = now();
|
|
58
|
+
deadlineAt = startedAt + normalizedTimeoutMs;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const record = (name, status, stepStartedAt, error = null) => {
|
|
62
|
+
steps.push(
|
|
63
|
+
Object.freeze({
|
|
64
|
+
name,
|
|
65
|
+
status,
|
|
66
|
+
durationMs: Math.max(0, now() - stepStartedAt),
|
|
67
|
+
errorCode: projectedErrorCode(error),
|
|
68
|
+
}),
|
|
69
|
+
);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
async run(name, operation) {
|
|
74
|
+
if (typeof name !== "string" || name.length === 0) {
|
|
75
|
+
throw new TypeError("cleanup step name is required");
|
|
76
|
+
}
|
|
77
|
+
if (typeof operation !== "function") {
|
|
78
|
+
record(name, "skipped", now());
|
|
79
|
+
return { status: "skipped" };
|
|
80
|
+
}
|
|
81
|
+
ensureStarted();
|
|
82
|
+
const stepStartedAt = now();
|
|
83
|
+
let promise;
|
|
84
|
+
try {
|
|
85
|
+
promise = Promise.resolve(operation());
|
|
86
|
+
} catch (error) {
|
|
87
|
+
record(name, "error", stepStartedAt, error);
|
|
88
|
+
return { status: "error", error };
|
|
89
|
+
}
|
|
90
|
+
// Always observe a late rejection after a timeout.
|
|
91
|
+
promise.catch(() => {});
|
|
92
|
+
const remainingMs = Math.max(0, deadlineAt - now());
|
|
93
|
+
if (exhausted || remainingMs === 0) {
|
|
94
|
+
exhausted = true;
|
|
95
|
+
record(name, "timeout", stepStartedAt);
|
|
96
|
+
return { status: "timeout" };
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
let timer = null;
|
|
100
|
+
const timeout = new Promise((resolve) => {
|
|
101
|
+
timer = setTimer(() => resolve({ timeout: true }), remainingMs);
|
|
102
|
+
});
|
|
103
|
+
const settled = await Promise.race([
|
|
104
|
+
promise.then(
|
|
105
|
+
(value) => ({ value }),
|
|
106
|
+
(error) => ({ error }),
|
|
107
|
+
),
|
|
108
|
+
timeout,
|
|
109
|
+
]);
|
|
110
|
+
if (timer !== null) clearTimer(timer);
|
|
111
|
+
if (settled?.timeout) {
|
|
112
|
+
// A platform timer can fire fractionally before performance.now()
|
|
113
|
+
// reaches deadlineAt. Latch exhaustion so later disposers are still
|
|
114
|
+
// invoked but never regain a sliver of cleanup budget.
|
|
115
|
+
exhausted = true;
|
|
116
|
+
record(name, "timeout", stepStartedAt);
|
|
117
|
+
return { status: "timeout" };
|
|
118
|
+
}
|
|
119
|
+
if (settled?.error) {
|
|
120
|
+
record(name, "error", stepStartedAt, settled.error);
|
|
121
|
+
return { status: "error", error: settled.error };
|
|
122
|
+
}
|
|
123
|
+
record(name, "completed", stepStartedAt);
|
|
124
|
+
return { status: "completed", value: settled.value };
|
|
125
|
+
},
|
|
126
|
+
report() {
|
|
127
|
+
const finishedAt = now();
|
|
128
|
+
const timedOut = steps.some((step) => step.status === "timeout");
|
|
129
|
+
return Object.freeze({
|
|
130
|
+
label,
|
|
131
|
+
timeoutMs: normalizedTimeoutMs,
|
|
132
|
+
startedAt,
|
|
133
|
+
finishedAt,
|
|
134
|
+
elapsedMs: startedAt === null ? 0 : Math.max(0, finishedAt - startedAt),
|
|
135
|
+
timedOut,
|
|
136
|
+
completed: !timedOut,
|
|
137
|
+
steps: Object.freeze([...steps]),
|
|
138
|
+
});
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export const MAX_CLI_CLEANUP_DEADLINE_MS = HOST_CLEANUP_DEADLINE_MS;
|