feature/recipe_implementation #5

Merged
gmgauthier merged 54 commits from feature/recipe_implementation into master 2026-03-07 23:17:54 +00:00
3 changed files with 18 additions and 16 deletions
Showing only changes of commit f5c73ab291 - Show all commits

View File

@ -32,26 +32,26 @@ func Load(path string, userParams map[string]any) (*Recipe, error) {
return nil, fmt.Errorf("yaml parse: %w", err) return nil, fmt.Errorf("yaml parse: %w", err)
} }
// Apply defaults // Apply defaults + user --param overrides
if r.Parameters == nil { if r.Parameters == nil {
r.Parameters = make(map[string]Parameter) r.Parameters = make(map[string]Parameter)
} }
params := make(map[string]any) r.ResolvedParams = make(map[string]any)
for name, p := range r.Parameters { for name, p := range r.Parameters {
if v, ok := userParams[name]; ok { if v, ok := userParams[name]; ok {
params[name] = v r.ResolvedParams[name] = v
} else if p.Default != nil { } 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])) tpl, err := template.New("recipe").Parse(string(parts[2]))
if err != nil { if err != nil {
return nil, err return nil, err
} }
var rendered bytes.Buffer var rendered bytes.Buffer
if err := tpl.Execute(&rendered, params); err != nil { if err := tpl.Execute(&rendered, r.ResolvedParams); err != nil {
return nil, err return nil, err
} }
body := rendered.String() body := rendered.String()

View File

@ -85,15 +85,15 @@ Execute this step now. Respond ONLY with the expected output format — no expla
func (r *Runner) discoverFiles() []string { func (r *Runner) discoverFiles() []string {
var files []string var files []string
// Get root from parameter or default // Get root from --param or default
root := "internal" root := "."
if p, ok := r.Recipe.Parameters["package_path"]; ok { if v, ok := r.Recipe.ResolvedParams["package_path"]; ok {
if def, ok := p.Default.(string); ok && def != "" { if s, ok := v.(string); ok && s != "" {
root = def root = s
} }
} }
// Build set of allowed extensions from recipe frontmatter // Build allowed extensions from recipe frontmatter
allowedExt := make(map[string]bool) allowedExt := make(map[string]bool)
for _, lang := range r.Recipe.ProjectLanguages { for _, lang := range r.Recipe.ProjectLanguages {
if exts, ok := r.Recipe.Extensions[lang]; ok { if exts, ok := r.Recipe.Extensions[lang]; ok {
@ -107,10 +107,9 @@ func (r *Runner) discoverFiles() []string {
if err != nil || d.IsDir() { if err != nil || d.IsDir() {
return nil return nil
} }
ext := filepath.Ext(path) if allowedExt[filepath.Ext(path)] {
if allowedExt[ext] {
b, _ := os.ReadFile(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) files = append(files, path)
} }
} }

View File

@ -7,10 +7,13 @@ type Recipe struct {
Parameters map[string]Parameter `yaml:"parameters"` Parameters map[string]Parameter `yaml:"parameters"`
AllowedShellCommands []string `yaml:"allowed_shell_commands"` AllowedShellCommands []string `yaml:"allowed_shell_commands"`
// New fields for generic file discovery (option 2) // Generic discovery support (option 2)
ProjectLanguages []string `yaml:"project_languages"` ProjectLanguages []string `yaml:"project_languages"`
Extensions map[string][]string `yaml:"extensions"` Extensions map[string][]string `yaml:"extensions"`
// Resolved runtime values from --param flags
ResolvedParams map[string]any `yaml:"-"`
// Internal fields populated by loader // Internal fields populated by loader
Overview string `yaml:"-"` Overview string `yaml:"-"`
Steps []Step `yaml:"-"` Steps []Step `yaml:"-"`