cmdx 0.4.0 → 1.0.0
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/.DS_Store +0 -0
- data/.cursor/rules/cursor-instructions.mdc +6 -0
- data/.rubocop.yml +16 -1
- data/.ruby-version +1 -1
- data/CHANGELOG.md +42 -1
- data/README.md +72 -25
- data/docs/ai_prompts.md +309 -0
- data/docs/basics/call.md +225 -14
- data/docs/basics/chain.md +271 -0
- data/docs/basics/context.md +232 -33
- data/docs/basics/setup.md +76 -12
- data/docs/callbacks.md +273 -0
- data/docs/configuration.md +158 -28
- data/docs/getting_started.md +134 -22
- data/docs/interruptions/exceptions.md +189 -11
- data/docs/interruptions/faults.md +187 -44
- data/docs/interruptions/halt.md +179 -35
- data/docs/logging.md +194 -53
- data/docs/middlewares.md +735 -0
- data/docs/outcomes/result.md +296 -10
- data/docs/outcomes/states.md +212 -19
- data/docs/outcomes/statuses.md +284 -18
- data/docs/parameters/coercions.md +402 -29
- data/docs/parameters/defaults.md +249 -25
- data/docs/parameters/definitions.md +238 -72
- data/docs/parameters/namespacing.md +250 -27
- data/docs/parameters/validations.md +193 -168
- data/docs/testing.md +550 -0
- data/docs/tips_and_tricks.md +95 -43
- data/docs/workflows.md +319 -0
- data/lib/cmdx/.DS_Store +0 -0
- data/lib/cmdx/callback.rb +69 -0
- data/lib/cmdx/callback_registry.rb +106 -0
- data/lib/cmdx/chain.rb +190 -0
- data/lib/cmdx/chain_inspector.rb +149 -0
- data/lib/cmdx/chain_serializer.rb +175 -0
- data/lib/cmdx/coercions/array.rb +37 -0
- data/lib/cmdx/coercions/big_decimal.rb +33 -0
- data/lib/cmdx/coercions/boolean.rb +41 -1
- data/lib/cmdx/coercions/complex.rb +31 -0
- data/lib/cmdx/coercions/date.rb +39 -0
- data/lib/cmdx/coercions/date_time.rb +39 -0
- data/lib/cmdx/coercions/float.rb +31 -0
- data/lib/cmdx/coercions/hash.rb +42 -0
- data/lib/cmdx/coercions/integer.rb +32 -0
- data/lib/cmdx/coercions/rational.rb +31 -0
- data/lib/cmdx/coercions/string.rb +31 -0
- data/lib/cmdx/coercions/time.rb +39 -0
- data/lib/cmdx/coercions/virtual.rb +31 -0
- data/lib/cmdx/configuration.rb +217 -9
- data/lib/cmdx/context.rb +173 -2
- data/lib/cmdx/core_ext/hash.rb +72 -0
- data/lib/cmdx/core_ext/module.rb +94 -0
- data/lib/cmdx/core_ext/object.rb +105 -0
- data/lib/cmdx/correlator.rb +217 -0
- data/lib/cmdx/error.rb +210 -8
- data/lib/cmdx/errors.rb +256 -1
- data/lib/cmdx/fault.rb +177 -2
- data/lib/cmdx/faults.rb +158 -2
- data/lib/cmdx/immutator.rb +121 -2
- data/lib/cmdx/lazy_struct.rb +261 -18
- data/lib/cmdx/log_formatters/json.rb +46 -0
- data/lib/cmdx/log_formatters/key_value.rb +46 -0
- data/lib/cmdx/log_formatters/line.rb +54 -0
- data/lib/cmdx/log_formatters/logstash.rb +64 -0
- data/lib/cmdx/log_formatters/pretty_json.rb +57 -0
- data/lib/cmdx/log_formatters/pretty_key_value.rb +51 -0
- data/lib/cmdx/log_formatters/pretty_line.rb +60 -0
- data/lib/cmdx/log_formatters/raw.rb +54 -0
- data/lib/cmdx/logger.rb +85 -0
- data/lib/cmdx/logger_ansi.rb +93 -7
- data/lib/cmdx/logger_serializer.rb +116 -0
- data/lib/cmdx/middleware.rb +74 -0
- data/lib/cmdx/middleware_registry.rb +106 -0
- data/lib/cmdx/middlewares/correlate.rb +266 -0
- data/lib/cmdx/middlewares/timeout.rb +232 -0
- data/lib/cmdx/parameter.rb +228 -1
- data/lib/cmdx/parameter_inspector.rb +61 -0
- data/lib/cmdx/parameter_registry.rb +125 -0
- data/lib/cmdx/parameter_serializer.rb +83 -0
- data/lib/cmdx/parameter_validator.rb +62 -0
- data/lib/cmdx/parameter_value.rb +109 -1
- data/lib/cmdx/parameters_inspector.rb +59 -0
- data/lib/cmdx/parameters_serializer.rb +102 -0
- data/lib/cmdx/railtie.rb +123 -3
- data/lib/cmdx/result.rb +399 -20
- data/lib/cmdx/result_ansi.rb +105 -9
- data/lib/cmdx/result_inspector.rb +76 -0
- data/lib/cmdx/result_logger.rb +90 -3
- data/lib/cmdx/result_serializer.rb +137 -0
- data/lib/cmdx/rspec/result_matchers.rb +917 -0
- data/lib/cmdx/rspec/task_matchers.rb +570 -0
- data/lib/cmdx/task.rb +409 -34
- data/lib/cmdx/task_serializer.rb +74 -2
- data/lib/cmdx/utils/ansi_color.rb +95 -0
- data/lib/cmdx/utils/log_timestamp.rb +48 -0
- data/lib/cmdx/utils/monotonic_runtime.rb +71 -4
- data/lib/cmdx/utils/name_affix.rb +78 -0
- data/lib/cmdx/validators/custom.rb +82 -0
- data/lib/cmdx/validators/exclusion.rb +94 -0
- data/lib/cmdx/validators/format.rb +102 -8
- data/lib/cmdx/validators/inclusion.rb +104 -0
- data/lib/cmdx/validators/length.rb +128 -0
- data/lib/cmdx/validators/numeric.rb +128 -0
- data/lib/cmdx/validators/presence.rb +93 -7
- data/lib/cmdx/version.rb +7 -1
- data/lib/cmdx/workflow.rb +394 -0
- data/lib/cmdx.rb +25 -64
- data/lib/generators/cmdx/install_generator.rb +37 -1
- data/lib/generators/cmdx/task_generator.rb +69 -1
- data/lib/generators/cmdx/templates/install.rb +8 -12
- data/lib/generators/cmdx/workflow_generator.rb +109 -0
- metadata +54 -15
- data/docs/basics/run.md +0 -34
- data/docs/batch.md +0 -53
- data/docs/example.md +0 -82
- data/docs/hooks.md +0 -59
- data/lib/cmdx/batch.rb +0 -43
- data/lib/cmdx/parameters.rb +0 -34
- data/lib/cmdx/run.rb +0 -38
- data/lib/cmdx/run_inspector.rb +0 -26
- data/lib/cmdx/run_serializer.rb +0 -16
- data/lib/cmdx/task_hook.rb +0 -18
- data/lib/generators/cmdx/batch_generator.rb +0 -30
- /data/lib/generators/cmdx/templates/{batch.rb.tt → workflow.rb.tt} +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 15c3343ebbc1be1654e955561dacc79a9a27f398005bb6aa890e2167de87855a
|
4
|
+
data.tar.gz: 3c3e4f9d6e8d86f89e0bea6cf5573734345ea10608a7ea499f3c5ea00426d8a2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a9fbc22f9d725f8798fd4efbecab466ca5baaad04ba3a4ece97a1ed878d40813b315cfaab1d2173fd220241904c061aa7b3604e34d7fa2aaa719b48df7d723b9
|
7
|
+
data.tar.gz: 7b2b7532835041a91867d2f0fc7f83c092f247de39d4668b33301008d847af43d352e0c8bf0820911290176af48cf396f351e651a04b126e0aebec42f415a2e9
|
data/.DS_Store
CHANGED
Binary file
|
data/.rubocop.yml
CHANGED
@@ -6,7 +6,6 @@ AllCops:
|
|
6
6
|
NewCops: enable
|
7
7
|
DisplayCopNames: true
|
8
8
|
DisplayStyleGuide: true
|
9
|
-
TargetRubyVersion: 3.1.0
|
10
9
|
Gemspec/DevelopmentDependencies:
|
11
10
|
EnforcedStyle: gemspec
|
12
11
|
Layout/EmptyLinesAroundAttributeAccessor:
|
@@ -17,10 +16,15 @@ Layout/EmptyLinesAroundModuleBody:
|
|
17
16
|
EnforcedStyle: empty_lines_except_namespace
|
18
17
|
Layout/LineLength:
|
19
18
|
Enabled: false
|
19
|
+
Lint/MissingSuper:
|
20
|
+
Exclude:
|
21
|
+
- 'lib/cmdx/middlewares/**/*'
|
22
|
+
- 'spec/**/**/*'
|
20
23
|
Metrics/AbcSize:
|
21
24
|
Enabled: false
|
22
25
|
Metrics/BlockLength:
|
23
26
|
Exclude:
|
27
|
+
- 'lib/cmdx/rspec/**/*'
|
24
28
|
- 'spec/**/**/*'
|
25
29
|
- '*.gemspec'
|
26
30
|
Metrics/ClassLength:
|
@@ -37,8 +41,15 @@ Naming/MethodParameterName:
|
|
37
41
|
Enabled: false
|
38
42
|
RSpec/AnyInstance:
|
39
43
|
Enabled: false
|
44
|
+
RSpec/DescribeClass:
|
45
|
+
Exclude:
|
46
|
+
- 'spec/integrations/**/*'
|
40
47
|
RSpec/ExampleLength:
|
41
48
|
Enabled: false
|
49
|
+
RSpec/MessageSpies:
|
50
|
+
Enabled: false
|
51
|
+
RSpec/MultipleMemoizedHelpers:
|
52
|
+
Enabled: false
|
42
53
|
RSpec/MultipleExpectations:
|
43
54
|
Enabled: false
|
44
55
|
RSpec/NestedGroups:
|
@@ -46,6 +57,10 @@ RSpec/NestedGroups:
|
|
46
57
|
RSpec/SpecFilePathFormat:
|
47
58
|
CustomTransform:
|
48
59
|
CMDx: cmdx
|
60
|
+
RSpec/StubbedMock:
|
61
|
+
Enabled: false
|
62
|
+
RSpec/VerifiedDoubles:
|
63
|
+
Enabled: false
|
49
64
|
RSpec/VerifiedDoubleReference:
|
50
65
|
Enabled: false
|
51
66
|
Style/Documentation:
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.4.
|
1
|
+
3.4.4
|
data/CHANGELOG.md
CHANGED
@@ -1,9 +1,47 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [1.0.0] - 2025-07-03
|
4
|
+
|
5
|
+
### Added
|
6
|
+
- Zeitwerk gem loader
|
7
|
+
- Add middleware support for tasks
|
8
|
+
- Add Cursor and Copilot rules
|
9
|
+
- Add YARDoc documentation
|
10
|
+
- Add `perform!` and `perform` alias to class `call!` and `call`
|
11
|
+
- Allow direct instantiation of Task and Batch objects
|
12
|
+
- Add pattern matching of results
|
13
|
+
- Add a `Hook` class
|
14
|
+
- Add hooks via configuration
|
15
|
+
### Changed
|
16
|
+
- Changed configuration to be a PORO class
|
17
|
+
- Changed ArgumentError to TypeError where checking `is_a?`
|
18
|
+
- Improve documentation readability, consistency, completeness
|
19
|
+
- Improve test readability, consistency, completeness
|
20
|
+
- Renames `Parameters` to `ParameterRegistry`
|
21
|
+
- Convert hooks hash to a registry
|
22
|
+
- Rename `Run` and its associated items to `Chain`
|
23
|
+
- Convert `Chain` to use threads instead of passing context
|
24
|
+
- Immutator now uses a `SKIP_CMDX_FREEZING` env var instead of `RACK_ENV` or `RAILS_ENV`
|
25
|
+
- Rename `Hook` to `Callback`
|
26
|
+
- Rename `Batch` to `Workflow`
|
27
|
+
### Removed
|
28
|
+
- Removed configuration `task_timeout` and `batch_timeout`
|
29
|
+
|
30
|
+
## [0.5.0] - 2025-03-21
|
31
|
+
|
32
|
+
### Added
|
33
|
+
- Add `to_a` alias on array of hashes serializers
|
34
|
+
- Add `state`, `status`, `outcome`, and `runtime` to run serializer
|
35
|
+
- Add `on_[state]` and `on_[status]` based result callback handlers
|
36
|
+
- Add `on_executed` state task hook
|
37
|
+
- Add `on_good` and `on_bad` status task hook
|
38
|
+
### Changed
|
39
|
+
- Changed status and state hook order
|
40
|
+
|
3
41
|
## [0.4.0] - 2025-03-17
|
4
42
|
|
5
43
|
### Added
|
6
|
-
- Add
|
44
|
+
- Add ANSI util
|
7
45
|
- Add string to json parsing in hash coercion
|
8
46
|
- Add string to json parsing in array coercion
|
9
47
|
### Changed
|
@@ -12,6 +50,7 @@
|
|
12
50
|
- Improve run inspector output
|
13
51
|
|
14
52
|
## [0.3.0] - 2025-03-14
|
53
|
+
|
15
54
|
### Added
|
16
55
|
- Add `progname` to logger instances
|
17
56
|
- Add `LoggerSerializer` to standardize log output
|
@@ -22,6 +61,7 @@
|
|
22
61
|
- Fix `call!` not marking state of failure as interrupted
|
23
62
|
|
24
63
|
## [0.2.0] - 2025-03-12
|
64
|
+
|
25
65
|
### Added
|
26
66
|
- Add `PrettyJson` log formatter
|
27
67
|
- Add `PrettyKeyValue` log formatter
|
@@ -36,5 +76,6 @@
|
|
36
76
|
- Wrap result logger in a `Logger#with_logger` block
|
37
77
|
|
38
78
|
## [0.1.0] - 2025-03-07
|
79
|
+
|
39
80
|
### Added
|
40
81
|
- Initial release
|
data/README.md
CHANGED
@@ -6,9 +6,7 @@
|
|
6
6
|
[](https://github.com/drexed/cmdx/actions/workflows/ci.yml)
|
7
7
|
[](http://makeapullrequest.com)
|
8
8
|
|
9
|
-
`CMDx` is a framework for
|
10
|
-
code of varying levels of complexity that is built through branching and
|
11
|
-
composition, informative halting, and exhaustive tracing/debugging.
|
9
|
+
`CMDx` is a Ruby framework for building maintainable, observable business logic through composable command objects. Design robust workflows with automatic parameter validation, structured error handling, comprehensive logging, and intelligent execution flow control that scales from simple tasks to complex multi-step processes.
|
12
10
|
|
13
11
|
## Installation
|
14
12
|
|
@@ -28,34 +26,83 @@ Or install it yourself as:
|
|
28
26
|
|
29
27
|
$ gem install cmdx
|
30
28
|
|
29
|
+
## Quick Example
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
# Setup task
|
33
|
+
class SendWelcomeEmailTask < CMDx::Task
|
34
|
+
use CMDx::Middlewares::Timeout, seconds: 5
|
35
|
+
|
36
|
+
on_success :track_email_delivery!
|
37
|
+
|
38
|
+
required :user_id, type: :integer, numeric: { min: 1 }
|
39
|
+
optional :template, type: :string, default: "welcome"
|
40
|
+
|
41
|
+
def call
|
42
|
+
if user.nil?
|
43
|
+
fail!(reason: "User not found", code: 404)
|
44
|
+
elsif user.unconfirmed?
|
45
|
+
skip!(reason: "Email not verified")
|
46
|
+
else
|
47
|
+
response = UserMailer.welcome(user, template).deliver_now
|
48
|
+
context.message_id = response.message_id
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def user
|
55
|
+
@user ||= User.find_by(id: user_id)
|
56
|
+
end
|
57
|
+
|
58
|
+
def track_email_delivery!
|
59
|
+
user.touch(:welcomed_at)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Execute task
|
64
|
+
result = SendWelcomeEmailTask.call(user_id: 123, template: "premium_welcome")
|
65
|
+
|
66
|
+
# Handle result
|
67
|
+
if result.success?
|
68
|
+
puts "Welcome email sent <message_id: #{result.context.message_id}>"
|
69
|
+
elsif result.skipped?
|
70
|
+
puts "Skipped: #{result.metadata[:reason]}"
|
71
|
+
elsif result.failed?
|
72
|
+
puts "Failed: #{result.metadata[:reason]} with code: #{result.metadata[:code]}"
|
73
|
+
end
|
74
|
+
```
|
75
|
+
|
31
76
|
## Table of contents
|
32
77
|
|
33
|
-
- [Getting Started](
|
34
|
-
- [Configuration](
|
78
|
+
- [Getting Started](docs/getting_started.md)
|
79
|
+
- [Configuration](docs/configuration.md)
|
35
80
|
- Basics
|
36
|
-
- [Setup](
|
37
|
-
- [Call](
|
38
|
-
- [Context](
|
39
|
-
- [
|
81
|
+
- [Setup](docs/basics/setup.md)
|
82
|
+
- [Call](docs/basics/call.md)
|
83
|
+
- [Context](docs/basics/context.md)
|
84
|
+
- [Chain](docs/basics/chain.md)
|
40
85
|
- Interruptions
|
41
|
-
- [Halt](
|
42
|
-
- [Faults](
|
43
|
-
- [Exceptions](
|
86
|
+
- [Halt](docs/interruptions/halt.md)
|
87
|
+
- [Faults](docs/interruptions/faults.md)
|
88
|
+
- [Exceptions](docs/interruptions/exceptions.md)
|
44
89
|
- Parameters
|
45
|
-
- [Definitions](
|
46
|
-
- [Namespacing](
|
47
|
-
- [Coercions](
|
48
|
-
- [Validations](
|
49
|
-
- [Defaults](
|
90
|
+
- [Definitions](docs/parameters/definitions.md)
|
91
|
+
- [Namespacing](docs/parameters/namespacing.md)
|
92
|
+
- [Coercions](docs/parameters/coercions.md)
|
93
|
+
- [Validations](docs/parameters/validations.md)
|
94
|
+
- [Defaults](docs/parameters/defaults.md)
|
50
95
|
- Outcomes
|
51
96
|
- [Result](#results)
|
52
|
-
- [States](
|
53
|
-
- [Statuses](
|
54
|
-
- [
|
55
|
-
- [
|
56
|
-
- [
|
57
|
-
- [
|
58
|
-
- [
|
97
|
+
- [States](docs/outcomes/states.md)
|
98
|
+
- [Statuses](docs/outcomes/statuses.md)
|
99
|
+
- [Callbacks](docs/callbacks.md)
|
100
|
+
- [Middlewares](docs/middlewares.md)
|
101
|
+
- [Workflows](docs/workflows.md)
|
102
|
+
- [Logging](docs/logging.md)
|
103
|
+
- [Testing](docs/testing.md)
|
104
|
+
- [AI Prompts](docs/ai_prompts.md)
|
105
|
+
- [Tips & Tricks](docs/tips_and_tricks.md)
|
59
106
|
|
60
107
|
## Development
|
61
108
|
|
@@ -73,4 +120,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
73
120
|
|
74
121
|
## Code of Conduct
|
75
122
|
|
76
|
-
Everyone interacting in the CMDx project
|
123
|
+
Everyone interacting in the CMDx project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](CODE_OF_CONDUCT.md).
|
data/docs/ai_prompts.md
ADDED
@@ -0,0 +1,309 @@
|
|
1
|
+
# AI Prompt Templates
|
2
|
+
|
3
|
+
This guide provides AI prompt templates for building CMDx Task and Workflow objects, helping you leverage AI assistants to generate well-structured, production-ready command objects.
|
4
|
+
|
5
|
+
## Table of Contents
|
6
|
+
|
7
|
+
- [Framework Context Template](#framework-context-template)
|
8
|
+
- [Task Generation Templates](#task-generation-templates)
|
9
|
+
- [Workflow Generation Templates](#workflow-generation-templates)
|
10
|
+
- [Testing Templates](#testing-templates)
|
11
|
+
- [Best Practices for AI Prompts](#best-practices-for-ai-prompts)
|
12
|
+
|
13
|
+
## Framework Context Template
|
14
|
+
|
15
|
+
Use this context in your AI conversations to ensure proper CMDx code generation:
|
16
|
+
|
17
|
+
```
|
18
|
+
I'm working with CMDx, a Ruby framework for designing and executing business logic within service/command objects.
|
19
|
+
|
20
|
+
KEY FRAMEWORK CONCEPTS:
|
21
|
+
- Tasks inherit from CMDx::Task and implement business logic in a `call` method
|
22
|
+
- Workflows inherit from CMDx::Workflow and orchestrate multiple tasks
|
23
|
+
- Parameters are defined with type coercion, validation, and defaults
|
24
|
+
- Results contain status (success/failed/skipped), state, context, and metadata
|
25
|
+
- Callbacks execute at specific lifecycle points (before_validation, on_success, etc.)
|
26
|
+
- Middlewares wrap task execution (authentication, logging, timeouts)
|
27
|
+
- Chains link multiple tasks together with shared context
|
28
|
+
|
29
|
+
CODING STANDARDS:
|
30
|
+
- Use Ruby 3.4+ syntax and conventions
|
31
|
+
- Follow snake_case for methods/variables, CamelCase for classes
|
32
|
+
- Use double quotes for strings
|
33
|
+
- Include comprehensive YARD documentation
|
34
|
+
- Write RSpec tests with CMDx custom matchers
|
35
|
+
- Name tasks as VerbNounTask (e.g., ProcessOrderTask)
|
36
|
+
- Name workflows as NounVerbWorkflow (e.g., OrderProcessingWorkflow)
|
37
|
+
|
38
|
+
Generate code that is production-ready with proper error handling, validation, and testing.
|
39
|
+
```
|
40
|
+
|
41
|
+
## Task Generation Templates
|
42
|
+
|
43
|
+
```
|
44
|
+
Create a CMDx task that [SPECIFIC_ACTION] with the following requirements:
|
45
|
+
|
46
|
+
PARAMETERS:
|
47
|
+
- [parameter_name]: [type] - [description] - [required/optional]
|
48
|
+
- [parameter_name]: [type] - [description] - [validation_rules]
|
49
|
+
|
50
|
+
BUSINESS LOGIC:
|
51
|
+
- [Step 1 description]
|
52
|
+
- [Step 2 description]
|
53
|
+
- [Error conditions to handle]
|
54
|
+
|
55
|
+
CONTEXT UPDATES:
|
56
|
+
- [What data should be added to context]
|
57
|
+
- [What side effects should occur]
|
58
|
+
|
59
|
+
TESTING:
|
60
|
+
- Generate comprehensive RSpec tests using CMDx matchers
|
61
|
+
- Include success, failure, and edge case scenarios
|
62
|
+
- Test parameter validation and context updates
|
63
|
+
|
64
|
+
Please include:
|
65
|
+
- Proper parameter definitions with validations
|
66
|
+
- Error handling and metadata
|
67
|
+
- YARD documentation
|
68
|
+
- RSpec test file
|
69
|
+
```
|
70
|
+
|
71
|
+
**Example Usage:**
|
72
|
+
```
|
73
|
+
Create a CMDx task that processes user email preferences with the following requirements:
|
74
|
+
|
75
|
+
PARAMETERS:
|
76
|
+
- user_id: integer - ID of the user - required, positive
|
77
|
+
- email_types: array - Types of emails to enable - required, inclusion in ['marketing', 'notifications', 'alerts']
|
78
|
+
- enabled: boolean - Whether to enable or disable - optional, defaults to true
|
79
|
+
|
80
|
+
BUSINESS LOGIC:
|
81
|
+
- Validate user exists and is active
|
82
|
+
- Update user's email preferences in database
|
83
|
+
- Send confirmation email if preferences changed
|
84
|
+
- Log preference changes for audit trail
|
85
|
+
|
86
|
+
CONTEXT UPDATES:
|
87
|
+
- Add updated user object to context
|
88
|
+
- Add preference_changes hash with before/after values
|
89
|
+
- Add confirmation_sent boolean
|
90
|
+
|
91
|
+
TESTING:
|
92
|
+
- Generate comprehensive RSpec tests using CMDx matchers
|
93
|
+
- Include success, failure, and edge case scenarios
|
94
|
+
- Test parameter validation and context updates
|
95
|
+
```
|
96
|
+
|
97
|
+
## Workflow Generation Templates
|
98
|
+
|
99
|
+
```
|
100
|
+
Create a CMDx workflow that orchestrates [BUSINESS_PROCESS] with the following requirements:
|
101
|
+
|
102
|
+
WORKFLOW STEPS:
|
103
|
+
1. [Task 1]: [Description and purpose]
|
104
|
+
2. [Task 2]: [Description and purpose]
|
105
|
+
3. [Task 3]: [Description and purpose]
|
106
|
+
|
107
|
+
TASK DEPENDENCIES:
|
108
|
+
- [How tasks share data through context]
|
109
|
+
- [Which tasks can run in parallel]
|
110
|
+
- [Sequential requirements]
|
111
|
+
|
112
|
+
ERROR HANDLING:
|
113
|
+
- [How to handle individual task failures]
|
114
|
+
- [Rollback requirements]
|
115
|
+
- [Compensation logic]
|
116
|
+
|
117
|
+
CONDITIONAL LOGIC:
|
118
|
+
- [When to skip certain tasks]
|
119
|
+
- [Branching based on context]
|
120
|
+
|
121
|
+
TESTING:
|
122
|
+
- Generate workflow integration tests
|
123
|
+
- Test success path and various failure scenarios
|
124
|
+
- Include individual task unit tests
|
125
|
+
```
|
126
|
+
|
127
|
+
**Example Usage:**
|
128
|
+
```
|
129
|
+
Create a CMDx workflow that orchestrates user onboarding with the following requirements:
|
130
|
+
|
131
|
+
WORKFLOW STEPS:
|
132
|
+
1. ValidateUserDataTask: Validate and sanitize user registration data
|
133
|
+
2. CreateUserAccountTask: Create user account in database
|
134
|
+
3. SendWelcomeEmailTask: Send personalized welcome email
|
135
|
+
4. SetupDefaultPreferencesTask: Configure default user preferences
|
136
|
+
5. TrackOnboardingEventTask: Log onboarding completion for analytics
|
137
|
+
|
138
|
+
TASK DEPENDENCIES:
|
139
|
+
- All tasks run sequentially
|
140
|
+
- User data flows through context from validation to account creation
|
141
|
+
- Welcome email uses created user object
|
142
|
+
- Preferences setup requires user ID
|
143
|
+
- Analytics tracking happens last with full context
|
144
|
+
|
145
|
+
ERROR HANDLING:
|
146
|
+
- If account creation fails, don't send email or setup preferences
|
147
|
+
- If email fails, continue with preferences but log the failure
|
148
|
+
- If preferences fail, still complete onboarding but flag for followup
|
149
|
+
|
150
|
+
CONDITIONAL LOGIC:
|
151
|
+
- Skip welcome email if user opted out during registration
|
152
|
+
- Skip analytics if user has privacy settings enabled
|
153
|
+
|
154
|
+
TESTING:
|
155
|
+
- Generate workflow integration tests
|
156
|
+
- Test success path and various failure scenarios
|
157
|
+
- Include individual task unit tests
|
158
|
+
```
|
159
|
+
|
160
|
+
## Testing Templates
|
161
|
+
|
162
|
+
### Task Testing Template
|
163
|
+
|
164
|
+
```
|
165
|
+
Generate comprehensive RSpec tests for [TASK_NAME] including:
|
166
|
+
|
167
|
+
PARAMETER VALIDATION TESTS:
|
168
|
+
- Test all required parameters
|
169
|
+
- Test type coercion and validation rules
|
170
|
+
- Test default values
|
171
|
+
- Test invalid parameter combinations
|
172
|
+
|
173
|
+
EXECUTION TESTS:
|
174
|
+
- Test successful execution with various inputs
|
175
|
+
- Test all error conditions and edge cases
|
176
|
+
- Test context updates and side effects
|
177
|
+
- Test metadata and timing information
|
178
|
+
|
179
|
+
INTEGRATION TESTS:
|
180
|
+
- Test external service interactions
|
181
|
+
- Test database operations
|
182
|
+
- Test file system operations (if applicable)
|
183
|
+
|
184
|
+
CALLBACK TESTS:
|
185
|
+
- Test lifecycle callbacks execute correctly
|
186
|
+
- Test callback order and context
|
187
|
+
|
188
|
+
Use CMDx custom matchers like:
|
189
|
+
- expect(result).to be_successful_task
|
190
|
+
- expect(result).to be_failed_task
|
191
|
+
- expect(TaskClass).to handle_exceptions_gracefully
|
192
|
+
```
|
193
|
+
|
194
|
+
### Workflow Testing Template
|
195
|
+
|
196
|
+
```
|
197
|
+
Generate comprehensive RSpec tests for [WORKFLOW_NAME] including:
|
198
|
+
|
199
|
+
INTEGRATION TESTS:
|
200
|
+
- Test complete workflow execution
|
201
|
+
- Test various success scenarios
|
202
|
+
- Test different failure points
|
203
|
+
- Test context flow between tasks
|
204
|
+
|
205
|
+
INDIVIDUAL TASK TESTS:
|
206
|
+
- Test each task in isolation
|
207
|
+
- Test task parameter validation
|
208
|
+
- Test task-specific logic
|
209
|
+
|
210
|
+
CONDITIONAL LOGIC TESTS:
|
211
|
+
- Test all branching paths
|
212
|
+
- Test edge cases in decision logic
|
213
|
+
- Test context preservation across branches
|
214
|
+
|
215
|
+
ERROR HANDLING TESTS:
|
216
|
+
- Test failure propagation
|
217
|
+
- Test recovery mechanisms
|
218
|
+
- Test compensation logic
|
219
|
+
```
|
220
|
+
|
221
|
+
## Best Practices for AI Prompts
|
222
|
+
|
223
|
+
### 1. Be Specific About Requirements
|
224
|
+
|
225
|
+
**Good:**
|
226
|
+
```
|
227
|
+
Create a task that validates credit card information, including:
|
228
|
+
- Card number validation with Luhn algorithm
|
229
|
+
- Expiry date validation (not expired, reasonable future date)
|
230
|
+
- CVV validation (3-4 digits depending on card type)
|
231
|
+
- Cardholder name validation (2-50 characters, letters and spaces only)
|
232
|
+
```
|
233
|
+
|
234
|
+
**Avoid:**
|
235
|
+
```
|
236
|
+
Create a task that validates credit cards
|
237
|
+
```
|
238
|
+
|
239
|
+
### 2. Include Context About Data Flow
|
240
|
+
|
241
|
+
**Good:**
|
242
|
+
```
|
243
|
+
The task should receive user_id and payment_amount, validate the payment method,
|
244
|
+
charge the card, and update the context with:
|
245
|
+
- transaction_id
|
246
|
+
- charged_amount
|
247
|
+
- payment_method_last_four
|
248
|
+
- charge_timestamp
|
249
|
+
```
|
250
|
+
|
251
|
+
**Avoid:**
|
252
|
+
```
|
253
|
+
Process a payment
|
254
|
+
```
|
255
|
+
|
256
|
+
### 3. Specify Error Conditions
|
257
|
+
|
258
|
+
**Good:**
|
259
|
+
```
|
260
|
+
Handle these error conditions:
|
261
|
+
- Invalid card number → failed result with metadata { error_code: 'INVALID_CARD' }
|
262
|
+
- Expired card → failed result with metadata { error_code: 'EXPIRED_CARD' }
|
263
|
+
- Insufficient funds → failed result with metadata { error_code: 'DECLINED', retryable: false }
|
264
|
+
- Network timeout → failed result with metadata { error_code: 'TIMEOUT', retryable: true }
|
265
|
+
```
|
266
|
+
|
267
|
+
**Avoid:**
|
268
|
+
```
|
269
|
+
Handle payment errors
|
270
|
+
```
|
271
|
+
|
272
|
+
### 4. Request Complete Examples
|
273
|
+
|
274
|
+
**Good:**
|
275
|
+
```
|
276
|
+
Generate a complete working example including:
|
277
|
+
- Task class with full implementation
|
278
|
+
- Parameter definitions with validations
|
279
|
+
- RSpec test file with success/failure scenarios
|
280
|
+
- YARD documentation
|
281
|
+
- Usage examples in comments
|
282
|
+
```
|
283
|
+
|
284
|
+
**Avoid:**
|
285
|
+
```
|
286
|
+
Show me the basic structure
|
287
|
+
```
|
288
|
+
|
289
|
+
### 5. Specify Framework Patterns
|
290
|
+
|
291
|
+
**Good:**
|
292
|
+
```
|
293
|
+
Follow CMDx patterns:
|
294
|
+
- Use present tense verbs in task names (ProcessPaymentTask, not ProcessingPaymentTask)
|
295
|
+
- Include proper error handling with metadata
|
296
|
+
- Use callbacks for audit logging
|
297
|
+
- Return detailed context updates
|
298
|
+
- Include comprehensive parameter validation
|
299
|
+
```
|
300
|
+
|
301
|
+
**Avoid:**
|
302
|
+
```
|
303
|
+
Use best practices
|
304
|
+
```
|
305
|
+
|
306
|
+
---
|
307
|
+
|
308
|
+
- **Prev:** [Testing](testing.md)
|
309
|
+
- **Next:** [Tips and Tricks](tips_and_tricks.md)
|