Files
rustfs/crates/AGENTS.md
T
安正超 b5e565c0ce chore(agents): add Rust code quality rules and skill (#3144)
* docs: update security advisory lessons

* chore(agents): add Rust code quality rules and skill

Add rules derived from full-project code review (48 findings across
7 dimensions) to prevent recurring issues in agent-generated code.

AGENTS.md changes:
- crates/AGENTS.md: error type design, concurrency, recursion safety,
  type casting, test quality rules
- root AGENTS.md: serde safety, naming conventions
- crates/ecstore/AGENTS.md: allocation discipline, lock ordering,
  recursion safety, dead code policy
- crates/notify/AGENTS.md: lock ordering for runtime_view/facade

Skill changes:
- code-change-verification: add Rust-specific checks (unwrap, as cast,
  clone, lock order, recursion, error types, test assertions)
- security-advisory-lessons: add serde deserialization safety pattern
- NEW rust-code-quality: automated scan + manual review checklist
2026-05-31 22:19:36 +08:00

3.1 KiB

Crates Instructions

Applies to all paths under crates/.

Library Design

  • Treat crate code as reusable library code by default.
  • Prefer thiserror for library-facing error types.
  • Do not use unwrap(), expect(), or panic-driven control flow outside tests.

Testing

  • Keep unit tests close to the module they test.
  • Keep integration tests under each crate's tests/ directory.
  • Add regression tests for bug fixes and behavior changes.

Error Type Design

  • Public API functions must return a typed error enum (preferably thiserror-derived), never Result<_, String>.
  • Do not use Box<dyn Error> or Box<dyn Error + Send + Sync> in public trait methods or struct methods. Define a concrete error type with specific variants.
  • When implementing std::error::Error, always override fn source() if you store an inner error. Breaking the error chain makes debugging impossible.
  • Internal helpers that return Result<_, String> and are immediately wrapped via .map_err(Error::other) should return the actual error type directly.

Concurrency

  • Document lock acquisition order when a module uses multiple locks. Never acquire the same set of locks in different orders across code paths.
  • Never hold a tokio::sync::RwLock/Mutex write guard across .await points unless the critical section is unavoidably async and the hold time is bounded.
  • Prefer compare_exchange loops over load-then-store for concurrent counters (peak values, adaptive heuristics).
  • When resetting multi-field atomic statistics, use a version/sequence counter or accept that concurrent readers may see partial snapshots; document the tradeoff.
  • std::sync::Mutex is acceptable in async context only when held for a brief, non-await-containing critical section. If in doubt, use tokio::sync::Mutex.

Recursion Safety

  • Recursive tree/graph traversals must have a depth limit (e.g., max_depth counter) or use an iterative approach with an explicit Vec stack.
  • This applies to cache trees, directory walks, and any user-influenced hierarchy.
  • A corrupted or malicious input must not be able to overflow the thread stack.

Type Casting

  • Never use as for numeric conversions that may truncate or overflow. Use try_into() with explicit error handling, or clamp with value.max(0) as usize when the domain is bounded.
  • f64 as usize saturates but is fragile; clamp to [0, usize::MAX as f64] first.
  • Treat every as cast in a PR review as a potential bug; require justification.

Testing

  • Keep unit tests close to the module they test.
  • Keep integration tests under each crate's tests/ directory.
  • Add regression tests for bug fixes and behavior changes.
  • Every test function must contain at least one assert!/assert_eq!/assert_matches!. A test that only calls code without asserting is not a test.
  • In tests, prefer .expect("context: what was being tested") over bare .unwrap(). A test failure should tell you which operation failed and with what input.

Async and Performance

  • Keep async paths non-blocking.
  • Move CPU-heavy operations out of async hot paths with tokio::task::spawn_blocking when appropriate.