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
Adds <summary>, <param>, <typeparam>, and <inheritdoc/> tags to public
members surfaced by commentchecker — resolves 5,847 of 5,869 issues
(99.6%) across three /fixdocs passes.
Driver.AbCip-001 — ReinitializeAsync silently discarded its config JSON.
Extracted AbCipDriverFactoryExtensions.ParseOptions; InitializeAsync now
re-parses a content-bearing driverConfigJson and replaces _options (and
recreates the alarm projection), so a reinitialize with a changed config
(new device/tag, changed timeout) actually takes effect. A blank or
empty-object JSON keeps construction-time options for the unit-test seam.
Driver.AbCip-002 — libplctag status mapping used wrong integer constants.
MapLibplctagStatus now switches on the libplctag.NET Status enum members
(Ok/Pending/ErrorTimeout/ErrorNotFound/ErrorNotAllowed/ErrorOutOfBounds/…)
instead of hand-typed natives, so timeout/not-found/not-allowed/out-of-bounds
get their specific OPC UA codes instead of all collapsing to
BadCommunicationError. The int overload casts to Status to stay correct
against the wrapper's contiguous renumbering.
Driver.AbCip-003 — whole-UDT reads decoded members at declaration-order
offsets, which Studio 5000 does not guarantee. Added the opt-in
AbCipDriverOptions.EnableDeclarationOnlyUdtGrouping flag (default false);
AbCipUdtReadPlanner.Build forms no groups when it is off, so by default
every UDT member reads per-tag rather than at possibly-wrong offsets.
Driver.AbCip-008 — probe loops were fire-and-forget and ShutdownAsync raced
them. Each probe Task is stored on DeviceState.ProbeTask; ShutdownAsync now
cancels every CTS, awaits each probe Task (10s timeout), then disposes the
CTS and handles. DeviceState.Runtimes/ParentRuntimes are ConcurrentDictionary
and the Ensure*RuntimeAsync paths use TryAdd, disposing the losing concurrent
creator instead of leaking a native tag handle.
Adds AbCipDriverCodeReviewRegressionTests and updates existing AbCip tests
to the corrected status constants + opt-in grouping flag. AbCip driver +
test project build clean; all 244 AbCip tests pass. (The full-solution
build has pre-existing, unrelated Driver.Galaxy protobuf-generation errors
in this worktree.)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Group all 69 projects into category subfolders under src/ and tests/ so the
Rider Solution Explorer mirrors the module structure. Folders: Core, Server,
Drivers (with a nested Driver CLIs subfolder), Client, Tooling.
- Move every project folder on disk with git mv (history preserved as renames).
- Recompute relative paths in 57 .csproj files: cross-category ProjectReferences,
the lib/ HintPath+None refs in Driver.Historian.Wonderware, and the external
mxaccessgw refs in Driver.Galaxy and its test project.
- Rebuild ZB.MOM.WW.OtOpcUa.slnx with nested solution folders.
- Re-prefix project paths in functional scripts (e2e, compliance, smoke SQL,
integration, install).
Build green (0 errors); unit tests pass. Docs left for a separate pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>