Migrate to Syside v1

Use this guide to migrate your SysML v2 models to Syside v1, whether you work in the VS Code Extension or with the Python library.

Syside v1 comes with additional validation rules that help ensure your models are correct, so a model created with an older version can report errors. This guide shows how to fix them.

Before you start, back up the model, so you can revert the fixes if needed.

Fix check errors

  1. Run syside check (Check command) from each project’s root folder.

  2. Fix any reference-error diagnostics first, then run syside check again.

  3. Fix each remaining error with the fix listed under its rule id.

feature-reference-expression-access

error (feature-reference-expression-access): Feature reference must be accessible from
the outer scope, did you mean to use chain notation?

Rule reference: feature-reference-expression-access.

Use the fix for your case:

  • If the path starts from a usage, write . after it, not ::.

    // before
    action def Responses { action restart; action shutdown; }
    action def FaultHandling {
        action responses : Responses;
        ref action recommendation = responses::restart;
    }
    // after: in FaultHandling, replace the recommendation line with
    ref action recommendation = responses.restart;
    
  • If the path starts from a definition’s name, chain from a feature typed by that definition instead. In a case with a subject, reach the subject’s features through the subject.

    // before
    part def BatteryMonitor { attribute reportedAccuracy : ScalarValues::Real; }
    verification def VerifyMonitorAccuracy {
        subject monitor : BatteryMonitor;
        action evaluateData {
            in measuredAccuracy : ScalarValues::Real = BatteryMonitor::reportedAccuracy;
        }
    }
    // after: in evaluateData, replace the measuredAccuracy line with
    in measuredAccuracy : ScalarValues::Real = monitor.reportedAccuracy;
    
  • In a filter, read a metadata attribute with the cast form. A bare filter @Review; needs no change.

    // before
    metadata def Review { attribute isApproved : ScalarValues::Boolean; }
    view def ApprovedOnly { filter @Review and Review::isApproved; }
    // after: in ApprovedOnly, replace the filter line with
    filter @Review and (as Review).isApproved;
    

    A table using this filter can show fewer rows than before: the v1 rows are the correct ones.

view-usage-types

error (view-usage-types): A view usage must be defined by a single view definition

Rule reference: view-usage-types.

Define one concrete view definition that specializes every type the usage lists, even when one of them is abstract, and type the usage by it.

// before
abstract view def Filter_PartsActions {
    filter (as SysML::PartUsage) hastype SysML::PartUsage or (as SysML::ActionUsage) hastype SysML::ActionUsage;
}
occurrence def ProjectViews {
    view GV_PartsActions : StandardViewDefinitions::GeneralView, Filter_PartsActions;
}
// after: keep Filter_PartsActions, add GeneralView_PartsActions, and in
// ProjectViews replace the view line
view def GeneralView_PartsActions specializes StandardViewDefinitions::GeneralView, Filter_PartsActions;
occurrence def ProjectViews {
    view GV_PartsActions : GeneralView_PartsActions;
}

*-usage-types

error (item-usage-types): An item usage must only be defined by item definitions or
KerML structures

Match each usage’s keyword to its definition’s kind.

  • item-usage-types: Data typed by an attribute def or a ScalarValues type is an attribute. So is an untyped usage bound to an attribute value: in item trigger = check.ready; becomes in attribute trigger = check.ready;. The rule also covers part usages. If the data really is an item, make its definition an item def instead.

    // before
    attribute def ManifestEntry { attribute stationId : ScalarValues::String; }
    action def LoadVehicle {
        in item manifest [*] ordered : ManifestEntry;
        out item doorClosed : ScalarValues::Boolean;
    }
    // after: in LoadVehicle, replace the two item lines with
    in attribute manifest [*] ordered : ManifestEntry;
    out attribute doorClosed : ScalarValues::Boolean;
    
  • requirement-usage-types: Type each usage by a definition of its own kind: a requirement by a requirement def, and a concern, including a frame concern, by a concern def.

    // before
    abstract constraint def ReqTemplate { attribute reqId : ScalarValues::String; }
    requirement def SystemRequirements {
        requirement <'REQ-001'> maxMass : ReqTemplate {
            require constraint { doc /* The mass shall not exceed 2 kg. */ }
        }
    }
    // after: replace the ReqTemplate line with
    abstract requirement def ReqTemplate { attribute reqId : ScalarValues::String; }
    
  • On a usage tagged with semantic metadata (metadata that specializes Metaobjects::SemanticMetadata), move the tag from the typed usage to its definition, and type the usage by that definition alone. This applies to requirements, concerns, cases, views, viewpoints and renderings, but not constraints. A concern usage reports requirement-usage-types.

    // before
    concern def Tracked;
    abstract concern trackedConcerns : Tracked [*];
    metadata def <tracked> TrackedMetadata specializes Metaobjects::SemanticMetadata {
        :>> baseType = trackedConcerns meta SysML::Type;
    }
    concern def Cost;
    occurrence def ProductContext { #tracked concern cost : Cost; }
    // after: replace the last two lines with
    #tracked concern def Cost;
    occurrence def ProductContext { concern cost : Cost; }
    

    An @tracked filter then no longer selects the usage. To keep it selectable, leave the tag on the usage and make its definition specialize the type of the tag’s base feature (here Tracked) instead:

    // after: keep the tag on the usage, and replace the concern def Cost line with
    concern def Cost specializes Tracked;
    
  • verification-case-usage-types: Type the usage by one definition, and move what the second definition set into the usage’s body.

    error (verification-case-usage-types): A verification case usage must be defined by a
    single verification case definition
    
    // before
    verification def VersionedTest { attribute version : ScalarValues::String; }
    verification def Release1 specializes VersionedTest { attribute :>> version = "1.0"; }
    verification def StartupTest specializes VersionedTest;
    verification def AcceptanceTests {
        verification startup : StartupTest, Release1;
    }
    // after: delete Release1 if nothing else uses it, and in AcceptanceTests replace
    // the startup line with
    verification startup : StartupTest { attribute :>> version = "1.0"; }
    

Rule settings

The severity of some rules can be set in the [lint] table of syside.toml. Of the rules on this page, only feature-reference-expression-access can be lowered: set lint.feature-reference-expression-access to "warning", or to "off" to hide it.

[lint]
feature-reference-expression-access = "warning"

Check the result

  1. With Syside v1, export every table and matrix with syside grid export (Grid command) and every diagram with syside viz view (Viz command) into an empty directory.

  2. Check that every file you expect exists and has the expected content.

Note

Optional: instructions for an LLM agent. If you use an LLM agent for the migration, you can give it these instructions as well as the steps above:

  • Fix one rule at a time across the model, then run syside check.

  • Change only what the fix for that rule needs. Don’t rename or restructure anything else.

  • Never make a check pass by downgrading a rule in [lint] or adding an exclude entry.

  • Don’t edit library files copied into the project. Report errors in them instead.

  • Stop and ask when a fix needs a modeling decision, such as which kind a definition should be.

  • Report every change in the exports to a person. Don’t accept one yourself.