feature/recipe_implementation #5

Merged
gmgauthier merged 54 commits from feature/recipe_implementation into master 2026-03-07 23:17:54 +00:00
2 changed files with 21 additions and 73 deletions
Showing only changes of commit 0b5aa5eb57 - Show all commits

View File

@ -1,7 +1,6 @@
package recipe package recipe
import ( import (
_ "bufio"
"encoding/json" "encoding/json"
"fmt" "fmt"
"os" "os"
@ -77,7 +76,7 @@ Execute this step now. Respond ONLY with the expected output format — no expla
return nil return nil
} }
// discoverFiles does a real filesystem scan // discoverFiles — temporary .go hard-code (we'll generalize with extensions next)
func (r *Runner) discoverFiles() []string { func (r *Runner) discoverFiles() []string {
var files []string var files []string
root := "internal" root := "internal"
@ -99,7 +98,11 @@ func (r *Runner) discoverFiles() []string {
return files 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) { func (r *Runner) handleApplyStep(previousResults []string) {
if len(previousResults) == 0 { if len(previousResults) == 0 {
fmt.Println(" ⚠️ No previous results to apply — skipping.") fmt.Println(" ⚠️ No previous results to apply — skipping.")
@ -118,11 +121,6 @@ func (r *Runner) handleApplyStep(previousResults []string) {
jsonStr := lastResult[start:end] jsonStr := lastResult[start:end]
type FileChange struct {
File string `json:"file"`
Content string `json:"content"`
}
var changes []FileChange var changes []FileChange
if err := json.Unmarshal([]byte(jsonStr), &changes); err != nil { if err := json.Unmarshal([]byte(jsonStr), &changes); err != nil {
fmt.Printf(" ⚠️ Could not parse JSON: %v\n", err) 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.") 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) f, err := os.Create(patchPath)
if err != nil { if err != nil {
return err return err
} }
defer f.Close() defer func(f *os.File) {
err := f.Close()
if err != nil {
return
}
}(f)
for _, ch := range changes { 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") { 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 return nil

View File

@ -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)
}
})
}
}