pubid 2.0.20 → 2.0.21

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 (39) hide show
  1. checksums.yaml +4 -4
  2. data/data/iho/s4-reserved-specs.yaml +15 -0
  3. data/data/parg/bipm.json +1 -1
  4. data/data/parg/bipm.parg +46 -11
  5. data/data/parg/iho.json +1 -1
  6. data/data/parg/iho.parg +128 -11
  7. data/data/parg/plateau.json +1 -1
  8. data/lib/pubid/bipm/CLAUDE.md +6 -1
  9. data/lib/pubid/bipm/builder.rb +20 -1
  10. data/lib/pubid/bipm/renderer.rb +14 -2
  11. data/lib/pubid/bipm/urn_generator.rb +80 -14
  12. data/lib/pubid/bipm/urn_parser.rb +70 -6
  13. data/lib/pubid/ecma/CLAUDE.md +12 -0
  14. data/lib/pubid/ecma/identifier.rb +1 -2
  15. data/lib/pubid/ecma/parser.rb +49 -0
  16. data/lib/pubid/iec/CLAUDE.md +5 -1
  17. data/lib/pubid/iec/identifier.rb +19 -70
  18. data/lib/pubid/iec/identifiers/fragment_identifier.rb +3 -3
  19. data/lib/pubid/iec/single_identifier.rb +69 -4
  20. data/lib/pubid/iec/supplement_identifier.rb +52 -76
  21. data/lib/pubid/iho/CLAUDE.md +52 -0
  22. data/lib/pubid/iho/builder.rb +105 -2
  23. data/lib/pubid/iho/identifiers/base.rb +52 -1
  24. data/lib/pubid/iho/pubid_urn_schema.rb +11 -4
  25. data/lib/pubid/iho/renderer.rb +39 -2
  26. data/lib/pubid/iho/reserved_specs.rb +54 -0
  27. data/lib/pubid/iho/urn_generator.rb +6 -0
  28. data/lib/pubid/iho/urn_parser.rb +50 -9
  29. data/lib/pubid/iho.rb +1 -0
  30. data/lib/pubid/nist/CLAUDE.md +11 -0
  31. data/lib/pubid/nist/preprocessor.rb +16 -0
  32. data/lib/pubid/plateau/CLAUDE.md +35 -0
  33. data/lib/pubid/plateau/builder.rb +4 -0
  34. data/lib/pubid/plateau/identifiers/handbook.rb +10 -2
  35. data/lib/pubid/plateau/pubid_urn_schema.rb +1 -0
  36. data/lib/pubid/plateau/renderer.rb +6 -1
  37. data/lib/pubid/sae/CLAUDE.md +11 -2
  38. data/lib/pubid/version.rb +1 -1
  39. metadata +4 -2
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "yaml"
4
+
5
+ module Pubid
6
+ module Iho
7
+ # The S-4 reserved specification registry
8
+ # (data/iho/s4-reserved-specs.yaml): the "NOT CURRENTLY USED"
9
+ # numbers, edition-keyed (owner rulings of 2026-11-11, issue #691).
10
+ # {Reserved?} answers from this table — a reserved number parses and
11
+ # resolves AS RESERVED, never invalid.
12
+ module ReservedSpecs
13
+ DATA_PATH =
14
+ File.expand_path("../../../data/iho/s4-reserved-specs.yaml", __dir__)
15
+
16
+ class << self
17
+ # True when the part-lettered spec number is reserved in the
18
+ # given S-4 edition. An edition-less reference is reserved when
19
+ # ANY seeded edition reserves the number: the number is out of
20
+ # circulation in every edition that names it.
21
+ def reserved?(edition, part, spec)
22
+ return false unless part && spec
23
+
24
+ if edition
25
+ specs_for(edition, part).include?(spec)
26
+ else
27
+ registry.values.any? do |parts|
28
+ specs_for_parts(parts, part).include?(spec)
29
+ end
30
+ end
31
+ end
32
+
33
+ # The edition-keyed registry: edition => part letter => spec
34
+ # numbers.
35
+ def registry
36
+ @registry ||=
37
+ (YAML.safe_load_file(DATA_PATH) || {}).transform_values do |parts|
38
+ parts.transform_values { |specs| Array(specs) }
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ def specs_for(edition, part)
45
+ specs_for_parts(registry.fetch(edition, {}), part)
46
+ end
47
+
48
+ def specs_for_parts(parts, part)
49
+ parts.fetch(part, [])
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -31,6 +31,7 @@ module Pubid
31
31
  # - urn:iho:m:2:sup-1 IHO M-2 Sup 1
32
32
  # - urn:iho:p:5:vol-2024 IHO P-5 Vol. 2024
33
33
  # - urn:iho:p:1:vol-30:issue-2 IHO P-1 Vol. 30 (2)
34
+ # - urn:iho:s:4:ed-4.10.0:part-B:spec-401 IHO S-4 4.10.0 B-401
34
35
  class UrnGenerator
35
36
  attr_reader :identifier
36
37
 
@@ -49,6 +50,11 @@ module Pubid
49
50
  [:supplement, "sup"], [:supplement_edition, "ed"],
50
51
  [:supplement_year, "year"],
51
52
  [:part, "part"], [:part_edition, "ed"], [:part_year, "year"],
53
+ # the S-4 spec citation: a child of its part (the citation
54
+ # letter rides the part- atom), the dotted sub and the
55
+ # parenthesized variant its own children. The SECTION is NOT
56
+ # emitted — derivable from the spec's hundreds digit.
57
+ [:spec, "spec"], [:spec_sub, "specsub"], [:spec_variant, "specvar"],
52
58
  [:annex, "annex"], [:annex_edition, "ed"], [:annex_year, "year"],
53
59
  [:appendix, "appendix"], [:appendix_subnumber, nil],
54
60
  [:appendix_edition, "ed"], [:appendix_year, "year"],
@@ -7,8 +7,8 @@ module Pubid
7
7
  # the segment table lives in the grammar header and the flavor notes):
8
8
  #
9
9
  # urn:iho:<type>:<number>[:ed-<x.y.z>][:sup-<n>][:part-<X>]
10
- # [:annex-<A>][:appendix-<B>][:<sub>][:vol-<n>][:issue-<n>]
11
- # [:year-<yyyy>]
10
+ # [:spec-<n>[:specsub-<n>][:specvar-<X>]][:annex-<A>]
11
+ # [:appendix-<B>][:<sub>][:vol-<n>][:issue-<n>][:year-<yyyy>]
12
12
  #
13
13
  # Segment discipline (mirrors the ISO URN parser's strictness):
14
14
  # - the docnumber occupies every leading bare number segment up to
@@ -22,7 +22,11 @@ module Pubid
22
22
  # directly after its appendix segment (a year is always
23
23
  # marker-tagged, so a bare digit there can only be the subnumber);
24
24
  # - the issue is allowed only beside its volume and validated as
25
- # digits.
25
+ # digits;
26
+ # - the S-4 spec atom is a child of its part (the citation letter
27
+ # rides the part- atom): specsub-/specvar- only after spec-, and
28
+ # no ed-/year- after a spec node (the spec rides its publication's
29
+ # edition; the section is derivable, never emitted).
26
30
  #
27
31
  # Legacy 2.0.x spellings remain decodable but are never emitted:
28
32
  # the bare a.b.c edition segment, the dotted keys part./annex./
@@ -38,6 +42,7 @@ module Pubid
38
42
  # - urn:iho:p:5:vol-2024 → IHO P-5 Vol. 2024
39
43
  # - urn:iho:p:1:vol-30:issue-2 → IHO P-1 Vol. 30 (2)
40
44
  # - urn:iho:s:158:100 → IHO S-158:100
45
+ # - urn:iho:s:4:ed-4.10.0:part-B:spec-401 → IHO S-4 4.10.0 B-401
41
46
  class UrnParser < Pubid::UrnParser::Base
42
47
  TYPE_LETTERS = %w[s p m b c].freeze
43
48
 
@@ -50,6 +55,9 @@ module Pubid
50
55
  "ed" => [:edition, /\A\d+\.\d+\.\d+\z/],
51
56
  "sup" => [:supplement, /\A\d+\z/],
52
57
  "part" => [:part, /\A(?:\d+[a-zA-Z]*|[A-Z]|[SPMBC]-\d+)\z/],
58
+ "spec" => [:spec, /\A[1-6]\d\d\z/],
59
+ "specsub" => [:spec_sub, /\A\d+\z/],
60
+ "specvar" => [:spec_variant, /\A[A-Z]+\z/],
53
61
  "annex" => [:annex, /\A[A-Z]\z/],
54
62
  "appendix" => [:appendix, /\A(?:[A-Z]|\d+)\z/],
55
63
  "vol" => [:volume, /\A\d+\z/],
@@ -63,6 +71,12 @@ module Pubid
63
71
  # follow (the component-edition duality).
64
72
  POSITIONAL_MARKERS = %i[edition year].freeze
65
73
 
74
+ # The S-4 spec node and its children: specsub-/specvar- are only
75
+ # allowed after their parent, and an S-4 spec rides its
76
+ # publication's edition — no ed-/year- inside a spec.
77
+ SPEC_NODES = %i[spec spec_sub spec_variant].freeze
78
+ SPEC_PARENTS = %i[spec spec_sub].freeze
79
+
66
80
  # Legacy dotted keys (deprecated; decodable, never emitted).
67
81
  # "ap" is the pre-positional appendix tag; "suppl" the pre-positional
68
82
  # supplement tag; "y" the pre-positional year tag — under the
@@ -97,11 +111,22 @@ module Pubid
97
111
  # own edition).
98
112
  ctx = { component: nil, edition_owner: nil }
99
113
  consume_segments!(attrs, segments, ctx, urn)
100
- Builder.build({ type: type_token.upcase, **attrs })
114
+ build_identifier({ type: type_token.upcase, **attrs }, urn)
101
115
  end
102
116
 
103
117
  private
104
118
 
119
+ # The semantic validations the builder applies to the decoded shape
120
+ # (the S-4 anchor, the citation letter) are URN validation at this
121
+ # layer: a URN that asserts a citation it cannot carry is a
122
+ # malformed URN, and the raw ArgumentError stays as the cause.
123
+ def build_identifier(hash, urn)
124
+ Builder.build(hash)
125
+ rescue ArgumentError => e
126
+ raise Pubid::Errors::UrnParseError,
127
+ "#{e.message} in #{urn.inspect}"
128
+ end
129
+
105
130
  def read_type!(segments, urn)
106
131
  type_token = segments.shift.to_s.downcase
107
132
  return type_token if TYPE_LETTERS.include?(type_token)
@@ -159,10 +184,9 @@ module Pubid
159
184
  marker, value = MARKER_RE.match(segment).captures
160
185
  key, pattern = MARKERS.fetch(marker)
161
186
  raise_invalid!(marker, value, urn) unless value.match?(pattern)
162
-
163
- if POSITIONAL_MARKERS.include?(key)
164
- return consume_positional!(attrs, key, value, ctx, urn)
165
- end
187
+ assert_spec_parent!(key, ctx, urn)
188
+ return consume_positional!(attrs, key, value, ctx, urn) if
189
+ POSITIONAL_MARKERS.include?(key)
166
190
 
167
191
  store!(attrs, key, value, urn)
168
192
  ctx[:component] = key
@@ -170,6 +194,16 @@ module Pubid
170
194
  consume_subnumber!(attrs, key, segments, ctx, urn)
171
195
  end
172
196
 
197
+ # specsub-/specvar- are children of the spec atom — allowed only
198
+ # in their parent's slot (the SEGMENTS table in the generator).
199
+ def assert_spec_parent!(key, ctx, urn)
200
+ return unless %i[spec_sub spec_variant].include?(key)
201
+ return if SPEC_PARENTS.include?(ctx[:component])
202
+
203
+ raise Pubid::Errors::UrnParseError,
204
+ "#{key}- is only allowed after spec- in #{urn.inspect}"
205
+ end
206
+
173
207
  def raise_invalid!(marker, value, urn)
174
208
  raise Pubid::Errors::UrnParseError,
175
209
  "Invalid #{marker} value #{value.inspect} in #{urn.inspect}"
@@ -177,8 +211,15 @@ module Pubid
177
211
 
178
212
  # ed- and year- are POSITIONAL markers (see the marker docs): the
179
213
  # edition attaches to the component it follows, the year to the
180
- # edition owner.
214
+ # edition owner. An S-4 spec carries neither — it rides its
215
+ # publication's edition.
181
216
  def consume_positional!(attrs, key, value, ctx, urn)
217
+ if SPEC_NODES.include?(ctx[:component])
218
+ raise Pubid::Errors::UrnParseError,
219
+ "an S-4 spec rides its publication's edition: #{key}- " \
220
+ "cannot follow a spec segment in #{urn.inspect}"
221
+ end
222
+
182
223
  if key == :edition
183
224
  return store_component_scoped!(attrs, :edition, value, ctx, urn)
184
225
  end
data/lib/pubid/iho.rb CHANGED
@@ -12,6 +12,7 @@ module Pubid
12
12
  autoload :Identifier, "#{__dir__}/iho/identifiers/base"
13
13
  autoload :Identifiers, "#{__dir__}/iho/identifiers"
14
14
  autoload :Renderer, "#{__dir__}/iho/renderer"
15
+ autoload :ReservedSpecs, "#{__dir__}/iho/reserved_specs"
15
16
  autoload :UrnGenerator, "#{__dir__}/iho/urn_generator"
16
17
  autoload :UrnParser, "#{__dir__}/iho/urn_parser"
17
18
  autoload :PubidUrnSchema, "#{__dir__}/iho/pubid_urn_schema"
@@ -135,3 +135,14 @@ Read this before you change `lib/pubid/nist/` or `spec/pubid/nist/`. The root
135
135
  `spec/pubid/nist/bare_series_reference_spec.rb`; the corpus round froze
136
136
  the six rows (`NBS CS`, `NBS CSM`, `NBS CIS`, `NBS CS-E`, `NIST PS`,
137
137
  `NIST DCI`) into the testsuite with the gem twin in lockstep.
138
+
139
+ - **"FIPS PUB <number>" is a preprocessor alias, not a grammar face
140
+ (pubid#697).** NIST prints the series as "FIPS PUB <number>" but the
141
+ grammar reads "NIST FIPS <number>", so `normalize_fips_pub_alias!`
142
+ (head-anchored, immediately after the publisher/series stage) rewrites
143
+ the printed prefix and the parse lands on exactly the canonical model —
144
+ hash-, render-, URN- and MR-identical to "NIST FIPS <number>". The
145
+ hyphenated numbers and the revision forms the grammar models
146
+ ("FIPS PUB 199 Rev. 1" with its `original_prefix` facet, compact
147
+ "rev1") ride the prefix alias; bare "FIPS <number>"
148
+ (publisher_was_parsed: false) and NBS FIPS are untouched.
@@ -68,6 +68,7 @@ module Pubid
68
68
  end
69
69
  normalize_spurious_u_suffix!
70
70
  normalize_publisher_and_series!
71
+ normalize_fips_pub_alias!
71
72
  normalize_lcirc_supplement_contexts!
72
73
  normalize_revision_spacing!
73
74
  normalize_letter_suffix_casing!
@@ -124,6 +125,21 @@ module Pubid
124
125
  @cleaned = @cleaned.gsub(/\bLC\b(?!IRC)/, "LCIRC")
125
126
  end
126
127
 
128
+ # The FIPS series' own printed face: NIST prints the series as
129
+ # "FIPS PUB <number>" (document cover and catalogue style), so the
130
+ # grammar accepts the publisher-prefixed canonical form only through
131
+ # this alias (pubid#697). Rewrites the prefix to "NIST FIPS", the
132
+ # spelling the grammar already reads, and the printed-form parse
133
+ # therefore lands on exactly the model "NIST FIPS <number>" builds
134
+ # (same to_hash, same render, revision spellings like
135
+ # "FIPS PUB 199 Rev. 1" included). Anchored at the head and run
136
+ # before every other stage so later digit/marker stages see the
137
+ # canonical face; "FIPS" alone (publisher_was_parsed: false) is
138
+ # untouched.
139
+ def normalize_fips_pub_alias!
140
+ @cleaned = @cleaned.sub(/\AFIPS PUB\b/i, "NIST FIPS")
141
+ end
142
+
127
143
  # LCIRC series: combine with NBS prefix when a supplement marker
128
144
  # follows, and convert MR-format dots to spaces so the grammar's
129
145
  # circ_supplement_identifier rule can match.
@@ -11,3 +11,38 @@ Integer, so its core is `:int` (`core: [["number", :int]]`): `#00` is the core
11
11
  `0`, and `00` in a URN is not canonical. The Annex type has no `number`; it
12
12
  has no core, its document comes first along `base`, and its `letter` is an
13
13
  atom. No input makes an Annex today, so the spec builds one by hand.
14
+
15
+ ## Handbook volume label (本編 / 本編+付録)
16
+
17
+ MLIT publishes Handbook #00 edition 5.0 twice on one date: `第5.0版 本編`
18
+ (main volume) and `第5.0版 本編+付録` (main volume and appendix, one PDF);
19
+ edition 6.0 only as `本編+付録`. `Identifiers::Handbook#volume` keeps that
20
+ label as Japanese text, as `edition` keeps `第X.Y版`. The grammar accepts it
21
+ only after an edition, separated by an ASCII or a full-width (U+3000) space,
22
+ with `+` or ASCII `+`; the builder normalizes `+` to `+`, and `to_s` writes
23
+ one ASCII space before it. The renderer prints the volume only after an
24
+ edition, so `exclude(:edition)` still renders a string that parses.
25
+ `volume` is in `==` and is `subset_strict`, so `#00 第5.0版` matches neither
26
+ labelled publication. A nil volume leaves no key in `to_hash`, so the
27
+ existing index-v2 rows keep their hash. The pubid-scheme URN carries it as
28
+ the `vol-` atom; `to_urn` is unchanged (it has no edition either). Locked by
29
+ `spec/pubid/plateau/handbook_volume_spec.rb`.
30
+
31
+ Known gaps, not caused by this change: a Technical Report drops an edition
32
+ and a volume without a diagnostic (the `handbook` rule matches any
33
+ `doc_type`), and `to_mr_string` raises for every Handbook with an edition
34
+ (the base `mr_edition` calls `edition.number` on a String).
35
+
36
+ ## The grammar is baked here ahead of pubid-grammar
37
+
38
+ `data/parg/plateau.json` was compiled here from its own embedded `source`
39
+ plus the volume rule, at parsanol **1.3.114** (the version of the earlier
40
+ bake; force it with `gem "parsanol", "1.3.114"`, as
41
+ `pubid-grammar/scripts/bake-one.rb` does, because the binstub resolves the
42
+ latest installed gem). Until pubid-grammar takes hand-off
43
+ `pubid__pubid-grammar__plateau-handbook-volume`, its `grammars/plateau.parg`
44
+ is the OLD grammar. To change the grammar, extract the source with
45
+ `jq -j .source data/parg/plateau.json` (`-j`: the source has no trailing
46
+ newline, and one extra byte changes the checksum), edit, re-bake, then run
47
+ `bundle exec parsanol parg test data/parg/plateau.json`. Read the `.parg`
48
+ file as UTF-8: under a US-ASCII locale the parsanol lexer raises on `第`.
@@ -34,6 +34,10 @@ module Pubid
34
34
  if parsed[:edition] && klass == Identifiers::Handbook
35
35
  params[:edition] = parsed[:edition].to_s
36
36
  end
37
+ # The grammar accepts an ASCII "+"; MLIT prints the full-width "+".
38
+ if parsed[:volume] && klass == Identifiers::Handbook
39
+ params[:volume] = parsed[:volume].to_s.tr("+", "+")
40
+ end
37
41
 
38
42
  klass.new(**params)
39
43
  end
@@ -4,10 +4,18 @@ module Pubid
4
4
  module Plateau
5
5
  module Identifiers
6
6
  # PLATEAU Handbook
7
- # Format: PLATEAU Handbook #NN[-annex] [第X.Y版]
7
+ # Format: PLATEAU Handbook #NN[-annex] [第X.Y版[ volume]]
8
8
  # Example: PLATEAU Handbook #00 第1.0版
9
+ # Example: PLATEAU Handbook #00 第5.0版 本編+付録
9
10
  class Handbook < Identifier
10
11
  attribute :edition, :string, default: -> {}
12
+ # The volume label MLIT prints after the edition: "本編" (the main
13
+ # volume alone) or "本編+付録" (main volume and appendix, one PDF).
14
+ attribute :volume, :string, default: -> {}
15
+
16
+ # A nil `volume` means the publication has no volume label:
17
+ # `#00 第5.0版` does not subsume `#00 第5.0版 本編+付録`.
18
+ subset_strict :volume
11
19
 
12
20
  def type_string
13
21
  "Handbook"
@@ -20,7 +28,7 @@ module Pubid
20
28
  def ==(other)
21
29
  return false unless other.is_a?(Handbook)
22
30
 
23
- super && edition == other.edition
31
+ super && edition == other.edition && volume == other.volume
24
32
  end
25
33
  end
26
34
  end
@@ -13,6 +13,7 @@ module Pubid
13
13
  atom "publisher", "pub"
14
14
  atom "edition", "ed"
15
15
  atom "annex", "annex", kind: :int
16
+ atom "volume", "vol"
16
17
 
17
18
  number = [["number", :int]]
18
19
  type "pubid:plateau:annex", "annex", core: [],
@@ -39,7 +39,12 @@ module Pubid
39
39
 
40
40
  def render_handbook(id)
41
41
  result = "#{id.publisher} #{id.type_string} #{id.formatted_number}#{id.formatted_annex}"
42
- result += " #{id.formatted_edition}" if id.edition
42
+ return result unless id.edition
43
+
44
+ # The grammar reads a volume label only after an edition, so a
45
+ # volume without one (e.g. after exclude(:edition)) is not printed.
46
+ result += " #{id.formatted_edition}"
47
+ result += " #{id.volume}" if id.volume
43
48
  result
44
49
  end
45
50
 
@@ -12,8 +12,17 @@ Measured on the full deposit list (2026-11-04, 47,692 DOIs): **46,726
12
12
  parse**, and every parsed code round-trips through `to_s`, `from_hash` and
13
13
  the URN, with **0 `to_hash` collisions**. The 966 that do not parse are:
14
14
 
15
- - **791 CP\*** (`CPGM`, `CPFD`, `CPKW`, …): collected-paper products, not
16
- standards. Out of scope by decision.
15
+ - **791 CP\*** (`CPGM`, `CPFD`, `CPKW`, …): SAE "Certified Power" data
16
+ products — engine power/torque data certified under SAE J1349, one per
17
+ vehicle and level (`CPGM2_15LFXCOCA`: "J1349 Certified Power Engine Data
18
+ for GM as used in 2015 LFX Colorado/Canyon - Level 2"). The letters after
19
+ `CP` name the manufacturer (`GM`, `FD` Ford, `FC` FCA, …). They are data
20
+ products, not standards, and stay out of `TYPES` by decision (pubid#686).
21
+ `SAE CPGM2016` in pubid#686 is not a deposit: it is the synthetic DOI of
22
+ relaton's "reports a record pubid cannot parse" spec
23
+ (`spec/sae/relaton/sae/data_fetcher_spec.rb`), which, with
24
+ `bibliography_spec.rb` and `docs/sae.md`, relies on it failing to parse.
25
+ `spec/pubid/sae/crossref_coverage_spec.rb` pins the rejection.
17
26
  - **175 one-offs**, none more than 32 of a kind: `SUP1` supplements
18
27
  (`AS4468SUP1A`, `ARP4737SUP1`), language tails (`AS9101F_PTBR`,
19
28
  `IA9137_DEDE`), `J2534-2/10_5_00`, `_4Q2012`, type-less `SAE6857`,
data/lib/pubid/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Pubid
4
- VERSION = "2.0.20"
4
+ VERSION = "2.0.21"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pubid
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.20
4
+ version: 2.0.21
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-11-10 00:00:00.000000000 Z
11
+ date: 2026-11-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: lutaml-model
@@ -71,6 +71,7 @@ files:
71
71
  - data/iec/stage-codes.md
72
72
  - data/iec/update_codes.yaml
73
73
  - data/ieee/update_codes.yaml
74
+ - data/iho/s4-reserved-specs.yaml
74
75
  - data/iso/update_codes.yaml
75
76
  - data/nist/series.yaml
76
77
  - data/nist/stages.yaml
@@ -733,6 +734,7 @@ files:
733
734
  - lib/pubid/iho/identifiers/standard.rb
734
735
  - lib/pubid/iho/pubid_urn_schema.rb
735
736
  - lib/pubid/iho/renderer.rb
737
+ - lib/pubid/iho/reserved_specs.rb
736
738
  - lib/pubid/iho/urn_generator.rb
737
739
  - lib/pubid/iho/urn_parser.rb
738
740
  - lib/pubid/isbn.rb