I’ve noticed many semantic issues with Syside. Here is one that didn’t show up, which is insidious.
Given the specification:
//**
* To fulfill the Return-to-Home (RTH) automated flight management requirements specified in
* Requirement 8.1.1 (All-Weather Runway Operations - Failsafe System), we must model a deterministic
* state machine. The system must automatically trigger RTH upon encountering signal loss, a critical
* sensor failure, or when the battery charge drops below 20%.
*
* In SysML v2 (Release 2026-03), flight management logic is represented using a state def block
* driven by conditional if expressions evaluating safety thresholds.
*/
package 'Autonomous Emergency Management' {
private import ScalarValues::*;
private import Quantities::*;
private import ISQ::*;
private import SI::*;
/* =========================================================================
* SECTION 1: EMERGENCY METRIC AND LINK MONITORING DATA SCHEMA
* ========================================================================= */
public attribute def Failsafe_Telemetry_Frame {
doc /* Sensory monitoring data structure continuously evaluated by the failsafe state machine. */
attribute batteryChargePercentage : Real; // Expressed from 0.0 to 100.0
attribute commandLinkLostDuration : TimeValue;
attribute hasCriticalSensorFailure : Boolean;
}
/* =========================================================================
* SECTION 2: FAILSAFE STATE MACHINE SPECIFICATION
* ========================================================================= */
public state def Autonomous_RTH_Lifecycle {
doc /* Automatically triggers and controls Return-to-Home trajectory profiles per Req 8.1.1 failsafe criteria. */
// Inbound parameter mapping active aircraft metrics into the conditional expressions
in item systemHealth : Failsafe_Telemetry_Frame;
// ---------------------------------------------------------------------
// STATE: Nominal Mission Profile Execution
// ---------------------------------------------------------------------
state nominalMissionExecution {
doc /* System operates normally, executing pre-programmed 3D waypoint navigation lines. */
}
// ---------------------------------------------------------------------
// STATE: Command Link Interruption Buffering
// ---------------------------------------------------------------------
state commandLinkLostTransient {
doc /* Buffers transient command link drops. Executes an un-jamming route for up to 15 seconds per Req 8.1.6. */
entry action executeUnjammingRoute;
}
// ---------------------------------------------------------------------
// STATE: Active Return-to-Home (RTH) Trajectory
// ---------------------------------------------------------------------
state activeReturnToHome {
doc /* System overrides normal routing to autonomously guide the aircraft back to the home waypoint. */
state ascendingToSafeAltitude {
doc /* Climbs to predefined minimum safe altitude clearance plane. */
entry action commandClimbPower;
}
state transitToHomeWaypoint {
doc /* Flies directly toward the home coordinates using pre-programmed autonomous flight logic. */
entry action engageHomeNavigationTrack;
}
state automatedRecoveryLanding {
doc /* Executes autoland sequence on the wet/snowy runway utilizing automated ABS traction control. */
entry action deployLandingGearAndABS;
}
// Standard nested entry path configuration
entry;
then ascendingToSafeAltitude;
// Internal sequencing within the RTH sub-states
transition first ascendingToSafeAltitude then transitToHomeWaypoint;
transition first transitToHomeWaypoint then automatedRecoveryLanding;
}
// ---------------------------------------------------------------------
// STATE MACHINE CORE TRANSITIONS
// ---------------------------------------------------------------------
entry;
then nominalMissionExecution;
// 1. Transition to short-term un-jamming buffer state upon losing command link encryption frame updates
transition first nominalMissionExecution
if systemHealth.commandLinkLostDuration > 0.0 [s]
then commandLinkLostTransient;
// 2. Recovery transition if link is restored within the 15-second grace window
transition first commandLinkLostTransient
if systemHealth.commandLinkLostDuration == 0.0 [s]
then nominalMissionExecution;
// 3. Escalation to full RTH if command link loss duration exceeds the 15-second mandatory threshold (Req 8.1.6)
transition first commandLinkLostTransient
if systemHealth.commandLinkLostDuration > 15.0 [s]
then activeReturnToHome;
// 4. Instant RTH activation from critical internal failures (Battery under 20% or sensor failure)
transition first nominalMissionExecution
if systemHealth.batteryChargePercentage < 20.0 or systemHealth.hasCriticalSensorFailure
then activeReturnToHome;
}
/* =========================================================================
* SECTION 3: SYSTEM HARDWARE DESIGN INTEGRATION
* ========================================================================= */
public part def Flight_Management_Computer {
doc /* Autopilot hardware node hosting the real-time safety lifecycle execution loop. */
// Active data monitor instance in local scope
item flightHealthMetrics : Failsafe_Telemetry_Frame;
// Instantiating the validated state behavior directly inside the hardware scope
state failsafeSupervisor : Autonomous_RTH_Lifecycle {
in item systemHealth = flightHealthMetrics;
}
}
}
The following lines are flagged errors by the OMG Eclipse editor for Rel. 2026-03
An occurrence, item or part must be typed by occurrence definitions.
Duplicate of inherited member name ‘self’
Lines 36, 118, and 122.
The correction is to use “attribute” and not “item”
An ItemUsage must directly or indirectly specialize the Systems Model Library ItemUsage items.
specializesFromLibrary('Items::items')
checkPartUsageSpecialization
A PartUsage must directly or indirectly specialize the PartUsage Parts::parts from the Systems Model
Library.
specializesFromLibrary('Parts::parts')
Howevere, these are semantic (check) constraints which are automatically applied by Syside.
Seems to stem from the invalid typing by attribute and implicit subsettings. Inherited name distinguishability across inheritance branches is not yet implemented in Syside.
Thank you for your analysis. The bug report is to document Syside and OMG evaluation of this specification. While the syntax allows the item/attribute statements, the semantics do not allow for this. Your last statement confirms that 0.10.3 is not quite there. I’ve read in the forum that 0.11.x is coming. I’ll upgrade and try again when Syside 0.11.x is available.
An occurrence definition or usage (that is not of a more specialized kind) can
be declared as described in 7.6.2 and 7.6.3 , using the kind keyword
occurrence. An occurrence usage may only be defined by occurrence definitions
(of any kind) or KerML classes (see [KerML, 7.4.3]).
Syside implements validation rules from chapter 8 instead of trying to parse the intent of chapter 7.
Quickly went through the specification and found a bunch more similar semantic constraints only mentioned in passing in chapter 7 but entirely omitted from chapter 8:
attributes must be defined by datatypes.
enums must be typed by a single enum def when declared outside of enum def.
occurrences must be defined by classes.
connections must be defined by assoc structs.
actions must be defined by behaviors.
behaviors and steps should not have result if return is bound.
requirements must be defined by a single requirement def.
cases must be defined by a single case def.
analysis cases must be defined by a single analysis case def.
verifications must be defined by a single verification def.
use cases must be defined by a single use case def.
views must be defined by a single view def.
viewpoints must be defined by a single viewpoint def.
renderings must be defined by a single rendering def.
Thanks for pointing out the semantic “misses” in the OMG specification between clauses (i.e., chapters) 7 and 8!
While the definition syntax is usually understood, the meta-model static semantics seem to be missing. Syside either doesn’t enforce a lot of these semantics yet or only performs a first-pass, syntax-only semantics check (i.e., parser-phase checking).
Regardless, if the OMG Pilot editor can catch the semantic issues, I’d hope that Syside would as well. What should my expectations be? Right now, I have to run all my code through Syside and the OMG Pilot to make sure I’ve caught as much as I can. I’m not Ed S. , so my code can be janky at times. Has Sensmetry created a regression suite for semantic checking? I would expect that, but some of the missed semantic catches make me wonder
Syside does perform both syntax and semantic checking. Nearly all validation rules defined in chapters 8 are implemented, see also Validation Rules — Syside. Currently only missing inherited name distinguishability across inheritance branches, and control node successions. Some structural constraints are enforced automatically by the model structure, some are inserted during semantic pass, e.g. implicit specializations.
Yes, every new feature always comes with corresponding tests. We can only test what we know.
Will add the missing checks for the release after 0.11.
Seems like this is triggered by the standard library, and probably meant associations (not assoc structs). E.g. Flows::Message contains connections with HappensDuring types, which is an association, not an association structure.
@Daumantas Notice that in SysML2, connections between parts are both links and parts, so connection usages must be typed/defined by association structures, while KerML connectors, which subsume succession usages, are typed by associations.
But these connection usages also subset binaryConnections, which is typed by an association structure, so they are typed by an association structure.
It’s a fundamental conceptual choice of SysML2: connections are both links and parts. Consequently, connection usages are typed by an association structure, not just by an association!
A connection usage must only be defined by connection definitions (of any kind) or KerML association structures (see [KerML, 7.4.5]).
Seems quite clear to me that connections may only have types that are connections def or assoc structs, and not assocs. Of course, this is the only sentence we have to go on since such constraints are not formalized in chapter 8.
The implicit subsetting to binaryConnections does not override the HappensDuring with a more derived type so those connections, in addition to being defined by all the types of binaryConnections, also have a HappensDuring type which is neither connection def nor assoc struct. The types of binaryConnections are not the ones that violate the constraint as it is written, only the feature typing to HappensDuring.
There is no violation. The subsetting to binaryConnection just implies another typing (by AssociationStructure), in addition to HappensDuring. And when a feature/usage is typed by several classifiers (such as HappensDuring and AssociationStructure), then its range is their intersection, which is a subclassifier of AssociationStructure, so any values of these connection usages are link objects..
Does not seem like a statement of constraint like in chapter 7:
8.3.13.4 ConnectionUsage
Description
A ConnectionUsage is a ConnectorAsUsage that is also a PartUsage. Nominally, if
its type is a ConnectionDefinition, then a ConnectionUsage is a Usage of that ConnectionDefinition, representing a connection between parts of a system. However,
other kinds of kernel AssociationStructures are also allowed, to permit use of AssociationStructures from the Kernel Model Libraries.
compared to
A connection usage must only be defined by connection definitions (of any kind) or KerML association structures (see [KerML, 7.4.5]).
Specification states that it is a union
deriveFeatureType
The types of a Feature are the union of the types of its typings and the types of the Features it subsets, with all redundant supertypes removed. If the Feature has chainingFeatures, then the union also includes the types of the last chainingFeature.
type =
let types : OrderedSet(Types) = OrderedSet{self}->
-- Note: The closure operation automatically handles circular relationships.
closure(typingFeatures()).typing.type->asOrderedSet() in
types->reject(t1 | types->exist(t2 | t2 <> t1 and t2.specializes(t1)))
Note that is no deriveUsageDefinition so I can only assume it is the same as Feature::type given that definition is a redefinition of type.
And intersection should result in the less derived of the two, i.e. Association ∩ AssociationStructure == Association.
You are confusing the (featured) types of a feature with its range (or co-domain):
A feature relates instances in the intersection of the extents of its featuring types (the domain) with
instances in the intersection of the extents of its featured types (the co-domain). [KerML 7.3.4.1]
The values of a feature need to be instances of its range, which is more specific than its types.
Using any loses all practical cases for these constraints as semantic constraints already implicitly satisfy them. These validations are intended to catch users misusing definitions, so that e.g. state is not defined by action def even if it is implicitly defined by state def. Just slapping on a compatible definition should not suddenly make the constraint pass. Of the standard library and official examples, only these two connections violated any of the constraints as they are written in the specification.
This is also how it is implemented in the Pilot implementation:
Pilot implementation also checks for Associations, not AssociationStructures
I may have been unclear a bit. While Feature::type returns a union, it is only in the context of the resulting set of types. How that set is used determines whether it means a union or an intersection:
A union is checked as any — any type in set satisfying a predicate means that the set also satisfies the predicate.
An intersection is checked as all — all types in the set must satisfy a predicate for the set to also satisfy the predicate.
Syside and Pilot implementation both use all consistently with specification.