Expose enabled vs gated commands at connect time (#324)#340
Merged
Conversation
A freshly provisioned session enables the standard observation/actuation tools but leaves `launch` and every raw `send_command` built-in (chars:, winr, mouse:, VK_* keys, chords) gated. An agent could only learn that set by hitting `command-disabled` one command at a time. Expose the split up front so the agent can batch a single request-command-access: - `initialize` result now carries a `commandAccess` map (`enabledTools`/`gatedTools`/`rawSendCommandGated` + a recovery note), derived from `ToolCatalog.CommandAccessDefaults` (the ProvisionedByDefault flags — single source of truth, so it never drifts as defaults change). - `session-start`/`session-status` stamp the LIVE table via `AgentToolExecutor.LiveCommandAccess`, so an agent can confirm a grant landed. Both surfaces share one builder (`ToolCatalog.CommandAccessMap`) and note, so shape and guidance can't diverge. - Connect-time prose (AgentInstructions.md PROVISION/COMMAND ACCESS) now points at the field instead of relying on trial-and-error discovery. - Docs (agent_control.md, AGENTS.md) updated. Bootstrap mode omits the block (its only tools are provision-session/end-session; no gated surface). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e010a4f9cf
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…#340) Codex P2: deriving `rawSendCommandGated` from `chars:` alone meant a partial grant (operator enables only `chars:`, a common first request) reported the whole raw send_command surface as open, even though `winr`/`mouse:`/VK/chord commands stayed disabled. An agent using session-status to confirm the grant would then hit `command-disabled` on the next raw command. Replace the lossy boolean with an explicit `enabledRawCommands` list: - LiveCommandAccess enumerates the actual command table and lists every enabled entry that is not a catalog tool, so a partial grant shows exactly which raw commands are live (chars: present, winr/mouse: absent). - CommandAccessDefaults reports it empty (no raw built-in is provisioned by default). Same shape on both surfaces via the shared CommandAccessMap. - Note/docs/prose updated: a raw command not in enabledRawCommands still needs a request; a partial grant does not open the whole raw surface. Test now grants chars: while leaving mouse: disabled and asserts mouse: is absent from enabledRawCommands (and launch, a catalog tool, is not double-reported as raw). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #324.
Problem
A freshly provisioned session enables the standard observation/actuation tools (
ToolCatalog.ProvisionedByDefault) but leaveslaunchand every rawsend_commandbuilt-in (chars:,winr,mouse:,VK_*keys, chords) gated. Per the #318 field report, an agent could only discover that set by hittingcommand-disabledone command at a time.Change
Expose the enabled/gated split at connect time so the agent can batch a single
request-command-accessbefore its first actuation.initializeresult now carries acommandAccessobject:{ "enabledTools": ["capture","query","displays","windows","window","find","wait-for","invoke","drag","click","focus","clipboard","record"], "gatedTools": ["launch"], "rawSendCommandGated": true, "note": "Gated commands need the operator's consent before first use: call request-command-access ... in ONE call ..." }Derived from
ToolCatalog.CommandAccessDefaults(theProvisionedByDefaultflags) — single source of truth in code, so it never drifts as provisioning defaults change (acceptance criterion Possible to Map Command to Key Combo? #2). Omitted in bootstrap mode (only tools areprovision-session/end-session; no gated surface).session-start/session-statusresults stamp the live table viaAgentToolExecutor.LiveCommandAccess, so an agent can re-check that a grant landed. Both surfaces share one builder (ToolCatalog.CommandAccessMap) and note, so shape/guidance can't diverge.Connect-time prose (
AgentInstructions.mdPROVISION / COMMAND ACCESS) now points at the field instead of relying on trial-and-error; docs (agent_control.md,AGENTS.md) updated.Why initialize over the provision handoff (issue Option A)
BuildAgentPromptonly renders on the operator's "Provision new…" dialog — a self-provisioning agent (bootstrap →provision-session→ reconnect) never sees it, and it's operator-pasted prose decoupled from the instance.initializeis true connect-time, zero round-trip, reaches every path, and (viasession-status) gives live post-grant accuracy.Note on the "one call" goal
The realistic win is knowing the shape up front (
launch+ raw built-ins gated) so the agent batches the built-ins its plan uses in one round — it still can't enumerate specific built-ins it hasn't planned yet, so the target isn't literally zerocommand-disabledever.Acceptance
initialize.commandAccess).ToolCatalog, not hand-maintained prose.Tests
Dispatch_Initialize_IncludesCommandAccessDefaults—launchgated,capture/invokeenabled,rawSendCommandGatedtrue, every gated name is a real catalog tool.Dispatch_SessionStatus_IncludesLiveCommandAccess_ReflectingTheTable— live table drives the split; an enabledlaunch/chars:flips out of the gated set.🤖 Generated with Claude Code