expressir 2.4.29-aarch64-linux → 2.4.35-aarch64-linux

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 (46) hide show
  1. checksums.yaml +4 -4
  2. data/.github/scripts/test_installed_gem.rb +18 -4
  3. data/.github/workflows/native-gems.yml +4 -1
  4. data/TODO.eengine/00-overview.md +39 -0
  5. data/TODO.eengine/01-resolution-diagnostics.md +30 -0
  6. data/TODO.eengine/02-check-catalog-completion.md +53 -0
  7. data/TODO.eengine/03-entity-computations.md +22 -0
  8. data/TODO.eengine/04-shtolo-rule-audit.md +32 -0
  9. data/TODO.eengine/05-shtolo-longform-flatten.md +12 -0
  10. data/TODO.eengine/06-population-p21.md +34 -0
  11. data/TODO.eengine/07-schema-compare-patch.md +25 -0
  12. data/TODO.eengine/08-official-corpus-gate.md +7 -0
  13. data/TODO.eengine/09-mim-mapping-parser.md +9 -0
  14. data/TODO.parity-ee/00-overview.md +1 -1
  15. data/TODO.suma-improvements/07-part28-xml.md +10 -13
  16. data/expressir.gemspec +5 -5
  17. data/lib/expressir/3.2/expressir_core.so +0 -0
  18. data/lib/expressir/3.3/expressir_core.so +0 -0
  19. data/lib/expressir/3.4/expressir_core.so +0 -0
  20. data/lib/expressir/4.0/expressir_core.so +0 -0
  21. data/lib/expressir/cli.rb +7 -0
  22. data/lib/expressir/commands/parity_inputs.rb +6 -1
  23. data/lib/expressir/commands/smrl_xml_index.rb +25 -0
  24. data/lib/expressir/commands.rb +2 -1
  25. data/lib/expressir/express/builder.rb +17 -5
  26. data/lib/expressir/express/builders/entity_decl_builder.rb +17 -5
  27. data/lib/expressir/express/checker.rb +191 -3
  28. data/lib/expressir/express/core.rb +1 -0
  29. data/lib/expressir/express/formatters/declarations_formatter.rb +21 -14
  30. data/lib/expressir/express/grammar/parser.rb +29 -1
  31. data/lib/expressir/express/pretty_formatter.rb +9 -14
  32. data/lib/expressir/express/schema_compare.rb +194 -0
  33. data/lib/expressir/express/shtolo.rb +194 -63
  34. data/lib/expressir/express.rb +2 -0
  35. data/lib/expressir/model/declarations/entity.rb +132 -0
  36. data/lib/expressir/model/declarations/schema.rb +37 -6
  37. data/lib/expressir/p21/builder.rb +92 -0
  38. data/lib/expressir/p21/grammar.rb +107 -0
  39. data/lib/expressir/p21/parser.rb +16 -0
  40. data/lib/expressir/p21/population.rb +35 -0
  41. data/lib/expressir/p21/validator.rb +213 -0
  42. data/lib/expressir/p21.rb +17 -0
  43. data/lib/expressir/version.rb +1 -1
  44. data/lib/expressir.rb +1 -0
  45. metadata +37 -19
  46. /data/lib/expressir/commands/{version.rb → version_command.rb} +0 -0
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "parsanol"
4
+
5
+ module Expressir
6
+ module P21
7
+ # ISO 10303-21 exchange-structure grammar (TODO.eengine/06 step 1).
8
+ # Parses the HEADER section and the DATA section's instance list
9
+ # into a capture tree; {Expressir::P21::PopulationBuilder} turns
10
+ # the tree into a {Expressir::P21::Population}.
11
+ #
12
+ # Reference: ISO 10303-21 exchange structure grammar
13
+ # (`~/src/mn/iso-10303-detached-docs/sources/iso-10303-21*/`);
14
+ # scope ladder in TODO.eengine/06 — the supported subset is the
15
+ # header FILE_* entities plus simple/complex data instances with
16
+ # lists, typed parameters, references, enumerations, binaries,
17
+ # strings, unset ($) and derived (*).
18
+ class Grammar < Parsanol::Parser
19
+ root(:exchange_structure)
20
+
21
+ rule(:comment) { str("/*") >> (str("*/").absent? >> any).repeat >> str("*/") }
22
+ rule(:ws?) { (match[" \t\r\n"] | comment).repeat }
23
+ rule(:ws1) { (match[" \t\r\n"] | comment).repeat(1) }
24
+ rule(:keyword) { match["!"].maybe >> match["A-Za-z0-9_"].repeat(1) }
25
+ rule(:entity_instance_name) { str("#") >> match["0-9"].repeat(1) }
26
+
27
+ rule(:string_literal) do
28
+ # ISO 10303-21: doubled quotes are escaped quotes
29
+ str("'") >> ((str("'").absent? >> any) | str("''")).repeat >> str("'")
30
+ end
31
+ rule(:binary_literal) { str('"') >> match["0-9A-Fa-f"].repeat >> str('"') }
32
+ rule(:enumeration) { str(".") >> match["A-Za-z0-9_"].repeat(1) >> str(".") }
33
+ rule(:unset) { str("$") }
34
+ rule(:derived) { str("*") }
35
+
36
+ rule(:parameter_list) do
37
+ str("(") >> ws? >>
38
+ (parameter.as(:parameter) >>
39
+ (str(",") >> ws? >> parameter.as(:parameter)).repeat).maybe >>
40
+ str(")") >> ws?
41
+ end
42
+
43
+ rule(:typed_parameter) do
44
+ keyword.as(:keyword) >> ws? >> parameter_list.as(:parameter_list)
45
+ end
46
+ rule(:list_parameter) { parameter_list }
47
+
48
+ rule(:number_literal) do
49
+ match["+-"].maybe >> match["0-9"].repeat(1) >>
50
+ (str(".") >> match["0-9"].repeat(1)).maybe >>
51
+ (match["Ee"] >> match["+-"].maybe >> match["0-9"].repeat(1)).maybe
52
+ end
53
+
54
+ rule(:parameter) do
55
+ typed_parameter.as(:typed_parameter) |
56
+ list_parameter.as(:parameter_list) |
57
+ entity_instance_name.as(:entity_instance_name) |
58
+ number_literal.as(:number_literal) |
59
+ enumeration.as(:enumeration) |
60
+ binary_literal.as(:binary_literal) |
61
+ string_literal.as(:string_literal) |
62
+ unset.as(:unset) | derived.as(:derived)
63
+ end
64
+
65
+ rule(:simple_record) do
66
+ keyword.as(:keyword) >> ws? >> parameter_list.as(:parameter_list)
67
+ end
68
+
69
+ rule(:subsuper_record) do
70
+ str("(") >> ws? >> simple_record.as(:simple_record).repeat(1) >>
71
+ str(")") >> ws?
72
+ end
73
+
74
+ rule(:simple_entity_instance) do
75
+ (entity_instance_name.as(:entity_instance_name) >> ws? >>
76
+ str("=") >> ws? >> simple_record.as(:simple_record) >>
77
+ str(";") >> ws?).as(:simple_entity_instance)
78
+ end
79
+ rule(:complex_entity_instance) do
80
+ (entity_instance_name.as(:entity_instance_name) >> ws? >>
81
+ str("=") >> ws? >> subsuper_record.as(:subsuper_record) >>
82
+ str(";") >> ws?).as(:complex_entity_instance)
83
+ end
84
+ rule(:entity_instance) { complex_entity_instance | simple_entity_instance }
85
+
86
+ rule(:header_entity) do
87
+ simple_record.as(:simple_record) >> str(";") >> ws?
88
+ end
89
+ rule(:header_section) do
90
+ str("HEADER;") >> ws? >> header_entity.repeat(1).as(:header_entity) >>
91
+ str("ENDSEC;") >> ws?
92
+ end
93
+ rule(:data_section) do
94
+ str("DATA;") >> ws? >>
95
+ (str("(") >> ws? >> parameter >> str(");") >> ws?).maybe >>
96
+ entity_instance.repeat.as(:instance_list) >>
97
+ str("ENDSEC;") >> ws?
98
+ end
99
+ rule(:exchange_structure) do
100
+ ws? >> str("ISO-10303-21;") >> ws? >>
101
+ header_section.as(:header_section) >>
102
+ data_section.as(:data_section) >>
103
+ str("END-ISO-10303-21;") >> ws?
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Expressir
4
+ module P21
5
+ # Facade: parse an ISO 10303-21 exchange structure into a
6
+ # {Population} (TODO.eengine/06 step 1).
7
+ module Parser
8
+ module_function
9
+
10
+ def parse(source)
11
+ tree = Grammar.new.parse(source)
12
+ Builder.build(tree)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Expressir
4
+ module P21
5
+ # A parsed ISO 10303-21 exchange structure (TODO.eengine/06).
6
+ # `header` — Hash: keyword => parameters (Array of values).
7
+ # `instances`— Hash: "#id" => Record.
8
+ #
9
+ # Values: String (string literal), Integer (reference id, keyed as
10
+ # "#id" in instances), Expressir::P21::Enumeration,
11
+ # Expressir::P21::Binary, Expressir::P21::TypedValue,
12
+ # Expressir::P21::ComplexRecord, :unset, :derived, or nested
13
+ # Arrays for lists.
14
+ class Population
15
+ attr_reader :header, :instances
16
+
17
+ def initialize(header: {}, instances: {})
18
+ @header = header
19
+ @instances = instances
20
+ end
21
+ end
22
+
23
+ # A data-section instance: `#12 = KEYWORD(param, ...) ;`
24
+ Record = Struct.new(:keyword, :params)
25
+
26
+ # `#21 = (A(...) B(...))` — complex entity instance.
27
+ ComplexRecord = Struct.new(:records)
28
+
29
+ TypedValue = Struct.new(:keyword, :value)
30
+
31
+ Enumeration = Struct.new(:name)
32
+
33
+ Binary = Struct.new(:hex)
34
+ end
35
+ end
@@ -0,0 +1,213 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Expressir
4
+ module P21
5
+ # Validates a {Population} against a loaded schema
6
+ # (TODO.eengine/06 step 2). Single-schema scope: instance keywords
7
+ # must be declared in the given schema; USE/REFERENCE visibility is
8
+ # a later ladder step.
9
+ #
10
+ # Mapping follows ISO 10303-21 clause 12: derived attributes are
11
+ # not mapped (a supertype attribute redeclared as DERIVED keeps its
12
+ # slot, valued `*`), inverse attributes are not mapped, and the
13
+ # value order is supertype attributes first.
14
+ module Validator
15
+ Note = Struct.new(:id, :severity, :instance, :message, keyword_init: true)
16
+
17
+ module_function
18
+
19
+ # `short_names` maps exchange-structure short names (ISO 10303-21,
20
+ # clause 12.3) to schema entity names, e.g. {"CPT" => "cartesian_point"}.
21
+ def validate(population, schema, short_names: nil)
22
+ short_names = short_names&.transform_keys(&:downcase)
23
+ notes = []
24
+ check_file_schema(notes, population, schema)
25
+ population.instances.each do |id, instance|
26
+ if instance.is_a?(ComplexRecord)
27
+ check_complex(notes, schema, population, id, instance, short_names)
28
+ else
29
+ check_simple(notes, schema, population, id, instance, short_names)
30
+ end
31
+ end
32
+ notes
33
+ end
34
+
35
+ def errors(notes)
36
+ notes.select { |note| note.severity == :error }
37
+ end
38
+
39
+ def warnings(notes)
40
+ notes.select { |note| note.severity == :warning }
41
+ end
42
+
43
+ def valid?(notes)
44
+ errors(notes).empty?
45
+ end
46
+
47
+ def note!(notes, id, severity, instance, message)
48
+ notes << Note.new(id: id, severity: severity, instance: instance,
49
+ message: message)
50
+ end
51
+
52
+ def check_file_schema(notes, population, schema)
53
+ declared = Array(population.header["FILE_SCHEMA"]).flatten.first
54
+ return unless declared && schema.id
55
+ return if declared.downcase == schema.id.downcase
56
+
57
+ note!(notes, :p21_schema_mismatch, :warning, nil,
58
+ "FILE_SCHEMA '#{declared}' does not match schema '#{schema.id}'")
59
+ end
60
+
61
+ def check_simple(notes, schema, population, id, record, short_names)
62
+ entity = find_entity(schema, record.keyword, short_names)
63
+ unless entity
64
+ note!(notes, :p21_unknown_entity, :error, id,
65
+ "#{record.keyword} is not declared in schema '#{schema.id}'")
66
+ return
67
+ end
68
+
69
+ check_params(notes, schema, population, id, record.params,
70
+ mapped_slots(entity))
71
+ end
72
+
73
+ def check_complex(notes, schema, population, id, complex, short_names)
74
+ pairs = complex.records.filter_map do |record|
75
+ entity = find_entity(schema, record.keyword, short_names)
76
+ unless entity
77
+ note!(notes, :p21_unknown_entity, :error, id,
78
+ "#{record.keyword} is not declared in schema '#{schema.id}'")
79
+ next nil
80
+ end
81
+
82
+ [record, entity]
83
+ end
84
+ return if pairs.empty?
85
+
86
+ check_clique(notes, id, pairs.map { |_, entity| entity })
87
+ pairs.each do |record, entity|
88
+ slots = explicit_attributes(entity).map { |attr| [attr, false] }
89
+ check_params(notes, schema, population, id, record.params, slots)
90
+ end
91
+ end
92
+
93
+ # A complex instance's records must form a valid supertype graph
94
+ # path: they share at least one common supertype.
95
+ def check_clique(notes, id, entities)
96
+ common = closure_keys(entities.first)
97
+ entities.drop(1).each { |entity| common &= closure_keys(entity) }
98
+ return unless common.empty?
99
+
100
+ note!(notes, :p21_complex_clique, :error, id,
101
+ "#{id}: complex records share no common supertype")
102
+ end
103
+
104
+ def closure_keys(entity)
105
+ keys = entity.supertype_closure.filter_map { |e| e.id&.downcase }
106
+ keys << entity.id&.downcase
107
+ end
108
+
109
+ # Part 21 value order: supertype attributes first; an attribute
110
+ # redeclared as DERIVED in the entity keeps its inherited slot,
111
+ # valued `*` (12.2.6).
112
+ def mapped_slots(entity)
113
+ own_derived_keys = own_derived_attributes(entity)
114
+ .filter_map { |attr| attr.id&.downcase }
115
+ inherited = entity.supertype_closure.flat_map do |supertype|
116
+ explicit_attributes(supertype)
117
+ end
118
+ inherited.map do |attr|
119
+ [attr, own_derived_keys.include?(attr.id&.downcase)]
120
+ end + explicit_attributes(entity).map { |attr| [attr, false] }
121
+ end
122
+
123
+ def check_params(notes, schema, population, id, params, slots)
124
+ if params.size != slots.size
125
+ note!(notes, :p21_arity_mismatch, :error, id,
126
+ "#{id}: #{params.size} values for #{slots.size} mapped attributes")
127
+ end
128
+
129
+ slots.zip(params).each do |(attr, derived_slot), value|
130
+ next if value.nil?
131
+
132
+ if derived_slot
133
+ next if value == :derived
134
+
135
+ note!(notes, :p21_derived_slot, :error, id,
136
+ "#{id}: attribute '#{attr.id}' redeclared DERIVED must be '*'")
137
+ next
138
+ end
139
+
140
+ check_value(notes, schema, population, id, attr, value)
141
+ end
142
+ end
143
+
144
+ def check_value(notes, schema, population, id, attr, value)
145
+ case value
146
+ when String
147
+ return unless value.match?(/\A#\d+\z/)
148
+
149
+ return if population.instances.key?(value)
150
+
151
+ note!(notes, :p21_unknown_reference, :error, id,
152
+ "#{id}: reference #{value} has no instance")
153
+ when :derived
154
+ note!(notes, :p21_derived_value, :error, id,
155
+ "#{id}: '*' outside a derived slot")
156
+ when TypedValue
157
+ return if find_entity(schema, value.keyword) || find_type(schema, value.keyword)
158
+
159
+ note!(notes, :p21_unknown_typed_keyword, :error, id,
160
+ "#{id}: typed parameter '#{value.keyword}' does not resolve")
161
+ when Enumeration
162
+ items = enumeration_items(schema, attr)
163
+ return unless items
164
+
165
+ names = items.filter_map { |item| item.id&.downcase }
166
+ return if names.include?(value.name.downcase)
167
+
168
+ note!(notes, :p21_enum_value, :error, id,
169
+ "#{id}: .#{value.name}. is not in attribute '#{attr.id}' enumeration")
170
+ when Array
171
+ value.each { |item| check_value(notes, schema, population, id, attr, item) }
172
+ end
173
+ end
174
+
175
+ def explicit_attributes(entity)
176
+ Array(entity.attributes)
177
+ .select { |attr| attr.instance_of?(Model::Declarations::Attribute) }
178
+ end
179
+
180
+ def own_derived_attributes(entity)
181
+ Array(entity.attributes)
182
+ .select { |attr| attr.instance_of?(Model::Declarations::DerivedAttribute) }
183
+ end
184
+
185
+ def find_entity(schema, keyword, short_names = nil)
186
+ key = keyword.downcase
187
+ Array(schema.entities).find { |entity| entity.id&.downcase == key } ||
188
+ resolve_short_name(schema, key, short_names)
189
+ end
190
+
191
+ def resolve_short_name(schema, key, short_names)
192
+ return nil unless short_names.is_a?(Hash) && short_names[key]
193
+
194
+ find_entity(schema, short_names[key], nil)
195
+ end
196
+
197
+ def find_type(schema, keyword)
198
+ Array(schema.types).find { |type| type.id&.downcase == keyword.downcase }
199
+ end
200
+
201
+ def enumeration_items(schema, attr)
202
+ type = attr&.type
203
+ return Array(type.items) if type.is_a?(Model::DataTypes::Enumeration)
204
+
205
+ return nil unless type.is_a?(Model::References::SimpleReference)
206
+
207
+ declaration = find_type(schema, type.id.to_s)
208
+ underlying = declaration&.underlying_type
209
+ underlying.is_a?(Model::DataTypes::Enumeration) ? Array(underlying.items) : nil
210
+ end
211
+ end
212
+ end
213
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Expressir
4
+ # ISO 10303-21 exchange-structure support (TODO.eengine/06).
5
+ module P21
6
+ autoload :Population, "#{__dir__}/p21/population"
7
+ autoload :Record, "#{__dir__}/p21/population"
8
+ autoload :ComplexRecord, "#{__dir__}/p21/population"
9
+ autoload :TypedValue, "#{__dir__}/p21/population"
10
+ autoload :Enumeration, "#{__dir__}/p21/population"
11
+ autoload :Binary, "#{__dir__}/p21/population"
12
+ autoload :Grammar, "#{__dir__}/p21/grammar"
13
+ autoload :Builder, "#{__dir__}/p21/builder"
14
+ autoload :Validator, "#{__dir__}/p21/validator"
15
+ autoload :Parser, "#{__dir__}/p21/parser"
16
+ end
17
+ end
@@ -3,6 +3,6 @@ module Expressir
3
3
  # autoload it (Ruby autoload only works for module/class constants, not
4
4
  # for string constants like `Expressir::VERSION`).
5
5
  module Version
6
- VERSION = "2.4.29".freeze
6
+ VERSION = "2.4.35".freeze
7
7
  end
8
8
  end
data/lib/expressir.rb CHANGED
@@ -30,6 +30,7 @@ module Expressir
30
30
 
31
31
  autoload :Version, "#{__dir__}/expressir/version"
32
32
  autoload :Mapping, "#{__dir__}/expressir/mapping"
33
+ autoload :P21, "#{__dir__}/expressir/p21"
33
34
 
34
35
  # Error classes — autoload the same errors.rb file from each name.
35
36
  # The first reference triggers the load; the file defines all 21 classes.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: expressir
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.29
4
+ version: 2.4.35
5
5
  platform: aarch64-linux
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-10-03 00:00:00.000000000 Z
11
+ date: 2026-10-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: base64
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: 0.1.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: 0.1.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: benchmark
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -70,16 +70,16 @@ dependencies:
70
70
  name: liquid
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ">="
73
+ - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '0'
75
+ version: '5'
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ">="
80
+ - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '0'
82
+ version: '5'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: lutaml-model
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -112,16 +112,16 @@ dependencies:
112
112
  name: nokogiri
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - ">="
115
+ - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: '0'
117
+ version: '1.19'
118
118
  type: :runtime
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - ">="
122
+ - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: '0'
124
+ version: '1.19'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: paint
127
127
  requirement: !ruby/object:Gem::Requirement
@@ -145,7 +145,7 @@ dependencies:
145
145
  version: 1.3.9
146
146
  - - ">="
147
147
  - !ruby/object:Gem::Version
148
- version: 1.3.9
148
+ version: 1.3.89
149
149
  type: :runtime
150
150
  prerelease: false
151
151
  version_requirements: !ruby/object:Gem::Requirement
@@ -155,7 +155,7 @@ dependencies:
155
155
  version: 1.3.9
156
156
  - - ">="
157
157
  - !ruby/object:Gem::Version
158
- version: 1.3.9
158
+ version: 1.3.89
159
159
  - !ruby/object:Gem::Dependency
160
160
  name: ruby-progressbar
161
161
  requirement: !ruby/object:Gem::Requirement
@@ -174,16 +174,16 @@ dependencies:
174
174
  name: rubyzip
175
175
  requirement: !ruby/object:Gem::Requirement
176
176
  requirements:
177
- - - ">="
177
+ - - "~>"
178
178
  - !ruby/object:Gem::Version
179
- version: '0'
179
+ version: '3.7'
180
180
  type: :runtime
181
181
  prerelease: false
182
182
  version_requirements: !ruby/object:Gem::Requirement
183
183
  requirements:
184
- - - ">="
184
+ - - "~>"
185
185
  - !ruby/object:Gem::Version
186
- version: '0'
186
+ version: '3.7'
187
187
  - !ruby/object:Gem::Dependency
188
188
  name: table_tennis
189
189
  requirement: !ruby/object:Gem::Requirement
@@ -287,6 +287,16 @@ files:
287
287
  - TODO.bugs/29-validate-ascii-god-class.md
288
288
  - TODO.bugs/30-unicode-map-extraction.md
289
289
  - TODO.bugs/README.md
290
+ - TODO.eengine/00-overview.md
291
+ - TODO.eengine/01-resolution-diagnostics.md
292
+ - TODO.eengine/02-check-catalog-completion.md
293
+ - TODO.eengine/03-entity-computations.md
294
+ - TODO.eengine/04-shtolo-rule-audit.md
295
+ - TODO.eengine/05-shtolo-longform-flatten.md
296
+ - TODO.eengine/06-population-p21.md
297
+ - TODO.eengine/07-schema-compare-patch.md
298
+ - TODO.eengine/08-official-corpus-gate.md
299
+ - TODO.eengine/09-mim-mapping-parser.md
290
300
  - TODO.max-perf/01-restore-ci-green.md
291
301
  - TODO.max-perf/02-streaming-parse-path.md
292
302
  - TODO.max-perf/03-cli-parallel-opt-in.md
@@ -445,10 +455,11 @@ files:
445
455
  - lib/expressir/commands/non_ascii_violation_collection.rb
446
456
  - lib/expressir/commands/package.rb
447
457
  - lib/expressir/commands/parity_inputs.rb
458
+ - lib/expressir/commands/smrl_xml_index.rb
448
459
  - lib/expressir/commands/validate.rb
449
460
  - lib/expressir/commands/validate_ascii.rb
450
461
  - lib/expressir/commands/validate_load.rb
451
- - lib/expressir/commands/version.rb
462
+ - lib/expressir/commands/version_command.rb
452
463
  - lib/expressir/commands/xsd.rb
453
464
  - lib/expressir/config.rb
454
465
  - lib/expressir/coverage.rb
@@ -536,6 +547,7 @@ files:
536
547
  - lib/expressir/express/remark_scanner.rb
537
548
  - lib/expressir/express/resolve_references_model_visitor.rb
538
549
  - lib/expressir/express/schema_block_scanner.rb
550
+ - lib/expressir/express/schema_compare.rb
539
551
  - lib/expressir/express/schema_head_formatter.rb
540
552
  - lib/expressir/express/schema_plain_source_formatter.rb
541
553
  - lib/expressir/express/schema_source_formatter.rb
@@ -648,6 +660,12 @@ files:
648
660
  - lib/expressir/model/supertype_expressions.rb
649
661
  - lib/expressir/model/supertype_expressions/binary_supertype_expression.rb
650
662
  - lib/expressir/model/supertype_expressions/oneof_supertype_expression.rb
663
+ - lib/expressir/p21.rb
664
+ - lib/expressir/p21/builder.rb
665
+ - lib/expressir/p21/grammar.rb
666
+ - lib/expressir/p21/parser.rb
667
+ - lib/expressir/p21/population.rb
668
+ - lib/expressir/p21/validator.rb
651
669
  - lib/expressir/package.rb
652
670
  - lib/expressir/package/builder.rb
653
671
  - lib/expressir/package/metadata.rb