mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-22 06:14:38 +00:00
* 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)
278 lines
7.5 KiB
Markdown
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
|