Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions pkg/rules/RETIRED.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Retired & Consolidated Rules

## Policy

Rules are retired from the default rule set when benchmarked data shows
they produce high noise-to-signal ratios on real repositories. Retired
source files are kept in the repo with a `//go:build ignore_retired`
build tag — they compile only when explicitly requested (`-tags ignore_retired`).

Rules are **consolidated** when their concern is fully covered by a
newer, more precise rule. Consolidated files are deleted from the repo.

## Curation Log

### 2026-06-20 — Whimsy benchmark curation

Trigger: Whimsy 15-day benchmark showed 7 rules with <5% useful findings.

**Retired (build-tagged):**

| Rule | Previous findings/10 PRs | Reason |
|------|------------------------|--------|
| SLP043 | 244 | Duplicate JSON key heuristic fires on any struct with >2 fields sharing a prefix. Only 1 real bug pattern confirmed, 243 noise. |
| SLP050 | 175 | Fires on every new function without param validation, including trivial getters/setters. No real bugs found. |
| SLP055 | 45 | "Function has N conditionals without comments" — pure style heuristic. No bugs. |

**Consolidated into SLP223 (deleted):**

| Rule | Previous findings/10 PRs | Reason |
|------|------------------------|--------|
| SLP044 | 26 | `_ = err` pattern — fully covered by SLP223's targeted ignored-error detection |
| SLP065 | 117 | Generic "ignored error return" — overlaps SLP044/SLP114/SLP120; SLP223 covers this with better precision (Close/Remove/MarkRun* etc.) |
| SLP114 | 96 | "Error-returning function called as statement" — same class as SLP065 |
| SLP120 | 14 | "Discarded value with `_ =`" — fully covered by SLP223 |

**Narrowed:**

| Rule | Change | Reason |
|------|--------|--------|
| SLP227 | Exclude strings <6 chars and HTTP method literals | Was flagging "GET"/"POST"/"run"/"config" etc. — 17 of 18 findings were noise from test helper/OpenAPI code |

## Restoring a Retired Rule

To temporarily re-enable a retired rule for a specific scan:

```bash
go run -tags ignore_retired ./cmd/slopgate --base origin/main
```

To permanently restore, remove the `//go:build ignore_retired` tag and
add the rule registration back to `registry.go`.
12 changes: 5 additions & 7 deletions pkg/rules/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,19 +44,15 @@ func Default() *Registry {
r.Register(SLP040{})
r.Register(SLP041{})
r.Register(SLP042{})
r.Register(SLP043{})
r.Register(SLP044{})
r.Register(SLP045{})
r.Register(SLP046{})
r.Register(SLP047{})
r.Register(SLP048{})
r.Register(SLP049{})
r.Register(SLP050{})
r.Register(SLP051{})
r.Register(SLP052{})
r.Register(SLP053{})
r.Register(SLP054{})
r.Register(SLP055{})
r.Register(SLP056{})
r.Register(SLP057{})
r.Register(SLP058{})
Expand All @@ -66,7 +62,6 @@ func Default() *Registry {
r.Register(SLP062{})
r.Register(SLP063{})
r.Register(SLP064{})
r.Register(SLP065{})
r.Register(SLP066{})
r.Register(SLP067{})
r.Register(SLP068{})
Expand Down Expand Up @@ -117,13 +112,11 @@ func Default() *Registry {
r.Register(SLP111{})
r.Register(SLP112{})
r.Register(SLP113{})
r.Register(SLP114{})
r.Register(SLP115{})
r.Register(SLP116{})
r.Register(SLP117{})
r.Register(SLP118{})
r.Register(SLP119{})
r.Register(SLP120{})
r.Register(SLP121{})
r.Register(SLP122{})
r.Register(SLP123{})
Expand Down Expand Up @@ -194,5 +187,10 @@ func Default() *Registry {
r.Register(SLP220{}) // filepath.Walk without context cancellation check
r.Register(SLP221{}) // exec.Command without capturing stderr on failure
r.Register(SLP222{}) // treating UTF-16/BOM data as UTF-8 without decoding
r.Register(SLP223{}) // ignored error return
r.Register(SLP224{}) // HTTP handler missing request body/param validation
r.Register(SLP225{}) // goroutine mutating shared state without sync
r.Register(SLP226{}) // SQL resource/transaction imbalance
r.Register(SLP227{}) // repeated string literal
return r
}
41 changes: 30 additions & 11 deletions pkg/rules/registry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,19 +44,15 @@ func TestDefault_RegistersAllV001Rules(t *testing.T) {
"SLP040": false,
"SLP041": false,
"SLP042": false,
"SLP043": false,
"SLP044": false,
"SLP045": false,
"SLP046": false,
"SLP047": false,
"SLP048": false,
"SLP049": false,
"SLP050": false,
"SLP051": false,
"SLP052": false,
"SLP053": false,
"SLP054": false,
"SLP055": false,
"SLP056": false,
"SLP057": false,
"SLP058": false,
Expand All @@ -66,7 +62,6 @@ func TestDefault_RegistersAllV001Rules(t *testing.T) {
"SLP062": false,
"SLP063": false,
"SLP064": false,
"SLP065": false,
"SLP066": false,
"SLP067": false,
"SLP068": false,
Expand Down Expand Up @@ -104,13 +99,11 @@ func TestDefault_RegistersAllV001Rules(t *testing.T) {
"SLP111": false,
"SLP112": false,
"SLP113": false,
"SLP114": false,
"SLP115": false,
"SLP116": false,
"SLP117": false,
"SLP118": false,
"SLP119": false,
"SLP120": false,
"SLP121": false,
"SLP122": false,
"SLP123": false,
Expand Down Expand Up @@ -142,6 +135,19 @@ func TestDefault_RegistersAllV001Rules(t *testing.T) {
"SLP207": false,
"SLP208": false,
"SLP209": false,
"SLP215": false,
"SLP216": false,
"SLP217": false,
"SLP218": false,
"SLP219": false,
"SLP220": false,
"SLP221": false,
"SLP222": false,
"SLP223": false,
"SLP224": false,
"SLP225": false,
"SLP226": false,
"SLP227": false,
}
for _, rule := range r.All() {
if _, ok := want[rule.ID()]; ok {
Expand All @@ -158,8 +164,8 @@ func TestDefault_RegistersAllV001Rules(t *testing.T) {
func TestDefault_NoExtraRules(t *testing.T) {
r := Default()

// Includes SLP202-SLP205, SLP207, the P3 rules SLP151, SLP152, new precision rules SLP155-159, SLP035 split rules SLP160-162, reviewer gap rules SLP210-214, reviewer gap closure v2 rules SLP215-218, and reviewer gap closure v3 rules SLP219-222.
wantCount := 164
// Includes SLP202-SLP205, SLP207, the P3 rules SLP151, SLP152, new precision rules SLP155-159, SLP035 split rules SLP160-162, reviewer gap rules SLP210-214, reviewer gap closure v2 rules SLP215-218, reviewer gap closure v3 rules SLP219-222, and v4 rules SLP223-227.
wantCount := 162
if got := len(r.All()); got != wantCount {
t.Errorf("Default registry has %d rules, want %d", got, wantCount)
}
Expand All @@ -177,8 +183,8 @@ func TestDefault_NoExtraRules(t *testing.T) {
"SLP101", "SLP102", "SLP103", "SLP104",
"SLP106", "SLP107", "SLP108", "SLP109", "SLP110",
"SLP111", "SLP112",
"SLP113", "SLP114", "SLP115", "SLP116", "SLP117",
"SLP118", "SLP119", "SLP120",
"SLP113", "SLP115", "SLP116", "SLP117",
"SLP118", "SLP119",
"SLP121", "SLP122", "SLP123", "SLP124", "SLP125",
"SLP126", "SLP127",
"SLP128", "SLP129", "SLP130", "SLP131", "SLP132",
Expand All @@ -197,6 +203,19 @@ func TestDefault_NoExtraRules(t *testing.T) {
"SLP207",
"SLP208",
"SLP209",
"SLP215",
"SLP216",
"SLP217",
"SLP218",
"SLP219",
"SLP220",
"SLP221",
"SLP222",
"SLP223",
"SLP224",
"SLP225",
"SLP226",
"SLP227",
}
for _, id := range newRules {
if !ruleIDs[id] {
Expand Down
2 changes: 2 additions & 0 deletions pkg/rules/slp043.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build ignore_retired

package rules

import (
Expand Down
59 changes: 0 additions & 59 deletions pkg/rules/slp044.go

This file was deleted.

2 changes: 2 additions & 0 deletions pkg/rules/slp050.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build ignore_retired

package rules

import (
Expand Down
2 changes: 2 additions & 0 deletions pkg/rules/slp050_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build ignore_retired

package rules

import (
Expand Down
2 changes: 2 additions & 0 deletions pkg/rules/slp055.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build ignore_retired

package rules

import (
Expand Down
2 changes: 2 additions & 0 deletions pkg/rules/slp055_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build ignore_retired

package rules

import (
Expand Down
Loading