chainlesschain 0.166.81 → 0.166.83
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 +1 -1
- package/src/assets/linux-subreaper/linux-arm64/manifest.json +1 -1
- package/src/assets/linux-subreaper/linux-x64/manifest.json +1 -1
- package/src/assets/web-panel/assets/{AIOps-BZPs-bVl.js → AIOps-D5a4i3N7.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-BP1iLSwn.js → ActionButton-DxsRk5n1.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-WxwtPqcd.js → Analytics-D-7EvH4S.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-DvcgeNkP.js → AppLayout-DDEWVr-d.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-CtYGOtnT.js → Artifacts-CAlJAjRB.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-BBzFYWMk.js → Audit-tuaWDOAM.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-Dl9wCt0Y.js → BackgroundAgents-CIwRFJ50.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-CAL13Eak.js → Backup-CpBepJlH.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-f_lncpU_.js → BaseInput-eKguCzQc.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-DLEbkiqI.js → Chat-CFrUfXDV.js} +4 -4
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-1tCmIvv1.js → ChatBubbleRenderer-DaRtY87l.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-SNvgd2UG.js → Checkbox-o5FEn6a1.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-BG0D-INl.js → Codegen-Dih8HogC.js} +1 -1
- package/src/assets/web-panel/assets/{Col-DUBBZz0e.js → Col-D5r-6WZe.js} +1 -1
- package/src/assets/web-panel/assets/{Community-8LfuBDPs.js → Community-jeQ6bGey.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-GWs7Ka6o.js → Compact-CEP7QsWp.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-CXRhB-KC.js → Compliance-B8NydOHd.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-OpW8dLKg.js → Cowork-Bmi1zuPy.js} +2 -2
- package/src/assets/web-panel/assets/{Cron-6e47Syc_.js → Cron-BAL9bwSp.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-D-vGH4nC.js → Crosschain-D8WUi2dS.js} +1 -1
- package/src/assets/web-panel/assets/{DID-zEIa2jNx.js → DID-CQCkYcLY.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-BfUbZxsl.js → Dashboard-DogXg6kh.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-BeCD8gf0.js → Dropdown-BJBJyQJn.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-apOBM2r2.js → EmailListRenderer-CxPWquJx.js} +1 -1
- package/src/assets/web-panel/assets/{EvolutionSettings-C2dK36po.js → EvolutionSettings-BijH1x8G.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-DPMLWPTR.js → FamilyGuardDashboard-DStwf-00.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-CivI2pzm.js → Federation-LU9_sNxC.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-B3zrwBDw.js → FormItemContext-DNfWhj7P.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-jGgdcPck.js → GenericCardRenderer-DWYsPjzk.js} +1 -1
- package/src/assets/web-panel/assets/{Git-Cpfkrasd.js → Git-CA0O9ulB.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-DG8_7YS3.js → Governance-ECShL7BJ.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-TQgUqPXx.js → Inference-9GA2542e.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-By657fHZ.js → KnowledgeGraph-nC5mTbEH.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-CFJ_70-E.js → Logs-B7IqgnDy.js} +2 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-BqlqrJkY.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-BWC3xler.js → Marketplace-CEr0suM8.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-B0NkUzeJ.js → McpTools-DhTPQKOE.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-DBnXwjWD.js → Memory-mHRZP1w4.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-BNWDrEJ4.js → MobileBridge-BNfX6Rdo.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-BaE94B_N.js → MobileProjects-8zG8f5li.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-Bp3OAEYb.js → Mtc-CzkV3wsn.js} +5 -5
- package/src/assets/web-panel/assets/{MtcAudit-_1T24zO3.js → MtcAudit-DWYljJik.js} +4 -4
- package/src/assets/web-panel/assets/{Multisig-C2i6Yi0B.js → Multisig-kHgtvZY_.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-CBq3ujGE.js → NLProgramming-56uQiPiY.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-BxRmci_W.js → Notes-DxGOZqRf.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-CqBLgOdv.js → NotificationSettings-DabaCpmo.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-cODPlpK7.js → OrderTableRenderer-SzeQNlGT.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-DlTnQBlp.js → Organization-D9gnPpK2.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-Df2jS2Ep.js → Overflow-Cqp_bXm4.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-BwieT0aA.js → P2P-DTeK-r0G.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-Btw816xR.js → PdhVaultBrowser-CsjG85GT.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-BhVYLcqT.js → Permissions-B4ofZq3j.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-CPbNKPCA.js → PersonalDataHub-Cvas5cYd.js} +4 -4
- package/src/assets/web-panel/assets/{Pipeline-B1BuhoY3.js → Pipeline-Er3wmAew.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-BWeikVbU.js → Privacy-DMFYeZox.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-BVXcimHE.js → ProjectInit-DaVaYPy0.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-CX87x3rT.js → ProjectSettings-dPx5q2Ac.js} +2 -2
- package/src/assets/web-panel/assets/Projects-N0JNeCui.js +1 -0
- package/src/assets/web-panel/assets/{Providers-CGm0Wuer.js → Providers-BPQo_gQa.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-DJxv7J64.js → QrScannerModal-CD-sEsWh.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-DOXBReRk.js → QuickAsk-LOKRJiN_.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend--MiLwmLM.js → Recommend-BwPXqcWy.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-D6LoXH94.js → RemoteSession-BjotndxF.js} +3 -3
- package/src/assets/web-panel/assets/{Reputation-G2jToiqh.js → Reputation-BlZ2gcbU.js} +1 -1
- package/src/assets/web-panel/assets/{Row-B79ZV_lZ.js → Row-D399HM-d.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-CHQN68w_.js → RssFeed-C7H-ibnY.js} +2 -2
- package/src/assets/web-panel/assets/{Search-j7v5S2Fa.js → Search-CNHCVmM1.js} +1 -1
- package/src/assets/web-panel/assets/{Security-B2ykFZJH.js → Security-C70eDGYY.js} +3 -3
- package/src/assets/web-panel/assets/{Services-H8BK8uX0.js → Services-6xfq9G-H.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-XEUUrOTK.js → Skeleton-BbY2zeZV.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-B387UJPk.js → Skills-DYtyZ7_6.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-CWWBujpe.js → Sla-CkWcl5OH.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-Q2AOv9DV.js → SpeechSettings-CiknYk2P.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-OSNyOUr8.js → SyncSettings-D-8JVip4.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-DfUDrno5.js → Tasks-B2KnR9XC.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-CSTkzDRS.js → Templates-CipXkOE-.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-BR__gCTG.js → Tenant-DbwgIMmx.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-Bv4DM5OI.js → Terminal-OtCriHEE.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-DUnZuAtn.js → TimelineRenderer-B9LU5qrl.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-Dm0sczRV.js → Tokens-B4iFVxvH.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-DsSOp0Ob.js → Trigger-BegM2v8q.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-C0HJtFwV.js → Trust-COkqnnFj.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-BbqIZiX-.js → UkeySign-BzqKPChj.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-D7dDTt3D.js → VideoEditing-D-F2XL3C.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-DJGu0KWq.js → Wallet-22PzRY9T.js} +2 -2
- package/src/assets/web-panel/assets/{WebAuthn-x8OoogZU.js → WebAuthn-eSMq_qtz.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-CC3jIUqx.js → WorkflowEditor-BvdAakpq.js} +1 -1
- package/src/assets/web-panel/assets/{chat-Bqgv5oe8.js → chat-C6jhpF7E.js} +1 -1
- package/src/assets/web-panel/assets/{colors-CbAMqLFr.js → colors-BbbW2Pfv.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-B-zIDFg3.js → compact-item-CVFeLTqt.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-D_s1ZLtZ.js → createContext-DS0m7NZc.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-D50gzPS9.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-Cj_J9Eb9.js → hasIn-DVouP0t6.js} +1 -1
- package/src/assets/web-panel/assets/{index-BtJzqXCQ.js → index--AdzSlH7.js} +1 -1
- package/src/assets/web-panel/assets/{index-D_igPAXH.js → index-54aHB4FL.js} +1 -1
- package/src/assets/web-panel/assets/{index-BivQyKes.js → index-8QbwhE3i.js} +1 -1
- package/src/assets/web-panel/assets/{index-3o8DjHHt.js → index-B5JRIZXi.js} +1 -1
- package/src/assets/web-panel/assets/{index-0je3TLmx.js → index-B8a_c_qZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cz0blpuN.js → index-BE_u-rXr.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cu3FtpNc.js → index-BOOsA080.js} +1 -1
- package/src/assets/web-panel/assets/{index-KY7udrs-.js → index-BXw6ivB8.js} +1 -1
- package/src/assets/web-panel/assets/{index-J4JLWUMK.js → index-BaUah6TO.js} +1 -1
- package/src/assets/web-panel/assets/{index-C6bAvixK.js → index-Be12HoCS.js} +3 -3
- package/src/assets/web-panel/assets/{index-Cy3XOp7S.js → index-BhvnNFfd.js} +1 -1
- package/src/assets/web-panel/assets/{index-C6lO24YD.js → index-BrIv7C9a.js} +1 -1
- package/src/assets/web-panel/assets/{index-BPdH-XTd.js → index-BvCgzl0X.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cg0oYTy5.js → index-Bw-ZGQCH.js} +1 -1
- package/src/assets/web-panel/assets/{index-ab6FUgkq.js → index-BwZnPiFd.js} +1 -1
- package/src/assets/web-panel/assets/{index-DuqVIsHL.js → index-BwozzG6k.js} +1 -1
- package/src/assets/web-panel/assets/{index-B6qoyCkx.js → index-ByLsH9CL.js} +1 -1
- package/src/assets/web-panel/assets/{index-BjfpW5s3.js → index-BzL3LWFX.js} +1 -1
- package/src/assets/web-panel/assets/{index-BFNO6ycz.js → index-C4xmLgLa.js} +1 -1
- package/src/assets/web-panel/assets/{index-dg0JqQDA.js → index-C6q2MkIG.js} +1 -1
- package/src/assets/web-panel/assets/{index-DtplHZ5o.js → index-C74emdKD.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bi1E5h9V.js → index-CIg4nqyp.js} +1 -1
- package/src/assets/web-panel/assets/{index-C-Z13SCI.js → index-CIk7mg6G.js} +1 -1
- package/src/assets/web-panel/assets/{index-JdSkHz64.js → index-CPS8E-J6.js} +1 -1
- package/src/assets/web-panel/assets/index-CgensV-n.js +1 -0
- package/src/assets/web-panel/assets/{index-DVjFV2mg.js → index-CkdYB0_g.js} +1 -1
- package/src/assets/web-panel/assets/{index-CsHTqPTg.js → index-CpTbnbUI.js} +1 -1
- package/src/assets/web-panel/assets/index-Ctkf06Z_.js +1 -0
- package/src/assets/web-panel/assets/{index-nEWJobH4.js → index-CwYFDMn_.js} +1 -1
- package/src/assets/web-panel/assets/{index-BN5sO3kL.js → index-DGYX17YW.js} +1 -1
- package/src/assets/web-panel/assets/{index-CD_A-N7c.js → index-DR6TDz5H.js} +1 -1
- package/src/assets/web-panel/assets/{index-ggeC-_dR.js → index-DUBkae39.js} +1 -1
- package/src/assets/web-panel/assets/{index-D9CqHOgd.js → index-DotRL126.js} +1 -1
- package/src/assets/web-panel/assets/{index-CSzWODfj.js → index-DpReoAGb.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bw88Mk2t.js → index-Ds4wbrgk.js} +1 -1
- package/src/assets/web-panel/assets/{index-BGxI_Qxg.js → index-DuVjTDcW.js} +1 -1
- package/src/assets/web-panel/assets/{index-BLwUCYDf.js → index-JeJqXbUU.js} +1 -1
- package/src/assets/web-panel/assets/{index-D1t2IqNU.js → index-SdFkCtiC.js} +1 -1
- package/src/assets/web-panel/assets/{index-CVPI_iIh.js → index-eaXEQFuP.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-DDIGXQ08.js → initDefaultProps-CB5cUnQ5.js} +1 -1
- package/src/assets/web-panel/assets/{motion-97SXSYE4.js → motion-bn_fWhQV.js} +1 -1
- package/src/assets/web-panel/assets/{move-CfDQMFRe.js → move-DY4-Odtu.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-qLYCGwY8.js → mtc-parser-B5l5mjoh.js} +1 -1
- package/src/assets/web-panel/assets/{omit-xVqy1mCI.js → omit-rJ-Ci8CW.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-DCGlFyfv.js → pickAttrs-BMwGJd6C.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-DYgPuMk3.js → placementArrow-CaiQyGXG.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-7zUIdAWH.js → responsiveObserve-DQTO5wDH.js} +1 -1
- package/src/assets/web-panel/assets/{slide-TyaiZlSh.js → slide-Dg6ZDtbz.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-BPd13Fae.js → statusUtils-bvjrktKc.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-A44XGgQ0.js → styleChecker-C1geIU_x.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-ZX5EUa8B.js → useFlexGapSupport-BzU3RJRi.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-Sh_fBPqz.js → useFs-B7l6OwLe.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-DhR6Izei.js → usePersonalDataHub-BYF1L_8x.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-DC8g6oRh.js → vnode-6c2GVkT-.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-DRjJmOwj.js → zoom-BYAY6QeD.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/agent.js +21 -10
- package/src/data/changelog.json +39 -0
- package/src/gateways/ws/session-protocol.js +19 -5
- package/src/gateways/ws/ws-agent-handler.js +6 -0
- package/src/gateways/ws/ws-session-gateway.js +133 -21
- package/src/lib/agent-execution-policy.js +177 -0
- package/src/lib/authority-launch-environment.js +99 -0
- package/src/lib/auto-mode-config.js +129 -45
- package/src/lib/claude-project-auto-memory.js +7 -30
- package/src/lib/context-memory-kernel/task-worklog-port.js +73 -24
- package/src/lib/diagnostic-excerpt.js +91 -10
- package/src/lib/diagnostic-workflow.js +2 -0
- package/src/lib/evolution/volcengine-function-replay-store.js +38 -28
- package/src/lib/git-tool-input.js +7 -0
- package/src/lib/host-tool-policy-authority.js +151 -0
- package/src/lib/permission-authority.js +67 -5
- package/src/lib/plugin-runtime/settings.js +9 -1
- package/src/lib/remote-read-loop-guard.js +59 -14
- package/src/lib/sandbox-egress-authority-monitor.js +3 -2
- package/src/lib/session-manager.js +20 -5
- package/src/lib/settings-loader.cjs +175 -19
- package/src/lib/settings-source-observation.cjs +270 -0
- package/src/lib/sub-agent-context.js +36 -18
- package/src/lib/task-progress-tracker.js +112 -12
- package/src/lib/unattended-action-policy.js +456 -38
- package/src/repl/agent-repl.js +58 -29
- package/src/repl/repl-tool-executor.js +39 -0
- package/src/runtime/agent-core.js +272 -5
- package/src/runtime/agent-runtime.js +15 -3
- package/src/runtime/headless-runner.js +13 -4
- package/src/runtime/headless-stream.js +9 -0
- package/src/runtime/policies/agent-policy.js +5 -4
- package/src/assets/web-panel/assets/MarkdownRenderer-BpRWpN1E.js +0 -1
- package/src/assets/web-panel/assets/Projects-3Qo2Mvxb.js +0 -1
- package/src/assets/web-panel/assets/devWarning-QMSC9xgn.js +0 -1
- package/src/assets/web-panel/assets/index-DVq7UuW0.js +0 -1
- package/src/assets/web-panel/assets/index-DYVepsIV.js +0 -1
|
@@ -18,6 +18,42 @@
|
|
|
18
18
|
* PURE: no fs / clock / RNG / process.
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
+
import { snapshotMcpJsonRpcInput } from "./mcp-call-ledger.js";
|
|
22
|
+
|
|
23
|
+
/** Bind startup-only authority without retaining caller-owned mutable data. */
|
|
24
|
+
export function captureUnattendedActionPolicy(policy) {
|
|
25
|
+
if (policy == null) return null;
|
|
26
|
+
try {
|
|
27
|
+
const snapshot = snapshotMcpJsonRpcInput(policy);
|
|
28
|
+
if (!snapshot || typeof snapshot !== "object" || Array.isArray(snapshot))
|
|
29
|
+
throw new TypeError();
|
|
30
|
+
for (const flag of ["unattended", "protectedBranch", "budgetExhausted"]) {
|
|
31
|
+
if (snapshot[flag] !== undefined && typeof snapshot[flag] !== "boolean")
|
|
32
|
+
throw new TypeError();
|
|
33
|
+
}
|
|
34
|
+
if (
|
|
35
|
+
snapshot.allowlist !== undefined &&
|
|
36
|
+
(!Array.isArray(snapshot.allowlist) ||
|
|
37
|
+
snapshot.allowlist.some((value) => typeof value !== "string"))
|
|
38
|
+
)
|
|
39
|
+
throw new TypeError();
|
|
40
|
+
if (
|
|
41
|
+
snapshot.trigger !== undefined &&
|
|
42
|
+
(!snapshot.trigger ||
|
|
43
|
+
typeof snapshot.trigger !== "object" ||
|
|
44
|
+
Array.isArray(snapshot.trigger) ||
|
|
45
|
+
(snapshot.trigger.trusted !== undefined &&
|
|
46
|
+
typeof snapshot.trigger.trusted !== "boolean"))
|
|
47
|
+
)
|
|
48
|
+
throw new TypeError();
|
|
49
|
+
return snapshot;
|
|
50
|
+
} catch {
|
|
51
|
+
const error = new TypeError("Unattended action policy is invalid");
|
|
52
|
+
error.code = "CC_UNATTENDED_POLICY_INVALID";
|
|
53
|
+
throw error;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
21
57
|
/** Canonical action classes, ordered low → high consequence. */
|
|
22
58
|
export const ACTION_CLASS = Object.freeze({
|
|
23
59
|
READ: "read",
|
|
@@ -86,6 +122,54 @@ export const TOOL_ACTION_CLASS = Object.freeze({
|
|
|
86
122
|
notify: ACTION_CLASS.EXTERNAL_MESSAGE,
|
|
87
123
|
});
|
|
88
124
|
|
|
125
|
+
// Fixed built-ins with local effects. Peer annotations and generic runtime
|
|
126
|
+
// descriptors cannot add to this list. Shell/Git have their own command
|
|
127
|
+
// ceilings; opaque executors and persistent/delegated runs remain unknown.
|
|
128
|
+
const LOCAL_TOOL_ACTION_CLASS = Object.freeze({
|
|
129
|
+
read_file: ACTION_CLASS.READ,
|
|
130
|
+
search_files: ACTION_CLASS.READ,
|
|
131
|
+
list_dir: ACTION_CLASS.READ,
|
|
132
|
+
list_skills: ACTION_CLASS.READ,
|
|
133
|
+
search_sessions: ACTION_CLASS.READ,
|
|
134
|
+
ask_user_question: ACTION_CLASS.READ,
|
|
135
|
+
write_file: ACTION_CLASS.LOCAL_WRITE,
|
|
136
|
+
edit_file: ACTION_CLASS.LOCAL_WRITE,
|
|
137
|
+
edit_file_hashed: ACTION_CLASS.LOCAL_WRITE,
|
|
138
|
+
delete_file: ACTION_CLASS.LOCAL_WRITE,
|
|
139
|
+
move_file: ACTION_CLASS.LOCAL_WRITE,
|
|
140
|
+
notebook_edit: ACTION_CLASS.LOCAL_WRITE,
|
|
141
|
+
todo_write: ACTION_CLASS.LOCAL_WRITE,
|
|
142
|
+
check_shell: ACTION_CLASS.LOCAL_WRITE,
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
/** Execution guard for built-ins; an opaque host/MCP executor stays unknown. */
|
|
146
|
+
export function evaluateUnattendedToolAction(
|
|
147
|
+
name,
|
|
148
|
+
args,
|
|
149
|
+
policy,
|
|
150
|
+
{ external = false } = {},
|
|
151
|
+
) {
|
|
152
|
+
let actionClass = null;
|
|
153
|
+
if (!external) {
|
|
154
|
+
actionClass = Object.hasOwn(TOOL_ACTION_CLASS, name)
|
|
155
|
+
? TOOL_ACTION_CLASS[name]
|
|
156
|
+
: Object.hasOwn(LOCAL_TOOL_ACTION_CLASS, name)
|
|
157
|
+
? LOCAL_TOOL_ACTION_CLASS[name]
|
|
158
|
+
: null;
|
|
159
|
+
if (["run_shell", "git"].includes(name)) actionClass = ACTION_CLASS.READ;
|
|
160
|
+
// Persistent child runs do not yet carry a durable parent effect ceiling.
|
|
161
|
+
if (
|
|
162
|
+
name === "schedule" &&
|
|
163
|
+
["list", "cancel"].includes(String(args?.action || "").toLowerCase())
|
|
164
|
+
)
|
|
165
|
+
actionClass = ACTION_CLASS.LOCAL_WRITE;
|
|
166
|
+
}
|
|
167
|
+
return {
|
|
168
|
+
actionClass,
|
|
169
|
+
...evaluateUnattendedAction({ ...policy, actionClass, attended: false }),
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
|
|
89
173
|
/**
|
|
90
174
|
* The agent tools an UNATTENDED run must be denied — the enforcement projection
|
|
91
175
|
* of `evaluateUnattendedAction` onto the tool layer (P1-8). A scheduled
|
|
@@ -127,10 +211,10 @@ export function classifyActionRisk(actionClass) {
|
|
|
127
211
|
* the highest-risk segment and unknown commands remain unknown so an
|
|
128
212
|
* unattended caller can fail closed.
|
|
129
213
|
*/
|
|
130
|
-
|
|
131
|
-
if (typeof command !== "string" || !command.trim()) return
|
|
214
|
+
function classifyShellSegments(command) {
|
|
215
|
+
if (typeof command !== "string" || !command.trim()) return [];
|
|
132
216
|
const segments = command
|
|
133
|
-
.split(/&&|\|\||[
|
|
217
|
+
.split(/&&|\|\||[;&\n]|\|/)
|
|
134
218
|
.map((part) =>
|
|
135
219
|
part
|
|
136
220
|
.trim()
|
|
@@ -139,15 +223,29 @@ export function classifyShellAction(command) {
|
|
|
139
223
|
)
|
|
140
224
|
.filter(Boolean);
|
|
141
225
|
const classifySegment = (segment) => {
|
|
142
|
-
|
|
143
|
-
|
|
226
|
+
// Substitution and executable search/filter options can hide effects
|
|
227
|
+
// inside a nominally read-only command. Unsupported syntax is unknown.
|
|
228
|
+
if (
|
|
229
|
+
/[$`'"\\^(){}]/.test(segment) ||
|
|
230
|
+
/(?:^|\s)(?:-exec(?:dir)?|-ok(?:dir)?|--pre)(?:\s|=|$)/.test(segment)
|
|
231
|
+
)
|
|
232
|
+
return null;
|
|
233
|
+
if (
|
|
234
|
+
/^git(?:\s|$)/.test(segment) &&
|
|
235
|
+
!hasKnownGitOptions(segment.split(/\s+/).slice(1))
|
|
236
|
+
)
|
|
237
|
+
return null;
|
|
238
|
+
if (/^git\s+push(?:\s|$)/.test(segment)) return ACTION_CLASS.PUSH;
|
|
239
|
+
if (/^git\s+(?:add|commit|fetch)(?:\s|$)/.test(segment))
|
|
240
|
+
return ACTION_CLASS.LOCAL_WRITE;
|
|
241
|
+
if (/^git\s+(?:merge|rebase|cherry-pick)(?:\s|$)/.test(segment)) {
|
|
144
242
|
return ACTION_CLASS.MERGE;
|
|
145
243
|
}
|
|
146
|
-
if (/^(?:npm|pnpm|yarn|bun)
|
|
244
|
+
if (/^(?:npm|pnpm|yarn|bun)(?:\.cmd)?\s+publish(?:\s|$)/.test(segment)) {
|
|
147
245
|
return ACTION_CLASS.PUBLISH;
|
|
148
246
|
}
|
|
149
247
|
if (
|
|
150
|
-
/^(?:terraform\s+(?:apply|destroy)|pulumi\s+up|kubectl\s+(?:apply|delete|rollout)|helm\s+(?:install|upgrade)|docker\s+push)
|
|
248
|
+
/^(?:terraform\s+(?:apply|destroy)|pulumi\s+up|kubectl\s+(?:apply|delete|rollout)|helm\s+(?:install|upgrade)|docker\s+push)(?:\s|$)/.test(
|
|
151
249
|
segment,
|
|
152
250
|
)
|
|
153
251
|
) {
|
|
@@ -155,55 +253,375 @@ export function classifyShellAction(command) {
|
|
|
155
253
|
? ACTION_CLASS.DEPLOY
|
|
156
254
|
: ACTION_CLASS.INFRA_MUTATION;
|
|
157
255
|
}
|
|
158
|
-
if (
|
|
159
|
-
|
|
256
|
+
if (
|
|
257
|
+
/^(?:npm|pnpm|yarn|bun)(?:\.cmd)?\s+run\s+(?:deploy|rollout)(?:\s|$)/.test(
|
|
258
|
+
segment,
|
|
259
|
+
)
|
|
260
|
+
)
|
|
261
|
+
return ACTION_CLASS.DEPLOY;
|
|
262
|
+
if (
|
|
263
|
+
/^(?:git\s+(?:status|diff|log|show)(?:\s|$)|git\s+branch\s*$|(?:ls|dir|pwd|cat|type|rg|grep|find|where)(?:\s|$))/.test(
|
|
264
|
+
segment,
|
|
265
|
+
)
|
|
266
|
+
) {
|
|
160
267
|
return ACTION_CLASS.READ;
|
|
161
268
|
}
|
|
162
|
-
if (
|
|
269
|
+
if (
|
|
270
|
+
/^(?:npm|pnpm|yarn|bun)(?:\.cmd)?\s+(?:test|run\s+(?:test|lint|build)|install)(?:\s|$)/.test(
|
|
271
|
+
segment,
|
|
272
|
+
) ||
|
|
273
|
+
/^(?:pytest|vitest|jest|cargo\s+test|go\s+test)(?:\s|$)/.test(segment)
|
|
274
|
+
) {
|
|
163
275
|
return ACTION_CLASS.LOCAL_WRITE;
|
|
164
276
|
}
|
|
165
|
-
if (/^echo
|
|
277
|
+
if (/^echo(?:\s|$)/.test(segment) && />/.test(segment)) {
|
|
166
278
|
return ACTION_CLASS.LOCAL_WRITE;
|
|
167
279
|
}
|
|
168
280
|
return null;
|
|
169
281
|
};
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
ACTION_CLASS.PUSH,
|
|
175
|
-
ACTION_CLASS.PUBLISH,
|
|
176
|
-
ACTION_CLASS.MERGE,
|
|
177
|
-
ACTION_CLASS.DEPLOY,
|
|
178
|
-
ACTION_CLASS.INFRA_MUTATION,
|
|
179
|
-
ACTION_CLASS.EXTERNAL_MESSAGE,
|
|
180
|
-
];
|
|
181
|
-
const classified = segments.map(classifySegment);
|
|
182
|
-
return classified.reduce((highest, current) => {
|
|
183
|
-
if (!current) return null;
|
|
184
|
-
if (!highest) return current;
|
|
185
|
-
return rank.indexOf(current) > rank.indexOf(highest) ? current : highest;
|
|
186
|
-
}, null);
|
|
282
|
+
return segments.map((segment) => ({
|
|
283
|
+
command: segment,
|
|
284
|
+
actionClass: classifySegment(segment),
|
|
285
|
+
}));
|
|
187
286
|
}
|
|
188
287
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
288
|
+
const ACTION_RANK = [
|
|
289
|
+
ACTION_CLASS.READ,
|
|
290
|
+
ACTION_CLASS.LOCAL_WRITE,
|
|
291
|
+
ACTION_CLASS.COMMIT,
|
|
292
|
+
ACTION_CLASS.PUSH,
|
|
293
|
+
ACTION_CLASS.PUBLISH,
|
|
294
|
+
ACTION_CLASS.MERGE,
|
|
295
|
+
ACTION_CLASS.DEPLOY,
|
|
296
|
+
ACTION_CLASS.INFRA_MUTATION,
|
|
297
|
+
ACTION_CLASS.EXTERNAL_MESSAGE,
|
|
298
|
+
];
|
|
299
|
+
|
|
300
|
+
// Unknown Git options may select executable helpers (upload-pack,
|
|
301
|
+
// receive-pack, rebase --exec, custom merge strategies, external diff, ...).
|
|
302
|
+
// Accept complete known options only; Git's long-option abbreviations do not
|
|
303
|
+
// inherit authority. These are command-specific because -s means different
|
|
304
|
+
// things for status, commit and merge.
|
|
305
|
+
const SAFE_GIT_OPTIONS = Object.freeze({
|
|
306
|
+
status: [
|
|
307
|
+
"--short",
|
|
308
|
+
"-s",
|
|
309
|
+
"--branch",
|
|
310
|
+
"-b",
|
|
311
|
+
"--porcelain",
|
|
312
|
+
"--porcelain=v1",
|
|
313
|
+
"--porcelain=v2",
|
|
314
|
+
"--untracked-files",
|
|
315
|
+
"--untracked-files=all",
|
|
316
|
+
"--untracked-files=no",
|
|
317
|
+
"--ignored",
|
|
318
|
+
],
|
|
319
|
+
diff: [
|
|
320
|
+
"--stat",
|
|
321
|
+
"--name-only",
|
|
322
|
+
"--name-status",
|
|
323
|
+
"--numstat",
|
|
324
|
+
"--shortstat",
|
|
325
|
+
"--patch",
|
|
326
|
+
"-p",
|
|
327
|
+
"--no-patch",
|
|
328
|
+
"-s",
|
|
329
|
+
"--cached",
|
|
330
|
+
"--staged",
|
|
331
|
+
"--no-ext-diff",
|
|
332
|
+
"--no-textconv",
|
|
333
|
+
"--no-renames",
|
|
334
|
+
"--no-color",
|
|
335
|
+
],
|
|
336
|
+
log: [
|
|
337
|
+
"--oneline",
|
|
338
|
+
"--stat",
|
|
339
|
+
"--name-only",
|
|
340
|
+
"--name-status",
|
|
341
|
+
"--patch",
|
|
342
|
+
"-p",
|
|
343
|
+
"--no-patch",
|
|
344
|
+
"--all",
|
|
345
|
+
"--graph",
|
|
346
|
+
"--decorate",
|
|
347
|
+
"--no-color",
|
|
348
|
+
"-n",
|
|
349
|
+
],
|
|
350
|
+
show: [
|
|
351
|
+
"--oneline",
|
|
352
|
+
"--stat",
|
|
353
|
+
"--name-only",
|
|
354
|
+
"--name-status",
|
|
355
|
+
"--patch",
|
|
356
|
+
"-p",
|
|
357
|
+
"--no-patch",
|
|
358
|
+
"--no-ext-diff",
|
|
359
|
+
"--no-textconv",
|
|
360
|
+
"--no-color",
|
|
361
|
+
],
|
|
362
|
+
"rev-parse": [
|
|
363
|
+
"--show-toplevel",
|
|
364
|
+
"--git-dir",
|
|
365
|
+
"--is-inside-work-tree",
|
|
366
|
+
"--verify",
|
|
367
|
+
"--short",
|
|
368
|
+
],
|
|
369
|
+
"ls-files": [
|
|
370
|
+
"--cached",
|
|
371
|
+
"--others",
|
|
372
|
+
"--modified",
|
|
373
|
+
"--deleted",
|
|
374
|
+
"--exclude-standard",
|
|
375
|
+
"--stage",
|
|
376
|
+
"--error-unmatch",
|
|
377
|
+
],
|
|
378
|
+
branch: [],
|
|
379
|
+
remote: ["-v"],
|
|
380
|
+
add: [
|
|
381
|
+
"--all",
|
|
382
|
+
"-A",
|
|
383
|
+
"--force",
|
|
384
|
+
"-f",
|
|
385
|
+
"--update",
|
|
386
|
+
"-u",
|
|
387
|
+
"--intent-to-add",
|
|
388
|
+
"-N",
|
|
389
|
+
"--dry-run",
|
|
390
|
+
"-n",
|
|
391
|
+
"--verbose",
|
|
392
|
+
"-v",
|
|
393
|
+
],
|
|
394
|
+
commit: [
|
|
395
|
+
"-m",
|
|
396
|
+
"--message",
|
|
397
|
+
"-a",
|
|
398
|
+
"--all",
|
|
399
|
+
"--amend",
|
|
400
|
+
"--no-verify",
|
|
401
|
+
"--allow-empty",
|
|
402
|
+
"--allow-empty-message",
|
|
403
|
+
"--signoff",
|
|
404
|
+
"-s",
|
|
405
|
+
"--no-gpg-sign",
|
|
406
|
+
"--quiet",
|
|
407
|
+
"-q",
|
|
408
|
+
"--dry-run",
|
|
409
|
+
],
|
|
410
|
+
fetch: [
|
|
411
|
+
"--all",
|
|
412
|
+
"--prune",
|
|
413
|
+
"-p",
|
|
414
|
+
"--tags",
|
|
415
|
+
"-t",
|
|
416
|
+
"--no-tags",
|
|
417
|
+
"--quiet",
|
|
418
|
+
"-q",
|
|
419
|
+
"--verbose",
|
|
420
|
+
"-v",
|
|
421
|
+
"--dry-run",
|
|
422
|
+
"--no-recurse-submodules",
|
|
423
|
+
"--unshallow",
|
|
424
|
+
],
|
|
425
|
+
push: [
|
|
426
|
+
"-u",
|
|
427
|
+
"--set-upstream",
|
|
428
|
+
"--force",
|
|
429
|
+
"-f",
|
|
430
|
+
"--force-with-lease",
|
|
431
|
+
"--no-verify",
|
|
432
|
+
"--dry-run",
|
|
433
|
+
"-n",
|
|
434
|
+
"--all",
|
|
435
|
+
"--mirror",
|
|
436
|
+
"--tags",
|
|
437
|
+
"--delete",
|
|
438
|
+
"-d",
|
|
439
|
+
],
|
|
440
|
+
merge: [
|
|
441
|
+
"--ff-only",
|
|
442
|
+
"--no-ff",
|
|
443
|
+
"--squash",
|
|
444
|
+
"--abort",
|
|
445
|
+
"--continue",
|
|
446
|
+
"--quit",
|
|
447
|
+
"--no-edit",
|
|
448
|
+
"--no-verify",
|
|
449
|
+
"--no-gpg-sign",
|
|
450
|
+
],
|
|
451
|
+
rebase: [
|
|
452
|
+
"--abort",
|
|
453
|
+
"--continue",
|
|
454
|
+
"--skip",
|
|
455
|
+
"--quit",
|
|
456
|
+
"--autostash",
|
|
457
|
+
"--no-autostash",
|
|
458
|
+
"--no-gpg-sign",
|
|
459
|
+
],
|
|
460
|
+
"cherry-pick": [
|
|
461
|
+
"--abort",
|
|
462
|
+
"--continue",
|
|
463
|
+
"--skip",
|
|
464
|
+
"--quit",
|
|
465
|
+
"--no-commit",
|
|
466
|
+
"-n",
|
|
467
|
+
"--no-gpg-sign",
|
|
468
|
+
],
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
function hasKnownGitOptions(argv) {
|
|
472
|
+
const [subcommand, ...args] = argv;
|
|
473
|
+
const known = SAFE_GIT_OPTIONS[subcommand];
|
|
474
|
+
if (!Array.isArray(known)) return false;
|
|
475
|
+
let pathOperands = false;
|
|
476
|
+
let valueOperand = false;
|
|
477
|
+
return args.every((value) => {
|
|
478
|
+
if (valueOperand) {
|
|
479
|
+
valueOperand = false;
|
|
480
|
+
return true;
|
|
481
|
+
}
|
|
482
|
+
if (/^[a-z][a-z0-9+.-]*::/i.test(value)) return false;
|
|
483
|
+
if (pathOperands) return true;
|
|
484
|
+
if (value === "--") {
|
|
485
|
+
pathOperands = true;
|
|
486
|
+
return true;
|
|
487
|
+
}
|
|
488
|
+
if (!value.startsWith("-")) return true;
|
|
489
|
+
if (
|
|
490
|
+
["log", "show"].includes(subcommand) &&
|
|
491
|
+
/^--(?:format|pretty)=/.test(value)
|
|
492
|
+
)
|
|
493
|
+
return true;
|
|
494
|
+
if (subcommand === "log" && /^(?:-\d+|--max-count=\d+)$/.test(value))
|
|
495
|
+
return true;
|
|
496
|
+
if (subcommand === "fetch" && /^--depth=\d+$/.test(value)) return true;
|
|
497
|
+
if (subcommand === "commit" && /^--message=/.test(value)) return true;
|
|
498
|
+
if (!known.includes(value)) return false;
|
|
499
|
+
if (
|
|
500
|
+
(subcommand === "commit" && ["-m", "--message"].includes(value)) ||
|
|
501
|
+
(subcommand === "log" && value === "-n")
|
|
502
|
+
)
|
|
503
|
+
valueOperand = true;
|
|
504
|
+
return true;
|
|
505
|
+
});
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
export function classifyShellAction(command) {
|
|
509
|
+
const segments = classifyShellSegments(command);
|
|
510
|
+
if (!segments.length || segments.some((segment) => !segment.actionClass))
|
|
511
|
+
return null;
|
|
512
|
+
return segments.reduce(
|
|
513
|
+
(highest, { actionClass }) =>
|
|
514
|
+
ACTION_RANK.indexOf(actionClass) > ACTION_RANK.indexOf(highest)
|
|
515
|
+
? actionClass
|
|
516
|
+
: highest,
|
|
517
|
+
null,
|
|
518
|
+
);
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
function pushNeedsMergeAuthorization(argv) {
|
|
522
|
+
const positional = [];
|
|
523
|
+
for (const value of argv) {
|
|
524
|
+
if (
|
|
525
|
+
[
|
|
526
|
+
"-u",
|
|
527
|
+
"--set-upstream",
|
|
528
|
+
"--force",
|
|
529
|
+
"-f",
|
|
530
|
+
"--force-with-lease",
|
|
531
|
+
"--no-verify",
|
|
532
|
+
"--dry-run",
|
|
533
|
+
"-n",
|
|
534
|
+
].includes(value)
|
|
535
|
+
)
|
|
536
|
+
continue;
|
|
537
|
+
if (value.startsWith("-")) return true;
|
|
538
|
+
positional.push(value);
|
|
539
|
+
}
|
|
540
|
+
// Require an explicit remote AND every destination ref. Git configuration
|
|
541
|
+
// controls omitted refspecs and may include protected branches.
|
|
542
|
+
if (positional.length < 2) return true;
|
|
543
|
+
return positional.slice(1).some((refspec) => {
|
|
544
|
+
const destination = refspec.replace(/^\+/, "").split(":").at(-1);
|
|
545
|
+
if (
|
|
546
|
+
!destination ||
|
|
547
|
+
!/^[a-z0-9._/-]+$/i.test(destination) ||
|
|
548
|
+
destination.toUpperCase() === "HEAD"
|
|
549
|
+
)
|
|
550
|
+
return true;
|
|
551
|
+
const branch = destination.replace(/^refs\/heads\//, "");
|
|
552
|
+
return (
|
|
553
|
+
/^(?:main|master|develop|production)$/i.test(branch) ||
|
|
554
|
+
(/^refs\//.test(destination) && !destination.startsWith("refs/heads/"))
|
|
196
555
|
);
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
/** Classify the exact argv used by the git tool, never a shell string. */
|
|
560
|
+
export function evaluateUnattendedGitAction(argv, params = {}) {
|
|
561
|
+
const validArgv =
|
|
562
|
+
Array.isArray(argv) && argv.every((value) => typeof value === "string");
|
|
563
|
+
const subcommand = validArgv ? argv[0] : null;
|
|
564
|
+
const actionClass =
|
|
565
|
+
!validArgv || !hasKnownGitOptions(argv)
|
|
566
|
+
? null
|
|
567
|
+
: subcommand === "push"
|
|
568
|
+
? ACTION_CLASS.PUSH
|
|
569
|
+
: ["merge", "rebase", "cherry-pick"].includes(subcommand)
|
|
570
|
+
? ACTION_CLASS.MERGE
|
|
571
|
+
: ["add", "commit", "fetch"].includes(subcommand)
|
|
572
|
+
? ACTION_CLASS.LOCAL_WRITE
|
|
573
|
+
: [
|
|
574
|
+
"status",
|
|
575
|
+
"diff",
|
|
576
|
+
"log",
|
|
577
|
+
"show",
|
|
578
|
+
"rev-parse",
|
|
579
|
+
"ls-files",
|
|
580
|
+
].includes(subcommand) ||
|
|
581
|
+
(subcommand === "branch" && argv.length === 1) ||
|
|
582
|
+
(subcommand === "remote" &&
|
|
583
|
+
argv.slice(1).every((value) => value === "-v"))
|
|
584
|
+
? ACTION_CLASS.READ
|
|
585
|
+
: null;
|
|
197
586
|
return {
|
|
198
587
|
actionClass,
|
|
199
588
|
...evaluateUnattendedAction({
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
589
|
+
...params,
|
|
590
|
+
actionClass,
|
|
591
|
+
protectedBranch:
|
|
592
|
+
params.protectedBranch === true ||
|
|
593
|
+
(subcommand === "push" && pushNeedsMergeAuthorization(argv.slice(1))),
|
|
203
594
|
}),
|
|
204
595
|
};
|
|
205
596
|
}
|
|
206
597
|
|
|
598
|
+
/** Apply the unattended policy to a shell command, including protected push targets. */
|
|
599
|
+
export function evaluateUnattendedShellAction(command, params = {}) {
|
|
600
|
+
const segments = classifyShellSegments(command);
|
|
601
|
+
const verdicts = (segments.length ? segments : [{ actionClass: null }]).map(
|
|
602
|
+
(segment) => ({
|
|
603
|
+
actionClass: segment.actionClass,
|
|
604
|
+
...evaluateUnattendedAction({
|
|
605
|
+
...params,
|
|
606
|
+
actionClass: segment.actionClass,
|
|
607
|
+
protectedBranch:
|
|
608
|
+
params.protectedBranch === true ||
|
|
609
|
+
(segment.actionClass === ACTION_CLASS.PUSH &&
|
|
610
|
+
pushNeedsMergeAuthorization(segment.command.split(/\s+/).slice(2))),
|
|
611
|
+
}),
|
|
612
|
+
}),
|
|
613
|
+
);
|
|
614
|
+
// An allowlist grants individual classes, never all lower-ranked actions.
|
|
615
|
+
const denied = verdicts.find((verdict) => !verdict.allow);
|
|
616
|
+
if (denied) return denied;
|
|
617
|
+
return verdicts.reduce((highest, current) =>
|
|
618
|
+
ACTION_RANK.indexOf(current.actionClass) >
|
|
619
|
+
ACTION_RANK.indexOf(highest.actionClass)
|
|
620
|
+
? current
|
|
621
|
+
: highest,
|
|
622
|
+
);
|
|
623
|
+
}
|
|
624
|
+
|
|
207
625
|
/**
|
|
208
626
|
* Decide whether a fired task may perform one action. Fail-closed.
|
|
209
627
|
*
|