You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Run 19 continues the universal reverify pattern and pairs it with a fresh audit of the manualmutexunlock analyzer — a registered-but-unenforced custom linter, structurally identical to how R17/R18 framed panicinlibrarycode. The codebase shows visible discipline gains: two prior open issues are effectively resolved this cycle (sg17a1 via linter refinement, sg18a1 via direct fix). One new actionable finding was filed.
Tools Snapshot
Total Serena tools: 23 (unchanged from R4–R18; 16-run stable plateau)
New tools: none
Removed tools: none
Tools used today: activate_project (cold start 7.4s on fresh container — usual). Most of the analysis ran through Grep+Read because broad find_symbol patterns remain 70s+ slow for ad-hoc audits.
Strategy Selection (50% cached / 50% new)
Cached reuse: reverify open trackers
The "reverify" half is now a 7-run staple (R12–R19). Today's reverify covered four open trackers:
2 sites still at cli/git.go:303 + cli/fix_command.go:410
unchanged
New exploration: manualmutexunlock audit
Hypothesis: the manualmutexunlock analyzer was registered alongside other custom linters in cmd/linters/main.go, but R12's tally of defer mu.Unlock adoption at ~85% suggested a residual 15% of manual-unlock sites that the analyzer would catch.
Method: enumerate every Lock()/RLock() in pkg/ excluding tests + testdata; inspect each for an immediately-following defer Unlock; for sites without defer, read the function body to assess panic-leak risk.
The analyzer at pkg/linters/manualmutexunlock/manualmutexunlock.go is wired into cmd/linters/main.go:44, but cgo.yml:1041 runs LINTER_FLAGS="-errstringmatch -panicinlibrarycode -test=false" — -manualmutexunlock is not in the selector. Of all Lock/RLock sites in pkg/:
Issue filed: see GitHub issues with the sergo + code-quality labels.
Medium
None this run — the new exploration converged on the single high-confidence finding above, and reverify produced only positive (issue-closing) signals.
Low (informational)
fmt.Errorf %w discipline audit — clean
1404fmt.Errorf calls in pkg/ (250 files).
%v wrapping err in production: 1 site (pkg/workflow/compiler_orchestrator_frontmatter.go:50), already //nolint:errorlint with documented justification ("intentionally not wrapping to avoid exposing os.PathError").
%s wrapping err.Error(): 0 sites.
errors.New(fmt.Sprintf(...)): 0 sites.
errors.Is(_, nil): 0 sites.
== io.EOF / == context.* direct comparisons: 0 sites.
Multi-%w (Go 1.20+) used correctly in 2 sites (pkg/cli/update_actions.go:291, pkg/cli/download_workflow.go:183).
Verdict: the codebase's error-wrapping discipline is mature.
Other clean audits this run
Deprecated stdlib: zero ioutil.*, strings.Title(, rand.Seed( usage.
time.After leaks: 4 sites total, 2 inside loops. Go 1.26 GC-reclaims unreferenced timers, so the classic leak is a non-issue.
Mutex copy bugs: zero. All 10 mutex-containing structs (Miner, Coordinator, Logger, OnceLoader[T], SpinnerWrapper, dockerPullState, mcpCacheStore, ScriptRegistry, builtinVirtualFiles*) use pointer receivers, and their constructors return *T.
Silent error swallow (if err != nil { return nil }): 8 sites, all in best-effort detection/lookup paths that intentionally treat failure as "absent."
Problem: Mutex Unlock() calls that are not deferred can leak the mutex on panic or unexpected early return, causing deadlocks. A registered analyzer is designed to catch this exact shape but isn't selected in the CI's LINTER_FLAGS.
Locations:
pkg/agentdrain/miner.go:118, 137, 148
pkg/console/spinner.go:130, 143, 159, 175, 195
pkg/cli/compile_watch.go:189, 197
pkg/cli/docker_images.go:104, 149
pkg/parser/virtual_fs.go:102
Severity: High (10 high-risk + 3 low-risk = 13 total)
Recommendation: Pick one of three remediation paths (also outlined in the filed issue):
Fix the high-risk sites first via defer Unlock (possibly with an inline func() { ... }() wrapper for short critical sections), leaving the 3 trivial sites as-is.
Refine the linter to allow trivial Lock-read-Unlock with no calls between, mirroring how panicinlibrarycode got 4 exemptions in R19.
Enable as-is and add //nolint:manualmutexunlock // justify annotations to the 3 low-risk sites.
Then append -manualmutexunlock to LINTER_FLAGS at .github/workflows/cgo.yml:1041.
Validation:
make golint-custom LINTER_FLAGS="-manualmutexunlock -test=false" exits clean
go test ./pkg/agentdrain/... ./pkg/console/... ./pkg/cli/... passes
CI workflow cgo.yml invokes the analyzer
Estimated Effort: Small–Medium (the 13 sites are concentrated in 5 files; fixes are mechanical).
The reverify-plus-X template has now produced 7 consecutive scores ≥ 8. R19 is structurally a sibling of R17 — both target "registered but unenforced custom linter" patterns. R17's tracker (#aw_sg17a1) reached resolution this run; R19's tracker (#aw_sg19a1) opens the next iteration of the same playbook.
Cumulative stats
Total runs: 19
Total findings: 169
Total tasks generated: 41
Average success score: 8.58/10
Most successful strategy: reverify-plus-helper-and-syncprims family (R12–R19, mean 8.75)
#aw_sg18a1 is fixed — if it was tracked in any open issue list, mark it closed.
Long-term
There is a meta-pattern worth a project decision: 12 of the 14 custom linters are registered but unenforced. Each future run could repeat the R17/R19 shape (audit linter X, file violations, propose refinement+enforcement). A focused mini-initiative could pick the next 2–3 linters most likely to have correctness payoff (fileclosenotdeferred, regexpcompileinfunction, rawloginlib) and march them through the same playbook.
Next Run Preview
Suggested focus areas for R20:
Reverify sg14a1, sg19a1, sgbo1 (the three remaining open trackers).
New exploration candidate: fileclosenotdeferred analyzer audit — same shape as manualmutexunlock, different bug class. Likely to find legitimate violations on os.Open / HTTP response body sites.
Alternative: regexpcompileinfunction — regexp.MustCompile inside loops or hot functions. Probably 3–10 sites worth surfacing.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
-
Executive Summary
Run 19 continues the universal reverify pattern and pairs it with a fresh audit of the
manualmutexunlockanalyzer — a registered-but-unenforced custom linter, structurally identical to how R17/R18 framedpanicinlibrarycode. The codebase shows visible discipline gains: two prior open issues are effectively resolved this cycle (sg17a1 via linter refinement, sg18a1 via direct fix). One new actionable finding was filed.Tools Snapshot
activate_project(cold start 7.4s on fresh container — usual). Most of the analysis ran throughGrep+Readbecause broadfind_symbolpatterns remain 70s+ slow for ad-hoc audits.Strategy Selection (50% cached / 50% new)
Cached reuse: reverify open trackers
The "reverify" half is now a 7-run staple (R12–R19). Today's reverify covered four open trackers:
#aw_sg14a1(#33459) — silent syscall discards#aw_sg17a1(#34382) — panicinlibrarycode unenforced#aw_sg18a1— uncheckedproject["id"].(string)pkg/cli/project_command.go:156#aw_sgbo1— different-shapefilepath.Joincli/git.go:303+cli/fix_command.go:410New exploration: manualmutexunlock audit
Hypothesis: the
manualmutexunlockanalyzer was registered alongside other custom linters incmd/linters/main.go, but R12's tally ofdefer mu.Unlockadoption at ~85% suggested a residual 15% of manual-unlock sites that the analyzer would catch.Method: enumerate every
Lock()/RLock()inpkg/excluding tests + testdata; inspect each for an immediately-followingdefer Unlock; for sites withoutdefer, read the function body to assess panic-leak risk.Findings
Critical / High
#aw_sg19a1—manualmutexunlocklinter unenforced; 13 prod Lock/Unlock sitesThe analyzer at
pkg/linters/manualmutexunlock/manualmutexunlock.gois wired intocmd/linters/main.go:44, butcgo.yml:1041runsLINTER_FLAGS="-errstringmatch -panicinlibrarycode -test=false"—-manualmutexunlockis not in the selector. Of all Lock/RLock sites inpkg/:pkg/agentdrain/miner.go:118Lockm.store.get(...), mutatepkg/agentdrain/miner.go:137RLockfindBestMatchingCluster(tokens)pkg/agentdrain/miner.go:148RLockm.store.get(result.ClusterID)pkg/console/spinner.go:130Locks.wg.Add(1)pkg/console/spinner.go:143Lockdeferpkg/console/spinner.go:159Locks.program.Quit() + s.wg.Wait()pkg/console/spinner.go:175Lockfmt.Fprintfpkg/console/spinner.go:195Lockpkg/cli/compile_watch.go:189Locktime.AfterFunc(...)registration (callback re-takes lock)pkg/cli/compile_watch.go:197Lockpkg/cli/docker_images.go:104RLockpkg/cli/docker_images.go:149Lockdefercleanuppkg/parser/virtual_fs.go:102RLockIssue filed: see GitHub issues with the
sergo+code-qualitylabels.Medium
None this run — the new exploration converged on the single high-confidence finding above, and reverify produced only positive (issue-closing) signals.
Low (informational)
fmt.Errorf %w discipline audit — clean
fmt.Errorfcalls inpkg/(250 files).%vwrappingerrin production: 1 site (pkg/workflow/compiler_orchestrator_frontmatter.go:50), already//nolint:errorlintwith documented justification ("intentionally not wrapping to avoid exposing os.PathError").%swrappingerr.Error(): 0 sites.errors.New(fmt.Sprintf(...)): 0 sites.errors.Is(_, nil): 0 sites.== io.EOF/== context.*direct comparisons: 0 sites.%w(Go 1.20+) used correctly in 2 sites (pkg/cli/update_actions.go:291,pkg/cli/download_workflow.go:183).Verdict: the codebase's error-wrapping discipline is mature.
Other clean audits this run
ioutil.*,strings.Title(,rand.Seed(usage.time.Afterleaks: 4 sites total, 2 inside loops. Go 1.26 GC-reclaims unreferenced timers, so the classic leak is a non-issue.Miner,Coordinator,Logger,OnceLoader[T],SpinnerWrapper,dockerPullState,mcpCacheStore,ScriptRegistry,builtinVirtualFiles*) use pointer receivers, and their constructors return*T.if err != nil { return nil }): 8 sites, all in best-effort detection/lookup paths that intentionally treat failure as "absent."Improvement Task Generated
Task 1: Enable
manualmutexunlocklinter or fix 13 prod sites (panic-safety)Issue Type: Code Quality / Concurrency Safety
Problem: Mutex
Unlock()calls that are not deferred can leak the mutex on panic or unexpected early return, causing deadlocks. A registered analyzer is designed to catch this exact shape but isn't selected in the CI'sLINTER_FLAGS.Locations:
pkg/agentdrain/miner.go:118, 137, 148pkg/console/spinner.go:130, 143, 159, 175, 195pkg/cli/compile_watch.go:189, 197pkg/cli/docker_images.go:104, 149pkg/parser/virtual_fs.go:102Severity: High (10 high-risk + 3 low-risk = 13 total)
Recommendation: Pick one of three remediation paths (also outlined in the filed issue):
defer Unlock(possibly with an inlinefunc() { ... }()wrapper for short critical sections), leaving the 3 trivial sites as-is.panicinlibrarycodegot 4 exemptions in R19.//nolint:manualmutexunlock // justifyannotations to the 3 low-risk sites.Then append
-manualmutexunlocktoLINTER_FLAGSat.github/workflows/cgo.yml:1041.Validation:
make golint-custom LINTER_FLAGS="-manualmutexunlock -test=false"exits cleango test ./pkg/agentdrain/... ./pkg/console/... ./pkg/cli/...passescgo.ymlinvokes the analyzerEstimated Effort: Small–Medium (the 13 sites are concentrated in 5 files; fixes are mechanical).
Success Metrics
sg19a1; no duplicates (only #33459 was open withsergolabel)Historical Context
Recent strategy trajectory
The
reverify-plus-Xtemplate has now produced 7 consecutive scores ≥ 8. R19 is structurally a sibling of R17 — both target "registered but unenforced custom linter" patterns. R17's tracker (#aw_sg17a1) reached resolution this run; R19's tracker (#aw_sg19a1) opens the next iteration of the same playbook.Cumulative stats
reverify-plus-helper-and-syncprimsfamily (R12–R19, mean 8.75)Recommendations
Immediate
#aw_sg19a1— pick remediation path (1/2/3 above).#aw_sg17a1/ [static-analysis] Report - 2026-05-24 #34382 with a note that the linter is now refined and enforced (the issue is RESOLVED).#aw_sg18a1is fixed — if it was tracked in any open issue list, mark it closed.Long-term
There is a meta-pattern worth a project decision: 12 of the 14 custom linters are registered but unenforced. Each future run could repeat the R17/R19 shape (audit linter X, file violations, propose refinement+enforcement). A focused mini-initiative could pick the next 2–3 linters most likely to have correctness payoff (
fileclosenotdeferred,regexpcompileinfunction,rawloginlib) and march them through the same playbook.Next Run Preview
Suggested focus areas for R20:
sg14a1,sg19a1,sgbo1(the three remaining open trackers).fileclosenotdeferredanalyzer audit — same shape asmanualmutexunlock, different bug class. Likely to find legitimate violations onos.Open/ HTTP response body sites.regexpcompileinfunction—regexp.MustCompileinside loops or hot functions. Probably 3–10 sites worth surfacing.References:
Generated by Sergo — The Serena Go Expert
Strategy: reverify-plus-manual-mutex-unlock-audit
Beta Was this translation helpful? Give feedback.
All reactions