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
6 changes: 5 additions & 1 deletion .github/skills/score-architecture/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ cross-checked against each other and against the implementation.
|------|-----------|-----------------------|---------|
| **Static** | `static` | Bazel `dependable_element`/`component`/`unit` tree; internal API; public API; sequences | Structural component/unit tree — the anchor for all other checks |
| **Dynamic** (sequence) | `dynamic` | Static component diagram; internal API | Unit interactions — participant names and cross-unit calls |
| **Public API** | `public_api` | Static diagram (top-level interfaces bound from the SEooC) | Interfaces the SEooC exposes; also feeds `FailureMode.interface` traceability |
| **Public API** | `public_api` | Static diagram (top-level interfaces bound from the SEooC) | Interfaces the SEooC exposes (class diagrams only); each public method becomes an `ApiMethod` TRLC record that `FailureMode.interface` references |
| **Internal API** | `internal_api` | Static component diagram; sequences | Interfaces between components/units inside the SEooC |

Real example diagrams (verbatim, from [`examples/seooc/design/`](../../../bazel/rules/rules_score/examples/seooc/design)):
Expand Down Expand Up @@ -299,6 +299,9 @@ namespace safety_software_seooc_example {
- **Public API** interfaces must be top-level in the static diagram and bound from the `<<SEooC>>`
(e.g. `safety_software_seooc_example -d- SampleLibraryAPI`); interfaces nested inside
components/units are treated as *internal* API.
- **Public API records**: only public methods (all overloads) and free functions yield `ApiMethod`
records; attributes, enums, typedefs and non-public members yield none. `package` is required with
`public_api`; reports show the generated `public_api.trlc` as item location, not the `.puml`.
- **Internal API** interfaces are modeled inside the owning element's `namespace` so their
fully-qualified name reflects containment.

Expand Down Expand Up @@ -386,6 +389,7 @@ One target bundles every diagram kind (from [`examples/seooc/design/BUILD`](../.
```starlark
architectural_design(
name = "sample_seooc_design",
package = "sample_seooc_api", # required with public_api; TRLC package of public_api.trlc
static = ["static_design.puml", "overview_design.puml", "index.md"],
dynamic = ["dynamic_design.puml"],
public_api = ["public_api.puml", "public_api.rst"],
Expand Down
28 changes: 17 additions & 11 deletions .github/skills/score-safety-analysis/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,14 @@ aliases, BUILD wired, `trlc` clean.
for each, apply the applicable fault models and ask *"can this occur, and would it violate a
safety goal?"* Dismiss low-relevance models with a short rationale.

| Fault-model category | Example models | `GuideWord` labels |
| Fault-model category | Example models | `Guideword` labels |
|----------------------|----------------|--------------------|
| Message (send/receive) | not sent/received, corrupted, lost, unintended (`MF_01_*`) | `LossOfFunction`, `PartialFunction`, `Corrupted`, `UnintendedFunction`, `Wrong` |
| Timing / duration | too late/early, boundary violated (`CO_01_*`) | `TooEarly`, `TooLate`, `DelayedFunction` |
| Execution | wrong result, loss, arbitrary/incomplete (`EX_01_*`) | `Wrong`, `LossOfFunction`, `ExceedingFunction`, `ArbitraryExecution` |

> **Clustering:** one `FailureMode` per *(interface, guide word)* effect — group methods sharing a
> root cause in the `interface` field; one root cause under two guide words → two records.
> root cause in the `interface` list; one root cause under two guide words → two records.

**Step 2 — effect, then causes.** Write `failureeffect` from the **caller/system perspective** in
worst-case terms relative to the safety goal. Then build the FTA top-down to **actionable root
Expand Down Expand Up @@ -108,24 +108,30 @@ Package: match the existing package declaration in the folder structure
```trlc
package <Pkg>
import ScoreReq
import <ArchApiPkg>

ScoreReq.FailureMode <RecordName> {
guideword = ScoreReq.GuideWord.<Word>
guidewords = [ScoreReq.Guideword.<Word>]
description = "statement describing the expected behaviour"
failureeffect = "What goes wrong for the caller / system"
potentialcause = "Root cause(s) from the FMEA"
interface = "<Interface>.<Method>[, <Interface>.<Method>]"
interface = [<ArchApiPkg>.<Entity>_<method>]
version = 1
safety = ScoreReq.Asil.B
}
```

**GuideWord enum values:** `LossOfFunction`, `PartialFunction`, `Corrupted`, `UnintendedFunction`, `TooEarly`, `TooLate`, `Wrong`, `DelayedFunction`, `ExceedingFunction`, `ArbitraryExecution`
`<ArchApiPkg>` is the `package` of the `architectural_design` target. The build generates one
`ScoreReq.ApiMethod` record per public method (all overloads) and per free function of its
`public_api` class diagrams, named `<Entity>_<method>` (`<Entity>` = namespace-qualified
entity id, `.` → `_`, e.g. `ns_Interface_Send`); the
`failure_modes` target lists the `architectural_design` in `deps`.

**Guideword enum values:** `LossOfFunction`, `PartialFunction`, `Corrupted`, `UnintendedFunction`, `TooEarly`, `TooLate`, `Wrong`, `DelayedFunction`, `ExceedingFunction`, `ArbitraryExecution`

**Rules:**
- One record per FailureMode, not per interface method.
- Same root cause spanning multiple guide words → separate records (trlc only allows one `guideword` per record).
- `interface` may list multiple methods as a comma-separated string when root cause is shared.
- Same root cause spanning multiple guide words → separate records.
- `interface` may list several `ApiMethod` records when the root cause is shared.

## Step 2 — Create FTA Diagrams (`fta_<snake_name>.puml`)

Expand Down Expand Up @@ -197,10 +203,10 @@ The `@<version>` of a measure pins the reviewed version; a version change of the
**Rule:** every `$RootCause` alias must be listed in the `root_causes` of exactly one `RootCauseAssessment`, and every own `AoU` must be listed in the `measures` of at least one. This is checked by lobster in the traceability report of the enclosing `dependable_element` (the Root Cause Assessments level traces to Root Causes and Assumptions of Use; uncovered items are reported as `missing reference to Root Cause Assessments`, and fail `bazel test <dependable_element>` with `maturity = "release"`). The safety analysis is three rules: `failure_modes` (the `FailureMode` records), `fault_trees` (`srcs` = FTA diagrams, `deps` = the `failure_modes` targets; generates the `<fta_package>` root causes) and `safety_analysis` (`failure_modes`, `fault_trees`, `assessments` and `safety_measures`: `assumptions_of_use` / `component_requirements` targets the assessments list; only their own records are rendered, targets in their `deps` just resolve references; raw `.trlc` files in `assessments` may only hold `RootCauseAssessment` records, every failure mode a root cause references must be in `failure_modes`, and an assessment may only list measures of `safety_measures`). Every `assumptions_of_use` target passed as `safety_measures` is an own AoU of the enclosing `dependable_element` (derived, deduplicated by label, forwarded to dependees); one no `safety_analysis` lists is neither rendered nor forwarded:

```python
failure_modes(name = "fm", srcs = ["failure_modes.trlc"])
failure_modes(name = "fm", srcs = ["failure_modes.trlc"], deps = [":arch"])
fault_trees(name = "ft", srcs = [":fta_files"], deps = [":fm"])
assumptions_of_use(name = "aous", srcs = ["aous.trlc"])
safety_analysis(name = "sa", arch_design = ":arch", failure_modes = [":fm"], fault_trees = ":ft",
safety_analysis(name = "sa", failure_modes = [":fm"], fault_trees = ":ft",
assessments = ["assessments.trlc"], safety_measures = [":aous"])
```

Expand Down Expand Up @@ -228,7 +234,7 @@ Pre-existing RSL union-type errors (`expected identifier, encountered '['`) are
**Traceability chain that must be complete:**

```
FailureMode.interface → public_api interface name
FailureMode.interface → ApiMethod record (generated from the public_api class diagram)
FailureMode record → $FailureMode fm1..fm8 arguments
$RootCause alias → RootCauseAssessment.root_causes
RootCauseAssessment → measures (AoU / CompReq, versioned)
Expand Down
17 changes: 12 additions & 5 deletions bazel/rules/rules_score/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,21 +110,28 @@ that `:satisfies:` / `:derived_from:` resolve in.
```starlark
architectural_design(
name = "my_design",
static = ["class.puml", "component.puml"],
package = "my_design_api",
static = ["component.puml"],
dynamic = ["sequence.puml"],
public_api = ["api.puml"],
)
```

**`bazel build`** — runs `puml_parser` on every `.puml` file, producing:
- a `.fbs.bin` FlatBuffers binary (diagram AST) — consumed by validation/core checks
- a `.lobster` traceability file (Interface elements only) — consumed by LOBSTER
- a `validation.log` from the `architectural-design` validation profile
- a `.idmap.json` sidecar — consumed by the `clickable_plantuml` Sphinx extension
to resolve cross-diagram links based on element *defines/references* roles
- a `public_api.trlc` — one `ScoreReq.ApiMethod` record per public method (all
overloads) and per free function of the `public_api` class diagrams (other
diagram kinds in `public_api` fail the build; attributes, enums, typedefs and
non-public members yield no record). The `package` attribute names its TRLC
package and is required with `public_api`. Provided as `TrlcProviderInfo`, so
`failure_modes(deps = [...])` can reference the records

Diagrams in `public_api` are classified separately so their lobster items flow
through `public_api_lobster_files` for failure-mode traceability.
`lobster-trlc` runs on `public_api.trlc` and the result flows through
`public_api_lobster_files` for failure-mode traceability. Reports show the
generated `public_api.trlc` as item location, not the `.puml` source.

---

Expand Down Expand Up @@ -194,6 +201,7 @@ requirements).
failure_modes(
name = "my_failure_modes",
srcs = ["failure_modes.trlc"],
deps = [":my_design"], # provides the ApiMethod records of FailureMode.interface
)

fault_trees(
Expand All @@ -209,7 +217,6 @@ assumptions_of_use(

safety_analysis(
name = "my_safety_analysis",
arch_design = ":my_design",
assessments = ["assessments.trlc"],
failure_modes = [":my_failure_modes"],
fault_trees = ":my_fault_trees",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ package "Generated files" {
rectangle "fta_events.trlc\n(RootCause stubs)" <<gen>> as fta_events
rectangle "safety_analysis.rst" <<gen>> as safety_analysis_rst
rectangle "failure_modes lobster" <<gen>> as fm_lob
rectangle "fta_root_causes.lobster" <<gen>> as ft_lob
rectangle "assessments.lobster" <<gen>> as sm_lob
rectangle "<fault_trees>.lobster" <<gen>> as ft_lob
rectangle "<safety_analysis>.lobster" <<gen>> as sm_lob
}

' ── Providers ────────────────────────────────────────────────────────────────
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,7 @@ package "Other dependable_element (listed in deps)" {

package "This dependable_element" {
package "Safety analysis" {
class FailureMode <<authored>> {
interface
}
class FailureMode <<authored>>
class RootCause <<generated>> {
title
diagram
Expand All @@ -52,13 +50,24 @@ package "This dependable_element" {
class "AoU\n(own)" as OwnAoU <<authored>>
}

package "Architecture" {
class ApiMethod <<generated>> {
diagram
line
signatures
}
}

package "Requirements" {
class CompReq <<authored>>
class FeatReq <<authored>>
class AssumedSystemReq <<authored>>
}
}

' ── Generated from the public API class diagrams (public_api.trlc) ──────────
FailureMode "0..*" --> "1..*" ApiMethod : interface

' ── Generated from the $RootCause macros of the FTA diagrams ────────────────
RootCause "1..*" --> FailureMode : failure_modes

Expand Down
2 changes: 1 addition & 1 deletion bazel/rules/rules_score/docs/_assets/tooling_chain.puml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ rectangle "sphinx_module" <<rule>> as sphinx
' ── Tools ─────────────────────────────────────────────────────────────────────
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**\npuml_cli (Rust)\n(.puml -> .fbs.bin + .lobster + .idmap.json)" <<tool>> as puml
rectangle "**PlantUML Parser**\npuml_cli (Rust)\n(.puml -> .fbs.bin + .idmap.json + public_api.trlc)" <<tool>> as puml
rectangle "**puml_cli** (FTA mode)\nextract root causes\n(.puml -> fta_events.trlc)" <<own>> as fta
rectangle "**safety_analysis_assembler**\nTRLCRST page build\n(.trlc + fta_events.trlc -> safety_analysis.rst)" <<own>> as asm
rectangle "**Lobster**\nlobster-trlc / -report /\n-ci-report / gtest_report" <<tool>> as lob
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ rectangle "Unit tests\n(cc_test / gtest)" <<src>> as test_in

' ── Lobster artefacts (one per source kind) ───────────────────────────────────
rectangle "requirements.lobster" <<lob>> as reqs_lob
rectangle "public_api.lobster" <<lob>> as api_lob
rectangle "failuremodes.lobster\nassessments.lobster" <<lob>> as fmcm_lob
rectangle "fta_root_causes.lobster" <<lob>> as rc_lob
rectangle "<architectural_design>.lobster" <<lob>> as api_lob
rectangle "failuremodes.lobster\n<safety_analysis>.lobster" <<lob>> as fmcm_lob
rectangle "<fault_trees>.lobster" <<lob>> as rc_lob
rectangle "<unit>.lobster\n(test results)" <<lob>> as test_lob

' ── Aggregation + gate ────────────────────────────────────────────────────────
Expand All @@ -51,7 +51,7 @@ rectangle "report.html\n+ RST report" <<rep>> as html
rectangle "PASS / FAIL\n(bazel test gate)" <<rep>> as gate

reqs_in --> reqs_lob : lobster-trlc
api_in --> api_lob : plantuml parser
api_in --> api_lob : puml_cli (public API TRLC)\nlobster-trlc
fmcm_in --> fmcm_lob : lobster-trlc
fta_in --> rc_lob : puml_cli (FTA mode)
test_in --> test_lob : gtest_report
Expand Down
6 changes: 4 additions & 2 deletions bazel/rules/rules_score/docs/integration_guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -202,16 +202,18 @@ Complete Example

# Architecture
architectural_design(name = "arch",
package = "my_arch_api",
static = ["docs/arch.puml"],
dynamic = ["docs/sequence.puml"],
public_api = ["docs/public_api.puml"])

# Safety analysis
failure_modes(name = "my_failure_modes", srcs = ["docs/failures.trlc"])
failure_modes(name = "my_failure_modes", srcs = ["docs/failures.trlc"],
deps = [":arch"])
fault_trees(name = "my_fault_trees",
srcs = ["docs/fta.puml"],
deps = [":my_failure_modes"])
safety_analysis(name = "my_safety_analysis", arch_design = ":arch",
safety_analysis(name = "my_safety_analysis",
assessments = ["docs/assessments.trlc"],
failure_modes = [":my_failure_modes"],
fault_trees = ":my_fault_trees",
Expand Down
7 changes: 4 additions & 3 deletions bazel/rules/rules_score/docs/overview.rst
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,10 @@ Bazel/C++ implementation:
methods, enum literals, relationships) must match the generated C++
implementation model
(:doc:`spec <tool_reference/specs/class_design_implementation>`).
- **Public API ↔ failure modes** — every public API interface item must be
referenced by a ``FailureMode`` (via ``FailureMode.interface``) in the
SEooC's own safety analysis; unreferenced interfaces fail traceability
- **Public API ↔ failure modes** — every public API method (``ApiMethod``
record generated from the public API class diagrams) must be referenced by a
``FailureMode`` (via ``FailureMode.interface``) in the SEooC's own safety
analysis; unreferenced methods fail traceability
(:doc:`spec <user_guide/dependability_analysis>`).

Certified scope (build)
Expand Down
Loading
Loading