pubid 2.0.0.pre.alpha.57 → 2.0.0.pre.alpha.59
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.
- checksums.yaml +4 -4
- data/data/iec/stage-codes.md +1 -9
- data/data/parg/ieee.json +2052 -1685
- data/lib/pubid/iec/CLAUDE.md +1 -1
- data/lib/pubid/ieee/builder.rb +42 -8
- data/lib/pubid/ieee/components/draft.rb +6 -1
- data/lib/pubid/ieee/identifiers/base.rb +23 -5
- data/lib/pubid/ieee/renderer.rb +9 -4
- data/lib/pubid/version.rb +1 -1
- metadata +2 -2
data/lib/pubid/iec/CLAUDE.md
CHANGED
|
@@ -30,4 +30,4 @@ These notes were part of the root `CLAUDE.md`. Read them before you change `lib/
|
|
|
30
30
|
|
|
31
31
|
**Two parent-slot gaps recorded by the cross-flavor `base` survey** (`lib/pubid/bsi/CLAUDE.md` has the measured version). `Identifiers::TestReportForm#cispr_identifier` is a polymorphic `Identifier` parent slot with no `#root` override, so `root` returns the form itself. And `Identifiers::ConsolidatedIdentifier#base_document` returns `identifiers&.first` **without** the recursive `&.base_document` that its BSI, CSA and CEN counterparts use — a one-level peel where the others peel fully, so a consolidated edition of a supplement does not reduce to the bare standard. Neither is chased here; both are pinned by nothing, which is why they are written down.
|
|
32
32
|
|
|
33
|
-
**Stage codes — the SSOT and what is settled.** The authoritative source for IEC stage abbreviations is committed in this repo: **`data/iec/stage-codes.md`** — the 52-row IEC/ISO stage-code correspondence table transcribed from IEC's official *IEC/ISO Harmonized APIs* documents (v0.0.8 2023-06, api-portal.iec.ch; v0.0.7 2021-05, iec-apiportal.apigee.io — the successors that replace the IEC Data Feeds), the legacy Data-Feeds field examples, and the IS-lifecycle ladder from `StageCodes_IS_v2.pdf` (2023-06). `www.iec.ch` itself is fully WAF-gated to non-browsers and the Wayback Machine holds no snapshots of its PDFs, so the extract — not the unreachable original — is the reference. **`Pubid::Iec.locate_stage` reads `TYPED_STAGES` only** (`lib/pubid/iec.rb`); `PROJECT_STAGES` (AFDIS, TCDV, PRVC…) are not queryable through it. Every one of metanorma-iec's 55 `STAGE_CODES` — the list quoted in pubid#237 — resolves, locked by `spec/pubid/iec/typed_stages_spec.rb` in the issue's own order; aliases are always **appended, never prepended**, so `abbr.first` (what renders) is unchanged. Notable rulings from that pass: **ADIS** is the legacy Data-Feeds spelling of AFDIS ("Approved for FDIS circulation", ISO_LEVEL 40.99) and is an alias on `cdv` (the typed stage claiming 40.99); **CDISH/CDPAS** are the 50.20 rows of the DISH/DPAS deliverables, not "committee draft ISH/PAS" (30.xx);
|
|
33
|
+
**Stage codes — the SSOT and what is settled.** The authoritative source for IEC stage abbreviations is committed in this repo: **`data/iec/stage-codes.md`** — the 52-row IEC/ISO stage-code correspondence table transcribed from IEC's official *IEC/ISO Harmonized APIs* documents (v0.0.8 2023-06, api-portal.iec.ch; v0.0.7 2021-05, iec-apiportal.apigee.io — the successors that replace the IEC Data Feeds), the legacy Data-Feeds field examples, and the IS-lifecycle ladder from `StageCodes_IS_v2.pdf` (2023-06). `www.iec.ch` itself is fully WAF-gated to non-browsers and the Wayback Machine holds no snapshots of its PDFs, so the extract — not the unreachable original — is the reference. **`Pubid::Iec.locate_stage` reads `TYPED_STAGES` only** (`lib/pubid/iec.rb`); `PROJECT_STAGES` (AFDIS, TCDV, PRVC…) are not queryable through it. Every one of metanorma-iec's 55 `STAGE_CODES` — the list quoted in pubid#237 — resolves, locked by `spec/pubid/iec/typed_stages_spec.rb` in the issue's own order; aliases are always **appended, never prepended**, so `abbr.first` (what renders) is unchanged. Notable rulings from that pass: **ADIS** is the legacy Data-Feeds spelling of AFDIS ("Approved for FDIS circulation", ISO_LEVEL 40.99) and is an alias on `cdv` (the typed stage claiming 40.99); **CDISH/CDPAS** are the 50.20 rows of the DISH/DPAS deliverables, not "committee draft ISH/PAS" (30.xx); **Reconciliation items recorded in the extract, deliberately not applied:** DELPUB sits at 99.60 there while the `is` ladder does not claim 99.60; CAN carries two codes (30.98 IS/TR/TS, 50.98 PAS/ISH/COR); the rows CDISH-table-siblings DECDISH/MERGED/SPLIT/PCC/PRVN/DEL/RPUB/TPUB and the per-deliverable translation/preparation families are not registered as typed-stage abbreviations.
|
data/lib/pubid/ieee/builder.rb
CHANGED
|
@@ -1079,11 +1079,17 @@ module Pubid
|
|
|
1079
1079
|
# P + a /D designator (any draft capture) is a DRAFT, never a
|
|
1080
1080
|
# printed Std (the owner's 2026-10-24 ruling): the P marker is
|
|
1081
1081
|
# project status, so the joint/project-draft family owns the row
|
|
1082
|
-
# whatever date trails the designator. The
|
|
1083
|
-
#
|
|
1084
|
-
|
|
1082
|
+
# whatever date trails the designator. The ruling extends to the
|
|
1083
|
+
# P-less joint rows (pubid#597): a numeric /D designator alone is
|
|
1084
|
+
# project status too — the row is a draft AND takes the P, so the
|
|
1085
|
+
# marker is set below when the source spelling lacked it.
|
|
1086
|
+
p_with_draft = (parsed[:project_marker] || numeric_draft) &&
|
|
1085
1087
|
(parsed[:draft_version] || parsed[:draft_iso_stage] ||
|
|
1086
1088
|
parsed[:draft_month] || parsed[:draft_year])
|
|
1089
|
+
if p_with_draft && !parsed[:project_marker]
|
|
1090
|
+
attributes[:project_marker] = true
|
|
1091
|
+
parsed[:project_marker] = "P"
|
|
1092
|
+
end
|
|
1087
1093
|
printed_joint = parsed[:iso_published] && parsed[:iso_stage].nil? &&
|
|
1088
1094
|
!p_with_draft &&
|
|
1089
1095
|
(parsed[:printed_dash_year] || parsed[:printed_month_year] ||
|
|
@@ -1151,6 +1157,13 @@ module Pubid
|
|
|
1151
1157
|
return Identifiers::Standard.new(**printed_attrs.compact)
|
|
1152
1158
|
end
|
|
1153
1159
|
|
|
1160
|
+
# The designation route ("IEEE P24748-4/D=FDIS") has no
|
|
1161
|
+
# publishers group and no parsed publisher slot; IEEE is the
|
|
1162
|
+
# sole publisher of the D= designator face, and the elections
|
|
1163
|
+
# below read the builder-local slots.
|
|
1164
|
+
attributes[:publisher] ||= "IEEE"
|
|
1165
|
+
attributes[:copublisher] ||= []
|
|
1166
|
+
|
|
1154
1167
|
# The re-parse of the pubid#203 designator render ("IEEE
|
|
1155
1168
|
# P15026.2/D=FDIS-201008") captures the stage and the verbatim
|
|
1156
1169
|
# date token (":2020", "-201008") with no publisher slot; the
|
|
@@ -1182,9 +1195,12 @@ module Pubid
|
|
|
1182
1195
|
if parsed[:iso_stage_iteration]
|
|
1183
1196
|
stage_abbr += extract_value(parsed[:iso_stage_iteration])
|
|
1184
1197
|
end
|
|
1198
|
+
# The designation route ("IEEE P24748-4/D=FDIS") carries no
|
|
1199
|
+
# publishers group, so the builder-local copublisher is nil on
|
|
1200
|
+
# it — the empty test must admit nil as none.
|
|
1185
1201
|
bare_ieee_project = parsed[:project_marker] &&
|
|
1186
1202
|
attributes[:publisher] == "IEEE" &&
|
|
1187
|
-
attributes[:copublisher]
|
|
1203
|
+
(attributes[:copublisher] || []).empty?
|
|
1188
1204
|
if bare_ieee_project && parsed[:draft_stage_year].nil?
|
|
1189
1205
|
# pubid#203: a bare-IEEE project row carrying an ISO stage is
|
|
1190
1206
|
# an IEEE draft of joint ISO/IEC work ("IEEE FDIS P15026.2,
|
|
@@ -1262,8 +1278,15 @@ module Pubid
|
|
|
1262
1278
|
# rather than the joint-development model.
|
|
1263
1279
|
if attributes[:draft] && parsed[:iso_stage].nil? &&
|
|
1264
1280
|
parsed[:iec_stage].nil? && parsed[:amd_number].nil?
|
|
1265
|
-
|
|
1266
|
-
|
|
1281
|
+
# The ruling (pubid#597): a joint row with a numeric /D designator
|
|
1282
|
+
# is a draft AND takes the P project marker, whatever the source
|
|
1283
|
+
# spelling printed — the marker is set on the identifier (and the
|
|
1284
|
+
# code prepended) even when the row reached it without one.
|
|
1285
|
+
draft_code = attributes[:code].to_s
|
|
1286
|
+
draft_code = "P" + draft_code unless draft_code.start_with?("P")
|
|
1287
|
+
draft_attrs = { code: draft_code,
|
|
1288
|
+
draft: attributes[:draft],
|
|
1289
|
+
project_marker: true }
|
|
1267
1290
|
if attributes[:publishers]
|
|
1268
1291
|
draft_attrs[:publisher] = attributes[:publishers].first
|
|
1269
1292
|
rest = attributes[:publishers][1..]
|
|
@@ -1517,9 +1540,13 @@ module Pubid
|
|
|
1517
1540
|
if pub_data[:copublishers]
|
|
1518
1541
|
copubs = pub_data[:copublishers]
|
|
1519
1542
|
copubs = [copubs] unless copubs.is_a?(Array)
|
|
1543
|
+
# A capture may carry its own separators ("/IEC/ISO" — a
|
|
1544
|
+
# joint token glued to the leading slash); the copublisher
|
|
1545
|
+
# collection renders join("/"), so entries hold bare orgs.
|
|
1520
1546
|
attributes[:copublisher] = copubs.filter_map do |cp|
|
|
1521
1547
|
extract_value(cp[:copublisher])
|
|
1522
|
-
end
|
|
1548
|
+
end.flat_map { |c| c.to_s.sub(%r{\A/}, "").split("/") }
|
|
1549
|
+
.reject(&:empty?)
|
|
1523
1550
|
end
|
|
1524
1551
|
elsif parsed[:publisher]
|
|
1525
1552
|
attributes[:publisher] = extract_value(parsed[:publisher])
|
|
@@ -2008,7 +2035,14 @@ module Pubid
|
|
|
2008
2035
|
end
|
|
2009
2036
|
end
|
|
2010
2037
|
else
|
|
2011
|
-
|
|
2038
|
+
# A degraded wire leaf carries the whole draft clause verbatim
|
|
2039
|
+
# ("/D2.1.1" — the three-segment designator the engine cannot
|
|
2040
|
+
# structure): Draft.parse is the inverse of Draft#to_s, so it
|
|
2041
|
+
# strips the prefix instead of double-appending it.
|
|
2042
|
+
draft = Components::Draft.parse(extract_value(draft_data).to_s)
|
|
2043
|
+
attributes[:draft_obj] = draft
|
|
2044
|
+
attributes[:draft] = draft.to_s
|
|
2045
|
+
return
|
|
2012
2046
|
end
|
|
2013
2047
|
|
|
2014
2048
|
# A stage-token draft's month rides the D= designator zero-padded
|
|
@@ -169,7 +169,12 @@ day: nil, iso_stage: nil, iso_iteration: nil)
|
|
|
169
169
|
end
|
|
170
170
|
|
|
171
171
|
def to_s
|
|
172
|
-
|
|
172
|
+
# A version that already opens with a designator word ("ED4",
|
|
173
|
+
# the IEC edition-draft ordinal; an ISO/IEC stage token such
|
|
174
|
+
# as "FDIS_March") renders verbatim — prepending D
|
|
175
|
+
# concatenates a hallucinated token ("DED4", "DFDIS") that no
|
|
176
|
+
# face spells. Every other version keeps the D designator.
|
|
177
|
+
result = version&.match?(/\A(ED\d|(FDIS|FCD|CDV|DIS|CD|WD|PWI|NP))/) ? "/#{version}" : "/D#{version}"
|
|
173
178
|
result += "=#{iso_stage}" if iso_stage
|
|
174
179
|
result += ".#{iso_iteration}" if iso_stage && iso_iteration
|
|
175
180
|
result += if revision.to_s.start_with?(".")
|
|
@@ -120,13 +120,13 @@ module Pubid
|
|
|
120
120
|
# Handle draft as component object
|
|
121
121
|
if args[:draft_obj]
|
|
122
122
|
self.draft_obj = args[:draft_obj]
|
|
123
|
-
self.draft = args[:draft_obj].to_s
|
|
123
|
+
self.draft = args[:draft_obj].to_s.sub(%r{\A/}, "")
|
|
124
124
|
elsif args[:draft].is_a?(String)
|
|
125
125
|
self.draft_obj = Components::Draft.parse(args[:draft])
|
|
126
|
-
self.draft = draft_obj.to_s
|
|
126
|
+
self.draft = draft_obj.to_s.sub(%r{\A/}, "")
|
|
127
127
|
elsif args[:draft]
|
|
128
128
|
self.draft_obj = args[:draft]
|
|
129
|
-
self.draft = args[:draft].to_s
|
|
129
|
+
self.draft = args[:draft].to_s.sub(%r{\A/}, "")
|
|
130
130
|
end
|
|
131
131
|
|
|
132
132
|
# Set other attributes.
|
|
@@ -150,9 +150,11 @@ module Pubid
|
|
|
150
150
|
public_send(setter, value)
|
|
151
151
|
end
|
|
152
152
|
end
|
|
153
|
+
|
|
153
154
|
end
|
|
154
155
|
|
|
155
|
-
|
|
156
|
+
# Override accessors to return component objects.
|
|
157
|
+
|
|
156
158
|
def code
|
|
157
159
|
code_obj
|
|
158
160
|
end
|
|
@@ -231,7 +233,23 @@ module Pubid
|
|
|
231
233
|
# no expansion (Draft.parse accepts the slashless form).
|
|
232
234
|
def self.from_hash(data, options = {})
|
|
233
235
|
data = Compaction.expand(Compaction.deep_dup(data)) if data.is_a?(::Hash)
|
|
234
|
-
super
|
|
236
|
+
identifier = super
|
|
237
|
+
# == compares the raw ivars: a rebuild whose lazy readers have not
|
|
238
|
+
# run carries @code_obj/@draft_obj nil while a parse has them set,
|
|
239
|
+
# so the objects compare unequal although their serialized hashes
|
|
240
|
+
# agree (pubid#596). Materialize the runtime components eagerly.
|
|
241
|
+
identifier.materialize_runtime_components
|
|
242
|
+
identifier
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
# Rebuild the runtime components from the wire strings. Safe on every
|
|
246
|
+
# construction path: the readers' ||= no-ops when already set, and the
|
|
247
|
+
# CodeNumber rebuild covers the split-column rows that carry no code
|
|
248
|
+
# string.
|
|
249
|
+
def materialize_runtime_components
|
|
250
|
+
code_obj
|
|
251
|
+
draft_obj
|
|
252
|
+
self
|
|
235
253
|
end
|
|
236
254
|
|
|
237
255
|
# Register the identifier classes the automatic `Identifiers::*` scan
|
data/lib/pubid/ieee/renderer.rb
CHANGED
|
@@ -141,11 +141,16 @@ module Pubid
|
|
|
141
141
|
# so the WHOLE type word is dropped — not just "Std" (pubid#318: the
|
|
142
142
|
# half-strip left "Draft" in the render, the re-parse dropped it, and
|
|
143
143
|
# to_s needed three rounds to converge while losing the type).
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
144
|
+
# A project draft carries the word Draft whatever the lead
|
|
145
|
+
# publisher — the ISO-led joint drafts (pubid#597) print it too.
|
|
146
|
+
should_render_type = id.publisher&.match?(/^(IEEE|AIEE)/) ||
|
|
147
|
+
id.is_a?(Identifiers::ProjectDraftIdentifier)
|
|
148
|
+
|
|
149
|
+
if should_render_type && !id.typed_stage&.project_status &&
|
|
150
|
+
((id.type && !id.type.to_s.strip.empty? && id.type != "P") ||
|
|
151
|
+
id.is_a?(Identifiers::ProjectDraftIdentifier)) &&
|
|
147
152
|
!id.draft_status.to_s.match?(/unapproved/i)
|
|
148
|
-
type_str = id.type.dup
|
|
153
|
+
type_str = id.type ? id.type.dup : "Draft"
|
|
149
154
|
type_str = type_str.sub(/^P/, "") if type_str.start_with?("P")
|
|
150
155
|
# A draft carries the word Draft alone in every face (the C2
|
|
151
156
|
# ruling): Std/Standard never renders on a draft, whatever
|
data/lib/pubid/version.rb
CHANGED
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.0.pre.alpha.
|
|
4
|
+
version: 2.0.0.pre.alpha.59
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-10-
|
|
11
|
+
date: 2026-10-25 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: lutaml-model
|