Files
lighthouse/.ai/CODE_REVIEW.md
Jimmy Chen 8948159a40 Add AI assistant documentation and commands (#8785)
* Add AI assistant documentation and commands

Adds structured documentation for AI coding assistants:

- CLAUDE.md / AGENTS.md: Lightweight entry points with critical rules
- .ai/: Shared knowledge base (CODE_REVIEW.md, DEVELOPMENT.md, ISSUES.md)
- .claude/commands/: Claude Code skills for review, issue, release
- .github/copilot-instructions.md: GitHub Copilot instructions

Supports Claude Code, OpenAI Codex, and GitHub Copilot with modular,
pointer-based structure for maintainability.

Includes guidelines for AI assistants to prompt developers about updating
these docs after receiving feedback, creating a continuous improvement loop.

* Add parallel development tip with git worktrees

* Address review feedback

- Add missing details to DEVELOPMENT.md: fork-specific testing, database
backends, cross-compilation targets, make test-release
- Simplify AGENTS.md to pointer to CLAUDE.md (Codex can read files)

* Address review feedback

- Add priority signaling: Critical vs Important vs Good Practices
- Restore actionable file references (canonical_head.rs, test_utils.rs, etc.)
- Add Rayon CPU oversubscription context
- Add tracing span guidelines
- Simplify AGENTS.md to pointer

* Address review feedback and remove Copilot instructions

- Restore anti-patterns section (over-engineering, unnecessary complexity)
- Restore design principles (simplicity first, high cohesion)
- Add architecture guidance (dependency bloat, schema migrations, backwards compat)
- Improve natural language guidance for AI comments
- Add try_read lock pattern
- Remove copilot-instructions.md (can't follow file refs, untestable)
2026-02-09 23:41:57 -07:00

278 lines
7.5 KiB
Markdown

# Lighthouse Code Review Guidelines
Code review guidelines based on patterns from Lighthouse maintainers.
## Core Principles
- **Correctness** over clever code
- **Clarity** through good documentation and naming
- **Safety** through proper error handling and panic avoidance
- **Maintainability** for long-term health
## Critical: Consensus Crate (`consensus/` excluding `types/`)
**Extra scrutiny required** - bugs here cause consensus failures.
### Requirements
1. **Safe Math Only**
```rust
// NEVER
let result = a + b;
// ALWAYS
let result = a.saturating_add(b);
// or use safe_arith crate
let result = a.safe_add(b)?;
```
2. **Zero Panics**
- No `.unwrap()`, `.expect()`, array indexing `[i]`
- Return `Result` or `Option` instead
3. **Deterministic Behavior**
- Identical results across all platforms
- No undefined behavior
## Panic Avoidance (All Code)
```rust
// NEVER at runtime
let value = option.unwrap();
let item = array[1];
// ALWAYS
let value = option.ok_or(Error::Missing)?;
let item = array.get(1)?;
// Only acceptable during startup for CLI/config validation
let flag = matches.get_one::<String>("flag")
.expect("Required due to clap validation");
```
## Code Clarity
### Variable Naming
```rust
// BAD - ambiguous
let bb = ...;
let bl = ...;
// GOOD - clear
let beacon_block = ...;
let blob = ...;
```
### Comments
- Explain the "why" not just the "what"
- All `TODO` comments must link to a GitHub issue
- Remove dead/commented-out code
## Error Handling
### Don't Silently Swallow Errors
```rust
// BAD
self.store.get_info().unwrap_or(None)
// GOOD
self.store.get_info().unwrap_or_else(|e| {
error!(self.log, "Failed to read info"; "error" => ?e);
None
})
```
### Check Return Values
Ask: "What happens if this returns `Ok(Failed)`?" Don't ignore results that might indicate failure.
## Performance & Concurrency
### Lock Safety
- Document lock ordering requirements
- Keep lock scopes narrow
- Seek detailed review for lock-related changes
- Use `try_read` when falling back to an alternative is acceptable
- Use blocking `read` when alternative is more expensive (e.g., state reconstruction)
### Async Patterns
```rust
// NEVER block in async context
async fn handler() {
expensive_computation(); // blocks runtime
}
// ALWAYS spawn blocking
async fn handler() {
tokio::task::spawn_blocking(|| expensive_computation()).await?;
}
```
### Rayon
- Use scoped rayon pools from beacon processor
- Avoid global thread pool (causes CPU oversubscription)
## Review Process
### Focus on Actionable Issues
**Limit to 3-5 key comments.** Prioritize:
1. Correctness issues - bugs, race conditions, panics
2. Missing test coverage - especially edge cases
3. Complex logic needing documentation
4. API design concerns
**Don't comment on:**
- Minor style issues
- Things caught by CI (formatting, linting)
- Nice-to-haves that aren't important
### Keep Comments Natural and Minimal
**Tone**: Natural and conversational, not robotic.
**Good review comment:**
```
Missing test coverage for the None blobs path. The existing test at
`store_tests.rs:2874` still provides blobs. Should add a test passing
None to verify backfill handles this correctly.
```
**Good follow-up after author addresses comments:**
```
LGTM, thanks!
```
or
```
Thanks for the updates, looks good!
```
**Avoid:**
- Checklists or structured formatting (✅ Item 1 fixed...)
- Repeating what was fixed (makes it obvious it's AI-generated)
- Headers, subsections, "Summary" sections
- Verbose multi-paragraph explanations
### Use Natural Language
```
BAD (prescriptive):
"This violates coding standards which strictly prohibit runtime panics."
GOOD (conversational):
"Should we avoid `.expect()` here? This gets called in hot paths and
we typically try to avoid runtime panics outside of startup."
```
### Verify Before Commenting
- If CI passes, trust it - types/imports must exist
- Check the full diff, not just visible parts
- Ask for verification rather than asserting things are missing
## Common Review Patterns
### Fork-Specific Changes
- Verify production fork code path unchanged
- Check SSZ compatibility (field order)
- Verify rollback/error paths handle edge cases
### API Design
- Constructor signatures should be consistent
- Avoid `Option` parameters when value is always required
### Concurrency
- Lock ordering documented?
- Potential deadlocks?
- Race conditions?
### Error Handling
- Errors logged?
- Edge cases handled?
- Context provided with errors?
## Deep Review Techniques
### Verify Against Specifications
- Read the actual spec in `./consensus-specs/`
- Compare formulas exactly
- Check constant values match spec definitions
### Trace Data Flow End-to-End
For new config fields:
1. Config file - Does YAML contain the field?
2. Config struct - Is it parsed with serde attributes?
3. apply_to_chain_spec - Is it actually applied?
4. Runtime usage - Used correctly everywhere?
### Check Error Handling Fallbacks
Examine every `.unwrap_or()`, `.unwrap_or_else()`:
- If the fallback triggers, does code behave correctly?
- Does it silently degrade or fail loudly?
### Look for Incomplete Migrations
When a PR changes a pattern across the codebase:
- Search for old pattern - all occurrences updated?
- Check test files - often lag behind implementation
## Architecture & Design
### Avoid Dependency Bloat
- Question whether imports add unnecessary dependencies
- Consider feature flags for optional functionality
- Large imports when only primitives are needed may warrant a `core` or `primitives` feature
### Schema Migrations
- Database schema changes require migrations
- Don't forget to add migration code when changing stored types
- Review pattern: "Needs a schema migration"
### Backwards Compatibility
- Consider existing users when changing behavior
- Document breaking changes clearly
- Prefer additive changes when possible
## Anti-Patterns to Avoid
### Over-Engineering
- Don't add abstractions until needed
- Keep solutions simple and focused
- "Three similar lines of code is better than a premature abstraction"
### Unnecessary Complexity
- Avoid feature flags for simple changes
- Don't add fallbacks for scenarios that can't happen
- Trust internal code and framework guarantees
### Premature Optimization
- Optimize hot paths based on profiling, not assumptions
- Document performance considerations but don't over-optimize
### Hiding Important Information
- Don't use generic variable names when specific ones are clearer
- Don't skip logging just to keep code shorter
- Don't omit error context
## Design Principles
### Simplicity First
Question every layer of abstraction:
- Is this `Arc` needed, or is the inner type already `Clone`?
- Is this `Mutex` needed, or can ownership be restructured?
- Is this wrapper type adding value or just indirection?
If you can't articulate why a layer of abstraction exists, it probably shouldn't.
### High Cohesion
Group related state and behavior together. If two fields are always set together, used together, and invalid without each other, they belong in a struct.
## Before Approval Checklist
- [ ] No panics: No `.unwrap()`, `.expect()`, unchecked array indexing
- [ ] Consensus safe: If touching consensus crate, all arithmetic is safe
- [ ] Errors logged: Not silently swallowed
- [ ] Clear naming: Variable names are unambiguous
- [ ] TODOs linked: All TODOs have GitHub issue links
- [ ] Tests present: Non-trivial changes have tests
- [ ] Lock safety: Lock ordering is safe and documented
- [ ] No blocking: Async code doesn't block runtime