Summary
Issue #62540 (uncheckedsliceindex selector-base blind spot, filed against the 73rd linter on its first ever audit) auto-expired closed as not_planned since the last run, but the underlying code is 100 percent unchanged. This is the first reverse phantom close for this specific bug.
Evidence
Re-read pkg/linters/unchecked-slice-index/uncheckedsliceindex.go lines 366-371. sameExpr requires BOTH compared expressions to reduce to a bare *ast.Ident via astutil.UnwrapParenExpr:
xID, xOK := astutil.UnwrapParenExpr(x).(*ast.Ident)
yID, yOK := astutil.UnwrapParenExpr(y).(*ast.Ident)
Any expression whose base is a *ast.SelectorExpr (for example obj.Field) fails this check entirely, even after full paren unwrapping. This cascades into every consumer of sameExpr, including isLenOf, isInRangeLoop, isInBoundedForLoop, writesObjects, hasTerminatingGuardBefore, and invalidBounds, all of which silently fail to recognize bounds checks, safe range loops, safe bounded for loops, or terminating guards for any struct field slice or string.
Impact
Two confirmed live production sites still trigger this: pkg/workflow/skills_ref_resolution.go around lines 30-31 (if i < len(data.SkillReferences) fails to protect data.SkillReferences[i] because the base is a selector, not a bare identifier) and pkg/workflow/cache_memory.go around lines 355-356 (the same gap via isInBoundedForLoop). uncheckedsliceindex is not yet CI-enforced, so this is not breaking CI today, but it would generate real false positive noise the moment it is enforced, since testdata/src/uncheckedsliceindex only ever indexes bare local identifiers, never a selector base.
Recommendation
Extend sameExpr to recognize structurally identical SelectorExpr chains (matching both the resolved base object and the selected field name at every level), not just bare Ident equality. mapdeletecheck.go already contains a fully recursive sameExpr style helper (covering Ident, BasicLit, ParenExpr, SelectorExpr, StarExpr, and IndexExpr) that would serve as a good reference implementation for this fix.
Validation checklist
- Add a test fixture indexing a struct field slice guarded by an if len(obj.Field) > i check, expecting no diagnostic
- Add a bounded for loop fixture over a struct field slice, expecting no diagnostic
- Confirm the existing bare identifier cases remain correctly flagged or unflagged
- Run go test ./pkg/linters/unchecked-slice-index/...
Effort: medium, a shared helper fix that benefits six call sites at once.
Generated by 🤖 Sergo - Serena Go Expert · claude · agent · 258.2 AIC · ⌖ 4.64 AIC · ⊞ 4.9K · ◷
Summary
Issue #62540 (uncheckedsliceindex selector-base blind spot, filed against the 73rd linter on its first ever audit) auto-expired closed as not_planned since the last run, but the underlying code is 100 percent unchanged. This is the first reverse phantom close for this specific bug.
Evidence
Re-read pkg/linters/unchecked-slice-index/uncheckedsliceindex.go lines 366-371. sameExpr requires BOTH compared expressions to reduce to a bare *ast.Ident via astutil.UnwrapParenExpr:
xID, xOK := astutil.UnwrapParenExpr(x).(*ast.Ident)
yID, yOK := astutil.UnwrapParenExpr(y).(*ast.Ident)
Any expression whose base is a *ast.SelectorExpr (for example obj.Field) fails this check entirely, even after full paren unwrapping. This cascades into every consumer of sameExpr, including isLenOf, isInRangeLoop, isInBoundedForLoop, writesObjects, hasTerminatingGuardBefore, and invalidBounds, all of which silently fail to recognize bounds checks, safe range loops, safe bounded for loops, or terminating guards for any struct field slice or string.
Impact
Two confirmed live production sites still trigger this: pkg/workflow/skills_ref_resolution.go around lines 30-31 (if i < len(data.SkillReferences) fails to protect data.SkillReferences[i] because the base is a selector, not a bare identifier) and pkg/workflow/cache_memory.go around lines 355-356 (the same gap via isInBoundedForLoop). uncheckedsliceindex is not yet CI-enforced, so this is not breaking CI today, but it would generate real false positive noise the moment it is enforced, since testdata/src/uncheckedsliceindex only ever indexes bare local identifiers, never a selector base.
Recommendation
Extend sameExpr to recognize structurally identical SelectorExpr chains (matching both the resolved base object and the selected field name at every level), not just bare Ident equality. mapdeletecheck.go already contains a fully recursive sameExpr style helper (covering Ident, BasicLit, ParenExpr, SelectorExpr, StarExpr, and IndexExpr) that would serve as a good reference implementation for this fix.
Validation checklist
Effort: medium, a shared helper fix that benefits six call sites at once.