From 78d944a285c4614c8dfaea8cbea617d321283a74 Mon Sep 17 00:00:00 2001 From: David Ingraham Date: Sat, 17 Oct 2026 09:08:02 -0700 Subject: [PATCH] feat: add qualitative failure analysis library and reusable views --- README.md | 25 +++++++++- engine-contract.json | 70 ++++++++++++++++++++++++++++ libraries/FailureAnalysis.sysml | 67 ++++++++++++++++++++++++++ libraries/FailureAnalysisViews.sysml | 20 ++++++++ libraries/OpenSysMLRenderings.sysml | 5 +- 5 files changed, 185 insertions(+), 2 deletions(-) create mode 100644 libraries/FailureAnalysis.sysml create mode 100644 libraries/FailureAnalysisViews.sysml diff --git a/README.md b/README.md index 479b66b..c44c85c 100644 --- a/README.md +++ b/README.md @@ -19,12 +19,14 @@ non-normative OpenSysML library; other tools resolve it when given the | AnalysisRecords | AnalysisRecords.sysml | Metadata a run, sweep or sample records itself with: when it ran, the tool and command, verdicts and evaluations. | Executing engine | | DiagramLayout | DiagramLayout.sysml | Diagram geometry: element placement, edge waypoints and the drawing extent. | Any SysML v2 tool | | DocumentQueries | DocumentQueries.sysml | Calc definitions (OwnedElements, Descendants, Ancestors, …) that document views evaluate to select elements. | Executing engine | +| FailureAnalysis | FailureAnalysis.sysml | RAAML-aligned qualitative event and AND/OR gate vocabulary, DFMEA rows and disposition checks; no probabilities or full RAAML conformance claim. | Any SysML v2 tool; execution requires an engine | +| FailureAnalysisViews | FailureAnalysisViews.sysml | Reusable fault-tree view and type-based DFMEA row query. | Executing engine | | IdentityMetadata | IdentityMetadata.sysml | Binds notation to repository element identity. | Any SysML v2 tool | | MOSA | MOSA.sysml | Modular Open Systems Approach (10 U.S.C. § 4401) vocabulary. | Any SysML v2 tool | | MigrationMetadata | MigrationMetadata.sysml | What a migration from another modelling language had to make up because the source left it unstated. | Any SysML v2 tool | | OOSEM | OOSEM.sysml | Object-Oriented Systems Engineering Method artefacts, viewpoints and product views. | Any SysML v2 tool | | OpenSysMLMathFunctions | OpenSysMLMathFunctions.kerml | exp, ln, log, atan2, ceiling and the Integer quotient the Kernel Function Library omits. | Executing engine | -| OpenSysMLRenderings | OpenSysMLRenderings.sysml | Renderings and views for case and mixed diagrams. `CaseView`/`asCaseDiagram` is a shorter way to write a standard `GeneralView` filtered on case-family metaclasses; the standard route is added by [OpenSysML#886](https://github.com/Open-MBEE/OpenSysML/pull/886). `MixedView`/`asMixedDiagram` is extension-only. | Any SysML v2 tool | +| OpenSysMLRenderings | OpenSysMLRenderings.sysml | Renderings and views for case, mixed and qualitative fault-tree diagrams. `CaseView`/`asCaseDiagram` is a shorter way to write a standard `GeneralView` filtered on case-family metaclasses; the standard route is added by [OpenSysML#886](https://github.com/Open-MBEE/OpenSysML/pull/886). `MixedView`/`asMixedDiagram` is extension-only. | Any SysML v2 tool | | RandomFunctions | RandomFunctions.kerml | Seeded random draws: uniform, uniformInteger, triangular, normal. | Executing engine | | Simulation | Simulation.sysml | How a behavior is meant to be run: run count, draw resolution, clock, Monte Carlo. | Executing engine | | StateActivity | StateActivity.kerml | `isActive`: a derived Boolean that is true while a state usage is in its state machine's active configuration. | Executing engine | @@ -109,3 +111,24 @@ longer emits. Apache-2.0. Every library was authored in OpenSysML; no OMG material is redistributed here. + +## Qualitative failure analysis + +The failure-analysis subset follows the basic/undeveloped/house event and AND/OR +concepts in [RAAML 1.1](https://www.omg.org/spec/RAAML/1.1). It is authored in SysML +v2; it does not import the UML profile or claim full RAAML conformance. Boolean +values describe one stated exposure interval, and unbound events remain unknown. +No probability, statistical independence or temporal ordering is inferred. + +Use standard `CauseAndEffect::Causation` connections between event usages. +`FailureAnalysisViews::FaultTreeView` requests gate glyphs and consistency checks +against the executable `inputs` references. A standard filtered interconnection +view can select these elements, but cannot request these gate symbols or the +agreement check; this is why the rendering needs an engine extension. + +`FailureAnalysisViews::ReviewRows` takes a qualified `reviewName` and selects its +owned descendant `ReviewRow` declarations, including specializations. It projects +referenced event descriptions, so adding rows needs no per-project renderer. +The query does not expand inherited runtime objects. The review readiness check +requires reviewed nonempty scope and accepted disposition/evidence with a nonempty +reference for each critical row; it is not a physical safety certification. diff --git a/engine-contract.json b/engine-contract.json index 27de973..c9041f7 100644 --- a/engine-contract.json +++ b/engine-contract.json @@ -524,6 +524,62 @@ "internal/ir/queryplan/compiler.go" ] }, + { + "name": "FailureAnalysis::AndGate", + "kind": "element", + "consumers": [ + "internal/ir/view/fault_tree.go" + ] + }, + { + "name": "FailureAnalysis::BasicEvent", + "kind": "element", + "consumers": [ + "internal/ir/view/fault_tree.go" + ] + }, + { + "name": "FailureAnalysis::Event", + "kind": "element", + "consumers": [ + "internal/ir/view/fault_tree.go" + ] + }, + { + "name": "FailureAnalysis::Gate", + "kind": "element", + "consumers": [ + "internal/ir/view/fault_tree.go" + ] + }, + { + "name": "FailureAnalysis::Gate::inputs", + "kind": "element", + "consumers": [ + "internal/ir/view/fault_tree.go" + ] + }, + { + "name": "FailureAnalysis::HouseEvent", + "kind": "element", + "consumers": [ + "internal/ir/view/fault_tree.go" + ] + }, + { + "name": "FailureAnalysis::OrGate", + "kind": "element", + "consumers": [ + "internal/ir/view/fault_tree.go" + ] + }, + { + "name": "FailureAnalysis::UndevelopedEvent", + "kind": "element", + "consumers": [ + "internal/ir/view/fault_tree.go" + ] + }, { "name": "IdentityMetadata::ElementId", "kind": "metadata", @@ -884,6 +940,13 @@ "internal/ir/view/view.go" ] }, + { + "name": "OpenSysMLRenderings::FaultTreeView", + "kind": "element", + "consumers": [ + "internal/ir/view/view.go" + ] + }, { "name": "OpenSysMLRenderings::MixedView", "kind": "element", @@ -898,6 +961,13 @@ "internal/ir/view/view.go" ] }, + { + "name": "OpenSysMLRenderings::asFaultTree", + "kind": "element", + "consumers": [ + "internal/ir/view/view.go" + ] + }, { "name": "OpenSysMLRenderings::asMixedDiagram", "kind": "element", diff --git a/libraries/FailureAnalysis.sysml b/libraries/FailureAnalysis.sysml new file mode 100644 index 0000000..a678865 --- /dev/null +++ b/libraries/FailureAnalysis.sysml @@ -0,0 +1,67 @@ +library package FailureAnalysis { + doc /* NON-NORMATIVE, RAAML-aligned qualitative failure analysis subset. + * Event/gate vocabulary follows RAAML 1.1 FTA; this is not the UML profile + * or a claim of RAAML conformance. No probabilities or independence inferred. + */ + private import ScalarValues::*; + occurrence def Event { + doc /* A proposition about an explicitly chosen exposure interval; present is unknown until bound. */ + attribute description : String; + attribute present : Boolean; + } + occurrence def BasicEvent :> Event { doc /* An event treated as a leaf within this analysis scope, without an assigned probability. */ } + occurrence def UndevelopedEvent :> Event { doc /* An event whose contributing causes remain to be developed. */ } + occurrence def HouseEvent :> Event { doc /* A scenario condition supplied as an explicit Boolean, not an inferred failure rate. */ } + abstract occurrence def Gate :> Event { + doc /* A proposition computed from referenced input events. */ + ref occurrence inputs : Event [1..*]; + } + occurrence def OrGate :> Gate { + doc /* True when at least one input proposition holds. */ + attribute :>> present = inputs->ControlFunctions::exists { in x : Event; x.present }; + } + occurrence def AndGate :> Gate { + doc /* True when every input holds in the same interval; no temporal ordering or independence is implied. */ + attribute :>> present = SequenceFunctions::size(inputs) > 0 and + inputs->ControlFunctions::forAll { in x : Event; x.present }; + } + analysis def Evaluate { doc /* Read an event proposition through the native analysis interface. */ subject proposition : Event; out attribute present : Boolean = proposition.present; } + part def ReviewRow { + doc /* A failure review and action record referencing events; not itself a failure occurrence. */ + attribute identifier : String; + ref part affected : Parts::Part; + attribute intendedFunction : String; + ref occurrence failureMode : Event; + ref occurrence cause : Event; + ref occurrence localEffect : Event; + ref occurrence missionEffect : Event; + attribute failureModeText : String = failureMode.description; + attribute causeText : String = cause.description; + attribute localEffectText : String = localEffect.description; + attribute missionEffectText : String = missionEffect.description; + attribute proposedDetection : String; + attribute recommendedAction : String; + attribute ownerRole : String; + attribute safetyCritical : Boolean; + attribute dispositionAccepted : Boolean default false; + attribute actionEvidenceAccepted : Boolean default false; + attribute evidenceReference : String default "Not yet available"; + } + part def Review { + doc /* An explicitly scoped review of a system, with one or more owned failure rows. */ + ref part system : Parts::Part; + part modes : ReviewRow [1..*]; + attribute scopeReviewed : Boolean; + } + analysis def DesignFailureReview { + doc /* Inventory and disposition checks only; declared evidence references do not establish physical adequacy. */ + subject review : Review; + out attribute modeCount : Integer = SequenceFunctions::size(review.modes); + out attribute safetyCriticalCount : Integer = SequenceFunctions::size(review.modes->ControlFunctions::select { in mode : ReviewRow; mode.safetyCritical }); + out attribute unresolvedCriticalCount : Integer = SequenceFunctions::size(review.modes->ControlFunctions::select { + in mode : ReviewRow; mode.safetyCritical and not (mode.dispositionAccepted and mode.actionEvidenceAccepted and mode.evidenceReference != "" and mode.evidenceReference != "Not yet available") }); + out attribute openActionCount : Integer = SequenceFunctions::size(review.modes->ControlFunctions::select { in mode : ReviewRow; not mode.actionEvidenceAccepted }); + return reviewReady : Boolean = modeCount > 0 and review.scopeReviewed and unresolvedCriticalCount == 0; + objective inventory { require constraint { modeCount > 0 } } + } +} diff --git a/libraries/FailureAnalysisViews.sysml b/libraries/FailureAnalysisViews.sysml new file mode 100644 index 0000000..d2c649b --- /dev/null +++ b/libraries/FailureAnalysisViews.sysml @@ -0,0 +1,20 @@ +library package FailureAnalysisViews { + doc /* NON-NORMATIVE views for the RAAML-aligned FailureAnalysis subset. + * Supply review scope as a qualified name; rows are selected by semantic type. + * The fault-tree rendering uses native types and standard Causation connections. + */ + private import DocumentQueries::*; + private import ScalarValues::*; + view def FaultTreeView :> OpenSysMLRenderings::FaultTreeView { doc /* A qualitative causal view with gate symbols; rendering requires a supporting engine. */ } + calc def ReviewRows :> Query { + doc /* Select owned descendant review rows by semantic type and project their referenced descriptions and actions. */ + in reviewName : String; + Project(source = WhereType(source = Descendants(source = Named(qualifiedName = reviewName)), + type = "FailureAnalysis::ReviewRow"), columns = ( + Column(name = "ID", path = "identifier"), + Column(name = "Function / scope", path = "intendedFunction"), + Column(name = "Cause", path = "causeText"), + Column(name = "Failure", path = "failureModeText"), + Column(name = "Action needed", path = "recommendedAction"))) + } +} diff --git a/libraries/OpenSysMLRenderings.sysml b/libraries/OpenSysMLRenderings.sysml index cdce24f..e97f14c 100644 --- a/libraries/OpenSysMLRenderings.sysml +++ b/libraries/OpenSysMLRenderings.sysml @@ -1,6 +1,6 @@ library package OpenSysMLRenderings { doc /* - * NON-NORMATIVE rendering vocabulary for case and mixed diagrams. + * NON-NORMATIVE rendering vocabulary for case, mixed and qualitative fault-tree diagrams. * Models using it are valid SysML v2 and depend on this OpenSysML library. */ @@ -9,6 +9,9 @@ library package OpenSysMLRenderings { rendering asCaseDiagram : GraphicalRendering[1] :> renderings; rendering asMixedDiagram : GraphicalRendering[1] :> renderings; + rendering asFaultTree : GraphicalRendering[1] :> renderings; + view def FaultTreeView { doc /* Qualitative failure events and semantic AND/OR gates; a filtered interconnection view cannot specify these gate glyphs or gate-input consistency checks. */ render asFaultTree; } + view def CaseView { render asCaseDiagram; }