.claude/skills/code-review/SKILL.md
Review code, PRs, diffs, and changes in the Pebble codebase for correctness issues including resource leaks, concurrency bugs, iterator misuse, and lint violations. Use when asked to review code, a pull request, diff, or changes.
npx skillsauth add cockroachdb/pebble code-reviewInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Use this skill when asked to review code, a PR, diff, or changes in the Pebble codebase.
These issues cause bugs, crashes, or data corruption. Flag immediately.
Get() returns a closer that MUST be closed:
// WRONG - memory leak
val, _, err := db.Get(key)
// CORRECT
val, closer, err := db.Get(key)
if err != nil {
return err
}
defer closer.Close()
Iterators must be closed: This refers to database iterators or internal key-value iterators.
iter, _ := db.NewIter(nil)
defer iter.Close() // Required
One iterator per goroutine:
// WRONG - race condition
iter := db.NewIter(nil)
go func() { iter.Next() }() // Goroutine 1
iter.First() // Goroutine 2
// CORRECT - separate iterators
go func() {
iter := db.NewIter(nil)
defer iter.Close()
// use exclusively
}()
Lock release on panic:
// WRONG - deadlock if panic
mu.Lock()
doWork()
mu.Unlock()
// CORRECT
mu.Lock()
defer mu.Unlock()
doWork()
This section refers to key-value iterators (including base.InternalIterator), not to Go loop iterators.
Must position before accessing Key/Value:
// WRONG - undefined behavior
iter := db.NewIter(nil)
key := iter.Key() // Not positioned!
// CORRECT
iter := db.NewIter(nil)
if iter.First() {
key := iter.Key()
}
Must check Error() after iteration:
// WRONG - silent failures
for iter.First(); iter.Valid(); iter.Next() {
process(iter.Key())
}
// What if I/O error occurred?
// CORRECT
for iter.First(); iter.Valid(); iter.Next() {
process(iter.Key())
}
if err := iter.Error(); err != nil {
return err
}
Many types panic on double-close. Use invariants.CloseChecker for new types:
type MyResource struct {
closeCheck invariants.CloseChecker
}
func (r *MyResource) Close() error {
r.closeCheck.Close() // Panics on double-close in invariant builds
return r.underlying.Close()
}
Use invariants package for safety:
// WRONG in hot paths
if i >= len(slice) {
panic("out of bounds")
}
// CORRECT - only panics in invariant builds
invariants.CheckBounds(i, len(slice))
These are caught by go test -tags invariants ./internal/lint but flag them in review.
// WRONG
return fmt.Errorf("failed: %v", err)
// CORRECT - preserves stack traces
return errors.Errorf("failed: %v", err)
return errors.Wrap(err, "context")
// WRONG - alignment issues, not type-safe
var count uint64
atomic.StoreUint64(&count, 10)
// CORRECT
var count atomic.Uint64
count.Store(10)
// WRONG
runtime.SetFinalizer(obj, cleanup)
// CORRECT - controlled, testable
invariants.SetFinalizer(obj, cleanup)
// WRONG
if os.IsNotExist(err) { ... }
// CORRECT
if oserror.IsNotExist(err) { ... }
errors → use github.com/cockroachdb/errorspkg/errors → use github.com/cockroachdb/errorsgolang.org/x/exp/slices → use slices (builtin)golang.org/x/exp/rand → use math/rand/v2Mark errors appropriately so they can be detected:
// For data corruption
return base.CorruptionErrorf("invalid key: %s", key)
// To check
if base.IsCorruptionError(err) {
// Handle corruption
}
Use invariants for assertions that should hold:
if invariants.Enabled {
if unexpectedCondition {
panic("invariant violated: ...")
}
}
Always add context when wrapping:
// WRONG
return err
// CORRECT
return errors.Wrap(err, "loading manifest")
return errors.Wrapf(err, "reading block %d", blockNum)
Use redact.SafeFormat for types that may contain user data:
func (k Key) SafeFormat(w redact.SafePrinter, _ rune) {
w.Print(redact.SafeString(k.String()))
}
Always attribute TODOs:
// TODO(username): description of future work
When reviewing, verify in order:
Resource Management
Get() callers close the returned closerConcurrency
Error Handling
iter.Error() checked after loopserrors.Errorf not fmt.ErrorfSafety
Lint Compliance
oserror not os.Is*invariants.SetFinalizer not runtime.SetFinalizerWhen reviewing commit messages:
package: short description (lowercase after colon)Good examples:
bloom: improve simulation output
db: add progressive bloom filter policy
internal/manifest: rename LevelFile to LevelTable
development
Audit a Go package in this repository for subtle correctness bugs, including both bugs inside the package and bugs in how the rest of the repository uses it. Optimized for Pebble- and CockroachDB-style code where invariants, iterator semantics, ownership, and API contracts matter more than style issues.
development
Maintainer-only workflow for handling GitHub Secret Scanning alerts on OpenClaw. Use when Codex needs to triage, redact, clean up, and resolve secret leakage found in issue comments, issue bodies, PR comments, or other GitHub content.
development
Maintainer workflow for OpenClaw releases, prereleases, changelog release notes, and publish validation. Use when Codex needs to prepare or verify stable or beta release steps, align version naming, assemble release notes, check release auth requirements, or validate publish-time commands and artifacts.
development
Run, watch, debug, and extend OpenClaw QA testing with qa-lab and qa-channel. Use when Codex needs to execute the repo-backed QA suite, inspect live QA artifacts, debug failing scenarios, add new QA scenarios, or explain the OpenClaw QA workflow. Prefer the live OpenAI lane with regular openai/gpt-5.4 in fast mode; do not use gpt-5.4-pro or gpt-5.4-mini unless the user explicitly overrides that policy.