I1: the U11 Bits[n] -> Bits[n/32] rewrite was unconditional. The native
runtime now keeps the original element path until the first reply settles the
layout: 0xD3 confirms DWORD addressing (bit n%32); any other reply type (e.g.
a 0xC1 per-element BOOL array) or a refusal of the DWORD index falls back to
Bits[n] and re-reads, and a write settles the layout by a read first, so it can
never decode or write element n/32 of an element-addressed array.
I2: libplctag ErrorNoMatch/ErrorBadDevice no longer fold into NotFound (they
now read as BadConnection: comms, Degraded, LastSuccessfulRead preserved).
ErrorNotImplemented - and the native runtime's own pre-send refusals - raise
AbCipLocalRefusalException: BadNotSupported, no health, LastSuccessfulRead NOT
advanced, no backoff record, not reachable for the probe or Test Connect.
M1: the bit RMW's parent read/write status words follow the health contract
(refusal: per-tag Bad + Warning; comms: evict the parent + Degraded).
M2: device Unsupported read refusals return Refused (advance
LastSuccessfulRead); device write refusals call RecordWriteAnswered (not the
pre-send native type gate).
M3: a good write clears a Degraded a write comms fault recorded (a read-side
Degraded is still left for the read path).
M4: a superseded init throws AbCipInitializationSupersededException (not an
OCE); ShutdownAsync stamps Unknown only if no newer init published meanwhile.
M5: the sync-Dispose timing assert is 2 s against a 4 s probe read; the
unencodable-array test asserts health.
Refs #737
Claude-Session: https://claude.ai/code/session_01Ub9hGmYLQvn9XETzw7CMsT
U10 (user decision: implement array encode now): config, the AdminUI and
discovery all advertised array tags Operate-writable, but both runtimes encoded
a scalar - an int[] threw InvalidCastException (BadTypeMismatch AND Degraded),
a scalar wrote element 0 natively, and libplctag re-sent its whole last-read
buffer with element 0 patched (stale elements 1..n-1).
- AbCipArrayCodec encodes count elements little-endian at the element width,
CONVERTING each element (ScadaBridge writes int[] to INT arrays; overflow is
BadOutOfRange, unconvertible BadTypeMismatch, both before anything is sent).
- The driver checks the shape before any runtime exists: not a list ->
BadTypeMismatch, length != elementCount -> BadOutOfRange, BOOL/STRING/
structure element types -> BadNotSupported; and, before sending, a controller
buffer that is not width x count -> BadTypeMismatch. Refusals warn once and
write no health.
- Native: ONE Write Tag of count elements with the controller's type code (the
client fragments a large one); libplctag: the codec's bytes copied into the
elem_count-sized buffer, refused TooSmall if it does not fit.
- IAbCipTagRuntime.EncodeArray (default: NotSupportedException).
Real-controller proof is a hardware userGate (see the lane report recipe).
Refs #737
Claude-Session: https://claude.ai/code/session_01Ub9hGmYLQvn9XETzw7CMsT