Skip to content

[refactor] Semantic Function Clustering Analysis: pkg/cli Refactoring Opportunities #29844

@github-actions

Description

@github-actions

Overview

This report analyzes 750 non-test Go source files across 23 packages in pkg/. The vast majority of packages are well-organized with clear single-purpose files. The primary refactoring opportunities are concentrated in the large pkg/cli package (~500+ files), where several patterns of scattered utilities and outlier functions were identified.

Analysis scope: 750 Go files, 23 packages
Significant findings: 4 medium-impact opportunities in pkg/cli
Critical issues: None — no duplicate implementations found


Finding 1: Format Utility Functions Scattered Across Audit Files

Severity: Medium

Thirteen+ small format* functions are spread across 10+ files in pkg/cli. The most actionable cluster is in the audit_* domain:

  • pkg/cli/audit_math_helpers.go:14formatPercent(pct float64) string (2-function file)
  • pkg/cli/audit_math_helpers.go:6safePercent(part, total int) float64
  • pkg/cli/audit_diff.go:219formatVolumeChange(total1, total2 int) string
  • pkg/cli/audit_diff.go:944formatPercentagePointChange(ratio1, ratio2 float64) string
  • pkg/cli/audit_diff.go:953formatCountChange(count1, count2 int) string
  • pkg/cli/audit_agentic_analysis.go:521formatAssessmentDuration(duration time.Duration) string
  • pkg/cli/audit_report_render_firewall.go:130formatUnixTimestamp(ts float64) string

audit_math_helpers.go was presumably created to centralize math helpers, but the 3 format functions in audit_diff.go were not moved there.

Recommendation: Move formatVolumeChange, formatPercentagePointChange, formatCountChange into audit_math_helpers.go. Optionally also move formatAssessmentDuration and formatUnixTimestamp there to create a single audit formatting utilities file.

Estimated effort: 1 hour


Finding 2: Non-Compilation Logic in compile_batch_operations.go

Severity: Medium

pkg/cli/compile_batch_operations.go is named for batch compilation operations but contains two unrelated concerns:

External tool runners (workflow analysis tools — not compilation):

  • RunActionlintOnFiles(lockFiles []string, verbose bool, strict bool) error (line 42)
  • RunZizmorOnFiles(lockFiles []string, verbose bool, strict bool) error (line 48)
  • RunPoutineOnDirectory(workflowDir string, verbose bool, strict bool) error (line 54)
  • RunRunnerGuardOnDirectory(workflowDir string, verbose bool, strict bool) error (line 60)
  • runBatchLockFileTool(...) (line 65) — internal dispatcher
  • runBatchDirectoryTool(...) (line 87) — internal dispatcher

File cleanup/purge (lifecycle management — not compilation):

  • purgeOrphanedLockFiles(workflowsDir string, expectedLockFiles []string, verbose bool) error (line 105)
  • purgeInvalidFiles(workflowsDir string, verbose bool) error (line 161)

Similarly, pkg/cli/compile_pipeline.go contains display and cache management outliers:

  • displayScheduleWarnings(compiler *workflow.Compiler, jsonOutput bool) (line 431) — output logic
  • displaySafeUpdateWarnings(compiler *workflow.Compiler, jsonOutput bool) (line 444) — output logic
  • pruneStaleActionCacheEntries(compiler *workflow.Compiler, actionCache *workflow.ActionCache) (line 545) — cache lifecycle

Note: A compile_post_processing.go file already exists, suggesting the project was moving in this direction.

Recommendation:

  • Move RunActionlintOnFiles, RunZizmorOnFiles, RunPoutineOnDirectory, RunRunnerGuardOnDirectory and helpers to compile_external_tools.go (new file)
  • Move purgeOrphanedLockFiles, purgeInvalidFiles to a new compile_cleanup.go or into compile_post_processing.go
  • Move displayScheduleWarnings, displaySafeUpdateWarnings, pruneStaleActionCacheEntries from compile_pipeline.go to compile_post_processing.go

Estimated effort: 2–3 hours


Finding 3: File Discovery Functions Scattered Across logs_*.go Files

Severity: Medium

A logs_utils.go file exists for centralizing log utilities, but file/artifact discovery functions are spread across multiple files:

In logs_utils.go (the intended central location):

  • getAgenticWorkflowNames() — reads .lock.yml files

In logs_parsing_core.go (should be parsing-only):

  • findAgentOutputFile(logDir string) (string, bool) (line 117)
  • findAgentLogFile(logDir string, engine workflow.CodingAgentEngine) (string, bool) (line 149)

In logs_download.go (should be download-only):

  • findArtifactDir(outputDir, baseName string, legacyName string) string (line 119)
  • listArtifacts(outputDir string) ([]string, error) (line 444)
  • listRunArtifactNames(ctx context.Context, ...) ([]string, error) (line 500)

The find* and list* patterns in parsing and download files suggest these are general utilities that happen to be near their first use.

Recommendation: Move findAgentOutputFile, findAgentLogFile from logs_parsing_core.go to logs_utils.go. Consider whether findArtifactDir, listArtifacts, listRunArtifactNames belong in logs_utils.go as well (they are used in the download flow but are utility-style functions).

Estimated effort: 1–2 hours


Finding 4: Repository/Path Utilities Split Between Files

Severity: Low–Medium

Three files each contain a subset of repository and path utility functions:

pkg/cli/git.go — git-specific but includes URL/path helpers:

  • getHostFromOriginRemote() (line 190)
  • getRepositorySlugFromRemote() (line 205)
  • getRepositorySlugFromRemoteForPath(path string) (line 226)

pkg/cli/helpers.go — general helpers:

  • getParentDir(path string) string (line 14)

pkg/cli/compile_file_operations.go — compilation file ops:

  • getRepositoryRelativePath(absPath string) (string, error) (line 53)
  • getAbsoluteWorkflowDir(workflowDir string, gitRoot string) string (line 82)

The getRepositoryRelativePath and getAbsoluteWorkflowDir functions are path manipulation utilities that don't depend on compilation; they happen to first be used in compile_file_operations.go.

Recommendation: Move getRepositoryRelativePath, getAbsoluteWorkflowDir, and getParentDir to helpers.go or a dedicated path_utils.go. This co-locates the non-git path utilities, keeping compile_file_operations.go focused on compilation file I/O.

Estimated effort: 1–2 hours


Packages with Good Organization (No Action Needed)

View packages assessed as well-organized
Package Files Assessment
actionpins 1 Single cohesive module
agentdrain 11 Complex but well-organized by concern
console 35+ Multi-platform stubs are intentional, not duplicates
constants 5 Proper semantic type helpers
envutil 1 Focused, minimal
fileutil 2 Focused file operations
gitutil 1 Focused git utilities
logger 5 Well-organized debug logging
parser 80+ Very large but well-organized by feature domain
repoutil 1 Minimal, focused
semverutil 1 All version functions grouped
sliceutil 1 All generic slice operations grouped
stats 1 Statistical aggregation methods
stringutil 8 Functional separation by concern
styles 2 Styling constants
timeutil 2 Time formatting functions
tty 2 Platform-specific terminal detection
types Type definitions
typeutil 1 Type conversion functions
workflow 80+ Well-organized by feature domain

Implementation Checklist

  • Move formatVolumeChange, formatPercentagePointChange, formatCountChange into audit_math_helpers.go
  • Create compile_external_tools.go for external linting/analysis tool runners
  • Move purge functions to compile_post_processing.go or new compile_cleanup.go
  • Move displayScheduleWarnings, displaySafeUpdateWarnings, pruneStaleActionCacheEntries to compile_post_processing.go
  • Move findAgentOutputFile, findAgentLogFile from logs_parsing_core.go to logs_utils.go
  • Move path utility functions to helpers.go or a new path_utils.go
  • Run tests to verify no regressions after each move

Analysis Metadata

  • Total Go files analyzed: 750
  • Packages analyzed: 23
  • Function clusters identified: 6
  • Outlier functions found: ~15 (compile_*.go and compile_pipeline.go)
  • Duplicate implementations: 0 (no true duplicates detected)
  • Detection method: Naming pattern analysis + semantic clustering via bash grep + Serena LSP
  • Analysis date: 2026-05-02
  • Workflow run: §25265086761

Generated by Semantic Function Refactoring · ● 550.9K ·

  • expires on May 5, 2026, 12:04 AM UTC

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    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