fix(dispatch): execute runcommands shell actions (VA-132) #131

Merged
longjacksonle merged 1 commit from fix/VA-132-runcommands-dispatch into main 2026-07-14 05:51:44 +02:00

Fixes VA-132. The console "Run command" sends action=runcommands (a shell command string), but the agent only handled executecommand (explicit program + args), so runcommands hit the unhandled-action path and never executed. Proven during VA-129 macOS validation: a touch via Run command created no file, and the agent logged unhandled JSON action action="runcommands".

Change

  • New runcommands arm in route_json that runs the command via the platform shell through the existing host::exec: /bin/sh -c <cmds> on Unix, cmd /C or (for type 1) powershell -Command on Windows. Fire-and-forget - no reply frame, matching the server's ack-routed contract; runs on a detached task so a long command can't stall the dispatch loop.
  • Execution core (run_shell_command) split from the fire-and-forget wrapper (spawn_runcommands) so it's deterministically unit-testable.
  • runAsUser != 0 is not yet supported and logs a warning (the console sends 0 = the agent's user).

Why not executecommand

executecommand (program + args, output capture + reply) has no live client - MCP's exec calls host::exec directly, and the console uses runcommands. The two are kept distinct; this adds the missing runcommands consumer rather than changing the client.

Tests / verification

  • New unit tests (pass on Linux; the unix arm is shared by macOS): runcommands_shell_unix_wraps_in_sh_dash_c, runcommands_executes_shell_string (asserts a marker file is actually created), runcommands_action_is_fire_and_forget (no reply frame; missing cmds ignored).
  • cargo clippy --all-targets -- --deny warnings and cargo fmt --check clean.
  • Windows arm covered by CI check-windows.
  • End-to-end macOS verification (console Run command executes) to be confirmed on the validation Mac before merge.

Cross-platform: the dispatcher is platform-agnostic; the gap affected Linux/Windows too. Surfaced during VA-129.

🤖 Generated with Claude Code

https://claude.ai/code/session_01QJiqE8CSatRaZysXtLHeVS

Fixes VA-132. The console "Run command" sends `action=runcommands` (a shell command string), but the agent only handled `executecommand` (explicit program + args), so `runcommands` hit the unhandled-action path and never executed. Proven during VA-129 macOS validation: a `touch` via Run command created no file, and the agent logged `unhandled JSON action action="runcommands"`. ## Change - New `runcommands` arm in `route_json` that runs the command via the platform shell through the existing `host::exec`: `/bin/sh -c <cmds>` on Unix, `cmd /C` or (for `type` 1) `powershell -Command` on Windows. Fire-and-forget - no reply frame, matching the server's ack-routed contract; runs on a detached task so a long command can't stall the dispatch loop. - Execution core (`run_shell_command`) split from the fire-and-forget wrapper (`spawn_runcommands`) so it's deterministically unit-testable. - `runAsUser != 0` is not yet supported and logs a warning (the console sends 0 = the agent's user). ## Why not `executecommand` `executecommand` (program + args, output capture + reply) has no live client - MCP's `exec` calls `host::exec` directly, and the console uses `runcommands`. The two are kept distinct; this adds the missing `runcommands` consumer rather than changing the client. ## Tests / verification - New unit tests (pass on Linux; the `unix` arm is shared by macOS): `runcommands_shell_unix_wraps_in_sh_dash_c`, `runcommands_executes_shell_string` (asserts a marker file is actually created), `runcommands_action_is_fire_and_forget` (no reply frame; missing `cmds` ignored). - `cargo clippy --all-targets -- --deny warnings` and `cargo fmt --check` clean. - Windows arm covered by CI `check-windows`. - End-to-end macOS verification (console Run command executes) to be confirmed on the validation Mac before merge. Cross-platform: the dispatcher is platform-agnostic; the gap affected Linux/Windows too. Surfaced during VA-129. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01QJiqE8CSatRaZysXtLHeVS
fix(dispatch): execute runcommands shell actions (VA-132)
All checks were successful
Check / fmt + clippy + tests (pull_request) Successful in 4m14s
Create release / Create release from merged PR (pull_request) Has been skipped
e032b289a3
The console "Run command" sends action=runcommands (a shell command string), but the agent only handled executecommand (explicit program + args). runcommands fell through to the unhandled-action path, so the command never ran (a touch via Run command created no file during VA-129 macOS validation).

Add a runcommands arm that runs the command through the platform shell (/bin/sh -c on Unix, cmd /C or powershell on Windows, selected by type) via the existing host::exec, fire-and-forget: no reply frame, matching the server's ack-routed contract. The execution core is split out so it is unit-testable while the live path stays detached. runAsUser != 0 is not yet supported and logs a warning.

Cross-platform (the dispatcher is platform-agnostic); surfaced on macOS but the same gap affected Linux/Windows. host::exec itself was already correct (its own tests pass on macOS).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QJiqE8CSatRaZysXtLHeVS
longjacksonle deleted branch fix/VA-132-runcommands-dispatch 2026-07-14 05:51:45 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/vervain-agent!131
No description provided.