Concepts¶
Pipeline¶
The high-level pipeline crosses an explicit project boundary:
![// SPDX-License-Identifier: MPL-2.0
// SPDX-FileCopyrightText: 2026 SECORO AG (secoro.uni-bremen.de)
// Author: Vamsi Kalagaturu
digraph pipeline {
rankdir=LR;
graph [bgcolor="white", nodesep=0.35, ranksep=0.65, compound=true];
node [shape=box, style="rounded,filled", fillcolor="white", fontname="sans-serif"];
edge [fontname="sans-serif"];
subgraph cluster_dsl {
label="motion-spec-dsl (authoring frontend)";
color="#2f81f7";
penwidth=2;
style="rounded,filled";
fillcolor="#eaf3ff";
source [label=".robmot + .scenex + .fsm"];
rdf [label="parse + resolve + emit\nJSON-LD RDF dataset"];
source -> rdf;
}
subgraph cluster_motion_spec {
label="motion-spec (compiler and runtime toolchain)";
color="#8a63d2";
penwidth=2;
style="rounded,filled";
fillcolor="#f3edff";
check [label="check\nSHACL validation"];
ir [label="gen ir\nmotion-spec IR"];
cpp [label="gen / gen code\ngenerated C++"];
build [label="build\nreusable executable"];
run [label="run\nREC + frame log"];
replay [label="replay\nsummary / decoded frames"];
ir -> cpp -> build;
build -> run [label="1..n"];
run -> replay;
}
rdf -> ir [ltail=cluster_dsl, lhead=cluster_motion_spec];
rdf -> check [style=dashed, label="optional validation"];
}](_images/graphviz-6bd39dd3b6b1d0bad05ff09ff64026e41d51ee9a.png)
Figure 1 Commands, ownership, and the reusable generation boundary.¶
motion-spec-dsl defines the
.robmot language, composes its scene and FSM imports, resolves DSL semantics,
owns the model classes, RDF vocabulary and manifest validation, and emits the
JSON-LD RDF dataset. motion-spec consumes that boundary: its RDF parser lowers
the combined dataset into compiler IR, after which code generation and runtime
tooling take over. It does not define or parse the authoring language itself.
The high-level motion-spec gen and motion-spec run MODEL commands invoke
the installed DSL frontend before continuing through their own stages.
motion-spec build compiles one generation. motion-spec run takes either a
model, which it generates and builds first, or an existing generation directory.
motion-spec replay consumes the resulting run.
Generations and runs¶
A generation is immutable input plus reusable generated and compiled artifacts.
It receives its own directory because separate generations may differ even when
they came from the same model. A new generation goes to
<base>/<model stem or --name>/<timestamp>/, where the base is -o or
$MOTION_SPEC_GEN; with neither, gen and run stop. gen prints the
generation’s path on stdout, and $MOTION_SPEC_GEN/latest points at the newest.
A generation may be executed many times. Each execution belongs under that
generation’s runs/<run-id>/ directory. Runs contain runtime data only; they
reference generation-owned model, controller, contract, and provenance files
instead of copying them.
<base>/<model>/<timestamp>/
generated/
source/ authored DSL snapshot
model/ application JSON-LD, imported graphs, scene and FSM graphs, motion IR
controller/ generated C++ and CMake project
contract/ schema, frame layout, and frame-log protocol
provenance/
generation.ld.json one document, one named graph per tool
derived.ld.json what IR generation derived, and from what
build/ reusable compiled controller
logs/ console.log: what the DSL, stst and cmake said
runs/<run-id>/
logs/ frame_log.pb (zstd-packed to frame_log.pb.zst once archived),
console.log and health information
files/ the environment file the run was given
provenance/
<run-id>.ld.json REC record: lifecycle, host, metrics
execution.ld.json who ran it, the command line, the files it used and generated,
sampling draws
manifest.json consumer-facing paths into the run and generation
JSON-LD artifacts use the .ld.json suffix and are loaded as RDF datasets,
not treated as application JSON.
High-level commands¶
Command |
Contract |
|---|---|
|
Report Python, executable, and target-native dependencies |
|
Generate JSON-LD, IR, contracts, provenance, and C++ |
|
Stop after JSON-LD and IR |
|
Configure and compile into |
|
Create a generation, build it, execute it, recover runtime RDF, and archive the run |
|
Execute an existing generation again, as a new run beside the earlier ones |
|
|
|
Summarize, verify, decode, or recover a recorded run |
|
Compose a scene in MuJoCo and view it, without generating or building anything |
Use --prefix on build or run to add CMake package prefixes. It is
repeatable for build. -o, --name, --prefix, and -j configure
generation and build, so they require a .robmot model; --headless,
--steps, and --run-id apply to both forms, --steps requires
--headless, and both are refused for a hardware generation.
Low-level commands¶
The individual stages remain available for automation and debugging:
Command |
Input and output |
|---|---|
|
Validate an application JSON-LD manifest and its imported graphs with SHACL |
|
Stop after lowering to IR |
The high-level model commands call these capabilities through the same Python implementation; they do not maintain a second pipeline.
Validation¶
check resolves the application manifest’s RDF imports and SHACL shapes. Pass
--meta-shacl to validate the shapes themselves against SHACL-of-SHACL. A
successful generation does not replace an explicit validation step when validation
is part of a release or CI contract.
Runtime recording¶
run creates the REC record provenance/<run-id>.ld.json before launching the executable
and exports the frame-log path to it. The run is recorded there as a
prov-ext:Execution with an OSLC Automation state and, once complete, a verdict;
the agents that ran it, its command line and the files it used and generated go to
provenance/execution.ld.json on the same run node. The log starts with a header containing the schema hash;
a model that samples follows it with the seed and every draw ([sampling] seed in the robot
config fixes the seed, otherwise the OS draws one). One protobuf frame per control tick follows. On completion, the CLI catalogs
run-owned files, records their provenance, and verifies the archive.
The manifest is deliberately small: its files map identifies what replay and
other consumers need. Lifecycle provenance lives in the REC record, runtime artifact hashes in
the execution document. Everything generation recorded lives in one document,
generated/provenance/generation.ld.json, with a named graph per tool that wrote into it.
Every prov:atLocation is a path from the generations root ($MOTION_SPEC_GEN), such as
pick_and_place/20261004T114752754313Z/generated/model/ir.json; each document states the
root as its @base, so a reader resolves it to the file.
Replay¶
With no option, replay prints a run summary. --verify requires the run’s
manifest.json: it checks that every file the manifest names exists, that the
log’s schema hash matches the generation’s frame_layout.json, and that the
log holds as many frames as the writer reported. A run without a manifest can
still be summarized and decoded, but not verified. --jsonl streams decoded
frames for external analysis.