|
| 1 | +# CLAUDE.md — apexe Development & Code Quality Specification |
| 2 | + |
| 3 | +## Project Overview |
| 4 | + |
| 5 | +`apexe` is an Outside-In CLI-to-Agent Bridge — automatically wraps existing CLI tools into governed apcore modules, served via MCP/A2A. |
| 6 | + |
| 7 | +--- |
| 8 | + |
| 9 | +## Rust Code Quality |
| 10 | + |
| 11 | +### Readability |
| 12 | + |
| 13 | +- Use precise, full-word names; standard abbreviations only when idiomatic (`buf`, `cfg`, `ctx`). |
| 14 | +- Functions ≤50 lines, single responsibility, verb-named (`parse_request`, `build_schema`). |
| 15 | +- Avoid obscure tricks, overly chained iterators, unnecessary macros, or excessive generics. |
| 16 | +- Break complex logic into small, well-named helper functions. |
| 17 | + |
| 18 | +### Types (Mandatory) |
| 19 | + |
| 20 | +- Provide explicit types on all public items; do not rely on inference for public API surfaces. |
| 21 | +- Prefer `struct` over raw tuples for anything with more than 2 fields. |
| 22 | +- Use **`newtype`** wrappers (`struct TaskId(Uuid);`) to encode domain semantics. |
| 23 | +- Use **`enum`** for exhaustive variants; avoid stringly-typed logic. |
| 24 | +- Implement `serde::Serialize` / `serde::Deserialize` on all public data types. |
| 25 | + |
| 26 | +### Design |
| 27 | + |
| 28 | +- Favor **composition over inheritance**; use `trait` only for true behavioral interfaces. |
| 29 | +- Prefer plain functions + data structs; minimize trait object (`dyn Trait`) indirection. |
| 30 | +- No circular module dependencies. |
| 31 | +- Use **dependency injection** (constructor arguments) for config, logging, DB connections, etc. |
| 32 | +- Keep `pub` surface minimal — default to module-private, expose only what consumers need. |
| 33 | + |
| 34 | +### Errors & Resources |
| 35 | + |
| 36 | +- Define domain errors with **`thiserror`**; no bare `Box<dyn Error>` in library code. |
| 37 | +- Propagate errors with `?`; no `unwrap()` / `expect()` in library paths (tests excepted). |
| 38 | +- If `unwrap()` / `expect()` is truly unreachable, document with a `// SAFETY:` or `// INVARIANT:` comment. |
| 39 | +- Validate and sanitize all public inputs at crate boundaries. |
| 40 | +- Use RAII / `Drop` for resource cleanup; avoid manual teardown. |
| 41 | + |
| 42 | +### Async |
| 43 | + |
| 44 | +- Runtime: **Tokio** (`features = ["full"]`). |
| 45 | +- Never block the async executor — use `tokio::task::spawn_blocking` for CPU-heavy work. |
| 46 | +- Use `tokio::time::sleep` / `tokio::time::timeout`, not `std::thread::sleep`. |
| 47 | + |
| 48 | +### Logging |
| 49 | + |
| 50 | +- Use **`tracing`** — no `println!` / `eprintln!` in production code. |
| 51 | +- Level guide: |
| 52 | + - `tracing::error!` — unrecoverable failures |
| 53 | + - `tracing::warn!` — recoverable anomalies |
| 54 | + - `tracing::info!` — key business events |
| 55 | + - `tracing::debug!` — internal state for debugging |
| 56 | +- Always include structured fields: `tracing::info!(task_id = %id, "task started")`. |
| 57 | + |
| 58 | +### Testing |
| 59 | + |
| 60 | +- Run with: `cargo test --all-features` |
| 61 | +- **Unit tests**: in the same file under `#[cfg(test)] mod tests { ... }`. |
| 62 | +- **Integration tests**: in `tests/` directory. |
| 63 | +- Test names: `test_<unit>_<behavior>` (e.g., `test_parse_request_returns_error_on_empty_body`). |
| 64 | +- Never change production code without adding or updating corresponding tests. |
| 65 | +- Use **`tokio-test`** for async test helpers. |
| 66 | + |
| 67 | +### Serialization |
| 68 | + |
| 69 | +- JSON: `serde_json`. YAML: `serde_yaml`. |
| 70 | +- Avoid manual `Serialize` / `Deserialize` impls unless schema shape requires it. |
| 71 | + |
| 72 | +--- |
| 73 | + |
| 74 | +## Mandatory Quality Gates (CI — all must pass) |
| 75 | + |
| 76 | +Run `make check` before every commit (mirrors CI exactly): |
| 77 | + |
| 78 | +| Command | Purpose | |
| 79 | +|---------|---------| |
| 80 | +| `cargo fmt --all -- --check` | Formatting | |
| 81 | +| `cargo clippy --all-targets --all-features -- -D warnings` | Lint (warnings = errors) | |
| 82 | +| `apdev-rs check-chars src/` | Character validation | |
| 83 | +| `cargo build --all-features` | Full build | |
| 84 | +| `cargo test --all-features` | Tests | |
| 85 | + |
| 86 | +```bash |
| 87 | +make setup # One-time: installs apdev-rs + pre-commit hook |
| 88 | +make fmt # Auto-format |
| 89 | +make check # Run all gates (do this before git commit) |
| 90 | +``` |
| 91 | + |
| 92 | +### Clippy & Formatting Rules |
| 93 | + |
| 94 | +- `#[allow(...)]` to silence Clippy requires an inline comment explaining why. |
| 95 | +- `#[rustfmt::skip]` is forbidden without documented justification. |
| 96 | +- `Cargo.lock` **must be committed** (reproducible CI builds). |
| 97 | + |
| 98 | +### CI Security |
| 99 | + |
| 100 | +- All `uses:` actions must be pinned to a **full commit SHA** (not just a tag): |
| 101 | + ```yaml |
| 102 | + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 |
| 103 | + ``` |
| 104 | +- Workflow default permissions: `contents: read` (minimum privilege). |
| 105 | + |
| 106 | +--- |
| 107 | + |
| 108 | +## Dependency Management |
| 109 | + |
| 110 | +- Evaluate necessity before adding a new dependency. |
| 111 | +- Specify minimum compatible versions; avoid over-pinning patch versions. |
| 112 | +- Dev-only crates go in `[dev-dependencies]`, never `[dependencies]`. |
| 113 | + |
| 114 | +--- |
| 115 | + |
| 116 | +## General Guidelines |
| 117 | + |
| 118 | +- **English only** for all code, comments, doc comments, error messages, and commit messages. |
| 119 | +- Fully understand surrounding code before making changes. |
| 120 | +- Do not generate unnecessary documentation stubs, example files, or boilerplate unless explicitly requested. |
| 121 | +- No secrets hardcoded — use environment variables or configuration files. |
0 commit comments