cmdx 1.9.0 → 1.10.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.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/.cursor/prompts/llms.md +3 -13
  3. data/.cursor/prompts/yardoc.md +1 -0
  4. data/CHANGELOG.md +16 -0
  5. data/LLM.md +436 -374
  6. data/README.md +7 -2
  7. data/docs/basics/setup.md +17 -0
  8. data/docs/callbacks.md +1 -1
  9. data/docs/getting_started.md +22 -2
  10. data/docs/index.md +13 -1
  11. data/docs/retries.md +121 -0
  12. data/docs/tips_and_tricks.md +2 -1
  13. data/examples/stoplight_circuit_breaker.md +36 -0
  14. data/lib/cmdx/attribute.rb +82 -1
  15. data/lib/cmdx/attribute_registry.rb +20 -0
  16. data/lib/cmdx/attribute_value.rb +25 -0
  17. data/lib/cmdx/callback_registry.rb +19 -0
  18. data/lib/cmdx/chain.rb +34 -1
  19. data/lib/cmdx/coercion_registry.rb +18 -0
  20. data/lib/cmdx/coercions/array.rb +2 -0
  21. data/lib/cmdx/coercions/big_decimal.rb +3 -0
  22. data/lib/cmdx/coercions/boolean.rb +5 -0
  23. data/lib/cmdx/coercions/complex.rb +2 -0
  24. data/lib/cmdx/coercions/date.rb +4 -0
  25. data/lib/cmdx/coercions/date_time.rb +5 -0
  26. data/lib/cmdx/coercions/float.rb +2 -0
  27. data/lib/cmdx/coercions/hash.rb +2 -0
  28. data/lib/cmdx/coercions/integer.rb +2 -0
  29. data/lib/cmdx/coercions/rational.rb +2 -0
  30. data/lib/cmdx/coercions/string.rb +2 -0
  31. data/lib/cmdx/coercions/symbol.rb +2 -0
  32. data/lib/cmdx/coercions/time.rb +5 -0
  33. data/lib/cmdx/configuration.rb +126 -3
  34. data/lib/cmdx/context.rb +36 -0
  35. data/lib/cmdx/deprecator.rb +3 -0
  36. data/lib/cmdx/errors.rb +22 -0
  37. data/lib/cmdx/executor.rb +71 -11
  38. data/lib/cmdx/faults.rb +14 -0
  39. data/lib/cmdx/identifier.rb +2 -0
  40. data/lib/cmdx/locale.rb +3 -0
  41. data/lib/cmdx/log_formatters/json.rb +2 -0
  42. data/lib/cmdx/log_formatters/key_value.rb +2 -0
  43. data/lib/cmdx/log_formatters/line.rb +2 -0
  44. data/lib/cmdx/log_formatters/logstash.rb +2 -0
  45. data/lib/cmdx/log_formatters/raw.rb +2 -0
  46. data/lib/cmdx/middleware_registry.rb +20 -0
  47. data/lib/cmdx/middlewares/correlate.rb +11 -0
  48. data/lib/cmdx/middlewares/runtime.rb +4 -0
  49. data/lib/cmdx/middlewares/timeout.rb +4 -0
  50. data/lib/cmdx/pipeline.rb +20 -1
  51. data/lib/cmdx/railtie.rb +4 -0
  52. data/lib/cmdx/result.rb +123 -1
  53. data/lib/cmdx/task.rb +91 -1
  54. data/lib/cmdx/utils/call.rb +2 -0
  55. data/lib/cmdx/utils/condition.rb +3 -0
  56. data/lib/cmdx/utils/format.rb +5 -0
  57. data/lib/cmdx/validator_registry.rb +18 -0
  58. data/lib/cmdx/validators/exclusion.rb +2 -0
  59. data/lib/cmdx/validators/format.rb +2 -0
  60. data/lib/cmdx/validators/inclusion.rb +2 -0
  61. data/lib/cmdx/validators/length.rb +14 -0
  62. data/lib/cmdx/validators/numeric.rb +14 -0
  63. data/lib/cmdx/validators/presence.rb +2 -0
  64. data/lib/cmdx/version.rb +4 -1
  65. data/lib/cmdx/workflow.rb +10 -0
  66. data/lib/cmdx.rb +8 -0
  67. data/lib/generators/cmdx/locale_generator.rb +0 -1
  68. data/mkdocs.yml +3 -1
  69. metadata +3 -1
data/LLM.md CHANGED
@@ -1,40 +1,33 @@
1
- # CMDx Documentation
2
-
3
- This file contains all the CMDx documentation consolidated from the docs directory.
1
+ # Getting Started
4
2
 
5
- ---
3
+ CMDx is a Ruby framework for building maintainable, observable business logic through composable command objects. It brings structure, consistency, and powerful developer tools to your business processes.
6
4
 
7
- url: https://github.com/drexed/cmdx/blob/main/docs/getting_started.md
8
- ---
5
+ **Common challenges it solves:**
9
6
 
10
- # Getting Started
7
+ - Inconsistent service object patterns across your codebase
8
+ - Limited logging makes debugging a nightmare
9
+ - Fragile error handling erodes confidence
11
10
 
12
- CMDx is a Ruby framework for building maintainable, observable business logic through composable command objects. Design robust workflows with automatic attribute validation, structured error handling, comprehensive logging, and intelligent execution flow control.
11
+ **What you get:**
13
12
 
14
- **Common Challenges:**
13
+ - Consistent, standardized architecture
14
+ - Built-in flow control and error handling
15
+ - Composable, reusable workflows
16
+ - Comprehensive logging for observability
17
+ - Attribute validation with type coercions
18
+ - Sensible defaults and developer-friendly APIs
15
19
 
16
- - Inconsistent patterns across implementations
17
- - Minimal or no logging, making debugging painful
18
- - Fragile designs that erode developer confidence
20
+ ## The CERO Pattern
19
21
 
20
- **CMDx Solutions:**
22
+ CMDx embraces the Compose, Execute, React, Observe (CERO) pattern—a simple yet powerful approach to building reliable business logic.
21
23
 
22
- - Establishes a consistent, standardized design
23
- - Provides flow control and error handling
24
- - Supports composable, reusable workflows
25
- - Includes detailed logging for observability
26
- - Defines input attributes with fallback defaults
27
- - Adds validations and type coercions
28
- - Plus many other developer-friendly tools
24
+ 🧩 **Compose** Define small, focused tasks with typed attributes and validations
29
25
 
30
- ## Compose, Execute, React, Observe pattern
26
+ **Execute** Run tasks with clear outcomes and pluggable behaviors
31
27
 
32
- CMDx encourages breaking business logic into composable tasks. Each task can be combined into larger workflows, executed with standardized flow control, and fully observed through logging, validations, and context.
28
+ 🔄 **React** Adapt to outcomes by chaining follow-up tasks or handling faults
33
29
 
34
- - **Compose** Define small, contract-driven tasks with typed attributes, validations, and natural workflow composition.
35
- - **Execute** → Run tasks with clear outcomes, intentional halts, and pluggable behaviors via middlewares and callbacks.
36
- - **React** → Adapt to outcomes by chaining follow-up tasks, handling faults, or shaping future flows.
37
- - **Observe** → Capture immutable results, structured logs, and full execution chains for reliable tracing and insight.
30
+ 🔍 **Observe** Capture structured logs and execution chains for debugging
38
31
 
39
32
  ## Installation
40
33
 
@@ -54,45 +47,54 @@ This creates `config/initializers/cmdx.rb` file.
54
47
 
55
48
  ## Configuration Hierarchy
56
49
 
57
- CMDx follows a two-tier configuration hierarchy:
50
+ CMDx uses a straightforward two-tier configuration system:
51
+
52
+ 1. **Global Configuration** — Framework-wide defaults
53
+ 2. **Task Settings** — Class-level overrides using `settings`
58
54
 
59
- 1. **Global Configuration**: Framework-wide defaults
60
- 2. **Task Settings**: Class-level overrides via `settings`
55
+ !!! warning "Important"
61
56
 
62
- > [!IMPORTANT]
63
- > Task-level settings take precedence over global configuration. Settings are inherited from superclasses and can be overridden in subclasses.
57
+ Task settings take precedence over global config. Settings are inherited from parent classes and can be overridden in subclasses.
64
58
 
65
59
  ## Global Configuration
66
60
 
67
- Global configuration settings apply to all tasks inherited from `CMDx::Task`.
68
- Globally these settings are initialized with sensible defaults.
61
+ Configure framework-wide defaults that apply to all tasks. These settings come with sensible defaults out of the box.
69
62
 
70
63
  ### Breakpoints
71
64
 
72
- Raise `CMDx::Fault` when a task called with `execute!` returns a matching status.
65
+ Control when `execute!` raises a `CMDx::Fault` based on task status.
73
66
 
74
67
  ```ruby
75
68
  CMDx.configure do |config|
76
- # String or Array[String]
77
- config.task_breakpoints = "failed"
69
+ config.task_breakpoints = "failed" # String or Array[String]
78
70
  end
79
71
  ```
80
72
 
81
- Workflow breakpoints stops execution and of workflow pipeline on the first task that returns a matching status and throws its `CMDx::Fault`.
73
+ For workflows, configure which statuses halt the execution pipeline:
82
74
 
83
75
  ```ruby
84
76
  CMDx.configure do |config|
85
- # String or Array[String]
86
77
  config.workflow_breakpoints = ["skipped", "failed"]
87
78
  end
88
79
  ```
89
80
 
81
+ ### Rollback
82
+
83
+ Control when a `rollback` of task execution is called.
84
+
85
+ ```ruby
86
+ CMDx.configure do |config|
87
+ config.rollback_on = ["failed"] # String or Array[String]
88
+ end
89
+ ```
90
+
90
91
  ### Backtraces
91
92
 
92
- Enable backtraces to be logged on any non-fault exceptions for improved debugging context. Run them through a cleaner to remove unwanted stack trace noise.
93
+ Enable detailed backtraces for non-fault exceptions to improve debugging. Optionally clean up stack traces to remove framework noise.
94
+
95
+ !!! note
93
96
 
94
- > [!NOTE]
95
- > The `backtrace_cleaner` is set to `Rails.backtrace_cleaner.clean` in a Rails env by default.
97
+ In Rails environments, `backtrace_cleaner` defaults to `Rails.backtrace_cleaner.clean`.
96
98
 
97
99
  ```ruby
98
100
  CMDx.configure do |config|
@@ -109,10 +111,11 @@ end
109
111
 
110
112
  ### Exception Handlers
111
113
 
112
- Use exception handlers are called on non-fault standard error based exceptions.
114
+ Register handlers that run when non-fault exceptions occur.
115
+
116
+ !!! tip
113
117
 
114
- > [!TIP]
115
- > Use exception handlers to send errors to your APM of choice.
118
+ Use exception handlers to send errors to your APM of choice.
116
119
 
117
120
  ```ruby
118
121
  CMDx.configure do |config|
@@ -136,7 +139,7 @@ end
136
139
 
137
140
  ### Middlewares
138
141
 
139
- See the [Middelwares](#https://github.com/drexed/cmdx/blob/main/docs/middlewares.md#declarations) docs for task level configurations.
142
+ See the [Middlewares](https://github.com/drexed/cmdx/blob/main/docs/middlewares.md#declarations) docs for task level configurations.
140
143
 
141
144
  ```ruby
142
145
  CMDx.configure do |config|
@@ -160,12 +163,13 @@ CMDx.configure do |config|
160
163
  end
161
164
  ```
162
165
 
163
- > [!NOTE]
164
- > Middlewares are executed in registration order. Each middleware wraps the next, creating an execution chain around task logic.
166
+ !!! note
167
+
168
+ Middlewares are executed in registration order. Each middleware wraps the next, creating an execution chain around task logic.
165
169
 
166
170
  ### Callbacks
167
171
 
168
- See the [Callbacks](#https://github.com/drexed/cmdx/blob/main/docs/callbacks.md#declarations) docs for task level configurations.
172
+ See the [Callbacks](https://github.com/drexed/cmdx/blob/main/docs/callbacks.md#declarations) docs for task level configurations.
169
173
 
170
174
  ```ruby
171
175
  CMDx.configure do |config|
@@ -191,7 +195,7 @@ end
191
195
 
192
196
  ### Coercions
193
197
 
194
- See the [Attributes - Coercions](#https://github.com/drexed/cmdx/blob/main/docs/attributes/coercions.md#declarations) docs for task level configurations.
198
+ See the [Attributes - Coercions](https://github.com/drexed/cmdx/blob/main/docs/attributes/coercions.md#declarations) docs for task level configurations.
195
199
 
196
200
  ```ruby
197
201
  CMDx.configure do |config|
@@ -217,7 +221,7 @@ end
217
221
 
218
222
  ### Validators
219
223
 
220
- See the [Attributes - Validations](#https://github.com/drexed/cmdx/blob/main/docs/attributes/validations.md#declarations) docs for task level configurations.
224
+ See the [Attributes - Validations](https://github.com/drexed/cmdx/blob/main/docs/attributes/validations.md#declarations) docs for task level configurations.
221
225
 
222
226
  ```ruby
223
227
  CMDx.configure do |config|
@@ -264,7 +268,8 @@ class GenerateInvoice < CMDx::Task
264
268
  deprecated: true, # Task deprecations
265
269
  retries: 3, # Non-fault exception retries
266
270
  retry_on: [External::ApiError], # List of exceptions to retry on
267
- retry_jitter: 1 # Space between retry iteration, eg: current retry num + 1
271
+ retry_jitter: 1, # Space between retry iteration, eg: current retry num + 1
272
+ rollback_on: ["failed", "skipped"], # Rollback on override
268
273
  )
269
274
 
270
275
  def work
@@ -273,13 +278,13 @@ class GenerateInvoice < CMDx::Task
273
278
  end
274
279
  ```
275
280
 
276
- > [!IMPORTANT]
277
- > Retries reuse the same context when executing its work. By default all `StandardErrors` will be retried if no `retry_on` option is passed.
281
+ !!! warning "Important"
282
+
283
+ Retries reuse the same context. By default, all `StandardError` exceptions (including faults) are retried unless you specify `retry_on` option for specific matches.
278
284
 
279
285
  ### Registrations
280
286
 
281
- Register middlewares, callbacks, coercions, and validators on a specific task.
282
- Deregister options that should not be available.
287
+ Register or deregister middlewares, callbacks, coercions, and validators for specific tasks:
283
288
 
284
289
  ```ruby
285
290
  class SendCampaignEmail < CMDx::Task
@@ -331,8 +336,9 @@ end
331
336
 
332
337
  ### Resetting
333
338
 
334
- > [!WARNING]
335
- > Resetting configuration affects the entire application. Use primarily in test environments or during application initialization.
339
+ !!! warning
340
+
341
+ Resetting affects your entire application. Use this primarily in test environments.
336
342
 
337
343
  ```ruby
338
344
  # Reset to framework defaults
@@ -369,21 +375,26 @@ class ModerateBlogPost < CMDx::Task
369
375
  end
370
376
  ```
371
377
 
372
- > [!TIP]
373
- > Use **present tense verbs + noun** for task names, eg: `ModerateBlogPost`, `ScheduleAppointment`, `ValidateDocument`
378
+ !!! tip
374
379
 
375
- ---
380
+ Use **present tense verbs + noun** for task names, eg: `ModerateBlogPost`, `ScheduleAppointment`, `ValidateDocument`
376
381
 
377
- url: https://github.com/drexed/cmdx/blob/main/docs/basics/setup.md
378
- ---
382
+ ## Type safety
383
+
384
+ CMDx includes built-in RBS (Ruby Type Signature) inline annotations throughout the codebase, providing type information for static analysis and editor support.
385
+
386
+ - **Type checking** — Catch type errors before runtime using tools like Steep or TypeProf
387
+ - **Better IDE support** — Enhanced autocomplete, navigation, and inline documentation
388
+ - **Self-documenting code** — Clear method signatures and return types
389
+ - **Refactoring confidence** — Type-aware refactoring reduces bugs
379
390
 
380
391
  # Basics - Setup
381
392
 
382
- Tasks are the core building blocks of CMDx, encapsulating business logic within structured, reusable objects. Each task represents a unit of work with automatic attribute validation, error handling, and execution tracking.
393
+ Tasks are the heart of CMDx—self-contained units of business logic with built-in validation, error handling, and execution tracking.
383
394
 
384
395
  ## Structure
385
396
 
386
- Tasks inherit from `CMDx::Task` and require only a `work` method:
397
+ Tasks need only two things: inherit from `CMDx::Task` and define a `work` method:
387
398
 
388
399
  ```ruby
389
400
  class ValidateDocument < CMDx::Task
@@ -393,7 +404,7 @@ class ValidateDocument < CMDx::Task
393
404
  end
394
405
  ```
395
406
 
396
- An exception will be raised if a work method is not defined.
407
+ Without a `work` method, execution raises `CMDx::UndefinedMethodError`.
397
408
 
398
409
  ```ruby
399
410
  class IncompleteTask < CMDx::Task
@@ -403,10 +414,25 @@ end
403
414
  IncompleteTask.execute #=> raises CMDx::UndefinedMethodError
404
415
  ```
405
416
 
417
+ ## Rollback
418
+
419
+ Undo any operations linked to the given status, helping to restore a pristine state.
420
+
421
+ ```ruby
422
+ class ValidateDocument < CMDx::Task
423
+ def work
424
+ # Your logic here...
425
+ end
426
+
427
+ def rollback
428
+ # Your undo logic...
429
+ end
430
+ end
431
+ ```
432
+
406
433
  ## Inheritance
407
434
 
408
- All configuration options are inheritable by any child classes.
409
- Create a base class to share common configuration across tasks:
435
+ Share configuration across tasks using inheritance:
410
436
 
411
437
  ```ruby
412
438
  class ApplicationTask < CMDx::Task
@@ -432,10 +458,11 @@ end
432
458
 
433
459
  ## Lifecycle
434
460
 
435
- Tasks follow a predictable call pattern with specific states and statuses:
461
+ Tasks follow a predictable execution pattern:
462
+
463
+ !!! danger "Caution"
436
464
 
437
- > [!CAUTION]
438
- > Tasks are single-use objects. Once executed, they are frozen and cannot be executed again.
465
+ Tasks are single-use objects. Once executed, they're frozen and immutable.
439
466
 
440
467
  | Stage | State | Status | Description |
441
468
  |-------|-------|--------|-------------|
@@ -444,20 +471,15 @@ Tasks follow a predictable call pattern with specific states and statuses:
444
471
  | **Execution** | `executing` | `success`/`failed`/`skipped` | `work` method runs |
445
472
  | **Completion** | `executed` | `success`/`failed`/`skipped` | Result finalized |
446
473
  | **Freezing** | `executed` | `success`/`failed`/`skipped` | Task becomes immutable |
447
-
448
- ---
449
-
450
- url: https://github.com/drexed/cmdx/blob/main/docs/basics/execution.md
451
- ---
474
+ | **Rollback** | `executed` | `failed`/`skipped` | Work undone |
452
475
 
453
476
  # Basics - Execution
454
477
 
455
- Task execution in CMDx provides two distinct methods that handle success and halt scenarios differently. Understanding when to use each method is crucial for proper error handling and control flow in your application workflows.
478
+ CMDx offers two execution methods with different error handling approaches. Choose based on your needs: safe result handling or exception-based control flow.
456
479
 
457
- ## Methods Overview
480
+ ## Execution Methods
458
481
 
459
- Tasks are single-use objects. Once executed, they are frozen and cannot be executed again.
460
- Create a new instance for subsequent executions.
482
+ Both methods return results, but handle failures differently:
461
483
 
462
484
  | Method | Returns | Exceptions | Use Case |
463
485
  |--------|---------|------------|----------|
@@ -466,10 +488,7 @@ Create a new instance for subsequent executions.
466
488
 
467
489
  ## Non-bang Execution
468
490
 
469
- The `execute` method always returns a `CMDx::Result` object regardless of execution outcome.
470
- This is the preferred method for most use cases.
471
-
472
- Any unhandled exceptions will be caught and returned as a task failure.
491
+ Always returns a `CMDx::Result`, never raises exceptions. Perfect for most use cases.
473
492
 
474
493
  ```ruby
475
494
  result = CreateAccount.execute(email: "user@example.com")
@@ -487,23 +506,22 @@ result.status #=> "success"
487
506
 
488
507
  ## Bang Execution
489
508
 
490
- The bang `execute!` method raises a `CMDx::Fault` based exception when tasks fail or are skipped, and returns a `CMDx::Result` object only on success.
491
-
492
- It raises any unhandled non-fault exceptions caused during execution.
509
+ Raises `CMDx::Fault` exceptions on failure or skip. Returns results only on success.
493
510
 
494
511
  | Exception | Raised When |
495
512
  |-----------|-------------|
496
513
  | `CMDx::FailFault` | Task execution fails |
497
514
  | `CMDx::SkipFault` | Task execution is skipped |
498
515
 
499
- > [!IMPORTANT]
500
- > `execute!` behavior depends on the `task_breakpoints` or `workflow_breakpoints` configuration. By default, it raises exceptions only on failures.
516
+ !!! warning "Important"
517
+
518
+ Behavior depends on `task_breakpoints` or `workflow_breakpoints` config. Default: only failures raise exceptions.
501
519
 
502
520
  ```ruby
503
521
  begin
504
522
  result = CreateAccount.execute!(email: "user@example.com")
505
523
  SendWelcomeEmail.execute(result.context)
506
- rescue CMDx::Fault => e
524
+ rescue CMDx::FailFault => e
507
525
  ScheduleAccountRetryJob.perform_later(e.result.context.email)
508
526
  rescue CMDx::SkipFault => e
509
527
  Rails.logger.info("Account creation skipped: #{e.result.reason}")
@@ -525,7 +543,7 @@ task.id #=> "abc123..." (unique task ID)
525
543
  task.context.email #=> "user@example.com"
526
544
  task.context.send_welcome #=> true
527
545
  task.result.state #=> "initialized"
528
- result.status #=> "success"
546
+ task.result.status #=> "success"
529
547
 
530
548
  # Manual execution
531
549
  task.execute
@@ -550,19 +568,15 @@ result.chain #=> Task execution chain
550
568
  # Context and metadata
551
569
  result.context #=> Context with all task data
552
570
  result.metadata #=> Hash with execution metadata
553
-
554
- ---
555
-
556
- url: https://github.com/drexed/cmdx/blob/main/docs/basics/context.md
557
- ---
571
+ ```
558
572
 
559
573
  # Basics - Context
560
574
 
561
- Task context provides flexible data storage, access, and sharing within task execution. It serves as the primary data container for all task inputs, intermediate results, and outputs.
575
+ Context is your data container for inputs, intermediate values, and outputs. It makes sharing data between tasks effortless.
562
576
 
563
577
  ## Assigning Data
564
578
 
565
- Context is automatically populated with all inputs passed to a task. All keys are normalized to symbols for consistent access:
579
+ Context automatically captures all task inputs, normalizing keys to symbols:
566
580
 
567
581
  ```ruby
568
582
  # Direct execution
@@ -572,12 +586,13 @@ CalculateShipping.execute(weight: 2.5, destination: "CA")
572
586
  CalculateShipping.new(weight: 2.5, "destination" => "CA")
573
587
  ```
574
588
 
575
- > [!IMPORTANT]
576
- > String keys are automatically converted to symbols. Use symbols for consistency in your code.
589
+ !!! warning "Important"
590
+
591
+ String keys convert to symbols automatically. Prefer symbols for consistency.
577
592
 
578
593
  ## Accessing Data
579
594
 
580
- Context provides multiple access patterns with automatic nil safety:
595
+ Access context data using method notation, hash keys, or safe accessors:
581
596
 
582
597
  ```ruby
583
598
  class CalculateShipping < CMDx::Task
@@ -600,8 +615,9 @@ class CalculateShipping < CMDx::Task
600
615
  end
601
616
  ```
602
617
 
603
- > [!IMPORTANT]
604
- > Accessing undefined context attributes returns `nil` instead of raising errors, enabling graceful handling of optional attributes.
618
+ !!! warning "Important"
619
+
620
+ Undefined attributes return `nil` instead of raising errors—perfect for optional data.
605
621
 
606
622
  ## Modifying Context
607
623
 
@@ -642,12 +658,13 @@ class CalculateShipping < CMDx::Task
642
658
  end
643
659
  ```
644
660
 
645
- > [!TIP]
646
- > Use context for both input values and intermediate results. This creates natural data flow through your task execution pipeline.
661
+ !!! tip
662
+
663
+ Use context for both input values and intermediate results. This creates natural data flow through your task execution pipeline.
647
664
 
648
665
  ## Data Sharing
649
666
 
650
- Context enables seamless data flow between related tasks in complex workflows:
667
+ Share context across tasks for seamless data flow:
651
668
 
652
669
  ```ruby
653
670
  # During execution
@@ -675,21 +692,17 @@ result = CalculateShipping.execute(destination: "New York, NY")
675
692
  CreateShippingLabel.execute(result)
676
693
  ```
677
694
 
678
- ---
679
-
680
- url: https://github.com/drexed/cmdx/blob/main/docs/basics/chain.md
681
- ---
682
-
683
695
  # Basics - Chain
684
696
 
685
- Chains automatically group related task executions within a thread, providing unified tracking, correlation, and execution context management. Each thread maintains its own chain through thread-local storage, eliminating the need for manual coordination.
697
+ Chains automatically track related task executions within a thread. Think of them as execution traces that help you understand what happened and in what order.
686
698
 
687
699
  ## Management
688
700
 
689
- Each thread maintains its own chain context through thread-local storage, providing automatic isolation without manual coordination.
701
+ Each thread maintains its own isolated chain using thread-local storage.
690
702
 
691
- > [!WARNING]
692
- > Chain operations are thread-local. Never share chain references across threads as this can lead to race conditions and data corruption.
703
+ !!! warning
704
+
705
+ Chains are thread-local. Don't share chain references across threads—it causes race conditions.
693
706
 
694
707
  ```ruby
695
708
  # Thread A
@@ -711,10 +724,11 @@ CMDx::Chain.clear #=> Clears current thread's chain
711
724
 
712
725
  ## Links
713
726
 
714
- Every task execution automatically creates or joins the current thread's chain:
727
+ Tasks automatically create or join the current thread's chain:
728
+
729
+ !!! warning "Important"
715
730
 
716
- > [!IMPORTANT]
717
- > Chain creation is automatic and transparent. You don't need to manually manage chain lifecycle.
731
+ Chain management is automatic—no manual lifecycle handling needed.
718
732
 
719
733
  ```ruby
720
734
  class ImportDataset < CMDx::Task
@@ -737,7 +751,7 @@ end
737
751
 
738
752
  ## Inheritance
739
753
 
740
- When tasks call subtasks within the same thread, all executions automatically inherit the current chain, creating a unified execution trail.
754
+ Subtasks automatically inherit the current thread's chain, building a unified execution trail:
741
755
 
742
756
  ```ruby
743
757
  class ImportDataset < CMDx::Task
@@ -762,10 +776,11 @@ chain.results.map { |r| r.task.class }
762
776
 
763
777
  ## Structure
764
778
 
765
- Chains provide comprehensive execution information with state delegation:
779
+ Chains expose comprehensive execution information:
780
+
781
+ !!! warning "Important"
766
782
 
767
- > [!IMPORTANT]
768
- > Chain state always reflects the first (outer-most) task result, not individual subtask outcomes. Subtasks maintain their own success/failure states.
783
+ Chain state reflects the first (outermost) task result. Subtasks maintain their own states.
769
784
 
770
785
  ```ruby
771
786
  result = ImportDataset.execute(dataset_id: 456)
@@ -786,21 +801,17 @@ chain.results.each_with_index do |result, index|
786
801
  end
787
802
  ```
788
803
 
789
- ---
790
-
791
- url: https://github.com/drexed/cmdx/blob/main/docs/interruptions/halt.md
792
- ---
793
-
794
804
  # Interruptions - Halt
795
805
 
796
- Halting stops task execution with explicit intent signaling. Tasks provide two primary halt methods that control execution flow and result in different outcomes.
806
+ Stop task execution intentionally using `skip!` or `fail!`. Both methods signal clear intent about why execution stopped.
797
807
 
798
808
  ## Skipping
799
809
 
800
- `skip!` communicates that the task is to be intentionally bypassed. This represents a controlled, intentional interruption where the task determines that execution is not necessary or appropriate.
810
+ Use `skip!` when the task doesn't need to run. It's a no-op, not an error.
811
+
812
+ !!! warning "Important"
801
813
 
802
- > [!IMPORTANT]
803
- > Skipping is a no-op, not a failure or error and are considered successful outcomes.
814
+ Skipped tasks are considered "good" outcomes—they succeeded by doing nothing.
804
815
 
805
816
  ```ruby
806
817
  class ProcessInventory < CMDx::Task
@@ -835,7 +846,7 @@ result.reason #=> "Warehouse closed"
835
846
 
836
847
  ## Failing
837
848
 
838
- `fail!` communicates that the task encountered an impediment that prevents successful completion. This represents controlled failure where the task explicitly determines that execution cannot continue.
849
+ Use `fail!` when the task can't complete successfully. It signals controlled, intentional failure:
839
850
 
840
851
  ```ruby
841
852
  class ProcessRefund < CMDx::Task
@@ -870,7 +881,7 @@ result.reason #=> "Refund period has expired"
870
881
 
871
882
  ## Metadata Enrichment
872
883
 
873
- Both halt methods accept metadata to provide additional context about the interruption. Metadata is stored as a hash and becomes available through the result object.
884
+ Enrich halt calls with metadata for better debugging and error handling:
874
885
 
875
886
  ```ruby
876
887
  class ProcessRenewal < CMDx::Task
@@ -970,7 +981,7 @@ end
970
981
 
971
982
  ## Best Practices
972
983
 
973
- Always try to provide a `reason` when using halt methods. This provides clear context for debugging and creates meaningful exception messages.
984
+ Always provide a reason for better debugging and clearer exception messages:
974
985
 
975
986
  ```ruby
976
987
  # Good: Clear, specific reason
@@ -988,10 +999,11 @@ fail! #=> "Unspecified"
988
999
 
989
1000
  ## Manual Errors
990
1001
 
991
- There are rare cases where you need to manually assign errors.
1002
+ For rare cases, manually add errors before halting:
992
1003
 
993
- > [!IMPORTANT]
994
- > Keep in mind you will still need to initiate a fault if a stoppage of work is required.
1004
+ !!! warning "Important"
1005
+
1006
+ Manual errors don't stop execution—you still need to call `fail!` or `skip!`.
995
1007
 
996
1008
  ```ruby
997
1009
  class ProcessRenewal < CMDx::Task
@@ -1006,14 +1018,9 @@ class ProcessRenewal < CMDx::Task
1006
1018
  end
1007
1019
  ```
1008
1020
 
1009
- ---
1010
-
1011
- url: https://github.com/drexed/cmdx/blob/main/docs/interruptions/faults.md
1012
- ---
1013
-
1014
1021
  # Interruptions - Faults
1015
1022
 
1016
- Faults are exception mechanisms that halt task execution via `skip!` and `fail!` methods. When tasks execute with the `execute!` method, fault exceptions matching the task's interruption status are raised, enabling sophisticated exception handling and control flow patterns.
1023
+ Faults are exceptions raised by `execute!` when tasks halt. They carry rich context about execution state, enabling sophisticated error handling patterns.
1017
1024
 
1018
1025
  ## Fault Types
1019
1026
 
@@ -1023,8 +1030,9 @@ Faults are exception mechanisms that halt task execution via `skip!` and `fail!`
1023
1030
  | `CMDx::SkipFault` | `skip!` method | Optional processing, early returns |
1024
1031
  | `CMDx::FailFault` | `fail!` method | Validation errors, processing failures |
1025
1032
 
1026
- > [!IMPORTANT]
1027
- > All fault exceptions inherit from `CMDx::Fault` and provide access to the complete task execution context including result, task, context, and chain information.
1033
+ !!! warning "Important"
1034
+
1035
+ All faults inherit from `CMDx::Fault` and expose result, task, context, and chain data.
1028
1036
 
1029
1037
  ## Fault Handling
1030
1038
 
@@ -1045,7 +1053,7 @@ end
1045
1053
 
1046
1054
  ## Data Access
1047
1055
 
1048
- Faults provide comprehensive access to execution context, eg:
1056
+ Access rich execution data from fault exceptions:
1049
1057
 
1050
1058
  ```ruby
1051
1059
  begin
@@ -1074,7 +1082,7 @@ end
1074
1082
 
1075
1083
  ### Task-Specific Matching
1076
1084
 
1077
- Use `for?` to handle faults only from specific task classes, enabling targeted exception handling in complex workflows.
1085
+ Handle faults only from specific tasks using `for?`:
1078
1086
 
1079
1087
  ```ruby
1080
1088
  begin
@@ -1104,7 +1112,7 @@ end
1104
1112
 
1105
1113
  ## Fault Propagation
1106
1114
 
1107
- Use `throw!` to propagate failures while preserving fault context and maintaining the error chain for debugging.
1115
+ Propagate failures with `throw!` to preserve context and maintain the error chain:
1108
1116
 
1109
1117
  ### Basic Propagation
1110
1118
 
@@ -1151,7 +1159,7 @@ end
1151
1159
 
1152
1160
  ## Chain Analysis
1153
1161
 
1154
- Results provide methods to analyze fault propagation and identify original failure sources in complex execution chains.
1162
+ Trace fault origins and propagation through the execution chain:
1155
1163
 
1156
1164
  ```ruby
1157
1165
  result = DocumentWorkflow.execute(invalid_data)
@@ -1180,23 +1188,19 @@ if result.failed?
1180
1188
  end
1181
1189
  ```
1182
1190
 
1183
- ---
1184
-
1185
- url: https://github.com/drexed/cmdx/blob/main/docs/interruptions/exceptions.md
1186
- ---
1187
-
1188
1191
  # Interruptions - Exceptions
1189
1192
 
1190
- CMDx provides robust exception handling that differs between the `execute` and `execute!` methods. Understanding how unhandled exceptions are processed is crucial for building reliable task execution flows and implementing proper error handling strategies.
1193
+ Exception handling differs between `execute` and `execute!`. Choose the method that matches your error handling strategy.
1191
1194
 
1192
1195
  ## Exception Handling
1193
1196
 
1194
- > [!IMPORTANT]
1195
- > When designing tasks try not to `raise` your own exceptions directly, instead use `skip!` or `fail!` to signal intent clearly.
1197
+ !!! warning "Important"
1198
+
1199
+ Prefer `skip!` and `fail!` over raising exceptions—they signal intent more clearly.
1196
1200
 
1197
1201
  ### Non-bang execution
1198
1202
 
1199
- The `execute` method captures **all** unhandled exceptions and converts them to failed results, ensuring predictable behavior and consistent result processing.
1203
+ Captures all exceptions and returns them as failed results:
1200
1204
 
1201
1205
  ```ruby
1202
1206
  class CompressDocument < CMDx::Task
@@ -1214,12 +1218,13 @@ result.reason #=> "[ActiveRecord::NotFoundError] record not found"
1214
1218
  result.cause #=> <ActiveRecord::NotFoundError>
1215
1219
  ```
1216
1220
 
1217
- > [!NOTE]
1218
- > The `exception_handler` setting only works with non-bang execution as it catches all exceptions preventing them from reaching your apps global error handler.
1221
+ !!! note
1222
+
1223
+ Use `exception_handler` with `execute` to send exceptions to APM tools before they become failed results.
1219
1224
 
1220
1225
  ### Bang execution
1221
1226
 
1222
- The `execute!` method allows unhandled exceptions to propagate, enabling standard Ruby exception handling while respecting CMDx fault configuration.
1227
+ Lets exceptions propagate naturally for standard Ruby error handling:
1223
1228
 
1224
1229
  ```ruby
1225
1230
  class CompressDocument < CMDx::Task
@@ -1236,21 +1241,17 @@ rescue ActiveRecord::NotFoundError => e
1236
1241
  end
1237
1242
  ```
1238
1243
 
1239
- ---
1240
-
1241
- url: https://github.com/drexed/cmdx/blob/main/docs/outcomes/result.md
1242
- ---
1243
-
1244
1244
  # Outcomes - Result
1245
1245
 
1246
- The result object is the comprehensive return value of task execution, providing complete information about the execution outcome, state, timing, and any data produced during the task lifecycle. Results serve as the primary interface for inspecting task execution outcomes and chaining task operations.
1246
+ Results are your window into task execution. They expose everything: outcome, state, timing, context, and metadata.
1247
1247
 
1248
1248
  ## Result Attributes
1249
1249
 
1250
- Every result provides access to essential execution information:
1250
+ Access essential execution information:
1251
+
1252
+ !!! warning "Important"
1251
1253
 
1252
- > [!IMPORTANT]
1253
- > Result objects are immutable after task execution completes and reflect the final state.
1254
+ Results are immutable after execution completes.
1254
1255
 
1255
1256
  ```ruby
1256
1257
  result = BuildApplication.execute(version: "1.2.3")
@@ -1272,7 +1273,7 @@ result.metadata #=> { error_code: "BUILD_TOOL.NOT_FOUND" }
1272
1273
 
1273
1274
  ## Lifecycle Information
1274
1275
 
1275
- Results provide comprehensive methods for checking execution state and status:
1276
+ Check execution state and status with predicate methods:
1276
1277
 
1277
1278
  ```ruby
1278
1279
  result = BuildApplication.execute(version: "1.2.3")
@@ -1294,7 +1295,7 @@ result.bad? #=> false (skipped or failed)
1294
1295
 
1295
1296
  ## Outcome Analysis
1296
1297
 
1297
- Results provide unified outcome determination depending on the fault causal chain:
1298
+ Get a unified outcome string combining state and status:
1298
1299
 
1299
1300
  ```ruby
1300
1301
  result = BuildApplication.execute(version: "1.2.3")
@@ -1304,7 +1305,7 @@ result.outcome #=> "success" (state and status)
1304
1305
 
1305
1306
  ## Chain Analysis
1306
1307
 
1307
- Use these methods to trace the root cause of faults or trace the cause points.
1308
+ Trace fault origins and propagation:
1308
1309
 
1309
1310
  ```ruby
1310
1311
  result = DeploymentWorkflow.execute(app_name: "webapp")
@@ -1345,7 +1346,7 @@ result.chain.results[result.index] == result #=> true
1345
1346
 
1346
1347
  ## Block Yield
1347
1348
 
1348
- Implement conditional logic using a block expression that yields a result for complete encapsulation.
1349
+ Execute code with direct result access:
1349
1350
 
1350
1351
  ```ruby
1351
1352
  BuildApplication.execute(version: "1.2.3") do |result|
@@ -1361,7 +1362,7 @@ end
1361
1362
 
1362
1363
  ## Handlers
1363
1364
 
1364
- Use result handlers for clean, functional-style conditional logic. Handlers return the result object, enabling method chaining and fluent interfaces.
1365
+ Handle outcomes with functional-style methods. Handlers return the result for chaining:
1365
1366
 
1366
1367
  ```ruby
1367
1368
  result = BuildApplication.execute(version: "1.2.3")
@@ -1385,10 +1386,11 @@ result
1385
1386
 
1386
1387
  ## Pattern Matching
1387
1388
 
1388
- Results support Ruby's pattern matching through array and hash deconstruction:
1389
+ Use Ruby 3.0+ pattern matching for elegant outcome handling:
1390
+
1391
+ !!! warning "Important"
1389
1392
 
1390
- > [!IMPORTANT]
1391
- > Pattern matching requires Ruby 3.0+
1393
+ Pattern matching works with both array and hash deconstruction.
1392
1394
 
1393
1395
  ### Array Pattern
1394
1396
 
@@ -1433,17 +1435,9 @@ in { runtime: time } if time > performance_threshold
1433
1435
  end
1434
1436
  ```
1435
1437
 
1436
- ---
1437
-
1438
- url: https://github.com/drexed/cmdx/blob/main/docs/outcomes/states.md
1439
- ---
1440
-
1441
1438
  # Outcomes - States
1442
1439
 
1443
- States represent the execution lifecycle condition of task execution, tracking
1444
- the progress of tasks through their complete execution journey. States provide
1445
- insight into where a task is in its lifecycle and enable lifecycle-based
1446
- decision making and monitoring.
1440
+ States track where a task is in its execution lifecycle—from creation through completion or interruption.
1447
1441
 
1448
1442
  ## Definitions
1449
1443
 
@@ -1467,8 +1461,9 @@ State-Status combinations:
1467
1461
 
1468
1462
  ## Transitions
1469
1463
 
1470
- > [!CAUTION]
1471
- > States are automatically managed during task execution and should **never** be modified manually. State transitions are handled internally by the CMDx framework.
1464
+ !!! danger "Caution"
1465
+
1466
+ States are managed automatically—never modify them manually.
1472
1467
 
1473
1468
  ```ruby
1474
1469
  # Valid state transition flow
@@ -1495,7 +1490,7 @@ result.executed? #=> true (complete OR interrupted)
1495
1490
 
1496
1491
  ## Handlers
1497
1492
 
1498
- Use state-based handlers for lifecycle event handling. The `on_executed` handler is particularly useful for cleanup operations that should run regardless of success, skipped, or failure.
1493
+ Handle lifecycle events with state-based handlers. Use `handle_executed` for cleanup that runs regardless of outcome:
1499
1494
 
1500
1495
  ```ruby
1501
1496
  result = ProcessVideoUpload.execute
@@ -1507,14 +1502,9 @@ result
1507
1502
  .handle_executed { |result| log_upload_metrics(result) }
1508
1503
  ```
1509
1504
 
1510
- ---
1511
-
1512
- url: https://github.com/drexed/cmdx/blob/main/docs/outcomes/statuses.md
1513
- ---
1514
-
1515
1505
  # Outcomes - Statuses
1516
1506
 
1517
- Statuses represent the business outcome of task execution logic, indicating how the task's business logic concluded. Statuses differ from execution states by focusing on the business outcome rather than the technical execution lifecycle. Understanding statuses is crucial for implementing proper business logic branching and error handling.
1507
+ Statuses represent the business outcome—did the task succeed, skip, or fail? This differs from state, which tracks the execution lifecycle.
1518
1508
 
1519
1509
  ## Definitions
1520
1510
 
@@ -1526,8 +1516,9 @@ Statuses represent the business outcome of task execution logic, indicating how
1526
1516
 
1527
1517
  ## Transitions
1528
1518
 
1529
- > [!IMPORTANT]
1530
- > Status transitions are unidirectional and final. Once a task is marked as skipped or failed, it cannot return to success status. Design your business logic accordingly.
1519
+ !!! warning "Important"
1520
+
1521
+ Status transitions are final and unidirectional. Once skipped or failed, tasks can't return to success.
1531
1522
 
1532
1523
  ```ruby
1533
1524
  # Valid status transitions
@@ -1560,7 +1551,7 @@ result.bad? #=> true if skipped OR failed (not success)
1560
1551
 
1561
1552
  ## Handlers
1562
1553
 
1563
- Use status-based handlers for business logic branching. The `on_good` and `on_bad` handlers are particularly useful for handling success/skip vs failed outcomes respectively.
1554
+ Branch business logic with status-based handlers. Use `handle_good` and `handle_bad` for success/skip vs failed outcomes:
1564
1555
 
1565
1556
  ```ruby
1566
1557
  result = ProcessNotification.execute
@@ -1577,19 +1568,15 @@ result
1577
1568
  .handle_bad { |result| track_delivery_failure(result) }
1578
1569
  ```
1579
1570
 
1580
- ---
1581
-
1582
- url: https://github.com/drexed/cmdx/blob/main/docs/attributes/definitions.md
1583
- ---
1584
-
1585
1571
  # Attributes - Definitions
1586
1572
 
1587
- Attributes define the interface between task callers and implementation, enabling automatic validation, type coercion, and method generation. They provide a contract to verify that task execution arguments match expected requirements and structure.
1573
+ Attributes define your task's interface with automatic validation, type coercion, and accessor generation. They're the contract between callers and your business logic.
1588
1574
 
1589
1575
  ## Declarations
1590
1576
 
1591
- > [!TIP]
1592
- > Prefer using the `required` and `optional` alias for `attributes` for brevity and to clearly signal intent.
1577
+ !!! tip
1578
+
1579
+ Prefer using the `required` and `optional` alias for `attributes` for brevity and to clearly signal intent.
1593
1580
 
1594
1581
  ### Optional
1595
1582
 
@@ -1658,7 +1645,7 @@ PublishArticle.execute(
1658
1645
 
1659
1646
  ## Sources
1660
1647
 
1661
- Attributes delegate to accessible objects within the task. The default source is `:context`, but any accessible method or object can serve as an attribute source.
1648
+ Attributes read from any accessible object—not just context. Use sources to pull data from models, services, or any callable:
1662
1649
 
1663
1650
  ### Context
1664
1651
 
@@ -1738,10 +1725,11 @@ end
1738
1725
 
1739
1726
  ## Nesting
1740
1727
 
1741
- Nested attributes enable complex attribute structures where child attributes automatically inherit their parent as the source. This allows validation and access of structured data.
1728
+ Build complex structures with nested attributes. Children inherit their parent as source and support all attribute options:
1742
1729
 
1743
- > [!NOTE]
1744
- > All options available to top-level attributes are available to nested attributes, eg: naming, coercions, and validations
1730
+ !!! note
1731
+
1732
+ Nested attributes support all features: naming, coercions, validations, defaults, and more.
1745
1733
 
1746
1734
  ```ruby
1747
1735
  class ConfigureServer < CMDx::Task
@@ -1794,15 +1782,17 @@ ConfigureServer.execute(
1794
1782
  )
1795
1783
  ```
1796
1784
 
1797
- > [!IMPORTANT]
1798
- > Child attributes are only required when their parent attribute is provided, enabling flexible optional structures.
1785
+ !!! warning "Important"
1786
+
1787
+ Child requirements only apply when the parent is provided—perfect for optional structures.
1799
1788
 
1800
1789
  ## Error Handling
1801
1790
 
1802
- Attribute validation failures result in structured error information with details about each failed attribute.
1791
+ Validation failures provide detailed, structured error messages:
1792
+
1793
+ !!! note
1803
1794
 
1804
- > [!NOTE]
1805
- > Nested attributes are only ever evaluated when the parent attribute is available and valid.
1795
+ Nested attributes are only validated when their parent is present and valid.
1806
1796
 
1807
1797
  ```ruby
1808
1798
  class ConfigureServer < CMDx::Task
@@ -1852,17 +1842,13 @@ result.metadata #=> {
1852
1842
  # }
1853
1843
  ```
1854
1844
 
1855
- ---
1856
-
1857
- url: https://github.com/drexed/cmdx/blob/main/docs/attributes/naming.md
1858
- ---
1859
-
1860
1845
  # Attributes - Naming
1861
1846
 
1862
- Attribute naming provides method name customization to prevent conflicts and enable flexible attribute access patterns. When attributes share names with existing methods or when multiple attributes from different sources have the same name, affixing ensures clean method resolution within tasks.
1847
+ Customize accessor method names to avoid conflicts and improve clarity. Affixing changes only the generated methods—not the original attribute names.
1848
+
1849
+ !!! note
1863
1850
 
1864
- > [!NOTE]
1865
- > Affixing modifies only the generated accessor method names within tasks.
1851
+ Use naming when attributes conflict with existing methods or need better clarity in your code.
1866
1852
 
1867
1853
  ## Prefix
1868
1854
 
@@ -1925,16 +1911,11 @@ end
1925
1911
  ScheduleMaintenance.execute(scheduled_at: DateTime.new(2024, 12, 15, 2, 0, 0))
1926
1912
  ```
1927
1913
 
1928
- ---
1929
-
1930
- url: https://github.com/drexed/cmdx/blob/main/docs/attributes/coercions.md
1931
- ---
1932
-
1933
1914
  # Attributes - Coercions
1934
1915
 
1935
- Attribute coercions automatically convert task arguments to expected types, ensuring type safety while providing flexible input handling. Coercions transform raw input values into the specified types, supporting simple conversions like string-to-integer and complex operations like JSON parsing.
1916
+ Automatically convert inputs to expected types. Coercions handle everything from simple string-to-integer conversions to JSON parsing.
1936
1917
 
1937
- Check out the [Getting Started](https://github.com/drexed/cmdx/blob/main/docs/getting_started.md#coercions) docs for global configuration.
1918
+ See [Global Configuration](https://github.com/drexed/cmdx/blob/main/docs/getting_started.md#coercions) for custom coercion setup.
1938
1919
 
1939
1920
  ## Usage
1940
1921
 
@@ -1965,8 +1946,9 @@ ParseMetrics.execute(
1965
1946
  )
1966
1947
  ```
1967
1948
 
1968
- > [!TIP]
1969
- > Specify multiple coercion types for attributes that could be a variety of value formats. CMDx attempts each type in order until one succeeds.
1949
+ !!! tip
1950
+
1951
+ Specify multiple coercion types for attributes that could be a variety of value formats. CMDx attempts each type in order until one succeeds.
1970
1952
 
1971
1953
  ## Built-in Coercions
1972
1954
 
@@ -1988,8 +1970,9 @@ ParseMetrics.execute(
1988
1970
 
1989
1971
  ## Declarations
1990
1972
 
1991
- > [!IMPORTANT]
1992
- > Coercions must raise a CMDx::CoercionError and its message is used as part of the fault reason and metadata.
1973
+ !!! warning "Important"
1974
+
1975
+ Custom coercions must raise `CMDx::CoercionError` with a descriptive message.
1993
1976
 
1994
1977
  ### Proc or Lambda
1995
1978
 
@@ -2039,10 +2022,11 @@ end
2039
2022
 
2040
2023
  ## Removals
2041
2024
 
2042
- Remove custom coercions when no longer needed:
2025
+ Remove unwanted coercions:
2026
+
2027
+ !!! warning
2043
2028
 
2044
- > [!WARNING]
2045
- > Only one removal operation is allowed per `deregister` call. Multiple removals require separate calls.
2029
+ Each `deregister` call removes one coercion. Use multiple calls for batch removals.
2046
2030
 
2047
2031
  ```ruby
2048
2032
  class TransformCoordinates < CMDx::Task
@@ -2083,16 +2067,11 @@ result.metadata #=> {
2083
2067
  # }
2084
2068
  ```
2085
2069
 
2086
- ---
2087
-
2088
- url: https://github.com/drexed/cmdx/blob/main/docs/attributes/validations.md
2089
- ---
2090
-
2091
2070
  # Attributes - Validations
2092
2071
 
2093
- Attribute validations ensure task arguments meet specified requirements before execution begins. Validations run after coercions and provide declarative rules for data integrity, supporting both built-in validators and custom validation logic.
2072
+ Ensure inputs meet requirements before execution. Validations run after coercions, giving you declarative data integrity checks.
2094
2073
 
2095
- Check out the [Getting Started](https://github.com/drexed/cmdx/blob/main/docs/getting_started.md#validations) docs for global configuration.
2074
+ See [Global Configuration](https://github.com/drexed/cmdx/blob/main/docs/getting_started.md#validators) for custom validator setup.
2096
2075
 
2097
2076
  ## Usage
2098
2077
 
@@ -2128,8 +2107,9 @@ ProcessSubscription.execute(
2128
2107
  )
2129
2108
  ```
2130
2109
 
2131
- > [!TIP]
2132
- > Validations run after coercions, so you can validate the final coerced values rather than raw input.
2110
+ !!! tip
2111
+
2112
+ Validations run after coercions, so you can validate the final coerced values rather than raw input.
2133
2113
 
2134
2114
  ## Built-in Validators
2135
2115
 
@@ -2284,8 +2264,9 @@ end
2284
2264
 
2285
2265
  ## Declarations
2286
2266
 
2287
- > [!IMPORTANT]
2288
- > Custom validators must raise a `CMDx::ValidationError` and its message is used as part of the fault reason and metadata.
2267
+ !!! warning "Important"
2268
+
2269
+ Custom validators must raise `CMDx::ValidationError` with a descriptive message.
2289
2270
 
2290
2271
  ### Proc or Lambda
2291
2272
 
@@ -2331,10 +2312,11 @@ end
2331
2312
 
2332
2313
  ## Removals
2333
2314
 
2334
- Remove custom validators when no longer needed:
2315
+ Remove unwanted validators:
2335
2316
 
2336
- > [!WARNING]
2337
- > Only one removal operation is allowed per `deregister` call. Multiple removals require separate calls.
2317
+ !!! warning
2318
+
2319
+ Each `deregister` call removes one validator. Use multiple calls for batch removals.
2338
2320
 
2339
2321
  ```ruby
2340
2322
  class SetupApplication < CMDx::Task
@@ -2344,7 +2326,7 @@ end
2344
2326
 
2345
2327
  ## Error Handling
2346
2328
 
2347
- Validation failures provide detailed error information including attribute paths, validation rules, and specific failure reasons:
2329
+ Validation failures provide detailed, structured error messages:
2348
2330
 
2349
2331
  ```ruby
2350
2332
  class CreateProject < CMDx::Task
@@ -2381,18 +2363,13 @@ result.metadata #=> {
2381
2363
  # }
2382
2364
  ```
2383
2365
 
2384
- ---
2385
-
2386
- url: https://github.com/drexed/cmdx/blob/main/docs/attributes/defaults.md
2387
- ---
2388
-
2389
2366
  # Attributes - Defaults
2390
2367
 
2391
- Attribute defaults provide fallback values when arguments are not provided or resolve to `nil`. Defaults ensure tasks have sensible values for optional attributes while maintaining flexibility for callers to override when needed.
2368
+ Provide fallback values for optional attributes. Defaults kick in when values aren't provided or are `nil`.
2392
2369
 
2393
2370
  ## Declarations
2394
2371
 
2395
- Defaults apply when attributes are not provided or resolve to `nil`. They work seamlessly with coercion, validation, and nested attributes.
2372
+ Defaults work seamlessly with coercions, validations, and nested attributes:
2396
2373
 
2397
2374
  ### Static Values
2398
2375
 
@@ -2452,7 +2429,7 @@ end
2452
2429
 
2453
2430
  ## Coercions and Validations
2454
2431
 
2455
- Defaults are subject to the same coercion and validation rules as provided values, ensuring consistency and catching configuration errors early.
2432
+ Defaults follow the same coercion and validation rules as provided values:
2456
2433
 
2457
2434
  ```ruby
2458
2435
  class ScheduleBackup < CMDx::Task
@@ -2464,14 +2441,9 @@ class ScheduleBackup < CMDx::Task
2464
2441
  end
2465
2442
  ```
2466
2443
 
2467
- ---
2468
-
2469
- url: https://github.com/drexed/cmdx/blob/main/docs/attributes/transformations.md
2470
- ---
2471
-
2472
2444
  # Attributes - Transformations
2473
2445
 
2474
- Transformations allow you to modify attribute values after they are derived and coerced from their source but before any validations. This enables data normalization, formatting, and conditional processing within the attribute pipeline.
2446
+ Modify attribute values after coercion but before validation. Perfect for normalization, formatting, and data cleanup.
2475
2447
 
2476
2448
  ## Declarations
2477
2449
 
@@ -2521,7 +2493,7 @@ end
2521
2493
 
2522
2494
  ## Validations
2523
2495
 
2524
- Transformed values are subject to the same validation rules as untransformed values, ensuring consistency and catching configuration errors early.
2496
+ Validations run on transformed values, ensuring data consistency:
2525
2497
 
2526
2498
  ```ruby
2527
2499
  class ScheduleBackup < CMDx::Task
@@ -2533,39 +2505,30 @@ class ScheduleBackup < CMDx::Task
2533
2505
  end
2534
2506
  ```
2535
2507
 
2536
- ---
2537
-
2538
- - **Prev:** [Attributes - Defaults](defaults.md)
2539
- - **Next:** [Callbacks](../callbacks.md)
2540
-
2541
- ---
2542
-
2543
- url: https://github.com/drexed/cmdx/blob/main/docs/callbacks.md
2544
- ---
2545
-
2546
2508
  # Callbacks
2547
2509
 
2548
- Callbacks provide precise control over task execution lifecycle, running custom logic at specific transition points. Callback callables have access to the same context and result information as the `execute` method, enabling rich integration patterns.
2510
+ Run custom logic at specific points during task execution. Callbacks have full access to task context and results, making them perfect for logging, notifications, cleanup, and more.
2549
2511
 
2550
- Check out the [Getting Started](https://github.com/drexed/cmdx/blob/main/docs/getting_started.md#callbacks) docs for global configuration.
2512
+ See [Global Configuration](https://github.com/drexed/cmdx/blob/main/docs/getting_started.md#callbacks) for framework-wide callback setup.
2551
2513
 
2552
- > [!IMPORTANT]
2553
- > Callbacks execute in the order they are declared within each hook type. Multiple callbacks of the same type execute in declaration order (FIFO: first in, first out).
2514
+ !!! warning "Important"
2515
+
2516
+ Callbacks execute in declaration order (FIFO). Multiple callbacks of the same type run sequentially.
2554
2517
 
2555
2518
  ## Available Callbacks
2556
2519
 
2557
- Callbacks execute in precise lifecycle order. Here is the complete execution sequence:
2520
+ Callbacks execute in a predictable lifecycle order:
2558
2521
 
2559
2522
  ```ruby
2560
2523
  1. before_validation # Pre-validation setup
2561
- 2. before_execution # Setup and preparation
2524
+ 2. before_execution # Prepare for execution
2562
2525
 
2563
- # --- Task#work executed ---
2526
+ # --- Task#work executes ---
2564
2527
 
2565
- 3. on_[complete|interrupted] # Based on execution state
2566
- 4. on_executed # Task finished (any outcome)
2567
- 5. on_[success|skipped|failed] # Based on execution status
2568
- 6. on_[good|bad] # Based on outcome classification
2528
+ 3. on_[complete|interrupted] # State-based (execution lifecycle)
2529
+ 4. on_executed # Always runs after work completes
2530
+ 5. on_[success|skipped|failed] # Status-based (business outcome)
2531
+ 6. on_[good|bad] # Outcome-based (success/skip vs fail)
2569
2532
  ```
2570
2533
 
2571
2534
  ## Declarations
@@ -2617,7 +2580,7 @@ end
2617
2580
 
2618
2581
  ### Class or Module
2619
2582
 
2620
- Implement reusable callback logic in dedicated classes:
2583
+ Implement reusable callback logic in dedicated modules and classes:
2621
2584
 
2622
2585
  ```ruby
2623
2586
  class BookingConfirmationCallback
@@ -2684,10 +2647,11 @@ end
2684
2647
 
2685
2648
  ## Callback Removal
2686
2649
 
2687
- Remove callbacks at runtime for dynamic behavior control:
2650
+ Remove unwanted callbacks dynamically:
2651
+
2652
+ !!! warning "Important"
2688
2653
 
2689
- > [!IMPORTANT]
2690
- > Only one removal operation is allowed per `deregister` call. Multiple removals require separate calls.
2654
+ Each `deregister` call removes one callback. Use multiple calls for batch removals.
2691
2655
 
2692
2656
  ```ruby
2693
2657
  class ProcessBooking < CMDx::Task
@@ -2699,23 +2663,19 @@ class ProcessBooking < CMDx::Task
2699
2663
  end
2700
2664
  ```
2701
2665
 
2702
- ---
2703
-
2704
- url: https://github.com/drexed/cmdx/blob/main/docs/middlewares.md
2705
- ---
2706
-
2707
2666
  # Middlewares
2708
2667
 
2709
- Middleware provides Rack-style wrappers around task execution for cross-cutting concerns like authentication, logging, caching, and error handling.
2668
+ Wrap task execution with middleware for cross-cutting concerns like authentication, caching, timeouts, and monitoring. Think Rack middleware, but for your business logic.
2710
2669
 
2711
- Check out the [Getting Started](https://github.com/drexed/cmdx/blob/main/docs/getting_started.md#middlewares) docs for global configuration.
2670
+ See [Global Configuration](https://github.com/drexed/cmdx/blob/main/docs/getting_started.md#middlewares) for framework-wide setup.
2712
2671
 
2713
- ## Order
2672
+ ## Execution Order
2714
2673
 
2715
- Middleware executes in a nested fashion, creating an onion-like execution pattern:
2674
+ Middleware wraps task execution in layers, like an onion:
2716
2675
 
2717
- > [!NOTE]
2718
- > Middleware executes in the order they are registered, with the first registered middleware being the outermost wrapper.
2676
+ !!! note
2677
+
2678
+ First registered = outermost wrapper. They execute in registration order.
2719
2679
 
2720
2680
  ```ruby
2721
2681
  class ProcessCampaign < CMDx::Task
@@ -2791,10 +2751,11 @@ end
2791
2751
 
2792
2752
  ## Removals
2793
2753
 
2794
- Class and Module based declarations can be removed at a global and task level.
2754
+ Remove class or module-based middleware globally or per-task:
2755
+
2756
+ !!! warning
2795
2757
 
2796
- > [!WARNING]
2797
- > Only one removal operation is allowed per `deregister` call. Multiple removals require separate calls.
2758
+ Each `deregister` call removes one middleware. Use multiple calls for batch removals.
2798
2759
 
2799
2760
  ```ruby
2800
2761
  class ProcessCampaign < CMDx::Task
@@ -2807,7 +2768,7 @@ end
2807
2768
 
2808
2769
  ### Timeout
2809
2770
 
2810
- Ensures task execution doesn't exceed a specified time limit:
2771
+ Prevent tasks from running too long:
2811
2772
 
2812
2773
  ```ruby
2813
2774
  class ProcessReport < CMDx::Task
@@ -2843,7 +2804,7 @@ result.metadata #=> { limit: 3 }
2843
2804
 
2844
2805
  ### Correlate
2845
2806
 
2846
- Tags tasks with a global correlation ID for distributed tracing:
2807
+ Add correlation IDs for distributed tracing and request tracking:
2847
2808
 
2848
2809
  ```ruby
2849
2810
  class ProcessExport < CMDx::Task
@@ -2873,8 +2834,7 @@ result.metadata #=> { correlation_id: "550e8400-e29b-41d4-a716-446655440000" }
2873
2834
 
2874
2835
  ### Runtime
2875
2836
 
2876
- The runtime middleware tags tasks with how long it took to execute the task.
2877
- The calculation uses a monotonic clock and the time is returned in milliseconds.
2837
+ Track task execution time in milliseconds using a monotonic clock:
2878
2838
 
2879
2839
  ```ruby
2880
2840
  class PerformanceMonitoringCheck
@@ -2895,18 +2855,13 @@ result = ProcessExport.execute
2895
2855
  result.metadata #=> { runtime: 1247 } (ms)
2896
2856
  ```
2897
2857
 
2898
- ---
2899
-
2900
- url: https://github.com/drexed/cmdx/blob/main/docs/logging.md
2901
- ---
2902
-
2903
2858
  # Logging
2904
2859
 
2905
- CMDx provides comprehensive automatic logging for task execution with structured data, customizable formatters, and intelligent severity mapping. All task results are logged after completion with rich metadata for debugging and monitoring.
2860
+ CMDx automatically logs every task execution with structured data, making debugging and monitoring effortless. Choose from multiple formatters to match your logging infrastructure.
2906
2861
 
2907
2862
  ## Formatters
2908
2863
 
2909
- CMDx supports multiple log formatters to integrate with various logging systems:
2864
+ Choose the format that works best for your logging system:
2910
2865
 
2911
2866
  | Formatter | Use Case | Output Style |
2912
2867
  |-----------|----------|--------------|
@@ -2936,12 +2891,13 @@ E, [2022-07-17T18:43:15.000000 #3784] ERROR -- BillingWorkflow:
2936
2891
  index=3 chain_id="018c2b95-b764-7615-a924-cc5b910ed1e5" type="Task" class="BillingWorkflow" state="interrupted" status="failed" caused_failure={index: 2, class: "CalculateTax", status: "failed"} threw_failure={index: 1, class: "ValidateCustomer", status: "failed"}
2937
2892
  ```
2938
2893
 
2939
- > [!TIP]
2940
- > Logging can be used as low-level eventing system, ingesting all tasks performed within a small action or long running request. This ie where correlation is especially handy.
2894
+ !!! tip
2895
+
2896
+ Use logging as a low-level event stream to track all tasks in a request. Combine with correlation for powerful distributed tracing.
2941
2897
 
2942
2898
  ## Structure
2943
2899
 
2944
- All log entries include comprehensive execution metadata. Field availability depends on execution context and outcome.
2900
+ Every log entry includes rich metadata. Available fields depend on execution context and outcome.
2945
2901
 
2946
2902
  ### Core Fields
2947
2903
 
@@ -2982,7 +2938,7 @@ All log entries include comprehensive execution metadata. Field availability dep
2982
2938
 
2983
2939
  ## Usage
2984
2940
 
2985
- Tasks have access to the frameworks logger.
2941
+ Access the framework logger directly within tasks:
2986
2942
 
2987
2943
  ```ruby
2988
2944
  class ProcessSubscription < CMDx::Task
@@ -2994,18 +2950,13 @@ class ProcessSubscription < CMDx::Task
2994
2950
  end
2995
2951
  ```
2996
2952
 
2997
- ---
2998
-
2999
- url: https://github.com/drexed/cmdx/blob/main/docs/internationalization.md
3000
- ---
3001
-
3002
2953
  # Internationalization (i18n)
3003
2954
 
3004
- CMDx provides comprehensive internationalization support for all error messages, attribute validation failures, coercion errors, and fault messages. All user-facing text is automatically localized based on the current `I18n.locale`, ensuring your applications can serve global audiences with native-language error reporting.
2955
+ CMDx supports 90+ languages out of the box for all error messages, validations, coercions, and faults. Error messages automatically adapt to the current `I18n.locale`, making it easy to build applications for global audiences.
3005
2956
 
3006
- ## Localization
2957
+ ## Usage
3007
2958
 
3008
- CMDx automatically localizes all error messages based on the `I18n.locale` setting.
2959
+ All error messages are automatically localized based on your current locale:
3009
2960
 
3010
2961
  ```ruby
3011
2962
  class ProcessQuote < CMDx::Task
@@ -3024,11 +2975,11 @@ end
3024
2975
 
3025
2976
  ## Configuration
3026
2977
 
3027
- Localization is handled by the `I18n` gem. In Rails applications, locales are loaded automatically and managed via the `I18n.available_locales` setting.
2978
+ CMDx uses the `I18n` gem for localization. In Rails, locales load automatically.
3028
2979
 
3029
- ### Local Copies
2980
+ ### Copy Locale Files
3030
2981
 
3031
- Execute the following command to copy any locale into the Rails applications `config/locales` directory:
2982
+ Copy locale files to your Rails application's `config/locales` directory:
3032
2983
 
3033
2984
  ```bash
3034
2985
  rails generate cmdx:locale [LOCALE]
@@ -3126,23 +3077,141 @@ rails generate cmdx:locale fr
3126
3077
  - zh-TW - Chinese (Traditional)
3127
3078
  - zh-YUE - Chinese (Yue)
3128
3079
 
3129
- ---
3080
+ # Retries
3081
+
3082
+ CMDx provides automatic retry functionality for tasks that encounter transient failures. This is essential for handling temporary issues like network timeouts, rate limits, or database locks without manual intervention.
3130
3083
 
3131
- url: https://github.com/drexed/cmdx/blob/main/docs/deprecation.md
3132
- ---
3084
+ ## Basic Usage
3085
+
3086
+ Configure retries upto n attempts without any delay.
3087
+
3088
+ ```ruby
3089
+ class FetchExternalData < CMDx::Task
3090
+ settings retries: 3
3091
+
3092
+ def work
3093
+ response = HTTParty.get("https://api.example.com/data")
3094
+ context.data = response.parsed_response
3095
+ end
3096
+ end
3097
+ ```
3098
+
3099
+ When an exception occurs during execution, CMDx automatically retries up to the configured limit.
3100
+
3101
+ ## Selective Retries
3102
+
3103
+ By default, CMDx retries on `StandardError` and its subclasses. Narrow this to specific exception types:
3104
+
3105
+ ```ruby
3106
+ class ProcessPayment < CMDx::Task
3107
+ settings retries: 5, retry_on: [Stripe::RateLimitError, Net::ReadTimeout]
3108
+
3109
+ def work
3110
+ # Your logic here...
3111
+ end
3112
+ end
3113
+ ```
3114
+
3115
+ !!! warning "Important"
3116
+
3117
+ Only exceptions matching the `retry_on` configuration will trigger retries. Uncaught exceptions immediately fail the task.
3118
+
3119
+ ## Retry Jitter
3120
+
3121
+ Add delays between retry attempts to avoid overwhelming external services or to implement exponential backoff strategies.
3122
+
3123
+ ### Fixed Value
3124
+
3125
+ Use a numeric value to calculate linear delay (`jitter * current_retry`):
3126
+
3127
+ ```ruby
3128
+ class ImportRecords < CMDx::Task
3129
+ settings retries: 3, retry_jitter: 0.5
3130
+
3131
+ def work
3132
+ # Delays: 0s, 0.5s (retry 1), 1.0s (retry 2), 1.5s (retry 3)
3133
+ context.records = ExternalAPI.fetch_records
3134
+ end
3135
+ end
3136
+ ```
3137
+
3138
+ ### Symbol References
3139
+
3140
+ Define an instance method for custom delay logic:
3141
+
3142
+ ```ruby
3143
+ class SyncInventory < CMDx::Task
3144
+ settings retries: 5, retry_jitter: :exponential_backoff
3145
+
3146
+ def work
3147
+ context.inventory = InventoryAPI.sync
3148
+ end
3149
+
3150
+ private
3151
+
3152
+ def exponential_backoff(current_retry)
3153
+ 2 ** current_retry # 2s, 4s, 8s, 16s, 32s
3154
+ end
3155
+ end
3156
+ ```
3157
+
3158
+ ### Proc or Lambda
3159
+
3160
+ Pass a proc for inline delay calculations:
3161
+
3162
+ ```ruby
3163
+ class PollJobStatus < CMDx::Task
3164
+ # Proc
3165
+ settings retries: 10, retry_jitter: proc { |retry_count| [retry_count * 0.5, 5.0].min }
3166
+
3167
+ # Lambda
3168
+ settings retries: 10, retry_jitter: ->(retry_count) { [retry_count * 0.5, 5.0].min }
3169
+
3170
+ def work
3171
+ # Delays: 0.5s, 1.0s, 1.5s, 2.0s, 2.5s, 3.0s, 3.5s, 4.0s, 4.5s, 5.0s (capped)
3172
+ context.status = JobAPI.check_status(context.job_id)
3173
+ end
3174
+ end
3175
+ ```
3176
+
3177
+ ### Class or Module
3178
+
3179
+ Implement reusable delay logic in dedicated modules and classes:
3180
+
3181
+ ```ruby
3182
+ class ExponentialBackoff
3183
+ def call(task, retry_count)
3184
+ base_delay = task.context.base_delay || 1.0
3185
+ [base_delay * (2 ** retry_count), 60.0].min
3186
+ end
3187
+ end
3188
+
3189
+ class FetchUserProfile < CMDx::Task
3190
+ # Class or Module
3191
+ settings retries: 4, retry_jitter: ExponentialBackoff
3192
+
3193
+ # Instance
3194
+ settings retries: 4, retry_jitter: ExponentialBackoff.new
3195
+
3196
+ def work
3197
+ # Your logic here...
3198
+ end
3199
+ end
3200
+ ```
3133
3201
 
3134
3202
  # Task Deprecation
3135
3203
 
3136
- Task deprecation provides a systematic approach to managing legacy tasks in CMDx applications. The deprecation system enables controlled migration paths by issuing warnings, logging messages, or preventing execution of deprecated tasks entirely, helping teams maintain code quality while providing clear upgrade paths.
3204
+ Manage legacy tasks gracefully with built-in deprecation support. Choose how to handle deprecated tasks—log warnings for awareness, issue Ruby warnings for development, or prevent execution entirely.
3137
3205
 
3138
3206
  ## Modes
3139
3207
 
3140
3208
  ### Raise
3141
3209
 
3142
- `:raise` mode prevents task execution entirely. Use this for tasks that should no longer be used under any circumstances.
3210
+ Prevent task execution completely. Perfect for tasks that must no longer run.
3211
+
3212
+ !!! warning
3143
3213
 
3144
- > [!WARNING]
3145
- > Use `:raise` mode carefully in production environments as it will break existing workflows immediately.
3214
+ Use `:raise` mode carefully—it will break existing workflows immediately.
3146
3215
 
3147
3216
  ```ruby
3148
3217
  class ProcessObsoleteAPI < CMDx::Task
@@ -3159,7 +3228,7 @@ result = ProcessObsoleteAPI.execute
3159
3228
 
3160
3229
  ### Log
3161
3230
 
3162
- `:log` mode allows continued usage while tracking deprecation warnings. Perfect for gradual migration scenarios where immediate replacement isn't feasible.
3231
+ Allow execution while tracking deprecation in logs. Ideal for gradual migrations.
3163
3232
 
3164
3233
  ```ruby
3165
3234
  class ProcessLegacyFormat < CMDx::Task
@@ -3182,7 +3251,7 @@ result.successful? #=> true
3182
3251
 
3183
3252
  ### Warn
3184
3253
 
3185
- `:warn` mode issues Ruby warnings visible in development and testing environments. Useful for alerting developers without affecting production logging.
3254
+ Issue Ruby warnings visible during development and testing. Keeps production logs clean while alerting developers.
3186
3255
 
3187
3256
  ```ruby
3188
3257
  class ProcessOldData < CMDx::Task
@@ -3276,21 +3345,17 @@ class OutdatedConnector < CMDx::Task
3276
3345
  end
3277
3346
  ```
3278
3347
 
3279
- ---
3280
-
3281
- url: https://github.com/drexed/cmdx/blob/main/docs/workflows.md
3282
- ---
3283
-
3284
3348
  # Workflows
3285
3349
 
3286
- Workflow orchestrates sequential execution of multiple tasks in a linear pipeline. Workflows provide a declarative DSL for composing complex business logic from individual task components, with support for conditional execution, context propagation, and configurable halt behavior.
3350
+ Compose multiple tasks into powerful, sequential pipelines. Workflows provide a declarative way to build complex business processes with conditional execution, shared context, and flexible error handling.
3287
3351
 
3288
3352
  ## Declarations
3289
3353
 
3290
- Tasks execute sequentially in declaration order (FIFO). The workflow context propagates to each task, allowing access to data from previous executions.
3354
+ Tasks run in declaration order (FIFO), sharing a common context across the pipeline.
3355
+
3356
+ !!! warning
3291
3357
 
3292
- > [!IMPORTANT]
3293
- > Do **NOT** define a `work` method in workflow tasks. The included module automatically provides the execution logic.
3358
+ Don't define a `work` method in workflows—the module handles execution automatically.
3294
3359
 
3295
3360
  ### Task
3296
3361
 
@@ -3305,15 +3370,17 @@ class OnboardingWorkflow < CMDx::Task
3305
3370
  end
3306
3371
  ```
3307
3372
 
3308
- > [!TIP]
3309
- > Execute tasks in parallel via the [cmdx-parallel](https://github.com/drexed/cmdx-parallel) gem.
3373
+ !!! tip
3374
+
3375
+ Execute tasks in parallel via the [cmdx-parallel](https://github.com/drexed/cmdx-parallel) gem.
3310
3376
 
3311
3377
  ### Group
3312
3378
 
3313
- Group related tasks for better organization and shared configuration:
3379
+ Group related tasks to share configuration:
3314
3380
 
3315
- > [!IMPORTANT]
3316
- > Settings and conditionals for a group apply to all tasks within that group.
3381
+ !!! warning "Important"
3382
+
3383
+ Settings and conditionals apply to all tasks in the group.
3317
3384
 
3318
3385
  ```ruby
3319
3386
  class ContentModerationWorkflow < CMDx::Task
@@ -3376,9 +3443,7 @@ end
3376
3443
 
3377
3444
  ## Halt Behavior
3378
3445
 
3379
- By default skipped tasks are considered no-op executions and does not stop workflow execution.
3380
- This is configurable via global and task level breakpoint settings. Task and group configurations
3381
- can be used together within a workflow.
3446
+ By default, skipped tasks don't stop the workflow—they're treated as no-ops. Configure breakpoints globally or per-task to customize this behavior.
3382
3447
 
3383
3448
  ```ruby
3384
3449
  class AnalyticsWorkflow < CMDx::Task
@@ -3434,7 +3499,7 @@ end
3434
3499
 
3435
3500
  ## Nested Workflows
3436
3501
 
3437
- Workflows can task other workflows for hierarchical composition:
3502
+ Build hierarchical workflows by composing workflows within workflows:
3438
3503
 
3439
3504
  ```ruby
3440
3505
  class EmailPreparationWorkflow < CMDx::Task
@@ -3461,10 +3526,11 @@ end
3461
3526
 
3462
3527
  ## Parallel Execution
3463
3528
 
3464
- Parallel task execution leverages the [Parallel](https://github.com/grosser/parallel) gem, which automatically detects the number of available processors to maximize concurrent task execution.
3529
+ Run tasks concurrently using the [Parallel](https://github.com/grosser/parallel) gem. It automatically uses all available processors for maximum throughput.
3530
+
3531
+ !!! warning
3465
3532
 
3466
- > [!IMPORTANT]
3467
- > Context cannot be modified during parallel execution. Ensure that all required data is preloaded into the context before parallelization begins.
3533
+ Context is read-only during parallel execution. Load all required data beforehand.
3468
3534
 
3469
3535
  ```ruby
3470
3536
  class SendWelcomeNotifications < CMDx::Task
@@ -3502,17 +3568,13 @@ class SendNotifications < CMDx::Task
3502
3568
  end
3503
3569
  ```
3504
3570
 
3505
- > [!TIP]
3506
- > Use **present tense verbs + pluralized noun** for workflow task names, eg: `SendNotifications`, `DownloadFiles`, `ValidateDocuments`
3507
-
3508
- ---
3571
+ !!! tip
3509
3572
 
3510
- url: https://github.com/drexed/cmdx/blob/main/docs/tips_and_tricks.md
3511
- ---
3573
+ Use **present tense verbs + pluralized noun** for workflow task names, eg: `SendNotifications`, `DownloadFiles`, `ValidateDocuments`
3512
3574
 
3513
3575
  # Tips and Tricks
3514
3576
 
3515
- This guide covers advanced patterns and optimization techniques for getting the most out of CMDx in production applications.
3577
+ Best practices, patterns, and techniques to build maintainable CMDx applications.
3516
3578
 
3517
3579
  ## Project Organization
3518
3580
 
@@ -3556,7 +3618,7 @@ class TokenGeneration < CMDx::Task; end # ❌ Avoid
3556
3618
 
3557
3619
  ### Story Telling
3558
3620
 
3559
- Consider using descriptive methods to express the task’s flow, rather than concentrating all logic inside the `work` method.
3621
+ Break down complex logic into descriptive methods that read like a narrative:
3560
3622
 
3561
3623
  ```ruby
3562
3624
  class ProcessOrder < CMDx::Task
@@ -3588,7 +3650,7 @@ end
3588
3650
 
3589
3651
  ### Style Guide
3590
3652
 
3591
- Follow a style pattern for consistent task design:
3653
+ Follow this order for consistent, readable tasks:
3592
3654
 
3593
3655
  ```ruby
3594
3656
  class ExportReport < CMDx::Task
@@ -3631,7 +3693,7 @@ end
3631
3693
 
3632
3694
  ## Attribute Options
3633
3695
 
3634
- Use Rails `with_options` to reduce duplication and improve readability:
3696
+ Use `with_options` to reduce duplication:
3635
3697
 
3636
3698
  ```ruby
3637
3699
  class ConfigureCompany < CMDx::Task
@@ -3657,9 +3719,9 @@ class ConfigureCompany < CMDx::Task
3657
3719
  end
3658
3720
  ```
3659
3721
 
3660
- ## Advance Examples
3722
+ ## More Examples
3661
3723
 
3662
3724
  - [Active Record Query Tagging](https://github.com/drexed/cmdx/blob/main/examples/active_record_query_tagging.md)
3663
3725
  - [Paper Trail Whatdunnit](https://github.com/drexed/cmdx/blob/main/examples/paper_trail_whatdunnit.md)
3726
+ - [Stoplight Circuit Breaker](https://github.com/drexed/cmdx/blob/main/examples/stoplight_circuit_breaker.md)
3664
3727
 
3665
- ---