Skip to content

zarvis: run read-only shell calls concurrently via explicit read_only flag (#331)#334

Merged
edwin-zvs merged 1 commit into
mainfrom
zarvis-read-only-shell-parallel
Jun 2, 2026
Merged

zarvis: run read-only shell calls concurrently via explicit read_only flag (#331)#334
edwin-zvs merged 1 commit into
mainfrom
zarvis-read-only-shell-parallel

Conversation

@edwin-zvs

Copy link
Copy Markdown
Contributor

Closes #331 (execution-side enabler, option 2).

What

Adds a read_only: boolean argument to the shell tool. A non-interactive shell call flagged read_only: true is downgraded to Safe in effective_risk(), which is what lets the agent loop fan it out concurrently (join_all) instead of serializing it through the approval gate. So several read-only shell inspections issued in one turn now run in parallel — mirroring the dedicated read-only inspection tools (agentd_context, agentd_get_diff, …) that are already Safe.

Why option 2

Per the issue, this is the model-trusting approach: the harness honors the model's read_only declaration rather than parsing the command line (which command substitution / redirects / chaining can defeat). It's scoped conservatively:

  • only the shell tool,
  • only when the flag is literally true,
  • never for interactive: true (a long-lived process is not a bounded read).

The read-only-only contract ("provably side-effect-free: no writes, redirects, $(...), or chaining into a mutator") lives in the tool's arg description and the system prompt.

Behavior change to note

A read-only shell call no longer prompts for approval — including in manual mode — exactly like other Safe read tools. This is intended (you don't want to approve every cat), but it does rely on the model labeling honestly. A mutating command the model mislabels would bypass the gate; that's the documented tradeoff of option 2. Option 1's command-line allowlist can be layered on later as defense-in-depth (the issue notes the options aren't mutually exclusive) — I left a Non-Goal in the spec for it.

Changes

  • tools/shell.rsread_only schema arg + description; updated tool description.
  • tools/mod.rseffective_risk() downgrade + shell_read_only_optin() helper; unit tests.
  • agent.rs — system-prompt nudge to mark parallel reads read_only: true.
  • specs/0017-read-only-shell-runs-concurrently.md — records the new approval-semantics decision (relates to 0015-approval-modes).

Tests

  • effective_risk_downgrades_read_only_shell — classification: read_only:true → Safe; absent/false → Risky; interactive overrides; opt-in doesn't leak to other tools.
  • read_only_shell_calls_are_safe_and_run_concurrently — duration test (two sleep 1 reads finish in ~1s, not ~2s).
  • Full suite: 146 passed.

Where the code lives

Only touches crates/adapter-zarvis → relevant binary is agentd-adapter-zarvis. All workspace binaries built (debug) in the worktree; the rest are unchanged from main.

No recording — harness execution/approval logic with no user-visible TUI render to demo.

🤖 Generated with Claude Code

… flag

Shell is Risky, and the agent loop only fans out Safe calls — Risky calls
serialize through the approval gate. So batched read-only shell inspections
(reading several files in one turn) could never run concurrently, even in
unsafe_auto.

Add a `read_only` boolean arg to the shell tool. effective_risk() downgrades
a non-interactive shell call flagged read_only:true to Safe, so such calls
fan out via join_all and skip the gate — mirroring the dedicated read-only
inspection tools (agentd_context, agentd_get_diff, …) that are already Safe.

This is the model-trusting design (option 2 of #331): the harness honors the
flag rather than parsing the command line. Scoped conservatively — only shell,
only an explicit true, never interactive. The read-only-only contract lives in
the arg description and the system prompt. Adds a spec (0017) and tests
covering classification and a concurrency duration check.

Closes #331
@edwin-zvs
edwin-zvs merged commit 5944c08 into main Jun 2, 2026
1 check passed
@edwin-zvs
edwin-zvs deleted the zarvis-read-only-shell-parallel branch June 2, 2026 15:11
@edwin-zvs edwin-zvs mentioned this pull request Jun 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Run read-only shell calls concurrently (conditionally downgrade from Risky)

1 participant