Files
zesdex/CLAUDE.md
T

87 lines
6.8 KiB
Markdown
Raw Normal View History

# 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<String> }`, 28 impls, gated by `Harness`.
- **Shell safety** — `tool/shell_filter/` blocks destructive git commands (`shell_filter::git::check_git_destructive`, called from `tool/shell.rs::Bash::run`). It also contains a `check_credential_read` detector for credential-file reads, but that one is intentionally NOT wired into `Bash::run` today — see the doc comment on `Bash::run` for why.
### 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<Vec<NodeDirective>> }` 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/<timestamp>-<slug>.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<StreamEvent> { ... }
/// 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.