Skip to content

Share discarded-error matching across Go analyzers - #65567

Merged
pelikhan merged 11 commits into
mainfrom
copilot/duplicate-code-fix
Oct 4, 2026
Merged

pelikhan merged 11 commits into
mainfrom
copilot/duplicate-code-fix

Conversation

Copilot AI commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

The strconv, glob, and JSON analyzers duplicated assignment-shape checks and imported-package resolution for discarded errors. Centralize that matching while preserving JSON’s additional Unmarshal and expression-statement cases.

  • Shared AST helpers: Resolve package-qualified calls and match two-result assignments with a discarded error.
  • Analyzer updates: Use the shared helpers in all three analyzers, retaining each analyzer’s function filters and diagnostics.
  • Coverage: Test aliased imports and reject named-error and method-call assignments.
n, _ := conv.Atoi("42") // matched as strconv.Atoi, including import aliases

Copilot AI and others added 2 commits October 4, 2026 13:29
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Refactor duplicate linter scaffolding for error handling Share discarded-error matching across Go analyzers Oct 4, 2026
Copilot AI requested a review from pelikhan October 4, 2026 13:31
@pelikhan
pelikhan marked this pull request as ready for review October 4, 2026 13:31
Copilot AI balanced review requested due to automatic review settings October 4, 2026 13:31
Comment thread go.mod Outdated

require (
github.com/rhysd/actionlint v1.7.12
go.yaml.in/yaml/v3 v3.0.5

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@copilot other yaml library already in use

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Switched the workflow test to the existing gopkg.in/yaml.v3 package and restored go.yaml.in/yaml/v3 to indirect-only. Committed as f97b43d.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Updated the test to use the existing goccy/go-yaml package and kept go.yaml.in/yaml/v3 indirect in go.mod (commit 7e0b20d).

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.

Copilot review overview

🟡 Changes recommended

Queue validation rejects compiler-generated expressions, and removed routes break existing centralized commands.

Review effort: Balanced
Findings: 2 High severity

Open (2)
What changed in this PR

Centralizes discarded-error matching across three Go analyzers, addressing #65436 while preserving JSON-specific checks.

Changes:

  • Adds shared assignment-matching and package-resolution helpers.
  • Migrates analyzers and tests aliases, named errors, and method calls.
  • Also changes queue validation, command routing, and dependency classification.
File Description
pkg/​workflow/​schemas/​github-workflow.json Restricts queue values to literals.
pkg/​linters/​strconvparseignorederror/​strconvparseignorederror.go Uses the shared matcher.
pkg/​linters/​jsonmarshalignoredeerror/​jsonmarshalignoredeerror.go Uses shared helpers while retaining JSON-specific cases.
pkg/​linters/​internal/​astutil/​astutil.go Adds reusable matching helpers.
pkg/​linters/​internal/​astutil/​astutil_test.go Covers aliases and rejected assignment forms.
pkg/​linters/​globwalkignorederror/​globwalkignorederror.go Uses shared matching and package-path diagnostics.
go.mod Marks YAML v3 as a direct dependency.
.github/​workflows/​agentic_commands.yml Removes command routes and related metadata.

Comment thread .github/workflows/agentic_commands.yml Outdated
# runner-guard:ignore RGS-016 -- routing tables below contain emoji variation selectors (U+FE0F) and zero-width joiners (U+200D) used to render standard emoji sequences, not steganographic payloads.
env:
GH_AW_SLASH_ROUTING: '{"*":[{"workflow":"skillet","events":["pull_request_comment","pull_request_review_comment"],"ai_reaction":"eyes","emoji":"🍳","status_comment":true}],"ace":[{"workflow":"ace-editor","events":["pull_request_comment"],"ai_reaction":"eyes","emoji":"✏️","status_comment":true}],"approach-validator":[{"workflow":"approach-validator","events":["issue_comment","pull_request_comment"],"ai_reaction":"eyes","emoji":"✅","status_comment":true}],"archie":[{"workflow":"archie","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"eyes","emoji":"🏛️","status_comment":true}],"cloclo":[{"workflow":"cloclo","events":["discussion","discussion_comment","issue_comment","issues","pull_request","pull_request_comment","pull_request_review_comment"],"ai_reaction":"eyes","emoji":"📊","status_comment":true}],"craft":[{"workflow":"craft","events":["issues"],"ai_reaction":"eyes","emoji":"✍️","status_comment":true}],"dependabot-burner":[{"workflow":"dependabot-burner","events":["pull_request_comment","pull_request_review_comment"],"ai_reaction":"eyes","emoji":"🔥","status_comment":true}],"grumpy":[{"workflow":"grumpy-reviewer","events":["pull_request_comment","pull_request_review_comment"],"ai_reaction":"eyes","emoji":"🔍","status_comment":true}],"matt":[{"workflow":"mattpocock-skills-reviewer","events":["pull_request_comment","pull_request_review_comment"],"ai_reaction":"eyes","emoji":"🔍","status_comment":true}],"mergefest":[{"workflow":"mergefest","events":["pull_request_comment"],"ai_reaction":"eyes","emoji":"🔀","status_comment":true}],"nit":[{"workflow":"pr-nitpick-reviewer","events":["pull_request_comment","pull_request_review_comment"],"ai_reaction":"eyes","emoji":"🔍","status_comment":true}],"plan":[{"workflow":"plan","events":["discussion_comment","issue_comment"],"ai_reaction":"eyes","emoji":"📋","status_comment":true}],"poem-bot":[{"workflow":"poem-bot","events":["issues"],"ai_reaction":"eyes","emoji":"🎭","status_comment":true}],"ponytail":[{"workflow":"ponytail-reviewer","events":["pull_request_comment","pull_request_review_comment"],"ai_reaction":"eyes","emoji":"✂️","status_comment":true}],"review":[{"workflow":"design-decision-gate","events":["pull_request_comment","pull_request_review_comment"],"ai_reaction":"eyes","emoji":"🏗️","status_comment":true},{"workflow":"pr-code-quality-reviewer","events":["pull_request_comment","pull_request_review_comment"],"ai_reaction":"eyes","emoji":"🔍","status_comment":true},{"workflow":"test-quality-sentinel","events":["pull_request_comment","pull_request_review_comment"],"ai_reaction":"eyes","emoji":"🧪","status_comment":true}],"ruflo":[{"workflow":"ruflo-backed-task","events":["issue_comment"],"ai_reaction":"eyes","status_comment":true}],"scout":[{"workflow":"scout","events":["discussion","discussion_comment","issue_comment","issues","pull_request","pull_request_comment","pull_request_review_comment"],"ai_reaction":"eyes","emoji":"🔭","status_comment":true}],"security-review":[{"workflow":"security-review","events":["pull_request_comment","pull_request_review_comment"],"ai_reaction":"eyes","emoji":"🔒","status_comment":true}],"smoke-agent-all-merged":[{"workflow":"smoke-agent-all-merged","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"eyes","emoji":"🧪","status_comment":true}],"smoke-agent-all-none":[{"workflow":"smoke-agent-all-none","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"eyes","emoji":"🧪","status_comment":true}],"smoke-agent-public-approved":[{"workflow":"smoke-agent-public-approved","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"eyes","emoji":"🧪","status_comment":true}],"smoke-agent-public-none":[{"workflow":"smoke-agent-public-none","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"eyes","emoji":"🧪","status_comment":true}],"smoke-agent-scoped-approved":[{"workflow":"smoke-agent-scoped-approved","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"eyes","emoji":"🧪","status_comment":true}],"smoke-aider":[{"workflow":"smoke-aider","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"rocket","emoji":"🧑‍✈️","status_comment":true}],"smoke-call-workflow":[{"workflow":"smoke-call-workflow","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"eyes","emoji":"🧪","status_comment":true}],"smoke-checkout-pr-dispatch":[{"workflow":"smoke-checkout-pr-dispatch","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"eyes","emoji":"🧪","status_comment":true}],"smoke-claude":[{"workflow":"smoke-claude","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"heart","emoji":"🧪","status_comment":true}],"smoke-claude-on-copilot":[{"workflow":"smoke-claude-on-copilot","events":["pull_request","pull_request_comment"],"ai_reaction":"eyes","emoji":"🧪","status_comment":true}],"smoke-codex":[{"workflow":"smoke-codex","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"hooray","emoji":"🧪","status_comment":true}],"smoke-copilot":[{"workflow":"smoke-copilot","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"eyes","emoji":"🧪","status_comment":true}],"smoke-copilot-aoai-apikey":[{"workflow":"smoke-copilot-aoai-apikey","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"eyes","emoji":"🧪","status_comment":true}],"smoke-copilot-aoai-entra":[{"workflow":"smoke-copilot-aoai-entra","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"eyes","emoji":"🧪","status_comment":true}],"smoke-copilot-arm":[{"workflow":"smoke-copilot-arm","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"eyes","emoji":"🧪","status_comment":true}],"smoke-copilot-mai":[{"workflow":"smoke-copilot-mai","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"eyes","emoji":"⚡","status_comment":true}],"smoke-copilot-sdk":[{"workflow":"smoke-copilot-sdk","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"eyes","emoji":"🔬","status_comment":true}],"smoke-copilot-small":[{"workflow":"smoke-copilot-small","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"eyes","emoji":"🪶","status_comment":true}],"smoke-create-cross-repo-pr":[{"workflow":"smoke-create-cross-repo-pr","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"eyes","emoji":"🧪","status_comment":true}],"smoke-crush":[{"workflow":"smoke-crush","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"eyes","emoji":"🧪","status_comment":true}],"smoke-cursor":[{"workflow":"smoke-cursor","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"rocket","emoji":"🖱️","status_comment":true}],"smoke-deepseek-harness":[{"workflow":"smoke-deepseek-harness","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"eyes","emoji":"🧪","status_comment":true}],"smoke-drive":[{"workflow":"smoke-drive","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"rocket","emoji":"💾","status_comment":true}],"smoke-gemini":[{"workflow":"smoke-gemini","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"rocket","emoji":"🧪","status_comment":true}],"smoke-github-claude":[{"workflow":"smoke-github-claude","events":["pull_request","pull_request_comment"],"ai_reaction":"eyes","emoji":"🧪","status_comment":true}],"smoke-goose":[{"workflow":"smoke-goose","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"rocket","emoji":"🪿","status_comment":true}],"smoke-kiro":[{"workflow":"smoke-kiro","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"rocket","emoji":"🧭","status_comment":true}],"smoke-multi-pr":[{"workflow":"smoke-multi-pr","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"eyes","emoji":"🧪","status_comment":true}],"smoke-opencode":[{"workflow":"smoke-opencode","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"rocket","emoji":"🧪","status_comment":true}],"smoke-otel-backends":[{"workflow":"smoke-otel-backends","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"eyes","emoji":"🧪","status_comment":true}],"smoke-pi":[{"workflow":"smoke-pi","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"rocket","emoji":"🧪","status_comment":true}],"smoke-project":[{"workflow":"smoke-project","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"eyes","emoji":"🧪","status_comment":true}],"smoke-pydantic":[{"workflow":"smoke-pydantic","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"rocket","emoji":"🐍","status_comment":true}],"smoke-service-ports":[{"workflow":"smoke-service-ports","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"eyes","emoji":"🧪","status_comment":true}],"smoke-temporary-id":[{"workflow":"smoke-temporary-id","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"eyes","emoji":"🧪","status_comment":true}],"smoke-test-tools":[{"workflow":"smoke-test-tools","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"eyes","emoji":"🧪","status_comment":true}],"smoke-update-cross-repo-pr":[{"workflow":"smoke-update-cross-repo-pr","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"eyes","emoji":"🧪","status_comment":true}],"souschef":[{"workflow":"pr-sous-chef","events":["pull_request_comment"],"ai_reaction":"eyes","emoji":"👨‍🍳","status_comment":true}],"squad-plan":[{"workflow":"squad-plan","events":["issue_comment"],"ai_reaction":"eyes","emoji":"🧑‍🤝‍🧑","status_comment":true}],"summarize":[{"workflow":"pdf-summary","events":["issue_comment","issues"],"ai_reaction":"eyes","emoji":"📄","status_comment":true}],"tidy":[{"workflow":"tidy","events":["pull_request_comment"],"ai_reaction":"eyes","emoji":"🧹","status_comment":true}],"unbloat":[{"workflow":"unbloat-docs","events":["pull_request_comment"],"ai_reaction":"eyes","emoji":"📝","status_comment":true}],"windows":[{"workflow":"windows","events":["discussion","discussion_comment","issue_comment","issues","pull_request","pull_request_comment","pull_request_review_comment"],"ai_reaction":"eyes","emoji":"🪟","status_comment":true}]}'
GH_AW_SLASH_ROUTING: '{"*":[{"workflow":"skillet","events":["pull_request_comment","pull_request_review_comment"],"ai_reaction":"eyes","emoji":"🍳","status_comment":true}],"ace":[{"workflow":"ace-editor","events":["pull_request_comment"],"ai_reaction":"eyes","emoji":"✏️","status_comment":true}],"approach-validator":[{"workflow":"approach-validator","events":["issue_comment","pull_request_comment"],"ai_reaction":"eyes","emoji":"✅","status_comment":true}],"archie":[{"workflow":"archie","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"eyes","emoji":"🏛️","status_comment":true}],"cloclo":[{"workflow":"cloclo","events":["discussion","discussion_comment","issue_comment","issues","pull_request","pull_request_comment","pull_request_review_comment"],"ai_reaction":"eyes","emoji":"📊","status_comment":true}],"craft":[{"workflow":"craft","events":["issues"],"ai_reaction":"eyes","emoji":"✍️","status_comment":true}],"dependabot-burner":[{"workflow":"dependabot-burner","events":["pull_request_comment","pull_request_review_comment"],"ai_reaction":"eyes","emoji":"🔥","status_comment":true}],"grumpy":[{"workflow":"grumpy-reviewer","events":["pull_request_comment","pull_request_review_comment"],"ai_reaction":"eyes","emoji":"🔍","status_comment":true}],"mergefest":[{"workflow":"mergefest","events":["pull_request_comment"],"ai_reaction":"eyes","emoji":"🔀","status_comment":true}],"nit":[{"workflow":"pr-nitpick-reviewer","events":["pull_request_comment","pull_request_review_comment"],"ai_reaction":"eyes","emoji":"🔍","status_comment":true}],"plan":[{"workflow":"plan","events":["discussion_comment","issue_comment"],"ai_reaction":"eyes","emoji":"📋","status_comment":true}],"poem-bot":[{"workflow":"poem-bot","events":["issues"],"ai_reaction":"eyes","emoji":"🎭","status_comment":true}],"ruflo":[{"workflow":"ruflo-backed-task","events":["issue_comment"],"ai_reaction":"eyes","status_comment":true}],"scout":[{"workflow":"scout","events":["discussion","discussion_comment","issue_comment","issues","pull_request","pull_request_comment","pull_request_review_comment"],"ai_reaction":"eyes","emoji":"🔭","status_comment":true}],"security-review":[{"workflow":"security-review","events":["pull_request_comment","pull_request_review_comment"],"ai_reaction":"eyes","emoji":"🔒","status_comment":true}],"smoke-claude-on-copilot":[{"workflow":"smoke-claude-on-copilot","events":["pull_request","pull_request_comment"],"ai_reaction":"eyes","emoji":"🧪","status_comment":true}],"smoke-copilot":[{"workflow":"smoke-copilot","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"eyes","emoji":"🧪","status_comment":true}],"smoke-copilot-aoai-apikey":[{"workflow":"smoke-copilot-aoai-apikey","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"eyes","emoji":"🧪","status_comment":true}],"smoke-copilot-aoai-entra":[{"workflow":"smoke-copilot-aoai-entra","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"eyes","emoji":"🧪","status_comment":true}],"smoke-copilot-mai":[{"workflow":"smoke-copilot-mai","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"eyes","emoji":"⚡","status_comment":true}],"smoke-copilot-sdk":[{"workflow":"smoke-copilot-sdk","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"eyes","emoji":"🔬","status_comment":true}],"smoke-copilot-small":[{"workflow":"smoke-copilot-small","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"eyes","emoji":"🪶","status_comment":true}],"smoke-github-claude":[{"workflow":"smoke-github-claude","events":["pull_request","pull_request_comment"],"ai_reaction":"eyes","emoji":"🧪","status_comment":true}],"smoke-otel-backends":[{"workflow":"smoke-otel-backends","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"eyes","emoji":"🧪","status_comment":true}],"smoke-service-ports":[{"workflow":"smoke-service-ports","events":["issue_comment","issues","pull_request","pull_request_comment"],"ai_reaction":"eyes","emoji":"🧪","status_comment":true}],"souschef":[{"workflow":"pr-sous-chef","events":["pull_request_comment"],"ai_reaction":"eyes","emoji":"👨‍🍳","status_comment":true}],"squad-plan":[{"workflow":"squad-plan","events":["issue_comment"],"ai_reaction":"eyes","emoji":"🧑‍🤝‍🧑","status_comment":true}],"summarize":[{"workflow":"pdf-summary","events":["issue_comment","issues"],"ai_reaction":"eyes","emoji":"📄","status_comment":true}],"tidy":[{"workflow":"tidy","events":["pull_request_comment"],"ai_reaction":"eyes","emoji":"🧹","status_comment":true}],"unbloat":[{"workflow":"unbloat-docs","events":["pull_request_comment"],"ai_reaction":"eyes","emoji":"📝","status_comment":true}],"windows":[{"workflow":"windows","events":["discussion","discussion_comment","issue_comment","issues","pull_request","pull_request_comment","pull_request_review_comment"],"ai_reaction":"eyes","emoji":"🪟","status_comment":true}]}'

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The merged branch has the complete router, including all three /review handlers and /smoke-codex; the file now matches the pre-PR routing state, so no router change was needed.

@github-actions

github-actions Bot commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

✅ Ponytail Reviewer completed successfully!

Generated by Ponytail Reviewer for #65567

@github-actions

github-actions Bot commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

✅ Test Quality Sentinel completed test quality analysis.

Test Quality Sentinel skipped because pre-fetch PR data was unavailable: unable to fetch test file diff

🧪 Test quality analysis by Test Quality Sentinel

@github-actions

github-actions Bot commented Oct 4, 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 4, 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.

🏗️ ADR gate enforced by Design Decision Gate 🏗️

@github-actions

github-actions Bot commented Oct 4, 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 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.

One small simplification opportunity.

net: -8 lines possible.

Generated by ✂️ Ponytail Reviewer for #65567 · codex · gpt56 · 12.7 AIC · ⌖ 6.52 AIC · ⊞ 13.4K
Comment /ponytail to run again

if pass == nil || pass.TypesInfo == nil || assign == nil || len(assign.Lhs) != 2 || len(assign.Rhs) != 1 {
return nil, "", "", false
}
var secondLHS ast.Expr

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.

L54: shrink: loops retrieve fixed indexes after exact length guards. Use assign.Lhs[1] and assign.Rhs[0], 8 fewer lines.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I kept the guarded loops: direct slice indexing is flagged by this repository's uncheckedsliceindex custom analyzer, even after the length checks. The safe form preserves lint compliance.

@github-actions

github-actions Bot commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

Comment Memory

reviewed_at: 2026-10-04T13:41:17Z
review_event: REQUEST_CHANGES
top_themes:
  - workflow schema regression for expression-valued concurrency queue
  - generated slash-command routing drops existing workflows/commands
files_reviewed:
  - .github/workflows/agentic_commands.yml
  - go.mod
  - pkg/linters/globwalkignorederror/globwalkignorederror.go
  - pkg/linters/internal/astutil/astutil.go
  - pkg/linters/internal/astutil/astutil_test.go
  - pkg/linters/jsonmarshalignoredeerror/jsonmarshalignoredeerror.go
  - pkg/linters/strconvparseignorederror/strconvparseignorederror.go
  - pkg/workflow/schemas/github-workflow.json
comment_count: 0

Note

This comment is managed by comment memory.

It stores persistent context for this thread in the code block at the top of this comment.
Edit only the text inside the backtick fences; workflow metadata and the footer are regenerated automatically.

Learn more about comment memory

🔎 Code quality review by PR Code Quality Reviewer · copilot · gpt54 · 45.2 AIC · ⌖ 7.93 AIC · ⊞ 19.4K · ◷
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.

Request changes

Blocking regressions are still in this patch even after the analyzer refactor.

Blocking themes
  • pkg/workflow/schemas/github-workflow.json now rejects expression-valued queue, so workflows that legitimately emit ${{ github.event_name == 'pull_request' && 'single' || 'max' }} will fail schema validation.
  • .github/workflows/agentic_commands.yml drops existing slash-command routes/workflows that were not part of the stated change, which is a production behavior change far outside a discarded-error helper extraction.

🔎 Code quality review by PR Code Quality Reviewer · copilot · gpt54 · 45.2 AIC · ⌖ 7.93 AIC · ⊞ 19.4K
Comment /review to run again

@github-actions

github-actions Bot commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

🏗️ Design Decision Gate: ADR Required

This PR triggers ADR enforcement and no ADR was found. A draft ADR has been committed to your branch for review.

Why this PR was gated

Check Value Result
implementation label absent not triggered
New lines in business-logic dirs 130 (threshold: 100) triggered
Custom .design-gate.yml not present (defaults used) —

Business-logic changes land in pkg/linters/ — a new shared helper plus refactors across three analyzers.

ADR search results

Location Result
PR body No link to docs/adr/, no ADR section
PR branch (docs/adr/) Latest ADRs are 65165, 65257, 65263, 65362 — none for this PR
Linked issue (Fixes #65436) Not fetched; branch/body search was conclusive

Decision inferred from the diff

  • Decision: Centralize discarded-error detection in astutil.MatchDiscardedErrorCall(pass, assign) under pkg/linters/internal/astutil, and have strconvparseignorederror, globwalkignorederror, and jsonmarshalignoredeerror call it instead of re-implementing AST shape matching and types.PkgName resolution.
  • Driver: Three copies of imported-package resolution had drifted (aliased imports such as import conv "strconv" were handled inconsistently) — the root cause behind [duplicate-code] Discarded-Error Linter Scaffolding Duplicated Across strconv/glob/json Analyzers #65436.
  • Alternatives: (1) keep each analyzer self-contained; (2) collapse all three into one table-driven analyzer.
  • Consequences: single source of truth for matching, smaller analyzers; but a new shared chokepoint, and jsonmarshalignoredeerror still needs bespoke code for _ = json.Unmarshal(...).

Draft ADR committed

📄 docs/adr/65567-share-discarded-error-matching-helper.md — Status: Draft

Two items are marked [TODO: verify] and need your input:

  1. The diagnostic message now derives the package display name via path.Base(pkgPath) rather than the resolved types.PkgName. These differ for packages whose declared name ≠ last path segment. Confirm no entry in checkedFuncs is affected.
  2. go.mod (promoting go.yaml.in/yaml/v3 to direct), .github/workflows/agentic_commands.yml, and pkg/workflow/schemas/github-workflow.json all change here but appear unrelated to the refactor. Confirm whether they belong in this PR.

Next action

Review the draft ADR, resolve the two [TODO: verify] markers, correct anything the inference got wrong, and change Status from Draft to Proposed or Accepted. Merge is gated until the ADR is reviewed.

🏗️ ADR gate enforced by Design Decision Gate 🏗️ · pi · opus50 · 71.7 AIC · ⌖ 50.2 AIC · ⊞ 6.7K · ◷
Comment /review to run again

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI requested a review from pelikhan October 4, 2026 13:47

@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 /diagnosing-bugs and /codebase-design — requesting changes due to a confirmed test-breaking regression bundled into this PR.

📋 Key Themes & Highlights

Key Themes

  • Blocking regression: pkg/workflow/schemas/github-workflow.json drops the expressionSyntax alternative for concurrency.queue, but pkg/workflow/concurrency.go still emits the ${{ github.event_name == ... }} expression form for command-triggered workflows. Running go test ./pkg/workflow/... -run TestConcurrencyQueueSchemaValidation on this branch fails with 'oneOf' failed, none matched. This file is unrelated to the PR's stated goal (sharing discarded-error AST matching across analyzers) and looks like an accidental revert swept in with the change.
  • Minor readability nit: astutil.MatchDiscardedErrorCall (and the mirrored code in jsonmarshalignoredeerror.go) replaces simple Lhs[1]/Rhs[0] indexing with manual for-loops to extract a single already-bounds-checked element, adding noise without benefit.

Positive Highlights

  • ✅ The new astutil.MatchDiscardedErrorCall / PackageCall helpers are a clean extraction — all three analyzers (globwalkignorederror, strconvparseignorederror, jsonmarshalignoredeerror) now share one well-tested matcher instead of duplicating package-resolution logic.
  • ✅ astutil_test.go adds solid coverage for the shared helper: aliased imports, named-error assignments, and method-call false positives are all exercised.
  • ✅ go.mod cleanup correctly promotes go.yaml.in/yaml/v3 to a direct dependency now that it's imported directly in test code.

Please drop the unrelated github-workflow.json schema tightening (or update concurrency.go to match it) so TestConcurrencyQueueSchemaValidation passes again, then this is good to merge.

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

"$ref": "#/definitions/expressionSyntax"
}
],
"type": "string",

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.

[/diagnosing-bugs] This removes the expressionSyntax alternative for concurrency.queue, but pkg/workflow/concurrency.go:43 still emits queue: ${{ github.event_name == 'pull_request' && 'single' || 'max' }} for command-triggered workflows. Compiling any such workflow now fails GitHub Actions schema validation with 'oneOf' failed, none matched.

💡 Repro

Running go test ./pkg/workflow/... -run TestConcurrencyQueueSchemaValidation -v on this branch fails with:

GitHub Actions schema validation failed ... 'oneOf' failed, none matched
  - at '/concurrency': got object, want string
  - at '/concurrency/queue': value must be one of 'single', 'max'

This looks unrelated to the PR's stated goal (sharing discarded-error matching across analyzers) — it appears to be an accidental revert bundled into this change. Please restore the oneOf with the expressionSyntax $ref, or confirm concurrency.go is being changed to stop emitting the expression form.

@copilot please address this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Restored the expressionSyntax alternative for concurrency.queue in commit 1af0c55; TestConcurrencyQueueSchemaValidation passes. The latest main merge also contains this schema fix.

func MatchDiscardedErrorCall(pass *analysis.Pass, assign *ast.AssignStmt) (call *ast.CallExpr, pkgPath, funcName string, ok bool) {
if pass == nil || pass.TypesInfo == nil || assign == nil || len(assign.Lhs) != 2 || len(assign.Rhs) != 1 {
return nil, "", "", false
}

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.

[/codebase-design] assign.Lhs[1] and assign.Rhs[0] are replaced with manual for-loops just to grab a single known-index element — this obscures intent versus the original direct indexing (lengths are already checked just above). Same pattern repeats in jsonmarshalignoredeerror.go's checkDiscardedJSONAssign.

💡 Suggestion
secondLHS := assign.Lhs[1]
blank, ok := secondLHS.(*ast.Ident)
...
rhs := assign.Rhs[0]
call, ok = rhs.(*ast.CallExpr)

The bounds are already guarded by the len(...) check on the previous line, so direct indexing is safe and much easier to read than a loop with a break.

@copilot please address this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I kept the guarded loops here for the same reason: direct slice indexing is flagged by the repository's uncheckedsliceindex custom analyzer. The existing guarded iteration retains the required safety behavior.

@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.

Reviewed with a correctness/maintainability focus (Impeccable modes distill/extract don't directly apply to this Go-only refactor).

Core refactor (astutil.go, the three analyzers, tests): Clean. MatchDiscardedErrorCall/PackageCall correctly centralize the shared logic, alias handling is preserved, and the verbose for ... { if index == N { ...; break } } pattern (instead of direct slice indexing) is necessary — I built and ran this repo's own uncheckedsliceindex custom analyzer against the new code and confirmed direct indexing (e.g. assign.Lhs[1]) would trigger it, while the loop form does not. go build ./... and the affected package tests all pass.

Pre-existing unresolved threads I independently verified as still valid and blocking:

  • pkg/workflow/schemas/github-workflow.json: removing the expressionSyntax oneOf branch for concurrency.queue is a real regression. I reproduced it with a schema-validation unit test against the exact string concurrency.go emits for command/PR workflows (queue: ${{ github.event_name == 'pull_request' && 'single' || 'max' }}) and it now fails validation ('oneOf' failed, none matched).
  • go.mod: moving go.yaml.in/yaml/v3 from indirect to direct require looks unrelated to this PR's stated scope (discarded-error matching); worth confirming it's intentional/needed.
  • agentic_commands.yml: the diff drops routing for workflows unrelated to this change (/review, /matt, /smoke-codex, etc.) — likely a stale/regenerated lock artifact rather than an intended change.

No new inline comments added since these are already called out in open review threads. Requesting changes until the schema regression (and ideally the unrelated workflow/go.mod diffs) are resolved.

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · copilot · sonnet50 · 109.7 AIC · ⌖ 13.1 AIC · ⊞ 8.1K

@pelikhan

pelikhan commented Oct 4, 2026

Copy link
Copy Markdown
Collaborator

@copilot resolve the merge conflicts on this branch.

Copilot AI and others added 2 commits October 4, 2026 16:45
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
…e-fix

# Conflicts:
#	pkg/workflow/concurrency_command_test.go

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>

Copilot AI commented Oct 4, 2026

Copy link
Copy Markdown
Contributor Author

@copilot resolve the merge conflicts on this branch.

Merged the latest main and resolved the YAML import conflict in the concurrency test; the merge commit is 1b238ae.

@pelikhan

pelikhan commented Oct 4, 2026

Copy link
Copy Markdown
Collaborator

@copilot run pr-finisher skill

Copilot AI and others added 3 commits October 4, 2026 17:08
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
…e-fix

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>

Copilot AI commented Oct 4, 2026

Copy link
Copy Markdown
Contributor Author

@copilot run pr-finisher skill

Ran the PR finisher: restored queue-schema expression support, merged the latest main, and validated formatting, lint, and impacted tests. The PR remains blocked; review threads still need resolution, the pre-push gate reports unrelated pre-existing custom-linter findings, and CI must be re-triggered by a maintainer.

@pelikhan
pelikhan merged commit cd9a3ed into main Oct 4, 2026
2 checks passed
@pelikhan
pelikhan deleted the copilot/duplicate-code-fix branch October 4, 2026 18:56
@github-actions

github-actions Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

🎉 This pull request is included in a new release.

Release: v0.91.0

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.

[duplicate-code] Discarded-Error Linter Scaffolding Duplicated Across strconv/glob/json Analyzers

3 participants