feat(tools): implement Bash tool with persistent sessions and timeouts (M4 complete)
This commit implements the complete M4 milestone (Bash tool) including:
Bash Session:
- Persistent bash session using tokio::process
- Environment variables persist between commands
- Current working directory persists between commands
- Session-based execution (not one-off commands)
- Automatic cleanup on session close
Key Features:
- Command timeout support (default: 2 minutes, configurable per-command)
- Output truncation (max 2000 lines for stdout/stderr)
- Exit code capture and propagation
- Stderr capture alongside stdout
- Command delimiter system to reliably detect command completion
- Automatic backup of exit codes to temp files
Implementation Details:
- Uses tokio::process for async command execution
- BashSession maintains single bash process across multiple commands
- stdio handles (stdin/stdout/stderr) are taken and restored for each command
- Non-blocking stderr reading with timeout to avoid deadlocks
- Mutex protection for concurrent access safety
CLI Integration:
- Added `bash` subcommand: `owlen bash <command> [--timeout <ms>]`
- Permission checks with command context for pattern matching
- Stdout/stderr properly routed to respective streams
- Exit code propagation (exits with same code as bash command)
Permission Enforcement:
- Plan mode (default): blocks Bash (asks for approval)
- Code mode: allows Bash
- Pattern matching support for command-specific rules (e.g., "npm test*")
Testing:
- 7 tests in tools-bash for session behavior
- bash_persists_env_between_calls ✅
- bash_persists_cwd_between_calls ✅
- bash_command_timeout ✅
- bash_output_truncation ✅
- bash_command_failure_returns_error_code ✅
- bash_stderr_captured ✅
- bash_multiple_commands_in_sequence ✅
- 3 new tests in CLI for permission enforcement
- plan_mode_blocks_bash_operations ✅
- code_mode_allows_bash ✅
- bash_command_timeout_works ✅
- All 43 workspace tests passing ✅
Dependencies Added:
- tokio with process, io-util, time, sync features
M4 milestone complete! ✅
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>