lutaml-xsd 1.1.13 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -1
  3. data/CLAUDE.md +18 -1
  4. data/Gemfile +2 -1
  5. data/Gemfile.lock +327 -0
  6. data/Rakefile +78 -1
  7. data/TODO.VISION.md +123 -0
  8. data/TODO.cleanup.md +43 -0
  9. data/TODO.conformance.md +99 -0
  10. data/TODO.docs-spa.md +46 -0
  11. data/TODO.interop.md +52 -0
  12. data/TODO.performance.md +80 -0
  13. data/TODO.som.md +47 -0
  14. data/benchmark/engines.rb +77 -0
  15. data/config/validation.yml +4 -0
  16. data/docs/CONFORMANCE.adoc +43 -0
  17. data/docs/JSON_SCHEMA.adoc +42 -0
  18. data/docs/superpowers/plans/2026-10-20-moxml-leptris-migration.md +735 -0
  19. data/docs/superpowers/specs/2026-10-20-moxml-leptris-migration-design.md +169 -0
  20. data/docs/superpowers/specs/2026-10-21-rule-engine-wiring-design.md +84 -0
  21. data/lib/lutaml/xsd/conformance/runner.rb +169 -0
  22. data/lib/lutaml/xsd/json_schema_exporter.rb +240 -0
  23. data/lib/lutaml/xsd/package_builder.rb +2 -2
  24. data/lib/lutaml/xsd/spa/schema_serializer.rb +12 -7
  25. data/lib/lutaml/xsd/validation/engine_context.rb +190 -0
  26. data/lib/lutaml/xsd/validation/rule_engine.rb +36 -18
  27. data/lib/lutaml/xsd/validation/rule_registry.rb +34 -0
  28. data/lib/lutaml/xsd/validation/rules/attribute_validation_rule.rb +126 -17
  29. data/lib/lutaml/xsd/validation/rules/content_model_validation_rule.rb +304 -194
  30. data/lib/lutaml/xsd/validation/rules/element_structure_rule.rb +25 -15
  31. data/lib/lutaml/xsd/validation/rules/identity_constraints_rule.rb +134 -0
  32. data/lib/lutaml/xsd/validation/rules/occurrence_validation_rule.rb +76 -25
  33. data/lib/lutaml/xsd/validation/rules/type_validation_rule.rb +134 -17
  34. data/lib/lutaml/xsd/validation/schema_definition_resolver.rb +254 -0
  35. data/lib/lutaml/xsd/validation/validation_configuration.rb +1 -0
  36. data/lib/lutaml/xsd/validation/validation_job.rb +70 -3
  37. data/lib/lutaml/xsd/validation/validation_rule.rb +44 -5
  38. data/lib/lutaml/xsd/validation/validator.rb +2 -1
  39. data/lib/lutaml/xsd/validation/xml_element.rb +2 -2
  40. data/lib/lutaml/xsd/version.rb +1 -1
  41. data/lib/lutaml/xsd.rb +14 -0
  42. data/lutaml-xsd.gemspec +2 -2
  43. metadata +27 -8
@@ -0,0 +1,254 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lutaml
4
+ module Xsd
5
+ module Validation
6
+ # Resolves instance elements to their schema declarations for the
7
+ # rule engine's element-scoped dispatch.
8
+ #
9
+ # Indexes top-level and inline element declarations across the
10
+ # repository's schemas. Namespace matching is strict (a target
11
+ # namespace matches only itself; no-namespace schemas match
12
+ # no-namespace instances) with a unique-name fallback for corpora
13
+ # whose instances omit namespaces.
14
+ #
15
+ # Deliberately not resolved here (rule-engine backlog): dynamic
16
+ # typing via xsi:type and derivation closure.
17
+ class SchemaDefinitionResolver
18
+ PARTICLE_KINDS = %i[sequence choice all].freeze
19
+
20
+ def initialize(repository)
21
+ @repository = repository
22
+ @namespaces = {}.compare_by_identity
23
+ @attributes = Hash.new { |hash, key| hash[key] = [] }
24
+ @elements = index_elements
25
+ end
26
+
27
+ # Owner schema's target namespace for a resolved declaration
28
+ # (parsed element models carry no owner-schema link).
29
+ #
30
+ # @param schema_element [Object]
31
+ # @return [String, nil]
32
+ def target_namespace_for(schema_element)
33
+ @namespaces[schema_element]
34
+ end
35
+
36
+ # @param name [String] local element name
37
+ # @param namespace_uri [String, nil] instance element namespace
38
+ # @return [Lutaml::Xml::Schema::Xsd::Element, nil]
39
+ def resolve(name, namespace_uri)
40
+ return nil if name.nil? || name.empty?
41
+
42
+ candidates = @elements[name]
43
+ return nil if candidates.empty?
44
+
45
+ exact = candidates.find do |_element, namespace, _kind|
46
+ namespace_matches?(namespace, namespace_uri)
47
+ end
48
+ return exact&.first if exact
49
+
50
+ # Unique-name fallback for instances that omit namespaces even
51
+ # though the schema declares one. A foreign namespace never
52
+ # falls back.
53
+ return nil unless namespace_uri.to_s.empty?
54
+
55
+ candidates.length == 1 ? candidates.first.first : nil
56
+ end
57
+
58
+ # Named type for an element's `type="prefix:Name"` reference.
59
+ #
60
+ # @param schema_element [Lutaml::Xml::Schema::Xsd::Element]
61
+ # @return [Object, nil]
62
+ def resolve_type(schema_element)
63
+ reference = schema_element.type
64
+ return nil if reference.nil? || reference.to_s.empty?
65
+
66
+ resolve_named_type(reference.to_s.split(":").last)
67
+ end
68
+
69
+ # Named complex or simple type by local name.
70
+ #
71
+ # @param local_name [String]
72
+ # @return [Object, nil]
73
+ def resolve_named_type(local_name)
74
+ return nil if local_name.nil? || local_name.empty?
75
+
76
+ schemas.each do |schema|
77
+ found = Array(schema.complex_type).find { |ct| ct.name == local_name }
78
+ return found if found
79
+
80
+ found = Array(schema.simple_type).find { |st| st.name == local_name }
81
+ return found if found
82
+ end
83
+ nil
84
+ end
85
+
86
+ # Global attribute declaration by name (for strict xs:anyAttribute
87
+ # checks).
88
+ #
89
+ # @param name [String] local attribute name
90
+ # @param namespace_uri [String, nil] instance attribute namespace
91
+ # @return [Lutaml::Xml::Schema::Xsd::Attribute, nil]
92
+ def resolve_attribute(name, namespace_uri)
93
+ return nil if name.nil? || name.empty?
94
+
95
+ candidates = @attributes[name]
96
+ return nil if candidates.empty?
97
+
98
+ exact = candidates.find do |_attribute, namespace|
99
+ namespace_matches?(namespace, namespace_uri)
100
+ end
101
+ return exact&.first if exact
102
+
103
+ return nil unless namespace_uri.to_s.empty?
104
+
105
+ candidates.length == 1 ? candidates.first.first : nil
106
+ end
107
+
108
+ # Content-model particle of the element's type, for occurrence
109
+ # and content-model rules.
110
+ #
111
+ # @param schema_element [Lutaml::Xml::Schema::Xsd::Element]
112
+ # @return [Object, nil]
113
+ def content_model_for(schema_element)
114
+ type = schema_element.complex_type || resolve_type(schema_element)
115
+ particle_for_type(type)
116
+ end
117
+
118
+ # Content-model particle of a NAMED type (for xsi:type overrides).
119
+ #
120
+ # @param local_name [String]
121
+ # @return [Object, nil]
122
+ def content_model_for_named(local_name)
123
+ particle_for_type(resolve_named_type(local_name))
124
+ end
125
+
126
+ private
127
+
128
+ def particle_for_type(type)
129
+ return nil unless type.respond_to?(:sequence) || type.respond_to?(:choice) || type.respond_to?(:all)
130
+
131
+ direct = Array(type.sequence).first ||
132
+ Array(type.choice).first || Array(type.all).first
133
+ return direct if direct
134
+
135
+ # Derived types keep their particles under complex_content.
136
+ if type.respond_to?(:complex_content) && type.complex_content
137
+ content = type.complex_content
138
+ part = Array(content.extension).first ||
139
+ Array(content.restriction).first
140
+ return particle_for_type(part) if part
141
+ end
142
+
143
+ nil
144
+ end
145
+
146
+ def schemas
147
+ @schemas ||= @repository.all_schemas.values
148
+ end
149
+
150
+ def namespace_matches?(schema_namespace, instance_namespace)
151
+ schema_namespace.to_s.empty? == instance_namespace.to_s.empty? &&
152
+ schema_namespace.to_s == instance_namespace.to_s
153
+ end
154
+
155
+ def index_elements
156
+ index = Hash.new { |hash, key| hash[key] = [] }
157
+ schemas.each do |schema|
158
+ index_schema(index, schema)
159
+ rescue StandardError
160
+ # Repositories can carry unparsable entries (broken packages);
161
+ # they contribute no declarations.
162
+ next
163
+ end
164
+ # Prefer top-level declarations over inline ones.
165
+ index.each_value do |candidates|
166
+ candidates.sort_by! { |_element, _ns, kind| kind == :top ? 0 : 1 }
167
+ end
168
+ index
169
+ end
170
+
171
+ def index_schema(index, schema)
172
+ namespace = schema.target_namespace
173
+ Array(schema.element).each do |element|
174
+ index_element(index, element, namespace, :top)
175
+ end
176
+ Array(schema.complex_type).each do |complex_type|
177
+ index_type(index, complex_type, namespace)
178
+ end
179
+ Array(schema.attribute).each do |attribute|
180
+ index_attribute(attribute, namespace)
181
+ end
182
+ end
183
+
184
+ def index_attribute(attribute, namespace)
185
+ return unless attribute
186
+ return if attribute.name.nil? || attribute.name.empty?
187
+
188
+ @namespaces[attribute] = namespace
189
+ @attributes[attribute.name] << [attribute, namespace]
190
+ end
191
+
192
+ def index_element(index, element, namespace, kind)
193
+ return unless element
194
+
195
+ @namespaces[element] = namespace
196
+ unless element.name.nil? || element.name.empty?
197
+ index[element.name] << [element, namespace, kind]
198
+ end
199
+ index_type(index, element.complex_type, namespace) if element.complex_type
200
+ end
201
+
202
+ def index_type(index, complex_type, namespace)
203
+ return unless complex_type
204
+
205
+ each_particle_element(complex_type) do |element|
206
+ index_element(index, element, namespace, :inline)
207
+ end
208
+ end
209
+
210
+ def each_particle_element(node, &)
211
+ return unless node
212
+
213
+ if node.is_a?(Array)
214
+ node.each { |child| each_particle_element(child, &) }
215
+ return
216
+ end
217
+ return if visited_particle?(node)
218
+
219
+ PARTICLE_KINDS.each do |kind|
220
+ next unless node.respond_to?(kind) # optional particle collections
221
+
222
+ Array(node.public_send(kind)).each do |particle|
223
+ next unless particle
224
+
225
+ Array(particle.element).each(&)
226
+ PARTICLE_KINDS.each do |nested|
227
+ next unless particle.respond_to?(nested)
228
+
229
+ each_particle_element(particle.public_send(nested), &)
230
+ end
231
+ end
232
+ end
233
+
234
+ return unless node.respond_to?(:complex_content) && node.complex_content
235
+
236
+ %i[extension restriction].each do |kind|
237
+ part = node.complex_content.public_send(kind)
238
+ each_particle_element(part, &) if part
239
+ end
240
+ end
241
+
242
+ # Particle collections can be cyclic in parsed models (a nested
243
+ # sequence pointing back at its container); visit each node once.
244
+ def visited_particle?(node)
245
+ @visited ||= {}.compare_by_identity
246
+ return true if @visited[node]
247
+
248
+ @visited[node] = true
249
+ false
250
+ end
251
+ end
252
+ end
253
+ end
254
+ end
@@ -237,6 +237,7 @@ module Lutaml
237
237
  "validate_facets" => true,
238
238
  "validate_content_models" => true,
239
239
  "validate_namespaces" => true,
240
+ "engine_validation" => true,
240
241
  },
241
242
  "error_reporting" => {
242
243
  "include_xpath" => true,
@@ -48,9 +48,10 @@ module Lutaml
48
48
  #
49
49
  # Performs validation in the following order:
50
50
  # 1. Parse XML document
51
- # 2. Validate structure (elements, namespaces)
52
- # 3. Validate types (simple and complex types)
53
- # 4. Validate constraints (occurrences, identity constraints)
51
+ # 2. Engine-native XSD validation (when the adapter provides one)
52
+ # 3. Validate structure (elements, namespaces)
53
+ # 4. Validate types (simple and complex types)
54
+ # 5. Validate constraints (occurrences, identity constraints)
54
55
  #
55
56
  # @return [ValidationResult] The complete validation result
56
57
  def execute
@@ -59,6 +60,8 @@ module Lutaml
59
60
  parse_xml
60
61
  return result_from_collector if should_stop_after_parse?
61
62
 
63
+ validate_root_declaration
64
+ run_engine_validation if @config.feature_enabled?(:engine_validation)
62
65
  validate_structure if @config.feature_enabled?(:validate_types)
63
66
  return result_from_collector if should_stop_after_structure?
64
67
 
@@ -68,11 +71,75 @@ module Lutaml
68
71
  validate_constraints if @config.feature_enabled?(:validate_occurrences)
69
72
  return result_from_collector if should_stop_after_constraints?
70
73
 
74
+ validate_identity if @config.feature_enabled?(:validate_identity_constraints)
75
+
71
76
  result_from_collector
72
77
  end
73
78
 
74
79
  private
75
80
 
81
+ # An instance whose root element is not declared by any schema in
82
+ # the package can never be valid; surface it explicitly (the
83
+ # engine's root-matching stays silent for unknown roots, and the
84
+ # rule engine skips unresolved declarations by design).
85
+ #
86
+ # @return [void]
87
+ def validate_root_declaration
88
+ root = @document&.root_element
89
+ return unless root
90
+
91
+ resolver = SchemaDefinitionResolver.new(@repository)
92
+ return if resolver.resolve(root.name, root.namespace_uri)
93
+
94
+ @result_collector.add_error(
95
+ ValidationError.new(
96
+ code: "element_not_allowed",
97
+ message: "Root element '#{root.name}' is not declared by any " \
98
+ "schema in the package",
99
+ severity: :error,
100
+ location: root.xpath,
101
+ context: {
102
+ element: root.name,
103
+ namespace: root.namespace_uri,
104
+ },
105
+ ),
106
+ )
107
+ rescue ResultCollector::StopValidationError
108
+ # Stop validation if configured to stop on first error
109
+ end
110
+
111
+ # Validate identity constraints (key/keyref/unique)
112
+ #
113
+ # @return [void]
114
+ def validate_identity
115
+ return unless @document && @rule_engine
116
+
117
+ @rule_engine.execute_category(:identity, @document, @repository)
118
+ rescue ResultCollector::StopValidationError
119
+ # Stop validation if configured to stop on first error
120
+ end
121
+
122
+ # Run engine-native XSD validation (Moxml::XSD) when the adapter
123
+ # supports it. Findings are additive to rule findings.
124
+ #
125
+ # @return [void]
126
+ def run_engine_validation
127
+ @engine_context ||= EngineContext.compile(@repository)
128
+ return unless @engine_context&.supported?
129
+
130
+ @engine_context.findings_for(@xml_content).each do |finding|
131
+ @result_collector.add_error(finding)
132
+ end
133
+ rescue StandardError => e
134
+ @result_collector.add_warning(
135
+ ValidationError.new(
136
+ code: "engine_validation_unavailable",
137
+ message: "Engine validation skipped: #{e.message}",
138
+ severity: :warning,
139
+ ),
140
+ )
141
+ end
142
+
76
143
  # Parse the XML content into a document object
77
144
  #
78
145
  # @return [void]
@@ -41,21 +41,60 @@ module Lutaml
41
41
 
42
42
  # Execute the validation rule
43
43
  #
44
- # This is the main entry point for validation. Subclasses must
45
- # implement this method to define their validation logic.
44
+ # This is the main entry point for validation. Rules are
45
+ # element-scoped: the engine calls this once per instance element
46
+ # with the schema argument selected by {#schema_argument}.
46
47
  #
47
48
  # @abstract
48
- # @param document [XmlDocument] The XML document to validate
49
- # @param repository [SchemaRepository] The schema repository
49
+ # @param xml_element [XmlElement] The instance element to validate
50
+ # @param schema_argument [Object, nil] What this rule validates
51
+ # against (schema element by default; see {#schema_argument})
50
52
  # @param collector [ResultCollector] Collector for validation results
53
+ # @param repository [SchemaDefinitionResolver, nil] Named-type
54
+ # resolution for `type="prefix:Name"` references
51
55
  # @return [void]
52
56
  #
53
57
  # @raise [NotImplementedError] if not implemented by subclass
54
- def validate(document, repository, collector)
58
+ def validate(xml_element, schema_argument, collector, repository: nil)
55
59
  raise NotImplementedError,
56
60
  "#{self.class} must implement #validate"
57
61
  end
58
62
 
63
+ # The schema object this rule validates the element against.
64
+ #
65
+ # Defaults to the resolved schema element; rules that need a
66
+ # different shape override this (e.g. the occurrence rule wants
67
+ # the content-model particle).
68
+ #
69
+ # @param schema_def [Object, nil] Resolved schema declaration
70
+ # @param repository [SchemaDefinitionResolver, nil]
71
+ # @return [Object, nil]
72
+ def schema_argument(schema_def, repository: nil) # rubocop:disable Lint/UnusedMethodArgument
73
+ # `repository` is part of the contract; the default selection
74
+ # does not consult it.
75
+ schema_def
76
+ end
77
+
78
+ # Whether the rule still runs when no schema declaration resolves.
79
+ #
80
+ # @return [Boolean]
81
+ def runs_without_schema?
82
+ false
83
+ end
84
+
85
+ XSI_NAMESPACE = "http://www.w3.org/2001/XMLSchema-instance"
86
+
87
+ # Find an xsi:-namespaced attribute on the instance element.
88
+ #
89
+ # @param xml_element [XmlElement]
90
+ # @param name [String] local name (e.g. "nil", "type")
91
+ # @return [XmlAttribute, nil]
92
+ def xsi_attribute(xml_element, name)
93
+ xml_element.attributes.find do |attr|
94
+ attr.name == name && attr.namespace_uri == XSI_NAMESPACE
95
+ end
96
+ end
97
+
59
98
  # Get the category of this validation rule
60
99
  #
61
100
  # Categories are used to group rules and execute them in phases:
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "engine_context"
3
4
  require_relative "validation_configuration"
4
5
  require_relative "validation_job"
5
6
  require_relative "validation_result"
@@ -118,7 +119,7 @@ module Lutaml
118
119
  # @return [RuleRegistry] The initialized rule registry
119
120
  def build_rule_registry
120
121
  require_relative "rule_registry"
121
- Validation::RuleRegistry.new(@config)
122
+ Validation::RuleRegistry.default(@config)
122
123
  end
123
124
  end
124
125
  end
@@ -42,7 +42,7 @@ module Lutaml
42
42
  #
43
43
  # @return [String, nil]
44
44
  def namespace_uri
45
- @moxml_element.namespace&.href
45
+ @moxml_element.namespace&.uri
46
46
  end
47
47
 
48
48
  # Get the element's namespace prefix
@@ -84,7 +84,7 @@ module Lutaml
84
84
  XmlAttribute.new(
85
85
  attr.name,
86
86
  attr.value,
87
- attr.namespace&.href,
87
+ attr.namespace&.uri,
88
88
  attr.namespace&.prefix,
89
89
  )
90
90
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Lutaml
4
4
  module Xsd
5
- VERSION = "1.1.13"
5
+ VERSION = "1.2.0"
6
6
  end
7
7
  end
data/lib/lutaml/xsd.rb CHANGED
@@ -60,3 +60,17 @@ require_relative "xsd/schema_dependency_analyzer"
60
60
  require_relative "xsd/type_hierarchy_analyzer"
61
61
  require_relative "xsd/xsd_spec_validator"
62
62
  require_relative "xsd/cli"
63
+
64
+ module Lutaml
65
+ module Xsd
66
+ # Public parsing entry point, as documented across docs/*.adoc.
67
+ # Delegates to lutaml-model's XML Schema parser.
68
+ #
69
+ # @param xsd [String] XSD content
70
+ # @param location [String, nil] base location for import/include paths
71
+ # @return [Lutaml::Xml::Schema::Xsd::Schema]
72
+ def self.parse(xsd, **)
73
+ Xml::Schema::Xsd.parse(xsd, **)
74
+ end
75
+ end
76
+ end
data/lutaml-xsd.gemspec CHANGED
@@ -34,9 +34,9 @@ Gem::Specification.new do |spec|
34
34
  spec.add_dependency "liquid", ">= 4.0", "< 6.0"
35
35
  spec.add_dependency "lutaml-model", "~> 0.8.114"
36
36
  spec.add_dependency "lutaml-store", "~> 0.3"
37
- spec.add_dependency "moxml"
37
+ spec.add_dependency "moxml", "~> 0.5.147"
38
38
  spec.add_dependency "paint", "~> 2.3"
39
- spec.add_dependency "rng", "~> 0.3.5"
39
+ spec.add_dependency "rng", "~> 0.3.9"
40
40
  spec.add_dependency "rubyzip", "~> 3.4"
41
41
  spec.add_dependency "table_tennis", "~> 0.0.7"
42
42
  spec.add_dependency "thor", "~> 1.0"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lutaml-xsd
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.13
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-10-19 00:00:00.000000000 Z
11
+ date: 2026-10-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: liquid
@@ -62,16 +62,16 @@ dependencies:
62
62
  name: moxml
63
63
  requirement: !ruby/object:Gem::Requirement
64
64
  requirements:
65
- - - ">="
65
+ - - "~>"
66
66
  - !ruby/object:Gem::Version
67
- version: '0'
67
+ version: 0.5.147
68
68
  type: :runtime
69
69
  prerelease: false
70
70
  version_requirements: !ruby/object:Gem::Requirement
71
71
  requirements:
72
- - - ">="
72
+ - - "~>"
73
73
  - !ruby/object:Gem::Version
74
- version: '0'
74
+ version: 0.5.147
75
75
  - !ruby/object:Gem::Dependency
76
76
  name: paint
77
77
  requirement: !ruby/object:Gem::Requirement
@@ -92,14 +92,14 @@ dependencies:
92
92
  requirements:
93
93
  - - "~>"
94
94
  - !ruby/object:Gem::Version
95
- version: 0.3.5
95
+ version: 0.3.9
96
96
  type: :runtime
97
97
  prerelease: false
98
98
  version_requirements: !ruby/object:Gem::Requirement
99
99
  requirements:
100
100
  - - "~>"
101
101
  - !ruby/object:Gem::Version
102
- version: 0.3.5
102
+ version: 0.3.9
103
103
  - !ruby/object:Gem::Dependency
104
104
  name: rubyzip
105
105
  requirement: !ruby/object:Gem::Requirement
@@ -190,9 +190,18 @@ files:
190
190
  - CLAUDE.md
191
191
  - CODE_OF_CONDUCT.md
192
192
  - Gemfile
193
+ - Gemfile.lock
193
194
  - LICENSE.md
194
195
  - README.adoc
195
196
  - Rakefile
197
+ - TODO.VISION.md
198
+ - TODO.cleanup.md
199
+ - TODO.conformance.md
200
+ - TODO.docs-spa.md
201
+ - TODO.interop.md
202
+ - TODO.performance.md
203
+ - TODO.som.md
204
+ - benchmark/engines.rb
196
205
  - bin/console
197
206
  - bin/setup
198
207
  - config/base_type_validators.yml
@@ -209,6 +218,7 @@ files:
209
218
  - docs/ARCHITECTURE.adoc
210
219
  - docs/CHANGELOG.md
211
220
  - docs/CLI.adoc
221
+ - docs/CONFORMANCE.adoc
212
222
  - docs/CONTRIBUTING.adoc
213
223
  - docs/DEPLOYMENT_GUIDE.adoc
214
224
  - docs/FAQ.adoc
@@ -217,6 +227,7 @@ files:
217
227
  - docs/INSTALLATION.adoc
218
228
  - docs/INTERACTIVE_SHELL_DEMO.adoc
219
229
  - docs/JING_ALGORITHM_PORTING_GUIDE.md
230
+ - docs/JSON_SCHEMA.adoc
220
231
  - docs/LIQUID_METHODS.adoc
221
232
  - docs/LXR_PACKAGES.adoc
222
233
  - docs/MAINTENANCE_GUIDE.adoc
@@ -266,6 +277,9 @@ files:
266
277
  - docs/schema_mapping.adoc
267
278
  - docs/schema_repository.adoc
268
279
  - docs/schemas/lxr-package-config.schema.json
280
+ - docs/superpowers/plans/2026-10-20-moxml-leptris-migration.md
281
+ - docs/superpowers/specs/2026-10-20-moxml-leptris-migration-design.md
282
+ - docs/superpowers/specs/2026-10-21-rule-engine-wiring-design.md
269
283
  - examples/01-simple/README.adoc
270
284
  - examples/01-simple/cli/run.sh
271
285
  - examples/01-simple/config.yml
@@ -431,6 +445,7 @@ files:
431
445
  - lib/lutaml/xsd/conflicts/namespace_conflict.rb
432
446
  - lib/lutaml/xsd/conflicts/schema_conflict.rb
433
447
  - lib/lutaml/xsd/conflicts/type_conflict.rb
448
+ - lib/lutaml/xsd/conformance/runner.rb
434
449
  - lib/lutaml/xsd/coverage_analyzer.rb
435
450
  - lib/lutaml/xsd/definition_extractor.rb
436
451
  - lib/lutaml/xsd/dependency_grapher.rb
@@ -453,6 +468,7 @@ files:
453
468
  - lib/lutaml/xsd/formatters/text_formatter.rb
454
469
  - lib/lutaml/xsd/formatters/yaml_formatter.rb
455
470
  - lib/lutaml/xsd/interactive_builder.rb
471
+ - lib/lutaml/xsd/json_schema_exporter.rb
456
472
  - lib/lutaml/xsd/namespace_mapping.rb
457
473
  - lib/lutaml/xsd/namespace_prefix_manager.rb
458
474
  - lib/lutaml/xsd/namespace_remapper.rb
@@ -533,6 +549,7 @@ files:
533
549
  - lib/lutaml/xsd/validation/base_types/qname_validator.rb
534
550
  - lib/lutaml/xsd/validation/base_types/string_validator.rb
535
551
  - lib/lutaml/xsd/validation/base_types/time_validator.rb
552
+ - lib/lutaml/xsd/validation/engine_context.rb
536
553
  - lib/lutaml/xsd/validation/facets/enumeration_facet_validator.rb
537
554
  - lib/lutaml/xsd/validation/facets/facet_validator.rb
538
555
  - lib/lutaml/xsd/validation/facets/facet_validator_registry.rb
@@ -553,8 +570,10 @@ files:
553
570
  - lib/lutaml/xsd/validation/rules/attribute_validation_rule.rb
554
571
  - lib/lutaml/xsd/validation/rules/content_model_validation_rule.rb
555
572
  - lib/lutaml/xsd/validation/rules/element_structure_rule.rb
573
+ - lib/lutaml/xsd/validation/rules/identity_constraints_rule.rb
556
574
  - lib/lutaml/xsd/validation/rules/occurrence_validation_rule.rb
557
575
  - lib/lutaml/xsd/validation/rules/type_validation_rule.rb
576
+ - lib/lutaml/xsd/validation/schema_definition_resolver.rb
558
577
  - lib/lutaml/xsd/validation/schema_location_extractor.rb
559
578
  - lib/lutaml/xsd/validation/schema_resolver.rb
560
579
  - lib/lutaml/xsd/validation/validation_configuration.rb