Skip to content

[refactor] Semantic function clustering: drifting wasm duplicates in pkg/parser + scattered helpers #45023

Description

@github-actions

🔧 Semantic Function Clustering Analysis

Repository: github/gh-aw · non-test .go files under pkg/ · analysis date 2026-07-12

Executive summary

Analyzed 1,057 non-test Go files (~5,141 free functions) across pkg/. The good news dominates: the codebase already follows a strong one-file-per-feature convention (e.g. codemod_*.go, logs_*.go, compile_*.go, outcome_eval_*.go), so there are almost no "function in the wrong file" outliers, and every same-name collision within a package is a deliberate //go:build platform pair, not accidental duplication.

Two actionable items surfaced after semantic verification:

# Finding Severity Where
1 Pure path/string helpers duplicated & drifting between the wasm and non-wasm builds Medium (correctness risk) pkg/parser/remote_fetch_wasm.go
2 Scattered render* / build* / format* / normalize* helpers with no home file Low (organization) pkg/cli, pkg/workflow

Detection method: ripgrep-based function inventory + name clustering, then Serena/manual read-verification of candidate pairs.


Finding 1 — Drifting duplicate helpers across build tags (actionable)

pkg/parser splits platform code into remote_resolve_path.go (//go:build !js && !wasm) and remote_fetch_wasm.go (//go:build js || wasm). Several helpers in the wasm file are pure path/string logic with no platform-specific reason to differ, yet they are hand-reimplemented — and have already drifted:

  • isUnderWorkflowsDirectory — canonical remote_resolve_path.go:14 uses constants.WorkflowsDirSlash; wasm copy remote_fetch_wasm.go:11 hardcodes the literal ".github/workflows/".
  • isCustomAgentFile — canonical uses constants.AgentsDir; wasm copy remote_fetch_wasm.go:23 hardcodes ".github/agents/".
  • isRepositoryImport — canonical uses strings.Cut; wasm copy remote_fetch_wasm.go:28 uses the older strings.Index slicing form.
  • IsWorkflowSpecremote_workflow_spec.go:14 vs remote_fetch_wasm.go:124; same intent, minor variation.

Why this matters: these are not stubs. If the .github/workflows/ path constant ever changes, the wasm build silently keeps the old value → divergent behavior only on the wasm target, which is exactly the case tests miss most easily.

Recommendation: move the platform-independent helpers into a build-tag-neutral file (e.g. pkg/parser/remote_path.go with no //go:build constraint) and delete both copies. Keep only the genuinely platform-specific functions build-tagged (ResolveIncludePath, remote-fetch I/O). This removes ~4 duplicated functions and the drift class entirely.

Confirmed distinct — do NOT merge (legitimate platform stubs)

These same-name pairs are correct as-is; listed so a mechanical "dedupe by name" pass doesn't collapse them:

  • pkg/workflow: RunGH/ExecGH/... (github_cli.go real vs github_cli_wasm.go → returns "gh CLI not available in Wasm"), findGitRoot (git_helpers_wasm.go"."), isDockerDaemonRunning (docker_validation_wasm.gofalse).
  • pkg/colorwriter: New/Stderr (real writer vs wasm passthrough).
  • pkg/tty: IsStdoutTerminal/IsStderrTerminal.
  • pkg/console: the Format*/Render* family (console.go vs console_wasm.go) — wasm twin intentionally strips TTY styling + logging. Could optionally share a style-free core, but the split is defensible; lower priority than Finding 1.

Finding 2 — Scattered helpers with no home file (organization)

The repo already models the desired pattern in pkg/workflow (parse_helpers.go, validation_helpers.go). Several helper families have grown without an equivalent home:

Helper-prefix scatter (free functions, ≥8 occurrences, no dedicated file)

pkg/cli — has only a generic helpers.go; no topic helper files:

Prefix occurrences files spread home file?
render* 95 25 none
build* 89 49 none
parse* 64 46 none
format* 33 20 none
normalize* 19 18 none

pkg/workflowparse*/validate* already have homes; these do not:

Prefix occurrences files spread home file?
format* 29 22 none
normalize* 28 25 none
render* 20 13 none

Recommendation (low priority, incremental): when touching these areas, consolidate obvious cross-file helpers into format_helpers.go / render_helpers.go / normalize_helpers.go, mirroring the existing parse_helpers.go convention. This is discoverability-driven, not a duplication bug — do it opportunistically, not as a big-bang move.


What was checked and found clean

  • Outliers (functions in the wrong file): none material. The *_command.go / feature-name file convention is followed consistently across pkg/cli and pkg/workflow.
  • Accidental in-package name collisions: zero — all 53 same-name groups are //go:build platform pairs.
  • Cross-package "same purpose" duplication: dedicated *util packages (stringutil, fileutil, sliceutil, setutil, ...) already centralize generic helpers.

Suggested next actions

  • Priority 1: hoist isUnderWorkflowsDirectory, isCustomAgentFile, isRepositoryImport (and IsWorkflowSpec if identical) into a build-tag-neutral pkg/parser/remote_path.go; delete the drifted wasm copies. Est. ~1–2h; removes a latent wasm-only correctness bug.
  • Priority 2 (opportunistic): introduce format_helpers.go / render_helpers.go in pkg/cli and pkg/workflow as those areas are touched.

Analysis metadata

  • Non-test Go files analyzed: 1,057 · free functions cataloged: ~5,141
  • Same-name groups: 53 (all build-tag pairs) · confirmed actionable duplicates: ~4 (pkg/parser wasm)
  • Method: ripgrep function inventory + name clustering + read-verification of candidate pairs

Generated by 🔧 Semantic Function Refactoring · 745.7 AIC · ⌖ 15 AIC · ⊞ 9.1K ·

  • expires on Jul 13, 2026, 4:25 PM UTC-08:00

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions