roast-ai 0.3.1 → 0.4.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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yaml +2 -2
- data/.gitignore +1 -0
- data/CHANGELOG.md +85 -0
- data/CLAUDE.md +106 -9
- data/Gemfile +4 -1
- data/Gemfile.lock +70 -16
- data/README.md +159 -8
- data/bin/console +1 -0
- data/bin/roast +1 -1
- data/claude-swarm.yml +210 -0
- data/docs/AGENT_STEPS.md +288 -0
- data/docs/VALIDATION.md +178 -0
- data/examples/agent_continue/add_documentation/prompt.md +5 -0
- data/examples/agent_continue/add_error_handling/prompt.md +5 -0
- data/examples/agent_continue/analyze_codebase/prompt.md +7 -0
- data/examples/agent_continue/combined_workflow.yml +24 -0
- data/examples/agent_continue/continue_adding_features/prompt.md +4 -0
- data/examples/agent_continue/create_integration_tests/prompt.md +3 -0
- data/examples/agent_continue/document_with_context/prompt.md +5 -0
- data/examples/agent_continue/explore_api/prompt.md +6 -0
- data/examples/agent_continue/implement_client/prompt.md +6 -0
- data/examples/agent_continue/inline_workflow.yml +20 -0
- data/examples/agent_continue/refactor_code/prompt.md +2 -0
- data/examples/agent_continue/verify_changes/prompt.md +6 -0
- data/examples/agent_continue/workflow.yml +27 -0
- data/examples/agent_workflow/README.md +75 -0
- data/examples/agent_workflow/apply_refactorings/prompt.md +22 -0
- data/examples/agent_workflow/identify_code_smells/prompt.md +15 -0
- data/examples/agent_workflow/summarize_improvements/prompt.md +18 -0
- data/examples/agent_workflow/workflow.png +0 -0
- data/examples/agent_workflow/workflow.yml +16 -0
- data/examples/api_workflow/workflow.png +0 -0
- data/examples/apply_diff_demo/README.md +58 -0
- data/examples/apply_diff_demo/apply_simple_change/prompt.md +13 -0
- data/examples/apply_diff_demo/create_sample_file/prompt.md +11 -0
- data/examples/apply_diff_demo/workflow.yml +24 -0
- data/examples/available_tools_demo/README.md +42 -0
- data/examples/available_tools_demo/analyze_files/prompt.md +6 -0
- data/examples/available_tools_demo/explore_directory/prompt.md +6 -0
- data/examples/available_tools_demo/workflow.png +0 -0
- data/examples/available_tools_demo/workflow.yml +32 -0
- data/examples/available_tools_demo/write_summary/prompt.md +6 -0
- data/examples/bash_prototyping/api_testing.png +0 -0
- data/examples/bash_prototyping/system_analysis.png +0 -0
- data/examples/case_when/detect_language/prompt.md +2 -2
- data/examples/case_when/workflow.png +0 -0
- data/examples/cmd/basic_workflow.png +0 -0
- data/examples/cmd/dev_workflow.png +0 -0
- data/examples/cmd/explorer_workflow.png +0 -0
- data/examples/conditional/simple_workflow.png +0 -0
- data/examples/conditional/workflow.png +0 -0
- data/examples/context_management_demo/README.md +43 -0
- data/examples/context_management_demo/workflow.yml +42 -0
- data/examples/direct_coerce_syntax/workflow.png +0 -0
- data/examples/dot_notation/workflow.png +0 -0
- data/examples/exit_on_error/workflow.png +0 -0
- data/examples/grading/run_coverage.rb +0 -2
- data/examples/grading/workflow.png +0 -0
- data/examples/interpolation/workflow.png +0 -0
- data/examples/interpolation/workflow.yml +1 -1
- data/examples/iteration/analyze_complexity/prompt.md +2 -2
- data/examples/iteration/generate_recommendations/prompt.md +2 -2
- data/examples/iteration/implement_fix/prompt.md +2 -2
- data/examples/iteration/prioritize_issues/prompt.md +1 -1
- data/examples/iteration/prompts/analyze_file.md +2 -2
- data/examples/iteration/prompts/generate_summary.md +1 -1
- data/examples/iteration/prompts/update_report.md +3 -3
- data/examples/iteration/prompts/write_report.md +3 -3
- data/examples/iteration/read_file/prompt.md +2 -2
- data/examples/iteration/select_next_issue/prompt.md +2 -2
- data/examples/iteration/update_fix_count/prompt.md +4 -4
- data/examples/iteration/verify_fix/prompt.md +3 -3
- data/examples/iteration/workflow.png +0 -0
- data/examples/json_handling/workflow.png +0 -0
- data/examples/mcp/README.md +3 -3
- data/examples/mcp/analyze_changes/prompt.md +1 -1
- data/examples/mcp/database_workflow.png +0 -0
- data/examples/mcp/database_workflow.yml +1 -1
- data/examples/mcp/env_demo/workflow.png +0 -0
- data/examples/mcp/fetch_pr_context/prompt.md +1 -1
- data/examples/mcp/filesystem_demo/workflow.png +0 -0
- data/examples/mcp/github_workflow.png +0 -0
- data/examples/mcp/github_workflow.yml +1 -1
- data/examples/mcp/multi_mcp_workflow.png +0 -0
- data/examples/mcp/post_review/prompt.md +1 -1
- data/examples/mcp/workflow.png +0 -0
- data/examples/no_model_fallback/README.md +17 -0
- data/examples/no_model_fallback/analyze_file/prompt.md +1 -0
- data/examples/no_model_fallback/analyze_patterns/prompt.md +27 -0
- data/examples/no_model_fallback/generate_report_for_md/prompt.md +10 -0
- data/examples/no_model_fallback/generate_report_for_rb/prompt.md +3 -0
- data/examples/no_model_fallback/sample.rb +42 -0
- data/examples/no_model_fallback/workflow.yml +19 -0
- data/examples/openrouter_example/workflow.png +0 -0
- data/examples/pre_post_processing/analyze_test_file/prompt.md +1 -1
- data/examples/pre_post_processing/improve_test_coverage/prompt.md +1 -1
- data/examples/pre_post_processing/optimize_test_performance/prompt.md +1 -1
- data/examples/pre_post_processing/post_processing/aggregate_metrics/prompt.md +2 -2
- data/examples/pre_post_processing/post_processing/generate_summary_report/prompt.md +1 -1
- data/examples/pre_post_processing/pre_processing/setup_test_environment/prompt.md +1 -1
- data/examples/pre_post_processing/validate_changes/prompt.md +2 -2
- data/examples/pre_post_processing/workflow.png +0 -0
- data/examples/rspec_to_minitest/workflow.png +0 -0
- data/examples/shared_config/example_with_shared_config/workflow.png +0 -0
- data/examples/shared_config/shared.png +0 -0
- data/examples/single_target_prepost/workflow.png +0 -0
- data/examples/smart_coercion_defaults/workflow.png +0 -0
- data/examples/step_configuration/workflow.png +0 -0
- data/examples/swarm_example.yml +25 -0
- data/examples/tool_config_example/workflow.png +0 -0
- data/examples/user_input/README.md +90 -0
- data/examples/user_input/funny_name/create_backstory/prompt.md +10 -0
- data/examples/user_input/funny_name/workflow.png +0 -0
- data/examples/user_input/funny_name/workflow.yml +26 -0
- data/examples/user_input/generate_summary/prompt.md +11 -0
- data/examples/user_input/simple_input_demo/workflow.png +0 -0
- data/examples/user_input/simple_input_demo/workflow.yml +35 -0
- data/examples/user_input/survey_workflow.png +0 -0
- data/examples/user_input/survey_workflow.yml +71 -0
- data/examples/user_input/welcome_message/prompt.md +3 -0
- data/examples/user_input/workflow.png +0 -0
- data/examples/user_input/workflow.yml +73 -0
- data/examples/workflow_generator/create_workflow_files/prompt.md +1 -1
- data/examples/workflow_generator/workflow.png +0 -0
- data/lib/roast/errors.rb +6 -4
- data/lib/roast/helpers/function_caching_interceptor.rb +0 -2
- data/lib/roast/helpers/logger.rb +12 -35
- data/lib/roast/helpers/minitest_coverage_runner.rb +0 -1
- data/lib/roast/helpers/prompt_loader.rb +0 -2
- data/lib/roast/helpers/timeout_handler.rb +91 -0
- data/lib/roast/resources/api_resource.rb +0 -4
- data/lib/roast/resources/url_resource.rb +0 -3
- data/lib/roast/resources.rb +0 -8
- data/lib/roast/services/context_threshold_checker.rb +42 -0
- data/lib/roast/services/token_counting_service.rb +44 -0
- data/lib/roast/tools/apply_diff.rb +128 -0
- data/lib/roast/tools/ask_user.rb +0 -2
- data/lib/roast/tools/bash.rb +12 -9
- data/lib/roast/tools/cmd.rb +29 -12
- data/lib/roast/tools/coding_agent.rb +65 -17
- data/lib/roast/tools/context_summarizer.rb +108 -0
- data/lib/roast/tools/grep.rb +0 -3
- data/lib/roast/tools/helpers/coding_agent_message_formatter.rb +1 -4
- data/lib/roast/tools/read_file.rb +0 -2
- data/lib/roast/tools/search_file.rb +0 -2
- data/lib/roast/tools/swarm.rb +124 -0
- data/lib/roast/tools/update_files.rb +0 -4
- data/lib/roast/tools/write_file.rb +0 -3
- data/lib/roast/tools.rb +0 -13
- data/lib/roast/value_objects/step_name.rb +14 -3
- data/lib/roast/value_objects/workflow_path.rb +0 -2
- data/lib/roast/value_objects.rb +4 -4
- data/lib/roast/version.rb +1 -1
- data/lib/roast/workflow/agent_step.rb +33 -0
- data/lib/roast/workflow/api_configuration.rb +0 -4
- data/lib/roast/workflow/base_iteration_step.rb +3 -6
- data/lib/roast/workflow/base_step.rb +54 -28
- data/lib/roast/workflow/base_workflow.rb +43 -23
- data/lib/roast/workflow/case_executor.rb +0 -1
- data/lib/roast/workflow/case_step.rb +0 -4
- data/lib/roast/workflow/command_executor.rb +0 -2
- data/lib/roast/workflow/conditional_executor.rb +0 -1
- data/lib/roast/workflow/conditional_step.rb +0 -4
- data/lib/roast/workflow/configuration.rb +5 -67
- data/lib/roast/workflow/configuration_loader.rb +63 -3
- data/lib/roast/workflow/configuration_parser.rb +1 -7
- data/lib/roast/workflow/context_manager.rb +89 -0
- data/lib/roast/workflow/dot_access_hash.rb +16 -1
- data/lib/roast/workflow/each_step.rb +1 -1
- data/lib/roast/workflow/error_handler.rb +0 -3
- data/lib/roast/workflow/expression_evaluator.rb +0 -3
- data/lib/roast/workflow/file_state_repository.rb +0 -5
- data/lib/roast/workflow/input_executor.rb +41 -0
- data/lib/roast/workflow/input_step.rb +163 -0
- data/lib/roast/workflow/iteration_executor.rb +0 -2
- data/lib/roast/workflow/output_handler.rb +1 -3
- data/lib/roast/workflow/output_manager.rb +0 -2
- data/lib/roast/workflow/repeat_step.rb +1 -1
- data/lib/roast/workflow/replay_handler.rb +1 -4
- data/lib/roast/workflow/resource_resolver.rb +0 -3
- data/lib/roast/workflow/session_manager.rb +0 -3
- data/lib/roast/workflow/sqlite_state_repository.rb +342 -0
- data/lib/roast/workflow/state_manager.rb +2 -4
- data/lib/roast/workflow/state_repository_factory.rb +36 -0
- data/lib/roast/workflow/step_completion_reporter.rb +27 -0
- data/lib/roast/workflow/step_executor_coordinator.rb +48 -24
- data/lib/roast/workflow/step_executor_factory.rb +0 -5
- data/lib/roast/workflow/step_executor_registry.rb +1 -4
- data/lib/roast/workflow/step_executor_with_reporting.rb +68 -0
- data/lib/roast/workflow/step_executors/hash_step_executor.rb +0 -3
- data/lib/roast/workflow/step_executors/parallel_step_executor.rb +0 -3
- data/lib/roast/workflow/step_executors/string_step_executor.rb +0 -2
- data/lib/roast/workflow/step_factory.rb +56 -0
- data/lib/roast/workflow/step_loader.rb +31 -17
- data/lib/roast/workflow/step_name_extractor.rb +84 -0
- data/lib/roast/workflow/step_orchestrator.rb +3 -2
- data/lib/roast/workflow/step_type_resolver.rb +28 -1
- data/lib/roast/workflow/validation_command.rb +197 -0
- data/lib/roast/workflow/validator.rb +0 -4
- data/lib/roast/workflow/validators/base_validator.rb +44 -0
- data/lib/roast/workflow/validators/dependency_validator.rb +223 -0
- data/lib/roast/workflow/validators/linting_validator.rb +113 -0
- data/lib/roast/workflow/validators/schema_validator.rb +90 -0
- data/lib/roast/workflow/validators/step_collector.rb +57 -0
- data/lib/roast/workflow/validators/validation_orchestrator.rb +52 -0
- data/lib/roast/workflow/workflow_executor.rb +11 -20
- data/lib/roast/workflow/workflow_initializer.rb +1 -8
- data/lib/roast/workflow/workflow_runner.rb +6 -7
- data/lib/roast/workflow.rb +0 -15
- data/lib/roast/workflow_diagram_generator.rb +298 -0
- data/lib/roast.rb +212 -10
- data/roast.gemspec +4 -2
- data/schema/workflow.json +123 -1
- metadata +143 -6
- data/lib/roast/helpers.rb +0 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b31e95a8d65d0b1fa798c0baed8bcbf9249cc67fca752154865d914d01ffbd8d
|
4
|
+
data.tar.gz: 21205a0a50e2301dda0936e67b02d05af94085b0e383f859aec282827649ebb3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 80b5ceada69faff53f5893e9378e628474b103c3d6b60a8701be80b1bfe11cb6e4bde252670d890a2ae7e460d90d956daed7813d251cf6d84399ab70d321b0d8
|
7
|
+
data.tar.gz: 620e7d46fc6f7e9b10a71807f213ba101cb2bbd9a3bad073a153057bd67bc842cf74e4ffaa179596a2ed3655dc7a864c366034a37f4a720d2fd6faafa86f5541
|
data/.github/workflows/ci.yaml
CHANGED
@@ -23,8 +23,8 @@ jobs:
|
|
23
23
|
BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile
|
24
24
|
steps:
|
25
25
|
- uses: actions/checkout@v4
|
26
|
-
- name: Install
|
27
|
-
run: sudo apt-get update && sudo apt-get install -y ripgrep
|
26
|
+
- name: Install dependencies
|
27
|
+
run: sudo apt-get update && sudo apt-get install -y ripgrep graphviz
|
28
28
|
- uses: ruby/setup-ruby@v1
|
29
29
|
with:
|
30
30
|
ruby-version: ${{ matrix.ruby }}
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -5,6 +5,91 @@ All notable changes to this project will be documented in this file.
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
7
|
|
8
|
+
## [0.4.1] - 2025-06-18
|
9
|
+
|
10
|
+
### Added
|
11
|
+
- **SQLite session storage** as the default storage backend (#252)
|
12
|
+
- Provides better performance and advanced querying capabilities
|
13
|
+
- Sessions are stored in `~/.roast/sessions.db` by default (configurable via `ROAST_SESSIONS_DB`)
|
14
|
+
- New `roast sessions` command to list and filter stored sessions
|
15
|
+
- New `roast session <id>` command to view detailed session information
|
16
|
+
- Session cleanup with `roast sessions --cleanup --older-than <duration>`
|
17
|
+
- Filter sessions by status, workflow name, or age
|
18
|
+
- Maintains full backward compatibility with filesystem storage
|
19
|
+
- **`--file-storage` CLI option** to use legacy filesystem storage instead of SQLite
|
20
|
+
- Use `-f` or `--file-storage` flag to opt into filesystem storage
|
21
|
+
- Environment variable `ROAST_STATE_STORAGE=file` still supported for compatibility
|
22
|
+
- **Foundation for wait_for_event feature** (#251)
|
23
|
+
- New `roast resume` command infrastructure for resuming paused workflows
|
24
|
+
- Event storage and tracking in SQLite sessions table
|
25
|
+
- **Configurable agent step options** for CodingAgent (#266)
|
26
|
+
- New `continue` option for agent steps to maintain session context across multiple agent invocations
|
27
|
+
- New `include_context_summary` option to provide AI-generated workflow context summaries to agents
|
28
|
+
- Context summaries are intelligently tailored to the agent's specific task using LLM analysis
|
29
|
+
- Helps reduce token usage by including only relevant context information
|
30
|
+
- **Token consumption reporting** for step execution (#264)
|
31
|
+
- Displays token usage (prompt and completion) after each step execution
|
32
|
+
- Helps users monitor and optimize their LLM token consumption
|
33
|
+
- Automatically enabled for all workflow runs
|
34
|
+
- **Timeout functionality for bash and cmd steps** (#261)
|
35
|
+
- New `timeout` option for bash and cmd steps to prevent hanging commands
|
36
|
+
- Configurable timeout duration in seconds
|
37
|
+
- Commands are automatically terminated if they exceed the specified timeout
|
38
|
+
- Prevents workflows from getting stuck on unresponsive commands
|
39
|
+
- **Claude Swarm tool integration** (#254)
|
40
|
+
- New `Roast::Tools::Swarm` for integrating with Claude Swarm framework
|
41
|
+
- Enables using Swarm's multi-agent orchestration capabilities within Roast workflows
|
42
|
+
- Provides seamless handoffs between specialized AI agents
|
43
|
+
- **Workflow visualization with diagram command** (#256)
|
44
|
+
- New `roast diagram` command to generate visual representations of workflows
|
45
|
+
- Creates GraphViz-based diagrams showing workflow structure and flow
|
46
|
+
- Supports both DOT format output and PNG/SVG image generation
|
47
|
+
- Helps understand complex workflow logic at a glance
|
48
|
+
- **Comprehensive workflow validation** (#244)
|
49
|
+
- New `roast validate` command to check workflow syntax and structure
|
50
|
+
- Validates YAML syntax, step references, and configuration options
|
51
|
+
- Provides detailed error messages for invalid workflows
|
52
|
+
- Helps catch errors before running workflows
|
53
|
+
- **apply_diff tool** (#246)
|
54
|
+
- New built-in tool for applying unified diff patches to files
|
55
|
+
- Supports standard diff format for making precise file modifications
|
56
|
+
- Enables AI models to suggest changes in diff format
|
57
|
+
- More reliable than search-and-replace for complex edits
|
58
|
+
- **Model fallback mechanism** (#257)
|
59
|
+
- Workflows without explicit model configuration now use a sensible default
|
60
|
+
- Prevents errors when model is not specified at workflow or step level
|
61
|
+
- Improves user experience for simple workflows
|
62
|
+
- **Context management foundation for auto-compaction** (#264)
|
63
|
+
- Infrastructure for future automatic context size management
|
64
|
+
- Enables intelligent token usage optimization in long-running workflows
|
65
|
+
|
66
|
+
### Changed
|
67
|
+
- Session storage now defaults to SQLite instead of filesystem
|
68
|
+
- Existing filesystem sessions remain accessible when using `--file-storage` flag
|
69
|
+
- No migration required - both storage backends can coexist
|
70
|
+
|
71
|
+
[0.4.1]: https://github.com/Shopify/roast/compare/v0.4.0...v0.4.1
|
72
|
+
|
73
|
+
## [0.4.0] - 2025-06-12
|
74
|
+
|
75
|
+
### Added
|
76
|
+
- **Input step type** for collecting user input during workflow execution (#154)
|
77
|
+
- Interactive prompts pause workflow execution to collect user input
|
78
|
+
- Supports multiple input types: `text` (default), `confirm`, `select`, and `password`
|
79
|
+
- `confirm` type provides yes/no prompts with boolean results
|
80
|
+
- `select` type allows choosing from a list of options
|
81
|
+
- `password` type masks input for sensitive data using io/console
|
82
|
+
- Input values are stored in workflow output and accessible via dot notation (e.g., `{{output.step_name}}`)
|
83
|
+
- Integrates with CLI::UI for consistent formatting and user experience
|
84
|
+
- **Agent step type** for direct pass-through to coding agents (#151)
|
85
|
+
- Steps prefixed with `^` send prompts directly to the CodingAgent tool
|
86
|
+
- Supports both file-based and inline agent prompts
|
87
|
+
- Bypasses LLM interpretation for precise agent instructions
|
88
|
+
|
89
|
+
### Fixed
|
90
|
+
- DotAccessHash array wrapping and template response handling
|
91
|
+
- CLI::UI formatting and color handling for better terminal output
|
92
|
+
|
8
93
|
## [0.3.1] - 2025-06-05
|
9
94
|
|
10
95
|
### Added
|
data/CLAUDE.md
CHANGED
@@ -4,17 +4,15 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|
4
4
|
|
5
5
|
## About the codebase
|
6
6
|
- This is a Ruby gem called Roast. Its purpose is to run AI workflows defined in a YAML file.
|
7
|
+
- Note that this project now uses Zeitwerk, which means you don't have to manually require project files anymore
|
7
8
|
|
8
9
|
## Commands
|
9
|
-
|
10
|
-
- Default (tests + lint): `bundle exec rake`
|
11
|
-
- Test all: `bundle exec test`
|
10
|
+
- Default THE SUITE RUNS FAST SO USE THIS IN MOST CASES (tests + lint w/autocorrect): `bundle exec rake`
|
12
11
|
- Run single test: `bundle exec ruby -Itest test/path/to/test_file.rb`
|
13
12
|
- Lint: `bundle exec rubocop`
|
14
13
|
- Lint (with autocorrect, preferred): `bundle exec rubocop -A`
|
15
14
|
- Whenever you want to run the whole test suite just run `bundle exec rake` to also run linting, and note the linting errors too (most will auto correct but not all)
|
16
15
|
- **Run roast locally**: Use `bin/roast` (not `bundle exec roast` which may use the installed gem)
|
17
|
-
- Alternative: `bundle exec exe/roast`
|
18
16
|
|
19
17
|
## Tech stack
|
20
18
|
- `thor` and `cli-ui` for the CLI tool
|
@@ -22,7 +20,6 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|
22
20
|
- Prefer using the more literate `test "this is a test description" do` type of testing that we get from extending ActiveSupport::TestCase over the primitive XUnit-style def test_description headings for tests
|
23
21
|
|
24
22
|
## Code Style Guidelines
|
25
|
-
|
26
23
|
- Naming: snake_case for variables/methods, CamelCase for classes/modules, ALL_CAPS for constants
|
27
24
|
- Module structure: Use nested modules under the `Roast` namespace
|
28
25
|
- Command pattern: Commands implement a `call` method and class-level `help` method
|
@@ -40,7 +37,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|
40
37
|
- Always leave a blank line after module includes and before the rest of the class
|
41
38
|
|
42
39
|
## Architecture Guidelines
|
43
|
-
|
40
|
+
- **SOLID principles are important** - don't violate them
|
44
41
|
- **Maintain proper separation of concerns**: Don't mix unrelated concepts in the same class or module
|
45
42
|
- Example: Conditional execution (if/unless) should NOT be mixed with iteration execution (each/repeat)
|
46
43
|
- Each concept should have its own executor class and be handled separately
|
@@ -51,14 +48,67 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|
51
48
|
- ConditionalExecutor handles conditionals (if, unless)
|
52
49
|
- Don't combine different responsibilities in one class
|
53
50
|
- **Do not implement prompts "inline" using a prompt: attribute nested under step names, that violates the primary design architecture of Roast**
|
51
|
+
- When faced with the choice between working around an architectural issue or code smell versus actually diving into fixing the design issue or code smell, choose the latter more principled approach
|
52
|
+
- When fixing code smells, you don't have to worry about internal backwards compatibility
|
53
|
+
|
54
|
+
## Workflow Configuration Syntax
|
55
|
+
- The `steps` key in the workflow configuration is an array of step names
|
56
|
+
- Only step names, inline prompts, and control flow keywords are allowed in the steps array
|
57
|
+
- Additional per-step configuration is provided in a top-level hash with the step name as the key, not within steps!!! (Very important)
|
58
|
+
- The reason that steps are not configured "inline" within the steps array is so that the shape of the workflow is as obvious as possible
|
59
|
+
- Step labels are inferred for most steps and optional for inline prompts, but required for steps that need custom configuration
|
60
|
+
- The result of running a step is stored in the `workflow.output` hash with the step label as the key
|
61
|
+
|
62
|
+
## How Roast Tools Work (CRITICAL - READ THIS!)
|
63
|
+
**Tools in Roast are NOT explicitly invoked in workflow steps!** This is a fundamental concept that differs from many other workflow systems.
|
64
|
+
|
65
|
+
### Key Concepts:
|
66
|
+
1. **Tools are capabilities available to the LLM** - They are functions the LLM can choose to call while executing a step
|
67
|
+
2. **Steps contain prompts** - Steps describe what needs to be done, not how to do it
|
68
|
+
3. **The LLM decides when to use tools** - While executing a step's prompt, the LLM analyzes the task and calls tools as needed
|
69
|
+
4. **Tools are registered, not declared in steps** - Use the `tools:` section to make tools available, but never use a `tool:` key in step configuration
|
70
|
+
|
71
|
+
### Correct inline prompt syntax:
|
72
|
+
```yaml
|
73
|
+
steps:
|
74
|
+
- analyze_code: |
|
75
|
+
Analyze the codebase and identify performance bottlenecks.
|
76
|
+
Use any available tools to read files and search for patterns.
|
77
|
+
```
|
78
|
+
|
79
|
+
### INCORRECT syntax (DO NOT USE):
|
80
|
+
```yaml
|
81
|
+
# WRONG - no 'prompt:' key
|
82
|
+
steps:
|
83
|
+
- analyze_code:
|
84
|
+
prompt: "Analyze the codebase"
|
85
|
+
|
86
|
+
# WRONG - no 'tool:' key
|
87
|
+
steps:
|
88
|
+
- run_analysis:
|
89
|
+
tool: coding_agent
|
90
|
+
prompt: "Analyze code"
|
91
|
+
```
|
54
92
|
|
55
|
-
|
93
|
+
### How tools are actually used:
|
94
|
+
When the LLM executes the `analyze_code` step above, it might:
|
95
|
+
1. Decide it needs to read files and call `read_file(path)`
|
96
|
+
2. Decide it needs to search and call `grep(pattern, path)`
|
97
|
+
3. Decide it needs Claude Swarm and call `swarm(prompt, config_path)`
|
56
98
|
|
99
|
+
The LLM makes these decisions based on the prompt and available tools, similar to how Claude (you) decides when to use Bash, Read, or other tools when responding to user requests.
|
100
|
+
|
101
|
+
## Step Configuration
|
102
|
+
- The `path` key in a step configuration is the path to a Ruby file that defines a custom step.
|
103
|
+
- The `model` key in a step configuration is the model to use for the step.
|
104
|
+
- The `print_response` key in a step configuration is a boolean that determines whether the step's response should be printed to the console.
|
105
|
+
|
106
|
+
## Coding Guidance and Expectations
|
57
107
|
- Do not decide unilaterally to leave code for the sake of "backwards compatibility"... always run those decisions by me first.
|
58
108
|
- Don't ever commit and push changes unless directly told to do so
|
109
|
+
- You can't test input steps yourself since they block, so ask me to do it manually
|
59
110
|
|
60
111
|
## Git Workflow Practices
|
61
|
-
|
62
112
|
1. **Amending Commits**:
|
63
113
|
- Use `git commit --amend --no-edit` to add staged changes to the last commit without changing the commit message
|
64
114
|
- This is useful for incorporating small fixes or changes that belong with the previous commit
|
@@ -130,6 +180,48 @@ gh pr view {pr_number}
|
|
130
180
|
gh pr diff {pr_number}
|
131
181
|
```
|
132
182
|
|
183
|
+
### Issue Labeling and Project Management
|
184
|
+
|
185
|
+
When creating GitHub issues, always check available labels, projects, and milestones first:
|
186
|
+
|
187
|
+
```bash
|
188
|
+
# List all available labels
|
189
|
+
gh api repos/Shopify/roast/labels | jq '.[].name'
|
190
|
+
|
191
|
+
# List all milestones
|
192
|
+
gh api repos/Shopify/roast/milestones | jq '.[] | {title: .title, number: .number, state: .state}'
|
193
|
+
|
194
|
+
# List projects linked to the roast repository
|
195
|
+
gh api graphql -f query='
|
196
|
+
{
|
197
|
+
repository(owner: "Shopify", name: "roast") {
|
198
|
+
projectsV2(first: 10) {
|
199
|
+
nodes {
|
200
|
+
title
|
201
|
+
number
|
202
|
+
url
|
203
|
+
}
|
204
|
+
}
|
205
|
+
}
|
206
|
+
}' --jq '.data.repository.projectsV2.nodes[] | {title: .title, number: .number, url: .url}'
|
207
|
+
```
|
208
|
+
|
209
|
+
**Issue Creation Workflow**:
|
210
|
+
1. First check what labels exist and apply appropriate ones when creating the issue
|
211
|
+
2. After creating the issue, ask the user if they want it added to an existing milestone
|
212
|
+
3. Ask the user if they want it added to a particular project board
|
213
|
+
|
214
|
+
```bash
|
215
|
+
# Create issue with labels
|
216
|
+
gh api repos/Shopify/roast/issues -X POST -F title="Issue Title" -F body="Issue description" -F 'labels=["bug", "enhancement"]'
|
217
|
+
|
218
|
+
# Add issue to a milestone (after creation)
|
219
|
+
gh api repos/Shopify/roast/issues/{issue_number} -X PATCH -F milestone={milestone_number}
|
220
|
+
|
221
|
+
# Add issue to a GitHub Project
|
222
|
+
gh project item-add {project_number} --url https://github.com/Shopify/roast/issues/{issue_number}
|
223
|
+
```
|
224
|
+
|
133
225
|
#### Formatting Tips for GitHub API
|
134
226
|
1. Use literal newlines in the body text instead of `\n` escape sequences
|
135
227
|
2. When formatting is stripped (like backticks), use alternatives:
|
@@ -167,4 +259,9 @@ gh pr diff {pr_number}
|
|
167
259
|
- Avoid premature optimization outside of hot paths
|
168
260
|
- Consider the tradeoff between readability and performance
|
169
261
|
- Suggest optimizations that improve both clarity and performance
|
170
|
-
|
262
|
+
|
263
|
+
## CLI::UI Formatting Tips
|
264
|
+
- To apply color to terminal output using CLI::UI, use the following syntax:
|
265
|
+
```ruby
|
266
|
+
puts ::CLI::UI.fmt("{{red:This field is required. Please provide a value.}}")
|
267
|
+
```
|
data/Gemfile
CHANGED
@@ -8,7 +8,7 @@ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
|
|
8
8
|
gemspec
|
9
9
|
|
10
10
|
gem "cgi"
|
11
|
-
gem "cli-ui"
|
11
|
+
gem "cli-ui", "2.3.0"
|
12
12
|
gem "dotenv"
|
13
13
|
gem "guard"
|
14
14
|
gem "guard-minitest"
|
@@ -18,3 +18,6 @@ gem "rubocop-shopify", require: false
|
|
18
18
|
gem "vcr", require: false
|
19
19
|
gem "webmock", require: false
|
20
20
|
gem "minitest-rg"
|
21
|
+
gem "sqlite3", "~> 1.7"
|
22
|
+
|
23
|
+
gem "claude_swarm"
|
data/Gemfile.lock
CHANGED
@@ -1,15 +1,17 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
roast-ai (0.
|
4
|
+
roast-ai (0.4.1)
|
5
5
|
activesupport (>= 7.0)
|
6
|
-
cli-ui
|
6
|
+
cli-ui (= 2.3.0)
|
7
7
|
diff-lcs (~> 1.5)
|
8
8
|
faraday-retry
|
9
9
|
json-schema
|
10
10
|
open_router (~> 0.3)
|
11
11
|
raix (~> 1.0)
|
12
|
+
ruby-graphviz (~> 1.2)
|
12
13
|
thor (~> 1.3)
|
14
|
+
zeitwerk (~> 2.6)
|
13
15
|
|
14
16
|
GEM
|
15
17
|
remote: https://rubygems.org/
|
@@ -33,17 +35,49 @@ GEM
|
|
33
35
|
base64 (0.3.0)
|
34
36
|
benchmark (0.4.1)
|
35
37
|
bigdecimal (3.2.2)
|
36
|
-
cgi (0.
|
37
|
-
|
38
|
+
cgi (0.5.0)
|
39
|
+
claude_swarm (0.1.15)
|
40
|
+
fast-mcp-annotations
|
41
|
+
thor (~> 1.3)
|
42
|
+
cli-ui (2.3.0)
|
38
43
|
coderay (1.1.3)
|
39
44
|
concurrent-ruby (1.3.5)
|
40
45
|
connection_pool (2.5.3)
|
41
46
|
crack (1.0.0)
|
42
47
|
bigdecimal
|
43
48
|
rexml
|
44
|
-
diff-lcs (1.6.
|
49
|
+
diff-lcs (1.6.2)
|
45
50
|
dotenv (3.1.8)
|
46
51
|
drb (2.2.3)
|
52
|
+
dry-configurable (1.3.0)
|
53
|
+
dry-core (~> 1.1)
|
54
|
+
zeitwerk (~> 2.6)
|
55
|
+
dry-core (1.1.0)
|
56
|
+
concurrent-ruby (~> 1.0)
|
57
|
+
logger
|
58
|
+
zeitwerk (~> 2.6)
|
59
|
+
dry-inflector (1.2.0)
|
60
|
+
dry-initializer (3.2.0)
|
61
|
+
dry-logic (1.6.0)
|
62
|
+
bigdecimal
|
63
|
+
concurrent-ruby (~> 1.0)
|
64
|
+
dry-core (~> 1.1)
|
65
|
+
zeitwerk (~> 2.6)
|
66
|
+
dry-schema (1.14.1)
|
67
|
+
concurrent-ruby (~> 1.0)
|
68
|
+
dry-configurable (~> 1.0, >= 1.0.1)
|
69
|
+
dry-core (~> 1.1)
|
70
|
+
dry-initializer (~> 3.2)
|
71
|
+
dry-logic (~> 1.5)
|
72
|
+
dry-types (~> 1.8)
|
73
|
+
zeitwerk (~> 2.6)
|
74
|
+
dry-types (1.8.3)
|
75
|
+
bigdecimal (~> 3.0)
|
76
|
+
concurrent-ruby (~> 1.0)
|
77
|
+
dry-core (~> 1.0)
|
78
|
+
dry-inflector (~> 1.0)
|
79
|
+
dry-logic (~> 1.4)
|
80
|
+
zeitwerk (~> 2.6)
|
47
81
|
event_stream_parser (1.0.0)
|
48
82
|
faraday (2.13.1)
|
49
83
|
faraday-net_http (>= 2.0, < 3.5)
|
@@ -55,6 +89,13 @@ GEM
|
|
55
89
|
net-http (>= 0.5.0)
|
56
90
|
faraday-retry (2.3.1)
|
57
91
|
faraday (~> 2.0)
|
92
|
+
fast-mcp-annotations (1.5.2)
|
93
|
+
addressable (~> 2.8)
|
94
|
+
base64
|
95
|
+
dry-schema (~> 1.14)
|
96
|
+
json (~> 2.0)
|
97
|
+
mime-types (~> 3.4)
|
98
|
+
rack (~> 3.1)
|
58
99
|
ffi (1.17.2-arm64-darwin)
|
59
100
|
ffi (1.17.2-x86_64-linux-gnu)
|
60
101
|
formatador (1.1.0)
|
@@ -73,14 +114,14 @@ GEM
|
|
73
114
|
guard-minitest (2.4.6)
|
74
115
|
guard-compat (~> 1.2)
|
75
116
|
minitest (>= 3.0)
|
76
|
-
hashdiff (1.
|
117
|
+
hashdiff (1.2.0)
|
77
118
|
i18n (1.14.7)
|
78
119
|
concurrent-ruby (~> 1.0)
|
79
120
|
json (2.12.2)
|
80
121
|
json-schema (5.1.1)
|
81
122
|
addressable (~> 2.8)
|
82
123
|
bigdecimal (~> 3.1)
|
83
|
-
language_server-protocol (3.17.0.
|
124
|
+
language_server-protocol (3.17.0.5)
|
84
125
|
lint_roller (1.1.0)
|
85
126
|
listen (3.9.0)
|
86
127
|
rb-fsevent (~> 0.10, >= 0.10.3)
|
@@ -88,6 +129,11 @@ GEM
|
|
88
129
|
logger (1.7.0)
|
89
130
|
lumberjack (1.2.10)
|
90
131
|
method_source (1.1.0)
|
132
|
+
mime-types (3.7.0)
|
133
|
+
logger
|
134
|
+
mime-types-data (~> 3.2025, >= 3.2025.0507)
|
135
|
+
mime-types-data (3.2025.0603)
|
136
|
+
mini_portile2 (2.8.9)
|
91
137
|
minitest (5.25.5)
|
92
138
|
minitest-rg (5.3.0)
|
93
139
|
minitest (~> 5.0)
|
@@ -114,22 +160,23 @@ GEM
|
|
114
160
|
pry (0.15.2)
|
115
161
|
coderay (~> 1.1)
|
116
162
|
method_source (~> 1.0)
|
117
|
-
public_suffix (6.0.
|
163
|
+
public_suffix (6.0.2)
|
118
164
|
racc (1.8.1)
|
165
|
+
rack (3.1.16)
|
119
166
|
rainbow (3.1.1)
|
120
|
-
raix (1.0.
|
167
|
+
raix (1.0.1)
|
121
168
|
activesupport (>= 6.0)
|
122
169
|
faraday-retry (~> 2.0)
|
123
170
|
open_router (~> 0.2)
|
124
171
|
ostruct
|
125
172
|
ruby-openai (~> 7)
|
126
|
-
rake (13.
|
173
|
+
rake (13.3.0)
|
127
174
|
rb-fsevent (0.11.2)
|
128
175
|
rb-inotify (0.11.1)
|
129
176
|
ffi (~> 1.0)
|
130
177
|
regexp_parser (2.10.0)
|
131
178
|
rexml (3.4.1)
|
132
|
-
rubocop (1.
|
179
|
+
rubocop (1.76.0)
|
133
180
|
json (~> 2.3)
|
134
181
|
language_server-protocol (~> 3.17.0.2)
|
135
182
|
lint_roller (~> 1.1.0)
|
@@ -137,14 +184,16 @@ GEM
|
|
137
184
|
parser (>= 3.3.0.2)
|
138
185
|
rainbow (>= 2.2.2, < 4.0)
|
139
186
|
regexp_parser (>= 2.9.3, < 3.0)
|
140
|
-
rubocop-ast (>= 1.
|
187
|
+
rubocop-ast (>= 1.45.0, < 2.0)
|
141
188
|
ruby-progressbar (~> 1.7)
|
142
189
|
unicode-display_width (>= 2.4.0, < 4.0)
|
143
|
-
rubocop-ast (1.
|
190
|
+
rubocop-ast (1.45.0)
|
144
191
|
parser (>= 3.3.7.2)
|
145
192
|
prism (~> 1.4)
|
146
|
-
rubocop-shopify (2.17.
|
193
|
+
rubocop-shopify (2.17.1)
|
147
194
|
rubocop (~> 1.62)
|
195
|
+
ruby-graphviz (1.2.5)
|
196
|
+
rexml
|
148
197
|
ruby-openai (7.4.0)
|
149
198
|
event_stream_parser (>= 0.3.0, < 2.0.0)
|
150
199
|
faraday (>= 1)
|
@@ -153,6 +202,8 @@ GEM
|
|
153
202
|
ruby2_keywords (0.0.5)
|
154
203
|
securerandom (0.4.1)
|
155
204
|
shellany (0.0.1)
|
205
|
+
sqlite3 (1.7.3)
|
206
|
+
mini_portile2 (~> 2.8.0)
|
156
207
|
thor (1.3.2)
|
157
208
|
tzinfo (2.0.6)
|
158
209
|
concurrent-ruby (~> 1.0)
|
@@ -166,14 +217,16 @@ GEM
|
|
166
217
|
addressable (>= 2.8.0)
|
167
218
|
crack (>= 0.3.2)
|
168
219
|
hashdiff (>= 0.4.0, < 2.0.0)
|
220
|
+
zeitwerk (2.7.3)
|
169
221
|
|
170
222
|
PLATFORMS
|
171
|
-
arm64-darwin
|
223
|
+
arm64-darwin
|
172
224
|
x86_64-linux
|
173
225
|
|
174
226
|
DEPENDENCIES
|
175
227
|
cgi
|
176
|
-
|
228
|
+
claude_swarm
|
229
|
+
cli-ui (= 2.3.0)
|
177
230
|
dotenv
|
178
231
|
guard
|
179
232
|
guard-minitest
|
@@ -182,6 +235,7 @@ DEPENDENCIES
|
|
182
235
|
rake
|
183
236
|
roast-ai!
|
184
237
|
rubocop-shopify
|
238
|
+
sqlite3 (~> 1.7)
|
185
239
|
vcr
|
186
240
|
webmock
|
187
241
|
|