# Test Coverage Report

> Last updated: 2026-03-31
> Suite: **912 tests** across **53 test files** | All passing | Lint clean

## Current Coverage by Module

### Config (94 tests) — Well Covered

| Source Module | Test File | Tests | What's Tested | What's Missing |
|---|---|---:|---|---|
| `config/settings.py` | `test_settings.py` | 17 | `_deep_merge`, `_load_yaml`, `Settings`, `load_settings`, `ModelsConfig`, `PermissionsConfig` | Edge cases for nested override merging |
| `config/models.py` | `test_models.py` | 20 | `ModelRegistry`, `DEFAULT_CONTEXT_WINDOW`, `ContextWindowResolver`, provider registration | Custom provider fallback chains |
| `config/permissions.py` | `test_permissions.py` | 12 | `PermissionGuard`, `check_file_read/write`, `check_shell_execute`, `_is_protected_path`, `_is_blocked_command` | Glob-based path rules, compound command detection |
| `config/tool_permissions.py` | `test_tool_permissions.py` | 28 | `_parse_rule`, `_args_to_str`, `_extract_domain`, `_match_rule_args`, default levels, `is_denied`, `needs_confirmation`, settings loading, arg-specific rules, `save_rule`, `FUNC_TO_TOOL` | Wildcard rules, negative patterns |
| `config/api_keys.py` | `test_api_keys.py` | 9 | Priority resolution (direct > env > cmd), missing env, cmd failure, empty entries | Multi-provider key rotation |
| `config/defaults.py` | — | 0 | — | Default value constants (low priority — static data) |

### Auth (27 tests) — Well Covered

| Source Module | Test File | Tests | What's Tested | What's Missing |
|---|---|---:|---|---|
| `auth/credentials.py` | `test_auth.py` | 22 | `Credentials` model, `save/load/clear_credentials`, `is_token_expired`, `get_access_token`, `decode_jwt_claims`, `get_org_id/get_org_name`, path resolution, file permissions | — |
| `auth/client.py` | `test_auth_client.py` | 5 | `request_device_code`, correct URL construction, `poll_for_token` (immediate success, 202→200 polling, timeout) | Token refresh logic |

### Session (55 tests) — Good Coverage

| Source Module | Test File | Tests | What's Tested | What's Missing |
|---|---|---:|---|---|
| `session/core.py` | `test_session.py` | 11 | Construction with defaults, `resume_session_id`, `additional_dirs`, cloud connection detection, message handling (basic), hook blocking, error handling, compaction thresholds | Tool execution pipeline, multi-turn conversations, system prompt assembly |
| `session/ide_context.py` | `test_ide_context.py` | 25 | `IDEContext`, `OpenFile`, `parse_system_reminder`, `parse_message`, `update_from_diagnostics` | — |
| `session/runner.py` | `test_session_runner.py` | 3 | Runs message and prints response, fires session start/end hooks, passes project_dir and additional_dirs | Signal handling, graceful shutdown |
| `session/persistence.py` | `test_persistence.py` | 12 | `SessionPersistence` construction, `list_sessions` (empty/formatted/tuple/exception), `auto_name`, `rename`, `get_name` | Corrupted file handling |
| `session/commands.py` | `test_commands.py` | 10 | Dispatch (sync/async/unknown), all commands registered, `/help`, `/agents`, `/clear`, `/config`, `/sync-knowledge` (enabled/disabled) | — |
| `session/knowledge_ops.py` | `test_knowledge_ops.py` | 10 | `share_enabled` conditions, `add` (no knowledge/no content/success), `search` (empty/results), `status` (disabled/enabled) | — |
| `session/memory_ops.py` | `test_memory_ops.py` | 6 | `create_manager` (no db), `get_memories` (no db/formatted/exception), `optimize` (no manager/not enough) | — |
| `session/interactive.py` | — | 0 | — | Interactive REPL loop, input handling |

### Tools (87 tests) — Good Coverage

| Source Module | Test File | Tests | What's Tested | What's Missing |
|---|---|---:|---|---|
| `tools/edit.py` | `test_tools.py` | 23 | `EmberEditTools`, file editing, pattern matching, whitespace handling | Multi-edit operations, encoding edge cases |
| `tools/registry.py` | `test_tools.py` | (shared) | `ToolRegistry`, tool resolution, deduplication, factory methods | Dynamic tool addition at runtime |
| `tools/search.py` | `test_tools.py` | (shared) | `GlobTools`, file globbing, pattern matching | Symlinks, permission errors |
| `tools/notebook.py` | `test_notebook.py` | 17 | All 5 operations (read, read_cell, edit_cell, add_cell, remove_cell), error cases, metadata preservation, output clearing | Large notebooks, kernel metadata |
| `tools/codeindex.py` | `test_codeindex.py` | 9 | `_get_git_remote`, search, item, tree, error handling | `codeindex_similar`, `codeindex_references`, rate limiting |
| `tools/web.py` | `test_web_tools.py` | 6 | `fetch_url`, `fetch_json`, `_extract_text_from_html`, truncation | Redirect handling, timeout errors |
| `tools/orchestrate.py` | `test_orchestrate.py` | 5 | `spawn_agent` (success, unknown, depth limit), `spawn_team` (basic) | Timeout handling, team modes (route, broadcast, tasks) |
| `tools/schedule.py` | `test_schedule_tools.py` | 4 | `schedule_task`, `list_scheduled_tasks`, `cancel_scheduled_task` | Recurring task scheduling |

### Skills (22 tests) — Good Coverage

| Source Module | Test File | Tests | What's Tested | What's Missing |
|---|---|---:|---|---|
| `skills/parser.py` | `test_skills.py` | 19 | `SkillParser`, `SkillDefinition`, argument rendering, template variables | Malformed YAML frontmatter |
| `skills/loader.py` | `test_skills.py` | (shared) | `SkillPool`, discovery, loading from directories | Hot-reload, duplicate skill names |
| `skills/executor.py` | `test_skill_executor.py` | 3 | Inline execution, forked execution, argument passing | Error handling in forked agent, model override |

### Scheduler (39 tests) — Well Covered

| Source Module | Test File | Tests | What's Tested | What's Missing |
|---|---|---:|---|---|
| `scheduler/models.py` | `test_scheduler.py` | 29 | `ScheduledTask`, `TaskStatus`, model validation | — |
| `scheduler/parser.py` | `test_scheduler.py` | (shared) | `parse_time`, `parse_recurrence`, `next_occurrence_from_recurrence`, natural language | Timezone-aware parsing |
| `scheduler/store.py` | `test_scheduler.py` | (shared) | `TaskStore` CRUD, query by status/time | Concurrent access |
| `scheduler/runner.py` | `test_scheduler_runner.py` | 6 | Start/stop lifecycle, due task execution, concurrency semaphore, callbacks | Task timeout, failure recovery |

### Hooks (16 tests) — Good Coverage

| Source Module | Test File | Tests | What's Tested | What's Missing |
|---|---|---:|---|---|
| `hooks/events.py` | `test_hooks.py` | 16 | `HookEvent` enum, all event types | — |
| `hooks/executor.py` | `test_hooks.py` | (shared) | `HookExecutor`, hook matching, command/HTTP hooks, pre/post hooks | Timeout handling |
| `hooks/loader.py` | `test_hooks.py` | (shared) | Loading from settings, invalid config handling | File-based hook loading |
| `hooks/schemas.py` | `test_hooks.py` | (shared) | `HookDefinition`, `HookResult` validation | — |

### Knowledge (93 tests) — Comprehensive

| Source Module | Test File | Tests | What's Tested | What's Missing |
|---|---|---:|---|---|
| `knowledge/embedder.py` | `test_knowledge.py` | 59 | `EmberEmbedder`, sync/async embedding, error handling, batch processing | — |
| `knowledge/embedder_registry.py` | `test_knowledge.py` | (shared) | Registry for embedder types | — |
| `knowledge/manager.py` | `test_knowledge.py` | (shared) | `KnowledgeManager`, embedder creation, disabled knowledge mode | — |
| `knowledge/models.py` | `test_knowledge.py` | (shared) | All data models, results, filters | — |
| `knowledge/sync.py` | `test_knowledge_sync.py` | 34 | `KnowledgeSyncer`, bidirectional YAML/DB sync, entry creation, deletion | Conflict resolution, large file sets |
| `knowledge/vector_store.py` | `test_knowledge_sync.py` | (shared) | `VectorStoreAdapter`, ChromaDB integration | — |

### MCP (95 tests) — Well Covered

| Source Module | Test File | Tests | What's Tested | What's Missing |
|---|---|---:|---|---|
| `mcp/client.py` | `test_mcp_client.py` | 13 | List servers, connect (missing/unsupported/sse-no-url/stdio-success/cached/no-tools/import-error), disconnect_all, disconnect skips SSE | Reconnection, timeout handling |
| `mcp/server.py` | `test_mcp_server.py` | 4 | Create without MCP, create with mock, settings storage | Request/response handling |
| `mcp/config.py` | `test_mcp_config.py` | 10 | `MCPServerConfig` defaults/stdio/sse, `MCPConfigLoader` empty/project/.ember/override/invalid/missing-key/multiple | — |
| `mcp/transport.py` | `test_mcp_transport.py` | 5 | Stores command/args, defaults, stdin/stdout none, stop without start | — |
| `mcp/tools.py` | — | 0 | — | MCP tool registration and dispatch |
| `mcp/ide_detect.py` | — | 0 | — | General IDE detection utilities |

### Evals (34 tests) — Good Coverage

| Source Module | Test File | Tests | What's Tested | What's Missing |
|---|---|---:|---|---|
| `evals/loader.py` | `test_evals.py` | 8 | `load_eval_file` (valid, invalid, missing fields, defaults), `load_eval_suites` (discovery, empty dir) | — |
| `evals/assertions.py` | `test_evals.py` | 8 | `check_unexpected_tool_calls` (tools attr, messages fallback, no tools), `check_file_assertion` (all 5 types + unknown) | — |
| `evals/runner.py` | `test_evals.py` | 6 | `CaseResult` defaults, `SuiteResult` aggregation, `run_eval_case` (pass, error, unexpected tools, file assertions) | `run_eval_suite`, `run_evals`, ReliabilityEval/AccuracyEval integration |
| `evals/reporter.py` | `test_evals.py` | 3 | `format_results` (all pass, mixed, empty) | — |
| `/evals` command | `test_evals.py` | 3 | Dispatch, agent filter arg, registration | — |

### TUI (263 tests) — Good Coverage

| Source Module | Test File | Tests | What's Tested | What's Missing |
|---|---|---:|---|---|
| `tui/widgets/*` | `test_widgets.py` | 78 | MessageWidget, StreamingMessageWidget, SpinnerWidget, SessionPickerWidget, RunStatsWidget, TokenBadge, QueuePanel, MCPCallWidget, ToolCallLiveWidget, InputHistory, AgentTreeWidget, StatusBar | `_task_progress.py`, `_dialogs.py` |
| `tui/command_handler.py` | `test_tui_handlers.py` | 56 | `CommandHandler`, `CommandResult`, command routing, argument parsing | — |
| `tui/format_helpers.py` | `test_tui_handlers.py` | (shared) | `format_tool_args` and formatting utilities | — |
| `tui/input_handler.py` | `test_tui_handlers.py` | (shared) | `InputHandler`, `AutocompleteProvider`, history navigation | — |
| `tui/status_tracker.py` | `test_status_tracker.py` | 27 | Token accumulation, context tracking, delegation to StatusBar, reset, no-bar safety, IDE/cloud status | — |
| `tui/hitl_handler.py` | `test_hitl_handler.py` | 38 | Pure formatters (`_format_args_short/detail`, `_build_rule/pattern_rule`), permission routing (allow/deny/session approval), confirmation flow, user input routing | Dialog widget interaction |
| `tui/session_manager.py` | `test_session_manager.py` | 8 | `clear()` delegation, `switch_to()` state updates, session name display, status bar update, input focus | `show_picker()` widget mounting |
| `tui/app.py` | — | 0 | — | Deeply coupled to Textual runtime (not unit-testable) |
| `tui/conversation_view.py` | — | 0 | — | Thin widget wrapper, no business logic |
| `tui/run_controller.py` | — | 0 | — | Widget-bound event dispatch (queue already tested in handlers) |

### Utils (69 tests) — Well Covered

| Source Module | Test File | Tests | What's Tested | What's Missing |
|---|---|---:|---|---|
| `utils/context.py` | `test_context.py` | 19 | `load_project_rules`, `load_subdirectory_rules`, `load_project_context`, rule merging | — |
| `utils/tips.py` | `test_tips_and_updates.py` | 28 | `get_tip`, `random_tip`, contextual/general tip pools | — |
| `utils/update_checker.py` | `test_tips_and_updates.py` | (shared) | `_is_newer`, `_parse_version`, cache read/write, `check_for_update` | — |
| `utils/audit.py` | `test_audit.py` | 5 | `AuditLogger.log`, `log_blocked`, file creation, multi-entry append, parent dir creation | Log rotation |
| `utils/response.py` | `test_response.py` | 4 | `extract_response_text` for various input types | Edge cases (nested content) |
| `utils/display.py` | `test_display.py` | 13 | `print_error`, `print_warning`, `print_info`, `print_response`, `print_tool_call`, `print_run_stats`, `print_welcome`, `print_markdown` | — |

### Top-Level Modules (50 tests)

| Source Module | Test File | Tests | What's Tested | What's Missing |
|---|---|---:|---|---|
| `pool.py` | `test_pool.py` | 16 | `parse_agent_file`, `AgentPool`, agent loading, discovery | Dynamic agent registration |
| `workspace.py` | `test_workspace.py` | 6 | `WorkspaceManager`, multi-dir, dedup, context instructions | — |
| `worktree.py` | `test_worktree.py` | 9 | `WorktreeManager`, create, has_changes, cleanup, stale worktrees | Branch conflict scenarios |
| `init.py` | `test_init.py` | 15 | `initialize_project`, built-in hooks, agent/skill/hook provisioning | Upgrade/migration scenarios |
| `cli.py` | `test_cli.py` | 19 | CLI flags (version, model, verbose, quiet, read-only, auto-approve, strict, no-memory, no-web), message mode, pipe mode (stdin, no-input, combined), no-tui, default TUI, worktree cleanup | `--add-dir` multi-directory |
| `prompts/` | `test_prompts.py` | 4 | `load_prompt`, missing prompt error, directory existence, result stripping | Template rendering |
| `queue_hook.py` | `test_queue_hook.py` | 11 | Func passthrough, args forwarding, no func, message injection, previous injection clearing, callbacks, empty queue, reset, factory | — |
| `memory/manager.py` | `test_memory_manager.py` | 8 | SQLite creation, unknown backend, sqlite/postgres failure, parent dir creation, `setup_db`/`setup_memory` delegation | Schema migration |

---

## Remaining Gaps

### Would Improve Coverage (lower priority)

| Module | What's Missing |
|---|---|
| `session/interactive.py` | Interactive REPL loop, input handling (hard to unit test) |
| `session/core.py` | Full message → team → response flow, system prompt assembly, tool injection |
| `tui/app.py` | App lifecycle (consider Textual's `async with app.run_test()`) |
| `tui/conversation_view.py` | Message rendering |
| `tui/hitl_handler.py` | Permission prompt display and response |
| `tui/run_controller.py` | Run start/stop/cancel |
| `tui/session_manager.py` | Session creation, resume in TUI |
| `mcp/tools.py` | MCP tool registration and dispatch |

---

## Coverage Summary

```
Category            Tests   Modules Tested / Total   Confidence
─────────────────── ─────── ────────────────────────  ──────────
Config               94     5 / 6                     High
Auth                 27     2 / 2                     High
Session              55     7 / 8                     Good
Tools                87     8 / 8                     High
Skills               22     3 / 3                     Good
Scheduler            39     4 / 4                     High
Hooks                16     4 / 4                     High
Evals                34     5 / 5                     Good
Knowledge            93     6 / 6                     High
MCP                  95     8 / 10                    Good
TUI                 263     7 / 11+                   Good
Utils                69     6 / 6                     High
Top-level            50     7 / 7                     High
─────────────────── ─────── ────────────────────────  ──────────
TOTAL               912     ~72 / ~80 non-init        High
```

**Bottom line:** All critical-path modules now have test coverage. The remaining gaps are primarily TUI app-layer modules (which are inherently harder to unit test) and deeper integration-level paths in the session core. The suite is production-ready for the non-TUI backend.
