Skip to content

[refactor] Semantic Function Clustering Analysis: Refactoring Opportunities in pkg/ #22294

@github-actions

Description

@github-actions

Overview

Semantic function clustering analysis was performed on all non-test Go files in pkg/ (597 files, 300 in pkg/workflow/, 206 in pkg/cli/, 40 in pkg/parser/, 25 in pkg/console/, and 26 across utility packages). The most significant new finding — introduced by the recent "Add per-handler staged mode to all safe output types" commit — is the discovery of two parallel safe-output config generation systems with diverging field coverage. Three previously-identified issues remain unresolved.


Critical Findings

1 dual-system architecture risk, 1 immediate staged field gap, 2 long-standing duplicate/misplaced function patterns, 1 oversized multi-concern file.


Issue 1: Two Parallel Safe-Output Config Generation Systems (New — High Priority)

Severity: High
Files:

  • pkg/workflow/safe_outputs_config_generation.go (664 lines) — OLD system
  • pkg/workflow/compiler_safe_outputs_config.go (929 lines) — NEW system

Two separate code paths generate safe-output handler configuration:

System Output Approach
generateSafeOutputsConfig() GH_AW_SAFE_OUTPUTS_CONFIG_PATH (config.json) Ad-hoc generateMax*Config() helpers
addHandlerManagerConfigEnvVar() GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG env var handlerRegistry + fluent handlerConfigBuilder

These must be kept in sync when adding new fields. In practice they are not in sync — the new system consistently includes fields that the old system omits.

Example — create_issue handler field comparison:

Old (generateSafeOutputsConfig):  allowed_labels, group, expires
New (handlerRegistry):            max, allowed_labels, allowed_repos, expires, labels,
                                  title_prefix, assignees, target-repo, group,
                                  close_older_issues, close_older_key, footer,
                                  github-token, staged

Recommendation: Evaluate whether config.json (old path) and GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG (new path) serve distinct runtime purposes. If they do, document the intended field contract for each. If the old path is superseded by the new one, deprecate generateSafeOutputsConfig() and safe_outputs_config_helpers.go together. Either way, add a comment in both files cross-referencing the other.


Issue 2: staged Flag Missing for Most Handlers in Old Config Path (New — Medium Priority)

Severity: Medium
File: pkg/workflow/safe_outputs_config_generation.go

The recent PR "Add per-handler staged mode to all safe output types" correctly updated:

  • compiler_safe_outputs_config.go — all 39 handlers include .AddIfTrue("staged", c.Staged)
  • safe_outputs_permissions.go — all handlers check isHandlerStaged(...) for permission computation ✅
  • safe_outputs_config.goparseBaseSafeOutputConfig parses the staged flag ✅

But safe_outputs_config_generation.go only emits staged: true for one handler:

// safe_outputs_config_generation.go:121-123
if data.SafeOutputs.ClosePullRequests.Staged {
    additionalFields["staged"] = true
}

All other handlers (create_issue, add_comment, close_issue, etc.) do not emit staged in the old config path. If this path is still consumed by runtime components that respect the staged field, this is a behavioral gap introduced in the recent PR.

Recommendation: Either add staged to all handlers in generateSafeOutputsConfig() (mirroring the handlerRegistry), or document explicitly that staged is only meaningful in GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG and the config.json path does not need it.


Issue 3: safeUintToInt Wrapper in Wrong File (Existing — Low Priority)

Severity: Low
Files:

  • pkg/workflow/map_helpers.go — defines safeUint64ToInt(u uint64) int
  • pkg/workflow/frontmatter_extraction_metadata.go:146 — defines thin wrapper safeUintToInt(u uint) int
// frontmatter_extraction_metadata.go:146
func safeUintToInt(u uint) int { return safeUint64ToInt(uint64(u)) }

This wrapper exists solely to adapt uint → uint64. All safe integer conversion utilities should be centralised in map_helpers.go.

Recommendation: Move safeUintToInt to map_helpers.go. Remove it from frontmatter_extraction_metadata.go. Estimated effort: < 1 hour.


Issue 4: Near-Duplicate Integer Parsing — parseIntValue vs ConvertToInt (Existing — Low Priority)

Severity: Low
File: pkg/workflow/map_helpers.go

// parseIntValue: handles int, int64, float64 — returns (value, ok)
func parseIntValue(value any) (int, bool)

// ConvertToInt: handles int, int64, float64, AND string — returns int (0 on failure)
func ConvertToInt(val any) int

ConvertToInt is a functional superset of parseIntValue with different error handling semantics. Both are used across the package with no documented guidance on which to prefer. The file header documents both as siblings.

Recommendation: Add a doc comment to each function clarifying the intended use case, or refactor ConvertToInt to delegate to parseIntValue for the numeric cases, adding only the string-parse path on top.


Issue 5: update_entity_helpers.go — Oversized Multi-Concern File (Existing — Low Priority)

Severity: Low
File: pkg/workflow/update_entity_helpers.go (543 lines, 8 functions)

This file contains update logic for issues, pull requests, discussions, and releases — four distinct entity domains — in violation of the "one file per feature" convention applied elsewhere (create_issue.go, create_pull_request.go, create_discussion.go).

Recommendation: Split into domain-specific files following the existing create-entity pattern:

  • update_issue_helpers.go
  • update_pull_request_helpers.go
  • update_discussion_helpers.go
  • update_release_helpers.go

Recommendations Summary

Priority Finding File(s) Effort
High Document/reconcile dual config generation systems safe_outputs_config_generation.go, compiler_safe_outputs_config.go 1–2 hours
Medium Add staged to all handlers in old config path, or document intentional omission safe_outputs_config_generation.go 1–2 hours
Low Move safeUintToInt to map_helpers.go map_helpers.go, frontmatter_extraction_metadata.go < 1 hour
Low Document/unify parseIntValue vs ConvertToInt map_helpers.go < 1 hour
Low Split update_entity_helpers.go by entity domain update_entity_helpers.go 2–3 hours

Implementation Checklist

  • Evaluate whether both config generation paths are needed or if one is superseded
  • Add cross-reference comments between safe_outputs_config_generation.go and compiler_safe_outputs_config.go
  • Resolve staged field gap in safe_outputs_config_generation.go (add to all or document omission)
  • Move safeUintToInt wrapper to map_helpers.go
  • Document or unify parseIntValue / ConvertToInt distinction
  • Split update_entity_helpers.go into per-entity files

Analysis Metadata

  • Total Go files analyzed: 597 (excluding *_test.go)
  • Packages covered: 18 (cli, workflow, parser, console, stringutil, fileutil, and 12 others)
  • Detection method: Naming pattern clustering, Serena LSP semantic analysis, git diff analysis of recent commits
  • Workflow run: §23408018753
  • Analysis date: 2026-03-22

References:

Generated by Semantic Function Refactoring ·

  • expires on Mar 24, 2026, 5:11 PM UTC

Metadata

Metadata

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