cmdx 1.0.1 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (170) hide show
  1. checksums.yaml +4 -4
  2. data/.cursor/prompts/docs.md +9 -0
  3. data/.cursor/prompts/rspec.md +21 -0
  4. data/.cursor/prompts/yardoc.md +13 -0
  5. data/.rubocop.yml +2 -0
  6. data/CHANGELOG.md +29 -3
  7. data/README.md +2 -1
  8. data/docs/ai_prompts.md +269 -195
  9. data/docs/basics/call.md +126 -60
  10. data/docs/basics/chain.md +190 -160
  11. data/docs/basics/context.md +242 -154
  12. data/docs/basics/setup.md +302 -32
  13. data/docs/callbacks.md +382 -119
  14. data/docs/configuration.md +211 -49
  15. data/docs/deprecation.md +245 -0
  16. data/docs/getting_started.md +161 -39
  17. data/docs/internationalization.md +590 -70
  18. data/docs/interruptions/exceptions.md +135 -118
  19. data/docs/interruptions/faults.md +152 -127
  20. data/docs/interruptions/halt.md +134 -80
  21. data/docs/logging.md +183 -120
  22. data/docs/middlewares.md +165 -392
  23. data/docs/outcomes/result.md +140 -112
  24. data/docs/outcomes/states.md +134 -99
  25. data/docs/outcomes/statuses.md +204 -146
  26. data/docs/parameters/coercions.md +251 -289
  27. data/docs/parameters/defaults.md +224 -169
  28. data/docs/parameters/definitions.md +289 -141
  29. data/docs/parameters/namespacing.md +250 -161
  30. data/docs/parameters/validations.md +247 -159
  31. data/docs/testing.md +196 -203
  32. data/docs/workflows.md +146 -101
  33. data/lib/cmdx/.DS_Store +0 -0
  34. data/lib/cmdx/callback.rb +39 -55
  35. data/lib/cmdx/callback_registry.rb +80 -73
  36. data/lib/cmdx/chain.rb +65 -122
  37. data/lib/cmdx/chain_inspector.rb +23 -116
  38. data/lib/cmdx/chain_serializer.rb +34 -146
  39. data/lib/cmdx/coercion.rb +57 -0
  40. data/lib/cmdx/coercion_registry.rb +113 -0
  41. data/lib/cmdx/coercions/array.rb +18 -36
  42. data/lib/cmdx/coercions/big_decimal.rb +21 -33
  43. data/lib/cmdx/coercions/boolean.rb +21 -40
  44. data/lib/cmdx/coercions/complex.rb +18 -31
  45. data/lib/cmdx/coercions/date.rb +20 -39
  46. data/lib/cmdx/coercions/date_time.rb +22 -39
  47. data/lib/cmdx/coercions/float.rb +19 -32
  48. data/lib/cmdx/coercions/hash.rb +22 -41
  49. data/lib/cmdx/coercions/integer.rb +20 -33
  50. data/lib/cmdx/coercions/rational.rb +20 -32
  51. data/lib/cmdx/coercions/string.rb +23 -31
  52. data/lib/cmdx/coercions/time.rb +24 -40
  53. data/lib/cmdx/coercions/virtual.rb +14 -31
  54. data/lib/cmdx/configuration.rb +101 -162
  55. data/lib/cmdx/context.rb +34 -166
  56. data/lib/cmdx/core_ext/hash.rb +42 -67
  57. data/lib/cmdx/core_ext/module.rb +35 -79
  58. data/lib/cmdx/core_ext/object.rb +63 -98
  59. data/lib/cmdx/correlator.rb +59 -154
  60. data/lib/cmdx/error.rb +37 -202
  61. data/lib/cmdx/errors.rb +153 -216
  62. data/lib/cmdx/fault.rb +68 -150
  63. data/lib/cmdx/faults.rb +26 -137
  64. data/lib/cmdx/immutator.rb +22 -110
  65. data/lib/cmdx/lazy_struct.rb +110 -186
  66. data/lib/cmdx/log_formatters/json.rb +14 -40
  67. data/lib/cmdx/log_formatters/key_value.rb +14 -40
  68. data/lib/cmdx/log_formatters/line.rb +14 -48
  69. data/lib/cmdx/log_formatters/logstash.rb +14 -57
  70. data/lib/cmdx/log_formatters/pretty_json.rb +14 -50
  71. data/lib/cmdx/log_formatters/pretty_key_value.rb +13 -46
  72. data/lib/cmdx/log_formatters/pretty_line.rb +16 -54
  73. data/lib/cmdx/log_formatters/raw.rb +19 -49
  74. data/lib/cmdx/logger.rb +22 -79
  75. data/lib/cmdx/logger_ansi.rb +31 -72
  76. data/lib/cmdx/logger_serializer.rb +74 -103
  77. data/lib/cmdx/middleware.rb +56 -60
  78. data/lib/cmdx/middleware_registry.rb +82 -77
  79. data/lib/cmdx/middlewares/correlate.rb +41 -226
  80. data/lib/cmdx/middlewares/timeout.rb +46 -185
  81. data/lib/cmdx/parameter.rb +167 -183
  82. data/lib/cmdx/parameter_evaluator.rb +231 -0
  83. data/lib/cmdx/parameter_inspector.rb +37 -55
  84. data/lib/cmdx/parameter_registry.rb +65 -84
  85. data/lib/cmdx/parameter_serializer.rb +32 -76
  86. data/lib/cmdx/railtie.rb +24 -107
  87. data/lib/cmdx/result.rb +254 -259
  88. data/lib/cmdx/result_ansi.rb +28 -80
  89. data/lib/cmdx/result_inspector.rb +34 -70
  90. data/lib/cmdx/result_logger.rb +23 -77
  91. data/lib/cmdx/result_serializer.rb +59 -125
  92. data/lib/cmdx/rspec/matchers.rb +28 -0
  93. data/lib/cmdx/rspec/result_matchers/be_executed.rb +42 -0
  94. data/lib/cmdx/rspec/result_matchers/be_failed_task.rb +94 -0
  95. data/lib/cmdx/rspec/result_matchers/be_skipped_task.rb +94 -0
  96. data/lib/cmdx/rspec/result_matchers/be_state_matchers.rb +59 -0
  97. data/lib/cmdx/rspec/result_matchers/be_status_matchers.rb +57 -0
  98. data/lib/cmdx/rspec/result_matchers/be_successful_task.rb +87 -0
  99. data/lib/cmdx/rspec/result_matchers/have_bad_outcome.rb +51 -0
  100. data/lib/cmdx/rspec/result_matchers/have_caused_failure.rb +58 -0
  101. data/lib/cmdx/rspec/result_matchers/have_chain_index.rb +59 -0
  102. data/lib/cmdx/rspec/result_matchers/have_context.rb +86 -0
  103. data/lib/cmdx/rspec/result_matchers/have_empty_metadata.rb +54 -0
  104. data/lib/cmdx/rspec/result_matchers/have_good_outcome.rb +52 -0
  105. data/lib/cmdx/rspec/result_matchers/have_metadata.rb +114 -0
  106. data/lib/cmdx/rspec/result_matchers/have_preserved_context.rb +66 -0
  107. data/lib/cmdx/rspec/result_matchers/have_received_thrown_failure.rb +64 -0
  108. data/lib/cmdx/rspec/result_matchers/have_runtime.rb +78 -0
  109. data/lib/cmdx/rspec/result_matchers/have_thrown_failure.rb +76 -0
  110. data/lib/cmdx/rspec/task_matchers/be_well_formed_task.rb +62 -0
  111. data/lib/cmdx/rspec/task_matchers/have_callback.rb +85 -0
  112. data/lib/cmdx/rspec/task_matchers/have_cmd_setting.rb +68 -0
  113. data/lib/cmdx/rspec/task_matchers/have_executed_callbacks.rb +92 -0
  114. data/lib/cmdx/rspec/task_matchers/have_middleware.rb +46 -0
  115. data/lib/cmdx/rspec/task_matchers/have_parameter.rb +181 -0
  116. data/lib/cmdx/task.rb +336 -427
  117. data/lib/cmdx/task_deprecator.rb +52 -0
  118. data/lib/cmdx/task_processor.rb +246 -0
  119. data/lib/cmdx/task_serializer.rb +34 -69
  120. data/lib/cmdx/utils/ansi_color.rb +13 -89
  121. data/lib/cmdx/utils/log_timestamp.rb +13 -42
  122. data/lib/cmdx/utils/monotonic_runtime.rb +11 -63
  123. data/lib/cmdx/utils/name_affix.rb +21 -71
  124. data/lib/cmdx/validator.rb +57 -0
  125. data/lib/cmdx/validator_registry.rb +108 -0
  126. data/lib/cmdx/validators/exclusion.rb +55 -94
  127. data/lib/cmdx/validators/format.rb +31 -85
  128. data/lib/cmdx/validators/inclusion.rb +65 -110
  129. data/lib/cmdx/validators/length.rb +117 -133
  130. data/lib/cmdx/validators/numeric.rb +123 -130
  131. data/lib/cmdx/validators/presence.rb +38 -79
  132. data/lib/cmdx/version.rb +1 -7
  133. data/lib/cmdx/workflow.rb +58 -330
  134. data/lib/cmdx.rb +1 -1
  135. data/lib/generators/cmdx/install_generator.rb +14 -31
  136. data/lib/generators/cmdx/task_generator.rb +39 -55
  137. data/lib/generators/cmdx/templates/install.rb +24 -6
  138. data/lib/generators/cmdx/workflow_generator.rb +41 -66
  139. data/lib/locales/ar.yml +0 -1
  140. data/lib/locales/cs.yml +0 -1
  141. data/lib/locales/da.yml +0 -1
  142. data/lib/locales/de.yml +0 -1
  143. data/lib/locales/el.yml +0 -1
  144. data/lib/locales/en.yml +0 -1
  145. data/lib/locales/es.yml +0 -1
  146. data/lib/locales/fi.yml +0 -1
  147. data/lib/locales/fr.yml +0 -1
  148. data/lib/locales/he.yml +0 -1
  149. data/lib/locales/hi.yml +0 -1
  150. data/lib/locales/it.yml +0 -1
  151. data/lib/locales/ja.yml +0 -1
  152. data/lib/locales/ko.yml +0 -1
  153. data/lib/locales/nl.yml +0 -1
  154. data/lib/locales/no.yml +0 -1
  155. data/lib/locales/pl.yml +0 -1
  156. data/lib/locales/pt.yml +0 -1
  157. data/lib/locales/ru.yml +0 -1
  158. data/lib/locales/sv.yml +0 -1
  159. data/lib/locales/th.yml +0 -1
  160. data/lib/locales/tr.yml +0 -1
  161. data/lib/locales/vi.yml +0 -1
  162. data/lib/locales/zh.yml +0 -1
  163. metadata +36 -8
  164. data/lib/cmdx/parameter_validator.rb +0 -81
  165. data/lib/cmdx/parameter_value.rb +0 -244
  166. data/lib/cmdx/parameters_inspector.rb +0 -72
  167. data/lib/cmdx/parameters_serializer.rb +0 -115
  168. data/lib/cmdx/rspec/result_matchers.rb +0 -917
  169. data/lib/cmdx/rspec/task_matchers.rb +0 -570
  170. data/lib/cmdx/validators/custom.rb +0 -102
@@ -13,24 +13,39 @@ decision making and monitoring.
13
13
  - [State Predicates](#state-predicates)
14
14
  - [State-Based Callbacks](#state-based-callbacks)
15
15
  - [State vs Status Distinction](#state-vs-status-distinction)
16
- - [State Inspection and Monitoring](#state-inspection-and-monitoring)
17
16
  - [State Persistence and Logging](#state-persistence-and-logging)
18
17
 
19
18
  ## TLDR
20
19
 
21
- - **States** - Track execution lifecycle: `initialized` → `executing` → `complete`/`interrupted`
22
- - **Automatic** - States are managed automatically by the framework, never modify manually
23
- - **Predicates** - Check with `result.complete?`, `result.interrupted?`, `result.executed?`
24
- - **Callbacks** - Use `.on_complete`, `.on_interrupted`, `.on_executed` for lifecycle events
25
- - **vs Status** - State = where in lifecycle, Status = how execution ended
20
+ ```ruby
21
+ # Check execution lifecycle
22
+ result.initialized? # false (after execution)
23
+ result.executing? # false (after execution)
24
+ result.complete? # true (successful completion)
25
+ result.interrupted? # → false (no interruption)
26
+ result.executed? # → true (complete OR interrupted)
27
+
28
+ # State-based callbacks
29
+ result
30
+ .on_complete { |r| send_confirmation_email(r.context) }
31
+ .on_interrupted { |r| log_error_and_retry(r) }
32
+ .on_executed { |r| cleanup_resources(r) }
33
+
34
+ # States: WHERE in lifecycle, Status: HOW it ended
35
+ result.state #=> "complete" (finished executing)
36
+ result.status #=> "success" (executed successfully)
37
+ ```
26
38
 
27
39
  ## State Definitions
28
40
 
29
- | State | Description |
30
- | ------------- | ----------- |
41
+ > [!IMPORTANT]
42
+ > States are automatically managed during task execution and should **never** be modified manually. State transitions are handled internally by the CMDx framework.
43
+
44
+ | State | Description |
45
+ | ----- | ----------- |
31
46
  | `initialized` | Task created but execution not yet started. Default state for new tasks. |
32
- | `executing` | Task is actively running its business logic. Transient state during execution. |
33
- | `complete` | Task finished execution successfully without any interruption or halt. |
47
+ | `executing` | Task is actively running its business logic. Transient state during execution. |
48
+ | `complete` | Task finished execution successfully without any interruption or halt. |
34
49
  | `interrupted` | Task execution was stopped due to a fault, exception, or explicit halt. |
35
50
 
36
51
  ## State Transitions
@@ -39,53 +54,60 @@ States follow a strict lifecycle with controlled transitions:
39
54
 
40
55
  ```ruby
41
56
  # Valid state transition flow
42
- initialized -> executing -> complete (successful execution)
43
- initialized -> executing -> interrupted (failed/halted execution)
57
+ initialized executing complete (successful execution)
58
+ initialized executing interrupted (failed/halted execution)
44
59
  ```
45
60
 
46
- > [!IMPORTANT]
47
- > States are automatically managed during task execution and should **never** be modified manually. State transitions are handled internally by the CMDx framework.
48
-
49
61
  ### Automatic State Management
50
62
 
51
- States are automatically managed during task execution and should **never** be modified manually:
52
-
53
63
  ```ruby
54
- task = ProcessUserOrderTask.new
64
+ class ProcessPaymentTask < CMDx::Task
65
+ def call
66
+ # State automatically managed:
67
+ # 1. initialized → executing (when call begins)
68
+ # 2. executing → complete (successful completion)
69
+ # 3. executing → interrupted (on failure/halt)
70
+
71
+ charge_customer(amount)
72
+ send_receipt(email)
73
+ end
74
+ end
75
+
76
+ task = ProcessPaymentTask.new
55
77
  task.result.state #=> "initialized"
56
78
 
57
- # During task execution, states transition automatically:
58
- # 1. initialized -> executing (when call begins)
59
- # 2. executing -> complete (successful completion)
60
- # 3. executing -> interrupted (on failure/halt)
61
-
62
- result = ProcessUserOrderTask.call
79
+ result = ProcessPaymentTask.call
63
80
  result.state #=> "complete" (if successful)
64
81
  ```
65
82
 
66
- ### State Transition Methods (Internal Use)
83
+ ### Internal State Transition Methods
67
84
 
68
- These methods handle state transitions internally and are not intended for direct use:
85
+ > [!WARNING]
86
+ > State transition methods (`executing!`, `complete!`, `interrupt!`) are for internal framework use only. Never call these methods directly in your application code.
69
87
 
70
88
  ```ruby
71
- result = ProcessUserOrderTask.new.result
89
+ result = ProcessPaymentTask.new.result
72
90
 
73
- # Internal state transition methods
74
- result.executing! # initialized -> executing
75
- result.complete! # executing -> complete
76
- result.interrupt! # executing -> interrupted
77
- result.executed! # executing -> complete OR interrupted (based on status)
91
+ # Internal state transition methods (DO NOT USE)
92
+ result.executing! # initialized executing
93
+ result.complete! # executing complete
94
+ result.interrupt! # executing interrupted
95
+ result.executed! # executing complete OR interrupted (based on status)
78
96
  ```
79
97
 
80
- > [!WARNING]
81
- > State transition methods (`executing!`, `complete!`, `interrupt!`) are for internal framework use only. Never call these methods directly in your application code.
82
-
83
98
  ## State Predicates
84
99
 
85
100
  Use state predicates to check the current execution lifecycle:
86
101
 
87
102
  ```ruby
88
- result = ProcessUserOrderTask.call
103
+ class OrderFulfillmentTask < CMDx::Task
104
+ def call
105
+ process_order
106
+ ship_items
107
+ end
108
+ end
109
+
110
+ result = OrderFulfillmentTask.call
89
111
 
90
112
  # Check current state
91
113
  result.initialized? #=> false (after execution)
@@ -97,132 +119,145 @@ result.interrupted? #=> false (no interruption)
97
119
  result.executed? #=> true (complete OR interrupted)
98
120
  ```
99
121
 
122
+ ### State Checking in Conditional Logic
123
+
124
+ ```ruby
125
+ def handle_task_result(result)
126
+ if result.complete?
127
+ notify_success(result.context)
128
+ elsif result.interrupted?
129
+ handle_failure(result.metadata)
130
+ end
131
+
132
+ # Always cleanup when execution finished
133
+ cleanup_resources if result.executed?
134
+ end
135
+ ```
136
+
100
137
  ## State-Based Callbacks
101
138
 
102
- Results provide callback methods for state-based conditional execution:
139
+ > [!TIP]
140
+ > 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.
103
141
 
104
142
  ```ruby
105
- result = ProcessUserOrderTask.call
143
+ class ProcessOrderTask < CMDx::Task
144
+ def call
145
+ validate_inventory
146
+ charge_payment
147
+ update_stock
148
+ end
149
+ end
106
150
 
107
- # Individual state callbacks
108
- result
109
- .on_initialized { |r| log_task_created(r) }
110
- .on_executing { |r| show_progress_indicator(r) }
111
- .on_complete { |r| celebrate_success(r) }
112
- .on_interrupted { |r| handle_interruption(r) }
151
+ result = ProcessOrderTask.call
113
152
 
114
- # Execution completion callback (complete OR interrupted)
153
+ # Individual state callbacks
115
154
  result
116
- .on_executed { |r| cleanup_resources(r) }
155
+ .on_complete { |r| send_confirmation_email(r.context.customer_email) }
156
+ .on_interrupted { |r| log_error(r.metadata) && schedule_retry(r) }
157
+ .on_executed { |r| update_analytics(r.runtime) }
117
158
  ```
118
159
 
119
- ### Callback Chaining and Combinations
160
+ ### Advanced Callback Patterns
120
161
 
121
162
  ```ruby
122
- ProcessUserOrderTask
163
+ ProcessOrderTask
123
164
  .call(order_id: 123)
124
165
  .on_complete { |result|
125
166
  # Only runs if task completed successfully
126
- send_confirmation_email(result.context)
127
- update_order_status(result.context.order)
167
+ OrderMailer.confirmation(result.context.order).deliver_now
168
+ Analytics.track("order_processed", order_id: result.context.order_id)
128
169
  }
129
170
  .on_interrupted { |result|
130
171
  # Only runs if task was interrupted
131
- log_interruption(result.metadata)
132
- schedule_retry(result) if result.metadata[:retryable]
172
+ ErrorLogger.log(result.metadata[:error])
173
+
174
+ if result.metadata[:retryable]
175
+ RetryWorker.perform_later(result.context.order_id)
176
+ end
133
177
  }
134
178
  .on_executed { |result|
135
179
  # Always runs after execution (complete OR interrupted)
136
- update_metrics(result.runtime)
137
- cleanup_temporary_files(result.context)
180
+ PerformanceTracker.record(result.runtime)
181
+ TempFileCleanup.perform(result.context.temp_files)
138
182
  }
139
183
  ```
140
184
 
141
- > [!TIP]
142
- > 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.
143
-
144
185
  ## State vs Status Distinction
145
186
 
187
+ > [!NOTE]
188
+ > 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.
189
+
146
190
  Understanding the difference between states and statuses is crucial:
147
191
 
148
192
  - **State**: Execution lifecycle position (`initialized` → `executing` → `complete`/`interrupted`)
149
193
  - **Status**: Execution outcome (`success`, `skipped`, `failed`)
150
194
 
151
195
  ```ruby
152
- result = ProcessUserOrderTask.call
196
+ class ProcessRefundTask < CMDx::Task
197
+ def call
198
+ return unless eligible_for_refund?
153
199
 
154
- # State indicates WHERE in the lifecycle
155
- result.state #=> "complete" (finished executing)
200
+ process_refund
201
+ notify_customer
202
+ end
203
+ end
156
204
 
157
- # Status indicates HOW the execution ended
205
+ # Successful execution
206
+ result = ProcessRefundTask.call
207
+ result.state #=> "complete" (finished executing)
158
208
  result.status #=> "success" (executed successfully)
159
209
 
160
- # Both can be different for interrupted tasks
161
- failed_result = ProcessFailingOrderTask.call
210
+ # Failed execution
211
+ failed_result = ProcessRefundTask.call(invalid_order_id: "xyz")
162
212
  failed_result.state #=> "interrupted" (execution stopped)
163
213
  failed_result.status #=> "failed" (outcome was failure)
164
214
  ```
165
215
 
166
216
  ### State-Status Combinations
167
217
 
168
- | State | Status | Meaning |
169
- | ------------- | --------- | ------- |
218
+ | State | Status | Meaning |
219
+ | ----- | ------ | ------- |
170
220
  | `initialized` | `success` | Task created, not yet executed |
171
- | `executing` | `success` | Task currently running |
172
- | `complete` | `success` | Task finished successfully |
173
- | `complete` | `skipped` | Task finished by skipping execution |
174
- | `interrupted` | `failed` | Task stopped due to failure |
221
+ | `executing` | `success` | Task currently running |
222
+ | `complete` | `success` | Task finished successfully |
223
+ | `complete` | `skipped` | Task finished by skipping execution |
224
+ | `interrupted` | `failed` | Task stopped due to failure |
175
225
  | `interrupted` | `skipped` | Task stopped by skip condition |
176
226
 
177
- > [!NOTE]
178
- > 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.
179
-
180
- ## State Inspection and Monitoring
181
-
182
- States provide valuable information for monitoring and debugging:
183
-
184
- ```ruby
185
- result = ProcessUserOrderTask.call
186
-
187
- # Basic state information
188
- puts "Execution state: #{result.state}"
189
- puts "Task completed: #{result.executed?}"
190
-
191
- # State in serialized form
192
- result.to_h[:state] #=> "complete"
193
-
194
- # Human-readable inspection
195
- result.to_s
196
- #=> "ProcessUserOrderTask: type=Task index=0 state=complete status=success outcome=success..."
197
- ```
198
-
199
227
  ## State Persistence and Logging
200
228
 
201
- States are automatically captured in result serialization:
229
+ > [!IMPORTANT]
230
+ > States are automatically captured in result serialization and logging. All state information persists through the complete task execution lifecycle.
202
231
 
203
232
  ```ruby
204
- result = ProcessUserOrderTask.call
233
+ result = ProcessOrderTask.call
205
234
 
206
235
  # Hash representation includes state
207
236
  result.to_h
208
237
  #=> {
209
- # class: "ProcessUserOrderTask",
238
+ # class: "ProcessOrderTask",
210
239
  # index: 0,
211
240
  # state: "complete",
212
241
  # status: "success",
213
242
  # outcome: "success",
214
- # # ... other attributes
243
+ # runtime: 0.045,
244
+ # metadata: {},
245
+ # context: { order_id: 123 }
215
246
  # }
216
247
 
248
+ # Human-readable inspection
249
+ result.to_s
250
+ #=> "ProcessOrderTask: type=Task index=0 state=complete status=success outcome=success runtime=0.045s"
251
+
217
252
  # Chain-level state aggregation
218
253
  result.chain.to_h
219
254
  #=> {
220
- # id: "chain-uuid...",
221
- # state: "complete", # Derived from first result
222
- # status: "success", # Derived from first result
255
+ # id: "chain-550e8400-e29b-41d4-a716-446655440000",
256
+ # state: "complete", # Derived from overall chain state
257
+ # status: "success", # Derived from overall chain status
223
258
  # results: [
224
259
  # { state: "complete", status: "success", ... },
225
- # # ... other results
260
+ # { state: "complete", status: "success", ... }
226
261
  # ]
227
262
  # }
228
263
  ```