roast-ai 0.1.7 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yaml +1 -1
  3. data/CHANGELOG.md +49 -1
  4. data/CLAUDE.md +20 -0
  5. data/CLAUDE_NOTES.md +68 -0
  6. data/Gemfile +1 -0
  7. data/Gemfile.lock +9 -6
  8. data/README.md +159 -26
  9. data/bin/roast +27 -0
  10. data/docs/ITERATION_SYNTAX.md +147 -0
  11. data/examples/case_when/README.md +58 -0
  12. data/examples/case_when/detect_language/prompt.md +16 -0
  13. data/examples/case_when/workflow.yml +58 -0
  14. data/examples/conditional/README.md +161 -0
  15. data/examples/conditional/check_condition/prompt.md +1 -0
  16. data/examples/conditional/simple_workflow.yml +15 -0
  17. data/examples/conditional/workflow.yml +23 -0
  18. data/examples/direct_coerce_syntax/README.md +32 -0
  19. data/examples/direct_coerce_syntax/workflow.yml +36 -0
  20. data/examples/dot_notation/README.md +37 -0
  21. data/examples/dot_notation/workflow.yml +44 -0
  22. data/examples/exit_on_error/README.md +50 -0
  23. data/examples/exit_on_error/analyze_lint_output/prompt.md +9 -0
  24. data/examples/exit_on_error/apply_fixes/prompt.md +2 -0
  25. data/examples/exit_on_error/workflow.yml +19 -0
  26. data/examples/grading/workflow.yml +10 -4
  27. data/examples/iteration/IMPLEMENTATION.md +88 -0
  28. data/examples/iteration/README.md +68 -0
  29. data/examples/iteration/analyze_complexity/prompt.md +22 -0
  30. data/examples/iteration/generate_recommendations/prompt.md +21 -0
  31. data/examples/iteration/generate_report/prompt.md +129 -0
  32. data/examples/iteration/implement_fix/prompt.md +25 -0
  33. data/examples/iteration/prioritize_issues/prompt.md +24 -0
  34. data/examples/iteration/prompts/analyze_file.md +28 -0
  35. data/examples/iteration/prompts/generate_summary.md +24 -0
  36. data/examples/iteration/prompts/update_report.md +29 -0
  37. data/examples/iteration/prompts/write_report.md +22 -0
  38. data/examples/iteration/read_file/prompt.md +9 -0
  39. data/examples/iteration/select_next_issue/prompt.md +25 -0
  40. data/examples/iteration/simple_workflow.md +39 -0
  41. data/examples/iteration/simple_workflow.yml +58 -0
  42. data/examples/iteration/update_fix_count/prompt.md +26 -0
  43. data/examples/iteration/verify_fix/prompt.md +29 -0
  44. data/examples/iteration/workflow.yml +42 -0
  45. data/examples/json_handling/README.md +32 -0
  46. data/examples/json_handling/workflow.yml +52 -0
  47. data/examples/openrouter_example/workflow.yml +2 -2
  48. data/examples/smart_coercion_defaults/README.md +65 -0
  49. data/examples/smart_coercion_defaults/workflow.yml +44 -0
  50. data/examples/step_configuration/README.md +87 -0
  51. data/examples/step_configuration/workflow.yml +60 -0
  52. data/examples/workflow_generator/README.md +27 -0
  53. data/examples/workflow_generator/analyze_user_request/prompt.md +34 -0
  54. data/examples/workflow_generator/create_workflow_files/prompt.md +32 -0
  55. data/examples/workflow_generator/get_user_input/prompt.md +14 -0
  56. data/examples/workflow_generator/info_from_roast.rb +22 -0
  57. data/examples/workflow_generator/workflow.yml +35 -0
  58. data/lib/roast/errors.rb +9 -0
  59. data/lib/roast/factories/api_provider_factory.rb +61 -0
  60. data/lib/roast/helpers/function_caching_interceptor.rb +1 -1
  61. data/lib/roast/helpers/minitest_coverage_runner.rb +1 -1
  62. data/lib/roast/helpers/prompt_loader.rb +50 -1
  63. data/lib/roast/resources/base_resource.rb +7 -0
  64. data/lib/roast/resources.rb +6 -6
  65. data/lib/roast/tools/ask_user.rb +40 -0
  66. data/lib/roast/tools/cmd.rb +1 -1
  67. data/lib/roast/tools/search_file.rb +1 -1
  68. data/lib/roast/tools.rb +11 -1
  69. data/lib/roast/value_objects/api_token.rb +49 -0
  70. data/lib/roast/value_objects/step_name.rb +39 -0
  71. data/lib/roast/value_objects/workflow_path.rb +77 -0
  72. data/lib/roast/value_objects.rb +5 -0
  73. data/lib/roast/version.rb +1 -1
  74. data/lib/roast/workflow/api_configuration.rb +61 -0
  75. data/lib/roast/workflow/base_iteration_step.rb +184 -0
  76. data/lib/roast/workflow/base_step.rb +44 -27
  77. data/lib/roast/workflow/base_workflow.rb +76 -73
  78. data/lib/roast/workflow/case_executor.rb +49 -0
  79. data/lib/roast/workflow/case_step.rb +82 -0
  80. data/lib/roast/workflow/command_executor.rb +88 -0
  81. data/lib/roast/workflow/conditional_executor.rb +50 -0
  82. data/lib/roast/workflow/conditional_step.rb +59 -0
  83. data/lib/roast/workflow/configuration.rb +35 -158
  84. data/lib/roast/workflow/configuration_loader.rb +78 -0
  85. data/lib/roast/workflow/configuration_parser.rb +13 -248
  86. data/lib/roast/workflow/context_path_resolver.rb +43 -0
  87. data/lib/roast/workflow/dot_access_hash.rb +198 -0
  88. data/lib/roast/workflow/each_step.rb +86 -0
  89. data/lib/roast/workflow/error_handler.rb +97 -0
  90. data/lib/roast/workflow/expression_evaluator.rb +78 -0
  91. data/lib/roast/workflow/expression_utils.rb +36 -0
  92. data/lib/roast/workflow/file_state_repository.rb +3 -2
  93. data/lib/roast/workflow/interpolator.rb +34 -0
  94. data/lib/roast/workflow/iteration_executor.rb +103 -0
  95. data/lib/roast/workflow/llm_boolean_coercer.rb +55 -0
  96. data/lib/roast/workflow/output_handler.rb +35 -0
  97. data/lib/roast/workflow/output_manager.rb +77 -0
  98. data/lib/roast/workflow/parallel_executor.rb +49 -0
  99. data/lib/roast/workflow/prompt_step.rb +4 -1
  100. data/lib/roast/workflow/repeat_step.rb +75 -0
  101. data/lib/roast/workflow/replay_handler.rb +123 -0
  102. data/lib/roast/workflow/resource_resolver.rb +77 -0
  103. data/lib/roast/workflow/session_manager.rb +6 -2
  104. data/lib/roast/workflow/state_manager.rb +97 -0
  105. data/lib/roast/workflow/step_executor_coordinator.rb +221 -0
  106. data/lib/roast/workflow/step_executor_factory.rb +47 -0
  107. data/lib/roast/workflow/step_executor_registry.rb +79 -0
  108. data/lib/roast/workflow/step_executors/base_step_executor.rb +23 -0
  109. data/lib/roast/workflow/step_executors/hash_step_executor.rb +43 -0
  110. data/lib/roast/workflow/step_executors/parallel_step_executor.rb +54 -0
  111. data/lib/roast/workflow/step_executors/string_step_executor.rb +29 -0
  112. data/lib/roast/workflow/step_finder.rb +97 -0
  113. data/lib/roast/workflow/step_loader.rb +155 -0
  114. data/lib/roast/workflow/step_orchestrator.rb +45 -0
  115. data/lib/roast/workflow/step_runner.rb +23 -0
  116. data/lib/roast/workflow/step_type_resolver.rb +133 -0
  117. data/lib/roast/workflow/workflow_context.rb +60 -0
  118. data/lib/roast/workflow/workflow_executor.rb +90 -209
  119. data/lib/roast/workflow/workflow_initializer.rb +112 -0
  120. data/lib/roast/workflow/workflow_runner.rb +87 -0
  121. data/lib/roast/workflow.rb +3 -0
  122. data/lib/roast.rb +96 -3
  123. data/roast.gemspec +2 -1
  124. data/schema/workflow.json +112 -0
  125. metadata +112 -4
@@ -0,0 +1,147 @@
1
+ # Using Iteration with Standardized Syntax
2
+
3
+ ## Overview
4
+
5
+ Roast supports powerful iteration constructs with the `repeat` and `each` workflow steps. These features now support a standardized approach to evaluating expressions using the double-curly braces syntax (`{{...}}`).
6
+
7
+ ## Syntax Options for Iteration Inputs
8
+
9
+ Both `until` conditions (in `repeat`) and collection expressions (in `each`) accept the following formats:
10
+
11
+ ### 1. Ruby Expressions with `{{...}}` Syntax
12
+
13
+ For evaluating Ruby code in the workflow context:
14
+
15
+ ```yaml
16
+ # Repeat until a condition is met
17
+ - repeat:
18
+ steps:
19
+ - process_item
20
+ until: "{{output['counter'] >= 5}}"
21
+ max_iterations: 10
22
+
23
+ # Iterate over a collection
24
+ - each: "{{output['items'].filter { |item| item.active? }}}"
25
+ as: "current_item"
26
+ steps:
27
+ - process_item
28
+ ```
29
+
30
+ ### 2. Bash Commands with `$(...)` Syntax
31
+
32
+ For executing shell commands and using their results:
33
+
34
+ ```yaml
35
+ # Repeat until a command succeeds
36
+ - repeat:
37
+ steps:
38
+ - check_service
39
+ until: "$(curl -s -o /dev/null -w '%{http_code}' http://service.local/ | grep -q 200)"
40
+ max_iterations: 20
41
+
42
+ # Iterate over files returned by a command
43
+ - each: "$(find . -name '*.rb' -type f)"
44
+ as: "current_file"
45
+ steps:
46
+ - process_file
47
+ ```
48
+
49
+ ### 3. Step Names (as strings)
50
+
51
+ For using the result of another step:
52
+
53
+ ```yaml
54
+ # Repeat until a step returns a truthy value
55
+ - repeat:
56
+ steps:
57
+ - process_batch
58
+ until: "check_completion"
59
+ max_iterations: 100
60
+
61
+ # Iterate over items returned by a step
62
+ - each: "get_pending_items"
63
+ as: "pending_item"
64
+ steps:
65
+ - process_pending_item
66
+ ```
67
+
68
+ ### 4. Prompt Content
69
+
70
+ For defining prompts directly in the workflow:
71
+
72
+ ```yaml
73
+ # Using a prompt to determine continuation
74
+ - repeat:
75
+ steps:
76
+ - process_content
77
+ until:
78
+ prompt: prompts/check_completion.md
79
+ model: claude-3-haiku
80
+ max_iterations: 10
81
+
82
+ # Using a prompt to generate a collection
83
+ - each:
84
+ prompt: prompts/generate_test_cases.md
85
+ model: claude-3-haiku
86
+ as: "test_case"
87
+ steps:
88
+ - run_test
89
+ ```
90
+
91
+ ## Type Coercion
92
+
93
+ ### Smart Defaults
94
+
95
+ Roast applies intelligent defaults for boolean coercion based on the type of expression:
96
+
97
+ - **Ruby expressions** (`{{expr}}`) → Regular boolean coercion (`!!value`)
98
+ - **Bash commands** (`$(cmd)`) → Exit code interpretation (0 = true, non-zero = false)
99
+ - **Inline prompts/step names** → LLM boolean interpretation (analyzes yes/no intent)
100
+
101
+ ### Manual Coercion
102
+
103
+ You can override the smart defaults by specifying `coerce_to` directly in the step:
104
+
105
+ ```yaml
106
+ # Override prompt to use regular boolean instead of LLM boolean
107
+ - repeat:
108
+ until: "check_condition"
109
+ coerce_to: boolean
110
+ steps:
111
+ - process_item
112
+
113
+ # Force a step result to be treated as iterable
114
+ - each: "get_items"
115
+ as: "item"
116
+ coerce_to: iterable
117
+ steps:
118
+ - process: "{{item}}"
119
+ ```
120
+
121
+ Available coercion types:
122
+ - `boolean` - Standard Ruby truthiness (`!!` operator)
123
+ - `llm_boolean` - Natural language yes/no interpretation
124
+ - `iterable` - Convert to array (splits strings on newlines)
125
+
126
+ ## Migrating Existing Workflows
127
+
128
+ If you're updating existing workflows:
129
+
130
+ 1. For Ruby expressions, wrap them in `{{...}}`:
131
+ ```yaml
132
+ # Old
133
+ until: "output['counter'] >= 5"
134
+
135
+ # New
136
+ until: "{{output['counter'] >= 5}}"
137
+ ```
138
+
139
+ 2. Bash commands, step names, and prompts can remain unchanged.
140
+
141
+ ## Best Practices
142
+
143
+ - Use `{{...}}` for all Ruby expressions to make them explicit
144
+ - For complex conditions, consider creating a dedicated step that returns a boolean
145
+ - For collections, ensure they return iterable objects (arrays, hashes, etc.)
146
+ - Always set reasonable `max_iterations` limits on repeat loops
147
+ - Use meaningful variable names in `each` loops
@@ -0,0 +1,58 @@
1
+ # Case/When/Else Example
2
+
3
+ This example demonstrates the use of `case/when/else` control flow in Roast workflows.
4
+
5
+ ## Overview
6
+
7
+ The `case/when/else` construct allows you to execute different steps based on the value of an expression, similar to Ruby's case statement or switch statements in other languages.
8
+
9
+ ## Syntax
10
+
11
+ ```yaml
12
+ - case: <expression>
13
+ when:
14
+ <value1>:
15
+ - <steps>
16
+ <value2>:
17
+ - <steps>
18
+ else:
19
+ - <steps>
20
+ ```
21
+
22
+ ## Features Demonstrated
23
+
24
+ 1. **Basic case/when/else**: Detect file language and execute language-specific analysis
25
+ 2. **Bash command evaluation**: Use environment variables to determine deployment strategy
26
+ 3. **Complex expressions**: Use Ruby expressions to categorize numeric values
27
+
28
+ ## Expression Types
29
+
30
+ The `case` expression can be:
31
+ - A simple string value
32
+ - An interpolated workflow output: `{{ workflow.output.variable }}`
33
+ - A Ruby expression: `{{ workflow.output.count > 10 ? 'high' : 'low' }}`
34
+ - A bash command: `$(echo $ENVIRONMENT)`
35
+ - A reference to a previous step's output
36
+
37
+ ## How It Works
38
+
39
+ 1. The `case` expression is evaluated to produce a value
40
+ 2. The value is compared against each key in the `when` clause
41
+ 3. If a match is found, the steps under that key are executed
42
+ 4. If no match is found and an `else` clause exists, those steps are executed
43
+ 5. If no match is found and no `else` clause exists, execution continues
44
+
45
+ ## Running the Example
46
+
47
+ ```bash
48
+ roast execute examples/case_when/workflow.yml
49
+ ```
50
+
51
+ This will process all Ruby, JavaScript, Python, and Go files in the current directory, detecting their language and running appropriate analysis steps.
52
+
53
+ ## Use Cases
54
+
55
+ - **Multi-language projects**: Different linting/testing for different file types
56
+ - **Environment-specific workflows**: Different deployment steps for prod/staging/dev
57
+ - **Conditional processing**: Different handling based on file size, complexity, or other metrics
58
+ - **Error handling**: Different recovery strategies based on error types
@@ -0,0 +1,16 @@
1
+ # Detect Programming Language
2
+
3
+ Based on the file extension and content, determine the primary programming language of this file:
4
+ - If it's a `.rb` file, return "ruby"
5
+ - If it's a `.js` file, return "javascript"
6
+ - If it's a `.py` file, return "python"
7
+ - If it's a `.go` file, return "go"
8
+ - Otherwise, return "unknown"
9
+
10
+ Return ONLY the language name in lowercase, nothing else.
11
+
12
+ File: {{ context.resource_uri }}
13
+ Content:
14
+ ```
15
+ {{ context.resource }}
16
+ ```
@@ -0,0 +1,58 @@
1
+ name: "Case/When/Else Example"
2
+
3
+ tools:
4
+ - Roast::Tools::Cmd
5
+ - Roast::Tools::ReadFile
6
+ - Roast::Tools::WriteFile
7
+
8
+ target: "**/*.{rb,js,py,go}"
9
+
10
+ steps:
11
+ - detect_language
12
+
13
+ - case: "{{ workflow.output.detect_language }}"
14
+ when:
15
+ ruby:
16
+ - analyze_ruby
17
+ - generate_ruby_report
18
+ javascript:
19
+ - analyze_javascript
20
+ - generate_js_report
21
+ python:
22
+ - analyze_python
23
+ - generate_python_report
24
+ go:
25
+ - analyze_go
26
+ - generate_go_report
27
+ else:
28
+ - analyze_generic
29
+ - generate_generic_report
30
+
31
+ # Another example using bash command for case expression
32
+ - get_environment: $(echo $ENVIRONMENT || echo "development")
33
+
34
+ - case: "{{ workflow.output.get_environment }}"
35
+ when:
36
+ production:
37
+ - production_checks
38
+ - deploy_production
39
+ staging:
40
+ - staging_checks
41
+ - deploy_staging
42
+ development:
43
+ - run_tests
44
+ - local_deploy
45
+ else:
46
+ - unknown_environment
47
+
48
+ # Example with numeric case values
49
+ - count_issues
50
+
51
+ - case: "{{ workflow.output.count_issues.to_i > 10 ? 'high' : workflow.output.count_issues.to_i > 5 ? 'medium' : 'low' }}"
52
+ when:
53
+ high:
54
+ - high_priority_alert
55
+ medium:
56
+ - medium_priority_notice
57
+ low:
58
+ - low_priority_info
@@ -0,0 +1,161 @@
1
+ # Conditional Execution in Roast Workflows
2
+
3
+ This example demonstrates how to use conditional execution (`if` and `unless`) in Roast workflows.
4
+
5
+ ## Overview
6
+
7
+ Conditional execution allows workflows to execute different steps based on runtime conditions. This feature supports:
8
+
9
+ - `if` conditions - execute steps when a condition is true
10
+ - `unless` conditions - execute steps when a condition is false
11
+ - `then` branches - steps to execute when the condition matches
12
+ - `else` branches - steps to execute when the condition doesn't match (optional, only for `if`)
13
+
14
+ ## Syntax
15
+
16
+ ### If Statement
17
+
18
+ ```yaml
19
+ - if: "{{expression}}"
20
+ then:
21
+ - step1
22
+ - step2
23
+ else:
24
+ - step3
25
+ - step4
26
+ ```
27
+
28
+ ### Unless Statement
29
+
30
+ ```yaml
31
+ - unless: "{{expression}}"
32
+ then:
33
+ - step1
34
+ - step2
35
+ ```
36
+
37
+ ## Condition Types
38
+
39
+ Conditions can be:
40
+
41
+ 1. **Ruby Expressions** - Wrapped in `{{...}}`
42
+ ```yaml
43
+ - if: "{{output.previous_step.success == true}}"
44
+ ```
45
+
46
+ 2. **Bash Commands** - Wrapped in `$(...)`
47
+ ```yaml
48
+ - if: "$(test -f /path/to/file && echo true || echo false)"
49
+ ```
50
+
51
+ 3. **Step References** - Reference to previous step output
52
+ ```yaml
53
+ - if: "check_condition" # References a previous step
54
+ ```
55
+
56
+ 4. **File Checks**
57
+ ```yaml
58
+ - if: "{{File.exist?('/tmp/myfile.txt')}}"
59
+ ```
60
+
61
+ ## Examples
62
+
63
+ ### Basic Example
64
+
65
+ ```yaml
66
+ name: Conditional Example
67
+ tools:
68
+ - Roast::Tools::Cmd
69
+
70
+ steps:
71
+ - check_status: "echo 'success'"
72
+
73
+ - if: "{{output.check_status.strip == 'success'}}"
74
+ then:
75
+ - success_action: "echo 'Operation succeeded!'"
76
+ else:
77
+ - failure_action: "echo 'Operation failed!'"
78
+ ```
79
+
80
+ ### Unless Example
81
+
82
+ ```yaml
83
+ name: Unless Example
84
+ tools: []
85
+
86
+ steps:
87
+ - check_file: "test -f /tmp/important.txt && echo exists || echo missing"
88
+
89
+ - unless: "{{output.check_file.strip == 'exists'}}"
90
+ then:
91
+ - create_file: "touch /tmp/important.txt"
92
+ - notify: "echo 'Created missing file'"
93
+ ```
94
+
95
+ ### Nested Conditionals
96
+
97
+ ```yaml
98
+ name: Nested Conditionals
99
+ tools: []
100
+
101
+ steps:
102
+ - outer_check: "echo 'true'"
103
+ - inner_check: "echo 'false'"
104
+
105
+ - if: "{{output.outer_check.strip == 'true'}}"
106
+ then:
107
+ - if: "{{output.inner_check.strip == 'true'}}"
108
+ then:
109
+ - both_true: "echo 'Both conditions are true'"
110
+ else:
111
+ - only_outer: "echo 'Only outer condition is true'"
112
+ else:
113
+ - outer_false: "echo 'Outer condition is false'"
114
+ ```
115
+
116
+ ### Platform-Specific Actions
117
+
118
+ ```yaml
119
+ name: Platform Detection
120
+ tools:
121
+ - Roast::Tools::Cmd
122
+
123
+ steps:
124
+ - detect_os: "uname -s"
125
+
126
+ - if: "{{output.detect_os.strip == 'Darwin'}}"
127
+ then:
128
+ - mac_setup: "brew --version || echo 'Homebrew not installed'"
129
+ else:
130
+ - if: "{{output.detect_os.strip == 'Linux'}}"
131
+ then:
132
+ - linux_setup: "apt-get --version || yum --version"
133
+ else:
134
+ - unknown_os: "echo 'Unknown operating system'"
135
+ ```
136
+
137
+ ## Best Practices
138
+
139
+ 1. **Use Clear Conditions**: Make your conditions explicit and easy to understand
140
+ 2. **Handle Edge Cases**: Always consider what happens when conditions fail
141
+ 3. **Test Both Branches**: Ensure both `then` and `else` branches work correctly
142
+ 4. **Avoid Deep Nesting**: Keep conditional logic simple and readable
143
+ 5. **Use Unless Sparingly**: `unless` can be less intuitive than `if` with negation
144
+
145
+ ## Debugging
146
+
147
+ To debug conditional execution:
148
+
149
+ 1. Check the workflow output to see which branch was executed
150
+ 2. Look for keys like `if_condition_name` or `unless_condition_name` in the output
151
+ 3. These keys contain information about the condition evaluation and branch taken
152
+
153
+ ## Running the Example
154
+
155
+ ```bash
156
+ # Run the simple conditional example
157
+ roast execute examples/conditional/simple_workflow.yml
158
+
159
+ # Run the full conditional example (requires API configuration)
160
+ roast execute examples/conditional/workflow.yml
161
+ ```
@@ -0,0 +1 @@
1
+ Check if the OS is macOS or Linux and return true if it's macOS, false otherwise.
@@ -0,0 +1,15 @@
1
+ name: Simple Conditional Test
2
+ tools: []
3
+
4
+ steps:
5
+ - set_value: "$(echo 'true')"
6
+
7
+ - if: "{{output.set_value.strip == 'true'}}"
8
+ then:
9
+ - success: "$(echo 'If condition worked!')"
10
+ else:
11
+ - failure: "$(echo 'If condition failed!')"
12
+
13
+ - unless: "{{output.set_value.strip == 'false'}}"
14
+ then:
15
+ - unless_success: "$(echo 'Unless condition worked!')"
@@ -0,0 +1,23 @@
1
+ name: Conditional Execution Example
2
+ tools:
3
+ - Roast::Tools::Cmd
4
+
5
+ steps:
6
+ - check_os: "$(uname -s)"
7
+
8
+ - if: "{{output.check_os.strip == 'Darwin'}}"
9
+ then:
10
+ - mac_message: "$(echo 'Running on macOS!')"
11
+ - mac_info: "$(sw_vers)"
12
+ else:
13
+ - linux_message: "$(echo 'Running on Linux!')"
14
+ - linux_info: "$(lsb_release -a)"
15
+
16
+ - check_file: "$(test -f /tmp/roast_test.txt && echo exists || echo missing)"
17
+
18
+ - unless: "{{output.check_file.strip == 'exists'}}"
19
+ then:
20
+ - create_file: "$(touch /tmp/roast_test.txt && echo 'File created')"
21
+
22
+ - verify_file: "$(ls -la /tmp/roast_test.txt)"
23
+ - cleanup: "$(rm -f /tmp/roast_test.txt)"
@@ -0,0 +1,32 @@
1
+ # Direct Coerce Syntax
2
+
3
+ This example demonstrates the simplified syntax for specifying `coerce_to` and other configuration options directly on iteration steps.
4
+
5
+ ## Direct Syntax
6
+
7
+ Configuration options are specified directly on the step:
8
+
9
+ ```yaml
10
+ - repeat:
11
+ until: "condition"
12
+ coerce_to: boolean
13
+ print_response: true
14
+ model: "claude-3-haiku"
15
+ steps: [...]
16
+ ```
17
+
18
+ ## Benefits
19
+
20
+ 1. **Cleaner YAML** - No unnecessary nesting
21
+ 2. **More intuitive** - Configuration options are at the same level as other step properties
22
+ 3. **Consistent** - Matches how other step properties are specified
23
+
24
+ ## Supported Options
25
+
26
+ All step configuration options can be specified directly:
27
+ - `coerce_to` - Type coercion (boolean, llm_boolean, iterable)
28
+ - `print_response` - Whether to print LLM responses
29
+ - `loop` - Auto-loop behavior
30
+ - `json` - JSON response mode
31
+ - `params` - Additional parameters
32
+ - `model` - Model override
@@ -0,0 +1,36 @@
1
+ name: Direct Coerce Syntax Demo
2
+ description: Demonstrates the simplified coerce_to syntax without config blocks
3
+
4
+ steps:
5
+ # Example 1: Direct coerce_to on repeat
6
+ - repeat:
7
+ until: "check_api_ready"
8
+ coerce_to: boolean # Direct syntax - no config block needed
9
+ max_iterations: 5
10
+ steps:
11
+ - check_api_ready:
12
+ prompt: "Check if the API endpoint returns a 200 status"
13
+ - wait: 2
14
+
15
+ # Example 2: Direct coerce_to on each
16
+ - get_data_sources:
17
+ prompt: "List available data sources, one per line"
18
+
19
+ - each: "get_data_sources"
20
+ as: "source"
21
+ coerce_to: iterable # Direct syntax
22
+ steps:
23
+ - validate_source: "Validating {{source}}..."
24
+ - process_source:
25
+ prompt: "Process data from {{source}}"
26
+
27
+ # Example 3: Multiple configuration options
28
+ - repeat:
29
+ until: "all_tests_pass"
30
+ coerce_to: llm_boolean # Override default
31
+ print_response: true # Other options work too
32
+ max_iterations: 10
33
+ steps:
34
+ - run_tests: "$(rake test)"
35
+ - all_tests_pass:
36
+ prompt: "Did all tests pass successfully?"
@@ -0,0 +1,37 @@
1
+ # Dot Notation Access Example
2
+
3
+ This example demonstrates the new dot notation access feature for workflow outputs.
4
+
5
+ ## Usage
6
+
7
+ With the new dot notation feature, you can access output values using Ruby's method syntax instead of hash syntax:
8
+
9
+ ### Before (hash syntax):
10
+ ```yaml
11
+ until: "output[:update_fix_count][:fixes_applied] >= 5 || output[:select_next_issue][:no_issues_left] == true"
12
+ ```
13
+
14
+ ### After (dot notation):
15
+ ```yaml
16
+ until: "output.update_fix_count.fixes_applied >= 5 || output.select_next_issue.no_issues_left?"
17
+ ```
18
+
19
+ ### Even cleaner (omitting output prefix):
20
+ ```yaml
21
+ until: "update_fix_count.fixes_applied >= 5 || select_next_issue.no_issues_left?"
22
+ ```
23
+
24
+ ## Features
25
+
26
+ 1. **Nested access**: `output.step_name.nested.value`
27
+ 2. **Boolean predicates**: `output.step_name.is_complete?` returns false for nil/false values
28
+ 3. **Direct access**: Omit the `output.` prefix for cleaner syntax
29
+ 4. **Backward compatible**: Hash syntax still works (`output[:step_name][:value]`)
30
+
31
+ ## Example Workflow
32
+
33
+ See `workflow.yml` for a complete example that demonstrates:
34
+ - Setting values in output
35
+ - Using dot notation in conditions
36
+ - Boolean predicate methods
37
+ - Nested value access
@@ -0,0 +1,44 @@
1
+ name: dot_notation_example
2
+ description: Example demonstrating dot notation access for workflow outputs
3
+
4
+ steps:
5
+ initialize:
6
+ prompt: |
7
+ Initialize the workflow with some sample data.
8
+
9
+ Set output.counter to 0
10
+ Set output.config.max_iterations to 5
11
+ Set output.config.enabled to true
12
+
13
+ process_items:
14
+ repeat:
15
+ # Using dot notation in conditions
16
+ until: "counter >= config.max_iterations || !config.enabled?"
17
+ steps:
18
+ - increment_counter
19
+ - check_status
20
+
21
+ increment_counter:
22
+ prompt: |
23
+ Increment the counter by 1.
24
+ Current counter value: {{counter}}
25
+
26
+ Set output.counter to {{counter}} + 1
27
+
28
+ check_status:
29
+ prompt: |
30
+ Check if we should continue processing.
31
+
32
+ Current counter: {{counter}}
33
+ Max iterations: {{config.max_iterations}}
34
+
35
+ If counter is 3, set output.config.enabled to false
36
+ Set output.status.last_checked to current counter value
37
+
38
+ summarize:
39
+ prompt: |
40
+ Summarize the results:
41
+ - Total iterations: {{counter}}
42
+ - Last checked at: {{status.last_checked}}
43
+ - Was enabled: {{config.enabled}}
44
+ - Hit max iterations: {{counter >= config.max_iterations ? "Yes" : "No"}}
@@ -0,0 +1,50 @@
1
+ # Exit on Error Example
2
+
3
+ This example demonstrates how to use the `exit_on_error` configuration option to continue workflow execution even when a command fails.
4
+
5
+ ## Use Case
6
+
7
+ When running a linter like RuboCop on a file with syntax errors or style violations, the command will exit with a non-zero status. By default, this would halt the workflow. However, we often want to:
8
+
9
+ 1. Capture the linter output (including errors)
10
+ 2. Analyze what went wrong
11
+ 3. Apply fixes based on the analysis
12
+
13
+ ## Configuration
14
+
15
+ The key configuration is in the step configuration section:
16
+
17
+ ```yaml
18
+ lint_check:
19
+ exit_on_error: false
20
+ ```
21
+
22
+ This tells Roast to:
23
+ - Continue workflow execution even if the command fails
24
+ - Capture the full output (stdout and stderr)
25
+ - Append the exit status to the output
26
+
27
+ ## Output Format
28
+
29
+ When a command fails with `exit_on_error: false`, the output will look like:
30
+
31
+ ```
32
+ lib/example.rb:5:3: C: Style/StringLiterals: Prefer double-quoted strings
33
+ 'hello'
34
+ ^^^^^^^
35
+ [Exit status: 1]
36
+ ```
37
+
38
+ This allows subsequent steps to process both the error output and the exit status.
39
+
40
+ ## Running the Example
41
+
42
+ ```bash
43
+ roast execute workflow.yml path/to/file.rb
44
+ ```
45
+
46
+ The workflow will:
47
+ 1. Run RuboCop on the file
48
+ 2. Continue even if RuboCop finds issues
49
+ 3. Analyze the linter output
50
+ 4. Apply fixes based on the analysis
@@ -0,0 +1,9 @@
1
+ The linter output from the previous step shows issues with the code.
2
+ Please analyze the output and identify the specific problems that need to be fixed.
3
+
4
+ Focus on:
5
+ - Syntax errors
6
+ - Style violations
7
+ - Best practice violations
8
+
9
+ Provide a structured list of issues found.