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 whose library already matches
the current release is a safe no-op (Found existing SysideReqIF.sysml library. No action needed.). If the copy in the workspace differs, init rewrites it to the
shipped text and says Updated SysideReqIF.sysml with latest SysideReqIF library content., so init doubles as the upgrade command. The other commands produce a clear
error pointing back to init when the library is missing or out of date, 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). An entry inside a .reqifz whose path would
land outside that directory is skipped with a warning rather than extracted, so a
malformed or hostile archive cannot write elsewhere in the workspace; the rest of the
import proceeds.
The directory must resolve to a subdirectory inside the workspace, and not to the
workspace root itself: an attachment link is recognized by its directory prefix, which
the root does not provide. The Markdown links written into the model are spelled
relative to the .sysml file that holds them (../../attachments_reqif/pic.png in a
--split-by member file), so the workspace stays portable across machines and the
language server can render the image on hover.
Changed in version 0.11.0: Attachment links used to be spelled relative to the workspace root, which resolved
only for files sitting directly in it. The workspace root is now rejected as
--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
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.
The flag also covers names that collide inside a single owner rather than in the
top-level namespace: EnumValues within one enumeration DatatypeDef, and
AttributeDefs within one SpecType. It additionally resolves an enumeration
DatatypeDef that shares its name with an AttributeDef it types. In that last
case the attribute is the side that gets the suffix, so the enumeration keeps its
original name: that name qualifies every value expression in the model
(Priority::high), and is what auto-completion offers while writing them.
Splitting large imports New in v0.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:
hierarchy: splits the objects file by following ReqIF specification hierarchy until a subtree can fit within--split-max-loclines (by default 10 000) or--split-max-depthlimit 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 syntaxFolder::Subfolder::'requirement name'.flat-greedy: splits the objects file into chunks where each one is at most--split-max-loclines long (by default 10 000).
Four further flags tune the result. Each is rejected outside the strategy it applies to, so a typo fails the import rather than being silently ignored:
--split-reexports/--no-split-reexports(either strategy): whether the baseReqIF_Import_Objectspackage re-exports the split member packages as public imports, so references through it resolve identically in every layout. Dropping them trades that for a smaller wildcard-import fan-out. Enabled on a fresh split import; on a delta, the workspace’s current state is kept.--split-min-depth <n>(hierarchy): force the folder tree to unroll at leastnlevels underReqIF_Import_Objects/, where the per-Specificationfolder is level 1, even where a subtree would fit one file. Use it to surface top-level semantic groups as folders. It must not exceed--split-max-depth, nor the shallowest leaf of any hierarchy, since a branch that ends before the floor cannot be unrolled to it. Default0, meaning no forced unrolling.--split-max-slug-length <n>(hierarchy): truncate the name-derived file and folder slugs toncharacters, guarding against overly long paths. Collisions the truncation causes are resolved with a deterministic identifier-derived suffix. Default64.--rename-files(hierarchy, delta imports): reconcile the name-derived files, folders, packages, and aliases with the elements’ current names. All stale names are fixed, not only the ones this delta renamed. Without it, renamed elements keep their old paths and a warning lists them.
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 New in v0.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.
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(aconnection) must stay inside theoccurrence deffor itsRelationGroup. The export resolves a relation’s source and target endpoints through thesource_specification/target_specificationfeatures 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 wholeRelationGroupoccurrence definstead; the contained connections travel with it.A nested
SpecHierarchy(arequirementusage indexed as'1','2', …) is owned by the parentSpecObjectdefand moves with thatdef; 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.
One thing does not travel with a moved element: links to extracted attachments are
spelled relative to the .sysml file that holds them. After moving text that
references an attachment into a file at a different directory depth, correct the ../
prefix of each such link, or re-run syside reqif import to have the whole body
regenerated. An uncorrected link resolves to nothing on hover and in rendered
Markdown, and one that no longer resolves at all is no longer recognized as an
attachment reference, so the attachment silently drops out of the next export. See
Known limitations.
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.reqifsomewhere to look it up.--reqifz: emit a zipped archive that bundles the XML and theattachments_reqif/files the document references 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 positionalfileargument, unchanged. The extension must agree with the flag:--reqifz outgoing.reqif(oroutgoing.reqifzwithout--reqifz) is rejected before any model work runs, so pick the matching.reqifz/.reqifname to start with.--attachments-dir <dir>: read attachments from a directory other thanattachments_reqif/. As on import, it must be a subdirectory inside the workspace.--source <name>: the exchange to export, when the workspace serves more than one partner. See Serving several exchange partners .
A .reqifz carries only the files the exported document actually references from an
XHTML attribute value. Anything else sitting under the attachments directory stays
out: stale files from an earlier import, scratch notes, and, in a workspace serving
several partners, the attachments belonging to the other exchanges. A reference with
no file behind it is reported as a warning naming the missing paths, and the export
still succeeds.
Changed in version 0.11.0: export used to bundle every file under the attachments directory recursively,
whether or not the document referenced it, which made curating that directory by hand
the only thing standing between one partner’s files and another partner’s inbox.
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.
Serving several exchange partners New in v0.11.0
A workspace can take part in more than one exchange at a time. Every @reqif
annotation carries a source naming the exchange it belongs to, and an element may
carry one annotation per partner, each with its own identifier and optional
long_name. The pair (source, identifier) is the ReqIF identity: it must select at
most one element in the workspace, and one element may hold at most one identity of a
given kind per source.
--source <name> selects the exchange for export, lock, and link scaffold. Its
default is the unnamed exchange (""), which is what a single-partner workspace uses
and what import writes, so nothing needs to change until a second partner appears.
The selection covers attachments too. Exporting one exchange bundles only the files
that exchange’s own requirements reference, so a shared attachments_reqif/ can hold
every partner’s images without one partner’s export carrying another’s.
Two paths lead into a multi-partner workspace:
syside reqif importgenerates a model from an incoming document, as described above.syside reqif linkmaps a partner’s document onto elements you authored yourself, which is how one ontology comes to carry several partners’ identities. See Linking an existing ontology.
Progress reporting New in v0.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.