Skip to content

Validate Recipe entries before pipeline execution - #170

Merged
id774 merged 1 commit into
masterfrom
fix/recipe-preflight
Sep 6, 2026
Merged

Validate Recipe entries before pipeline execution#170
id774 merged 1 commit into
masterfrom
fix/recipe-preflight

Conversation

@id774

@id774 id774 commented Sep 6, 2026

Copy link
Copy Markdown
Owner

Summary

  • Added structural validation for each Recipe plugins entry: an entry must be a mapping, its module must be a required non-empty (non-whitespace-only) string, and its config must be either omitted/null or a mapping. A malformed entry is now refused as Automatic::InvalidRecipeError at Recipe load time, identified by its index (e.g. plugins[2] is not a mapping).
  • Automatic::Pipeline.run now discovers every plugin module named in the Recipe (via the existing load_plugin) before running any plugin. If any module is undiscoverable, Automatic::NoPluginError is raised before any plugin's initialize/run is called, regardless of where in the Recipe the unknown module is.
  • Plugin source loading stays lazy: discovery only registers an autoload (unchanged load_plugin behavior); a plugin's file is still read only when execution actually reaches that plugin's turn.

Reason

doc/PLUGINS.md documents each plugins entry's shape (a mapping naming a module, with an optional config mapping) and documents an unknown plugin as refused before any plugin runs. Previously, malformed entries were not validated at the Recipe boundary and could surface as an internal NoMethodError/TypeError once the pipeline reached them, and Pipeline.run discovered and executed each entry interleaved, so a typo'd module later in the Recipe was only discovered after any earlier plugin's side effect had already happened. This change makes both checks happen up front, before any plugin runs.

Tests

  • bundle exec rspec spec/lib/automatic/recipe_safety_spec.rb — 20 examples, 0 failures.
  • bundle exec rspec spec/lib/automatic/pipeline_spec.rb — 10 examples, 0 failures.
  • bundle exec rake spec:lib — 108 examples, 0 failures.
  • bundle exec rake spec — 403 examples, 0 failures.
  • gem build automatic.gemspec — succeeded.
  • bundle exec ruby -Ilib -e "require 'automatic'" — succeeded.
  • bundle exec bin/automatic --version and --help — succeeded.
  • Additionally smoke-tested through the real CLI: a malformed entry (plugins:\n - nope) is refused with plugins[0] is not a mapping, and a Recipe with a valid plugin followed by an unknown one is refused with unknown plugin named ... before the valid plugin runs.

New pipeline_spec.rb coverage includes a fixture plugin (spec/user_dir/plugins/filter/load_marker.rb) used to check $LOADED_FEATURES directly, proving discovery does not read a plugin's source file even when an unknown module follows it, and that the file is read only once execution reaches it.

Compatibility

  • Automatic::Recipe.new(path), Automatic::Recipe#each_plugin, Automatic::Pipeline.run(recipe) and Automatic::Pipeline.load_plugin(module_name) keep their existing public call shapes.
  • A valid, documented Recipe's plugin execution order and pipeline chaining are unchanged.
  • Omitted config, config: null, mapping config, repeated modules, and YAML aliases all continue to be accepted.
  • Plugin search precedence (user plugins shadowing shipped ones) is unchanged.
  • YAML safe-load policy is unchanged.
  • No dependency, VERSION, CLI, or Ruby-support change.

Version History

Recorded as part of one consolidated v26.09 release item in doc/VERSIONS (the existing seven bullets in that section were also consolidated into two, at the user's explicit request in this session, to stop the section from growing by one bullet per change):

Harden the framework's execution boundary: fix CLI inspect/scaffold contract drift, distinguish missing optional dependencies from unrelated load failures, preserve standard item metadata when FeedMaker rebuilds pipelines, and validate Recipe plugin entries with a discovery preflight before any plugin runs.

VERSION remains 26.09; no version bump.

🤖 Generated with Claude Code

https://claude.ai/code/session_01H8NygEHhT3zGMnBmQF2F6Q


Generated by Claude Code

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H8NygEHhT3zGMnBmQF2F6Q
@id774
id774 merged commit 0e49585 into master Sep 6, 2026
8 checks passed
@id774
id774 deleted the fix/recipe-preflight branch September 6, 2026 11:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants