From f5c73ab291d8b5f711088068fd4eea4caf83e03d Mon Sep 17 00:00:00 2001 From: Greg Gauthier Date: Sat, 7 Mar 2026 00:07:21 +0000 Subject: [PATCH] refactor(recipe): add ResolvedParams for better param handling Introduce ResolvedParams field to Recipe struct for storing resolved parameter values from defaults and user overrides. Update loader to populate and use it for template rendering. Adjust runner to use ResolvedParams for root path and generalize file discovery. --- internal/recipe/loader.go | 12 ++++++------ internal/recipe/runner.go | 17 ++++++++--------- internal/recipe/types.go | 5 ++++- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/internal/recipe/loader.go b/internal/recipe/loader.go index c7d960b..b4ac37d 100644 --- a/internal/recipe/loader.go +++ b/internal/recipe/loader.go @@ -32,26 +32,26 @@ func Load(path string, userParams map[string]any) (*Recipe, error) { return nil, fmt.Errorf("yaml parse: %w", err) } - // Apply defaults + // Apply defaults + user --param overrides if r.Parameters == nil { r.Parameters = make(map[string]Parameter) } - params := make(map[string]any) + r.ResolvedParams = make(map[string]any) for name, p := range r.Parameters { if v, ok := userParams[name]; ok { - params[name] = v + r.ResolvedParams[name] = v } else if p.Default != nil { - params[name] = p.Default + r.ResolvedParams[name] = p.Default } } - // Render templates (so {{.package_path}} becomes "internal") + // Render templates with resolved values tpl, err := template.New("recipe").Parse(string(parts[2])) if err != nil { return nil, err } var rendered bytes.Buffer - if err := tpl.Execute(&rendered, params); err != nil { + if err := tpl.Execute(&rendered, r.ResolvedParams); err != nil { return nil, err } body := rendered.String() diff --git a/internal/recipe/runner.go b/internal/recipe/runner.go index 9eb3791..347ddb1 100644 --- a/internal/recipe/runner.go +++ b/internal/recipe/runner.go @@ -85,15 +85,15 @@ Execute this step now. Respond ONLY with the expected output format — no expla func (r *Runner) discoverFiles() []string { var files []string - // Get root from parameter or default - root := "internal" - if p, ok := r.Recipe.Parameters["package_path"]; ok { - if def, ok := p.Default.(string); ok && def != "" { - root = def + // Get root from --param or default + root := "." + if v, ok := r.Recipe.ResolvedParams["package_path"]; ok { + if s, ok := v.(string); ok && s != "" { + root = s } } - // Build set of allowed extensions from recipe frontmatter + // Build allowed extensions from recipe frontmatter allowedExt := make(map[string]bool) for _, lang := range r.Recipe.ProjectLanguages { if exts, ok := r.Recipe.Extensions[lang]; ok { @@ -107,10 +107,9 @@ func (r *Runner) discoverFiles() []string { if err != nil || d.IsDir() { return nil } - ext := filepath.Ext(path) - if allowedExt[ext] { + if allowedExt[filepath.Ext(path)] { b, _ := os.ReadFile(path) - if strings.Contains(string(b), "if err != nil") { // this is still Go-specific for now; we can generalize later + if strings.Contains(string(b), "if err != nil") { files = append(files, path) } } diff --git a/internal/recipe/types.go b/internal/recipe/types.go index 55b392a..d59a950 100644 --- a/internal/recipe/types.go +++ b/internal/recipe/types.go @@ -7,10 +7,13 @@ type Recipe struct { Parameters map[string]Parameter `yaml:"parameters"` AllowedShellCommands []string `yaml:"allowed_shell_commands"` - // New fields for generic file discovery (option 2) + // Generic discovery support (option 2) ProjectLanguages []string `yaml:"project_languages"` Extensions map[string][]string `yaml:"extensions"` + // Resolved runtime values from --param flags + ResolvedParams map[string]any `yaml:"-"` + // Internal fields populated by loader Overview string `yaml:"-"` Steps []Step `yaml:"-"`