Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ use_repo(pip, "manual_analysis_deps")
bazel_dep(name = "trlc", version = "0.0.0")
git_override(
module_name = "trlc",
commit = "c4c531b9d667085daa09dfc1590edacc314bfda4",
commit = "8d25f639ff44976893d7866ba421a04db5698ebe",
remote = "https://github.com/bmw-software-engineering/trlc.git",
)

Expand Down
16 changes: 12 additions & 4 deletions bazel/rules/rules_score/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,17 @@ py_binary(
visibility = ["//visibility:public"],
)

# Safety analysis tools (preprocess FTA PlantUML + extract lobster traceability items)
# FMEA page assembler: builds the failure-mode-centric fmea.rst body in-process
# via the extended TRLCRST library and the FTA chains JSON from puml_cli.
py_binary(
name = "safety_analysis_tools",
srcs = ["src/safety_analysis_tools.py"],
name = "fmea_assembler",
srcs = ["src/fmea_assembler.py"],
imports = ["src"],
main = "src/safety_analysis_tools.py",
main = "src/fmea_assembler.py",
visibility = ["//visibility:public"],
deps = [
"@trlc//tools/trlc_rst:trlc_rst_lib",
],
)

# AoU forwarding filter: filters received AoU lobster entries for chain-forwarding
Expand Down Expand Up @@ -187,6 +191,10 @@ py_binary(
srcs = ["src/sphinx_wrapper.py"],
data = [
"//tools/sphinx:plantuml",
# Ship the FTA metamodel in the docs-build runfiles so conf.py can put it
# on PlantUML's include path; FTA diagrams keep ``!include
# fta_metamodel.puml`` and resolve it even under -pipe rendering.
"//plantuml:fta_metamodel",
],
env = {
"SOURCE_DIRECTORY": "",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,76 +13,103 @@

@startuml safety_analysis_doc_pipeline

' Data flow from safety analysis source files through Bazel rules into the
' Sphinx staging tree.
' Component view of the FMEA build: input artifacts (authored + tooling
' defaults) flow through three in-process tool actions of the ``fmea`` rule into
' the generated files, the providers, and finally the Sphinx staging tree.

skinparam linetype ortho
skinparam ArrowFontSize 10
skinparam defaultTextAlignment center
skinparam nodesep 40
skinparam ranksep 50
skinparam nodesep 30
skinparam ranksep 45

skinparam rectangle {
BackgroundColor<<src>> #EFF6FB
BorderColor<<src>> #0066B1
BackgroundColor<<def>> #E3F2FD
BorderColor<<def>> #1565C0
BackgroundColor<<gen>> #FFF3E0
BorderColor<<gen>> #EF6C00
BackgroundColor<<rule>> #E8F5E9
BorderColor<<rule>> #2E7D32
BackgroundColor<<stage>> #F3E5F5
BorderColor<<stage>> #7B1FA2
BackgroundColor<<prov>> #FFFDE7
BorderColor<<prov>> #F9A825
}
skinparam component {
BackgroundColor<<tool>> #E8F5E9
BorderColor<<tool>> #2E7D32
}

' ── Inputs ────────────────────────────────────────────────────────────────────
rectangle "failuremodes.trlc\ncontrolmeasures.trlc" <<src>> as trlc
rectangle "fta_*.puml" <<src>> as fta
rectangle "dfa.rst" <<src>> as dfa

' ── fmea rule ─────────────────────────────────────────────────────────────────
rectangle "**fmea**" <<rule>> as fmea

' ── fmea generated files ──────────────────────────────────────────────────────
rectangle "fmea.rst" <<gen>> as fmea_rst
rectangle "failuremodes.inc\ncontrolmeasures.inc" <<gen>> as inc_files
rectangle "fta_*.puml (inlined)\nroot_causes.lobster" <<gen>> as puml_proc
rectangle "detail_*.rst" <<gen>> as detail_rst

' ── fmea SphinxSourcesInfo ────────────────────────────────────────────────────
rectangle "SphinxSourcesInfo\n──────────────────\nsrcs: fmea.rst\ndeps: fmea.rst + *.inc + *.puml\naux_srcs: detail_*.rst" <<prov>> as fmea_ssi

' ── dependability_analysis rule ───────────────────────────────────────────────
rectangle "**dependability_analysis**" <<rule>> as da

' ── dependability_analysis SphinxSourcesInfo ─────────────────────────────────
rectangle "SphinxSourcesInfo\n──────────────────\nsrcs: dfa.rst + fmea.rst\ndeps: + *.inc + *.puml\naux_srcs: detail_*.rst" <<prov>> as da_ssi

' ── dependable_element rule ───────────────────────────────────────────────────
rectangle "**dependable_element**" <<rule>> as de

' ── Sphinx staging tree ───────────────────────────────────────────────────────
rectangle "dependability_analysis/\n dfa.rst ← toctree\n fmea.rst ← toctree\n failuremodes.inc\n controlmeasures.inc\n fta_*.puml\n detail_*.rst ← sub-pages" <<stage>> as stage

' ── Edges ─────────────────────────────────────────────────────────────────────
trlc --> fmea : trlc_rst\nlobster-trlc
fta --> fmea : safety_analysis_tools

fmea --> fmea_rst
fmea --> inc_files
fmea --> puml_proc
fmea --> detail_rst
fmea_rst --> fmea_ssi
inc_files --> fmea_ssi
puml_proc --> fmea_ssi
detail_rst --> fmea_ssi
' ── Input artifacts ──────────────────────────────────────────────────────────
package "Authored by the component team" {
rectangle "failuremodes.trlc\n(FailureMode records)" <<src>> as fm_trlc
rectangle "controlmeasures.trlc\n(ControlMeasure records)" <<src>> as cm_trlc
rectangle "fta_*.puml\n(root_causes attr)" <<src>> as fta_puml
}
package "Tooling defaults (rules_score / ScoreReq)" {
rectangle "ScoreReq *.rsl\n(spec attr)" <<def>> as rsl
rectangle "fta_metamodel.puml\n(on PlantUML include path)" <<def>> as meta
rectangle "fmea.template.rst\n({body})" <<def>> as tmpl
rectangle "fm/cm lobster\nconfigs" <<def>> as lcfg
}

dfa --> da
fmea_ssi --> da : merge
' ── fmea rule: three tool actions ────────────────────────────────────────────
package "fmea rule actions" {
component "puml_cli (FTA mode)\n--fta-output-dir\n[crate: puml_fta]" <<tool>> as puml
component "fmea_assembler\n[lib: TRLCRST]" <<tool>> as asm
component "lobster-trlc x2" <<tool>> as ltrlc
}

da --> da_ssi
' ── Generated files ──────────────────────────────────────────────────────────
package "Generated files" {
rectangle "fta_*.puml\n(authored, symlinked)" <<gen>> as puml_inl
rectangle "fta_chains.json" <<gen>> as chains
rectangle "root_causes.lobster" <<gen>> as rc_lob
rectangle "fmea.rst" <<gen>> as fmea_rst
rectangle "failuremodes.lobster\ncontrolmeasures.lobster" <<gen>> as fmcm_lob
}

da_ssi --> de : dependability_analysis attr
de --> stage : symlink srcs+deps\nsymlink aux_srcs\n(no outer toctree entry)
' ── Providers ────────────────────────────────────────────────────────────────
rectangle "SphinxSourcesInfo\n────────────────\nsrcs: fmea.rst\ndeps: fmea.rst\naux_srcs: fta_*.puml" <<prov>> as ssi
rectangle "AnalysisInfo.lobster_files\n────────────────\nfailuremodes.lobster\ncontrolmeasures.lobster\nroot_causes.lobster" <<prov>> as ai

' ── Downstream rules + staging ───────────────────────────────────────────────
component "dependability_analysis" <<tool>> as da
component "dependable_element" <<tool>> as de
rectangle "dependability_analysis/\n dfa.rst <- toctree\n fmea.rst <- toctree\n fta_*.puml (.. uml::)" <<stage>> as stage

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

chains --> asm
fm_trlc --> asm
cm_trlc --> asm
rsl --> asm : import resolution
tmpl --> asm

fm_trlc --> ltrlc
cm_trlc --> ltrlc
rsl --> ltrlc
lcfg --> ltrlc

' ── Edges: tools -> generated ────────────────────────────────────────────────
fta_puml --> puml_inl : symlinked beside fmea.rst
meta --> stage : on PlantUML include path
puml --> chains
puml --> rc_lob
asm --> fmea_rst
ltrlc --> fmcm_lob

' ── Edges: generated -> providers ────────────────────────────────────────────
fmea_rst --> ssi
puml_inl --> ssi
rc_lob --> ai
fmcm_lob --> ai

' ── Edges: providers -> downstream -> staging ────────────────────────────────
ssi --> da : merge SphinxSourcesInfo
ai --> da : merge lobster_files
da --> de
de --> stage : symlink srcs + aux_srcs\n(aux not indexed in toctree)

@enduml
10 changes: 6 additions & 4 deletions bazel/rules/rules_score/docs/_assets/tooling_chain.puml
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,11 @@ rectangle "dependable_element" <<rule>> as de
rectangle "sphinx_module" <<rule>> as sphinx

' ── Tools ─────────────────────────────────────────────────────────────────────
rectangle "**TRLC**\ntrlc parser + trlc_rst\n(.trlc/.rsl -> .rst/.inc)" <<tool>> as trlc
rectangle "**TRLC**\ntrlc parser + trlc_rst\n(.trlc/.rsl -> .rst; TRLCRST lib)" <<tool>> as trlc
rectangle "**rst_to_trlc**\n(.rst -> .trlc)" <<own>> as r2t
rectangle "**PlantUML Parser**\nparser + linker (Rust)\n(.puml -> .fbs.bin + .lobster)" <<tool>> as puml
rectangle "**safety_analysis_tools**\nFTA preprocess + lobster\n(.puml -> root_causes.lobster)" <<own>> as sat
rectangle "**puml_cli** (FTA mode)\ninline metamodel + extract\n(.puml -> inlined .puml +\nfta_chains.json + root_causes.lobster)" <<own>> as fta
rectangle "**fmea_assembler**\nTRLCRST page build\n(.trlc + chains -> fmea.rst)" <<own>> as asm
rectangle "**Lobster**\nlobster-trlc / -report /\n-ci-report / gtest_report" <<tool>> as lob
rectangle "**Architecture Verifier**\nvalidation_cli\n(arch.json + .fbs.bin)" <<tool>> as verifier
rectangle "**Sphinx**\nscore_build + html_merge\n(.rst -> needs.json + HTML)" <<tool>> as docs
Expand All @@ -57,8 +58,9 @@ req --> trlc : render + typecheck
req --> lob : lobster-trlc

arch --> puml : parse diagrams
fmea --> trlc : render FM/CM
fmea --> sat : FTA root causes
fmea --> fta : FTA root causes
fmea --> asm : assemble fmea.rst
asm ..> trlc : TRLCRST lib
fmea --> lob : lobster-trlc
unit --> lob : gtest_report

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ rectangle "PASS / FAIL\n(bazel test gate)" <<rep>> as gate
reqs_in --> reqs_lob : lobster-trlc
api_in --> api_lob : plantuml parser
fmcm_in --> fmcm_lob : lobster-trlc
fta_in --> rc_lob : safety_analysis_tools
fta_in --> rc_lob : puml_cli (FTA mode)
test_in --> test_lob : gtest_report

reqs_lob --> conf
Expand Down
92 changes: 68 additions & 24 deletions bazel/rules/rules_score/docs/tooling_architecture.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@ build wires layers 2 and 3 automatically.
:doc:`overview` for the provider-flow diagram.
#. **Tools** — the executables each action runs. Some are vendored third-party
tools (TRLC, Lobster, the PlantUML parser, Sphinx); some are local helpers
under ``src/`` (``rst_to_trlc.py``, ``safety_analysis_tools.py``,
``sphinx_html_merge.py``).
under ``src/`` (``rst_to_trlc.py``, ``fmea_assembler.py``,
``sphinx_html_merge.py``). The FMEA fault-tree processing lives in the Rust
``puml_cli`` (FTA mode, backed by the ``puml_fta`` crate).

Rule → tool invocation map
--------------------------
Expand Down Expand Up @@ -80,8 +81,10 @@ are rendered under :doc:`tool_reference/index`.
- ``feature_requirements``, ``component_requirements``,
``assumed_system_requirements``, ``fmea``
- Parses and type-checks requirement / FMEA records against the ``.rsl``
metamodel, then renders them to ``.rst`` (requirements) or ``.inc``
(FMEA sections) for Sphinx.
metamodel and renders them to ``.rst``. ``trlc_rst`` also ships a
reusable ``TRLCRST`` library that ``fmea_assembler`` links directly to
build the FMEA page from a single in-process parse (no per-record
``.inc`` files).
* - **rst_to_trlc**
- ``src/rst_to_trlc.py`` (local)
- ``score_requirements_rule`` macro
Expand All @@ -95,13 +98,29 @@ are rendered under :doc:`tool_reference/index`.
items. The **linker** merges the FlatBuffers into ``plantuml_links.json``
for the ``clickable_plantuml`` Sphinx extension. Rejects syntactically
invalid diagrams with a non-zero exit code.
* - **safety_analysis_tools**
- ``//bazel/rules/rules_score:safety_analysis_tools``
(``src/safety_analysis_tools.py``, local)
* - **puml_cli (FTA mode)**
- ``//plantuml/parser/puml_cli`` ``--fta-output-dir`` (Rust; FTA model in
the ``puml_fta`` crate)
- ``fmea``
- Inlines ``fta_metamodel.puml`` into root-cause FTA diagrams (making them
hermetic) and extracts ``$TopEvent`` / ``$BasicEvent`` calls into
``root_causes.lobster`` in ``lobster-act-trace`` format.
- Analysis only: parses the ``$TopEvent`` / ``$BasicEvent`` / gate macro
calls of each root-cause FTA diagram into
two outputs: ``root_causes.lobster`` (``lobster-act-trace``) and
``fta_chains.json`` (the ordered per-failure-mode chains). The authored
diagram keeps its ``!include fta_metamodel.puml``; the metamodel ships in
the docs toolchain runfiles and is put on PlantUML's global include path
(``-Dplantuml.include.path``) so the include resolves at render even under
sphinxcontrib-plantuml's ``-pipe`` mode. Unrooted basic events and
malformed TRLC aliases are reported as build warnings rather than silently
dropped.
* - **fmea_assembler**
- ``//bazel/rules/rules_score:fmea_assembler``
(``src/fmea_assembler.py``, local; links the ``TRLCRST`` library)
- ``fmea``
- Assembles the failure-mode-centric ``fmea.rst`` from ``fta_chains.json``
plus the FailureMode / ControlMeasure records in one in-process TRLC
parse: an overview table, one section per failure mode (detail + inline
fault tree + that chain's control measures), and trailing "Unlinked"
sections so nothing is dropped.
* - **Lobster**
- ``@lobster//`` : ``lobster-trlc``, ``lobster-report``,
``lobster-ci-report``, ``lobster-html-report``, ``gtest_report``,
Expand Down Expand Up @@ -176,7 +195,7 @@ feed that pipeline:
* **Public API diagrams** (``public_api.puml``) → PlantUML parser →
``public_api.lobster`` (enables failure-mode-to-interface tracing).
* **FMEA** (``failuremodes.trlc`` / ``controlmeasures.trlc``) → ``lobster-trlc``;
**FTA** (``fta.puml``) → ``safety_analysis_tools`` → ``root_causes.lobster``.
**FTA** (``fta.puml``) → ``puml_cli`` (FTA mode) → ``root_causes.lobster``.
* **Unit tests** (gtest) → ``gtest_report`` → ``<unit>.lobster``.

.. _two-phase-sphinx-build:
Expand Down Expand Up @@ -267,26 +286,51 @@ self-contained.
Safety analysis document pipeline
----------------------------------

The diagram below shows how FMEA and FTA source files travel through the three
rules (``fmea`` → ``dependability_analysis`` → ``dependable_element``) and land
in the Sphinx staging tree. Blue boxes are source files authored by the
component team; orange boxes are generated files; yellow boxes are the
``SphinxSourcesInfo`` provider payloads; the purple box is the final staging
directory consumed by Sphinx.
The component diagram below shows how the FMEA **input artifacts** — authored
``.trlc`` records and ``fta_*.puml`` diagrams plus the tooling defaults
(``ScoreReq`` ``.rsl`` spec, ``fta_metamodel.puml``, ``fmea.template.rst`` and
the lobster configs) — flow through the three in-process tool actions of the
``fmea`` rule into the generated files, the providers, and finally the Sphinx
staging tree. Blue boxes are authored sources, light-blue are tooling defaults,
green components are the tool actions, orange boxes are generated files, yellow
boxes are the provider payloads, and the purple box is the staging directory
consumed by Sphinx.

.. uml:: _assets/safety_analysis_doc_pipeline.puml
:align: center
:alt: Safety analysis document pipeline
:width: 100%

The ``fmea`` rule drives three actions, all reading the input artifacts above:

#. **puml_cli (FTA mode)** parses each ``fta_*.puml`` directly (no rewriting)
and writes ``root_causes.lobster`` and ``fta_chains.json`` (the ordered
per-failure-mode chains). The diagrams keep their ``!include
fta_metamodel.puml``; the metamodel is on PlantUML's global include path
(shipped in the docs toolchain runfiles), so it resolves at render time.
#. **fmea_assembler** consumes ``fta_chains.json`` and parses the FailureMode /
ControlMeasure ``.trlc`` records (with the ``.rsl`` spec for import
resolution) in a single in-process ``TRLCRST`` pass, expanding
``fmea.template.rst`` into ``fmea.rst``.
#. **lobster-trlc** (run twice) turns the FailureMode and ControlMeasure records
into ``failuremodes.lobster`` / ``controlmeasures.lobster`` for the
traceability report.

``SphinxSourcesInfo`` carries three depsets:

- **srcs** — files that become top-level toctree entries in the enclosing
document section (``fmea.rst``, ``dfa.rst``).
- **deps** — all files that must be present in the staging directory: own
``srcs`` plus ``.inc`` rendered sections and preprocessed ``.puml`` diagrams
that ``fmea.rst`` pulls in via ``.. include::`` / ``.. uml::``.
document section. ``fmea`` emits exactly one: ``fmea.rst``.
- **deps** — all files that must be present in the staging directory; for
``fmea`` this is just ``fmea.rst``, because the page is self-contained
(failure modes and control measures are rendered inline, not pulled in via
``.. include::``).
- **aux_srcs** — files to symlink alongside ``srcs``/``deps`` but **not** added
to the outer index toctree. ``fmea`` uses this for the ``detail_*.rst``
sub-pages, which are referenced from the inner ``.. toctree::`` inside
``fmea.rst`` rather than from the section index.
to any toctree. ``fmea`` uses this for the authored ``fta_*.puml`` diagrams,
which ``fmea.rst`` references inline via ``.. uml::`` and which must therefore
sit beside it in the staging tree without being indexed as documents. (The
metamodel is not staged here — it resolves via PlantUML's global include
path.)

The lobster outputs travel separately on ``AnalysisInfo.lobster_files``
(``failuremodes.lobster``, ``controlmeasures.lobster``, ``root_causes.lobster``)
into the ``dependability_analysis`` traceability report.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ filegroup(
name = "sample_fta",
srcs = [
"sample_fta.puml",
"sample_fta2.puml",
],
visibility = ["//visibility:public"],
)
Expand Down
Loading
Loading