review-verification-protocol-d2828a — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited review-verification-protocol-d2828a (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
This protocol MUST be followed before reporting any code review finding. Skipping these steps leads to false positives that waste developer time and erode trust in reviews.
Before issuing any verdict — flag, reject, or downgrade a finding — you MUST echo the exact artifact you are judging, quoted from a source you read in this turn:
The artifact is the only source of truth. Never infer what you are reviewing from the branch name, the working directory, surrounding files, or recollection. If your mental model differs from the freshly read source, the source wins. A verdict issued without a same-turn echo of its target is invalid — emit the echo first, or do not emit the verdict.
This gate exists because an LLM under contextual priming will confidently flag code that is not in the file. It runs before the hard gates below.
Complete these in order before you add a finding. Skip a gate only when it clearly does not apply (e.g. skip the usages gate if the finding is not about dead code or “unused”).
impl, or macro_rules! block you read in full (not only a diff hunk or partial snippet).rg, IDE references, or equivalent) and either state zero matches for the symbol you call unused, or list each match and why it still supports the finding.#[cfg], or error propagation that could make the pattern intentional; note one concrete checked location (path + rough location) or state “none relevant after search.”Cargo.toml for the crate under review and either quote the [package] edition = "..." line or state the default edition applies and name the manifest path you checked.Before flagging ANY issue, verify:
Before flagging, you MUST:
pub and used by other crates in the workspace#[cfg])Common false positives:
#[cfg(test)] items only used in test buildsFrom/Into conversionsBefore flagging, you MUST:
?)unwrap() isn't in test code or after a safety-ensuring checkCommon false positives:
unwrap() in tests and examples (expected pattern)expect("reason") after validation (e.g., regex::Regex::new on a literal)? (the caller handles it)let _ = tx.send(...) — intentional when receiver may have droppedBefore flagging, you MUST:
Cargo.toml-> impl Trait captures ALL in-scope lifetimes by default+ use<'a> syntax, this is precise capture control, not a mistakeCommon false positives:
impl Trait — edition 2024 captures them implicitly+ use<'a, T> syntax — this is the new precise capturing syntax, not an errorBefore flagging, you MUST:
unsafe fnunsafe_op_in_unsafe_fn is deny-by-default — unsafe operations inside unsafe fn REQUIRE explicit unsafe {} blocksCommon false positives:
unsafe {} blocks inside unsafe fn — REQUIRED in edition 2024, not redundantunsafe extern "C" {} — REQUIRED in edition 2024, not optional#[unsafe(no_mangle)] / #[unsafe(export_name)] — REQUIRED in edition 2024Before flagging, you MUST:
Copy (clone on Copy types is a no-op)Common false positives:
Arc::clone(&arc) — this is the recommended explicit clone for Arctokio::spawn — required for 'static boundBefore flagging, you MUST:
Mutex, RwLock, or atomic operations protect the accessArc<Mutex<T>>)Common false positives:
Arc<Mutex<T>> — already thread-safestd::sync::atomic operations — designed for concurrent accessBefore flagging, you MUST:
Do NOT flag:
.collect() on small iteratorsONLY use for:
unsafe code with unsound invariantsUse for:
Use for:
String parameters where &str would work#[must_use] on functions with important return valuesUse for:
#[non_exhaustive]These are NOT review blockers.
if let vs match for single variant)| Pattern | Why It's Valid |
|---|---|
unwrap() in tests | Standard test behavior — panics on unexpected errors |
.clone() in test setup | Clarity over performance |
use super::* in test modules | Standard pattern for accessing parent items |
Box<dyn Error> in binaries | Not every app needs custom error types |
String fields in structs | Owned data is correct for struct fields |
Arc::clone(&x) | Explicit Arc cloning is idiomatic and recommended |
#[allow(clippy::...)] with reason | Intentional suppression is valid |
#[expect(lint)] instead of #[allow] | Self-cleaning suppression (stable since 1.81) — warns when lint no longer triggers |
unsafe {} inside unsafe fn | Required in edition 2024 (unsafe_op_in_unsafe_fn = deny) |
unsafe extern "C" {} | Required in edition 2024 for extern blocks |
#[unsafe(no_mangle)] | Required in edition 2024 for safety-relevant attributes |
#[unsafe(export_name = "...")] | Required in edition 2024 for safety-relevant attributes |
+ use<'a, T> on impl Trait returns | Precise capture syntax for edition 2024 RPIT |
r#gen as identifier | gen is reserved in edition 2024 |
LazyLock / LazyCell | Standard library replacements for once_cell/lazy_static (stable since 1.80) |
async fn in trait definitions | No longer needs async-trait crate (stable since 1.75) |
#[diagnostic::on_unimplemented] | Custom trait error messages (stable since 1.78) |
| Pattern | Why It's Valid |
|---|---|
std::sync::Mutex for short critical sections | Tokio docs recommend this for non-async locks |
tokio::spawn without join | Valid for background tasks with shutdown signaling |
select! with default branch | Non-blocking check, intentional pattern |
#[tokio::test] without multi_thread | Default single-thread is fine for most tests |
| Pattern | Why It's Valid |
|---|---|
expect() in tests | Acceptable for test setup/assertions |
#[should_panic] with expected | Valid for testing panic behavior |
| Large test functions | Integration tests can be long |
let _ = ... in test cleanup | Cleanup errors are often unactionable |
| Pattern | Why It's Valid |
|---|---|
todo!() in new code | Valid placeholder during development |
#[allow(dead_code)] during development | Common during iteration |
Multiple impl blocks for one type | Organized by trait or concern |
| Type aliases for complex types | Reduces boilerplate, improves readability |
Flag unnecessary .clone() ONLY IF:
Send/'static boundsCopyFlag missing error context ONLY IF:
? loses meaningful information about what operation failedFlag unsafe ONLY IF:
Edition 2024 unsafe changes — check Cargo.toml edition before flagging:
unsafe {} inside unsafe fn is required (not style) in edition 2024unsafe extern "C" {} is required in edition 2024 — bare extern "C" {} is a compile error#[unsafe(no_mangle)] and #[unsafe(export_name)] are required in edition 2024BEFORE flagging any edition-specific pattern, check Cargo.toml for the project's edition:
[package]
edition = "2024" # or "2021", "2018"Edition 2024 changes that affect review findings:
| Change | Edition 2021 | Edition 2024 |
|---|---|---|
unsafe inside unsafe fn | Optional style | Required (unsafe_op_in_unsafe_fn = deny) |
extern "C" {} | Valid | Must be unsafe extern "C" {} |
#[no_mangle] | Valid | Must be #[unsafe(no_mangle)] |
#[export_name] | Valid | Must be #[unsafe(export_name)] |
-> impl Trait lifetime capture | Explicit only | Captures all in-scope lifetimes |
gen as identifier | Valid | Reserved keyword (use r#gen) |
! type fallback | Falls back to () | Falls back to ! |
if let temporaries | Dropped at end of block | Dropped earlier (end of if let) |
| Tail expression temporaries | Dropped after locals | Dropped before local variables |
Box<[T]> iteration | Needs explicit .iter() | Has IntoIterator impl |
If edition is not specified, Rust defaults to edition 2015. Most modern projects use 2021 or later.
Cross-reference: The rust-code-review and rust-best-practices skills provide edition-specific code review guidance and idiomatic patterns.
Before flagging, you MUST:
macro_rules!$crate is used correctly for exported macros (not crate or self)::core:: / ::alloc:: paths are needed (only for macros used in no_std contexts)#[macro_export]Common false positives:
$crate not used in macros that are only pub(crate) — $crate is for cross-crate usage::std:: in macros for std-only crates — only flag if crate supports no_stdBefore flagging, you MUST:
Cargo.toml for proc-macro = true)syn features are minimized (full syn with "full" feature vs selective features)Before flagging, you MUST:
:tt is intentionally used for flexibility (common in TT munching patterns):expr greediness issues actually manifest (test with the macro's actual call sites)Before flagging, you MUST:
#[repr(transparent)] wrapper insteadCommon false positives:
repr(C)repr(transparent) newtype wrappers — the wrapper handles layout*mut c_void) — no layout guarantee neededBefore flagging, you MUST:
Box::into_raw/Box::from_raw pairs)Common false positives:
extern "C" fn callbacks that never panic — catch_unwind not needed*const c_char from CStr::as_ptr() held within the same scope — lifetime is fineunsafe — bindgen output is inherently unsafe-heavy by designBefore flagging, you MUST:
Relaxed is sufficient (counters, flags with no dependent data)Acquire/Release vs SeqCst choice matters (most code doesn't need SeqCst)Common false positives:
Relaxed on simple counters/metrics — no ordering needed for independent valuesRelaxed on boolean flags polled in a loop — the loop provides eventual visibilitySeqCst used "for safety" — not wrong, just potentially over-synchronizedSubmission gate — Pass: Every finding uses [FILE:LINE] ISSUE_TITLE and includes the exact line (or minimal contiguous lines) that demonstrates the issue, so a reader can jump to the proof without trusting memory.
Final verification:
[FILE:LINE] ISSUE_TITLEIf uncertain about any finding, either:
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.