π§ Semantic Function Clustering Analysis
Analysis of repository: github/gh-aw β non-test .go files in pkg/workflow, pkg/cli, pkg/parser (plus pkg/stringutil, pkg/console).
Executive summary
I clustered ~5,347 function declarations across 833 non-test Go files by name and purpose, then hunted for duplicate names, functional duplicates, scattered helpers, and file outliers using semantic + naming analysis.
Headline: the codebase is already well-factored. Almost every apparent duplicate turned out to be an intentional pattern (build-tag _wasm.go variants, or thin re-export wrappers over centralized stringutil/timeutil/fileutil helpers). Only one genuine, actionable duplication survived verification. Reporting it plus the false-positive patterns so future runs don't re-flag them.
β
Finding 1 (actionable): copilot-requests: write check is implemented 3 times
The logic "does this workflow grant copilot-requests: write?" β i.e. permissions.Get(PermissionCopilotRequests) == PermissionWrite β is duplicated across three sites with three different input shapes:
| # |
Location |
Signature / input |
| 1 |
pkg/workflow/permissions_operations.go:62 |
hasCopilotRequestsWritePermission(workflowData *WorkflowData) bool |
| 2 |
pkg/cli/workflow_secrets.go:120 |
hasCopilotRequestsWritePermission(frontmatter map[string]any) bool |
| 3 |
pkg/workflow/permissions_compiler_validator.go:221 |
inline workflowPermissions.Get(PermissionCopilotRequests) + PermissionWrite compare |
Each independently does: obtain a *Permissions, then Get(PermissionCopilotRequests) and compare to PermissionWrite.
Side-by-side of the two named functions
// pkg/workflow/permissions_operations.go:62
func hasCopilotRequestsWritePermission(workflowData *WorkflowData) bool {
if workflowData == nil { return false }
perms := workflowData.CachedPermissions
if perms == nil {
perms = NewPermissionsParser(workflowData.Permissions).ToPermissions()
}
if perms == nil { return false }
level, ok := perms.Get(PermissionCopilotRequests)
return ok && level == PermissionWrite
}
// pkg/cli/workflow_secrets.go:120
func hasCopilotRequestsWritePermission(frontmatter map[string]any) bool {
if frontmatter == nil { return false }
permissionsValue, ok := frontmatter["permissions"]
if !ok { return false }
perms := workflow.NewPermissionsParserFromValue(permissionsValue).ToPermissions()
level, exists := perms.Get(workflow.PermissionCopilotRequests)
return exists && level == workflow.PermissionWrite
}
Recommendation: add one exported method on the already-shared *Permissions type and have all three sites route through it:
// pkg/workflow/permissions_operations.go (or permissions.go)
func (p *Permissions) HasCopilotRequestsWrite() bool {
if p == nil { return false }
level, ok := p.Get(PermissionCopilotRequests)
return ok && level == PermissionWrite
}
Then each caller only differs in how it produces *Permissions (WorkflowData vs. NewPermissionsParserFromValue(frontmatter["permissions"])), and the comparison logic lives in one place. Low risk β the parsing helpers (NewPermissionsParser, NewPermissionsParserFromValue) and constants (PermissionCopilotRequests, PermissionWrite) are already exported and used at all three sites.
Impact: single source of truth for a security-relevant permission gate; eliminates the risk of the three copies drifting.
iοΈ Patterns that look like duplicates but are intentional (do NOT refactor)
So future automated passes don't re-flag these:
- Build-tag
_wasm.go variants β validateDockerImage, isDockerDaemonRunning, markDockerDaemonUnavailable, setupGHCommand, getDefaultGHHost, findGitRoot, isTTY, isUnderWorkflowsDirectory, isCustomAgentFile, isRepositoryImport. Each has a *_wasm.go stub paired with a real implementation gated by build constraints. Correct and required.
- Thin re-export wrappers over centralized helpers β
workflow.SanitizeName β stringutil.SanitizeName; workflow.compileSchema / parser.compileSchema β parser.CompileSchema. These are deliberate package-local aliases (often with type X = pkg.X) to preserve call sites while keeping one implementation. Good practice, already consolidated.
β
Positive organization notes
- Feature-per-file is followed well:
codemod_*.go, audit_*.go, forecast_*.go, gateway_logs_*.go, compile_*.go, add_interactive_*.go families each isolate one concern.
- Generic string/time/file utilities are already centralized in
pkg/stringutil, pkg/timeutil, pkg/fileutil rather than scattered.
- No exact-duplicate plain functions found within a single package (beyond the intentional patterns above).
Analysis metadata
- Files analyzed: 833 non-test
.go files (pkg/workflow 437, pkg/cli 345, pkg/parser 51)
- Function declarations cataloged: ~5,347
- Genuine actionable duplicate found: 1 (copilot-requests permission check)
- False-positive duplicate patterns identified: build-tag variants, thin re-export wrappers
- Method: naming-pattern clustering + cross-package same-name detection + manual verification of every candidate
- Note: semantic-analysis code execution was restricted in this environment, so clustering was done via pattern search over function declarations plus targeted reads of each candidate; findings below were all read-verified.
Implementation checklist
Generated by π§ Semantic Function Refactoring Β· 180 AIC Β· β 15 AIC Β· β 9.1K Β· β·
π§ Semantic Function Clustering Analysis
Analysis of repository:
github/gh-awβ non-test.gofiles inpkg/workflow,pkg/cli,pkg/parser(pluspkg/stringutil,pkg/console).Executive summary
I clustered ~5,347 function declarations across 833 non-test Go files by name and purpose, then hunted for duplicate names, functional duplicates, scattered helpers, and file outliers using semantic + naming analysis.
Headline: the codebase is already well-factored. Almost every apparent duplicate turned out to be an intentional pattern (build-tag
_wasm.govariants, or thin re-export wrappers over centralizedstringutil/timeutil/fileutilhelpers). Only one genuine, actionable duplication survived verification. Reporting it plus the false-positive patterns so future runs don't re-flag them.β Finding 1 (actionable):
copilot-requests: writecheck is implemented 3 timesThe logic "does this workflow grant
copilot-requests: write?" β i.e.permissions.Get(PermissionCopilotRequests) == PermissionWriteβ is duplicated across three sites with three different input shapes:pkg/workflow/permissions_operations.go:62hasCopilotRequestsWritePermission(workflowData *WorkflowData) boolpkg/cli/workflow_secrets.go:120hasCopilotRequestsWritePermission(frontmatter map[string]any) boolpkg/workflow/permissions_compiler_validator.go:221workflowPermissions.Get(PermissionCopilotRequests)+PermissionWritecompareEach independently does: obtain a
*Permissions, thenGet(PermissionCopilotRequests)and compare toPermissionWrite.Side-by-side of the two named functions
Recommendation: add one exported method on the already-shared
*Permissionstype and have all three sites route through it:Then each caller only differs in how it produces
*Permissions(WorkflowDatavs.NewPermissionsParserFromValue(frontmatter["permissions"])), and the comparison logic lives in one place. Low risk β the parsing helpers (NewPermissionsParser,NewPermissionsParserFromValue) and constants (PermissionCopilotRequests,PermissionWrite) are already exported and used at all three sites.Impact: single source of truth for a security-relevant permission gate; eliminates the risk of the three copies drifting.
iοΈ Patterns that look like duplicates but are intentional (do NOT refactor)
So future automated passes don't re-flag these:
_wasm.govariants βvalidateDockerImage,isDockerDaemonRunning,markDockerDaemonUnavailable,setupGHCommand,getDefaultGHHost,findGitRoot,isTTY,isUnderWorkflowsDirectory,isCustomAgentFile,isRepositoryImport. Each has a*_wasm.gostub paired with a real implementation gated by build constraints. Correct and required.workflow.SanitizeNameβstringutil.SanitizeName;workflow.compileSchema/parser.compileSchemaβparser.CompileSchema. These are deliberate package-local aliases (often withtype X = pkg.X) to preserve call sites while keeping one implementation. Good practice, already consolidated.β Positive organization notes
codemod_*.go,audit_*.go,forecast_*.go,gateway_logs_*.go,compile_*.go,add_interactive_*.gofamilies each isolate one concern.pkg/stringutil,pkg/timeutil,pkg/fileutilrather than scattered.Analysis metadata
.gofiles (pkg/workflow437,pkg/cli345,pkg/parser51)Implementation checklist
(*Permissions).HasCopilotRequestsWrite()helper inpkg/workflowpkg/workflow/permissions_operations.go:62through itpkg/workflow/permissions_compiler_validator.go:221through itpkg/cli/workflow_secrets.go:120through it