Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Contract format reference

Reference · Level 3: Production and tuning

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.

To write a contract for your own nodes, see Contracts for a C or C++ workspace.

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.

manifest

keykindstatusmeaning
versionmetaManifest format version. Absent means 1.
usemetaThe 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.
rlmmetasince v0.1.49The 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.
argsmetaArguments this manifest requires, supplied by the launch scope.
exclude_patternsremovedRemoved — it was parsed and read by nothing, so it excluded nothing. Mark an expected-absent side with external:.
nodesmetaNode declarations, keyed by bare node name.
topicsmetaTopic declarations, keyed by topic name.
servicesmetaService declarations, keyed by service name.
actionsmetaAction declarations, keyed by action name.
includesmetaChild scopes, each an inline manifest (the file-reference form was removed in v0.1.59).
pathsmetaEvent chains: end-to-end requirements naming two topics and a budget.
hazardsmetaHazards: what is watched, how long the system has, and which path reaches the safe state.
functionsmetaNamed guard groups: what a set of topics together provides. A mode requires functions; a hazard may guard one by name.
modesmetaOperational modes: what each requires, and the fallback sequence (the ordered degradation levels) to fall to when it is lost.
severity_levelsremovedRenamed 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_levelsmetasince v0.3.3The 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_topicsdeprecated — use topics.<name>.externalDeprecated 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.
chainsremovedRemoved — state the requirement as an event chain and let the route be derived.
ifmetaOnly 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.
unlessmetaOnly on an INLINE includes: entry: include this child unless the condition holds. Refused at the root of a standalone manifest.
policymetasince v0.1.61Project policy for the consumer’s rules: { unsupervised_measured: warn | error }. Absent: the defaults.
linksfactsince v0.3.4Named 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.
supervisionfactsince v0.1.61The 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:.
acknowledgedmetasince v0.2.3Findings 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.
letmetasince v0.2.4Names 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.

nodes.<name>

keykindstatusmeaning
ifmetaInclude this node only when the condition holds.
unlessmetaInclude this node unless the condition holds.
lifecyclefactTrue for a ROS 2 managed node; runtime monitors skip checks until it is Active.
pubmetaPublisher 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.
submetaSubscriber 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.
srvmetaService 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.
climetaService 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.
pathsmetaThis node’s internal paths, keyed by path name.
criticalityconsequenceScheduling criticality: high
concurrencyfactWhich 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.
paramsfactParameters 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.

pub/sub/cli.<endpoint>

keykindstatusmeaning
min_rate_hzfact (pub) / requirement (sub)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_hzfact (pub) / requirement (sub)Upper bound on this endpoint’s rate.
max_agerequirementSubscriber: maximum data age at receive (now - header.stamp).
max_age_msremovedRemoved — 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.
statefactSubscriber: 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.
requiredfactSubscriber: this endpoint must be connected.
qosfactQoS overrides for this endpoint.
max_transportrequirementClient (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).
linkfactsince v0.3.4Subscriber 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_msremovedRemoved — 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_violationrequirementThe reaction this subscriber owes when its assumption is violated.
ingressremovedRenamed 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_curverequirementsince v0.3.7Subscriber: 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_interarrivalrequirementsince v0.1.68Subscriber: 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.
budgetrequirementsince v0.1.68Subscriber: 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_periodrequirementsince v0.1.68Subscriber: the server period P of budget. Only beside budget.
callfactsince v0.1.69Client: 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:.
timeoutfactsince v0.2.5Client: 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_timeoutfactsince v0.2.5Client: 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_rejectedfactsince v0.2.5Client: 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:.
bufferfactBuffering discriminator for a state subscriber: latest
on_demandremovedRenamed 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.
aperiodicfactsince v0.3.7Publisher: 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:.
jitterremovedRemoved — jitter is a property of a route, not one publisher. Use max_jitter on a path.
jitter_msremovedRemoved — see jitter.

srv.<endpoint>

keykindstatusmeaning
max_responserequirementDeadline for answering a request on this service.
min_interarrivalrequirementsince v0.1.68The least time between two requests. The server’s callback is then a sporadic task (T_min). See min_interarrival on a subscriber.
budgetrequirementsince v0.1.68The execution time the server’s callback may use per budget_period (a served callback). Requires budget_period, and may not exceed it.
budget_periodrequirementsince v0.1.68The server period P of budget. Only beside budget.
idempotentfactsince v0.2.5A 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_afterfactsince v0.2.5The 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_msremovedRemoved — 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.

topics.<name>

keykindstatusmeaning
ifmetaDeclare this topic only when the condition holds.
unlessmetaDeclare this topic unless the condition holds.
typefactROS message type. Required.
pubmetaPublishing endpoints, as node/endpoint.
submetaSubscribing endpoints, as node/endpoint.
qosfactTopic-level QoS, overridable per endpoint.
rate_hzconsequencePublication rate. Derivable from the timers that drive it — see derivable-rate.
max_transportdeprecated — use nodes.<n>.sub.<ep>.max_transportDeprecated 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_msremovedRemoved — 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.
droprequirementPermitted message loss on this topic.
externalmetaMark one side of this topic as provided by an external system.

external_topics.<name>

keykindstatusmeaning
sidemetaWhich side is external: pub
externaldeprecated — use sideDeprecated spelling.
typefactROS message type, when known.
qosfactQoS the external side uses, when known.

services.<name>

keykindstatusmeaning
ifmetaDeclare this service only when the condition holds.
unlessmetaDeclare this service unless the condition holds.
typefactROS service type.
servermetaServer endpoints, as node/endpoint.
clientmetaClient endpoints, as node/endpoint.
externalmetaMark one side of this service as provided by an external system: server
max_transportrequirementsince v0.2.5The 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.

actions.<name>

keykindstatusmeaning
ifmetaDeclare this action only when the condition holds.
unlessmetaDeclare this action unless the condition holds.
typefactROS action type.
servermetaServer endpoints, as node/endpoint.
clientmetaClient endpoints, as node/endpoint.
externalmetaMark one side of this action as provided by an external system: server
callfactsince v0.1.69How 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.

includes.<name>

keykindstatusmeaning
manifestremovedRemoved 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.

args.<name>

keykindstatusmeaning
typemetaArgument type: bool, or omitted for a free string.
choicesmetaPermitted values. Consulted only when type is absent.

paths.<name>

keykindstatusmeaning
ifmetaDeclare this path only when the condition holds.
unlessmetaDeclare this path unless the condition holds.
inputdeprecated — use trigger: { input: [...] }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.
outputfactEndpoints (node path) or topics (event chain) this path produces.
max_latencyrequirementLatency 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_msremovedRemoved — 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.
correlationremovedRemoved — nothing ever read it. State fan-in policy with sync:.
tolerancefactMax header.stamp spread between a fan-in path’s inputs still treated as one set.
tolerance_msremovedRemoved — write tolerance: <n>ms (or ns/us/s). The unit in a NAME is what lets a value be 1000x wrong and still parse.
droprequirementEvent 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.
triggerfactWhat causes this path’s output: timer
syncfactFan-in synchronization policy for an input trigger with two or more endpoints.
max_jitterrequirementPermitted variation in this path’s latency.
min_latencyfactBest-case latency. Exists so that max_jitter is falsifiable.
safe_statefactWhat this path produces when it is a reaction: the endpoint it commands, and the plant’s settle time.
missrequirementWhat a missed deadline costs and what to do about it.
segmentsremovedRemoved with chains: — a written route is a second copy of the graph.

trigger

keykindstatusmeaning
timerfactPeriodic self-clocked callback.
inputfactOutput caused by these input endpoints or topics.

trigger.timer

keykindstatusmeaning
rate_hzfactTimer 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.
jitterfactsince v0.1.49Release 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.
paramfactsince v0.1.58The 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_paramfactsince v0.1.58The parameter of this path’s node that holds the timer’s PERIOD, seconds. Its resolved launch value must equal 1 / rate_hz (timer-param).

sync

keykindstatusmeaning
policyfactFan-in policy. Required.
max_intervalfactWidest permitted spread between matched inputs.
max_interval_msremovedRemoved — write max_interval: <n>ms (or ns/us/s). The unit in a NAME is what lets a value be 1000x wrong and still parse.
timeoutfactHow long to wait for the remaining inputs.
timeout_msremovedRemoved — write timeout: <n>ms (or ns/us/s). The unit in a NAME is what lets a value be 1000x wrong and still parse.

drop

keykindstatusmeaning
max_countrequirementPermitted losses over a window, as N / W.
max_consecutiverequirementPermitted consecutive losses.

qos

keykindstatusmeaning
reliabilityfactreliable
durabilityfactvolatile
depthfactHistory depth.
historyfactkeep_last
lifespanfactHow long a message stays valid after publication.
lifespan_msremovedRemoved — write lifespan: <n>ms (or ns/us/s). The unit in a NAME is what lets a value be 1000x wrong and still parse.
livelinessfactautomatic
deadlinefactQoS deadline between consecutive messages.
lease_durationfactLiveliness lease: how often a publisher must assert it is alive. Checked pub against sub by qos-match.

miss

keykindstatusmeaning
toleraterequirementPermitted misses over a window, as N / W.
consecutiverequirementPermitted consecutive misses.
actionrequirementWhat to do on a miss: continue

concurrency

keykindstatusmeaning
exclusivefactGroups of path names that may not run at the same time.

params.<name>

keykindstatusmeaning
typefactROS 2 parameter type: bool
defaultfactsince v0.2.4The 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.

hazards.<name>

keykindstatusmeaning
integrityrequirementsince v0.3.3Integrity 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.
severityremovedRenamed 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.
descriptionmetaWhat the hazardous event is.
guardsremovedRenamed 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.
monitorsmetasince v0.3.7The 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.
onfactFault classes the monitors report, one or a list: omission
fttirequirementFault-tolerant time interval: fault to hazardous event, absent reaction. Checked by fault-reaction-time.
entersmetasince v0.1.59The 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.
reactionmetaThe 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).
whenfactThe 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).
detectionfactFault 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_byrequirement<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_totalremovedRead-only: the consumer computes it (detection + route + settle) and hands it to extension checks. A contract never writes it.

modes.<name>

keykindstatusmeaning
descriptionmetaWhat this mode is.
requiresfactFunctions (or bare topics) this mode needs; it is available while every one holds.
fallbackrequirementModes 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.
reactionmetaThe event chain that reaches this mode’s safe state.
overridesrequirementRequirement values that apply IN THIS MODE, pinned over the scalar declared elsewhere.
min_dwellrequirementsince v0.3.3A 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.
windowremovedRenamed 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.
exitrequirement{ 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.

hazards.<name>.monitors[]

keykindstatusmeaning
all_ofremovedRemoved 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.

on_violation

keykindstatusmeaning
onfactFault classes that trigger the reaction: omission
reactionmetaA path on this node whose trigger includes the subscription.
withinrequirementThis hop’s share of the fault reaction time.
mechanismfactWhere the runtime observer reads the violation: qos (default)

arrival_curve

keykindstatusmeaning
rate_hzrequirementsince v0.1.64Sustained messages per second the subscriber absorbs. Finite and > 0, and not below the endpoint’s own min_rate_hz.
burstrequirementsince v0.1.64Messages that may arrive back to back before pacing applies. An integer >= 1.

safe_state

keykindstatusmeaning
emitsfactThe endpoint this reaction commands the safe state on.
settlefactHow 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).

functions.<name>

keykindstatusmeaning
all_ofmetaMembers of a redundant group, lost only when every member is. At least two.
ofmetaThe topics a value function reads. Requires when:; without one, write the bare list.
whenfactThe predicate that LOSES the function by value. A value function is lost by the value or by silence.

when

keykindstatusmeaning
fieldfactOne scalar field of the message, a dotted path from its root. Checked against the .msg when the ament index resolves it (when-field-unknown).
equalsfactThe field equals the constant: a bool, a number, a message constant name (upper snake case) or a string.
not_equalsfactThe field differs from the constant.
ltfactThe field is below the constant, a number.
lefactThe field is at most the constant, a number.
gtfactThe field is above the constant, a number.
gefactThe field is at least the constant, a number.

modes.<name>.exit

keykindstatusmeaning
holdsfactsince v0.1.59The function whose holding ends the fallback sequence. Some node implementing the level must take its topic on a path trigger (mode-exit-unwired).
ondeprecated — use holdsDeprecated spelling.
tometaThe mode the fallback sequence ends in. Not a member of any fallback: list (mode-exit-target).

safe_state.settle

keykindstatusmeaning
durationfactThe 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.
responsefactsince v0.1.58The 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.
sourcemetasince v0.1.60Where the written duration comes from, as a budget’s source:. Requires duration: a profile’s settle is derived from its parameters.
superviserequirementsince v0.1.61The 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.

<budget> (map form)

keykindstatusmeaning
durationrequirementsince v0.1.58The 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.
paramfactsince v0.1.58The 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.
sourcemetasince v0.1.58Where 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.
superviserequirementsince v0.1.61The 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).

source.measured

keykindstatusmeaning
maxfactsince v0.1.58Single-term form: the largest value observed (a duration). For a timer tick with period, the largest lateness beyond the period.
nfactsince v0.1.58Single-term form: how many samples the maximum is over.
periodfactsince v0.1.58Single-term form: a timer tick’s period, charged without margin: the term is period + max x (1 + margin).
marginrequirementsince v0.1.58The margin over the observed maximum, a fraction (0.2 = 20 %). Required with max or terms.
runmetasince v0.3.4Where 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.
termsfactsince v0.1.58Several 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.

source.derived

keykindstatusmeaning
byfactThe extension that derived the value, a dotted name (vehicle.braking). Required.
versionfactThe extension’s version, MAJOR.MINOR.PATCH. Required.
sha256factThe sha256 of the extension’s canonical ASCII form, 64 lowercase hex digits.
inputsfactThe inputs the derivation read, a map of name -> value as written (entry_speed: 8.33 m/s).
tracefactThe derivation’s steps, a list of lines, printed by --explain.

source.measured.terms.<name>

keykindstatusmeaning
maxfactsince v0.1.58The largest value observed for this term (a duration). Required.
nfactsince v0.1.58How many samples the maximum is over.
periodfactsince v0.1.58A timer tick’s period, charged without margin.

<budget>.supervise

keykindstatusmeaning
reactionfactsince v0.1.61The 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.
entersfactsince v0.1.61The mode a miss enters; its reaction: event chain is what runs. Exactly one of reaction and enters.
mechanismfactsince v0.1.61What 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).
observesfactsince v0.1.62A 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.
earlyrequirementsince v0.3.1A 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.
resumefactsince v0.3.2The 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.

links.<name>

keykindstatusmeaning
max_transportrequirementsince v0.3.4The 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.
clockfactsince v0.3.4synced 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.
monitorfactsince v0.3.4Reserved, 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.

links.<name>.monitor

keykindstatusmeaning
reactionfactsince v0.3.4The 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.
entersfactsince v0.3.4The mode a link fault enters; its reaction: event chain is what runs. Exactly one of reaction and enters. Reserved: monitor is not read.

<budget>.supervise.resume

keykindstatusmeaning
afterfactsince v0.3.2How 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.

safe_state.settle.supervise.early

keykindstatusmeaning
withinrequirementsince v0.3.1When 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.
droprequirementsince v0.3.1The 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.

acknowledged[]

keykindstatusmeaning
rulemetasince v0.2.3The rule id of the finding, as the diagnostic prints it (reaction-unguarded). Required, non-empty.
atmetasince v0.2.3The 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.
reasonmetasince v0.2.3Why the finding is kept, printed beside it. Required, non-empty.

cli.<endpoint>.on_timeout

keykindstatusmeaning
reactionmetasince v0.2.5The mode the hazard falls to, or the event chain that runs, when the wait passes. Without retry:.
retryfactsince v0.2.5The 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).
thenmetasince v0.2.5What the code does after the last attempt, { reaction }. Only beside retry:.

cli.<endpoint>.on_timeout.retry

keykindstatusmeaning
attemptsfactsince v0.2.5The tries in all, the first included (>= 1). Absent: the code retries without a bound.
backofffactsince v0.2.5The wait between two tries (a duration, $(param …)-capable).

on_rejected / on_timeout.then

keykindstatusmeaning
reactionmetasince v0.2.5The mode the hazard falls to, or the event chain that runs. Required.

policy

keykindstatusmeaning
unsupervised_measuredrequirementsince v0.1.61The severity of a measured budget nothing supervises (measured-unsupervised): warn (the default) or error.

supervision

keykindstatusmeaning
tickfactsince v0.1.61The 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.
switchfactsince v0.1.61The interrupt plus the thread switch before a timer mechanism’s reaction runs (a duration). Required by a mechanism: timer supervision.

trigger.timer.rate_hz (map form)

keykindstatusmeaning
valuefactsince v0.1.61The rate, Hz. Required; greater than zero.
sourcemetasince v0.1.61Where the rate comes from, as a budget’s source:. allocated: chosen inside the range the consumer derives, which refuses a period outside it.

Bounds

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.

keywherekindlimitunitmap form
max_latencypaths.<name>latencyat mostduration{ duration, source }
min_latencypaths.<name>latencyat leastduration
max_jitterpaths.<name>jitterat mostduration{ duration, source }
jittertrigger.timerjitterat mostduration{ duration, source }
min_rate_hzpub/sub/cli.<endpoint>rateat leastHz
max_rate_hzpub/sub/cli.<endpoint>rateat mostHz
max_agepub/sub/cli.<endpoint>ageat mostduration{ duration, source, param }; param: a parameter of the subscriber’s node, seconds (max-age-param)
max_transportpub/sub/cli.<endpoint>transportat mostduration{ duration, source }
max_transporttopics.<name>transportat mostduration{ duration, source } deprecated
max_transportlinks.<name>transportat mostduration{ duration, source }
max_transportservices.<name>transportat mostduration{ duration, source }
max_responsesrv.<endpoint>responseat mostduration{ duration, source }
withinon_violationdeadlineat mostduration{ duration, source }
fttihazards.<name>deadlineat mostduration{ duration, source }
detectionhazards.<name>latencyat mostduration{ duration, source }
min_dwellmodes.<name>least timeat leastduration{ duration, source, param }; param: <node>.<parameter>, seconds (dwell-param)
settlesafe_stateresponseat mostduration{ duration ; response ; source } plus a used extension’s keys (settle: <d> is { duration: <d> })
durationsafe_state.settleresponseat mostduration
responsesafe_state.settleresponseat mostduration{ duration, source }
max_countdropcountat mostcount / window
max_consecutivedropcountat mostcount
toleratemisscountat mostcount / window
consecutivemisscountat mostcount

Values read from the launch tree

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] ')'
referencereads
$(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.

Integrity level to criticality

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):

integritycriticality
QMnone
ASIL_Alow
ASIL_Bmedium
ASIL_Chigh
ASIL_Dhigh

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).