# vtcode-bash-runner
## Modules
## Rules
- `CommandExecutor` trait = primary abstraction for new backends.
- `CommandPolicy` trait = execution gate. `WorkspaceGuardPolicy` enforces boundaries.
- Preserve command shape through admission: direct argv executes without shell reconstruction; shell scripts require explicit validated syntax and never fall back from malformed argv.
- Feature flags: `dry-run`, `pure-rust`, `exec-events`, `serde-errors`.
- `process_group` uses safe `nix` wrappers (`Pid::from_raw`, `signal::killpg`, `setpgid` in `pre_exec`); there is no `unsafe` here. Unsafe env mutation is centralized in `vtcode-commons::env_lock`, serialized by a process-wide mutex.
## Testing
## Gotchas
- `BashRunner::new()` canonicalizes root — bails if missing.
- Authorization resolves paths freshly; never cache symlink targets across operations. OS sandboxing or bound filesystem handles remain necessary against concurrent replacement.
- Unsafe env mutation (`set_var`/`remove_var`) is centralized in `vtcode-commons::env_lock`, serialized by a process-wide mutex, single-threaded startup only.
- `policy` containment delegates to `vtcode_commons::paths::ensure_path_within_workspace` — `..`-traversal paths are rejected (intentionally stricter than the old `starts_with`).
- Pipe spooling opts into `SpawnedProcess::reliable_output_rx`, a bounded lossless stream; legacy broadcast subscribers must remain independent of that backpressure path.
- `wait_with_output` bounds post-exit draining even when a descendant inherits the pipe; never turn that drain back into an unbounded wait.