.claude/skills/race-check/SKILL.md
Run Go race detector to find data races in concurrent code. Use after any change to mutexes, goroutines, or channels.
npx skillsauth add PeterBooker/veloria race-checkInstall 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.
Run Go's race detector to identify data races in concurrent code.
/race-check - Run race detection on all packages/race-check ./internal/repo/... - Run on specific packageIdentify target packages
$ARGUMENTS specifies a package, use thatRun race detector
go test -race -timeout 5m $ARGUMENTS 2>&1
Use extended timeout since race detection is slower.
Parse race detector output
Look for patterns like:
WARNING: DATA RACE
Write at 0x... by goroutine N:
...
Previous read at 0x... by goroutine M:
For each race detected, identify:
Analyze the race
Read the identified source files and determine:
Suggest fixes based on codebase patterns
Veloria uses these synchronization patterns:
RWMutex for read-heavy data:
e.mu.RLock()
defer e.mu.RUnlock()
// read operations
Separate UpdateMutex for hot-swap:
e.UpdateMutex.Lock()
defer e.UpdateMutex.Unlock()
// update operations
Atomic operations for simple counters:
atomic.AddInt64(&counter, 1)
Report findings
For each race:
## Race #N: [brief description]
**Location:** file.go:123 vs file.go:456
**Type:** read-write race on [field/variable]
**Goroutines:** [description of concurrent operations]
**Suggested Fix:**
[specific code change with before/after]
These packages require extra scrutiny:
| Package | Concurrent Access Pattern |
|---------|--------------------------|
| internal/repo/ | Multiple readers during search, exclusive writer during update |
| internal/index/ | Index read during search, replaced during hot-swap |
| internal/tasks/ | Background workers accessing shared state |
| internal/manager/ | Coordinates multiple repositories |
| internal/cache/ | Ristretto handles its own concurrency |
// WRONG
return e.index.Search(query)
// RIGHT
e.mu.RLock()
idx := e.index
e.mu.RUnlock()
return idx.Search(query)
// WRONG: Different order in different functions
func A() { mu1.Lock(); mu2.Lock() }
func B() { mu2.Lock(); mu1.Lock() } // Deadlock risk
// RIGHT: Always same order
func A() { mu1.Lock(); mu2.Lock() }
func B() { mu1.Lock(); mu2.Lock() }
// WRONG: Lock held during long operation
mu.Lock()
defer mu.Unlock()
result := expensiveOperation() // Blocks others
// RIGHT: Copy under lock, process outside
mu.Lock()
data := sharedData
mu.Unlock()
result := process(data)
If no races are detected, confirm:
t.Parallel() where appropriatedevelopment
Run Go unit tests. Use after code changes to verify correctness.
development
Run gosec and govulncheck to find security vulnerabilities. Use before releases or after dependency changes.
tools
Trigger reindexing of a specific WordPress extension. Use to rebuild the search index for a plugin, theme, or core version.
tools
Run CPU and memory profiling with pprof to identify performance hotspots. Use when investigating high resource usage.