Skip to content

[refactor] Semantic function clustering: no problematic duplication; one naming-collision cleanup #44137

Description

@github-actions

🔧 Semantic Function Clustering Analysis

Repository: github/gh-aw · analyzed all non-test .go files under pkg/ · 2026-07-08

Overview

I inventoried every top-level function and method across pkg/ and clustered them by name/purpose to find duplicates and misplaced ("outlier") functions. Headline: the codebase is already well-factored. The naive "same function name in multiple files" signal is almost entirely false positives — the repeated names are intentional cross-package delegation shims into shared util packages, not copy-pasted logic. Each candidate below was verified by reading the actual function bodies.

The one genuinely actionable semantic finding is a small set of same-name / different-semantics unexported helpers across pkg/parser and pkg/workflow that invite confusion. Large-file / long-function splits are intentionally out of scope here because they are already tracked by the existing [file-diet] and [lint-monster] backlog issues.

Key metrics

Metric Value
Non-test .go files (pkg/) ~1026
Functions + methods cataloged ~6,494
Top-level package dirs 30
Cross-file same-name groups (raw) dominated by framework/build-tag noise
Verified problematic body duplicates 0
Actionable naming collisions 2

Function concentration: pkg/workflow (2808 funcs / 419 files) + pkg/cli (1919 / 332) hold ~73% of all functions.

Why the duplicate signals are false positives (verified)

Every "duplicate" flagged by name-matching turned out to be a deliberate thin wrapper that forwards to a single shared implementation:

Name Site A Site B Reality
SanitizeName pkg/workflow/strings.go:97 pkg/stringutil/sanitize.go:76 workflow delegates → stringutil.SanitizeName
GetVersion pkg/cli/version.go:11 pkg/workflow/version.go:34 cli delegates → workflow.GetVersion
FindClosestMatches pkg/parser/schema_suggestions.go:231 pkg/stringutil/fuzzy_match.go:19 parser delegates → stringutil.FindClosestMatches
compileSchema pkg/parser/schema_compiler.go:148 pkg/workflow/schema_utils.go:13 both delegate → parser.CompileSchema
Additional noise classes excluded (build-tag twins, framework, fixtures)
  • _wasm.go build-tag twins: many exported names (FormatErrorMessage, RunGH, RenderTable, ExecGH, IsStderrTerminal, the Format*/Render* set, stderrWriter) are a foo.go + foo_wasm.go pair in the same package under different build constraints. Deduping these would break the wasm build.
  • Framework conventions: run(pass *analysis.Pass) appears in ~42 pkg/linters/* analyzers (go/analysis convention); init, New constructors.
  • pkg/linters/*/testdata/ fixtures: bad, good, doWork, suppressed, etc. are lint test inputs, not product code.

Because Go rejects two receiverless funcs with the same name in one package at compile time, there are no accidental same-package duplicates by construction.

The one actionable finding: same-name / different-semantics helpers

These unexported helpers share a name across pkg/parser and pkg/workflow but do different things with different signatures. They are not duplicates and not bugs — but grepping/navigating for them is misleading, and a future reader may assume they are interchangeable.

1. extractToolsFromFrontmatter

  • pkg/parser/content_extractor.go:60func(frontmatter map[string]any) (string, error) — merges tools and mcp-servers into a JSON string.
  • pkg/workflow/frontmatter_extraction_metadata.go:305func(frontmatter map[string]any) map[string]any — returns only the tools field via ExtractMapField.
  • Recommendation: rename the workflow one to extractToolsMapFromFrontmatter (it sits beside extractMCPServersFromFrontmatter/extractRuntimesFromFrontmatter, so a ...Map suffix reads naturally), or the parser one to extractToolsAndMCPJSON.

2. resolveImportInputPath

  • pkg/parser/import_input_substitution.go:47 → returns (string, bool) (formats resolved value to string).
  • pkg/workflow/expression_extraction.go:537 → returns (any, bool) (returns the raw resolved value).
  • Recommendation: rename the workflow variant to resolveImportInputValue for parity with the parser helper of the same name/behavior (parser.resolveImportInputValue already returns any).
Also-collides but lower value: hasCopilotRequestsWritePermission
  • pkg/cli/workflow_secrets.go:120func(frontmatter map[string]any) bool
  • pkg/workflow/permissions_operations.go:62func(workflowData *WorkflowData) bool

Different input types (raw frontmatter vs parsed WorkflowData), same intent. Acceptable as-is; consider aligning names only if these two ever need to agree on semantics.

Clustering / organization health

  • Utility layering is good: shared logic lives in dedicated packages (stringutil, fileutil, gitutil, typeutil, envutil, semverutil, importinpututil, ...) and the big packages call into them via the shims above. This is the desired end-state of a de-duplication effort — no action needed.
  • Files are feature-named (create_issue.go, create_pull_request.go, add_comment.go, codemod_*.go, compile_*.go), so the create*/codemod*/compile* clusters are correctly one-file-per-feature. ✓
  • Scattered helper families (build*/validate*/extract*/parse* span 40–64 files each in pkg/workflow and pkg/cli). This is expected spread for two 300–400-file feature packages and does not by itself indicate duplication. No consolidation recommended without body-level evidence, which I did not find.

Deliberately out of scope

Large files / long functions (e.g. pkg/cli/token_usage.go ~1128 LOC, pkg/workflow/compiler_activation_job_builder.go ~1110 LOC, pkg/cli/add_package_manifest.go ~984 LOC, pkg/cli/audit.go ~933 LOC) are already covered by the open [file-diet] and [lint-monster] function-length backlog issues. Not re-filed here to avoid duplication.

Next actions

  • Rename workflow.extractToolsFromFrontmatterextractToolsMapFromFrontmatter (or parser side → extractToolsAndMCPJSON).
  • Rename workflow.resolveImportInputPathresolveImportInputValue for parity with the parser helper.
  • (Optional) Align naming of the two hasCopilotRequestsWritePermission helpers only if their semantics ever need to converge.
  • No de-duplication work required — the cross-package "duplicates" are intentional delegation shims; do not collapse them.

Analysis metadata

  • Method: full function inventory via AST-line extraction → name/receiver clustering → manual body verification of every duplicate candidate (delegation shims ruled out by reading source).
  • Files analyzed: all non-test .go under pkg/.
  • Verified problematic duplicates: 0 · Naming collisions: 2 actionable + 1 optional.

Generated by 🔧 Semantic Function Refactoring · 487.7 AIC · ⌖ 15.2 AIC · ⊞ 9.1K ·

  • expires on Jul 9, 2026, 4:20 PM UTC-08:00

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions