diff --git a/docs/plans/2026-10-07-native-ab-transport.md.tasks.json b/docs/plans/2026-10-07-native-ab-transport.md.tasks.json index 99bc4d78..ae21d976 100644 --- a/docs/plans/2026-10-07-native-ab-transport.md.tasks.json +++ b/docs/plans/2026-10-07-native-ab-transport.md.tasks.json @@ -193,7 +193,7 @@ { "id": 21, "subject": "Task 21: Real-press read-only gate (CR CompactLogix)", - "status": "pending", + "status": "completed", "description": "**Goal:** Run the Task 18 differential harness and a latency comparison against one production CompactLogix 5069-L320ERS2 press at CR, **read-only**, and record the evidence that decides the AbCip default flip.\n\n> **USER-ORDERED GATE \u2014 NON-SKIPPABLE.** This task was requested by the user in the current conversation. It MUST NOT be closed by walking around it, by declaring it \"verified inline\", or by substituting a cheaper check. Close only after every item in `acceptanceCriteria` has been re-validated independently, with output captured.\n\n**Files:**\n- Modify: `docs/plans/2026-10-07-native-ab-transport-gate-results.md` (append the press results)\n- Create: `tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/Differential/PollLatencyComparisonTests.cs`\n\n**Acceptance Criteria:**\n- [ ] **Preconditions (human):** the VPN to CR is up, the user has OK'd touching the press at this time, and the target is **one** press. The default is Z-35162 at `10.209.70.160:44818`, path `1,0`; any other press must be named by the user.\n- [ ] **Run the differential:**\n - `AB_DIFF_ENDPOINT=10.209.70.160:44818 AB_DIFF_FAMILY=CompactLogix AB_DIFF_COUNT_OPENS=1 dotnet test \u2026--filter \"FullyQualifiedName~Differential\"` passes.\n - Browse parity holds: the same discovered tag set (the 2026-10-07 run saw ~23,412 variables across 80 programs) and identical UDT shapes.\n - Read parity holds over `AB_DIFF_MAX_TAGS=200`, with zero unexpected divergences. Every `TypeMismatch` expected-divergence is listed by tag name.\n - Native made exactly **1** Forward Open over the run. That is achievable only because T18's harness holds an anchor lease for the whole run; if the count is higher, the harness is broken, not the press.\n- [ ] **Latency comparison** (`PollLatencyComparisonTests`, env-gated by the same variables):\n - Read a fixed set of 100 atomic tags 30 times per transport, sequentially; transports are never concurrent. The native side runs under an anchor lease, as in T18.\n - Native passes issue all 100 reads **concurrently** (`Task.WhenAll`), so the shared scheduler can MSP-pack them. libplctag passes do the same; libplctag packs internally.\n - Record the CIP round-trips per pass (native: `CipConnection.RequestsSent` from Task 9, delta per pass; libplctag: report n/a) and the p50/p95 wall time per pass.\n - Pass criterion: native p95 \u2264 libplctag p95 \u00d7 1.10.\n- [ ] **No writes:**\n - Evidence: the Task 18 source guard passes.\n - `grep -c WriteAsync` over both differential test files returns 0.\n- [ ] **Recorded results:** under the `## Real press (T21)` and `## Latency (T21)` headings, the results doc carries the raw `dotnet test` output, the divergence table, the latency table, the Forward Open count, the date/time (UTC) of the run and the press ID.\n- [ ] **Failure handling:** if any criterion fails, the task stays open. Fix the code (with a pinning test), re-run the ab_server suites (Task 17) and the press run. **Do not** relax the criterion.\n\n**Verify:** `AB_DIFF_ENDPOINT=10.209.70.160:44818 AB_DIFF_FAMILY=CompactLogix AB_DIFF_COUNT_OPENS=1 dotnet test tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests --filter \"FullyQualifiedName~Differential\" --logger \"console;verbosity=detailed\"` \u2192 passed, 0 unexpected divergences, `ForwardOpenCount=1`, and native p95 \u2264 1.10 \u00d7 libplctag p95.\n\nSteps + code: docs/plans/2026-10-07-native-ab-transport.md \u00a7 Task 21.\n\n```json:metadata\n{\"files\": [\"docs/plans/2026-10-07-native-ab-transport-gate-results.md\", \"tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/Differential/PollLatencyComparisonTests.cs\"], \"verifyCommand\": \"AB_DIFF_ENDPOINT=10.209.70.160:44818 AB_DIFF_FAMILY=CompactLogix AB_DIFF_COUNT_OPENS=1 dotnet test tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests --filter \\\"FullyQualifiedName~Differential\\\" --logger \\\"console;verbosity=detailed\\\"\", \"modelTier\": \"frontier\", \"model\": \"opus\", \"userGate\": true, \"tags\": [\"user-gate\"], \"gateScope\": \"task\", \"failurePolicy\": \"keep-open-and-fix\", \"requireEvidenceTokens\": [[\"libplctag\", \"baseline\"], [\"native\"], [\"ForwardOpenCount=1\", \"ForwardOpenCount: 1\"]], \"acceptanceCriteriaCount\": 6}\n```", "blockedBy": [ 18