Files
everything-claude-code/research/ecc2-codebase-analysis.md
2026-03-28 20:15:46 -04:00

10 KiB
Raw Blame History

ECC2 Codebase Research Report

Date: 2026-03-26 Subject: ecc-tui v0.1.0 — Agentic IDE Control Plane Total Lines: 4,417 across 15 .rs files

1. Architecture Overview

ECC2 is a Rust TUI application that orchestrates AI coding agent sessions. It uses:

  • ratatui 0.29 + crossterm 0.28 for terminal UI
  • rusqlite 0.32 (bundled) for local state persistence
  • tokio 1 (full) for async runtime
  • clap 4 (derive) for CLI

Module Breakdown

Module Lines Purpose
session/ 1,974 Session lifecycle, persistence, runtime, output
tui/ 1,613 Dashboard, app loop, custom widgets
observability/ 409 Tool call risk scoring and logging
config/ 144 Configuration (TOML file)
main.rs 142 CLI entry point
worktree/ 99 Git worktree management
comms/ 36 Inter-agent messaging (send only)

Key Architectural Patterns

  • DbWriter thread in session/runtime.rs — dedicated OS thread for SQLite writes from async context via mpsc::unbounded_channel with oneshot acknowledgements. Clean solution to the "SQLite from async" problem.
  • Session state machine with enforced transitions: Pending → {Running, Failed, Stopped}, Running → {Idle, Completed, Failed, Stopped}, etc.
  • Ring buffer for session output — OUTPUT_BUFFER_LIMIT = 1000 lines per session with automatic eviction.
  • Risk scoring on tool calls — 4-axis analysis (base tool risk, file sensitivity, blast radius, irreversibility) producing composite 0.01.0 scores with suggested actions (Allow/Review/RequireConfirmation/Block).

2. Code Quality Metrics

Metric Value
Total lines 4,417
Test functions 29
unwrap() calls 3
unsafe blocks 0
TODO/FIXME comments 0
Max file size 1,273 lines (dashboard.rs)

Assessment: The codebase is clean. Only 3 unwrap() calls (2 in tests, 1 in config default()), zero unsafe, and all modules use proper anyhow::Result error propagation. The dashboard.rs file at 1,273 lines exceeds the repo's 800-line max-file guideline, but it is still manageable at the current scope.

3. Identified Gaps

3.1 Comms Module — Send Without Receive

comms/mod.rs (36 lines) has send() but no receive(), poll(), inbox(), or subscribe(). The messages table exists in SQLite, but nothing reads from it. The inter-agent messaging story is half-built.

Impact: Agents cannot coordinate. The TaskHandoff, Query, Response, and Conflict message types are defined but unusable.

3.2 New Session Dialog — Stub

dashboard.rs:495new_session() logs "New session dialog requested" but does nothing. Users must use the CLI (ecc start --task "...") to create sessions; the TUI dashboard cannot.

3.3 Single Agent Support

session/manager.rsagent_program() only supports "claude". The CLI accepts --agent but anything other than "claude" fails. No codex, opencode, or custom agent support.

3.4 Config — File-Only

Config::load() reads ~/.claude/ecc2.toml only. The implementation lacks environment variable overrides (e.g., ECC_DB_PATH, ECC_WORKTREE_ROOT) and CLI flags for configuration.

3.5 Legacy Dependency Candidate: git2

git2 = "0.20" is still declared in Cargo.toml, but the worktree module shells out to the git CLI instead. That makes git2 a strong removal candidate rather than an already-completed cleanup.

3.6 No Metrics Aggregation

SessionMetrics tracks tokens, cost, duration, tool_calls, files_changed per session. But there's no aggregate view: total cost across sessions, average duration, top tools by usage, etc. The Metrics pane in the dashboard shows per-session detail only.

3.7 Daemon — No Health Reporting

session/daemon.rs runs an infinite loop checking session timeouts. No health endpoint, no log rotation, no PID file, no signal handling for graceful shutdown. Ctrl+C during daemon mode kills the process uncleanly.

4. Test Coverage Analysis

34 test functions across 10 source modules:

Module Tests Coverage Focus
main.rs 1 CLI parsing
config/mod.rs 5 Defaults, deserialization, legacy fallback
observability/mod.rs 5 Risk scoring, persistence, pagination
session/daemon.rs 2 Crash recovery / liveness handling
session/manager.rs 4 Session lifecycle, resume, stop, latest status
session/output.rs 2 Ring buffer, broadcast
session/runtime.rs 1 Output capture persistence/events
session/store.rs 3 Buffer window, migration, state transitions
tui/dashboard.rs 8 Rendering, selection, pane navigation, scrolling
tui/widgets.rs 3 Token meter rendering and thresholds

Direct coverage gaps:

  • comms/mod.rs — 0 tests
  • worktree/mod.rs — 0 tests

The core I/O-heavy paths are no longer completely untested: manager.rs, runtime.rs, and daemon.rs each have targeted tests. The remaining gap is breadth rather than total absence, especially around comms/, worktree/, and more adversarial process/worktree failure cases.

5. Security Observations

  • No secrets in code. Config reads from TOML file, no hardcoded credentials.
  • Process spawning uses tokio::process::Command with explicit Stdio::piped() — no shell injection vectors.
  • Risk scoring is a strong feature — catches rm -rf, git push --force origin main, file access to .env/secrets.
  • No input sanitization on session task strings. The task string is passed directly to claude --print. If the task contains shell metacharacters, it could be exploited depending on how Command handles argument quoting. Currently safe (arguments are not shell-interpreted), but worth auditing.

6. Dependency Health

Crate Version Latest Notes
ratatui 0.29 0.30.0 Update available
crossterm 0.28 0.29.0 Update available
rusqlite 0.32 0.39.0 Update available
tokio 1 1.50.0 Update available
serde 1 1.0.228 Update available
clap 4 4.6.0 Update available
chrono 0.4 0.4.44 Update available
uuid 1 1.22.0 Update available

git2 is still present in Cargo.toml even though the worktree module shells out to the git CLI. Several other dependencies are outdated; either remove git2 or start using it before the next release.

7. Recommendations (Prioritized)

P0 — Quick Wins

  1. Add environment variable support to Config::load()ECC_DB_PATH, ECC_WORKTREE_ROOT, ECC_DEFAULT_AGENT. Standard practice for CLI tools.

P1 — Feature Completions

  1. Implement comms::receive() / comms::poll() — read unread messages from the messages table, optionally with a broadcast channel for real-time delivery. Wire it into the dashboard.
  2. Build the new-session dialog in the TUI — modal form with task input, agent selector, worktree toggle. Should call session::manager::create_session().
  3. Add aggregate metrics — total cost, average session duration, tool call frequency, cost per session. Show in the Metrics pane.

P2 — Robustness

  1. Expand integration coverage for manager.rs, runtime.rs, and daemon.rs — the repo now has baseline tests here, but it still needs failure-path coverage around process crashes, timeouts, and cleanup edge cases.
  2. Add first-party tests for worktree/mod.rs and comms/mod.rs — these are still uncovered and back important orchestration features.
  3. Add daemon health reporting — PID file, structured logging, graceful shutdown via signal handler.
  4. Task string security audit — The session task uses claude --print via tokio::process::Command. Verify arguments are never shell-interpreted. Checklist: confirm Command arg usage, threat-model metacharacter injection, input validation/escaping strategy, logging of raw inputs, and automated tests. Re-audit if invocation code changes.
  5. Break up dashboard.rs — extract SessionsPane, OutputPane, MetricsPane, LogPane into separate files under tui/panes/.

P3 — Extensibility

  1. Multi-agent support — make agent_program() pluggable. Add codex, opencode, custom agent types.
  2. Config validation — validate risk thresholds sum correctly, budget values are positive, paths exist.

8. Comparison with Ratatui 0.29 Best Practices

The codebase follows ratatui conventions well:

  • Uses TableState for stateful selection (correct pattern)
  • Custom Widget trait implementation for TokenMeter (idiomatic)
  • tick() method for periodic state sync (standard)
  • broadcast::channel for real-time output events (appropriate)

Minor deviations:

  • The Dashboard struct directly holds StateStore (SQLite connection). Ratatui best practice is to keep the state store behind an Arc<Mutex<>> to allow background updates. Currently the TUI owns the DB exclusively, which blocks adding a background metrics refresh task.
  • No Clear widget usage when rendering the help overlay — could cause rendering artifacts on some terminals.

9. Risk Assessment

Risk Likelihood Impact Mitigation
Dashboard file exceeds 1500 lines (projected) High Medium At 1,273 lines currently (Section 2); extract panes into modules before it grows further
SQLite lock contention Low High DbWriter pattern already handles this
No agent diversity Medium Medium Pluggable agent support
Task-string handling assumptions drift over time Medium Medium Keep Command argument handling shell-free, document the threat model, and add regression tests for metacharacter-heavy task input

Bottom line: ECC2 is a well-structured Rust project with clean error handling, good separation of concerns, and strong security features (risk scoring). The main gaps are incomplete features (comms, new-session dialog, single agent) rather than architectural problems. The codebase is ready for feature work on top of the solid foundation.