# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. Tests use `#[cfg(test)] mod tests` blocks inline in production files (not a separate `tests/` dir). Tracing output goes to `~/.local/share/zesdex/zesdex.log`. Set `RUST_LOG=debug` for verbose logging. ## Architecture Overview Zesdex is an autonomous AI coding agent with a TUI — an OpenAI/Anthropic-compatible LLM client wrapped in a tool-use harness with 37 built-in tools. Detailed architecture documentation is in `docs/CODEMAPS/`: | File | Covers | |------|--------| | [`docs/CODEMAPS/architecture.md`](docs/CODEMAPS/architecture.md) | System layout, process modes, data flow, key files | | [`docs/CODEMAPS/backend.md`](docs/CODEMAPS/backend.md) | Provider, OAuth, IPC, workflow engine, MCP, review, bg bash | | [`docs/CODEMAPS/frontend.md`](docs/CODEMAPS/frontend.md) | TUI render pipeline, 16 overlays, toasts, input handling | | [`docs/CODEMAPS/data.md`](docs/CODEMAPS/data.md) | Persistence, SQLite msglog, memory files, settings/config | | [`docs/CODEMAPS/dependencies.md`](docs/CODEMAPS/dependencies.md) | 23 Rust crates, 5 external services | `docs/runs/` holds an auto-generated audit trail: one markdown file per hive-mind convergence (see below), written deterministically by `app::workflow::docs::write_hive_mind_convergence` — not hand-maintained like `docs/CODEMAPS/`. ### Key Patterns - **State mutation** — `AppStateRest` is mutable in-place from `actions/mod.rs` and `controller/input.rs`. No generic update function. - **No DI** — modules call `Settings::load()`, `AppConfig::load()`, `all_tools()` directly. - **Logging** — `tracing::warn!` to `~/.local/share/zesdex/zesdex.log` (not stderr, avoids TUI corruption). - **Error handling** — `anyhow::Result` and `anyhow::bail!` throughout. No custom error types. - **Static strings** — MCP tool descriptions use `Box::leak` + `OnceLock` cache. - **Tools** — `trait Tool { fn name() -> &str, fn run() -> Result }`, 28 impls, gated by `Harness`. - **Shell safety** — `tool/shell_filter/` blocks credential leaks and destructive git commands. ### Hive-Mind Orchestration (Machine Intelligence) - **A single Core Intelligence spawning anonymous processing nodes.** The Core Intelligence (main agent) compiles a cognitive cycle plan per task: an ordered list of cycles, each cycle a set of processing nodes that run in parallel. Each node's sole identity is its directive (what to do) and an access tier. Cycle count and nodes-per-cycle are entirely Core-Intelligence output. - **Access tiers** in `src/app/subagent/division.rs` (`tool_scope` module): tool access is granted per node via one of three tiers (`read` / `write` / `full`, see `tool_scope::tools_for`) picked by the Core Intelligence based on what each node's directive actually needs. - **Orchestrator** in `src/app/workflow/hive_mind.rs`: `run_hive_mind()` executes a `CognitiveCyclePlan { cycles: Vec> }` cycle-by-cycle. Node IDs are system-assigned coordinates (e.g. `"Node-0-1"`). - **Continuous collective state, not phase-boundary sync**: `engine::execute_primitive`'s `ScopedAgent` arm merges each node's complete output into the shared collective-state channel the instant that node finishes — not after its whole parallel cohort completes — so sibling/later nodes see it in real time. - **Consensus synthesis, not a per-node summary**: after all cycles complete, `synthesize_consensus()` spawns one final read-only node whose sole directive is to reconcile the entire collective state into a single consensus assessment — a real reasoning pass, not string concatenation, since node outputs can overlap or conflict. - **Auto-trigger** in `run_agent_turn()` (`actions/mod.rs`): `is_complex_request()` heuristics decide only whether to ask the Core Intelligence to compile a plan at all — the plan's shape is fully dynamic. - **`hive_mind` tool** (`src/tool/workflow.rs`) is the manual entry point: the calling LLM supplies its own `cycles` array of `{directive, access}` directly. - **Guaranteed documentation**: after every convergence, `src/app/workflow/docs.rs::write_hive_mind_convergence()` deterministically (not an LLM step, not skippable) writes every node's full output plus the final consensus to `docs/runs/-.md`. - **Live node progress** in TUI panel (`view/workflow.rs`): shows node designation + current tool via `AgentStatus::progress`. - **Auto inline review** after each edit: `src/app/subagent/auto.rs` — `spawn_quick_review()` injects verdict back into LLM conversation. - **Background subagents** (test-gen, arch-review, security-review) fire asynchronously at turn end via `TurnEvent::SystemNote`, retrying once on failure and escalating to a blocking (`ESCALATED:`-prefixed, `ToastKind::Error`) notice if the retry also fails. Commit convention (Conventional Commits, Bahasa Indonesia): see the `commit-convention` skill. ## Code Documentation Every function, struct, enum, trait, module, and significant code block must have a doc comment (`///` or `//!`) that explains: - **What** the function/module does (purpose, not how) - **Flow** — a brief ASCII or prose description of the code flow / data flow above each non-trivial function - **Why** — non-obvious decisions, edge cases, invariants - **Return** — what the caller gets back, especially for `Result` types Examples: ```rust /// Parse an SSE data chunk into one or more StreamEvents. /// /// Flow: buffer → split on '\n' → flush on blank line → JSON parse → match event type /// → return Token / ToolCallDelta / Usage / Done. /// /// Edge case: chunk may split mid-line; remaining bytes stay in buffer /// for the next feed() call. fn feed(&mut self, chunk: &str) -> Vec { ... } /// The single source-of-truth state struct for the entire application. /// /// Mutated in-place from two locations: actions/mod.rs (apply_action) /// and controller/input.rs (key event handlers). Read-only from /// every other module. struct AppStateRest { ... } ``` Rules: - Every `pub fn` needs a doc comment - Every `pub struct` / `pub enum` / `pub trait` needs a doc comment - Non-trivial private functions (≥10 lines) need a doc comment - Write the comment above the code it documents (not inline in the body) - Update comments when code behavior changes — stale docs are worse than no docs - NEVER use compiler/linter bypass annotations or attributes (such as `#[allow(clippy::too_many_lines, clippy::too_many_arguments, clippy::ref_option)]`, `#[allow(dead_code)]`, etc.) to silence warnings or skip linter checks. Always fix the underlying code issues instead.