roast-ai 0.4.7 → 0.4.9

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 (311) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +1 -0
  4. data/Gemfile.lock +3 -3
  5. data/README.md +9 -5
  6. data/Rakefile +2 -0
  7. data/dsl/less_simple.rb +112 -0
  8. data/dsl/prototype.rb +17 -0
  9. data/dsl/simple.rb +5 -7
  10. data/dsl/step_communication.rb +18 -0
  11. data/examples/README.md +9 -0
  12. data/examples/available_tools_demo/workflow.yml +1 -1
  13. data/examples/basic_prompt_workflow/workflow.md +1 -0
  14. data/examples/basic_prompt_workflow/workflow.yml +14 -0
  15. data/examples/grading/README.md +1 -26
  16. data/examples/grading/analyze_coverage/prompt.md +1 -1
  17. data/examples/grading/calculate_final_grade.rb +10 -13
  18. data/examples/grading/format_result.rb +5 -8
  19. data/examples/grading/generate_grades/prompt.md +1 -1
  20. data/examples/grading/generate_recommendations/prompt.md +1 -1
  21. data/examples/grading/read_dependencies/prompt.md +0 -1
  22. data/examples/grading/verify_test_helpers/prompt.md +1 -1
  23. data/examples/grading/workflow.md +1 -4
  24. data/examples/grading/workflow.yml +3 -16
  25. data/lib/roast/dsl/cog/config.rb +31 -0
  26. data/lib/roast/dsl/cog/stack.rb +21 -0
  27. data/lib/roast/dsl/cog/store.rb +26 -0
  28. data/lib/roast/dsl/cog.rb +70 -0
  29. data/lib/roast/dsl/cog_execution_context.rb +29 -0
  30. data/lib/roast/dsl/cogs/cmd.rb +55 -0
  31. data/lib/roast/dsl/cogs/graph.rb +53 -0
  32. data/lib/roast/dsl/cogs.rb +65 -0
  33. data/lib/roast/dsl/config_context.rb +54 -0
  34. data/lib/roast/dsl/executor.rb +62 -7
  35. data/lib/roast/dsl/workflow_execution_context.rb +47 -0
  36. data/lib/roast/error.rb +7 -0
  37. data/lib/roast/errors.rb +3 -3
  38. data/lib/roast/graph/edge.rb +25 -0
  39. data/lib/roast/graph/node.rb +40 -0
  40. data/lib/roast/graph/quantum_edge.rb +27 -0
  41. data/lib/roast/graph/threaded_exec.rb +93 -0
  42. data/lib/roast/graph.rb +233 -0
  43. data/lib/roast/resources/api_resource.rb +2 -2
  44. data/lib/roast/resources/url_resource.rb +2 -2
  45. data/lib/roast/tools/apply_diff.rb +1 -1
  46. data/lib/roast/tools/ask_user.rb +1 -1
  47. data/lib/roast/tools/bash.rb +1 -1
  48. data/lib/roast/tools/cmd.rb +2 -2
  49. data/lib/roast/tools/coding_agent.rb +2 -2
  50. data/lib/roast/tools/grep.rb +1 -1
  51. data/lib/roast/tools/read_file.rb +1 -1
  52. data/lib/roast/tools/search_file.rb +1 -1
  53. data/lib/roast/tools/swarm.rb +1 -1
  54. data/lib/roast/tools/update_files.rb +2 -2
  55. data/lib/roast/tools/write_file.rb +1 -1
  56. data/lib/roast/tools.rb +1 -1
  57. data/lib/roast/value_objects/api_token.rb +1 -1
  58. data/lib/roast/value_objects/uri_base.rb +1 -1
  59. data/lib/roast/value_objects/workflow_path.rb +1 -1
  60. data/lib/roast/version.rb +1 -1
  61. data/lib/roast/workflow/base_step.rb +2 -3
  62. data/lib/roast/workflow/base_workflow.rb +38 -2
  63. data/lib/roast/workflow/command_executor.rb +1 -1
  64. data/lib/roast/workflow/configuration_loader.rb +1 -1
  65. data/lib/roast/workflow/error_handler.rb +1 -1
  66. data/lib/roast/workflow/step_executor_registry.rb +1 -1
  67. data/lib/roast/workflow/step_loader.rb +3 -8
  68. data/lib/roast/workflow/workflow_executor.rb +1 -1
  69. data/lib/roast.rb +7 -2
  70. data/sorbet/config +2 -0
  71. data/sorbet/rbi/annotations/.gitattributes +1 -0
  72. data/sorbet/rbi/annotations/activesupport.rbi +495 -0
  73. data/sorbet/rbi/annotations/faraday.rbi +17 -0
  74. data/sorbet/rbi/annotations/minitest.rbi +119 -0
  75. data/sorbet/rbi/annotations/mocha.rbi +34 -0
  76. data/sorbet/rbi/annotations/rainbow.rbi +269 -0
  77. data/sorbet/rbi/annotations/webmock.rbi +9 -0
  78. data/sorbet/rbi/gems/rbs-inline@0.12.0.rbi +2170 -0
  79. data/sorbet/rbi/gems/{rexml@3.4.1.rbi → rexml@3.4.2.rbi} +284 -239
  80. data/sorbet/rbi/shims/lib/roast/dsl/config_context.rbi +11 -0
  81. data/sorbet/rbi/shims/lib/roast/dsl/workflow_execution_context.rbi +11 -0
  82. data/sorbet/rbi/todo.rbi +7 -0
  83. metadata +37 -231
  84. data/CHANGELOG.md +0 -369
  85. data/examples/agent_continue/add_documentation/prompt.md +0 -5
  86. data/examples/agent_continue/add_error_handling/prompt.md +0 -5
  87. data/examples/agent_continue/analyze_codebase/prompt.md +0 -7
  88. data/examples/agent_continue/combined_workflow.yml +0 -24
  89. data/examples/agent_continue/continue_adding_features/prompt.md +0 -4
  90. data/examples/agent_continue/create_integration_tests/prompt.md +0 -3
  91. data/examples/agent_continue/document_with_context/prompt.md +0 -5
  92. data/examples/agent_continue/explore_api/prompt.md +0 -6
  93. data/examples/agent_continue/implement_client/prompt.md +0 -6
  94. data/examples/agent_continue/inline_workflow.yml +0 -20
  95. data/examples/agent_continue/refactor_code/prompt.md +0 -2
  96. data/examples/agent_continue/verify_changes/prompt.md +0 -6
  97. data/examples/agent_continue/workflow.yml +0 -27
  98. data/examples/agent_workflow/README.md +0 -75
  99. data/examples/agent_workflow/apply_refactorings/prompt.md +0 -22
  100. data/examples/agent_workflow/identify_code_smells/prompt.md +0 -15
  101. data/examples/agent_workflow/summarize_improvements/prompt.md +0 -18
  102. data/examples/agent_workflow/workflow.png +0 -0
  103. data/examples/agent_workflow/workflow.yml +0 -16
  104. data/examples/api_workflow/README.md +0 -85
  105. data/examples/api_workflow/fetch_api_data/prompt.md +0 -10
  106. data/examples/api_workflow/generate_report/prompt.md +0 -10
  107. data/examples/api_workflow/prompt.md +0 -10
  108. data/examples/api_workflow/transform_data/prompt.md +0 -10
  109. data/examples/api_workflow/workflow.png +0 -0
  110. data/examples/api_workflow/workflow.yml +0 -30
  111. data/examples/apply_diff_demo/README.md +0 -58
  112. data/examples/apply_diff_demo/apply_simple_change/prompt.md +0 -13
  113. data/examples/apply_diff_demo/create_sample_file/prompt.md +0 -11
  114. data/examples/apply_diff_demo/workflow.yml +0 -24
  115. data/examples/available_tools_demo/workflow.png +0 -0
  116. data/examples/bash_prototyping/README.md +0 -53
  117. data/examples/bash_prototyping/analyze_network/prompt.md +0 -13
  118. data/examples/bash_prototyping/analyze_system/prompt.md +0 -11
  119. data/examples/bash_prototyping/api_testing.png +0 -0
  120. data/examples/bash_prototyping/api_testing.yml +0 -14
  121. data/examples/bash_prototyping/check_processes/prompt.md +0 -11
  122. data/examples/bash_prototyping/generate_report/prompt.md +0 -16
  123. data/examples/bash_prototyping/process_json_response/prompt.md +0 -24
  124. data/examples/bash_prototyping/system_analysis.png +0 -0
  125. data/examples/bash_prototyping/system_analysis.yml +0 -14
  126. data/examples/bash_prototyping/test_public_api/prompt.md +0 -22
  127. data/examples/case_when/README.md +0 -58
  128. data/examples/case_when/detect_language/prompt.md +0 -16
  129. data/examples/case_when/workflow.png +0 -0
  130. data/examples/case_when/workflow.yml +0 -58
  131. data/examples/cmd/README.md +0 -99
  132. data/examples/cmd/analyze_project/prompt.md +0 -57
  133. data/examples/cmd/basic_demo/prompt.md +0 -48
  134. data/examples/cmd/basic_workflow.png +0 -0
  135. data/examples/cmd/basic_workflow.yml +0 -16
  136. data/examples/cmd/check_repository/prompt.md +0 -57
  137. data/examples/cmd/create_and_verify/prompt.md +0 -56
  138. data/examples/cmd/dev_workflow.png +0 -0
  139. data/examples/cmd/dev_workflow.yml +0 -26
  140. data/examples/cmd/explore_project/prompt.md +0 -67
  141. data/examples/cmd/explorer_workflow.png +0 -0
  142. data/examples/cmd/explorer_workflow.yml +0 -21
  143. data/examples/cmd/smart_tool_selection/prompt.md +0 -99
  144. data/examples/coding_agent_with_model.yml +0 -20
  145. data/examples/coding_agent_with_retries.yml +0 -30
  146. data/examples/conditional/README.md +0 -161
  147. data/examples/conditional/check_condition/prompt.md +0 -1
  148. data/examples/conditional/simple_workflow.png +0 -0
  149. data/examples/conditional/simple_workflow.yml +0 -15
  150. data/examples/conditional/workflow.png +0 -0
  151. data/examples/conditional/workflow.yml +0 -23
  152. data/examples/context_management_demo/README.md +0 -43
  153. data/examples/context_management_demo/workflow.yml +0 -42
  154. data/examples/direct_coerce_syntax/README.md +0 -32
  155. data/examples/direct_coerce_syntax/workflow.png +0 -0
  156. data/examples/direct_coerce_syntax/workflow.yml +0 -36
  157. data/examples/dot_notation/README.md +0 -37
  158. data/examples/dot_notation/workflow.png +0 -0
  159. data/examples/dot_notation/workflow.yml +0 -44
  160. data/examples/exit_on_error/README.md +0 -50
  161. data/examples/exit_on_error/analyze_lint_output/prompt.md +0 -9
  162. data/examples/exit_on_error/apply_fixes/prompt.md +0 -2
  163. data/examples/exit_on_error/workflow.png +0 -0
  164. data/examples/exit_on_error/workflow.yml +0 -19
  165. data/examples/grading/js_test_runner +0 -31
  166. data/examples/grading/rb_test_runner +0 -19
  167. data/examples/grading/run_coverage.rb +0 -54
  168. data/examples/grading/workflow.png +0 -0
  169. data/examples/grading/workflow.rb.md +0 -6
  170. data/examples/grading/workflow.ts+tsx.md +0 -6
  171. data/examples/instrumentation.rb +0 -76
  172. data/examples/interpolation/README.md +0 -50
  173. data/examples/interpolation/analyze_file/prompt.md +0 -1
  174. data/examples/interpolation/analyze_patterns/prompt.md +0 -27
  175. data/examples/interpolation/generate_report_for_js/prompt.md +0 -3
  176. data/examples/interpolation/generate_report_for_rb/prompt.md +0 -3
  177. data/examples/interpolation/sample.js +0 -48
  178. data/examples/interpolation/sample.rb +0 -42
  179. data/examples/interpolation/workflow.md +0 -1
  180. data/examples/interpolation/workflow.png +0 -0
  181. data/examples/interpolation/workflow.yml +0 -21
  182. data/examples/iteration/IMPLEMENTATION.md +0 -88
  183. data/examples/iteration/README.md +0 -68
  184. data/examples/iteration/analyze_complexity/prompt.md +0 -22
  185. data/examples/iteration/generate_recommendations/prompt.md +0 -21
  186. data/examples/iteration/generate_report/prompt.md +0 -129
  187. data/examples/iteration/implement_fix/prompt.md +0 -25
  188. data/examples/iteration/prioritize_issues/prompt.md +0 -24
  189. data/examples/iteration/prompts/analyze_file.md +0 -28
  190. data/examples/iteration/prompts/generate_summary.md +0 -24
  191. data/examples/iteration/prompts/update_report.md +0 -29
  192. data/examples/iteration/prompts/write_report.md +0 -22
  193. data/examples/iteration/read_file/prompt.md +0 -9
  194. data/examples/iteration/select_next_issue/prompt.md +0 -25
  195. data/examples/iteration/simple_workflow.md +0 -39
  196. data/examples/iteration/simple_workflow.yml +0 -58
  197. data/examples/iteration/update_fix_count/prompt.md +0 -26
  198. data/examples/iteration/verify_fix/prompt.md +0 -29
  199. data/examples/iteration/workflow.png +0 -0
  200. data/examples/iteration/workflow.yml +0 -42
  201. data/examples/json_handling/README.md +0 -32
  202. data/examples/json_handling/workflow.png +0 -0
  203. data/examples/json_handling/workflow.yml +0 -52
  204. data/examples/mcp/README.md +0 -223
  205. data/examples/mcp/analyze_changes/prompt.md +0 -8
  206. data/examples/mcp/analyze_issues/prompt.md +0 -4
  207. data/examples/mcp/analyze_schema/prompt.md +0 -4
  208. data/examples/mcp/check_data_quality/prompt.md +0 -5
  209. data/examples/mcp/check_documentation/prompt.md +0 -4
  210. data/examples/mcp/create_recommendations/prompt.md +0 -5
  211. data/examples/mcp/database_workflow.png +0 -0
  212. data/examples/mcp/database_workflow.yml +0 -29
  213. data/examples/mcp/env_demo/workflow.png +0 -0
  214. data/examples/mcp/env_demo/workflow.yml +0 -34
  215. data/examples/mcp/fetch_pr_context/prompt.md +0 -4
  216. data/examples/mcp/filesystem_demo/create_test_file/prompt.md +0 -2
  217. data/examples/mcp/filesystem_demo/list_files/prompt.md +0 -6
  218. data/examples/mcp/filesystem_demo/read_with_mcp/prompt.md +0 -7
  219. data/examples/mcp/filesystem_demo/workflow.png +0 -0
  220. data/examples/mcp/filesystem_demo/workflow.yml +0 -38
  221. data/examples/mcp/generate_insights/prompt.md +0 -4
  222. data/examples/mcp/generate_report/prompt.md +0 -6
  223. data/examples/mcp/generate_review/prompt.md +0 -16
  224. data/examples/mcp/github_workflow.png +0 -0
  225. data/examples/mcp/github_workflow.yml +0 -32
  226. data/examples/mcp/multi_mcp_workflow.png +0 -0
  227. data/examples/mcp/multi_mcp_workflow.yml +0 -58
  228. data/examples/mcp/post_review/prompt.md +0 -3
  229. data/examples/mcp/save_report/prompt.md +0 -6
  230. data/examples/mcp/search_issues/prompt.md +0 -2
  231. data/examples/mcp/summarize/prompt.md +0 -1
  232. data/examples/mcp/test_filesystem/prompt.md +0 -6
  233. data/examples/mcp/test_github/prompt.md +0 -8
  234. data/examples/mcp/test_read/prompt.md +0 -1
  235. data/examples/mcp/workflow.png +0 -0
  236. data/examples/mcp/workflow.yml +0 -35
  237. data/examples/no_model_fallback/README.md +0 -17
  238. data/examples/no_model_fallback/analyze_file/prompt.md +0 -1
  239. data/examples/no_model_fallback/analyze_patterns/prompt.md +0 -27
  240. data/examples/no_model_fallback/generate_report_for_md/prompt.md +0 -10
  241. data/examples/no_model_fallback/generate_report_for_rb/prompt.md +0 -3
  242. data/examples/no_model_fallback/sample.rb +0 -42
  243. data/examples/no_model_fallback/workflow.yml +0 -19
  244. data/examples/openrouter_example/README.md +0 -48
  245. data/examples/openrouter_example/analyze_input/prompt.md +0 -16
  246. data/examples/openrouter_example/generate_response/prompt.md +0 -9
  247. data/examples/openrouter_example/workflow.png +0 -0
  248. data/examples/openrouter_example/workflow.yml +0 -12
  249. data/examples/pre_post_processing/README.md +0 -111
  250. data/examples/pre_post_processing/analyze_test_file/prompt.md +0 -23
  251. data/examples/pre_post_processing/improve_test_coverage/prompt.md +0 -17
  252. data/examples/pre_post_processing/optimize_test_performance/prompt.md +0 -25
  253. data/examples/pre_post_processing/post_processing/aggregate_metrics/prompt.md +0 -31
  254. data/examples/pre_post_processing/post_processing/cleanup_environment/prompt.md +0 -28
  255. data/examples/pre_post_processing/post_processing/generate_summary_report/prompt.md +0 -32
  256. data/examples/pre_post_processing/post_processing/output.txt +0 -24
  257. data/examples/pre_post_processing/pre_processing/gather_baseline_metrics/prompt.md +0 -26
  258. data/examples/pre_post_processing/pre_processing/setup_test_environment/prompt.md +0 -11
  259. data/examples/pre_post_processing/validate_changes/prompt.md +0 -24
  260. data/examples/pre_post_processing/workflow.png +0 -0
  261. data/examples/pre_post_processing/workflow.yml +0 -21
  262. data/examples/retry/workflow.yml +0 -23
  263. data/examples/rspec_to_minitest/README.md +0 -68
  264. data/examples/rspec_to_minitest/analyze_spec/prompt.md +0 -30
  265. data/examples/rspec_to_minitest/create_minitest/prompt.md +0 -33
  266. data/examples/rspec_to_minitest/run_and_improve/prompt.md +0 -35
  267. data/examples/rspec_to_minitest/workflow.md +0 -10
  268. data/examples/rspec_to_minitest/workflow.png +0 -0
  269. data/examples/rspec_to_minitest/workflow.yml +0 -40
  270. data/examples/shared_config/README.md +0 -52
  271. data/examples/shared_config/example_with_shared_config/workflow.png +0 -0
  272. data/examples/shared_config/example_with_shared_config/workflow.yml +0 -6
  273. data/examples/shared_config/shared.png +0 -0
  274. data/examples/shared_config/shared.yml +0 -7
  275. data/examples/single_target_prepost/README.md +0 -36
  276. data/examples/single_target_prepost/post_processing/output.txt +0 -27
  277. data/examples/single_target_prepost/pre_processing/gather_dependencies/prompt.md +0 -11
  278. data/examples/single_target_prepost/workflow.png +0 -0
  279. data/examples/single_target_prepost/workflow.yml +0 -20
  280. data/examples/smart_coercion_defaults/README.md +0 -65
  281. data/examples/smart_coercion_defaults/workflow.png +0 -0
  282. data/examples/smart_coercion_defaults/workflow.yml +0 -44
  283. data/examples/step_configuration/README.md +0 -84
  284. data/examples/step_configuration/workflow.png +0 -0
  285. data/examples/step_configuration/workflow.yml +0 -57
  286. data/examples/swarm_example.yml +0 -25
  287. data/examples/tool_config_example/README.md +0 -109
  288. data/examples/tool_config_example/example_step/prompt.md +0 -42
  289. data/examples/tool_config_example/workflow.png +0 -0
  290. data/examples/tool_config_example/workflow.yml +0 -17
  291. data/examples/user_input/README.md +0 -90
  292. data/examples/user_input/funny_name/create_backstory/prompt.md +0 -10
  293. data/examples/user_input/funny_name/workflow.png +0 -0
  294. data/examples/user_input/funny_name/workflow.yml +0 -25
  295. data/examples/user_input/generate_summary/prompt.md +0 -11
  296. data/examples/user_input/simple_input_demo/workflow.png +0 -0
  297. data/examples/user_input/simple_input_demo/workflow.yml +0 -35
  298. data/examples/user_input/survey_workflow.png +0 -0
  299. data/examples/user_input/survey_workflow.yml +0 -71
  300. data/examples/user_input/welcome_message/prompt.md +0 -3
  301. data/examples/user_input/workflow.png +0 -0
  302. data/examples/user_input/workflow.yml +0 -73
  303. data/examples/workflow_generator/README.md +0 -27
  304. data/examples/workflow_generator/analyze_user_request/prompt.md +0 -34
  305. data/examples/workflow_generator/create_workflow_files/prompt.md +0 -32
  306. data/examples/workflow_generator/get_user_input/prompt.md +0 -14
  307. data/examples/workflow_generator/info_from_roast.rb +0 -22
  308. data/examples/workflow_generator/workflow.png +0 -0
  309. data/examples/workflow_generator/workflow.yml +0 -34
  310. data/package-lock.json +0 -6
  311. /data/sorbet/rbi/gems/{rack@2.2.17.rbi → rack@2.2.18.rbi} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f1d2d1b26f4618a6036bc890e0426b5fe6c10dfd530e1c391d68b46680d2c2bc
4
- data.tar.gz: e6b5670d414a2349c639b45a9b9d7b45b74a6dafc48cd706fedf8b55af88b6d2
3
+ metadata.gz: fc01ff6a90dbe17c735b17935bb75bcfda0ee47c0b9dbee6234292cc4f5f3799
4
+ data.tar.gz: caa21e581b5476a65c2dc8b0b7a27f1b20baf2f493260d954785724f73a3ff40
5
5
  SHA512:
6
- metadata.gz: 447c20f3a2b170ce7ced6c14c5a1f62117299a984f513a6fb83f9c53934bbb6239c3dd11a791fe0437475af127a315120140b6e1918c124c25d774e3cc1cf2d3
7
- data.tar.gz: cabe9380d1d1859c49d71d79547a1cc13f0d15f550aa373d82523384a0a8a8dda1f21bf1a6a2bfb2196bf3e4d6f1161ff047cbd498ca790c90e86006629e972b
6
+ metadata.gz: 6ea65bb2381627119b5740f9353b064d046e26b2769e0be36baf3f13b9696e30e6bd6332fbbf8c4305fea33d1b2bb12d81a4a56871f3793c3718e2ac8407c6ae
7
+ data.tar.gz: 23ff60c01817d64bae76bb16c0395d8cc7aa95cd621550cebc5fc6763fcf5ba8a023542bf07b49067fa9210d8f228f538b0e82159d897397d08532deece73bc4
data/.gitignore CHANGED
@@ -8,6 +8,7 @@
8
8
  /pkg/
9
9
  /spec/reports/
10
10
  /tmp/
11
+ /sig/generated/
11
12
  .CLAUDE.local.md
12
13
  .rspec_status
13
14
  **/.claude/settings.local.json
data/.rubocop.yml CHANGED
@@ -15,6 +15,7 @@ AllCops:
15
15
  - 'bin/*'
16
16
  - 'spec/fixtures/**/*'
17
17
  - 'test/fixtures/**/*'
18
+ - 'examples/**/*'
18
19
  SuggestExtensions: false
19
20
  TargetRubyVersion: 3.4
20
21
  UseCache: true
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- roast-ai (0.4.7)
4
+ roast-ai (0.4.9)
5
5
  activesupport (>= 7.0)
6
6
  cli-kit (~> 5.0)
7
7
  cli-ui (= 2.3.0)
@@ -167,7 +167,7 @@ GEM
167
167
  method_source (~> 1.0)
168
168
  public_suffix (6.0.2)
169
169
  racc (1.8.1)
170
- rack (2.2.17)
170
+ rack (2.2.19)
171
171
  rainbow (3.1.1)
172
172
  raix (1.0.2)
173
173
  activesupport (>= 6.0)
@@ -185,7 +185,7 @@ GEM
185
185
  rbs (3.9.4)
186
186
  logger
187
187
  regexp_parser (2.10.0)
188
- rexml (3.4.1)
188
+ rexml (3.4.2)
189
189
  rubocop (1.77.0)
190
190
  json (~> 2.3)
191
191
  language_server-protocol (~> 3.17.0.2)
data/README.md CHANGED
@@ -374,20 +374,24 @@ Roast supports several types of steps:
374
374
  ```yaml
375
375
  steps:
376
376
  - analyze_code
377
- - get_user_feedback:
377
+ - input:
378
+ name: get_user_feedback
378
379
  prompt: "Should we proceed with the refactoring? (yes/no)"
379
380
  type: confirm
380
- - review_changes:
381
+ - input:
382
+ name: review_changes
381
383
  prompt: "Enter your review comments"
382
384
  type: text
383
- - select_strategy:
385
+ - input:
386
+ name: select_strategy
384
387
  prompt: "Choose optimization strategy"
385
- type: select
388
+ type: choice
386
389
  options:
387
390
  - "Performance optimization"
388
391
  - "Memory optimization"
389
392
  - "Code clarity"
390
- - api_configuration:
393
+ - input:
394
+ name: api_configuration
391
395
  prompt: "Enter API key"
392
396
  type: password
393
397
  ```
data/Rakefile CHANGED
@@ -31,3 +31,5 @@ RuboCop::RakeTask.new(:rubocop) do |task|
31
31
  end
32
32
 
33
33
  task default: [:test, :rubocop]
34
+
35
+ task lint: [:rubocop]
@@ -0,0 +1,112 @@
1
+ # typed: false
2
+ # frozen_string_literal: true
3
+
4
+ #### cmd
5
+
6
+ # Passing just the command to execute will run it and return the output
7
+ cmd <<~SHELLSTEP
8
+ echo "raw run without storing, should see me once""
9
+ SHELLSTEP
10
+
11
+ # Passing a name finds or creates an object and returns that
12
+ cmd_cog = cmd(:hello)
13
+ puts "This is our new cmd_cog named ':hello': #{cmd_cog}"
14
+
15
+ # We can set a command to run for later
16
+ cmd(:set_and_run).set("echo 'set_and_run, should see me once'")
17
+ cmd(:set_and_run).run
18
+
19
+ # Similarly, we can run immediately and then re-run later
20
+ cmd(:run_and_rerun).run("echo 'run_and_rerun, should see me twice'")
21
+ cmd(:run_and_rerun).run
22
+
23
+ #### graph
24
+
25
+ # We can open and re-open a graph, and then execute it
26
+ graph(:updatable) do |graph|
27
+ graph.node(:open_cmd) do |state|
28
+ state[:open] = cmd("echo 'From a node added in first open, should see me once'")
29
+ end
30
+ end
31
+
32
+ graph(:updatable) do |graph|
33
+ graph.node(:reopen_cmd) do |state|
34
+ state[:reopen] = cmd("echo 'From a node added in reopen, should see me once'")
35
+ end
36
+ end
37
+
38
+ graph(:yea).execute
39
+
40
+ # We can also just populate and execute a graph in one go by calling graph.execute in the block.
41
+ graph(:define_and_exec) do |graph|
42
+ graph.node(:hi) do |state|
43
+ state[:hi_msg] = cmd("echo 'hi msg'")
44
+ end
45
+
46
+ graph.execute
47
+ end
48
+
49
+ # We can have subgraphs, because why not
50
+ graph(:outer) do |graph|
51
+ graph.subgraph(:inner) do |subgraph|
52
+ subgraph.node(:inner_node) do |inner_state|
53
+ inner_state[:foo] = cmd("echo 'inner_state foo'")
54
+ end
55
+ end
56
+
57
+ graph.node(:outer) do |outer_state|
58
+ outer_state[:bar] = cmd("echo 'outer_state bar'")
59
+ end
60
+
61
+ graph.execute
62
+ end
63
+
64
+ # We can specify our own edges
65
+ graph(:edges) do |graph|
66
+ graph.node(:thing1) do |state|
67
+ state[:thing1] = cmd("echo 'thing1'")
68
+ end
69
+
70
+ graph.node(:thing2) do |state|
71
+ state[:thing2] = cmd("echo 'thing2'")
72
+ end
73
+
74
+ graph.edge(from: :START, to: :thing1)
75
+ graph.edge(from: :thing1, to: :thing2)
76
+ graph.edge(from: :thing2, to: :DONE)
77
+
78
+ graph.execute
79
+ end
80
+
81
+ # We can have parallel execution
82
+ graph(:parallel) do |graph|
83
+ graph.node(:thing1) do |state|
84
+ state[:thing1] = cmd("sleep 0.5 && echo 'parallel thing1'")
85
+ end
86
+
87
+ graph.node(:thing2) do |state|
88
+ state[:thing2] = cmd("sleep 0.5 && echo 'parallel thing2'")
89
+ end
90
+
91
+ graph.edge(from: :START, to: [:thing1, :thing2])
92
+ graph.edge(from: [:thing1, :thing2], to: :DONE)
93
+
94
+ graph.execute
95
+ end
96
+
97
+ # We can have edges that are defined with a block
98
+ graph(:quantum) do |graph|
99
+ graph.node(:thing1) do |state|
100
+ state[:thing1] = cmd("echo 'quantum thing1'")
101
+ end
102
+
103
+ graph.edge(from: :START) do |_state|
104
+ :thing1
105
+ end
106
+
107
+ graph.edge(from: :thing1) do |_state|
108
+ :DONE
109
+ end
110
+
111
+ graph.execute
112
+ end
data/dsl/prototype.rb ADDED
@@ -0,0 +1,17 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ #: self as Roast::DSL::Executor
5
+
6
+ config do
7
+ cmd(:echo) { print_all! }
8
+ end
9
+
10
+ execute do
11
+ # Anonymous cog. Added to the stack directly and given an autogenerated key in cog storage
12
+ # Use for actions you do once and forget about, don't need configuration
13
+ cmd { "touch tmp/#{SecureRandom.uuid} " }
14
+
15
+ # Named cog. Configuration for this specific instance will be looked up from config block
16
+ cmd(:echo) { "echo 'Hello World!'" }
17
+ end
data/dsl/simple.rb CHANGED
@@ -1,10 +1,8 @@
1
- # typed: true
1
+ # typed: false
2
2
  # frozen_string_literal: true
3
3
 
4
- #: self as Roast::DSL::Executor
5
-
6
- # This is a dead simple workflow that calls two shell scripts
7
- shell <<~SHELLSTEP
4
+ # This is a dead simple workflow that calls two commands
5
+ cmd <<~CMDSTEP
8
6
  echo "I have no idea what's going on"
9
- SHELLSTEP
10
- shell "pwd"
7
+ CMDSTEP
8
+ cmd "pwd"
@@ -0,0 +1,18 @@
1
+ # typed: false
2
+ # frozen_string_literal: true
3
+
4
+ # How do we pass information between steps?
5
+ # Demonstrate by passing result of a command output to another step
6
+
7
+ config do
8
+ cmd(:echo) { display! }
9
+ end
10
+
11
+ execute do
12
+ cmd(:ls) { "ls -al" }
13
+ cmd(:echo) do
14
+ # TODO: this is a bespoke output object for cmd, is there a generic one we can offer
15
+ first_line = cmd(:ls).command_output.split("\n").second
16
+ "echo '#{first_line}'"
17
+ end
18
+ end
@@ -0,0 +1,9 @@
1
+ These examples demonstrate various usages and features of Roast. They are automatically tested and verified by functional tests (see `test/functional/roast_examples_test.rb`).
2
+
3
+ ### available_tools_demo
4
+
5
+ Demonstrates use of Roast tool implementations in LLM steps. Steps are implemented with `prompt.md` in directories that match the step name
6
+
7
+ ### basic_prompt_workflow
8
+
9
+ Demonstrates using LLM steps to glean insights from a provided data file (`test/fixtures/sample_data/skateboard_orders.csv`).
@@ -1,4 +1,4 @@
1
- model: openai:gpt-4o-mini
1
+ model: gpt-4o-mini
2
2
 
3
3
  tools:
4
4
  - Roast::Tools::Grep
@@ -0,0 +1 @@
1
+ You are a skateboard shop owner looking for insights on their business.
@@ -0,0 +1,14 @@
1
+ name: Analyze My Business
2
+ description: Examines a CSV list of orders for insights
3
+
4
+ # Default model for all steps
5
+ model: google:gemini-2.5-flash
6
+ tools:
7
+ - Roast::Tools::ReadFile
8
+ - Roast::Tools::Grep
9
+
10
+ steps:
11
+ - Read the provided CSV files.
12
+ - "Where are most of my customers from?"
13
+ - "What is my most popular product?"
14
+ - Summarize the insights from the report.
@@ -2,30 +2,6 @@
2
2
 
3
3
  This workflow acts as a senior software engineer and testing expert to evaluate the quality of test files based on best practices and guidelines.
4
4
 
5
- ## Prerequisites
6
-
7
- This example uses `shadowenv` for environment management, which is specific to Shopify's development environment. If you're not using shadowenv, you'll need to adapt the commands to your own setup.
8
-
9
- ### If you're using shadowenv:
10
- ```bash
11
- brew install shadowenv
12
- ```
13
-
14
- ### If you're NOT using shadowenv:
15
- You'll need to modify the `run_coverage.rb` file to remove the shadowenv commands. Look for lines like:
16
- ```ruby
17
- command = "shadowenv exec -- bundle exec ruby ..."
18
- ```
19
-
20
- And change them to match your environment:
21
- ```ruby
22
- # For standard Ruby/Bundler setup:
23
- command = "bundle exec ruby ..."
24
-
25
- # Or if you're using rbenv/rvm:
26
- command = "ruby ..."
27
- ```
28
-
29
5
  ## Usage
30
6
 
31
7
  ```bash
@@ -52,7 +28,6 @@ Feel free to adapt this workflow to your testing environment:
52
28
  - **Different test frameworks**: Modify `run_coverage.rb` to work with RSpec, Jest, pytest, etc.
53
29
  - **Coverage tools**: Replace the coverage command with your preferred tool (SimpleCov, Istanbul, Coverage.py)
54
30
  - **Grading criteria**: Adjust the prompts in each step to match your team's standards
55
- - **Environment setup**: Remove or replace shadowenv with your environment management tool
56
31
 
57
32
  ## Example Output
58
33
 
@@ -68,4 +43,4 @@ RECOMMENDATIONS:
68
43
  - Add edge case testing for error conditions
69
44
  - Improve test descriptions for clarity
70
45
  - Consider extracting common setup to helper methods
71
- ```
46
+ ```
@@ -49,4 +49,4 @@ You must respond in JSON format within <json> XML tags. Example:
49
49
  "justification": "The source file has 80% branch coverage, indicating some branches need testing."
50
50
  }
51
51
  }
52
- </json>
52
+ </json>
@@ -1,21 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class CalculateFinalGrade < Roast::Workflow::BaseStep
4
- attr_accessor :llm_analysis
5
-
6
4
  WEIGHTS = {
7
- line_coverage: 0.1,
8
- method_coverage: 0.1,
9
- branch_coverage: 0.3,
10
- test_helpers: 0.1,
11
- mocks_and_stubs: 0.1,
12
- readability: 0.1,
13
- maintainability: 0.1,
14
- effectiveness: 0.1,
5
+ test_helpers: 0.2,
6
+ mocks_and_stubs: 0.2,
7
+ readability: 0.2,
8
+ maintainability: 0.2,
9
+ effectiveness: 0.2,
15
10
  }.freeze
16
11
 
17
12
  def call
18
- @llm_analysis = workflow.output["generate_grades"].merge(workflow.output["analyze_coverage"])
13
+ llm_analysis = workflow.output["generate_grades"]
14
+
19
15
  weighted_sum = WEIGHTS.sum do |criterion, weight|
20
16
  score = llm_analysis[criterion.to_s]["score"].to_f / 10.0
21
17
  score * weight
@@ -26,7 +22,7 @@ class CalculateFinalGrade < Roast::Workflow::BaseStep
26
22
  weighted_score: weighted_sum,
27
23
  letter_grade: calculate_letter_grade(weighted_sum),
28
24
  },
29
- rubric_scores: calculate_rubric_scores,
25
+ rubric_scores: calculate_rubric_scores(llm_analysis),
30
26
  }
31
27
  end
32
28
 
@@ -47,10 +43,11 @@ class CalculateFinalGrade < Roast::Workflow::BaseStep
47
43
  end
48
44
  end
49
45
 
50
- def calculate_rubric_scores
46
+ def calculate_rubric_scores(llm_analysis)
51
47
  scores = {}
52
48
 
53
49
  WEIGHTS.each_key do |criterion|
50
+ next 1 unless llm_analysis[criterion.to_s]
54
51
  raw_score = llm_analysis[criterion.to_s]["score"].to_f
55
52
  normalized_score = raw_score / 10.0
56
53
 
@@ -2,14 +2,11 @@
2
2
 
3
3
  class FormatResult < Roast::Workflow::BaseStep
4
4
  RUBRIC = {
5
- line_coverage: { description: "Line Coverage", weight: 0.1 },
6
- method_coverage: { description: "Method Coverage", weight: 0.1 },
7
- branch_coverage: { description: "Branch Coverage", weight: 0.3 },
8
- test_helpers: { description: "Test Helpers Usage", weight: 0.1 },
9
- mocks_and_stubs: { description: "Mocks and Stubs Usage", weight: 0.1 },
10
- readability: { description: "Test Readability", weight: 0.1 },
11
- maintainability: { description: "Test Maintainability", weight: 0.1 },
12
- effectiveness: { description: "Test Effectiveness", weight: 0.1 },
5
+ test_helpers: { description: "Test Helpers Usage", weight: 0.2 },
6
+ mocks_and_stubs: { description: "Mocks and Stubs Usage", weight: 0.2 },
7
+ readability: { description: "Test Readability", weight: 0.2 },
8
+ maintainability: { description: "Test Maintainability", weight: 0.2 },
9
+ effectiveness: { description: "Test Effectiveness", weight: 0.2 },
13
10
  }.freeze
14
11
 
15
12
  def call
@@ -102,4 +102,4 @@ RESPONSE FORMAT: You must respond in JSON format within <json> XML tags.
102
102
  "justification": "Tests validate most expected behaviors and would catch common bugs."
103
103
  }
104
104
  }
105
- </json>
105
+ </json>
@@ -57,4 +57,4 @@ Example:
57
57
  }
58
58
  ]
59
59
  }
60
- </json>
60
+ </json>
@@ -13,4 +13,3 @@ If you are told to find the dependencies of `test/services/country_db_interface_
13
13
  then you would use the functions as explained above and ultimately respond with `<sut>app/services/country_db_interface.rb</sut>`
14
14
 
15
15
  If the file is found at `lib/roast/workflow/workflow_initializer.rb`, respond with `<sut>lib/roast/workflow/workflow_initializer.rb</sut>` (include the lib/ prefix)
16
-
@@ -50,4 +50,4 @@ Once you are done understanding the custom test helpers used in the test file, a
50
50
 
51
51
  Where possible, use your best judgment to make recommendations for how to fix problems that you find, but ONLY related to test helpers.
52
52
 
53
- Note: You are only being used to help find problems so it is not necessary to report on correct usage of helpers or to make positive comments.
53
+ Note: You are only being used to help find problems so it is not necessary to report on correct usage of helpers or to make positive comments.
@@ -2,7 +2,4 @@ As a senior software engineer and testing expert, evaluate the quality of this t
2
2
 
3
3
  Next I will now provide the source code of the test that we will be analyzing, and then step you through a series of analysis activities, before finally asking you to provided a final report.
4
4
 
5
- <test>
6
- # <%= file %>
7
- <%= File.read(file) %>
8
- </test>
5
+ # <%= file %> <%= File.read(file) %>
@@ -1,21 +1,13 @@
1
1
  name: Test Grading
2
- api_token: $(echo $OPENAI_API_KEY)
3
- # model: anthropic:claude-opus-4
4
- model: gpt-4.1-mini
5
2
 
6
3
  tools:
7
4
  - Roast::Tools::Grep
8
5
  - Roast::Tools::ReadFile
9
6
  - Roast::Tools::SearchFile
10
7
 
11
- # Uncomment this to run the workflow on modified tests automatically
12
- # each: '% cd $(git rev-parse --show-toplevel) && git status --porcelain | grep "_test\.rb" | cut -c4- | xargs realpath'
13
-
14
8
  steps:
15
9
  - read_dependencies
16
- - run_coverage
17
10
  -
18
- - analyze_coverage
19
11
  - verify_test_helpers
20
12
  - verify_mocks_and_stubs
21
13
  - generate_grades
@@ -23,19 +15,14 @@ steps:
23
15
  - format_result
24
16
  - generate_recommendations
25
17
 
26
- # set non-default attributes for steps below
27
18
  analyze_coverage:
28
- # model: gpt-4.1-mini
29
19
  json: true
30
-
20
+
31
21
  generate_grades:
32
- # model: o3
22
+ model: o3
33
23
  json: true
34
24
 
35
25
  generate_recommendations:
36
- # model: o3
26
+ model: o3
37
27
  json: true
38
- params:
39
- max_completion_tokens: 5_000
40
-
41
28
 
@@ -0,0 +1,31 @@
1
+ # typed: false
2
+ # frozen_string_literal: true
3
+
4
+ module Roast
5
+ module DSL
6
+ class Cog
7
+ class Config
8
+ attr_reader :values
9
+
10
+ def initialize(initial = {})
11
+ @values = initial
12
+ end
13
+
14
+ def merge(config_object)
15
+ self.class.new(values.merge(config_object.values))
16
+ end
17
+
18
+ # It is recommended to implement a custom config object for a nicer interface,
19
+ # but for simple cases where it would just be a key value store we provide one by default.
20
+
21
+ def []=(key, value)
22
+ @values[key] = value
23
+ end
24
+
25
+ def [](key)
26
+ @values[key]
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,21 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module Roast
5
+ module DSL
6
+ class Cog
7
+ class Stack
8
+ delegate :map, :push, :size, :empty?, to: :@queue
9
+
10
+ def initialize
11
+ @queue = []
12
+ end
13
+
14
+ #: () -> Roast::DSL::Cog?
15
+ def pop
16
+ @queue.shift
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,26 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module Roast
5
+ module DSL
6
+ class Cog
7
+ class Store
8
+ class CogAlreadyDefinedError < Roast::Error; end
9
+
10
+ delegate :[], to: :store
11
+
12
+ #: (Symbol, Roast::DSL::Cog) -> Roast::DSL::Cog
13
+ def insert(id, inst)
14
+ raise CogAlreadyDefinedError if store.key?(id)
15
+
16
+ store[id] = inst
17
+ end
18
+
19
+ #: () -> Hash[Symbol, Roast::DSL::Cog]
20
+ def store
21
+ @store ||= {}
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,70 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module Roast
5
+ module DSL
6
+ class Cog
7
+ class CogAlreadyRanError < StandardError; end
8
+
9
+ class << self
10
+ def on_create
11
+ eigen = self
12
+ proc do |instance_name = Random.uuid, &action|
13
+ #: self as Roast::DSL::WorkflowExecutionContext
14
+ add_cog_instance(instance_name, eigen.new(instance_name, action))
15
+ end
16
+ end
17
+
18
+ def on_config
19
+ eigen = self
20
+ proc do |cog_name = nil, &configuration|
21
+ #: self as Roast::DSL::ConfigContext
22
+ config_object = if cog_name.nil?
23
+ fetch_execution_scope(eigen)
24
+ else
25
+ fetch_or_create_cog_config(eigen, cog_name)
26
+ end
27
+
28
+ config_object.instance_exec(&configuration) if configuration
29
+ end
30
+ end
31
+
32
+ def config_class
33
+ @config_class ||= find_child_config_or_default
34
+ end
35
+
36
+ private
37
+
38
+ def find_child_config_or_default
39
+ config_constant = "#{name}::Config"
40
+ const_defined?(config_constant) ? const_get(config_constant) : Cog::Config # rubocop:disable Sorbet/ConstantsFromStrings
41
+ end
42
+ end
43
+
44
+ attr_reader :name, :output
45
+
46
+ def initialize(name, cog_input_proc)
47
+ @name = name
48
+ @cog_input_proc = cog_input_proc
49
+ @finished = false
50
+ end
51
+
52
+ def run!(config, cog_execution_context)
53
+ raise CogAlreadyRanError if ran?
54
+
55
+ @config = config
56
+ @output = execute(cog_execution_context.instance_exec(&@cog_input_proc))
57
+ @finished = true
58
+ end
59
+
60
+ def ran?
61
+ @finished
62
+ end
63
+
64
+ # Inheriting cog must implement this
65
+ def execute(input)
66
+ raise NotImplementedError
67
+ end
68
+ end
69
+ end
70
+ end