Every key a contract file (<stem>.contract.yaml beside a launch file, or
system.contract.yaml in a bringup with no launch/) accepts. The contract
format is ros-launch-manifest’s, and this page is its format reference at
v0.3.12, the release the nros CLI is built
against (commit d2e2290a327d). The CLI reads a contract with that
release’s parser, so a key this page does not list is a parse error.
Every key below is accepted in the context that heads its section, and a key that is not listed is a parse error. Contexts whose keys are chosen by the author — nodes:, topics:, services:, actions:, includes:, paths:, args:, external_topics:, the endpoint maps under pub:/sub:/srv:/cli:, and the parameter names under a node’s params: — have no section here, because no allowlist applies to them.
This is the core grammar. A contract that use:s an extension may also write the keys that extension declares, in hazards.<name> and safe_state.settle: those are listed per extension in extension-reference.md (the bundled vehicle.braking and the reference extensions), and extension-guide.md says how to write one.
The kind column is the rule of contract-primitives.md as data: a fact is what the code does, a requirement is what it must achieve, meta is structure, and a consequence is computable from the facts — a second copy the graph already knows, kept only where the graph has no answer (an external source). scripts/derivation_census.py counts how often each consequence agrees.
The extensions this contract uses, a map of name -> version requirement (use: { vehicle.braking: "^1" }; ^, ~, = or >=). With it, hazards.<name> and safe_state.settle may carry the keys those extensions declare; without it an unknown key is an error.
rlm
meta
since v0.1.49
The grammar release this file needs, v<major>.<minor>.<patch> (or >= that). Checked before any other key: a checker whose grammar is older refuses the file naming both releases, instead of refusing the first key it does not know as if it were a typo. A checker before v0.1.49 refuses the key itself as unknown. Optional; beside version, which is the file format and stays 1.
args
meta
Arguments this manifest requires, supplied by the launch scope.
exclude_patterns
removed
Removed — it was parsed and read by nothing, so it excluded nothing. Mark an expected-absent side with external:.
nodes
meta
Node declarations, keyed by bare node name.
topics
meta
Topic declarations, keyed by topic name.
services
meta
Service declarations, keyed by service name.
actions
meta
Action declarations, keyed by action name.
includes
meta
Child scopes, each an inline manifest (the file-reference form was removed in v0.1.59).
paths
meta
Event chains: end-to-end requirements naming two topics and a budget.
hazards
meta
Hazards: what is watched, how long the system has, and which path reaches the safe state.
functions
meta
Named guard groups: what a set of topics together provides. A mode requires functions; a hazard may guard one by name.
modes
meta
Operational modes: what each requires, and the fallback sequence (the ordered degradation levels) to fall to when it is lost.
severity_levels
removed
Renamed integrity_levels: in v0.3.3: an ASIL, SIL or DAL is an integrity level, and ISO 26262’s severity is the S0-S3 class it is derived from. play_launch migrate <contract> --write rewrites it.
integrity_levels
meta
since v0.3.3
The integrity scale hazards draw from, ascending; the first entry derives no criticality. Default: QM, ASIL_A..ASIL_D (ISO 26262), so writing that scale out changes nothing and is only for the reader. A contract that uses a profile takes the profile’s scale and may not also write this.
external_topics
deprecated — use topics.<name>.external
Deprecated in v0.1.59: the second place for the fact topics.<name>.external states. Move each entry under topics: as <name>: { external: <side>, type, qos }; play_launch migrate does it. Removed in the next grammar release.
chains
removed
Removed — state the requirement as an event chain and let the route be derived.
if
meta
Only on an INLINE includes: entry, whose value is a nested manifest: include this child only when the condition holds. Refused at the root of a standalone manifest.
unless
meta
Only on an INLINE includes: entry: include this child unless the condition holds. Refused at the root of a standalone manifest.
policy
meta
since v0.1.61
Project policy for the consumer’s rules: { unsupervised_measured: warn | error }. Absent: the defaults.
links
fact
since v0.3.4
Named links: <name>: { max_transport, clock, monitor }, one transport stated once, with its source. A subscriber names the link its hop crosses (sub.<ep>.link). Visible to this manifest and its inline includes.
supervision
fact
since v0.1.61
The platform terms of a supervised budget’s detection delay, stated once: { tick, switch }. Read by the consumer’s overrun case (supervised-fit); required once any budget states supervise:.
acknowledged
meta
since v0.2.3
Findings the author has read and keeps: a list of { rule, at, reason }, at the contract’s root only. The consumer reports a warning or info whose rule id and path match an entry as acknowledged, with the reason, and counts it apart from the warnings; an entry matching an error is itself an error (errors cannot be acknowledged), and one matching nothing is a warning, so an acknowledgement cannot outlive its finding.
let
meta
since v0.2.4
Names for values, stated once and read as $(let <name>): a mapping of name to value, in order, at the contract’s root. An entry may read earlier entries (and $(param), $(var)); a forward reference or a cycle is an error. Separate from launch configurations: $(var) never reads it.
True for a ROS 2 managed node; runtime monitors skip checks until it is Active.
pub
meta
Publisher endpoints, keyed by endpoint name. A key is a LOCAL name: the node’s FQN is prefixed to it, so a / in a key is refused; connect the topic with a launch remap or a topics: entry.
sub
meta
Subscriber endpoints, keyed by endpoint name. A key is a LOCAL name: the node’s FQN is prefixed to it, so a / in a key is refused; connect the topic with a launch remap or a topics: entry.
srv
meta
Service server endpoints, keyed by LOCAL endpoint name. Not neutral when omitted: a consumer sizes the image’s pools from this list (an embedded realizer derives its service counts from it), so a server the code creates and the contract leaves out is found at boot, not here.
cli
meta
Service client endpoints, keyed by LOCAL endpoint name. Not neutral when omitted, for the same reason as srv:: pools are sized from the list. A reaction route crosses a client -> server edge as a message (the resolver’s reaction walk); a server with no path its request triggers latches the request for its own timer, and the walk charges that timer’s period as a sampling hop.
paths
meta
This node’s internal paths, keyed by path name.
criticality
consequence
Scheduling criticality: high
concurrency
fact
Which of this node’s paths may NOT run concurrently. Absent means all of them serialize: every path of the node waits for any other that is running (a single-threaded executor), and the checker charges that wait (path-exclusion). Declare exclusive groups to say which may in fact overlap.
params
fact
Parameters this node declares, keyed by name, each { type: <ROS 2 type> }. Names and types only: a string or array capacity is a board fact, not a contract one. params: {} means the node declares no parameters; a missing params: means not stated. The two stay distinct in the model: {} becomes an empty contracts.node_params entry, a missing key none.
Lower bound on this endpoint’s rate. A REQUIREMENT, not a mechanism: nothing fires when a period passes. A fault is detected only by a mechanism that does – a QoS lease_duration or deadline, or a max_age someone evaluates (on_violation.mechanism) – so min_rate_hz never counts as a hazard’s detector. A publisher that promises no rate states aperiodic: true instead of leaving this out.
max_rate_hz
fact (pub) / requirement (sub)
Upper bound on this endpoint’s rate.
max_age
requirement
Subscriber: maximum data age at receive (now - header.stamp).
max_age_ms
removed
Removed — write max_age: <n>ms (or ns/us/s). The unit in a NAME is what lets a value be 1000x wrong and still parse.
state
fact
Subscriber: read-latest rather than causal. The node caches the message and a timer path reads it, so a reaction arriving here waits for that timer: the walk charges one period (the timer’s jitter too, when stated) as a sampling hop, shown as (+Nms sampling) in a route.
required
fact
Subscriber: this endpoint must be connected.
qos
fact
QoS overrides for this endpoint.
max_transport
requirement
Client (since v0.2.5): the request leg’s worst-case transport, overriding the service’s max_transport; charged on a reaction route’s success branch through the call. Subscriber: the worst-case transport into THIS subscriber, overriding the topic’s (one topic does not have one cost: in-process, another process, another machine). Charged in path and chain latencies, and in a hazard’s reaction route on the GUARD EDGE (the hop into the subscriber that detects the fault), but not after a dwell’s deadline, which the dwelling level’s owner reads on its own clock. A declaration on no guard edge changes no hazard’s numbers (declared-not-charged).
link
fact
since v0.3.4
Subscriber only: the link this subscriber’s hop crosses, a name under links:. The link’s max_transport is this subscriber’s, charged wherever a written one is; writing both is refused. A written max_transport stays legal and is reported as transport-inline.
max_transport_ms
removed
Removed — write max_transport: <n>ms (or ns/us/s). The unit in a NAME is what lets a value be 1000x wrong and still parse.
on_violation
requirement
The reaction this subscriber owes when its assumption is violated.
ingress
removed
Renamed arrival_curve: in v0.3.7: a token bucket bounding what arrives is network calculus’s arrival curve. play_launch migrate <contract> --write rewrites it.
arrival_curve
requirement
since v0.3.7
Subscriber: what this endpoint is made to ABSORB, an arrival curve in token-bucket form (network calculus: rate ρ, burst σ) { rate_hz, burst }. Not a QoS policy, and not the rate it needs (min_rate_hz): a consumer bounds the device’s read path and the router’s pacing by it. Both keys required, so an unstated burst never reads as unbounded. Refused under pub:/cli:.
min_interarrival
requirement
since v0.1.68
Subscriber: the least time between two arrivals. Its callback is then a sporadic task (T_min). An event input with no rate bound, no min_interarrival and no budget is unanalysable: a consumer that supervises a deadline refuses it. Refused under pub:/cli:, and above 1 / min_rate_hz.
budget
requirement
since v0.1.68
Subscriber: the execution time its callback may use per budget_period. Its callback is then served (a server of budget Q per period P, analysed as a periodic task). Requires budget_period, and may not exceed it. Refused under pub:/cli:.
budget_period
requirement
since v0.1.68
Subscriber: the server period P of budget. Only beside budget.
call
fact
since v0.1.69
Client: how the code waits for the response. blocking: the callback that sends the request waits for it, so under a preemptive executor the server must run at a more urgent level (a less urgent one is a priority inversion, its own level a deadlock). async: the request is sent and a later callback takes the response. Absent means not stated: a consumer checks a stated call and reports an unstated one. Refused under pub:/sub:.
timeout
fact
since v0.2.5
Client: how long the code waits for the response before it gives up (a duration, $(param …)-capable): spin_until_future_complete with a timeout, a pending-request prune, a tick-counting poll. A fact about the code, not a requirement. Absent means the client may wait forever (rclcpp’s default), so a reaction route through the call is unbounded unless the degradation level is supervised (call-unbounded). Refused under pub:/sub:.
on_timeout
fact
since v0.2.5
Client: what the code does when timeout passes, { reaction: <mode | event chain> } or { retry: { attempts, backoff }, then: { reaction } }. A route through the call is charged the worse of the success branch and timeout x attempts + backoff x (attempts - 1) + this reaction’s route. Refused under pub:/sub:.
on_rejected
fact
since v0.2.5
Client: what the code does when the server answers and refuses (success: false), { reaction: <mode | event chain> }. Needed when the route continues at the client after a blocking call (call-rejected-unhandled). Refused under pub:/sub:.
buffer
fact
Buffering discriminator for a state subscriber: latest
on_demand
removed
Renamed aperiodic: in v0.3.7: an activation with no period and no minimum separation is an aperiodic task. play_launch migrate <contract> --write rewrites it.
aperiodic
fact
since v0.3.7
Publisher: aperiodic – publishes only when asked (a service call, an operator) and promises no rate. Unlike an omitted min_rate_hz, which says nothing, this is acted on: no rate is derived for the topic, no runtime rate monitor is generated for the endpoint, and a subscriber’s min_rate_hz or a topic rate_hz against it is a rate-hierarchy error. Refused beside min_rate_hz, and under sub:/cli:.
jitter
removed
Removed — jitter is a property of a route, not one publisher. Use max_jitter on a path.
The least time between two requests. The server’s callback is then a sporadic task (T_min). See min_interarrival on a subscriber.
budget
requirement
since v0.1.68
The execution time the server’s callback may use per budget_period (a served callback). Requires budget_period, and may not exceed it.
budget_period
requirement
since v0.1.68
The server period P of budget. Only beside budget.
idempotent
fact
since v0.2.5
A repeated request has the effect of one. Licenses a client’s on_timeout.retry (call-retry-not-idempotent): a retry after a lost response runs the operation twice.
stale_after
fact
since v0.2.5
The server refuses a request older than this, by the request’s source timestamp. Without it a request the client timed out on may still act after the client’s fallback (call-late-effect).
max_response_ms
removed
Removed — write max_response: <n>ms (or ns/us/s). The unit in a NAME is what lets a value be 1000x wrong and still parse.
Publication rate. Derivable from the timers that drive it — see derivable-rate.
max_transport
deprecated — use nodes.<n>.sub.<ep>.max_transport
Deprecated in v0.1.60: a transport is the hop into ONE subscriber, stated on that subscriber’s endpoint. Still read for one release as the max_transport of every subscriber of this topic that states none of its own (charged as the subscriber’s is: path and chain latencies, and a reaction route’s guard edge). play_launch migrate copies the value onto each such subscriber declared in the same file and deletes this key. Removed in the next grammar release.
max_transport_ms
removed
Removed — write max_transport: <n>ms (or ns/us/s). The unit in a NAME is what lets a value be 1000x wrong and still parse.
drop
requirement
Permitted message loss on this topic.
external
meta
Mark one side of this topic as provided by an external system.
Declare this service only when the condition holds.
unless
meta
Declare this service unless the condition holds.
type
fact
ROS service type.
server
meta
Server endpoints, as node/endpoint.
client
meta
Client endpoints, as node/endpoint.
external
meta
Mark one side of this service as provided by an external system: server
max_transport
requirement
since v0.2.5
The request leg’s worst-case transport for every client of this service that states none of its own (cli.<e>.max_transport). Charged on a reaction route’s success branch through the call.
Declare this action only when the condition holds.
unless
meta
Declare this action unless the condition holds.
type
fact
ROS action type.
server
meta
Server endpoints, as node/endpoint.
client
meta
Client endpoints, as node/endpoint.
external
meta
Mark one side of this action as provided by an external system: server
call
fact
since v0.1.69
How every client in client waits for its result: blocking (the callback that sends the goal waits for the result) or async (a later callback takes it). Absent means not stated. See call on a cli: endpoint.
Removed in v0.1.59 – nothing ever loaded the named file, so the include declared nothing. Write the child contract inline as includes.<name>: { nodes: ..., ... } (its if/unless at that inline manifest’s root), or delete the entry; a launch include’s own contract is found next to its launch file.
Deprecated in v0.1.59: the legacy spelling of trigger: { input: [...] }, read as that trigger when no trigger: is written; play_launch migrate rewrites it. An empty or missing input: does NOT make a timer: a timer is trigger: { timer: ... }, and a path with neither is unclassified. Removed in the next grammar release.
output
fact
Endpoints (node path) or topics (event chain) this path produces.
max_latency
requirement
Latency budget for this path. On a NODE path: take -> publish of one callback, and the cost a reaction route charges for the hop; an embedded realizer may ALSO turn it into a derived node deadline and a runtime latency monitor in the image, so a cost that must not be a deadline (a queueing wait, a link) belongs in its own key (max_transport, a timer’s jitter), not here. On a EVENT CHAIN: the NOMINAL end-to-end traversal of the subtree, checked by chain-latency; a hazard’s fault route is derived separately by walking the reactions, and does not read it.
max_latency_ms
removed
Removed — write max_latency: <n>ms (or ns/us/s). The unit in a NAME is what lets a value be 1000x wrong and still parse.
correlation
removed
Removed — nothing ever read it. State fan-in policy with sync:.
tolerance
fact
Max header.stamp spread between a fan-in path’s inputs still treated as one set.
tolerance_ms
removed
Removed — write tolerance: <n>ms (or ns/us/s). The unit in a NAME is what lets a value be 1000x wrong and still parse.
drop
requirement
Event chain only: the end-to-end loss budget, max_count: N / W and max_consecutive: K (or the bare N / W). No topic on the path’s route may permit more loss than the whole (drop-tightness). On a node path it is refused since v0.1.60: nothing read it there; the loss belongs on the topic the path outputs (topics.<t>.drop), where play_launch migrate moves it.
trigger
fact
What causes this path’s output: timer
sync
fact
Fan-in synchronization policy for an input trigger with two or more endpoints.
max_jitter
requirement
Permitted variation in this path’s latency.
min_latency
fact
Best-case latency. Exists so that max_jitter is falsifiable.
safe_state
fact
What this path produces when it is a reaction: the endpoint it commands, and the plant’s settle time.
miss
requirement
What a missed deadline costs and what to do about it.
segments
removed
Removed with chains: — a written route is a second copy of the graph.
Timer rate, Hz. Required, and must be greater than zero. A bare number, or the map form { value, source } (since v0.1.61) to say where the rate comes from: source: allocated lets the consumer refuse a period outside the range it derives.
jitter
fact
since v0.1.49
Release jitter: how late a tick may be released after its nominal instant, measured (a duration, less than one period). A reaction that waits for this timer is charged period + jitter (the reaction walk’s sampling hop and dwell-expiry’s notice) instead of a bare period. Absent: ticks are on time. A budget: the map form { duration, source } applies.
param
fact
since v0.1.58
The parameter of this path’s node that holds the timer’s RATE, Hz (update_rate). Its resolved launch value must equal rate_hz (timer-param). At most one of param and period_param.
period_param
fact
since v0.1.58
The parameter of this path’s node that holds the timer’s PERIOD, seconds. Its resolved launch value must equal 1 / rate_hz (timer-param).
The value a $(param <name>) reads when no launch source sets the parameter (the code’s compiled-in default, stated). Without it, reading an unset parameter is param-unset.
Integrity level from the HARA (ASIL_D, SIL_3, DAL_A, …): the level the analysis assigns, not ISO 26262’s S0-S3 severity class, which is one of its inputs. Consumed, never computed.
severity
removed
Renamed integrity: in v0.3.3: an ASIL, SIL or DAL is an integrity level, and ISO 26262’s severity is the S0-S3 class it is derived from. play_launch migrate <contract> --write rewrites it.
description
meta
What the hazardous event is.
guards
removed
Renamed monitors: in v0.3.7: the topics watched for a fault are its monitored signals (in formal methods a guard is a transition’s condition). play_launch migrate <contract> --write rewrites it.
monitors
meta
since v0.3.7
The monitored signals: topics watched for the fault. A bare name is one guard (a topic, or a function by name: a redundant set is functions.<f>: { all_of: [...] }, guarded as f); a list is a group lost when any member is.
on
fact
Fault classes the monitors report, one or a list: omission
ftti
requirement
Fault-tolerant time interval: fault to hazardous event, absent reaction. Checked by fault-reaction-time.
enters
meta
since v0.1.59
The mode the hazard enters: the first degradation level of the fallback: sequence it walks to a safe state, each level checked in its own right (degradation-level-time) and the minimal risk condition (the last level) against ftti. Exactly one of enters and reaction; a name that is not a mode of this scope is enters-unknown-mode.
reaction
meta
The event chain whose route reaches the safe state: a one-level reaction. Exactly one of enters and reaction. A mode named here is the pre-0.1.59 spelling of enters (deprecated-spelling; play_launch migrate rewrites it).
when
fact
The value that is the fault, { field: <name>, <op>: <constant> }, on a hazard whose guard is a detector’s output. Requires reported among the on: classes (when-requires-reported).
detection
fact
Fault to detection when that is physics, not a detector’s timeout (an occlusion building pressure), a duration or { duration, source }. Charged before the detection the consumer derives from the detectors, so stating it never buys slack. Usually derived by an extension (source: { derived: ... }).
deadline_by
requirement
<extension>/<check>: the check that is this hazard’s requirement when it is not a time (a safety distance). A hazard states ftti, deadline_by, or both.
reaction_total
removed
Read-only: the consumer computes it (detection + route + settle) and hands it to extension checks. A contract never writes it.
Functions (or bare topics) this mode needs; it is available while every one holds.
fallback
requirement
Modes to fall to, in order, when this one is lost: the fallback sequence of degradation levels. The last is the minimal risk condition (MRC) and must require nothing losable.
reaction
meta
The event chain that reaches this mode’s safe state.
overrides
requirement
Requirement values that apply IN THIS MODE, pinned over the scalar declared elsewhere.
min_dwell
requirement
since v0.3.3
A transitional degradation level’s dwell time (window: before v0.3.3): while the level stays available the system stays AT LEAST this long (the time the level promises whoever it waits for, a driver’s takeover time), then takes the next level. The level below starts no sooner than the deadline and within its own reaction route after it, and that route is where the deadline’s notice is charged (dwell-expiry); its first hop crosses no link (the owner reads its own clock), so a guard edge’s max_transport is not charged there. A duration, or { duration, param } binding it to the parameter that enforces it. Never on the minimal risk condition (dwell-at-mrc); unbound is dwell-unbound.
window
removed
Renamed min_dwell: in v0.3.3: a least time in a mode before the next is the switched-systems dwell time. play_launch migrate <contract> --write rewrites it.
exit
requirement
{ holds: <function>, to: <mode> }: while this level is active, the function holding ends the fallback sequence in to. Only on a level with a min_dwell; to is outside every fallback: list.
Removed in v0.1.59 – an inline redundant group is the same group functions.<f>: { all_of: [...] } states by name. Declare the function and monitor it by name: monitors: [<f>]; play_launch migrate does it.
The endpoint this reaction commands the safe state on.
settle
fact
How long the plant takes to reach the safe state once commanded. settle: <d> is shorthand for settle: { duration: <d> }; the map is { duration ; response ; source } plus the keys of a used extension that derives settle.duration (v0.2.0: the braking profile decel, jerk with the hazard’s entry_speed is the bundled vehicle.braking’s; settle-derived prints its trace). response is added to either (omitted: 0). Both a duration and a derivation: the derivation is charged and the two compared (settle-conflict).
The written settle (a measured duration): settle: { duration: 2s } is settle: 2s. Beside an extension’s keys, the fallback when a hazard does not write a key the derivation needs (settle-entry-missing), and compared against the derivation (settle-conflict). Required when no extension derives the settle.
response
fact
since v0.1.58
The vehicle’s response: from the braking command to the deceleration the plant then holds (a duration). Added to the settle, a written duration or a derived one alike (an extension that reads settle.response, as vehicle.braking does, adds it in its own formula; settle-derived and --explain print both parts). Omitted: 0, so a written duration that already includes the response omits it. The map form { duration, source } applies.
source
meta
since v0.1.60
Where the written duration comes from, as a budget’s source:. Requires duration: a profile’s settle is derived from its parameters.
supervise
requirement
since v0.1.61
The runtime supervision of the WHOLE settle (since v0.1.62): from the safe state’s command to standstill, the written duration or the derived profile plus the response. { reaction: <path> | enters: <mode>, mechanism: executor | timer, observes: <node>/<subscriber> }: the platform arms due = command + settle + how late it sees standstill (observes: that input’s period + its max_transport), and a vehicle not at standstill by then starts the reaction. The consumer’s overrun case charges the level up to the settle’s end, that observation, the detection and the reaction’s route and settle. v0.1.61 took it on a written duration only.
The budget itself, with a unit. Required. max_latency: { duration: 149ms, source: ... } states the same budget as max_latency: 149ms, plus where it comes from. Accepted by max_latency, max_jitter, max_transport, max_age, max_response, within, ftti, a timer’s jitter, a settle’s response and a mode’s min_dwell (where it is the least time the level lasts while it stays available: the level below starts no sooner; positive). See Bounds below.
param
fact
since v0.1.58
The parameter whose resolved launch value, in seconds, must equal duration. On max_age: a parameter of this subscriber’s node (max-age-param). On a mode’s min_dwell: <node>.<parameter> (dwell-param). No other bound takes one.
source
meta
since v0.1.58
Where the budget comes from: requirement (chosen: a hazard analysis, a decision, a configured value), measured (an observed maximum plus a margin: NOT a bound), derived (computed from other numbers of the contract or the image’s parameters) or analysed (an upper bound from an analysis). { measured: { max, n, margin } } states the observations, and the consumer checks that max x (1 + margin), rounded up to the next ms, reproduces duration (budget-rule). allocated (since v0.1.61): chosen inside a range the consumer derives.
supervise
requirement
since v0.1.61
The runtime checks the budget while the system runs and a miss starts a fallback: { reaction: <path> | enters: <mode>, mechanism: executor | timer }. The consumer derives the detection delay and checks that the overrun case (the budget + the detection + the fallback’s route and settle) fits the hazard’s FTTI. A budget’s level is derived from this and source: analysed -> bound; supervised; measured alone -> unsupervised. Not on a min_dwell (a least time).
Single-term form: the largest value observed (a duration). For a timer tick with period, the largest lateness beyond the period.
n
fact
since v0.1.58
Single-term form: how many samples the maximum is over.
period
fact
since v0.1.58
Single-term form: a timer tick’s period, charged without margin: the term is period + max x (1 + margin).
margin
requirement
since v0.1.58
The margin over the observed maximum, a fraction (0.2 = 20 %). Required with max or terms.
run
meta
since v0.3.4
Where the observations were made (since v0.3.4): a run directory, a date, a method, free text. play_launch measure writes the run it read.
terms
fact
since v0.1.58
Several terms summed, a map of name -> { max, n, period }: each is rounded up to the next ms on its own, then they are added (tick: { period: 100ms, max: 14.84ms }, work: { max: 25.04ms } -> 118 + 31 = 149 ms). Refused beside max.
The path a miss starts: a path of the budget’s own node (as on_violation.reaction), else an event chain of the manifest. Exactly one of reaction and enters.
enters
fact
since v0.1.61
The mode a miss enters; its reaction: event chain is what runs. Exactly one of reaction and enters.
mechanism
fact
since v0.1.61
What checks the budget. Required. executor: checked in the spin loop, so the detection waits for the longest callback on that executor, and a stuck callback is not caught (slowness, not a hang). timer: an independent timer and thread, which catches both and adds the platform’s switch (supervision.switch).
observes
fact
since v0.1.62
A settle’s supervision only: the input the platform sees standstill on, <node>/<subscriber> of this manifest. The consumer derives how late standstill is seen: the input’s period (the slowest of the topic’s rate_hz and the subscriber’s min_rate_hz) + the subscriber’s max_transport, and adds it to the supervised deadline. Refused on any other budget.
early
requirement
since v0.3.1
A settle’s supervision only: the response check, { within, drop }. The platform arms a second, earlier due, command + within + the observation (observes), and judges the speed against the one it saw when it armed: met when the vehicle has shed at least drop or is at standstill; a miss starts the same reaction as the settle’s. The consumer charges its own overrun row (the level up to the command + within + the observation + the detection + the reaction’s route and settle) and checks drop against the speed the nominal profile sheds by within (supervised-early). Refused on any other budget.
resume
fact
since v0.3.2
The reaction hands its output back and resumes it, { after }: once the reaction has run, the path that normally publishes the reaction’s output takes it over again when it next runs; if that path then stays silent for after, the reaction resumes the output, once and for good. The consumer charges the gap (after + this supervision’s detection delay) once on every overrun row whose fallback is this reaction (supervised-fit). Absent: the reaction keeps its output, and no gap is charged.
The bound on one message’s transport across the link, from the publish to the subscriber’s take. Required. A best-effort link (serial, TCP, DDS between processes or hosts) has no derivable worst case: state it measured, with source: { measured: { max, n, margin, run } } (link-unsourced otherwise). play_launch check --against <run> holds it: a message in a run over the bound is transport-exceeded.
clock
fact
since v0.3.4
synced or unsynced (the default): whether the two ends’ clocks are comparable. Synced: a message’s stamp age at the receiver is its transport, so it can be measured per message. Unsynced: only arrivals can be timed, so measure cannot propose the bound.
monitor
fact
since v0.3.4
Reserved, parsed and not read: a runtime link monitor, { reaction: <path> } or { enters: <mode> }. No consumer builds one and no rule reads it (not adopted): a link’s bound is measured and sourced, and check --against holds it against runs. A best-effort link on an unsynchronised wire could only be monitored by the gap between arrivals, which duplicates the receiver’s own silence detector.
The path a link fault starts: a path of the subscriber’s node, else an event chain of the manifest. Exactly one of reaction and enters. Reserved: monitor is not read.
enters
fact
since v0.3.4
The mode a link fault enters; its reaction: event chain is what runs. Exactly one of reaction and enters. Reserved: monitor is not read.
How long the handed-back output may stay silent before the reaction resumes it: <n> periods of the path that publishes the reaction’s output in the normal case (the consumer reads its timer’s period), or a duration. Positive. Required.
When the check runs, from the safe state’s command (a duration, positive). Past the settle’s response and before the settle’s end; the observation is added, as on the settle’s own due. Required.
drop
requirement
since v0.3.1
The least speed the vehicle must have shed by within, against the speed the platform saw when it armed (a speed with m/s or km/h, positive). The consumer refuses a drop above what the nominal profile sheds by within (an extension’s derive settle.speed_lost, as vehicle.braking 1.1 states), which would call a nominal stop a fault. Required.
The rule id of the finding, as the diagnostic prints it (reaction-unguarded). Required, non-empty.
at
meta
since v0.2.3
The dotted path the diagnostic reports (hazards.<h>.reaction; check --format json prints it as path). Required, non-empty. Two entries naming the same rule and path are refused.
reason
meta
since v0.2.3
Why the finding is kept, printed beside it. Required, non-empty.
The mode the hazard falls to, or the event chain that runs, when the wait passes. Without retry:.
retry
fact
since v0.2.5
The code asks again: { attempts, backoff }. Sound only when every server declares idempotent: true (call-retry-not-idempotent), and bounded only with attempts and then: (call-retry-unbounded).
then
meta
since v0.2.5
What the code does after the last attempt, { reaction }. Only beside retry:.
The period the monitor’s clock is read at: the executor’s tick, the supervision timer’s resolution (a duration, positive). Part of every supervised budget’s detection delay.
switch
fact
since v0.1.61
The interrupt plus the thread switch before a timer mechanism’s reaction runs (a duration). Required by a mechanism: timer supervision.
Every key below is a spelling of one bound: a value with a unit, what it limits (its kind), from which side, where the number comes from (source, in the map form) and, for two of them, the parameter of the image that must carry it (param). The keys keep their names; each parses to the bound its row gives. map form says what the key accepts besides its bare value: { duration, source } (the budget map form above), or that plus param.
key
where
kind
limit
unit
map form
max_latency
paths.<name>
latency
at most
duration
{ duration, source }
min_latency
paths.<name>
latency
at least
duration
max_jitter
paths.<name>
jitter
at most
duration
{ duration, source }
jitter
trigger.timer
jitter
at most
duration
{ duration, source }
min_rate_hz
pub/sub/cli.<endpoint>
rate
at least
Hz
max_rate_hz
pub/sub/cli.<endpoint>
rate
at most
Hz
max_age
pub/sub/cli.<endpoint>
age
at most
duration
{ duration, source, param }; param: a parameter of the subscriber’s node, seconds (max-age-param)
A quantity may READ a number instead of restating it: a duration, a rate, a count, the duration: or value: of a braces form, a QoS duration, and an extension key typed param. The value is an expression:
value := term (('+' | '-') term)*
term := factor (('*' | '/') factor)*
factor := number unit? | ref unit | '$(let' name ')' | '(' value ')'
ref := '$(param' [node] name ')' | '$(var' name ['@' node] ')'
reference
reads
$(param [<node>] <name>)
the node’s effective parameter value; one argument: the node the key sits under; a bare node: a node key of this contract; /<fqn>: any node of the launch tree
$(var <name> [@<node>])
a launch configuration, at the end of the contract’s launch file (or where <node> was declared)
$(let <name>)
an entry of the root let:
A $(param) or $(var) takes a unit, always ($(param watchdog_ms) ms): a parameter carries none, and reading it in SI would make a 100 ms lease a 100 s one. On a count it takes none. A $(let) carries its entry’s unit. Units are rlx’s (extension-reference.md); a value of the wrong dimension for its key is param-dimension. source: beside a reference is a parse error (source-on-reference): the reference is the value’s source. A value with no reference is the literal it always was.
The consumer that holds the launch tree evaluates every reference per scope instance and hands each rule a plain number; a contract read alone leaves the value unknown (the key absent), never zero.
A node a hazard reaches (it feeds, detects for, or reacts for the hazard) takes a scheduling criticality from the hazard’s integrity, the MAX over every hazard that reaches it. The first entry of integrity_levels is “no safety requirement” and derives nothing; the other n entries split into three buckets by ceil(3 rank / n) (1 low, 2 medium, 3 high). A written criticality on such a node is an error; on a node no hazard reaches it stands. The default scale (no integrity_levels declared):
integrity
criticality
QM
none
ASIL_A
low
ASIL_B
medium
ASIL_C
high
ASIL_D
high
A contract that uses a profile (use: { iec61508: "^1" }) draws integrity levels from the profile’s integrity_scale and takes each level’s criticality from the profile’s criticality map, stated level by level, instead of the split above; it may not also write integrity_levels:. Reference profiles ship with the checker: iso26262, iec61508, iec61511, do178c, iec62304, iso13849, en50129 (iso26262 is the default scale and map above).