Skip to content

Add formatintitoa and osisnotexist Go linters - #70801

Merged
pelikhan merged 3 commits into
mainfrom
pelikhan-reimagined-waddle
Oct 21, 2026
Merged

pelikhan merged 3 commits into
mainfrom
pelikhan-reimagined-waddle

Conversation

@pelikhan

Copy link
Copy Markdown
Collaborator

Summary

Add the two requested Go linters to catch unnecessarily verbose integer formatting and legacy error checks that miss arbitrarily wrapped errors.

  • formatintitoa recommends strconv.Itoa(x) for decimal strconv.FormatInt(int64(x), 10) calls where x is an int. Suggested fixes handle parentheses and import/type aliases and are withheld when comments overlap or the call is indirect.
  • osisnotexist flags os.IsNotExist, os.IsExist, os.IsPermission, and os.IsTimeout. It recommends the appropriate errors.Is sentinel checks, but uses separate errors.As guidance for timeouts because os.ErrDeadlineExceeded does not represent every timeout.
  • Register both analyzers, synchronize documentation and registry contracts, and add diagnostic and golden-fix regression fixtures covering aliases, shadowing, suppression, and generated files.

Both analyzers remain outside CI enforcement while existing production findings are reviewed and remediated. The branch incorporates main through 84f7eee67e.

Validation

  • Targeted analyzer and registry tests pass.
  • Go lint and custom linters pass for the changed packages.
  • Both analyzers were exercised against production packages and reported 116 existing findings.
  • The full validation gate encountered unrelated workflow-lock manifest drift. A later attempt encountered shared golangci-lint contention; a serialized Go lint run passed. Unrelated generated workflow changes were excluded.

Closes #70313

Closes #70579

pelikhan and others added 2 commits October 20, 2026 22:39
Implement the linter requests in #70313 and #70579 with registry and documentation updates, conservative fixes, and regression coverage. Keep CI enforcement deferred while existing production findings are remediated.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@pelikhan
pelikhan marked this pull request as ready for review October 21, 2026 05:46
Copilot AI max review requested due to automatic review settings October 21, 2026 05:46
@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

✅ Design Decision Gate 🏗️ completed the design decision gate check. See the comment below for the result and any generated ADR draft.

Commit pushed: e0fc25b

🏗️ ADR gate enforced by Design Decision Gate 🏗️

@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

✅ PR Code Quality Reviewer completed the code quality review.

🔎 Code quality review by PR Code Quality Reviewer

@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer

@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

✅ Ponytail Reviewer completed successfully!

Ponytail Reviewer

Outcome: reported_no_action

The agent completed and reported no action. A no-op output alone does not verify that all required work was completed or that publication was possible.

Agent messages are omitted from this comment. The category uses structured run status, not interpretation of agent prose.

Generated from Ponytail Reviewer · gpt56 · 8.32 AIC · ⌖ 5.33 AIC · ⊞ 14.8K · ◷

Generated by Ponytail Reviewer for #70801

@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

✅ Test Quality Sentinel completed test quality analysis.

Test Quality Sentinel

Outcome: reported_no_action

The agent completed and reported no action. A no-op output alone does not verify that all required work was completed or that publication was possible.

Agent messages are omitted from this comment. The category uses structured run status, not interpretation of agent prose.

Generated from Test Quality Sentinel · sonnet50 · 14.1 AIC · ⌖ 15.1 AIC · ◇ 6.7 AIC · ⊞ 12.7K · ◷

🧪 Test quality analysis by Test Quality Sentinel

@github-actions

Copy link
Copy Markdown
Contributor

🏗️ Design Decision Gate — ADR Required

This PR adds 404 lines in pkg/ (more than the 100-line threshold) but has no linked Architecture Decision Record (ADR). Neither the PR body nor issues #70313 and #70579, as referenced in the body, contain one.

📄 Draft ADR committed: docs/adr/70801-add-formatintitoa-and-osisnotexist-linters.md. Review and complete it before merging.

The draft records these decisions: add two standalone go/analysis linters (formatintitoa, osisnotexist) registered in pkg/linters/registry.go, give separate errors.As guidance for os.IsTimeout, and keep both linters out of CI enforcement until the 116 existing findings are fixed.

🔒 This PR cannot merge until an ADR is linked in the PR body.

📋 What to do next
  1. Review the draft ADR committed to your branch. It was generated from the PR diff.
  2. Complete the missing sections. Fix the [TODO: verify] note about whether upstream linters (errorlint, perfsprint, gocritic) were evaluated, and confirm the deciders.
  3. Commit the finalized ADR to docs/adr/ on your branch.
  4. Reference the ADR in this PR body with a line such as:

    ADR: ADR-70801: Add formatintitoa and osisnotexist analysis-pass linters

Once an ADR is linked in the PR body, this gate will re-run and check that the implementation matches the decision.

📋 Michael Nygard ADR Format Reference

An ADR must contain these four sections to be considered complete:

  • Context: What is the problem? What forces are at play?
  • Decision: What did you decide? Why?
  • Alternatives Considered: What else could have been done?
  • Consequences: What are the trade-offs (positive and negative)?

All ADRs are stored in docs/adr/ as Markdown files numbered by PR number.

🏗️ ADR gate enforced by Design Decision Gate 🏗️ · pi · opus55 · 27.7 AIC · ⌖ 40.5 AIC · ⊞ 1.9K · ◷
Comment /review to run again

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review summary

No actionable blocking issues found in the changed lines. The analyzer implementations, package/type resolution, suppression/generated-file handling, registry updates, and regression fixtures are internally consistent. Static review only; repository tests were not executed.

🔎 Code quality review by PR Code Quality Reviewer · copilot · gpt50 · 3.39 AIC · ⌖ 0.543 AIC · ⊞ 1.6K
Comment /review to run again

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skills-Based Review 🧠

Applied /codebase-design and /tdd — commenting with minor consistency suggestions, no blocking issues.

📋 Key Themes & Highlights

Key Themes

  • Minor message-format duplication in osisnotexist's IsTimeout branch, which bypasses the shared report template used for the other three predicates.
  • Inconsistent fix coverage: formatintitoa ships SuggestedFixes, while osisnotexist does not, even though most of its rewrites are mechanical. Likely intentional given the advisory-only rollout, but worth a short comment to document the decision.

Positive Highlights

  • ✅ Both analyzers follow the existing analyzerutil/astutil/filecheck/nolint conventions closely — no architectural drift.
  • ✅ Excellent test coverage: aliases, dot-imports, shadowed identifiers, generated-file skipping, and (nolint/redacted) suppression are all exercised, and golden-fix fixtures validate the exact rewritten text for formatintitoa.
  • ✅ Both linters are correctly held out of CI enforcement with documented rationale in doc_sync_test.go while 116 existing production findings are triaged — a sensible, low-risk rollout strategy.
  • ✅ Documentation (README.md, doc.go, spec_test.go, registry) is updated consistently and the doc_sync_test.go cross-checks keep these in sync automatically.

Note: pr-triage ran successfully and confirmed the high_impact_files reviewed here; no fallback heuristic was needed.

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · copilot · sonnet50 · 98.5 AIC · ⌖ 15.1 AIC · ⊞ 10.2K
Comment /matt to run again

Comments that could not be inline-anchored

pkg/linters/osisnotexist/osisnotexist.go:52

[/codebase-design] The IsTimeout message duplicates the &quot;does not inspect arbitrary wrapped errors&quot; phrase that the shared os.%s does not inspect arbitrary wrapped errors; use %s instead template below already encodes, instead of reusing it with a timeout-specific replacement string.

Content redacted to fit size limit.

@copilot please address this.

pkg/linters/osisnotexist/osisnotexist.go:57

[/codebase-design] Unlike its sibling formatintitoa in this same PR (and most of the other 80 analyzers in this package), osisnotexist ships no SuggestedFixes, even though IsNotExist/IsExist/IsPermission rewrites are largely mechanical (os.IsX(err) -&gt; errors.Is(err, fs.ErrX)).

Content redacted to fit size limit.

@copilot please address this.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The integer-formatting autofix can remove an import’s last use and break compilation.

2 open issues
2 files not reviewed
  • pkg/linters/formatintitoa/testdata/src/formatintitoa/generated.go: Generated file
  • pkg/linters/osisnotexist/testdata/src/osisnotexist/generated.go: Generated file
What changed in this PR

Extends gh-aw’s custom Go linters with integer-formatting simplification and wrapped-error-aware error checks.

Changes:

  • Add formatintitoa and osisnotexist analyzers.
  • Add diagnostic and suggested-fix regression fixtures.
  • Update registration and documentation while deferring CI enforcement.
File Description
pkg/​linters/​spec_test.go Extend analyzer contracts.
pkg/​linters/​registry.go Register both analyzers.
pkg/​linters/​README.md Document both rules.
pkg/​linters/​osisnotexist/​testdata/​src/​osisnotexist/​osisnotexist.go Cover predicates, aliases, and suppression.
pkg/​linters/​osisnotexist/​testdata/​src/​osisnotexist/​generated.go Verify generated-file exclusion.
pkg/​linters/​osisnotexist/​testdata/​src/​dotimport/​dotimport.go Cover dot imports.
pkg/​linters/​osisnotexist/​osisnotexist.go Detect legacy error predicates.
pkg/​linters/​osisnotexist/​osisnotexist_test.go Run diagnostic fixtures.
pkg/​linters/​formatintitoa/​testdata/​src/​formatintitoa/​generated.go Verify generated-file exclusion.
pkg/​linters/​formatintitoa/​testdata/​src/​formatintitoa/​formatintitoa.go.golden Define expected fixes.
pkg/​linters/​formatintitoa/​testdata/​src/​formatintitoa/​formatintitoa.go Cover conversions and exclusions.
pkg/​linters/​formatintitoa/​testdata/​src/​dotimport/​dotimport.go Cover dot imports and shadowing.
pkg/​linters/​formatintitoa/​testdata/​src/​alias/​alias.go.golden Define import-alias fix output.
pkg/​linters/​formatintitoa/​testdata/​src/​alias/​alias.go Cover aliased imports.
pkg/​linters/​formatintitoa/​formatintitoa.go Detect verbose formatting and offer fixes.
pkg/​linters/​formatintitoa/​formatintitoa_test.go Run diagnostic and golden-fix fixtures.
pkg/​linters/​doc.go Update analyzer catalog.
pkg/​linters/​doc_sync_test.go Record deferred enforcement.

Review effort: Max

astutil.HasOverlappingComment(pass.Files, call.Pos(), call.End()) {
return nil
}
pkgText := astutil.NodeText(pass.Fset, selector.X)
nolint.HasDirectiveForLinter(pos, noLintIndex, "formatintitoa") {
return
}
pkgPath, name, ok := astutil.PackageCall(pass, call)
@pelikhan
pelikhan merged commit cc19f14 into main Oct 21, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[linter-miner] Add osisnotexist linter [linter-miner] feat(linters): add formatintitoa linter

2 participants