|
| 1 | +# Rust Workspace Agent Instructions |
| 2 | + |
| 3 | +## Scope |
| 4 | + |
| 5 | +- This template targets Rust workspaces only. |
| 6 | +- `bin/` contains CLI binary crates. |
| 7 | +- `crates/` contains reusable library crates. |
| 8 | +- No frontend/web-framework-specific assumptions. |
| 9 | + |
| 10 | +## Cargo Workspace Rules (Critical) |
| 11 | + |
| 12 | +1. Never manually type dependency versions in `Cargo.toml`; use `cargo add`. |
| 13 | +2. Add workspace-level dependencies with: |
| 14 | + |
| 15 | + ```bash |
| 16 | + cargo add <crate> --workspace |
| 17 | + ``` |
| 18 | + |
| 19 | +3. Add sub-crate dependencies with: |
| 20 | + |
| 21 | + ```bash |
| 22 | + cargo add <crate> -p <crate-name> --workspace |
| 23 | + ``` |
| 24 | + |
| 25 | +4. Root `[workspace.dependencies]` should use numeric versions only. |
| 26 | +5. Root `[workspace.dependencies]` should not carry features by default. |
| 27 | +6. Sub-crates must use `workspace = true` for `version`, `edition`, and shared dependencies. |
| 28 | + |
| 29 | +## Preferred Dependencies and Versions |
| 30 | + |
| 31 | +When introducing new dependencies, prefer these versions unless compatibility requires an upgrade: |
| 32 | + |
| 33 | +- `clap = "4.5.60"` |
| 34 | +- `config = "0.15.19"` |
| 35 | +- `eyre = "0.6.12"` |
| 36 | +- `serde = "1.0.228"` |
| 37 | +- `thiserror = "2.0.18"` |
| 38 | +- `tokio = "1.49.0"` |
| 39 | +- `tracing = "0.1.44"` |
| 40 | +- `tracing-subscriber = "0.3.22"` |
| 41 | +- `tracing-opentelemetry = "0.32.1"` |
| 42 | +- `opentelemetry = "0.31.0"` |
| 43 | +- `opentelemetry-otlp = "0.31.0"` |
| 44 | +- `sqlx = "=0.9.0-alpha.1"` |
| 45 | +- `utoipa = "5.4.0"` |
| 46 | +- `utoipa-swagger-ui = "9.0.2"` |
| 47 | +- `arc-swap = "1.8.2"` |
| 48 | +- `hpx = "2.3.1"` |
| 49 | +- `scc = "3.6.5"` |
| 50 | +- `winnow = "0.7.14"` |
| 51 | +- `shadow-rs = "1.7.0"` |
| 52 | +- `ecdysis = "1.0.1"` |
| 53 | + |
| 54 | +## Dependency Priority and Forbidden Choices |
| 55 | + |
| 56 | +- HTTP client preference: `hpx` (with `rustls`) over `reqwest`. |
| 57 | +- Concurrent map/set preference: `scc` over `dashmap` and `RwLock<HashMap<...>>`. |
| 58 | +- Parsing preference: `winnow` or `pest` over ad-hoc manual parsing. |
| 59 | +- Read-heavy shared state: `arc-swap` over `RwLock`. |
| 60 | +- Forbidden by default: `anyhow`, `log`, `reqwest`, `dashmap`. |
| 61 | + |
| 62 | +## Engineering Principles |
| 63 | + |
| 64 | +### Rust Implementation Guidelines |
| 65 | + |
| 66 | +1. Error handling: |
| 67 | + - Application layer: `eyre`. |
| 68 | + - Library layer: `thiserror`. |
| 69 | +2. Database (`sqlx`): |
| 70 | + - Prefer runtime queries (`sqlx::query_as`). |
| 71 | + - DB structs should derive `sqlx::FromRow`. |
| 72 | + - Avoid compile-time `sqlx::query!` macros by default. |
| 73 | +3. Concurrency: |
| 74 | + - Prefer lock-free/container-first approaches (`scc`, `ArcSwap`). |
| 75 | + - Avoid `Arc<Mutex<T>>` when better alternatives are available. |
| 76 | +4. Observability: |
| 77 | + - Logging: `tracing` only. |
| 78 | + - Metrics/traces: OpenTelemetry OTLP gRPC. |
| 79 | + - Prometheus should not be the default instrumentation path. |
| 80 | +5. API docs: |
| 81 | + - Generate OpenAPI with `utoipa` when exposing HTTP APIs. |
| 82 | +6. Configuration: |
| 83 | + - Use the `config` crate and external configuration files (prefer TOML). |
| 84 | +7. Binaries: |
| 85 | + - Use `ecdysis` for graceful restart/reload flows in daemon/server binaries. |
| 86 | +8. Safety: |
| 87 | + - Avoid `unsafe` unless strictly required and documented. |
| 88 | + |
| 89 | +### Key Design Principles |
| 90 | + |
| 91 | +- Modularity: Design each crate so it can be used as a standalone library with clear boundaries and minimal hidden coupling. |
| 92 | +- Performance: Prefer architectures that support parallelism, memory-mapped I/O when appropriate, optimized data structures, and lock-free data types. |
| 93 | +- Extensibility: Use traits and generic types to support multiple implementations without invasive refactors. |
| 94 | +- Type Safety: Maintain strong static typing across interfaces and internals, with minimal use of dynamic dispatch. |
| 95 | + |
| 96 | +### Performance Considerations |
| 97 | + |
| 98 | +- Avoid allocations in hot paths; prefer references and borrowing to reduce allocation and copy overhead. |
| 99 | +- Use `rayon` for CPU-bound parallel processing. |
| 100 | +- Use `tokio` async/await for I/O-bound concurrency. |
| 101 | + |
| 102 | +### Concurrency and Async Execution |
| 103 | + |
| 104 | +- Prefer atomic types (`AtomicUsize`, `AtomicBool`, etc.) with explicit `Ordering` for simple shared state. |
| 105 | +- Use `scc` for highly concurrent maps/sets; avoid `Arc<RwLock<HashMap<...>>>` and `Arc<Mutex<HashMap<...>>>` on hot paths. |
| 106 | +- Use `moka` for concurrent caches instead of custom LRU implementations. |
| 107 | +- Prefer `parking_lot::{Mutex, RwLock}` over `std::sync` locks for synchronous locking. |
| 108 | +- Never hold `std::sync::Mutex` or `parking_lot::Mutex` guards across `.await`. |
| 109 | +- Use `tokio::sync::Mutex` only when a lock must be held across `.await`. |
| 110 | +- Use `tokio::task::spawn_blocking` for CPU-bound work and blocking I/O. |
| 111 | +- Avoid massive volumes of tiny Tokio tasks; batch work or use bounded worker patterns. |
| 112 | +- Channel selection: |
| 113 | + - Async-to-Async: `tokio::sync::mpsc` / `tokio::sync::broadcast` |
| 114 | + - Sync/MPMC: `crossbeam-channel` or `flume` |
| 115 | + - Avoid `std::sync::mpsc` |
| 116 | + |
| 117 | +### Memory and Allocation |
| 118 | + |
| 119 | +- For binary server applications, configure `tikv-jemallocator` or `mimalloc`. |
| 120 | +- For trusted internal hash keys, prefer `ahash` or `rustc-hash` over default SipHash-based maps. |
| 121 | +- Use `compact_str` or `smol_str` for small-string-heavy paths. |
| 122 | +- Prefer `beef::Cow` over `std::borrow::Cow` when minimizing footprint. |
| 123 | +- Use `bytes::Bytes` / `bytes::BytesMut` for network buffers; pass `Bytes` instead of cloning `Vec<u8>`. |
| 124 | +- For critical serialization hot paths, prefer `rkyv` or `zerocopy`; reserve `serde_json` for config and non-critical APIs. |
| 125 | + |
| 126 | +### Type and Layout |
| 127 | + |
| 128 | +- Order struct fields from largest to smallest unless stronger semantic grouping is required. |
| 129 | +- Use `#[repr(C)]` / `#[repr(packed)]` only for FFI or fixed protocol layout requirements. |
| 130 | +- Keep error types compact on hot paths; box large error payloads when needed to reduce `Result<T, E>` size. |
| 131 | +- Prefer typestate-style APIs for compile-time state transitions instead of runtime state checks. |
| 132 | + |
| 133 | +### Tooling and Hot Paths |
| 134 | + |
| 135 | +- Keep code clean under `clippy::pedantic`, `clippy::nursery`, and `clippy::cargo` (allow `missing_errors_doc` for non-public APIs when needed). |
| 136 | +- Use `#[inline]` for tiny frequently called methods, especially across crate boundaries. |
| 137 | +- Mark cold error paths with `#[cold]` and `#[inline(never)]` when it improves hot-path instruction locality. |
| 138 | + |
| 139 | +### Common Pitfalls |
| 140 | + |
| 141 | +- Do not block async tasks. |
| 142 | +- Handle errors explicitly and consistently with the `?` operator and concrete error types. |
| 143 | + |
| 144 | +### What to Avoid |
| 145 | + |
| 146 | +- Incomplete implementations: finish features before submitting. |
| 147 | +- Large, sweeping changes: keep changes focused and reviewable. |
| 148 | +- Mixing unrelated changes: keep one logical change per commit. |
| 149 | + |
| 150 | +## Foundry Rules (If Solidity Exists) |
| 151 | + |
| 152 | +- Use `soldeer` for dependencies; do not use git submodules. |
| 153 | +- Required commands: |
| 154 | + - `forge soldeer install` |
| 155 | + - `forge soldeer update` |
| 156 | + - `forge build` |
| 157 | + - `forge test` |
| 158 | + |
| 159 | +## Development Workflow |
| 160 | + |
| 161 | +When fixing failures, identify root cause first, then apply idiomatic fixes instead of suppressing warnings or patching symptoms. |
| 162 | + |
| 163 | +After each feature or bug fix, run: |
| 164 | + |
| 165 | +```bash |
| 166 | +just format |
| 167 | +just lint |
| 168 | +just test |
| 169 | +``` |
| 170 | + |
| 171 | +If any command fails, report the failure and do not claim completion. |
| 172 | + |
| 173 | +## Testing Requirements |
| 174 | + |
| 175 | +- Unit tests: colocate with implementation (`#[cfg(test)]`). |
| 176 | +- Integration tests: place in crate-level `tests/`. |
| 177 | +- Add tests for behavioral changes and public API changes. |
| 178 | + |
| 179 | +## Language Requirement |
| 180 | + |
| 181 | +- Documentation, comments, and commit messages must be English only. |
0 commit comments