Scenarios are YAML. The conductor loads them, executes phases in order, and
applies the escalation policy between phases. Anything not in the interferer
catalog (docs/interferers.md) is rejected at load.
name: worst-case-ramp
version: 1
band: 2.4ghz # 2.4ghz | 5ghz | 6ghz — one scenario file tests one band;
# bands are tested independently, graded on separate curves
dut:
profile: glasses-plus-phone # DUT profile; defines pass thresholds
link: ble # link under test: ble | bredr | wifi
chamber:
contained: true # shielded chamber; false = quiet room
dut_path_loss_db: 60 # programmable attenuator setting
# Nodes available to phases. Params are validated against each node's schema.
nodes:
inquiry-looper: { enabled: true }
ble-adv-spammer-1: { interval_ms: 20, tx_dbm: 8 }
ble-adv-spammer-2: { interval_ms: 20, tx_dbm: 8 }
ble-adv-spammer-3: { interval_ms: 100, tx_dbm: 8 }
wifi-ap-farm: { count: 4, forty_mhz: true }
phonekey-sim: { enabled: true }
rf-observer: { enabled: true } # always on for citizenship scoring
phases:
- name: baseline
duration_s: 120
nodes: [rf-observer]
note: "DUT alone in chamber; measures its own good-citizen baseline."
- name: busy-office
duration_s: 300
nodes: [rf-observer, ble-adv-spammer-3, wifi-ap-farm]
node_overrides:
wifi-ap-farm: { count: 2, forty_mhz: false }
- name: parking-garage
duration_s: 300
nodes: [rf-observer, phonekey-sim, inquiry-looper, ble-active-scanner]
- name: worst-case
duration_s: 600
nodes: [rf-observer, inquiry-looper, page-stormer, ble-adv-spammer-1,
ble-adv-spammer-2, ble-adv-spammer-3, ble-active-scanner,
ble-conn-saturator, auracast-tx, phonekey-sim,
wifi-ap-farm, wifi-slow-client, probe-stormer, zigbee-chatter]
# Escalation: the conductor advances only while the DUT stays within
# thresholds. On breach it holds, then binary-searches the breaking point.
escalation:
policy: ramp-while-healthy
soak_s: 60 # settle time before sampling each phase
sample_window_s: 60
on_breach: bisect # hold | bisect | abort
# Abort guards: hard stops regardless of phase.
abort:
max_disconnects: 10
max_run_s: 3600
# Citizenship checks run in every phase via rf-observer.
citizenship:
enabled: true
spec: docs/dut-citizenship.md
Schema notes
bandis required:2.4ghz,5ghz, or6ghz. One scenario file tests one band. Run the scenario once per band (seescenarios/wifi-5g-6g.yaml).nodes.<id>must matchdocs/interferers.md(plus-Ninstance suffixes).node_overridesin a phase replace the top-level params for that phase only.requires: test_modenodes (e.g.a2dp-hogwith forced AFH map) fail load unless the chamber is flaggedtest_mode: trueand a human approved it.- Every run records: scenario hash, RNG seed, full event timeline, per-phase
metric series, and the observer capture.
replay(run_id)reproduces it.