igniter-extensions 0.5.2

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 (100) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +381 -0
  3. data/lib/igniter/extensions/contracts/aggregate_pack.rb +103 -0
  4. data/lib/igniter/extensions/contracts/audit/builder.rb +132 -0
  5. data/lib/igniter/extensions/contracts/audit/event.rb +34 -0
  6. data/lib/igniter/extensions/contracts/audit/snapshot.rb +44 -0
  7. data/lib/igniter/extensions/contracts/audit_pack.rb +60 -0
  8. data/lib/igniter/extensions/contracts/branch_pack.rb +199 -0
  9. data/lib/igniter/extensions/contracts/capabilities/declaration.rb +31 -0
  10. data/lib/igniter/extensions/contracts/capabilities/error.rb +35 -0
  11. data/lib/igniter/extensions/contracts/capabilities/policy.rb +20 -0
  12. data/lib/igniter/extensions/contracts/capabilities/report.rb +47 -0
  13. data/lib/igniter/extensions/contracts/capabilities/violation.rb +30 -0
  14. data/lib/igniter/extensions/contracts/capabilities_pack.rb +146 -0
  15. data/lib/igniter/extensions/contracts/collection_pack.rb +212 -0
  16. data/lib/igniter/extensions/contracts/commerce_pack.rb +91 -0
  17. data/lib/igniter/extensions/contracts/compose_pack.rb +213 -0
  18. data/lib/igniter/extensions/contracts/content_addressing/cache.rb +59 -0
  19. data/lib/igniter/extensions/contracts/content_addressing/content_key.rb +63 -0
  20. data/lib/igniter/extensions/contracts/content_addressing/declaration.rb +47 -0
  21. data/lib/igniter/extensions/contracts/content_addressing_pack.rb +90 -0
  22. data/lib/igniter/extensions/contracts/creator/profile.rb +196 -0
  23. data/lib/igniter/extensions/contracts/creator/report.rb +85 -0
  24. data/lib/igniter/extensions/contracts/creator/scaffold.rb +461 -0
  25. data/lib/igniter/extensions/contracts/creator/scope.rb +79 -0
  26. data/lib/igniter/extensions/contracts/creator/wizard.rb +269 -0
  27. data/lib/igniter/extensions/contracts/creator/workflow.rb +189 -0
  28. data/lib/igniter/extensions/contracts/creator/workflow_step.rb +51 -0
  29. data/lib/igniter/extensions/contracts/creator/write_result.rb +48 -0
  30. data/lib/igniter/extensions/contracts/creator/write_step.rb +63 -0
  31. data/lib/igniter/extensions/contracts/creator/writer.rb +131 -0
  32. data/lib/igniter/extensions/contracts/creator_pack.rb +128 -0
  33. data/lib/igniter/extensions/contracts/dataflow/aggregate_operators.rb +119 -0
  34. data/lib/igniter/extensions/contracts/dataflow/aggregate_state.rb +60 -0
  35. data/lib/igniter/extensions/contracts/dataflow/builder.rb +66 -0
  36. data/lib/igniter/extensions/contracts/dataflow/collection_result.rb +70 -0
  37. data/lib/igniter/extensions/contracts/dataflow/diff.rb +37 -0
  38. data/lib/igniter/extensions/contracts/dataflow/item_result.rb +44 -0
  39. data/lib/igniter/extensions/contracts/dataflow/result.rb +58 -0
  40. data/lib/igniter/extensions/contracts/dataflow/session.rb +173 -0
  41. data/lib/igniter/extensions/contracts/dataflow/window_filter.rb +49 -0
  42. data/lib/igniter/extensions/contracts/dataflow_pack.rb +66 -0
  43. data/lib/igniter/extensions/contracts/debug/pack_audit.rb +181 -0
  44. data/lib/igniter/extensions/contracts/debug/pack_snapshot.rb +46 -0
  45. data/lib/igniter/extensions/contracts/debug/profile_snapshot.rb +50 -0
  46. data/lib/igniter/extensions/contracts/debug/report.rb +50 -0
  47. data/lib/igniter/extensions/contracts/debug_pack.rb +115 -0
  48. data/lib/igniter/extensions/contracts/differential/divergence.rb +37 -0
  49. data/lib/igniter/extensions/contracts/differential/formatter.rb +85 -0
  50. data/lib/igniter/extensions/contracts/differential/report.rb +83 -0
  51. data/lib/igniter/extensions/contracts/differential/runner.rb +136 -0
  52. data/lib/igniter/extensions/contracts/differential_pack.rb +61 -0
  53. data/lib/igniter/extensions/contracts/execution_report_pack.rb +38 -0
  54. data/lib/igniter/extensions/contracts/incremental/formatter.rb +60 -0
  55. data/lib/igniter/extensions/contracts/incremental/node_state.rb +30 -0
  56. data/lib/igniter/extensions/contracts/incremental/result.rb +65 -0
  57. data/lib/igniter/extensions/contracts/incremental/session.rb +146 -0
  58. data/lib/igniter/extensions/contracts/incremental_pack.rb +40 -0
  59. data/lib/igniter/extensions/contracts/invariants/builder.rb +27 -0
  60. data/lib/igniter/extensions/contracts/invariants/cases_report.rb +47 -0
  61. data/lib/igniter/extensions/contracts/invariants/error.rb +34 -0
  62. data/lib/igniter/extensions/contracts/invariants/invariant.rb +30 -0
  63. data/lib/igniter/extensions/contracts/invariants/report.rb +45 -0
  64. data/lib/igniter/extensions/contracts/invariants/suite.rb +36 -0
  65. data/lib/igniter/extensions/contracts/invariants/violation.rb +39 -0
  66. data/lib/igniter/extensions/contracts/invariants_pack.rb +88 -0
  67. data/lib/igniter/extensions/contracts/journal_pack.rb +55 -0
  68. data/lib/igniter/extensions/contracts/language/formula_pack.rb +185 -0
  69. data/lib/igniter/extensions/contracts/language/piecewise_pack.rb +166 -0
  70. data/lib/igniter/extensions/contracts/language/scale_pack.rb +147 -0
  71. data/lib/igniter/extensions/contracts/lookup_pack.rb +50 -0
  72. data/lib/igniter/extensions/contracts/mcp/creator_session.rb +105 -0
  73. data/lib/igniter/extensions/contracts/mcp/tool_argument.rb +35 -0
  74. data/lib/igniter/extensions/contracts/mcp/tool_definition.rb +33 -0
  75. data/lib/igniter/extensions/contracts/mcp/tool_result.rb +28 -0
  76. data/lib/igniter/extensions/contracts/mcp_pack.rb +335 -0
  77. data/lib/igniter/extensions/contracts/provenance/builder.rb +80 -0
  78. data/lib/igniter/extensions/contracts/provenance/lineage.rb +59 -0
  79. data/lib/igniter/extensions/contracts/provenance/node_trace.rb +53 -0
  80. data/lib/igniter/extensions/contracts/provenance/text_formatter.rb +62 -0
  81. data/lib/igniter/extensions/contracts/provenance_pack.rb +52 -0
  82. data/lib/igniter/extensions/contracts/reactive/builder.rb +43 -0
  83. data/lib/igniter/extensions/contracts/reactive/dispatch_result.rb +59 -0
  84. data/lib/igniter/extensions/contracts/reactive/engine.rb +79 -0
  85. data/lib/igniter/extensions/contracts/reactive/event.rb +36 -0
  86. data/lib/igniter/extensions/contracts/reactive/matcher.rb +20 -0
  87. data/lib/igniter/extensions/contracts/reactive/plan.rb +58 -0
  88. data/lib/igniter/extensions/contracts/reactive/subscription.rb +29 -0
  89. data/lib/igniter/extensions/contracts/reactive_pack.rb +169 -0
  90. data/lib/igniter/extensions/contracts/saga/compensation.rb +25 -0
  91. data/lib/igniter/extensions/contracts/saga/compensation_record.rb +28 -0
  92. data/lib/igniter/extensions/contracts/saga/compensation_set.rb +47 -0
  93. data/lib/igniter/extensions/contracts/saga/formatter.rb +39 -0
  94. data/lib/igniter/extensions/contracts/saga/result.rb +56 -0
  95. data/lib/igniter/extensions/contracts/saga/runner.rb +124 -0
  96. data/lib/igniter/extensions/contracts/saga_pack.rb +56 -0
  97. data/lib/igniter/extensions/contracts.rb +445 -0
  98. data/lib/igniter/extensions.rb +6 -0
  99. data/lib/igniter-extensions.rb +3 -0
  100. metadata +152 -0
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "content_addressing/content_key"
4
+ require_relative "content_addressing/cache"
5
+ require_relative "content_addressing/declaration"
6
+
7
+ module Igniter
8
+ module Extensions
9
+ module Contracts
10
+ module ContentAddressingPack
11
+ module_function
12
+
13
+ def manifest
14
+ Igniter::Contracts::PackManifest.new(
15
+ name: :extensions_content_addressing,
16
+ metadata: { category: :runtime, capabilities: [:pure] }
17
+ )
18
+ end
19
+
20
+ def install_into(kernel)
21
+ kernel
22
+ end
23
+
24
+ def cache
25
+ @cache ||= ContentAddressing::Cache.new
26
+ end
27
+
28
+ def cache=(value)
29
+ @cache = value
30
+ end
31
+
32
+ def reset_cache!
33
+ cache.clear
34
+ end
35
+
36
+ def stats
37
+ cache.stats
38
+ end
39
+
40
+ def content_key(inputs:, fingerprint: nil, callable: nil)
41
+ resolved_fingerprint =
42
+ if fingerprint
43
+ fingerprint
44
+ elsif callable
45
+ callable.respond_to?(:content_fingerprint) ? callable.content_fingerprint : default_fingerprint_for(callable)
46
+ else
47
+ raise ArgumentError, "content_key requires fingerprint: or callable:"
48
+ end
49
+
50
+ ContentAddressing::ContentKey.compute(fingerprint: resolved_fingerprint, inputs: inputs)
51
+ end
52
+
53
+ def content_addressed(callable: nil, fingerprint: nil, capabilities: [:pure], cache: self.cache, &block)
54
+ target = callable || block
55
+ raise ArgumentError, "content_addressed requires a callable or block" unless target
56
+
57
+ ContentAddressing::Declaration.new(
58
+ callable: target,
59
+ fingerprint: fingerprint || default_fingerprint_for(target),
60
+ cache: cache,
61
+ capabilities: capabilities
62
+ )
63
+ end
64
+
65
+ def pure(callable: nil, fingerprint: nil, cache: self.cache, &block)
66
+ content_addressed(
67
+ callable: callable,
68
+ fingerprint: fingerprint,
69
+ capabilities: [:pure],
70
+ cache: cache,
71
+ &block
72
+ )
73
+ end
74
+
75
+ def default_fingerprint_for(target)
76
+ if target.respond_to?(:content_fingerprint)
77
+ target.content_fingerprint
78
+ elsif target.is_a?(Proc)
79
+ file, line = target.source_location
80
+ "proc:#{file}:#{line}"
81
+ elsif target.respond_to?(:name) && !target.name.nil?
82
+ target.name
83
+ else
84
+ "anonymous_callable"
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,196 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Igniter
4
+ module Extensions
5
+ module Contracts
6
+ module Creator
7
+ class Profile
8
+ REGISTRY_CAPABILITIES = {
9
+ node: :nodes,
10
+ dsl_keyword: :dsl_keywords,
11
+ validator: :validators,
12
+ runtime_handler: :runtime_handlers,
13
+ diagnostic: :diagnostics_contributors,
14
+ effect: :effects,
15
+ executor: :executors,
16
+ dependency_pack: :pack_manifests
17
+ }.freeze
18
+
19
+ PRESETS = {
20
+ feature_node: {
21
+ kind: :feature,
22
+ capabilities: %i[node dsl_keyword validator runtime_handler],
23
+ dependency_hints: [],
24
+ summary: "feature node pack with DSL, validation, and runtime"
25
+ },
26
+ diagnostic_bundle: {
27
+ kind: :bundle,
28
+ capabilities: %i[dependency_pack diagnostic],
29
+ dependency_hints: %w[Igniter::Extensions::Contracts::ExecutionReportPack Igniter::Extensions::Contracts::ProvenancePack],
30
+ summary: "developer-facing diagnostics bundle pack"
31
+ },
32
+ operational_adapter: {
33
+ kind: :operational,
34
+ capabilities: %i[effect executor],
35
+ dependency_hints: [],
36
+ summary: "effect/executor operational adapter pack"
37
+ },
38
+ bundle_pack: {
39
+ kind: :bundle,
40
+ capabilities: %i[dependency_pack],
41
+ dependency_hints: [],
42
+ summary: "bundle pack that installs or presets other packs"
43
+ }
44
+ }.freeze
45
+
46
+ attr_reader :name,
47
+ :kind,
48
+ :capabilities,
49
+ :runtime_dependency_hints,
50
+ :development_dependency_hints,
51
+ :development_hints,
52
+ :summary
53
+
54
+ def self.available
55
+ PRESETS.keys
56
+ end
57
+
58
+ def self.build(profile: nil, kind: nil, capabilities: nil)
59
+ if profile
60
+ preset = PRESETS.fetch(profile.to_sym) do
61
+ raise ArgumentError, "unknown creator profile #{profile.inspect}"
62
+ end
63
+ effective_capabilities = Array(capabilities)
64
+ effective_capabilities = preset.fetch(:capabilities) if capabilities.nil? || effective_capabilities.empty?
65
+
66
+ runtime_hints = preset.fetch(:dependency_hints)
67
+ development_pack_hints = development_dependency_hints_for(effective_capabilities, runtime_hints)
68
+
69
+ return new(
70
+ name: profile,
71
+ kind: preset.fetch(:kind),
72
+ capabilities: effective_capabilities,
73
+ runtime_dependency_hints: runtime_hints,
74
+ development_dependency_hints: development_pack_hints,
75
+ development_hints: development_hints_for(effective_capabilities, runtime_hints, development_pack_hints),
76
+ summary: preset.fetch(:summary)
77
+ )
78
+ end
79
+
80
+ normalized_kind = (kind || infer_kind(Array(capabilities))).to_sym
81
+ inferred_capabilities = Array(capabilities)
82
+ inferred_capabilities = default_capabilities_for(normalized_kind) if inferred_capabilities.empty?
83
+ runtime_hints = dependency_hints_for(inferred_capabilities)
84
+ development_pack_hints = development_dependency_hints_for(inferred_capabilities, runtime_hints)
85
+
86
+ new(
87
+ name: :custom,
88
+ kind: normalized_kind,
89
+ capabilities: inferred_capabilities,
90
+ runtime_dependency_hints: runtime_hints,
91
+ development_dependency_hints: development_pack_hints,
92
+ development_hints: development_hints_for(inferred_capabilities, runtime_hints, development_pack_hints),
93
+ summary: "custom #{normalized_kind} authoring profile"
94
+ )
95
+ end
96
+
97
+ def self.dependency_hints_for(capabilities)
98
+ caps = capabilities.map(&:to_sym)
99
+ hints = []
100
+ if caps.include?(:diagnostic)
101
+ hints.concat([
102
+ "Igniter::Extensions::Contracts::ExecutionReportPack",
103
+ "Igniter::Extensions::Contracts::ProvenancePack"
104
+ ])
105
+ end
106
+ hints << "Igniter::Extensions::Contracts::DebugPack" if caps.include?(:dependency_pack) && caps.include?(:diagnostic)
107
+
108
+ hints.uniq
109
+ end
110
+
111
+ def self.development_dependency_hints_for(capabilities, dependency_hints)
112
+ caps = capabilities.map(&:to_sym)
113
+ hints = []
114
+ hints << "Igniter::Extensions::Contracts::DebugPack"
115
+ hints << "Igniter::Extensions::Contracts::JournalPack" if (caps & %i[effect executor]).any?
116
+ hints << "Igniter::Extensions::Contracts::DebugPack" if caps.include?(:dependency_pack) && caps.include?(:diagnostic)
117
+ hints.reject { |hint| dependency_hints.include?(hint) }.uniq
118
+ end
119
+
120
+ def self.development_hints_for(capabilities, dependency_hints, development_dependency_hints)
121
+ caps = capabilities.map(&:to_sym)
122
+ hints = []
123
+ hints << "use Igniter::Extensions::Contracts::DebugPack while authoring and validating the pack"
124
+ hints << "consider Igniter::Extensions::Contracts::JournalPack while developing effect/executor adapters" if (caps & %i[
125
+ effect executor
126
+ ]).any?
127
+ hints << "bundle diagnostics contributors only when they are truly additive and non-semantic" if caps.include?(:diagnostic)
128
+ hints << "review runtime dependency pack composition carefully: #{dependency_hints.join(", ")}" unless dependency_hints.empty?
129
+ hints << "keep development-only helper packs out of the runtime bundle surface: #{development_dependency_hints.join(", ")}" unless development_dependency_hints.empty?
130
+ hints.uniq
131
+ end
132
+
133
+ def self.default_capabilities_for(kind)
134
+ case kind.to_sym
135
+ when :feature
136
+ %i[node dsl_keyword validator runtime_handler]
137
+ when :operational
138
+ %i[effect executor]
139
+ when :bundle
140
+ %i[dependency_pack]
141
+ else
142
+ []
143
+ end
144
+ end
145
+
146
+ def self.infer_kind(capabilities)
147
+ caps = capabilities.map(&:to_sym)
148
+ return :operational if (caps & %i[effect executor]).any?
149
+ return :bundle if caps.include?(:dependency_pack) && (caps & %i[node dsl_keyword runtime_handler effect
150
+ executor]).empty?
151
+
152
+ :feature
153
+ end
154
+
155
+ def initialize(name:, kind:, capabilities:, runtime_dependency_hints:, development_dependency_hints:,
156
+ development_hints:, summary:)
157
+ @name = name.to_sym
158
+ @kind = kind.to_sym
159
+ @capabilities = capabilities.map(&:to_sym).uniq.freeze
160
+ @runtime_dependency_hints = runtime_dependency_hints.dup.freeze
161
+ @development_dependency_hints = development_dependency_hints.dup.freeze
162
+ @development_hints = development_hints.dup.freeze
163
+ @summary = summary
164
+ freeze
165
+ end
166
+
167
+ def dependency_hints
168
+ runtime_dependency_hints
169
+ end
170
+
171
+ def registry_capabilities
172
+ capabilities.filter_map { |capability| REGISTRY_CAPABILITIES[capability] }.uniq
173
+ end
174
+
175
+ def capability?(name)
176
+ capabilities.include?(name.to_sym)
177
+ end
178
+
179
+ def to_h
180
+ {
181
+ name: name,
182
+ kind: kind,
183
+ capabilities: capabilities,
184
+ registry_capabilities: registry_capabilities,
185
+ dependency_hints: dependency_hints,
186
+ runtime_dependency_hints: runtime_dependency_hints,
187
+ development_dependency_hints: development_dependency_hints,
188
+ development_hints: development_hints,
189
+ summary: summary
190
+ }
191
+ end
192
+ end
193
+ end
194
+ end
195
+ end
196
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "scaffold"
4
+
5
+ module Igniter
6
+ module Extensions
7
+ module Contracts
8
+ module Creator
9
+ class Report
10
+ attr_reader :scaffold, :audit
11
+
12
+ def initialize(scaffold:, audit: nil)
13
+ @scaffold = scaffold
14
+ @audit = audit
15
+ freeze
16
+ end
17
+
18
+ def next_steps
19
+ steps = [
20
+ "fill in #{scaffold.pack_file_path} using only public Igniter::Contracts APIs",
21
+ "run the generated spec and example",
22
+ "use Igniter::Extensions::Contracts.audit_pack(...) before finalize"
23
+ ]
24
+
25
+ case scaffold.profile.name
26
+ when :feature_node
27
+ steps << "implement node kind, DSL keyword, validator, and runtime handler"
28
+ when :operational_adapter
29
+ steps << "implement effect and executor handlers with typed invocation contracts"
30
+ when :diagnostic_bundle
31
+ steps << "compose the suggested diagnostic dependency packs and add one pack-specific diagnostics contributor"
32
+ when :bundle_pack
33
+ steps << "install dependency packs and keep the bundle free of hidden runtime mutation"
34
+ else
35
+ case scaffold.kind
36
+ when :feature
37
+ steps << "make sure declared node contracts, DSL, validators, and runtime handlers stay aligned"
38
+ when :operational
39
+ steps << "make sure executor/effect contracts stay aligned with typed invocation objects"
40
+ when :bundle
41
+ steps << "prefer explicit dependency installation over hidden runtime mutation"
42
+ end
43
+ end
44
+
45
+ steps << "review dependency hints: #{scaffold.profile.dependency_hints.join(", ")}" unless scaffold.profile.dependency_hints.empty?
46
+
47
+ scaffold.profile.development_hints.each do |hint|
48
+ steps << hint
49
+ end
50
+
51
+ scaffold.scope.packaging_hints.each do |hint|
52
+ steps << hint
53
+ end
54
+
55
+ steps
56
+ end
57
+
58
+ def quality_bar
59
+ {
60
+ public_contracts_only: true,
61
+ includes_spec: true,
62
+ includes_example: true,
63
+ includes_readme: true,
64
+ audit_ok: audit&.ok?,
65
+ authoring_profile: scaffold.profile.name,
66
+ target_scope: scaffold.scope.name,
67
+ runtime_dependency_hints: scaffold.profile.runtime_dependency_hints,
68
+ development_dependency_hints: scaffold.profile.development_dependency_hints
69
+ }
70
+ end
71
+
72
+ def to_h
73
+ payload = {
74
+ scaffold: scaffold.to_h,
75
+ next_steps: next_steps,
76
+ quality_bar: quality_bar
77
+ }
78
+ payload[:audit] = audit.to_h if audit
79
+ payload
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end