Working with ReqIF

The ReqIF specification frames its use around two exchange scenarios between exchange partners, typically two different requirement authoring tools, possibly at two different organizations:

  • One-way exchange: partner A exports a specification from their authoring tool, transmits it to partner B, and partner B imports it into their authoring tool.

  • Round-trip exchange: same as one-way, but partner B then modifies the specification, exports it back to partner A, and partner A re-imports it on top of the original.

The Syside ReqIF CLI plays the role of the “ReqIF tool” on the SysML v2 side of either scenario. The current workspace (the directory where the CLI runs) is the SysML v2 authoring tool’s storage. The remote partner is whatever requirements management tool produced or will consume the .reqif / .reqifz exchange document.

The sections below follow a full round-trip, importing a requirements specification, revising it in SysML v2, and exporting it back to ReqIF.

Workspace Setup

Before any ReqIF document can be imported or exported, the workspace needs the SysideReqIF.sysml library. This library defines the metadata used to mark SysML v2 elements as ReqIF carriers: the @reqif / @reqif_* tags that pin a stable ReqIF identity onto every imported element, and the #reqif_*_type prefixes used on the four ReqIF *Type templates.

From the directory to be used as the workspace, run:

syside reqif init

This drops lib/SysideReqIF.sysml into the workspace. Pass --lib-dir to put it somewhere else. The library is plain SysML v2 and is intended to be checked in alongside the rest of the model.

init is idempotent: re-running it against a workspace that already contains the library is a safe no-op (Found existing SysideReqIF.sysml library. No action needed.). The other commands also produce a clear error pointing back to init when the library is missing, so it is hard to forget.

ReqIF to SysML v2

This section describes the workflow for importing a ReqIF document into the workspace as SysML v2.

Importing the Document

This step covers the ReqIF specification’s UC2: Import New Requirement Specifications and UC3: Update Requirement Specifications. From the SysML v2 side they are the same command: the CLI decides whether to create new elements or merge changes into existing ones based on what the workspace already contains. The import command provides several configuration options; the subsections below cover each one.

Receive a .reqif or .reqifz from the upstream partner and place it anywhere on disk, then run:

syside reqif import path/to/incoming.reqif

The command parses the exchange document, runs the Preconditions against both the incoming document and the workspace, and writes a fixed package layout into the workspace (ReqIF_Import_Enums, ReqIF_Import_Types, ReqIF_Import_Objects, ReqIF_Import_Specifications, ReqIF_Import_Relations). Binary attachments referenced from XHTML attribute values are extracted into attachments_reqif/ (or the directory passed to --attachments-dir).

Tip

Run syside reqif import from a clean Git working tree (or whichever VCS is in use). import rewrites the ReqIF_Import_*.sysml files in place, and on a delta run also rewrites any other files that hold ReqIF elements, so committing first allows reviewing the git diff afterwards to see exactly what the partner changed, or, on a fresh import, sanity-checking the generated layout before building on it.

Imported elements are already locked: each carries an @reqif (or @reqif_*) metadata tag with the original ReqIF identifier and last_change timestamp, so they will round-trip back out without losing their identity.

Note

Re-running syside reqif import against a workspace that already contains a prior import applies only the delta. Elements that had a ReqIF identifier but are no longer present in the incoming document are reported as orphaned and left in place. Review and delete them by hand if they should be removed. See Known Limitations for the cases that the delta path does not yet handle and that require a fresh workspace.

Resolving Duplicate Names

Added in version 0.9.1.

Some upstream requirement tools require every element to carry a LONG_NAME but do not enforce that those names be unique. The resulting .reqif fails the SysML v2 side’s name-uniqueness preconditions (see Preconditions) because two SysML v2 elements in the same effective namespace cannot share a name. Re-run the import with --resolve-duplicate-names to make it pass:

syside reqif import --resolve-duplicate-names path/to/incoming.reqif

The flag appends a short identifier-derived suffix (__<6chars> from each colliding element’s ReqIF id) to every name involved in a collision. A one-line stderr report is printed for each rename so the SysML v2 output can be correlated back to the source. On the way back out, syside reqif export strips the suffix automatically, and the receiving partner sees the original LONG_NAME. The unmangling is keyed off the recorded identifier, so if a mangled element is renamed on the SysML v2 side (drop the suffix, change the base, etc.) the export honors the chosen name instead of trying to restore the original.

Splitting Large Imports

Added in version 0.10.1.

By default, requirements are stored in a single ReqIF_Import_Objects.sysml file. For very large specifications, this file can become huge and hard to work with because VS Code automatically disables LSP for huge files. Therefore, when importing a large specification for the first time, pass the --split-by=<strategy> flag to partition the objects across several files using the specified <strategy>. Currently, Syside supports two strategies:

  1. hierarchy: splits the objects file by following ReqIF specification hierarchy until a subtree can fit within --split-max-loc lines (by default 10 000) or --split-max-depth limit is reached (by default unlimited). The files are named based on the corresponding requirement names by removing spaces and punctuation and converting them to PascalCase and grouped into folders mirroring the hierarchy. Since SysML file names do not affect namespaces, to avoid name collisions, the contents of the files are wrapped in packages whose names are constructed by concatenating the names of the entire path. Syside additionally emits aliases for the contained packages so that the elements can be reached by using qualified name syntax Folder::Subfolder::'requirement name'.

  2. flat-greedy: splits the objects file into chunks where each one is at most --split-max-loc lines long (by default 10 000).

To import ReqIF using the hierarchical strategy, use:

syside reqif import --split-by=hierarchy path/to/incoming.reqif

--split-by is taken into account only during the first import. During the reimport, the split strategy is automatically recognized; specifying a different strategy during the reimport is, currently, an error. To make the file diff minimal and easy to review, reimport never reorganizes the existing elements; instead it adds them into locations that are closest to the ones where the elements would have been put during the regular import.

Namespacing Imports

Added in version 0.10.1.

By default every import writes the same fixed ReqIF_Import_* package and file names, so importing two different specifications into one workspace would collide in those shared files. Pass --domain <label> to insert a label immediately after the ReqIF_Import_ unit: --domain Powertrain turns ReqIF_Import_Specifications into ReqIF_Import_Powertrain_Specifications (and likewise for the file names):

syside reqif import --domain Powertrain path/to/powertrain.reqif

Characters that are not filename-safe (spaces, the path separators / and \, and : * ? " < > |, etc.) are percent-encoded so the names stay valid paths on Windows and *nix and decode back to the original value; a warning lists any characters that were encoded. A delta re-import into the same workspace must reuse the same --domain value, since it selects which packages to update.

Working in SysML v2

If partner A sent the document for information only, the workflow ends here: the SysML v2 model is ready to be browsed, analyzed, or fed into downstream tooling. This is the one-way scenario from the ReqIF specification.

Otherwise, this is where the model takes shape, whether it arrived by import or is authored directly in SysML v2. Edit it as ordinary SysML v2: rename requirements, change attribute values, attach SysML v2 constructs that ReqIF cannot express (parts, actions, analyses), or add a new requirement under an existing Specification.

Two practical points:

  • Anything written in SysML v2 that is not annotated with an @reqif / @reqif_* metadata tag stays SysML-only and will not appear in any future ReqIF export. This is the intended way to enrich an imported document with model content that has no ReqIF counterpart.

  • Anything that is annotated with such a tag and intended to round-trip back out must end up with a stable identifier. Imported elements already have one; newly authored elements do not until the locking step runs.

See ReqIF and SysML v2 Mapping for the table of equivalent constructs to use when authoring on the SysML v2 side.

Authoring from Scratch

The workflow above starts from an incoming .reqif, but the SysML v2 side can also be the originator of a one-way exchange. In that case the steps reduce to:

  1. syside reqif init to drop in the library.

  2. Author the model directly in SysML v2 using the constructs listed in ReqIF and SysML v2 Mapping. Use a #reqif_*_type stereotype on each abstract *Type template def, and an @reqif metadata block on each instance-side element (a specification, spec object, relation group, or spec relation) that should round-trip through ReqIF.

  3. syside reqif lock to assign identifiers.

  4. syside reqif export --title "<title>" outgoing.reqif to produce the exchange document.

From there the receiving partner imports outgoing.reqif into their tool exactly as in the inbound case above; the format is symmetric.

Organizing the Model Files

The five ReqIF_Import_*.sysml files written by import are a starting point, not a fixed layout. export and the import delta path key off the @reqif metadata, not the file or package the element happens to live in, so any def-shaped element (DatatypeDefinitionEnumeration, SpecificationType, SpecObjectType, SpecRelationType, RelationGroupType, Specification, SpecObject, and RelationGroup itself) can be moved into a different file or SysML v2 package once the private import lines are fixed up so cross-references still resolve. A subsequent syside reqif export writes out exactly the same ReqIF content as before the move, and a subsequent delta syside reqif import recognizes the moved elements as already-present and reports No changes detected.

The exception is usage-shaped elements that depend on their enclosing context:

  • A SpecRelation (a connection) must stay inside the occurrence def for its RelationGroup. The export resolves a relation’s source and target endpoints through the source_specification / target_specification features of the enclosing group, and the precondition that “every ReqIF tag must be an owned feature of a ReqIF-annotated type” rejects a relation hoisted into a top-level package. Move the whole RelationGroup occurrence def instead; the contained connections travel with it.

  • A nested SpecHierarchy (a requirement usage indexed as '1', '2', …) is owned by the parent SpecObject def and moves with that def; it cannot be hoisted on its own.

A practical layout is to break the imported model up by subsystem or document (for example, one file per Specification plus a shared types file) instead of keeping the four flat ReqIF_Import_Objects / …Specifications / …Relations / …Types files generated by import. Subdirectories are fine: the workspace is scanned recursively, so files under specs/, types/, etc. are picked up just like top-level ones.

Locking Newly-Authored Elements

Run:

syside reqif lock

lock walks every @reqif_*-tagged element in the workspace, fills in a fresh UUID identifier and a last_change timestamp on any element that does not already have them, and leaves elements that were imported (or locked previously) alone. Locking is idempotent: re-running it on an already-locked workspace is a no-op.

Without this step, freshly-authored ReqIF elements would be exported with regenerated identifiers each time, defeating the round-trip identity promise. There is no need to remember to run lock, though: syside reqif export re-runs the preconditions before writing and fails with a clear message if any element is unlocked, and lock is also safe to run as a pre-commit hook.

Note

syside reqif lock does not track when the element was last modified, only gives the initial date. To track which element was modified precisely when, set up a review process where every modified requirement also has its last_change updated before a Git (or equivalent) branch can be merged.

Validating Requirements

The SysML v2 checks that export runs automatically can also be invoked on their own, to confirm the workspace is export-ready without producing an output file:

syside reqif check sysml

Its inbound counterpart, syside reqif check reqif path/to/incoming.reqif, screens a .reqif from a new partner before an import. The full list of checks is documented in Preconditions.

Tip

Wire syside reqif check sysml into the CI/CD pipeline as a gating step. It exits non-zero on any precondition failure, so a green build means the workspace is ready for an export or a delta import at any time, with no last-minute surprises about an unlocked element or a stray top-level package when a partner actually asks for the next round-trip.

SysML v2 to ReqIF

This step covers the ReqIF specification’s UC1: Export Requirement Specifications. Run:

syside reqif export --title "Brake System Requirements, rev. 3" outgoing.reqif

The --title flag is required and ends up in the exchange document’s REQ-IF-HEADER as the human-readable name partner A will see. Useful additional flags:

  • --comment "<text>": free-form description that goes into the header alongside the title.

  • --repository-id <id>: identifier (UUID, URL, …) of the repository this export was produced from. Recommended for any round-trip workflow so the receiver can correlate exports. The Git remote URL of the repository where the SysML v2 model lives is usually the best choice: it identifies the workspace unambiguously and gives a recipient looking at a stale .reqif somewhere to look it up.

  • --reqifz: emit a zipped archive that bundles the XML and any attachments_reqif/ files into a single file. Use this whenever the document references binary attachments. The flag controls the format of the bytes written; the output filename is whatever is passed as the positional file argument, unchanged. The extension must agree with the flag: --reqifz outgoing.reqif (or outgoing.reqifz without --reqifz) is rejected before any model work runs, so pick the matching .reqifz / .reqif name to start with.

  • --attachments-dir <dir>: read attachments from a directory other than attachments_reqif/.

Transmit the resulting file to partner A through any channel (email, shared drive, ticket attachment, …). The transmission itself is out of scope of the ReqIF specification and of this CLI.

Note

The body of an exported document (the CORE-CONTENT) is deterministic: running export twice against an unchanged workspace produces byte-identical CORE-CONTENT. The REQ-IF-HEADER, however, gets a fresh IDENTIFIER (a random UUID) and a fresh CREATION-TIME (the current wall-clock time) on every run. Committing exported .reqif files to version control alongside the SysML v2 sources produces a two-line diff in the header on every re-export even when nothing in the model has changed.

Progress Reporting

Added in version 0.10.1.

Both syside reqif import and syside reqif export report progress as they work. When stdout is a TTY, a live rich progress bar is shown. When stdout is not a TTY (for example when redirected to a file or run in CI), progress is instead logged as periodic line-by-line updates, by default one every 1000 items:

syside reqif import --progress-interval 1000 path/to/incoming.reqif

--progress-interval N controls how many items pass between those non-TTY updates. Setting it to 0 disables progress output entirely. The flag has no effect on the live TTY bar, which is rendered regardless of its value.

Example Model

A small ready-to-go model ships with these docs, a worked example that exercises every ReqIF concept: an enumeration datatype, all four type templates, five spec objects across two specifications with nested hierarchies, and a relation group of two refine relations.

Download the starter model (ZIP)

Drop it into an empty directory, then run syside reqif init, syside reqif lock, and syside reqif export --title "Brake System Requirements" out.reqif to produce a ready-to-send out.reqif.