suma 0.5.7 → 0.5.8
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/.github/workflows/nightly-benchmark.yml +25 -0
- data/.github/workflows/release-provenance.yml +38 -0
- data/.rubocop_todo.yml +84 -0
- data/CLAUDE.md +44 -0
- data/Rakefile +13 -1
- data/bin/benchmark_corpus +138 -0
- data/bin/release_provenance +40 -0
- data/lib/suma/build_plan.rb +71 -0
- data/lib/suma/change_classification.rb +37 -0
- data/lib/suma/change_impact.rb +61 -0
- data/lib/suma/change_manifest.rb +147 -0
- data/lib/suma/cli/build.rb +23 -0
- data/lib/suma/cli/compare.rb +49 -2
- data/lib/suma/cli/core.rb +83 -0
- data/lib/suma/cli/export.rb +140 -10
- data/lib/suma/cli/extract_terms.rb +11 -0
- data/lib/suma/cli/generate_register.rb +12 -0
- data/lib/suma/cli/resolve.rb +45 -0
- data/lib/suma/cli/validate.rb +90 -0
- data/lib/suma/cli.rb +1 -0
- data/lib/suma/closure_validator.rb +317 -0
- data/lib/suma/corpus_graph.rb +141 -0
- data/lib/suma/express_schema.rb +22 -28
- data/lib/suma/null_cache.rb +4 -0
- data/lib/suma/owl_projection.rb +611 -0
- data/lib/suma/processor.rb +55 -6
- data/lib/suma/provenance.rb +159 -0
- data/lib/suma/publication.rb +108 -0
- data/lib/suma/register_manifest_generator.rb +76 -8
- data/lib/suma/schema_cache.rb +72 -13
- data/lib/suma/schema_category.rb +31 -2
- data/lib/suma/schema_collection.rb +58 -5
- data/lib/suma/schema_exporter.rb +5 -5
- data/lib/suma/schema_naming.rb +29 -33
- data/lib/suma/schema_profile.rb +134 -0
- data/lib/suma/term_classification.rb +9 -2
- data/lib/suma/term_extractor.rb +76 -35
- data/lib/suma/urn_resolver.rb +318 -0
- data/lib/suma/version.rb +1 -1
- data/lib/suma/worker_pool.rb +62 -0
- data/lib/suma.rb +12 -0
- metadata +19 -2
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Suma
|
|
4
|
+
# The typed change taxonomy (S3): every schema change is classified as
|
|
5
|
+
# additive, compatible, breaking, or editorial.
|
|
6
|
+
#
|
|
7
|
+
# The mapping is data — a frozen Hash keyed by the eengine action — so a
|
|
8
|
+
# finer-grained rule is a one-line addition. Modifications are classified
|
|
9
|
+
# as breaking conservatively: eengine reports structural deltas (type
|
|
10
|
+
# changes, attribute additions on entities, interface changes) without
|
|
11
|
+
# enough detail to prove backwards compatibility, so additive/editorial
|
|
12
|
+
# claims are only made where the action itself guarantees them.
|
|
13
|
+
class ChangeClassification
|
|
14
|
+
ADDITIVE = "additive"
|
|
15
|
+
COMPATIBLE = "compatible"
|
|
16
|
+
BREAKING = "breaking"
|
|
17
|
+
EDITORIAL = "editorial"
|
|
18
|
+
|
|
19
|
+
BY_ACTION = {
|
|
20
|
+
"added" => ADDITIVE,
|
|
21
|
+
"removed" => BREAKING,
|
|
22
|
+
"modified" => BREAKING,
|
|
23
|
+
"mapping" => EDITORIAL,
|
|
24
|
+
}.freeze
|
|
25
|
+
|
|
26
|
+
ALL = [ADDITIVE, COMPATIBLE, BREAKING, EDITORIAL].freeze
|
|
27
|
+
|
|
28
|
+
# @param action [String, Symbol] added / removed / modified / mapping
|
|
29
|
+
# @return [String] one of ALL
|
|
30
|
+
def self.classify(action:)
|
|
31
|
+
BY_ACTION.fetch(action.to_s) do
|
|
32
|
+
raise Error, "[suma] unknown change action #{action.inspect} " \
|
|
33
|
+
"(known: #{BY_ACTION.keys.sort.join(', ')})"
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "expressir"
|
|
4
|
+
require "pathname"
|
|
5
|
+
|
|
6
|
+
module Suma
|
|
7
|
+
# Change-impact analysis (S3): given a changed schema, which schemas and
|
|
8
|
+
# AP publications are affected?
|
|
9
|
+
#
|
|
10
|
+
# Walks the reverse interface closure of the CorpusGraph, so the answer
|
|
11
|
+
# is transitive: every schema that USEs FROM the changed schema directly
|
|
12
|
+
# or through other schemas is reported, and every AP publication whose
|
|
13
|
+
# dependency closure contains the changed schema is flagged.
|
|
14
|
+
class ChangeImpact
|
|
15
|
+
attr_reader :graph, :schema_manifest_file
|
|
16
|
+
|
|
17
|
+
# @param graph [CorpusGraph]
|
|
18
|
+
# @param schema_manifest_file [String] corpus manifest, for AP detection
|
|
19
|
+
def initialize(graph, schema_manifest_file)
|
|
20
|
+
@graph = graph
|
|
21
|
+
@schema_manifest_file = schema_manifest_file
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# @param schema_id [String] the changed schema
|
|
25
|
+
# @return [Array<String>] transitively affected schema ids
|
|
26
|
+
def affected_schemas(schema_id)
|
|
27
|
+
graph.dependents_of(schema_id)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# @param schema_id [String] the changed schema
|
|
31
|
+
# @return [Array<String>] AP publication leads whose closure includes it
|
|
32
|
+
def affected_publications(schema_id)
|
|
33
|
+
target = schema_id.to_s.downcase
|
|
34
|
+
application_protocol_ids.select do |lead|
|
|
35
|
+
graph.dependency_closure(lead).include?(target)
|
|
36
|
+
end.sort
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# @param schema_id [String]
|
|
40
|
+
# @return [Hash]
|
|
41
|
+
def report(schema_id)
|
|
42
|
+
{
|
|
43
|
+
"schema" => schema_id,
|
|
44
|
+
"affected_schemas" => affected_schemas(schema_id),
|
|
45
|
+
"affected_publications" => affected_publications(schema_id),
|
|
46
|
+
}
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
private
|
|
50
|
+
|
|
51
|
+
def application_protocol_ids
|
|
52
|
+
manifest = Expressir::SchemaManifest.from_file(
|
|
53
|
+
File.expand_path(schema_manifest_file),
|
|
54
|
+
)
|
|
55
|
+
manifest.schemas.select do |entry|
|
|
56
|
+
SchemaCategory.for_schema(id: entry.id, path: entry.path) ==
|
|
57
|
+
SchemaCategory::APPLICATION_PROTOCOLS
|
|
58
|
+
end.map { |entry| entry.id.downcase }
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "lutaml/model"
|
|
4
|
+
require "expressir/changes"
|
|
5
|
+
|
|
6
|
+
module Suma
|
|
7
|
+
# One typed change entry: which element changed, how, and whether the
|
|
8
|
+
# change is additive/compatible/breaking/editorial.
|
|
9
|
+
class ChangeEntry < Lutaml::Model::Serializable
|
|
10
|
+
attribute :element, :string
|
|
11
|
+
attribute :element_type, :string
|
|
12
|
+
attribute :action, :string
|
|
13
|
+
attribute :classification, :string
|
|
14
|
+
attribute :description, :string, collection: true
|
|
15
|
+
|
|
16
|
+
yaml do
|
|
17
|
+
map "element", to: :element
|
|
18
|
+
map "element_type", to: :element_type
|
|
19
|
+
map "action", to: :action
|
|
20
|
+
map "classification", to: :classification
|
|
21
|
+
map "description", to: :description
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# The typed change manifest for one schema edition pair (S3): the
|
|
26
|
+
# machine-readable companion to eengine's .changes.yaml.
|
|
27
|
+
#
|
|
28
|
+
# Built from the Expressir::Changes::SchemaChange model (the same model
|
|
29
|
+
# the .changes.yaml embodies), adding the classification dimension and a
|
|
30
|
+
# rendered changelog.
|
|
31
|
+
class ChangeManifest < Lutaml::Model::Serializable
|
|
32
|
+
attribute :schema, :string
|
|
33
|
+
attribute :version, :integer
|
|
34
|
+
attribute :entries, ChangeEntry, collection: true
|
|
35
|
+
|
|
36
|
+
yaml do
|
|
37
|
+
map "schema", to: :schema
|
|
38
|
+
map "version", to: :version
|
|
39
|
+
map "entries", to: :entries
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
class << self
|
|
43
|
+
# Build a manifest from a SchemaChange model.
|
|
44
|
+
#
|
|
45
|
+
# @param change [Expressir::Changes::SchemaChange]
|
|
46
|
+
# @param version [Integer, String, nil] version to select
|
|
47
|
+
# (default: the latest)
|
|
48
|
+
# @return [ChangeManifest]
|
|
49
|
+
def from_schema_change(change, version: nil)
|
|
50
|
+
selected = select_version(change.versions, version)
|
|
51
|
+
return new(schema: change.schema) if selected.nil?
|
|
52
|
+
|
|
53
|
+
new(
|
|
54
|
+
schema: change.schema,
|
|
55
|
+
version: selected.version,
|
|
56
|
+
entries: entries_for(selected),
|
|
57
|
+
)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Build a manifest from a .changes.yaml file.
|
|
61
|
+
#
|
|
62
|
+
# @param path [String]
|
|
63
|
+
# @param version [Integer, String, nil]
|
|
64
|
+
# @return [ChangeManifest]
|
|
65
|
+
def from_file(path, version: nil)
|
|
66
|
+
from_schema_change(
|
|
67
|
+
Expressir::Changes::SchemaChange.from_file(path),
|
|
68
|
+
version: version,
|
|
69
|
+
)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
private
|
|
73
|
+
|
|
74
|
+
def select_version(versions, version)
|
|
75
|
+
return versions.last if version.nil?
|
|
76
|
+
|
|
77
|
+
versions.find { |candidate| candidate.version == version.to_i }
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def entries_for(version_change)
|
|
81
|
+
entries = []
|
|
82
|
+
entries.concat(item_entries(version_change.additions, "added"))
|
|
83
|
+
entries.concat(item_entries(version_change.modifications, "modified"))
|
|
84
|
+
entries.concat(item_entries(version_change.deletions, "removed"))
|
|
85
|
+
entries.concat(mapping_entries(version_change.mappings))
|
|
86
|
+
entries.concat(mapping_entries(version_change.changes))
|
|
87
|
+
entries
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def item_entries(items, action)
|
|
91
|
+
Array(items).map do |item|
|
|
92
|
+
ChangeEntry.new(
|
|
93
|
+
element: item.name,
|
|
94
|
+
element_type: item.type,
|
|
95
|
+
action: action,
|
|
96
|
+
classification: ChangeClassification.classify(action: action),
|
|
97
|
+
description: Array(item.description),
|
|
98
|
+
)
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def mapping_entries(mappings)
|
|
103
|
+
Array(mappings).map do |mapping|
|
|
104
|
+
ChangeEntry.new(
|
|
105
|
+
element: mapping.name,
|
|
106
|
+
element_type: "MAPPING",
|
|
107
|
+
action: "mapping",
|
|
108
|
+
classification: ChangeClassification::EDITORIAL,
|
|
109
|
+
description: [mapping.description].compact,
|
|
110
|
+
)
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Counts per classification.
|
|
116
|
+
#
|
|
117
|
+
# @return [Hash{String => Integer}]
|
|
118
|
+
def summary
|
|
119
|
+
entries.group_by(&:classification)
|
|
120
|
+
.transform_values(&:size)
|
|
121
|
+
.sort.to_h
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# @return [Boolean]
|
|
125
|
+
def breaking?
|
|
126
|
+
entries.any? do |entry|
|
|
127
|
+
entry.classification == ChangeClassification::BREAKING
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Render a markdown changelog section.
|
|
132
|
+
#
|
|
133
|
+
# @return [String]
|
|
134
|
+
def to_changelog
|
|
135
|
+
lines = ["## Schema `#{schema}` — version #{version}", ""]
|
|
136
|
+
entries.sort_by { |entry| [entry.classification, entry.element.to_s] }
|
|
137
|
+
.each do |entry|
|
|
138
|
+
lines << "- **#{entry.classification}** — #{entry.element_type} " \
|
|
139
|
+
"`#{entry.element}` #{entry.action}"
|
|
140
|
+
Array(entry.description).each do |description|
|
|
141
|
+
lines << " - #{description}"
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
lines.join("\n")
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
data/lib/suma/cli/build.rb
CHANGED
|
@@ -16,6 +16,23 @@ module Suma
|
|
|
16
16
|
desc: "Memory-bounded staged build: compile each member in " \
|
|
17
17
|
"its own process (sequential) and reinflate. For large " \
|
|
18
18
|
"collections that OOM a single-process build (suma#94)."
|
|
19
|
+
option :incremental, type: :boolean, default: false,
|
|
20
|
+
desc: "Re-render only changed schemas and their " \
|
|
21
|
+
"transitive dependents (state file defaults " \
|
|
22
|
+
"to plain_schemas/.suma-build-state.json)"
|
|
23
|
+
option :state_file, type: :string,
|
|
24
|
+
desc: "Path to the incremental build state file"
|
|
25
|
+
option :jobs, type: :numeric, default: 1,
|
|
26
|
+
desc: "Concurrent schema export workers (document " \
|
|
27
|
+
"compilation remains sequential)"
|
|
28
|
+
option :provenance, type: :string,
|
|
29
|
+
desc: "Write a provenance manifest (sha256 of inputs " \
|
|
30
|
+
"and outputs + toolchain versions) to this path"
|
|
31
|
+
option :sign, type: :string, banner: "METHOD",
|
|
32
|
+
desc: "Sign the provenance manifest: minisign or sigstore"
|
|
33
|
+
option :sign_key, type: :string,
|
|
34
|
+
desc: "Signing key (minisign requires it; sigstore " \
|
|
35
|
+
"signs keylessly when omitted)"
|
|
19
36
|
|
|
20
37
|
def build(metanorma_site_manifest)
|
|
21
38
|
unless File.exist?(metanorma_site_manifest)
|
|
@@ -39,6 +56,12 @@ module Suma
|
|
|
39
56
|
compile: options[:compile],
|
|
40
57
|
output_directory: "_site",
|
|
41
58
|
staged: options[:staged],
|
|
59
|
+
incremental: options[:incremental],
|
|
60
|
+
state_file: options[:state_file],
|
|
61
|
+
jobs: options[:jobs],
|
|
62
|
+
provenance_file: options[:provenance],
|
|
63
|
+
sign_method: options[:sign],
|
|
64
|
+
sign_key: options[:sign_key],
|
|
42
65
|
).run
|
|
43
66
|
end
|
|
44
67
|
|
data/lib/suma/cli/compare.rb
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "yaml"
|
|
4
|
+
|
|
3
5
|
require "thor"
|
|
4
6
|
|
|
5
7
|
module Suma
|
|
@@ -39,6 +41,16 @@ module Suma
|
|
|
39
41
|
desc: "Override auto-detected reference repo root"
|
|
40
42
|
option :verbose, type: :boolean, default: false,
|
|
41
43
|
desc: "Enable verbose output"
|
|
44
|
+
option :typed_output, type: :string, banner: "FILE",
|
|
45
|
+
desc: "Write the typed ChangeManifest " \
|
|
46
|
+
"(classification + descriptions) as YAML"
|
|
47
|
+
option :changelog, type: :boolean, default: false,
|
|
48
|
+
desc: "Print a markdown changelog for the changes"
|
|
49
|
+
option :impact, type: :boolean, default: false,
|
|
50
|
+
desc: "Print affected schemas and AP publications " \
|
|
51
|
+
"(requires --manifest)"
|
|
52
|
+
option :manifest, type: :string, banner: "SCHEMAS_YAML",
|
|
53
|
+
desc: "Corpus schema manifest, for --impact"
|
|
42
54
|
|
|
43
55
|
def compare(trial_schema, reference_schema)
|
|
44
56
|
comparer = SchemaComparer.new(trial_schema, reference_schema, options)
|
|
@@ -47,12 +59,47 @@ module Suma
|
|
|
47
59
|
|
|
48
60
|
if result.nil?
|
|
49
61
|
say "No changes detected between schemas", :yellow
|
|
50
|
-
|
|
51
|
-
say "Change YAML file: #{result}", :green
|
|
62
|
+
return
|
|
52
63
|
end
|
|
64
|
+
|
|
65
|
+
say "Change YAML file: #{result}", :green
|
|
66
|
+
report_typed_changes(result, trial_schema)
|
|
53
67
|
rescue Suma::Error => e
|
|
54
68
|
raise Thor::Error, e.message
|
|
55
69
|
end
|
|
70
|
+
|
|
71
|
+
private
|
|
72
|
+
|
|
73
|
+
def report_typed_changes(change_yaml, trial_schema)
|
|
74
|
+
manifest = ChangeManifest.from_file(change_yaml,
|
|
75
|
+
version: options[:version])
|
|
76
|
+
write_typed_output(manifest)
|
|
77
|
+
say manifest.to_changelog if options[:changelog]
|
|
78
|
+
print_impact(manifest, trial_schema) if options[:impact]
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def write_typed_output(manifest)
|
|
82
|
+
path = options[:typed_output]
|
|
83
|
+
return unless path
|
|
84
|
+
|
|
85
|
+
File.write(path, manifest.to_yaml)
|
|
86
|
+
say "Typed change manifest: #{path}", :green
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def print_impact(manifest, trial_schema)
|
|
90
|
+
unless options[:manifest]
|
|
91
|
+
raise Thor::Error, "--impact requires --manifest SCHEMAS_YAML"
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
graph = CorpusGraph.from_manifest(options[:manifest])
|
|
95
|
+
impact = ChangeImpact.new(graph, options[:manifest])
|
|
96
|
+
.report(changed_schema_id(manifest, trial_schema))
|
|
97
|
+
say impact.to_yaml
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def changed_schema_id(manifest, trial_schema)
|
|
101
|
+
manifest.schema || File.basename(trial_schema, ".exp")
|
|
102
|
+
end
|
|
56
103
|
end
|
|
57
104
|
end
|
|
58
105
|
end
|
data/lib/suma/cli/core.rb
CHANGED
|
@@ -21,6 +21,27 @@ module Suma
|
|
|
21
21
|
|
|
22
22
|
desc "build METANORMA_SITE_MANIFEST",
|
|
23
23
|
"Build collection specified in site manifest (`metanorma*.yml`)"
|
|
24
|
+
# Mirrors so Core accepts the switches Cli::Build reparses; the inner
|
|
25
|
+
# class owns their declarations.
|
|
26
|
+
option :compile, type: :boolean, default: true,
|
|
27
|
+
desc: "Compile or skip compile of collection"
|
|
28
|
+
option :schemas_all_path, type: :string, aliases: "-s",
|
|
29
|
+
desc: "Generate file that contains all schemas " \
|
|
30
|
+
"in the collection."
|
|
31
|
+
option :staged, type: :boolean, default: false,
|
|
32
|
+
desc: "Memory-bounded staged build"
|
|
33
|
+
option :incremental, type: :boolean, default: false,
|
|
34
|
+
desc: "Re-render only changed schemas and dependents"
|
|
35
|
+
option :state_file, type: :string,
|
|
36
|
+
desc: "Path to the incremental build state file"
|
|
37
|
+
option :jobs, type: :numeric, default: 1,
|
|
38
|
+
desc: "Concurrent schema export workers"
|
|
39
|
+
option :provenance, type: :string,
|
|
40
|
+
desc: "Write a build provenance manifest"
|
|
41
|
+
option :sign, type: :string, banner: "METHOD",
|
|
42
|
+
desc: "Sign the provenance manifest: minisign or sigstore"
|
|
43
|
+
option :sign_key, type: :string,
|
|
44
|
+
desc: "Signing key (sigstore signs keylessly when omitted)"
|
|
24
45
|
def build(_site_manifest)
|
|
25
46
|
Cli::Build.start
|
|
26
47
|
end
|
|
@@ -45,12 +66,18 @@ module Suma
|
|
|
45
66
|
"(used for section references)"
|
|
46
67
|
option :language_code, type: :string, default: "eng", aliases: "-l",
|
|
47
68
|
desc: "Language code for the Glossarist"
|
|
69
|
+
option :edition, type: :numeric,
|
|
70
|
+
desc: "Owning edition recorded on each concept"
|
|
71
|
+
option :language_codes, type: :array,
|
|
72
|
+
desc: "Additional linked localization languages"
|
|
48
73
|
def extract_terms(schema_manifest_file, glossarist_output_path)
|
|
49
74
|
TermExtractor.new(
|
|
50
75
|
schema_manifest_file,
|
|
51
76
|
glossarist_output_path,
|
|
52
77
|
urn: options[:urn],
|
|
53
78
|
language_code: options[:language_code],
|
|
79
|
+
edition: options[:edition],
|
|
80
|
+
language_codes: options[:language_codes],
|
|
54
81
|
).call
|
|
55
82
|
end
|
|
56
83
|
|
|
@@ -66,6 +93,14 @@ module Suma
|
|
|
66
93
|
desc: "Language code for section names"
|
|
67
94
|
option :owner, type: :string, default: Suma::RegisterManifestGenerator::DEFAULT_OWNER,
|
|
68
95
|
desc: "Owner of the dataset (e.g. 'ISO/TC 184/SC 4')"
|
|
96
|
+
option :profile, type: :string, default: "iso10303",
|
|
97
|
+
desc: "Corpus profile (iso10303 or generic)"
|
|
98
|
+
option :year, type: :numeric,
|
|
99
|
+
desc: "Edition year for the register"
|
|
100
|
+
option :supersedes, type: :string,
|
|
101
|
+
desc: "URN/ref of the superseded edition"
|
|
102
|
+
option :edition, type: :numeric,
|
|
103
|
+
desc: "Edition number (tagged as edition:N)"
|
|
69
104
|
def generate_register(schema_manifest_file, output_path)
|
|
70
105
|
RegisterManifestGenerator.new(
|
|
71
106
|
schema_manifest_file,
|
|
@@ -75,6 +110,10 @@ module Suma
|
|
|
75
110
|
ref: options[:ref],
|
|
76
111
|
language_code: options[:language_code],
|
|
77
112
|
owner: options[:owner],
|
|
113
|
+
profile: options[:profile],
|
|
114
|
+
year: options[:year],
|
|
115
|
+
supersedes: options[:supersedes],
|
|
116
|
+
edition: options[:edition],
|
|
78
117
|
).generate
|
|
79
118
|
end
|
|
80
119
|
|
|
@@ -87,6 +126,31 @@ module Suma
|
|
|
87
126
|
desc "export *FILES",
|
|
88
127
|
"Export EXPRESS schemas from manifest files or " \
|
|
89
128
|
"standalone EXPRESS files"
|
|
129
|
+
# The inner class reparses ARGV and owns the canonical declarations;
|
|
130
|
+
# these mirrors exist only so Core accepts the switches it passes
|
|
131
|
+
# through (Core checks unknown options before dispatch).
|
|
132
|
+
option :output, type: :string, aliases: "-o", required: true,
|
|
133
|
+
desc: "Output directory path"
|
|
134
|
+
option :annotations, type: :boolean, default: false,
|
|
135
|
+
desc: "Include annotations (remarks/comments)"
|
|
136
|
+
option :zip, type: :boolean, default: false,
|
|
137
|
+
desc: "Create ZIP archive of exported schemas"
|
|
138
|
+
option :publication, type: :string, banner: "SCHEMA_ID",
|
|
139
|
+
desc: "Export an AP publication bundle: the " \
|
|
140
|
+
"lead schema plus its transitive " \
|
|
141
|
+
"USE-FROM/REFERENCE closure (manifest " \
|
|
142
|
+
"input only)"
|
|
143
|
+
option :profile, type: :string, default: "iso10303",
|
|
144
|
+
desc: "Corpus profile (iso10303 or generic)"
|
|
145
|
+
option :format, type: :string, default: "express", banner: "FORMAT",
|
|
146
|
+
desc: "Output format: express (default) or owl"
|
|
147
|
+
option :corpus, type: :boolean, default: false,
|
|
148
|
+
desc: "OWL only: emit one ontology for the whole " \
|
|
149
|
+
"manifest instead of one per schema"
|
|
150
|
+
option :urn, type: :string, banner: "URN",
|
|
151
|
+
desc: "OWL only: base URN for IRIs, before the " \
|
|
152
|
+
":tech component " \
|
|
153
|
+
"(e.g. urn:iso:std:iso:10303:-2:ed-2:en)"
|
|
90
154
|
def export(*_files)
|
|
91
155
|
Cli::Export.start
|
|
92
156
|
end
|
|
@@ -100,6 +164,25 @@ module Suma
|
|
|
100
164
|
desc "validate SUBCOMMAND ...ARGS", "Validate express documents"
|
|
101
165
|
subcommand "validate", Cli::Validate
|
|
102
166
|
|
|
167
|
+
desc "resolve [URN]", "Resolve URNs to canonical JSON + HTML artifacts"
|
|
168
|
+
# Mirrors so Core accepts the switches Cli::Resolve reparses; the
|
|
169
|
+
# inner class owns their declarations.
|
|
170
|
+
option :manifest, type: :string, required: true,
|
|
171
|
+
desc: "Schema manifest used for schema/entity URNs"
|
|
172
|
+
option :urn, type: :string,
|
|
173
|
+
desc: "Corpus URN base (defaults to the register URN)"
|
|
174
|
+
option :concepts, type: :string,
|
|
175
|
+
desc: "Directory of Glossarist concept YAML files"
|
|
176
|
+
option :register, type: :string,
|
|
177
|
+
desc: "Glossarist register.yaml (dataset URN)"
|
|
178
|
+
option :output, type: :string, aliases: "-o", required: true,
|
|
179
|
+
desc: "Artifact output directory"
|
|
180
|
+
option :all, type: :boolean, default: false,
|
|
181
|
+
desc: "Emit artifacts for every known URN"
|
|
182
|
+
def resolve(_urn = nil)
|
|
183
|
+
Cli::Resolve.start
|
|
184
|
+
end
|
|
185
|
+
|
|
103
186
|
desc "check_svg_quality [PATH]",
|
|
104
187
|
"Check SVG quality and sort by severity (critical files first)"
|
|
105
188
|
option :pattern, type: :string, default: Cli::CheckSvgQuality::DEFAULT_PATTERN,
|