Overview
The file pkg/cli/experiments_command.go has grown to 1120 lines, making it difficult to maintain and test. This task involves refactoring it into smaller, focused files with improved test coverage.
Current State
- File:
pkg/cli/experiments_command.go
- Size: 1120 lines
- Test Coverage:
pkg/cli/experiments_command_test.go is 539 lines (~48% test-to-source ratio)
- Complexity: Contains ~40 top-level functions spanning several distinct concerns: CLI command wiring, list/analyze orchestration, remote & local data fetching (git branches, GitHub API), JSONL state parsing, git-ref safety validation, and console rendering.
Full File Analysis
Detailed Breakdown
Functions and their approximate responsibilities:
- Cobra command wiring (lines 94–195):
NewExperimentsCommand, NewExperimentsListSubcommand, NewExperimentsAnalyzeSubcommand
- Command orchestration (lines 195–330):
RunExperimentsList, RunExperimentsAnalyze, computeExperimentAnalyses
- Metric eval loading/summarizing (lines 331–411):
loadLocalMetricEvalResults, loadRemoteMetricEvalResults, summarizeMetricEvalResults
- Experiment config discovery (lines 412–612):
loadLocalExperimentConfigs, loadRemoteExperimentConfigs, findRemoteWorkflowFilenameForExperiment, matchWorkflowFilenameByExperiment, findWorkflowFileForExperiment, workflowFileCandidates
- Experiment listing/details fetch (local & remote) (lines 613–762):
fetchLocalExperiments, fetchRemoteExperiments, fetchLocalExperimentDetails, fetchRemoteExperimentDetails, experimentStateFilenames, readLocalExperimentState
- Git ref/path safety validation (lines 762–851):
buildSafeGitShowObjectArg, isSafeExperimentStateRef, isHexObjectIDPrefix, isSafeGitRefName, isSafeGitTreePath
- Experiment state parsing & aggregation (lines 851–1023):
readRemoteExperimentState, appendExperimentRun, parseExperimentStateJSONL, parseExperimentState, emptyExperimentState, experimentInfoFromState, experimentDetailsFromState, experimentTotalRuns, experimentLastRun, extractExperimentName, gitRefExists
- Rendering (lines 1024–1106):
printExperimentDetails, formatAssignments
- Generic helper (lines 1106+):
parsePagedJSONArray[T any]
Notable coupling/complexity:
- Local vs. remote variants of many functions (
fetchLocal*/fetchRemote*, loadLocal*/loadRemote*) duplicate structural logic while differing only in the data source (local git state vs. remote GitHub API), a strong signal for extracting a shared interface/abstraction.
- The git-ref/path safety validators (
isSafe*) are a self-contained security-sensitive module that would benefit from isolation and dedicated, exhaustive testing.
- JSONL/state parsing functions are independent of CLI/cobra concerns and could be moved to a state-only file.
Refactoring Strategy
Proposed File Splits
-
experiments_command.go (kept, slimmed down)
- Functions:
NewExperimentsCommand, NewExperimentsListSubcommand, NewExperimentsAnalyzeSubcommand, RunExperimentsList, RunExperimentsAnalyze, computeExperimentAnalyses
- Responsibility: Cobra command definitions and top-level orchestration only
- Estimated LOC: ~250
-
experiments_fetch.go
- Functions:
fetchLocalExperiments, fetchRemoteExperiments, fetchLocalExperimentDetails, fetchRemoteExperimentDetails, loadLocalExperimentConfigs, loadRemoteExperimentConfigs, findRemoteWorkflowFilenameForExperiment, matchWorkflowFilenameByExperiment, findWorkflowFileForExperiment, workflowFileCandidates, loadLocalMetricEvalResults, loadRemoteMetricEvalResults, summarizeMetricEvalResults
- Responsibility: Discovering and loading experiment configs/metrics from local git state and remote GitHub API
- Estimated LOC: ~420
-
experiments_state.go
- Functions:
experimentStateFilenames, readLocalExperimentState, readRemoteExperimentState, appendExperimentRun, parseExperimentStateJSONL, parseExperimentState, emptyExperimentState, experimentInfoFromState, experimentDetailsFromState, experimentTotalRuns, experimentLastRun, extractExperimentName, gitRefExists
- Responsibility: Parsing and aggregating experiment state (JSONL records → structured results), independent of CLI wiring
- Estimated LOC: ~270
-
experiments_git_safety.go
- Functions:
buildSafeGitShowObjectArg, isSafeExperimentStateRef, isHexObjectIDPrefix, isSafeGitRefName, isSafeGitTreePath
- Responsibility: Security-sensitive validation of git refs/paths used when reading experiment state via
git show
- Estimated LOC: ~90
-
experiments_render.go
- Functions:
printExperimentDetails, formatAssignments
- Responsibility: Console rendering of experiment details
- Estimated LOC: ~90
Shared Utilities
experiments_json_utils.go: Extract parsePagedJSONArray[T any] here since it's a generic helper usable by any paged-JSON-array consumer beyond experiments (or move to an existing generic utils file if one already fits, e.g. a shared json_utils.go).
Interface Abstractions
- Introduce a small
experimentDataSource interface (e.g., FetchExperiments() ([]ExperimentInfo, error), FetchExperimentDetails(id string) (*ExperimentDetails, error)) with localExperimentDataSource and remoteExperimentDataSource implementations. This removes the pervasive Local/Remote function-name duplication and lets RunExperimentsList/RunExperimentsAnalyze select an implementation based on repoOverride instead of branching per call site.
Test Coverage Plan
-
experiments_fetch_test.go
- Test cases: local config discovery with matching/mismatched workflow IDs, remote fetch fallback paths, metric eval summarization with malformed/empty JSON, workflow filename matching heuristics
- Target coverage: >80%
-
experiments_state_test.go
- Test cases: JSONL parsing with valid/partial/corrupt lines, state aggregation across multiple runs, empty-state defaults,
extractExperimentName edge cases (missing prefix, unusual ref formats)
- Target coverage: >80%
-
experiments_git_safety_test.go
- Test cases: valid/invalid git ref names, path traversal attempts in tree paths, hex object ID prefix boundary cases, injection attempts in
buildSafeGitShowObjectArg
- Target coverage: >90% (security-sensitive)
-
experiments_render_test.go
- Test cases: formatting assignments with empty/singleton/multiple entries, printing details with nil/partial fields
- Target coverage: >80%
Implementation Guidelines
- Preserve Behavior: Ensure all existing functionality works identically
- Maintain Exports: Keep public API unchanged (exported functions/types)
- Add Tests First: Write tests for each new file before refactoring
- Incremental Changes: Split one module at a time
- Run Tests Frequently: Verify
make test-unit passes after each split
- Update Imports: Ensure all import paths are correct
- Document Changes: Add comments explaining module boundaries
Acceptance Criteria
Additional Context
- Repository Guidelines: Follow patterns in
.github/agents/developer.instructions.agent.md
- Code Organization: Prefer many small files grouped by functionality
- Testing: Match existing test patterns in
pkg/cli/*_test.go
Priority: Medium
Effort: Medium (5 new files, existing test coverage at ~48% needs to grow alongside the split)
Expected Impact: Improved maintainability, easier testing, reduced complexity
Generated by 🧹 Daily File Diet · auto · 89.6 AIC · ⌖ 11.3 AIC · ⊞ 10.1K · ◷
Overview
The file
pkg/cli/experiments_command.gohas grown to 1120 lines, making it difficult to maintain and test. This task involves refactoring it into smaller, focused files with improved test coverage.Current State
pkg/cli/experiments_command.gopkg/cli/experiments_command_test.gois 539 lines (~48% test-to-source ratio)Full File Analysis
Detailed Breakdown
Functions and their approximate responsibilities:
NewExperimentsCommand,NewExperimentsListSubcommand,NewExperimentsAnalyzeSubcommandRunExperimentsList,RunExperimentsAnalyze,computeExperimentAnalysesloadLocalMetricEvalResults,loadRemoteMetricEvalResults,summarizeMetricEvalResultsloadLocalExperimentConfigs,loadRemoteExperimentConfigs,findRemoteWorkflowFilenameForExperiment,matchWorkflowFilenameByExperiment,findWorkflowFileForExperiment,workflowFileCandidatesfetchLocalExperiments,fetchRemoteExperiments,fetchLocalExperimentDetails,fetchRemoteExperimentDetails,experimentStateFilenames,readLocalExperimentStatebuildSafeGitShowObjectArg,isSafeExperimentStateRef,isHexObjectIDPrefix,isSafeGitRefName,isSafeGitTreePathreadRemoteExperimentState,appendExperimentRun,parseExperimentStateJSONL,parseExperimentState,emptyExperimentState,experimentInfoFromState,experimentDetailsFromState,experimentTotalRuns,experimentLastRun,extractExperimentName,gitRefExistsprintExperimentDetails,formatAssignmentsparsePagedJSONArray[T any]Notable coupling/complexity:
fetchLocal*/fetchRemote*,loadLocal*/loadRemote*) duplicate structural logic while differing only in the data source (local git state vs. remote GitHub API), a strong signal for extracting a shared interface/abstraction.isSafe*) are a self-contained security-sensitive module that would benefit from isolation and dedicated, exhaustive testing.Refactoring Strategy
Proposed File Splits
experiments_command.go(kept, slimmed down)NewExperimentsCommand,NewExperimentsListSubcommand,NewExperimentsAnalyzeSubcommand,RunExperimentsList,RunExperimentsAnalyze,computeExperimentAnalysesexperiments_fetch.gofetchLocalExperiments,fetchRemoteExperiments,fetchLocalExperimentDetails,fetchRemoteExperimentDetails,loadLocalExperimentConfigs,loadRemoteExperimentConfigs,findRemoteWorkflowFilenameForExperiment,matchWorkflowFilenameByExperiment,findWorkflowFileForExperiment,workflowFileCandidates,loadLocalMetricEvalResults,loadRemoteMetricEvalResults,summarizeMetricEvalResultsexperiments_state.goexperimentStateFilenames,readLocalExperimentState,readRemoteExperimentState,appendExperimentRun,parseExperimentStateJSONL,parseExperimentState,emptyExperimentState,experimentInfoFromState,experimentDetailsFromState,experimentTotalRuns,experimentLastRun,extractExperimentName,gitRefExistsexperiments_git_safety.gobuildSafeGitShowObjectArg,isSafeExperimentStateRef,isHexObjectIDPrefix,isSafeGitRefName,isSafeGitTreePathgit showexperiments_render.goprintExperimentDetails,formatAssignmentsShared Utilities
experiments_json_utils.go: ExtractparsePagedJSONArray[T any]here since it's a generic helper usable by any paged-JSON-array consumer beyond experiments (or move to an existing generic utils file if one already fits, e.g. a sharedjson_utils.go).Interface Abstractions
experimentDataSourceinterface (e.g.,FetchExperiments() ([]ExperimentInfo, error),FetchExperimentDetails(id string) (*ExperimentDetails, error)) withlocalExperimentDataSourceandremoteExperimentDataSourceimplementations. This removes the pervasiveLocal/Remotefunction-name duplication and letsRunExperimentsList/RunExperimentsAnalyzeselect an implementation based onrepoOverrideinstead of branching per call site.Test Coverage Plan
experiments_fetch_test.goexperiments_state_test.goextractExperimentNameedge cases (missing prefix, unusual ref formats)experiments_git_safety_test.gobuildSafeGitShowObjectArgexperiments_render_test.goImplementation Guidelines
make test-unitpasses after each splitAcceptance Criteria
make test-unit)make lint)make build)Additional Context
.github/agents/developer.instructions.agent.mdpkg/cli/*_test.goPriority: Medium
Effort: Medium (5 new files, existing test coverage at ~48% needs to grow alongside the split)
Expected Impact: Improved maintainability, easier testing, reduced complexity