commits
- Add resolve_nonexistent_path() to find nearest existing ancestor
- Expand ~ in input paths to match allowlist behavior
- Reject .. traversal in non-canonical path suffix
- Normalize . components in paths
- Add post-create TOCTOU check in WriteFileTool
- Add 6 new security tests for edge cases
- Fix collapsible_if clippy warning in planning/mod.rs
- Preserve structured LlmError through anyhow (use .into() not anyhow!())
- Fix HTTP-date parsing: use chrono RFC2822 parser, handle negative timestamps
- Add with_retry_config() builder for per-provider configuration
- Add 408/425 to retryable status codes
- Add test for REQUEST_TIMEOUT classification
- Add src/llm/error.rs with structured LlmError type and ErrorKind enum
- Add src/llm/retry.rs with RetryConfig, exponential backoff, and jitter
- Parse Retry-After header (delta-seconds and HTTP-date formats)
- Parse retry delays from message text (e.g., 'try again in 45.622s')
- Server hints override client backoff calculations
- Sanitized user_message for TUI, raw details for debug logs only
- Refactor anthropic.rs, openai.rs, ollama.rs to use shared retry module
- Update tests to use new error/retry APIs
Implement comprehensive scrolling for Planning and Execution chat screens:
- Manual scrolling via ↑↓/jk, PageUp/PageDown, Home/End
- Auto-scroll to bottom when new messages arrive
- Smart auto-scroll toggle (disabled when scrolling up, re-enabled near bottom)
- Visual scroll indicator showing position and [auto] status
- Proper text wrapping calculation for accurate scroll heights
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Critical fixes:
- Restore original panic hook after TUI exits
- Pass blocked reason through from signal_completion
- Emit message for unknown signal states
- Emit PlanningComplete when spec.json is written
- Prevent concurrent planning/execution spawns
Moderate fixes:
- Help overlay now blocks other keys (modal behavior)
- Clamp selection after load_specs() to prevent invalid state
- Display PlanningToolCall/Result in chat history
Minor fixes:
- Add spinner to execution view title when running
- NavDirection enum for Up/Down/Left/Right
- move_selection method on DashboardState
- Arrow keys and h/j/k/l navigate kanban columns and rows
- Shift+K/A for Kanban/Activity mode toggle
- Updated help overlay with new keybindings
- Dashboard Enter spawns RalphLoop execution
- SpecSummary now includes path for spec selection
- Animated spinner widget ticks in event loop
- Planning view uses animated spinner during thinking
- Help overlay with ? toggle shows keybindings
- PlanningAgent.run_with_sender sends AgentMessage via channel
- RalphLoop.run_with_sender with execute_task_with_sender
- App stores Config for agent creation
- Planning submit spawns agent as tokio task
- Add AgentMessage enum with planning and execution variants
- Refactor run/run_loop to async with tokio::select! multiplexing
- Add agent_tx, spec_dir to App struct
- Add handle_agent_message to route messages to view state
- Retry up to 3 times with exponential backoff
- Detect retryable errors (rate limit, timeout, connection, 5xx)
- Log retry attempts with delay information
- 2^n second delay between retries (2s, 4s, 8s)
- Add helper function and test for error detection
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
- Replace expect() with ok_or_else() and descriptive errors
- Replace panic!() with anyhow::bail()
- Use per-mode LLM config (planning_llm, ralph_llm)
- Provide helpful error messages for missing configs
- More robust error handling for unsupported providers
- Update new() methods to return Result
- Replace expect("Task should exist") with context()
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
- Extract system messages and place in separate 'system' field
- Filter system messages from messages array
- Anthropic API expects system as top-level field
- Add test for system message handling
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
- Add ModeConfig with separate llm config per mode
- Add planning and ralph mode-specific configs
- Fallback to default [llm] config if mode-specific not provided
- Add max_tokens to LlmConfig
- Update AnthropicClient to accept model and max_tokens
- Add tests for per-mode config and fallback
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
- Add path validation to ReadFileTool, WriteFileTool, ListFilesTool
- Check file size limits before reading
- Track runtime-allowed paths from permission prompts
- Update planning and ralph to use secured file tools
- Add tests for path validation and size checks
- Update all existing file tool tests to use security
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
- RunCommandTool now requires SecurityValidator and PermissionHandler
- Validate commands before execution
- Track runtime-allowed commands from permission prompts
- Update planning and ralph to use secured tools
- Fix main.rs to use library modules instead of redeclaring
- Add tests for allowlist enforcement
- Fix Send issues with RwLock guards across await points
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
- PermissionHandler trait for requesting user permission
- CliPermissionHandler with interactive CLI prompts
- Support for one-time, always-allow, and deny responses
- AutoApproveHandler for testing
- Add basic permission handler test
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
- SecurityValidator validates shell commands and file paths
- Allowlist/blocklist policy support with regex patterns
- Path canonicalization and validation against allowed dirs
- File size checking
- Add comprehensive tests for validation logic
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
- Add ShellPolicy enum (Allowlist, Blocklist, Unrestricted)
- Add SecurityConfig with shell, file, and path security
- Default to Allowlist policy with common safe commands
- Default 10MB file size limit
- Default allowed paths to current directory
- Add tests for default and custom security configs
- Update integration test to include security config
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
- regex for pattern matching in security validation
- shellexpand for tilde expansion in path handling
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
- Add fs::create_dir_all in Spec::save() before writing
- Prevents errors when saving to nested paths
- Add test for multi-level directory creation
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
- Use Arc<RwLock<HashMap>> for concurrent access
- Tools stored as Arc<dyn Tool> for sharing
- Registry is now Clone (just clones the Arc)
- Safe to use across multiple threads
- Add concurrency tests
- Remove mut from registry declarations (register no longer needs &mut)
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
- Use chrono::DateTime<Utc> for type-safe timestamp handling
- Automatic RFC3339 serialization via serde (with 'Z' suffix)
- Easier date arithmetic and comparison
- Update ralph loop to use Utc::now() directly
- Enable chrono serde feature for serialization support
- Update all tests to use DateTime types
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
- Collapse nested if statement in planning agent
- Use char literals instead of string literals in ralph loop
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
Design covers three phases:
- Phase 1: Code quality (clippy, timestamps, thread-safe registry)
- Phase 2: Security (shell hardening, path validation, permission system)
- Phase 3: Enhanced features (per-mode LLM config, system messages, error handling)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add resolve_nonexistent_path() to find nearest existing ancestor
- Expand ~ in input paths to match allowlist behavior
- Reject .. traversal in non-canonical path suffix
- Normalize . components in paths
- Add post-create TOCTOU check in WriteFileTool
- Add 6 new security tests for edge cases
- Fix collapsible_if clippy warning in planning/mod.rs
- Add src/llm/error.rs with structured LlmError type and ErrorKind enum
- Add src/llm/retry.rs with RetryConfig, exponential backoff, and jitter
- Parse Retry-After header (delta-seconds and HTTP-date formats)
- Parse retry delays from message text (e.g., 'try again in 45.622s')
- Server hints override client backoff calculations
- Sanitized user_message for TUI, raw details for debug logs only
- Refactor anthropic.rs, openai.rs, ollama.rs to use shared retry module
- Update tests to use new error/retry APIs
Implement comprehensive scrolling for Planning and Execution chat screens:
- Manual scrolling via ↑↓/jk, PageUp/PageDown, Home/End
- Auto-scroll to bottom when new messages arrive
- Smart auto-scroll toggle (disabled when scrolling up, re-enabled near bottom)
- Visual scroll indicator showing position and [auto] status
- Proper text wrapping calculation for accurate scroll heights
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Critical fixes:
- Restore original panic hook after TUI exits
- Pass blocked reason through from signal_completion
- Emit message for unknown signal states
- Emit PlanningComplete when spec.json is written
- Prevent concurrent planning/execution spawns
Moderate fixes:
- Help overlay now blocks other keys (modal behavior)
- Clamp selection after load_specs() to prevent invalid state
- Display PlanningToolCall/Result in chat history
Minor fixes:
- Add spinner to execution view title when running
- Retry up to 3 times with exponential backoff
- Detect retryable errors (rate limit, timeout, connection, 5xx)
- Log retry attempts with delay information
- 2^n second delay between retries (2s, 4s, 8s)
- Add helper function and test for error detection
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
- Replace expect() with ok_or_else() and descriptive errors
- Replace panic!() with anyhow::bail()
- Use per-mode LLM config (planning_llm, ralph_llm)
- Provide helpful error messages for missing configs
- More robust error handling for unsupported providers
- Update new() methods to return Result
- Replace expect("Task should exist") with context()
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
- Extract system messages and place in separate 'system' field
- Filter system messages from messages array
- Anthropic API expects system as top-level field
- Add test for system message handling
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
- Add ModeConfig with separate llm config per mode
- Add planning and ralph mode-specific configs
- Fallback to default [llm] config if mode-specific not provided
- Add max_tokens to LlmConfig
- Update AnthropicClient to accept model and max_tokens
- Add tests for per-mode config and fallback
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
- Add path validation to ReadFileTool, WriteFileTool, ListFilesTool
- Check file size limits before reading
- Track runtime-allowed paths from permission prompts
- Update planning and ralph to use secured file tools
- Add tests for path validation and size checks
- Update all existing file tool tests to use security
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
- RunCommandTool now requires SecurityValidator and PermissionHandler
- Validate commands before execution
- Track runtime-allowed commands from permission prompts
- Update planning and ralph to use secured tools
- Fix main.rs to use library modules instead of redeclaring
- Add tests for allowlist enforcement
- Fix Send issues with RwLock guards across await points
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
- PermissionHandler trait for requesting user permission
- CliPermissionHandler with interactive CLI prompts
- Support for one-time, always-allow, and deny responses
- AutoApproveHandler for testing
- Add basic permission handler test
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
- SecurityValidator validates shell commands and file paths
- Allowlist/blocklist policy support with regex patterns
- Path canonicalization and validation against allowed dirs
- File size checking
- Add comprehensive tests for validation logic
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
- Add ShellPolicy enum (Allowlist, Blocklist, Unrestricted)
- Add SecurityConfig with shell, file, and path security
- Default to Allowlist policy with common safe commands
- Default 10MB file size limit
- Default allowed paths to current directory
- Add tests for default and custom security configs
- Update integration test to include security config
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
- Add fs::create_dir_all in Spec::save() before writing
- Prevents errors when saving to nested paths
- Add test for multi-level directory creation
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
- Use Arc<RwLock<HashMap>> for concurrent access
- Tools stored as Arc<dyn Tool> for sharing
- Registry is now Clone (just clones the Arc)
- Safe to use across multiple threads
- Add concurrency tests
- Remove mut from registry declarations (register no longer needs &mut)
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
- Use chrono::DateTime<Utc> for type-safe timestamp handling
- Automatic RFC3339 serialization via serde (with 'Z' suffix)
- Easier date arithmetic and comparison
- Update ralph loop to use Utc::now() directly
- Enable chrono serde feature for serialization support
- Update all tests to use DateTime types
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
Design covers three phases:
- Phase 1: Code quality (clippy, timestamps, thread-safe registry)
- Phase 2: Security (shell hardening, path validation, permission system)
- Phase 3: Enhanced features (per-mode LLM config, system messages, error handling)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>