[typist] π€ Typist β Go Type Consistency Analysis #33996
Closed
Replies: 1 comment
-
|
This discussion was automatically closed because it expired on 2026-05-23T12:17:48.367Z.
|
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
Analysed ~817 type definitions across the non-test Go files under
pkg/. Name-based duplicates are rare (mostly intentional re-export aliases or_wasm.gobuild-tag variants), but several structural / semantic clusters carry real maintenance cost β notably the CLI run-summary types inpkg/cli/logs_models.goand three near-identical error types inpkg/workflow/workflow_errors.go.Untyped usage is the dominant problem: 877
interface{}/anyparameters/returns across 333 files, 1,821map[string]anyoccurrences across 275 files, and 556.(map[string]any)assertions. The largest concentrations sit in three hot spots β the safe-output handler registry, MCP renderer entry points, and the import field extractor β where the upstream structures are already typed. Replacing theanyhops there would remove dozens of unsafe assertions.Full Analysis Report
Duplicated Type Definitions
Summary Statistics
Cluster 1: Source-location structs (EXACT)
Impact: medium
Locations
pkg/console/console_types.go:4βErrorPositionpkg/workflow/workflow_errors.go:33βFieldLocationRecommendation: keep
console.ErrorPositionas the canonical type and aliasworkflow.FieldLocationto it, or move both topkg/types/sourceloc.go. A single type simplifies the parser β workflow β console error-formatting bridge.Cluster 2:
RunSummaryvsDownloadResult(NEAR)Locations
pkg/cli/logs_models.go:203βRunSummarypkg/cli/logs_models.go:229βDownloadResultBoth share 14+ identical fields:
Run,Metrics,AwContext,TaskDomain,BehaviorFingerprint,AgenticAssessments,AccessAnalysis,FirewallAnalysis,RedactedDomainsAnalysis,MissingTools,MissingData,Noops,MCPFailures,MCPToolUsage,TokenUsage,GitHubRateLimitUsage,JobDetails.DownloadResultaddsError,Skipped,Cached,LogsPath;RunSummaryaddsCLIVersion,RunID,ProcessedAt,PolicyAnalysis,ArtifactsList.Recommendation: extract an embedded
RunAnalysisstruct that both compose. Every new analysis field currently has to be added in two places.Impact: high β these are the central CLI data carriers.
Cluster 3:
*Reporttypes (NEAR)Locations:
pkg/cli/logs_models.go:111-146All four share
Timestamp,WorkflowName,RunIDand the first two also shareReason/Alternatives.Recommendation: introduce
ReportBase { Timestamp string; WorkflowName string; RunID int64 }and embed it.Impact: medium β keeps JSON tags from drifting across parallel report types.
Cluster 4:
*Summaryaggregations (NEAR)Locations:
pkg/cli/logs_models.go:148-177βMissingToolSummaryandMissingDataSummarydiffer only inToolvsDataType;Count,Workflows,WorkflowsDisplay,FirstReason,FirstReasonDisplay,RunIDsare identical (same console tags too).Recommendation: parameterise via a single
AggregatedReportSummarywith aSubjectfield, or share a base.Impact: medium β aggregation code is duplicated in lock-step.
Cluster 5: Workflow error structs (NEAR)
Locations:
pkg/workflow/workflow_errors.go:40,127,183All three carry
Reason(orCause),Suggestion,Timestampand have near-identicalError()formatters.Recommendation: factor a
baseWorkflowError { Reason, Suggestion string; Timestamp time.Time }with a sharedformatTail()helper.Impact: medium β three near-identical
Error()implementations live in the same file.Cluster 6: Tool-call statistics (SEMANTIC)
Locations
pkg/workflow/metrics.go:16βToolCallInfo { Name; CallCount; MaxInputSize, MaxOutputSize int; MaxDuration time.Duration }pkg/cli/audit_report.go:169βMCPToolSummary { ServerName, ToolName; CallCount; TotalInputSize, TotalOutputSize, MaxInputSize, MaxOutputSize int; AvgDuration, MaxDuration string; ErrorCount int }Both track per-tool call statistics; they differ in units (
time.Durationvs pre-formatted string) and granularity.pkg/cli/logs_models.go:87already re-exportsToolCallInfo = workflow.ToolCallInfo.Recommendation: unify into a single
ToolCallStatsinpkg/types/with internaltime.Duration; format only at render time.Impact: medium β duplicate aggregation paths in
workflow/andcli/.Cluster 7: Validation results (SEMANTIC)
Locations:
pkg/cli/compile_config.go:49ValidationResult,pkg/workflow/permissions_validation.go:18PermissionsValidationResult,pkg/parser/frontmatter_content.go:19FrontmatterResult. Different shapes, but all represent βa checked thing plus errors/warnings.βRecommendation: keep separate concrete types but introduce a tiny
HasIssuesinterface (Errors() []...,HasErrors() bool) so CLI aggregation isnβt branching on concrete types.Impact: low.
Intentionally excluded (NOT duplicates)
ProgressBar,SpinnerWrapper,RepositoryFeaturesβ same name across*_wasm.gofiles; required for build-tag variants.ActionPin,ContainerPin,SHAResolver,SanitizeOptions, etc. β declared astype X = pkg.Xre-export aliases.BaseMCPServerConfiginpkg/types/mcp.gois already embedded byparser.RegistryMCPServerConfigandworkflow.MCPServerConfigβ positive precedent for the consolidations above.LogParser(interface inpkg/workflow, generic func type inpkg/cli) β different concepts despite the shared name.Untyped Usages
Summary Statistics
interface{}/anyin function signatures: 877 hits across 333 filesmap[string]any/map[string]interface{}: 1,821 occurrences across 275 files.(map[string]any)assertions: 556.(string)assertions: 612Category 1:
anyparameters that always receive one concrete type (HIGH)Example 1: GitHub tool accessors
pkg/workflow/mcp_github_config.go:84,138,163,182,194,204,264,284,414,532andpkg/workflow/mcp_renderer_github.go:17,110*GitHubToolConfigexists inpkg/workflow/tools_types.goand is the parsed form.*GitHubToolConfigdirectly; remove ~10 type assertions.Example 2: MCP renderer entry points
pkg/workflow/mcp_renderer_builtin.go:13βRenderPlaywrightMCP(yaml, playwrightTool any)immediately callsparsePlaywrightTool(playwrightTool)to obtain*PlaywrightToolConfig. The caller already has the parsed struct.RenderPlaywrightMCP(yaml, cfg *PlaywrightToolConfig).Example 3:
safeOutputHandlerDescriptor.NewConfig func() anypkg/workflow/safe_output_handlers.goβ 41 entries ofNewConfig: func() any { return &SomeConfig{} }. Each handler returns a distinct concrete*XxxConfig.SafeOutputConfiginterface (or a genericHandler[T]) so the factory return type is checked at compile time.NewConfig()call.Category 2:
map[string]anyin function signatures (MEDIUM-HIGH)Example 4: Handler builder pattern
pkg/workflow/compiler_safe_outputs_handlers.goβ 46 handler entries each build amap[string]anyfield by field. Each handler has a known JSON schema.Example 5:
MergeTools/MergeMCPServers/MergeFeatures/MergeEnvpkg/parser/imports.go:20,63,184,549,589β all acceptmap[string]anyon both sides. The top side is already typed (*Tools); imported side could deserialise into the same struct.Example 6: Frontmatter / import field extractor
pkg/parser/import_field_extractor.goβ 13anysignatures plus ~17 nested.(map[string]any)ladders (lines 301, 628-630, 724, 752, 843, 851, 921, 938, 969, 977, 989, 1058, 1085, 1096, 1114, 1153). The whole structure could deserialise into a typedImportSchemaviayaml.Unmarshal.Category 3: Untyped constants with semantic meaning (MEDIUM)
Example 7: Rate-limit constants mix units
pkg/constants/job_constants.go:220-221:time.Durationat lines 251-269 β the inconsistency invites unit bugs.const DefaultRateLimitWindow = 60 * time.Minute.Example 8: Byte-size constants
pkg/constants/constants.go:195βconst DefaultMCPGatewayPayloadSizeThreshold = 524288(no unit; comment says bytes).pkg/cli/gateway_logs_types.go:15βconst maxScannerBufferSize = 1024 * 1024.Bytestyped alias, or at minimum theKiB * 1024style throughout.Example 9: Threshold percentages
pkg/cli/audit_diff.go:21βconst volumeChangeThresholdPercent = 100.0(untyped).pkg/cli/audit_cross_run.go:14,18β*RateThresholdconstants.float64typedPercentalias.Category 4: Type-assertion-heavy code (HIGH)
556
.(map[string]any)assertions and 612.(string)assertions are concentrated in YAML/frontmatter parsers. Most assertion ladders trace back to ananyparameter that could be a typed struct.Hot files (highest
interface{}/anydensity)pkg/workflow/safe_output_handlers.goβ 42interface{}+ 41func() anyfactory entriespkg/workflow/compiler_safe_outputs_handlers.goβ 46 hitspkg/workflow/role_checks.goβ 20 hitspkg/workflow/tools_parser.goβ 15 (mostly legitimate boundary parsing)pkg/parser/import_field_extractor.goβ 13 signatures + the worst assertion density in the repoIntentional
anyusage β leave aloneparseGitHubTool(val any)etc. inpkg/workflow/tools_parser.goβ accept YAML polymorphism (bool / object / array) at the parse boundary.pkg/typeutil/convert.goβ generic numeric helpers.pkg/logger/logger.goPrintf(..., args ...any)β matchesfmt.Printf.MapToolConfig.GetAnyinpkg/workflow/mcp_config_types.goβ explicit untyped accessor by design.Refactoring Recommendations
Priority 1: High β Replace
anyin handler/renderer entry pointsTargets:
pkg/workflow/mcp_github_config.go,pkg/workflow/mcp_renderer_*.go,pkg/workflow/safe_output_handlers.go.Steps
*GitHubToolConfig,*PlaywrightToolConfig, ...).safeOutputHandlerDescriptor, define aSafeOutputConfiginterface (or a generic descriptor) soNewConfigreturns a typed value..(map[string]any)assertion sites that the change makes obsolete.Impact: removes ~50+ unsafe assertions; compile-time safety on the safe-outputs registry.
Priority 2: High β Consolidate
RunSummary/DownloadResultTarget:
pkg/cli/logs_models.go.Steps
RunAnalysisstruct holding the 14 shared fields.RunSummaryandDownloadResult.Impact: single source of truth for run-analysis fields; ends per-field double-edits.
Priority 3: Medium β Typed import schema
Target:
pkg/parser/import_field_extractor.go.Steps
ImportSchemamirroring the YAML.yaml.Unmarshalinto it once at the entry point..(map[string]any)ladders with field access.Impact: largest assertion-removal win in the codebase; safer error messages.
Priority 4: Medium β Shared error/report bases
Targets
pkg/workflow/workflow_errors.goβbaseWorkflowError { Reason, Suggestion string; Timestamp time.Time }.pkg/cli/logs_models.goβReportBase { Timestamp string; WorkflowName string; RunID int64 }andAggregatedReportSummary.Impact: removes cross-type drift; JSON tags stay aligned.
Priority 5: Low β Typed semantic constants
Targets:
pkg/constants/job_constants.go(usetime.Durationconsistently);pkg/cli/audit_diff.go,pkg/cli/audit_cross_run.go(typedPercent); byte-size constants.Implementation Checklist
anyin MCP renderer entry points with concrete tool configsSafeOutputConfiginterface for the safe-output handler registryRunAnalysisfromRunSummary/DownloadResultReportBase/AggregatedReportSummaryand embed inpkg/cli/logs_models.gobaseWorkflowErrorand sharedformatTail()inpkg/workflow/workflow_errors.goToolCallInfo/MCPToolSummaryinto a singleToolCallStatsImportSchemaforpkg/parser/import_field_extractor.goDefaultRateLimitWindowtotime.Durationgo vet ./...after each batchAnalysis Metadata
pkg/map[string]any+ 556 + 612 assertionsBeta Was this translation helpful? Give feedback.
All reactions