Skip to content

Cross-cutting

universal scenarios run for every adapter. capability:cross_cutting.* scenarios run only when the adapter's capabilities-coverage.yaml declares that slug applicable. Event/command names are the canonical PQ taxonomy (Pq.Adapters.Framework/pq-events.yaml).

Generated from the matrix

20 scenarios, from Matrix v9. See Adapter Acceptance Tests for how a scenario is written, what the waves mean, and which verdicts a run can record.

Scenario Purpose Stimulus Wave
AAT-CROSS-CUTTING-UNIVERSAL-01 The adapter connects to the device and reports itself online. pq 1
AAT-CROSS-CUTTING-UNIVERSAL-02 A link that goes silent mid-session is detected and reported, then recovered on reconnect. pq 1
AAT-CROSS-CUTTING-UNIVERSAL-03 A command that reaches the device is confirmed, not silently dropped. pq 1
AAT-CROSS-CUTTING-UNIVERSAL-07 An operator command is confirmed by its paired audited event in the remote form, with attribution. pq 1
AAT-CROSS-CUTTING-UNIVERSAL-04 An audited event that occurs while disconnected is recovered on reconnect, once. human 3
AAT-CROSS-CUTTING-UNIVERSAL-05 A vendor event code the adapter does not map is surfaced, never silently swallowed. human 3
AAT-CROSS-CUTTING-UNIVERSAL-06 An invalid credential configuration is rejected, not accepted and silently ignored. pq 1
AAT-CROSS-CUTTING-TIME-SYNC-01 The adapter writes the device clock and the change is observable. pq 1
AAT-CROSS-CUTTING-SUPERVISION-01 A device tamper is reported and its restore is reported too. human 4
AAT-CROSS-CUTTING-SUPERVISION-02 A power/battery fault is reported and restored. human 4
AAT-CROSS-CUTTING-SUPERVISION-03 A missing/supervised module is reported and restored. human 4
AAT-CROSS-CUTTING-DISCOVERY-01 Importing the device configuration builds a tree matching the physical panel. pq 1
AAT-CROSS-CUTTING-DISCOVERY-02 Re-importing does not duplicate Things and preserves reconciled properties. pq 1
AAT-CROSS-CUTTING-UNIVERSAL-08 A command aimed at a Thing the running adapter does not hold fails fast with a reason. pq 1
AAT-CROSS-CUTTING-UNIVERSAL-09 Restarting the adapter neither duplicates audited history nor re-pushes unchanged data. pq 1
AAT-CROSS-CUTTING-UNIVERSAL-14 State is read back from the device after startup, not merely accumulated from events. pq 1
AAT-CROSS-CUTTING-COMMAND-TARGETING-01 A command is confirmed on the Thing it was issued for, never on a sibling sharing its command — on every type where the rig offers a pair. pq 1
AAT-CROSS-CUTTING-UNIVERSAL-11 A command issued while the channel is held exclusively is refused, not deadlocked. pq 1
AAT-CROSS-CUTTING-UNIVERSAL-15 A protocol message split across transport segments is reassembled before it is parsed. pq 1
AAT-CROSS-CUTTING-UNIVERSAL-13 An event addressed to a Thing that is not modeled stays visible instead of being dropped. human 3

Universal: connection & liveness

AAT-CROSS-CUTTING-UNIVERSAL-01

The adapter connects to the device and reports itself online.

Applies when universal
Stimulus pq · wave 1

Given. The adapter is configured for a reachable device.

When. The adapter starts.

Then. It establishes the session and PQ sees it online.

PQ-visible behavior. Adapter presence goes online, pq.event.system.adapter.started is observed for the adapter and its Things reach lifecycle.ready, with no authentication/session errors in trace. A cold start raises no pq.event.connection.restored — "restored" states a recovery, and nothing was lost yet; that event belongs to AAT-CROSS-CUTTING-UNIVERSAL-02.

Steps.

- expect:
    - kind=presence
    - type=pq.event.system.adapter.started;thing={root}
    - state=lifecycle.ready;thing={root}
  timeout: 120
- require: thing={root};state=lifecycle.ready

AAT-CROSS-CUTTING-UNIVERSAL-02

A link that goes silent mid-session is detected and reported, then recovered on reconnect.

Applies when universal
Stimulus pq · wave 1
Hardware A way to silence the link without closing the socket.
Preconditions adapter_connected
Depends on AAT-CROSS-CUTTING-UNIVERSAL-01
Since Matrix v4

Given. The adapter is online with an established session carrying traffic.

When. The link goes silent while that session is up — no data passes in either direction and the socket is neither closed nor reset, exactly as a severed cable behaves — and is later restored.

Then. PQ reports the loss and, on reconnect, the recovery.

PQ-visible behavior. pq.event.connection.lost within the keepalive/watchdog window after the link falls silent, then pq.event.connection.restored once traffic resumes; presence tracks offline→online. The detection must come from the adapter's own keepalive or watchdog: an adapter that only notices a link failure when the socket closes will never report the loss here, which is the point of the scenario. Reconnect attempts during the outage are neither refused nor closed — they carry no traffic.

Physical acts.

  • cut_link — the link between the adapter and the device, left silent and then restored · performed by the lab: lab link cut

Steps.

- stimulus: cut_link
  expect:
    - type=pq.event.connection.lost;thing={root}
  timeout: 180
- stimulus: cut_link
  restore: True
  expect:
    - type=pq.event.connection.restored;thing={root}
  timeout: 180

AAT-CROSS-CUTTING-UNIVERSAL-03

A command that reaches the device is confirmed, not silently dropped.

Applies when universal
Stimulus pq · wave 1
Preconditions adapter_connected

Given. The adapter is online and accepts at least one command.

When. An operator issues a supported command from PQ.

Then. The adapter reports the command outcome.

PQ-visible behavior. The command result carries the outcome — success or failure with a reason — and is never lost. Only a failure is additionally audited as pq.event.technical.command.failed; success has no audited event of its own, because the effect the operator asked for is what the domain event or status reports.

Steps.

- command: {any_supported_command}
  on: {root}
  expect:
    - kind=commandResult
  timeout: 60

AAT-CROSS-CUTTING-UNIVERSAL-07

An operator command is confirmed by its paired audited event in the remote form, with attribution.

Applies when universal
Stimulus pq · wave 1
Preconditions adapter_connected
Since Matrix v3

Given. The adapter is online and supervises at least one state-changing or momentary command via an audited execution event (ExecuteCommand event-supervision).

When. An operator issues such a command from PQ and the device executes it.

Then. The device's execution event surfaces paired to the command — in its remote variant, carrying the operator identity and the device timestamp.

PQ-visible behavior. The confirming audit event arrives as the remote variant of the action (pq.event.intrusion.armed.remote, pq.event.access.door.unsecured.remote, ...) with the operator identity from the command and the device-side timestamp — never the local/plain variant and never an unknown/unattributed actor. The timestamp is the device's own, carries a timezone offset, and is not substituted by adapter wall-clock. A local/plain variant for an operator-issued command means the command→event pairing was severed (the command was concluded by ACK or a state read-back instead of the event) and is a fail. Commands documented as ACK-only (no audited execution event exists for them) are exempt.

Steps.

- command: {any_supervised_command}
  on: {any_commandable_thing}
  expect:
    - type=.remote;kind=event
  timeout: 60

Universal: audit visibility (RULE-020/026/027)

AAT-CROSS-CUTTING-UNIVERSAL-04

An audited event that occurs while disconnected is recovered on reconnect, once.

Applies when universal
Stimulus human · wave 3
Hardware A device that buffers events offline and a way to trip one event.
Preconditions adapter_connected
Depends on AAT-CROSS-CUTTING-UNIVERSAL-02, AAT-CROSS-CUTTING-UNIVERSAL-07

Given. The adapter is online and the device buffers events while we are away.

When. The link is cut, an audited event is caused on the device, then the link is restored.

Then. The buffered event arrives after reconnect with its device timestamp, exactly once.

PQ-visible behavior. The event surfaces on pq.event.* after reconnect carrying the device-side timestamp (not wall-clock of readback), with no duplicate on a second reconnect (replay dedup).

Physical acts.

  • cut_link — the link between the adapter and the device, cut for the outage and restored after it · performed by the lab: lab link cut
  • trip_zone — a zone the device audits, tripped while the link is down

Steps.

- stimulus: cut_link
  expect:
    - type=pq.event.connection.lost;thing={root}
  timeout: 180
- stimulus: trip_zone
  timeout: 300
- stimulus: cut_link
  restore: True
  expect:
    - type=pq.event.connection.restored;thing={root}
    - type=pq.event.intrusion;thing={zone}
  order: sequence
  timeout: 300

AAT-CROSS-CUTTING-UNIVERSAL-05

A vendor event code the adapter does not map is surfaced, never silently swallowed.

Applies when universal
Stimulus human · wave 3
Preconditions adapter_connected
Depends on AAT-CROSS-CUTTING-UNIVERSAL-07

Given. The adapter is online.

When. The device emits an event whose meaning the adapter cannot resolve.

Then. PQ still sees it — as unresolved (address known, Thing missing) or unknown (code unmapped).

PQ-visible behavior. pq.event.device.unresolved when the address is known but no Thing exists, or pq.event.device.unknown for a genuinely unmapped code; a documented code must NOT arrive as device.unknown (that would be a false "I don't know" — RULE-020) and must never be dropped.

Physical acts.

  • trip_zone — a source whose resulting event code the adapter has no mapping for

Steps.

- stimulus: trip_zone
  expect:
    - type=pq.event.device.unresolved|pq.event.device.unknown
  timeout: 180

Universal: configuration integrity

AAT-CROSS-CUTTING-UNIVERSAL-06

An invalid credential configuration is rejected, not accepted and silently ignored.

Applies when universal
Stimulus pq · wave 1
Preconditions adapter_connected

Given. The adapter is online.

When. A credential with a configuration the device cannot honor is pushed (e.g. wrong format).

Then. The adapter rejects it with a reason rather than reporting a phantom success.

PQ-visible behavior. The sync/credential operation reports a failure with a reason (credential enrollment failed / command failed), and the bad credential does not appear as synced.

Steps.

- command: pq.command.access.synchronize
  on: {root}
  expect:
    - type=pq.event.access.credential.enrollment.failed|pq.event.technical.command.failed
  timeout: 300

Capability-conditional: time synchronization

AAT-CROSS-CUTTING-TIME-SYNC-01

The adapter writes the device clock and the change is observable.

Applies when capability:cross_cutting.time_synchronization
Stimulus pq · wave 1
Capability cross_cutting.time_synchronization
Preconditions adapter_connected

Given. The adapter declares time synchronization and the device clock is writable.

When. A time sync is triggered (startup or periodic resync).

Then. The device clock is set to PQ time.

PQ-visible behavior. pq.event.system.time.changed (or the adapter's time-sync confirmation) reflects the device clock moving to PQ time; subsequent device event timestamps align with PQ time.

Steps.

- expect:
    - type=pq.event.system.time.changed;thing={root}
  timeout: 300

Capability-conditional: health & supervision

AAT-CROSS-CUTTING-SUPERVISION-01

A device tamper is reported and its restore is reported too.

Applies when capability:cross_cutting.health_and_supervision
Stimulus human · wave 4
Capability cross_cutting.health_and_supervision
Hardware Physical access to open a tamper switch (enclosure/cover).
Preconditions adapter_connected
Depends on AAT-CROSS-CUTTING-UNIVERSAL-07

Given. The device exposes a tamper signal.

When. A tamper is caused on the device, then cleared.

Then. PQ sees the tamper and, separately, the restore.

PQ-visible behavior. pq.event.intrusion.tamper (or supervision fault) on tamper, then pq.event.intrusion.tamper.cleared on restore — both directions routed, restore not swallowed.

Physical acts.

  • tamper — the tamper-protected enclosure or cover of the panel or a peripheral

Steps.

- stimulus: tamper
  expect:
    - type=pq.event.intrusion.tamper|pq.event.supervision.fault
  timeout: 180
- stimulus: tamper
  restore: True
  expect:
    - type=pq.event.intrusion.tamper.cleared|pq.event.supervision.fault.cleared
  timeout: 180

AAT-CROSS-CUTTING-SUPERVISION-02

A power/battery fault is reported and restored.

Applies when capability:cross_cutting.health_and_supervision
Stimulus human · wave 4
Capability cross_cutting.health_and_supervision
Hardware Ability to disconnect mains or battery safely on the rig.
Preconditions adapter_connected
Depends on AAT-CROSS-CUTTING-UNIVERSAL-07

Given. The device exposes power/battery supervision.

When. A power or battery fault condition is induced, then removed.

Then. PQ sees the fault and the return to normal.

PQ-visible behavior. pq.event.technical.battery.low / .fault (or mains fault) on the condition, then pq.event.technical.battery.normal / fault.cleared on restore.

Physical acts.

  • power_fault — the panel's mains supply or its backup battery

Steps.

- stimulus: power_fault
  expect:
    - type=pq.event.technical.battery|pq.event.technical.power
  timeout: 300
- stimulus: power_fault
  restore: True
  expect:
    - type=pq.event.technical.battery|pq.event.technical.power
  timeout: 300

AAT-CROSS-CUTTING-SUPERVISION-03

A missing/supervised module is reported and restored.

Applies when capability:cross_cutting.health_and_supervision
Stimulus human · wave 4
Capability cross_cutting.health_and_supervision
Hardware A removable bus module/peripheral on the rig.
Preconditions adapter_connected
Depends on AAT-CROSS-CUTTING-UNIVERSAL-07

Given. The device supervises the presence of expansion modules/peripherals.

When. A supervised module is removed from the bus, then reconnected.

Then. PQ sees the supervision fault and its clear.

PQ-visible behavior. pq.event.supervision.fault or pq.event.system.device.module.missing on removal, then the corresponding restore/enabled event on reconnection.

Physical acts.

  • remove_module — a supervised expansion module or peripheral on the device bus

Steps.

- stimulus: remove_module
  expect:
    - type=pq.event.supervision.fault|pq.event.system.device.module.missing
  timeout: 300
- stimulus: remove_module
  restore: True
  expect:
    - type=pq.event.supervision|pq.event.system.device.module
  timeout: 300

Capability-conditional: configuration discovery (cluster 0)

AAT-CROSS-CUTTING-DISCOVERY-01

Importing the device configuration builds a tree matching the physical panel.

Applies when capability:cross_cutting.configuration_discovery
Stimulus pq · wave 1
Capability cross_cutting.configuration_discovery
Preconditions adapter_connected

Given. The device holds a real configuration (zones, partitions, readers, doors).

When. pq.command.config.import runs.

Then. PQ's device tree reflects the panel's actual configuration.

PQ-visible behavior. After import, lab tree shows the panel's real counts and names of zones, partitions and readers; the user confirms they match the physical panel. This tree serves as the precondition for all later scenarios (setup = test).

Steps.

- command: pq.command.config.discover
  on: {root}
  expect:
    - kind=commandResult;result=success;thing={root}
  timeout: 600

What the steps cannot decide. Whether the discovered tree matches the physical panel is a comparison against the rig, not a record on the timeline — the steps only prove the import ran to completion.

AAT-CROSS-CUTTING-DISCOVERY-02

Re-importing does not duplicate Things and preserves reconciled properties.

Applies when capability:cross_cutting.configuration_discovery
Stimulus pq · wave 1
Capability cross_cutting.configuration_discovery
Preconditions adapter_connected

Given. The device tree was already imported once.

When. pq.command.config.import runs a second time with an unchanged device.

Then. The tree is stable — no duplicate Things, ref properties and names preserved.

PQ-visible behavior. lab tree --json before/after the second import is equivalent (no new Thing ids, tri-state deviceRefs and preserved names honored per the discovery reconciliation contract).

Steps.

- command: pq.command.config.discover
  on: {root}
  expect:
    - kind=commandResult;result=success;thing={root}
  timeout: 600

What the steps cannot decide. The verdict is the equivalence of two lab tree --json dumps taken around the second import. That comparison has no shape on the timeline, so the steps only carry the import itself.

Universal: registry, restart & state recovery

AAT-CROSS-CUTTING-UNIVERSAL-08

A command aimed at a Thing the running adapter does not hold fails fast with a reason.

Applies when universal
Stimulus pq · wave 1
Preconditions adapter_connected
Since Matrix v4

Given. A Thing exists in PQ's device tree but not in the running adapter's registry — the state after a configuration change without a restart. The registry is built at startup only, so lab tree restore <node> without a following restart reproduces it deterministically.

When. An operator issues a supported command on that Thing.

Then. The adapter reports the command as failed, naming the unresolved target.

PQ-visible behavior. pq.event.technical.command.failed carrying a not-ready / device-not-found reason within the command timeout. The command never hangs and never reports success. After a restart the same command succeeds — proving the failure was the stale registry, not a broken command path.

Steps.

- command: {any_supported_command}
  on: {unregistered_thing}
  expect:
    - type=pq.event.technical.command.failed;thing={unregistered_thing}
  reject:
    - kind=commandResult;result=success;thing={unregistered_thing}
  timeout: 60
- command: pq.command.restart
  on: {root}
  expect:
    - state=lifecycle.ready;thing={root}
  timeout: 180
- command: {any_supported_command}
  on: {unregistered_thing}
  expect:
    - kind=commandResult;result=success;thing={unregistered_thing}
  timeout: 60

AAT-CROSS-CUTTING-UNIVERSAL-09

Restarting the adapter neither duplicates audited history nor re-pushes unchanged data.

Applies when universal
Stimulus pq · wave 1
Preconditions adapter_connected
Since Matrix v4

Given. The adapter is online with an imported tree and a completed synchronization.

When. The adapter is stopped and started again with unchanged configuration and unchanged PQ data.

Then. It comes back to the same picture without replaying what PQ already holds.

PQ-visible behavior. After restart the tree is identical; no audit event arrives a second time with a device timestamp already seen before the restart (replay dedup holds); and no synchronization operation runs against unchanged input. Presence returns online without an error burst.

Steps.

- restart: process
- expect:
    - type=pq.event.connection.restored;thing={root}
  timeout: 300
- reject:
    - type=pq.event.access.synchronization.started;thing={root}
  timeout: 60

What the steps cannot decide. Replay dedup is a comparison of device timestamps seen before and after the restart, which no single expectation expresses; the steps prove the adapter came back and re-pushed nothing.

AAT-CROSS-CUTTING-UNIVERSAL-14

State is read back from the device after startup, not merely accumulated from events.

Applies when universal
Stimulus pq · wave 1
Topology 1× door / partition / detector / output
Preconditions adapter_connected
Since Matrix v4

Given. A stateful Thing is put into a non-default state through PQ (bypass a zone, arm a partition, hold a door open) and PQ observes that state.

When. The adapter is restarted while the device stays in that non-default state.

Then. PQ shows the device's real state after startup, without needing a new event to learn it.

PQ-visible behavior. The Thing's status after startup matches the state the device is actually in. An adapter that only accumulates state from the event stream shows the default/stale value here and reports a state PQ never left — a fail. Targets are chosen from the discovered topology, so the scenario covers whichever stateful types the rig actually has.

Steps.

- command: {any_state_command}
  on: {any_stateful_thing}
  expect:
    - kind=event;thing={any_stateful_thing}
  timeout: 60
- require: thing={any_stateful_thing};state={non_default_state}
- restart: process
- expect:
    - kind=status;thing={any_stateful_thing}
  timeout: 300
- require: thing={any_stateful_thing};state={non_default_state}

Universal: command addressing fidelity

AAT-CROSS-CUTTING-COMMAND-TARGETING-01

A command is confirmed on the Thing it was issued for, never on a sibling sharing its command — on every type where the rig offers a pair.

Applies when universal
Stimulus pq · wave 1
Topology 2× door / partition / zone / output / switch on distinct addresses
Preconditions adapter_connected
Since Matrix v8

Given. Every type of which the rig holds two or more commandable siblings on distinct addresses — relays and outputs, zones, partitions, doors.

When. An operator issues the type's command on A, and then, separately, on B.

Then. Each command is confirmed on the Thing it was issued for, and the two confirmations name different Things — for every such type, not merely for one of them.

PQ-visible behavior. The command on A yields its confirming event carrying A's node id; the same command on B yields its confirming event carrying B's node id. The two node ids differ, and neither command confirms on the other's Thing. Where the protocol confirms by status read-back instead of an event, the same assertion applies to the status target. A shared, transposed or off-by-one address shows up here as both commands confirming on one Thing. The concern is addressing, not the domain, and it is not one address family: a panel that gets doors right can still transpose relay outputs or zones, because each type is addressed by its own scheme on the wire. So the scenario is run once per type that offers a pair — every one of them must hold for the verdict, and a type with only one instance on the rig is simply not covered here. The partition variant (AAT-INTRUSION-TARGETING-01) folds into this scenario once requires_topology can select on a declared command rather than on a category.

Steps.

- command: pq.command.access.open
  on: {door}
  expect:
    - type=pq.event.access.door.unsecured.remote;thing={door}
  reject:
    - type=pq.event.access.door.unsecured;thing={door2}
  timeout: 30
- command: pq.command.access.open
  on: {door2}
  expect:
    - type=pq.event.access.door.unsecured.remote;thing={door2}
  reject:
    - type=pq.event.access.door.unsecured;thing={door}
  timeout: 30

Strengthening. When both Things report an independently readable state — a door contact, a partition's armed state, a relay's on/off — additionally assert that the sibling's state stays unchanged during the other's command. This raises the scenario to observed evidence but is not required for a verdict.

What the steps cannot decide. The steps carry one pair — doors, where requires_topology can express the requirement. The runner repeats the same shape for every other type holding a pair (relays/outputs, zones, partitions), and the verdict holds only when all of them targeted correctly. A type whose confirmation is a status rather than an event is asserted on the status target instead.

Universal: channel arbitration

AAT-CROSS-CUTTING-UNIVERSAL-11

A command issued while the channel is held exclusively is refused, not deadlocked.

Applies when universal
Stimulus pq · wave 1
Preconditions adapter_connected
Since Matrix v4

Given. The adapter holds the protocol channel exclusively for a long operation (configuration discovery, history read, bulk synchronization).

When. An operator issues a command while that operation is in flight.

Then. The command is refused with a busy outcome, and succeeds once the channel frees up.

PQ-visible behavior. The command result is Busy (or pq.event.technical.command.failed with a busy reason) — never a hang until timeout and never interleaved bytes corrupting the exclusive exchange. Re-issuing the same command after the operation completes succeeds.

Steps.

- command: pq.command.config.discover
  on: {root}
  timeout: 30
- command: {any_supported_command}
  on: {any_commandable_thing}
  expect:
    - type=pq.event.technical.command.failed;thing={any_commandable_thing}
  timeout: 60
- expect:
    - kind=commandResult;result=success;thing={root}
  timeout: 600
- command: {any_supported_command}
  on: {any_commandable_thing}
  expect:
    - kind=commandResult;result=success;thing={any_commandable_thing}
  timeout: 60

Universal: transport framing

AAT-CROSS-CUTTING-UNIVERSAL-15

A protocol message split across transport segments is reassembled before it is parsed.

Applies when universal
Stimulus pq · wave 1
Preconditions adapter_connected
Depends on AAT-CROSS-CUTTING-UNIVERSAL-03
Since Matrix v4

Given. A baseline run has established the PQ-visible result of an exchange whose payload exceeds one segment — a command with its confirming event, a status poll, or a configuration import.

When. The same exchange runs again with the transport delivering the payload in small fragments.

Then. The adapter produces the same result as the baseline.

PQ-visible behavior. The fragmented run yields the same PQ events and status values as the baseline, with no parse or checksum errors and no partial-frame timeouts in trace. An adapter that reads per transport read instead of per protocol frame fails here — it drops, truncates or mis-parses the split message. This is a common defect that a healthy link never exposes, which is why it is worth forcing. lab link fragment supplies the fragmentation. Adapters whose transport is not a byte stream — vendor SDK owning its own framing, datagram-only protocols — record n_a, since reassembly is not theirs to get wrong. Keep the per-byte delay well inside the adapter's own response timeout. Chosen too large, the exchange times out and the scenario measures the timeout instead of reassembly, which reads as a failure the adapter did not commit. Size the delay so the longest expected frame still completes within that timeout, and record the settings used with the verdict.

Steps.

- command: {any_supported_command}
  on: {any_commandable_thing}
  expect:
    - kind=commandResult;result=success;thing={any_commandable_thing}
  timeout: 60
- fragment: True
- command: {any_supported_command}
  on: {any_commandable_thing}
  expect:
    - kind=commandResult;result=success;thing={any_commandable_thing}
  timeout: 120
- fragment: False

What the steps cannot decide. The verdict is the equality of the fragmented run's events and status values with the baseline run's, which only a comparison of the two windows shows; the steps carry both runs and prove each completed.

Universal: unresolved addressing (pairs with UNIVERSAL-05)

AAT-CROSS-CUTTING-UNIVERSAL-13

An event addressed to a Thing that is not modeled stays visible instead of being dropped.

Applies when universal
Stimulus human · wave 3
Hardware A zone the user can physically trip.
Preconditions adapter_connected, thing_omitted_from_tree
Depends on AAT-CROSS-CUTTING-UNIVERSAL-01, AAT-CROSS-CUTTING-UNIVERSAL-05
Since Matrix v4

Given. The device knows a source that PQ does not model — one trippable zone is left out of the imported tree and the adapter is restarted so its registry omits it too.

When. That source produces an event on the device.

Then. PQ still sees the event, marked as addressed to an unresolved target.

PQ-visible behavior. pq.event.device.unresolved on the panel carrying the source address in its payload, within the routing window. Silence is a fail: the address was decodable, so the event had a known origin and must not vanish from the audit trail.

Physical acts.

  • trip_zone — the zone omitted from the tree

Steps.

- stimulus: trip_zone
  expect:
    - type=pq.event.device.unresolved;thing={root}
  reject:
    - type=pq.event.device.unknown
  timeout: 180