Code Change Verification
Use this skill to review code changes consistently before merge, before release, and during incident follow-up.
Quick Start
- Read the scope: commit, PR, patch, or file list.
- Map each changed area by risk and user impact.
- Inspect each risky change in context.
- Report findings first, ordered by severity.
- Close with residual risks and verification recommendations.
Core Workflow
1) Scope and assumptions
- Confirm change source (diff, commit, PR, files), target branch, language/runtime, and version.
- If context is missing, state assumptions before deeper analysis.
- Focus only on requested scope; avoid reviewing unrelated files.
2) Risk map
- Prioritize in this order:
- Data correctness and user-visible behavior
- API/contract compatibility
- Security and authz/authn boundaries
- Concurrency and lifecycle correctness
- Performance and resource usage
- Give higher priority to stateful paths, migration logic, defaults, and error handling.
3) Evidence-based inspection
- Read each modified hunk with neighboring context.
- Trace call paths and call-site expectations.
- Check for:
- invariant breaks and missing guards
- unchecked assumptions and null/empty/error-path handling
- stale tests, fixtures, and configs
- hidden coupling to shared helpers/constants/features
- If a point is uncertain, mark it as an open question instead of guessing.
Rust-specific checks (apply to all Rust changes)
- unwrap/expect in production: Search changed files for
.unwrap()and.expect(outside test modules. Everyunwrap()in production code must have a justification comment or be replaced with?. - Silent type truncation: Search for
as u8/u16/u32/u64/usize/i8/i16/i32/i64/isizecasts. Everyascast must be justified; negative-to-unsigned and large-to-small are bugs by default. Usetry_into()or explicit clamping. - Unnecessary cloning: Check
.clone()calls in loops, per-request paths, and on structs with >5 heap-allocated fields. ConsiderArc, references, orCow<str>. - Lock ordering: If the change acquires multiple locks, verify the order matches all other call sites. Document the order in a comment.
- Locks across .await: Flag any
tokio::sync::RwLock/Mutexguard held across an.awaitpoint without bounded hold time. - Recursion depth: If the change adds or modifies a recursive function, verify it has a depth limit or uses iterative traversal with an explicit stack.
- Error types: Flag
Result<_, String>,Box<dyn Error>, and missingError::source()implementations in public APIs. - Test assertions: Every test function must have at least one
assert!. Flag tests that only call code without verifying results. - println/eprintln: Search changed files for
println!/eprintln!outside test modules. Production code must usetracingmacros. - Serde safety: Structs deserialized from untrusted input (S3 API, user config) should have
#[serde(deny_unknown_fields)].
4) Findings-first output
- Order findings by severity:
- P0: critical failure, security breach, or data loss risk
- P1: high-impact regression
- P2: medium risk correctness gap
- P3: low risk/quality debt
- For each finding include:
- Severity
path:linereference- concise issue statement
- impact and likely failure mode
- specific fix or mitigation
- validation step to confirm
- If no issues exist, explicitly state
No findingsand why.
5) Close
- Report assumptions and unknowns.
- Suggest targeted checks (tests, canary checks, logs/metrics, migration validation).
Output Template
- Findings
- No findings (if applicable)
- Assumptions / Unknowns
- Recommended verification steps
Finding Template
[P1] Missing timeout for downstream call- Location:
path/to/file.rs:123 - Issue: ...
- Impact: ...
- Fix suggestion: ...
- Validation: ...
- Location: