Requirements

Note

A complete working example covering all requirement rules is available in bazel/rules/rules_score/examples/seooc/ (standalone Bazel workspace).

rules_score provides three rules for capturing different levels of requirements.

Requirement Hierarchy & Traceability

AssumedSystemReq  →  FeatReq  →  CompReq
    (System)        (Feature)   (Component)
         \                          ↑
          \________________________/

Type

Description

Traceability

AssumedSystemReq

Requirements from the user / assumed system towards the SEooC.

Too high-level for a single component — can only be satisfied by multiple components working together.

Root — no parent

FeatReq

Refined requirements derived from AssumedSystemReq.

Used when assumed system requirements are too high-level to be broken down directly to one component — still require multiple components.

Must reference ≥ 1 AssumedSystemReq via derived_from

CompReq

Requirements assigned to exactly one component.

Can be directly implemented and tested within that component.

Optionally references ≥ 1 FeatReq via derived_from using [Package.FeatReq@version]

Traceability throughout the complete requirements traceability is performed via TRLC. It includes also (manual) version pinning (e.g. @1) of requirements, which ensures that when a parent requirement changes its content (and thus version), all downstream references must be explicitly updated.

Writing Good Requirements

The rules only check that requirements are well-formed and traceable — not that they are well-written. The authoritative writing rules live in the Requirements Writing Guidelines (the same guidelines the AI quality check applies) and the S-CORE Requirements Engineering process area.

The guideline document defines: a mandatory sentence template for every requirement; a set of quality criteria (unambiguous, verifiable, atomic, consistent, complete, necessary) with terms and patterns to avoid; a short explanation of the requirement types (functional, interface, non-functional, process) and how each is verified; and a list of pre-flight checks that the AI quality check applies before raising a finding (e.g. not flagging formally defined domain terms as vague, or intentional design constraints as level mismatches). The essentials are distilled below.

Sentence template

Every requirement follows one structure — subject shall verb [object] [parameter] [condition] — with at least one of object / parameter / condition present:

The component shall detect if a key-value pair got corrupted and set its status to INVALID during every restart of the SW platform.

Quality criteria

  • Unambiguous — one interpretation. Prefer :term: glossary nouns over pronouns and vague words (fast, efficient, as appropriate).

  • Verifiable — a test or review can objectively pass or fail it.

  • Atomic — one shall; split “and”/”or” and unbounded lists (etc., and so on).

  • Consistent — no contradiction with other requirements.

  • Complete — has subject + verb + at least one of object/parameter/condition, and fully specifies behaviour at its own level without pre-empting lower-level detail.

  • Necessary — traces to a parent or a rationale.

Use shall for obligations; put non-normative notes in the note field, not description. Keep implementation detail out of system/feature requirements — but an intentional design constraint (mandating a transport, mechanism, or safety property) is a legitimate requirement, not a level violation.

Choosing the level

Levels differ by scope and observer, not wording:

  • AssumedSystemReq — the need comes from outside the SEooC; describes it as a black box.

  • FeatReq — spans several components on one feature; phrased against the public interface, solution-neutral.

  • CompReq — fully implementable and testable inside one component.

If the level is unclear, discuss the boundary with the requirements owner — it drives allocation and traceability.

Refining a parent into children

derived_from is a refinement claim: each child is a narrower, consistent refinement; the children together must be sufficient to satisfy the parent; a child inherits the parent’s safety level unless a lower one is justified. On any content change, bump version and re-pin every child (@1@2).

# Weak — unverifiable, multi-concern, leaks implementation
"The manager should quickly handle values and store them efficiently in a hash map."
# Better — atomic, verifiable, follows the template
"The numeric value manager shall return the most recently stored uint8_t value on every read access."

Modeling Requirements

All requirements are written in TRLC (Traceability Requirements Language Checker). Each record maps to a specific ScoreReq type defined in the S-CORE requirements model.

For TRLC both a VSCode Extension and a LSP Server (e.g. for Clion) are available

Assumed System Requirements

System-level requirements that your SEooC receives from the wider context — for example, from a system specification. The excerpt below is taken from the reference example’s assumed_system_requirements.trlc:

package SampleSEooC

import ScoreReq

ScoreReq.AssumedSystemReq ASR_SAMPLE_001 {
    description = "The system shall provide safe and reliable numeric value management through encapsulated classes, compliant with the selected :term:`integrity level`."
    safety = ScoreReq.Asil.B
    version = 1
    rationale = "System-level requirement for managing numeric values in a safety-critical context"
}
Listing 1 docs/requirements/BUILD
assumed_system_requirements(
    name = "assumed_system_requirements",
    srcs = ["assumed_system_requirements.trlc"],
    visibility = ["//visibility:public"],
)

Feature Requirements

Taken from feature_requirements.trlc, derived from the ASR_SAMPLE_001 requirement above:

package SampleSEooC

import ScoreReq

ScoreReq.FeatReq FEAT_001 {
    description = "The :term:`component` shall provide a numeric value management interface that returns a `uint8_t` value on every read access, aligned with the :term:`feature requirements`."
    safety = ScoreReq.Asil.B
    derived_from = [SampleSEooC.ASR_SAMPLE_001@1]
    version = 1
}
Listing 2 docs/requirements/BUILD
feature_requirements(
    name = "feature_requirements",
    srcs = ["feature_requirements.trlc"],
    visibility = ["//visibility:public"],
    deps = [":assumed_system_requirements"],
)

Component Requirements

derived_from uses the versioned tuple syntax [Package.RecordId@version] and may reference more than one parent requirement, as REQ_COMP_004 does below. Taken from component_requirements.trlc:

package SampleComponent

import ScoreReq
import SampleSEooC

ScoreReq.CompReq REQ_COMP_001 {
    description = "The numeric value management interface shall provide a read operation that returns a uint8_t value"
    safety = ScoreReq.Asil.B
    derived_from = [SampleSEooC.FEAT_001@1]
    version = 1
}

ScoreReq.CompReq REQ_COMP_004 {
    description = "The numeric value validator shall accept a numeric value manager instance as its sole constructor argument"
    safety = ScoreReq.Asil.B
    derived_from = [SampleSEooC.FEAT_003@1, SampleSEooC.FEAT_004@1]
    version = 1
}
Listing 3 docs/requirements/BUILD
component_requirements(
    name = "component_requirements",
    srcs = ["component_requirements.trlc"],
    visibility = ["//visibility:public"],
    deps = [
        ":assumed_system_requirements",
        ":feature_requirements",
    ],
)

Validation

Every requirement target generates a <name>_test target that runs trlc --verify on your .trlc sources. This check runs automatically as part of bazel test ....

The validation catches:

  • Syntax errors — malformed TRLC records

  • Type errors — wrong value types for fields (e.g. a string where an enum is expected)

  • Mandatory field violations — missing description, safety, or version

  • Broken cross-references — a derived_from or satisfies pointing to a non-existent record

  • Unknown fields — fields not defined in the S-CORE requirements model

To run the validation for a single target:

bazel test //my/package:my_feature_req_test

Adding Images and Diagrams to Requirement Descriptions

A requirement’s description field can embed images and PlantUML diagrams so they are rendered directly in the generated Sphinx documentation, right next to the requirement text.

Markdown-style images — use ![alt](path); it is converted to an RST .. image:: directive:

ScoreReq.CompReq COMP_002 {
    description = '''The system shall expose the following architecture.

    ![Architecture overview](diagrams/arch.svg)'''
    safety       = ScoreReq.Asil.B
    derived_from = [MySeooc.FEAT_001@1]
    version      = 1
}

PlantUML diagrams — write a raw .. uml:: RST directive; it is passed through unmodified (any RST directive, e.g. .. image::, .. figure::, or .. uml::, is preserved as-is):

ScoreReq.CompReq COMP_003 {
    description = '''The `ClientConnection` shall maintain a state machine.

    .. uml:: client_connection_activity_diagram.puml'''
    safety       = ScoreReq.Asil.B
    derived_from = [MySeooc.FEAT_001@1]
    version      = 1
}

In both cases, the referenced file must also be declared via the image_srcs attribute (available on assumed_system_requirements, feature_requirements, and component_requirements) so it gets staged next to the rendered .rst file. The path written in the directive must match the file’s package-relative path:

component_requirements(
    name = "comp_req",
    srcs = ["docs/requirements.trlc"],
    image_srcs = [
        "diagrams/arch.svg",
        "//path/to:client_connection_activity_diagram.puml",
    ],
)

Note

Prefer .svg over .png for images checked into git. SVG is text-based and diffs/compresses cleanly, whereas .png is a binary blob — every change adds a full new copy to the git history and bloats the repository over time.

Allocation of Requirements to Architectural Elements

Requirements are allocated to architectural elements differently depending on their level:

Component Requirements (``CompReq``) CompReq records are associated with exactly one component. The allocation is expressed implicitly through Bazel: The Bazel Component rule exposes an attribute for requirements that accepts any component_requirements target. However, since the entire file is assigned to a single component, requirements must be split into separate files.

component(
    name = "MyComponent",
    components = [":MyUnit"],
    requirements = [":component_requirements"],
    tests = [],
)

Feature Requirements (``FeatReq``) FeatReq records operate at the integration level — they are too broad for a single component and can only be satisfied by multiple components working together. They are therefore allocated to the dependable_element as a whole via the Bazel requirements attribute:

dependable_element(
    name = "my_element",
    requirements = [":feature_requirements"],   # FeatReq targets
    ...
)

The traceability from FeatReq down to the components that implement it runs through the component_requirements chain (FeatReq CompReq component).

AI-Powered Quality Check

In addition to the structural TRLC validation described above, rules_score provides an AI-powered quality check for requirements via the trlc_requirements_ai_test rule. Unlike the structural check — which validates syntax, types, and cross-references — the AI check evaluates the quality of each requirement against requirements engineering guidelines (clarity, testability, completeness, etc.). However since LLM are not deterministic, it is not recommended to run it in the CI.

trlc_requirements_ai_test

load("@score_tooling//validation/ai_checker:ai_checker.bzl",
     "trlc_requirements_ai_test")

trlc_requirements_ai_test(
    name = "feature_requirements_ai_check",
    reqs = [":feature_requirements"],
    score_threshold = "6.0",
    tags = ["manual"],
)

Run the check explicitly with:

bazel test //my/package:feature_requirements_ai_check

Prerequisites: a GitHub Copilot licence (default) or a custom AI model configured via the _custom_ai_model attribute — see https://github.com/eclipse-score/tooling/blob/main/validation/ai_checker/README.md in the score-tooling repository for details.

Modeling Requirements in Bazel Rules

For the complete attribute reference for all requirements Bazel rules, see the rule index: