fix(conductor): let the fleet read surface run without prompting - #328
Merged
Conversation
conductor-design §3 specifies that the fleet READ verbs — fleet_list, fleet_find, fleet_summary, fleet_recall, fleet_tasks, machine_map — "run silently". They did not. `isSafeTool` knew the memory and blackboard mounts but not the fleet, so in guarded mode every one of them raised an approval prompt. Found by driving a real conductor rather than reading the code: asking it to resolve a session reference produced an approval request for `fleet_find`, which is a read. An assistant that asks permission to look something up is not an assistant, and this is the first friction anyone meets in the new conductor pane (#325). The daemon already put these verbs in the provider's `allowedTools`, so the SDK warned it would auto-approve them — but codeoid's own gate is consulted independently and did not recognise them, which is why the two disagreed. Follows the established shape exactly: match the namespace prefix, then require the suffix to be a known read verb. Never a bare prefix match — an over-broad match here is a prompt bypass, which is why a look-alike segment (`mcp__evil_codeoid_fleet__…`) is asserted to gain nothing. The read list is `FLEET_READ_TOOLS` from the shared protocol package, so the send half cannot leak in by someone editing one of two copies. Send verbs remain hard-gated BEFORE this function is consulted (`isFleetSendTool` in Session#shouldAutoApprove, checked ahead of any mode logic); this is defence in depth, not the fence. Verified live, both directions. With the fix, fleet_list / fleet_find / machine_map go straight to `executing` with zero prompts; fleet_spawn still lands in `waiting_confirmation` and waits for the owner. The R3 invariant is intact. Also lists the bare (non-`mcp__`) namespacing so a mounted fleet (#245) does not silently regress to prompting on every read. 10 tool-safety tests; 2452 daemon tests; typecheck and lint clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
rsharath
approved these changes
Sep 6, 2026
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.
The bug
conductor-design §3 specifies that the fleet read verbs run silently:
They don't.
isSafeToolknows the memory and blackboard mounts but not the fleet, so inguardedmode every one of them raises an approval prompt.Found by driving a real conductor rather than reading code — asking it to resolve a session reference produced an approval request for
fleet_find, which is a read. An assistant that asks permission to look something up is not an assistant, and it's the first friction anyone meets in the conductor pane from #325.Worth noting the two layers disagreed: the daemon already puts these verbs in the provider's
allowedTools(the SDK even warns it will auto-approve them), but codeoid's own gate is consulted independently and didn't recognise them.The fix
Follows the established shape exactly — match the namespace prefix, then require the suffix to be a known read verb. Never a bare prefix match: an over-broad match here is a prompt bypass, which is why a look-alike segment (
mcp__evil_codeoid_fleet__fleet_find) is asserted to gain nothing.The read list is
FLEET_READ_TOOLSfrom the shared protocol package (#323), so the send half cannot leak in by someone editing one of two copies.Why this is safe
Send-class verbs are hard-gated before this function is ever consulted —
isFleetSendToolinSession#shouldAutoApprove, checked ahead of any mode logic, as the R3 invariant. This change is defence in depth, not the fence.Verified live, both directions
With the fix, on a real conductor:
And the half that must never regress — same daemon, asking it to spawn:
Reads run silently; the owner still confirms every dispatch.
Also
Lists the bare (non-
mcp__) namespacing alongside the in-process one, so a mounted fleet (#245) doesn't silently regress to prompting on every read.Verification: 10 tool-safety tests (4 new, covering both namespacings, every send verb, an unknown verb, and look-alike prefixes), 2452 daemon tests, typecheck and lint clean.
🤖 Generated with Claude Code