How this toolkit's interchange JSON relates to the normative sources — the OMG pilot implementation (its Xtext grammars vendored in spec-refs/, the published 20250201 JSON schemas and XMI metamodel) — and what to expect when exchanging payloads with other SysML v2 implementations. Representation choices below were adjudicated against the pilot implementation as the normative reference; where other tools serialize differently, this toolkit follows the pilot.
Full-form output validates against the published 20250201 JSON schemas, with one documented departure: the value of a numeric literal that no JSON number denotes exactly is emitted as the literal's own text, where the schema declares LiteralInteger.value an integer or null and LiteralRational.value a number or null (see Numeric literal values below for why, and crates/sysmlv2-parser/tests/full_json.rs, where the schema check's expectations live, for the exception itself). Compact output contains owned properties and deliberately omits derived properties required by those schemas; it is checked separately against the XMI property inventory. The full form computes every derived property the derivation layer answers and, by default, emits the inheritance/import closures as type-correct empty values and the inheritance-aware properties over the owned side — the API's "passthrough" level — so payload size stays proportional to the model. Under the closure policy (EmissionPolicy::closures, sysmlv2 convert --to full-json keeps the passthrough level) the four closure names — inheritedMembership, inheritedFeature, importedMembership, featuringType — are written and the inheritance-aware properties carry their computed values over the inherited and imported memberships (these remain approximations where semantic dependencies are incomplete), with or without the implied library heritage. Measured on the standard corpus (251 files, library loaded): the closure form over the written heritage is 1.28× the passthrough payload, and 2.69× with the implied heritage (every part listing the members of Parts::Part and its bases). Both forms are schema-valid and this toolkit reads either; acyclic inheritance is evaluated iteratively without a depth cap. An actual import-walk or cyclic-fallback depth cut is refused under the closure policy. Known unsupported positional dependencies, cycles and failure to stabilize named selection within its pass budget are reported separately by inheritance_incomplete; compatibility emission remains qualified, while checked reads and strict export retain their conservative refusal behavior.
Full-form scalar completion uses the effective metamodel declaration's owned default when no stored value is present; for example, a non-individual part definition exports isIndividual: false. Retained values, including invalid values, remain available for validation. A conjugated port typing's portDefinition references the original port definition. An operator expression with a loaded library Function and an available return parameter exports that parameter as its result, including at the passthrough level. These corrections do not make incomplete checked expression reads exact: strict export still refuses unavailable properties, while compatibility export retains placeholders when required references cannot be computed.
-
Operator-expression operands are wrapped: each operand becomes the
FeatureValueof an ownedinparameter Feature under a private ParameterMembership (pilotOperandEList/TypeUtil.addOwnedParameterTo; the 20250201 metamodel removed the oldoperandcontainment). Explicit argument lists (f(a, b)) wrap the same way with default visibility (KerML.xtextArgumentMember). -
Effective names:
Membership.memberNameand full-formnamederive from an unnamed feature's naming feature — the first redefined feature (attribute :>> uid = 4;is member-nameduid), a referenced feature, or a chain's last link (pilotElement::name → effectiveName()→Feature::namingFeature). Binary connector/succession ends take their computed positional names (source/target,earlierOccurrence/laterOccurrence), payloadspayload, return parametersresult, subjectssubj, objectivesobj. -
Qualified names follow the
escapedNamederivation literally (KerML 8.3.2.1): only a name without the form of a basic name is quoted, so a reserved word used as a name stays bare —ControlFunctions::if,ViewDefinition::view— which is the spelling the normative library ids (below) hash and the pilot implementation's XMI carries.qualifiedNameis therefore a model property, not guaranteed to parse as a reference; textual emission quotes such names ('part'::'view'). -
isComposite/isReference: SysML usages are composite by default, except the inherently referential metaclasses (attribute, reference, enumeration, binding/succession-as-usage, event, exhibit, include, perform — pilot*Implconstructors),ref/directed/enddeclarations, usages with no featuring type, and non-subport ports.isReferencederives as the negation; therefkeyword round-trips exactly. -
Membership-implied directions: subjects/actors/stakeholders are
in, return parametersout(pilotParameterMembershipAdapter). -
Metadata usages are AnnotatingElements owned via OwningMembership even in type bodies (unfeatured, referential); a bare about-less
@M;member canonicalizes to the#Mprefix shape. -
Comment/doc bodies are normalized like the pilot's
ElementUtil.processCommentBody, iterated to a fixpoint (the round-trip gate requires idempotence); requirementtextderives from documentation bodies. -
Classification/cast/extent expressions: type references are owned parameter Features with a
FeatureTyping; casts use a ReturnParameterMembership; the implicit subject spells as a self-reference; themeta/@@left side as a MetadataAccessExpression. -
Connector ends are ReferenceUsages (pilot
ConnectorEndrule), succession ends included; interface ends are PortUsages (pilot InterfaceEnd/DefaultInterfaceEnd). Flow ends follow the pilot'sFlowEndrule (prefix ReferenceSubsetting when spelled, plus an owned ReferenceUsage whose FlowRedefinition targets the last step). -
Multiplicity bounds: the pilot's
MultiplicityBoundsrule owns the bound literals directly under the MultiplicityRange (no operator wrapping). -
Numeric literal values carry a JSON number whenever one denotes the written literal exactly, and the literal's own text otherwise. A JSON number is a 64-bit integer or a double, so it holds neither an integer past 64 bits, nor more significant digits than a double's precision, nor an exponent outside its range; evaluation reads literals exactly, so emitting a rounded number there would make a model's JSON form and its textual form disagree.
LiteralInteger.valueis thus12but"170141183460469231731687303715884105727", andLiteralRational.valueis3.5or0.1but"1.234567890123456789012345678901"and"1e400". Readers accept either spelling for both metaclasses; a string value is parsed as the literal text it is. The published schema declares both properties numeric, so the text spelling is the one departure from it noted above. -
Variations (and enum definitions) are implicitly abstract; exposes force
isImportAll; chain/index/collect/select expressions carry their fixedoperator; multi-step chain expressions flatten to a single FeatureChainExpression + OwnedFeatureChain member. -
Every SysML port definition owns its implicit
~PConjugatedPortDefinition (OwningMembership, declaredName~P) with the PortConjugation pointing back at the original. -
Satisfy
bytargets bind per the pilot'sSatisfactionFeatureValue; named invocation/constructor arguments own the pilot'sParameterRedefinitionof the callee's parameter; positional arguments take the callee'sinparameter names (in-document callees); binding connector ends take theLinks::SelfLinkpositional namesthisThing/sameThing. -
Supported implied library and variation specializations are emitted when their targets are known. A required edge is omitted only when another specialization path still reaches its target; cycles retain enough edges to satisfy every requirement. Supported positional end, non-return parameter and result Redefinitions are materialized; imported positional sequences and other implied families remain incomplete.
-
A named import retains the selected Membership's identity, including an alias reached through another import. Its
importedElementstill references that Membership's member element. Imported membership collections retain declaration order and apply visibility, filters and ancestor exclusions. The Namespace imported-membership projection deduplicates identity and removes known name/metaclass collisions before Package filters; visibility-specific re-exports are separate operations. External or specialized inferred names and complete inheritance/import composition remain qualified. -
Declared connector-end names resolve in the connector's body through the connected feature, for binary and non-binary connectors. Binary
source/targetlookup aliases remain available after declared-name lookup. -
Shorthand successions can materialize source/target ReferenceSubsettings from checked neighboring occurrences and supported transition entries. Missing source evidence does not shift a known target into the source role. Broader transition feature chains remain qualified.
-
Generic ReferenceSubsetting does not confer a semantic name. Existing replay name-map helpers and
resolve_qualifiedretain historical syntax locators, and user ID scheme 2 retains its identity labels; neither is a normative name authority.resolve_semantic_qualifiedexcludes those locators while preserving named aliases. Namespace imports exclude unnamed reference locators before merging candidates, so multiple anonymous references do not hide a declared or inherited name.
Top-level standard-library packages get uuid5(NameSpace_URL, prefix + escapedName); every named — including effectively named (KerML 8.2.3.5) — element under fully-named ancestry gets uuid5(topPackageUuid, qualifiedName); the owning membership of such an element gets …qualifiedName + "/owningMembership"; alias Memberships get the alias's qualified name; each document root Namespace is uuid5(top, ""). The norm's positional ids for unnamed elements are 1-based ownedRelationship indices that count an implementation's implied-relationship closure, so they are not portable across implementations; such elements are never name-referenceable and keep deterministic path-based ids here (cargo run --example libids prints the table).
The complete derived-property census — every isDerived name with its class (structural, inheritance-aware, closure) and whether the emitter derives it — is generated into spec-refs/derived-properties.md by tools/derived_census.py; the bullets below are the hand-maintained notes that the census does not express.
- Supported positional end, non-return parameter and result Redefinitions are materialized, including relationships owned by library features. Nonrecursive imports from leaf providers can contribute inherited FeatureMembership slots; directly imported features and alias Memberships are not the importing type's feature slots. CanonicalV3 positional planning additionally supports recursive/transitive plain-package import selection and direct Type-owned Membership imports with certified dependency order. Checked Type reads additionally certify recursive imports with explicit global targets into named plain-package trees and aliases to explicit global declarations. Qualified paths through named plain packages require exact direct public declaration bindings at every segment after the global root; short names are supported. Membership import targets, namespace cache targets and alias targets retain their distinct resolver depth limits. Acyclic internal imports and mixed recursive/ordinary import sets are supported when every target has that same checked global declaration path and all raw import entries, mirrors and caches agree. Package aliases reuse the same checked target proof. Unnamed Namespace children, owned Type namespaces, filters, local aliases on other importing owners, lexical targets and cyclic provider paths remain qualified. The shared Membership selector counts namespace import and recursive containment edges against its depth bound; helper calls within the same namespace consume no additional depth. Selection beyond the bound is refused rather than returned as a truncated collection. Supported foreign ordinary end Features under Class owners and parameter/result Features under Behavior/Function owners use separate planning prerequisites, so their relationships are computed before import reduction without inheriting unrelated members. Ordinary parameters pair with direct-base owned parameters; results pair with the effective result, including inherited results. Acyclic authored positional chains into strict actual ancestors are supported; their existing authored paths prevent duplicate implied edges. Supported public/protected imports inside those foreign owners reuse the shared visibility selectors and complete source proof. They add no inheritance to a consumer merely because the foreign owner is scheduled; actual descendants retain the imported Memberships. Other external positional dependencies, same-owner or unrelated-owner positional chains, nested imports needing additional foreign positional owners, recursive Type traversal, metadata filters, some implicit binary KerML bases, and other implied relationship families remain incomplete. LegacyV2 keeps its prior publication behavior, including a known declaration-order limitation for aliases to foreign positional Features; checked reads refuse those uncertified dependencies in both formats.
- Checked
Definition.usageanddirectedUsageuse complete inherited feature sequences for supported structural definitions, retaining order and redefinition removal. Their success does not certify each member's internal semantics or complete implied-relationship coverage. - Compatibility export still computes some parameter/result properties independently of the shared semantic reader and can emit required-reference recovery placeholders. The checked property reader and strict export refuse unavailable semantics; complete expression graphs and export convergence remain unfinished.
- Inherited non-owning aliases of Features participate in redefinition removal. Distinct Memberships of the same Feature suppress each other through its reflexive redefinition closure; repeated paths to one Membership are deduplicated. This filtering also governs inherited positional slots. For supported explicit KerML inheritance with named, in-model memberships, lookup selects surviving Memberships before matching names. Stored reference endpoints use the same selection, including after library replay. Explicit bases may be bound through imports in enclosing namespaces: those import walks belong to the specialization reference sites and do not propagate to inherited member accesses. Redefinition headers try complete stored explicit generals in declaration order, including when each starting context requires contextual lookup; unsupported no-result cases remain qualified. Derived inheritance applies the same header context so a redefinition does not lose the members of its suppressed target. Alias targets enter recorded selection only when their complete spelling can be structurally certified without an import walk, including supported aliases, effective bindings and filtered explicit inheritance. Imports in the type itself, uncertified alias paths, filters, chains, unnamed effective-name inference, SysML Usage/Definition contexts and potential positional redefinitions retain the contextual resolver; lookup is not fully aligned in those cases.
- Checked Usage
mayTimeVaryand its effectiveisVariablealias use bounded shared ownership and specialization evidence under implied closure. Supported ordinary Usage contexts and independent exclusions can be certified. Positive ordinary end proofs require complete ordered end and redefinition evidence; unsupported contextual inheritance, metadata, Association/Connector and cross-feature contexts refuse. LegacyV2 compatibility export retains its existing defaults. CanonicalV3 source-origin end constancy and export share this evidence; imported owned flags remain explicit. Canonical export no longer forces every end Usage to be variable and constant. Incomplete end-specialization evidence still qualifies completion; compatibility JSON can retain uncertified syntax defaults, while checked reads and strict export report the gap. - The compact owner-side
conjugatedPortDefinitionproperty remains an explicit XMI-audit omission. The implicit~Pelement and full-form property are emitted; this is a property-coverage gap, not absence of the conjugated element.
Errors are reserved for what is provably wrong (syntax, illegal body context, a metadata feature typed by a resolved non-metaclass, provably violated multiplicity…). Unresolved references are warnings — the resolver covers 99.9%+ of the reference corpus, and conforming models must not fail on the long tail or on genuinely incomplete load paths. Pipelines that must refuse incomplete models (e.g. gating a Flexo commit) opt in with check --strict, which treats any finding as failure. Partial models are not second-class: in full-form output unresolved references become deterministic dangling @ids plus schema-valid TextualRepresentation recovery annotations by default, so converting the payload back to text restores the exact source references. Recovery is independent of the optional Flexo envelope.
The binary form (CBOR.md) is a byte-level re-encoding of the compact interchange element array — schema-equivalent by construction, since decoding reproduces the exact compact JSON Value before any consumer sees it. It adds no conformance surface of its own: everything above about representation rules, library element IDs, and partial models applies unchanged. The payload header carries the generated-table version; a decoder refuses a version it does not carry rather than silently mis-indexing, and the reserved id-elision flag bit is likewise refused by decoders that predate it.
User-element @ids are graph-derived (see IDS.md): chained UUIDv5 from the document root through ownership, with name-based segments for membership-owned named elements — chained past the membership's ordinal, so a named member and its membership derive from the owner and the member's name alone — and positional segments otherwise. Consequence for interchange consumers: every non-root id of a compact payload is recomputable from structure + names (ids::derive_ids), and re-emitting a model from text is id-stable under edits that do not move or rename the element's own ancestry — including inserting members before it. Payloads that carry explicit ids lift verbatim. Library element ids are unchanged (normative KerML 9.1 where named).
Sibling anonymous redefinitions such as ref :>> items = a; and ref :>> items = b; resolve their target against the inherited feature, including an inherited override. Their inferred local names cannot resolve each other's redefinedFeature. Each occurrence remains a distinct feature; compact JSON and navigation reference sites point at the same intended base target. For the supported explicit KerML cases, a Redefinition target starts in each direct general Type in declaration order, including for a globally qualified target. The declaring Type's local members do not supply that target. With no direct general Type, the reference stays unresolved. Qualifier reference sites retain the selected base context so rename can preserve the binding. Broader contextual cases remain qualified. If recorded selection cannot stabilize within its bounded replay, the model restores the complete initial contextual result and reports inheritance_incomplete; it does not expose a mixture of replayed endpoints and diagnostics.
CanonicalV3 constructor expressions own their argument carriers through an explicit
result Feature. constructor_selection_report certifies the first type selector
and sole result; constructor_binding_report orders supplied named and supported
positional arguments by the complete public instantiated-Type feature sequence,
including undirected and output features. Positional mappings require current
published redefinition witnesses. Duplicate assignments and incomplete mappings
refuse. constructor_default_report selects omitted-feature defaults, including
inherited and private features; conflicting or cyclic inheritance refuses.
constructor_result_report checks result specialization and the default
BindingConnectors installed under the result by the shared publisher. Constructor
model-level evaluability uses the same checked supplied arguments. These reports
do not certify unrelated whole-model constraints. LegacyV2 keeps its existing
shape and defaults. See IDS.md for the explicit migration and identity contract.
Checked cardinality reports expose exact supported intervals and their source identities. Inherited constraints intersect, incompatible constraints are errors, and symbolic collections retain their bounds instead of counting as one item. Bound references can select a unique receiver redefinition and certify its current local valuation through complete Type feature evidence. Runtime parameters, metadata-dependent values and incomplete receiver projections remain qualified. Unknown receiver members remain qualified because the current value representation does not retain their receiver cardinality. CanonicalV3 numeric bound formulas use current graph operands and shared published bindings to exact loaded library functions. Unsupported providers and stale generated evidence refuse. Compatibility cardinality helpers also reject contradictory ownership and stale generated edges. LegacyV2 remains the default graph format and retains its publication shape.
CanonicalV3 also supplies the owned FeatureTyping obligations for Features typed by
Structure, Class or DataType: subsetting Objects::objects,
Occurrences::occurrences or Base::dataValues, respectively. Multiple applicable
obligations enter the shared specialization planner before redundant-edge reduction.
Targets require unique loaded library identities and reciprocal owned typing
evidence. LegacyV2 retains its existing edges. Ordinary typed reference ends under
supported OccurrenceDefinition owners can therefore complete checked constancy;
owners whose inherited Usage families lack a complete provider still qualify.