一键导入
code-review
Guide for conducting code reviews. Use when reviewing pull requests, auditing code quality, identifying security issues, or providing code feedback.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Guide for conducting code reviews. Use when reviewing pull requests, auditing code quality, identifying security issues, or providing code feedback.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Identify and refactor Rust anti-patterns and clippy anti-idioms. Use when reviewing Rust code for smells, hunting anti-patterns to fix or remove, or refactoring code that clones to satisfy the borrow checker, takes &String/&Vec parameters, unwraps on fallible paths, or returns sentinel values instead of Option/Result.
Guide for async and concurrent Rust programming. Use when writing async functions, using tokio, spawning threads, working with channels, or sharing state with Arc/Mutex.
Guide for building Rust command-line applications. Use when parsing CLI arguments with clap, adding progress bars or verbosity flags, testing a CLI binary as a subprocess, choosing process exit codes, or reporting errors to end users with anyhow context.
Guide for Rust error handling. Use when working with Result, Option, the ? operator, implementing custom error types, or composing errors with thiserror and anyhow.
Guide for Rust ownership, borrowing, and lifetimes. Use when working with ownership rules, move semantics, borrowing, slices, or lifetime annotations.
Guide for Rust programming language. Use when writing Rust code, setting up Rust projects, or needing an overview of Rust development workflows.
| name | code-review |
| description | Guide for conducting code reviews. Use when reviewing pull requests, auditing code quality, identifying security issues, or providing code feedback. |
This skill activates when reviewing code for quality, correctness, security, and maintainability.
Activate when:
Does the code do what it's supposed to do?
Questions to ask:
Is the code secure?
Common security issues:
# BAD: SQL injection vulnerability
query = "SELECT * FROM users WHERE id = #{user_id}"
# GOOD: Use parameterized queries
query = from u in User, where: u.id == ^user_id
# BAD: XSS vulnerability
raw("<div>#{user_input}</div>")
# GOOD: Escape user input
<div><%= user_input %></div>
# BAD: Hardcoded secrets
api_key = "sk_live_123456789"
# GOOD: Use environment variables
api_key = System.get_env("API_KEY")
# BAD: Mass assignment vulnerability
User.changeset(%User{}, params)
# GOOD: Whitelist allowed fields
User.changeset(%User{}, params)
# Where changeset only casts allowed fields:
# cast(user, attrs, [:name, :email])
Is the code efficient?
Common performance issues:
# BAD: N+1 query
posts = Repo.all(Post)
Enum.map(posts, fn post ->
author = Repo.get(User, post.author_id) # Query for each post!
{post, author}
end)
# GOOD: Preload associations
posts = Post |> preload(:author) |> Repo.all()
# BAD: Loading entire dataset
users = Repo.all(User) # Loads all millions of users
Enum.filter(users, & &1.active)
# GOOD: Query in database
users = User |> where(active: true) |> Repo.all()
# BAD: Inefficient data structure
list = [1, 2, 3, 4, 5]
if 3 in list do # O(n) lookup in list
# ...
end
# GOOD: Use set/map for lookups
set = MapSet.new([1, 2, 3, 4, 5])
if MapSet.member?(set, 3) do # O(1) lookup
# ...
end
Is the code readable and maintainable?
Code quality issues:
# BAD: Unclear names
def calc(x, y, z) do
r = x * y / z
r * 1.2
end
# GOOD: Clear names
def calculate_discounted_price(quantity, unit_price, discount_percentage) do
subtotal = quantity * unit_price
discount_amount = subtotal * (discount_percentage / 100)
subtotal - discount_amount
end
# BAD: Long function with multiple responsibilities
def process_order(order) do
# Validate order (responsibility 1)
# Calculate totals (responsibility 2)
# Update inventory (responsibility 3)
# Send email (responsibility 4)
# Log analytics (responsibility 5)
end
# GOOD: Single responsibility functions
def process_order(order) do
with {:ok, order} <- validate_order(order),
{:ok, order} <- calculate_totals(order),
{:ok, order} <- update_inventory(order),
:ok <- send_confirmation_email(order),
:ok <- log_order_analytics(order) do
{:ok, order}
end
end
# BAD: Magic numbers
if user.age >= 13 do
# ...
end
# GOOD: Named constants
@minimum_age_coppa 13
if user.age >= @minimum_age_coppa do
# ...
end
Are errors handled properly?
Error handling patterns:
# BAD: Silent failure
try do
dangerous_operation()
rescue
_ -> nil # Error is swallowed!
end
# GOOD: Handle errors explicitly
case dangerous_operation() do
{:ok, result} -> result
{:error, reason} ->
Logger.error("Operation failed: #{inspect(reason)}")
{:error, reason}
end
# BAD: Generic error message
{:error, "failed"}
# GOOD: Specific error
{:error, :invalid_email_format}
{:error, {:validation_failed, errors}}
# BAD: Let it crash when shouldn't
def parse_config(path) do
File.read!(path) # Crashes if file missing
|> Jason.decode!() # Crashes if invalid JSON
end
# GOOD: Handle expected errors
def parse_config(path) do
with {:ok, content} <- File.read(path),
{:ok, config} <- Jason.decode(content) do
{:ok, config}
else
{:error, :enoent} -> {:error, :config_file_not_found}
{:error, %Jason.DecodeError{}} -> {:error, :invalid_config_format}
end
end
Is the code properly tested?
Testing concerns:
# BAD: Unclear test name
test "test1" do
# ...
end
# GOOD: Descriptive test name
test "create_user/1 returns error when email is invalid" do
# ...
end
# BAD: Testing too much at once
test "user workflow" do
# Creates user
# Updates user
# Deletes user
# All in one test!
end
# GOOD: Focused tests
test "create_user/1 creates user with valid attributes" do
# ...
end
test "update_user/2 updates user name" do
# ...
end
test "delete_user/1 removes user from database" do
# ...
end
# BAD: Non-deterministic test
test "async operation completes" do
start_async_operation()
Process.sleep(100) # Race condition!
assert operation_completed?()
end
# GOOD: Deterministic test
test "async operation completes" do
start_async_operation()
assert_receive {:completed, _result}, 1000
end
Is the code documented?
Are dependencies handled properly?
Does every new symbol earn its place in the diff?
For each NEW symbol introduced by the diff (function, class, config, dependency), check it against the restraint ladder before approving:
Flag speculative abstractions (interfaces with one implementation, config for values that never change, factories for one product) and unrequested features as findings, not nits. See /core:restraint.
Understand the context
Build and test locally
Start with the big picture
Review for correctness
Check security and performance
Review code quality
Be constructive and specific:
# BAD: Vague criticism
"This function is bad."
# GOOD: Specific, actionable feedback
"This function has three responsibilities: validation, database update, and email sending. Consider splitting it into separate functions for better testability and maintainability:
```elixir
def update_user(user, attrs) do
with {:ok, changeset} <- validate_user_update(user, attrs),
{:ok, user} <- save_user(changeset),
:ok <- send_update_notification(user) do
{:ok, user}
end
end
"You must change this."
"What do you think about extracting this into a separate function? It would make the code easier to test."
"Use single quotes instead of double quotes."
"Our style guide prefers single quotes for consistency (see CONTRIBUTING.md section 3.2)."
**Use labels to categorize feedback:**
- **[blocking]**: Must be fixed before merging
- **[suggestion]**: Optional improvement
- **[question]**: Asking for clarification
- **[nit]**: Very minor, cosmetic issue
- **[security]**: Security concern
- **[performance]**: Performance concern
**Example:**
```markdown
[blocking] This creates a SQL injection vulnerability. Use parameterized queries:
```elixir
# Instead of:
query = "SELECT * FROM users WHERE name = '#{name}'"
# Use:
from(u in User, where: u.name == ^name)
[suggestion] Consider extracting this logic into a separate function for reusability.
[question] Why are we using a map here instead of a struct?
[nit] Extra blank line here.
### After Review
1. **Respond to author's questions**
2. **Re-review after changes**
3. **Approve when satisfied**
4. **Celebrate good code**
## Language-Specific Considerations
### Elixir
- Pattern matching is used effectively
- Functions leverage pipe operator for readability
- Atoms aren't created dynamically from untrusted input
- `with` statements handle errors properly
- Changesets validate all input
- No direct database queries in controllers/LiveViews (use contexts)
### JavaScript/TypeScript
- Types are properly defined (TypeScript)
- Promises are handled with .catch() or try/catch
- == vs === is used correctly
- Arrays/objects aren't mutated unexpectedly
- this binding is correct
- Async operations are properly awaited
### Python
- Type hints are used
- List comprehensions aren't overly complex
- Exceptions are specific (not bare except:)
- Resources are closed (use with statements)
- Code follows PEP 8
### Rust
- Ownership and borrowing are correct
- Error handling uses Result/Option properly
- Unsafe blocks are justified and minimal
- Clone/copy is used appropriately
- Lifetimes are correctly specified
## Common Code Smells
### Complexity Smells
- **Long functions** - Function does too much
- **Long parameter list** - Too many parameters
- **Deep nesting** - Too many levels of indentation
- **Complex conditionals** - Hard to understand if statements
### Duplication Smells
- **Copy-paste code** - Same code in multiple places
- **Similar functions** - Functions that do almost the same thing
- **Magic numbers** - Repeated literal values
### Naming Smells
- **Unclear names** - Variables like x, tmp, data
- **Misleading names** - Name doesn't match behavior
- **Inconsistent names** - Same concept called different things
### Design Smells
- **God object** - Class/module doing everything
- **Feature envy** - Function using another object's data more than its own
- **Inappropriate intimacy** - Too much coupling between modules
## Anti-Patterns to Watch For
### Premature Optimization
```elixir
# BAD: Optimizing before measuring
def calculate(data) do
# Complex, hard-to-read optimization
# that saves 0.1ms
end
# GOOD: Start simple, optimize if needed
def calculate(data) do
# Clear, simple code
# Optimize later if profiling shows bottleneck
end
# BAD: Abstract after one use
defmodule AbstractDataProcessorFactoryBuilder do
# Complex abstraction for single use case
end
# GOOD: Wait for second use case
def process_user_data(data) do
# Simple, direct implementation
# Abstract when pattern emerges
end
# BAD: Hiding errors
try do
risky_operation()
rescue
_ -> :ok # What went wrong?
end
# GOOD: Handle explicitly
case risky_operation() do
{:ok, result} -> {:ok, result}
{:error, reason} ->
Logger.error("Operation failed: #{inspect(reason)}")
{:error, reason}
end
Before submitting code for review:
/core:restraintreferences/no-todos-scan.md — Scan PR diffs for new TODO/FIXME/XXX/HACK/KLUDGE/DEFERRED markers; treat as BLOCKER, not nit