Skip to content

memo_core_relationships

SysML API

Public namespace memo::core::relationships
Declared package memo_core_relationships
Source src/core/relationships/memo_relationships.sysml

Namespace hierarchy

memo → memo::core → memo::core::relationships

Packages

Package
memo_core_relationships

Imports

Visibility Target
private Metaobjects::SemanticMetadata
private ScalarValues::*
private Connections::BinaryConnection
private memo_core_common::*
private memo_core_enumerations::*
private Allocations::Allocation

Declarations

Name SysML kind Description Specializes
MemoRelationship connection def Typed relationship for memo relationship. Connections::BinaryConnection
MemoTypedDependency metadata def A link whose ends are not both usages cannot be a connection def: a connection joins features, and a ref cannot point at a definition.… —
ScopedTo connection def Typed relationship from any element to MemoPart. MemoRelationship
DerivesFrom connection def Typed relationship from any element to MemoRequirementElement. MemoRelationship
ProducesEvidence connection def Typed relationship from MemoVerificationCase to MemoEvidence. MemoRelationship
DerivesCyberRequirement connection def Typed relationship from RequirementDriver to MemoRequirementElement. MemoRelationship
CrossesTrustBoundary connection def Typed relationship from any element to any element. MemoRelationship
Validates connection def Typed relationship from any element to MemoVerificationCase. MemoRelationship
HostedBy allocation def A processing node hosted by an assembly is allocated to it. The end NAMES were already right; two of the three usages wrote them in reverse order, and the builder binds by position, so those two edges pointed the wrong way. See the reversed-end-name lint in memo-tools. MemoRelationship
BindsToInterface connection def Typed relationship from any element to any element. MemoRelationship

MemoRelationship

abstract connection def MemoRelationship :> Connections::BinaryConnection
Property Value
Description Typed relationship for memo relationship.
Kind connection def
Abstract Yes
Specializes Connections::BinaryConnection
Owning package memo_core_relationships

MemoTypedDependency

abstract metadata def MemoTypedDependency
Property Value
Description A link whose ends are not both usages cannot be a connection def: a connection joins features, and a ref cannot point at a definition.…
Kind metadata def
Abstract Yes
Specializes —
Owning package memo_core_relationships

ScopedTo

connection def ScopedTo :> MemoRelationship
Property Value
Description Typed relationship from any element to MemoPart.
Kind connection def
Abstract No
Specializes MemoRelationship
Owning package memo_core_relationships

DerivesFrom

connection def DerivesFrom :> MemoRelationship
Property Value
Description Typed relationship from any element to MemoRequirementElement.
Kind connection def
Abstract No
Specializes MemoRelationship
Owning package memo_core_relationships

ProducesEvidence

connection def ProducesEvidence :> MemoRelationship
Property Value
Description Typed relationship from MemoVerificationCase to MemoEvidence.
Kind connection def
Abstract No
Specializes MemoRelationship
Owning package memo_core_relationships

DerivesCyberRequirement

connection def DerivesCyberRequirement :> MemoRelationship
Property Value
Description Typed relationship from RequirementDriver to MemoRequirementElement.
Kind connection def
Abstract No
Specializes MemoRelationship
Owning package memo_core_relationships

CrossesTrustBoundary

connection def CrossesTrustBoundary :> MemoRelationship
Property Value
Description Typed relationship from any element to any element.
Kind connection def
Abstract No
Specializes MemoRelationship
Owning package memo_core_relationships

Validates

connection def Validates :> MemoRelationship
Property Value
Description Typed relationship from any element to MemoVerificationCase.
Kind connection def
Abstract No
Specializes MemoRelationship
Owning package memo_core_relationships

HostedBy

allocation def HostedBy :> MemoRelationship, Allocations::Allocation
Property Value
Description A processing node hosted by an assembly is allocated to it. The end NAMES were already right; two of the three usages wrote them in reverse order, and the builder binds by position, so those two edges pointed the wrong way. See the reversed-end-name lint in memo-tools.
Kind allocation def
Abstract No
Specializes MemoRelationship
Owning package memo_core_relationships

BindsToInterface

connection def BindsToInterface :> MemoRelationship
Property Value
Description Typed relationship from any element to any element.
Kind connection def
Abstract No
Specializes MemoRelationship
Owning package memo_core_relationships

Source

core/relationships/memo_relationships.sysml
package memo_core_relationships {
    private import Metaobjects::SemanticMetadata;
    private import ScalarValues::*;

    private import Connections::BinaryConnection;

    private import memo_core_common::*;
    private import memo_core_enumerations::*;

    private import Allocations::Allocation;
    // All MEMO relations are native SysML v2 `connection def`s (each is a
    // Connection/Association), specializing the MemoRelationship base. The
    // relationship name is the verb; the RelationshipRegistry derives the
    // navigable type as camelCase(name) and navigation is bidirectional.
    //
    // MemoRelationship roots on the SysML v2 standard library's
    // Connections::BinaryConnection rather than floating free. Every two-ended
    // `connection def` implicitly specializes it anyway; saying so explicitly
    // is what lets MEMO relations be read as ordinary SysML connections by any
    // conforming tool instead of as a MEMO-private construct.
    //
    // A relation is a MEMO element like any other, so it carries the same
    // identification core as the part/action/item/requirement bases in
    // memo_core_common — with four exceptions, R10-S5 (2026-08-13). `name`,
    // `description`, `rationale` and `status` were declared here too, and a
    // tree measurement found them dead weight: across every connection usage
    // in src/ and examples/ (876 of them, 77 with a body at all), exactly one
    // ever set `rationale` and none ever set `name`, `description` or
    // `status`. The former `linkStatus` (planned/active/verified/obsolete) is
    // already gone for the same reason: a link being "verified" was never an
    // editorial state.
    //
    // The replacement is native, not a MEMO-authored substitute:
    //   - `name`        → the connection usage's own declared name
    //     (`connection linkFoo : Bar …`), which every usage already has.
    //   - `description` → `doc /* … */` on the usage.
    //   - `rationale`   → standard `Rationale` metadata: `@Rationale { :>> text
    //     = "…"; }` (ModelingMetadata.sysml:95). `text` is exported into
    //     `rel.attributes.rationale` by the builder, same key as before.
    //   - `status`      → standard `StatusInfo` metadata: `@StatusInfo { :>>
    //     status = StatusKind::…; }` (ModelingMetadata.sysml:60). StatusKind
    //     (open/tbd/tbr/tbc/done/closed) is NOT ElementStatusKind
    //     (proposed/draft/inReview/approved/released/deprecated/retired) — the
    //     mapping between them, and why no MEMO-side conversion code exists, is
    //     recorded in docs/reference/naming-and-native-constructs.md. Exported
    //     into `rel.attributes.status`.
    // Both metadata defs live in the standard `ModelingMetadata` package;
    // `private import ModelingMetadata::*;` wherever they are applied.
    //
    // isReflexive/isUnique are structural properties of the relation itself,
    // declared here so authoring and validation read them from the ontology
    // instead of assuming them. Both are unset on the base and carry the
    // conservative reading: a relation forbids self-links and forbids repeats
    // unless it says otherwise. A subtype opts out by redefining, e.g.
    // `attribute :>> isReflexive = true;`.
    abstract connection def MemoRelationship :> Connections::BinaryConnection {
        attribute id : String;
        attribute uuid : String;
        attribute shortDescription : String;
        attribute sourceReference : String;
        doc /* True when an element may be related to itself by this relation.
             * Unset is read as false. */
        attribute isReflexive : Boolean;
        doc /* True when at most one link of this type may join the same ordered
             * pair of elements — KerML Feature::isUnique over the relation.
             * Unset is read as true. */
        attribute isUnique : Boolean;
        doc /* True when this relation is a connector between two parts, the kind of link that makes a part
             * count as wired in an internal block diagram (rule AR-IBD-001). Trace, allocation, deployment and
             * satisfaction links are not. Unset is read as false. Interface and flow usages are connectors by
             * their language construct and need no value. */
        attribute isConnector : Boolean;
    }

    // ─── Typed dependencies ─────────────────────────────────────────────
    //
    // A link whose ends are not both usages cannot be a `connection def`: a
    // connection joins features, and a `ref` cannot point at a definition. SysML
    // already has the construct for a client and a supplier that are any element,
    // the Dependency (SysML-textual-bnf.kebnf:51-59), and a metadata prefix
    // names what kind of dependency it is (`#RealizesFeature dependency from a to
    // b;`, PrefixMetadataAnnotation, kebnf:52). A `metadata def` that specializes
    // this marker declares such a link as a MEMO relation: it joins the
    // relationship registry under camelCase(name), is navigated like any other
    // relation, and needs a row in the workspace-membership table. A metadata
    // def that does not specialize it (`EnforcesClause`) is plain metadata on a
    // dependency and builds no relation. Source is the client, target the
    // supplier. Ends are untyped: what a relation may join is a rule's to say
    // (see the note above on metaclass-neutral ends).
    abstract metadata def MemoTypedDependency;

    // ─── Metaclass-neutral ends (Track A0) ──────────────────────────────
    //
    // An end is left UNTYPED (`:>> source` / `:>> target`) wherever its
    // legitimate endpoints do not share a MEMO base, and a rule in
    // memo_rules_ontology states the constraint the type used to state.
    //
    // The reason is structural, not stylistic. KerML will not let a port or a
    // behaviour specialize a part-based type, so a `MemoPart`-typed end forces
    // everything it accepts to be a part. That is what made PhysicalPort and
    // SoftwarePort part defs (so they could terminate exchanges), what made
    // SystemFunction a part def with its behaviour stapled on through a
    // separate action def, and what makes `allocate <function> to <actor>` —
    // ARCADIA's own System Analysis mechanism — illegal, since Actor is a
    // MemoPart but not a narrower part subtype.
    //
    // Several of the relaxed ends were ALREADY being violated by real content
    // before they were relaxed: `composes` links parts to OperativeAction
    // (an action def) and to SoftwarePort/PhysicalPort;
    // `precedes` links OperativeAction to OperativeAction; `allocatedTo`
    // has ActionUsage sources; `bindsToInterface` targets an `interface def`,
    // which an InterfaceElement-typed end cannot hold. The types were not
    // buying the strictness they appeared to buy.
    //
    // What is NOT relaxed stays typed on purpose: `verificationCase` and
    // `validationCase` are verification defs, `performed` and `enabled` are
    // MemoActions, `targetRequirement` is a MemoRequirementElement. Those ends
    // name one metaclass and mean it.
    //
    // The strictness did not evaporate — see CR-ONT-060..CR-ONT-071 in
    // src/rules/ontology/ontology_invariants.sysml. Relaxing the ends without
    // those rules would have been a silent loss of every constraint the ends
    // were carrying.
    //
    // The general relation that can join any two model elements, whatever
    // their metaclass. MemoLink leaves both ends untyped and adds no
    // domain-specific semantics, which is what makes it universal.
    //
    // It is deliberately the weakest relation in the ontology. Reach for it
    // only when no specific relation carries the meaning, and say why in the
    // inherited `rationale` — an untyped link with no stated reason is an
    // audit gap, not a model fact.

    // An item belongs to the scope of one system or system of systems: a need,
    // requirement, risk or verification case that describes, constrains or
    // assesses that system and is its to deliver or verify. Imported records
    // arrive with no design element to anchor them (a requirement is not
    // allocated to anything yet), so this is how an import says whose they are;
    // without it they are Unassigned in every workspace. The target is the
    // system, typed as a part (a System and a SystemOfSystems both are). The
    // source stays untyped: the items span metaclasses (a need is a requirement
    // def, a risk an item, a verification case an action), as for DerivesFrom.
    connection def ScopedTo :> MemoRelationship {
        end scopedItem :>> source;
        end scopeSystem : MemoPart :>> target;
    }
    abstract connection scopedToLinks : ScopedTo[*];
    metadata def <scopedTo> ScopedToMetadata :> SemanticMetadata {
        :> annotatedElement : SysML::ConnectionDefinition;
        :> annotatedElement : SysML::ConnectionUsage;
        :>> baseType = scopedToLinks meta SysML::Usage;
    }

    connection def DerivesFrom :> MemoRelationship {
        // Drivers span metaclasses — a need is a requirement def, a hazard an
        // item, a threat an item — so the source end stays untyped. The target
        // is now typed: since Requirement re-rooted onto MemoRequirement, one
        // type name covers the whole requirement family.
        end sourceDriver :>> source;
        end targetRequirement : MemoRequirementElement :>> target;
    }
    abstract connection derivesFromLinks : DerivesFrom[*];
    metadata def <derivesFrom> DerivesFromMetadata :> SemanticMetadata {
        :> annotatedElement : SysML::ConnectionDefinition;
        :> annotatedElement : SysML::ConnectionUsage;
        :>> baseType = derivesFromLinks meta SysML::Usage;
    }
    // `Realizes` (realizing/concrete element → realized/abstract element) is
    // native `#refinement dependency` (R10-S6): write
    // `#refinement dependency <realizing> to <realized>;` instead. It used to
    // unify RealizesInterface, RealizesComponentExchange,
    // RealizedByArchitecture, RealizesScenario, ModuleRealizesLogical,
    // ComponentRealizesModule, PhysicalModuleRealizesLogical,
    // Implements{Component,Procedure}, UIRealizesFunctional,
    // FunctionalRealizesOper{ative,ational} and ScenarioRealizesUseCase; the
    // native form keeps that reach, since `#refinement` places no metaclass
    // restriction on either end.
    connection def ProducesEvidence :> MemoRelationship {
        end producer : MemoVerificationCase :>> source;
        end producedEvidence : MemoEvidence :>> target;
    }
    abstract connection producesEvidenceLinks : ProducesEvidence[*];
    metadata def <producesEvidence> ProducesEvidenceMetadata :> SemanticMetadata {
        :> annotatedElement : SysML::ConnectionDefinition;
        :> annotatedElement : SysML::ConnectionUsage;
        :>> baseType = producesEvidenceLinks meta SysML::Usage;
    }
    // `Precedes` is native `succession` (`first a then b;`), R10-S6.
    // `sameStepRequired`/`precedenceRationale` had zero usages anywhere in
    // the tree (same free-deletion shape R10-S5 found for `rationale`), so
    // there was no content to carry forward.

    connection def DerivesCyberRequirement :> MemoRelationship {
        end sourceThreatOrRisk : RequirementDriver :>> source;
        end targetRequirement : MemoRequirementElement :>> target;
    }
    abstract connection derivesCyberRequirementLinks : DerivesCyberRequirement[*];
    metadata def <derivesCyberRequirement> DerivesCyberRequirementMetadata :> SemanticMetadata {
        :> annotatedElement : SysML::ConnectionDefinition;
        :> annotatedElement : SysML::ConnectionUsage;
        :>> baseType = derivesCyberRequirementLinks meta SysML::Usage;
    }
    connection def CrossesTrustBoundary :> MemoRelationship {
        attribute crossingKind : InterfaceKind;
        end boundary :>> source;
        end crossingItem :>> target;
    }
    abstract connection crossesTrustBoundaryLinks : CrossesTrustBoundary[*];
    metadata def <crossesTrustBoundary> CrossesTrustBoundaryMetadata :> SemanticMetadata {
        :> annotatedElement : SysML::ConnectionDefinition;
        :> annotatedElement : SysML::ConnectionUsage;
        :>> baseType = crossesTrustBoundaryLinks meta SysML::Usage;
    }

    connection def Validates :> MemoRelationship {
        // Validation targets include use cases and other behavioural elements,
        // so the target remains untyped across SysML metaclass families.
        end validationTarget :>> source;
        end validationCase : MemoVerificationCase :>> target;
    }
    abstract connection validatesLinks : Validates[*];
    metadata def <validates> ValidatesMetadata :> SemanticMetadata {
        :> annotatedElement : SysML::ConnectionDefinition;
        :> annotatedElement : SysML::ConnectionUsage;
        :>> baseType = validatesLinks meta SysML::Usage;
    }

    // Enables unifies the former EnablesWorkflow / EnablesActivity synonyms
    // (an enabling system/function enables a workflow/activity).
    // `Enables` is native `dependency` (2026-08-18): write
    // `dependency from <enabling> to <enabled>;`. Same call as `Supports`,
    // which was deleted as a duplicate of both `dependency` and `Enables`.

        // A processing node hosted by an assembly is allocated to it. The end
    // NAMES were already right; two of the three usages wrote them in reverse
    // order, and the builder binds by position, so those two edges pointed the
    // wrong way. See the reversed-end-name lint in memo-tools.
    allocation def HostedBy :> MemoRelationship, Allocations::Allocation {
        end processingNode : MemoPart :>> source;
        end hostAssembly : MemoPart :>> target;
    }
    abstract connection hostedByLinks : HostedBy[*];
    metadata def <hostedBy> HostedByMetadata :> SemanticMetadata {
        :> annotatedElement : SysML::AllocationDefinition;
        :> annotatedElement : SysML::AllocationUsage;
        :>> baseType = hostedByLinks meta SysML::Usage;
    }




    // `Composes` is deleted (R10-S7). Containment is NESTING — the child is
    // declared inside the parent — which is how SysML v2 models composition:
    // composite feature ownership, not a link. The relation specialized
    // `Connections::BinaryConnection`, "a link between two things WITHIN some
    // containing structure", so it was the wrong category for the containment
    // itself, and the corpus has no composition connection to specialize.
    //
    // Nothing is lost: the builder synthesizes a `composes` edge from every
    // nested part and item, so rules, the DSM and traceability read exactly the
    // graph they read before. The edge type is registered natively in
    // memo-tools' relationship registry.


    connection def BindsToInterface :> MemoRelationship {
        end portElement :>> source;
        end boundInterface :>> target;
    }
    abstract connection bindsToInterfaceLinks : BindsToInterface[*];
    metadata def <bindsToInterface> BindsToInterfaceMetadata :> SemanticMetadata {
        :> annotatedElement : SysML::ConnectionDefinition;
        :> annotatedElement : SysML::ConnectionUsage;
        :>> baseType = bindsToInterfaceLinks meta SysML::Usage;
    }
}