@memoarchitect/ontology 0.11.2 → 0.12.1

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 (53) hide show
  1. package/README.md +1 -1
  2. package/examples/gpca-pump/memo.identity.yaml +27 -0
  3. package/examples/gpca-pump/model/catalog/gpca_system.sysml +3 -3
  4. package/examples/sysml-diagram-samples/README.md +10 -0
  5. package/examples/sysml-diagram-samples/dashboards/README.md +17 -0
  6. package/examples/sysml-diagram-samples/dashboards/viewpoint-vp-demo-ibd.md +61 -0
  7. package/examples/sysml-diagram-samples/memo.identity.yaml +616 -0
  8. package/examples/sysml-diagram-samples/model/catalog/project.sysml +2 -11
  9. package/examples/sysml-diagram-samples/model/catalog/viewpoints/unassigned/viewpoint.sysml +81 -6
  10. package/examples/sysml-diagram-samples/model/catalog/viewpoints/unassigned/views/action_flow_view.sysml +15 -5
  11. package/examples/sysml-diagram-samples/model/catalog/viewpoints/unassigned/views/browser_view.sysml +88 -0
  12. package/examples/sysml-diagram-samples/model/catalog/viewpoints/unassigned/views/context_view.sysml +6 -6
  13. package/examples/sysml-diagram-samples/model/catalog/viewpoints/unassigned/views/functional_flow_view.sysml +3 -3
  14. package/examples/sysml-diagram-samples/model/catalog/viewpoints/unassigned/views/grid_view.sysml +64 -0
  15. package/examples/sysml-diagram-samples/model/catalog/viewpoints/unassigned/views/interconnection_view.sysml +64 -4
  16. package/examples/sysml-diagram-samples/model/catalog/viewpoints/unassigned/views/operational_behaviour_view.sysml +3 -3
  17. package/examples/sysml-diagram-samples/model/catalog/viewpoints/unassigned/views/package_view.sysml +69 -0
  18. package/examples/sysml-diagram-samples/model/catalog/viewpoints/unassigned/views/requirements_view.sysml +11 -11
  19. package/examples/sysml-diagram-samples/model/catalog/viewpoints/unassigned/views/sequence_view.sysml +97 -0
  20. package/examples/sysml-diagram-samples/model/catalog/viewpoints/unassigned/views/standard_activity_view.sysml +18 -18
  21. package/examples/sysml-diagram-samples/model/catalog/viewpoints/unassigned/views/state_transition_view.sysml +18 -6
  22. package/examples/sysml-diagram-samples/model/catalog/viewpoints/unassigned/views/tree_view.sysml +5 -5
  23. package/examples/sysml-diagram-samples/model/catalog/viewpoints/unassigned/views/use_case_view.sysml +34 -11
  24. package/extensions/aadl/memo.package.yaml +1 -1
  25. package/extensions/cloud/memo.package.yaml +1 -1
  26. package/extensions/container/memo.package.yaml +1 -1
  27. package/extensions/messaging/memo.package.yaml +1 -1
  28. package/extensions/ros/memo.package.yaml +1 -1
  29. package/methodologies/default/memo.package.yaml +1 -1
  30. package/methodologies/gpca/memo.package.yaml +1 -1
  31. package/ontology/memo.package.yaml +1 -1
  32. package/package.json +1 -1
  33. package/profile/memo.package.yaml +1 -1
  34. package/src/architecture/functional/behavior/memo_behavior.sysml +8 -1
  35. package/src/architecture/functional/functions/memo_functions.sysml +16 -2
  36. package/src/architecture/implementation/ui/memo_ui.sysml +46 -20
  37. package/src/core/enumerations/memo_enumerations.sysml +49 -13
  38. package/src/memo_namespaces.sysml +2 -0
  39. package/src/viewpoints/clinical/clinical_viewpoint.sysml +3 -4
  40. package/src/viewpoints/context/context_viewpoint.sysml +3 -5
  41. package/src/viewpoints/cybersecurity/cybersecurity_viewpoint.sysml +3 -5
  42. package/src/viewpoints/definitions/memo_stakeholders_concerns.sysml +192 -0
  43. package/src/viewpoints/definitions/memo_viewpoint_definitions.sysml +94 -6
  44. package/src/viewpoints/functional/functional_viewpoint.sysml +3 -4
  45. package/src/viewpoints/logical/logical_viewpoint.sysml +3 -4
  46. package/src/viewpoints/operational/operational_viewpoint.sysml +3 -4
  47. package/src/viewpoints/physical/physical_viewpoint.sysml +3 -4
  48. package/src/viewpoints/requirements/requirements_viewpoint.sysml +3 -4
  49. package/src/viewpoints/risk/risk_viewpoint.sysml +3 -4
  50. package/src/viewpoints/software/software_viewpoint.sysml +3 -4
  51. package/src/viewpoints/ui_layout/ui_layout_viewpoint.sysml +3 -5
  52. package/src/viewpoints/usability/usability_viewpoint.sysml +3 -4
  53. package/src/viewpoints/verification/verification_viewpoint.sysml +3 -4
@@ -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
  }