Skip to content

[refactor] Semantic Function Clustering: Refactoring Opportunities in Go Source Files #3315

@github-actions

Description

@github-actions

Overview

Automated semantic function clustering analysis of 98 non-test Go files across 26 packages. The previous cycle's items remain unresolved — helper function misplacement in cmd/root.go and server/difc_log.go, response reshaping helpers in proxy/handler.go, and a set of oversized files combining distinct responsibilities. Several files have grown slightly since the last analysis (config/validation.go, config/validation_schema.go, mcp/connection.go), reinforcing the need to split them before they become harder to navigate.


Progress Since Last Analysis

Item Status
Move ExpandEnvArgs to internal/envutil/ Done
Extract CLI flags from cmd/root.go Done (split into flags_core.go, flags_difc.go, flags_launch.go, flags_logging.go, flags_tracing.go)
Move cmd/root.go helpers to run_helpers.go ⬜ Open
Extract generic JSON helpers from server/difc_log.go ⬜ Open
Extract response helpers from proxy/handler.go ⬜ Open
Split oversized files (9 critical, 7 moderate) ⬜ Open

1. Misplaced Functions

1a. Helper functions embedded in cmd/root.go (669 lines)

Despite successful flag extraction, four substantial helpers remain alongside the core CLI lifecycle (init, preRun, run, postRun, Execute, SetVersion):

Function Line Nature
resolveGuardPolicyOverride 448 Guard policy resolution logic
writeGatewayConfigToStdout 502 Config serialization
writeGatewayConfig 506 Config serialization to writer
loadEnvFile 608 .env file parsing

Recommendation: Move these four functions to a new internal/cmd/run_helpers.go, keeping root.go focused on CLI lifecycle wiring only.

Effort: < 1 hour


1b. Generic JSON map helpers in server/difc_log.go

internal/server/difc_log.go:64–103 contains three domain-agnostic JSON traversal helpers:

func getStringField(m map[string]interface{}, fields ...string) string { ... }
func extractAuthorLogin(m map[string]interface{}) string { ... }
func extractNumberField(m map[string]interface{}) string { ... }

These are general-purpose map accessors, not specific to DIFC logging. internal/proxy/handler.go independently operates on map[string]interface{} values, confirming the risk of future reinvention.

Recommendation (minimal): Add a comment marking them as local helpers to deter copy-paste.
Recommendation (better): Extract to internal/maputil/ package for shared use.

Effort: 1–2 hours (if extracting to maputil)


1c. Response reshaping helpers in proxy/handler.go (562 lines)

internal/proxy/handler.go intermingles HTTP handler logic with JSON response transformation functions:

func rewrapSearchResponse(originalData interface{}, filteredItems interface{}) interface{} { ... }  // line 425
func unwrapSingleObject(originalData interface{}, filteredData interface{}) interface{} { ... }      // line 459
func rebuildGraphQLResponse(originalData interface{}, filtered *difc.FilteredCollectionLabeledData) interface{} { ... } // line 481
func replaceNodesArray(v interface{}, items []interface{}) bool { ... }                              // line 521
func deepCloneJSON(v interface{}) interface{} { ... }                                               // line 545

These five JSON transformation/reshaping helpers have no HTTP handler semantics — they operate purely on data structures.

Recommendation: Extract to internal/proxy/response_helpers.go to give the handler file a single clear responsibility (HTTP routing + DIFC integration).

Effort: 30–60 min


1d. Logging helpers in config/validation.go (609 lines)

Three logging helpers are embedded among validation logic:

func logValidateServerStart(name, serverType string) { ... }   // line 33
func logValidateServerPassed(name string) { ... }              // line 38
func logValidateServerFailed(name, reason string) { ... }      // line 43

Recommendation: Move to a dedicated internal/config/validation_log.go, or inline the single-line bodies into their call sites.

Effort: 15–30 min


2. Oversized Files — Candidates for Decomposition

Files combining multiple distinct responsibilities. All suggested splits stay within the same package; no exported API changes since all are under internal/.

2a. internal/guard/wasm.go1,168 lines ⚠️ CRITICAL

Five distinct responsibilities:

Responsibility Key Functions Suggested File
Guard lifecycle NewWasmGuard*, Close keep in wasm.go
WASM runtime / memory management callWasmFunction, tryCallWasmFunction, wasmAlloc, wasmDealloc, isWasmTrap wasm_runtime.go
Host function bindings instantiateHostFunctions, hostCallBackend, hostLog wasm_host.go
Payload building BuildLabelAgentPayload, buildStrictLabelAgentPayload, normalizePolicyPayload wasm_payload.go
Response parsing parseLabelAgentResponse, parseResourceResponse, parseCollectionLabeledData wasm_parse.go

Recommendation: Split into wasm.go + wasm_runtime.go + wasm_host.go + wasm_payload.go + wasm_parse.go.

Effort: 3–4 hours


2b. internal/config/guard_policy.go721 lines

Four distinct responsibilities:

Responsibility Suggested File
Core types + (un)marshaling keep in guard_policy.go
Validation (ValidateGuardPolicy, ValidateWriteSinkPolicy, validateAcceptEntry, isValidRepo*) guard_policy_validate.go
Parsing (ParseGuardPolicyJSON, ParsePolicyMap, ParseServerGuardPolicy, BuildAllowOnlyPolicy) guard_policy_parse.go
Normalization (NormalizeGuardPolicy, normalizeAndValidateScopeArray, NormalizeScopeKind) guard_policy_normalize.go

Effort: 2–3 hours


2c. internal/server/unified.go758 lines

Combines server setup, tool execution, DIFC integration, backend calling, lifecycle/shutdown, and env lookups:

Responsibility Key Functions Suggested File
Core server + lifecycle NewUnified, Run, Close, IsShutdown, InitiateShutdown, ShouldExit, SetHTTPShutdown, GetHTTPShutdown keep in unified.go
Tool execution + backend calling callBackendTool, executeBackendToolCall, newErrorCallToolResult, guardBackendCaller unified_tools.go
Env lookups lookupEnrichmentToken, lookupGitHubAPIBaseURL unified_env.go
Status / introspection GetServerIDs, GetServerStatus, GetToolsForBackend, GetToolHandler, GetPayloadSizeThreshold, IsDIFCEnabled, RegisterTestTool, SetTestMode unified_status.go

Effort: 3–4 hours


2d. internal/mcp/connection.go690 lines (+10 since last analysis)

Mixes connection construction, reconnection, session management, and MCP method wrappers:

Responsibility Suggested File
Core connection lifecycle keep in connection.go
Send / reconnect logic connection_send.go
MCP method wrappers (listTools, callTool, listResources, getPrompt, etc.) connection_methods.go

Effort: 2–3 hours


2e. internal/mcp/http_transport.go643 lines

Mixes client construction, transport probing, and request/response handling:

Responsibility Suggested File
Client construction + RoundTrip keep in http_transport.go
Transport probing (trySDKTransport, tryStreamableHTTPTransport, trySSETransport, tryPlainJSONTransport) http_transport_probe.go
Request execution + parsing (setupHTTPRequest, executeHTTPRequest, initializeHTTPSession) http_transport_request.go

Effort: 2–3 hours


2f. internal/config/validation.go609 lines (+5 since last analysis)

Mixes variable expansion, mount validation, server config validation, auth validation, gateway validation, and trusted bots validation:

Responsibility Suggested File
Variable expansion + core dispatch keep in validation.go
Mount + standard server validation validation_server.go
Auth + gateway + trusted-bots validation validation_auth.go

Effort: 2–3 hours


2g. internal/config/validation_schema.go560 lines (+10 since last analysis)

Mixes schema fetching, compilation/validation, and error formatting:

Responsibility Suggested File
Schema fetching + HTTP retry (isTransientHTTPError, fetchAndFixSchema, fixSchemaBytes) validation_schema_fetch.go
Schema compilation + validation (getOrCompileSchema, validateJSONSchema) keep in validation_schema.go
Error formatting (formatSchemaError, formatValidationErrorRecursive, formatErrorContext) validation_schema_format.go

Effort: 1–2 hours


2h. internal/config/config_stdin.go540 lines (+4 since last analysis)

Mixes JSON parsing, type conversion/normalization, field stripping, and variable expansion:

Responsibility Suggested File
JSON parsing + top-level loading (LoadFromStdin, UnmarshalJSON, stripExtensionFieldsForValidation) keep in config_stdin.go
Type conversion + normalization (convertStdinConfig, convertStdinServerConfig, buildStdioServerConfig, normalizeLocalType) config_stdin_convert.go

Effort: 1–2 hours


2i. Other large files (moderate priority)

File Lines Suggested Action
internal/middleware/jqschema.go 456 Split schema transform from file I/O for payloads (jqschema_storage.go)
internal/difc/evaluator.go 449 Split flow evaluation from label formatting helpers (evaluator_format.go)
internal/proxy/router.go 444 Separate route table data from routing logic (routes.go)
internal/proxy/proxy.go 419 Split proxy core from middleware/transport configuration
internal/server/guard_init.go 414 Split guard registration from policy resolution and WASM discovery
internal/server/tool_registry.go 421 Split tool registration from parallel/sequential launch strategies
internal/difc/labels.go 404 28 functions; consider splitting label operations from label constructors

3. Intentional Patterns (No Action Needed)

  • withLock on each logger type — identical body per type; correct because each is on a different receiver.
  • setup*Logger / handle*LoggerError — different fallback strategies per logger type; differentiation is intentional.
  • Log{Info,Warn,Error,Debug}[WithServer] families — one-liner wrappers with distinct signatures; idiomatic Go.
  • Session ID extraction split (extractAndValidateSession vs SessionIDFromContext) — different extraction points (header vs. context).
  • paginateAll[T]() — generic pagination helper, correctly placed in connection.go.
  • randomSerial() vs GenerateRandomAPIKey() vs generateRandomSpanID() — similar crypto-random patterns serving distinct purposes (TLS cert serial, API key, tracing span ID).
  • getDefault* functions in flags_*.go — 13 functions following the same pattern; each reads a specific env var with type-appropriate fallback.
  • resolve* functions in tracing/provider.go — 5 functions resolving different fields of TracingConfig.
  • launcher/log_helpers.go — logging helpers correctly extracted into their own file ✅.

Refactoring Recommendations

Quick Wins (< 1 hour each)

  • Move cmd/root.go helpers (resolveGuardPolicyOverride, writeGatewayConfig, loadEnvFile) to internal/cmd/run_helpers.go
  • Extract response reshaping functions from proxy/handler.go to proxy/response_helpers.go
  • Move or inline 3 log helpers from config/validation.go

Medium Effort — split large files (no API breakage, all internal/)

  • Split guard/wasm.gowasm.go + wasm_runtime.go + wasm_host.go + wasm_payload.go + wasm_parse.go
  • Split config/guard_policy.go → core + _validate.go + _parse.go + _normalize.go
  • Split server/unified.go → core + unified_tools.go + unified_env.go + unified_status.go
  • Split mcp/connection.go → core + connection_send.go + connection_methods.go
  • Split mcp/http_transport.go → core + http_transport_probe.go + http_transport_request.go
  • Split config/validation_schema.go → core + _fetch.go + _format.go
  • Split config/config_stdin.go → parser + _convert.go
  • Split config/validation.go → core + validation_server.go + validation_auth.go

Optional / Longer Term

  • Extract getStringField/extractAuthorLogin/extractNumberField from server/difc_log.go to internal/maputil/
  • Review and split remaining 400+ line files in proxy/, middleware/, difc/, server/

Analysis Metadata

Metric Value
Go files analyzed (non-test) 98
Packages covered 26
Resolved since last analysis 0 (no changes in this cycle)
Cumulative resolved items 2 (ExpandEnvArgsenvutil/, CLI flags split)
Misplaced functions identified 7 (4 in cmd/root.go, 3 in server/difc_log.go)
Response helpers to extract 5 (from proxy/handler.go)
Files recommended for split (critical) 8
Files recommended for split (moderate) 7
Analysis date 2026-04-07

References: §24077006028

Generated by Semantic Function Refactoring · ● 440.3K ·

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions