Skip to content

Commit 37043e8

Browse files
hoe-jocastler
authored andcommitted
[rules score] link root causes directly to failure modes
- `safety_analysis` exports `TrlcProviderInfo` (fta_events + failure modes); AoU files with `root_causes` go to `assumptions_of_use` deps and to `safety_analysis(safetymeasures=...)` for coverage
1 parent 058d7de commit 37043e8

37 files changed

Lines changed: 964 additions & 889 deletions

‎.github/skills/score-requirements/SKILL.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ Requirement → description (Markup_String), version (Integer),
159159
RequirementSafety → + safety (Asil)
160160
AssumedSystemReq → + rationale (String)
161161
FeatReq → + derived_from (AssumedSystemReqId[1..*])
162-
CompReq → + derived_from (CompReqSourceId[1..*]) # FeatReq or AssumedSystemReq
162+
CompReq → + derived_from (CompReqSourceId[1..*]) # FeatReq, AssumedSystemReq, received AoU, or RootCause (control measure)
163163
```
164164

165165
- `description` is a `Markup_String` — it may contain `:term:` references and embedded

‎.github/skills/score-safety-analysis/SKILL.md‎

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ $RootCause("<Root cause label 2>", "<RootCauseAlias2>", "OG1")
159159
| `$TransferInGate(name, alias, connection)` | Link to sub-tree | parent alias |
160160

161161
**Rules:**
162-
- `$RootCause` alias is a plain identifier; the `puml_cli` FTA parser auto-generates a `fta_events.trlc` stub (imported as `<name>_fta`) containing a `RootCause` record named after that alias — `Mitigation`/`CompReq`/`AoU` records reference it explicitly (e.g. `root_causes = [sample_safety_analysis_fta.JustBadLuck]`); there is no implicit name-matching.
162+
- `$RootCause` alias is a plain identifier; the `puml_cli` FTA parser auto-generates a `fta_events.trlc` stub (imported as `<name>_fta`) containing a `RootCause` record named after that alias (its `failure_modes` lists the `FailureMode`s of the tree's `$FailureMode` root) — `Mitigation`/`CompReq`/`AoU` records reference it explicitly (e.g. `root_causes = [sample_safety_analysis_fta.JustBadLuck]`); there is no implicit name-matching.
163163
- Build top-down in the file: `$FailureMode` first, then gates, then `$RootCause` leaves.
164164
- The same `$RootCause` alias may appear in multiple FTAs (shared root cause).
165165
- `$OrGate` is the default for independent root causes; use `$AndGate` only when all causes must co-occur.
@@ -181,10 +181,15 @@ ScoreReq.Mitigation <RecordName> {
181181
```
182182

183183
Other ways to close a root cause:
184-
- `ScoreReq.CompReq` — closes it via `derived_from`, referencing the `RootCause` stub alongside any `FeatReq`/`AssumedSystemReq`/`AoU` it also derives from
185-
- `ScoreReq.AoU` — assumption the caller must satisfy; does **not** extend `SafetyMeasure` and has its own independent, optional `root_causes` field (no `justification` required)
184+
- `ScoreReq.CompReq` — closes it via `derived_from`, referencing the `RootCause` stub alongside any `FeatReq`/`AssumedSystemReq` it also derives from. An `AoU` in `derived_from` is only for an AoU **received** from another dependable element; the element's own AoUs are never a `derived_from` source
185+
- `ScoreReq.AoU` — own assumption the caller must satisfy; does **not** extend `SafetyMeasure` and has its own independent, optional `root_causes` field (no `justification` required)
186186

187-
**Rule:** every `$RootCause` alias must be referenced by at least one `Mitigation.root_causes`, `CompReq.derived_from`, or `AoU.root_causes` — this is validated by `bazel test` on the owning `dependability_analysis` target.
187+
**Rule:** every `$RootCause` alias must be referenced by at least one `Mitigation.root_causes`, `CompReq.derived_from`, or `AoU.root_causes`. This is checked by lobster in the traceability report of the enclosing `dependable_element` (Root Causes are covered via the Safety Measures level **or** the Component Requirements level; uncovered ones are reported as `missing reference to Component Requirements or Safety Measures`, and fail `bazel test <dependable_element>` with `maturity = "release"`). Only files passed as `safety_analysis.safetymeasures` form the Safety Measures level, so an AoU file with `root_causes` must be listed there **and** the `assumptions_of_use` target must list the `safety_analysis` target in `deps` (the generated `<fta_package>` package resolves only through it). Every AoU in a `safetymeasures` file must reference a root cause, otherwise it is reported as `missing up reference`; keep AoUs without `root_causes` in a separate file passed only to `assumptions_of_use`:
188+
189+
```python
190+
safety_analysis(name = "sa", safetymeasures = ["aou.trlc"], ...)
191+
assumptions_of_use(name = "aous", srcs = ["aou.trlc"], deps = [":sa"])
192+
```
188193

189194
## Step 4 — Update BUILD
190195

@@ -223,5 +228,7 @@ $RootCause alias → Mitigation.root_causes / CompReq.derived_from / AoU.r
223228
| `$FailureMode` fm1..fm8 argument does not match any TRLC record | Ensure `<Pkg>.<RecordName>` is spelled identically in both places |
224229
| A root cause (`$RootCause`) is not referenced by any `Mitigation`/`CompReq`/`AoU` | Add an explicit reference to the generated `<fta_package>.<Alias>` `RootCause` stub |
225230
| New `.puml` not in BUILD `fta_files` | Add the file path to the `srcs` list |
226-
| AoU added to `safetymeasures.trlc` | AoUs belong in `aous.trlc`; `AoU` does not extend `SafetyMeasure`, it has its own independent `root_causes` field |
231+
| AoU added to `safetymeasures.trlc` | AoUs belong in `aous.trlc`; `AoU` does not extend `SafetyMeasure`, it has its own independent `root_causes` field. If the AoU closes a root cause, pass `aous.trlc` as `safety_analysis.safetymeasures` (coverage) and add the `safety_analysis` target to `assumptions_of_use.deps` |
232+
| `CompReq.derived_from` references an own `AoU` | Only AoUs received from another dependable element belong there; own AoUs close root causes via `AoU.root_causes` |
233+
| Unknown symbol `<fta_package>` when parsing `aous.trlc` | Add the `safety_analysis` target to the `assumptions_of_use` `deps` |
227234
| Wrong RSL used for trlc validation | Always pass the tooling RSL as the first directory argument |

‎bazel/rules/rules_score/README.md‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,10 @@ safety_analysis(
149149
)
150150
```
151151

152-
**`bazel build`** — generates `safety_analysis.rst` (merged FM / Safety Measures / FTA sections),
152+
**`bazel build`** — generates `safety_analysis.rst` (failure modes with their root causes and measures, fault trees, safety measures),
153153
runs `lobster-trlc` on TRLC inputs, and extracts FTA events from `.puml`
154-
diagrams into `fta_events.trlc`. Build-only; traceability validation is done
154+
diagrams into `fta_events.trlc` (generated `RootCause` records, usable via the
155+
target's `TrlcProviderInfo`). Build-only; traceability validation is done
155156
by the wrapping `dependability_analysis` test.
156157

157158
---

‎bazel/rules/rules_score/docs/_assets/safety_analysis_doc_pipeline.puml‎

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -57,31 +57,33 @@ package "Tooling defaults (rules_score / ScoreReq)" {
5757
package "safety_analysis rule actions" {
5858
component "puml_cli (FTA mode)\n--fta-output-dir\n[crate: puml_fta]" <<tool>> as puml
5959
component "safety_analysis_assembler\n[lib: TRLCRST]" <<tool>> as asm
60-
component "lobster-trlc x4" <<tool>> as ltrlc
60+
component "lobster-trlc x3" <<tool>> as ltrlc
6161
}
6262

6363
' ── Generated files ──────────────────────────────────────────────────────────
6464
package "Generated files" {
6565
rectangle "fta_*.puml\n(authored, symlinked)" <<gen>> as puml_inl
66-
rectangle "fta_events.trlc\n(FtaFailureMode/RootCause stubs)" <<gen>> as fta_events
66+
rectangle "fta_events.trlc\n(RootCause stubs)" <<gen>> as fta_events
6767
rectangle "safety_analysis.rst" <<gen>> as safety_analysis_rst
68-
rectangle "failuremodes.lobster\nsafetymeasures.lobster\nfta_failure_modes.lobster\nfta_root_causes.lobster" <<gen>> as fmcm_lob
68+
rectangle "failuremodes.lobster\nsafetymeasures.lobster\nfta_root_causes.lobster" <<gen>> as fmcm_lob
6969
}
7070

7171
' ── Providers ────────────────────────────────────────────────────────────────
7272
rectangle "SphinxSourcesInfo\n────────────────\nsrcs: safety_analysis.rst\ndeps: safety_analysis.rst\naux_srcs: fta_*.puml" <<prov>> as ssi
73-
rectangle "AnalysisInfo.lobster_files\n────────────────\nfailuremodes.lobster\nsafetymeasures.lobster\nfta_failure_modes.lobster\nfta_root_causes.lobster" <<prov>> as ai
74-
rectangle "SafetyAnalysisProviderInfo\n────────────────\nfailuremodes, safetymeasures,\nfta_events, spec" <<prov>> as tpi
73+
rectangle "AnalysisInfo.lobster_files\n────────────────\nfailuremodes.lobster\nsafetymeasures.lobster\nfta_root_causes.lobster" <<prov>> as ai
74+
rectangle "TrlcProviderInfo\n────────────────\nreqs: fta_events.trlc, failuremodes\n(safetymeasures excluded: they\nreference fta_events)" <<prov>> as trlcpi
7575

7676
' ── Downstream rules + staging ───────────────────────────────────────────────
77-
component "dependability_analysis\n(+ root-cause coverage check)" <<tool>> as da
77+
component "dependability_analysis" <<tool>> as da
7878
component "dependable_element" <<tool>> as de
79+
component "assumptions_of_use\n(deps = [safety_analysis])" <<tool>> as aou
7980
rectangle "dependability_analysis/\n dfa.rst <- toctree\n safety_analysis.rst <- toctree\n fta_*.puml (.. uml::)" <<stage>> as stage
8081

8182
' ── Edges: inputs -> tools ───────────────────────────────────────────────────
8283
fta_puml --> puml : parse macro calls
8384

8485
fta_events --> asm
86+
fta_puml --> asm : diagram names\n(one .. uml:: each)
8587
fm_trlc --> asm
8688
sm_trlc --> asm
8789
rsl --> asm : import resolution
@@ -104,14 +106,13 @@ ltrlc --> fmcm_lob
104106
safety_analysis_rst --> ssi
105107
puml_inl --> ssi
106108
fmcm_lob --> ai
107-
fm_trlc --> tpi
108-
sm_trlc --> tpi
109-
fta_events --> tpi
109+
fta_events --> trlcpi
110+
fm_trlc --> trlcpi
110111

111112
' ── Edges: providers -> downstream -> staging ────────────────────────────────
112113
ssi --> da : merge SphinxSourcesInfo
113114
ai --> da : merge lobster_files
114-
tpi --> da : merge for root-cause\ncoverage check
115+
trlcpi --> aou : resolve AoU.root_causes\n(<fta_package>.<RootCause>)
115116
da --> de
116117
de --> stage : symlink srcs + aux_srcs\n(aux not indexed in toctree)
117118

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
' *******************************************************************************
2+
' Copyright (c) 2026 Contributors to the Eclipse Foundation
3+
'
4+
' See the NOTICE file(s) distributed with this work for additional
5+
' information regarding copyright ownership.
6+
'
7+
' This program and the accompanying materials are made available under the
8+
' terms of the Apache License Version 2.0 which is available at
9+
' https://www.apache.org/licenses/LICENSE-2.0
10+
'
11+
' SPDX-License-Identifier: Apache-2.0
12+
' *******************************************************************************
13+
14+
@startuml safety_analysis_linkage
15+
16+
' Record linkage of a dependable element's safety analysis. Arrows point from
17+
' the referencing record to the referenced one; the label is the TRLC field.
18+
19+
skinparam ArrowFontSize 10
20+
skinparam defaultTextAlignment center
21+
skinparam nodesep 60
22+
skinparam ranksep 70
23+
24+
skinparam class {
25+
BackgroundColor<<authored>> #EFF6FB
26+
BorderColor<<authored>> #0066B1
27+
BackgroundColor<<generated>> #FFF3E0
28+
BorderColor<<generated>> #EF6C00
29+
BackgroundColor<<received>> #F3E5F5
30+
BorderColor<<received>> #7B1FA2
31+
}
32+
33+
package "Other dependable_element (listed in deps)" {
34+
class "AoU\n(received)" as RecvAoU <<received>>
35+
}
36+
37+
package "This dependable_element" {
38+
package "Safety analysis" {
39+
class FailureMode <<authored>> {
40+
interface
41+
}
42+
class RootCause <<generated>> {
43+
title
44+
diagram
45+
line
46+
}
47+
class Mitigation <<authored>> {
48+
justification
49+
}
50+
class "AoU\n(own)" as OwnAoU <<authored>>
51+
}
52+
53+
package "Requirements" {
54+
class CompReq <<authored>>
55+
class FeatReq <<authored>>
56+
class AssumedSystemReq <<authored>>
57+
}
58+
}
59+
60+
' ── Generated from the $RootCause macros of the FTA diagrams ────────────────
61+
RootCause "1..*" --> FailureMode : failure_modes
62+
63+
' ── Safety measures: every RootCause needs at least one ─────────────────────
64+
Mitigation "1..*" --> RootCause : root_causes\n(+ justification)
65+
OwnAoU "0..*" --> RootCause : root_causes\n(preventive measure)
66+
CompReq "0..*" --> RootCause : derived_from\n(control measure)
67+
68+
' ── Requirement chain ───────────────────────────────────────────────────────
69+
CompReq --> FeatReq : derived_from
70+
CompReq --> AssumedSystemReq : derived_from
71+
CompReq --> RecvAoU : derived_from\n(received AoU only)
72+
FeatReq --> AssumedSystemReq : derived_from
73+
74+
note bottom of RootCause
75+
Every RootCause needs at least one incoming
76+
Mitigation, own AoU or CompReq.
77+
end note
78+
79+
note bottom of OwnAoU
80+
Own AoUs are never a CompReq
81+
derived_from source.
82+
end note
83+
84+
@enduml

‎bazel/rules/rules_score/docs/_assets/tooling_chain.puml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ rectangle "sphinx_module" <<rule>> as sphinx
4343
rectangle "**TRLC**\ntrlc parser + trlc_rst\n(.trlc/.rsl -> .rst; TRLCRST lib)" <<tool>> as trlc
4444
rectangle "**rst_to_trlc**\n(.rst -> .trlc)" <<own>> as r2t
4545
rectangle "**PlantUML Parser**\npuml_cli (Rust)\n(.puml -> .fbs.bin + .lobster + .idmap.json)" <<tool>> as puml
46-
rectangle "**puml_cli** (FTA mode)\ninline metamodel + extract\n(.puml -> inlined .puml +\nfta_events.trlc)" <<own>> as fta
46+
rectangle "**puml_cli** (FTA mode)\nextract root causes\n(.puml -> fta_events.trlc)" <<own>> as fta
4747
rectangle "**safety_analysis_assembler**\nTRLCRST page build\n(.trlc + fta_events.trlc -> safety_analysis.rst)" <<own>> as asm
4848
rectangle "**Lobster**\nlobster-trlc / -report /\n-ci-report / gtest_report" <<tool>> as lob
4949
rectangle "**Architecture Verifier**\nvalidation_cli\n(arch.json + .fbs.bin)" <<tool>> as verifier
@@ -64,7 +64,7 @@ asm ..> trlc : TRLCRST lib
6464
safety_analysis --> lob : lobster-trlc
6565
unit --> lob : gtest_report
6666

67-
da --> lob : lobster-report (FM+CM+FTA)
67+
da --> lob : lobster-report (FM+RC)
6868
de --> verifier : conformance check
6969
de --> lob : lobster-ci-report (gate)
7070
de --> sphinx : assemble docs

‎bazel/rules/rules_score/docs/_assets/traceability_dataflow.puml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ rectangle "Unit tests\n(cc_test / gtest)" <<src>> as test_in
4141
rectangle "requirements.lobster" <<lob>> as reqs_lob
4242
rectangle "public_api.lobster" <<lob>> as api_lob
4343
rectangle "failuremodes.lobster\nsafetymeasures.lobster" <<lob>> as fmcm_lob
44-
rectangle "fta_failure_modes.lobster\nfta_root_causes.lobster" <<lob>> as rc_lob
44+
rectangle "fta_root_causes.lobster" <<lob>> as rc_lob
4545
rectangle "<unit>.lobster\n(test results)" <<lob>> as test_lob
4646

4747
' ── Aggregation + gate ────────────────────────────────────────────────────────

‎bazel/rules/rules_score/docs/overview.rst‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ Traceability (test)
173173
``bazel test`` runs ``lobster-ci-report`` over the merged requirement /
174174
architecture / test / safety-analysis graph — assumed-system and feature
175175
requirements, component requirements, architecture, public API, unit tests,
176-
failure modes, control measures, root causes, and AoUs — and fails if any item
176+
failure modes, safety measures, root causes, and AoUs — and fails if any item
177177
lacks full up/down traceability.
178178

179179
.. graphviz::
@@ -197,12 +197,13 @@ lacks full up/down traceability.
197197
"Forwarded AoUs" -> "Received AoUs";
198198
"Component Requirements" -> "Feature Requirements";
199199
"Component Requirements" -> "Received AoUs";
200+
"Component Requirements" -> "Root Causes";
200201
"Unit Test" -> "Component Requirements";
201202
"Test Case Coverage" -> "Component Requirements";
202203
"Architecture" -> "Component Requirements";
203204
"Failure Modes" -> "Public API";
204205
"Root Causes" -> "Failure Modes";
205-
"Root Causes" -> "Safety Measures";
206+
"Safety Measures" -> "Root Causes";
206207
}
207208

208209
Execution Overview (Current Behavior)

‎bazel/rules/rules_score/docs/rule_reference.rst‎

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -275,9 +275,10 @@ testable within that component.
275275
**Generated targets:** ``<name>`` (documentation), ``<name>_test`` (TRLC validation)
276276

277277
A ``CompReq`` record's ``derived_from`` field (``CompReqSourceId``) may also
278-
reference an AoU that this requirement implements, alongside its usual
278+
reference an AoU *received* from another dependable element, alongside its usual
279279
``FeatReq``/``AssumedSystemReq`` references (e.g. ``[SampleType.SampleAoU@1]``).
280-
This requires importing the AoU's package and listing the
280+
The element's own AoUs are never a ``derived_from`` source. This requires
281+
importing the AoU's package and listing the
281282
``assumptions_of_use`` target that defines it directly in this target's
282283
``deps`` — see :doc:`user_guide/assumptions_of_use`.
283284

@@ -314,7 +315,7 @@ Conditions that the *integrating project* must fulfil when using this SEooC.
314315
* - ``deps``
315316
- label list
316317
- no
317-
- Other requirement targets (``TrlcProviderInfo``) needed for cross-reference parsing (default ``[]``)
318+
- Other requirement targets (``TrlcProviderInfo``) needed for cross-reference parsing (default ``[]``). List the ``safety_analysis`` target when an ``AoU`` references its generated ``<fta_package>.<RootCause>`` records.
318319
* - ``ref_package``
319320
- string
320321
- no
@@ -574,7 +575,9 @@ documentation target.
574575
- string
575576
- no
576577
- TRLC package name for the generated ``fta_events.trlc`` stub (the
577-
``FtaFailureMode``/``RootCause`` records derived from ``root_causes``).
578+
``RootCause`` records derived from ``root_causes``). The target
579+
exports it (plus ``failuremodes``) as ``TrlcProviderInfo``, so other
580+
targets such as ``assumptions_of_use`` can list it in ``deps``.
578581
Defaults to a sanitized form of ``name`` with a ``_fta`` suffix.
579582
* - ``arch_design``
580583
- label
@@ -619,10 +622,6 @@ Running ``bazel test`` validates the full FMEA traceability chain.
619622
- label list
620623
- no
621624
- ``safety_analysis`` targets to include in this analysis (default ``[]``)
622-
* - ``measures``
623-
- label list
624-
- no
625-
- Additional ``Mitigation``/``AoU``/``CompReq`` ``.trlc`` files not scoped to a single ``safety_analysis`` target, considered for the root-cause-coverage completeness check (default ``[]``)
626625
* - ``arch_design``
627626
- label
628627
- no

0 commit comments

Comments
 (0)