9.1 The grammar of safety-critical requirements
A safety-critical requirement is, at heart, a prescriptive statement: the system shall, followed by a behavior. The form is centuries old. The legal, prescriptive sense of shall goes back to medieval English statute drafting, and every modern functional-safety standard still uses it.
The sentence is only the start, though. A safety-critical requirement also carries structured metadata: a safety level, a requirement type, a status, a rationale and verification criteria. It carries trace links to parent and child requirements, plus allocation to functions and architectural blocks. In this subchapter I'll walk you through that structured form.
Anatomy of a safety requirement
In Sylang, a def requirement has about a dozen properties. They fall into four groups: identity, classification, content and traceability. Here's a canonical example from the insulin pump anchor:
def requirement REQ_INS_001
name "Limit maximum bolus to programmed safety ceiling"
description """
The infusion pump shall not deliver a bolus exceeding the
MaxBolusUnits parameter currently programmed for the patient,
regardless of the source of the bolus request (manual,
bolus-calculator-derived, or remote-initiated).
"""
reqtype safety
safetylevel SIL-3
status approved
rationale """
Bolus overdose is the most-reported severe-harm event in FDA
MAUDE database queries for insulin pumps (2010-2023). The
ceiling provides a hardware-enforced backstop independent
of software computation paths.
"""
verificationcriteria """
HIL test: request bolus = MaxBolusUnits + 1 via each of the
three sources. Verify no bolus delivered; verify DTC emitted.
"""
derivedfrom ref safetygoal SG_NoBolusOverdose
implements ref function BolusController, DoseLimiter
allocatedto ref block PumpControllerEach property has one job. Here they are, in the order you'll usually write them:
- name is the requirement's display title: one line, no period.
- description is the prescriptive statement. It's triple-quoted, can run over several lines, and uses the shall form.
- reqtype classifies the requirement. safety is one of 16 values; others include functional, nonfunctional, system, software, hardware, interface and several process-related types.
- safetylevel assigns the safety level: ASIL-A to ASIL-D, QM, or SIL-1 to SIL-4.
- status tracks the requirement's lifecycle: draft, review, approved, implemented, deprecated and several others.
- rationale explains why the requirement exists. It's evidence for the safety case argument, and auditors read it carefully.
- verificationcriteria describes how the requirement will be verified. The test cases that satisfy the requirement reference these criteria.
Four more properties place the requirement in the artifact graph: derivedfrom, refinedfrom, implements and allocatedto. derivedfrom ref safetygoal points upstream to the safety goal the requirement derives from (or derivedfrom ref requirement, for a parent requirement). refinedfrom ref requirement points to a refinement parent: a parent requirement that this one elaborates.
implements ref function names the functions the requirement governs. allocatedto ref block names the architectural block that hosts the requirement's implementation. Once you've written your first .req file, you'll notice these four lines do most of the traceability work for you.
The 'shall' discipline
Write every description in the prescriptive shall form: the [subject] shall [behavior]. The subject is usually the system, the device, or the block that owns the requirement (the EPB ECU shall, the infusion pump shall). State the behavior as a positive, observable action. Shall not is allowed, but prefer the positive form when it's just as clear.
Three anti-patterns keep turning up in conventional requirements practice. Keep them out of your Sylang files:
- Should or may. A requirement with should or may isn't a requirement. It's a recommendation, and it belongs in design rationale or guidance, not in the description.
- Compound requirements. A requirement with several shall clauses should be split into separate single-shall requirements, each of which you can verify on its own.
- Implementation in the requirement. The system shall use a PID controller describes how the system is built. The requirement should say what the system does; the implementation goes in the architecture artifacts.
Why .req files have no 'testedby'
Sylang's .req files have no testedby relationship pointing from a requirement to the test case that verifies it. That's deliberate. It's the single most consequential design choice in the requirements vocabulary, so let me explain it.
The conventional pattern (DOORS, Polarion, Rhapsody, every major requirements-management tool) puts explicit forward trace links on the requirement. Each requirement lists the test cases that verify it. That's convenient: the requirements engineer can see, right on the requirement page, which tests cover it.
Under any non-trivial workflow, though, it fails in a predictable way: the requirement and the test case can disagree about whether the link exists. The test is usually committed first, because it's the test-engineering team's deliverable. The requirement's testedby link is updated separately, often in a different commit, sometimes not at all.
Sylang puts the link on the test-case side only, as satisfies ref requirement <ID> on each def testcase. The link is single-sided, not bilateral. You never touch a requirement when a test is added or removed, because the test's authoring is the single source of truth.
So how do you find the tests that verify a requirement? You consult the coverage report. It scans every .tst file for satisfies references to that requirement. The answer is computed, not maintained.
The choice has a cost. To see the verifying tests, you run the coverage report instead of reading a property on the requirement. Sylang Studio computes this view on demand, in the traceability matrix and in the requirement's Verified by tab.
What follows
Subchapter 9.2 covers the controlled vocabularies (reqtype, safetylevel, status) that classify requirements in a machine-readable way. Subchapter 9.3 goes deep on bilateral traceability (the derivedfrom, refinedfrom, implements and allocatedto edges) and on the rationale and verification-criteria conventions that make your artifacts auditable. Subchapter 9.4 covers variant-aware requirements, and Subchapter 9.5 walks the insulin pump's complete safety requirement set with cross-anchor mirrors.
Exercises
9.2 Controlled vocabularies: reqtype, safetylevel, status
Three properties take their values from fixed lists that the validator enforces: reqtype, safetylevel and status. This is how the language makes requirements machine-queryable. Ask for every approved ASIL-D safety requirement, every draft software requirement, or a count by status. The query runs on consistent values instead of free-text fields that drift from author to author.
reqtype: the sixteen requirement types
The reqtype enumeration has 16 values, in three categories:
- Technical content: functional, nonfunctional, system, software, hardware, interface, safety. These describe what the technical system must do or be.
- Stakeholder and process: stakeholder, process, compliance, quality, IT, manufacturing, supplier, program. These cover non-technical requirements: process requirements for development, compliance requirements for regulatory obligations, manufacturing requirements for production.
- Catchall: others.
functional is the workhorse. Use it for any requirement that describes what the system does without specific safety implications. Use safety for any requirement whose violation contributes to a hazard. Those typically carry safetylevel ASIL-A or higher (not every requirement with a safety level is reqtype safety, but most are).
Use nonfunctional for performance, reliability, availability and maintainability constraints that aren't behaviors as such. Use system, software, hardware or interface when the requirement is specifically constrained to one technology layer.
You won't find performance in the list. Many older requirements systems have a separate performance category. Sylang folds it into nonfunctional (with tags for finer classification if you need it), because at the requirement level, performance is rarely meaningfully separable from other nonfunctional properties.
safetylevel: ASIL, SIL, QM
The safetylevel enumeration has nine values. ASIL-A, ASIL-B, ASIL-C and ASIL-D are the ISO 26262 Automotive Safety Integrity Levels. QM (Quality Management) is the ISO 26262 baseline level for items below ASIL-A. SIL-1 to SIL-4 are the IEC 61508 Safety Integrity Levels.
Which one do you pick? Match the safety-integrity level of the parent safety goal or hazard. ISO 26262 contexts use the ASIL- prefix; IEC 61508 contexts use the SIL- prefix.
ISO 26262 Part 9 (ASIL decomposition) permits an ASIL-D requirement to be implemented by two independent ASIL-B(D) channels. The decomposition itself is documented in the safety case argument, not in the requirement's safetylevel. So a decomposed channel's requirement carries safetylevel ASIL-B, with a note in rationale explaining how the decomposition was derived.
Sylang doesn't yet have first-class support for ASIL-X(Y) notation. Until it does, the convention is to document the decomposition in rationale and track it through tags.
status: the lifecycle
The status enumeration has ten values: draft, review, approved, deprecated, implemented, accepted, rejected, accepted+proposal, notapplicable, unknown. They fall into four groups:
- Primary lifecycle: draft, review, approved, deprecated.
- Stakeholder acceptance: implemented, accepted, rejected. Use these where an external commitment drives the requirement (a customer commitment, a regulatory commitment).
- Accepted with modification: the compound accepted+proposal.
- Escape values: notapplicable and unknown, for requirements excluded from scope or whose status can't be determined.
In practice, most projects use only draft → review → approved → implemented (or deprecated). The other values exist for specific needs, such as customer-acceptance workflows or regulatory-commitment tracking, that not every project has.
One trap to watch for: active is not a valid status. Many older requirements databases use active as a synonym for approved, and the Sylang validator rejects it with SYLANG_INVALID_ENUM_VALUE. Sylang says approved because, in the legal-prescriptive sense, an authority approves a requirement before it becomes binding.
What follows
Subchapter 9.3 takes bilateral traceability to the level of detail you need for production authoring. It's conceptually close to the function-model traceability of Chapter 7, with extra complexity because requirements have so many parent and child types.
A requirement can derive from another requirement, a safety goal or a hazard. It can refine another requirement, implement a function and be allocated to a block. And it can be satisfied by zero, one or many test cases.
Exercises
9.3 Bilateral traceability, rationale, and verification criteria
Requirements are the most heavily connected artifact in the engineering spine. A typical safety requirement has at least four outgoing edges: to a safety goal, a parent requirement, an implementing function and an allocating block. It can also have any number of incoming edges, from test cases and safety mechanisms that satisfy it and from FMEA failure modes that reference it.
In this subchapter I'll show you how to keep that web internally consistent and externally auditable. Then we'll look at the rationale and verificationcriteria conventions that produce auditor-grade content.
Outgoing traceability: upstream and lateral
A safety requirement usually carries three outgoing trace edges, each pointing upstream or laterally.
- derivedfrom ref safetygoal (or derivedfrom ref requirement for a child requirement derived from a parent). The upstream trace to the safety goal or parent requirement that motivates this one. The auditor's question: why does this requirement exist? derivedfrom gives the structural answer; rationale gives the explanation in prose.
- implements ref function. The lateral trace to the function whose behavior the requirement constrains. The auditor's question: what does this requirement govern? The reference makes the answer explicit and machine-checkable: the function exists in the model and is clearly the subject of the requirement's prescriptive statement.
- allocatedto ref block. The downstream trace to the architectural block that hosts the requirement's implementation. The auditor's question: where in the architecture does this requirement live? The reference answers it explicitly and supports the per-block requirement queries that organize design reviews.
You'll also meet a few less common outgoing edges. refinedfrom ref requirement names a refinement parent, used when a child elaborates a more general parent without strict derivation. requires ref parameter|datatype|feature says the requirement depends on specific configuration data existing. meets ref characteristic|safetygoal is a less frequently used satisfaction edge.
Incoming traceability: downstream
A requirement's incoming edges (the references to it from other artifacts) aren't written on the requirement itself. They're written on the referencing artifact, and the requirement's incoming traceability is computed by scanning the project's other files. The typical incoming edges are:
- satisfies (testcase → requirement). The verification edge. You write it on the test case as satisfies ref requirement REQ_X. The requirement's verified by view is computed by scanning all
.tstfiles for satisfies references. - satisfies (safetymechanism → requirement). The implementation edge for safety mechanisms. A def safetymechanism that satisfies a requirement carries it.
- derivedfrom (downstream requirement → this requirement). Requirements derived from this one carry the edge; this requirement's children view is the inverse.
- derivedfrom (failuremode → requirement). Carried by the FMEA failure modes that reference the requirement they analyze.
- implementedby (function → requirement). The ASPICE bilateral inverse of implements; the function that implements the requirement carries it.
This asymmetry is the structural reason the requirements set doesn't drift. Outgoing edges are written on the requirement; incoming edges are written elsewhere and computed. The requirement file is the single source of truth for its outgoing intent, and the verifier's side is the single source of truth for verification.
rationale: why this requirement exists
rationale is the property auditors read most. It answers why does this requirement exist?, separately from the structural answer derivedfrom gives. The two complement each other: derivedfrom gives the upstream artifact; rationale gives the engineering reasoning.
Good rationales have three qualities:
- They cite verifiable sources: industry data, published incident reports, regulatory citations, internal hazard analyses. The insulin pump's REQ_INS_001 cites the FDA MAUDE database queries for insulin pumps (2010-2023), a public source the auditor can verify.
- They explain the choice of bound or behavior instead of restating the requirement. A rationale like "this requirement exists because we need to limit the bolus" adds no information.
- They stand alone. The rationale should make sense to a reader who hasn't just read the requirement, because it's often quoted in the safety case argument or in regulatory submissions.
verificationcriteria: how it will be verified
verificationcriteria says how the requirement will be verified. It doesn't point at the verifying test case; the test case's satisfies edge does that. Instead, it describes the verification approach in prose, and the test engineer uses that prose to design the test.
Good criteria name the verification method, the test conditions, the expected behavior and the pass/fail threshold. They're concrete enough that two test engineers given the same criteria would design substantively similar tests.
Write verificationcriteria when you write the requirement, not later at test-design time. It catches unverifiable requirements early. If you can't give a requirement concrete criteria, it's one of two things. Either it's too abstract to be a requirement (it belongs in design rationale or guidance), or it describes something that can't be tested in practice (and may need restructuring into something that can).
What follows
Subchapter 9.4 covers variant-aware requirements: requirements that exist only in some variants, gated on when ref config. Subchapter 9.5 walks the insulin pump's complete safety requirement set, with cross-anchor mirrors.
Exercises
9.4 Variant-aware requirements
In a product line, requirements often differ from one variant to the next. The dual-motor EPB has requirements (motor cross-check, mismatch detection) that the single-motor variant doesn't. The advanced-trim autopilot has autoland-specific requirements the standard trim doesn't, and the CGM-integrated insulin pump has predictive low-glucose suspend requirements that the basic variant lacks.
Sylang represents this variability with when ref config on the requirement definition, using the same propagation semantics Chapter 6 introduced for artifacts in general. In this subchapter I'll show you the patterns specific to requirements.
The simple pattern: gate a requirement on a feature
The most common pattern gates a requirement on a single optional feature. The requirement exists only in variants where that feature is selected. Here's one from the insulin pump anchor:
def requirement REQ_INS_010
name "Predictive low-glucose suspend trigger threshold"
description """
The infusion pump shall suspend basal delivery when CGM readings
predict a glucose excursion below 70 mg/dL within 30 minutes,
with prediction confidence >= 80%.
"""
reqtype safety
safetylevel SIL-3
status approved
when ref config c_PredictiveLgs
derivedfrom ref safetygoal SG_NoUndetectedHypoglycemia
implements ref function PredictiveLgsController
allocatedto ref block PumpControllerNow take a variant whose .vcf has c_PredictiveLgs = 0: a basic-trim infusion pump without CGM-integrated predictive logic. There, the requirement is inactive and coverage analysis excludes it. The function it implements is inactive too (it carries the same gating), and so are the test cases that satisfy it.
Partial gating: a requirement modified by variant
A subtler pattern shows up when a requirement exists in every variant but its content differs between them. A threshold might take one numeric value in one variant and a different value in another. Think of the engage timeout in the EPB, or the analogous dose-rate threshold in the insulin pump. You have two ways to handle it.
- Two separate requirements, each gated. You write REQ_EPB_001a (gated on c_SingleMotorCaliper) with one threshold and REQ_EPB_001b (gated on c_DualMotorCaliper) with another. It's explicit and auditable, but it duplicates content in the requirement set. It suits cases where the variant-specific requirements differ in more than a parameter value (different test methods, different rationales).
- One requirement with a parameterized threshold. You write REQ_EPB_001 with the threshold as a reference to a def parameter in the interface set, and gate two variant-specific parameter values separately. It's more elegant, but the elegance has a cost: the auditor must trace through the parameter to see each variant's value. It suits cases where the variant-specific values are pure numeric differences.
My practical guidance: use pattern 2 (parameterized) for numeric threshold differences, and pattern 1 (separate requirements) where the variants differ in test method, rationale or scope. The EPB anchor does both. It uses pattern 1 for its dual-motor-only requirements (the REQ_EPB_003 cross-check) and pattern 2 for parameter differences (the clamp force setpoint varies by caliper type through the ClampForceSetpoint parameter).
Per-variant coverage analysis
The coverage analysis in Chapter 15 can evaluate each variant on its own. You can ask: for the dual-motor variant of the EPB, what fraction of the safety requirements are verified by passing test cases? The report scopes itself to the requirements and test cases active in that variant (both through when ref config gating). Then it computes that variant's coverage figure.
This per-variant view is operationally essential. Without it, you get a single figure that aggregates across all variants and doesn't match any specific variant's release readiness. With it, you can produce a variant-specific coverage report for the safety case argument behind each shipped variant.
What follows
Subchapter 9.5 walks the insulin pump's complete safety requirement set, putting the conventions of the earlier subchapters to work at production scale. It includes cross-anchor mirrors that show the same patterns expressing different domain content in the EPB, autopilot and cobot anchors.
Exercises
9.5 The insulin pump safety requirements walkthrough
In this subchapter we'll walk the insulin pump's safety requirement set using everything this chapter has covered, with mirror examples from the EPB, autopilot and cobot anchors. The pump has the densest safety profile of the four: nearly every requirement carries SIL implications. That makes it the best place to watch bilateral traceability work at production scale.
The top-level safety requirements
The pump's safety requirement set opens with three top-level requirements. Together they cover the device's dominant safety concerns: bolus overdose, occlusion and air-in-line delivery.
def requirement REQ_INS_001
name "Limit maximum bolus to programmed safety ceiling"
reqtype safety
safetylevel SIL-3
derivedfrom ref safetygoal SG_NoBolusOverdose
implements ref function BolusController, DoseLimiter
allocatedto ref block PumpController
def requirement REQ_INS_002
name "Detect occlusion within 60 seconds at maximum basal rate"
reqtype safety
safetylevel SIL-3
derivedfrom ref safetygoal SG_NoUndetectedOcclusion
implements ref function OcclusionDetector
allocatedto ref block PumpController
def requirement REQ_INS_003
name "Detect air-in-line above 0.05 mL bolus volume"
reqtype safety
safetylevel SIL-3
derivedfrom ref safetygoal SG_NoAirEmbolism
implements ref function AirInLineDetector
allocatedto ref block PumpControllerEach top-level requirement carries the four traceability edges discussed in Subchapter 9.3 (derivedfrom safetygoal, implements function(s), allocatedto block). Each carries reqtype safety, and each carries safetylevel SIL-3.
Each also has a rationale (citing FDA MAUDE database entries, IEC 60601-2-24 thresholds, or published clinical incident reports) and verificationcriteria (specifying the HIL test approach). I've left those out here for length, but you'll find them in the actual anchor file.
Cross-anchor mirror examples
The same three-edge traceability pattern shows up in the other anchors, with domain-appropriate content.
// EPB: corresponding ASIL-D safety requirement
def requirement REQ_EPB_001
name "Detect clamp force undershoot within 100 ms"
reqtype safety
safetylevel ASIL-D
derivedfrom ref safetygoal SG_NoUnintendedRelease
implements ref function ClampForceMonitor
allocatedto ref block EpbController// Autopilot: DAL-A alpha-protection requirement
def requirement REQ_AP_001
name "Limit pitch command authority above alpha_protection_threshold"
reqtype safety
safetylevel ASIL-D
derivedfrom ref safetygoal SG_NoStall
implements ref function AlphaProtectionLaw
allocatedto ref block FlightControlComputer// Cobot: SIL-3 safe-monitored-speed requirement
def requirement REQ_COB_001
name "Limit TCP speed to 250 mm/s in operator-presence mode"
reqtype safety
safetylevel SIL-3
derivedfrom ref safetygoal SG_NoOperatorImpact
implements ref function SpeedMonitor
allocatedto ref block CobotControllerThe four mirror requirements share one structural shape: a def requirement with reqtype, safetylevel and three traceability edges. Only the domain-specific content differs: the threshold (clamp force, alpha, TCP speed, dose limit) and the timing (100 ms, alpha-protection real-time, instantaneous, per-bolus). The names of the safety goal, the implementing function and the block differ too.
Closing Chapter 9
That completes the requirements artifact set. You've covered the grammar of safety-critical requirements (9.1) and the three controlled vocabularies that classify them machine-readably (9.2). Then came bilateral traceability with the rationale and verification-criteria conventions (9.3), the variant-aware patterns (9.4), and a worked walkthrough across all four anchors (this subchapter).
Chapter 10 covers the test set, the .tst file type, which satisfies the requirements through verification. It's anchored on the industrial cobot. The cobot's variety of test methods (HIL for the safety functions, manual for the operator-interaction scenarios, automated for the regression suite) shows the full method enumeration. Then Chapter 11, the closing chapter of Part III, walks the EPB anchor end-to-end from .ple to .tst to show the engineering spine as one integrated whole.
Exercises
Key takeaways
You’ve got this chapter if you remember:
- A Sylang requirement is one shall statement plus structured metadata: type, safety level, status, rationale, verification criteria and trace links.
.reqfiles have no testedby: tests point at requirements with satisfies, and the coverage report computes the rest, so the two sides can't drift.- reqtype, safetylevel and status are fixed vocabularies the validator enforces, which is what makes a requirement set machine-queryable.
- Good rationales cite verifiable sources, explain the chosen bound and stand alone, and good verification criteria are concrete enough that two test engineers would design similar tests.
- Gating requirements with when ref config shrinks each variant's requirement set by construction and lets you report coverage per shipped variant.
Check yourself
Answer in your head first, then reveal.
1Why doesn't a
.reqfile have a testedby relationship?Because links kept on both sides drift apart. Sylang keeps the link only on the test case, as satisfies, and computes the verifying tests on demand in the coverage report.
2Which three anti-patterns does the shall discipline rule out?
Using should or may (a recommendation, not a requirement), compound requirements with several shall clauses, and requirements that describe the implementation instead of the behavior.
3The validator rejects
status active. Why, and what should you write instead?active isn't in the status enumeration, so the validator raises SYLANG_INVALID_ENUM_VALUE. Use approved, which reflects an authority approving the requirement before it becomes binding.
4When should a variant-specific threshold become two gated requirements rather than one parameterized requirement?
Split it when the variants differ in test method, rationale or scope. Parameterize it when the difference is purely numeric.