Project

suma

0.0
The project is in a healthy, maintained state
Utility for SUMA (STEP Unified Model-Based Standards Architecture)
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Runtime

 Project Readme

Suma: utility for the STEP Unified Model-driven Architecture

Purpose

SUMA, the "STEP Unified Model-Based Standards Architecture", is a authoring and publication system developed for the management of EXPRESS schemas and its documentation.

This utility is used by the ISO 10303 collection to build the following artifacts:

  • the STEP Resource Library (SRL)

Features

  • EXPRESS schema management for STEP and other schema collections

  • Document collection building and compilation

  • Referential closure validation over the whole corpus

  • EXPRESS links validation and extraction

  • Schema listing file generation

  • OWL/Turtle projection with structural validation

  • Typed change manifests, changelogs, and dependency impact analysis

  • Glossarist terminology and hierarchical registers with edition metadata

  • Dereferenceable URN artifacts (canonical JSON + static HTML)

  • Incremental, parallel, and cached corpus builds

  • Reproducible outputs with verifiable, optionally signed provenance

  • Integration with the Metanorma ecosystem

Installation

$ gem install suma

Usage: CLI

General

# Defaults to `suma help`
$ suma
 Commands:
  suma build METANORMA_SITE_MANIFEST                                  # Build collection from site manifest
  suma check_svg_quality [PATH]                                       # Check SVG quality
  suma compare TRIAL_SCHEMA REFERENCE_SCHEMA                          # Compare schemas; typed changes, impact
  suma convert-jsdai XML_FILE IMAGE_FILE OUTPUT_DIR                   # Convert JSDAI XML and image files to SVG and EXP
  suma export *FILES -o OUTPUT                                        # Export EXPRESS schemas or project them to OWL
  suma extract-terms SCHEMA_MANIFEST_FILE GLOSSARIST_OUTPUT_PATH      # Extract entity concepts to Glossarist v3
  suma ingest-translations CONCEPTS_DIR TRANSLATIONS_FILE [-o OUT]    # Overlay translated content onto extracted concepts
  suma generate-register SCHEMA_MANIFEST_FILE OUTPUT_PATH             # Generate hierarchical register.yaml
  suma generate-schemas METANORMA_MANIFEST_FILE SCHEMA_MANIFEST_FILE  # Generate a schema manifest from a site manifest
  suma reformat EXPRESS_FILE_PATH                                     # Reformat EXPRESS files
  suma resolve [URN] --manifest=MANIFEST -o OUTPUT                    # Emit canonical JSON + HTML for URNs
  suma package-gcr CONCEPTS_DIR --register=REGISTER -o OUTPUT         # Package concepts into a .gcr archive
  suma serve DIRECTORY                                                # Serve resolved artifacts (Accept negotiation)
  suma validate SUBCOMMAND ...ARGS                                    # Validate express documents

Build command

The build command processes a Metanorma site manifest and generates the specified output.

$ suma build METANORMA_SITE_MANIFEST [options]

Parameters:

METANORMA_SITE_MANIFEST

This is the path to the Metanorma site manifest, typically metanorma.yml.

Options:

--[no-]compile

Compile or skip compilation of collection (default: true)

--schemas-all-path=PATH, -s PATH

Generate file that contains all schemas in the collection

--[no-]staged

Memory-bounded build: compile each member in its own process, then reinflate

--[no-]incremental

Re-render only changed schemas and their transitive dependents

--state-file=PATH

Incremental build state file (default: plain_schemas/.suma-build-state.json)

--jobs=N

Concurrent schema export workers (document compilation stays sequential; default: 1)

--provenance=PATH

Write a provenance manifest (sha256 of inputs/outputs + toolchain versions)

--sign=METHOD

Sign the provenance manifest: minisign or sigstore

--sign-key=PATH

Signing key; minisign requires it, sigstore signs keylessly when omitted

The generated schemas-*.yaml file name is derived from the input file name with the word metanorma replaced with schemas.

Repeated builds reuse work and are reproducible: a schema document is rendered again only when its adoc, schema config, schema source, or the rendering toolchain changed, and the collection render is skipped entirely when no site input changed (state: _site/.suma-site-build.json). Metanorma’s random manifest identifiers and per-document type markers are canonicalized, so two identical builds produce byte-identical output. A provenance manifest covers schema_docs, plain_schemas, and _site, and verification reports files that appeared under those roots without being recorded (build metadata such as the site state file is excluded explicitly).

Top-level schema documents render with live cross-reference links: every schema.entity and entity.attribute reference Expressir emits becomes an in-page link, and suma validate anchors verifies that no link is dead.

To compile SRL subset test collection
$ bundle exec suma build metanorma-test.yml
To build SRL collection
$ bundle exec suma build metanorma-srl.yml
To generate schema listing without compilation
$ bundle exec suma build --no-compile metanorma-srl.yml
# => generates schemas-srl.yml

All documents need to have a schemas.yaml in their document root that lists out which schemas the document includes.

Reformat command

The reformat command provides utilities for reformatting EXPRESS files.

$ suma reformat EXPRESS_FILE_PATH [options]

Parameters:

EXPRESS_FILE_PATH

Path to an EXPRESS file or a folder containing EXPRESS files

Options:

--[no-]recursive, -r

Select EXPRESS files recursively based on the specified folder path (default: false)

To reformat all EXPRESS files under the current directory recursively
$ bundle exec suma reformat `pwd` -r

This command:

  • Loads the EXPRESS files specified in the EXPRESS_FILE_PATH

  • Reformats and saves the loaded EXPRESS files

Validate command

General

The validate command groups various validation utilities for EXPRESS documents.

$ suma validate SUBCOMMAND [options]

Subcommands:

links

Validate EXPRESS links

closure

Validate referential closure over the whole corpus

The links subcommand extracts and validates EXPRESS links without creating intermediate files.

$ suma validate links SCHEMAS_FILE DOCUMENTS_PATH [OUTPUT_FILE]

Parameters:

SCHEMAS_FILE

Path to the schemas file (default: "schemas-srl.yml")

DOCUMENTS_PATH

Path to the documents directory (default: "documents")

OUTPUT_FILE

Path to write validation results (default: "validation_results.txt")

To validate EXPRESS links in documents
$ bundle exec suma validate links schemas-srl.yml documents validation_results.txt

This command:

  • Loads the schemas specified in the SCHEMAS_FILE

  • Searches for EXPRESS links in all AsciiDoc files in the DOCUMENTS_PATH

  • Validates these links against the loaded schemas

  • Writes validation results to the OUTPUT_FILE

  • Provides progress bars to track schema loading and link validation

Closure subcommand

The closure subcommand extracts every EXPRESS-internal reference (attribute domains, SELECT and aggregate branches, where-rule expressions, subtype constraints, supertype/subtype lists, rule applies-to, and USE/REFERENCE interfaces) and resolves it against the corpus graph. It exits non-zero when any reference does not resolve, which makes it usable as a CI gate (rake closure runs it on the fixture corpus).

$ suma validate closure SCHEMAS_MANIFEST [DOCUMENTS_PATH] [--format terminal|json|yaml]

When DOCUMENTS_PATH is given, documentation-layer link failures are merged into the same report.

Anchors subcommand

The anchors subcommand checks rendered schema documents for dead links: every Expressir cross-reference (…​, …​) emitted in a compiled doc_*.adoc must have a matching anchor in its rendered doc_*.html, and every in-page href must point at an existing id. It exits non-zero on violations.

$ suma validate anchors SCHEMA_DOCS_PATH

Generate schemas command

The suma generate-schemas command generates an EXPRESS schema manifest file containing all schemas of documents referenced in the Metanorma manifest file, recursively.

$ suma generate-schemas METANORMA_MANIFEST_FILE SCHEMA_MANIFEST_FILE [options]

Parameters:

METANORMA_MANIFEST_FILE

Path to the Metanorma manifest file (e.g.: "metanorma-smrl-all.yml")

Options:

--exclude_path, -e

Exclude schemas by pattern (e.g. *_lf.exp)

To generate schemas manifest file from Metanorma manifest file
$ bundle exec suma generate-schemas metanorma-smrl-all.yml schemas-smrl-all.yml
# => generates schemas-smrl-all.yml
To generate schemas manifest file from Metanorma manifest file and exclude schemas with names like *_lf.exp
$ bundle exec suma generate-schemas metanorma-smrl-all.yml schemas-smrl-all.yml -e *_lf.exp
# => generates schemas-smrl-all.yml without schemas with names like *_lf.exp

All documents need to have a schemas.yaml in their document root that lists out which schemas the document includes.

Extract terms command

The "extract terms" command is implemented for ISO 10303-2, and could also be used for other EXPRESS schema collections that require term extraction for glossary or dictionary applications.

The suma extract-terms command extracts terms from EXPRESS schemas and generates a Glossarist v3 dataset in the output directory. This command processes various types of STEP schemas and creates standardized terminology datasets suitable for glossary and dictionary applications.

$ suma extract-terms SCHEMA_MANIFEST_FILE GLOSSARIST_OUTPUT_PATH [options]

Parameters:

SCHEMA_MANIFEST_FILE

Path to the schema manifest file that lists all schemas to process (e.g., "schemas-smrl-all.yml")

GLOSSARIST_OUTPUT_PATH

Path to the output directory where the Glossarist v3 dataset will be generated

Options:

--language_code, -l

Language code for the Glossarist dataset (default: "eng")

--edition=N

Owning edition recorded on each concept

--language-codes=a,b

Additional linked localization languages (the primary language is always included)

Supported schema types

The command supports extraction from the following EXPRESS schema types:

  • ARM (application reference model) - application module schemas ending with _arm

  • MIM (module implementation model) - application module schemas ending with _mim

  • Resource schemas - General resource schemas

  • BOM (business object model) - business object model schemas ending with _bom

Note
The "Long Form" EXPRESS schemas (ending with _lf) should be excluded from the manifest file as they do not contain definitions of ENTITY objects.

Extracted concepts

The command extracts ENTITY objects from EXPRESS schemas, with the following information:

  1. a unique identifier in form of {schema_name}.{entity_name} (where entity_name is a slug derived from the ENTITY name);

  2. a generated definition depending on the schema type and entity type;

  3. a "Note to entry" from its first coherent textual element described in Annotated EXPRESS;

  4. source information including: schema name and schema version;

  5. domain in the pattern of: {domain_type}: {schema_name}, where domain_type is one of application module, resource, or business object model.

Output format

The command generates a Glossarist v3 compliant dataset with:

  • concept/ directory containing concept definition files in YAML

  • localized_concept/ directory containing localized concept files in YAML

Example 1. To extract terms from a schema manifest file
$ bundle exec suma extract-terms schemas-smrl-all.yml glossarist_output
# => generates glossarist_output/concept/*.yaml and
#      glossarist_output/localized_concept/*.yaml
Example 2. To extract terms from a specific schema subset
$ bundle exec suma extract-terms schemas-activity-modules.yml terms_output
# => processes only schemas listed in the manifest file

Ingest translations command

The suma ingest-translations command overlays translated content onto extracted concepts. A translations file is a YAML sequence of localized-concept documents, each keyed by concept id (or localized UUID) and carrying the fields to apply:

- concept_id: example_schema.part
  data:
    language_code: fra
    terms:
      - designation: pièce
        type: expression
        normative_status: preferred
    definition:
      - content: "Composant d'un assemblage."

Every field the entry provides replaces that localization’s field; every field it omits keeps the source-language content (a language absent from the extracted concepts is created with the same stable UUID convention the linked localizations use). Updated concepts are written in place, or to --output when given.

$ suma ingest-translations CONCEPTS_DIR TRANSLATIONS_FILE [-o OUTPUT_DIR]

Generate register command

The suma generate-register command reads an EXPRESS schema manifest and emits a Glossarist v3 register.yaml with hierarchical sections. The output is used by the concept browser to render a navigable sidebar of sections and to resolve concept cross-references.

$ suma generate-register SCHEMA_MANIFEST_FILE OUTPUT_PATH -u URN --id ID --ref REF

Parameters:

SCHEMA_MANIFEST_FILE

Path to the schema manifest (e.g., "schemas-smrl-part-2.yml")

OUTPUT_PATH

Directory where register.yaml will be written

Options:

--urn, -u

Base URN prefix for the dataset (e.g. urn:iso:std:iso:10303:-2:ed-2:en:tech:*). The wildcard is stripped for the base URN and kept in urnAliases. Required.

--year=N

Edition year recorded on the register

--supersedes=URN

URN/ref of the superseded edition

--edition=N

Edition number, tagged as edition:N; every register also carries a dataset:<id> tag so sibling editions can be grouped.

The URN is fully configurable — every component can be changed to match the dataset being exported. The general structure is:

urn:iso:std:iso:<part>:ed-<edition>:<lang>:tech:*

For example, to export edition 3 in French:

--urn urn:iso:std:iso:10303:-2:ed-3:fr:tech:*

The current ISO 10303-2 SMRL data is edition 2; use ed-2 unless you are re-publishing an earlier edition.

--id

Dataset identifier (e.g. iso10303-2-express). Required.

--ref

Human-readable dataset reference label (e.g. ISO 10303-2 EXPRESS Concepts). Required.

--language_code, -l

Language code for section names (default: "eng")

The generated register contains two top-level groups:

  • Resources — integrated resource schemas (path contains schemas/resources/)

  • Application Modules — ARM and MIM schemas (path contains schemas/modules/)

Each schema gets a human-readable name via the SchemaNaming module (e.g. topology_schema → "Resource: Topology", Activity_method_assignment_mim → "Module: Activity Method Assignment (MIM)"). Acronyms (AIC, AEC, BREP, 2D, 3D) are preserved; function words (as, of, the) are lowercased per ISO title-case convention.

Convert JSDAI image outputs to SVG and Annotated EXPRESS

The suma convert-jsdai command converts JSDAI EXPRESS-G diagram outputs (XML + image file) into SVG and Annotated EXPRESS formats suitable for Metanorma documentation.

JSDAI (Java Step Data Access Interface) Java tool is used by ISO/TC 184/SC 4 to create EXPRESS-G diagrams.

JSDAI generates two files for each diagram:

  • a raster image file (GIF or JPEG)

  • an XML file containing image metadata and clickable area definitions

This command converts these inputs into:

  • an SVG file that embeds the raster image as Base64 with clickable rectangular areas

  • an Annotated EXPRESS file with a Metanorma svgmap block for easy copy-paste

$ suma convert-jsdai XML_FILE IMAGE_FILE OUTPUT_DIR

Where:

XML_FILE

Path to the JSDAI XML file (e.g., "action_schemaexpg1.xml")

IMAGE_FILE

Path to the raster image file (GIF or JPEG format)

OUTPUT_DIR

Path to the output directory where SVG and EXP files will be generated

Example 3. To convert JSDAI outputs for a resource schema diagram
$ bundle exec suma convert-jsdai \
    documents/resources/action_schema/action_schemaexpg1.xml \
    documents/resources/action_schema/action_schemaexpg1.gif \
    output/
# => generates:
#    output/action_schemaexpg1.svg
#    output/action_schemaexpg1.exp

This command:

  • Parses the JSDAI XML file to extract image metadata and clickable area definitions

  • Reads the raster image file and converts it to base64 format

  • Generates an SVG file with:

    • The embedded base64-encoded image

    • Clickable rectangular areas (<a> and <rect> elements) corresponding to the XML definitions

    • Proper viewBox dimensions matching the source image

  • Generates an Annotated EXPRESS file containing:

    • A Metanorma svgmap block with numbered cross-references

    • Proper anchor IDs for document integration

    • Cross-reference targets extracted from the XML href attributes

The generated SVG and EXP files work together through a numbered mapping system:

  1. In the SVG file, each clickable area is assigned a sequential number:

    <a href="1"><rect .../></a>
    <a href="2"><rect .../></a>
    <a href="3"><rect .../></a>
  2. In the EXPRESS file, the svgmap block maps these numbers to targets which are either EXPRESS or AsciiDoc anchors.

    Example 4. Resource schema diagram with SVG and Annotated EXPRESS cross-references
    (*"action_schema.__expressg"
    [[action_schema_expg1]]
    [.svgmap]
    ====
    image::action_schemaexpg1.svg[]
    
    * <<express:basic_attribute_schema>>; 1
    * <<express:action_schema>>; 2
    * <<express:support_resource_schema>>; 3
    ====
    *)
    Example 5. Module schema diagram with SVG and Annotated EXPRESS cross-references
    (*"Activity_mim.__expressg"
    [[Activity_mim_expg1]]
    [.svgmap]
    ====
    image::mimexpg1.svg[]
    
    * <<Activity_mim_expg2>>; 1
    * <<express:action_schema>>; 2
    * <<Activity_method_mim_expg1>>; 3
    * <<express:basic_attribute_schema>>; 4
    * <<express:management_resources_schema>>; 5
    ====
    *)
  3. When rendered in Metanorma, clicking on "area 1" in the SVG, will navigate to the express:basic_attribute_schema anchor, "area 2" to express:action_schema, and so on.

The mapping is derived from the original JSDAI XML file, where each <img.area> element contains:

coords attribute

converted to SVG <rect> dimensions

href attribute

converted to EXPRESS cross-reference target in the svgmap block

Sequential position

assigned as the numbered href in both SVG and svgmap list

Export schemas command

General

The suma export command exports EXPRESS schemas from manifest files and/or standalone EXPRESS files to a specified output directory.

This command is useful for extracting plain or annotated EXPRESS schemas for distribution or further processing.

$ suma export -o OUTPUT_DIR FILE1 [FILE2 FILE3 ...]

Parameters:

FILE1 [FILE2 FILE3 …​]

One or more files to export. Each file can be:

An EXPRESS schema manifest file (.yml, .yaml)

schemas listed in the manifest will be exported

An standalone EXPRESS file (.exp)

the schema will be exported directly

Options:

--output=PATH, -o PATH

(required) Output directory path

--[no-]annotations

Include annotations (remarks/comments) in exported schemas (default: false)

--[no-]zip

Create ZIP archive of exported schemas (default: false)

--profile=PROFILE

Schema profile: iso10303 (default) or generic

--publication=SCHEMA_ID

Export an AP publication bundle: the lead schema plus its transitive USE-FROM/REFERENCE closure

--format=FORMAT

Output format: express (default) or owl

--[no-]corpus

OWL only: emit one corpus ontology importing every schema ontology

--urn=URN

OWL only: base URN for IRIs, before the :tech component

Behavior

The command exports schemas based on the input file types:

For EXPRESS schema manifest files:

  • Schemas are exported while preserving the directory structure from the manifest file paths

  • Schemas under resources/ are exported to OUTPUT/resources/

  • Schemas under modules/ are exported to OUTPUT/modules/

  • Other categories (business_object_models/, core_model/) follow the same pattern

For standalone EXPRESS files:

  • Schemas are exported directly to the output directory root

  • Output filename format: {schema_id}.exp

By default, schemas are exported without annotations (plain EXPRESS). Use the --annotations flag to include remarks and comments.

The --zip flag creates a ZIP archive in addition to the directory output, named OUTPUT.zip.

To export schemas from a manifest file
$ bundle exec suma export -o express-files schemas-srl.yml
# => generates express-files/ directory with plain EXPRESS schemas
To export a single plain schema
$ bundle exec suma export -o express-files geometry_schema.exp
# => generates express-files/geometry_schema.exp
To export multiple plain schemas
$ bundle exec suma export -o express-files schema1.exp schema2.exp schema3.exp
# => generates express-files/{schema1,schema2,schema3}.exp
To export from multiple manifest files
$ bundle exec suma export -o express-files schemas-srl.yml additional-schemas.yml
# => exports schemas from both manifest files
To export mix of manifest and plain schemas
$ bundle exec suma export -o express-files schemas-srl.yml geometry_schema.exp
# => exports schemas from manifest with directory structure
#    plus geometry_schema.exp at the root
To export schemas with annotations
$ bundle exec suma export -o express-files --annotations schemas-srl.yml
# => generates express-files/ directory with annotated EXPRESS schemas
To export and create ZIP archive
$ bundle exec suma export -o express-files --zip schemas-srl.yml
# => generates both:
#    - express-files/ directory
#    - express-files.zip archive
To export with all options
$ bundle exec suma export -o express-files \
    --annotations \
    --zip \
    schemas-srl.yml geometry_schema.exp
# => generates annotated schemas in both directory and ZIP format

Output structure

The exported directory structure depends on the input file types:

express-files/
├── geometry_schema.exp          # standalone EXPRESS file (at root)
├── topology_schema.exp          # standalone EXPRESS file (at root)
├── resources/                   # from manifest files
│   ├── action_schema/
│   │   └── action_schema.exp
│   └── ...
├── modules/                     # from manifest files
│   ├── activity/
│   │   ├── arm.exp
│   │   └── mim.exp
│   └── ...
├── business_object_models/      # from manifest files
│   └── ...
└── core_model/                  # from manifest files
    └── ...

Schema profiles and AP publications

Suma works with any schema collection. Suma::SchemaProfile declares how schema identifiers and paths map to types, how identifiers become display names, and the ordered register categories. Registered profiles:

iso10303

Default; STEP conventions including /applications/ classifying as an application protocol

generic

No STEP conventions (one category for every schema)

ifc

buildingSMART IFC editions: one standalone schema per edition (ifc4, ifc4x3, …​), edition names preserved uppercase (IFC4, IFC4X3), Ifc-prefixed declarations, one Other Schemas register category

An AP publication is a lead schema bundled with the module and resource schemas it USEs. --publication SCHEMA_ID computes the transitive USE-FROM/REFERENCE closure and writes the bundle flat under OUTPUT/<lead_id>/. In the register, application protocols are grouped under a per-publication parent section.

OWL projection

suma export --format owl projects a parsed corpus into OWL/Turtle:

  • entities become owl:Class; SUBTYPE OF becomes rdfs:subClassOf

  • SELECT types become owl:unionOf; enumerations become owl:oneOf named individuals

  • simple type aliases become rdfs:Datatype

  • explicit, derived, and inverse attributes become object/datatype properties attached through named owl:Restriction nodes, with cardinality from optionality and aggregate bounds

  • WHERE, DERIVE, and INVERSE clauses are preserved as annotated constraints

IRIs derive from the corpus URN scheme (<base>:tech:<schema>.<element>). Per-schema ontologies declare owl:imports for their USE-FROM/REFERENCE targets, and --corpus adds a corpus ontology importing every schema. The projection is validated before writing (materialization, property declarations, orphan classes, dangling superclasses, superclass cycles), and contains no blank nodes, so it is deterministic and golden-comparable.

$ suma export --format owl --urn urn:iso:std:iso:10303:-2:ed-2:en \
    -o OUTPUT schemas.yaml
$ suma export --format owl --corpus --urn urn:iso:std:iso:10303:-2:ed-2:en \
    -o OUTPUT schemas.yaml

Package concepts for the Vocabulary Browser

The package-gcr command bundles extracted concepts into a GCR (Glossarist Concept Repository) archive — the sealed distribution format consumed by the Glossarist Vocabulary Browser:

$ suma package-gcr CONCEPTS_DIR --register register.yaml \
    --shortname my-dataset --version 1.0.0 \
    --title "My Dataset" --description "Concepts from my corpus" \
    -o OUT

The archive contains metadata.yaml (identity, statistics), the original register.yaml, and concepts/ in the browser’s canonical flat format (termid, term, one block per language). Both a versioned ({shortname}-{version}.gcr) and an unversioned ({shortname}.gcr) archive are written. Pass --created-at to pin the package timestamp for byte-reproducible archives. Point the browser’s datasets.yml at the published archive (or at the concepts directory in development via localPath).

Serve resolved artifacts

suma serve serves a resolve --all artifact tree at its URN-derived paths, returning JSON or HTML according to the request’s Accept header:

$ suma serve OUT --port 2113
$ curl -H "Accept: application/json" \
    http://localhost:2113/urn/iso/std/iso/10303/-2/ed-2/en/tech/action_schema.action

Production hosting maps the same paths statically; no application server is required.

Resolve URNs command

The resolve command turns URNs into static, dereferenceable artifacts: a canonical JSON document (sorted keys) and an HTML page per URN, written under a path derived from the URN itself. It resolves:

  • tech: schema, declared-element, and attribute (OWL property) URNs from a schema manifest

  • term: concept URNs from Glossarist concept documents

  • the dataset URN from register.yaml

$ suma resolve URN --manifest SCHEMAS_YAML [--concepts DIR] [--register register.yaml] -o OUT
$ suma resolve --all --manifest SCHEMAS_YAML [--concepts DIR] [--register register.yaml] -o OUT

--all also writes index.html, linking every artifact. No server is required.

Compare schemas command

General

The suma compare command compares two EXPRESS schemas using eengine and generates an EXPRESS Changes YAML file tracking the differences.

This command is essential for managing schema evolution across versions, particularly when working with multiple git branches of the same repository.

$ suma compare TRIAL_SCHEMA REFERENCE_SCHEMA --version VERSION [options]

Parameters:

TRIAL_SCHEMA

Path to the new/trial EXPRESS schema file

REFERENCE_SCHEMA

Path to the old/reference EXPRESS schema file

Options:

--version=VERSION, -v VERSION

(required) Version number for this change version

--output=PATH, -o PATH

Output Change YAML file path (default: {schema}.changes.yaml in trial schema directory)

--mode=MODE

Schema comparison mode: resource or module (default: resource)

--trial-stepmod=PATH

Override auto-detected trial repository root

--reference-stepmod=PATH

Override auto-detected reference repository root

--verbose

Enable verbose output

--typed-output=PATH

Write a typed change manifest (lutaml-model records with classification)

--[no-]changelog

Render a markdown changelog alongside the change manifest

--[no-]impact

Report affected schemas and AP publications using the corpus graph

--manifest=SCHEMAS_YAML

Schema manifest used for impact analysis

Typical workflow

The compare command is designed for a two-repository workflow where you have different branches checked out:

# 1. Check out old version at /path/to/repo-old
# 2. Check out new version at /path/to/repo-new
# 3. Compare schemas:
$ suma compare \
    /path/to/repo-new/schemas/resources/action_schema/action_schema.exp \
    /path/to/repo-old/schemas/resources/action_schema/action_schema.exp \
    --version 2

Behavior

The command:

  • Auto-detects git repository roots from schema file paths

  • Uses detected roots as stepmod paths for eengine

  • Generates or updates .changes.yaml file in the trial schema directory

  • Replaces existing change version if the version already exists

  • Adds new change version if the version is different

Requirements

This command requires eengine to be installed:

To compare schemas with auto-detection
$ suma compare \
    ~/iso-10303-new/schemas/resources/support_resource_schema/support_resource_schema.exp \
    ~/iso-10303-old/schemas/resources/support_resource_schema/support_resource_schema.exp \
    --version 2
# => generates or updates support_resource_schema.changes.yaml
To compare with verbose output
$ suma compare schema_new.exp schema_old.exp --version 2 --verbose
# Shows: eengine version, detected repo roots, XML generation, etc.
To specify custom output location
$ suma compare schema_new.exp schema_old.exp \
    --version 2 \
    --output /path/to/custom.changes.yaml
To override auto-detected repository roots
$ suma compare schema_new.exp schema_old.exp \
    --version 2 \
    --trial-stepmod ~/repo-new \
    --reference-stepmod ~/repo-old

Generated Change YAML format

The command generates EXPRESS Changes YAML files in the ISO 10303 format:

---
schema: support_resource_schema
versions:
- version: '2'
  description: 'TYPE text: Underlying Type changed'
  modifications:
  - type: TYPE
    name: text

For complete format documentation, see the EXPRESS Changes specification.

Expressir command

General

The suma expressir command provides access to all Expressir commands for working with EXPRESS schemas. This includes documentation coverage analysis, schema formatting, validation, and other EXPRESS-related operations.

Expressir is a comprehensive toolkit for EXPRESS schema processing that Suma integrates to provide additional functionality beyond Suma’s core features.

$ suma expressir SUBCOMMAND ...ARGS [options]

Available subcommands:

coverage

Check documentation coverage of EXPRESS schemas

format

Pretty print EXPRESS schemas

clean

Strip remarks and prettify EXPRESS schemas

validate

Validate EXPRESS schemas

benchmark

Benchmark schema loading performance

version

Display expressir version

Coverage subcommand

The coverage subcommand analyzes EXPRESS schemas to determine documentation coverage, reporting how many EXPRESS objects (entities, constants, functions, types, etc.) have been documented with Annotated EXPRESS.

This addresses the need to measure and improve documentation quality in EXPRESS schema collections.

$ suma expressir coverage PATH [PATH...] [options]

Parameters:

PATH

One or more paths to analyze. Each path can be:

  • An EXPRESS schema manifest file (.yml, .yaml)

  • A single EXPRESS file (.exp)

  • A directory containing EXPRESS files

Options:

--format=FORMAT

Output format: text (default), json, or yaml

--output=FILE

Output file path for JSON/YAML formats (defaults to coverage_report.json or coverage_report.yaml)

--exclude=TYPES

Comma-separated list of EXPRESS entity types to exclude from coverage analysis (e.g., TYPE,CONSTANT,TYPE:SELECT)

--ignore-files=FILE

Path to YAML file containing array of file patterns to ignore from overall coverage calculation

To analyze documentation coverage of a schema collection
$ suma expressir coverage schemas-srl.yml
To analyze coverage and export as JSON
$ suma expressir coverage schemas-srl.yml --format=json --output=coverage.json
To analyze with exclusions
$ suma expressir coverage schemas/ --exclude=TYPE:ENUMERATION,PARAMETER
To analyze multiple sources
$ suma expressir coverage schemas-srl.yml additional-schemas.yml

The coverage report includes:

  • Overall coverage statistics (total entities, documented entities, percentage)

  • Per-file coverage details

  • Per-directory coverage summaries

  • List of undocumented entities by type and name

Format subcommand

The format subcommand pretty-prints EXPRESS schemas.

$ suma expressir format PATH

Parameters:

PATH

Path to the EXPRESS schema file to format

To format an EXPRESS schema
$ suma expressir format schema.exp

Clean subcommand

The clean subcommand strips remarks and prettifies EXPRESS schemas.

$ suma expressir clean PATH [options]

Parameters:

PATH

Path to the EXPRESS schema file to clean

Options:

--output=FILE

Output file path (defaults to stdout)

To clean an EXPRESS schema and save to file
$ suma expressir clean schema.exp --output=cleaned_schema.exp

Validate subcommand

The validate subcommand validates EXPRESS schemas for syntactic correctness.

$ suma expressir validate PATH [PATH...]

Parameters:

PATH

One or more paths to EXPRESS schema files or directories to validate

To validate EXPRESS schemas
$ suma expressir validate schema.exp
$ suma expressir validate schemas/

Additional information

For complete documentation of all Expressir commands and options, see the Expressir documentation.

Check SVG quality command

General

The check_svg_quality command validates SVG files for conformance and quality using the svg_conform library. It supports both batch directory scanning and single file analysis.

By default, it uses the metanorma profile which allows raster images (PNG, JPEG) and other features specific to Metanorma documentation.

$ suma check_svg_quality [PATH] [options]

Parameters:

PATH

Path to directory containing SVG files or a single SVG file. Defaults to schemas directory.

Batch directory scanning

When given a directory, it scans all SVG files and produces a quality report sorted by error count (most problematic files first).

Check all SVG files in schemas directory
$ suma check_svg_quality ../iso-10303/schemas
Output
🔍 Scanning 3878 SVG files...

╔══════════════════════════════════════════════════════════════════════════════╗
║  🔍 SVG Quality Report    Sorted by error count (most first)             ║
╚══════════════════════════════════════════════════════════════════════════════╝

  📊 OVERVIEW

    ● Total Files   : 3878
    ● Valid         : 3845 ✅
    ● Invalid      : 33 ❌
    ...

  💥 CRITICAL QUALITY (2 files)

    ✗   0/100    813 errors  schemas/resources/action_schema/action_schemaexpg2.svg
    ✗  25/100    156 errors  schemas/modules/activity/mimexpg1.svg

Single file analysis

When given a path to a single SVG file, it shows detailed error breakdown grouped by requirement type.

Analyze a single SVG file
$ suma check_svg_quality schemas/resources/action_schema/action_schemaexpg2.svg
Output
📄 SVG Quality Report: schemas/resources/action_schema/action_schemaexpg2.svg

  Valid: NO ❌
  Errors: 813

  📋 Error Details

  style (56 occurrences)
    - Style property 'enable-background' removed
    - Style property 'overflow' removed
    ...

  allowed_elements (109 occurrences)
    - The element 'image' is not allowed as a child of 'svg'
    ...

  color_restrictions (108 occurrences)
    - Color 'rgb(33, 128, 255)' in style property 'fill' is not allowed
    ...

Options:

--profile=PROFILE

Validation profile to use (default: metanorma). Other options: svg_1_2_rfc, svg_1_2_rfc_with_rdf, base, lucid_fix

--sort=MODE

Sort order: errors (most errors first, default) or quality (lowest quality scores first)

--format=FORMAT

Output format: terminal (default), json, or yaml

--output=PATH, -o PATH

Write output to file instead of stdout

--min_errors=N

Filter to show only files with at least N errors

--limit=N

Limit output to top N files

--progress

Show progress during batch scanning

--summary-only

Show only summary, not individual file details

Check with custom profile
$ suma check_svg_quality schemas/ --profile svg_1_2_rfc
Output as JSON
$ suma check_svg_quality schemas/ --format json --output quality_report.json
Show only files with 100+ errors
$ suma check_svg_quality schemas/ --min_errors 100

Usage: Ruby

General

Suma can be used programmatically in your Ruby applications. The following examples demonstrate common usage patterns.

Building collections

require 'suma'

# Build a collection with default settings
Suma::Processor.new(
  metanorma_yaml_path: "metanorma-srl.yml",
  schemas_all_path: "schemas-srl.yml",
  compile: true,
  output_directory: "_site"
).run

# Generate schema listing without compilation
Suma::Processor.new(
  metanorma_yaml_path: "metanorma-srl.yml",
  schemas_all_path: "schemas-srl.yml",
  compile: false
).run

Working with schema manifests

Schema manifests are loaded via Expressir::SchemaManifest:

require 'suma'

schemas_file_path = "schemas-srl.yml"
schemas_config = Expressir::SchemaManifest.from_file(schemas_file_path)

# Access schema information
schemas_config.schemas.each do |schema|
  puts "Schema ID: #{schema.id}"
  puts "Schema path: #{schema.path}"
end

Extracting terms

require 'suma'

Suma::TermExtractor.new(
  "schemas-smrl-part-2.yml",
  "glossarist_output",
  urn: "urn:iso:std:iso:10303:-2:ed-2:en:tech:*",
).call

Generating a register.yaml

require 'suma'

Suma::RegisterManifestGenerator.new(
  "schemas-smrl-part-2.yml",
  "register_output",
  urn: "urn:iso:std:iso:10303:-2:ed-2:en:tech:*",
  id: "iso10303-2-express",
  ref: "ISO 10303-2 EXPRESS Concepts",
).generate

Architecture

Suma’s domain is split into MECE concerns:

  • Data models (pure): CollectionManifest, ExpressSchema

  • Value objects (pure): SchemaCategory, Urn

  • Services (single concern): ManifestTraverser, SchemaDiscovery, SchemaCompiler, SchemaExporter, SchemaIndex, LinkValidator, SchemaComparer, SchemaManifestGenerator, TermExtractor, RegisterManifestGenerator, Processor

  • Renderers (pure, composable): SchemaTemplate::Plain, SchemaTemplate::Document

Key invariants:

  • The classifier ExpressSchema::Type.classify(id:, path:) is the single source of truth for schema type. SchemaCategory, SchemaNaming, SchemaExporter, and RegisterManifestGenerator all derive from it.

  • Urn owns URN semantics (wildcard stripping, base/alias split, leaf composition).

  • CollectionManifest is a pure data model; tree walking lives in ManifestTraverser, schema I/O lives in SchemaDiscovery.

  • SchemaCompiler orchestrates one Metanorma compilation; the adoc body is injected via a SchemaTemplate::* renderer.

Code-style rules enforced throughout lib/suma/:

  • Ruby autoload only — no require_relative

  • No send to call private methods

  • No instance_variable_set / instance_variable_get

  • No respond_to? for type checking

  • Utils.log writes to $stderr; debug level gated by SUMA_DEBUG

Copyright Ribose. BSD 2-clause license.

Development and benchmarks

The default gate is rake (specs, RuboCop, referential closure).

$ rake benchmark

rake benchmark builds a synthetic 1,000-schema corpus and asserts wall-time and peak-RSS budgets; the same benchmark runs nightly in CI. Schema export can run in parallel with build --jobs N, while Metanorma document compilation stays sequential and composes with staged process isolation.