Skip to content

feat: add guarded autopilot mode for Grok - #970

Open
sazora wants to merge 2 commits into
FerroxLabs:mainfrom
sazora:feat/grok-guarded-autopilot
Open

feat: add guarded autopilot mode for Grok#970
sazora wants to merge 2 commits into
FerroxLabs:mainfrom
sazora:feat/grok-guarded-autopilot

Conversation

@sazora

@sazora sazora commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Summary

  • adds a per-conversation Guarded Autopilot mode for the Grok ACP backend
  • keeps Grok on its native default ACP mode and lets Wayland own guarded approval handling; it does not enable raw YOLO/full-auto behavior
  • prevents a paired remote WebUI client from arming autoGuarded, while preserving ordinary remote ACP mode changes

Safety behavior

Routine Grok permission requests are auto-approved in guarded mode. Existing catastrophic shell-command checks remain explicit confirmations. This intentionally does not add Grok to FULL_AUTO_MODE.

Verification

  • focused unit/red-team suite: 38 passing
  • TypeScript typecheck: passed
  • lint: no errors (existing repository warnings remain)
  • production package: passed

The mode is scoped to a local desktop conversation and is not a sandbox or a replacement for workspace/egress controls.

@sazora
sazora requested a review from FerroxLabs as a code owner August 16, 2026 03:33
@github-actions github-actions Bot added area:desktop-ui Desktop UI area:core Wayland Core engine / backends labels Aug 16, 2026
@sazora
sazora force-pushed the feat/grok-guarded-autopilot branch from 6e1dc0c to daffcbf Compare August 16, 2026 03:38
@sazora
sazora force-pushed the feat/grok-guarded-autopilot branch from f30b6ad to ef71700 Compare August 16, 2026 04:03
@FerroxLabs

Copy link
Copy Markdown
Owner

Thank you for this, and separately thank you for going back to confirm #940 was still broken after the release. That kind of follow-through is genuinely valuable and it did not go unnoticed.

I have given this a full adversarial pass, because it is approval-behaviour code in the security shell and it deserved more than a skim. I want to be straight with you: the verdict is not-yet, but most of the reasoning is about scope rather than craft. Your reading of the trust boundary is right. The WebSocket adapter is the correct place for a value-level gate, isRemoteDeniedConfigWrite is the correct thing to mirror, settleRejectedInvoke is used correctly so the WebUI does not white-screen, and the subscribe-acp.set-mode wire name is right (I chased that as a suspected typo; it is not one). That is a better grasp of this codebase than most first contributions to it.

Five things need resolving before this can land.

1. The guardrail only inspects execute-kind tool calls.
classifyDestructiveToolCall returns not-destructive for every other kind, so in autoGuarded a delete, move, fetch, or MCP tool call is auto-approved with no inspection at all. Compare workspaceTrust.ts, where Cowork, our most conservative axis, allows only read, search and edit, and the comment explicitly excludes delete and move because destructive file ops must always prompt. As written, Guarded Autopilot would be less strict than Cowork while being presented in the UI as the guarded option. This needs an explicit kind allowlist before the command classifier runs.

2. The classifier is not strong enough to carry a user-facing promise.
It is a pattern denylist, and the file header is honest that it is a backstop rather than a sandbox. That is a fair description for the internal unattended paths it serves today. The new dropdown copy makes a stronger guarantee than the code delivers, and quoting and path-shape variations matter more than they look. We are hardening this separately; I would rather land that first so you are building on something firmer. Either way the labelling and the guarantee need to agree.

3. The remote gate closes one door of several.
isAllowedForRemote is default-allow, and none of these paths is currently denied: create-conversation carrying extra.sessionMode, update-conversation with mergeExtra writing the same field, agent.config.storage.set writing the acp.config preferred-mode key, and team.set-session-mode. Each of those arms autoGuarded without ever touching acp.set-mode. That third one is very close to the workspace.trustLevel side door described in the comment you modelled this on, so it is worth re-reading. It is also worth looking just above it at the outbound rule, where we concluded that a second hand-maintained list is exactly how these two drift apart, and derived the rule structurally instead. The same argument applies to a fourth predicate here.

4. Selector and engine can diverge silently.
AgentModeSelector prefers dynamic modes, then cached modes, then the static list, and grok will never advertise a Wayland-invented autoGuarded. Once grok reports its own modes, validInitialMode falls back to Default while the manager is still in autoGuarded and still auto-approving. Because the effect only sets local state, it never calls set-mode and so never reconciles. The same path may also make the option unselectable, which would render the feature inert. The Wayland-owned mode needs to be unioned onto capability modes rather than replaced by them.

5. Please split out the recoveryCapture change.
The slow Windows fixture is a real problem and worth fixing. But that test was proving the production 20,000-entry cap holds on an attestation path, and after the change it proves that a cap of one rejects two, via a new parameter on the production signature. That deserves its own PR and its own discussion rather than riding along with a feature.

None of this is wasted work. The adapter gate is sound and worth keeping; it needs the declarative paths alongside it. If you want to take another pass, I am happy to review it again, and I would start with the kind allowlist in point 1 since it is the smallest change with the largest effect. If you would rather hand it off at this point that is completely fine too, just say the word and we will pick it up from here with credit to you.

One practical note: main has moved a fair way under this branch, including two changes to bridgeAllowlist.ts, so it will need a rebase before it is mergeable.

@FerroxLabs

Copy link
Copy Markdown
Owner

Core-lane triage: removing area:core — this PR contains no Core code.

All nine changed files are TypeScript in the Desktop tree (src/common/adapter/, src/process/, src/renderer/, tests/unit/). There are no crates/** changes, so nothing here is reviewable or testable by the wayland-core lane, and the label was routing it to a lane that cannot act on it.

Two things for the Desktop lane, neither of which is a Core call:

  • The PR is currently CONFLICTING against its base and was last updated 2026-08-16. It needs a rebase before it can be assessed.
  • The safety claim ("routine Grok permission requests are auto-approved in guarded mode; existing catastrophic shell-command checks remain explicit confirmations") is an approval-policy change and deserves a review against the Desktop approval surface. Core has no equivalent gate to cross-check it against, and the engine-side non-bypassable command floor is separately tracked in [0.12.0 L3] Non-Bypassable Command Floor + Learned Egress/Approval #693 — worth reading together, but they are not the same control.

Leaving area:desktop-ui, no other change.

@FerroxLabs FerroxLabs removed the area:core Wayland Core engine / backends label Aug 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants