igniter 0.3.1 → 0.4.3

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 (114) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -0
  3. data/README.md +238 -218
  4. data/docs/DISTRIBUTED_CONTRACTS_V1.md +493 -0
  5. data/docs/LLM_V1.md +335 -0
  6. data/docs/PATTERNS.md +189 -0
  7. data/docs/SERVER_V1.md +313 -0
  8. data/examples/README.md +129 -0
  9. data/examples/agents.rb +150 -0
  10. data/examples/differential.rb +161 -0
  11. data/examples/distributed_server.rb +94 -0
  12. data/examples/distributed_workflow.rb +52 -0
  13. data/examples/effects.rb +184 -0
  14. data/examples/invariants.rb +179 -0
  15. data/examples/order_pipeline.rb +163 -0
  16. data/examples/provenance.rb +122 -0
  17. data/examples/saga.rb +110 -0
  18. data/lib/igniter/agent/mailbox.rb +96 -0
  19. data/lib/igniter/agent/message.rb +21 -0
  20. data/lib/igniter/agent/ref.rb +86 -0
  21. data/lib/igniter/agent/runner.rb +129 -0
  22. data/lib/igniter/agent/state_holder.rb +23 -0
  23. data/lib/igniter/agent.rb +155 -0
  24. data/lib/igniter/compiler/compiled_graph.rb +12 -0
  25. data/lib/igniter/compiler/validation_pipeline.rb +3 -1
  26. data/lib/igniter/compiler/validators/await_validator.rb +53 -0
  27. data/lib/igniter/compiler/validators/callable_validator.rb +21 -3
  28. data/lib/igniter/compiler/validators/dependencies_validator.rb +41 -1
  29. data/lib/igniter/compiler/validators/remote_validator.rb +58 -0
  30. data/lib/igniter/compiler.rb +2 -0
  31. data/lib/igniter/contract.rb +59 -8
  32. data/lib/igniter/differential/divergence.rb +29 -0
  33. data/lib/igniter/differential/formatter.rb +96 -0
  34. data/lib/igniter/differential/report.rb +86 -0
  35. data/lib/igniter/differential/runner.rb +130 -0
  36. data/lib/igniter/differential.rb +51 -0
  37. data/lib/igniter/dsl/contract_builder.rb +74 -4
  38. data/lib/igniter/effect.rb +91 -0
  39. data/lib/igniter/effect_registry.rb +78 -0
  40. data/lib/igniter/errors.rb +17 -2
  41. data/lib/igniter/execution_report/builder.rb +54 -0
  42. data/lib/igniter/execution_report/formatter.rb +50 -0
  43. data/lib/igniter/execution_report/node_entry.rb +24 -0
  44. data/lib/igniter/execution_report/report.rb +65 -0
  45. data/lib/igniter/execution_report.rb +32 -0
  46. data/lib/igniter/extensions/differential.rb +114 -0
  47. data/lib/igniter/extensions/execution_report.rb +27 -0
  48. data/lib/igniter/extensions/invariants.rb +116 -0
  49. data/lib/igniter/extensions/provenance.rb +45 -0
  50. data/lib/igniter/extensions/saga.rb +74 -0
  51. data/lib/igniter/integrations/agents.rb +18 -0
  52. data/lib/igniter/integrations/llm/config.rb +69 -0
  53. data/lib/igniter/integrations/llm/context.rb +74 -0
  54. data/lib/igniter/integrations/llm/executor.rb +159 -0
  55. data/lib/igniter/integrations/llm/providers/anthropic.rb +148 -0
  56. data/lib/igniter/integrations/llm/providers/base.rb +33 -0
  57. data/lib/igniter/integrations/llm/providers/ollama.rb +137 -0
  58. data/lib/igniter/integrations/llm/providers/openai.rb +153 -0
  59. data/lib/igniter/integrations/llm.rb +59 -0
  60. data/lib/igniter/integrations/rails/cable_adapter.rb +49 -0
  61. data/lib/igniter/integrations/rails/contract_job.rb +76 -0
  62. data/lib/igniter/integrations/rails/generators/contract/contract_generator.rb +22 -0
  63. data/lib/igniter/integrations/rails/generators/install/install_generator.rb +33 -0
  64. data/lib/igniter/integrations/rails/railtie.rb +25 -0
  65. data/lib/igniter/integrations/rails/webhook_concern.rb +49 -0
  66. data/lib/igniter/integrations/rails.rb +12 -0
  67. data/lib/igniter/invariant.rb +50 -0
  68. data/lib/igniter/model/await_node.rb +21 -0
  69. data/lib/igniter/model/effect_node.rb +37 -0
  70. data/lib/igniter/model/remote_node.rb +26 -0
  71. data/lib/igniter/model.rb +3 -0
  72. data/lib/igniter/property_testing/formatter.rb +66 -0
  73. data/lib/igniter/property_testing/generators.rb +115 -0
  74. data/lib/igniter/property_testing/result.rb +45 -0
  75. data/lib/igniter/property_testing/run.rb +43 -0
  76. data/lib/igniter/property_testing/runner.rb +47 -0
  77. data/lib/igniter/property_testing.rb +64 -0
  78. data/lib/igniter/provenance/builder.rb +97 -0
  79. data/lib/igniter/provenance/lineage.rb +82 -0
  80. data/lib/igniter/provenance/node_trace.rb +65 -0
  81. data/lib/igniter/provenance/text_formatter.rb +70 -0
  82. data/lib/igniter/provenance.rb +29 -0
  83. data/lib/igniter/registry.rb +67 -0
  84. data/lib/igniter/runtime/execution.rb +2 -2
  85. data/lib/igniter/runtime/input_validator.rb +5 -3
  86. data/lib/igniter/runtime/resolver.rb +58 -1
  87. data/lib/igniter/runtime/stores/active_record_store.rb +13 -1
  88. data/lib/igniter/runtime/stores/file_store.rb +50 -2
  89. data/lib/igniter/runtime/stores/memory_store.rb +55 -2
  90. data/lib/igniter/runtime/stores/redis_store.rb +13 -1
  91. data/lib/igniter/saga/compensation.rb +31 -0
  92. data/lib/igniter/saga/compensation_record.rb +20 -0
  93. data/lib/igniter/saga/executor.rb +85 -0
  94. data/lib/igniter/saga/formatter.rb +49 -0
  95. data/lib/igniter/saga/result.rb +47 -0
  96. data/lib/igniter/saga.rb +56 -0
  97. data/lib/igniter/server/client.rb +123 -0
  98. data/lib/igniter/server/config.rb +27 -0
  99. data/lib/igniter/server/handlers/base.rb +105 -0
  100. data/lib/igniter/server/handlers/contracts_handler.rb +15 -0
  101. data/lib/igniter/server/handlers/event_handler.rb +28 -0
  102. data/lib/igniter/server/handlers/execute_handler.rb +37 -0
  103. data/lib/igniter/server/handlers/health_handler.rb +32 -0
  104. data/lib/igniter/server/handlers/status_handler.rb +27 -0
  105. data/lib/igniter/server/http_server.rb +109 -0
  106. data/lib/igniter/server/rack_app.rb +35 -0
  107. data/lib/igniter/server/registry.rb +56 -0
  108. data/lib/igniter/server/router.rb +75 -0
  109. data/lib/igniter/server.rb +67 -0
  110. data/lib/igniter/stream_loop.rb +80 -0
  111. data/lib/igniter/supervisor.rb +167 -0
  112. data/lib/igniter/version.rb +1 -1
  113. data/lib/igniter.rb +14 -0
  114. metadata +92 -2
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ module Igniter
6
+ module Server
7
+ # Transport-agnostic HTTP router.
8
+ # Receives (method, path, body_string) and returns { status:, body:, headers: }.
9
+ # Used by both HttpServer (TCPServer) and RackApp.
10
+ class Router
11
+ ROUTES = [
12
+ { method: "GET", pattern: %r{\A/v1/health\z}, handler: :health },
13
+ { method: "GET", pattern: %r{\A/v1/contracts\z}, handler: :contracts },
14
+ { method: "POST", pattern: %r{\A/v1/contracts/(?<name>[^/]+)/execute\z}, handler: :execute },
15
+ { method: "POST", pattern: %r{\A/v1/contracts/(?<name>[^/]+)/events\z}, handler: :event },
16
+ { method: "GET", pattern: %r{\A/v1/executions/(?<id>[^/]+)\z}, handler: :status }
17
+ ].freeze
18
+
19
+ def initialize(config)
20
+ @config = config
21
+ end
22
+
23
+ # Main dispatch entry point — called by both WEBrick and Rack adapters.
24
+ def call(http_method, path, body_str) # rubocop:disable Metrics/MethodLength,Metrics/AbcSize
25
+ method_uc = http_method.to_s.upcase
26
+ ROUTES.each do |route|
27
+ next unless route[:method] == method_uc
28
+
29
+ match = route[:pattern].match(path)
30
+ next unless match
31
+
32
+ params = match.named_captures.transform_keys(&:to_sym)
33
+ body = parse_body(body_str)
34
+
35
+ handler = build_handler(route[:handler])
36
+ return handler.call(params: params, body: body)
37
+ end
38
+
39
+ not_found_response(path)
40
+ rescue JSON::ParserError => e
41
+ { status: 400, body: JSON.generate({ error: "Invalid JSON: #{e.message}" }), headers: json_ct }
42
+ end
43
+
44
+ private
45
+
46
+ def build_handler(key)
47
+ registry = @config.registry
48
+ store = @config.store
49
+ node_url = "http://#{@config.host}:#{@config.port}"
50
+
51
+ case key
52
+ when :health then Handlers::HealthHandler.new(registry, store, node_url: node_url)
53
+ when :contracts then Handlers::ContractsHandler.new(registry, store)
54
+ when :execute then Handlers::ExecuteHandler.new(registry, store)
55
+ when :event then Handlers::EventHandler.new(registry, store)
56
+ when :status then Handlers::StatusHandler.new(registry, store)
57
+ end
58
+ end
59
+
60
+ def parse_body(str)
61
+ return {} if str.nil? || str.strip.empty?
62
+
63
+ JSON.parse(str)
64
+ end
65
+
66
+ def not_found_response(path)
67
+ { status: 404, body: JSON.generate({ error: "Not found: #{path}" }), headers: json_ct }
68
+ end
69
+
70
+ def json_ct
71
+ { "Content-Type" => "application/json" }
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "igniter"
4
+ require "json"
5
+
6
+ # Define the top-level Server module and Error class first,
7
+ # so subfiles can inherit from Igniter::Server::Error.
8
+ module Igniter
9
+ module Server
10
+ class Error < Igniter::Error; end
11
+ end
12
+ end
13
+
14
+ require_relative "server/registry"
15
+ require_relative "server/config"
16
+ require_relative "server/router"
17
+ require_relative "server/http_server"
18
+ require_relative "server/rack_app"
19
+ require_relative "server/client"
20
+ require_relative "server/handlers/base"
21
+ require_relative "server/handlers/health_handler"
22
+ require_relative "server/handlers/contracts_handler"
23
+ require_relative "server/handlers/execute_handler"
24
+ require_relative "server/handlers/event_handler"
25
+ require_relative "server/handlers/status_handler"
26
+
27
+ module Igniter
28
+ module Server
29
+ class << self
30
+ def config
31
+ @config ||= Config.new
32
+ end
33
+
34
+ def configure
35
+ yield config
36
+ self
37
+ end
38
+
39
+ # Start the built-in HTTP server (blocking).
40
+ def start(**options)
41
+ apply_options!(options)
42
+ HttpServer.new(config).start
43
+ end
44
+
45
+ # Return a Rack-compatible application for use with Puma/Unicorn/etc.
46
+ def rack_app
47
+ RackApp.new(config)
48
+ end
49
+
50
+ # Reset configuration (useful in tests).
51
+ def reset!
52
+ @config = nil
53
+ end
54
+
55
+ private
56
+
57
+ def apply_options!(options) # rubocop:disable Metrics/AbcSize
58
+ config.port = options[:port] if options[:port]
59
+ config.host = options[:host] if options[:host]
60
+ config.store = options[:store] if options[:store]
61
+ return unless options[:contracts].is_a?(Hash)
62
+
63
+ options[:contracts].each { |name, klass| config.register(name.to_s, klass) }
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Igniter
4
+ # Runs an Igniter contract in a continuous tick-loop.
5
+ #
6
+ # Each tick resolves the contract with the current inputs and delivers the
7
+ # result to the on_result callback. Useful for sensor polling, feed
8
+ # processing, or any recurring computation.
9
+ #
10
+ # stream = Igniter::StreamLoop.new(
11
+ # contract: SensorContract,
12
+ # tick_interval: 0.1,
13
+ # inputs: { sensor_id: "temp-1", threshold: 25.0 },
14
+ # on_result: ->(result) { puts result.status },
15
+ # on_error: ->(err) { warn err.message }
16
+ # )
17
+ #
18
+ # stream.start
19
+ # stream.update_inputs(threshold: 30.0) # hot-swap inputs between ticks
20
+ # stream.stop
21
+ #
22
+ class StreamLoop
23
+ def initialize(contract:, tick_interval: 1.0, inputs: {}, on_result: nil, on_error: nil)
24
+ @contract_class = contract
25
+ @tick_interval = tick_interval.to_f
26
+ @on_result = on_result
27
+ @on_error = on_error
28
+ @mutex = Mutex.new
29
+ @current_inputs = inputs.dup
30
+ @running = false
31
+ @thread = nil
32
+ end
33
+
34
+ # Start the loop in a background thread. Returns self.
35
+ def start
36
+ @running = true
37
+ @thread = Thread.new { loop_body }
38
+ @thread.abort_on_exception = false
39
+ self
40
+ end
41
+
42
+ # Stop the loop and wait for the current tick to finish.
43
+ def stop(timeout: 5)
44
+ @running = false
45
+ @thread&.join(timeout)
46
+ self
47
+ end
48
+
49
+ # Merge +new_inputs+ into the current input set. Takes effect on the next tick.
50
+ def update_inputs(new_inputs)
51
+ @mutex.synchronize { @current_inputs.merge!(new_inputs) }
52
+ self
53
+ end
54
+
55
+ def alive?
56
+ @thread&.alive? || false
57
+ end
58
+
59
+ private
60
+
61
+ def loop_body
62
+ while @running
63
+ tick_start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
64
+ run_tick
65
+ elapsed = Process.clock_gettime(Process::CLOCK_MONOTONIC) - tick_start
66
+ sleep_for = [@tick_interval - elapsed, 0].max
67
+ sleep(sleep_for) if sleep_for.positive? && @running
68
+ end
69
+ end
70
+
71
+ def run_tick
72
+ inputs = @mutex.synchronize { @current_inputs.dup }
73
+ contract = @contract_class.new(**inputs)
74
+ contract.resolve_all
75
+ @on_result&.call(contract.result)
76
+ rescue StandardError => e
77
+ @on_error&.call(e)
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,167 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Igniter
4
+ # Supervises a group of agents and restarts them when they crash.
5
+ #
6
+ # Subclass Supervisor and declare children with the class-level DSL:
7
+ #
8
+ # class AppSupervisor < Igniter::Supervisor
9
+ # strategy :one_for_one # default
10
+ # max_restarts 5, within: 60 # default
11
+ #
12
+ # children do |c|
13
+ # c.worker :counter, CounterAgent
14
+ # c.worker :logger, LoggerAgent, initial_state: { level: :info }
15
+ # end
16
+ # end
17
+ #
18
+ # sup = AppSupervisor.start
19
+ # sup.child(:counter).send(:increment, by: 1)
20
+ # sup.stop
21
+ #
22
+ # Restart strategies:
23
+ # :one_for_one — restart only the crashed agent (default)
24
+ # :one_for_all — stop all agents and restart them all when any one crashes
25
+ #
26
+ # Restart budget: if more than +max_restarts+ crashes happen within +within+
27
+ # seconds, the supervisor logs the failure and stops trying to restart.
28
+ #
29
+ class Supervisor
30
+ class RestartBudgetExceeded < Igniter::Error; end
31
+
32
+ # ── ChildSpec ────────────────────────────────────────────────────────────
33
+
34
+ ChildSpec = Struct.new(:name, :agent_class, :init_opts, keyword_init: true)
35
+
36
+ class ChildSpecBuilder
37
+ attr_reader :specs
38
+
39
+ def initialize
40
+ @specs = []
41
+ end
42
+
43
+ def worker(name, agent_class, **opts)
44
+ @specs << ChildSpec.new(name: name.to_sym, agent_class: agent_class, init_opts: opts)
45
+ end
46
+ end
47
+
48
+ # ── Class-level defaults ─────────────────────────────────────────────────
49
+
50
+ @strategy = :one_for_one
51
+ @max_restarts = 5
52
+ @restart_window = 60
53
+ @spec_builder = ChildSpecBuilder.new
54
+
55
+ class << self
56
+ def inherited(subclass)
57
+ super
58
+ subclass.instance_variable_set(:@strategy, :one_for_one)
59
+ subclass.instance_variable_set(:@max_restarts, 5)
60
+ subclass.instance_variable_set(:@restart_window, 60)
61
+ subclass.instance_variable_set(:@spec_builder, ChildSpecBuilder.new)
62
+ end
63
+
64
+ def strategy(sym)
65
+ @strategy = sym
66
+ end
67
+
68
+ def max_restarts(count, within:)
69
+ @max_restarts = count
70
+ @restart_window = within
71
+ end
72
+
73
+ def children(&block)
74
+ block.call(@spec_builder)
75
+ end
76
+
77
+ def child_specs
78
+ @spec_builder.specs
79
+ end
80
+
81
+ def start
82
+ new.tap(&:start_all)
83
+ end
84
+ end
85
+
86
+ # ── Instance ─────────────────────────────────────────────────────────────
87
+
88
+ def initialize
89
+ @refs = {}
90
+ @specs_by_name = {}
91
+ @restart_log = []
92
+ @mutex = Mutex.new
93
+ end
94
+
95
+ def start_all
96
+ self.class.child_specs.each do |spec|
97
+ @specs_by_name[spec.name] = spec
98
+ start_child(spec)
99
+ end
100
+ end
101
+
102
+ # Return the Ref for a named child. Returns nil if not found.
103
+ def child(name)
104
+ @mutex.synchronize { @refs[name.to_sym] }
105
+ end
106
+
107
+ # Stop all children gracefully.
108
+ def stop
109
+ refs = @mutex.synchronize { @refs.values.dup }
110
+ refs.each do |ref|
111
+ ref.stop
112
+ rescue StandardError
113
+ nil
114
+ end
115
+ self
116
+ end
117
+
118
+ private
119
+
120
+ def start_child(spec)
121
+ opts = spec.init_opts.dup
122
+ opts[:on_crash] = ->(error) { handle_crash(spec, error) }
123
+ ref = spec.agent_class.start(**opts)
124
+ @mutex.synchronize { @refs[spec.name] = ref }
125
+ ref
126
+ end
127
+
128
+ def handle_crash(spec, _error)
129
+ check_restart_budget!
130
+
131
+ case self.class.instance_variable_get(:@strategy)
132
+ when :one_for_one
133
+ start_child(spec)
134
+ when :one_for_all
135
+ stop_all_children
136
+ self.class.child_specs.each { |s| start_child(s) }
137
+ end
138
+ rescue RestartBudgetExceeded => e
139
+ warn "Igniter::Supervisor #{self.class.name}: #{e.message}"
140
+ end
141
+
142
+ def check_restart_budget! # rubocop:disable Metrics/MethodLength
143
+ now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
144
+ window = self.class.instance_variable_get(:@restart_window).to_f
145
+ max = self.class.instance_variable_get(:@max_restarts)
146
+
147
+ @mutex.synchronize do
148
+ @restart_log.reject! { |t| now - t > window }
149
+ @restart_log << now
150
+
151
+ if @restart_log.size > max
152
+ raise RestartBudgetExceeded,
153
+ "#{@restart_log.size} crashes in #{window}s (max=#{max})"
154
+ end
155
+ end
156
+ end
157
+
158
+ def stop_all_children
159
+ refs = @mutex.synchronize { @refs.values.dup }
160
+ refs.each do |ref|
161
+ ref.stop(timeout: 2)
162
+ rescue StandardError
163
+ nil
164
+ end
165
+ end
166
+ end
167
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Igniter
4
- VERSION = "0.3.1"
4
+ VERSION = "0.4.3"
5
5
  end
data/lib/igniter.rb CHANGED
@@ -5,6 +5,8 @@ require_relative "igniter/errors"
5
5
  require_relative "igniter/type_system"
6
6
  require_relative "igniter/executor"
7
7
  require_relative "igniter/executor_registry"
8
+ require_relative "igniter/effect"
9
+ require_relative "igniter/effect_registry"
8
10
  require_relative "igniter/model"
9
11
  require_relative "igniter/compiler"
10
12
  require_relative "igniter/events"
@@ -32,6 +34,14 @@ module Igniter
32
34
  executor_registry.register(key, executor_class, **metadata)
33
35
  end
34
36
 
37
+ def effect_registry
38
+ @effect_registry ||= EffectRegistry.new
39
+ end
40
+
41
+ def register_effect(key, adapter_class, **metadata)
42
+ effect_registry.register(key, adapter_class, **metadata)
43
+ end
44
+
35
45
  def compile(&block)
36
46
  DSL::ContractBuilder.compile(&block)
37
47
  end
@@ -39,5 +49,9 @@ module Igniter
39
49
  def compile_schema(schema, name: nil)
40
50
  DSL::SchemaBuilder.compile(schema, name: name)
41
51
  end
52
+
53
+ def configure
54
+ yield self
55
+ end
42
56
  end
43
57
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: igniter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander
@@ -54,20 +54,38 @@ files:
54
54
  - docs/BACKLOG.md
55
55
  - docs/BRANCHES_V1.md
56
56
  - docs/COLLECTIONS_V1.md
57
+ - docs/DISTRIBUTED_CONTRACTS_V1.md
57
58
  - docs/EXECUTION_MODEL_V2.md
58
59
  - docs/IGNITER_CONCEPTS.md
60
+ - docs/LLM_V1.md
59
61
  - docs/PATTERNS.md
62
+ - docs/SERVER_V1.md
60
63
  - docs/STORE_ADAPTERS.md
61
64
  - examples/README.md
65
+ - examples/agents.rb
62
66
  - examples/async_store.rb
63
67
  - examples/basic_pricing.rb
64
68
  - examples/collection.rb
65
69
  - examples/collection_partial_failure.rb
66
70
  - examples/composition.rb
67
71
  - examples/diagnostics.rb
72
+ - examples/differential.rb
73
+ - examples/distributed_server.rb
74
+ - examples/distributed_workflow.rb
75
+ - examples/effects.rb
76
+ - examples/invariants.rb
68
77
  - examples/marketing_ergonomics.rb
78
+ - examples/order_pipeline.rb
79
+ - examples/provenance.rb
69
80
  - examples/ringcentral_routing.rb
81
+ - examples/saga.rb
70
82
  - lib/igniter.rb
83
+ - lib/igniter/agent.rb
84
+ - lib/igniter/agent/mailbox.rb
85
+ - lib/igniter/agent/message.rb
86
+ - lib/igniter/agent/ref.rb
87
+ - lib/igniter/agent/runner.rb
88
+ - lib/igniter/agent/state_holder.rb
71
89
  - lib/igniter/compiler.rb
72
90
  - lib/igniter/compiler/compiled_graph.rb
73
91
  - lib/igniter/compiler/graph_compiler.rb
@@ -75,9 +93,11 @@ files:
75
93
  - lib/igniter/compiler/validation_context.rb
76
94
  - lib/igniter/compiler/validation_pipeline.rb
77
95
  - lib/igniter/compiler/validator.rb
96
+ - lib/igniter/compiler/validators/await_validator.rb
78
97
  - lib/igniter/compiler/validators/callable_validator.rb
79
98
  - lib/igniter/compiler/validators/dependencies_validator.rb
80
99
  - lib/igniter/compiler/validators/outputs_validator.rb
100
+ - lib/igniter/compiler/validators/remote_validator.rb
81
101
  - lib/igniter/compiler/validators/type_compatibility_validator.rb
82
102
  - lib/igniter/compiler/validators/uniqueness_validator.rb
83
103
  - lib/igniter/contract.rb
@@ -87,35 +107,84 @@ files:
87
107
  - lib/igniter/diagnostics/introspection/formatters/mermaid_formatter.rb
88
108
  - lib/igniter/diagnostics/introspection/formatters/text_tree_formatter.rb
89
109
  - lib/igniter/diagnostics/report.rb
110
+ - lib/igniter/differential.rb
111
+ - lib/igniter/differential/divergence.rb
112
+ - lib/igniter/differential/formatter.rb
113
+ - lib/igniter/differential/report.rb
114
+ - lib/igniter/differential/runner.rb
90
115
  - lib/igniter/dsl.rb
91
116
  - lib/igniter/dsl/contract_builder.rb
92
117
  - lib/igniter/dsl/schema_builder.rb
118
+ - lib/igniter/effect.rb
119
+ - lib/igniter/effect_registry.rb
93
120
  - lib/igniter/errors.rb
94
121
  - lib/igniter/events.rb
95
122
  - lib/igniter/events/bus.rb
96
123
  - lib/igniter/events/event.rb
124
+ - lib/igniter/execution_report.rb
125
+ - lib/igniter/execution_report/builder.rb
126
+ - lib/igniter/execution_report/formatter.rb
127
+ - lib/igniter/execution_report/node_entry.rb
128
+ - lib/igniter/execution_report/report.rb
97
129
  - lib/igniter/executor.rb
98
130
  - lib/igniter/executor_registry.rb
99
131
  - lib/igniter/extensions.rb
100
132
  - lib/igniter/extensions/auditing.rb
101
133
  - lib/igniter/extensions/auditing/timeline.rb
134
+ - lib/igniter/extensions/differential.rb
135
+ - lib/igniter/extensions/execution_report.rb
102
136
  - lib/igniter/extensions/introspection.rb
103
137
  - lib/igniter/extensions/introspection/graph_formatter.rb
104
138
  - lib/igniter/extensions/introspection/plan_formatter.rb
105
139
  - lib/igniter/extensions/introspection/runtime_formatter.rb
140
+ - lib/igniter/extensions/invariants.rb
141
+ - lib/igniter/extensions/provenance.rb
106
142
  - lib/igniter/extensions/reactive.rb
107
143
  - lib/igniter/extensions/reactive/engine.rb
108
144
  - lib/igniter/extensions/reactive/matcher.rb
109
145
  - lib/igniter/extensions/reactive/reaction.rb
146
+ - lib/igniter/extensions/saga.rb
147
+ - lib/igniter/integrations/agents.rb
148
+ - lib/igniter/integrations/llm.rb
149
+ - lib/igniter/integrations/llm/config.rb
150
+ - lib/igniter/integrations/llm/context.rb
151
+ - lib/igniter/integrations/llm/executor.rb
152
+ - lib/igniter/integrations/llm/providers/anthropic.rb
153
+ - lib/igniter/integrations/llm/providers/base.rb
154
+ - lib/igniter/integrations/llm/providers/ollama.rb
155
+ - lib/igniter/integrations/llm/providers/openai.rb
156
+ - lib/igniter/integrations/rails.rb
157
+ - lib/igniter/integrations/rails/cable_adapter.rb
158
+ - lib/igniter/integrations/rails/contract_job.rb
159
+ - lib/igniter/integrations/rails/generators/contract/contract_generator.rb
160
+ - lib/igniter/integrations/rails/generators/install/install_generator.rb
161
+ - lib/igniter/integrations/rails/railtie.rb
162
+ - lib/igniter/integrations/rails/webhook_concern.rb
163
+ - lib/igniter/invariant.rb
110
164
  - lib/igniter/model.rb
165
+ - lib/igniter/model/await_node.rb
111
166
  - lib/igniter/model/branch_node.rb
112
167
  - lib/igniter/model/collection_node.rb
113
168
  - lib/igniter/model/composition_node.rb
114
169
  - lib/igniter/model/compute_node.rb
170
+ - lib/igniter/model/effect_node.rb
115
171
  - lib/igniter/model/graph.rb
116
172
  - lib/igniter/model/input_node.rb
117
173
  - lib/igniter/model/node.rb
118
174
  - lib/igniter/model/output_node.rb
175
+ - lib/igniter/model/remote_node.rb
176
+ - lib/igniter/property_testing.rb
177
+ - lib/igniter/property_testing/formatter.rb
178
+ - lib/igniter/property_testing/generators.rb
179
+ - lib/igniter/property_testing/result.rb
180
+ - lib/igniter/property_testing/run.rb
181
+ - lib/igniter/property_testing/runner.rb
182
+ - lib/igniter/provenance.rb
183
+ - lib/igniter/provenance/builder.rb
184
+ - lib/igniter/provenance/lineage.rb
185
+ - lib/igniter/provenance/node_trace.rb
186
+ - lib/igniter/provenance/text_formatter.rb
187
+ - lib/igniter/registry.rb
119
188
  - lib/igniter/runtime.rb
120
189
  - lib/igniter/runtime/cache.rb
121
190
  - lib/igniter/runtime/collection_result.rb
@@ -136,6 +205,27 @@ files:
136
205
  - lib/igniter/runtime/stores/file_store.rb
137
206
  - lib/igniter/runtime/stores/memory_store.rb
138
207
  - lib/igniter/runtime/stores/redis_store.rb
208
+ - lib/igniter/saga.rb
209
+ - lib/igniter/saga/compensation.rb
210
+ - lib/igniter/saga/compensation_record.rb
211
+ - lib/igniter/saga/executor.rb
212
+ - lib/igniter/saga/formatter.rb
213
+ - lib/igniter/saga/result.rb
214
+ - lib/igniter/server.rb
215
+ - lib/igniter/server/client.rb
216
+ - lib/igniter/server/config.rb
217
+ - lib/igniter/server/handlers/base.rb
218
+ - lib/igniter/server/handlers/contracts_handler.rb
219
+ - lib/igniter/server/handlers/event_handler.rb
220
+ - lib/igniter/server/handlers/execute_handler.rb
221
+ - lib/igniter/server/handlers/health_handler.rb
222
+ - lib/igniter/server/handlers/status_handler.rb
223
+ - lib/igniter/server/http_server.rb
224
+ - lib/igniter/server/rack_app.rb
225
+ - lib/igniter/server/registry.rb
226
+ - lib/igniter/server/router.rb
227
+ - lib/igniter/stream_loop.rb
228
+ - lib/igniter/supervisor.rb
139
229
  - lib/igniter/type_system.rb
140
230
  - lib/igniter/version.rb
141
231
  - sig/igniter.rbs
@@ -161,7 +251,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
161
251
  - !ruby/object:Gem::Version
162
252
  version: '0'
163
253
  requirements: []
164
- rubygems_version: 3.7.2
254
+ rubygems_version: 4.0.9
165
255
  specification_version: 4
166
256
  summary: Declarative dependency-graph runtime for business logic
167
257
  test_files: []