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
Enforce-readiness: three clean autofix linters (appendoneelement, timenowsub, stringsjoinone) have zero production violations —
[Content truncated due to length] #47916
Three registered analyzers — appendoneelement, timenowsub, and stringsjoinone — are clean, fully type-resolved, autofix-golden-verified (RunWithSuggestedFixes), nolint-wired, and have zero production violations under both the default and js/wasm builds. None is in the CI enforcement set (cgo.yml:1227 currently enforces 25 analyzers). They are safe to enforce today: enforcement would pass immediately and lock in the improvement.
This is the same enforce-readiness pattern that landed for the previous clean batches (#42416, #42644, #45186, #45629, #46341, #46978). These three have never been the subject of an enforce issue.
Evidence
Registration: all three are wired in pkg/linters/registry.go (All()), lines 73 (appendoneelement), 123 (timenowsub), 116 (stringsjoinone).
Not enforced:.github/workflows/cgo.yml:1227LINTER_FLAGS lists 25 analyzers; none of the three appears (default build) — and line 1230 (GOOS=js GOARCH=wasm) omits them too.
Type-resolved (no syntactic-package-match FP, the #43934 class):
appendoneelement.go:61 — pass.TypesInfo.ObjectOf(ident) != types.Universe.Lookup("append") gates on the builtin, not the identifier spelling.
timenowsub.go:119-127 — timeNowQualifier resolves the receiver via *types.PkgName and checks pkgName.Imported().Path() == "time"; alias/shadow-safe.
appendoneelement: append(s, []T{x}...) → append(s, x). The surrounding append re-imposes s's element type on x, so no type change; elided-type nested literals ([][]int{{1}}) and keyed elements are correctly skipped (appendoneelement.go:112-117).
timenowsub: time.Now().Sub(t) → time.Since(t). isSafeSinceArg (timenowsub.go:132-149) restricts the argument to side-effect-free forms (ident / basiclit / selector / index / deref / paren), so the evaluation-order flip (Since reads its arg before calling Now) cannot change behavior.
Golden autofix parity (RunWithSuggestedFixes):appendoneelement_test.go:15, timenowsub_test.go:15, stringsjoinone_test.go:15 all use analysistest.RunWithSuggestedFixes — the fixes are golden-verified, not merely diagnostic-tested.
Suppression + generated-file skip wired: each Requires includes nolint.Analyzer and filecheck.Analyzer, and each calls nolint.HasDirectiveForLinter + filecheck.ShouldSkipFilename (e.g. appendoneelement.go:24,69-73; timenowsub.go:23,78-83; stringsjoinone.go:23,65-69). CI enforcement passes -test=false, so test-file scope is moot.
Zero production violations (grep, excluding _test.go / testdata):
time.Now().Sub( — 0 non-test/non-doc production sites.
strings.Join([]string{ — production sites (pkg/workflow/call_workflow_permissions.go:136, checkout_path_validation.go:68, threat_detection_external.go:47, push_to_pull_request_branch_validation.go:118,136, audit_agentic_analysis.go:212) are all multi-element joins; no single-element literal.
append(x, []T{one}...) — the only }...) production sites (pkg/workflow/threat_detection_steps.go:255,295,313,327, threat_detection_external.go:443) are multi-element append blocks; no single-element spread.
Impact
These three checks are currently advisory-only: a regression (time.Now().Sub, a single-element strings.Join, or a spread single-element append) can merge without CI feedback, even though the codebase is already clean. Enforcing them locks in the current state at zero cost and gives contributors immediate feedback — the exact value delivered by the prior enforce batches that landed.
Recommendation
Add -appendoneelement -timenowsub -stringsjoinone to the LINTER_FLAGS on cgo.yml:1227 (and the wasm variant on :1230).
make golint-custom LINTER_FLAGS="-appendoneelement -timenowsub -stringsjoinone -test=false" reports zero findings on the default build.
Same three flags added to the js/wasm invocation (cgo.yml:1230) report zero findings for LINTER_PACKAGES.
Confirm each flag name matches the analyzer Name (appendoneelement, timenowsub, stringsjoinone).
No new production violation was introduced between filing and merge (re-run the three greps above).
Effort
Small — a two-line workflow edit (default + wasm), no linter code change. Each analyzer is independently clean, so the three can be enforced together or split without interaction.
Note on scope
Each analyzer was individually audited this run and found correct; stringsjoinone's bare-element autofix was specifically checked for a named-string type-change bug (the #44187/#47704 class) and cleared — Go assignability forbids a defined string type appearing bare in []string{...}, so the emitted element is always string-typed.
Summary
Three registered analyzers —
appendoneelement,timenowsub, andstringsjoinone— are clean, fully type-resolved, autofix-golden-verified (RunWithSuggestedFixes),nolint-wired, and have zero production violations under both the default andjs/wasmbuilds. None is in the CI enforcement set (cgo.yml:1227currently enforces 25 analyzers). They are safe to enforce today: enforcement would pass immediately and lock in the improvement.This is the same enforce-readiness pattern that landed for the previous clean batches (#42416, #42644, #45186, #45629, #46341, #46978). These three have never been the subject of an enforce issue.
Evidence
Registration: all three are wired in
pkg/linters/registry.go(All()), lines 73 (appendoneelement), 123 (timenowsub), 116 (stringsjoinone).Not enforced:
.github/workflows/cgo.yml:1227LINTER_FLAGSlists 25 analyzers; none of the three appears (default build) — and line 1230 (GOOS=js GOARCH=wasm) omits them too.Type-resolved (no syntactic-package-match FP, the #43934 class):
appendoneelement.go:61—pass.TypesInfo.ObjectOf(ident) != types.Universe.Lookup("append")gates on the builtin, not the identifier spelling.timenowsub.go:119-127—timeNowQualifierresolves the receiver via*types.PkgNameand checkspkgName.Imported().Path() == "time"; alias/shadow-safe.stringsjoinone.go:56→astutil.AsStringsMethodCall→astutil.IsPkgSelector(pass, sel, "strings")(astutil.go:424), the canonical type-resolved package-identity check.Behavior-preserving autofixes (verified):
appendoneelement:append(s, []T{x}...)→append(s, x). The surroundingappendre-imposess's element type onx, so no type change; elided-type nested literals ([][]int{{1}}) and keyed elements are correctly skipped (appendoneelement.go:112-117).timenowsub:time.Now().Sub(t)→time.Since(t).isSafeSinceArg(timenowsub.go:132-149) restricts the argument to side-effect-free forms (ident / basiclit / selector / index / deref / paren), so the evaluation-order flip (Sincereads its arg before callingNow) cannot change behavior.stringsjoinone:strings.Join([]string{s}, sep)→s. Guarded byisSafeToDiscardSeparator(constant separator only,stringsjoinone.go:104-107) andformatReplacementText(:139-146) which parenthesizes non-primary elements to preserve precedence (the stringsjoinone autofix drops precedence: bare unparenthesized element replacement emits non-compiling / behavior-changed code in [Content truncated due to length] #47467 fix). The bare-element output is type-safe because Go assignability forces the single element to bestringor an untyped string constant.Golden autofix parity (RunWithSuggestedFixes):
appendoneelement_test.go:15,timenowsub_test.go:15,stringsjoinone_test.go:15all useanalysistest.RunWithSuggestedFixes— the fixes are golden-verified, not merely diagnostic-tested.Suppression + generated-file skip wired: each
Requiresincludesnolint.Analyzerandfilecheck.Analyzer, and each callsnolint.HasDirectiveForLinter+filecheck.ShouldSkipFilename(e.g.appendoneelement.go:24,69-73;timenowsub.go:23,78-83;stringsjoinone.go:23,65-69). CI enforcement passes-test=false, so test-file scope is moot.Zero production violations (grep, excluding
_test.go/testdata):time.Now().Sub(— 0 non-test/non-doc production sites.strings.Join([]string{— production sites (pkg/workflow/call_workflow_permissions.go:136,checkout_path_validation.go:68,threat_detection_external.go:47,push_to_pull_request_branch_validation.go:118,136,audit_agentic_analysis.go:212) are all multi-element joins; no single-element literal.append(x, []T{one}...)— the only}...)production sites (pkg/workflow/threat_detection_steps.go:255,295,313,327,threat_detection_external.go:443) are multi-element append blocks; no single-element spread.Impact
These three checks are currently advisory-only: a regression (
time.Now().Sub, a single-elementstrings.Join, or a spread single-elementappend) can merge without CI feedback, even though the codebase is already clean. Enforcing them locks in the current state at zero cost and gives contributors immediate feedback — the exact value delivered by the prior enforce batches that landed.Recommendation
Add
-appendoneelement -timenowsub -stringsjoinoneto theLINTER_FLAGSoncgo.yml:1227(and the wasm variant on:1230).Before → after (line 1227 flags, additions only):
... -mapclearloop -mapdeletecheck -sprintfbool -test=false... -mapclearloop -mapdeletecheck -sprintfbool -appendoneelement -timenowsub -stringsjoinone -test=falseValidation checklist
make golint-custom LINTER_FLAGS="-appendoneelement -timenowsub -stringsjoinone -test=false"reports zero findings on the default build.js/wasminvocation (cgo.yml:1230) report zero findings forLINTER_PACKAGES.Name(appendoneelement,timenowsub,stringsjoinone).Effort
Small — a two-line workflow edit (default + wasm), no linter code change. Each analyzer is independently clean, so the three can be enforced together or split without interaction.
Note on scope
Each analyzer was individually audited this run and found correct;
stringsjoinone's bare-element autofix was specifically checked for a named-string type-change bug (the #44187/#47704 class) and cleared — Go assignability forbids a defined string type appearing bare in[]string{...}, so the emitted element is alwaysstring-typed.