Rust Code Review
Arguments
--parallel: Spawn specialized subagents per technology area- Path: Target directory (default: current working directory)
Hard gates
Complete in order before writing Issues in the output (empty scope is allowed; fabricated findings are not).
- Scope gate: You have an explicit list of
.rspaths under review (from Step 1 or the user-provided path). Pass: List printed or "No Rust files in scope" — then stop with no Issues. - Compiler/linter gate: Step 3 commands were run from the crate or workspace root (
Cargo.tomlpresent); if they cannot run, one line states why (e.g. missing toolchain, noCargo.toml, sandbox). Pass: You do not report a problem already shown as an error/warning in Step 3 output, and you do not duplicate compiler or clippy diagnostics the author must fix first. - Protocol gate:
beagle-rust:review-verification-protocolis loaded before Step 7. Pass: Every Critical/Major finding satisfies Step 8 (and the protocol); if there are zero findings, say "Protocol applied; no issues" in the Review Summary. - Evidence gate (Critical/Major): For each Critical or Major item, you re-read the file at
FILE:LINEwith full surrounding context (not only the diff hunk). Pass: The Issue description matches observable code at that location.
Step 1: Identify Changed Files
git diff --name-only $(git merge-base HEAD main)..HEAD | grep -E '\.rs$'
Step 2: Check Rust Edition and MSRV
# Check Cargo.toml for edition and rust-version
grep -E 'edition|rust-version' Cargo.toml
# Check workspace members if workspace
grep -A 20 '\[workspace\]' Cargo.toml
Edition 2024 awareness (requires MSRV 1.85+):
If edition = "2024" is detected, the following behavioral changes apply throughout the review:
unsafe_op_in_unsafe_fnis deny by default — unsafe operations insideunsafe fnMUST use explicitunsafe {}blocksextern "C" {}blocks must beunsafe extern "C" {}#[no_mangle]and#[export_name]must be#[unsafe(no_mangle)]and#[unsafe(export_name)]-> impl Traitcaptures ALL in-scope lifetimes by default (RPIT lifetime capture change); use+ use<'a>for precise capturegenis a reserved keyword — code using it as an identifier must user#gen!(never type) falls back to!instead of()— may change behavior of inferred types- Temporaries in
if letconditions and tail expressions are dropped earlier than in edition 2021 Box<[T]>now implementsIntoIterator
Record the detected edition — it affects severity calibration in Steps 3, 8, and the verification protocol.
Step 3: Verify Linter Status
CRITICAL: Run clippy and check BEFORE flagging style or correctness issues. Do NOT flag issues that clippy or the compiler already catches.
cargo clippy --all-targets --all-features -- -D warnings 2>&1 | head -50
cargo clippy -- -D clippy::perf 2>&1 | head -20
cargo check --all-targets 2>&1 | head -50
Edition 2024 note: Edition 2024 promotes several previously-warn lints to deny (notably unsafe_op_in_unsafe_fn). If clippy or cargo check already reports edition-related errors, do not duplicate those as review findings — instead note that the author must fix compiler errors first.
Step 4: Detect Technologies
# Detect tokio async runtime
grep -r "tokio" --include="Cargo.toml" -l | head -3
# Detect axum web framework
grep -r "axum" --include="Cargo.toml" -l | head -3
# Detect sqlx database
grep -r "sqlx" --include="Cargo.toml" -l | head -3
# Detect serde serialization
grep -r "serde" --include="Cargo.toml" -l | head -3
# Detect thiserror / anyhow
grep -r "thiserror\|anyhow" --include="Cargo.toml" -l | head -3
# Detect tracing
grep -r "tracing" --include="Cargo.toml" -l | head -3
# Check for test files in diff
git diff --name-only $(git merge-base HEAD main)..HEAD | grep -E '((^|/)(test|tests)/.*\.rs$)|(_test\.rs$)'
# Check for unsafe code in diff
git diff $(git merge-base HEAD main)..HEAD -- '*.rs' | grep -c 'unsafe'
# Detect async fn in traits (no async-trait crate needed since Rust 1.75)
grep -r "async-trait" --include="Cargo.toml" -l | head -3
# Detect LazyLock/LazyCell usage (replaces once_cell/lazy_static since 1.80)
grep -r "once_cell\|lazy_static" --include="Cargo.toml" -l | head -3
# Detect #[expect] lint attribute usage (stable since 1.81)
git diff $(git merge-base HEAD main)..HEAD -- '*.rs' | grep -c '#\[expect('
# Detect macro definitions in diff
git diff $(git merge-base HEAD main)..HEAD -- '*.rs' | grep -cE 'macro_rules!|#\[proc_macro|#\[derive\('
# Detect FFI code in diff
git diff $(git merge-base HEAD main)..HEAD -- '*.rs' | grep -cE 'extern "C"|#\[no_mangle\]|#\[repr\(C\)\]|bindgen|#\[unsafe\(no_mangle\)\]'
# Detect concurrency primitives (atomics, lock-free, hand-rolled sync)
git diff $(git merge-base HEAD main)..HEAD -- '*.rs' | grep -cE 'std::sync::atomic|Atomic(Bool|U?size|U?(8|16|32|64)|Ptr)|compare_exchange|fetch_(add|sub|or|and|xor|update)|UnsafeCell|unsafe impl (Send|Sync)|Ordering::(Relaxed|Acquire|Release|AcqRel|SeqCst)|atomic::fence'
# Detect concurrency test tooling
grep -rE 'loom|^miri$' --include='Cargo.toml' -l | head -3
git diff $(git merge-base HEAD main)..HEAD -- '*.rs' | grep -cE 'loom::|#\[cfg\(loom\)\]|cfg_attr\(miri'
# Detect concurrency crates
grep -rE '^crossbeam|^arc-swap|^parking_lot|^dashmap|^flurry|^haphazard|^seize|^atomic_wait' --include='Cargo.toml' -l | head -3
# Detect criterion benchmarks
grep -rE '^criterion' --include='Cargo.toml' -l | head -3
ls -d benches 2>/dev/null
# Detect proc-macro crate or trybuild
grep -rE 'proc-macro\s*=\s*true|^trybuild' --include='Cargo.toml' -l | head -3
# Detect public-surface changes (interface-design.md routing)
git diff $(git merge-base HEAD main)..HEAD -- '*.rs' | grep -cE '^\+\s*pub (trait|fn|struct|enum|mod|use)|^\+\s*impl[<\s].*Drop for'
# Detect ecosystem patterns (patterns-in-the-wild.md routing)
grep -rE '^slotmap|^petgraph|^scopeguard|^indexmap' --include='Cargo.toml' -l | head -3
git diff $(git merge-base HEAD main)..HEAD -- '*.rs' | grep -cE 'mem::replace|swap_remove|prelude'
Modern Rust detection notes:
- If
async-traitis a dependency but the project uses edition 2024 or MSRV >= 1.75, flag as Informational — nativeasync fnin traits is available andasync-traitcan likely be removed. - If
once_cellorlazy_staticis a dependency but MSRV >= 1.80, flag as Informational —std::sync::LazyLockandstd::cell::LazyCellare stable replacements. - If
#[allow(...)]is used where#[expect(...)]would be better (MSRV >= 1.81), note as Minor —#[expect]warns when the suppressed lint no longer fires, keeping suppressions clean.
Concurrency detection notes:
- If atomics (
std::sync::atomic,compare_exchange,fetch_*),UnsafeCell,unsafe impl Send/Sync, orcrossbeam/arc-swap/parking_lotare present in the diff, loadbeagle-rust:rust-code-reviewand consultreferences/concurrency-primitives.md,references/memory-ordering.md, andreferences/lock-free-patterns.md. - If the diff introduces or restructures concurrency (worker pools, actor-style channels,
tokio::spawnpatterns, threads-vs-async choices), also consultreferences/concurrency-models.mdfor design-level review questions. - If hand-rolled atomics / lock-free types appear with no
loomdependency or nocargo +nightly miri testin CI, loadbeagle-rust:rust-testing-code-reviewand consultreferences/concurrency-testing.md.
Interface design / API surface detection:
- If the diff introduces or changes
pub trait,pub fn,pub struct, derive impls on public types,impl Dropon owning types, or re-exports of foreign types, loadbeagle-rust:rust-code-reviewand consultreferences/interface-design.mdfor object-safety, ergonomic-impl, fallible-destructor, and hidden-contract review checks. - If the diff uses index-pointer graphs (`Vec