Workspace Layout

rho-coding-agent/
├── Cargo.toml              # Workspace root — version, edition, lints
├── CHANGELOG.md             # Generated via git-cliff
├── cliff.toml               # git-cliff configuration
├── AGENTS.md                # Project instructions for AI assistants
├── docs/                    # This book (mdBook)
│   └── rpc-schema/
│       └── openrpc.json    # OpenRPC 1.3.1 schema (machine-readable API spec)
├── rho/                     # Binary entry point (headless JSON-RPC 2.0)
│   └── src/
│       ├── main.rs           # Thin: parse CLI, build App, run
│       ├── lib.rs            # Module declarations
│       ├── cli.rs            # `Cli` — CLI flags with clap
│       ├── app.rs            # `App` — runtime state, build/run orchestration, extension loading
│       ├── model.rs          # Model resolution (config-as-truth, provider-first)
│       ├── ext_observer.rs   # `CompositeObserver` — fans out to RPC observer + extension observers
│       ├── rpc.rs            # JSON-RPC 2.0: `run_rpc`, `run_rpc_on`, observer, approval gate
│       ├── rpc_wire.rs        # Typed wire-format structs (params, results, notifications)
│       ├── transport.rs        # `Transport` trait, `StdioTransport` (newline-delimited JSON)
│       └── presenter/
│           └── rpc.rs        # `RpcPresenter` — diagnostic output to stderr
├── rho-ai/                 # Unified LLM provider abstraction
│   └── src/
│       ├── lib.rs           # Re-exports: `LlmService`, `EventStream`, unified types
│       ├── service.rs       # `LlmService` trait
│       ├── openai.rs        # `OpenAiService` — Chat Completions HTTP + SSE
│       ├── responses.rs     # `ResponsesService` — OpenAI Responses HTTP + SSE
│       ├── sse.rs           # Server-sent event parser
│       ├── retry.rs         # Exponential backoff retry logic
│       ├── catalog.rs       # `Catalog`, `Model`, `ModelCost` — model registry + pricing
│       ├── catalog_generated.rs # Generated model list (`cargo xtask generate-models`)
│       ├── types.rs         # `LlmMessage`, `LlmRequest`, `StreamEvent`, `AccumulatedResponse`
│       └── error.rs         # `ProviderError`
│   └── model-overrides.json # Manual catalog overrides (thinking flags, compatibility)
├── rho-ext/                # TypeScript extension runtime (V8/deno-core)
│   └── src/
│       ├── lib.rs          # Re-exports: `ExtensionLoader`, `DenoTool`, `DenoObserver`, etc.
│       ├── runtime.rs      # `ExtensionRuntime` — V8 isolate on dedicated OS thread
│       ├── async_dispatcher.rs # Async bridge between V8 isolate and tokio
│       ├── loader.rs       # `ExtensionLoader` — discovery, filtering, spawning, hot reload
│       ├── deno_tool.rs    # `DenoTool` — `Tool` trait wrapper
│       ├── deno_observer.rs# `DenoObserver` — `AgentObserver` wrapper
│       ├── manifest.rs     # `LoadedExtension` — manifest parsing and validation
│       ├── discover.rs     # Extension discovery (single-file and multi-file)
│       ├── transpile.rs    # TS → JS transpilation
│       ├── module_loader.rs# `RhoModuleLoader` — ESM module resolution
│       ├── host.rs         # `rho.*` host ops (log, readFile, writeFile, runCommand, getModel, getCwd)
│       ├── ops.rs          # Helper macros for host op boilerplate
│       ├── error.rs        # `ExtensionError`
│       ├── host_shim.js    # ESM shim for extension module loading
│       └── std_shim.js    # Standard library shim for extensions
│   └── types/
│       └── rho.d.ts        # TypeScript type definitions for extension authors
├── rho-core/                # Agent kernel
│   └── src/
│       ├── lib.rs           # Module declarations, convenience re-exports
│       ├── agent.rs         # Agent loop state machine, `run_loop`, `AgentResult`, `CollectingObserver`, `LoopFinishReason`, phase tracking, auto-compact
│       ├── approval.rs      # `ApprovalPolicy`, `ApprovalGate` traits
│       ├── client.rs        # `RhoAiClient`, `resolve_api_key`, `is_local_endpoint`, `ModelInfo`, `ModelList`
│       ├── client/          # Module directory
│       │   └── error.rs      # `ClientError`
│       ├── config.rs        # `RhoConfig`, `ConfigLoader`, two-tier TOML loading
│       ├── context.rs       # `ContextManager`, `SlidingWindowContextManager`, `TokenBudget`
│       ├── context_files.rs # Project context file scanner, `TrustStore`, prompt composition
│       ├── conversation.rs  # `Conversation`, `AssistantResponse`
│       ├── denylist.rs      # `CommandDenylist` — shell command denylist
│       ├── diagnostic.rs    # Structured compiler diagnostic types
│       ├── error.rs         # `RhoError` and `Result`
│       ├── message.rs       # `ChatMessage`, `ContentBlock`, `ModelToolCall`
│       ├── model_match.rs   # Model name matching / fuzzy matching
│       ├── newtypes.rs      # `FilePath`, `ToolName`, `ToolCallId`, `EntryId`, `DiagnosticCode`
│       ├── prompts.rs       # `base_prompt()`, `compact_prompt()` (embedded from `prompts/`)
│       ├── redact.rs        # `Redactor` — secret pattern matching
│       ├── request.rs       # `ChatRequest`
│       ├── response.rs      # `ModelResponse`, `FinishReason`, `ModelUsage`
│       ├── sandbox.rs       # `SandboxRoot` — file sandbox validation
│       ├── schema.rs        # `ToolSchema` — wire-format tool definitions
│       ├── provider.rs      # `Provider` trait, `OpenAiCompatibleProvider`, `ProviderRegistry`
│       ├── session.rs       # `Session` struct, module declarations, re-exports
│       ├── session/
│       │   ├── accessors.rs    # Header, leaf, entry, flush, path, getters/setters
│       │   ├── append.rs       # Append ops, close, extension typed methods, append_entry core
│       │   ├── builder.rs      # `new`, `in_memory`, `with_*` builder methods
│       │   ├── compaction.rs   # `CompactionStrategy`, `MechanicalCompactionStrategy`, `LlmCompactionStrategy`
│       │   ├── context.rs      # `path_messages`, `send_current`, `compact_older_than`, `context_stats`, `prepare_context`
│       │   ├── context_stats.rs # `ContextStats`, `RoleTokenDistribution`, `ResolutionTokenDistribution`, `PhaseTokenDistribution`
│       │   ├── entry.rs        # `Entry`, `EntryPayload`, `EntryResolution`, `CompactionPhase`
│       │   ├── error.rs        # `SessionError`
│       │   ├── estimator.rs    # `TokenEstimator`, `HeuristicEstimator`
│       │   ├── eviction.rs     # Selective downgrade planner (`plan_downgrades`)
│       │   ├── extensions.rs   # `ExtensionEntry`, `ExtensionMessageEntry` traits
│       │   ├── header.rs       # `SessionHeader`
│       │   ├── outliner.rs     # Tool-specific structural summary formatters
│       │   ├── persist.rs      # JSONL persistence, `SessionMetadata`
│       │   ├── phase.rs        # `SessionPhase` enum, `classify_tool_phase()`, `transition_phase()`
│       │   ├── tree.rs         # `path_to_root`, `branch_to`, `branch_with_summary`
│       │   └── truncation.rs   # Bounded truncation, char boundary, footer
│       ├── shell.rs         # `ShellExecutor` trait, `ShellOutput`
│       ├── stream.rs        # `StreamChunk` — unified streaming event type
│       └── tool.rs          # `Tool` trait, `ToolRegistry`, `ToolRisk`, `ToolOutcome`
├── rho-memory/             # Persistent knowledge base (SQLite/FTS5)
│   ├── src/
│   │   ├── lib.rs           # Re-exports: `Memory`, `Document`, `SearchResult`
│   │   ├── brain.rs         # `Memory` — public knowledge-base API
│   │   ├── db.rs            # `Database` — raw SQLite operations
│   │   ├── models.rs        # `Document`, `SearchResult`, `CreateRequest`, `Stats`
│   │   └── error.rs         # Knowledge-base errors
│   └── migrations/
│       └── 001_initial.sql  # Schema: documents, FTS5, triggers
├── rho-highlight/           # Tree-sitter syntax analysis
│   └── src/
│       ├── lib.rs           # Re-exports
│       ├── lang.rs          # `Language` enum
│       ├── parse.rs         # Tree-sitter parsing
│       ├── highlight.rs     # Token classification and highlighting
│       ├── query.rs         # `node_at()` — AST node lookup by position
│       └── error.rs         # `HighlightError`
├── rho-tools/               # Built-in tool implementations
│   └── src/
│       ├── lib.rs           # `register_all()`
│       ├── files.rs         # Re-exports file tools from `file_ops` + `edit`
│       ├── file_ops.rs      # `ReadFile`, `WriteFile`, `BatchRead`, `ListDir`
│       ├── edit.rs          # `EditFile` — hashline-anchored editing
│       ├── hashline.rs      # Hashline content-addressed editing
│       ├── shell.rs         # `RunCommand`, `PowerShellExecutor`, `CommandDenylist`
│       ├── crates_io.rs     # `CratesIoLookup`
│       ├── session_summary.rs # `SessionSummary` — compressed session history tool
│       ├── memory.rs        # `MemoryTool` — knowledge base (via `rho-memory`)
│       ├── error.rs         # Tool error types
│       └── rust/            # Rust tooling (module root: `rust.rs`)
│           ├── tools.rs     # `CargoCheck`, `CargoClippy`, `CargoTest`, `CargoFix`, `RustcExplain`
│           ├── rustdoc.rs   # `RustdocTool` — local rustdoc HTML parsing
│           ├── parse.rs     # NDJSON output parsing
│           ├── convert.rs   # Diagnostic conversion
│           ├── format.rs    # Diagnostic formatting
│           └── types.rs     # Shared Rust tool types
├── rho-test-helpers/        # Shared test infrastructure (dev-only)
│   └── src/lib.rs           # `MockChatClient`, `TestProvider`, response builders, helpers
└── xtask/                   # Dev task runner
    └── src/
        ├── main.rs          # CLI dispatch
        └── tasks.rs         # `ci`, `test`, `build`, `release`, `changelog`, `fmt`, `fmt-fix`, `lint`, `run`, `clean`, `status`, `schema`, `generate-models` tasks