@memoarchitect/ontology 0.11.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/README.md +1 -1
  2. package/examples/gpca-pump/model/catalog/gpca_system.sysml +3 -3
  3. package/extensions/aadl/memo.package.yaml +1 -1
  4. package/extensions/cloud/memo.package.yaml +1 -1
  5. package/extensions/container/memo.package.yaml +1 -1
  6. package/extensions/messaging/memo.package.yaml +1 -1
  7. package/extensions/ros/memo.package.yaml +1 -1
  8. package/methodologies/default/memo.package.yaml +1 -1
  9. package/methodologies/gpca/memo.package.yaml +1 -1
  10. package/ontology/memo.package.yaml +1 -1
  11. package/package.json +1 -1
  12. package/profile/memo.package.yaml +1 -1
  13. package/src/architecture/functional/behavior/memo_behavior.sysml +8 -1
  14. package/src/architecture/functional/functions/memo_functions.sysml +16 -2
  15. package/src/architecture/implementation/ui/memo_ui.sysml +46 -20
  16. package/src/assurance/cybersecurity/memo_cybersecurity.sysml +5 -0
  17. package/src/assurance/safety_risk/memo_risk.sysml +19 -16
  18. package/src/assurance/verification_validation/memo_assurance.sysml +18 -0
  19. package/src/core/enumerations/memo_enumerations.sysml +49 -13
  20. package/src/memo_namespaces.sysml +2 -0
  21. package/src/viewpoints/clinical/clinical_viewpoint.sysml +3 -4
  22. package/src/viewpoints/context/context_viewpoint.sysml +3 -5
  23. package/src/viewpoints/cybersecurity/cybersecurity_viewpoint.sysml +3 -5
  24. package/src/viewpoints/definitions/memo_stakeholders_concerns.sysml +192 -0
  25. package/src/viewpoints/definitions/memo_viewpoint_definitions.sysml +94 -6
  26. package/src/viewpoints/functional/functional_viewpoint.sysml +3 -4
  27. package/src/viewpoints/logical/logical_viewpoint.sysml +3 -4
  28. package/src/viewpoints/operational/operational_viewpoint.sysml +3 -4
  29. package/src/viewpoints/physical/physical_viewpoint.sysml +3 -4
  30. package/src/viewpoints/requirements/requirements_viewpoint.sysml +3 -4
  31. package/src/viewpoints/risk/risk_viewpoint.sysml +3 -4
  32. package/src/viewpoints/software/software_viewpoint.sysml +3 -4
  33. package/src/viewpoints/ui_layout/ui_layout_viewpoint.sysml +3 -5
  34. package/src/viewpoints/usability/usability_viewpoint.sysml +3 -4
  35. package/src/viewpoints/verification/verification_viewpoint.sysml +3 -4
package/README.md CHANGED
@@ -23,7 +23,7 @@ pin an exact release; the package has no repository or runtime dependency on Mem
23
23
  Tools or Memo Architect.
24
24
 
25
25
  ```bash
26
- pnpm add @memoarchitect/ontology@0.11.0
26
+ pnpm add @memoarchitect/ontology@0.12.0
27
27
  ```
28
28
 
29
29
  > **Pre-1.0 notice:** ontology names, relationships, and package layout may
@@ -15,7 +15,7 @@ package memo_examples_gpca_pump_gpca_system {
15
15
  // retired: "mission" duplicated the regulated intended-use statement.
16
16
 
17
17
  // ── Functional chains ───────────────────────────────────────
18
- part fcPatientBolus : FunctionalFlow {
18
+ action fcPatientBolus : FunctionalFlow {
19
19
  @MemoIdentity { :>> providedId = "FC-001"; }
20
20
  attribute :>> name = "PatientBolusChain";
21
21
  attribute :>> flowCategory = FunctionalFlowKind::nominal;
@@ -54,7 +54,7 @@ package memo_examples_gpca_pump_gpca_system {
54
54
  first fcsBolusCommand then fcsBolusActuate;
55
55
  first fcsBolusActuate then fcsBolusLog;
56
56
 
57
- part fcAlarmStop : FunctionalFlow {
57
+ action fcAlarmStop : FunctionalFlow {
58
58
  @MemoIdentity { :>> providedId = "FC-002"; }
59
59
  attribute :>> name = "AlarmDetectionToSafeStateChain";
60
60
  attribute :>> flowCategory = FunctionalFlowKind::alarm;
@@ -87,7 +87,7 @@ package memo_examples_gpca_pump_gpca_system {
87
87
  first fcsAlarmEvaluate then fcsAlarmStopInfusion;
88
88
  first fcsAlarmStopInfusion then fcsAlarmAnnunciate;
89
89
 
90
- part fcStartup : FunctionalFlow {
90
+ action fcStartup : FunctionalFlow {
91
91
  @MemoIdentity { :>> providedId = "FC-003"; }
92
92
  attribute :>> name = "PowerOnSelfTestChain";
93
93
  attribute :>> flowCategory = FunctionalFlowKind::startup;
@@ -7,7 +7,7 @@
7
7
  # (`type`, `extends`, `usage`, `ontologies`, `methodology`, `modules`) were
8
8
  # removed at the native semantic flip and are now rejected if present.
9
9
  name: '@memoarchitect/extension-aadl'
10
- version: 0.11.0
10
+ version: 0.12.0
11
11
  description: AADL (SAE AS5506) correspondence profile and runtime component families
12
12
  license: MIT
13
13
  tags:
@@ -7,7 +7,7 @@
7
7
  # (`type`, `extends`, `usage`, `ontologies`, `methodology`, `modules`) were
8
8
  # removed at the native semantic flip and are now rejected if present.
9
9
  name: '@memoarchitect/extension-cloud'
10
- version: 0.11.0
10
+ version: 0.12.0
11
11
  description: Networked services and managed data stores
12
12
  license: MIT
13
13
  tags:
@@ -7,7 +7,7 @@
7
7
  # (`type`, `extends`, `usage`, `ontologies`, `methodology`, `modules`) were
8
8
  # removed at the native semantic flip and are now rejected if present.
9
9
  name: '@memoarchitect/extension-container'
10
- version: 0.11.0
10
+ version: 0.12.0
11
11
  description: OCI container images and container runtimes as deployment content
12
12
  license: MIT
13
13
  tags:
@@ -7,7 +7,7 @@
7
7
  # (`type`, `extends`, `usage`, `ontologies`, `methodology`, `modules`) were
8
8
  # removed at the native semantic flip and are now rejected if present.
9
9
  name: '@memoarchitect/extension-messaging'
10
- version: 0.11.0
10
+ version: 0.12.0
11
11
  description: Publish/subscribe messaging — topics, brokers, and delivery semantics
12
12
  license: MIT
13
13
  tags:
@@ -7,7 +7,7 @@
7
7
  # (`type`, `extends`, `usage`, `ontologies`, `methodology`, `modules`) were
8
8
  # removed at the native semantic flip and are now rejected if present.
9
9
  name: '@memoarchitect/extension-ros'
10
- version: 0.11.0
10
+ version: 0.12.0
11
11
  description: ROS 2 nodes, messages, topic/service/action interfaces, QoS, and containerized deployment
12
12
  license: MIT
13
13
  tags:
@@ -7,7 +7,7 @@
7
7
  # (`type`, `extends`, `usage`, `ontologies`, `methodology`, `modules`) were
8
8
  # removed at the native semantic flip and are now rejected if present.
9
9
  name: '@memoarchitect/methodology-default'
10
- version: 0.11.0
10
+ version: 0.12.0
11
11
  description: "MEMO default medical-device methodology \u2014 selects viewpoints/views/DHF documents from @memoarchitect/ontology and adds rules, gates, patterns, profiles, and workflow."
12
12
  license: MIT
13
13
  tags:
@@ -7,7 +7,7 @@
7
7
  # (`type`, `extends`, `usage`, `ontologies`, `methodology`, `modules`) were
8
8
  # removed at the native semantic flip and are now rejected if present.
9
9
  name: '@memoarchitect/methodology-gpca'
10
- version: 0.11.0
10
+ version: 0.12.0
11
11
  description: "GPCA infusion pump methodology \u2014 subtraction-based tailoring of @memoarchitect/methodology-default for the non-networked prototype variant. Excludes cybersecurity and SOUP."
12
12
  license: MIT
13
13
  tags:
@@ -7,7 +7,7 @@
7
7
  # (`type`, `extends`, `usage`, `ontologies`, `methodology`, `modules`) were
8
8
  # removed at the native semantic flip and are now rejected if present.
9
9
  name: '@memoarchitect/ontology'
10
- version: 0.11.0
10
+ version: 0.12.0
11
11
  description: "MEMO \u2014 the single canonical medical-device ontology: core semantics, the Arcadia-inspired architecture layers (context, requirements, behavior, structure, interfaces, risk, cybersecurity,\
12
12
  \ assurance, \u2026), compliance, viewpoints, views, and invariant rules. One namespace (memo::), one src/ tree."
13
13
  license: MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memoarchitect/ontology",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "packageManager": "pnpm@9.15.0",
5
5
  "description": "MEMO — Medical Engineering Modelling Ontology. Pure SysML v2 medical-device ontology with native constraints, portable to any conformant SysML v2 tool (SysIDE, SysON, sysand).",
6
6
  "scripts": {
@@ -7,7 +7,7 @@
7
7
  # (`type`, `extends`, `usage`, `ontologies`, `methodology`, `modules`) were
8
8
  # removed at the native semantic flip and are now rejected if present.
9
9
  name: '@memoarchitect/medical-modeling-profile'
10
- version: 0.11.0
10
+ version: 0.12.0
11
11
  description: Closure rules and viewpoints for medical device modeling
12
12
  license: MIT
13
13
  tags:
@@ -88,7 +88,14 @@ package memo_architecture_functional_behavior {
88
88
  attribute constraintKind : TimingConstraintKind;
89
89
  attribute minMs : String;
90
90
  attribute maxMs : String;
91
- ref referenceElement : MemoPart[1];
91
+ // Untyped, the way `InteractsInContext::systemOfInterest` is: what a
92
+ // latency or period is measured against is a behaviour at least as
93
+ // often as it is a structure — a functional flow, an action, a port.
94
+ // `MemoPart[1]` said otherwise and could only ever have held the
95
+ // structural half, which is the same A0 residue that kept
96
+ // `FunctionalFlow` a part def. MEMO has no root above the metaclasses
97
+ // by design, so spanning them means naming none.
98
+ ref referenceElement[1];
92
99
  attribute verificationMethod : MemoVerificationMethodKind;
93
100
  }
94
101
  }
@@ -17,7 +17,9 @@
17
17
  // ZERO example files. The ends are metaclass-neutral now (CR-ONT-060..073), so
18
18
  // the split has no cause and is gone: OperativeAction is merged into the function
19
19
  // family, and its `actionKind` moved onto MemoFunction where it was always
20
- // describing the function anyway.
20
+ // describing the function anyway. `FunctionalFlow` was the one element A0 left
21
+ // behind on the part side; it is an `action def` now, for the same reason and
22
+ // on the same evidence.
21
23
  //
22
24
  // `functionCategory` and `actionKind` are NOT two spellings of one axis, and
23
25
  // merging them would lose information. `actionKind` is the verb — sense,
@@ -112,7 +114,19 @@ package memo_architecture_functional_functions {
112
114
 
113
115
  // A reusable functional route through system responsibilities. Functional
114
116
  // flows are part of functional architecture, never logical structure.
115
- part def FunctionalFlow specializes MemoPart {
117
+ //
118
+ // An `action def`, like every other behaviour in MEMO. It was
119
+ // `part def ... specializes MemoPart` for the Track A0 reason described at
120
+ // the top of this file — relation ends typed on part-based types, and
121
+ // KerML forbids a behaviour from specializing one — and it was the single
122
+ // element A0 did not carry across when that reason went away. A route
123
+ // through responsibilities is the same shape as the `OperationalWorkflow`
124
+ // and `OperativeScenario` it sits beside: the scenarios package calls a
125
+ // scenario "a selected path through a workflow (or functional flow)",
126
+ // naming the two as one kind of thing, and its steps are `action def`s
127
+ // already. A structure whose whole body is `perform` is a behaviour that
128
+ // has not been allowed to say so.
129
+ action def FunctionalFlow specializes MemoAction {
116
130
  attribute flowCategory : FunctionalFlowKind;
117
131
  attribute endToEndLatencyBudgetMs : String;
118
132
  attribute safetyRelevant : Boolean;
@@ -115,21 +115,15 @@ package memo_architecture_implementation_ui {
115
115
  attribute uiTechnology : String;
116
116
  }
117
117
 
118
- // What a rendered control and a physical one genuinely share: a label, an
119
- // accessibility story, and — when they annunciate — an alarm character.
120
- // The base exists so that the §18 traceability relations can type against
121
- // "something the user interacts with" rather than against software
122
- // specifically. Without it a use error on a knob would be unmodellable,
123
- // because ErrorAtElement would only accept a UIElement.
124
- abstract part def InteractionElement specializes MemoPart {
125
- attribute labelText : String;
126
- attribute accessibilitySummary : String;
127
- // alarm annunciation (optional; IEC 60601-1-8)
128
- attribute alarmPriority : NotificationPriorityKind[0..1];
129
- attribute annunciationModality : String;
130
- attribute silenceable : Boolean;
131
- }
132
-
118
+ // `InteractionElement` was an abstract base over UIElement and
119
+ // OperatorInterfaceElement, existing so the §18 relations could type
120
+ // against "something the user interacts with". It was both redundant and
121
+ // too narrow: the nearest real common ancestor is already `MemoPart`, and
122
+ // IEC 62366-1 puts the whole means of interaction in scope — a mis-keyed
123
+ // connector, a moulded marking on a housing, a tube routed backwards are
124
+ // use errors at parts that were never interaction elements and so could
125
+ // not be named. `ErrorAtElement` and `ElementTriggersAction` now take
126
+ // `MemoPart`; the attributes moved to whichever type actually set them.
133
127
 
134
128
  // One UIElement — the single UI part type. The widget form — holding
135
129
  // (screen/panel/dialog), acting (button/knob/slider), presenting
@@ -153,8 +147,20 @@ package memo_architecture_implementation_ui {
153
147
  // CODE, and a screen is not a source module. Runtime processes are
154
148
  // SoftwareComponent, code is SoftwareModule, and the UI is a third view of
155
149
  // the same software — a sibling of those, not a kind of either.
156
- part def UIElement specializes SoftwareElement, InteractionElement {
150
+ part def UIElement specializes SoftwareElement {
157
151
  attribute formKind : UIElementFormKind;
152
+ // The visible label. Held here rather than on a shared interaction
153
+ // base: a physical control's label is moulded or printed, and is
154
+ // `legendText` on OperatorInterfaceElement.
155
+ attribute labelText : String;
156
+ // ── alarm annunciation (optional; IEC 60601-1-8) ──
157
+ // On the rendered element, because that is where every modelled
158
+ // annunciation lives. A physical annunciator that needs a priority
159
+ // wants an alarm concept of its own, not three attributes copied onto
160
+ // every front-panel part.
161
+ attribute alarmPriority : NotificationPriorityKind[0..1];
162
+ attribute annunciationModality : String;
163
+ attribute silenceable : Boolean;
158
164
  // ── screen layout (optional; set for elements that are laid out) ──
159
165
  // Bounds are relative to the parent element in the Composes tree; a
160
166
  // root screen's bounds are the full frame.
@@ -222,7 +228,7 @@ package memo_architecture_implementation_ui {
222
228
  enum printedMarking;
223
229
  }
224
230
 
225
- part def OperatorInterfaceElement specializes PhysicalComponent, InteractionElement {
231
+ part def OperatorInterfaceElement specializes PhysicalComponent {
226
232
  attribute formKind : OperatorInterfaceFormKind;
227
233
  // actuation (optional; set for actuated forms)
228
234
  attribute actuationForce : String;
@@ -267,7 +273,17 @@ package memo_architecture_implementation_ui {
267
273
  attribute intent : InteractionIntentKind;
268
274
  }
269
275
 
270
- action def UIAction specializes MemoAction {
276
+ // Clicking a button IS an operative action: it has a trigger, a
277
+ // precondition, a criticality, a potential harm and a frequency of use,
278
+ // exactly as turning a knob does. Specializing MemoAction directly made
279
+ // UIAction a SIBLING of OperativeAction, which cost two things — a UI
280
+ // action could carry none of those ten attributes, and `CommitsUseError`
281
+ // (source end: OperativeAction) would not accept it, so a use error
282
+ // committed by a click was unmodellable.
283
+ //
284
+ // The three attributes here are what a UI action adds on top: what the
285
+ // user meant by it, what came back, and whether it asks first.
286
+ action def UIAction specializes OperativeAction {
271
287
  attribute intent : InteractionIntentKind;
272
288
  attribute feedbackProvided : String;
273
289
  attribute confirmationRequired : Boolean;
@@ -310,8 +326,13 @@ package memo_architecture_implementation_ui {
310
326
  // from here, and only this relation says so.
311
327
 
312
328
  // ── §18 traceability ─────────────────────────────────────────
329
+ // Source is `MemoPart`, not a UI-specific base: a foot pedal and a
330
+ // rendered button trigger the same kind of action, and the two are a
331
+ // PhysicalComponent and a SoftwareElement whose only common ancestor is
332
+ // MemoPart. CR-MED-111 still holds rendered controls to it, and it is
333
+ // scoped to UIElement, so the wider end does not weaken the rule.
313
334
  connection def ElementTriggersAction :> MemoRelationship {
314
- end element : InteractionElement :>> source;
335
+ end element : MemoPart :>> source;
315
336
  end triggeredAction : UIAction :>> target;
316
337
  }
317
338
  abstract connection elementTriggersActionLinks : ElementTriggersAction[*];
@@ -334,9 +355,14 @@ package memo_architecture_implementation_ui {
334
355
  }
335
356
  // A UI scenario realizes a functional scenario one layer up: each is a
336
357
  // OperativeScenario selected by scenarioKind rather than a separate definition.
358
+ // Target is `MemoPart`. IEC 62366-1 scopes the user interface to every
359
+ // means of interaction, so a use error lands wherever the user got it
360
+ // wrong — a mis-keyed connector, a moulded marking, a tube routed
361
+ // backwards — not only on a control. Narrowing this to an interaction
362
+ // base made those unmodellable.
337
363
  connection def ErrorAtElement :> MemoRelationship {
338
364
  end useError : UseError :>> source;
339
- end element : InteractionElement :>> target;
365
+ end element : MemoPart :>> target;
340
366
  }
341
367
  abstract connection errorAtElementLinks : ErrorAtElement[*];
342
368
  metadata def <errorAtElement> ErrorAtElementMetadata :> SemanticMetadata {
@@ -46,6 +46,11 @@ package memo_assurance_cybersecurity {
46
46
  attribute affectedLayer : String;
47
47
  attribute cweReference : String;
48
48
  attribute remediable : Boolean;
49
+ // CVSS v3.1 quantitative rating — the core output of a vulnerability
50
+ // analysis (e.g. RSK-00058). `cvssBaseScore` is the 0.0-10.0 numeric
51
+ // score; `cvssVector` the source vector string (AV:.../AC:.../...).
52
+ attribute cvssBaseScore : Real;
53
+ attribute cvssVector : String;
49
54
  }
50
55
 
51
56
  item def CyberHazard specializes Hazard {
@@ -39,22 +39,10 @@ package memo_assurance_safety_risk {
39
39
  attribute riskLevelMapping : String;
40
40
  attribute acceptabilityThresholds : String;
41
41
  }
42
- part def DesignControlRiskRow specializes Risk {
43
- attribute rowTitle : String;
44
- attribute hazardAnalysis : String;
45
- attribute hazardCategory : String;
46
- attribute hazardSubcategory : String;
47
- attribute causeSequenceOfEventsFailure : String;
48
- attribute harmText : String;
49
- attribute probabilityBeforeRaw : String;
50
- attribute severityBeforeRaw : String;
51
- attribute riskBeforeMeasureRaw : String;
52
- attribute probabilityAfterRaw : String;
53
- attribute severityAfterRaw : String;
54
- attribute riskAfterMitigationRaw : String;
55
- attribute cannotReduceFurther : Boolean;
56
- attribute linkSummary : String;
57
- }
42
+ // `DesignControlRiskRow` was a denormalized spreadsheet transcription.
43
+ // Risk rows now decompose into the ISO 14971 chain below: Risk owns its
44
+ // Hazard, SequenceOfEvents, HazardousSituation, and Harm items, linked by
45
+ // TracesRisk / LeadsToHarm, with ResidualRisk after mitigation.
58
46
  // A device characteristic whose implementation, failure, or misuse can
59
47
  // affect safety. This is the modelable output of ISO 14971 §5.3.
60
48
  part def SafetyRelatedCharacteristic specializes MemoPart {
@@ -102,6 +90,8 @@ package memo_assurance_safety_risk {
102
90
  item def HazardousSituation specializes RiskItem {
103
91
  attribute exposedPersons : String;
104
92
  attribute operatingCondition : String;
93
+ // ISO 14971 P1: probability that the hazardous situation occurs.
94
+ attribute probabilityOfOccurrence : ProbabilityKind;
105
95
  }
106
96
  item def Harm specializes RiskItem {
107
97
  attribute clinicalImpact : String;
@@ -138,6 +128,19 @@ package memo_assurance_safety_risk {
138
128
  :> annotatedElement : SysML::ConnectionUsage;
139
129
  :>> baseType = tracesRiskLinks meta SysML::Usage;
140
130
  }
131
+ // The final ISO 14971 chain edge. P2 is the conditional probability that
132
+ // the hazardous situation results in the harm.
133
+ connection def LeadsToHarm :> MemoRelationship {
134
+ attribute conditionalProbability : ProbabilityKind;
135
+ end hazardousSituation : HazardousSituation :>> source;
136
+ end resultingHarm : Harm :>> target;
137
+ }
138
+ abstract connection leadsToHarmLinks : LeadsToHarm[*];
139
+ metadata def <leadsToHarm> LeadsToHarmMetadata :> SemanticMetadata {
140
+ :> annotatedElement : SysML::ConnectionDefinition;
141
+ :> annotatedElement : SysML::ConnectionUsage;
142
+ :>> baseType = leadsToHarmLinks meta SysML::Usage;
143
+ }
141
144
  // IEC 62366-1 3.9's hazard-related use scenario: the scenario a hazard can
142
145
  // arise in. It is declared HERE rather than as a `hazardReference` string
143
146
  // on the scenario, which is what stood in for it: a string names nothing a
@@ -21,10 +21,28 @@ package memo_assurance_verification_validation {
21
21
  // a second spelling of `status`.
22
22
  // Specializes the standard library verification case as well as MEMO's
23
23
  // base, rather than shadowing it — see the note on UseCase.
24
+ // Reusable test action, distinct from a case's pass/fail criteria.
25
+ action def TestStep specializes MemoAction {
26
+ attribute stepAction : String;
27
+ attribute expectedResult : String;
28
+ attribute referencedItem : String;
29
+ }
24
30
  verification def VerificationCase :> MemoVerificationCase, VerificationCases::VerificationCase {
25
31
  attribute methodKind : MemoVerificationMethodKind;
26
32
  attribute acceptanceCriteria : String;
27
33
  }
34
+ // Orders a reusable TestStep within a verification or validation case.
35
+ connection def PerformsStep :> MemoRelationship {
36
+ attribute sequence : Integer;
37
+ end verificationCase : MemoVerificationCase :>> source;
38
+ end testStep : TestStep :>> target;
39
+ }
40
+ abstract connection performsStepLinks : PerformsStep[*];
41
+ metadata def <performsStep> PerformsStepMetadata :> SemanticMetadata {
42
+ :> annotatedElement : SysML::ConnectionDefinition;
43
+ :> annotatedElement : SysML::ConnectionUsage;
44
+ :>> baseType = performsStepLinks meta SysML::Usage;
45
+ }
28
46
  verification def ValidationCase :> MemoVerificationCase {
29
47
  attribute validationMethod : ValidationMethodKind;
30
48
  attribute userParticipation : String;
@@ -1,6 +1,35 @@
1
1
  package memo_core_enumerations {
2
2
  private import ScalarValues::*;
3
3
 
4
+ // Where a legend gets the value it colours by, when that value is not
5
+ // stored on the element at all but derived from the model.
6
+ enum def LegendSourceKind {
7
+ // Depth in the view's own composition hierarchy: the root is 0, its
8
+ // parts 1, theirs 2. This is what "L0 / L1 / L2" actually means, and
9
+ // the tree already computes it — reading it back out of an id string
10
+ // would make a naming convention load-bearing and break the moment
11
+ // something is renamed or re-parented.
12
+ enum hierarchyDepth;
13
+ // The element's ontology kind, which is a field rather than an
14
+ // attribute — and on a block definition diagram it is usually the only
15
+ // thing worth colouring by, since definitions carry few attributes.
16
+ enum elementKind;
17
+ }
18
+
19
+ // What a legend colours. The values are SysML's own usage keywords, so a
20
+ // renderer matches an element's construct directly rather than translating
21
+ // a private vocabulary into one.
22
+ enum def LegendScopeKind {
23
+ // Plural, because `part`, `item`, `port`, `action` and `connection` are
24
+ // SysML keywords and cannot name an enum literal. The renderer maps
25
+ // each to the construct it scopes.
26
+ enum parts;
27
+ enum items;
28
+ enum ports;
29
+ enum actions;
30
+ enum connections;
31
+ }
32
+
4
33
  enum def ConcernKind {
5
34
  enum safety;
6
35
  enum usability;
@@ -228,6 +257,26 @@ package memo_core_enumerations {
228
257
  }
229
258
  // The eight standard SysML v2 view kinds (spec taxonomy). Every
230
259
  // diagram view resolves to exactly one of these (Epic KK).
260
+ // How much of an interconnection drawing's port and connector detail is
261
+ // shown. Declared on the view, because how much detail a drawing carries
262
+ // is part of what the drawing IS — a summary IBD and a fully expanded one
263
+ // answer different questions about the same elements.
264
+ // `everything` and `hidden`, not `all` and `none`: both of those are SysML
265
+ // keywords and a literal cannot be named one — the same reason
266
+ // LegendScopeKind is plural. The renderer maps each to the display mode it
267
+ // names.
268
+ enum def PortDisplayKind {
269
+ enum everything;
270
+ enum ports;
271
+ enum hidden;
272
+ }
273
+
274
+ enum def ConnectionDisplayKind {
275
+ enum summary;
276
+ enum everything;
277
+ enum hidden;
278
+ }
279
+
231
280
  enum def DiagramViewKind {
232
281
  enum general;
233
282
  enum interconnection;
@@ -343,19 +392,6 @@ package memo_core_enumerations {
343
392
  enum evidence;
344
393
  enum documents;
345
394
  }
346
- enum def AudienceKind {
347
- enum systemArchitect;
348
- enum softwareArchitect;
349
- enum hardwareEngineer;
350
- enum safetyEngineer;
351
- enum verificationEngineer;
352
- enum regulatoryEngineer;
353
- enum projectLead;
354
- enum securityEngineer;
355
- enum privacyEngineer;
356
- enum clinicalEngineer;
357
- enum usabilityEngineer;
358
- }
359
395
  enum def ThreatCategoryKind {
360
396
  enum spoofing;
361
397
  enum tampering;
@@ -39,6 +39,7 @@ package memo {
39
39
  public import memo_architecture_decisions::*;
40
40
 
41
41
  public import memo_viewpoints_definitions::*;
42
+ public import memo_viewpoints_stakeholders_concerns::*;
42
43
  public import memo_viewpoints_catalog::*;
43
44
  public import memo_viewpoints_context_context_viewpoint::*;
44
45
  public import memo_viewpoints_context_views_system_context_view::*;
@@ -530,6 +531,7 @@ package memo_namespace_viewpoints_cybersecurity {
530
531
 
531
532
  package memo_namespace_viewpoints_definitions {
532
533
  public import memo_viewpoints_definitions::*;
534
+ public import memo_viewpoints_stakeholders_concerns::*;
533
535
  }
534
536
 
535
537
  package memo_namespace_viewpoints_functional {
@@ -3,6 +3,7 @@ package memo_viewpoints_clinical_clinical_viewpoint {
3
3
 
4
4
  private import memo_viewpoints_definitions::*;
5
5
  private import memo_core_enumerations::*;
6
+ private import memo_viewpoints_stakeholders_concerns::*;
6
7
 
7
8
  private import memo_core_common::*;
8
9
  private import memo_core_common::MemoIdentity;
@@ -12,16 +13,14 @@ package memo_viewpoints_clinical_clinical_viewpoint {
12
13
  @MemoIdentity { :>> shortDescription = "Shows clinical context, users, use environment, and clinical evidence."; }
13
14
  attribute :>> description = "Default viewpoint derived from the context and assurance layers for clinical stakeholders — intended use, patient/clinician interaction, clinical evidence, and clinical safety claims.";
14
15
  attribute :>> purpose = "Communicate clinical use context and clinical evidence for the device.";
15
- attribute :>> audience = (AudienceKind::clinicalEngineer, AudienceKind::regulatoryEngineer);
16
+ ref :>> stakeholders = (ClinicalEngineer, RegulatoryEngineer);
16
17
  attribute :>> stage = WorkflowStageKind::context;
17
18
  attribute :>> abstractionLevel = "clinical";
18
19
  attribute :>> outputKind = (ViewOutputKind::documentSection, ViewOutputKind::table);
19
20
  attribute :>> presentationKind = (PresentationKind::narrativeSection);
20
- attribute :>> concernKinds = (ConcernKind::safety, ConcernKind::clinical);
21
- attribute :>> includedLayers = ("context", "assurance");
21
+ ref :>> framedConcerns = (SafetyConcern, ClinicalConcern);
22
22
  attribute :>> explorerLane = "assurance";
23
23
  attribute :>> explorerOrder = 4;
24
- attribute :>> allowedElementKinds = ("Actor", "UseContext", "MemoEvidence");
25
24
  attribute :>> userExtensible = true;
26
25
  }
27
26
  }
@@ -3,6 +3,7 @@ package memo_viewpoints_context_context_viewpoint {
3
3
 
4
4
  private import memo_viewpoints_definitions::*;
5
5
  private import memo_core_enumerations::*;
6
+ private import memo_viewpoints_stakeholders_concerns::*;
6
7
 
7
8
  private import memo_core_common::*;
8
9
  private import memo_core_common::MemoIdentity;
@@ -12,25 +13,22 @@ package memo_viewpoints_context_context_viewpoint {
12
13
  @MemoIdentity { :>> shortDescription = "Shows actors, use context, and system boundary."; }
13
14
  attribute :>> description = "Default viewpoint derived from the context layer to communicate who interacts with the device, under which use conditions, and where trust or safety boundaries exist.";
14
15
  attribute :>> purpose = "Communicate operational context and boundaries.";
15
- attribute :>> audience = (AudienceKind::systemArchitect);
16
+ ref :>> stakeholders = (SystemArchitect);
16
17
  attribute :>> stage = WorkflowStageKind::context;
17
18
  attribute :>> abstractionLevel = "system";
18
19
  attribute :>> outputKind = (ViewOutputKind::diagram);
19
20
  attribute :>> presentationKind = (PresentationKind::blockDiagram);
20
- attribute :>> concernKinds = (ConcernKind::safety, ConcernKind::interoperability);
21
- attribute :>> includedLayers = ("context");
21
+ ref :>> framedConcerns = (SafetyConcern, InteroperabilityConcern);
22
22
  attribute :>> explorerLane = "architecture";
23
23
  attribute :>> explorerOrder = 0;
24
24
  // UseEnvironment (IEC 62366-1 3.20) is what the device sits inside —
25
25
  // facility, procedure area, ambient conditions. A context view that
26
26
  // cannot show it is missing half of "where is this used".
27
- attribute :>> allowedElementKinds = ("Actor", "UseContext", "UseEnvironment", "IntendedUse", "ReasonablyForeseeableMisuse", "OperationalEntity", "TrustBoundary", "LogicalComponent");
28
27
  // InteractsInContext is the context relation: a context view draws it
29
28
  // and nothing else, so general-purpose model edges cannot leak into the
30
29
  // boundary picture. Projects derive their own verbs from it and are
31
30
  // picked up through the specialization closure. The three older
32
31
  // relations remain for models authored before it existed.
33
- attribute :>> allowedRelationshipKinds = ("InteractsInContext", "connect", "flow", "bind");
34
32
  attribute :>> userExtensible = true;
35
33
  }
36
34
  }
@@ -3,6 +3,7 @@ package memo_viewpoints_cybersecurity_cybersecurity_viewpoint {
3
3
 
4
4
  private import memo_viewpoints_definitions::*;
5
5
  private import memo_core_enumerations::*;
6
+ private import memo_viewpoints_stakeholders_concerns::*;
6
7
 
7
8
  private import memo_core_common::*;
8
9
  private import memo_core_common::MemoIdentity;
@@ -12,17 +13,14 @@ package memo_viewpoints_cybersecurity_cybersecurity_viewpoint {
12
13
  @MemoIdentity { :>> shortDescription = "Shows assets, trust boundaries, threats, vulnerabilities, cyber hazards, cyber risks, and mitigations."; }
13
14
  attribute :>> description = "Default viewpoint derived from the cybersecurity layer, using STRIDE-style threat categories by default while allowing safety and privacy impacts to be traced into the broader model.";
14
15
  attribute :>> purpose = "Communicate cybersecurity design, threat analysis, and cyber risk posture.";
15
- attribute :>> audience = (AudienceKind::securityEngineer);
16
+ ref :>> stakeholders = (SecurityEngineer);
16
17
  attribute :>> stage = WorkflowStageKind::risk;
17
18
  attribute :>> abstractionLevel = "analysis";
18
19
  attribute :>> outputKind = (ViewOutputKind::diagram);
19
20
  attribute :>> presentationKind = (PresentationKind::custom);
20
- attribute :>> concernKinds = (ConcernKind::cybersecurity, ConcernKind::privacy, ConcernKind::safety);
21
- attribute :>> includedLayers = ("cybersecurity", "software_structure", "hardware_structure", "interfaces", "risk", "assurance");
21
+ ref :>> framedConcerns = (CybersecurityConcern, PrivacyConcern, SafetyConcern);
22
22
  attribute :>> explorerLane = "assurance";
23
23
  attribute :>> explorerOrder = 3;
24
- attribute :>> allowedElementKinds = ("CybersecurityAsset", "Threat", "Vulnerability", "CyberHazard", "CyberRisk", "CyberMitigation", "SecurityRequirement", "TrustBoundary", "OperativeScenario[scenarioKind=threat]");
25
- attribute :>> allowedRelationshipKinds = ("ThreatenedBy", "Exploits", "RealizedByScenario", "Mitigates", "DerivesCyberRequirement", "ImpactsSafety", "CrossesTrustBoundary");
26
24
  attribute :>> userExtensible = true;
27
25
  }
28
26
  }
@@ -0,0 +1,192 @@
1
+ // Stakeholders and concerns, as elements.
2
+ //
3
+ // ISO/IEC/IEEE 42010 gives a viewpoint three jobs: name the stakeholders,
4
+ // frame their concerns, and be what a view conforms to. MEMO used to do the
5
+ // first two with enumerations — `AudienceKind` and `ConcernKind` — which meant
6
+ // a stakeholder was a literal from a closed list of eleven and a concern was a
7
+ // literal from nine. You could tag a viewpoint with one; you could not declare
8
+ // a concern, give it an id, say who holds it, trace a requirement to it, or
9
+ // add one without editing the ontology.
10
+ //
11
+ // They are elements now. SysML v2 already models both — `ConcernDefinition`
12
+ // and `StakeholderMembership` are in the metamodel, and MEMO's grammar has
13
+ // carried `concern def`, `concern`, `frame` and `stakeholder` all along — so
14
+ // nothing new is invented here. Each carries `@MemoIdentity`, which is what
15
+ // makes it citable in a review the way every other MEMO element is.
16
+ //
17
+ // The literals they replace are kept verbatim as names, so a project reading
18
+ // `AudienceKind::safetyEngineer` finds `SafetyEngineer` and nothing is lost in
19
+ // the move.
20
+ package memo_viewpoints_stakeholders_concerns {
21
+ private import ScalarValues::*;
22
+ private import memo_core_common::*;
23
+
24
+ // ─── Concerns ────────────────────────────────────────────────────────
25
+ //
26
+ // A concern is an interest in the system held by one or more stakeholders.
27
+ // `concern def` is the native SysML construct for it; a viewpoint frames
28
+ // the concerns it addresses.
29
+ abstract concern def MemoConcern;
30
+
31
+ concern def SafetyConcern :> MemoConcern {
32
+ @MemoIdentity { :>> providedId = "CNC-1"; }
33
+ attribute name = "Safety";
34
+ attribute description = "Freedom from unacceptable risk of harm to the patient, the operator or a bystander.";
35
+ }
36
+ concern def UsabilityConcern :> MemoConcern {
37
+ @MemoIdentity { :>> providedId = "CNC-2"; }
38
+ attribute name = "Usability";
39
+ attribute description = "Whether the intended user can operate the device correctly under use conditions.";
40
+ }
41
+ concern def CybersecurityConcern :> MemoConcern {
42
+ @MemoIdentity { :>> providedId = "CNC-3"; }
43
+ attribute name = "Cybersecurity";
44
+ attribute description = "Resistance to compromise of the device, its data, or the network it participates in.";
45
+ }
46
+ concern def PerformanceConcern :> MemoConcern {
47
+ @MemoIdentity { :>> providedId = "CNC-4"; }
48
+ attribute name = "Performance";
49
+ attribute description = "Timing, throughput and capacity against what the clinical procedure demands.";
50
+ }
51
+ concern def InteroperabilityConcern :> MemoConcern {
52
+ @MemoIdentity { :>> providedId = "CNC-5"; }
53
+ attribute name = "Interoperability";
54
+ attribute description = "Correct exchange with the equipment and systems the device is used alongside.";
55
+ }
56
+ concern def ReliabilityConcern :> MemoConcern {
57
+ @MemoIdentity { :>> providedId = "CNC-6"; }
58
+ attribute name = "Reliability";
59
+ attribute description = "Continuity of correct service, and behaviour on failure.";
60
+ }
61
+ concern def PrivacyConcern :> MemoConcern {
62
+ @MemoIdentity { :>> providedId = "CNC-7"; }
63
+ attribute name = "Privacy";
64
+ attribute description = "Protection of patient and operator data through its lifecycle.";
65
+ }
66
+ concern def RegulatoryConcern :> MemoConcern {
67
+ @MemoIdentity { :>> providedId = "CNC-8"; }
68
+ attribute name = "Regulatory";
69
+ attribute description = "Evidence a submission requires, and conformance to the standards claimed.";
70
+ }
71
+ concern def ClinicalConcern :> MemoConcern {
72
+ @MemoIdentity { :>> providedId = "CNC-9"; }
73
+ attribute name = "Clinical";
74
+ attribute description = "Whether the device serves the clinical procedure and its intended use.";
75
+ }
76
+
77
+ // ─── Quality attributes ──────────────────────────────────────────────
78
+ //
79
+ // A concern is what a stakeholder cares about; a quality attribute is the
80
+ // measurable property of the system through which that care is answered.
81
+ // The SEI's separation (Bass, Clements & Kazman): "performance" as a
82
+ // concern is a worry, and only becomes designable once it is stated as a
83
+ // property with a stimulus, a response and a measure.
84
+ //
85
+ // `addressesConcerns` is the mapping, and it is many-to-many on purpose.
86
+ // Availability answers safety AND clinical continuity; security answers
87
+ // cybersecurity AND privacy. A quality attribute that addresses no concern
88
+ // is one nobody asked for, and a concern with no quality attribute behind
89
+ // it is a worry the architecture has not yet answered — both are findings
90
+ // this mapping makes visible.
91
+ abstract part def MemoQualityAttribute :> MemoPart {
92
+ ref addressesConcerns : MemoConcern[*];
93
+ /** How the property is measured — the response measure of a quality
94
+ * attribute scenario, stated once for the attribute. */
95
+ attribute measure : String;
96
+ }
97
+
98
+ part def Availability :> MemoQualityAttribute {
99
+ @MemoIdentity { :>> providedId = "QA-1"; }
100
+ attribute :>> name = "Availability";
101
+ ref :>> addressesConcerns = (SafetyConcern, ReliabilityConcern, ClinicalConcern);
102
+ attribute :>> measure = "Proportion of scheduled procedure time the function is delivered, and time to recover after a fault.";
103
+ }
104
+ part def Performance :> MemoQualityAttribute {
105
+ @MemoIdentity { :>> providedId = "QA-2"; }
106
+ attribute :>> name = "Performance";
107
+ ref :>> addressesConcerns = (PerformanceConcern, ClinicalConcern);
108
+ attribute :>> measure = "Latency and throughput under the arrival pattern the procedure produces.";
109
+ }
110
+ part def Security :> MemoQualityAttribute {
111
+ @MemoIdentity { :>> providedId = "QA-3"; }
112
+ attribute :>> name = "Security";
113
+ ref :>> addressesConcerns = (CybersecurityConcern, PrivacyConcern, SafetyConcern);
114
+ attribute :>> measure = "Resistance to a stated threat, and time to detect and recover from a compromise.";
115
+ }
116
+ part def Modifiability :> MemoQualityAttribute {
117
+ @MemoIdentity { :>> providedId = "QA-4"; }
118
+ attribute :>> name = "Modifiability";
119
+ ref :>> addressesConcerns = (RegulatoryConcern);
120
+ attribute :>> measure = "Cost and blast radius of a stated change, including the re-verification it forces.";
121
+ }
122
+ part def Testability :> MemoQualityAttribute {
123
+ @MemoIdentity { :>> providedId = "QA-5"; }
124
+ attribute :>> name = "Testability";
125
+ ref :>> addressesConcerns = (RegulatoryConcern, SafetyConcern);
126
+ attribute :>> measure = "Probability that a fault present is revealed by the next test, and the effort to observe it.";
127
+ }
128
+ part def Usability :> MemoQualityAttribute {
129
+ @MemoIdentity { :>> providedId = "QA-6"; }
130
+ attribute :>> name = "Usability";
131
+ ref :>> addressesConcerns = (UsabilityConcern, SafetyConcern, ClinicalConcern);
132
+ attribute :>> measure = "Task success and use-error rate for the intended user under use conditions (IEC 62366-1).";
133
+ }
134
+ part def Interoperability :> MemoQualityAttribute {
135
+ @MemoIdentity { :>> providedId = "QA-7"; }
136
+ attribute :>> name = "Interoperability";
137
+ ref :>> addressesConcerns = (InteroperabilityConcern, ClinicalConcern);
138
+ attribute :>> measure = "Proportion of exchanges with a named partner system that are correctly understood.";
139
+ }
140
+
141
+ // ─── Stakeholders ────────────────────────────────────────────────────
142
+ //
143
+ // A stakeholder holds concerns. These are the engineering and regulatory
144
+ // roles a viewpoint is written FOR; the clinical actors who operate the
145
+ // device are OperationalParticipants and are a different population.
146
+ abstract part def MemoStakeholder :> MemoPart;
147
+
148
+ part def SystemArchitect :> MemoStakeholder {
149
+ @MemoIdentity { :>> providedId = "STK-1"; }
150
+ attribute :>> name = "System Architect";
151
+ }
152
+ part def SoftwareArchitect :> MemoStakeholder {
153
+ @MemoIdentity { :>> providedId = "STK-2"; }
154
+ attribute :>> name = "Software Architect";
155
+ }
156
+ part def HardwareEngineer :> MemoStakeholder {
157
+ @MemoIdentity { :>> providedId = "STK-3"; }
158
+ attribute :>> name = "Hardware Engineer";
159
+ }
160
+ part def SafetyEngineer :> MemoStakeholder {
161
+ @MemoIdentity { :>> providedId = "STK-4"; }
162
+ attribute :>> name = "Safety Engineer";
163
+ }
164
+ part def VerificationEngineer :> MemoStakeholder {
165
+ @MemoIdentity { :>> providedId = "STK-5"; }
166
+ attribute :>> name = "Verification Engineer";
167
+ }
168
+ part def RegulatoryEngineer :> MemoStakeholder {
169
+ @MemoIdentity { :>> providedId = "STK-6"; }
170
+ attribute :>> name = "Regulatory Engineer";
171
+ }
172
+ part def ProjectLead :> MemoStakeholder {
173
+ @MemoIdentity { :>> providedId = "STK-7"; }
174
+ attribute :>> name = "Project Lead";
175
+ }
176
+ part def SecurityEngineer :> MemoStakeholder {
177
+ @MemoIdentity { :>> providedId = "STK-8"; }
178
+ attribute :>> name = "Security Engineer";
179
+ }
180
+ part def PrivacyEngineer :> MemoStakeholder {
181
+ @MemoIdentity { :>> providedId = "STK-9"; }
182
+ attribute :>> name = "Privacy Engineer";
183
+ }
184
+ part def ClinicalEngineer :> MemoStakeholder {
185
+ @MemoIdentity { :>> providedId = "STK-10"; }
186
+ attribute :>> name = "Clinical Engineer";
187
+ }
188
+ part def UsabilityEngineer :> MemoStakeholder {
189
+ @MemoIdentity { :>> providedId = "STK-11"; }
190
+ attribute :>> name = "Usability Engineer";
191
+ }
192
+ }
@@ -12,6 +12,7 @@ package memo_viewpoints_definitions {
12
12
  private import memo_core_dimensions::*;
13
13
  private import memo_core_terminology::*;
14
14
  private import memo_core_relationships::*;
15
+ private import memo_viewpoints_stakeholders_concerns::*;
15
16
 
16
17
  // Extends the native SysML viewpoint (Views::ViewpointCheck, a
17
18
  // RequirementCheck whose subject is a View) with MEMO's catalog
@@ -28,16 +29,28 @@ package memo_viewpoints_definitions {
28
29
  attribute applicableStandards : ExternalReference[0..*];
29
30
  attribute codes : TerminologyCode[0..*];
30
31
  attribute purpose : String;
31
- attribute audience : AudienceKind[*];
32
+ /**
33
+ * Who the viewpoint is written for, and what it frames for them.
34
+ *
35
+ * References, not enum literals. A stakeholder and a concern are
36
+ * elements with ids — citable in a review, traceable from a
37
+ * requirement, and extensible by a project without editing the
38
+ * ontology, which `AudienceKind` and `ConcernKind` were not.
39
+ */
40
+ ref stakeholders : MemoStakeholder[*];
32
41
  attribute stage : WorkflowStageKind;
33
42
  attribute abstractionLevel : String;
34
43
  attribute outputKind : ViewOutputKind[*];
35
44
  attribute presentationKind : PresentationKind[*];
36
- attribute concernKinds : ConcernKind[*];
37
- attribute includedLayers : String[*];
38
- attribute allowedElementKinds : String[*];
39
- attribute allowedRelationshipKinds : String[*];
40
- attribute filterExpression : String;
45
+ ref framedConcerns : MemoConcern[*];
46
+ // A viewpoint identifies stakeholders, the concerns it frames, and the
47
+ // views that conform to it — ISO/IEC/IEEE 42010, and nothing further.
48
+ // It used to also carry `includedLayers`, `allowedElementKinds`,
49
+ // `allowedRelationshipKinds` and `filterExpression`: scoping rules over
50
+ // its views. Nothing ever read them, and the filtering that did happen
51
+ // came from a union the deriver accumulated out of the views
52
+ // themselves. What a view shows is the view's to say, through its own
53
+ // expose members and selectionQuery.
41
54
  attribute extendsViewpointIds : String[*];
42
55
  attribute userExtensible : Boolean;
43
56
  // Optional navigation grouping interpreted by Memo Architect.
@@ -68,6 +81,53 @@ package memo_viewpoints_definitions {
68
81
  attribute rationaleText : String;
69
82
  }
70
83
 
84
+ // ─── Legends ────────────────────────────────────────────────────────
85
+ //
86
+ // A legend gives colour a meaning, and a view picks exactly one of them —
87
+ // because two legends at once would put two meanings on the same channel
88
+ // and neither could be read.
89
+ //
90
+ // Each legend is tied to ONE attribute or enumeration, which is what makes
91
+ // it a legend rather than a palette: every entry is a value of that same
92
+ // thing, so the key can be stated as "this attribute, these values, these
93
+ // colours". Colour is otherwise a property of a diagram, defined nowhere,
94
+ // reproducible in no other view and reviewable by nobody.
95
+ // A swatch, not an "entry": `entry` is a SysML keyword (a state's entry
96
+ // action), and the keyword-collision lint is right that a definition should
97
+ // not reach for one that means something else. A swatch is what this is —
98
+ // a colour with a label.
99
+ part def MemoLegendSwatch specializes MemoPart {
100
+ /** The value of the legend's attribute or enumeration this entry is for. */
101
+ attribute value : String;
102
+ /** Shown in the key. Defaults to the value when unstated. */
103
+ attribute label : String;
104
+ /** `#RRGGBB`. */
105
+ attribute color : String;
106
+ }
107
+
108
+ part def MemoLegend specializes MemoPart {
109
+ /** The attribute whose value each entry names — e.g. "realizationStage". */
110
+ attribute attributeName : String;
111
+ /**
112
+ * An `enum def` whose values each entry names, as an alternative to
113
+ * `attributeName`.
114
+ */
115
+ attribute enumerationName : String;
116
+ /**
117
+ * A value the model derives rather than stores — hierarchy depth, or
118
+ * the element's kind. Use instead of `attributeName` when the thing
119
+ * being coloured is not written on the element.
120
+ */
121
+ attribute derivedFrom : LegendSourceKind[0..1];
122
+ /**
123
+ * Which constructs are coloured. A legend may cover parts and the
124
+ * connections between them, or only one of them. Empty means every
125
+ * construct the legend has an entry for.
126
+ */
127
+ attribute appliesTo : LegendScopeKind[*];
128
+ part swatches : MemoLegendSwatch[*];
129
+ }
130
+
71
131
  view def MemoView :> Views::View {
72
132
  // Identity comes from the `@MemoIdentity` metadata carrier, which
73
133
  // annotates any metaclass — so a view stays native SysML without
@@ -103,6 +163,34 @@ package memo_viewpoints_definitions {
103
163
  attribute diagramType : String;
104
164
  attribute layoutHint : String;
105
165
  attribute styleHint : String;
166
+ /**
167
+ * The one legend this view colours by. At most one: colour is a single
168
+ * channel, and a second legend competing for it makes both unreadable.
169
+ * Without one, an element keeps its layer colour.
170
+ */
171
+ ref legend : MemoLegend[0..1];
172
+
173
+ // ── What the drawing SHOWS ────────────────────────────────────────
174
+ //
175
+ // These are the view's own statement about what it presents, so they
176
+ // are declared here and not in the layout companion beside it. That
177
+ // file records where boxes were dragged to; whether a drawing names
178
+ // its ports at all is a decision about the view, survives a layout
179
+ // reset, and belongs where the rest of the view's intent is written.
180
+ //
181
+ // Each is optional and the renderer keeps its default when a view says
182
+ // nothing, so no existing view changes meaning by their arrival.
183
+ attribute portDisplay : PortDisplayKind[0..1];
184
+ attribute connectionDisplay : ConnectionDisplayKind[0..1];
185
+ /** Name each port on the drawing. Off where the connector label
186
+ * already carries the same string, as on a ROS pub/sub view where the
187
+ * port and the topic share a name. */
188
+ attribute showPortText : Boolean[0..1];
189
+ attribute showConnectionText : Boolean[0..1];
190
+ /** Animate direction along connectors. */
191
+ attribute flowAnimation : Boolean[0..1];
192
+ /** The renderer profile this view opts into, by id. */
193
+ attribute rendererProfile : String[0..1];
106
194
  }
107
195
 
108
196
  view def MemoDocumentBackedView :> MemoView {
@@ -3,6 +3,7 @@ package memo_viewpoints_functional_functional_viewpoint {
3
3
 
4
4
  private import memo_viewpoints_definitions::*;
5
5
  private import memo_core_enumerations::*;
6
+ private import memo_viewpoints_stakeholders_concerns::*;
6
7
 
7
8
  private import memo_core_common::*;
8
9
  private import memo_core_common::MemoIdentity;
@@ -12,16 +13,14 @@ package memo_viewpoints_functional_functional_viewpoint {
12
13
  @MemoIdentity { :>> shortDescription = "Shows system functions, their decomposition, and allocation."; }
13
14
  attribute :>> description = "Default viewpoint derived from the functions layer for what the system does, independent of how it is structured — function trees, function allocation, and behavior triggers.";
14
15
  attribute :>> purpose = "Describe the system's functional decomposition and behavior.";
15
- attribute :>> audience = (AudienceKind::systemArchitect);
16
+ ref :>> stakeholders = (SystemArchitect);
16
17
  attribute :>> stage = WorkflowStageKind::architecture;
17
18
  attribute :>> abstractionLevel = "functional";
18
19
  attribute :>> outputKind = (ViewOutputKind::diagram);
19
20
  attribute :>> presentationKind = (PresentationKind::activityDiagram);
20
- attribute :>> concernKinds = (ConcernKind::safety, ConcernKind::performance);
21
- attribute :>> includedLayers = ("functions");
21
+ ref :>> framedConcerns = (SafetyConcern, PerformanceConcern);
22
22
  attribute :>> explorerLane = "architecture";
23
23
  attribute :>> explorerOrder = 2;
24
- attribute :>> allowedElementKinds = ("SystemFunction", "ComponentFunction", "FunctionalFlow", "FunctionalFlowStep", "OperativeScenario[scenarioKind=functional]", "FunctionalExchange");
25
24
  attribute :>> userExtensible = true;
26
25
  }
27
26
  }
@@ -3,6 +3,7 @@ package memo_viewpoints_logical_logical_viewpoint {
3
3
 
4
4
  private import memo_viewpoints_definitions::*;
5
5
  private import memo_core_enumerations::*;
6
+ private import memo_viewpoints_stakeholders_concerns::*;
6
7
 
7
8
  private import memo_core_common::*;
8
9
  private import memo_core_common::MemoIdentity;
@@ -12,16 +13,14 @@ package memo_viewpoints_logical_logical_viewpoint {
12
13
  @MemoIdentity { :>> shortDescription = "Shows logical decomposition and interfaces."; }
13
14
  attribute :>> description = "Default viewpoint derived from the logical architecture layer for subsystem structure, responsibilities, and major interactions, independent of physical realization.";
14
15
  attribute :>> purpose = "Describe the system's logical decomposition.";
15
- attribute :>> audience = (AudienceKind::systemArchitect);
16
+ ref :>> stakeholders = (SystemArchitect);
16
17
  attribute :>> stage = WorkflowStageKind::architecture;
17
18
  attribute :>> abstractionLevel = "logical";
18
19
  attribute :>> outputKind = (ViewOutputKind::diagram);
19
20
  attribute :>> presentationKind = (PresentationKind::blockDiagram);
20
- attribute :>> concernKinds = (ConcernKind::safety, ConcernKind::performance);
21
- attribute :>> includedLayers = ("logical_structure", "interfaces");
21
+ ref :>> framedConcerns = (SafetyConcern, PerformanceConcern);
22
22
  attribute :>> explorerLane = "architecture";
23
23
  attribute :>> explorerOrder = 3;
24
- attribute :>> allowedElementKinds = ("LogicalComponent", "Interface");
25
24
  attribute :>> userExtensible = true;
26
25
  }
27
26
  }
@@ -3,6 +3,7 @@ package memo_viewpoints_operational_operational_viewpoint {
3
3
 
4
4
  private import memo_viewpoints_definitions::*;
5
5
  private import memo_core_enumerations::*;
6
+ private import memo_viewpoints_stakeholders_concerns::*;
6
7
 
7
8
  private import memo_core_common::*;
8
9
  private import memo_core_common::MemoIdentity;
@@ -12,16 +13,14 @@ package memo_viewpoints_operational_operational_viewpoint {
12
13
  @MemoIdentity { :>> shortDescription = "Shows actors, use contexts, operational scenarios, and system capabilities."; }
13
14
  attribute :>> description = "Default viewpoint derived from the context, operational, and system layers for how actors use the device — operational scenarios, capabilities, and the functional chains that realize them.";
14
15
  attribute :>> purpose = "Communicate how actors interact with the system and which capabilities they invoke.";
15
- attribute :>> audience = (AudienceKind::projectLead, AudienceKind::systemArchitect);
16
+ ref :>> stakeholders = (ProjectLead, SystemArchitect);
16
17
  attribute :>> stage = WorkflowStageKind::context;
17
18
  attribute :>> abstractionLevel = "operational";
18
19
  attribute :>> outputKind = (ViewOutputKind::diagram);
19
20
  attribute :>> presentationKind = (PresentationKind::custom);
20
- attribute :>> concernKinds = (ConcernKind::performance, ConcernKind::interoperability);
21
- attribute :>> includedLayers = ("context", "operational", "system");
21
+ ref :>> framedConcerns = (PerformanceConcern, InteroperabilityConcern);
22
22
  attribute :>> explorerLane = "architecture";
23
23
  attribute :>> explorerOrder = 1;
24
- attribute :>> allowedElementKinds = ("Actor", "UseContext", "OperativeAction", "OperativeScenario[scenarioKind=operative]");
25
24
  attribute :>> userExtensible = true;
26
25
  }
27
26
  }
@@ -3,6 +3,7 @@ package memo_viewpoints_physical_physical_viewpoint {
3
3
 
4
4
  private import memo_viewpoints_definitions::*;
5
5
  private import memo_core_enumerations::*;
6
+ private import memo_viewpoints_stakeholders_concerns::*;
6
7
 
7
8
  private import memo_core_common::*;
8
9
  private import memo_core_common::MemoIdentity;
@@ -12,16 +13,14 @@ package memo_viewpoints_physical_physical_viewpoint {
12
13
  @MemoIdentity { :>> shortDescription = "Shows physical components, hardware structure, and their interconnections."; }
13
14
  attribute :>> description = "Default viewpoint derived from the physical and hardware structure layers for bill-of-materials, hardware decomposition, physical interfaces, and network/connectivity topology.";
14
15
  attribute :>> purpose = "Describe the system's physical realization and interconnections.";
15
- attribute :>> audience = (AudienceKind::hardwareEngineer);
16
+ ref :>> stakeholders = (HardwareEngineer);
16
17
  attribute :>> stage = WorkflowStageKind::architecture;
17
18
  attribute :>> abstractionLevel = "physical";
18
19
  attribute :>> outputKind = (ViewOutputKind::diagram);
19
20
  attribute :>> presentationKind = (PresentationKind::blockDiagram);
20
- attribute :>> concernKinds = (ConcernKind::reliability, ConcernKind::interoperability);
21
- attribute :>> includedLayers = ("hardware_structure", "physical");
21
+ ref :>> framedConcerns = (ReliabilityConcern, InteroperabilityConcern);
22
22
  attribute :>> explorerLane = "architecture";
23
23
  attribute :>> explorerOrder = 5;
24
- attribute :>> allowedElementKinds = ("ProcessingNode", "HardwareAssembly", "PhysicalPort");
25
24
  attribute :>> userExtensible = true;
26
25
  }
27
26
  }
@@ -3,6 +3,7 @@ package memo_viewpoints_requirements_requirements_viewpoint {
3
3
 
4
4
  private import memo_viewpoints_definitions::*;
5
5
  private import memo_core_enumerations::*;
6
+ private import memo_viewpoints_stakeholders_concerns::*;
6
7
 
7
8
  private import memo_core_common::*;
8
9
  private import memo_core_common::MemoIdentity;
@@ -12,16 +13,14 @@ package memo_viewpoints_requirements_requirements_viewpoint {
12
13
  @MemoIdentity { :>> shortDescription = "Shows stakeholder needs and their decomposition into system, software, and hardware requirements."; }
13
14
  attribute :>> description = "Default viewpoint derived from the requirements layer for requirements traceability — the chain from stakeholder need through system, software, and hardware requirements, supporting IEC 62304 §5.1.1 and ISO 13485 §7.3.3.";
14
15
  attribute :>> purpose = "Communicate requirements decomposition and traceability.";
15
- attribute :>> audience = (AudienceKind::regulatoryEngineer, AudienceKind::systemArchitect);
16
+ ref :>> stakeholders = (RegulatoryEngineer, SystemArchitect);
16
17
  attribute :>> stage = WorkflowStageKind::requirements;
17
18
  attribute :>> abstractionLevel = "requirements";
18
19
  attribute :>> outputKind = (ViewOutputKind::diagram, ViewOutputKind::matrix);
19
20
  attribute :>> presentationKind = (PresentationKind::traceMatrix);
20
- attribute :>> concernKinds = (ConcernKind::regulatory, ConcernKind::safety);
21
- attribute :>> includedLayers = ("requirements");
21
+ ref :>> framedConcerns = (RegulatoryConcern, SafetyConcern);
22
22
  attribute :>> explorerLane = "assurance";
23
23
  attribute :>> explorerOrder = 1;
24
- attribute :>> allowedElementKinds = ("Need", "Requirement");
25
24
  attribute :>> userExtensible = true;
26
25
  }
27
26
  }
@@ -3,6 +3,7 @@ package memo_viewpoints_risk_risk_viewpoint {
3
3
 
4
4
  private import memo_viewpoints_definitions::*;
5
5
  private import memo_core_enumerations::*;
6
+ private import memo_viewpoints_stakeholders_concerns::*;
6
7
 
7
8
  private import memo_core_common::*;
8
9
  private import memo_core_common::MemoIdentity;
@@ -12,16 +13,14 @@ package memo_viewpoints_risk_risk_viewpoint {
12
13
  @MemoIdentity { :>> shortDescription = "Shows hazards, risks, controls, and assurance links."; }
13
14
  attribute :>> description = "Default viewpoint derived from the risk layer for ISO 14971-style reasoning across hazard, hazardous situation, harm, control, and verification evidence.";
14
15
  attribute :>> purpose = "Communicate safety risk chains and controls.";
15
- attribute :>> audience = (AudienceKind::safetyEngineer);
16
+ ref :>> stakeholders = (SafetyEngineer);
16
17
  attribute :>> stage = WorkflowStageKind::risk;
17
18
  attribute :>> abstractionLevel = "analysis";
18
19
  attribute :>> outputKind = (ViewOutputKind::table);
19
20
  attribute :>> presentationKind = (PresentationKind::riskTable);
20
- attribute :>> concernKinds = (ConcernKind::safety, ConcernKind::regulatory);
21
- attribute :>> includedLayers = ("risk", "assurance");
21
+ ref :>> framedConcerns = (SafetyConcern, RegulatoryConcern);
22
22
  attribute :>> explorerLane = "assurance";
23
23
  attribute :>> explorerOrder = 2;
24
- attribute :>> allowedElementKinds = ("SafetyRelatedCharacteristic", "HazardCause", "Hazard", "SequenceOfEvents", "HazardousSituation", "Harm", "Risk", "RiskControlMeasure", "ResidualRisk", "Benefit", "OverallResidualRiskEvaluation", "VerificationCase");
25
24
  attribute :>> userExtensible = true;
26
25
  }
27
26
  }
@@ -3,6 +3,7 @@ package memo_viewpoints_software_software_viewpoint {
3
3
 
4
4
  private import memo_viewpoints_definitions::*;
5
5
  private import memo_core_enumerations::*;
6
+ private import memo_viewpoints_stakeholders_concerns::*;
6
7
 
7
8
  private import memo_core_common::*;
8
9
  private import memo_core_common::MemoIdentity;
@@ -12,16 +13,14 @@ package memo_viewpoints_software_software_viewpoint {
12
13
  @MemoIdentity { :>> shortDescription = "Shows software systems, components, SOUP, and software interfaces."; }
13
14
  attribute :>> description = "Default viewpoint derived from the software structure layer for IEC 62304 software architecture description — software item decomposition, SOUP inventory, and software-to-software interfaces, distinct from system-level logical decomposition.";
14
15
  attribute :>> purpose = "Describe the software architecture for IEC 62304 design documentation.";
15
- attribute :>> audience = (AudienceKind::softwareArchitect);
16
+ ref :>> stakeholders = (SoftwareArchitect);
16
17
  attribute :>> stage = WorkflowStageKind::architecture;
17
18
  attribute :>> abstractionLevel = "software";
18
19
  attribute :>> outputKind = (ViewOutputKind::diagram);
19
20
  attribute :>> presentationKind = (PresentationKind::blockDiagram);
20
- attribute :>> concernKinds = (ConcernKind::safety, ConcernKind::reliability);
21
- attribute :>> includedLayers = ("software_structure", "interfaces");
21
+ ref :>> framedConcerns = (SafetyConcern, ReliabilityConcern);
22
22
  attribute :>> explorerLane = "architecture";
23
23
  attribute :>> explorerOrder = 4;
24
- attribute :>> allowedElementKinds = ("SoftwareSystem", "SoftwareModule", "SoftwareModule[moduleKind=soup]", "Interface");
25
24
  attribute :>> userExtensible = true;
26
25
  }
27
26
  }
@@ -3,6 +3,7 @@ package memo_viewpoints_ui_layout_ui_layout_viewpoint {
3
3
 
4
4
  private import memo_viewpoints_definitions::*;
5
5
  private import memo_core_enumerations::*;
6
+ private import memo_viewpoints_stakeholders_concerns::*;
6
7
 
7
8
  private import memo_core_common::*;
8
9
  private import memo_core_common::MemoIdentity;
@@ -12,17 +13,14 @@ package memo_viewpoints_ui_layout_ui_layout_viewpoint {
12
13
  @MemoIdentity { :>> shortDescription = "Shows screen captures with the UI element tree laid out over them."; }
13
14
  attribute :>> description = "Frames the user interface spatially: a captured rendering of a screen, and the UIElement tree laid out over it by each element's bounds. Supports IEC 62366-1 use-related design review and the UI description in the software design specification, by making 'which control is this, and what does it do' answerable from the picture. There is one tree, not two — the elements carrying the geometry are the same elements carrying the requirements, functions, use errors, and risk controls.";
14
15
  attribute :>> purpose = "Review the interface as the user sees it, with every functional area backed by a design record.";
15
- attribute :>> audience = (AudienceKind::usabilityEngineer, AudienceKind::softwareArchitect, AudienceKind::safetyEngineer);
16
+ ref :>> stakeholders = (UsabilityEngineer, SoftwareArchitect, SafetyEngineer);
16
17
  attribute :>> stage = WorkflowStageKind::architecture;
17
18
  attribute :>> abstractionLevel = "implementation";
18
19
  attribute :>> outputKind = (ViewOutputKind::diagram, ViewOutputKind::documentSection);
19
20
  attribute :>> presentationKind = (PresentationKind::screenLayout);
20
- attribute :>> concernKinds = (ConcernKind::usability, ConcernKind::safety);
21
- attribute :>> includedLayers = ("implementation");
21
+ ref :>> framedConcerns = (UsabilityConcern, SafetyConcern);
22
22
  attribute :>> explorerLane = "architecture";
23
23
  attribute :>> explorerOrder = 4;
24
- attribute :>> allowedElementKinds = ("ScreenCapture", "UIElement", "UserInterface");
25
- attribute :>> allowedRelationshipKinds = ("CapturesScreen", "NavigatesTo", "Composes", "satisfy", "ElementTriggersAction");
26
24
  attribute :>> defaultViewKind = DiagramViewKind::geometry;
27
25
  attribute :>> userExtensible = true;
28
26
  }
@@ -3,6 +3,7 @@ package memo_viewpoints_usability_usability_viewpoint {
3
3
 
4
4
  private import memo_viewpoints_definitions::*;
5
5
  private import memo_core_enumerations::*;
6
+ private import memo_viewpoints_stakeholders_concerns::*;
6
7
 
7
8
  private import memo_core_common::*;
8
9
  private import memo_core_common::MemoIdentity;
@@ -12,16 +13,14 @@ package memo_viewpoints_usability_usability_viewpoint {
12
13
  @MemoIdentity { :>> shortDescription = "Shows use contexts, actors, use errors, and usability requirements."; }
13
14
  attribute :>> description = "Default viewpoint derived from the context and requirements layers for IEC 62366-1 usability engineering — actors, use contexts, identified use errors, and requirements tagged with the usability concern. Reuses existing context-layer elements (Actor, UseContext, UseError) rather than a separate usability layer.";
14
15
  attribute :>> purpose = "Communicate use-related hazards and usability requirements for the device.";
15
- attribute :>> audience = (AudienceKind::usabilityEngineer, AudienceKind::safetyEngineer);
16
+ ref :>> stakeholders = (UsabilityEngineer, SafetyEngineer);
16
17
  attribute :>> stage = WorkflowStageKind::requirements;
17
18
  attribute :>> abstractionLevel = "usability";
18
19
  attribute :>> outputKind = (ViewOutputKind::documentSection);
19
20
  attribute :>> presentationKind = (PresentationKind::narrativeSection);
20
- attribute :>> concernKinds = (ConcernKind::usability, ConcernKind::safety);
21
- attribute :>> includedLayers = ("context", "requirements");
21
+ ref :>> framedConcerns = (UsabilityConcern, SafetyConcern);
22
22
  attribute :>> explorerLane = "assurance";
23
23
  attribute :>> explorerOrder = 4;
24
- attribute :>> allowedElementKinds = ("Actor", "UseContext", "UseError", "Requirement");
25
24
  attribute :>> userExtensible = true;
26
25
  }
27
26
  }
@@ -3,6 +3,7 @@ package memo_viewpoints_verification_verification_viewpoint {
3
3
 
4
4
  private import memo_viewpoints_definitions::*;
5
5
  private import memo_core_enumerations::*;
6
+ private import memo_viewpoints_stakeholders_concerns::*;
6
7
 
7
8
  private import memo_core_common::*;
8
9
  private import memo_core_common::MemoIdentity;
@@ -12,16 +13,14 @@ package memo_viewpoints_verification_verification_viewpoint {
12
13
  @MemoIdentity { :>> shortDescription = "Shows verification cases, validation cases, and the evidence they produce, traced to requirements."; }
13
14
  attribute :>> description = "Default viewpoint derived from the requirements and assurance layers for V&V coverage — which requirements are verified/validated, by which case, and what evidence was produced, supporting ISO 13485 §7.3.6/§7.3.7 and IEC 62304 §5.7/§5.8.";
14
15
  attribute :>> purpose = "Communicate verification and validation coverage against requirements.";
15
- attribute :>> audience = (AudienceKind::verificationEngineer);
16
+ ref :>> stakeholders = (VerificationEngineer);
16
17
  attribute :>> stage = WorkflowStageKind::verificationStage;
17
18
  attribute :>> abstractionLevel = "verification";
18
19
  attribute :>> outputKind = (ViewOutputKind::matrix);
19
20
  attribute :>> presentationKind = (PresentationKind::traceMatrix);
20
- attribute :>> concernKinds = (ConcernKind::safety, ConcernKind::regulatory);
21
- attribute :>> includedLayers = ("requirements", "assurance");
21
+ ref :>> framedConcerns = (SafetyConcern, RegulatoryConcern);
22
22
  attribute :>> explorerLane = "assurance";
23
23
  attribute :>> explorerOrder = 5;
24
- attribute :>> allowedElementKinds = ("Requirement", "VerificationCase", "ValidationCase", "MemoEvidence");
25
24
  attribute :>> userExtensible = true;
26
25
  }
27
26
  }