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
Two custom analyzers are registered in pkg/linters (60 total, pkg/linters/registry.go) but are not in the CI enforcement flag list (.github/workflows/cgo.yml:1362/1365, LINTER_FLAGS). Both were manually audited this run against their known bug classes (syntactic stdlib-package matching, FuncLit scope-boundary crossing, test-file false positives) and found clean, with zero real production violations under the current tree.
Correctly skips test and generated files via filecheck.ShouldSkipFilename (line 64), which internally checks IsTestFile — the common idiom of ctx, cancel := context.WithCancel(...); cancel() (cancel-immediately, used throughout *_test.go for cancellation tests) is filtered out at the file level, not just a lucky miss.
Reviewed every non-test, non-testdata production call site (grep -rn 'context.With(Cancel|Timeout|Deadline)(' pkg --include=*.go, ~20 sites across pkg/cli, pkg/workflow, pkg/modelsdev): every site either defers cancel immediately (e.g. actionlint.go:185-186, mcp_validation.go:188-189, update_container_pins.go:316-317/335-336/354-355/360-361, mcp_inspect_mcp.go x6, action_resolver.go x3, repository_features_validation.go x2, docker_validation.go:75-76, copilot_billing_check.go:26-27, codemod_workflow_run_branches.go:26-27, mcp_permissions.go:105-106, forecast.go:34-35, bootstrap_profile_github_app.go:226-227, safe_outputs_actions.go:302-303) or intentionally returns the context.CancelFunc to the caller for external lifecycle management (update_check.go:258CheckForUpdatesAsync, logs_orchestrator_download.go:156buildLogsDownloadContext, mcp_tools_privileged.go:73,301newMCPSubprocessContext) — the linter's hasDirectCancel tracking correctly stays false for the latter pattern since the cancel object is never called via a bare ExprStmt in the analyzed scope, so no false positive is possible there either.
Only two production sync.WaitGroup.Done() call sites exist in the whole tree (excluding ctx.Done() channel receives, a different API): pkg/console/spinner.go:193 (defer s.wg.Done()) and pkg/cli/forecast_compute.go:233 (defer wg.Done()) — both already deferred. Zero violations.
Recommendation
Add both -contextcancelnotdeferred and -wgdonenotdeferred to the LINTER_FLAGS string in the make golint-custom invocation in .github/workflows/cgo.yml:1362 (production-code gate). wgdonenotdeferred's only prod hit outside pkg/cli is in pkg/console, which is inside the wasm-scoped LINTER_PACKAGES list at cgo.yml:1365, so add it there too; contextcancelnotdeferred's hits (pkg/cli, pkg/workflow, pkg/modelsdev) don't intersect that list.
Validation checklist
Add -contextcancelnotdeferred -wgdonenotdeferred to cgo.yml:1362LINTER_FLAGS
Add -wgdonenotdeferred to cgo.yml:1365LINTER_FLAGS (pkg/console is in its LINTER_PACKAGES)
Run make golint-custom locally with the new flags against ./... and confirm zero findings
Effort
Small — CI config change only, no linter code changes required.
Context
Not itself a bug, but background for this finding: the analyzer registry has grown from 43 (last recorded snapshot) to 60 analyzers and moved from direct instantiation in cmd/linters/main.go to a canonical linters.All() in pkg/linters/registry.go. Of the 60 registered analyzers, 33 are currently enforced in CI; this issue proposes 2 more, bringing it to 35.
Summary
Two custom analyzers are registered in
pkg/linters(60 total,pkg/linters/registry.go) but are not in the CI enforcement flag list (.github/workflows/cgo.yml:1362/1365,LINTER_FLAGS). Both were manually audited this run against their known bug classes (syntactic stdlib-package matching,FuncLitscope-boundary crossing, test-file false positives) and found clean, with zero real production violations under the current tree.1.
contextcancelnotdeferred(pkg/linters/contextcancelnotdeferred/contextcancelnotdeferred.go)astutil.IsPkgSelector(pass, sel, "context")(contextcancelnotdeferred.go:152), not a rawident.Name == "context"string match — immune to the syntactic-match regression class fixed in Linter precision (regression): the syntactic stdlib-package-match migration never landed — 5 holdouts remain, 3 CI-enforced (#40 [Content truncated due to length] #43934.FuncLit:inspectCancelNodereturnsfalseon*ast.FuncLit(line 90-92), so a cancel func stored/returned from an enclosingFuncDecland later invoked inside a closure is never mis-attributed — immune to the class fixed in timesleepnocontext: enclosing-scope walk crosses arbitrary FuncLit boundaries — false positives + misleading fix for request/cal [Content truncated due to length] #42901/execcommandwithoutcontext: enclosing-scope walk crosses non-go/defer FuncLit boundaries — false positives + misleading fix (same [Content truncated due to length] #43683.filecheck.ShouldSkipFilename(line 64), which internally checksIsTestFile— the common idiom ofctx, cancel := context.WithCancel(...); cancel()(cancel-immediately, used throughout*_test.gofor cancellation tests) is filtered out at the file level, not just a lucky miss.grep -rn 'context.With(Cancel|Timeout|Deadline)(' pkg --include=*.go, ~20 sites across pkg/cli, pkg/workflow, pkg/modelsdev): every site either defers cancel immediately (e.g. actionlint.go:185-186, mcp_validation.go:188-189, update_container_pins.go:316-317/335-336/354-355/360-361, mcp_inspect_mcp.go x6, action_resolver.go x3, repository_features_validation.go x2, docker_validation.go:75-76, copilot_billing_check.go:26-27, codemod_workflow_run_branches.go:26-27, mcp_permissions.go:105-106, forecast.go:34-35, bootstrap_profile_github_app.go:226-227, safe_outputs_actions.go:302-303) or intentionally returns thecontext.CancelFuncto the caller for external lifecycle management (update_check.go:258CheckForUpdatesAsync,logs_orchestrator_download.go:156buildLogsDownloadContext,mcp_tools_privileged.go:73,301newMCPSubprocessContext) — the linter'shasDirectCanceltracking correctly staysfalsefor the latter pattern since the cancel object is never called via a bareExprStmtin the analyzed scope, so no false positive is possible there either.2.
wgdonenotdeferred(pkg/linters/wgdonenotdeferred/wgdonenotdeferred.go)FuncLit-boundary-crossing bug for goroutines launched inside loops was already fixed (wgdonenotdeferred precision: non-deferred wg.Done() inside a goroutine launched in a loop escapes detection (FuncLit scope bound [Content truncated due to length] #40947); confirmed the fix is intact.sync.WaitGroup.Done()call sites exist in the whole tree (excludingctx.Done()channel receives, a different API):pkg/console/spinner.go:193(defer s.wg.Done()) andpkg/cli/forecast_compute.go:233(defer wg.Done()) — both already deferred. Zero violations.Recommendation
Add both
-contextcancelnotdeferredand-wgdonenotdeferredto theLINTER_FLAGSstring in themake golint-custominvocation in.github/workflows/cgo.yml:1362(production-code gate).wgdonenotdeferred's only prod hit outside pkg/cli is inpkg/console, which is inside the wasm-scopedLINTER_PACKAGESlist at cgo.yml:1365, so add it there too;contextcancelnotdeferred's hits (pkg/cli, pkg/workflow, pkg/modelsdev) don't intersect that list.Validation checklist
-contextcancelnotdeferred -wgdonenotdeferredtocgo.yml:1362LINTER_FLAGS-wgdonenotdeferredtocgo.yml:1365LINTER_FLAGS(pkg/console is in itsLINTER_PACKAGES)make golint-customlocally with the new flags against./...and confirm zero findingsEffort
Small — CI config change only, no linter code changes required.
Context
Not itself a bug, but background for this finding: the analyzer registry has grown from 43 (last recorded snapshot) to 60 analyzers and moved from direct instantiation in
cmd/linters/main.goto a canonicallinters.All()inpkg/linters/registry.go. Of the 60 registered analyzers, 33 are currently enforced in CI; this issue proposes 2 more, bringing it to 35.