This commit completes all remaining Sprint 1 tasks from the project analysis:
**MCP RPC Timeout Protection**
- Add configurable `rpc_timeout_secs` field to McpServerConfig
- Implement operation-specific timeouts (10s-120s based on method type)
- Wrap all MCP RPC calls with tokio::time::timeout to prevent indefinite hangs
- Add comprehensive test suite (mcp_timeout.rs) with 5 test cases
- Modified files: config.rs, remote_client.rs, presets.rs, failover.rs, factory.rs, chat_app.rs, mcp.rs
**Async Migration Completion**
- Remove all remaining tokio::task::block_in_place calls
- Replace with try_lock() spin loop pattern for uncontended config access
- Maintains sync API for UI rendering while completing async migration
- Modified files: session.rs (config/config_mut), chat_app.rs (controller_lock)
**Dependency Updates**
- Update tokio 1.47.1 → 1.48.0 for latest performance improvements
- Update reqwest 0.12.23 → 0.12.24 for security patches
- Update 60+ transitive dependencies via cargo update
- Run cargo audit: identified 3 CVEs for Sprint 2 (sqlx, ring, rsa)
**Code Quality**
- Fix clippy deprecation warnings (generic-array 0.x usage in encryption/storage)
- Add temporary #![allow(deprecated)] with TODO comments for future generic-array 1.x upgrade
- All tests passing (except 1 pre-existing failure unrelated to these changes)
Sprint 1 is now complete. Next up: Sprint 2 security fixes and test coverage improvements.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Acceptance Criteria:\n- Declarative keymap sequences replace pending_key/pending_focus_chord logic.\n- :keymap show streams the active binding table and bindings export reflects new schema.\n- Vim/Emacs default keymaps resolve multi-step chords via the registry.
Test Notes:\n- cargo test -p owlen-tui
Acceptance Criteria:\n- Users can toggle high-contrast and reduced-chrome modes via :accessibility commands.\n- Accessibility flags persist in config and update UI header legends without restart.\n- Reduced chrome removes glass shadows while preserving layout readability.
Test Notes:\n- cargo test -p owlen-tui
Acceptance-Criteria:\n- snapshot coverage for idle chat and tool-call streaming states protects header, toast, and transcript rendering.\n- Tests use deterministic settings so reruns pass without manual snapshot acceptance.
Test-Notes:\n- INSTA_UPDATE=always cargo test -p owlen-tui --test chat_snapshots\n- cargo test
Acceptance-Criteria:\n- spec-compliant names are shared via WEB_SEARCH_TOOL_NAME and ModeConfig checks canonical identifiers.\n- workspace depends on once_cell so regex helpers build without local target hacks.
Test-Notes:\n- cargo test
Acceptance-Criteria:\n- cloud WireMock tests pass when providers.ollama_cloud.base_url targets a local endpoint.\n- 429 responses surface ProviderErrorKind::RateLimited and 401 payloads report API key guidance.
Test-Notes:\n- cargo test -p owlen-core --test ollama_wiremock cloud_rate_limit_returns_error_without_usage\n- cargo test -p owlen-core --test ollama_wiremock cloud_tool_call_flows_through_web_search\n- cargo test
- Introduce reference MCP presets with installation/audit helpers and remove legacy connector lists.
- Add CLI `owlen tools` commands to install presets or audit configuration, with optional pruning.
- Extend the TUI :tools command to support listing presets, installing them, and auditing current configuration.
- Document the preset workflow and provide regression tests for preset application.
- Reject dotted tool identifiers during registration and remove alias-backed lookups.
- Drop web.search compatibility, normalize all code/tests around the canonical web_search name, and update consent/session logic.
- Harden CLI toggles to manage the spec-compliant identifier and ensure MCP configs shed non-compliant entries automatically.
Acceptance Criteria:
- Tool registry denies invalid identifiers by default and no alias codepaths remain.
Test Notes:
- cargo check -p owlen-core (tests unavailable in sandbox).
Acceptance Criteria:
- Workspace builds against ratatui 0.29, crossterm 0.28.1, and tui-textarea 0.7 with palette support enabled
- Chat header context and usage gauges render with refreshed tailwind gradients
- Header layout uses the Flex API to balance top-row metadata across window widths
Test Notes:
- cargo test -p owlen-tui
Acceptance Criteria:\n- Local provider chat succeeds and records usage\n- Cloud tool-call scenario exercises web.search and usage tracking\n- Unauthorized and rate-limited cloud responses surface errors without recording usage\n\nTest Notes:\n- CARGO_NET_OFFLINE=true cargo test -p owlen-core --tests ollama_wiremock
AC:\n- Providers emit ProviderFailure with structured kind/detail for auth, rate-limit, timeout, and unavailable cases.\n- TUI maps ProviderFailure kinds to consistent toasts and fallbacks (no 429 string matching).\n- Cloud health checks detect unauthorized failures without relying on string parsing.\n\nTests:\n- cargo test -p owlen-core (fails: httpmock cannot bind 127.0.0.1 inside sandbox).\n- cargo test -p owlen-providers\n- cargo test -p owlen-tui
AC:
- :web on/off updates tool exposure immediately and persists the toggle.
- owlen providers web --enable/--disable reflects the same setting and reports current status.
- Help/docs cover the new toggle paths and troubleshooting guidance.
Tests:
- cargo test -p owlen-cli
- cargo test -p owlen-core toggling_web_search_updates_config_and_registry
AC:\n- Theme, help, command, and model modals share the glass chrome.\n- Theme selector shows a live preview for the highlighted palette.\n- Updated docs and screenshots explain the refreshed cockpit.\n\nTests:\n- cargo test -p owlen-tui
Acceptance Criteria:\n- web.search proxies Ollama Cloud's /api/web_search via the configured provider endpoint\n- Tool is only registered when remote search is enabled and the cloud provider is active\n- Consent prompts, docs, and MCP tooling no longer reference DuckDuckGo or expose web_search_detailed
Test Notes:\n- cargo check
Acceptance Criteria:\n- header shows hourly/weekly usage with colored thresholds\n- :limits command prints persisted usage data and quotas\n- token usage survives restarts and emits 80%/95% toasts
Test Notes:\n- cargo test -p owlen-core usage
Acceptance Criteria:\n- tool descriptors from MCP are forwarded to Ollama chat requests\n- models advertise tool support when metadata or heuristics imply function calling\n- chat responses include provider metadata with final token metrics
Test Notes:\n- cargo test -p owlen-core providers::ollama::tests::prepare_chat_request_serializes_tool_descriptors\n- cargo test -p owlen-core providers::ollama::tests::convert_model_marks_tool_capability\n- cargo test -p owlen-core providers::ollama::tests::convert_response_attaches_provider_metadata
Acceptance Criteria:\n- streaming chunks retain leading whitespace and indentation\n- end-of-stream metadata is still propagated\n- malformed frames emit defensive logging without crashing
Test Notes:\n- cargo test -p owlen-providers
- Introduce `StreamingMessageState` to track full text, last tool calls, and completion.
- Add `StreamDiff`, `TextDelta`, and `TextDeltaKind` for describing incremental changes.
- SessionController now maintains a `stream_states` map keyed by response IDs.
- `apply_stream_chunk` uses the new state to emit append/replace text deltas and tool‑call updates, handling final chunks and cleanup.
- `Conversation` gains `set_stream_content` to replace streaming content and manage metadata.
- Ensure stream state is cleared on cancel, conversation reset, and controller clear.
- Introduce built‑in Emacs keymap (`keymap_emacs.toml`) alongside existing Vim layout.
- Add `ui.keymap_profile` and `ui.keymap_path` configuration options; persist profile changes via `:keymap` command.
- Expose `KeymapProfile` enum (Vim, Emacs, Custom) and integrate it throughout state, UI rendering, and help overlay.
- Extend command registry with `keymap.set_vim` and `keymap.set_emacs` to allow profile switching.
- Update help overlay, command specs, and README to reflect new keybindings and profile commands.
- Adjust `Keymap::load` to honor preferred profile, custom paths, and fallback logic.
- Extend event handling to include `MouseEvent` and expose it via a new `Event::Mouse` variant.
- Introduce `LayoutSnapshot` to capture the geometry of UI panels each render cycle.
- Store the latest layout snapshot in `ChatApp` for mouse region lookup.
- Implement mouse click and scroll handling across panels (file tree, thinking, actions, code, model info, chat, input, etc.).
- Add utility functions for region detection, cursor placement from mouse position, and scrolling logic.
- Update UI rendering to populate the layout snapshot with panel rectangles.