// runRepo + runScrum are Phase B entry points. Phase A leaves them // as compilable stubs that produce the JSON shapes the gates expect // but with zero analyzer findings — letting the pipeline structure // be exercised end-to-end before analyzers land. package cli import ( "context" "fmt" "os" "path/filepath" "local-review-harness/internal/config" "local-review-harness/internal/pipeline" ) func runRepo(ctx context.Context, repoPath string, cf commonFlags) int { if _, err := os.Stat(repoPath); err != nil { fmt.Fprintln(os.Stderr, "repo: target path:", err) return 65 } rp, err := config.LoadReviewProfile(cf.reviewProfilePath) if err != nil { fmt.Fprintln(os.Stderr, "config:", err) return 65 } mp, err := config.LoadModelProfile(cf.modelProfilePath) if err != nil { fmt.Fprintln(os.Stderr, "config:", err) return 65 } outDir := resolveOutputDir(&cf, rp, repoPath) res, err := pipeline.RunRepo(ctx, pipeline.Inputs{ RepoPath: repoPath, ReviewProfile: rp, ModelProfile: mp, OutputDir: outDir, EmitScrum: false, EnableLLM: cf.enableLLM, }) if err != nil { fmt.Fprintln(os.Stderr, "pipeline:", err) return 65 } for _, f := range res.OutputFiles { fmt.Println(filepath.Join(outDir, f)) } return res.ExitCode } func runScrum(ctx context.Context, repoPath string, cf commonFlags) int { if _, err := os.Stat(repoPath); err != nil { fmt.Fprintln(os.Stderr, "scrum: target path:", err) return 65 } rp, err := config.LoadReviewProfile(cf.reviewProfilePath) if err != nil { fmt.Fprintln(os.Stderr, "config:", err) return 65 } mp, err := config.LoadModelProfile(cf.modelProfilePath) if err != nil { fmt.Fprintln(os.Stderr, "config:", err) return 65 } outDir := resolveOutputDir(&cf, rp, repoPath) res, err := pipeline.RunRepo(ctx, pipeline.Inputs{ RepoPath: repoPath, ReviewProfile: rp, ModelProfile: mp, OutputDir: outDir, EmitScrum: true, EnableLLM: cf.enableLLM, }) if err != nil { fmt.Fprintln(os.Stderr, "pipeline:", err) return 65 } for _, f := range res.OutputFiles { fmt.Println(filepath.Join(outDir, f)) } return res.ExitCode }