Skip to content

Traceability

GUIDE · TRACEABILITY

Section §12 of the format spec defines seven enforced traceability rules. All are checked by the validator.

Links always point upstream. The derived/verifying/satisfying artifact holds the reference.

✓  FaultTolerantFCReq.md  →  derivedFrom: [REQ-UAV-SAFE-000]
✗  SafetyParentReq.md    →  derivedChildren: [REQ-UAV-FC-001]  # WRONG direction

Concretely:

Relationship Field on Points to
Requirement derivation Child requirement derivedFrom: [REQ-PARENT-*]
Requirement satisfaction Architecture element satisfies: [REQ-LEAF-*]
Implementation Architecture element implementedBy: [src/...]
Test case verification TestCase verifies: [REQ-*]
Direct element verification TestCase verifiesElement: [PartDef/InterfaceDef/ActionDef/StateDef] — an active element with neither this nor a verified satisfied requirement raises W104; testExempt: <why> on the element suppresses it
Allocation (default) Source element allocatedTo: [target] — allocatedFrom is derived

Allocation — two forms (§12.9)

An allocation can be authored two ways, sharing one edge model and a derived allocatedFrom reverse index (shown as ## Allocated from on the target in show):

  • allocatedTo: on the source element — the OSLC-canonical, lightweight default. The source holds allocatedTo: <target>; allocatedFrom is derived, never authored (same direction as satisfies/verifies/refines). Use this for simple allocations.
  • A standalone Allocation element naming both allocatedFrom and allocatedTo — a reified relationship artifact, kept for documented allocations whose body carries rationale (e.g. the freedom-from-interference / deployment allocations of §12.6). Naming both endpoints is its purpose, not redundancy.

Both forms feed MG041/MG081, matrix --allocations, and the derived index identically. A features: entry of an Allocation element is an edge when it has both allocatedFrom and allocatedTo, with or without a per-entry type: Allocation; the same entry on any other element type is not an allocation (warning W930). Declaring the same edge in both forms is redundant — warning W503. Guidance: allocatedTo by default; promote to an Allocation element only when the allocation needs its own documentation.

Rule 2 — Decomposition requires an ADR (§12.2)

Every requirement with derivedFrom: must have breakdownAdr: set to an accepted ADR.

derivedFrom:
  - REQ-UAV-SAFE-000
breakdownAdr: Decisions::SafetyDecompositionADR   # must be status: accepted
  • E310 — derivedFrom: present but breakdownAdr: absent
  • E311 — breakdownAdr: does not resolve, or does not resolve to an ADR element
  • W303 — breakdownAdr: resolves to a proposed ADR but the requirement is approved or higher

A project that does not want an ADR for every breakdown can switch E310 off in .syscribe.toml:

[traceability]
require_breakdown_adr = false   # default true

A breakdownAdr: that is present is still checked (E311, W303). A malformed entry is W632 and the default stays.

Rule 3 — Leaf assignment (§12.3)

Requirements are decomposed until each leaf can be assigned to the architecture that fulfils it. Leaf requirements at approved or implemented status with no satisfies: link fire W300.

A leaf requirement may be satisfied by more than one element — for example a PartDef and the StateDef that gives it its behaviour, or redundant channels. That is not a finding (W301 is retired, GH #121): decompose a requirement only when the children add requirement content, never just to reach one satisfier per leaf. Satisfying a parent requirement is still E312 (below).

Rule 4 — No parent assignment (§12.4)

A requirement with derivedChildren (i.e. other requirements derive from it) must not appear in any satisfies: list. Only leaf requirements can be directly satisfied by an architecture element.

  • E312 — parent requirement found in a satisfies: list

Rule 5 — Domain classification (§12.5)

Requirements carry reqDomain: system | hardware | software. Architecture elements carry domain: system | hardware | software. A leaf requirement at a non-system domain can only be satisfied by an element in the same domain.

# FlightController.md
domain: software
satisfies:
  - REQ-UAV-FC-001    # reqDomain: software  ✓
  - REQ-UAV-NAV-001   # reqDomain: hardware  ✗ E313
  • E313 — satisfies domain mismatch
  • E302 — unknown reqDomain value
  • E303 — unknown domain value
  • W302 — leaf requirement at implemented / verified still has reqDomain: system

Rule 6 — HW/SW independence (§12.6)

Elements with domain: software and domain: hardware must not share a direct supertype: or typedBy: link. Cross-domain integration uses Allocation elements.

  • E315 — cross-domain direct reference
  • E314 — element with isDeploymentPackage: true has no Allocation to a hardware element
  • W304 — isDeploymentPackage: true combined with domain: hardware

Rule 7 — Implementation trace (§12.8)

The optional implementedBy: field closes the downstream leg of the V-model, linking an architecture element to the source artifact(s) that realise it:

Requirement ─satisfies→ Architecture ─implementedBy→ Code ─verifies→ Test
# Scheduler.md — architecture element pointing at its implementation
type: PartDef
domain: software
satisfies: [REQ-SCHED-001]
implementedBy:
  - src/scheduler/mod.rs
  - repo:src/scheduler/bitmap.rs

The field accepts a single string or a list. Path resolution is identical to a TestCase's sourceFile: model-/repo-relative, model:/repo: prefixes, absolute, and file:// paths are checked on disk; remote URIs (scheme://) and package-registry references (crates.io:tokio@1.38.0, npm:lodash@4.17.21, github:org/repo@v1, … — the forms sbom emits as package components) are accepted as external pointers and not verified locally.

  • W023 — a non-draft Part/PartDef/Interface/InterfaceDef has an implementedBy: path that does not exist on disk

The check is opt-in (only when implementedBy: is present) and draft-suppressed (skipped for status: draft, where the implementation may not exist yet). Gate it in CI with validate --deny W023.

Discoverability:

  • syscribe links <element> lists the implementedBy paths as outbound relationships.
  • syscribe refs <path-or-dir> reverse-maps a source path (or a directory prefix) back to the architecture element(s) that declare it.

Integration test coverage for parent requirements (W305)

Leaf-level TestCases (L1/L2) verify individual derived requirements but do not cover the emergent, composed behaviour expressed by the parent. A parent requirement at approved, implemented, or verified status must have at least one active TestCase at testLevel: L3 (formal proof), L4 (integration on an emulator) or L5 (hardware-in-the-loop).

# TC-UAV-PERF-001.md — system test covering the parent requirement
type: TestCase
id: TC-UAV-PERF-001
name: Full performance envelope system test
status: active
testLevel: L3
verifies:
  - REQ-UAV-PERF-000   # the parent requirement

This is distinct from ASIL D tests: W702 specifically requires an L5 test for ASIL D requirements, while W305 applies to all parent requirements regardless of safety level.

  • W305 — parent requirement at approved or higher has no active L3/L4/L5 TestCase

Traceability matrix

The validation report (section 4) prints a matrix of all leaf requirements against all active TestCases, with ✓ where verifies: covers the requirement.

| Requirement       | TC-UAV-FC-001 | TC-UAV-NAV-001 | Active TCs |
|---|---|---|---|
| REQ-UAV-FC-001    | ✓             |                | 1          |
| REQ-UAV-NAV-001   |               | ✓              | 1          |

A ✓ says a TestCase claims the requirement, not that anything ran. requirement-coverage says which requirements have executable evidence (scenarios that ran and exercised what satisfies the requirement) and which only descriptive tests; see Executable evidence.

A trace link asserts a relationship that was valid when a human reviewed it. When the target later changes, the assertion may silently become stale — a test may no longer cover the requirement it verifies. Suspect-link detection flags this by storing a content baseline of the target at review time and re-checking it on every validate.

The baseline is a blake3 hash of the target's normative projection (its body plus normative frontmatter — status, reqDomain, safety fields, …). Editorial fields (name, displayOrder, extRef, diagram layout) are excluded, so cosmetic edits never raise a false flag. It lives on the source element (the one holding the link, per Rule 1), keyed by the target reference:

# Verification/SafeLandingTest.md — a reviewed verification link
verifies:
  - REQ-UAV-SAFE-001
traceBaselines:
  REQ-UAV-SAFE-001: "blake3:1ddab032…"   # captured with `suspect accept`

The feature is opt-in and additive: a link with no baseline is never flagged. Baseline a reviewed link, and thereafter any change to the target's projected content raises W090.

# Discover links (suspect vs. never-baselined); onboard an existing model in one pass
syscribe -m model/ suspect list
syscribe -m model/ suspect accept --all-unbaselined     # baseline every un-baselined link

# Capture a single reviewed link, then gate CI on staleness
syscribe -m model/ suspect accept TC-UAV-SAFE-001 REQ-UAV-SAFE-001
syscribe -m model/ validate --deny W090

Try it on the demo model: edit the body of REQ-UAV-SAFE-001 and re-run validate — the TC-UAV-SAFE-001 → REQ-UAV-SAFE-001 link (baselined above) is now reported suspect (W090). Review the change and clear it by re-running suspect accept (or suspect accept --all to clear every suspect link at once). Propagation is implicit, one hop per review: only the direct link goes suspect; a link into the source flips only once the source's own projection actually changes. The same operations are exposed over MCP as suspect_list and the guarded suspect_accept.

Custom links declared under [linkTypes] take part in suspect-link detection too, unless a type opts out with suspect = false (see below).

When a relationship the format does not name is needed — mitigates, conflictsWith, partiallySatisfies — declare it as a link type in .syscribe.toml and author it under links: rather than bending a built-in field or hiding it in custom_fields:. Custom links follow Rule 1 (the source holds the link), resolve like satisfies:, can extend a built-in trace link with named rules relaxed (for example a satisfies variant that relaxes E313), and are traversed by follow, links, refs, impact and trace:

syscribe -m model/ link-types                                  # the project's vocabulary
syscribe -m model/ follow REQ-BRK-003 mitigatedBy              # walk one link type

See User-Defined Link Types for the full guide.