diff --git a/docs/plans/2026-06-17-stillpending-phase-4d-s7-wide-types.md.tasks.json b/docs/plans/2026-06-17-stillpending-phase-4d-s7-wide-types.md.tasks.json index d5f00de7..560c22af 100644 --- a/docs/plans/2026-06-17-stillpending-phase-4d-s7-wide-types.md.tasks.json +++ b/docs/plans/2026-06-17-stillpending-phase-4d-s7-wide-types.md.tasks.json @@ -7,15 +7,23 @@ "scope": "S7 read+write for Int64/UInt64/Float64(LReal)/String/DateTime + read for Timer/Counter (AskUserQuestion: all five + Timer/Counter). Byte-buffer codec path + pure S7.Net.Types decoders; byte-anchored wide-type addressing; init-guard fail-fast; Int64/UInt64 node-mapping fix. OUT: wide-type arrays, S7WString, DTL, Timer/Counter writes.", "dependencyGraph": "T1 -> T2 -> {T3, T4, T5} -> T6 -> T7 -> T8 (T3/T4/T5 serialize: all build on T2's dispatch seam + share S7Driver.cs)", "tasks": [ - {"id": 1, "subject": "Init guards (empty UnimplementedDataTypes, drop Timer/Counter reject, add wide-array/non-Byte-address/Timer-Counter-DataType guards) + MapDataType Int64/UInt64 fix", "classification": "standard", "status": "pending"}, - {"id": 2, "subject": "8-byte numerics (Int64/UInt64/LReal) scalar read+write: codec dispatch + ReadScalarBlockAsync/WriteScalarBlockAsync + pure DecodeScalarBlock/EncodeScalarBlock", "classification": "high-risk", "status": "pending", "blockedBy": [1]}, - {"id": 3, "subject": "String read+write (S7String + StringLength)", "classification": "standard", "status": "pending", "blockedBy": [2]}, - {"id": 4, "subject": "DateTime read+write (DATE_AND_TIME / DT, 8-byte BCD)", "classification": "standard", "status": "pending", "blockedBy": [2]}, - {"id": 5, "subject": "Timer/Counter read (decode by area, read-only)", "classification": "standard", "status": "pending", "blockedBy": [2]}, - {"id": 6, "subject": "CLI help + docs (driver-specs §5, drivers/S7.md) + plan-record §2 clear", "classification": "small", "status": "pending", "blockedBy": [5]}, - {"id": 7, "subject": "Full build + S7 + S7.Cli test + final integration review", "classification": "standard", "status": "pending", "blockedBy": [6]}, - {"id": 8, "subject": "Live /run acceptance (S7 sim best-effort) + finish branch (merge to master + push)", "classification": "standard", "status": "pending", "blockedBy": [7]} + {"id": 1, "subject": "Init guards (empty UnimplementedDataTypes, drop Timer/Counter reject, add wide-array/non-Byte-address/Timer-Counter-DataType guards) + MapDataType Int64/UInt64 fix", "classification": "standard", "status": "completed", "commit": "06b858eb", "review": "spec ✅; code ⚠️ minor (carried to T2): dedup CapturingBuilder vs RecordingAddressSpaceBuilder; replace stale S7DriverCodeReviewFixTests2 'rejects not-yet-implemented' wide-type cases (now pass via guard-b on DBD0) with real round-trip tests; +Timer+Float64 positive guard test; empty-set loop comment"}, + {"id": 2, "subject": "8-byte numerics (Int64/UInt64/LReal) scalar read+write: codec dispatch + ReadScalarBlockAsync/WriteScalarBlockAsync + pure DecodeScalarBlock/EncodeScalarBlock", "classification": "high-risk", "status": "completed", "commit": "286be5df", "review": "spec ✅; code ⚠️ minor. Caught+fixed a switch-expr boxing bug (Int64 boxed as Double). INTERIM-ONLY finding (accepted): a Timer+Float64 tag passes init but falls through to narrow path → BadNotSupported at read; CLOSED end-state by T5 broadening IsBufferType to route Timer/Counter through the buffer path (verify in T7). Carried minors: +NaN/Inf Float64 round-trip cases (→T3); DateTime ScalarByteWidth arm comment (→T4). T1 cleanup done: builder dedup → S7TestBuilders.cs; S7DriverCodeReviewFixTests2 relabeled to guard-(b)."}, + {"id": 3, "subject": "String read+write (S7String + StringLength)", "classification": "standard", "status": "completed", "commit": "1e5fec2f", "review": "BUNDLED with T4+T5 (one combined reviewer over the 3 codec-arm fills). Confirmed S7String API empirically: FromByteArray(byte[]); ToByteArray(string, reservedLength) pads to reservedLength+2; overflow throws ArgumentException (not silent truncate). global:: qualifier needed (namespace shadow). NaN/Inf Float64 carried-minor added (round-trips). 193 green."}, + {"id": 4, "subject": "DateTime read+write (DATE_AND_TIME / DT, 8-byte BCD)", "classification": "standard", "status": "completed", "commit": "5db08e9e", "review": "BUNDLED with T3+T5. S7.Net.Types.DateTime FromByteArray/ToByteArray (8 bytes); DT preserves FULL ms precision (round-trips to ms incl. 2089 DT-max); out-of-range year (1990-2089) throws ArgumentOutOfRangeException. Replaced T3 throw-stubs. 200 green."}, + {"id": 5, "subject": "Timer/Counter read (decode by area, read-only)", "classification": "standard", "status": "completed", "commit": "8cfb8e92", "reviewFixCommit": "11e8e430", "review": "BUNDLE review (T3+T4+T5) ⚠️ approved-with-minor, all critical value-correctness clean. Interim hole CLOSED (IsBufferType routes Timer/Counter; DecodeScalarBlock area-first; ScalarByteWidth(tag,addr) forces width 2 over Float64). Timer→double seconds (S5TIME 4 time-bases), Counter→int RAW big-endian (S7.Net Counter.FromByteArray is NOT BCD — known-limitation for legacy S7-300/400 C-area, live-hw-gated follow-up; document in T6). ReadBytesAsync Timer/Counter framing wire-faithful+unit-proven. Fixes 11e8e430: Counter raw-word note + reject Writable Timer/Counter + Timer time-base 0/3 tests. 214 green."}, + {"id": 6, "subject": "CLI help + docs (driver-specs §5, drivers/S7.md) + plan-record §2 clear", "classification": "small", "status": "completed", "commit": "b7dfb5af", "review": "folded into T7 final integration review. CLI Read/Write/Subscribe help updated (byte-anchored + Timer/Counter read-only); driver-specs §5 + docs/drivers/S7.md document supported types, byte-anchored addressing, Timer/Counter, deferrals (arrays/S7WString/DTL/T-C writes) + Counter raw-word known-limitation. stillpending.md NOT staged. 36 CLI tests green."}, + {"id": 7, "subject": "Full build + S7 + S7.Cli test + final integration review", "classification": "standard", "status": "completed", "reviewFixCommit": "988a7a93", "review": "S7.Tests 220 + S7.Cli.Tests 36 green; driver-internal only (no public API change). Final integration review ⚠️ SHIP WITH MINOR — all 8 integration checks pass (no passes-init-throws-at-read hole, dispatch coherent, read/write symmetric, 4c array path untouched, staging clean). Closed M1 (UInt64 (object) cast) + M2 (transient Timer/Counter write → BadNotWritable) in 988a7a93."}, + {"id": 8, "subject": "Live /run acceptance (S7 sim best-effort) + finish branch (merge to master + push)", "classification": "standard", "status": "completed", "live": "LIVE-PROVEN on the wire vs a local python-snap7 S7-1500 sim (built from the IntegrationTests fixture, localhost:1102) via the S7.Cli (same S7Driver codec). String READ of seeded S7 STRING DB1.DBB200 → \"Hello\" Good; Int64 round-trip DBB100 (1234567890123456789) Good; Float64/LReal round-trip DBB108 (2.718281828459045) Good; UInt64 round-trip DBB116 (ulong.Max 18446744073709551615 > long.MaxValue — proves unsigned wire + boxing) Good; DateTime/DT round-trip DBB300 (2026-06-17T12:34:56) Good. Narrow path unchanged (DBW0=4242). Timer/Counter stay UNIT-PROVEN (sim seeds no TM/CT area; python-snap7 TM/CT support limited)."} + ], + "executionState": "COMPLETE — merged to master + pushed. All 8 tasks done. S7.Tests 220 + S7.Cli.Tests 36 green. Wide types (Int64/UInt64/LReal/String/DateTime read+write) + Timer/Counter read shipped; byte-anchored addressing; init-guard fail-fast; Int64/UInt64 node-mapping fixed. 4 wide types live round-tripped on the wire + seeded String read live; Timer/Counter unit-proven.", + "reviewFollowUps": [ + "Wide-type ARRAYS (Int64[]/String[]/DateTime[]/...) — DecodeArrayBlock keeps the deferred throw; init guard rejects them (named deferral)", + "S7WString (2-byte UTF-16 chars) — classic 1-byte STRING only this phase (named deferral)", + "DTL / DateTimeLong (12-byte) — DATE_AND_TIME (8-byte DT) only this phase (named deferral)", + "Timer/Counter WRITES — read-only this phase (named deferral)", + "Counter decode surfaces S7.Net's RAW big-endian word, NOT BCD — on legacy S7-300/400 C-area (BCD 0-999) this can mis-surface; S7-1200/1500 use IEC/DB counters where it's correct. BCD reinterpretation is a live-hardware-gated follow-up (documented in code + docs)", + "Timer/Counter live /run is unit-proven only (the snap7 sim seeds no TM/CT area + python-snap7 TM/CT support is limited) — confirm against a real S7-300/400 CPU" ], - "reviewFollowUps": [], "lastUpdated": "2026-06-17" }