From 0b5aa5eb57d880b3e070199a2e91671ec4a1bc6b Mon Sep 17 00:00:00 2001 From: Greg Gauthier Date: Fri, 6 Mar 2026 22:48:15 +0000 Subject: [PATCH] refactor(recipe): improve error handling and restructure in runner - Move FileChange struct to top-level for better organization. - Enhance createUnifiedPatch with proper error handling on writes. - Remove unused bufio import and update comments. - Delete obsolete runner_test.go file. --- internal/recipe/runner.go | 33 +++++++++++------- internal/recipe/runner_test.go | 61 ---------------------------------- 2 files changed, 21 insertions(+), 73 deletions(-) delete mode 100644 internal/recipe/runner_test.go diff --git a/internal/recipe/runner.go b/internal/recipe/runner.go index 4899a83..c83eccc 100644 --- a/internal/recipe/runner.go +++ b/internal/recipe/runner.go @@ -1,7 +1,6 @@ package recipe import ( - _ "bufio" "encoding/json" "fmt" "os" @@ -77,7 +76,7 @@ Execute this step now. Respond ONLY with the expected output format — no expla return nil } -// discoverFiles does a real filesystem scan +// discoverFiles — temporary .go hard-code (we'll generalize with extensions next) func (r *Runner) discoverFiles() []string { var files []string root := "internal" @@ -99,7 +98,11 @@ func (r *Runner) discoverFiles() []string { return files } -// handleApplyStep parses strict JSON from the refactor step — no regex at all +type FileChange struct { + File string `json:"file"` + Content string `json:"content"` +} + func (r *Runner) handleApplyStep(previousResults []string) { if len(previousResults) == 0 { fmt.Println(" ⚠️ No previous results to apply — skipping.") @@ -118,11 +121,6 @@ func (r *Runner) handleApplyStep(previousResults []string) { jsonStr := lastResult[start:end] - type FileChange struct { - File string `json:"file"` - Content string `json:"content"` - } - var changes []FileChange if err := json.Unmarshal([]byte(jsonStr), &changes); err != nil { fmt.Printf(" ⚠️ Could not parse JSON: %v\n", err) @@ -144,17 +142,28 @@ func (r *Runner) handleApplyStep(previousResults []string) { fmt.Println(" Review it, then run with dry_run=false to apply.") } -func createUnifiedPatch(changes []struct{ File, Content string }, patchPath string) error { +func createUnifiedPatch(changes []FileChange, patchPath string) error { f, err := os.Create(patchPath) if err != nil { return err } - defer f.Close() + defer func(f *os.File) { + err := f.Close() + if err != nil { + return + } + }(f) for _, ch := range changes { - fmt.Fprintf(f, "--- %s\n+++ %s\n@@ -0,0 +1,%d @@\n", ch.File, ch.File, strings.Count(ch.Content, "\n")+1) + _, err := fmt.Fprintf(f, "--- %s\n+++ %s\n@@ -0,0 +1,%d @@\n", ch.File, ch.File, strings.Count(ch.Content, "\n")+1) + if err != nil { + return err + } for _, line := range strings.Split(ch.Content, "\n") { - fmt.Fprintf(f, "+%s\n", line) + _, err := fmt.Fprintf(f, "+%s\n", line) + if err != nil { + return err + } } } return nil diff --git a/internal/recipe/runner_test.go b/internal/recipe/runner_test.go deleted file mode 100644 index 00f0002..0000000 --- a/internal/recipe/runner_test.go +++ /dev/null @@ -1,61 +0,0 @@ -package recipe - -import ( - "reflect" - "testing" -) - -func TestExtractCodeBlocks(t *testing.T) { - t.Parallel() - - tests := []struct { - name string - input string - expected map[string]string - }{ - { - name: "Single block", - input: "// main.go\n```go\npackage main\n\nfunc main() {}\n```", - expected: map[string]string{ - "main.go": "package main\n\nfunc main() {}", - }, - }, - { - name: "Multiple blocks", - input: `// internal/utils.go -` + "```" + `go -package utils -func Help() {} -` + "```" + ` -Some commentary. -// cmd/root.go -` + "```" + `go -package cmd -func Execute() {} -` + "```", - expected: map[string]string{ - "internal/utils.go": "package utils\nfunc Help() {}", - "cmd/root.go": "package cmd\nfunc Execute() {}", - }, - }, - { - name: "No blocks", - input: "Just some text without any blocks.", - expected: map[string]string{}, - }, - { - name: "Incomplete block", - input: "// oops.go\n```go\nfunc incomplete() {", - expected: map[string]string{}, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got := extractCodeBlocks(tt.input) - if !reflect.DeepEqual(got, tt.expected) { - t.Errorf("extractCodeBlocks() = %v, want %v", got, tt.expected) - } - }) - } -}