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.
Files changed (126) hide show
  1. checksums.yaml +4 -4
  2. data/.DS_Store +0 -0
  3. data/.cursor/rules/cursor-instructions.mdc +6 -0
  4. data/.rubocop.yml +16 -1
  5. data/.ruby-version +1 -1
  6. data/CHANGELOG.md +42 -1
  7. data/README.md +72 -25
  8. data/docs/ai_prompts.md +309 -0
  9. data/docs/basics/call.md +225 -14
  10. data/docs/basics/chain.md +271 -0
  11. data/docs/basics/context.md +232 -33
  12. data/docs/basics/setup.md +76 -12
  13. data/docs/callbacks.md +273 -0
  14. data/docs/configuration.md +158 -28
  15. data/docs/getting_started.md +134 -22
  16. data/docs/interruptions/exceptions.md +189 -11
  17. data/docs/interruptions/faults.md +187 -44
  18. data/docs/interruptions/halt.md +179 -35
  19. data/docs/logging.md +194 -53
  20. data/docs/middlewares.md +735 -0
  21. data/docs/outcomes/result.md +296 -10
  22. data/docs/outcomes/states.md +212 -19
  23. data/docs/outcomes/statuses.md +284 -18
  24. data/docs/parameters/coercions.md +402 -29
  25. data/docs/parameters/defaults.md +249 -25
  26. data/docs/parameters/definitions.md +238 -72
  27. data/docs/parameters/namespacing.md +250 -27
  28. data/docs/parameters/validations.md +193 -168
  29. data/docs/testing.md +550 -0
  30. data/docs/tips_and_tricks.md +95 -43
  31. data/docs/workflows.md +319 -0
  32. data/lib/cmdx/.DS_Store +0 -0
  33. data/lib/cmdx/callback.rb +69 -0
  34. data/lib/cmdx/callback_registry.rb +106 -0
  35. data/lib/cmdx/chain.rb +190 -0
  36. data/lib/cmdx/chain_inspector.rb +149 -0
  37. data/lib/cmdx/chain_serializer.rb +175 -0
  38. data/lib/cmdx/coercions/array.rb +37 -0
  39. data/lib/cmdx/coercions/big_decimal.rb +33 -0
  40. data/lib/cmdx/coercions/boolean.rb +41 -1
  41. data/lib/cmdx/coercions/complex.rb +31 -0
  42. data/lib/cmdx/coercions/date.rb +39 -0
  43. data/lib/cmdx/coercions/date_time.rb +39 -0
  44. data/lib/cmdx/coercions/float.rb +31 -0
  45. data/lib/cmdx/coercions/hash.rb +42 -0
  46. data/lib/cmdx/coercions/integer.rb +32 -0
  47. data/lib/cmdx/coercions/rational.rb +31 -0
  48. data/lib/cmdx/coercions/string.rb +31 -0
  49. data/lib/cmdx/coercions/time.rb +39 -0
  50. data/lib/cmdx/coercions/virtual.rb +31 -0
  51. data/lib/cmdx/configuration.rb +217 -9
  52. data/lib/cmdx/context.rb +173 -2
  53. data/lib/cmdx/core_ext/hash.rb +72 -0
  54. data/lib/cmdx/core_ext/module.rb +94 -0
  55. data/lib/cmdx/core_ext/object.rb +105 -0
  56. data/lib/cmdx/correlator.rb +217 -0
  57. data/lib/cmdx/error.rb +210 -8
  58. data/lib/cmdx/errors.rb +256 -1
  59. data/lib/cmdx/fault.rb +177 -2
  60. data/lib/cmdx/faults.rb +158 -2
  61. data/lib/cmdx/immutator.rb +121 -2
  62. data/lib/cmdx/lazy_struct.rb +261 -18
  63. data/lib/cmdx/log_formatters/json.rb +46 -0
  64. data/lib/cmdx/log_formatters/key_value.rb +46 -0
  65. data/lib/cmdx/log_formatters/line.rb +54 -0
  66. data/lib/cmdx/log_formatters/logstash.rb +64 -0
  67. data/lib/cmdx/log_formatters/pretty_json.rb +57 -0
  68. data/lib/cmdx/log_formatters/pretty_key_value.rb +51 -0
  69. data/lib/cmdx/log_formatters/pretty_line.rb +60 -0
  70. data/lib/cmdx/log_formatters/raw.rb +54 -0
  71. data/lib/cmdx/logger.rb +85 -0
  72. data/lib/cmdx/logger_ansi.rb +93 -7
  73. data/lib/cmdx/logger_serializer.rb +116 -0
  74. data/lib/cmdx/middleware.rb +74 -0
  75. data/lib/cmdx/middleware_registry.rb +106 -0
  76. data/lib/cmdx/middlewares/correlate.rb +266 -0
  77. data/lib/cmdx/middlewares/timeout.rb +232 -0
  78. data/lib/cmdx/parameter.rb +228 -1
  79. data/lib/cmdx/parameter_inspector.rb +61 -0
  80. data/lib/cmdx/parameter_registry.rb +125 -0
  81. data/lib/cmdx/parameter_serializer.rb +83 -0
  82. data/lib/cmdx/parameter_validator.rb +62 -0
  83. data/lib/cmdx/parameter_value.rb +109 -1
  84. data/lib/cmdx/parameters_inspector.rb +59 -0
  85. data/lib/cmdx/parameters_serializer.rb +102 -0
  86. data/lib/cmdx/railtie.rb +123 -3
  87. data/lib/cmdx/result.rb +399 -20
  88. data/lib/cmdx/result_ansi.rb +105 -9
  89. data/lib/cmdx/result_inspector.rb +76 -0
  90. data/lib/cmdx/result_logger.rb +90 -3
  91. data/lib/cmdx/result_serializer.rb +137 -0
  92. data/lib/cmdx/rspec/result_matchers.rb +917 -0
  93. data/lib/cmdx/rspec/task_matchers.rb +570 -0
  94. data/lib/cmdx/task.rb +409 -34
  95. data/lib/cmdx/task_serializer.rb +74 -2
  96. data/lib/cmdx/utils/ansi_color.rb +95 -0
  97. data/lib/cmdx/utils/log_timestamp.rb +48 -0
  98. data/lib/cmdx/utils/monotonic_runtime.rb +71 -4
  99. data/lib/cmdx/utils/name_affix.rb +78 -0
  100. data/lib/cmdx/validators/custom.rb +82 -0
  101. data/lib/cmdx/validators/exclusion.rb +94 -0
  102. data/lib/cmdx/validators/format.rb +102 -8
  103. data/lib/cmdx/validators/inclusion.rb +104 -0
  104. data/lib/cmdx/validators/length.rb +128 -0
  105. data/lib/cmdx/validators/numeric.rb +128 -0
  106. data/lib/cmdx/validators/presence.rb +93 -7
  107. data/lib/cmdx/version.rb +7 -1
  108. data/lib/cmdx/workflow.rb +394 -0
  109. data/lib/cmdx.rb +25 -64
  110. data/lib/generators/cmdx/install_generator.rb +37 -1
  111. data/lib/generators/cmdx/task_generator.rb +69 -1
  112. data/lib/generators/cmdx/templates/install.rb +8 -12
  113. data/lib/generators/cmdx/workflow_generator.rb +109 -0
  114. metadata +54 -15
  115. data/docs/basics/run.md +0 -34
  116. data/docs/batch.md +0 -53
  117. data/docs/example.md +0 -82
  118. data/docs/hooks.md +0 -59
  119. data/lib/cmdx/batch.rb +0 -43
  120. data/lib/cmdx/parameters.rb +0 -34
  121. data/lib/cmdx/run.rb +0 -38
  122. data/lib/cmdx/run_inspector.rb +0 -26
  123. data/lib/cmdx/run_serializer.rb +0 -16
  124. data/lib/cmdx/task_hook.rb +0 -18
  125. data/lib/generators/cmdx/batch_generator.rb +0 -30
  126. /data/lib/generators/cmdx/templates/{batch.rb.tt → workflow.rb.tt} +0 -0
@@ -1,17 +1,303 @@
1
- # Outcomes - Result
1
+ # Outcomes - Result
2
2
 
3
- The result object is returned after a task execution. This is the main object
4
- that will be interacted with post call.
3
+ The result object is the comprehensive return value of task execution, providing
4
+ complete information about the execution outcome, state, timing, and any data
5
+ produced during the task lifecycle. Results serve as the primary interface for
6
+ inspecting task execution outcomes and chaining task operations.
7
+
8
+ ## Table of Contents
9
+
10
+ - [Core Result Attributes](#core-result-attributes)
11
+ - [State and Status Information](#state-and-status-information)
12
+ - [Execution Outcome Analysis](#execution-outcome-analysis)
13
+ - [Runtime and Performance](#runtime-and-performance)
14
+ - [Failure Chain Analysis](#failure-chain-analysis)
15
+ - [Index and Position](#index-and-position)
16
+ - [Result Callbacks and Chaining](#result-callbacks-and-chaining)
17
+ - [Pattern Matching](#pattern-matching)
18
+ - [Serialization and Inspection](#serialization-and-inspection)
19
+
20
+ ## Core Result Attributes
21
+
22
+ Every result provides access to essential execution information:
23
+
24
+ ```ruby
25
+ result = ProcessUserOrderTask.call(order_id: 123)
26
+
27
+ # Core objects
28
+ result.task #=> <ProcessUserOrderTask instance>
29
+ result.context #=> <CMDx::Context with all task data>
30
+ result.chain #=> <CMDx::Chain execution tracking>
31
+ result.metadata #=> Hash with execution metadata
32
+
33
+ # Execution information
34
+ result.id #=> "abc123..." (unique task execution ID)
35
+ result.state #=> "complete" (execution state)
36
+ result.status #=> "success" (execution outcome)
37
+ result.runtime #=> 0.5 (execution time in seconds)
38
+ ```
39
+
40
+ > [!NOTE]
41
+ > Result objects are immutable after task execution completes. All result data reflects the final state of the task execution and cannot be modified.
42
+
43
+ ## State and Status Information
44
+
45
+ Results provide comprehensive methods for checking execution state and status:
46
+
47
+ ```ruby
48
+ result = ProcessUserOrderTask.call
49
+
50
+ # State predicates (execution lifecycle)
51
+ result.initialized? #=> false (after execution)
52
+ result.executing? #=> false (after execution)
53
+ result.complete? #=> true (successful completion)
54
+ result.interrupted? #=> false (no interruption)
55
+ result.executed? #=> true (execution finished)
56
+
57
+ # Status predicates (execution outcome)
58
+ result.success? #=> true (successful execution)
59
+ result.skipped? #=> false (not skipped)
60
+ result.failed? #=> false (no failure)
61
+
62
+ # Outcome categorization
63
+ result.good? #=> true (success or skipped)
64
+ result.bad? #=> false (skipped or failed)
65
+ ```
66
+
67
+ ## Execution Outcome Analysis
68
+
69
+ Results provide additional methods for understanding execution outcomes:
70
+
71
+ ```ruby
72
+ result = ProcessOrderWorkflowTask.call
73
+
74
+ # Outcome determination
75
+ result.outcome #=> "success" (combines state and status)
76
+ ```
77
+
78
+ ## Runtime and Performance
79
+
80
+ Results capture detailed timing information:
81
+
82
+ ```ruby
83
+ result = ProcessUserOrderTask.call
84
+
85
+ # Execution timing
86
+ result.runtime #=> 0.5 (total execution time in seconds)
87
+ ```
88
+
89
+ ## Failure Chain Analysis
90
+
91
+ For failed results, comprehensive failure analysis is available:
92
+
93
+ ```ruby
94
+ result = ProcessOrderWorkflowTask.call
95
+
96
+ if result.failed?
97
+ # Find the original cause of failure
98
+ original_failure = result.caused_failure
99
+ if original_failure
100
+ puts "Original failure: #{original_failure.task.class.name}"
101
+ puts "Reason: #{original_failure.metadata[:reason]}"
102
+ end
103
+
104
+ # Find what threw the failure to this result
105
+ throwing_task = result.threw_failure
106
+ if throwing_task
107
+ puts "Failure thrown by: #{throwing_task.task.class.name}"
108
+ end
109
+
110
+ # Failure classification
111
+ result.caused_failure? #=> true if this result was the original cause
112
+ result.threw_failure? #=> true if this result threw a failure
113
+ result.thrown_failure? #=> true if this result received a thrown failure
114
+ end
115
+ ```
116
+
117
+ > [!IMPORTANT]
118
+ > Failure chain analysis is only available for failed results. Use these methods to trace the root cause of failures in complex task workflows.
119
+
120
+ ## Index and Position
121
+
122
+ Results track their position within execution chains:
5
123
 
6
124
  ```ruby
7
- result = ProcessOrderTask.call
8
- result.task #=> <ProcessOrderTask ...>
9
- result.context #=> <CMDx::Context ...>
10
- result.metadata #=> { ... }
11
- result.run #=> <CMDx::Run ...>
125
+ result = ProcessUserOrderTask.call
126
+
127
+ # Position in execution sequence
128
+ result.index #=> 0 (first task in chain)
129
+
130
+ # Access via chain
131
+ result.chain.results[result.index] == result #=> true
12
132
  ```
13
133
 
134
+ ## Result Callbacks and Chaining
135
+
136
+ Results support fluent callback patterns for conditional logic:
137
+
138
+ ```ruby
139
+ result = ProcessUserOrderTask.call
140
+
141
+ # State-based callbacks
142
+ result
143
+ .on_complete { |r| logger.info "Task completed successfully" }
144
+ .on_interrupted { |r| logger.warn "Task was interrupted" }
145
+ .on_executed { |r| update_metrics(r.runtime) }
146
+
147
+ # Status-based callbacks
148
+ result
149
+ .on_success { |r| send_confirmation_email(r.context) }
150
+ .on_skipped { |r| logger.info "Skipped: #{r.metadata[:reason]}" }
151
+ .on_failed { |r| handle_failure(r) }
152
+
153
+ # Outcome-based callbacks
154
+ result
155
+ .on_good { |r| celebrate_success }
156
+ .on_bad { |r| handle_problem }
157
+ ```
158
+
159
+ ### Callback Chaining Examples
160
+
161
+ ```ruby
162
+ ProcessUserOrderTask
163
+ .call(order_id: 123)
164
+ .on_success { |result|
165
+ SendOrderNotificationTask.call(result.context)
166
+ }
167
+ .on_failed { |result|
168
+ ErrorReporter.notify(result.metadata)
169
+ }
170
+ .on_executed { |result|
171
+ MetricsService.record_execution_time(result.runtime)
172
+ }
173
+ ```
174
+
175
+ > [!TIP]
176
+ > Use result callbacks for clean, functional-style conditional logic. Callbacks return the result object, enabling method chaining and fluent interfaces.
177
+
178
+ ## Pattern Matching
179
+
180
+ Results support Ruby's pattern matching (Ruby 3.0+) through array and hash deconstruction:
181
+
182
+ ### Array Pattern Matching
183
+
184
+ Match against state and status in order:
185
+
186
+ ```ruby
187
+ result = ProcessUserOrderTask.call
188
+
189
+ case result
190
+ in ["complete", "success"]
191
+ puts "Task completed successfully"
192
+ in ["interrupted", "failed"]
193
+ puts "Task failed during execution"
194
+ in ["complete", "skipped"]
195
+ puts "Task was skipped but completed"
196
+ end
197
+ ```
198
+
199
+ ### Hash Pattern Matching
200
+
201
+ Match against specific result attributes:
202
+
203
+ ```ruby
204
+ result = ProcessUserOrderTask.call
205
+
206
+ case result
207
+ in { state: "complete", status: "success" }
208
+ puts "Perfect execution!"
209
+ in { state: "interrupted", status: "failed", metadata: { retryable: true } }
210
+ puts "Failed but can retry"
211
+ in { good: true }
212
+ puts "Execution went well overall"
213
+ in { bad: true, metadata: { reason: String => reason } }
214
+ puts "Something went wrong: #{reason}"
215
+ end
216
+ ```
217
+
218
+ ### Pattern Matching with Guards
219
+
220
+ Use guard clauses for conditional matching:
221
+
222
+ ```ruby
223
+ case result
224
+ in { status: "failed", metadata: { attempts: n } } if n < 3
225
+ retry_task(result)
226
+ in { status: "failed", metadata: { attempts: n } } if n >= 3
227
+ give_up_task(result)
228
+ in { runtime: time } if time > threshold
229
+ log_performance_issue(result)
230
+ end
231
+ ```
232
+
233
+ > [!NOTE]
234
+ > Pattern matching requires Ruby 3.0+. The `deconstruct` method returns `[state, status]` for array patterns, while `deconstruct_keys` provides hash access to `state`, `status`, `metadata`, `executed`, `good`, and `bad` attributes.
235
+
236
+ ## Serialization and Inspection
237
+
238
+ Results provide comprehensive serialization and inspection capabilities:
239
+
240
+ ### Hash Serialization
241
+
242
+ ```ruby
243
+ result = ProcessUserOrderTask.call
244
+
245
+ result.to_h
246
+ #=> {
247
+ # class: "ProcessUserOrderTask",
248
+ # type: "Task",
249
+ # index: 0,
250
+ # id: "abc123...",
251
+ # chain_id: "def456...",
252
+ # tags: [],
253
+ # state: "complete",
254
+ # status: "success",
255
+ # outcome: "success",
256
+ # metadata: {},
257
+ # runtime: 0.5
258
+ # }
259
+ ```
260
+
261
+ ### Human-Readable Inspection
262
+
263
+ ```ruby
264
+ result = ProcessUserOrderTask.call
265
+
266
+ result.to_s
267
+ #=> "ProcessUserOrderTask: type=Task index=0 id=abc123... state=complete status=success outcome=success metadata={} runtime=0.5"
268
+ ```
269
+
270
+ ### Failure Chain Serialization
271
+
272
+ Failed results include failure chain information:
273
+
274
+ ```ruby
275
+ failed_result = ProcessOrderWorkflowTask.call
276
+
277
+ failed_result.to_h
278
+ #=> {
279
+ # # ... standard result data ...
280
+ # caused_failure: {
281
+ # class: "ValidateUserOrderTask",
282
+ # index: 1,
283
+ # id: "xyz789...",
284
+ # state: "interrupted",
285
+ # status: "failed"
286
+ # },
287
+ # threw_failure: {
288
+ # class: "ProcessOrderPaymentTask",
289
+ # index: 2,
290
+ # id: "uvw123...",
291
+ # state: "interrupted",
292
+ # status: "failed"
293
+ # }
294
+ # }
295
+ ```
296
+
297
+ > [!NOTE]
298
+ > Serialized results include complete failure chain information for debugging and audit trails. Use `to_h` for structured data and `to_s` for human-readable output.
299
+
14
300
  ---
15
301
 
16
- - **Prev:** [Interruptions - Exceptions](https://github.com/drexed/cmdx/blob/main/docs/interruptions/exceptions.md)
17
- - **Next:** [Outcomes - Statuses](https://github.com/drexed/cmdx/blob/main/docs/outcomes/statuses.md)
302
+ - **Prev:** [Interruptions - Exceptions](../interruptions/exceptions.md)
303
+ - **Next:** [Outcomes - Statuses](statuses.md)
@@ -1,31 +1,224 @@
1
- # Outcomes - States
1
+ # Outcomes - States
2
2
 
3
- State represents the condition of all the code task should execute.
3
+ States represent the execution lifecycle condition of task execution, tracking
4
+ the progress of tasks through their complete execution journey. States provide
5
+ insight into where a task is in its lifecycle and enable lifecycle-based
6
+ decision making and monitoring.
4
7
 
5
- | Status | Description |
8
+ ## Table of Contents
9
+
10
+ - [State Definitions](#state-definitions)
11
+ - [State Transitions](#state-transitions)
12
+ - [State Predicates](#state-predicates)
13
+ - [State-Based Callbacks](#state-based-callbacks)
14
+ - [State vs Status Distinction](#state-vs-status-distinction)
15
+ - [State Inspection and Monitoring](#state-inspection-and-monitoring)
16
+ - [State Persistence and Logging](#state-persistence-and-logging)
17
+
18
+ ## State Definitions
19
+
20
+ | State | Description |
6
21
  | ------------- | ----------- |
7
- | `initialized` | Initial task state prior to any execution. |
8
- | `executing` | Task is actively executing code. |
9
- | `complete` | Task executed to completion without halting for any reason. |
10
- | `interrupted` | Task could **NOT** be executed to completion due to a fault/exception. |
22
+ | `initialized` | Task created but execution not yet started. Default state for new tasks. |
23
+ | `executing` | Task is actively running its business logic. Transient state during execution. |
24
+ | `complete` | Task finished execution successfully without any interruption or halt. |
25
+ | `interrupted` | Task execution was stopped due to a fault, exception, or explicit halt. |
26
+
27
+ ## State Transitions
28
+
29
+ States follow a strict lifecycle with controlled transitions:
30
+
31
+ ```ruby
32
+ # Valid state transition flow
33
+ initialized -> executing -> complete (successful execution)
34
+ initialized -> executing -> interrupted (failed/halted execution)
35
+ ```
36
+
37
+ > [!IMPORTANT]
38
+ > States are automatically managed during task execution and should **never** be modified manually. State transitions are handled internally by the CMDx framework.
39
+
40
+ ### Automatic State Management
41
+
42
+ States are automatically managed during task execution and should **never** be modified manually:
43
+
44
+ ```ruby
45
+ task = ProcessUserOrderTask.new
46
+ task.result.state #=> "initialized"
47
+
48
+ # During task execution, states transition automatically:
49
+ # 1. initialized -> executing (when call begins)
50
+ # 2. executing -> complete (successful completion)
51
+ # 3. executing -> interrupted (on failure/halt)
52
+
53
+ result = ProcessUserOrderTask.call
54
+ result.state #=> "complete" (if successful)
55
+ ```
56
+
57
+ ### State Transition Methods (Internal Use)
58
+
59
+ These methods handle state transitions internally and are not intended for direct use:
60
+
61
+ ```ruby
62
+ result = ProcessUserOrderTask.new.result
63
+
64
+ # Internal state transition methods
65
+ result.executing! # initialized -> executing
66
+ result.complete! # executing -> complete
67
+ result.interrupt! # executing -> interrupted
68
+ result.executed! # executing -> complete OR interrupted (based on status)
69
+ ```
70
+
71
+ > [!WARNING]
72
+ > State transition methods (`executing!`, `complete!`, `interrupt!`) are for internal framework use only. Never call these methods directly in your application code.
73
+
74
+ ## State Predicates
75
+
76
+ Use state predicates to check the current execution lifecycle:
77
+
78
+ ```ruby
79
+ result = ProcessUserOrderTask.call
80
+
81
+ # Check current state
82
+ result.initialized? #=> false (after execution)
83
+ result.executing? #=> false (after execution)
84
+ result.complete? #=> true (successful completion)
85
+ result.interrupted? #=> false (no interruption)
86
+
87
+ # Combined state checking
88
+ result.executed? #=> true (complete OR interrupted)
89
+ ```
90
+
91
+ ## State-Based Callbacks
92
+
93
+ Results provide callback methods for state-based conditional execution:
94
+
95
+ ```ruby
96
+ result = ProcessUserOrderTask.call
97
+
98
+ # Individual state callbacks
99
+ result
100
+ .on_initialized { |r| log_task_created(r) }
101
+ .on_executing { |r| show_progress_indicator(r) }
102
+ .on_complete { |r| celebrate_success(r) }
103
+ .on_interrupted { |r| handle_interruption(r) }
104
+
105
+ # Execution completion callback (complete OR interrupted)
106
+ result
107
+ .on_executed { |r| cleanup_resources(r) }
108
+ ```
109
+
110
+ ### Callback Chaining and Combinations
111
+
112
+ ```ruby
113
+ ProcessUserOrderTask
114
+ .call(order_id: 123)
115
+ .on_complete { |result|
116
+ # Only runs if task completed successfully
117
+ send_confirmation_email(result.context)
118
+ update_order_status(result.context.order)
119
+ }
120
+ .on_interrupted { |result|
121
+ # Only runs if task was interrupted
122
+ log_interruption(result.metadata)
123
+ schedule_retry(result) if result.metadata[:retryable]
124
+ }
125
+ .on_executed { |result|
126
+ # Always runs after execution (complete OR interrupted)
127
+ update_metrics(result.runtime)
128
+ cleanup_temporary_files(result.context)
129
+ }
130
+ ```
131
+
132
+ > [!TIP]
133
+ > Use state-based callbacks for lifecycle event handling. The `on_executed` callback is particularly useful for cleanup operations that should run regardless of success or failure.
134
+
135
+ ## State vs Status Distinction
136
+
137
+ Understanding the difference between states and statuses is crucial:
138
+
139
+ - **State**: Execution lifecycle position (`initialized` → `executing` → `complete`/`interrupted`)
140
+ - **Status**: Execution outcome (`success`, `skipped`, `failed`)
141
+
142
+ ```ruby
143
+ result = ProcessUserOrderTask.call
144
+
145
+ # State indicates WHERE in the lifecycle
146
+ result.state #=> "complete" (finished executing)
147
+
148
+ # Status indicates HOW the execution ended
149
+ result.status #=> "success" (executed successfully)
150
+
151
+ # Both can be different for interrupted tasks
152
+ failed_result = ProcessFailingOrderTask.call
153
+ failed_result.state #=> "interrupted" (execution stopped)
154
+ failed_result.status #=> "failed" (outcome was failure)
155
+ ```
156
+
157
+ ### State-Status Combinations
158
+
159
+ | State | Status | Meaning |
160
+ | ------------- | --------- | ------- |
161
+ | `initialized` | `success` | Task created, not yet executed |
162
+ | `executing` | `success` | Task currently running |
163
+ | `complete` | `success` | Task finished successfully |
164
+ | `complete` | `skipped` | Task finished by skipping execution |
165
+ | `interrupted` | `failed` | Task stopped due to failure |
166
+ | `interrupted` | `skipped` | Task stopped by skip condition |
167
+
168
+ > [!NOTE]
169
+ > State tracks the execution lifecycle (where the task is), while status tracks the outcome (how the task ended). Both provide valuable but different information about task execution.
170
+
171
+ ## State Inspection and Monitoring
172
+
173
+ States provide valuable information for monitoring and debugging:
174
+
175
+ ```ruby
176
+ result = ProcessUserOrderTask.call
177
+
178
+ # Basic state information
179
+ puts "Execution state: #{result.state}"
180
+ puts "Task completed: #{result.executed?}"
181
+
182
+ # State in serialized form
183
+ result.to_h[:state] #=> "complete"
184
+
185
+ # Human-readable inspection
186
+ result.to_s
187
+ #=> "ProcessUserOrderTask: type=Task index=0 state=complete status=success outcome=success..."
188
+ ```
189
+
190
+ ## State Persistence and Logging
11
191
 
12
- > [!CAUTION]
13
- > States are automatically transitioned and should **NEVER** be altered manually.
192
+ States are automatically captured in result serialization:
14
193
 
15
194
  ```ruby
16
- result = ProcessOrderTask.call
17
- result.state #=> "complete"
195
+ result = ProcessUserOrderTask.call
18
196
 
19
- result.pending? #=> false
20
- result.executing? #=> false
21
- result.complete? #=> true
22
- result.interrupted? #=> false
197
+ # Hash representation includes state
198
+ result.to_h
199
+ #=> {
200
+ # class: "ProcessUserOrderTask",
201
+ # index: 0,
202
+ # state: "complete",
203
+ # status: "success",
204
+ # outcome: "success",
205
+ # # ... other attributes
206
+ # }
23
207
 
24
- # `complete` or `interrupted`
25
- result.executed?
208
+ # Chain-level state aggregation
209
+ result.chain.to_h
210
+ #=> {
211
+ # id: "chain-uuid...",
212
+ # state: "complete", # Derived from first result
213
+ # status: "success", # Derived from first result
214
+ # results: [
215
+ # { state: "complete", status: "success", ... },
216
+ # # ... other results
217
+ # ]
218
+ # }
26
219
  ```
27
220
 
28
221
  ---
29
222
 
30
- - **Prev:** [Outcomes - Statuses](https://github.com/drexed/cmdx/blob/main/docs/outcomes/statuses.md)
31
- - **Next:** [Hooks](https://github.com/drexed/cmdx/blob/main/docs/hooks.md)
223
+ - **Prev:** [Outcomes - Statuses](statuses.md)
224
+ - **Next:** [Parameters - Definitions](../parameters/definitions.md)