Soft-RT PLC runtime heart

This page captures the requirements for using taktora-executor as the runtime heart of a soft-real-time PLC. It follows from the gap analysis between typical PLC architecture (Beckhoff TwinCAT, Siemens TIA, B&R Automation Studio, Rockwell Logix) and the abstractions taktora-executor provides today.

The decomposition is two-tier:

  • Top-level featurePLC runtime heart on iceoryx2 (FEAT_0010) — the umbrella capability.

  • Sub-features — capability themes, each one :satisfies: the top-level feature.

  • Requirements — concrete shall-clauses that :satisfies: a sub-feature.

Sub-features are grouped into foundation capabilities (already provided by taktora-executor v0.1) and gap capabilities (must be added before the runtime credibly serves as a soft-RT PLC heart). Foundation reqs reference the existing API surface; gap reqs describe TBD work.

Top-level feature

Feature: PLC runtime heart on iceoryx2 FEAT_0010

A Rust runtime that schedules, sequences, and observes the cyclic execution of PLC-style logic (read inputs → run logic → write outputs) under soft-real-time constraints, with iceoryx2 as the inter-process data plane.

The runtime targets non-safety industrial automation, robotics control loops, and machine-monitoring scenarios. Hard-real-time bounds, safety certification, IEC 61131-3 frontends, hot-standby, and specific fieldbus protocol stacks are explicitly out of scope; the runtime integrates with such concerns but does not implement them.


Foundation capabilities

The following sub-features are already provided by taktora-executor v0.1. Their requirements describe the contracts the runtime exposes today; the work for them is closing the review/approval lifecycle, not authoring new implementation.

Cyclic scan execution

Feature: Cyclic scan execution FEAT_0011
status: open
satisfies: FEAT_0010
is satisfied by: REQ_0001, REQ_0002, REQ_0003

Periodic execution of a scheduled item at a configured scan period — the PLC equivalent of a scan cycle.

Requirement: Configurable scan period REQ_0001
status: open
satisfies: FEAT_0011

The runtime shall allow each cyclic item to declare a scan period as a Duration via TriggerDeclarer::interval(period).

Requirement: One execution per scan period REQ_0002
status: open
satisfies: FEAT_0011

Under nominal load (no item exceeding its scan period), the runtime shall invoke each cyclic item exactly once per declared period.

Requirement: Scan-cycle execution observability REQ_0003
status: open
satisfies: FEAT_0011

The runtime shall emit pre-execute and post-execute timestamps for every scan-cycle invocation through the ExecutionMonitor trait.

Event-driven I/O dispatch

Feature: Event-driven I/O dispatch FEAT_0012
status: open
satisfies: FEAT_0010
is satisfied by: REQ_0010, REQ_0011, REQ_0012, REQ_0013

Inter-process inputs and outputs flow through iceoryx2 channels so producers wake consumers without polling.

Requirement: Subscriber-triggered ingestion REQ_0010
status: open
satisfies: FEAT_0012

The runtime shall trigger an item’s execute whenever a declared Subscriber<T> receives a new sample.

Requirement: Publisher-driven emission REQ_0011
status: open
satisfies: FEAT_0012

The runtime shall expose Publisher<T> send paths (send_copy, loan_send, loan) for emitting outputs to other processes.

Requirement: Zero-copy IPC transport REQ_0012
status: open
satisfies: FEAT_0012

Pub/sub data transfer between processes shall be zero-copy across shared memory via iceoryx2; receivers shall obtain a borrowed view of the producer’s payload, not a deserialised copy.

Requirement: Notification-drop visibility REQ_0013
status: open
satisfies: FEAT_0012

The runtime shall surface dropped event-service notifications to the sender as a non-error counter (NotifyOutcome::listeners_notified) so the sender can detect consumer back-pressure programmatically.

Deterministic logic sequencing

Feature: Deterministic logic sequencing FEAT_0013
status: open
satisfies: FEAT_0010
is satisfied by: REQ_0020, REQ_0021, REQ_0022, REQ_0023

Items compose into chains and DAGs with explicit ordering and abort semantics — the structural equivalent of a PLC cause-effect network.

Requirement: Sequential chain execution REQ_0020
status: open
satisfies: FEAT_0013

The runtime shall execute the items of a chain in declared order on a single dispatch slot per chain invocation.

Requirement: Parallel DAG execution REQ_0021
status: open
satisfies: FEAT_0013

The runtime shall execute the vertices of a DAG concurrently when their in-edges are all satisfied, and shall block downstream vertices until all of their upstream vertices have completed.

Requirement: Abort propagation REQ_0022
status: open
satisfies: FEAT_0013

An item returning Ok(ControlFlow::StopChain) or Err shall prevent any downstream items in its enclosing chain or DAG from being dispatched within the same triggering cycle.

Requirement: Conditional inclusion REQ_0023
status: open
satisfies: FEAT_0013

The runtime shall provide a wrap_with_condition(item, predicate) helper that gates an item’s execution on a runtime-evaluated predicate.

Cycle-time watchdog

Feature: Cycle-time watchdog FEAT_0014
status: open
satisfies: FEAT_0010
is satisfied by: REQ_0030, REQ_0031

Visibility into deadline-missed events at the dispatch layer.

Requirement: Subscriber deadline detection REQ_0030
status: open
satisfies: FEAT_0014

The runtime shall provide a TriggerDeclarer::deadline(subscriber, deadline) declaration that fires the item if no event arrives at the subscriber within deadline.

Requirement: Per-execute timing visibility REQ_0031
status: open
satisfies: FEAT_0014

The runtime shall report each item’s actual execute duration through ExecutionMonitor::post_execute(task, started_at, took, ok).

Real-time scheduling

Feature: Real-time worker scheduling FEAT_0015
status: open
satisfies: FEAT_0010
is satisfied by: REQ_0040, REQ_0041

Worker threads can be pinned and prioritized for predictable latency on PREEMPT_RT-capable Linux systems.

Requirement: Core-affinity assignment REQ_0040
status: open
satisfies: FEAT_0015

The runtime shall, behind the thread_attrs feature, allow worker threads to be pinned to a specified set of CPU cores.

Requirement: SCHED_FIFO priority on Linux REQ_0041
status: open
satisfies: FEAT_0015

The runtime shall, behind the thread_attrs feature on Linux, allow worker threads to run under SCHED_FIFO at a configured priority, subject to the process holding CAP_SYS_NICE.

Cooperative shutdown

Feature: Cooperative shutdown FEAT_0016
status: open
satisfies: FEAT_0010
is satisfied by: REQ_0050, REQ_0051

The runtime exits cleanly on signal or programmatic stop without leaking worker threads or shared-memory artefacts.

Requirement: Signal-driven shutdown REQ_0050
status: open
satisfies: FEAT_0016

The runtime shall return cleanly from run() when SIGINT or SIGTERM is delivered to the process, surfacing iceoryx2’s WaitSetRunResult Interrupt and TerminationRequest variants.

Requirement: Programmatic shutdown wakeup REQ_0051
status: open
satisfies: FEAT_0016

The runtime shall expose a clonable Stoppable handle whose stop() method wakes the WaitSet thread within a bounded time even when no other trigger is pending.


Gap capabilities

The following sub-features are not yet provided by taktora-executor v0.1. Each is a prerequisite for credibly calling the runtime a soft-real-time PLC heart. Their requirements are authored at status: open and represent work to be planned and executed.

Bounded-time dispatch

Feature: Bounded-time dispatch FEAT_0017
status: open
satisfies: FEAT_0010
is satisfied by: REQ_0060, REQ_0061, REQ_0063, REQ_0062

The dispatch hot path shall not allocate, take unbounded locks, or block on poll loops, so steady-state cycle latency is bounded by factors the runtime declares (not by the system allocator or kernel futex implementation).

Requirement: No heap allocation in dispatch REQ_0060
status: implemented
satisfies: FEAT_0017
is refined by: ADR_0011, IMPL_0001, REQ_0104
is implemented by: BB_0023
is verified by: TEST_0170
links outgoing: BB_0023, IMPL_0001, TEST_0170

The runtime’s dispatch path shall perform zero heap allocations during steady-state execution after Executor::run has been entered. All per-iteration data structures (error capture, vertex tracking, completion signalling) shall reuse capacity provisioned at Executor::build time.

Requirement: Statically-sized task pool REQ_0061
status: open
satisfies: FEAT_0017

The runtime’s worker pool shall be sized at Executor::build time from a configuration value, and the dispatch path shall not grow or shrink the pool during execution.

Requirement: Wait-free completion signalling REQ_0063
status: open
satisfies: FEAT_0017

The graph DAG scheduler shall not rely on a polling condvar wait_timeout for vertex-completion signalling. Completion shall be communicated via a wait-free or bounded-wait primitive whose worst-case wakeup latency is documented and dominated by the kernel’s wakeup delivery latency, not by an internal polling interval.

Requirement: Pre-allocated error slot REQ_0062
status: open
satisfies: FEAT_0017

The runtime shall capture per-iteration item errors in a pre-allocated bounded slot rather than constructing an Arc<Mutex<Option<...>>> per dispatch iteration.

Cycle-overrun fault primitive

Feature: Cycle-overrun fault primitive FEAT_0018
status: open
satisfies: FEAT_0010
is satisfied by: REQ_0070, REQ_0071, REQ_0072, REQ_0073

Deadline violations transition the runtime — at task or executor scope — to a configured fault state, rather than only being reported as timestamps via ExecutionMonitor.

Requirement: Per-task overrun fault transition REQ_0070
status: open
satisfies: FEAT_0018

When a task’s execute exceeds a configured per-task deadline, the runtime shall transition that task to a configured fault state and shall not invoke its normal execute again until cleared.

Requirement: Executor-wide overrun fault transition REQ_0071
status: open
satisfies: FEAT_0018

When any single dispatch iteration exceeds a configured executor-wide deadline, the runtime shall transition the executor to a configured fault state.

Requirement: Fault-handler item dispatch REQ_0072
status: open
satisfies: FEAT_0018

When a task or the executor is in a fault state, the runtime shall not run the normal item logic and shall instead dispatch an optional user-supplied fault-handler item once per triggering cycle.

Requirement: Fault state observability REQ_0073
status: open
satisfies: FEAT_0018

Fault transitions shall be visible to the configured Observer via a dedicated callback distinct from on_app_error so users can react to overruns separately from item-returned errors.

Mode / state-machine framework

Feature: Mode / state-machine framework FEAT_0019
status: open
satisfies: FEAT_0010
is satisfied by: REQ_0080, REQ_0081, REQ_0082, REQ_0083

A first-class lifecycle for the runtime — distinct from item lifecycle — that captures the operational modes typical of PLC programs.

Requirement: Mode lifecycle REQ_0080
status: open
satisfies: FEAT_0019

The runtime shall support an explicit mode lifecycle of at least {init, ready, running, fault, stopping, stopped} and shall expose the current mode through a query API.

Requirement: Mode transition triggers REQ_0081
status: open
satisfies: FEAT_0019

Mode transitions shall be triggered both programmatically (caller-driven) and as a consequence of configured events (executor-wide deadline overrun, item error, signal-driven stop).

Requirement: Per-mode task gating REQ_0082
status: open
satisfies: FEAT_0019

Each registered task shall declare which modes it is enabled in; the runtime shall not dispatch a task while it is disabled by the current mode.

Requirement: Mode change observability REQ_0083
status: open
satisfies: FEAT_0019

Mode transitions shall be visible to the configured Observer via a dedicated callback that reports the previous mode, the new mode, and the reason for the transition.

Retentive state

Feature: Retentive state FEAT_0020
status: open
satisfies: FEAT_0010
is satisfied by: REQ_0090, REQ_0091, REQ_0092, REQ_0093

State that survives process restarts — the equivalent of NVRAM-backed retentive memory in classical PLCs.

Requirement: Process-restart persistence REQ_0090
status: open
satisfies: FEAT_0020

The runtime shall provide a retentive memory abstraction whose declared contents persist unchanged across cooperative process restarts.

Requirement: Memory-mapped backing REQ_0091
status: open
satisfies: FEAT_0020

Retentive memory regions shall be backed by a memory-mapped file with a checksum verified at load.

Requirement: Crash-atomic checkpoints REQ_0092
status: open
satisfies: FEAT_0020

A retentive-memory checkpoint shall be atomic with respect to process crash — a concurrent crash shall yield either the pre-checkpoint or post-checkpoint contents, never a partial state.

Requirement: Recovery status reporting REQ_0093
status: open
satisfies: FEAT_0020

At startup, the runtime shall report whether retentive state was loaded cleanly, recovered from an incomplete checkpoint (and which version was selected), or initialised from defaults because no prior state existed.

Scan-cycle observability

Feature: Scan-cycle observability FEAT_0021
status: open
satisfies: FEAT_0010

First-class statistics on cycle-time behaviour — percentiles, jitter, overrun counts — exposed without requiring users to build their own.

Requirement: Per-task latency percentiles REQ_0100
status: draft
satisfies: FEAT_0021
is refined by: ADR_0060, IMPL_0070
is implemented by: BB_0050
is verified by: TEST_0190

The runtime shall report p50, p95, and p99 execute-duration percentiles per registered task, computed over a sliding window whose size is configurable at Executor::build time.

Percentile estimation shall use a fixed-bucket log-linear histogram covering the value range 100 ns … 10 s with at least three buckets per decade (yielding ≤ 1% relative error at bucket centroids). The bucket layout shall be fixed at compile time so the per-sample update path is allocation-free; see Allocation-free telemetry u... (REQ_0104) and Fixed-bucket histogram for ... (ADR_0060).

Requirement: Per-task maximum jitter REQ_0101
status: draft
satisfies: FEAT_0021
is verified by: TEST_0191

The runtime shall report the maximum observed jitter — defined as the absolute difference between actual and declared scan period — per cyclic task, computed over the same sliding window as Per-task latency percentiles (REQ_0100). Lifetime maxima are out of scope; the reported value ages out with the window.

Requirement: Per-task overrun counter REQ_0102
status: draft
satisfies: FEAT_0021
is verified by: TEST_0192

The runtime shall expose a monotonic counter per task that increments on each scan-cycle execution that exceeds the declared scan period.

Requirement: Statistics query API REQ_0103
status: draft
satisfies: FEAT_0021
is refined by: REQ_0113
is implemented by: BB_0051
is verified by: TEST_0193

Cycle-cycle statistics shall be available via two distinct paths:

  • Push — the Observer trait shall expose an on_cycle_stats(&CycleObservation) callback (provided as a no-op default for backward compatibility) that fires once per completed scan cycle with the raw per-cycle observation (task_id, period_ns, actual_period_ns, jitter_ns, took_ns). The push path delivers raw samples, not aggregates.

  • PullExecutor::stats_snapshot() shall return a borrowed view of the current per-task aggregates (p50, p95, p99, max_jitter_ns, overrun_count), readable concurrently with dispatch.

Both paths shall be allocation-free on the runtime side (see Allocation-free telemetry u... (REQ_0104)); allocations on the consumer side are out of scope.

Requirement: Allocation-free telemetry update REQ_0104
status: draft
satisfies: FEAT_0021
refines: REQ_0060
is verified by: TEST_0194

The runtime’s per-sample telemetry update path — the code that runs inside the dispatch loop’s timing hooks to update the histogram, max-jitter, and overrun counter — shall perform zero heap allocations and shall complete in bounded time.

The update path’s worst-case runtime shall be dominated by the histogram bucket-index computation (a log2-style lookup, no loops over samples) and atomic updates to the bucket counter plus the max-jitter and overrun fields. The verification harness mirrors Zero allocations in steady-... (TEST_0170) (CountingAllocator covering pool worker threads); see Allocation-free telemetry u... (TEST_0194).

PREEMPT_RT validation

Feature: PREEMPT_RT validation harness FEAT_0022
status: open
satisfies: FEAT_0010
is satisfied by: REQ_0110, REQ_0111, REQ_0112, REQ_0113

The runtime’s worst-case latency on PREEMPT_RT Linux is characterised under realistic load — a continuous regression gate, not a one-off measurement.

Requirement: Documented worst-case jitter REQ_0110
status: draft
satisfies: FEAT_0022

The repository shall ship a versioned document (spec/safety/preempt-rt-envelope.rst or sibling) recording an observed worst-case jitter envelope on at least one PREEMPT_RT Linux configuration. The document shall record: kernel version (e.g. 6.6.0-rt8), isolation flags applied (isolcpus, nohz_full, rcu_nocbs), CPU model and core-pinning layout, load profile selected (see Cyclictest-style benchmark ... (REQ_0111)), and the observed p50 / p95 / p99 / max jitter values per task as reported by Per-task latency percentiles (REQ_0100) and Per-task maximum jitter (REQ_0101).

Requirement: Cyclictest-style benchmark harness REQ_0111
status: draft
satisfies: FEAT_0022
is refined by: IMPL_0071
is implemented by: BB_0052
is verified by: TEST_0240, TEST_0241

The repository shall include a benchmark harness, packaged as a cargo binary under xtask/preempt-rt/, that exercises the taktora-executor dispatch path under a configured load profile and emits per-cycle latency observations as NDJSON to stdout.

Each NDJSON record shall conform to the schema { ts_ns: u64, task_id: u32, period_ns: u64, actual_period_ns: u64, jitter_ns: i64, took_ns: u64 } and shall be emitted once per completed scan cycle.

The harness shall offer at least three selectable load profiles:

  • idle — no co-resident load; baseline measurement.

  • cpu-stressstress-ng --cpu N-style background load on non-isolated cores.

  • cyclictest-coexist — runs alongside cyclictest so the two measurements can be cross-checked.

Requirement: Documented reproducer procedure REQ_0112
status: draft
satisfies: FEAT_0022
is refined by: ADR_0061

The repository shall ship a documented procedure (docs/preempt-rt-procedure.md) by which any maintainer with access to a PREEMPT_RT-equipped Linux host can reproduce the Documented worst-case jitter (REQ_0110) envelope. The procedure shall be runnable from a single cargo xtask preempt-rt-bench invocation given a pre-installed PREEMPT_RT kernel and the documented isolation flags.

A continuous CI gate on jitter is explicitly not required by this REQ. See Harness as xtask, not CI gate (ADR_0061) for the rationale (no persistent self-hosted RT runner; cloud GH runners cannot guarantee PREEMPT_RT).

Requirement: Harness consumes runtime telemetry REQ_0113
status: draft
satisfies: FEAT_0022
refines: REQ_0103
is verified by: TEST_0242

The benchmark harness (Cyclictest-style benchmark ... (REQ_0111)) shall obtain its per-cycle observations exclusively via the Observer::on_cycle_stats push callback defined in Statistics query API (REQ_0103). The harness shall not instantiate a parallel timing path (no direct Instant::now polling around execute); what the harness measures is what the runtime would report in production.

Fieldbus integration interface

Feature: Fieldbus integration interface FEAT_0023
status: open
satisfies: FEAT_0010
is satisfied by: REQ_0120, REQ_0121

The shape by which fieldbus protocol stacks (EtherCAT, Modbus, Profinet, CIP) plug into the runtime — without committing to any specific protocol implementation in the core.

Requirement: Adapter-driven I/O REQ_0120
status: open
satisfies: FEAT_0023

The runtime shall expose an adapter trait by which a fieldbus driver produces Channel<T> / Subscriber<T> bindings for ingested process variables and consumes Publisher<T> for outputs.

Requirement: Out-of-tree driver crates REQ_0121
status: open
satisfies: FEAT_0023

Fieldbus driver implementations shall live in separate crates and shall not require modifications to the executor core.

Requirement: Protocol-neutral runtime REQ_0122
status: open
satisfies: FEAT_0010

The executor core shall not embed any specific fieldbus protocol implementation; protocol selection is a deployment concern carried in adapter crates.


Cross-cutting traceability

Every requirement on this page :satisfies: exactly one parent feature; every sub-feature :satisfies: PLC runtime heart on iceoryx2 (FEAT_0010). The needtables on Requirements and Architecture will populate as spec artefacts are authored.

Used filter: types(feat)

ID

Title

Status

Satisfies

FEAT_0010

PLC runtime heart on iceoryx2

open

FEAT_0011

Cyclic scan execution

open

FEAT_0010

FEAT_0012

Event-driven I/O dispatch

open

FEAT_0010

FEAT_0013

Deterministic logic sequencing

open

FEAT_0010

FEAT_0014

Cycle-time watchdog

open

FEAT_0010

FEAT_0015

Real-time worker scheduling

open

FEAT_0010

FEAT_0016

Cooperative shutdown

open

FEAT_0010

FEAT_0017

Bounded-time dispatch

open

FEAT_0010

FEAT_0018

Cycle-overrun fault primitive

open

FEAT_0010

FEAT_0019

Mode / state-machine framework

open

FEAT_0010

FEAT_0020

Retentive state

open

FEAT_0010

FEAT_0021

Scan-cycle observability

open

FEAT_0010

FEAT_0022

PREEMPT_RT validation harness

open

FEAT_0010

FEAT_0023

Fieldbus integration interface

open

FEAT_0010

FEAT_0030

Connector framework

open

FEAT_0031

Envelope transport

open

FEAT_0030

FEAT_0032

Codec abstraction

open

FEAT_0030

FEAT_0033

Connector trait and routing

open

FEAT_0030

FEAT_0034

Connection lifecycle

open

FEAT_0030

FEAT_0035

Process boundary deployments

open

FEAT_0030

FEAT_0036

MQTT reference connector

open

FEAT_0030

FEAT_0037

Host wiring and builder

open

FEAT_0030

FEAT_0040

Bounded global allocator

open

FEAT_0041

EtherCAT reference connector

open

FEAT_0030

FEAT_0042

Zenoh reference connector

open

FEAT_0030

FEAT_0043

Zenoh pub/sub

open

FEAT_0042

FEAT_0044

Zenoh queries

open

FEAT_0042

FEAT_0045

Zenoh session topology and health

open

FEAT_0042

FEAT_0046

CAN (SocketCAN) reference connector

open

FEAT_0030

FEAT_0047

CAN frame transport (classical + FD)

open

FEAT_0046

FEAT_0048

Multi-interface gateway and per-channel filtering

open

FEAT_0046

FEAT_0049

Bus health, error frames, and reconnect

open

FEAT_0046

FEAT_0050

Device-driver codegen toolchain

open

FEAT_0051

ESI parser

open

FEAT_0050

FEAT_0052

IR and codegen backend trait

open

FEAT_0050

FEAT_0053

ethercrab codegen backend

open

FEAT_0050

FEAT_0054

Runtime trait surface

open

FEAT_0050

FEAT_0055

Build helper (build.rs glue)

open

FEAT_0050

FEAT_0056

CLI inspection (cargo subcommand)

open

FEAT_0050

FEAT_0057

EEPROM diff verification

open

FEAT_0050

FEAT_0060

CANopen device-driver codegen toolchain

open

FEAT_0061

Shared OD core

open

FEAT_0060

FEAT_0062

EDS parser

open

FEAT_0060

FEAT_0063

Codegen IR and backend trait

open

FEAT_0060

FEAT_0064

taktora-connector-can codegen backend

open

FEAT_0060

FEAT_0065

Runtime trait surface

open

FEAT_0060

FEAT_0066

Build helper (build.rs glue)

open

FEAT_0060

FEAT_0067

CLI inspection (cargo subcommand)

open

FEAT_0060

FEAT_0068

EDS ↔ SDO-dump verification

open

FEAT_0060

Used filter: types(req)

ID

Title

Status

Satisfies

REQ_0001

Configurable scan period

open

FEAT_0011

REQ_0002

One execution per scan period

open

FEAT_0011

REQ_0003

Scan-cycle execution observability

open

FEAT_0011

REQ_0010

Subscriber-triggered ingestion

open

FEAT_0012

REQ_0011

Publisher-driven emission

open

FEAT_0012

REQ_0012

Zero-copy IPC transport

open

FEAT_0012

REQ_0013

Notification-drop visibility

open

FEAT_0012

REQ_0020

Sequential chain execution

open

FEAT_0013

REQ_0021

Parallel DAG execution

open

FEAT_0013

REQ_0022

Abort propagation

open

FEAT_0013

REQ_0023

Conditional inclusion

open

FEAT_0013

REQ_0030

Subscriber deadline detection

open

FEAT_0014

REQ_0031

Per-execute timing visibility

open

FEAT_0014

REQ_0040

Core-affinity assignment

open

FEAT_0015

REQ_0041

SCHED_FIFO priority on Linux

open

FEAT_0015

REQ_0050

Signal-driven shutdown

open

FEAT_0016

REQ_0051

Programmatic shutdown wakeup

open

FEAT_0016

REQ_0060

No heap allocation in dispatch

implemented

FEAT_0017

REQ_0061

Statically-sized task pool

open

FEAT_0017

REQ_0062

Pre-allocated error slot

open

FEAT_0017

REQ_0063

Wait-free completion signalling

open

FEAT_0017

REQ_0070

Per-task overrun fault transition

open

FEAT_0018

REQ_0071

Executor-wide overrun fault transition

open

FEAT_0018

REQ_0072

Fault-handler item dispatch

open

FEAT_0018

REQ_0073

Fault state observability

open

FEAT_0018

REQ_0080

Mode lifecycle

open

FEAT_0019

REQ_0081

Mode transition triggers

open

FEAT_0019

REQ_0082

Per-mode task gating

open

FEAT_0019

REQ_0083

Mode change observability

open

FEAT_0019

REQ_0090

Process-restart persistence

open

FEAT_0020

REQ_0091

Memory-mapped backing

open

FEAT_0020

REQ_0092

Crash-atomic checkpoints

open

FEAT_0020

REQ_0093

Recovery status reporting

open

FEAT_0020

REQ_0100

Per-task latency percentiles

draft

FEAT_0021

REQ_0101

Per-task maximum jitter

draft

FEAT_0021

REQ_0102

Per-task overrun counter

draft

FEAT_0021

REQ_0103

Statistics query API

draft

FEAT_0021

REQ_0104

Allocation-free telemetry update

draft

FEAT_0021

REQ_0110

Documented worst-case jitter

draft

FEAT_0022

REQ_0111

Cyclictest-style benchmark harness

draft

FEAT_0022

REQ_0112

Documented reproducer procedure

draft

FEAT_0022

REQ_0113

Harness consumes runtime telemetry

draft

FEAT_0022

REQ_0120

Adapter-driven I/O

open

FEAT_0023

REQ_0121

Out-of-tree driver crates

open

FEAT_0023

REQ_0122

Protocol-neutral runtime

open

FEAT_0010

REQ_0200

ConnectorEnvelope is a POD type

open

FEAT_0031

REQ_0201

Per-channel max payload size

open

FEAT_0031

REQ_0202

Sequence number monotonically increasing

open

FEAT_0031

REQ_0203

Timestamp recorded at send

open

FEAT_0031

REQ_0204

Correlation id is a passive carrier

open

FEAT_0031

REQ_0205

Zero-copy publish via iceoryx2 loan

open

FEAT_0031

REQ_0206

One iceoryx2 service per channel direction

open

FEAT_0031

REQ_0210

PayloadCodec trait

open

FEAT_0032

REQ_0211

Codec is a generic parameter on connectors

open

FEAT_0032

REQ_0212

JsonCodec is the default codec

open

FEAT_0032

REQ_0213

Codec encode error variant

open

FEAT_0032

REQ_0214

Codec decode error variant

open

FEAT_0032

REQ_0220

Connector trait

open

FEAT_0033

REQ_0221

ChannelDescriptor carries typed routing

open

FEAT_0033

REQ_0222

Routing is a marker trait with bounds

open

FEAT_0033

REQ_0223

create_writer / create_reader return concrete handles

open

FEAT_0033

REQ_0224

Connector ships its own routing struct

open

FEAT_0033

REQ_0230

ConnectorHealth state machine

open

FEAT_0034

REQ_0231

subscribe_health returns a Channel of HealthEvent

open

FEAT_0034

REQ_0232

ReconnectPolicy trait

open

FEAT_0034

REQ_0233

ExponentialBackoff default policy

open

FEAT_0034

REQ_0234

HealthEvent emitted on every transition

open

FEAT_0034

REQ_0235

Stack-internal-reconnect connectors emit health uniformly

open

FEAT_0034

REQ_0240

Same envelope contract for both deployments

open

FEAT_0035

REQ_0241

In-process gateway is a tokio task

open

FEAT_0035

REQ_0242

Separate-process gateway is a self-contained binary

open

FEAT_0035

REQ_0243

Clean exit on SIGINT / SIGTERM on both sides

open

FEAT_0035

REQ_0244

No app↔gateway control-plane envelopes

open

FEAT_0035

REQ_0250

MqttConnector implements Connector

open

FEAT_0036

REQ_0251

MqttRouting carries topic, qos, retained

open

FEAT_0036

REQ_0252

QoS 0 and 1 supported

open

FEAT_0036

REQ_0253

Retained-message publish supported

open

FEAT_0036

REQ_0254

Wildcard subscriptions supported

open

FEAT_0036

REQ_0255

Username/password authentication

open

FEAT_0036

REQ_0256

TLS is optional via cargo feature

open

FEAT_0036

REQ_0257

MQTT 3.1.1 baseline

open

FEAT_0036

REQ_0258

Tokio sidecar inside the gateway crate

open

FEAT_0036

REQ_0259

Bridge channels are bounded

open

FEAT_0036

REQ_0260

Outbound bridge saturation surfaces as BackPressure

open

FEAT_0036

REQ_0261

Inbound bridge saturation surfaces as DroppedInbound HealthEvent

open

FEAT_0036

REQ_0270

ConnectorHost builder API

open

FEAT_0037

REQ_0271

ConnectorGateway builder API

open

FEAT_0037

REQ_0272

Host registers connector items with the executor

open

FEAT_0037

REQ_0273

Optional Observer adapter for tracing

open

FEAT_0037

REQ_0290

NO request/response matching by the framework

rejected

FEAT_0030

REQ_0291

NO app↔gateway control plane

rejected

FEAT_0030

REQ_0292

NO persistent outbox or durable buffering

rejected

FEAT_0030

REQ_0293

NO schema/contract enforcement across the boundary

rejected

FEAT_0030

REQ_0294

NO protocol-portable Channel<T>

rejected

FEAT_0030

REQ_0295

NO multi-broker / multi-tenant gateway

rejected

FEAT_0030

REQ_0296

NO supervision / panic recovery

rejected

FEAT_0030

REQ_0300

Pre-allocated fixed-block arena

open

FEAT_0040

REQ_0301

Fail-closed on cap overrun

open

FEAT_0040

REQ_0302

Lock-after-init panic mode

open

FEAT_0040

REQ_0303

Allocation accounting API

open

FEAT_0040

REQ_0304

Thread-safe allocation

open

FEAT_0040

REQ_0310

EthercatConnector implements Connector

open

FEAT_0041

REQ_0311

EthercatRouting carries SubDevice and PDO addressing

open

FEAT_0041

REQ_0312

Single MainDevice per gateway instance

open

FEAT_0041

REQ_0313

Bus reaches OP before serving traffic

open

FEAT_0041

REQ_0314

Static PDO mapping per SubDevice

open

FEAT_0041

REQ_0315

PDO mapping applied during PRE-OP to SAFE-OP transition

open

FEAT_0041

REQ_0316

Cycle time configurable with millisecond resolution

open

FEAT_0041

REQ_0317

Missed cycle ticks are skipped not queued

open

FEAT_0041

REQ_0318

Distributed Clocks bring-up is opt-in

open

FEAT_0041

REQ_0319

Working-counter-based health policy

open

FEAT_0041

REQ_0320

Working-counter mismatch degrades health

open

FEAT_0041

REQ_0321

Tokio sidecar contained inside the connector crate

open

FEAT_0041

REQ_0322

Bridge channels are bounded

open

FEAT_0041

REQ_0323

Outbound bridge saturation surfaces as BackPressure

open

FEAT_0041

REQ_0324

Inbound bridge saturation surfaces as DroppedInbound HealthEvent

open

FEAT_0041

REQ_0325

Linux raw socket required on gateway host

open

FEAT_0041

REQ_0326

Outbound payload written to PDI bit slice per routing

open

FEAT_0041

REQ_0327

Inbound payload read from PDI bit slice per routing

open

FEAT_0041

REQ_0328

Per-channel routing registry on the gateway

open

FEAT_0041

REQ_0400

ZenohConnector implements Connector

open

FEAT_0043

REQ_0401

ZenohRouting carries key_expr and pub/sub QoS fields

open

FEAT_0043

REQ_0402

JsonCodec is the default codec for Zenoh

open

FEAT_0043

REQ_0403

Tokio sidecar contained inside the Zenoh connector crate

implemented

FEAT_0043

REQ_0404

Zenoh bridge channels are bounded

open

FEAT_0043

REQ_0405

Outbound bridge saturation surfaces as BackPressure

open

FEAT_0043

REQ_0406

Inbound bridge saturation surfaces as DroppedInbound

open

FEAT_0043

REQ_0407

Zenoh zero-copy publish via iceoryx2 loan

open

FEAT_0043

REQ_0408

Zenoh gateway is byte-only on the inbound publish path

open

FEAT_0043

REQ_0420

ZenohConnector exposes create_querier and create_queryable

open

FEAT_0044

REQ_0421

ZenohQuerier maps QueryId to envelope correlation_id

open

FEAT_0044

REQ_0422

ZenohQueryable correlates replies via correlation_id

open

FEAT_0044

REQ_0423

Multi-reply per query supported

open

FEAT_0044

REQ_0424

Reply stream end-of-stream framed in payload

open

FEAT_0044

REQ_0425

Query timeout sourced from options, overridable per-querier

open

FEAT_0044

REQ_0426

terminate(id) finalizes the upstream zenoh::Query

open

FEAT_0044

REQ_0427

Codec applied to Q on send and to R on reply

open

FEAT_0044

REQ_0428

Reply-side inbound saturation emits DroppedInbound

open

FEAT_0044

REQ_0440

Zenoh session mode is a config knob

open

FEAT_0045

REQ_0441

NO ReconnectPolicy on Zenoh session loss

rejected

FEAT_0045

REQ_0442

HealthEvent emitted on every Zenoh session transition

implemented

FEAT_0045

REQ_0443

Connect and listen locators surfaced to zenoh::Config

open

FEAT_0045

REQ_0444

zenoh-integration cargo feature gates the real zenoh dep

implemented

FEAT_0045

REQ_0445

MockZenohSession ships unfeature-gated

implemented

FEAT_0045

REQ_0446

Linux, macOS, and Windows are supported host operating systems

implemented

FEAT_0045

REQ_0500

Pure parse function with no I/O

open

FEAT_0051

REQ_0501

no_std + alloc compatible

open

FEAT_0051

REQ_0502

quick-xml + serde backend

open

FEAT_0051

REQ_0503

Parser does not depend on ethercrab or codegen

open

FEAT_0051

REQ_0504

IR carries identity, PDO maps, mailbox, DC, and OD

open

FEAT_0051

REQ_0505

Vendor-specific extensions captured as opaque blobs

open

FEAT_0051

REQ_0506

Parse errors carry line and column

open

FEAT_0051

REQ_0510

CodegenBackend trait shape

open

FEAT_0052

REQ_0511

Naming policy is owned by codegen, not the backend

open

FEAT_0052

REQ_0512

Revision collision handled deterministically

open

FEAT_0052

REQ_0513

Common PDO entry types deduplicated

open

FEAT_0052

REQ_0514

Emission target is proc_macro2 TokenStream

open

FEAT_0052

REQ_0520

Backend crate is the sole ethercrab dependency

open

FEAT_0053

REQ_0521

One device struct per ESI device entry

open

FEAT_0053

REQ_0522

SubDeviceIdentity const emitted per device

open

FEAT_0053

REQ_0523

PDO assignment alternatives emitted as sum type

open

FEAT_0053

REQ_0524

One PDO struct per assignment alternative

open

FEAT_0053

REQ_0525

Generated module root exposes a registry

open

FEAT_0053

REQ_0526

Generated code compiles under no_std + alloc

open

FEAT_0053

REQ_0530

EsiDevice trait shape

open

FEAT_0054

REQ_0531

EsiConfigurable trait shape for preop bring-up

open

FEAT_0054

REQ_0532

Traits live in ethercat-esi-rt, not taktora-connector

open

FEAT_0054

REQ_0533

Object dictionary emission is a default-off cargo feature

open

FEAT_0054

REQ_0534

Process image access via bitvec BitSlice

open

FEAT_0054

REQ_0540

Builder API shape

open

FEAT_0055

REQ_0541

Output written to OUT_DIR

open

FEAT_0055

REQ_0542

Cargo rerun-if directives emitted per ESI input

open

FEAT_0055

REQ_0543

Generated output passes through prettyplease

open

FEAT_0055

REQ_0550

cargo esi expand emits one device's generated code

open

FEAT_0056

REQ_0551

cargo esi list enumerates devices in a glob

open

FEAT_0056

REQ_0552

CLI shares the parser and codegen crates

open

FEAT_0056

REQ_0560

Verifier ingests ESI XML plus SII binary

open

FEAT_0057

REQ_0561

Diagnostic output names the differing field

open

FEAT_0057

REQ_0562

Verifier reuses the parser

open

FEAT_0057

REQ_0563

Verifier exits non-zero on mismatch

open

FEAT_0057

REQ_0590

NO CAN / CANopen / EDS support in this round

rejected

FEAT_0050

REQ_0591

NO proc-macro front-end

rejected

FEAT_0050

REQ_0592

NO unification of EtherCAT and CANopen runtime traits

rejected

FEAT_0050

REQ_0593

NO runtime XML parsing

rejected

FEAT_0050

REQ_0594

NO modification of taktora-connector-ethercat runtime

rejected

FEAT_0050

REQ_0595

NO automatic vendor library scraping

rejected

FEAT_0050

REQ_0600

CanConnector implements Connector

open

FEAT_0046

REQ_0601

CanRouting carries iface, can_id, mask, kind, fd_flags

open

FEAT_0046

REQ_0602

Linux is the supported host OS for real I/O

open

FEAT_0046

REQ_0603

socketcan-integration cargo feature gates the real socketcan dep

open

FEAT_0046

REQ_0604

MockCanInterface ships unfeature-gated

open

FEAT_0046

REQ_0605

Tokio sidecar contained inside the CAN connector crate

open

FEAT_0046

REQ_0606

CAN bridge channels are bounded

open

FEAT_0046

REQ_0607

Outbound bridge saturation surfaces as BackPressure

open

FEAT_0046

REQ_0608

Inbound bridge saturation surfaces as DroppedInbound

open

FEAT_0046

REQ_0610

Classical CAN frames supported

open

FEAT_0047

REQ_0611

CAN-FD frames supported

open

FEAT_0047

REQ_0612

Channel payload sizing keyed on frame kind

open

FEAT_0047

REQ_0613

Outbound payload serialised to socketcan frame

open

FEAT_0047

REQ_0614

Inbound gateway is byte-only on the publish path

open

FEAT_0047

REQ_0615

CAN ID extended flag preserved end-to-end

open

FEAT_0047

REQ_0620

Multiple interfaces per gateway

open

FEAT_0048

REQ_0621

Routing identifies the interface

open

FEAT_0048

REQ_0622

Per-interface filter is the union of channel masks

open

FEAT_0048

REQ_0623

Filter recomputed on channel add/remove

open

FEAT_0048

REQ_0624

Inbound demux to all matching readers

open

FEAT_0048

REQ_0625

Per-iface routing registry has stable iteration order

open

FEAT_0048

REQ_0630

ConnectorHealth aggregates per-iface state via worst-of

open

FEAT_0049

REQ_0631

Error frames consumed internally

open

FEAT_0049

REQ_0632

error-passive transitions to Degraded

open

FEAT_0049

REQ_0633

bus-off transitions to Down and triggers reconnect

open

FEAT_0049

REQ_0634

ReconnectPolicy reused; ExponentialBackoff default

open

FEAT_0049

REQ_0635

HealthEvent emitted on every transition

open

FEAT_0049

REQ_0636

Error frames not exposed to plugin

open

FEAT_0049

REQ_0640

NO DBC parsing or typed signal extraction in taktora-connector-can

rejected

FEAT_0046

REQ_0641

NO ISO-TP or J1939 support in taktora-connector-can

rejected

FEAT_0046

REQ_0642

NO CAN-XL support

rejected

FEAT_0046

REQ_0643

NO plugin-visible error-frame channel

rejected

FEAT_0049

REQ_0644

NO can-restart-ms management from the gateway

rejected

FEAT_0049

REQ_0700

No transport-specific types in fieldbus-od-core

open

FEAT_0061

REQ_0701

no_std + alloc, no mandatory serde

open

FEAT_0061

REQ_0702

OD type surface

open

FEAT_0061

REQ_0703

ethercat-esi re-exports lifted types

open

FEAT_0061

REQ_0704

canopen-eds uses fieldbus-od-core types

open

FEAT_0061

REQ_0720

Pure parse function with no I/O

open

FEAT_0062

REQ_0721

no_std + alloc, no upstream coupling

open

FEAT_0062

REQ_0722

serde-derive INI backend

open

FEAT_0062

REQ_0723

Parse errors carry line and column

open

FEAT_0062

REQ_0724

Unknown sections captured as RawSection

open

FEAT_0062

REQ_0725

Liberal parsing — warn and continue on quirks

open

FEAT_0062

REQ_0726

IR carries identity, OD, PDO comm + maps

open

FEAT_0062

REQ_0730

CodegenBackend trait shape

open

FEAT_0063

REQ_0731

Naming policy is owned by codegen, not the backend

open

FEAT_0063

REQ_0732

Revision collision handled deterministically

open

FEAT_0063

REQ_0733

Common PDO entry types deduplicated

open

FEAT_0063

REQ_0734

Emission target is proc_macro2 TokenStream

open

FEAT_0063

REQ_0735

One EDS file equals one device

open

FEAT_0063

REQ_0740

Backend crate is the sole canopen-eds-rt dependency

open

FEAT_0064

REQ_0741

One device struct per EDS file

open

FEAT_0064

REQ_0742

Identity const emitted per device

open

FEAT_0064

REQ_0743

PDO declarations emitted as sum types

open

FEAT_0064

REQ_0744

Dummy entries skipped in PDO payload structs

open

FEAT_0064

REQ_0745

Generated module root exposes a registry

open

FEAT_0064

REQ_0746

Bring-up SDO writes emitted from EDS

open

FEAT_0064

REQ_0747

Object dictionary emission is a default-off cargo feature

open

FEAT_0064

REQ_0748

Generated code compiles under no_std + alloc

open

FEAT_0064

REQ_0750

CanOpenDevice trait shape

open

FEAT_0065

REQ_0751

CanOpenConfigurable trait shape for bring-up

open

FEAT_0065

REQ_0752

Traits live in canopen-eds-rt, not taktora-connector-can

open

FEAT_0065

REQ_0753

Frame payloads use heapless::Vec<u8, 8>

open

FEAT_0065

REQ_0754

Frame-per-PDO dispatch shape

open

FEAT_0065

REQ_0755

CanOpenError variant surface

open

FEAT_0065

REQ_0756

RPDO rejected outside Operational state

open

FEAT_0065

REQ_0760

Builder API shape

open

FEAT_0066

REQ_0761

Output written to OUT_DIR

open

FEAT_0066

REQ_0762

Cargo rerun-if directives emitted per EDS input

open

FEAT_0066

REQ_0763

Generated output passes through prettyplease

open

FEAT_0066

REQ_0764

Parser warnings surface as cargo warnings

open

FEAT_0066

REQ_0770

cargo eds expand emits one device's generated code

open

FEAT_0067

REQ_0771

cargo eds list enumerates devices in a glob

open

FEAT_0067

REQ_0772

CLI shares the parser and codegen crates

open

FEAT_0067

REQ_0780

Verifier ingests EDS plus JSON SDO-dump

open

FEAT_0068

REQ_0781

Diagnostic output names the differing field

open

FEAT_0068

REQ_0782

Verifier reuses the parser

open

FEAT_0068

REQ_0783

Verifier exits non-zero on mismatch

open

FEAT_0068

REQ_0784

SDO-dump JSON schema versioned

open

FEAT_0068

REQ_0790

NO DCF support this round

rejected

FEAT_0060

REQ_0791

NO CAN-FD payload support in PdoOut

rejected

FEAT_0060

REQ_0792

NO proc-macro front-end

rejected

FEAT_0060

REQ_0793

NO unification of EtherCAT and CANopen runtime traits

rejected

FEAT_0060

REQ_0794

NO runtime EDS parsing

rejected

FEAT_0060

REQ_0795

NO modification of taktora-connector-can runtime

rejected

FEAT_0060

REQ_0796

NO automatic vendor library scraping

rejected

FEAT_0060

REQ_0797

NO live-bus verifier this round

rejected

FEAT_0060

Safety refinements

The PLC runtime (taktora-executor) carries four TSRs from the SEooC safety concept (see Technical Safety Concept — TSRs):