[object Object]

← back to Cli Printing Press

fix(pipeline): clean generated cli artifacts

421c81bdcbb83d7a2d35e7c1e1f6d206ae804416 · 2026-03-28 01:35:03 -0700 · Trevin Chow

Clean up disposable binaries and recursive generated copies around validation and verification without breaking iterative work.
Keep the runtime verify binary and build cache until explicit cleanup, and add coverage for the new artifact lifecycle.

Files touched

Diff

commit 421c81bdcbb83d7a2d35e7c1e1f6d206ae804416
Author: Trevin Chow <trevin@trevinchow.com>
Date:   Sat Mar 28 01:35:03 2026 -0700

    fix(pipeline): clean generated cli artifacts
    
    Clean up disposable binaries and recursive generated copies around validation and verification without breaking iterative work.
    Keep the runtime verify binary and build cache until explicit cleanup, and add coverage for the new artifact lifecycle.
---
 internal/artifacts/cleanup.go        | 99 ++++++++++++++++++++++++++++++++++++
 internal/artifacts/cleanup_test.go   | 52 +++++++++++++++++++
 internal/cli/verify.go               | 36 +++++++++++++
 internal/cli/verify_test.go          | 39 ++++++++++++++
 internal/generator/generator_test.go |  1 +
 internal/generator/validate.go       | 16 ++++++
 internal/pipeline/dogfood.go         | 17 ++++---
 internal/pipeline/fullrun.go         |  1 +
 internal/pipeline/runtime.go         | 42 +++++++++------
 internal/pipeline/runtime_test.go    | 60 ++++++++++++++++++++++
 internal/pipeline/verify.go          | 10 ++++
 11 files changed, 349 insertions(+), 24 deletions(-)

diff --git a/internal/artifacts/cleanup.go b/internal/artifacts/cleanup.go
new file mode 100644
index 00000000..62a8e937
--- /dev/null
+++ b/internal/artifacts/cleanup.go
@@ -0,0 +1,99 @@
+package artifacts
+
+import (
+	"errors"
+	"os"
+	"path/filepath"
+	"strings"
+)
+
+// CleanupOptions controls which generated artifacts to remove.
+type CleanupOptions struct {
+	RemoveCache              bool
+	RemoveRuntimeBinary      bool
+	RemoveValidationBinaries bool
+	RemoveDogfoodBinaries    bool
+	RemoveRecursiveCopies    bool
+	RemoveFinderMetadata     bool
+}
+
+// CleanupGeneratedCLI removes reproducible artifacts from a generated CLI tree.
+func CleanupGeneratedCLI(dir string, opts CleanupOptions) error {
+	var errs []error
+
+	if opts.RemoveRuntimeBinary {
+		name := filepath.Base(filepath.Clean(dir))
+		if name != "." && name != string(filepath.Separator) {
+			errs = append(errs, removeFileIfExists(filepath.Join(dir, name)))
+		}
+	}
+
+	if opts.RemoveValidationBinaries || opts.RemoveDogfoodBinaries {
+		entries, err := os.ReadDir(dir)
+		if err != nil && !os.IsNotExist(err) {
+			errs = append(errs, err)
+		}
+		for _, entry := range entries {
+			if entry.IsDir() {
+				continue
+			}
+			name := entry.Name()
+			switch {
+			case opts.RemoveValidationBinaries && strings.HasSuffix(name, "-validation"):
+				errs = append(errs, removeFileIfExists(filepath.Join(dir, name)))
+			case opts.RemoveDogfoodBinaries && strings.HasSuffix(name, "-dogfood"):
+				errs = append(errs, removeFileIfExists(filepath.Join(dir, name)))
+			}
+		}
+	}
+
+	if opts.RemoveRecursiveCopies {
+		errs = append(errs, removeDirIfExists(filepath.Join(dir, "cmd", "library")))
+	}
+
+	if opts.RemoveFinderMetadata {
+		errs = append(errs, removeFinderMetadata(dir))
+	}
+
+	if opts.RemoveCache {
+		errs = append(errs, removeDirIfExists(filepath.Join(dir, ".cache")))
+	}
+
+	return errors.Join(errs...)
+}
+
+func removeFinderMetadata(root string) error {
+	var errs []error
+	walkErr := filepath.WalkDir(root, func(path string, d os.DirEntry, err error) error {
+		if err != nil {
+			errs = append(errs, err)
+			return nil
+		}
+		if d.IsDir() || d.Name() != ".DS_Store" {
+			return nil
+		}
+		errs = append(errs, removeFileIfExists(path))
+		return nil
+	})
+	if walkErr != nil {
+		errs = append(errs, walkErr)
+	}
+	return errors.Join(errs...)
+}
+
+func removeFileIfExists(path string) error {
+	if err := os.Remove(path); err != nil && !os.IsNotExist(err) {
+		return err
+	}
+	return nil
+}
+
+func removeDirIfExists(path string) error {
+	if _, err := os.Stat(path); err != nil {
+		if os.IsNotExist(err) {
+			return nil
+		}
+		return err
+	}
+	return os.RemoveAll(path)
+}
diff --git a/internal/artifacts/cleanup_test.go b/internal/artifacts/cleanup_test.go
new file mode 100644
index 00000000..a2bceb41
--- /dev/null
+++ b/internal/artifacts/cleanup_test.go
@@ -0,0 +1,52 @@
+package artifacts
+
+import (
+	"os"
+	"path/filepath"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+)
+
+func TestCleanupGeneratedCLI(t *testing.T) {
+	dir := filepath.Join(t.TempDir(), "sample-cli")
+	require.NoError(t, os.MkdirAll(filepath.Join(dir, "cmd", "library", "sample-cli"), 0o755))
+	require.NoError(t, os.MkdirAll(filepath.Join(dir, ".cache", "go-build"), 0o755))
+	require.NoError(t, os.MkdirAll(filepath.Join(dir, "nested"), 0o755))
+
+	writeArtifactFile(t, filepath.Join(dir, "sample-cli"))
+	writeArtifactFile(t, filepath.Join(dir, "sample-cli-validation"))
+	writeArtifactFile(t, filepath.Join(dir, "sample-cli-dogfood"))
+	writeArtifactFile(t, filepath.Join(dir, ".DS_Store"))
+	writeArtifactFile(t, filepath.Join(dir, "nested", ".DS_Store"))
+	writeArtifactFile(t, filepath.Join(dir, ".cache", "go-build", "index"))
+	writeArtifactFile(t, filepath.Join(dir, "cmd", "library", "sample-cli", "main.go"))
+
+	err := CleanupGeneratedCLI(dir, CleanupOptions{
+		RemoveRuntimeBinary:      true,
+		RemoveValidationBinaries: true,
+		RemoveDogfoodBinaries:    true,
+		RemoveRecursiveCopies:    true,
+		RemoveFinderMetadata:     true,
+	})
+	require.NoError(t, err)
+
+	assert.NoFileExists(t, filepath.Join(dir, "sample-cli"))
+	assert.NoFileExists(t, filepath.Join(dir, "sample-cli-validation"))
+	assert.NoFileExists(t, filepath.Join(dir, "sample-cli-dogfood"))
+	assert.NoFileExists(t, filepath.Join(dir, ".DS_Store"))
+	assert.NoFileExists(t, filepath.Join(dir, "nested", ".DS_Store"))
+	assert.NoDirExists(t, filepath.Join(dir, "cmd", "library"))
+	assert.DirExists(t, filepath.Join(dir, ".cache"))
+
+	err = CleanupGeneratedCLI(dir, CleanupOptions{RemoveCache: true})
+	require.NoError(t, err)
+	assert.NoDirExists(t, filepath.Join(dir, ".cache"))
+}
+
+func writeArtifactFile(t *testing.T, path string) {
+	t.Helper()
+	require.NoError(t, os.MkdirAll(filepath.Dir(path), 0o755))
+	require.NoError(t, os.WriteFile(path, []byte("artifact"), 0o644))
+}
diff --git a/internal/cli/verify.go b/internal/cli/verify.go
index 165c7695..8f29f00d 100644
--- a/internal/cli/verify.go
+++ b/internal/cli/verify.go
@@ -4,7 +4,9 @@ import (
 	"encoding/json"
 	"fmt"
 	"os"
+	"path/filepath"
 
+	"github.com/mvanhorn/cli-printing-press/internal/artifacts"
 	"github.com/mvanhorn/cli-printing-press/internal/pipeline"
 	"github.com/spf13/cobra"
 )
@@ -18,6 +20,7 @@ func newVerifyCmd() *cobra.Command {
 	var fix bool
 	var maxIterations int
 	var asJSON bool
+	var cleanup bool
 
 	cmd := &cobra.Command{
 		Use:   "verify",
@@ -39,6 +42,9 @@ Use --fix to auto-patch common failures and re-test (max 3 iterations).`,
   # Auto-fix failures and re-test
   printing-press verify --dir ./github-cli --spec /tmp/spec.json --fix
 
+  # Remove transient build artifacts after the final verification pass
+  printing-press verify --dir ./github-cli --spec /tmp/spec.json --cleanup
+
   # Set pass threshold and output JSON
   printing-press verify --dir ./github-cli --spec /tmp/spec.json --threshold 70 --json`,
 		RunE: func(cmd *cobra.Command, args []string) error {
@@ -68,6 +74,10 @@ Use --fix to auto-patch common failures and re-test (max 3 iterations).`,
 				}
 			}
 
+			if err := cleanupVerifyArtifacts(dir, cleanup); err != nil {
+				return err
+			}
+
 			if asJSON {
 				output := map[string]any{"verify": report}
 				if fixReport != nil {
@@ -103,6 +113,7 @@ Use --fix to auto-patch common failures and re-test (max 3 iterations).`,
 	cmd.Flags().BoolVar(&fix, "fix", false, "Auto-fix common failures and re-test")
 	cmd.Flags().IntVar(&maxIterations, "max-iterations", 3, "Maximum fix loop iterations")
 	cmd.Flags().BoolVar(&asJSON, "json", false, "Output as JSON")
+	cmd.Flags().BoolVar(&cleanup, "cleanup", false, "Remove transient build artifacts after verification")
 	_ = cmd.MarkFlagRequired("dir")
 	return cmd
 }
@@ -130,6 +141,31 @@ func printVerifyReport(report *pipeline.VerifyReport) {
 	fmt.Printf("Verdict: %s\n", report.Verdict)
 }
 
+func cleanupVerifyArtifacts(dir string, cleanup bool) error {
+	if !cleanup {
+		return nil
+	}
+	if dir == "" {
+		return fmt.Errorf("cleaning generated artifacts: empty dir")
+	}
+	if !filepath.IsAbs(dir) {
+		if absDir, err := filepath.Abs(dir); err == nil {
+			dir = absDir
+		}
+	}
+	if err := artifacts.CleanupGeneratedCLI(dir, artifacts.CleanupOptions{
+		RemoveCache:              true,
+		RemoveRuntimeBinary:      true,
+		RemoveValidationBinaries: true,
+		RemoveDogfoodBinaries:    true,
+		RemoveRecursiveCopies:    true,
+		RemoveFinderMetadata:     true,
+	}); err != nil {
+		return fmt.Errorf("cleaning generated artifacts: %w", err)
+	}
+	return nil
+}
+
 func passFail(b bool) string {
 	if b {
 		return "PASS"
diff --git a/internal/cli/verify_test.go b/internal/cli/verify_test.go
new file mode 100644
index 00000000..ba477863
--- /dev/null
+++ b/internal/cli/verify_test.go
@@ -0,0 +1,39 @@
+package cli
+
+import (
+	"os"
+	"path/filepath"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+)
+
+func TestCleanupVerifyArtifacts(t *testing.T) {
+	dir := filepath.Join(t.TempDir(), "sample-cli")
+	require.NoError(t, os.MkdirAll(filepath.Join(dir, ".cache", "go-build"), 0o755))
+	require.NoError(t, os.MkdirAll(filepath.Join(dir, "cmd", "library", "sample-cli"), 0o755))
+	require.NoError(t, os.WriteFile(filepath.Join(dir, "sample-cli"), []byte("bin"), 0o755))
+	require.NoError(t, os.WriteFile(filepath.Join(dir, "sample-cli-validation"), []byte("bin"), 0o755))
+	require.NoError(t, os.WriteFile(filepath.Join(dir, "sample-cli-dogfood"), []byte("bin"), 0o755))
+	require.NoError(t, os.WriteFile(filepath.Join(dir, ".DS_Store"), []byte("finder"), 0o644))
+
+	require.NoError(t, cleanupVerifyArtifacts(dir, true))
+
+	assert.NoFileExists(t, filepath.Join(dir, "sample-cli"))
+	assert.NoFileExists(t, filepath.Join(dir, "sample-cli-validation"))
+	assert.NoFileExists(t, filepath.Join(dir, "sample-cli-dogfood"))
+	assert.NoFileExists(t, filepath.Join(dir, ".DS_Store"))
+	assert.NoDirExists(t, filepath.Join(dir, ".cache"))
+	assert.NoDirExists(t, filepath.Join(dir, "cmd", "library"))
+}
+
+func TestCleanupVerifyArtifacts_NoOpWhenDisabled(t *testing.T) {
+	dir := filepath.Join(t.TempDir(), "sample-cli")
+	require.NoError(t, os.MkdirAll(dir, 0o755))
+	require.NoError(t, os.WriteFile(filepath.Join(dir, "sample-cli"), []byte("bin"), 0o755))
+
+	require.NoError(t, cleanupVerifyArtifacts(dir, false))
+
+	assert.FileExists(t, filepath.Join(dir, "sample-cli"))
+}
diff --git a/internal/generator/generator_test.go b/internal/generator/generator_test.go
index 2b965183..9dfc3ebb 100644
--- a/internal/generator/generator_test.go
+++ b/internal/generator/generator_test.go
@@ -143,6 +143,7 @@ func TestGenerateWithNoAuth(t *testing.T) {
 	gen := New(apiSpec, outputDir)
 	require.NoError(t, gen.Generate())
 	require.NoError(t, gen.Validate())
+	assert.NoFileExists(t, filepath.Join(outputDir, "noauth-cli-validation"))
 }
 
 func TestGenerateWithOwnerField(t *testing.T) {
diff --git a/internal/generator/validate.go b/internal/generator/validate.go
index 2080e0d0..7a290241 100644
--- a/internal/generator/validate.go
+++ b/internal/generator/validate.go
@@ -9,6 +9,8 @@ import (
 	"path/filepath"
 	"strings"
 	"time"
+
+	"github.com/mvanhorn/cli-printing-press/internal/artifacts"
 )
 
 type validationGate struct {
@@ -18,6 +20,20 @@ type validationGate struct {
 
 func (g *Generator) Validate() error {
 	binPath := filepath.Join(g.OutputDir, g.Spec.Name+"-cli-validation")
+	if err := artifacts.CleanupGeneratedCLI(g.OutputDir, artifacts.CleanupOptions{
+		RemoveValidationBinaries: true,
+		RemoveRecursiveCopies:    true,
+		RemoveFinderMetadata:     true,
+	}); err != nil {
+		return fmt.Errorf("pre-validating cleanup: %w", err)
+	}
+	defer func() {
+		_ = artifacts.CleanupGeneratedCLI(g.OutputDir, artifacts.CleanupOptions{
+			RemoveValidationBinaries: true,
+			RemoveRecursiveCopies:    true,
+			RemoveFinderMetadata:     true,
+		})
+	}()
 
 	gates := []validationGate{
 		{
diff --git a/internal/pipeline/dogfood.go b/internal/pipeline/dogfood.go
index 455efa3a..91b062e2 100644
--- a/internal/pipeline/dogfood.go
+++ b/internal/pipeline/dogfood.go
@@ -14,14 +14,14 @@ import (
 )
 
 type DogfoodReport struct {
-	Dir           string          `json:"dir"`
-	SpecPath      string          `json:"spec_path,omitempty"`
-	Verdict       string          `json:"verdict"`
-	PathCheck     PathCheckResult `json:"path_check"`
-	AuthCheck     AuthCheckResult `json:"auth_check"`
-	DeadFlags     DeadCodeResult  `json:"dead_flags"`
-	DeadFuncs     DeadCodeResult  `json:"dead_functions"`
-	PipelineCheck PipelineResult    `json:"pipeline_check"`
+	Dir           string             `json:"dir"`
+	SpecPath      string             `json:"spec_path,omitempty"`
+	Verdict       string             `json:"verdict"`
+	PathCheck     PathCheckResult    `json:"path_check"`
+	AuthCheck     AuthCheckResult    `json:"auth_check"`
+	DeadFlags     DeadCodeResult     `json:"dead_flags"`
+	DeadFuncs     DeadCodeResult     `json:"dead_functions"`
+	PipelineCheck PipelineResult     `json:"pipeline_check"`
 	ExampleCheck  ExampleCheckResult `json:"example_check"`
 	Issues        []string           `json:"issues"`
 }
@@ -466,6 +466,7 @@ func checkExamples(dir string) ExampleCheckResult {
 		result.Detail = fmt.Sprintf("could not build CLI binary: %v", err)
 		return result
 	}
+	defer os.Remove(binaryPath)
 
 	// Get global flags from root --help
 	globalOut, err := runDogfoodCmd(binaryPath, 15*time.Second, "--help")
diff --git a/internal/pipeline/fullrun.go b/internal/pipeline/fullrun.go
index 990282c3..00a3db28 100644
--- a/internal/pipeline/fullrun.go
+++ b/internal/pipeline/fullrun.go
@@ -146,6 +146,7 @@ func MakeBestCLI(apiName, level, specFlag, specURL, outputDir, pressBinary strin
 		result.DogfoodError = fmt.Sprintf("build failed: %v", buildErr)
 		result.Errors = append(result.Errors, fmt.Sprintf("dogfood build: %v", buildErr))
 	} else {
+		defer os.Remove(cliBinaryPath)
 		dogfood, dogErr := RunDogfood(outputDir, "")
 		if dogErr != nil {
 			result.DogfoodError = dogErr.Error()
diff --git a/internal/pipeline/runtime.go b/internal/pipeline/runtime.go
index 49691882..ee3be5ea 100644
--- a/internal/pipeline/runtime.go
+++ b/internal/pipeline/runtime.go
@@ -12,6 +12,8 @@ import (
 	"regexp"
 	"strings"
 	"time"
+
+	"github.com/mvanhorn/cli-printing-press/internal/artifacts"
 )
 
 // VerifyConfig configures a runtime verification run.
@@ -25,27 +27,27 @@ type VerifyConfig struct {
 
 // VerifyReport is the output of a runtime verification run.
 type VerifyReport struct {
-	Mode         string         `json:"mode"` // "live" or "mock"
-	Total        int            `json:"total"`
-	Passed       int            `json:"passed"`
-	Failed       int            `json:"failed"`
-	Critical     int            `json:"critical"`
-	PassRate     float64        `json:"pass_rate"`
-	DataPipeline bool           `json:"data_pipeline"`
-	Verdict      string         `json:"verdict"` // PASS, WARN, FAIL
+	Mode         string          `json:"mode"` // "live" or "mock"
+	Total        int             `json:"total"`
+	Passed       int             `json:"passed"`
+	Failed       int             `json:"failed"`
+	Critical     int             `json:"critical"`
+	PassRate     float64         `json:"pass_rate"`
+	DataPipeline bool            `json:"data_pipeline"`
+	Verdict      string          `json:"verdict"` // PASS, WARN, FAIL
 	Results      []CommandResult `json:"results"`
-	Binary       string         `json:"binary"`
+	Binary       string          `json:"binary"`
 }
 
 // CommandResult is the test result for a single command.
 type CommandResult struct {
-	Command  string `json:"command"`
-	Kind     string `json:"kind"` // read, write, local, data-layer
-	Help     bool   `json:"help"`
-	DryRun   bool   `json:"dry_run"`
-	Execute  bool   `json:"execute"`
-	Score    int    `json:"score"` // 0-3
-	Error    string `json:"error,omitempty"`
+	Command string `json:"command"`
+	Kind    string `json:"kind"` // read, write, local, data-layer
+	Help    bool   `json:"help"`
+	DryRun  bool   `json:"dry_run"`
+	Execute bool   `json:"execute"`
+	Score   int    `json:"score"` // 0-3
+	Error   string `json:"error,omitempty"`
 }
 
 // RunVerify executes the runtime verification pipeline.
@@ -53,6 +55,14 @@ func RunVerify(cfg VerifyConfig) (*VerifyReport, error) {
 	if cfg.Threshold == 0 {
 		cfg.Threshold = 80
 	}
+	if err := artifacts.CleanupGeneratedCLI(cfg.Dir, artifacts.CleanupOptions{
+		RemoveValidationBinaries: true,
+		RemoveDogfoodBinaries:    true,
+		RemoveRecursiveCopies:    true,
+		RemoveFinderMetadata:     true,
+	}); err != nil {
+		return nil, fmt.Errorf("pre-verify cleanup: %w", err)
+	}
 
 	report := &VerifyReport{}
 
diff --git a/internal/pipeline/runtime_test.go b/internal/pipeline/runtime_test.go
new file mode 100644
index 00000000..69b13bc7
--- /dev/null
+++ b/internal/pipeline/runtime_test.go
@@ -0,0 +1,60 @@
+package pipeline
+
+import (
+	"os"
+	"path/filepath"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+)
+
+func TestRunVerify_CleansTransientArtifactsButKeepsCache(t *testing.T) {
+	dir := filepath.Join(t.TempDir(), "sample-cli")
+	require.NoError(t, os.MkdirAll(filepath.Join(dir, "cmd", "sample-cli"), 0o755))
+	require.NoError(t, os.MkdirAll(filepath.Join(dir, "internal", "cli"), 0o755))
+	require.NoError(t, os.MkdirAll(filepath.Join(dir, "cmd", "library", "sample-cli"), 0o755))
+	require.NoError(t, os.MkdirAll(filepath.Join(dir, ".cache", "go-build"), 0o755))
+
+	writeTestFile(t, filepath.Join(dir, "go.mod"), "module example.com/sample-cli\n\ngo 1.26.1\n")
+	writeTestFile(t, filepath.Join(dir, "cmd", "sample-cli", "main.go"), `package main
+func main() {}
+`)
+	writeTestFile(t, filepath.Join(dir, "internal", "cli", "root.go"), `package cli
+func initRoot() {
+	rootCmd.AddCommand(newUsersListCmd())
+}
+`)
+	writeTestFile(t, filepath.Join(dir, "cmd", "library", "sample-cli", "main.go"), "package recursive\n")
+	writeTestFile(t, filepath.Join(dir, ".DS_Store"), "finder")
+	writeTestFile(t, filepath.Join(dir, ".cache", "go-build", "index"), "cache")
+
+	report, err := RunVerify(VerifyConfig{Dir: dir})
+	require.NoError(t, err)
+	assert.Equal(t, "PASS", report.Verdict)
+	assert.FileExists(t, report.Binary)
+
+	assert.FileExists(t, filepath.Join(dir, "sample-cli"))
+	assert.NoDirExists(t, filepath.Join(dir, "cmd", "library"))
+	assert.NoFileExists(t, filepath.Join(dir, ".DS_Store"))
+	assert.DirExists(t, filepath.Join(dir, ".cache"))
+}
+
+func TestRunVerify_KeepsExistingBinaryWhenRebuildFails(t *testing.T) {
+	dir := filepath.Join(t.TempDir(), "sample-cli")
+	require.NoError(t, os.MkdirAll(filepath.Join(dir, "cmd", "sample-cli"), 0o755))
+
+	existingBinary := filepath.Join(dir, "sample-cli")
+	require.NoError(t, os.WriteFile(existingBinary, []byte("previous-build"), 0o755))
+	writeTestFile(t, filepath.Join(dir, "go.mod"), "module example.com/sample-cli\n\ngo 1.26.1\n")
+	writeTestFile(t, filepath.Join(dir, "cmd", "sample-cli", "main.go"), `package main
+func main() {
+	this will not compile
+}
+`)
+
+	report, err := RunVerify(VerifyConfig{Dir: dir})
+	require.Error(t, err)
+	assert.Nil(t, report)
+	assert.FileExists(t, existingBinary)
+}
diff --git a/internal/pipeline/verify.go b/internal/pipeline/verify.go
index 49a9a839..307f5b91 100644
--- a/internal/pipeline/verify.go
+++ b/internal/pipeline/verify.go
@@ -10,6 +10,8 @@ import (
 	"strings"
 	"time"
 	"unicode"
+
+	"github.com/mvanhorn/cli-printing-press/internal/artifacts"
 )
 
 type Verifier struct {
@@ -84,6 +86,14 @@ func (v *Verifier) CompileGate() error {
 	if v == nil {
 		return fmt.Errorf("nil verifier")
 	}
+	if err := artifacts.CleanupGeneratedCLI(v.Dir, artifacts.CleanupOptions{
+		RemoveValidationBinaries: true,
+		RemoveDogfoodBinaries:    true,
+		RemoveRecursiveCopies:    true,
+		RemoveFinderMetadata:     true,
+	}); err != nil {
+		return fmt.Errorf("pre-compile cleanup: %w", err)
+	}
 
 	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
 	defer cancel()

← 3a850fc5 fix(pipeline): match short path declarations  ·  back to Cli Printing Press  ·  docs: add compound engineering plugin to setup instructions 23925ce9 →