You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Analysis of repository: github/gh-aw · run §31796643848
Executive Summary
I scanned ~1,200 non-test .go files under pkg/ (≈938 real top-level type declarations, plus ~630 any-typed signatures/fields and ~630 top-level constants) looking for duplicated types and untyped code that could be made safer. The good news: there are no accidental exact-duplicate structs anywhere in the codebase — the three same-named types that do repeat (ProgressBar, SpinnerWrapper, RepositoryFeatures) are intentional native/WASM build-tag pairs. The real opportunity is semantic duplication concentrated almost entirely in pkg/cli's audit/logs subsystem, where the same "server/tool call stats" and "request counter" concepts have been independently reinvented 4-5 times with different field names across files like audit_report.go, gateway_logs_types.go, audit_expanded.go, and audit_cross_run.go.
On the typing side, interface{} is already fully gone (migrated to any), and most any/map[string]any usage is legitimate (dynamic YAML/JSON frontmatter). But there's a clear, high-confidence win in pkg/parser/schema_compiler.go, where getParsedSchemaDoc returns bare any even though all its downstream consumers immediately assert it to map[string]any — a one-line signature fix removes redundant assertions everywhere it's used. There's also a small set of untyped constants (hours vs. days duration constants, port numbers, enum-like string groups) in pkg/workflow and pkg/cli that sit right next to properly-typed siblings, showing the team already knows the pattern — it's just inconsistently applied.
Full Analysis Report
Duplicated Type Definitions
Method: rg -n '^type \w+ (struct|interface)' pkg --glob '*.go' --glob '!*_test.go' plus manual field-by-field comparison of same-named and semantically-similar types.
Summary Statistics
Total types analyzed: ~938 (excluding pkg/linters/** test fixtures)
Plus a parallel trio for per-tool stats: MCPToolSummary/ToolUsageInfo (audit_report.go:174,155) and GatewayToolMetrics (gateway_logs_types.go:97) — same "tool name + call count + total/max size + avg/max duration" concept under three different names.
Type: Semantic duplicate. All share ServerName + a request/call count + an error count + a duration, just renamed (RequestCount vs ToolCallCount vs TotalCalls; ErrorCount vs TotalErrors).
Recommendation: Define one canonical MCPServerCallStats/MCPToolCallStats pair (e.g. in pkg/types or a new shared pkg/cli file) and have audit, gateway-logs, expanded-audit, and cross-run health build views from it instead of independently accumulating from raw logs. Estimated effort: 4-6 hours · Impact: High — most scattered logic in the audit subsystem.
Cluster 2: RunSummary vs DownloadResult — 14 duplicated fields in the same file
Recommendation: Have DownloadResult embed RunSummary plus its 4 download-specific fields (Error, Skipped, Cached, LogsPath) instead of re-declaring all 14. Estimated effort: 1 hour · Impact: High — eliminates copy/paste drift risk between the two.
Cluster 3: Rate/request counter family — 4 different spellings of the same concept
Recommendation: Standardize on one RequestCounters{Total, Allowed, Denied} value type used by all four instead of ad hoc int fields with inconsistent names (AllowedRequests/AllowedCount/TotalAllowed/Allowed). Estimated effort: 2-3 hours · Impact: Medium-High.
Cluster 4: RedactedDomainsAnalysis / RedactedDomainsLogSummary — a regression vs. sibling fixes already applied
pkg/cli/redacted_domains.go:21 and :29. RedactedDomainsLogSummary re-declares TotalDomains int and Domains []string verbatim instead of embedding RedactedDomainsAnalysis — notable because sibling types in the same package already solved this exact problem (AccessLogSummary/FirewallLogSummary embed a shared FirewallSummaryBase; DomainAnalysis/FirewallAnalysis embed AnalysisBase).
Recommendation: Embed RedactedDomainsAnalysis inside RedactedDomainsLogSummary to match the pattern already used by its neighbors. Estimated effort: 30 min · Impact: Low effort, easy win.
Cluster 5: WorkflowRun vs WorkflowRunInfo — exact-name subset duplicate
pkg/cli/logs_models.go:57 (WorkflowRun) vs pkg/cli/run_workflow_tracking.go:19 (WorkflowRunInfo). WorkflowRunInfo{URL, DatabaseID, Status, Conclusion, CreatedAt} is an exact-name, exact-type subset of WorkflowRun's first several fields.
Recommendation: Reuse WorkflowRun (or extract a minimal WorkflowRunRef) instead of a parallel struct. Estimated effort: 1 hour · Impact: Low-Medium.
Cluster 6: GitHub rate-limit info across 3 independent models (lower priority)
rateLimitResponse/rateLimitResource (live API, logs_rate_limit.go:39,46, correctly reused by update_org.go), GitHubRateLimitEntry/GitHubRateLimitResourceUsage/GitHubRateLimitUsage (derived-from-logs usage model, logs_github_rate_limit_usage.go:33,46,57), and GitHubRateLimitDiff (audit_diff.go:366). The live-snapshot and derived-usage types serve genuinely different data sources, but GitHubRateLimitDiff duplicates fields from the usage type unnecessarily. Impact: Low — partly justified by differing data sources.
Cluster 7: "Domain-then-Display" pattern (architectural, not urgent)
OverviewData/OverviewDisplay and PolicyAnalysis/PolicySummaryDisplay (both in audit_report.go) repeat a subset of fields for console-tag rendering. Consider a .Display() projection method instead of hand-maintained parallel structs.
Untyped Usages (interface{} / any)
Summary Statistics
interface{} (old syntax): effectively 0 in production code — already fully migrated to any.
any as a type: ~1,250+ real occurrences; map[string]any (~2,175+) and []any (~400+) dominate and are mostly legitimate dynamic YAML/JSON.
Bare any in params/returns/fields (the real refactor surface): ~300 occurrences — pkg/workflow (~140), pkg/cli (~100), pkg/parser (~45), rest of pkg (~35).
pkg/github: 0 hits — already fully typed.
Category 1: Function Parameters
pkg/parser/schema_compiler.go:82 — getParsedSchemaDoc(schemaJSON string) (any, error), whose value flows to 8 downstream consumers in schema_suggestions.go (lines 76, 101, 245, 321, 344, 360, 667, 756), every one of which immediately asserts map[string]any. Highest-confidence fix in this audit: change the return type to (map[string]any, error) and delete 8 repeated inline assertions.
pkg/workflow/mcp_setup_gateway.go, mcp_renderer.go:102,129, gemini_mcp.go:13 — all take tools map[string]any, even though pkg/workflow/tools_types.go already defines ToolsConfig/ParseToolsConfig/ToMap() as a documented typed alternative that most call sites simply haven't adopted yet.
pkg/cli/trial_helpers.go:361 — saveTrialResult(filename string, result any, verbose bool) error is only ever called with WorkflowTrialResult or CombinedTrialResult. Suggested: a generic constraint [T WorkflowTrialResult | CombinedTrialResult] — it's never actually polymorphic.
pkg/cli/add_package_manifest.go:383,415,484,518 — four functions share an identical switch value.(type) { case []any: ...; case []string: ... } body; consolidate into one extractManifestStringList(value any) ([]string, bool) helper.
pkg/console/layout_wasm.go:16 — LayoutEmphasisBox(content string, color any) string; color is unused and the function has zero callers — dead code, remove.
Category 2: Return Types
pkg/parser/schema_compiler.go:82 (see above).
pkg/cli/status_command.go:140,195 — var onField any for a workflow trigger value, re-serialized for display/JSON. A small TriggerValue type (string | []string | map[string]any with custom MarshalJSON) would replace the opaque any threaded through 3 call sites.
pkg/typeutil helpers (LookupMap, ParseIntValue, ConvertToInt) return any by stated design as generic YAML-extraction utilities — lower priority, genericity is the point.
Category 3: Struct Fields
pkg/workflow/tools_types.go:302 — type GitHubReposScope any // string or []any, type-switched 3 ways at cache_integrity.go:130-155, while every other AllowedRepos field elsewhere in the codebase is plain []string. Suggested: a real named type with custom UnmarshalYAML.
pkg/workflow/safe_jobs.go:21 — RunsOn any, type-switched at lines 235-238 — but the codebase already hastype RunsOnValue []string with FormatRunsOn (repo_config.go:436) built for exactly this. Just reuse it.
pkg/workflow/safe_jobs.go:24, safe_outputs_config_types.go:115, threat_detection_config.go:9-10 — Steps []any/PostSteps []any converted at 10+ call sites in workflow_builder.go via SliceToSteps/MapToStep/ToMap. Typing these as []*WorkflowStep directly removes the repeated round-trip conversions.
pkg/console/console_types.go:50 — FormField.Value any — investigated and found to be dead/vestigial (only referenced by a WASM stub that returns an error); type or remove rather than refactor.
Category 4: Map/Slice Values — the ~1,710-line map[string]any volume in pkg/workflow is mostly legitimate raw frontmatter, but is the natural long-term target for incremental migration onto ToolsConfig at the parse boundary, per Category 1.
Excluded as legitimate: YAML/JSON frontmatter and MCP tool config trees, the analysis.Analyzer.Run(pass) (any, error) stdlib-mandated signature (~65 occurrences in pkg/linters/*), variadic args ...any in fmt/slog, real Go generics ([T any] in pkg/sliceutil, pkg/syncutil.OnceLoader[T]), and pkg/typeutil/pkg/importinpututil (whose entire purpose is generic YAML extraction).
Untyped Constants
Summary Statistics: ~499 top-level const NAME = value declarations plus 131 const (...) blocks examined; roughly 60-70% are untyped built-ins, most of which are fine as opaque path/URL/env-var strings. The list below is the genuine high-value subset.
Numeric constants
pkg/workflow/repo_config.go:63DefaultActionFailureIssueExpiresHours = 24 * 7 and pkg/workflow/maintenance_workflow.go:128defaultNoOpIssueExpirationHours = 24 * 30 — both bare-int "hours" constants, independently named/typed; a third sibling, pkg/workflow/nodejs.go:13npmDefaultCooldownDays = 3, uses a different unit (days) as another bare int in the same package. Suggested: a shared type Hours int (or convert all three to time.Duration) so hours/days can't be mixed by accident.
pkg/constants/constants.go:104-120 — DefaultMCPGatewayPort, DefaultMCPServerPort, DefaultMCPInspectorPort, DefaultCopilotSDKPort, MinNetworkPort — all untyped ints for network ports. Suggested type Port int (and similarly type VCPUs int/type MemoryMiB int for the adjacent Cloud Hypervisor constants at lines 181-183).
pkg/cli/audit_cross_run.go:14,18,22 — mcpErrorRateThreshold = 0.10, mcpConnectionRateThreshold = 0.75, spikeDetectionMultiplier = 2.0 — untyped floats mixing "ratio 0-1" and "multiplier" semantics; a Ratio/Multiplier type distinction would prevent misuse.
pkg/cli/audit_diff.go:21volumeChangeThresholdPercent = 100.0 — untyped float meant to be a percentage, easily confused with the 0-1 ratios above; candidate type Percent float64.
String constants
pkg/workflow/run_phase.go:7-11 — runPhaseAgent = "agent", runPhaseDetection = "detection", runPhaseEvals = "evals", returned from workflowRunPhase(...) string. Clearest cluster candidate — same package already uses type X string + typed consts for ActionMode/LLMProvider. Suggested: type RunPhase string.
pkg/workflow/sandbox_validation.go:334-339 — validBoundedQuerySensitivities keyed by bare strings "public"/"internal"/"confidential"/"sealed", while the sibling set two lines down (validBoundedQueryRuntimes) already uses the properly-typed BoundedQueryRuntime. Suggested: type QuerySensitivity string to match.
pkg/cli/token_usage_types.go:147-151 — modelMismatchReasonTokenUsageMissing/modelMismatchReasonModelNotObserved (reason-code pair) and tokenSteeringEventName/timeoutSteeringEventName (event-name pair), both untyped. Suggested type ModelMismatchReason string and type SteeringEventName string.
pkg/constants/engine_constants.go:179-213 — secret-name constants (CopilotGitHubToken, AnthropicAPIKey, etc.) and env-var-name constants (EnvVarModel* block) are both plain string, despite being semantically distinct categories. Suggested type SecretName string and type EnvVarName string.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
🔤 Typist — Go Type Consistency Analysis
Analysis of repository: github/gh-aw · run §31796643848
Executive Summary
I scanned ~1,200 non-test
.gofiles underpkg/(≈938 real top-level type declarations, plus ~630any-typed signatures/fields and ~630 top-level constants) looking for duplicated types and untyped code that could be made safer. The good news: there are no accidental exact-duplicate structs anywhere in the codebase — the three same-named types that do repeat (ProgressBar,SpinnerWrapper,RepositoryFeatures) are intentional native/WASM build-tag pairs. The real opportunity is semantic duplication concentrated almost entirely inpkg/cli's audit/logs subsystem, where the same "server/tool call stats" and "request counter" concepts have been independently reinvented 4-5 times with different field names across files likeaudit_report.go,gateway_logs_types.go,audit_expanded.go, andaudit_cross_run.go.On the typing side,
interface{}is already fully gone (migrated toany), and mostany/map[string]anyusage is legitimate (dynamic YAML/JSON frontmatter). But there's a clear, high-confidence win inpkg/parser/schema_compiler.go, wheregetParsedSchemaDocreturns bareanyeven though all its downstream consumers immediately assert it tomap[string]any— a one-line signature fix removes redundant assertions everywhere it's used. There's also a small set of untyped constants (hours vs. days duration constants, port numbers, enum-like string groups) inpkg/workflowandpkg/clithat sit right next to properly-typed siblings, showing the team already knows the pattern — it's just inconsistently applied.Full Analysis Report
Duplicated Type Definitions
Method:
rg -n '^type \w+ (struct|interface)' pkg --glob '*.go' --glob '!*_test.go'plus manual field-by-field comparison of same-named and semantically-similar types.Summary Statistics
pkg/linters/**test fixtures)pkg/types(the shared-types package),pkg/github,pkg/githubapi,pkg/parser— no notable duplication found;pkg/workflow's size (~450 types) reflects genuinely distinct per-feature config types, not copy/paste.Cluster 1: MCP server/tool call-stats reinvented 4-5 times (highest impact)
Four to five near-identical "per-server / per-tool call statistics" shapes exist in parallel, all in
pkg/cli:MCPServerStatspkg/cli/audit_report.go:202GatewayServerMetricspkg/cli/gateway_logs_types.go:85MCPServerHealthDetailpkg/cli/audit_expanded.go:90MCPServerCrossRunHealthpkg/cli/audit_cross_run.go:81Plus a parallel trio for per-tool stats:
MCPToolSummary/ToolUsageInfo(audit_report.go:174,155) andGatewayToolMetrics(gateway_logs_types.go:97) — same "tool name + call count + total/max size + avg/max duration" concept under three different names.Type: Semantic duplicate. All share
ServerName+ a request/call count + an error count + a duration, just renamed (RequestCountvsToolCallCountvsTotalCalls;ErrorCountvsTotalErrors).Recommendation: Define one canonical
MCPServerCallStats/MCPToolCallStatspair (e.g. inpkg/typesor a new sharedpkg/clifile) and have audit, gateway-logs, expanded-audit, and cross-run health build views from it instead of independently accumulating from raw logs.Estimated effort: 4-6 hours · Impact: High — most scattered logic in the audit subsystem.
Cluster 2:
RunSummaryvsDownloadResult— 14 duplicated fields in the same filepkg/cli/logs_models.go:225(RunSummary) andpkg/cli/logs_models.go:252(DownloadResult), ~30 lines apart. 14 fields are byte-for-byte identical:Run WorkflowRun,Metrics LogMetrics,AwContext,TaskDomain,BehaviorFingerprint,AgenticAssessments,AccessAnalysis,FirewallAnalysis,RedactedDomainsAnalysis,MissingTools,MissingData,Noops,MCPFailures,SkillActivations,MCPToolUsage,TokenUsage,GitHubRateLimitUsage,JobDetails.Recommendation: Have
DownloadResultembedRunSummaryplus its 4 download-specific fields (Error,Skipped,Cached,LogsPath) instead of re-declaring all 14.Estimated effort: 1 hour · Impact: High — eliminates copy/paste drift risk between the two.
Cluster 3: Rate/request counter family — 4 different spellings of the same concept
AnalysisBase—pkg/cli/domain_buckets.go:41(TotalRequests, AllowedRequests, BlockedRequests)PolicyAnalysis—pkg/cli/firewall_policy.go:79(TotalRequests, AllowedCount, DeniedCount, UniqueDomains)CrossRunSummary—pkg/cli/audit_cross_run.go:40(TotalRequests, TotalAllowed, TotalBlocked, OverallDenyRate, UniqueDomains)PolicySummaryDisplay—pkg/cli/audit_report.go:231(Policy, TotalRequests, Allowed, Denied, UniqueDomains)Recommendation: Standardize on one
RequestCounters{Total, Allowed, Denied}value type used by all four instead of ad hoc int fields with inconsistent names (AllowedRequests/AllowedCount/TotalAllowed/Allowed).Estimated effort: 2-3 hours · Impact: Medium-High.
Cluster 4:
RedactedDomainsAnalysis/RedactedDomainsLogSummary— a regression vs. sibling fixes already appliedpkg/cli/redacted_domains.go:21and:29.RedactedDomainsLogSummaryre-declaresTotalDomains intandDomains []stringverbatim instead of embeddingRedactedDomainsAnalysis— notable because sibling types in the same package already solved this exact problem (AccessLogSummary/FirewallLogSummaryembed a sharedFirewallSummaryBase;DomainAnalysis/FirewallAnalysisembedAnalysisBase).Recommendation: Embed
RedactedDomainsAnalysisinsideRedactedDomainsLogSummaryto match the pattern already used by its neighbors.Estimated effort: 30 min · Impact: Low effort, easy win.
Cluster 5:
WorkflowRunvsWorkflowRunInfo— exact-name subset duplicatepkg/cli/logs_models.go:57(WorkflowRun) vspkg/cli/run_workflow_tracking.go:19(WorkflowRunInfo).WorkflowRunInfo{URL, DatabaseID, Status, Conclusion, CreatedAt}is an exact-name, exact-type subset ofWorkflowRun's first several fields.Recommendation: Reuse
WorkflowRun(or extract a minimalWorkflowRunRef) instead of a parallel struct.Estimated effort: 1 hour · Impact: Low-Medium.
Cluster 6: GitHub rate-limit info across 3 independent models (lower priority)
rateLimitResponse/rateLimitResource(live API,logs_rate_limit.go:39,46, correctly reused byupdate_org.go),GitHubRateLimitEntry/GitHubRateLimitResourceUsage/GitHubRateLimitUsage(derived-from-logs usage model,logs_github_rate_limit_usage.go:33,46,57), andGitHubRateLimitDiff(audit_diff.go:366). The live-snapshot and derived-usage types serve genuinely different data sources, butGitHubRateLimitDiffduplicates fields from the usage type unnecessarily.Impact: Low — partly justified by differing data sources.
Cluster 7: "Domain-then-Display" pattern (architectural, not urgent)
OverviewData/OverviewDisplayandPolicyAnalysis/PolicySummaryDisplay(both inaudit_report.go) repeat a subset of fields for console-tag rendering. Consider a.Display()projection method instead of hand-maintained parallel structs.Untyped Usages (
interface{}/any)Summary Statistics
interface{}(old syntax): effectively 0 in production code — already fully migrated toany.anyas a type: ~1,250+ real occurrences;map[string]any(~2,175+) and[]any(~400+) dominate and are mostly legitimate dynamic YAML/JSON.anyin params/returns/fields (the real refactor surface): ~300 occurrences — pkg/workflow (~140), pkg/cli (~100), pkg/parser (~45), rest of pkg (~35).Category 1: Function Parameters
pkg/parser/schema_compiler.go:82—getParsedSchemaDoc(schemaJSON string) (any, error), whose value flows to 8 downstream consumers inschema_suggestions.go(lines 76, 101, 245, 321, 344, 360, 667, 756), every one of which immediately assertsmap[string]any. Highest-confidence fix in this audit: change the return type to(map[string]any, error)and delete 8 repeated inline assertions.pkg/workflow/mcp_setup_gateway.go,mcp_renderer.go:102,129,gemini_mcp.go:13— all taketools map[string]any, even thoughpkg/workflow/tools_types.goalready definesToolsConfig/ParseToolsConfig/ToMap()as a documented typed alternative that most call sites simply haven't adopted yet.pkg/cli/trial_helpers.go:361—saveTrialResult(filename string, result any, verbose bool) erroris only ever called withWorkflowTrialResultorCombinedTrialResult. Suggested: a generic constraint[T WorkflowTrialResult | CombinedTrialResult]— it's never actually polymorphic.pkg/cli/add_package_manifest.go:383,415,484,518— four functions share an identicalswitch value.(type) { case []any: ...; case []string: ... }body; consolidate into oneextractManifestStringList(value any) ([]string, bool)helper.pkg/console/layout_wasm.go:16—LayoutEmphasisBox(content string, color any) string;coloris unused and the function has zero callers — dead code, remove.Category 2: Return Types
pkg/parser/schema_compiler.go:82(see above).pkg/cli/status_command.go:140,195—var onField anyfor a workflow trigger value, re-serialized for display/JSON. A smallTriggerValuetype (string | []string | map[string]any with customMarshalJSON) would replace the opaqueanythreaded through 3 call sites.pkg/typeutilhelpers (LookupMap,ParseIntValue,ConvertToInt) returnanyby stated design as generic YAML-extraction utilities — lower priority, genericity is the point.Category 3: Struct Fields
pkg/workflow/tools_types.go:302—type GitHubReposScope any // string or []any, type-switched 3 ways atcache_integrity.go:130-155, while every otherAllowedReposfield elsewhere in the codebase is plain[]string. Suggested: a real named type with customUnmarshalYAML.pkg/workflow/safe_jobs.go:21—RunsOn any, type-switched at lines 235-238 — but the codebase already hastype RunsOnValue []stringwithFormatRunsOn(repo_config.go:436) built for exactly this. Just reuse it.pkg/workflow/safe_jobs.go:24,safe_outputs_config_types.go:115,threat_detection_config.go:9-10—Steps []any/PostSteps []anyconverted at 10+ call sites inworkflow_builder.goviaSliceToSteps/MapToStep/ToMap. Typing these as[]*WorkflowStepdirectly removes the repeated round-trip conversions.pkg/console/console_types.go:50—FormField.Value any— investigated and found to be dead/vestigial (only referenced by a WASM stub that returns an error); type or remove rather than refactor.Category 4: Map/Slice Values — the ~1,710-line
map[string]anyvolume inpkg/workflowis mostly legitimate raw frontmatter, but is the natural long-term target for incremental migration ontoToolsConfigat the parse boundary, per Category 1.Excluded as legitimate: YAML/JSON frontmatter and MCP tool config trees, the
analysis.Analyzer.Run(pass) (any, error)stdlib-mandated signature (~65 occurrences inpkg/linters/*), variadicargs ...anyinfmt/slog, real Go generics ([T any]inpkg/sliceutil,pkg/syncutil.OnceLoader[T]), andpkg/typeutil/pkg/importinpututil(whose entire purpose is generic YAML extraction).Untyped Constants
Summary Statistics: ~499 top-level
const NAME = valuedeclarations plus 131const (...)blocks examined; roughly 60-70% are untyped built-ins, most of which are fine as opaque path/URL/env-var strings. The list below is the genuine high-value subset.Numeric constants
pkg/workflow/repo_config.go:63DefaultActionFailureIssueExpiresHours = 24 * 7andpkg/workflow/maintenance_workflow.go:128defaultNoOpIssueExpirationHours = 24 * 30— both bare-int "hours" constants, independently named/typed; a third sibling,pkg/workflow/nodejs.go:13npmDefaultCooldownDays = 3, uses a different unit (days) as another bare int in the same package. Suggested: a sharedtype Hours int(or convert all three totime.Duration) so hours/days can't be mixed by accident.pkg/constants/constants.go:104-120—DefaultMCPGatewayPort,DefaultMCPServerPort,DefaultMCPInspectorPort,DefaultCopilotSDKPort,MinNetworkPort— all untyped ints for network ports. Suggestedtype Port int(and similarlytype VCPUs int/type MemoryMiB intfor the adjacent Cloud Hypervisor constants at lines 181-183).pkg/cli/audit_cross_run.go:14,18,22—mcpErrorRateThreshold = 0.10,mcpConnectionRateThreshold = 0.75,spikeDetectionMultiplier = 2.0— untyped floats mixing "ratio 0-1" and "multiplier" semantics; aRatio/Multipliertype distinction would prevent misuse.pkg/cli/audit_diff.go:21volumeChangeThresholdPercent = 100.0— untyped float meant to be a percentage, easily confused with the 0-1 ratios above; candidatetype Percent float64.String constants
pkg/workflow/run_phase.go:7-11—runPhaseAgent = "agent",runPhaseDetection = "detection",runPhaseEvals = "evals", returned fromworkflowRunPhase(...) string. Clearest cluster candidate — same package already usestype X string+ typed consts forActionMode/LLMProvider. Suggested:type RunPhase string.pkg/workflow/sandbox_validation.go:334-339—validBoundedQuerySensitivitieskeyed by bare strings"public"/"internal"/"confidential"/"sealed", while the sibling set two lines down (validBoundedQueryRuntimes) already uses the properly-typedBoundedQueryRuntime. Suggested:type QuerySensitivity stringto match.pkg/cli/token_usage_types.go:147-151—modelMismatchReasonTokenUsageMissing/modelMismatchReasonModelNotObserved(reason-code pair) andtokenSteeringEventName/timeoutSteeringEventName(event-name pair), both untyped. Suggestedtype ModelMismatchReason stringandtype SteeringEventName string.pkg/constants/engine_constants.go:179-213— secret-name constants (CopilotGitHubToken,AnthropicAPIKey, etc.) and env-var-name constants (EnvVarModel*block) are both plainstring, despite being semantically distinct categories. Suggestedtype SecretName stringandtype EnvVarName string.pkg/workflow/permissions_validation.go:44-49—validPermissionMetaKeys("all","read-all","write-all","none") untyped; candidatetype PermissionScope string.pkg/workflow/safe_outputs_data_schema.go:16-20—supportedDataSchemaTypes(JSON-schema type names) untyped; candidatetype JSONSchemaType string.Priority Recommendations
Priority 1 — Quick, high-confidence wins (each under ~2 hours)
pkg/parser/schema_compiler.go:82getParsedSchemaDoc→ return(map[string]any, error)directly.pkg/cli/logs_models.go— embedRunSummaryinDownloadResult.pkg/cli/redacted_domains.go— embedRedactedDomainsAnalysisinRedactedDomainsLogSummary.pkg/workflow/safe_jobs.go:21RunsOn any→ reuse existingRunsOnValue.pkg/workflow/run_phase.go→ introducetype RunPhase string.Priority 2 — Consolidation (higher effort, high impact)
MCPServerCallStats/MCPToolCallStatsand refactor the 4-5pkg/cliaudit/gateway structs to use them.RequestCounters{Total, Allowed, Denied}and apply acrossAnalysisBase/PolicyAnalysis/CrossRunSummary/PolicySummaryDisplay.map[string]anytool-config call sites onto the existingToolsConfigtype inpkg/workflow/tools_types.go.Priority 3 — Semantic clarity (lower urgency)
pkg/workflowandpkg/constants.QuerySensitivity,PermissionScope,JSONSchemaType,ModelMismatchReason,SecretName/EnvVarName).Implementation Checklist
getParsedSchemaDocreturn type and its 8 consumersRunSummaryinDownloadResultRedactedDomainsAnalysisinRedactedDomainsLogSummaryRunsOnValueinsafe_jobs.goRunPhasetype inpkg/workflowRequestCountersshared typeToolsConfigadoption acrossmcp_setup_gateway.go/mcp_renderer.go/gemini_mcp.goAnalysis Metadata
pkg/anylocations examined: ~300 (of ~1,250+ totalanyusages)All reactions