RunExperimentsAnalyze analyzes a specific experiment branch.
(config ExperimentsAnalyzeConfig)
| 231 | |
| 232 | // RunExperimentsAnalyze analyzes a specific experiment branch. |
| 233 | func RunExperimentsAnalyze(config ExperimentsAnalyzeConfig) error { |
| 234 | experimentsLog.Printf("Analyzing experiment: name=%s, repo=%s, json=%v", |
| 235 | config.ExperimentName, config.RepoOverride, config.JSONOutput) |
| 236 | |
| 237 | branchName := experimentsBranchPrefix + config.ExperimentName |
| 238 | |
| 239 | // Load experiment configs from the workflow frontmatter to enrich the statistical output |
| 240 | // with hypothesis text, analysis_type, min_samples, and guardrail thresholds. |
| 241 | // Config loading is best-effort: failures are silently ignored and analysis falls back to |
| 242 | // defaults (min_samples=20, equal expected proportions, no hypothesis displayed). |
| 243 | // This ensures the command remains functional even when the workflow .md file is absent |
| 244 | // (e.g., when analysing experiments from a remote repository without the workflow checked out). |
| 245 | var experimentConfigs map[string]*workflow.ExperimentConfig |
| 246 | if config.RepoOverride != "" { |
| 247 | experimentConfigs = loadRemoteExperimentConfigs(config.RepoOverride, config.ExperimentName) |
| 248 | } else { |
| 249 | experimentConfigs = loadLocalExperimentConfigs(config.ExperimentName) |
| 250 | } |
| 251 | experimentsLog.Printf("Loaded %d experiment config(s) for %s", len(experimentConfigs), config.ExperimentName) |
| 252 | |
| 253 | var details *ExperimentDetails |
| 254 | var err error |
| 255 | |
| 256 | if config.RepoOverride != "" { |
| 257 | details, err = fetchRemoteExperimentDetails(config.RepoOverride, branchName, config.ExperimentName) |
| 258 | } else { |
| 259 | details, err = fetchLocalExperimentDetails(branchName, config.ExperimentName) |
| 260 | } |
| 261 | |
| 262 | if err != nil { |
| 263 | fmt.Fprintln(os.Stderr, console.FormatErrorMessage(err.Error())) |
| 264 | return nil |
| 265 | } |
| 266 | |
| 267 | // Compute statistical analyses for each named experiment. |
| 268 | details.Analyses = computeExperimentAnalyses(details.Experiments, experimentConfigs) |
| 269 | |
| 270 | if config.JSONOutput { |
| 271 | jsonBytes, err := json.MarshalIndent(details, "", " ") |
| 272 | if err != nil { |
| 273 | return fmt.Errorf("failed to marshal JSON: %w", err) |
| 274 | } |
| 275 | fmt.Fprintln(os.Stdout, string(jsonBytes)) |
| 276 | return nil |
| 277 | } |
| 278 | |
| 279 | printExperimentDetails(details) |
| 280 | return nil |
| 281 | } |
| 282 | |
| 283 | // computeExperimentAnalyses computes statistical analyses for all named experiments. |
| 284 | // configs maps experiment names to their configuration; values may be nil. |
no test coverage detected