The libplctag-path positive control asserted 'timed out', but libplctag's internal
timeout equals the probe timeout and races the probe's own cancellation; under CPU
load it surfaces as 'ErrorTimeout' instead. Accept either libplctag stall outcome
(native never produces either: it fails at once with 'Connection lost').
Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
#572: listing continues at max(instance in page)+1 (no ascending-order assumption, no-progress guard kept);
browsePageDelayMs (default 5 ms) paces pages; DiscoverAsync reads templates through one batch reader
(IAbCipTemplateReaderFactory.CreateBatch) holding one lease.
#575: differential harness reports a same-status template refusal as an equal refusal; offline test pins the
open-attempt budget without relying on the abort ending the phase.
Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
The old AdminUI cannot author the per-driver transport key (#576), so the
'pin before upgrading' recipe had no working path. A node-level appsetting
(env Drivers__AbCip__DefaultTransport) now supplies the default for AbCip
drivers with no key: explicit key > node default > compiled Native. Bound
and validated unconditionally (bad value fails host start); the driver
factory and the Test Connect probe both read it so they agree. AbCip.md
upgrade recipe rewritten around the key; Configuration.md documents it.
Also documents first-wins for AllowPacking/probe and host-alias throttles
(final review M6) and moves the status-bit note out of AbCip.md (M5).
Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
- I1: the upgrade restart itself moves every no-key AbCip/AbLegacy driver to Native (every process
start constructs drivers, incl. boot-from-cache). Docs + CLAUDE.md now say so and tell operators
to set "transport": "Libplctag" BEFORE upgrading (older builds ignore the unknown key).
- I2: AbLegacy release note leads with the status-bit write refusal (T4:0.DN, C5:0.CU, R6:0.EN, ...)
on defaulted SLC/MicroLogix drivers and the fallback. The real client status is
BadCommunicationError, not BadNotSupported (the driver's write catch-all maps the runtime's
AbTransportException like any transport failure, as #571 does for PLC-5), with handle eviction
and Degraded health; pinned by a driver-level test (no 0xAA write on the wire, with a positive
control). ST string byte order stated as unverified. Also corrects the docs' "T4:0/DN" examples:
the driver's address grammar is "T4:0.DN" ("/DN" is a malformed address).
- I3: DriverProbeHandshakeE2eTests' two AbCip probe tests are a [Theory] over Native and
Libplctag. Run against ab_server controllogix: all 4 rows pass with identical exact messages.
- M1: documented (docs + resolver XML doc): the AdminUI merges only the probed device, so a
mixed-family defaulted AbLegacy driver can probe Native while running Libplctag.
- M2: factory ParseEnum rejects undefined integer strings ("7") via Enum.IsDefined (both drivers).
- M3: AbCip driver-level bad value reads "AB CIP config in '<id>' has unknown Transport ..."; the
named constant is gone (tagName: null now means driver-level).
- M4: the explicit-Native limited-family Warning is once per instance, not per (re)init.
- Nit: EffectiveTransport docs note that injected factories bypass it.
Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
Task 22 (spec section 8 P5), with the controller rulings that exclude PLC-5 and LogixPccc.
- Transport is nullable on both option records; null (key absent) means "use the default" and is
never serialized. Factory DTO parse: absent -> null; a bad value still fails via ParseEnum.
- One resolver per driver (AbCipTransportResolver / AbLegacyTransportResolver), used by the driver
constructor, the Test Connect probe and (through the driver) the CLI.
AbCip: null -> Native. AbLegacy: null -> Native unless any device is Plc5 or LogixPccc, then the
whole driver resolves to Libplctag. Explicit values always win; explicit Native with a
Plc5/LogixPccc device logs one Warning at init.
- Init log shows configured vs effective, e.g. transport=Native (default).
- AdminUI forms: "Default (...)" / "Native (managed)" / "libplctag (fallback)". Default omits the
key on save (reverses Task 19's explicit re-emit, which would have pinned every edited driver).
- CLIs: --transport default|native|libplctag, default "default" via the resolver, so
--plc-type Plc5 with no --transport runs libplctag.
- Tests pinned to Libplctag where a default-path runtime was created: found by instrumenting the
native factories with the current xUnit test name (one unit test, AbLegacyReinitConfigAdoption;
plus the two fixture-gated AbCip probe E2E tests whose exact messages were proven on libplctag).
TransportMatrix and the differential harness already pass explicit transports.
- Switch/resolver/CLI/form tests are falsified by mutating the resolver (default -> Libplctag,
exclusion removed, AbLegacy default -> Libplctag): each mutation turns them red.
- Replaces the inline role-name literal in AbCipDriverFactoryExtensions' ParseEnum call with a named
constant; RoleAuthorityGuardTests was already red on the base commit for that line.
- Docs: AbCip.md / AbLegacy.md default + release note; CLAUDE.md AB section.
Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe