tasker-rb 0.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 (78) hide show
  1. checksums.yaml +7 -0
  2. data/DEVELOPMENT.md +548 -0
  3. data/README.md +87 -0
  4. data/ext/tasker_core/Cargo.lock +4720 -0
  5. data/ext/tasker_core/Cargo.toml +76 -0
  6. data/ext/tasker_core/extconf.rb +38 -0
  7. data/ext/tasker_core/src/CLAUDE.md +7 -0
  8. data/ext/tasker_core/src/bootstrap.rs +320 -0
  9. data/ext/tasker_core/src/bridge.rs +400 -0
  10. data/ext/tasker_core/src/client_ffi.rs +173 -0
  11. data/ext/tasker_core/src/conversions.rs +131 -0
  12. data/ext/tasker_core/src/diagnostics.rs +57 -0
  13. data/ext/tasker_core/src/event_handler.rs +179 -0
  14. data/ext/tasker_core/src/event_publisher_ffi.rs +239 -0
  15. data/ext/tasker_core/src/ffi_logging.rs +245 -0
  16. data/ext/tasker_core/src/global_event_system.rs +16 -0
  17. data/ext/tasker_core/src/in_process_event_ffi.rs +319 -0
  18. data/ext/tasker_core/src/lib.rs +41 -0
  19. data/ext/tasker_core/src/observability_ffi.rs +339 -0
  20. data/lib/tasker_core/batch_processing/batch_aggregation_scenario.rb +85 -0
  21. data/lib/tasker_core/batch_processing/batch_worker_context.rb +238 -0
  22. data/lib/tasker_core/bootstrap.rb +394 -0
  23. data/lib/tasker_core/domain_events/base_publisher.rb +220 -0
  24. data/lib/tasker_core/domain_events/base_subscriber.rb +178 -0
  25. data/lib/tasker_core/domain_events/publisher_registry.rb +253 -0
  26. data/lib/tasker_core/domain_events/subscriber_registry.rb +152 -0
  27. data/lib/tasker_core/domain_events.rb +43 -0
  28. data/lib/tasker_core/errors/CLAUDE.md +7 -0
  29. data/lib/tasker_core/errors/common.rb +305 -0
  30. data/lib/tasker_core/errors/error_classifier.rb +61 -0
  31. data/lib/tasker_core/errors.rb +4 -0
  32. data/lib/tasker_core/event_bridge.rb +330 -0
  33. data/lib/tasker_core/handlers.rb +159 -0
  34. data/lib/tasker_core/internal.rb +31 -0
  35. data/lib/tasker_core/logger.rb +234 -0
  36. data/lib/tasker_core/models.rb +337 -0
  37. data/lib/tasker_core/observability/types.rb +158 -0
  38. data/lib/tasker_core/observability.rb +292 -0
  39. data/lib/tasker_core/registry/handler_registry.rb +453 -0
  40. data/lib/tasker_core/registry/resolver_chain.rb +258 -0
  41. data/lib/tasker_core/registry/resolvers/base_resolver.rb +90 -0
  42. data/lib/tasker_core/registry/resolvers/class_constant_resolver.rb +156 -0
  43. data/lib/tasker_core/registry/resolvers/explicit_mapping_resolver.rb +146 -0
  44. data/lib/tasker_core/registry/resolvers/method_dispatch_wrapper.rb +144 -0
  45. data/lib/tasker_core/registry/resolvers/registry_resolver.rb +229 -0
  46. data/lib/tasker_core/registry/resolvers.rb +42 -0
  47. data/lib/tasker_core/registry.rb +12 -0
  48. data/lib/tasker_core/step_handler/api.rb +48 -0
  49. data/lib/tasker_core/step_handler/base.rb +354 -0
  50. data/lib/tasker_core/step_handler/batchable.rb +50 -0
  51. data/lib/tasker_core/step_handler/decision.rb +53 -0
  52. data/lib/tasker_core/step_handler/mixins/api.rb +452 -0
  53. data/lib/tasker_core/step_handler/mixins/batchable.rb +465 -0
  54. data/lib/tasker_core/step_handler/mixins/decision.rb +252 -0
  55. data/lib/tasker_core/step_handler/mixins.rb +66 -0
  56. data/lib/tasker_core/subscriber.rb +212 -0
  57. data/lib/tasker_core/task_handler/base.rb +254 -0
  58. data/lib/tasker_core/tasker_rb.so +0 -0
  59. data/lib/tasker_core/template_discovery.rb +181 -0
  60. data/lib/tasker_core/tracing.rb +166 -0
  61. data/lib/tasker_core/types/batch_processing_outcome.rb +301 -0
  62. data/lib/tasker_core/types/client_types.rb +145 -0
  63. data/lib/tasker_core/types/decision_point_outcome.rb +177 -0
  64. data/lib/tasker_core/types/error_types.rb +72 -0
  65. data/lib/tasker_core/types/simple_message.rb +151 -0
  66. data/lib/tasker_core/types/step_context.rb +328 -0
  67. data/lib/tasker_core/types/step_handler_call_result.rb +307 -0
  68. data/lib/tasker_core/types/step_message.rb +112 -0
  69. data/lib/tasker_core/types/step_types.rb +207 -0
  70. data/lib/tasker_core/types/task_template.rb +240 -0
  71. data/lib/tasker_core/types/task_types.rb +148 -0
  72. data/lib/tasker_core/types.rb +132 -0
  73. data/lib/tasker_core/version.rb +13 -0
  74. data/lib/tasker_core/worker/CLAUDE.md +7 -0
  75. data/lib/tasker_core/worker/event_poller.rb +224 -0
  76. data/lib/tasker_core/worker/in_process_domain_event_poller.rb +271 -0
  77. data/lib/tasker_core.rb +160 -0
  78. metadata +322 -0
@@ -0,0 +1,240 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dry-types'
4
+ require 'dry-struct'
5
+ require 'time'
6
+
7
+ module TaskerCore
8
+ module Types
9
+ # TaskTemplate Types - Self-Describing Workflow Configuration
10
+ #
11
+ # This module implements the self-describing TaskTemplate structure, featuring:
12
+ # - Callable-based handlers for maximum flexibility
13
+ # - Structured handler initialization configuration
14
+ # - Clear system dependency declarations
15
+ # - First-class domain event support
16
+ # - Enhanced environment-specific overrides
17
+ # - JSON Schema-based input validation
18
+
19
+ module Types
20
+ include Dry.Types()
21
+ end
22
+
23
+ # Template metadata for documentation and discovery
24
+ class TemplateMetadata < Dry::Struct
25
+ attribute :author, Types::String.optional.default(nil)
26
+ attribute :tags, Types::Array.of(Types::String).default([].freeze)
27
+ attribute :documentation_url, Types::String.optional.default(nil)
28
+ attribute :created_at, Types::String.optional.default(nil) # ISO8601 format
29
+ attribute :updated_at, Types::String.optional.default(nil) # ISO8601 format
30
+ end
31
+
32
+ # Handler definition with callable and initialization
33
+ #
34
+ # TAS-93: Extended with handler_method and resolver fields for the resolver chain pattern.
35
+ # - `handler_method`: Optional method name override (defaults to 'call')
36
+ # - `resolver`: Optional resolver hint to bypass inferential resolution
37
+ #
38
+ # NOTE: We use `handler_method` instead of `method` to avoid collision with
39
+ # Ruby's built-in `Object#method`.
40
+ class HandlerDefinition < Dry::Struct
41
+ attribute :callable, Types::Strict::String
42
+ attribute :initialization, Types::Hash.default({}.freeze)
43
+ # TAS-93: Method name to invoke on the handler (defaults to 'call')
44
+ # Named handler_method to avoid collision with Ruby's Object#method
45
+ attribute :handler_method, Types::String.optional.default(nil)
46
+ # TAS-93: Resolver hint to bypass the resolver chain (e.g., 'payment_resolver')
47
+ attribute :resolver, Types::String.optional.default(nil)
48
+
49
+ # TAS-93: Get the effective method name to invoke
50
+ # Returns the configured method name or defaults to 'call'
51
+ #
52
+ # @return [String] The method name to invoke on the handler
53
+ def effective_method
54
+ handler_method.presence || 'call'
55
+ end
56
+
57
+ # TAS-93: Check if this handler uses custom method dispatch
58
+ # Returns true if a non-default method is configured
59
+ #
60
+ # @return [Boolean] true if handler_method is something other than 'call'
61
+ def uses_method_dispatch?
62
+ handler_method.present? && handler_method != 'call'
63
+ end
64
+
65
+ # TAS-93: Check if a resolver hint is specified
66
+ # When true, the resolver chain should skip inferential resolution
67
+ # and directly use the named resolver
68
+ #
69
+ # @return [Boolean] true if resolver hint is present
70
+ def has_resolver_hint?
71
+ resolver.present?
72
+ end
73
+ end
74
+
75
+ # External system dependencies
76
+ class SystemDependencies < Dry::Struct
77
+ attribute :primary, Types::String.default('default')
78
+ attribute :secondary, Types::Array.of(Types::String).default([].freeze)
79
+ end
80
+
81
+ # Domain event definition with schema
82
+ class DomainEventDefinition < Dry::Struct
83
+ attribute :name, Types::Strict::String
84
+ attribute :description, Types::String.optional.default(nil)
85
+ attribute :schema, Types::Hash.optional.default(nil) # JSON Schema
86
+ end
87
+
88
+ # Retry configuration with backoff strategies
89
+ class RetryConfiguration < Dry::Struct
90
+ attribute :retryable, Types::Bool.default(true)
91
+ attribute :limit, Types::Integer.default(3)
92
+ attribute :backoff, Types::String.default('exponential').enum('none', 'linear', 'exponential', 'fibonacci')
93
+ attribute :backoff_base_ms, Types::Integer.optional.default(1000)
94
+ attribute :max_backoff_ms, Types::Integer.optional.default(30_000)
95
+ end
96
+
97
+ # Individual workflow step definition
98
+ class StepDefinition < Dry::Struct
99
+ attribute :name, Types::Strict::String
100
+ attribute :description, Types::String.optional.default(nil)
101
+ attribute :handler, HandlerDefinition
102
+ attribute :system_dependency, Types::String.optional.default(nil)
103
+ attribute :dependencies, Types::Array.of(Types::String).default([].freeze)
104
+ attribute(:retry, RetryConfiguration.default { RetryConfiguration.new })
105
+ attribute :timeout_seconds, Types::Integer.optional.default(nil)
106
+ attribute :publishes_events, Types::Array.of(Types::String).default([].freeze)
107
+ # TAS-53: Decision point step type classification
108
+ # Matches Rust field serialization name (Rust field: step_type, YAML: type)
109
+ attribute :type, Types::String.optional.default(nil).enum('standard', 'decision')
110
+
111
+ # Check if this step depends on another step
112
+ def depends_on?(other_step_name)
113
+ dependencies.include?(other_step_name.to_s)
114
+ end
115
+
116
+ # TAS-53: Check if this is a decision point step
117
+ def decision?
118
+ type == 'decision'
119
+ end
120
+
121
+ # TAS-53: Check if this is a standard step
122
+ def standard?
123
+ type.nil? || type == 'standard'
124
+ end
125
+ end
126
+
127
+ # Handler override for environments
128
+ class HandlerOverride < Dry::Struct
129
+ attribute :initialization, Types::Hash.optional.default(nil)
130
+ end
131
+
132
+ # Step override for environments
133
+ class StepOverride < Dry::Struct
134
+ attribute :name, Types::Strict::String # Step name or "ALL" for all steps
135
+ attribute :handler, HandlerOverride.optional.default(nil)
136
+ attribute :timeout_seconds, Types::Integer.optional.default(nil)
137
+ attribute :retry, RetryConfiguration.optional.default(nil)
138
+ end
139
+
140
+ # Environment-specific overrides
141
+ class EnvironmentOverride < Dry::Struct
142
+ attribute :task_handler, HandlerOverride.optional.default(nil)
143
+ attribute :steps, Types::Array.of(StepOverride).default([].freeze)
144
+ end
145
+
146
+ # Main TaskTemplate structure with self-describing configuration
147
+ class TaskTemplate < Dry::Struct
148
+ # Semantic version pattern validation
149
+ VERSION_PATTERN = /\A\d+\.\d+\.\d+\z/
150
+
151
+ # Core required attributes
152
+ attribute :name, Types::Strict::String
153
+ attribute :namespace_name, Types::Strict::String
154
+ attribute :version, Types::String.constrained(format: VERSION_PATTERN).default('1.0.0')
155
+
156
+ # Self-describing structure
157
+ attribute :description, Types::String.optional.default(nil)
158
+ attribute :metadata, TemplateMetadata.optional.default(nil)
159
+ attribute :task_handler, HandlerDefinition.optional.default(nil)
160
+ attribute(:system_dependencies, SystemDependencies.default { SystemDependencies.new })
161
+ attribute :domain_events, Types::Array.of(DomainEventDefinition).default([].freeze)
162
+ attribute :input_schema, Types::Hash.optional.default(nil) # JSON Schema
163
+ attribute :steps, Types::Array.of(StepDefinition).default([].freeze)
164
+ attribute :environments, Types::Hash.map(Types::String, EnvironmentOverride).default({}.freeze)
165
+
166
+ # Metadata (not persisted to database)
167
+ attribute :loaded_from, Types::String.optional.default(nil)
168
+
169
+ # Generate a unique key for this template
170
+ def template_key
171
+ "#{namespace_name}/#{name}:#{version}"
172
+ end
173
+
174
+ # Extract all callable references
175
+ def all_callables
176
+ callables = []
177
+ callables << task_handler.callable if task_handler
178
+ steps.each { |step| callables << step.handler.callable }
179
+ callables
180
+ end
181
+
182
+ # Check if template is valid for registration
183
+ def valid_for_registration?
184
+ return false if name.empty? || namespace_name.empty?
185
+ return false unless version.match?(VERSION_PATTERN)
186
+
187
+ # Ensure all steps have callables
188
+ return false if steps.any? { |step| step.handler.callable.empty? }
189
+
190
+ true
191
+ end
192
+
193
+ # Resolve template for specific environment
194
+ def resolve_for_environment(environment_name)
195
+ resolved_template = deep_dup
196
+
197
+ if environments[environment_name]
198
+ env_override = environments[environment_name]
199
+
200
+ # Apply task handler overrides
201
+ if env_override.task_handler && resolved_template.task_handler && env_override.task_handler.initialization
202
+ resolved_template.task_handler.initialization.merge!(env_override.task_handler.initialization)
203
+ end
204
+
205
+ # Apply step overrides
206
+ env_override.steps.each do |step_override|
207
+ if step_override.name == 'ALL'
208
+ # Apply to all steps
209
+ resolved_template.steps.each { |step| apply_step_override(step, step_override) }
210
+ else
211
+ # Apply to specific step
212
+ step = resolved_template.steps.find { |s| s.name == step_override.name }
213
+ apply_step_override(step, step_override) if step
214
+ end
215
+ end
216
+ end
217
+
218
+ resolved_template
219
+ end
220
+
221
+ private
222
+
223
+ # Deep duplicate for environment resolution
224
+ def deep_dup
225
+ # Simple deep dup implementation for dry-struct
226
+ TaskTemplate.new(to_h)
227
+ end
228
+
229
+ # Apply step override to a step
230
+ def apply_step_override(step, step_override)
231
+ if step_override.handler&.initialization
232
+ step.handler.initialization.merge!(step_override.handler.initialization)
233
+ end
234
+
235
+ step.timeout_seconds = step_override.timeout_seconds if step_override.timeout_seconds
236
+ step.retry = step_override.retry if step_override.retry
237
+ end
238
+ end
239
+ end
240
+ end
@@ -0,0 +1,148 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dry-struct'
4
+ require 'dry-types'
5
+
6
+ module TaskerCore
7
+ module Types
8
+ # Task-related type definitions for TaskerCore domain objects
9
+ module TaskTypes
10
+ module Types
11
+ include Dry.Types()
12
+ end
13
+
14
+ # Task request struct with full validation
15
+ class TaskRequest < Dry::Struct
16
+ # Core identification
17
+ attribute :namespace, Types::Coercible::String
18
+ attribute :name, Types::Coercible::String
19
+ attribute :version, Types::Coercible::String.default('1.0.0')
20
+
21
+ # Task state and metadata
22
+ attribute :status, Types::Coercible::String.default('pending').enum(
23
+ 'pending',
24
+ 'in_progress',
25
+ 'completed',
26
+ 'failed',
27
+ 'cancelled',
28
+ 'paused'
29
+ )
30
+ attribute :initiator, Types::Coercible::String
31
+ attribute :source_system, Types::Coercible::String
32
+ attribute :reason, Types::Coercible::String
33
+ attribute :complete, Types::Strict::Bool.default(false)
34
+ attribute :tags, Types::Array.of(Types::Coercible::String).default([].freeze)
35
+
36
+ # Task context (business data)
37
+ attribute :context, Types::Coercible::Hash
38
+
39
+ # Optional fields for advanced use cases
40
+ attribute? :priority, Types::Integer.default(0) # Higher values = higher priority, default 0
41
+ attribute? :claim_timeout_seconds, Types::Integer.default(60) # Timeout for distributed orchestration claims
42
+ attribute? :max_retries, Types::Integer.default(3)
43
+ attribute? :timeout_seconds, Types::Integer.default(300)
44
+ attribute? :parent_task_uuid, Types::String
45
+ attribute? :correlation_id, Types::Coercible::String
46
+
47
+ attribute?(:requested_at, Types::Constructor(Time) do |value|
48
+ value.is_a?(Time) ? value : Time.parse(value.to_s)
49
+ end.default { Time.now })
50
+
51
+ # Validation methods
52
+ def valid_for_creation?
53
+ !namespace.nil? && !namespace.empty? &&
54
+ !name.nil? && !name.empty? &&
55
+ !initiator.nil? && !initiator.empty? &&
56
+ !source_system.nil? && !source_system.empty? &&
57
+ !reason.nil? && !reason.empty? &&
58
+ context.is_a?(Hash)
59
+ end
60
+
61
+ # Convert to hash suitable for FFI serialization
62
+ def to_ffi_hash
63
+ # Build options hash for fields that go in the options field (legacy fields)
64
+ options_hash = {}
65
+ options_hash['max_retries'] = max_retries if max_retries
66
+ options_hash['timeout_seconds'] = timeout_seconds if timeout_seconds
67
+ options_hash['parent_task_uuid'] = parent_task_uuid if parent_task_uuid
68
+ options_hash['correlation_id'] = correlation_id if correlation_id
69
+
70
+ # Build the exact fields that Rust TaskRequest expects
71
+ rust_hash = {
72
+ namespace: namespace,
73
+ name: name,
74
+ version: version,
75
+ status: status,
76
+ initiator: initiator,
77
+ source_system: source_system,
78
+ reason: reason,
79
+ complete: complete,
80
+ tags: tags,
81
+ context: context,
82
+
83
+ requested_at: requested_at&.utc&.strftime('%Y-%m-%dT%H:%M:%S'),
84
+ # New direct fields for distributed orchestration
85
+ priority: priority,
86
+ claim_timeout_seconds: claim_timeout_seconds
87
+ }
88
+
89
+ # Add options field only if there are options to add
90
+ rust_hash[:options] = options_hash unless options_hash.empty?
91
+
92
+ rust_hash
93
+ end
94
+
95
+ # Create from hash with proper type coercion
96
+ def self.from_hash(hash)
97
+ new(hash.transform_keys(&:to_sym))
98
+ rescue Dry::Struct::Error => e
99
+ raise TaskerCore::ValidationError, "Invalid TaskRequest: #{e.message}"
100
+ end
101
+
102
+ # Quick factory method for tests
103
+ def self.build_test(namespace:, name:, context:, **options)
104
+ from_hash({
105
+ namespace: namespace,
106
+ name: name,
107
+ context: context,
108
+ initiator: options[:initiator] || 'test',
109
+ source_system: options[:source_system] || 'rspec',
110
+ reason: options[:reason] || 'testing',
111
+ tags: options[:tags] || ['test'],
112
+ **options
113
+ })
114
+ end
115
+
116
+ # Pretty string representation
117
+ def to_s
118
+ "#<TaskRequest #{namespace}/#{name}:#{version} status=#{status} initiator=#{initiator}>"
119
+ end
120
+
121
+ def inspect
122
+ to_s
123
+ end
124
+ end
125
+
126
+ # Task response struct (for initialize_task results)
127
+ class TaskResponse < Dry::Struct
128
+ attribute :task_uuid, Types::String
129
+ attribute :status, Types::Coercible::String.enum(
130
+ 'pending',
131
+ 'in_progress',
132
+ 'completed',
133
+ 'failed',
134
+ 'cancelled',
135
+ 'paused'
136
+ )
137
+ attribute :workflow_steps, Types::Array.of(Types::Hash)
138
+ attribute? :created_at, Types::Constructor(Time)
139
+ attribute? :estimated_completion, Types::Constructor(Time)
140
+ attribute? :metadata, Types::Hash
141
+
142
+ def to_s
143
+ "#<TaskResponse task_uuid=#{task_uuid} status=#{status} steps=#{workflow_steps.size}>"
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,132 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dry-struct'
4
+ require 'dry-types'
5
+
6
+ # Load all type modules
7
+ require_relative 'types/task_types'
8
+ require_relative 'types/step_types'
9
+ require_relative 'types/step_message'
10
+ require_relative 'types/simple_message' # NEW: simplified UUID-based messages
11
+ require_relative 'types/task_template' # TaskTemplate and StepTemplate types
12
+ require_relative 'types/step_handler_call_result' # NEW: standardized handler results
13
+ require_relative 'types/decision_point_outcome' # TAS-53: decision point outcomes
14
+ require_relative 'types/batch_processing_outcome' # TAS-59: batch processing outcomes
15
+ require_relative 'types/step_context' # TAS-96: cross-language standard step context
16
+ require_relative 'types/error_types' # TAS-96: cross-language standard error types
17
+ require_relative 'types/client_types' # TAS-231: client API response types
18
+
19
+ module TaskerCore
20
+ # Centralized type definitions for TaskerCore domain objects
21
+ #
22
+ # This module serves as the main entry point for all TaskerCore types,
23
+ # organizing them into logical groupings for better maintainability.
24
+ # All types are powered by dry-types for automatic validation, coercion,
25
+ # and schema enforcement.
26
+ #
27
+ # Type Categories:
28
+ # - **Task Types**: TaskRequest, TaskResponse for task creation and responses
29
+ # - **Step Types**: StepCompletion for step execution results
30
+ # - **Message Types**: SimpleStepMessage, SimpleTaskMessage for lightweight messaging
31
+ # - **Template Types**: TaskTemplate, StepTemplate for workflow definitions
32
+ # - **Result Types**: StepHandlerCallResult for standardized handler responses
33
+ #
34
+ # @example Using task types with validation
35
+ # # Build a task request with automatic validation
36
+ # request = TaskerCore::Types::TaskRequest.new(
37
+ # namespace: "fulfillment",
38
+ # name: "process_order",
39
+ # context: { order_id: "123", items: [...] }
40
+ # )
41
+ # # => Automatically validates required fields and types
42
+ #
43
+ # @example Type coercion and defaults
44
+ # # dry-types automatically coerces compatible types
45
+ # completion = TaskerCore::Types::StepCompletion.new(
46
+ # task_uuid: "123",
47
+ # step_uuid: "456",
48
+ # success: "true" # Automatically coerced to boolean true
49
+ # )
50
+ #
51
+ # @example Building test fixtures
52
+ # # Use build_test for quick test data generation
53
+ # request = TaskerCore::Types::TaskRequest.build_test(
54
+ # namespace: "fulfillment",
55
+ # name: "process_order",
56
+ # context: { order_id: "123" }
57
+ # )
58
+ # # => Creates valid request with sensible test defaults
59
+ #
60
+ # @example Using simple message types for UUID-based communication
61
+ # # Lightweight message for step execution
62
+ # simple_message = TaskerCore::Types::SimpleStepMessage.new(
63
+ # task_uuid: "550e8400-e29b-41d4-a716-446655440000",
64
+ # step_uuid: "7c9e6679-7425-40de-944b-e07fc1f90ae7",
65
+ # ready_dependency_step_uuids: [
66
+ # "123e4567-e89b-12d3-a456-426614174000",
67
+ # "456e7890-e12b-34d5-a678-426614174001"
68
+ # ]
69
+ # )
70
+ #
71
+ # @example Using template types for workflow definitions
72
+ # # Define a task template
73
+ # template = TaskerCore::Types::TaskTemplate.new(
74
+ # namespace: "payments",
75
+ # name: "process_payment",
76
+ # steps: [
77
+ # { name: "validate", handler_class: "ValidatePaymentHandler" },
78
+ # { name: "charge", handler_class: "ChargePaymentHandler" }
79
+ # ]
80
+ # )
81
+ #
82
+ # @example Standardized handler results
83
+ # # Return structured results from handlers
84
+ # result = TaskerCore::Types::StepHandlerCallResult.success(
85
+ # result: { payment_id: "pay_123", amount: 100.00 },
86
+ # metadata: {
87
+ # processing_time_ms: 125,
88
+ # gateway: "stripe"
89
+ # }
90
+ # )
91
+ #
92
+ # Validation Benefits:
93
+ # - **Type Safety**: Automatic type checking and coercion
94
+ # - **Required Fields**: Ensures all required data is present
95
+ # - **Schema Enforcement**: Validates structure matches expectations
96
+ # - **Early Error Detection**: Catches data issues before processing
97
+ # - **Documentation**: Types serve as living documentation
98
+ #
99
+ # @see TaskerCore::Types::TaskRequest For task creation
100
+ # @see TaskerCore::Types::TaskResponse For task responses
101
+ # @see TaskerCore::Types::StepCompletion For step execution results
102
+ # @see TaskerCore::Types::SimpleStepMessage For UUID-based step messaging
103
+ # @see TaskerCore::Types::SimpleTaskMessage For UUID-based task messaging
104
+ # @see TaskerCore::Types::TaskTemplate For workflow definitions
105
+ # @see TaskerCore::Types::StepHandlerCallResult For standardized handler responses
106
+ # @see https://dry-rb.org/gems/dry-types For dry-types documentation
107
+ module Types
108
+ include Dry.Types()
109
+
110
+ # Make base types available in class scope
111
+
112
+ # Re-export all type classes for backward compatibility and convenience
113
+
114
+ # Task-related types
115
+ TaskRequest = TaskTypes::TaskRequest
116
+ TaskResponse = TaskTypes::TaskResponse
117
+
118
+ # Step-related types
119
+ StepCompletion = StepTypes::StepCompletion
120
+
121
+ # Simple message types (UUID-based) - already defined in the namespace
122
+
123
+ # Client API types (TAS-231)
124
+ ClientTaskResponse = ClientTypes::TaskResponse
125
+ ClientTaskListResponse = ClientTypes::TaskListResponse
126
+ ClientStepResponse = ClientTypes::StepResponse
127
+ ClientStepAuditResponse = ClientTypes::StepAuditResponse
128
+ ClientHealthResponse = ClientTypes::HealthResponse
129
+ ClientPaginationInfo = ClientTypes::PaginationInfo
130
+ ClientStepReadiness = ClientTypes::StepReadiness
131
+ end
132
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TaskerCore
4
+ # Version synchronization with the core Rust crate
5
+ # This should be kept in sync with the Cargo.toml version
6
+ VERSION = '0.1.1'
7
+
8
+ def self.version_info
9
+ {
10
+ version: VERSION
11
+ }
12
+ end
13
+ end
@@ -0,0 +1,7 @@
1
+ <claude-mem-context>
2
+ # Recent Activity
3
+
4
+ <!-- This section is auto-generated by claude-mem. Edit content outside the tags. -->
5
+
6
+ *No recent activity*
7
+ </claude-mem-context>