Skip to content

memo_rules_closure

SysML API

Public namespace memo::rules::closure
Declared package memo_rules_closure
Source src/rules/closure/closure_rules.sysml

Namespace hierarchy

memo → memo::rules → memo::rules::closure

Packages

Package
memo_rules_closure

Imports

Visibility Target
private ScalarValues::*
private memo_core_consistency_rules::*
private memo_core_enumerations::*
private memo_core_common::*
private memo_core_common::MemoIdentity
private memo_artifacts_standards_traceability::EnforcesClause
private memo_artifacts_standards_fda_cybersecurity_2023::*
private memo_artifacts_standards_iec_62304::*
private memo_artifacts_standards_iec_62366_1::*
private memo_artifacts_standards_iso_13485::*
private memo_artifacts_standards_iso_14971::*

Declarations

Name SysML kind Description Specializes
HazardMitigationRule constraint def Constraint that checks hazard mitigation rule. MemoConsistencyRule
HazardSeverityRule constraint def Constraint that checks hazard severity rule. MemoConsistencyRule
RiskControlVerificationRule constraint def Constraint that checks risk control verification rule. MemoConsistencyRule
InitialRiskMatrixRule constraint def Constraint that checks initial risk matrix rule. MemoConsistencyRule
SysReqTraceRule constraint def Constraint that checks sys req trace rule. MemoConsistencyRule
SwReqTraceRule constraint def Constraint that checks sw req trace rule. MemoConsistencyRule
SwComponentSafetyClassRule constraint def Constraint that checks sw component safety class rule. MemoConsistencyRule
SwComponentReqRule constraint def Constraint that checks sw component req rule. MemoConsistencyRule
LogicalFunctionAllocationRule constraint def Constraint that checks logical function allocation rule. MemoConsistencyRule
FunctionInChainRule constraint def A function that no edge reaches is not in the chain. This was a TypeScript rule (BV-002) applying to every action usage in the model, which reported a scenario and a flow step as defects for not being wired like a function.… MemoConsistencyRule
UserNeedIdentifiesUserRule constraint def A user need names the user whose need it is. IEC 62366-1's user profile is typed on the User element — population, impairments, training, qualification — so the need points at that element rather than restating any of it in prose, which is what userPopulationReference was do… MemoConsistencyRule
VerificationCaseMethodRule constraint def Constraint that checks verification case method rule. MemoConsistencyRule
VerificationCaseTargetRule constraint def Constraint that checks verification case target rule. MemoConsistencyRule
EvidenceProductionRule constraint def Constraint that checks evidence production rule. MemoConsistencyRule
ThreatMitigationRule constraint def Constraint that checks threat mitigation rule. MemoConsistencyRule
AssetThreatLinkRule constraint def Constraint that checks asset threat link rule. MemoConsistencyRule
LogicalInterfaceDirectionRule constraint def Constraint that checks logical interface direction rule. MemoConsistencyRule
SafetyClassCVerificationRule constraint def Constraint that checks safety class cverification rule. MemoConsistencyRule
UiElementDesignRecordRule constraint def The load-bearing traceability rule. A UI element that is not chrome must reach a design record — a requirement it satisfies, or an action it triggers. Chrome must be DECLARED decoration; an element left unclassified fails rather than passing as scenery. MemoConsistencyRule
ControlInvokesFunctionRule constraint def Interactive UI is where use error happens (IEC 62366-1), so a control that reaches no system function is either dead UI or unmodelled UI. The interactive-form restriction lives in the predicate because it spans several enum values. MemoConsistencyRule
BoundsDetectionConfirmedRule constraint def Automatic boundary detection proposes; a reviewer disposes. An unconfirmed machine guess must never reach a design review looking like an engineering decision. MemoConsistencyRule
ScreenCaptureProvenanceRule constraint def A screenshot with no build behind it is undated design intent, not evidence of what the device does. MemoConsistencyRule
HazardHasSituationRule constraint def Written from the classification in plans/memo-rules-domain-trace-and-editor.md (Step 5): each checks a property the model carries, and each traces to the clause it enforces. MemoConsistencyRule
SituationLeadsToHarmRule constraint def Constraint that checks situation leads to harm rule. MemoConsistencyRule
RiskEstimateRule constraint def Constraint that checks risk estimate rule. MemoConsistencyRule
RiskAcceptabilityRule constraint def Constraint that checks risk acceptability rule. MemoConsistencyRule
ResidualRiskAcceptabilityRule constraint def Constraint that checks residual risk acceptability rule. MemoConsistencyRule
ResidualRiskEvaluatedRule constraint def Constraint that checks residual risk evaluated rule. MemoConsistencyRule
MisuseReachesSituationRule constraint def ISO 14971 clauses 5.2, 5.3 and 7.4 on the links the model already has: a misuse is not an item of the risk chain, so it reaches the chain by causes (the risk can start at any element: an operational flow, an FMEA row, a use error, a misuse); a safety-related characteristic r… MemoConsistencyRule
CharacteristicReachesHazardRule constraint def Constraint that checks characteristic reaches hazard rule. MemoConsistencyRule
BenefitRiskWeighedRule constraint def Constraint that checks benefit risk weighed rule. MemoConsistencyRule
SoupAnomaliesRule constraint def Constraint that checks soup anomalies rule. MemoConsistencyRule
SoupIdentifiedRule constraint def Constraint that checks soup identified rule. MemoConsistencyRule
SoupRequirementRule constraint def Constraint that checks soup requirement rule. MemoConsistencyRule
UnitDecompositionRule constraint def Constraint that checks unit decomposition rule. MemoConsistencyRule
ChangeImpactRule constraint def Constraint that checks change impact rule. MemoConsistencyRule
ChangeApprovalRule constraint def Constraint that checks change approval rule. MemoConsistencyRule
ChangeTraceRule constraint def Constraint that checks change trace rule. MemoConsistencyRule

HazardMitigationRule

constraint def HazardMitigationRule :> MemoConsistencyRule
Property Value
Description Constraint that checks hazard mitigation rule.
Kind constraint def
Abstract No
Specializes MemoConsistencyRule
Owning package memo_rules_closure

HazardSeverityRule

constraint def HazardSeverityRule :> MemoConsistencyRule
Property Value
Description Constraint that checks hazard severity rule.
Kind constraint def
Abstract No
Specializes MemoConsistencyRule
Owning package memo_rules_closure

RiskControlVerificationRule

constraint def RiskControlVerificationRule :> MemoConsistencyRule
Property Value
Description Constraint that checks risk control verification rule.
Kind constraint def
Abstract No
Specializes MemoConsistencyRule
Owning package memo_rules_closure

InitialRiskMatrixRule

constraint def InitialRiskMatrixRule :> MemoConsistencyRule
Property Value
Description Constraint that checks initial risk matrix rule.
Kind constraint def
Abstract No
Specializes MemoConsistencyRule
Owning package memo_rules_closure

SysReqTraceRule

constraint def SysReqTraceRule :> MemoConsistencyRule
Property Value
Description Constraint that checks sys req trace rule.
Kind constraint def
Abstract No
Specializes MemoConsistencyRule
Owning package memo_rules_closure

SwReqTraceRule

constraint def SwReqTraceRule :> MemoConsistencyRule
Property Value
Description Constraint that checks sw req trace rule.
Kind constraint def
Abstract No
Specializes MemoConsistencyRule
Owning package memo_rules_closure

SwComponentSafetyClassRule

constraint def SwComponentSafetyClassRule :> MemoConsistencyRule
Property Value
Description Constraint that checks sw component safety class rule.
Kind constraint def
Abstract No
Specializes MemoConsistencyRule
Owning package memo_rules_closure

SwComponentReqRule

constraint def SwComponentReqRule :> MemoConsistencyRule
Property Value
Description Constraint that checks sw component req rule.
Kind constraint def
Abstract No
Specializes MemoConsistencyRule
Owning package memo_rules_closure

LogicalFunctionAllocationRule

constraint def LogicalFunctionAllocationRule :> MemoConsistencyRule
Property Value
Description Constraint that checks logical function allocation rule.
Kind constraint def
Abstract No
Specializes MemoConsistencyRule
Owning package memo_rules_closure

FunctionInChainRule

constraint def FunctionInChainRule :> MemoConsistencyRule
Property Value
Description A function that no edge reaches is not in the chain. This was a TypeScript rule (BV-002) applying to every action usage in the model, which reported a scenario and a flow step as defects for not being wired like a function.…
Kind constraint def
Abstract No
Specializes MemoConsistencyRule
Owning package memo_rules_closure

UserNeedIdentifiesUserRule

constraint def UserNeedIdentifiesUserRule :> MemoConsistencyRule
Property Value
Description A user need names the user whose need it is. IEC 62366-1's user profile is typed on the User element — population, impairments, training, qualification — so the need points at that element rather than restating any of it in prose, which is what userPopulationReference was do…
Kind constraint def
Abstract No
Specializes MemoConsistencyRule
Owning package memo_rules_closure

VerificationCaseMethodRule

constraint def VerificationCaseMethodRule :> MemoConsistencyRule
Property Value
Description Constraint that checks verification case method rule.
Kind constraint def
Abstract No
Specializes MemoConsistencyRule
Owning package memo_rules_closure

VerificationCaseTargetRule

constraint def VerificationCaseTargetRule :> MemoConsistencyRule
Property Value
Description Constraint that checks verification case target rule.
Kind constraint def
Abstract No
Specializes MemoConsistencyRule
Owning package memo_rules_closure

EvidenceProductionRule

constraint def EvidenceProductionRule :> MemoConsistencyRule
Property Value
Description Constraint that checks evidence production rule.
Kind constraint def
Abstract No
Specializes MemoConsistencyRule
Owning package memo_rules_closure

ThreatMitigationRule

constraint def ThreatMitigationRule :> MemoConsistencyRule
Property Value
Description Constraint that checks threat mitigation rule.
Kind constraint def
Abstract No
Specializes MemoConsistencyRule
Owning package memo_rules_closure

AssetThreatLinkRule

constraint def AssetThreatLinkRule :> MemoConsistencyRule
Property Value
Description Constraint that checks asset threat link rule.
Kind constraint def
Abstract No
Specializes MemoConsistencyRule
Owning package memo_rules_closure

LogicalInterfaceDirectionRule

constraint def LogicalInterfaceDirectionRule :> MemoConsistencyRule
Property Value
Description Constraint that checks logical interface direction rule.
Kind constraint def
Abstract No
Specializes MemoConsistencyRule
Owning package memo_rules_closure

SafetyClassCVerificationRule

constraint def SafetyClassCVerificationRule :> MemoConsistencyRule
Property Value
Description Constraint that checks safety class cverification rule.
Kind constraint def
Abstract No
Specializes MemoConsistencyRule
Owning package memo_rules_closure

UiElementDesignRecordRule

constraint def UiElementDesignRecordRule :> MemoConsistencyRule
Property Value
Description The load-bearing traceability rule. A UI element that is not chrome must reach a design record — a requirement it satisfies, or an action it triggers. Chrome must be DECLARED decoration; an element left unclassified fails rather than passing as scenery.
Kind constraint def
Abstract No
Specializes MemoConsistencyRule
Owning package memo_rules_closure

ControlInvokesFunctionRule

constraint def ControlInvokesFunctionRule :> MemoConsistencyRule
Property Value
Description Interactive UI is where use error happens (IEC 62366-1), so a control that reaches no system function is either dead UI or unmodelled UI. The interactive-form restriction lives in the predicate because it spans several enum values.
Kind constraint def
Abstract No
Specializes MemoConsistencyRule
Owning package memo_rules_closure

BoundsDetectionConfirmedRule

constraint def BoundsDetectionConfirmedRule :> MemoConsistencyRule
Property Value
Description Automatic boundary detection proposes; a reviewer disposes. An unconfirmed machine guess must never reach a design review looking like an engineering decision.
Kind constraint def
Abstract No
Specializes MemoConsistencyRule
Owning package memo_rules_closure

ScreenCaptureProvenanceRule

constraint def ScreenCaptureProvenanceRule :> MemoConsistencyRule
Property Value
Description A screenshot with no build behind it is undated design intent, not evidence of what the device does.
Kind constraint def
Abstract No
Specializes MemoConsistencyRule
Owning package memo_rules_closure

HazardHasSituationRule

constraint def HazardHasSituationRule :> MemoConsistencyRule
Property Value
Description Written from the classification in plans/memo-rules-domain-trace-and-editor.md (Step 5): each checks a property the model carries, and each traces to the clause it enforces.
Kind constraint def
Abstract No
Specializes MemoConsistencyRule
Owning package memo_rules_closure

SituationLeadsToHarmRule

constraint def SituationLeadsToHarmRule :> MemoConsistencyRule
Property Value
Description Constraint that checks situation leads to harm rule.
Kind constraint def
Abstract No
Specializes MemoConsistencyRule
Owning package memo_rules_closure

RiskEstimateRule

constraint def RiskEstimateRule :> MemoConsistencyRule
Property Value
Description Constraint that checks risk estimate rule.
Kind constraint def
Abstract No
Specializes MemoConsistencyRule
Owning package memo_rules_closure

RiskAcceptabilityRule

constraint def RiskAcceptabilityRule :> MemoConsistencyRule
Property Value
Description Constraint that checks risk acceptability rule.
Kind constraint def
Abstract No
Specializes MemoConsistencyRule
Owning package memo_rules_closure

ResidualRiskAcceptabilityRule

constraint def ResidualRiskAcceptabilityRule :> MemoConsistencyRule
Property Value
Description Constraint that checks residual risk acceptability rule.
Kind constraint def
Abstract No
Specializes MemoConsistencyRule
Owning package memo_rules_closure

ResidualRiskEvaluatedRule

constraint def ResidualRiskEvaluatedRule :> MemoConsistencyRule
Property Value
Description Constraint that checks residual risk evaluated rule.
Kind constraint def
Abstract No
Specializes MemoConsistencyRule
Owning package memo_rules_closure

MisuseReachesSituationRule

constraint def MisuseReachesSituationRule :> MemoConsistencyRule
Property Value
Description ISO 14971 clauses 5.2, 5.3 and 7.4 on the links the model already has: a misuse is not an item of the risk chain, so it reaches the chain by causes (the risk can start at any element: an operational flow, an FMEA row, a use error, a misuse); a safety-related characteristic r…
Kind constraint def
Abstract No
Specializes MemoConsistencyRule
Owning package memo_rules_closure

CharacteristicReachesHazardRule

constraint def CharacteristicReachesHazardRule :> MemoConsistencyRule
Property Value
Description Constraint that checks characteristic reaches hazard rule.
Kind constraint def
Abstract No
Specializes MemoConsistencyRule
Owning package memo_rules_closure

BenefitRiskWeighedRule

constraint def BenefitRiskWeighedRule :> MemoConsistencyRule
Property Value
Description Constraint that checks benefit risk weighed rule.
Kind constraint def
Abstract No
Specializes MemoConsistencyRule
Owning package memo_rules_closure

SoupAnomaliesRule

constraint def SoupAnomaliesRule :> MemoConsistencyRule
Property Value
Description Constraint that checks soup anomalies rule.
Kind constraint def
Abstract No
Specializes MemoConsistencyRule
Owning package memo_rules_closure

SoupIdentifiedRule

constraint def SoupIdentifiedRule :> MemoConsistencyRule
Property Value
Description Constraint that checks soup identified rule.
Kind constraint def
Abstract No
Specializes MemoConsistencyRule
Owning package memo_rules_closure

SoupRequirementRule

constraint def SoupRequirementRule :> MemoConsistencyRule
Property Value
Description Constraint that checks soup requirement rule.
Kind constraint def
Abstract No
Specializes MemoConsistencyRule
Owning package memo_rules_closure

UnitDecompositionRule

constraint def UnitDecompositionRule :> MemoConsistencyRule
Property Value
Description Constraint that checks unit decomposition rule.
Kind constraint def
Abstract No
Specializes MemoConsistencyRule
Owning package memo_rules_closure

ChangeImpactRule

constraint def ChangeImpactRule :> MemoConsistencyRule
Property Value
Description Constraint that checks change impact rule.
Kind constraint def
Abstract No
Specializes MemoConsistencyRule
Owning package memo_rules_closure

ChangeApprovalRule

constraint def ChangeApprovalRule :> MemoConsistencyRule
Property Value
Description Constraint that checks change approval rule.
Kind constraint def
Abstract No
Specializes MemoConsistencyRule
Owning package memo_rules_closure

ChangeTraceRule

constraint def ChangeTraceRule :> MemoConsistencyRule
Property Value
Description Constraint that checks change trace rule.
Kind constraint def
Abstract No
Specializes MemoConsistencyRule
Owning package memo_rules_closure

Source

rules/closure/closure_rules.sysml
// Closure consistency rules. Portable SysML bodies remain literal `true` where
// cross-model navigation is not resolvable by a general SysML compiler; MEMO
// compiles the ontology-owned `predicateExpression` against the semantic model.
package memo_rules_closure {
    private import ScalarValues::*;

    private import memo_core_consistency_rules::*;
    private import memo_core_enumerations::*;

    private import memo_core_common::*;
    private import memo_core_common::MemoIdentity;
    private import memo_artifacts_standards_traceability::EnforcesClause;
    private import memo_artifacts_standards_fda_cybersecurity_2023::*;
    private import memo_artifacts_standards_iec_62304::*;
    private import memo_artifacts_standards_iec_62366_1::*;
    private import memo_artifacts_standards_iso_13485::*;
    private import memo_artifacts_standards_iso_14971::*;
    // ─── Risk Layer Rules ────────────────────────────────────────────────

    constraint def HazardMitigationRule :> MemoConsistencyRule {
        @MemoIdentity { :>> providedId = "CR-MED-001"; }
        attribute tailoring = RuleTailoringKind::assurance;
        attribute domain = RuleDomainKind::medicalDevice;
        attribute obligation = RuleObligationKind::required;
        attribute appliesTo = "Hazard";
        attribute severity = RuleSeverityKind::error;
        attribute rationaleText = "ISO 14971 requires each identified hazard to have risk control measures.";
        attribute predicateExpression = "mitigates->size() >= 1";
        constraint { true }
    }
    #EnforcesClause dependency from HazardMitigationRule to iso14971::iso14971Clause7::iso14971Clause7_1;

    constraint def HazardSeverityRule :> MemoConsistencyRule {
        @MemoIdentity { :>> providedId = "CR-MED-002"; }
        attribute tailoring = RuleTailoringKind::assurance;
        attribute domain = RuleDomainKind::medicalDevice;
        attribute obligation = RuleObligationKind::required;
        attribute appliesTo = "Hazard";
        attribute severity = RuleSeverityKind::error;
        attribute rationaleText = "Hazard severity is required for risk estimation per ISO 14971.";
        attribute predicateExpression = "attributes.severity != ''";
        constraint { true }
    }
    #EnforcesClause dependency from HazardSeverityRule to iso14971::iso14971Clause5::iso14971Clause5_5;

    constraint def RiskControlVerificationRule :> MemoConsistencyRule {
        @MemoIdentity { :>> providedId = "CR-MED-003"; }
        attribute tailoring = RuleTailoringKind::assurance;
        attribute domain = RuleDomainKind::medicalDevice;
        attribute obligation = RuleObligationKind::required;
        // Note: ISO 14971:2019 puts verification of the implementation and effectiveness of a risk control measure in 7.2; the rule text used to say 7.4, which is benefit-risk analysis.
        attribute appliesTo = "RiskControlMeasure";
        attribute severity = RuleSeverityKind::error;
        attribute rationaleText = "Risk controls shall be verified per ISO 14971 clause 7.2.";
        attribute predicateExpression = "verifiedBy->size() >= 1";
        constraint { true }
    }
    #EnforcesClause dependency from RiskControlVerificationRule to iso14971::iso14971Clause7::iso14971Clause7_2;

    constraint def InitialRiskMatrixRule :> MemoConsistencyRule {
        @MemoIdentity { :>> providedId = "CR-MED-004"; }
        attribute tailoring = RuleTailoringKind::assurance;
        attribute domain = RuleDomainKind::medicalDevice;
        attribute obligation = RuleObligationKind::required;
        // To confirm: inferred from the clause scope, the rule text names no clause; confirm.
        attribute appliesTo = "Risk";
        attribute severity = RuleSeverityKind::warning;
        attribute rationaleText = "Pre-mitigation risk must be assessed against a risk acceptability matrix.";
        attribute predicateExpression = "assessedAgainst->size() >= 1";
        constraint { true }
    }
    #EnforcesClause dependency from InitialRiskMatrixRule to iso14971::iso14971Clause6;

    // ─── Requirements Layer Rules ────────────────────────────────────────

    constraint def SysReqTraceRule :> MemoConsistencyRule {
        @MemoIdentity { :>> providedId = "CR-MED-010"; }
        attribute tailoring = RuleTailoringKind::assurance;
        attribute domain = RuleDomainKind::medicalDevice;
        attribute obligation = RuleObligationKind::required;
        // To confirm: inferred from the clause scope; confirm.
        attribute appliesTo = "Requirement[requirementType=system]";
        attribute severity = RuleSeverityKind::error;
        attribute rationaleText = "Requirements shall be traceable to stakeholder needs per ISO 13485.";
        attribute predicateExpression = "derivesFrom->size() >= 1";
        constraint { true }
    }
    #EnforcesClause dependency from SysReqTraceRule to iso13485::iso13485Clause7::iso13485Clause7_3::iso13485Clause7_3_3;

    constraint def SwReqTraceRule :> MemoConsistencyRule {
        @MemoIdentity { :>> providedId = "CR-MED-011"; }
        attribute tailoring = RuleTailoringKind::assurance;
        attribute domain = RuleDomainKind::medicalDevice;
        attribute obligation = RuleObligationKind::required;
        attribute appliesTo = "Requirement[requirementType=software]";
        attribute severity = RuleSeverityKind::error;
        attribute rationaleText = "Software requirements derive from system requirements per IEC 62304.";
        attribute predicateExpression = "derivesFrom->size() >= 1";
        constraint { true }
    }
    #EnforcesClause dependency from SwReqTraceRule to iec62304::iec62304Clause5::iec62304Clause5_2::iec62304Clause5_2_1;

    // CR-MED-012 (RequirementIdMustBeUnique) is intentionally omitted from the native
    // constraint set: cross-element uniqueness is not a single-subject predicate and
    // cannot be expressed as a `constraint { … }` body over one Requirement.
    // It remains an engine-level check.
    // Do not reintroduce the `predicate="uniqueAttribute"` part.

    // ─── Architecture Layer Rules ────────────────────────────────────────

    constraint def SwComponentSafetyClassRule :> MemoConsistencyRule {
        @MemoIdentity { :>> providedId = "CR-MED-020"; }
        attribute tailoring = RuleTailoringKind::assurance;
        attribute domain = RuleDomainKind::medicalDevice;
        attribute obligation = RuleObligationKind::required;
        attribute appliesTo = "SoftwareModule";
        attribute severity = RuleSeverityKind::error;
        attribute rationaleText = "IEC 62304 requires safety classification for all software items.";
        attribute predicateExpression = "attributes.safetyClass != ''";
        constraint { true }
    }
    #EnforcesClause dependency from SwComponentSafetyClassRule to iec62304::iec62304Clause4::iec62304Clause4_3;

    constraint def SwComponentReqRule :> MemoConsistencyRule {
        @MemoIdentity { :>> providedId = "CR-MED-021"; }
        attribute tailoring = RuleTailoringKind::assurance;
        attribute domain = RuleDomainKind::medicalDevice;
        attribute obligation = RuleObligationKind::recommended;
        attribute appliesTo = "SoftwareModule";
        attribute severity = RuleSeverityKind::warning;
        attribute rationaleText = "Software items shall be linked to their requirements per IEC 62304.";
        attribute predicateExpression = "satisfiedBy->size() >= 1";
        constraint { true }
    }

    constraint def LogicalFunctionAllocationRule :> MemoConsistencyRule {
        @MemoIdentity { :>> providedId = "CR-MED-022"; }
        attribute tailoring = RuleTailoringKind::assurance;
        attribute domain = RuleDomainKind::modelling;
        attribute obligation = RuleObligationKind::recommended;
        attribute appliesTo = "SystemFunction";
        attribute severity = RuleSeverityKind::warning;
        attribute rationaleText = "Functions should be allocated to implementation elements. A function definition is a type and is not allocated; its usages are.";
        attribute predicateExpression = "isDefinition == 'true' or allocatedTo->size() >= 1";
        constraint { true }
    }

    // A function that no edge reaches is not in the chain. This was a
    // TypeScript rule (BV-002) applying to every action usage in the model,
    // which reported a scenario and a flow step as defects for not being
    // wired like a function. It is declared here instead: scoped by the
    // ontology to the family it is about, tailorable by a methodology, and
    // readable next to the rule that requires the allocation.
    constraint def FunctionInChainRule :> MemoConsistencyRule {
        @MemoIdentity { :>> providedId = "CR-MED-023"; }
        attribute tailoring = RuleTailoringKind::assurance;
        attribute domain = RuleDomainKind::modelling;
        attribute obligation = RuleObligationKind::recommended;
        attribute appliesTo = "MemoFunction";
        attribute severity = RuleSeverityKind::warning;
        attribute rationaleText = "A function participates in the functional chain through a flow or a succession, through the functions it decomposes into, or by being performed — by a functional chain, or by the action that triggers it. One that participates in none of them is unreachable behaviour: nothing triggers it and nothing consumes what it produces.";
        // `downstream` and not a bare `composes`: the relation navigates both
        // ways, so a bare name would exempt every child on the strength of
        // having a parent. A decomposed function participates through its
        // parts; a leaf has to be reached by an edge of its own.
        //
        // `upstream(performs)`: a `perform` IS participation. A functional
        // chain names its steps that way, and a UI action performing a
        // function is what triggers it. Without it the rule reported gpca-pump's
        // startup chain's own two steps, and ui-screen-regions' two functions
        // that a control invokes, as reached by nothing.
        attribute predicateExpression = "isDefinition == 'true' or flow->size() >= 1 or succession->size() >= 1 or downstream(composes)->size() >= 1 or upstream(performs)->size() >= 1";
        constraint { true }
    }

    // A user need names the user whose need it is. IEC 62366-1's user profile
    // is typed on the User element — population, impairments, training,
    // qualification — so the need points at that element rather than restating
    // any of it in prose, which is what `userPopulationReference` was doing.
    constraint def UserNeedIdentifiesUserRule :> MemoConsistencyRule {
        @MemoIdentity { :>> providedId = "CR-MED-024"; }
        attribute tailoring = RuleTailoringKind::assurance;
        attribute domain = RuleDomainKind::medicalDevice;
        attribute obligation = RuleObligationKind::required;
        attribute appliesTo = "Need";
        attribute severity = RuleSeverityKind::warning;
        attribute rationaleText = "A user need is a need someone has. Which users a device serves, and what they can be assumed to see, know and do, is the input a usability engineering file is built from (IEC 62366-1 5.1); a need that names no user leaves that input to prose.";
        attribute predicateExpression = "not(needKind == 'user' or needKind == 'clinicalUser' or needKind == 'patientUser') or heldBy->size() >= 1";
        constraint { true }
    }
    #EnforcesClause dependency from UserNeedIdentifiesUserRule to iec62366_1::iec62366_1Clause5::iec62366_1Clause5_1;

    // ─── Verification Layer Rules ────────────────────────────────────────

    constraint def VerificationCaseMethodRule :> MemoConsistencyRule {
        @MemoIdentity { :>> providedId = "CR-MED-030"; }
        attribute tailoring = RuleTailoringKind::assurance;
        attribute domain = RuleDomainKind::medicalDevice;
        attribute obligation = RuleObligationKind::recommended;
        attribute appliesTo = "VerificationCase";
        attribute severity = RuleSeverityKind::error;
        attribute rationaleText = "Verification method (test, analysis, inspection, demonstration) required per IEC 62304.";
        attribute predicateExpression = "attributes.methodKind != ''";
        constraint { true }
    }

    constraint def VerificationCaseTargetRule :> MemoConsistencyRule {
        @MemoIdentity { :>> providedId = "CR-MED-031"; }
        attribute tailoring = RuleTailoringKind::assurance;
        attribute domain = RuleDomainKind::medicalDevice;
        attribute obligation = RuleObligationKind::recommended;
        attribute appliesTo = "VerificationCase";
        attribute severity = RuleSeverityKind::error;
        attribute rationaleText = "Verification cases must be linked to verifiable items.";
        attribute predicateExpression = "verifiedBy->size() >= 1";
        constraint { true }
    }

    constraint def EvidenceProductionRule :> MemoConsistencyRule {
        @MemoIdentity { :>> providedId = "CR-MED-032"; }
        attribute tailoring = RuleTailoringKind::assurance;
        attribute domain = RuleDomainKind::medicalDevice;
        attribute obligation = RuleObligationKind::recommended;
        attribute appliesTo = "VerificationCase";
        attribute severity = RuleSeverityKind::warning;
        attribute rationaleText = "Verification results should be documented as evidence records.";
        attribute predicateExpression = "producesEvidence->size() >= 1";
        constraint { true }
    }

    // ─── Cybersecurity Layer Rules ───────────────────────────────────────

    constraint def ThreatMitigationRule :> MemoConsistencyRule {
        @MemoIdentity { :>> providedId = "CR-MED-040"; }
        attribute tailoring = RuleTailoringKind::assurance;
        attribute domain = RuleDomainKind::medicalDevice;
        attribute obligation = RuleObligationKind::required;
        // To confirm: inferred from the section scope; confirm.
        attribute appliesTo = "Threat";
        attribute severity = RuleSeverityKind::error;
        attribute rationaleText = "FDA cybersecurity guidance requires threat mitigation.";
        attribute predicateExpression = "derivesCyberRequirement->size() >= 1";
        constraint { true }
    }
    #EnforcesClause dependency from ThreatMitigationRule to fdaCybersecurity2023::fdaCyberSection5::fdaCyberSection5A;

    constraint def AssetThreatLinkRule :> MemoConsistencyRule {
        @MemoIdentity { :>> providedId = "CR-MED-041"; }
        attribute tailoring = RuleTailoringKind::assurance;
        attribute domain = RuleDomainKind::medicalDevice;
        attribute obligation = RuleObligationKind::required;
        // To confirm: inferred from the section scope; confirm.
        attribute appliesTo = "CybersecurityAsset";
        attribute severity = RuleSeverityKind::warning;
        attribute rationaleText = "Assets should have threat analysis per FDA cybersecurity guidance.";
        attribute predicateExpression = "threatenedBy->size() >= 1";
        constraint { true }
    }
    #EnforcesClause dependency from AssetThreatLinkRule to fdaCybersecurity2023::fdaCyberSection5::fdaCyberSection5A;

    // ─── Interface Rules ─────────────────────────────────────────────────

    constraint def LogicalInterfaceDirectionRule :> MemoConsistencyRule {
        @MemoIdentity { :>> providedId = "CR-MED-050"; }
        attribute tailoring = RuleTailoringKind::assurance;
        attribute domain = RuleDomainKind::modelling;
        attribute obligation = RuleObligationKind::recommended;
        attribute appliesTo = "Interface";
        attribute severity = RuleSeverityKind::error;
        attribute rationaleText = "Interface direction required for integration analysis.";
        attribute predicateExpression = "attributes.direction != ''";
        constraint { true }
    }

    // ─── Conditional Rules ───────────────────────────────────────────────

    constraint def SafetyClassCVerificationRule :> MemoConsistencyRule {
        @MemoIdentity { :>> providedId = "CR-MED-101"; }
        attribute tailoring = RuleTailoringKind::assurance;
        attribute domain = RuleDomainKind::medicalDevice;
        attribute obligation = RuleObligationKind::required;
        attribute appliesTo = "SoftwareModule";
        attribute severity = RuleSeverityKind::error;
        attribute rationaleText = "IEC 62304 requires rigorous verification for Class C software.";
        attribute predicateExpression = "not(attributes.safetyClass == 'C') or verifiedBy->size() >= 1";
        // To confirm: inferred: 5.5.4 and 5.5.5 are the unit verification clauses that Class C adds to; confirm.
        constraint { true }
    }
    #EnforcesClause dependency from SafetyClassCVerificationRule to iec62304::iec62304Clause5::iec62304Clause5_5::iec62304Clause5_5_4, iec62304::iec62304Clause5::iec62304Clause5_5::iec62304Clause5_5_5;

    // ─── UI Layout Rules ─────────────────────────────────────────────────
    //
    // Traceability only: every part of a screen must have a design record
    // behind it, and captured evidence must say where it came from.
    //
    // Scope is traceability, not geometry. Layout correctness (child within
    // parent, inline siblings disjoint) is checked where the geometry is drawn,
    // in the renderer: a pairwise sibling comparison has no KerML constraint
    // form, since the evaluator has no Real literal and binds one implicit
    // subject per quantifier.

    // The load-bearing traceability rule. A UI element that is not chrome must
    // reach a design record — a requirement it satisfies, or an action it
    // triggers. Chrome must be DECLARED `decoration`; an element left
    // unclassified fails rather than passing as scenery.
    constraint def UiElementDesignRecordRule :> MemoConsistencyRule {
        @MemoIdentity { :>> providedId = "CR-MED-110"; }
        attribute tailoring = RuleTailoringKind::assurance;
        attribute domain = RuleDomainKind::modelling;
        attribute obligation = RuleObligationKind::recommended;
        attribute appliesTo = "UIElement";
        attribute severity = RuleSeverityKind::error;
        attribute rationaleText = "Every functional UI element must have a design record — a requirement it satisfies or an action it triggers. Elements with formKind `decoration` are chrome and are exempt.";
        attribute predicateExpression = "attributes.formKind == 'decoration' or satisfiedBy->size() >= 1 or elementTriggersAction->size() >= 1";
        constraint { true }
    }

    // Interactive UI is where use error happens (IEC 62366-1), so a control
    // that reaches no system function is either dead UI or unmodelled UI.
    // The interactive-form restriction lives in the predicate because it spans
    // several enum values.
    constraint def ControlInvokesFunctionRule :> MemoConsistencyRule {
        @MemoIdentity { :>> providedId = "CR-MED-111"; }
        attribute tailoring = RuleTailoringKind::assurance;
        attribute domain = RuleDomainKind::modelling;
        attribute obligation = RuleObligationKind::recommended;
        attribute appliesTo = "UIElement";
        attribute severity = RuleSeverityKind::warning;
        attribute rationaleText = "An interactive UI element (button, selector, slider, field) should trigger a UIAction that invokes a system function; otherwise the control's purpose is not in the model. Physical controls are OperatorInterfaceElement and are covered separately.";
        attribute predicateExpression = "not(formKind == 'button' or formKind == 'selector' or formKind == 'slider' or formKind == 'field') or elementTriggersAction->size() >= 1";
        constraint { true }
    }

    // Automatic boundary detection proposes; a reviewer disposes. An
    // unconfirmed machine guess must never reach a design review looking like
    // an engineering decision.
    constraint def BoundsDetectionConfirmedRule :> MemoConsistencyRule {
        @MemoIdentity { :>> providedId = "CR-MED-112"; }
        attribute tailoring = RuleTailoringKind::assurance;
        attribute domain = RuleDomainKind::modelling;
        attribute obligation = RuleObligationKind::recommended;
        attribute appliesTo = "UIElement";
        attribute severity = RuleSeverityKind::warning;
        attribute rationaleText = "Automatically detected bounds are a proposal until a reviewer confirms them; released UI documentation should contain no unconfirmed automatic bounds.";
        attribute predicateExpression = "not(attributes.detectionMethod == 'automatic') or attributes.confirmedBy != ''";
        constraint { true }
    }

    // A screenshot with no build behind it is undated design intent, not
    // evidence of what the device does.
    constraint def ScreenCaptureProvenanceRule :> MemoConsistencyRule {
        @MemoIdentity { :>> providedId = "CR-MED-113"; }
        attribute tailoring = RuleTailoringKind::assurance;
        attribute domain = RuleDomainKind::modelling;
        attribute obligation = RuleObligationKind::recommended;
        attribute appliesTo = "ScreenCapture";
        attribute severity = RuleSeverityKind::error;
        attribute rationaleText = "A screen capture used as design or usability evidence must identify the build it was taken from and hash the image bytes, or it cannot be relied on in the DHF.";
        attribute predicateExpression = "attributes.capturedBuild != '' and attributes.imageHash != ''";
        constraint { true }
    }

    // ─── Risk analysis and software lifecycle rules (clause by clause) ─────
    // Written from the classification in plans/memo-rules-domain-trace-and-editor.md
    // (Step 5): each checks a property the model carries, and each traces to the clause it enforces.

    constraint def HazardHasSituationRule :> MemoConsistencyRule {
        @MemoIdentity { :>> providedId = "CR-MED-005"; }
        attribute tailoring = RuleTailoringKind::assurance;
        attribute domain = RuleDomainKind::medicalDevice;
        attribute obligation = RuleObligationKind::required;
        attribute appliesTo = "Hazard";
        attribute severity = RuleSeverityKind::warning;
        attribute rationaleText = "A hazard is analysed through the hazardous situations it can lead to: a hazard that reaches no hazardous situation has not been analysed far enough to estimate a risk.";
        attribute predicateExpression = "downstream(tracesRisk)->exists(conformsTo(HazardousSituation))";
        constraint { true }
    }
    #EnforcesClause dependency from HazardHasSituationRule to iso14971::iso14971Clause5::iso14971Clause5_4;

    constraint def SituationLeadsToHarmRule :> MemoConsistencyRule {
        @MemoIdentity { :>> providedId = "CR-MED-006"; }
        attribute tailoring = RuleTailoringKind::assurance;
        attribute domain = RuleDomainKind::medicalDevice;
        attribute obligation = RuleObligationKind::required;
        attribute appliesTo = "HazardousSituation";
        attribute severity = RuleSeverityKind::warning;
        attribute rationaleText = "A hazardous situation is described by the harm it can cause; one that reaches no harm leaves the severity of the risk unestimated.";
        attribute predicateExpression = "downstream(tracesRisk)->exists(conformsTo(Harm))";
        constraint { true }
    }
    #EnforcesClause dependency from SituationLeadsToHarmRule to iso14971::iso14971Clause5::iso14971Clause5_4;

    constraint def RiskEstimateRule :> MemoConsistencyRule {
        @MemoIdentity { :>> providedId = "CR-MED-007"; }
        attribute tailoring = RuleTailoringKind::assurance;
        attribute domain = RuleDomainKind::medicalDevice;
        attribute obligation = RuleObligationKind::required;
        attribute appliesTo = "Risk";
        attribute severity = RuleSeverityKind::warning;
        attribute rationaleText = "A risk is estimated from the probability of occurrence and the severity of the harm; a risk missing either has no estimate.";
        attribute predicateExpression = "attributes.probabilityEstimate != '' and attributes.severityEstimate != ''";
        constraint { true }
    }
    #EnforcesClause dependency from RiskEstimateRule to iso14971::iso14971Clause5::iso14971Clause5_5;

    constraint def RiskAcceptabilityRule :> MemoConsistencyRule {
        @MemoIdentity { :>> providedId = "CR-MED-008"; }
        attribute tailoring = RuleTailoringKind::assurance;
        attribute domain = RuleDomainKind::medicalDevice;
        attribute obligation = RuleObligationKind::required;
        attribute appliesTo = "Risk";
        attribute severity = RuleSeverityKind::warning;
        attribute rationaleText = "Each estimated risk is evaluated against the acceptability criteria, so a risk states whether it is acceptable.";
        attribute predicateExpression = "attributes.acceptability != ''";
        constraint { true }
    }
    #EnforcesClause dependency from RiskAcceptabilityRule to iso14971::iso14971Clause6;

    constraint def ResidualRiskAcceptabilityRule :> MemoConsistencyRule {
        @MemoIdentity { :>> providedId = "CR-MED-009"; }
        attribute tailoring = RuleTailoringKind::assurance;
        attribute domain = RuleDomainKind::medicalDevice;
        attribute obligation = RuleObligationKind::required;
        attribute appliesTo = "ResidualRisk";
        attribute severity = RuleSeverityKind::warning;
        attribute rationaleText = "After risk control the residual risk is evaluated: it follows a control and states whether it is acceptable.";
        attribute predicateExpression = "reducedBy->size() >= 1 and attributes.acceptability != ''";
        constraint { true }
    }
    #EnforcesClause dependency from ResidualRiskAcceptabilityRule to iso14971::iso14971Clause7::iso14971Clause7_3;

    constraint def ResidualRiskEvaluatedRule :> MemoConsistencyRule {
        @MemoIdentity { :>> providedId = "CR-MED-014"; }
        attribute tailoring = RuleTailoringKind::assurance;
        attribute domain = RuleDomainKind::medicalDevice;
        attribute obligation = RuleObligationKind::required;
        attribute appliesTo = "ResidualRisk";
        attribute severity = RuleSeverityKind::warning;
        attribute rationaleText = "The overall residual risk is evaluated from the individual residual risks, so each residual risk is an input to that evaluation.";
        attribute predicateExpression = "evaluatedIn->size() >= 1";
        constraint { true }
    }
    #EnforcesClause dependency from ResidualRiskEvaluatedRule to iso14971::iso14971Clause8;

    // ISO 14971 clauses 5.2, 5.3 and 7.4 on the links the model already has: a misuse is not an item of the risk
    // chain, so it reaches the chain by `causes` (the risk can start at any element: an operational flow, an
    // FMEA row, a use error, a misuse); a safety-related characteristic reaches a hazard by `impactsSafety`; a
    // benefit is weighed against a risk by `weighedAgainst`.
    constraint def MisuseReachesSituationRule :> MemoConsistencyRule {
        @MemoIdentity { :>> providedId = "CR-MED-027"; }
        attribute tailoring = RuleTailoringKind::assurance;
        attribute domain = RuleDomainKind::medicalDevice;
        attribute obligation = RuleObligationKind::required;
        attribute appliesTo = "ReasonablyForeseeableMisuse";
        attribute severity = RuleSeverityKind::warning;
        attribute rationaleText = "Reasonably foreseeable misuse is an input to the risk analysis: a misuse that leads to no hazardous situation has not been analysed, and one that is not recorded as leading anywhere cannot be shown to have been considered.";
        attribute predicateExpression = "downstream(causes)->exists(conformsTo(HazardousSituation) or downstream(tracesRisk)->exists(conformsTo(HazardousSituation)))";
        constraint { true }
    }
    #EnforcesClause dependency from MisuseReachesSituationRule to iso14971::iso14971Clause5::iso14971Clause5_2;

    constraint def CharacteristicReachesHazardRule :> MemoConsistencyRule {
        @MemoIdentity { :>> providedId = "CR-MED-028"; }
        attribute tailoring = RuleTailoringKind::assurance;
        attribute domain = RuleDomainKind::medicalDevice;
        attribute obligation = RuleObligationKind::required;
        attribute appliesTo = "SafetyRelatedCharacteristic";
        attribute severity = RuleSeverityKind::warning;
        attribute rationaleText = "A characteristic that could affect safety is identified so that the hazards it bears on are analysed: one linked to no hazard has been identified and then left unused.";
        attribute predicateExpression = "downstream(impactsSafety)->exists(conformsTo(RiskItem))";
        constraint { true }
    }
    #EnforcesClause dependency from CharacteristicReachesHazardRule to iso14971::iso14971Clause5::iso14971Clause5_3;

    constraint def BenefitRiskWeighedRule :> MemoConsistencyRule {
        @MemoIdentity { :>> providedId = "CR-MED-029"; }
        attribute tailoring = RuleTailoringKind::assurance;
        attribute domain = RuleDomainKind::medicalDevice;
        attribute obligation = RuleObligationKind::required;
        attribute appliesTo = "ResidualRisk";
        attribute severity = RuleSeverityKind::warning;
        attribute rationaleText = "Where a residual risk calls for a benefit-risk analysis, the benefit it is weighed against is stated.";
        attribute predicateExpression = "attributes.benefitRiskRequired != 'true' or upstream(weighedAgainst)->exists(conformsTo(Benefit))";
        constraint { true }
    }
    #EnforcesClause dependency from BenefitRiskWeighedRule to iso14971::iso14971Clause7::iso14971Clause7_4;

    constraint def SoupAnomaliesRule :> MemoConsistencyRule {
        @MemoIdentity { :>> providedId = "CR-MED-015"; }
        attribute tailoring = RuleTailoringKind::assurance;
        attribute domain = RuleDomainKind::medicalDevice;
        attribute obligation = RuleObligationKind::required;
        attribute appliesTo = "SOUPSoftwareModule";
        attribute severity = RuleSeverityKind::warning;
        attribute rationaleText = "The published anomaly list of a SOUP item is evaluated for anomalies that could lead to a hazardous situation, and the result is recorded on the item.";
        attribute predicateExpression = "attributes.knownAnomalies != ''";
        constraint { true }
    }
    #EnforcesClause dependency from SoupAnomaliesRule to iec62304::iec62304Clause7::iec62304Clause7_1::iec62304Clause7_1_3;

    constraint def SoupIdentifiedRule :> MemoConsistencyRule {
        @MemoIdentity { :>> providedId = "CR-MED-016"; }
        attribute tailoring = RuleTailoringKind::assurance;
        attribute domain = RuleDomainKind::medicalDevice;
        attribute obligation = RuleObligationKind::required;
        attribute appliesTo = "SOUPSoftwareModule";
        attribute severity = RuleSeverityKind::warning;
        attribute rationaleText = "A SOUP item is identified under configuration management by its title, manufacturer and version, so a SOUP item states a vendor and a version.";
        attribute predicateExpression = "attributes.version != '' and attributes.supplier != ''";
        constraint { true }
    }
    #EnforcesClause dependency from SoupIdentifiedRule to iec62304::iec62304Clause8::iec62304Clause8_1::iec62304Clause8_1_2;

    constraint def SoupRequirementRule :> MemoConsistencyRule {
        @MemoIdentity { :>> providedId = "CR-MED-017"; }
        attribute tailoring = RuleTailoringKind::assurance;
        attribute domain = RuleDomainKind::medicalDevice;
        attribute obligation = RuleObligationKind::required;
        attribute appliesTo = "SOUPSoftwareModule";
        attribute severity = RuleSeverityKind::warning;
        attribute rationaleText = "The functional and performance a software item needs from a SOUP item are stated as requirements, so a SOUP item is the subject of at least one requirement.";
        attribute predicateExpression = "satisfiedBy->size() >= 1";
        constraint { true }
    }
    #EnforcesClause dependency from SoupRequirementRule to iec62304::iec62304Clause5::iec62304Clause5_3::iec62304Clause5_3_3;

    constraint def UnitDecompositionRule :> MemoConsistencyRule {
        @MemoIdentity { :>> providedId = "CR-MED-018"; }
        attribute tailoring = RuleTailoringKind::assurance;
        attribute domain = RuleDomainKind::medicalDevice;
        attribute obligation = RuleObligationKind::required;
        attribute appliesTo = "SoftwareModule";
        attribute severity = RuleSeverityKind::warning;
        attribute rationaleText = "A software item of safety class B or C is subdivided into software units, so such an item contains at least one module of kind unit.";
        attribute predicateExpression = "not(attributes.moduleKind == 'item' and (attributes.safetyClass == 'B' or attributes.safetyClass == 'C')) or downstream(composes)->exists(attributes.moduleKind == 'unit')";
        constraint { true }
    }
    #EnforcesClause dependency from UnitDecompositionRule to iec62304::iec62304Clause5::iec62304Clause5_4::iec62304Clause5_4_1;

    constraint def ChangeImpactRule :> MemoConsistencyRule {
        @MemoIdentity { :>> providedId = "CR-MED-019"; }
        attribute tailoring = RuleTailoringKind::assurance;
        attribute domain = RuleDomainKind::medicalDevice;
        attribute obligation = RuleObligationKind::required;
        attribute appliesTo = "ChangeRequest";
        attribute severity = RuleSeverityKind::warning;
        attribute rationaleText = "A change request is analysed for its effect on the organisation, the released software and the systems that interface with it, and the analysis is recorded on the request.";
        attribute predicateExpression = "attributes.impactAssessment != ''";
        constraint { true }
    }
    #EnforcesClause dependency from ChangeImpactRule to iec62304::iec62304Clause6::iec62304Clause6_2::iec62304Clause6_2_3;

    constraint def ChangeApprovalRule :> MemoConsistencyRule {
        @MemoIdentity { :>> providedId = "CR-MED-025"; }
        attribute tailoring = RuleTailoringKind::assurance;
        attribute domain = RuleDomainKind::medicalDevice;
        attribute obligation = RuleObligationKind::required;
        attribute appliesTo = "ChangeRequest";
        attribute severity = RuleSeverityKind::warning;
        attribute rationaleText = "A change request records whether it was approved before the change is made.";
        attribute predicateExpression = "attributes.approvalStatus != ''";
        constraint { true }
    }
    #EnforcesClause dependency from ChangeApprovalRule to iec62304::iec62304Clause6::iec62304Clause6_2::iec62304Clause6_2_4, iec62304::iec62304Clause8::iec62304Clause8_2::iec62304Clause8_2_1;

    constraint def ChangeTraceRule :> MemoConsistencyRule {
        @MemoIdentity { :>> providedId = "CR-MED-026"; }
        attribute tailoring = RuleTailoringKind::assurance;
        attribute domain = RuleDomainKind::medicalDevice;
        attribute obligation = RuleObligationKind::required;
        attribute appliesTo = "ChangeRequest";
        attribute severity = RuleSeverityKind::warning;
        attribute rationaleText = "A change request is traceable to the items it changes, so it has a changes relation to at least one element.";
        attribute predicateExpression = "changes->size() >= 1";
        constraint { true }
    }
    #EnforcesClause dependency from ChangeTraceRule to iec62304::iec62304Clause8::iec62304Clause8_2::iec62304Clause8_2_4;
}