svg_conform 0.2.4 → 0.2.6

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 (116) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +1 -0
  3. data/.github/workflows/rake.yml +3 -0
  4. data/Gemfile +7 -3
  5. data/Gemfile.lock +272 -0
  6. data/TODO.issue-100/00-overview.md +135 -0
  7. data/TODO.issue-100/01-build-lens-core-v1.md +92 -0
  8. data/TODO.issue-100/02-adopt-lens-core-in-svg.md +123 -0
  9. data/TODO.issue-100/03-ship-svg-1-1-full-static.md +138 -0
  10. data/TODO.issue-100/04-ship-svg-2-secure-static.md +131 -0
  11. data/TODO.issue-100/05-freeze-candidate-and-handoff.md +108 -0
  12. data/TODO.issue-100/90-progress.md +65 -0
  13. data/config/profiles/metanorma.yml +3 -3
  14. data/config/profiles/svg_1_1_full_static.yml +69 -0
  15. data/config/profiles/svg_2_secure_static.yml +55 -0
  16. data/config/requirements/processing_features_static.yml +29 -0
  17. data/data/svg_1_1/manifest.yml +7 -0
  18. data/data/svg_1_1/svg11-flat-20110816.dtd +5664 -0
  19. data/docs/api_reference.adoc +19 -1
  20. data/docs/cli_guide.adoc +35 -45
  21. data/docs/diagnostics.adoc +73 -0
  22. data/docs/lens_core_handoff.adoc +84 -0
  23. data/docs/profiles.adoc +94 -1
  24. data/lib/svg_conform/cli.rb +3 -3
  25. data/lib/svg_conform/commands/check.rb +11 -60
  26. data/lib/svg_conform/conformance_report.rb +79 -1
  27. data/lib/svg_conform/diagnostics/lens_core_adapter.rb +200 -0
  28. data/lib/svg_conform/document.rb +12 -1
  29. data/lib/svg_conform/node_helpers.rb +1 -1
  30. data/lib/svg_conform/profile.rb +11 -2
  31. data/lib/svg_conform/quality_metrics/complexity_calculator.rb +3 -3
  32. data/lib/svg_conform/references/base_reference.rb +153 -0
  33. data/lib/svg_conform/report_comparator.rb +4 -4
  34. data/lib/svg_conform/requirements/base_requirement.rb +6 -0
  35. data/lib/svg_conform/requirements/external_references_requirement.rb +234 -0
  36. data/lib/svg_conform/requirements/link_validation_requirement.rb +2 -0
  37. data/lib/svg_conform/requirements/processing_features_requirement.rb +175 -0
  38. data/lib/svg_conform/requirements/svg_1_1_document_requirement.rb +213 -0
  39. data/lib/svg_conform/requirements.rb +6 -0
  40. data/lib/svg_conform/sax_document.rb +8 -4
  41. data/lib/svg_conform/sax_validation_handler.rb +22 -1
  42. data/lib/svg_conform/validation/css2_core_grammar.rb +359 -0
  43. data/lib/svg_conform/validation/css_references.rb +122 -0
  44. data/lib/svg_conform/validation/error_tracker.rb +3 -1
  45. data/lib/svg_conform/validation/svg_1_1_document_conformance.rb +155 -0
  46. data/lib/svg_conform/validation_context.rb +25 -5
  47. data/lib/svg_conform/validation_result.rb +91 -16
  48. data/lib/svg_conform/version.rb +1 -1
  49. data/lib/svg_conform.rb +24 -0
  50. data/spec/fixtures/diagnostics/external-reference-info.svg +6 -0
  51. data/spec/fixtures/plantuml/README.adoc +11 -0
  52. data/spec/fixtures/plantuml/unit-type.svg +1 -0
  53. data/spec/fixtures/profiles/svg_1_1_full_static/invalid/animation.svg +4 -0
  54. data/spec/fixtures/profiles/svg_1_1_full_static/invalid/css-grammar.svg +4 -0
  55. data/spec/fixtures/profiles/svg_1_1_full_static/invalid/dtd-attribute.svg +4 -0
  56. data/spec/fixtures/profiles/svg_1_1_full_static/invalid/dtd-content-model.svg +4 -0
  57. data/spec/fixtures/profiles/svg_1_1_full_static/invalid/interaction.svg +4 -0
  58. data/spec/fixtures/profiles/svg_1_1_full_static/invalid/malformed-xml.svg +4 -0
  59. data/spec/fixtures/profiles/svg_1_1_full_static/invalid/script.svg +5 -0
  60. data/spec/fixtures/profiles/svg_1_1_full_static/invalid/wrong-namespace.svg +4 -0
  61. data/spec/fixtures/profiles/svg_1_1_full_static/invalid/wrong-version.svg +4 -0
  62. data/spec/fixtures/profiles/svg_1_1_full_static/invalid/xml-stylesheet.svg +5 -0
  63. data/spec/fixtures/profiles/svg_1_1_full_static/valid/css.svg +5 -0
  64. data/spec/fixtures/profiles/svg_1_1_full_static/valid/foreign-metadata.svg +6 -0
  65. data/spec/fixtures/profiles/svg_1_1_full_static/valid/minimal-full.svg +5 -0
  66. data/spec/fixtures/profiles/svg_1_1_full_static/valid/xml-stylesheet.svg +5 -0
  67. data/spec/fixtures/profiles/svg_2_secure_static/invalid/animation.svg +4 -0
  68. data/spec/fixtures/profiles/svg_2_secure_static/invalid/css-import.svg +4 -0
  69. data/spec/fixtures/profiles/svg_2_secure_static/invalid/css-url.svg +4 -0
  70. data/spec/fixtures/profiles/svg_2_secure_static/invalid/data-bad-png.svg +4 -0
  71. data/spec/fixtures/profiles/svg_2_secure_static/invalid/data-empty-png.svg +4 -0
  72. data/spec/fixtures/profiles/svg_2_secure_static/invalid/data-malformed-base64.svg +4 -0
  73. data/spec/fixtures/profiles/svg_2_secure_static/invalid/data-malformed-percent.svg +4 -0
  74. data/spec/fixtures/profiles/svg_2_secure_static/invalid/data-unsupported-type.svg +4 -0
  75. data/spec/fixtures/profiles/svg_2_secure_static/invalid/file-like-fragment.svg +4 -0
  76. data/spec/fixtures/profiles/svg_2_secure_static/invalid/http.svg +4 -0
  77. data/spec/fixtures/profiles/svg_2_secure_static/invalid/https.svg +4 -0
  78. data/spec/fixtures/profiles/svg_2_secure_static/invalid/interaction.svg +4 -0
  79. data/spec/fixtures/profiles/svg_2_secure_static/invalid/protocol-relative.svg +4 -0
  80. data/spec/fixtures/profiles/svg_2_secure_static/invalid/relative-file-fragment.svg +4 -0
  81. data/spec/fixtures/profiles/svg_2_secure_static/invalid/relative-file.svg +4 -0
  82. data/spec/fixtures/profiles/svg_2_secure_static/invalid/script.svg +4 -0
  83. data/spec/fixtures/profiles/svg_2_secure_static/invalid/svg-data-excessive-nesting.svg +4 -0
  84. data/spec/fixtures/profiles/svg_2_secure_static/invalid/svg-data-malformed-xml.svg +4 -0
  85. data/spec/fixtures/profiles/svg_2_secure_static/invalid/svg-data-nested-external.svg +4 -0
  86. data/spec/fixtures/profiles/svg_2_secure_static/invalid/urn.svg +4 -0
  87. data/spec/fixtures/profiles/svg_2_secure_static/invalid/xml-stylesheet.svg +5 -0
  88. data/spec/fixtures/profiles/svg_2_secure_static/valid/jpeg-base64.svg +4 -0
  89. data/spec/fixtures/profiles/svg_2_secure_static/valid/jpeg-percent.svg +4 -0
  90. data/spec/fixtures/profiles/svg_2_secure_static/valid/png-base64.svg +4 -0
  91. data/spec/fixtures/profiles/svg_2_secure_static/valid/png-percent.svg +4 -0
  92. data/spec/fixtures/profiles/svg_2_secure_static/valid/same-document-fragment.svg +4 -0
  93. data/spec/fixtures/profiles/svg_2_secure_static/valid/svg-base64.svg +4 -0
  94. data/spec/fixtures/profiles/svg_2_secure_static/valid/svg-percent.svg +4 -0
  95. data/spec/svg_conform/commands/check_command_spec.rb +22 -2
  96. data/spec/svg_conform/commands/profiles_command_spec.rb +18 -0
  97. data/spec/svg_conform/conformance_report_spec.rb +90 -0
  98. data/spec/svg_conform/diagnostics/lens_core_adapter_spec.rb +136 -0
  99. data/spec/svg_conform/gemspec_spec.rb +21 -0
  100. data/spec/svg_conform/profiles/svg_1_1_full_static_profile_spec.rb +146 -0
  101. data/spec/svg_conform/profiles/svg_2_secure_static_profile_spec.rb +150 -0
  102. data/spec/svg_conform/profiles_plantuml_spec.rb +81 -0
  103. data/spec/svg_conform/references/data_uri_reference_spec.rb +97 -0
  104. data/spec/svg_conform/references/integration_spec.rb +30 -0
  105. data/spec/svg_conform/references/reference_classifier_spec.rb +17 -0
  106. data/spec/svg_conform/requirements/external_references_requirement_spec.rb +109 -0
  107. data/spec/svg_conform/requirements/link_validation_requirement_spec.rb +16 -0
  108. data/spec/svg_conform/requirements/processing_features_requirement_spec.rb +75 -0
  109. data/spec/svg_conform/requirements/svg_1_1_document_requirement_spec.rb +141 -0
  110. data/spec/svg_conform/validation/css2_core_grammar_spec.rb +116 -0
  111. data/spec/svg_conform/validation/svg_1_1_document_conformance_spec.rb +144 -0
  112. data/spec/svg_conform/validation_context_source_plumbing_spec.rb +122 -0
  113. data/spec/svg_conform/validation_context_spec.rb +39 -0
  114. data/spec/svg_conform/validation_result_spec.rb +123 -0
  115. data/svg_conform.gemspec +3 -2
  116. metadata +102 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f1d7de294c1bcf83f963e80f3505faa12d65d90a45ec86decb82ee828e79b1e2
4
- data.tar.gz: 932524562cb5d1b9a78387725ab659dd21c5f2cf964ebbbec291202f5d87c876
3
+ metadata.gz: f10bc419be4fc98db66f773730223b021d90914c88fd6ce7421015c5a8a2be84
4
+ data.tar.gz: e70f5fe9224c41bf35e02eea2fbfa8b08fac28ceb997cb58529ca6b1a521626b
5
5
  SHA512:
6
- metadata.gz: 85956fa210da5c6e1282baaeddc02c44450413a9d5b5dfebdfd73d9f7534ae83ce5b0858790db2e1f1d77498dac944ba21f1f868d97fbc202cea0eb017980c36
7
- data.tar.gz: 4bcddffa2c56f0ccafaf708e99bea046787c949adb0a07d58581667e421c68abcd49e8014b58e2f225078d5ea83a5d12920c8ddedc4cd6a3daedb23920a6a502
6
+ metadata.gz: 8706aaee4a68d144e8edd9a5bd031eb2f5b8ca75ad5796acc85a58ff10a3fde582ea47e85cc8c41463eff42a66204148429ac3297fa2aef6bc0f022ab4a7fd5d
7
+ data.tar.gz: 4de2cd0a001c640514e4d7622c2225cce1dad6f6849706d6b8bbe4b9cbab1a12ff8db609c1af3313c725729f51d92d047dc02da7b79af0ca0bb2e8d485151b42
data/.gitattributes ADDED
@@ -0,0 +1 @@
1
+ data/svg_1_1/* -text
@@ -14,5 +14,8 @@ on:
14
14
  jobs:
15
15
  rake:
16
16
  uses: metanorma/ci/.github/workflows/generic-rake.yml@main
17
+ with:
18
+ # tests-passed dispatch is refused on pull_request runs; releases come from push
19
+ cascade: ${{ github.event_name != 'pull_request' }}
17
20
  secrets:
18
21
  pat_token: ${{ secrets.GITHUB_TOKEN }}
data/Gemfile CHANGED
@@ -6,9 +6,13 @@ source "https://rubygems.org"
6
6
  gemspec
7
7
 
8
8
  gem "canon", "~>0.1.10"
9
- gem "lutaml-model", github: "lutaml/lutaml-model", branch: "main"
10
- gem "moxml", github: "lutaml/moxml", branch: "main"
11
- gem "leptris", ">= 1.9.365.1"
9
+ gem "leptris", ">= 1.9.399.0"
10
+ gem "lutaml-model", "~> 0.8.155" # rubygems line; drop the git-main float
11
+ gem "moxml", "~> 0.6.0"
12
+ # Temporary pin on the lens_core v1 freeze candidate (claricle/lens_core#5 merge commit, after final-review fixes);
13
+ # replace with a released gem before release.
14
+ gem "lens_core", git: "https://github.com/claricle/lens_core.git", ref: "d00a6e8f7c0b5365a76b43e256a2f41ef9aee4ef"
15
+ gem "nokogiri", "~> 1.16"
12
16
  gem "openssl", "~> 3.0"
13
17
  gem "rake"
14
18
  gem "rspec"
data/Gemfile.lock ADDED
@@ -0,0 +1,272 @@
1
+ GIT
2
+ remote: https://github.com/claricle/lens_core.git
3
+ revision: d00a6e8f7c0b5365a76b43e256a2f41ef9aee4ef
4
+ ref: d00a6e8f7c0b5365a76b43e256a2f41ef9aee4ef
5
+ specs:
6
+ lens_core (0.1.0)
7
+
8
+ PATH
9
+ remote: .
10
+ specs:
11
+ svg_conform (0.2.6)
12
+ lutaml-model (~> 0.8.155)
13
+ moxml (~> 0.6.0)
14
+ nokogiri (~> 1.16)
15
+ rainbow
16
+ table_tennis
17
+ thor
18
+
19
+ GEM
20
+ remote: https://rubygems.org/
21
+ specs:
22
+ ast (2.4.3)
23
+ base64 (0.3.0)
24
+ bigdecimal (4.1.3)
25
+ canon (0.1.23)
26
+ diff-lcs
27
+ json
28
+ moxml
29
+ nokogiri
30
+ paint
31
+ table_tennis
32
+ thor
33
+ unicode-name
34
+ concurrent-ruby (1.3.8)
35
+ csv (3.3.7)
36
+ diff-lcs (1.6.2)
37
+ ffi (1.17.4-aarch64-linux-gnu)
38
+ ffi (1.17.4-aarch64-linux-musl)
39
+ ffi (1.17.4-arm-linux-gnu)
40
+ ffi (1.17.4-arm-linux-musl)
41
+ ffi (1.17.4-arm64-darwin)
42
+ ffi (1.17.4-x64-mingw-ucrt)
43
+ ffi (1.17.4-x86_64-darwin)
44
+ ffi (1.17.4-x86_64-linux-gnu)
45
+ ffi (1.17.4-x86_64-linux-musl)
46
+ json (3.1.0)
47
+ language_server-protocol (3.17.0.6)
48
+ leptris (1.9.399.0-aarch64-linux)
49
+ ffi (~> 1.15)
50
+ leptris (1.9.399.0-aarch64-linux-musl)
51
+ ffi (~> 1.15)
52
+ leptris (1.9.399.0-arm-linux)
53
+ ffi (~> 1.15)
54
+ leptris (1.9.399.0-arm-linux-musl)
55
+ ffi (~> 1.15)
56
+ leptris (1.9.399.0-arm64-darwin)
57
+ ffi (~> 1.15)
58
+ leptris (1.9.399.0-x64-mingw-ucrt)
59
+ ffi (~> 1.15)
60
+ leptris (1.9.399.0-x86_64-darwin)
61
+ ffi (~> 1.15)
62
+ leptris (1.9.399.0-x86_64-linux)
63
+ ffi (~> 1.15)
64
+ leptris (1.9.399.0-x86_64-linux-musl)
65
+ ffi (~> 1.15)
66
+ lint_roller (1.1.0)
67
+ liquid (5.14.0)
68
+ bigdecimal
69
+ strscan (>= 3.1.1)
70
+ lutaml-model (0.8.155)
71
+ base64 (>= 0.1.1)
72
+ bigdecimal
73
+ canon
74
+ concurrent-ruby
75
+ liquid (>= 4.0, < 6.0)
76
+ moxml (>= 0.5.139, < 0.7)
77
+ ostruct
78
+ rubyzip (~> 3.7)
79
+ thor (~> 1.4)
80
+ memo_wise (1.13.0)
81
+ moxml (0.6.1)
82
+ nokogiri (1.19.4-aarch64-linux-gnu)
83
+ racc (~> 1.4)
84
+ nokogiri (1.19.4-aarch64-linux-musl)
85
+ racc (~> 1.4)
86
+ nokogiri (1.19.4-arm-linux-gnu)
87
+ racc (~> 1.4)
88
+ nokogiri (1.19.4-arm-linux-musl)
89
+ racc (~> 1.4)
90
+ nokogiri (1.19.4-arm64-darwin)
91
+ racc (~> 1.4)
92
+ nokogiri (1.19.4-x64-mingw-ucrt)
93
+ racc (~> 1.4)
94
+ nokogiri (1.19.4-x86_64-darwin)
95
+ racc (~> 1.4)
96
+ nokogiri (1.19.4-x86_64-linux-gnu)
97
+ racc (~> 1.4)
98
+ nokogiri (1.19.4-x86_64-linux-musl)
99
+ racc (~> 1.4)
100
+ openssl (3.3.3)
101
+ ostruct (0.6.3)
102
+ paint (2.3.0)
103
+ parallel (2.3.0)
104
+ parser (3.3.12.0)
105
+ ast (~> 2.4.1)
106
+ racc
107
+ prism (1.9.0)
108
+ racc (1.8.1)
109
+ rainbow (3.1.1)
110
+ rake (13.4.2)
111
+ regexp_parser (2.13.1)
112
+ rspec (3.13.2)
113
+ rspec-core (~> 3.13.0)
114
+ rspec-expectations (~> 3.13.0)
115
+ rspec-mocks (~> 3.13.0)
116
+ rspec-core (3.13.6)
117
+ rspec-support (~> 3.13.0)
118
+ rspec-expectations (3.13.5)
119
+ diff-lcs (>= 1.2.0, < 2.0)
120
+ rspec-support (~> 3.13.0)
121
+ rspec-mocks (3.13.8)
122
+ diff-lcs (>= 1.2.0, < 2.0)
123
+ rspec-support (~> 3.13.0)
124
+ rspec-support (3.13.7)
125
+ rubocop (1.92.1)
126
+ json (>= 2.3)
127
+ language_server-protocol (~> 3.17.0.2)
128
+ lint_roller (~> 1.1.0)
129
+ parallel (>= 1.10)
130
+ parser (>= 3.3.0.2)
131
+ rainbow (>= 2.2.2, < 4.0)
132
+ regexp_parser (>= 2.11.3, < 3.0)
133
+ rubocop-ast (>= 1.49.0, < 2.0)
134
+ ruby-progressbar (~> 1.7)
135
+ unicode-display_width (>= 2.4.0, < 4.0)
136
+ rubocop-ast (1.50.0)
137
+ parser (>= 3.3.7.2)
138
+ prism (~> 1.7)
139
+ rubocop-performance (1.27.0)
140
+ lint_roller (~> 1.1)
141
+ rubocop (>= 1.89.0, < 2.0)
142
+ rubocop-ast (>= 1.47.1, < 2.0)
143
+ rubocop-rake (0.7.1)
144
+ lint_roller (~> 1.1)
145
+ rubocop (>= 1.72.1)
146
+ rubocop-rspec (3.10.2)
147
+ lint_roller (~> 1.1)
148
+ regexp_parser (>= 2.0)
149
+ rubocop (~> 1.86, >= 1.86.2)
150
+ ruby-progressbar (1.13.0)
151
+ rubyzip (3.7.0)
152
+ strscan (3.1.8)
153
+ table_tennis (1.0.0)
154
+ csv (~> 3.3)
155
+ ffi (~> 1.17)
156
+ memo_wise (~> 1.13)
157
+ paint (~> 2.3)
158
+ unicode-display_width (~> 3.2)
159
+ thor (1.5.0)
160
+ unicode-display_width (3.3.0)
161
+ unicode-emoji (~> 4.3)
162
+ unicode-emoji (4.3.0)
163
+ unicode-name (1.15.1)
164
+ unicode-types (~> 1.12)
165
+ unicode-types (1.12.0)
166
+
167
+ PLATFORMS
168
+ aarch64-linux
169
+ aarch64-linux-gnu
170
+ aarch64-linux-musl
171
+ arm-linux
172
+ arm-linux-gnu
173
+ arm-linux-musl
174
+ arm64-darwin
175
+ x64-mingw-ucrt
176
+ x86_64-darwin
177
+ x86_64-linux
178
+ x86_64-linux-gnu
179
+ x86_64-linux-musl
180
+
181
+ DEPENDENCIES
182
+ canon (~> 0.1.10)
183
+ lens_core!
184
+ leptris (>= 1.9.399.0)
185
+ lutaml-model (~> 0.8.155)
186
+ moxml (~> 0.6.0)
187
+ nokogiri (~> 1.16)
188
+ openssl (~> 3.0)
189
+ rake
190
+ rspec
191
+ rubocop
192
+ rubocop-performance
193
+ rubocop-rake
194
+ rubocop-rspec
195
+ svg_conform!
196
+
197
+ CHECKSUMS
198
+ ast (2.4.3) sha256=954615157c1d6a382bc27d690d973195e79db7f55e9765ac7c481c60bdb4d383
199
+ base64 (0.3.0) sha256=27337aeabad6ffae05c265c450490628ef3ebd4b67be58257393227588f5a97b
200
+ bigdecimal (4.1.3) sha256=61ebe1e5e559bdc3cc6f2c0ee7f427321fc838f59611c294356eb04d6e21cf66
201
+ canon (0.1.23) sha256=502646c0d50cd9e17c8867d24e5808b4adb85230482ad02157f4d4f161f74cc0
202
+ concurrent-ruby (1.3.8) sha256=b2f1be836e968ccc78ccfce277ea79c72a88633f22306782c16ff23fb415d1e1
203
+ csv (3.3.7) sha256=15a3f16f6628da8664d455eb634e7f22031bcf53044923caf56975109e71b9f8
204
+ diff-lcs (1.6.2) sha256=9ae0d2cba7d4df3075fe8cd8602a8604993efc0dfa934cff568969efb1909962
205
+ ffi (1.17.4-aarch64-linux-gnu) sha256=b208f06f91ffd8f5e1193da3cae3d2ccfc27fc36fba577baf698d26d91c080df
206
+ ffi (1.17.4-aarch64-linux-musl) sha256=9286b7a615f2676245283aef0a0a3b475ae3aae2bb5448baace630bb77b91f39
207
+ ffi (1.17.4-arm-linux-gnu) sha256=d6dbddf7cb77bf955411af5f187a65b8cd378cb003c15c05697f5feee1cb1564
208
+ ffi (1.17.4-arm-linux-musl) sha256=9d4838ded0465bef6e2426935f6bcc93134b6616785a84ffd2a3d82bc3cf6f95
209
+ ffi (1.17.4-arm64-darwin) sha256=19071aaf1419251b0a46852abf960e77330a3b334d13a4ab51d58b31a937001b
210
+ ffi (1.17.4-x64-mingw-ucrt) sha256=f6ff9618cfccc494138bddade27aa06c74c6c7bc367a1ea1103d80c2fcb9ed35
211
+ ffi (1.17.4-x86_64-darwin) sha256=aa70390523cf3235096cf64962b709b4cfbd5c082a2cb2ae714eb0fe2ccda496
212
+ ffi (1.17.4-x86_64-linux-gnu) sha256=9d3db14c2eae074b382fa9c083fe95aec6e0a1451da249eab096c34002bc752d
213
+ ffi (1.17.4-x86_64-linux-musl) sha256=3fdf9888483de005f8ef8d1cf2d3b20d86626af206cbf780f6a6a12439a9c49e
214
+ json (3.1.0) sha256=3ce7ccf8fde58960177a3a756c31f292a4c1e1dedee884547096a5b0604e3bd8
215
+ language_server-protocol (3.17.0.6) sha256=5ef2c0c138f8267e1bc631d3328347d354f96724b0af22f2c79516120443b7f0
216
+ lens_core (0.1.0)
217
+ leptris (1.9.399.0-aarch64-linux) sha256=f96125c2ceb69a48c9576dbba33d20466fd27b017ab7f54041f6bf37f0d3dc78
218
+ leptris (1.9.399.0-aarch64-linux-musl) sha256=feede158d84c3a46ac11da49e99ba2108a0b85a3e7113e056fa33e88f1dc694f
219
+ leptris (1.9.399.0-arm-linux) sha256=39046099c3d16e429966a79e5d509e120ad839bb41f3a1ed8183f0174f5a22fb
220
+ leptris (1.9.399.0-arm-linux-musl) sha256=b7526a73a8b06843228010fc03c00c801241ca591b1504aaf09fae8a12bb7bdb
221
+ leptris (1.9.399.0-arm64-darwin) sha256=f2c3e513cc31026307d4a28a92d97624fdb9dc1a67ef098a9586e0e76f250097
222
+ leptris (1.9.399.0-x64-mingw-ucrt) sha256=b3aced983a662307e930eed3d408d844b82d947d63f80dc6e4c48fec962d6a7b
223
+ leptris (1.9.399.0-x86_64-darwin) sha256=428c84f7c2e763bc2db614b1cafb49792852cd781d2c353e27206bf4aea3ce1c
224
+ leptris (1.9.399.0-x86_64-linux) sha256=ae235c244456b8949920d10c21bf9d8f01cf05fb6900c41bc2ef2531e01e86a8
225
+ leptris (1.9.399.0-x86_64-linux-musl) sha256=f7cf698c4858e132a19bf00667587ad96add7c35b3c629cbe97fdb20ef8099ce
226
+ lint_roller (1.1.0) sha256=2c0c845b632a7d172cb849cc90c1bce937a28c5c8ccccb50dfd46a485003cc87
227
+ liquid (5.14.0) sha256=e1020c2b2ee58c7a4d3bfdc7a331537bd27a783353748bff0bf27c6ac0c17065
228
+ lutaml-model (0.8.155) sha256=3d90f2fb4fdf41a42d4a05b62b3f6644b433070b82291a9371deaa8e68a1e02d
229
+ memo_wise (1.13.0) sha256=30220c38c4cef410849bc73553c58664dc2c91c6379e4a1df22aea02358b716b
230
+ moxml (0.6.1) sha256=5b7677258bbad372f0725a421f8adeae37b65d6f7871da2747e2c1906cdac7ea
231
+ nokogiri (1.19.4-aarch64-linux-gnu) sha256=1269fb644a6de405057a53dd5c762b1209b43ca7424f839454d3dbc677c31a8f
232
+ nokogiri (1.19.4-aarch64-linux-musl) sha256=35c65b9ce72b3bb03207bdbe7067915019dc18c1b9b59139684bd6690fdd01af
233
+ nokogiri (1.19.4-arm-linux-gnu) sha256=a301313e38bb065d68239e79734bcd6f56fb6efaacebde29e9abf2a4735340ca
234
+ nokogiri (1.19.4-arm-linux-musl) sha256=588923c101bcfa78869734d247d25b598674323e7f22474fc468f6e5647311eb
235
+ nokogiri (1.19.4-arm64-darwin) sha256=a46db9853286e6597b36ebc6953817d15acf3a299583eb3f89fdc6f91dd63527
236
+ nokogiri (1.19.4-x64-mingw-ucrt) sha256=051da97b8eccfdb5444fed40246a35e10d7298b9efe759b4cd25455ea04c587e
237
+ nokogiri (1.19.4-x86_64-darwin) sha256=7fd17057d3e1f00e9954a74b3cd76595d3d4a5ef233b7ed9599047c204f70551
238
+ nokogiri (1.19.4-x86_64-linux-gnu) sha256=379fae440b28915e3f19d752ce2dcf8465ed2b2fbefd2a7ca0dd497bc981a06a
239
+ nokogiri (1.19.4-x86_64-linux-musl) sha256=17dfb7c1fa194ae02fbf7c51a7afc8d278045ab3fdacfd86f91d02d7b274470b
240
+ openssl (3.3.3) sha256=d46902138f2987c13122fab826030a11c2bb9b8a16394215cbfc5062c5e2d335
241
+ ostruct (0.6.3) sha256=95a2ed4a4bd1d190784e666b47b2d3f078e4a9efda2fccf18f84ddc6538ed912
242
+ paint (2.3.0) sha256=327d623e4038619d5bd99ae5db07973859cd78400c7f0329eea283cef8e83be5
243
+ parallel (2.3.0) sha256=f75a3e904101ce6a1ccb6b8dc800cbafd42166d83330192438dcf29395167a6f
244
+ parser (3.3.12.0) sha256=21a6d7f755d5a24dfbdc6e6b772e4e879a52e7631a88bc5a3a134606052c9828
245
+ prism (1.9.0) sha256=7b530c6a9f92c24300014919c9dcbc055bf4cdf51ec30aed099b06cd6674ef85
246
+ racc (1.8.1) sha256=4a7f6929691dbec8b5209a0b373bc2614882b55fc5d2e447a21aaa691303d62f
247
+ rainbow (3.1.1) sha256=039491aa3a89f42efa1d6dec2fc4e62ede96eb6acd95e52f1ad581182b79bc6a
248
+ rake (13.4.2) sha256=cb825b2bd5f1f8e91ca37bddb4b9aaf345551b4731da62949be002fa89283701
249
+ regexp_parser (2.13.1) sha256=5aedb6b7c35688f51e86eef17a15374dfd287c83f4ca644b2c5f3ec50a33b44b
250
+ rspec (3.13.2) sha256=206284a08ad798e61f86d7ca3e376718d52c0bc944626b2349266f239f820587
251
+ rspec-core (3.13.6) sha256=a8823c6411667b60a8bca135364351dda34cd55e44ff94c4be4633b37d828b2d
252
+ rspec-expectations (3.13.5) sha256=33a4d3a1d95060aea4c94e9f237030a8f9eae5615e9bd85718fe3a09e4b58836
253
+ rspec-mocks (3.13.8) sha256=086ad3d3d17533f4237643de0b5c42f04b66348c28bf6b9c2d3f4a3b01af1d47
254
+ rspec-support (3.13.7) sha256=0640e5570872aafefd79867901deeeeb40b0c9875a36b983d85f54fb7381c47c
255
+ rubocop (1.92.1) sha256=a905381a5344215a79abcfe80f6c94366447e6a55347c9a525b5a24990e33f62
256
+ rubocop-ast (1.50.0) sha256=b9ca88300da0803ee222ad20cdb30494c0a784eed06fdc35d254b06d662788db
257
+ rubocop-performance (1.27.0) sha256=eeeb1374d062a368ee1c787b70eb0b0cc4b184cb1f8565f424760946146d61ce
258
+ rubocop-rake (0.7.1) sha256=3797f2b6810c3e9df7376c26d5f44f3475eda59eb1adc38e6f62ecf027cbae4d
259
+ rubocop-rspec (3.10.2) sha256=0b3e2ecc592cd10ecbf0095bb58d1e357905276e069643523cc19eb7495f65e2
260
+ ruby-progressbar (1.13.0) sha256=80fc9c47a9b640d6834e0dc7b3c94c9df37f08cb072b7761e4a71e22cff29b33
261
+ rubyzip (3.7.0) sha256=65c19294da75297a939006f3516deacc33185fbd721ff1954f7a231db6d3e121
262
+ strscan (3.1.8) sha256=aae2db611a225559f21ffbb71765c9a4e60fd262534a9ea84f4f11c7f32f679e
263
+ svg_conform (0.2.6)
264
+ table_tennis (1.0.0) sha256=955f76ca4debd42ee88682af8d4554a74d533c89de4f1581bc37855b15faa956
265
+ thor (1.5.0) sha256=e3a9e55fe857e44859ce104a84675ab6e8cd59c650a49106a05f55f136425e73
266
+ unicode-display_width (3.3.0) sha256=4b7aa66a4b11db50f6f7e98411215cd0dd10eaecb665d36eec5bcacb3fa0b613
267
+ unicode-emoji (4.3.0) sha256=11c02fa73290378c066bb0562cd4c87d8e1b706fbbe0059ca12746a4244de8ce
268
+ unicode-name (1.15.1) sha256=b8f2e3ca14bc24799f84a4f74d43a3612d02a051700d88bc6ca8e3bd53cda3f6
269
+ unicode-types (1.12.0) sha256=7e26a4352cecc2a50325a3793df834b732581ca9f25c5e29f46f3378934363f6
270
+
271
+ BUNDLED WITH
272
+ 2.7.2
@@ -0,0 +1,135 @@
1
+ # Issue 100 — Spec-version profiles and shared lens diagnostics
2
+
3
+ ## Outcome
4
+
5
+ Ship a versioned, zero-runtime-dependency `LensCore` diagnostics contract, make
6
+ `svg_conform` emit that contract without breaking its transitional interfaces,
7
+ and add two opt-in, corpus-backed profiles:
8
+
9
+ - SVG 1.1 Full in static processing mode.
10
+ - SVG 2 in secure static processing mode.
11
+
12
+ The work ends with a pinned LensCore candidate and an observable adoption
13
+ handoff. Publishing a LensCore gem and migrating other lens repositories are
14
+ follow-on work, not part of this issue.
15
+
16
+ ## Current state
17
+
18
+ - `svg_conform` defines diagnostics in several places. `ValidationContext` and
19
+ `ErrorTracker` collect `infos`, but `ValidationResult`,
20
+ `ConformanceReport`, and the `check` command project only errors and warnings.
21
+ - `ValidationResult#to_h` and `#to_text`, Lutaml-backed
22
+ `ConformanceReport`, CLI JSON/YAML/table output, and the svgcheck compatibility
23
+ path do not share one canonical report object.
24
+ - Profiles are Lutaml models loaded from `config/profiles/*.yml`; requirements
25
+ are registered independently in `lib/svg_conform/profile.rb`,
26
+ `lib/svg_conform/profile_compiler.rb`, and
27
+ `lib/svg_conform/requirements.rb`.
28
+ - Validation supports DOM and SAX requirement hooks, with SAX as the normal
29
+ validation path. The current profiles describe project policies, not complete
30
+ SVG 1.1 Full or SVG 2 secure-static conformance.
31
+ - `SvgConform::References::ReferenceClassifier.classify` already returns typed
32
+ internal-fragment, data-URI, URN, external-URL, and relative-path references.
33
+ `LinkValidationRequirement` consumes that API. Data URIs currently expose
34
+ their media type but are not decoded or syntax-checked.
35
+ - The repository has no committed `Gemfile.lock` and no LensCore dependency.
36
+
37
+ ## Target design
38
+
39
+ ### One diagnostics contract
40
+
41
+ The new `claricle/lens_core` repository owns schema version `1`, Ruby value
42
+ objects, JSON/YAML parsers, and JSON/YAML/human renderers. A report carries its
43
+ schema version, producer, profile identity, validity, summary counts, and an
44
+ ordered diagnostics collection. A diagnostic has a stable severity, extensible
45
+ kind, stable requirement ID, message, optional citations/remediation/context,
46
+ and an optional typed location that can represent XML coordinates or binary
47
+ offsets/records.
48
+
49
+ `svg_conform` constructs that report once. Existing hashes, text/table output,
50
+ `ConformanceReport`, and svgcheck-compatible output become projections or
51
+ adapters over it for one transition. The adapter preserves all four existing
52
+ channels: errors, validity errors, warnings, and infos.
53
+
54
+ ### Profiles as explicit requirement matrices
55
+
56
+ Each profile has stable requirement IDs, normative citations, expected failure
57
+ behavior, DOM/SAX coverage, focused fixtures, and documentation. SVG 1.1 Full
58
+ uses the pinned 2011 Recommendation and its flat DTD, plus the Recommendation's
59
+ Appendix G.2 handling and referenced CSS/XML-stylesheet rules. SVG 2 uses the
60
+ pinned Candidate Recommendation and enforces secure-static processing,
61
+ including its external-resource boundary.
62
+
63
+ The profiles are additive and opt-in. Existing profile behavior and the default
64
+ profile do not change.
65
+
66
+ ## Work sequence
67
+
68
+ | Card | Work item | Depends on | Effort |
69
+ | --- | --- | --- | --- |
70
+ | 01 | Build LensCore diagnostics v1 | — | 4–7 person-days |
71
+ | 02 | Adopt LensCore in svg_conform | 01 | 3–5 person-days |
72
+ | 03 | Ship SVG 1.1 Full/static | 02 | 8–12 person-days |
73
+ | 04 | Ship SVG 2 secure-static | 02, 03 shared processing/source plumbing | 4–6 person-days |
74
+ | 05 | Freeze the candidate and adoption handoff | 01–04 | 2–4 person-days |
75
+
76
+ Overall estimate: **21–34 person-days**. The range includes implementation,
77
+ focused tests, fixtures, documentation, and integration fixes. It excludes gem
78
+ publication, work in other lens repositories, and external review latency.
79
+ Confidence is medium: the largest uncertainty is whether the existing XML stack
80
+ can perform offline SVG 1.1 DTD validation without another runtime dependency;
81
+ Card 03 resolves that with a bounded spike before implementation proceeds.
82
+
83
+ ## Acceptance map
84
+
85
+ | Issue acceptance criterion | Planned evidence |
86
+ | --- | --- |
87
+ | SVG 1.1 and SVG 2 profiles ship, are documented, and each has a corpus | Cards 03 and 04 profile specs, focused fixture directories, CLI checks, and profile documentation |
88
+ | The diagnostics model is extracted, versioned, and shaped for reuse by other lenses | Cards 01 and 02 schema/model/renderer specs plus XML and binary location examples |
89
+ | A diagnostics JSON round-trip corpus is pinned | Card 05 byte-stable parse/render goldens tied to exact LensCore and svg_conform commits |
90
+ | Other lenses can adopt the shape without SVG code | Card 05 host-only check and handoff manifest; actual EMF/PNG/PostScript migrations remain separate issues |
91
+
92
+ ## Scope boundaries
93
+
94
+ Included:
95
+
96
+ - LensCore schema/model/parser/renderer v1 and its zero-runtime-dependency gem.
97
+ - The svg_conform adapter and transitional aliases.
98
+ - SVG 1.1 Full/static and SVG 2 secure-static profiles.
99
+ - A pinned JSON corpus and cross-repository adoption handoff.
100
+
101
+ Excluded:
102
+
103
+ - EMF, PNG, or PostScript implementation, fixtures, dependency changes, and
104
+ releases.
105
+ - Publishing LensCore or replacing its temporary Git pin with a released gem.
106
+ - SVG 1.1 Tiny/Basic profiles. They are a future sibling profile of
107
+ `svg_1_1_full_static`, to be added once the SVG 1.1 Mobile Profiles
108
+ specification is available as reference material; the repository's available
109
+ Tiny reference is for SVG Tiny 1.2.
110
+ - Complete SVG 2 document/rendering conformance beyond secure-static processing.
111
+ - Profile inheritance or a redesign of existing profile discovery.
112
+ - Full-suite, full-corpus, or fuzz testing for this issue.
113
+
114
+ ## Normative sources
115
+
116
+ - SVG 1.1 Second Edition Recommendation:
117
+ <https://www.w3.org/TR/2011/REC-SVG11-20110816/>
118
+ - SVG 1.1 conformance criteria:
119
+ <https://www.w3.org/TR/2011/REC-SVG11-20110816/conform.html#ConformingSVGDocuments>
120
+ - SVG 1.1 flat DTD:
121
+ <https://www.w3.org/Graphics/SVG/1.1/DTD/svg11-flat-20110816.dtd>
122
+ - CSS 2 core grammar referenced by SVG 1.1:
123
+ <https://www.w3.org/TR/2008/REC-CSS2-20080411/grammar.html>
124
+ - Associating Style Sheets with XML 1.0:
125
+ <https://www.w3.org/TR/1999/REC-xml-stylesheet-19990629/>
126
+ - SVG 2 Candidate Recommendation snapshot:
127
+ <https://www.w3.org/TR/2026/CR-SVG2-20261006/>
128
+ - SVG 2 secure-static processing mode:
129
+ <https://www.w3.org/TR/2026/CR-SVG2-20261006/conform.html#secure-static-mode>
130
+
131
+ ## Verification policy
132
+
133
+ Each card names only focused specs, fixture checks, lint, and build commands.
134
+ No card requires a full test suite, a corpus sweep, or fuzzing. Commands are run
135
+ in the repository named by the card.
@@ -0,0 +1,92 @@
1
+ # 01 — Build LensCore diagnostics v1
2
+
3
+ Effort: **4–7 person-days**
4
+
5
+ Repository: `claricle/lens_core` (new)
6
+
7
+ ## Purpose
8
+
9
+ Create the independent, zero-runtime-dependency gem that owns the shared
10
+ diagnostics wire format and all of its renderers. It must be useful without
11
+ loading svg_conform or any document-format implementation.
12
+
13
+ ## Contract
14
+
15
+ Schema version `1` defines these public concepts:
16
+
17
+ - `LensCore::Report`: `schema_version`, producer name/version, profile ID and
18
+ citations, validity, summary counts, ordered diagnostics, and an optional
19
+ caller-supplied timestamp.
20
+ - `LensCore::Diagnostic`: severity (`error`, `warning`, or `info`), extensible
21
+ kind, stable requirement ID, message, citations, optional remediation,
22
+ JSON-safe context, and optional location.
23
+ - `LensCore::Citation`: required absolute `uri` and optional human label.
24
+ - `LensCore::Location`: an explicit location type plus applicable fields. XML
25
+ locations can carry line, column, and path; binary locations can carry byte
26
+ offset, byte length, record index, and record type. Absent coordinates are
27
+ omitted rather than populated with invented zeroes.
28
+
29
+ The schema rejects an unsupported major schema version but permits new
30
+ diagnostic `kind` values and unknown additive object members so compatible v1
31
+ producers can evolve. Parsers return stable LensCore error classes for malformed
32
+ JSON/YAML, unsupported versions, schema violations, unsafe YAML tags, and
33
+ non-UTF-8 text.
34
+
35
+ Rendering rules are deterministic: diagnostic input order is preserved,
36
+ standard object keys follow schema order, extension keys are lexical, summary
37
+ counts are derived from diagnostics, and timestamps appear only when supplied.
38
+ JSON parsing followed by JSON rendering is byte-stable for canonical inputs.
39
+
40
+ ## Files and implementation
41
+
42
+ - Add `lens_core.gemspec`, `Gemfile`, `Rakefile`, and `lib/lens_core.rb`. The
43
+ gemspec has no runtime dependencies; implementation uses Ruby's JSON, YAML,
44
+ and time facilities.
45
+ - Add value objects in:
46
+ - `lib/lens_core/report.rb`
47
+ - `lib/lens_core/diagnostic.rb`
48
+ - `lib/lens_core/citation.rb`
49
+ - `lib/lens_core/location.rb`
50
+ - Add `lib/lens_core/parsers/json.rb` and `yaml.rb`, and matching renderers in
51
+ `lib/lens_core/renderers/json.rb`, `yaml.rb`, and `human.rb`. Keep validation
52
+ and canonicalization shared rather than reimplemented in each format.
53
+ - Add the normative machine-readable schema at
54
+ `schemas/lens-diagnostics-v1.json` and document field semantics, compatibility
55
+ rules, omission/null behavior, ordering, UTF-8 handling, and failure classes
56
+ in `docs/diagnostics-v1.adoc`.
57
+ - Add `spec/lens_core/report_spec.rb`, `spec/lens_core/parsers_spec.rb`,
58
+ `spec/lens_core/renderers_spec.rb`, and `spec/lens_core/schema_spec.rb`, with
59
+ small fixtures under `spec/fixtures/v1/`. Include XML-location and
60
+ binary-location reports to prove the contract is not SVG-shaped; these are
61
+ format-neutral examples, not claims that another lens has adopted the gem.
62
+
63
+ Keep the Ruby model and JSON Schema at independently readable version constants,
64
+ so a host can report both the gem version and schema version. Do not add SVG
65
+ names, SVG requirement IDs, or dependencies on a lens repository.
66
+
67
+ ## Done when
68
+
69
+ - The gem builds with zero runtime dependencies and can be required in a clean
70
+ Ruby process.
71
+ - Schema-valid JSON and safe YAML parse to the same report model; JSON, YAML,
72
+ and human renderers all include errors, warnings, and infos.
73
+ - Canonical JSON fixtures round-trip byte-for-byte, while malformed, unsafe,
74
+ non-UTF-8, and unsupported-version fixtures fail with documented LensCore
75
+ errors.
76
+ - XML and binary fixture locations survive parse/render without losing present
77
+ coordinates or manufacturing absent ones.
78
+ - The schema, Ruby model, and documentation agree on required fields,
79
+ compatibility behavior, ordering, timestamp handling, and omission rules.
80
+ - All changed Ruby passes the repository linter and the gem artifact builds.
81
+
82
+ ```sh
83
+ bundle install
84
+ bundle exec rspec spec/lens_core/report_spec.rb spec/lens_core/parsers_spec.rb spec/lens_core/renderers_spec.rb spec/lens_core/schema_spec.rb
85
+ bundle exec rubocop
86
+ bundle exec rake build
87
+ ```
88
+
89
+ ## Status
90
+
91
+ State: done
92
+ PR: https://github.com/claricle/lens_core/pull/1
@@ -0,0 +1,123 @@
1
+ # 02 — Adopt LensCore in svg_conform
2
+
3
+ Effort: **3–5 person-days**
4
+
5
+ Repository: `claricle/svg_conform`
6
+
7
+ Depends on: Card 01
8
+
9
+ ## Purpose
10
+
11
+ Make one `LensCore::Report` the canonical representation of an svg_conform
12
+ validation result while preserving the current public and svgcheck-compatible
13
+ surfaces for one transition.
14
+
15
+ ## Dependency and load boundary
16
+
17
+ - Add LensCore to `Gemfile` with the HTTPS Git repository and the exact Card 01
18
+ candidate commit. Generate and commit `Gemfile.lock`; assert that its LensCore
19
+ revision equals the handoff commit.
20
+ - Do not add an unreleased Git dependency or Bundler-only options to
21
+ `svg_conform.gemspec`. Replacing the temporary Git pin with a released gem
22
+ requirement belongs to the later release work.
23
+ - Load LensCore from `lib/svg_conform.rb` and expose the adapter without making
24
+ LensCore depend on svg_conform.
25
+
26
+ ## Canonical mapping
27
+
28
+ Add `SvgConform::Diagnostics::LensCoreAdapter` at
29
+ `lib/svg_conform/diagnostics/lens_core_adapter.rb` with one entry point:
30
+
31
+ ```ruby
32
+ SvgConform::Diagnostics::LensCoreAdapter.call(
33
+ validation_result,
34
+ filename: nil,
35
+ timestamp: nil
36
+ )
37
+ ```
38
+
39
+ The adapter maps:
40
+
41
+ | svg_conform source | LensCore severity | LensCore kind |
42
+ | --- | --- | --- |
43
+ | `errors` | `error` | the issue's violation type, falling back to `validation` |
44
+ | `validity_errors` | `error` | `validity` |
45
+ | `warnings` | `warning` | the issue's violation type, falling back to `validation` |
46
+ | `infos` | `info` | the issue's violation type, falling back to `notice` |
47
+
48
+ It preserves the source collection order within those channels, maps explicit
49
+ requirement IDs without generating new IDs from messages, includes available
50
+ line/column/element-path data, carries remediation fields already exposed by
51
+ `ValidationIssue`, and converts issue data to JSON-safe primitives. An
52
+ unsupported object in context fails at the adapter boundary with a stable error
53
+ rather than leaking Ruby object inspection into JSON.
54
+
55
+ Add profile-level `specification_uri`/`specification_label` to `Profile` in
56
+ `lib/svg_conform/profile.rb`, and requirement-level
57
+ `citation_uri`/`citation_label` to `BaseRequirement` in
58
+ `lib/svg_conform/requirements/base_requirement.rb`; map both pairs in their
59
+ Lutaml YAML definitions. The adapter turns them into LensCore citations.
60
+ Existing profiles may omit them; the two new profiles may not.
61
+
62
+ ## Public and transitional surfaces
63
+
64
+ - Extend `ValidationResult` with `infos`, `info_count`, and
65
+ `to_lens_core_report(timestamp: nil)`. Include infos and validity errors in
66
+ counts/projections without changing `valid?`: only errors and validity errors
67
+ make a result invalid.
68
+ - Make `ValidationResult#to_h`, `#to_json`, and text output project the canonical
69
+ report. Keep their current call signatures and retain file/reference/fix data
70
+ as documented compatibility extensions.
71
+ - Back `ConformanceReport.from_svg_conform_result` with the same report and keep
72
+ its current class, factory signature, and YAML shape as a deprecated legacy
73
+ projection. Preserve the `use_svgcheck_mapping:` adapter and
74
+ `from_svgcheck_result`; svgcheck filtering happens after canonical report
75
+ construction and does not mutate the canonical report.
76
+ - Route `lib/svg_conform/commands/check.rb` JSON, YAML, and table output through
77
+ LensCore renderers. The accepted CLI value `table` remains an alias for the
78
+ human renderer for compatibility.
79
+ - Extend `ValidationContext#add_notice`,
80
+ `ValidationContext#add_external_reference_notice`, and
81
+ `Validation::ErrorTracker#add_notice` to accept an optional explicit
82
+ requirement ID while preserving existing calls. Store it on the existing
83
+ `Errors::ValidationIssue` used by the info channel. Requirements pass their
84
+ own stable ID so infos no longer fall back to `unknown`.
85
+
86
+ Document the v1 API and transition in the proposed `docs/diagnostics.adoc`, and
87
+ update the existing `docs/api_reference.adoc` and `docs/cli_guide.adoc`. Add
88
+ focused specs at `spec/svg_conform/diagnostics/lens_core_adapter_spec.rb`,
89
+ `spec/svg_conform/validation_result_spec.rb`,
90
+ `spec/svg_conform/conformance_report_spec.rb`, and the existing command/context
91
+ spec paths used below. Add
92
+ `spec/fixtures/diagnostics/external-reference-info.svg` so the library and CLI
93
+ assertions use a small SVG that emits an ordinary informational external
94
+ reference notice without depending on later profile fixtures.
95
+
96
+ ## Done when
97
+
98
+ - `Gemfile.lock` pins the exact LensCore candidate commit, while the gemspec has
99
+ no unreleased LensCore dependency.
100
+ - One validation result containing an error, validity error, warning, and info
101
+ produces one schema-valid report with correct validity and per-channel
102
+ summary counts.
103
+ - The library's JSON/YAML/human paths and the ordinary `check` command render
104
+ from that report and preserve the informational diagnostic.
105
+ - Existing `ValidationResult`, `ConformanceReport`, table-output, and svgcheck
106
+ factory call signatures remain callable and are covered by compatibility
107
+ specs.
108
+ - Profile and requirement citations survive YAML loading and appear in the
109
+ canonical report; JSON-unsafe issue context fails deterministically.
110
+ - All changed Ruby passes the repository linter and the gem builds.
111
+
112
+ ```sh
113
+ bundle install
114
+ bundle exec rspec spec/svg_conform/diagnostics/lens_core_adapter_spec.rb spec/svg_conform/validation_result_spec.rb spec/svg_conform/conformance_report_spec.rb spec/svg_conform/validation_context_spec.rb spec/svg_conform/commands/check_command_spec.rb
115
+ bundle exec svg_conform check spec/fixtures/diagnostics/external-reference-info.svg --profile svg_1_2_rfc --format json
116
+ bundle exec rubocop
117
+ bundle exec rake build
118
+ ```
119
+
120
+ ## Status
121
+
122
+ State: done
123
+ PR: https://github.com/claricle/svg_conform/pull/103