Automated semantic analysis of 545 non-test Go files across 18 packages in pkg/. The overall codebase is well-structured, but a few concrete refactoring opportunities were identified.
Summary
- Total Go files analyzed: 545 (across
pkg/cli, pkg/workflow, and 16 utility packages)
- Function clusters identified: 12 major clusters (permissions, runtime, mcp_config, safe_outputs, compile, audit, codemods, etc.)
- Outliers found: 2 confirmed (stub files)
- Duplicates detected: 2 confirmed
- Mixed concerns: 1 confirmed
Identified Issues
1. Duplicate truncateSnippet() vs stringutil.Truncate()
Issue: A private truncateSnippet() function in pkg/workflow/markdown_security_scanner.go reimplements the same truncation logic already available in pkg/stringutil.
|
truncateSnippet |
stringutil.Truncate |
| File |
pkg/workflow/markdown_security_scanner.go:798 |
pkg/stringutil/stringutil.go:17 |
| Behavior |
strings.TrimSpace(s) then truncate with "..." |
Truncate with "...", respects maxLen ≤ 3 edge case |
| Used |
10+ call sites within the same file |
Throughout the codebase |
// markdown_security_scanner.go:798 — private duplicate
func truncateSnippet(s string, maxLen int) string {
s = strings.TrimSpace(s)
if len(s) <= maxLen { return s }
return s[:maxLen] + "..."
}
// stringutil/stringutil.go:17 — canonical implementation
func Truncate(s string, maxLen int) string {
if len(s) <= maxLen { return s }
if maxLen <= 3 { return s[:maxLen] }
return s[:maxLen-3] + "..."
}
Recommendation: Remove truncateSnippet and replace call sites with strings.TrimSpace inline + stringutil.Truncate(), or add a TrimAndTruncate variant to stringutil.
2. Overlapping normalizeWorkflowID() vs stringutil.NormalizeWorkflowName()
Issue: pkg/cli/commands.go defines a private normalizeWorkflowID() that largely overlaps with the already-public stringutil.NormalizeWorkflowName().
|
normalizeWorkflowID |
stringutil.NormalizeWorkflowName |
| File |
pkg/cli/commands.go:153 |
pkg/stringutil/identifiers.go:30 |
| Handles paths |
Yes (filepath.Base first) |
No (name only) |
Strips .lock.yml |
No |
Yes |
| Used at |
8 call sites across pkg/cli |
Throughout pkg/workflow |
// commands.go:153 — handles full paths but not .lock.yml
func normalizeWorkflowID(workflowIDOrPath string) string {
basename := filepath.Base(workflowIDOrPath)
return strings.TrimSuffix(basename, ".md")
}
// stringutil/identifiers.go:30 — handles .lock.yml but expects name only
func NormalizeWorkflowName(name string) string { ... }
Recommendation: Extend stringutil.NormalizeWorkflowName to optionally accept paths (calling filepath.Base internally), then replace normalizeWorkflowID across pkg/cli. Or document the distinction explicitly to avoid future confusion.
3. Empty stub files in pkg/workflow
Issue: Two files exist that contain only package declarations and legacy comments, indicating leftover scaffolding after migration.
pkg/workflow/compiler_safe_outputs_shared.go — 1 line (only package workflow)
pkg/workflow/compiler_safe_outputs_discussions.go — 6 lines (package declaration + comment explaining the file previously had content but it was removed)
// compiler_safe_outputs_discussions.go
package workflow
// This file previously contained discussion-related step config builders.
// Those functions have been removed as discussions are now handled by the
// safe output handler manager (safe_output_handler_manager.cjs).
// See pkg/workflow/compiler_safe_outputs_core.go for the new implementation.
Recommendation: Delete both empty files. The explanatory comment in compiler_safe_outputs_discussions.go can be moved to compiler_safe_outputs_core.go if the context is useful.
4. Mixed concerns in pkg/cli/commands.go
Issue: commands.go acts as a catch-all file containing three unrelated concerns:
| Concern |
Functions |
| Version management |
SetVersionInfo(), GetVersion() (lines 36–44) |
| Agent file download |
downloadAgentFileFromGitHub(), downloadAgentFileViaGHCLI(), patchAgentFileURLs(), isGHCLIAvailable() (lines 47–151) |
| Workflow file resolution |
normalizeWorkflowID(), resolveWorkflowFile(), resolveWorkflowFileInDir() (lines 153–228) |
| Workflow creation |
NewWorkflow(), createWorkflowTemplate() (lines 229–end) |
Recommendation: Split into purpose-focused files:
version.go ← version management functions
agent_download.go ← agent file download functions
- Move
resolveWorkflowFile* to workflows.go (which already contains getMarkdownWorkflowFiles())
Well-Organized Patterns (for reference)
The following areas were analyzed and found to be exemplary — no changes needed:
View well-organized patterns
permissions_*.go (5 files): Clean separation by types, factory, operations, parser, validator
runtime_*.go (6 files): Separated by definitions, detection, validation, overrides, step generation, deduplication
mcp_config_*.go (7 files): Types, utils, rendering by engine, and validation all separated
audit_report_*.go (3 files): Clean collect → analyze → render layering
compile_*.go (9 files in pkg/cli): Properly separated by config types, helpers, validation, stats, and batch operations
update_entity_helpers.go + close_entity_helpers.go: Excellent use of generics to unify similar entity parsers
codemod_yaml_utils.go: Legitimate shared utility serving all 53 codemod transformation files
validation_helpers.go, map_helpers.go, git_helpers.go: All appropriately scoped domain helpers
Implementation Checklist
Analysis Metadata
- Total Go files analyzed: 545
- Packages covered:
pkg/cli, pkg/workflow, pkg/stringutil, pkg/sliceutil, pkg/mathutil, pkg/fileutil, pkg/gitutil, pkg/timeutil, pkg/envutil, pkg/repoutil, pkg/types, pkg/constants
- Detection method: Serena LSP semantic analysis + naming pattern clustering + cross-package comparison
- Workflow run: §22825681455
References:
Generated by Semantic Function Refactoring · ◷
Automated semantic analysis of 545 non-test Go files across 18 packages in
pkg/. The overall codebase is well-structured, but a few concrete refactoring opportunities were identified.Summary
pkg/cli,pkg/workflow, and 16 utility packages)Identified Issues
1. Duplicate
truncateSnippet()vsstringutil.Truncate()Issue: A private
truncateSnippet()function inpkg/workflow/markdown_security_scanner.goreimplements the same truncation logic already available inpkg/stringutil.truncateSnippetstringutil.Truncatepkg/workflow/markdown_security_scanner.go:798pkg/stringutil/stringutil.go:17strings.TrimSpace(s)then truncate with"...""...", respectsmaxLen ≤ 3edge caseRecommendation: Remove
truncateSnippetand replace call sites withstrings.TrimSpaceinline +stringutil.Truncate(), or add aTrimAndTruncatevariant tostringutil.2. Overlapping
normalizeWorkflowID()vsstringutil.NormalizeWorkflowName()Issue:
pkg/cli/commands.godefines a privatenormalizeWorkflowID()that largely overlaps with the already-publicstringutil.NormalizeWorkflowName().normalizeWorkflowIDstringutil.NormalizeWorkflowNamepkg/cli/commands.go:153pkg/stringutil/identifiers.go:30filepath.Basefirst).lock.ymlpkg/clipkg/workflowRecommendation: Extend
stringutil.NormalizeWorkflowNameto optionally accept paths (callingfilepath.Baseinternally), then replacenormalizeWorkflowIDacrosspkg/cli. Or document the distinction explicitly to avoid future confusion.3. Empty stub files in
pkg/workflowIssue: Two files exist that contain only package declarations and legacy comments, indicating leftover scaffolding after migration.
pkg/workflow/compiler_safe_outputs_shared.go— 1 line (onlypackage workflow)pkg/workflow/compiler_safe_outputs_discussions.go— 6 lines (package declaration + comment explaining the file previously had content but it was removed)Recommendation: Delete both empty files. The explanatory comment in
compiler_safe_outputs_discussions.gocan be moved tocompiler_safe_outputs_core.goif the context is useful.4. Mixed concerns in
pkg/cli/commands.goIssue:
commands.goacts as a catch-all file containing three unrelated concerns:SetVersionInfo(),GetVersion()(lines 36–44)downloadAgentFileFromGitHub(),downloadAgentFileViaGHCLI(),patchAgentFileURLs(),isGHCLIAvailable()(lines 47–151)normalizeWorkflowID(),resolveWorkflowFile(),resolveWorkflowFileInDir()(lines 153–228)NewWorkflow(),createWorkflowTemplate()(lines 229–end)Recommendation: Split into purpose-focused files:
version.go← version management functionsagent_download.go← agent file download functionsresolveWorkflowFile*toworkflows.go(which already containsgetMarkdownWorkflowFiles())Well-Organized Patterns (for reference)
The following areas were analyzed and found to be exemplary — no changes needed:
View well-organized patterns
permissions_*.go(5 files): Clean separation by types, factory, operations, parser, validatorruntime_*.go(6 files): Separated by definitions, detection, validation, overrides, step generation, deduplicationmcp_config_*.go(7 files): Types, utils, rendering by engine, and validation all separatedaudit_report_*.go(3 files): Clean collect → analyze → render layeringcompile_*.go(9 files inpkg/cli): Properly separated by config types, helpers, validation, stats, and batch operationsupdate_entity_helpers.go+close_entity_helpers.go: Excellent use of generics to unify similar entity parserscodemod_yaml_utils.go: Legitimate shared utility serving all 53 codemod transformation filesvalidation_helpers.go,map_helpers.go,git_helpers.go: All appropriately scoped domain helpersImplementation Checklist
truncateSnippet()frompkg/workflow/markdown_security_scanner.go, replace usages withstrings.TrimSpace+stringutil.Truncate()normalizeWorkflowID()andstringutil.NormalizeWorkflowName()— either consolidate or document the distinctionpkg/workflow/compiler_safe_outputs_shared.goandpkg/workflow/compiler_safe_outputs_discussions.gopkg/cli/commands.gointo purpose-focused files (version.go,agent_download.go)Analysis Metadata
pkg/cli,pkg/workflow,pkg/stringutil,pkg/sliceutil,pkg/mathutil,pkg/fileutil,pkg/gitutil,pkg/timeutil,pkg/envutil,pkg/repoutil,pkg/types,pkg/constantsReferences: