π§ Semantic Function Clustering Analysis
Analysis of github/gh-aw β scope: pkg/stringutil, pkg/styles (10 non-test .go files)
Executive Summary
Both packages are, overall, cleanly feature-organized. Scope covered 10 files / ~35 functions. No exact duplicates and no misplaced cross-domain functions (e.g. no parser logic in a network file) were found. Two low/medium-impact organizational opportunities surfaced and are detailed below. Everything else clusters correctly and is left as-is.
Function Inventory
By file / cluster
pkg/stringutil
ansi.go β StripANSI, skipEscapeSequence, skipCSISequence, skipOSCSequence, isFinalCSIChar, isCSIParameterChar (cohesive ANSI cluster)
fuzzy_match.go β FindClosestMatches, LevenshteinDistance (cohesive)
identifiers.go β NormalizeWorkflowName, NormalizeSafeOutputIdentifier, MarkdownToLockFile, LockFileToMarkdown (cohesive)
pat_validation.go β PATType + methods, ClassifyPAT, ValidateCopilotPAT, GetPATTypeDescription (cohesive)
sanitize.go β SanitizeName, SanitizeErrorMessage, SanitizeIdentifierName, SanitizeParameterName, SanitizePythonVariableName, SanitizeToolID, SanitizeForFilename + helpers
urls.go β NormalizeGitHubHostURL, ExtractDomainFromURL, extractDomainFallback (cohesive)
stringutil.go β Truncate, NormalizeWhitespace, ParseVersionValue, FormatList, NormalizeLeadingWhitespace, IsPositiveInteger (grab-bag)
pkg/styles
theme.go / theme_wasm.go β build-tag pair (real vs Wasm no-op); intentional pattern
huh_theme.go β huh form theme mapping; correctly shares the color* palette vars with theme.go
Identified Issues
1. stringutil.go is a catch-all file (medium)
- File:
pkg/stringutil/stringutil.go
- Issue: Unlike its six siblings (each named after one feature), this file bundles unrelated concerns: whitespace normalization (
NormalizeWhitespace, NormalizeLeadingWhitespace), truncation (Truncate), version stringifying (ParseVersionValue), list formatting (FormatList), and integer validation (IsPositiveInteger). This breaks the package's own one-file-per-feature convention.
- Recommendation: Extract the two whitespace functions into
whitespace.go (they form a clear cluster). The remaining small, genuinely-generic helpers (Truncate, FormatList, ParseVersionValue, IsPositiveInteger) can stay in stringutil.go as the residual utility file. No signature or behavior changes β pure file moves.
- Impact: Better discoverability; brings this file in line with the rest of the package. Low risk (same package, no API change).
2. Two parallel rune-mapping sanitizers (low)
- Occurrence 1:
sanitize.go:223 SanitizeIdentifierName(name, extraAllowed) β strings.Map, allows [A-Za-z0-9_] + extraAllowed, replaces disallowed with _, prepends _ if leading digit.
- Occurrence 2:
sanitize.go:325 SanitizeForFilename(slug) β strings.Builder loop, allows [A-Za-z0-9-_.], replaces disallowed with -.
- Similarity: Same underlying shape (rune-by-rune,
isASCIIAlphanumeric gate, replace-disallowed). They differ only in the allow-set, the replacement char, and the leading-digit rule.
- Recommendation: Optional. A shared private helper
mapRunes(s string, allow func(rune) bool, replacement rune) string would let SanitizeForFilename reuse the same core as SanitizeIdentifierName. Given the semantic differences (hyphen vs underscore output, leading-digit handling), this is a judgment call β only worth it if a third rune-mapping sanitizer appears. Flagged for awareness, not urgent.
- Impact: Marginal dedup; do not do preemptively.
Not Issues (verified, left alone)
theme.go and theme_wasm.go duplicated var lists β intentional build-tag no-op stubs, not a refactor target.
huh_theme.go re-deriving colors β already sourced from the shared color* vars; single source of truth is intact.
SanitizeParameterName / SanitizePythonVariableName β thin, well-named wrappers over SanitizeIdentifierName; idiomatic, keep.
Recommendations
- Priority 1 β Split whitespace helpers out of
stringutil.go into whitespace.go (finding 1). ~30 min, mechanical.
- Priority 3 β Revisit sanitizer consolidation (finding 2) only when/if a third similar sanitizer lands.
Analysis Metadata
- Files analyzed: 10 (test files excluded)
- Functions cataloged: ~35
- Clusters: 9 (7 cohesive, 1 grab-bag, 1 build-tag pair)
- Outliers: 1 file (catch-all)
- Exact duplicates: 0
- Near-duplicates: 1 pair (low significance)
- Method: per-file symbol inventory + naming/purpose clustering
Generated by π§ Semantic Function Refactoring Β· sonnet46 Β· 197.1 AIC Β· β 9.95 AIC Β· β 9.7K Β· β·
π§ Semantic Function Clustering Analysis
Analysis of
github/gh-awβ scope:pkg/stringutil,pkg/styles(10 non-test.gofiles)Executive Summary
Both packages are, overall, cleanly feature-organized. Scope covered 10 files / ~35 functions. No exact duplicates and no misplaced cross-domain functions (e.g. no parser logic in a network file) were found. Two low/medium-impact organizational opportunities surfaced and are detailed below. Everything else clusters correctly and is left as-is.
Function Inventory
By file / cluster
pkg/stringutil
ansi.goβStripANSI,skipEscapeSequence,skipCSISequence,skipOSCSequence,isFinalCSIChar,isCSIParameterChar(cohesive ANSI cluster)fuzzy_match.goβFindClosestMatches,LevenshteinDistance(cohesive)identifiers.goβNormalizeWorkflowName,NormalizeSafeOutputIdentifier,MarkdownToLockFile,LockFileToMarkdown(cohesive)pat_validation.goβPATType+ methods,ClassifyPAT,ValidateCopilotPAT,GetPATTypeDescription(cohesive)sanitize.goβSanitizeName,SanitizeErrorMessage,SanitizeIdentifierName,SanitizeParameterName,SanitizePythonVariableName,SanitizeToolID,SanitizeForFilename+ helpersurls.goβNormalizeGitHubHostURL,ExtractDomainFromURL,extractDomainFallback(cohesive)stringutil.goβTruncate,NormalizeWhitespace,ParseVersionValue,FormatList,NormalizeLeadingWhitespace,IsPositiveInteger(grab-bag)pkg/styles
theme.go/theme_wasm.goβ build-tag pair (real vs Wasm no-op); intentional patternhuh_theme.goβ huh form theme mapping; correctly shares thecolor*palette vars withtheme.goIdentified Issues
1.
stringutil.gois a catch-all file (medium)pkg/stringutil/stringutil.goNormalizeWhitespace,NormalizeLeadingWhitespace), truncation (Truncate), version stringifying (ParseVersionValue), list formatting (FormatList), and integer validation (IsPositiveInteger). This breaks the package's own one-file-per-feature convention.whitespace.go(they form a clear cluster). The remaining small, genuinely-generic helpers (Truncate,FormatList,ParseVersionValue,IsPositiveInteger) can stay instringutil.goas the residual utility file. No signature or behavior changes β pure file moves.2. Two parallel rune-mapping sanitizers (low)
sanitize.go:223 SanitizeIdentifierName(name, extraAllowed)βstrings.Map, allows[A-Za-z0-9_]+extraAllowed, replaces disallowed with_, prepends_if leading digit.sanitize.go:325 SanitizeForFilename(slug)βstrings.Builderloop, allows[A-Za-z0-9-_.], replaces disallowed with-.isASCIIAlphanumericgate, replace-disallowed). They differ only in the allow-set, the replacement char, and the leading-digit rule.mapRunes(s string, allow func(rune) bool, replacement rune) stringwould letSanitizeForFilenamereuse the same core asSanitizeIdentifierName. Given the semantic differences (hyphen vs underscore output, leading-digit handling), this is a judgment call β only worth it if a third rune-mapping sanitizer appears. Flagged for awareness, not urgent.Not Issues (verified, left alone)
theme.goandtheme_wasm.goduplicated var lists β intentional build-tag no-op stubs, not a refactor target.huh_theme.gore-deriving colors β already sourced from the sharedcolor*vars; single source of truth is intact.SanitizeParameterName/SanitizePythonVariableNameβ thin, well-named wrappers overSanitizeIdentifierName; idiomatic, keep.Recommendations
stringutil.gointowhitespace.go(finding 1). ~30 min, mechanical.Analysis Metadata