[typist] Typist — Go Type Consistency Analysis (duplicated types & untyped usages) #42949
Closed
Replies: 1 comment
-
|
This discussion has been marked as outdated by Typist - Go Type Analysis. A newer discussion is available at Discussion #43185. |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
🔤 Typist - Go Type Consistency Analysis
Analysis of repository: github/gh-aw
Executive Summary
Good news first: this codebase is already disciplined about cross-package type sharing. Rather than copy-pasting struct definitions, it leans on Go type aliases — e.g.
type InputDefinition = types.InputDefinition,type SanitizeOptions = stringutil.SanitizeOptions,type LogMetrics = workflow.LogMetrics, theActionPin/ActionYAMLInputfamily re-exported frompkg/actionpins, and fan-outs likeMissingDataConfig/MissingToolConfig/ReportIncompleteConfig = IssueReportingConfigandCloseIssuesConfig/ClosePullRequestsConfig/CloseDiscussionsConfig = CloseEntityConfig. So most same-name-in-two-places hits are intentional single-source-of-truth aliases, not duplication. 🎉Across ~990 non-test
.gofiles underpkg/(~1,015 top-level types), the genuine opportunities cluster into: three parallel shapes for GitHub rate-limit data, a family of per-tool scanner finding structs, several MCP-server-config representations, and two parallel audit diff vs. comparison delta vocabularies. On typing,any/interface{}appears in 160+ files — mostly legitimate YAML/frontmatter parsing, with a few spots where a concrete type would remove runtime assertions. Nothing on fire — a friendly punch-list. 🙂Full Analysis Report
Duplicated Type Definitions
pkg/)Cluster 1 (near) — GitHub rate-limit data, 3 shapes in
pkg/clilogs_github_rate_limit_usage.go:33GitHubRateLimitEntry(Reset asstring)logs_rate_limit.go:36rateLimitResource(Reset asint64)update_org.go:48orgRateLimitResponseSame limit/remaining/used/reset concept modeled 3x, with a
Resettype mismatch (stringvsint64). Fix: one sharedRateLimitBucket; reconcile theResetencoding. Effort 2-3h.Cluster 2 (near) — Per-tool scanner finding structs
cli/zizmor.go:23zizmorFinding·cli/poutine.go:24poutineFinding·cli/runner_guard.go:21runnerGuardFinding·cli/audit_report.go:63Finding·workflow/markdown_security_scanner.go:57SecurityFindingOverlapping fields (rule id, message, severity, path, line). Fix: keep thin per-tool decode structs, add one internal
ScanFinding, convert at each boundary. Effort 3-4h.Cluster 3 (near) — Experiment records (exported vs. JSON twin)
cli/experiments_command.go:41ExperimentRunRecordvscli/audit_report_experiments.go:42experimentRunRecord; alsoExperimentStatevsexperimentStateJSON.Fix: if the twins only decode the same JSON, delete them and decode into the exported types. Effort 1-2h.
Cluster 4 (semantic) — MCP-server config shapes across packages
types/mcp.go:6BaseMCPServerConfig·workflow/tools_types.go:430MCPServerConfig·parser/mcp.go:39RegistryMCPServerConfig(+MCPServerInfo) ·cli/mcp_registry.go:19MCPRegistryServerForProcessing·cli/mcp_registry_types.go:26ServerDetail·cli/mcp_config_file.go:22VSCodeMCPServerLayered-by-design, so not a full merge — but check whether the others can embed
BaseMCPServerConfiginstead of redeclaring overlapping fields. Effort 4-6h.Cluster 5 (semantic) — Audit diff vs. comparison deltas
cli/audit_diff.go—AuditDiff,FirewallDiff,MCPToolsDiff,ToolCallsDiff,TokenUsageDiff, and morecli/audit_comparison.go—AuditComparisonDelta,AuditComparisonIntDelta,AuditComparisonStringDelta, and moreTwo parallel difference-between-two-runs vocabularies. Consider a generic
Delta[T any] struct{ Before, After T; Changed bool }to collapse the int/string delta twins. Effort 3-5h.Untyped Usages
any/interface{}in 160+ non-test files; dominant pattern ismap[string]anyfor YAML/frontmatter (largely idiomatic at the boundary).Category 1 — map[string]any threaded deep (medium):
cli/codemod_factory.go:13PostTransformFunc(... frontmatter map[string]any, fieldValue any)— both untypedcli/outcome_eval_update.go:25mutableStateLoader ... (map[string]any, bool, error)cli/devcontainer.go:45DevcontainerFeatures map[string]any·workflow/mcp_config_types.go:66MapToolConfig map[string]anyDecode into structs near the boundary where the shape is known; keep the map only at the raw-YAML edge.
Category 2 — any factory + untyped scope (low/medium):
workflow/safe_output_handlers.go:17NewConfig func() any(40+ uses). A marker interface would restore some compile-time safety.workflow/tools_types.go:302type GitHubReposScope any— the comment documents two real shapes (string or slice); a small sum-type or decode-time validation fits.Category 3 — untyped string constants (low):
pkg/constantsalready defines strong types (JobName,StepID,EngineName,WorkflowID,URL, and more), but filename/artifact-name constants injob_constants.go(SafeOutputArtifactName,AgentOutputFilename,SarifFileName) stay untyped. Optional — type only to prevent mixing artifact names with arbitrary strings.Prioritized Recommendations
RateLimitBucket, reconcileResetencoding (Cluster 1). 2-3h.ScanFinding+ per-tool adapters (Cluster 2). 3-4h.BaseMCPServerConfig(Cluster 4); genericDelta[T](Cluster 5); marker interface for the safe-output factory (Cat 2).Checklist
RateLimitBucket+Resetencoding reconciledScanFinding+ adaptersBaseMCPServerConfigembeddingDelta[T]Files analyzed: ~990 · Types: ~1,015 · Clusters: 5 (+3 false positives) · Untyped footprint: 160+ files · Date: 2026-07-02
Beta Was this translation helpful? Give feedback.
All reactions