expressir 2.1.29 → 2.1.31

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 (111) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/docs.yml +98 -0
  3. data/.github/workflows/links.yml +100 -0
  4. data/.github/workflows/rake.yml +4 -0
  5. data/.github/workflows/release.yml +5 -0
  6. data/.github/workflows/validate_schemas.yml +1 -1
  7. data/.gitignore +3 -0
  8. data/.rubocop.yml +1 -1
  9. data/.rubocop_todo.yml +209 -55
  10. data/Gemfile +2 -1
  11. data/README.adoc +650 -83
  12. data/docs/Gemfile +12 -0
  13. data/docs/_config.yml +141 -0
  14. data/docs/_guides/changes/changes-format.adoc +778 -0
  15. data/docs/_guides/changes/importing-eengine.adoc +898 -0
  16. data/docs/_guides/changes/index.adoc +396 -0
  17. data/docs/_guides/changes/programmatic-usage.adoc +1038 -0
  18. data/docs/_guides/changes/validating-changes.adoc +681 -0
  19. data/docs/_guides/cli/benchmark-performance.adoc +834 -0
  20. data/docs/_guides/cli/coverage-analysis.adoc +921 -0
  21. data/docs/_guides/cli/format-schemas.adoc +547 -0
  22. data/docs/_guides/cli/index.adoc +8 -0
  23. data/docs/_guides/cli/managing-changes.adoc +927 -0
  24. data/docs/_guides/cli/validate-ascii.adoc +645 -0
  25. data/docs/_guides/cli/validate-schemas.adoc +534 -0
  26. data/docs/_guides/index.adoc +165 -0
  27. data/docs/_guides/ler/creating-packages.adoc +664 -0
  28. data/docs/_guides/ler/index.adoc +305 -0
  29. data/docs/_guides/ler/loading-packages.adoc +707 -0
  30. data/docs/_guides/ler/package-formats.adoc +748 -0
  31. data/docs/_guides/ler/querying-packages.adoc +826 -0
  32. data/docs/_guides/ler/validating-packages.adoc +750 -0
  33. data/docs/_guides/liquid/basic-templates.adoc +813 -0
  34. data/docs/_guides/liquid/documentation-generation.adoc +1042 -0
  35. data/docs/_guides/liquid/drops-reference.adoc +829 -0
  36. data/docs/_guides/liquid/filters-and-tags.adoc +912 -0
  37. data/docs/_guides/liquid/index.adoc +468 -0
  38. data/docs/_guides/manifests/creating-manifests.adoc +483 -0
  39. data/docs/_guides/manifests/index.adoc +307 -0
  40. data/docs/_guides/manifests/resolving-manifests.adoc +557 -0
  41. data/docs/_guides/manifests/validating-manifests.adoc +713 -0
  42. data/docs/_guides/ruby-api/formatting-schemas.adoc +605 -0
  43. data/docs/_guides/ruby-api/index.adoc +257 -0
  44. data/docs/_guides/ruby-api/parsing-files.adoc +421 -0
  45. data/docs/_guides/ruby-api/search-engine.adoc +609 -0
  46. data/docs/_guides/ruby-api/working-with-repository.adoc +577 -0
  47. data/docs/_pages/data-model.adoc +665 -0
  48. data/docs/_pages/express-language.adoc +506 -0
  49. data/docs/_pages/getting-started.adoc +414 -0
  50. data/docs/_pages/index.adoc +116 -0
  51. data/docs/_pages/introduction.adoc +256 -0
  52. data/docs/_pages/ler-packages.adoc +837 -0
  53. data/docs/_pages/parsers.adoc +683 -0
  54. data/docs/_pages/schema-manifests.adoc +431 -0
  55. data/docs/_references/index.adoc +228 -0
  56. data/docs/_tutorials/creating-ler-package.adoc +735 -0
  57. data/docs/_tutorials/documentation-coverage.adoc +795 -0
  58. data/docs/_tutorials/index.adoc +221 -0
  59. data/docs/_tutorials/liquid-templates.adoc +806 -0
  60. data/docs/_tutorials/parsing-your-first-schema.adoc +522 -0
  61. data/docs/_tutorials/querying-schemas.adoc +751 -0
  62. data/docs/_tutorials/working-with-multiple-schemas.adoc +676 -0
  63. data/docs/index.adoc +242 -0
  64. data/docs/lychee.toml +84 -0
  65. data/examples/demo_ler_usage.sh +86 -0
  66. data/examples/ler/README.md +111 -0
  67. data/examples/ler/simple_example.ler +0 -0
  68. data/examples/ler/simple_schema.exp +33 -0
  69. data/examples/ler_build.rb +75 -0
  70. data/examples/ler_cli.rb +79 -0
  71. data/examples/ler_demo_complete.rb +276 -0
  72. data/examples/ler_query.rb +91 -0
  73. data/examples/ler_query_examples.rb +305 -0
  74. data/examples/ler_stats.rb +81 -0
  75. data/examples/phase3_demo.rb +159 -0
  76. data/examples/query_demo_simple.rb +131 -0
  77. data/expressir.gemspec +2 -0
  78. data/lib/expressir/changes/schema_change.rb +32 -22
  79. data/lib/expressir/changes/{edition_change.rb → version_change.rb} +3 -3
  80. data/lib/expressir/cli.rb +12 -4
  81. data/lib/expressir/commands/changes_import_eengine.rb +2 -2
  82. data/lib/expressir/commands/changes_validate.rb +1 -1
  83. data/lib/expressir/commands/manifest.rb +427 -0
  84. data/lib/expressir/commands/package.rb +1274 -0
  85. data/lib/expressir/commands/validate.rb +70 -37
  86. data/lib/expressir/commands/validate_ascii.rb +607 -0
  87. data/lib/expressir/commands/validate_load.rb +88 -0
  88. data/lib/expressir/express/formatter.rb +5 -1
  89. data/lib/expressir/express/formatters/remark_item_formatter.rb +25 -0
  90. data/lib/expressir/express/parser.rb +33 -0
  91. data/lib/expressir/manifest/resolver.rb +213 -0
  92. data/lib/expressir/manifest/validator.rb +195 -0
  93. data/lib/expressir/model/declarations/entity.rb +6 -0
  94. data/lib/expressir/model/dependency_resolver.rb +270 -0
  95. data/lib/expressir/model/indexes/entity_index.rb +103 -0
  96. data/lib/expressir/model/indexes/reference_index.rb +148 -0
  97. data/lib/expressir/model/indexes/type_index.rb +149 -0
  98. data/lib/expressir/model/interface_validator.rb +384 -0
  99. data/lib/expressir/model/repository.rb +400 -5
  100. data/lib/expressir/model/repository_validator.rb +295 -0
  101. data/lib/expressir/model/search_engine.rb +525 -0
  102. data/lib/expressir/model.rb +4 -94
  103. data/lib/expressir/package/builder.rb +200 -0
  104. data/lib/expressir/package/metadata.rb +81 -0
  105. data/lib/expressir/package/reader.rb +165 -0
  106. data/lib/expressir/schema_manifest.rb +11 -1
  107. data/lib/expressir/version.rb +1 -1
  108. data/lib/expressir.rb +16 -3
  109. metadata +115 -5
  110. data/docs/benchmarking.adoc +0 -107
  111. data/docs/liquid_drops.adoc +0 -1547
@@ -0,0 +1,750 @@
1
+ ---
2
+ title: Validating Packages
3
+ parent: LER Packages
4
+ grand_parent: Guides
5
+ nav_order: 4
6
+ ---
7
+
8
+ = Validating Packages
9
+
10
+ == Purpose
11
+
12
+ This guide explains how to validate LER package integrity and repository
13
+ consistency using both the CLI and Ruby API. Validation ensures packages are
14
+ complete, correct, and ready for production use.
15
+
16
+ == References
17
+
18
+ * link:index.html[LER Packages Overview]
19
+ * link:creating-packages.html[Creating Packages]
20
+ * link:loading-packages.html[Loading Packages]
21
+ * link:../ruby-api/working-with-repository.html[Working with Repository]
22
+
23
+ == Concepts
24
+
25
+ Package validation:: Checking package structure, metadata integrity, and
26
+ repository consistency.
27
+
28
+ Repository validator:: The [`RepositoryValidator`](../../lib/expressir/model/repository_validator.rb:11)
29
+ class that performs consistency checks.
30
+
31
+ Schema references:: Validation that all `USE FROM` and `REFERENCE FROM`
32
+ statements point to existing schemas.
33
+
34
+ Interface validation:: Checking that all interface items exist in referenced
35
+ schemas.
36
+
37
+ Completeness checks:: Optional validation for schema completeness (entities,
38
+ types, functions).
39
+
40
+ == Validation types
41
+
42
+ === Basic validation
43
+
44
+ Always performed:
45
+
46
+ Schema reference validation:: Verifies all referenced schemas exist
47
+ Interface item validation:: Checks interface items exist in target schemas
48
+ Circular dependency detection:: Identifies circular references (valid but noteworthy)
49
+
50
+ === Optional validation
51
+
52
+ Enabled with flags:
53
+
54
+ Strict mode:: Checks for unused schemas
55
+ Interface validation:: Detailed interface consistency checks
56
+ Completeness checks:: Validates schema completeness
57
+ Duplicate checks:: Finds duplicate interface aliases
58
+ Self-reference checks:: Detects self-referencing interfaces
59
+
60
+ == CLI validation
61
+
62
+ === Basic validation command
63
+
64
+ Use [`expressir package validate`](../../lib/expressir/commands/package.rb:150)
65
+ to validate packages:
66
+
67
+ [source,bash]
68
+ ----
69
+ # Basic validation
70
+ expressir package validate schemas.ler
71
+
72
+ # With verbose output
73
+ expressir package validate schemas.ler --verbose
74
+ ----
75
+
76
+ .Success output
77
+ [example]
78
+ ====
79
+ [source]
80
+ ----
81
+ ✓ Package is valid
82
+ ----
83
+ ====
84
+
85
+ .Error output
86
+ [example]
87
+ ====
88
+ [source]
89
+ ----
90
+ ✗ Validation failed
91
+
92
+ Errors (2):
93
+ 1. [missing_schema_reference] Interface references non-existent schema
94
+ Schema: action_schema
95
+ Referenced: missing_schema
96
+ 2. [missing_interface_item] Interface item not found
97
+ Schema: action_schema
98
+ Referenced: approval_schema
99
+ Item: missing_entity
100
+ ----
101
+ ====
102
+
103
+ === Validation options
104
+
105
+ ==== Strict mode
106
+
107
+ Enable strict validation for unused schema warnings:
108
+
109
+ [source,bash]
110
+ ----
111
+ expressir package validate schemas.ler --strict
112
+ ----
113
+
114
+ Strict mode checks:
115
+
116
+ * Unused schemas (not referenced by others)
117
+ * Isolated schema groups
118
+ * Orphaned schemas
119
+
120
+ ==== Interface validation
121
+
122
+ Enable detailed interface checking:
123
+
124
+ [source,bash]
125
+ ----
126
+ expressir package validate schemas.ler --check-interfaces
127
+ ----
128
+
129
+ Interface checks include:
130
+
131
+ * Interface item existence
132
+ * Interface consistency
133
+ * Cross-schema references
134
+ * Type compatibility
135
+
136
+ ==== Completeness validation
137
+
138
+ Check for schema completeness:
139
+
140
+ [source,bash]
141
+ ----
142
+ expressir package validate schemas.ler --check-completeness
143
+ ----
144
+
145
+ Completeness checks:
146
+
147
+ * Schemas with no entities
148
+ * Schemas with entities but no types
149
+ * Empty schemas
150
+ * Minimal schemas
151
+
152
+ ==== Duplicate checking
153
+
154
+ Find duplicate interface aliases:
155
+
156
+ [source,bash]
157
+ ----
158
+ expressir package validate schemas.ler --check-duplicates
159
+ ----
160
+
161
+ ==== Self-reference checking
162
+
163
+ Detect self-referencing interfaces:
164
+
165
+ [source,bash]
166
+ ----
167
+ expressir package validate schemas.ler --check-self-references
168
+ ----
169
+
170
+ ==== Detailed reports
171
+
172
+ Get detailed validation reports:
173
+
174
+ [source,bash]
175
+ ----
176
+ expressir package validate schemas.ler \
177
+ --check-interfaces \
178
+ --detailed
179
+ ----
180
+
181
+ Detailed reports include:
182
+
183
+ * Fix suggestions for each error
184
+ * Context information
185
+ * Related items
186
+ * Severity levels
187
+
188
+ ==== Combined validation
189
+
190
+ Use multiple options together:
191
+
192
+ [source,bash]
193
+ ----
194
+ expressir package validate schemas.ler \
195
+ --strict \
196
+ --check-interfaces \
197
+ --check-completeness \
198
+ --check-duplicates \
199
+ --check-self-references \
200
+ --detailed
201
+ ----
202
+
203
+ === Output formats
204
+
205
+ Choose output format:
206
+
207
+ [source,bash]
208
+ ----
209
+ # Text format (default)
210
+ expressir package validate schemas.ler
211
+
212
+ # JSON format
213
+ expressir package validate schemas.ler --format json
214
+
215
+ # YAML format
216
+ expressir package validate schemas.ler --format yaml
217
+ ----
218
+
219
+ .JSON output example
220
+ [example]
221
+ ====
222
+ [source,json]
223
+ ----
224
+ {
225
+ "valid?": false,
226
+ "errors": [
227
+ {
228
+ "type": "missing_schema_reference",
229
+ "schema": "action_schema",
230
+ "referenced_schema": "missing_schema",
231
+ "message": "Schema 'action_schema' references non-existent schema 'missing_schema'"
232
+ }
233
+ ],
234
+ "warnings": [
235
+ {
236
+ "type": "unused_schema",
237
+ "schema": "utility_schema",
238
+ "message": "Schema 'utility_schema' is not referenced by any other schema"
239
+ }
240
+ ]
241
+ }
242
+ ----
243
+ ====
244
+
245
+ == Ruby API validation
246
+
247
+ === Basic validation
248
+
249
+ Validate using the repository:
250
+
251
+ [source,ruby]
252
+ ----
253
+ require "expressir"
254
+
255
+ # Load package
256
+ repo = Expressir::Model::Repository.from_package("schemas.ler")
257
+
258
+ # Validate
259
+ validation = repo.validate
260
+
261
+ if validation[:valid?]
262
+ puts "✓ Package is valid"
263
+ else
264
+ puts "✗ Validation failed"
265
+ puts "Errors: #{validation[:errors].size}"
266
+ puts "Warnings: #{validation[:warnings].size}"
267
+ end
268
+ ----
269
+
270
+ === Validation with options
271
+
272
+ Enable additional checks:
273
+
274
+ [source,ruby]
275
+ ----
276
+ validation = repo.validate(
277
+ strict: true, # Enable strict mode
278
+ check_interfaces: true, # Detailed interface validation
279
+ check_completeness: true, # Check schema completeness
280
+ check_duplicates: true, # Check for duplicate aliases
281
+ check_self_references: true, # Check self-references
282
+ detailed: true # Generate detailed reports
283
+ )
284
+ ----
285
+
286
+ === Handling validation results
287
+
288
+ Process validation results:
289
+
290
+ [source,ruby]
291
+ ----
292
+ validation = repo.validate(strict: true, check_interfaces: true)
293
+
294
+ # Check if valid
295
+ if validation[:valid?]
296
+ puts "✓ Validation passed"
297
+ else
298
+ puts "✗ Validation failed with #{validation[:errors].size} errors"
299
+
300
+ # Display errors
301
+ validation[:errors].each_with_index do |error, i|
302
+ puts "\nError #{i + 1}: [#{error[:type]}]"
303
+ puts " Message: #{error[:message]}"
304
+ puts " Schema: #{error[:schema]}" if error[:schema]
305
+ puts " Referenced: #{error[:referenced_schema]}" if error[:referenced_schema]
306
+ puts " Item: #{error[:item]}" if error[:item]
307
+ puts " Fix: #{error[:fix_suggestion]}" if error[:fix_suggestion]
308
+ end
309
+ end
310
+
311
+ # Display warnings
312
+ if validation[:warnings]&.any?
313
+ puts "\nWarnings (#{validation[:warnings].size}):"
314
+
315
+ validation[:warnings].each_with_index do |warning, i|
316
+ puts "\nWarning #{i + 1}: [#{warning[:type]}]"
317
+ puts " Message: #{warning[:message]}"
318
+ puts " Schema: #{warning[:schema]}" if warning[:schema]
319
+ end
320
+ end
321
+
322
+ # Display detailed report if available
323
+ if validation[:interface_report]
324
+ puts "\n" + validation[:interface_report]
325
+ end
326
+ ----
327
+
328
+ === Validation in build pipeline
329
+
330
+ Validate before creating package:
331
+
332
+ [source,ruby]
333
+ ----
334
+ # Parse schemas
335
+ files = Dir.glob("schemas/**/*.exp")
336
+ repo = Expressir::Express::Parser.from_files(files)
337
+
338
+ # Validate before packaging
339
+ validation = repo.validate(
340
+ strict: true,
341
+ check_interfaces: true,
342
+ check_completeness: true
343
+ )
344
+
345
+ unless validation[:valid?]
346
+ puts "Validation failed - cannot create package"
347
+ validation[:errors].each do |error|
348
+ puts " - #{error[:message]}"
349
+ end
350
+ exit 1
351
+ end
352
+
353
+ # Create package
354
+ repo.export_to_package(
355
+ "output.ler",
356
+ name: "Validated Package",
357
+ version: "1.0.0"
358
+ )
359
+
360
+ puts "✓ Package created and validated"
361
+ ----
362
+
363
+ == Common validation errors
364
+
365
+ === Missing schema reference
366
+
367
+ .Error
368
+ [example]
369
+ ====
370
+ [source]
371
+ ----
372
+ Type: missing_schema_reference
373
+ Schema: action_schema
374
+ Referenced: geometric_model_schema
375
+ Message: Schema 'action_schema' references non-existent schema 'geometric_model_schema'
376
+ ----
377
+ ====
378
+
379
+ .Causes
380
+ [example]
381
+ ====
382
+ * Referenced schema not included in package
383
+ * Typo in schema name
384
+ * Schema file not found during build
385
+ * Missing dependency
386
+ ====
387
+
388
+ .Solutions
389
+ [example]
390
+ ====
391
+ 1. Add missing schema to package build
392
+ 2. Check spelling of schema references
393
+ 3. Verify all dependencies are included
394
+ 4. Use dependency resolver to find all schemas
395
+ ====
396
+
397
+ === Missing interface item
398
+
399
+ .Error
400
+ [example]
401
+ ====
402
+ [source]
403
+ ----
404
+ Type: missing_interface_item
405
+ Schema: action_schema
406
+ Referenced: approval_schema
407
+ Item: approval_status_item
408
+ Message: Interface item 'approval_status_item' not found in schema 'approval_schema'
409
+ ----
410
+ ====
411
+
412
+ .Causes
413
+ [example]
414
+ ====
415
+ * Item renamed or removed in target schema
416
+ * Typo in interface item name
417
+ * Wrong schema referenced
418
+ * Version mismatch between schemas
419
+ ====
420
+
421
+ .Solutions
422
+ [example]
423
+ ====
424
+ 1. Update interface to use correct item name
425
+ 2. Add missing item to target schema
426
+ 3. Remove obsolete interface item
427
+ 4. Sync schema versions
428
+ ====
429
+
430
+ === Circular dependency
431
+
432
+ .Warning
433
+ [example]
434
+ ====
435
+ [source]
436
+ ----
437
+ Type: circular_dependency
438
+ Cycle: action_schema -> approval_schema -> action_schema
439
+ Message: Circular dependency (valid in EXPRESS): action_schema -> approval_schema -> action_schema
440
+ ----
441
+ ====
442
+
443
+ .Note
444
+ [example]
445
+ ====
446
+ Circular dependencies are valid in EXPRESS but flagged as warnings for
447
+ awareness. Mutual `USE FROM` statements are common and acceptable.
448
+ ====
449
+
450
+ === Unused schema
451
+
452
+ .Warning (strict mode)
453
+ [example]
454
+ ====
455
+ [source]
456
+ ----
457
+ Type: unused_schema
458
+ Schema: utility_schema
459
+ Message: Schema 'utility_schema' is not referenced by any other schema
460
+ ----
461
+ ====
462
+
463
+ .Causes
464
+ [example]
465
+ ====
466
+ * Schema is entry point (no references expected)
467
+ * Schema is utility library
468
+ * Obsolete schema included accidentally
469
+ * Missing interface statements
470
+ ====
471
+
472
+ .Solutions
473
+ [example]
474
+ ====
475
+ 1. Verify schema is needed
476
+ 2. Add as documented entry point
477
+ 3. Remove if obsolete
478
+ 4. Add missing USE FROM/REFERENCE FROM
479
+ ====
480
+
481
+ === Empty schema
482
+
483
+ .Warning (completeness check)
484
+ [example]
485
+ ====
486
+ [source]
487
+ ----
488
+ Type: empty_schema
489
+ Schema: placeholder_schema
490
+ Message: Schema 'placeholder_schema' has no entities defined
491
+ ----
492
+ ====
493
+
494
+ .Causes
495
+ [example]
496
+ ====
497
+ * Work-in-progress schema
498
+ * Interface-only schema
499
+ * Template schema
500
+ * Incomplete development
501
+ ====
502
+
503
+ == Validation best practices
504
+
505
+ === Pre-deployment validation
506
+
507
+ Always validate before deploying:
508
+
509
+ [source,ruby]
510
+ ----
511
+ def deploy_package(package_path)
512
+ # Load package
513
+ repo = Expressir::Model::Repository.from_package(package_path)
514
+
515
+ # Comprehensive validation
516
+ validation = repo.validate(
517
+ strict: true,
518
+ check_interfaces: true,
519
+ check_completeness: true,
520
+ check_duplicates: true,
521
+ check_self_references: true
522
+ )
523
+
524
+ # Fail fast on errors
525
+ if !validation[:valid?]
526
+ raise "Package validation failed: #{validation[:errors].size} errors"
527
+ end
528
+
529
+ # Log warnings
530
+ if validation[:warnings]&.any?
531
+ puts "Package has #{validation[:warnings].size} warnings"
532
+ validation[:warnings].each do |w|
533
+ puts " - #{w[:message]}"
534
+ end
535
+ end
536
+
537
+ # Deploy package
538
+ deploy_to_production(package_path)
539
+ end
540
+ ----
541
+
542
+ === CI/CD validation
543
+
544
+ Automate validation in CI/CD:
545
+
546
+ [source,yaml]
547
+ ----
548
+ # .github/workflows/validate.yml
549
+ name: Validate Package
550
+
551
+ on: [push, pull_request]
552
+
553
+ jobs:
554
+ validate:
555
+ runs-on: ubuntu-latest
556
+ steps:
557
+ - uses: actions/checkout@v2
558
+
559
+ - name: Set up Ruby
560
+ uses: ruby/setup-ruby@v1
561
+ with:
562
+ ruby-version: 3.0
563
+
564
+ - name: Install Expressir
565
+ run: gem install expressir
566
+
567
+ - name: Build package
568
+ run: |
569
+ expressir package build \
570
+ schemas/main.exp \
571
+ output/schemas.ler \
572
+ --validate
573
+
574
+ - name: Validate package
575
+ run: |
576
+ expressir package validate \
577
+ output/schemas.ler \
578
+ --strict \
579
+ --check-interfaces \
580
+ --check-completeness \
581
+ --format json > validation.json
582
+
583
+ - name: Upload validation results
584
+ uses: actions/upload-artifact@v2
585
+ with:
586
+ name: validation-results
587
+ path: validation.json
588
+ ----
589
+
590
+ === Validation gates
591
+
592
+ Implement validation gates:
593
+
594
+ [source,ruby]
595
+ ----
596
+ class ValidationGate
597
+ REQUIRED_CHECKS = {
598
+ basic: true,
599
+ interfaces: true,
600
+ completeness: false, # Warning only
601
+ duplicates: true,
602
+ self_references: true
603
+ }
604
+
605
+ def self.validate(package_path)
606
+ repo = Expressir::Model::Repository.from_package(package_path)
607
+
608
+ validation = repo.validate(
609
+ strict: true,
610
+ check_interfaces: REQUIRED_CHECKS[:interfaces],
611
+ check_completeness: REQUIRED_CHECKS[:completeness],
612
+ check_duplicates: REQUIRED_CHECKS[:duplicates],
613
+ check_self_references: REQUIRED_CHECKS[:self_references]
614
+ )
615
+
616
+ # Fail on errors
617
+ if !validation[:valid?]
618
+ log_errors(validation)
619
+ return false
620
+ end
621
+
622
+ # Log but allow warnings
623
+ log_warnings(validation) if validation[:warnings]&.any?
624
+
625
+ true
626
+ end
627
+
628
+ def self.log_errors(validation)
629
+ puts "VALIDATION FAILED"
630
+ validation[:errors].each do |error|
631
+ puts " ✗ #{error[:message]}"
632
+ end
633
+ end
634
+
635
+ def self.log_warnings(validation)
636
+ puts "VALIDATION WARNINGS"
637
+ validation[:warnings].each do |warning|
638
+ puts " ⚠ #{warning[:message]}"
639
+ end
640
+ end
641
+ end
642
+ ----
643
+
644
+ == Fixing validation issues
645
+
646
+ === Automated fixes
647
+
648
+ Some issues can be fixed automatically:
649
+
650
+ [source,ruby]
651
+ ----
652
+ def fix_and_validate(schema_dir, output_package)
653
+ # Parse all schemas
654
+ files = Dir.glob("#{schema_dir}/**/*.exp")
655
+ repo = Expressir::Express::Parser.from_files(files)
656
+
657
+ # Initial validation
658
+ validation = repo.validate(strict: true)
659
+
660
+ if validation[:errors].any?
661
+ puts "Found #{validation[:errors].size} errors"
662
+
663
+ # Attempt automated fixes
664
+ validation[:errors].each do |error|
665
+ case error[:type]
666
+ when :missing_schema_reference
667
+ puts "Cannot auto-fix missing schema: #{error[:referenced_schema]}"
668
+ puts " Add schema manually or update reference"
669
+
670
+ when :missing_interface_item
671
+ puts "Cannot auto-fix missing item: #{error[:item]}"
672
+ puts " Update interface or add item to schema"
673
+ end
674
+ end
675
+
676
+ return false
677
+ end
678
+
679
+ # Create package
680
+ repo.export_to_package(output_package)
681
+ true
682
+ end
683
+ ----
684
+
685
+ === Manual review process
686
+
687
+ Create validation report for review:
688
+
689
+ [source,ruby]
690
+ ----
691
+ def create_validation_report(package_path, output_file)
692
+ repo = Expressir::Model::Repository.from_package(package_path)
693
+
694
+ validation = repo.validate(
695
+ strict: true,
696
+ check_interfaces: true,
697
+ check_completeness: true,
698
+ detailed: true
699
+ )
700
+
701
+ report = {
702
+ package: package_path,
703
+ validated_at: Time.now.iso8601,
704
+ valid: validation[:valid?],
705
+ summary: {
706
+ errors: validation[:errors].size,
707
+ warnings: validation[:warnings].size
708
+ },
709
+ errors: validation[:errors],
710
+ warnings: validation[:warnings],
711
+ interface_report: validation[:interface_report]
712
+ }
713
+
714
+ File.write(output_file, JSON.pretty_generate(report))
715
+ puts "Validation report written to #{output_file}"
716
+ end
717
+ ----
718
+
719
+ == Next steps
720
+
721
+ * link:package-formats.html[Package Formats] - Understanding serialization
722
+ formats
723
+ * link:creating-packages.html[Creating Packages] - Build validated packages
724
+ * link:loading-packages.html[Loading Packages] - Load validated packages
725
+ * link:../ruby-api/working-with-repository.html[Working with Repository] - API
726
+ reference
727
+
728
+ == Summary
729
+
730
+ Key takeaways for validating LER packages:
731
+
732
+ * Always validate packages before deployment
733
+ * Use strict mode for production packages
734
+ * Enable interface validation for completeness
735
+ * Check for common errors: missing schemas and items
736
+ * Automate validation in CI/CD pipelines
737
+ * Log warnings even if validation passes
738
+ * Create validation reports for review
739
+ * Fix errors before creating packages
740
+
741
+ Best practices:
742
+
743
+ * Validate early and often
744
+ * Use comprehensive checks for production
745
+ * Automate validation in build process
746
+ * Log validation results
747
+ * Implement validation gates
748
+ * Review warnings regularly
749
+ * Fix errors at source
750
+ * Document known issues