Repository navigation
Conversation
…ines and indexed-fact integrity Expose per-layer receive/decode/acceptance counters and terminal accounting invariants. Reject untrustworthy GI/cyclic state baselines, verify temporary indexed evidence with canonical CRC32, and add 5k dual-circuit full-writer plus 50k mixed-object deterministic stress and corruption tests.
| var dir = Path.Combine(Path.GetTempPath(), | ||
| "ariec-c3-crc-" + Guid.NewGuid().ToString("N")); |
| journal.Append(new PassiveObservedFrame(1, 0, DateTime.UtcNow, | ||
| "Variable", true, MakeFrame(0)), 1); | ||
| Assert.Single(journal.ReadAfter(0, 1)); // flush existing writer buffers | ||
| using (var disk = new FileStream(Path.Combine(dir, "process-events.bin"), |
| var output = Path.Combine(Path.GetTempPath(), | ||
| "ariec-c3-dual-" + Guid.NewGuid().ToString("N")); |
… and event projection
…I backlog Prevent end-of-session engine summary replacement of source-qualified live observations; drain all accepted UI evidence in bounded yielding batches before terminal state, with real-WPF regression for 280 queued items and summary-vs-journal mismatch.
… epoch Stamp bounded WPF ingress with source epoch, discard queued and callback stale data after a new Connect/Capture, detach active Master subscriptions on cancellation/fault, and reject delayed dual-link snapshots. Exercise negative and current-epoch paths in real Windows WPF acceptance; expose explicit source rejection telemetry.
…ture epoch Restore PassiveMonitor's existing OnFindingRaised entrypoint through the same stamped UI finding queue; active Master delegates remain connection-owned.
Share canonical Master physical-frame reference across final IEC103 ValuePoints, EventLog and RX evidence. Fail closed for incomplete Type1 ASDU despite valid FT1.2 checksum; test real Master receive via deterministic secondary frames with positive and truncated negatives.
Require FUN/INF, DPI, four-byte CP32Time2a and SIN before promoting Type1; never decode partial CP32 from a DPI byte. Add six truncation negatives and exact time/SIN positive; retain original bytes for forensic inspection.
…Frames Distinguish zero physical UART bytes from received but incomplete/invalid FT1.2 traffic, accepted writer frames waiting on GUI, and COM startup. Add measured source counters and one-shot no-UART diagnostic, compact zero-state within existing WPF viewport, deterministic health-state regressions and actual WPF acceptance. Zero protocol TX changes.
…prior smoke fixtures App startup runs smoke/history probes on the same MainWindow. Begin the new-capture zero-byte check with ClearSessionView, matching actual passive Start semantics, before asserting visible no-UART diagnosis.
Reconciliation — 2026-11-06 (latest audited head
|
Show bounded real UART HEX in the Raw Frames viewport when no decoded frame exists, reset stale Trace filters each Start, expire stalled FT1.2 partials live on writer-owned idle tick, retain source offsets without inventing protocol Values. Exercise actual dual-COM 1200-bps receive-to-writer-to-live-feed with byte-split fixtures plus real WPF raw fallback acceptance.
…id ASDU trust boundary Keep all original COM RX frame bytes visible independently of IEC101 decode, classify unknown/partial/noise deterministically for operators, reject incomplete or unsupported ASDU objects from Values/SOE, preserve one raw physical frame row. Add tested positive/negative parser fixtures, real-WPF unknown/noise/partial acceptance and future-agent wire-first architecture contract. No passive TX, baud, or GUI thread ownership changes.
| decode?.CauseOfTransmission == 3 && decode.TypeId is >= 1 and <= 44, | ||
| IsRelayValue = direction == FrameDirection.SlaveToMaster && first is not null && decode is not null && | ||
| decode.TypeId is 1 or 2 or 3 or 4 or 5 or 6 or 7 or 8 or 9 or 10 or 11 or 12 or 13 or 14 or 15 or 16 or 30 or 31 or 32 or 34 or 35 or 36 or 37, | ||
| trustedDecode?.CauseOfTransmission == 3 && trustedDecode.TypeId is >= 1 and <= 44, |
| IsRelayValue = direction == FrameDirection.SlaveToMaster && first is not null && decode is not null && | ||
| decode.TypeId is 1 or 2 or 3 or 4 or 5 or 6 or 7 or 8 or 9 or 10 or 11 or 12 or 13 or 14 or 15 or 16 or 30 or 31 or 32 or 34 or 35 or 36 or 37, | ||
| trustedDecode?.CauseOfTransmission == 3 && trustedDecode.TypeId is >= 1 and <= 44, | ||
| IsRelayValue = direction == FrameDirection.SlaveToMaster && first is not null && trustedDecode is not null && |
…s in wire-first classifier Retain existing WPF smoke and parser reason terminology while explicitly distinguishing Unknown ASDU and untrusted physical bytes. Do not weaken integration assertions.
…r vocabulary Keep exact raw hex and no-false-Values/Events hard checks; report independent unknown/noise/partial/trust states on failure for fast root cause.
Independent source audit — 2026-11-06, exact PR head
|
P0 Frame Trace reliability milestone — ASE2000 behavioral benchmark (2026-11-06)Exact tested head: Reference: Public ASE2000 V2 material describes raw+interpreted line monitoring, a compact message list, Unknown messages, communication status/error counters and linked source-value inspection. We adopt the operational evidence principles, not proprietary source code, artwork or literal design. See https://www.ase-systems.com/products/ase2000-v2/ and https://www.ase-systems.com/ase2000-v1-faq/. Source-stage corrections
Exact-head acceptance
Remain open — P0 field/behavioral parity
|
Phase C3-A — source-owned IEC-101 process integrity (tested candidate)
Base:
masterat0967a590ed1f07f103195c0a4a7233adfb934e4d(Phase-C2 merged). Exact tested HEAD:bc9dacc092a92d9957f7700658c6be6d7402f25e. Still Draft and unmerged: this is a substantial IEC-101 C3-A engineering slice, not a completed IEC-101/103/104 Phase-C3 or hardware FAT.Structural issues and owning corrections
PassiveProcessDecodeCounters, exposed in live progress and capture manifest, with final invariant checks: observed frames = nonvariable + invalid + primary + secondary; secondary = decoded + rejected ASDUs; decoded objects = accepted + excluded; accepted writer objects = indexed + unindexed. No GUI queue can redefine source totals.SOEeven when event policy included eligible process/measurement observations. Label is nowOBSwith decoded invalid FT1.2 / rejected ASDU diagnostics.C3-A did not change protocol decoders, IEC-101 Master TX/poll/GI, IEC-104 APCI, release/stable, passive RX-only contract or visual design. Subsequent C3-B commits in this same draft PR extend active IEC-104 receive admission, shared Desktop trust projection, and IEC-101 dual-link source-frame identity. C3-A engineering scope:
docs/P0C3_PROCESS_INTEGRITY_20261106.md.Exact-head automated verification
CI artifacts (same Windows run)
ARIEC60870-Passive-Monitor-P0-GUI-win-x64, artifact ID13463066615ARIEC60870-IEC101-RX-Field-Tools-win-x64, ID13463156437ARIEC60870-OBS-C-ui-evidence, ID13463321209ARIEC60870-test-results, ID13462368268Next acceptance gate: IEC-103 and IEC-104 end-to-end canonical facts/provenance, stale-epoch rejection/reconnect stress, full 50k mixed pipeline measurements and WPF visible/retained version parity; physical 1200bps SOE FAT remains separate. Preserve Draft while these critical gates are not proven.
Phase C3-B integrated increment — IEC-104 trusted admission and IEC-101 dual-link original-frame parity
Exact-head verified:
86a0e422328c6e84c15f2268bc54db4a886d61d2onphase-c3-evidence-integrity-20261106relative to unchanged master0967a590ed1f07f103195c0a4a7233adfb934e4d. Still Draft / unmerged. This is a substantial C3-integrated increment, not completed end-to-end IEC-101/103/104 Phase-C3 and not physical 1200-bps SOE FAT.Production root causes and corrections
ReceiveOneAsyncwarned about out-of-window peer N(R), but still promoted the same I-frame as valid if N(S) matched. It could advance receive N(S), user-data/GI counters and publish valid-looking process objects. Invalid S-format acknowledgements were counted as good. An unaccepted COT10 could prematurely stop the receive burst. Fixed in the existing IEC-104 Master session owner: N(R) window is part of the single I acceptance verdict; rejected I/S are accounted, not promoted; burst termination uses only accepted I-frame evidence. Raw rejected frames/findings remain, and in-sequence retransmission is accepted.IsIec10xProcessValueindependently fell back to Type/IOA even for engine-rejectedRX Warningobservations. Blocked typed untrusted IEC-101/104 RX at the existing projection entry, before Value/Event or GI/command projection. Trace retains rejected wire evidence; no second APCI decoder or protocol state machine was introduced in UI.Iec101DualLinkRedundancySessionenriched evidence. Channel now receives the real session-assigned parent frame sequence from the existing publish callback and passesPhysicalFrameSequenceNumberto siblings. Navigation matches exact original frame and Link A/B, not a fabricated shared IOA or merged source.Deterministic regression
Exact-head evidence on
86a0e422328c6e84c15f2268bc54db4a886d61d2Previously covered C3-A workloads remain: 2,560 durable capture/preview observations, 5,000 accepted/indexed multi-source IEC-101 monitor objects with zero unindexed, and 50,000 IEC-101 decoded classifier objects (30,000 accepted, 20,000 excluded). This is not a new three-protocol 50,000 end-to-end performance measurement.
Exact-head CI artifacts: GUI
ARIEC60870-Passive-Monitor-P0-GUI-win-x64(13464799269), Windows WPFARIEC60870-OBS-C-ui-evidence(13464654728),ARIEC60870-test-results(13464539646), 2/4-RX toolkitARIEC60870-IEC101-RX-Field-Tools-win-x64(13464499875).Engineering analysis:
docs/P0C3B_IEC104_TRUSTED_RECEIVE_20261106.md. Phase C4 readiness gates: cross-protocol IEC-103/104 typed event source-fact parity from ingest through Replay/Reports, reconnect/Stop/epoch isolation, 2k/5k/50k mixed full-pipeline reproducible CPU/alloc/latency/queue/retention measurements, and an independent electrical 1200-bps FAT instrumenting sender, RTU, serial RX and SCADA. Remain Draft until critical gates are proved. Never equate green CI with physical IED/RTU interoperability.Phase C3-C — terminal Event/Values integrity (2026-11-06)
Production fix, exact PR head:
4bb79bafc00dee93b6ab33ff05406a2dabf082c0.masterremains0967a590ed1f07f103195c0a4a7233adfb934e4d; PR remains Draft. No protocol TX/poll/APCI semantics altered.Verified root cause in Desktop finalization:
ApplyFinalResultused toClear()the live Event ring and Values dictionary then replace them withIec103MasterRunResult.EventLog/ValuePoints. Those session result summaries are narrower than the source-qualified per-object Event/Values projections, and they lack some original-frame links. A complete active journal could therefore collapse to a handful of rows on session termination, independently of filters/auto-follow. The finalizer also flushed at most one bounded batch before reporting completion, allowing pending accepted observations to be stranded.Owning correction: existing WPF projection is retained through completion; result remains available for report/assessment via
_lastResultbut does not overwrite the live event/value authority. Finalization drains pending evidence and findings with boundedFlushUiQueues()dispatch batches andDispatcher.Yield(Background)until empty, before unlocking the next connection; no extra parser, archive writer, polling/GI/reset or timer. EVENT count at completion remains the projected actual observation count rather than the narrower engine edge-summary count.Deterministic Windows WPF regression: synthetic terminal
EventLogcontains only 1 summary entry andValuePointscontains 1 placeholder while live Event and Value stores contain multiple original facts. Enqueue 280 additional test evidence records (> one 42-item normal flush), invoke real terminal finalization, and assert: zero queue residue, unchanged retained Event objects, unchanged WPF Event/Value rows and source references, zero WPFResetnotifications, exact bound Event grid count, truthful EVENT counter.Exact-head checks: CI #42137403583 SUCCESS: Windows Release build 0 warnings/0 errors, 19/19 protocol smoke, 592/592 xUnit (63 Core, 185 Master, 106 Monitor, 5 Reporting, 218 Desktop, 15 Repository), actual Windows WPF 1400-frame viewport and new terminal regression PASS, Windows GUI/independent IEC101 RX toolkit packaging PASS. Hygiene #42137403542 SUCCESS and Dependency review #42137403604 SUCCESS. CodeQL #42137403705 SUCCESS on the exact same head.
Artifacts: Windows GUI ZIP, independent 2/4-RX toolkit, WPF screenshots/metrics, test results.
Acceptance boundary: fixes a reproducible terminal result-vs-live authority conflict; DOES NOT prove that the separately reported in-flight Event full/one/full flicker has no other root cause, full unbounded Event history, mixed 2k/5k/50k IEC101/103/104 end-to-end parity, archive/replay/report equivalence, measured CPU/GC/p50-p95/Stop metrics, exceptional Stop stale-epoch convergence, or physical 1200bps SICAM/SCADA ~2000 SOE FAT. Source Event preview remains intentionally bounded to 420 rows, not a claim of complete history without recording. Remain Draft until these gates are met.
C3-D/E — active session epoch isolation and native IEC-103 original-frame parity (2026-11-06)
Exact integrated HEAD:
4d5cd82702b67a0e9d6c5a0e395e74a597984139, basemaster0967a590ed1f07f103195c0a4a7233adfb934e4d. PR is still Draft/unmerged; no active IEC-101/103/104 TX, polling/GI/reset or passive RX-only contract was changed.C3-D: independently proven lifecycle isolation. Active single-link IEC-101, IEC-103, IEC-104 and IEC-101 dual-link subscriptions now bind immutable session epoch to callbacks; source-stamped evidence/finding queue entries are validated at enqueue AND dequeue. Delayed dual-link WPF snapshots re-check epoch before presentation; all session handlers detach in
finallyon Stop, fault, or success. Existing passive RX-only callback remains available and stamps its current capture epoch. Source-scope resets explicitly invalidate older epochs. A real Windows WPF acceptance injects old callbacks, already-queued stale observations/findings, then a current-epoch IEC-104 process object; asserts old evidence/finding rejection without loss of the new Value/Event. Rejection counters are reported separately from low-value UI compression. Seedocs/OUTPUT_AND_PERFORMANCE_POLICY.md.C3-E: IEC-103 source fact parity and verified decoder protection. The real IEC-103 Master now assigns native
ValuePointsandEventLogthe exact canonical physical RX frame reference already owned by the Master evidence event. In a real receive-path fixture, Type 1 COT1 spontaneous DPI and relay CP32Time2a retain identical origin references, event sequence and byte-for-byte frame HEX. An FT1.2-valid but truncated IEC-103 Type 1 previously returnedDecodeStatus.Okand could seed a false value; Core now requires FUN/INF + DPI (1) + CP32Time2a (4) + SIN (1). The full timestamp is decoded from its proper four bytes; SIN remains separate. Six zero-through-five-byte truncations plus positive full-payload test, and valid/invalid Master transport integration, prove fail-closed process promotion without erasing raw frame evidence.Exact-head automated proof: Windows CI #42145368494 SUCCESS with Release 0 warnings, 0 errors, 19/19 protocol smoke and 601/601 xUnit (Core 70, Master 187, Monitor 106, Reporting 5, Desktop 218, Repository 15; 0 failed/skipped); Windows real-WPF viewport/1400+ synthetic frames and new epoch acceptance PASS; integrated GUI ZIP and independent IEC-101 2/4-RX toolkit packaging PASS. Dependency review #42145368646 SUCCESS; hygiene #42145368507 SUCCESS. CodeQL #42145368825 SUCCESS on the exact integrated HEAD.
User-testable exact-head artifacts:
Unverified critical acceptance remains: complete native IEC-103 and IEC-104 indexed durable event/replay/report equivalence, active IEC-104 real TCP reconnect/cancellation under timing pressure, 2k/5k/50k whole production mixed IEC-101/103/104 CPU/alloc/memory/latency p50/p95 measurements, manual multi-DPI screenshot review, and isolated physical 1200-bps 2/4-COM SICAM-CP8050/SCADA receipt of ~2,000 sender SOEs with RTU FIFO accounting. Never infer hardware lossless delivery from source-level or CI tests. Keep PR Draft until these are separately established.
P0 field report — Passive IEC-101 COM4/COM3: empty Raw Frames (2026-11-06)
Grounded field observation: the user photographed a live Windows application with the subtitle Passive IEC-101 Link A · COM4/COM3, Stop Monitor available and an entirely empty Raw Frames viewport. The screenshot does not expose COM byte counters or prove whether any UART byte reached COM4/COM3, nor does it prove which build SHA was executing. Do not conflate the pre-read "Passive monitor started" status with physical traffic or claim a wiring defect from this image.
Code-path audit:
MainWindow.PassiveMonitor.RunPassiveMonitorAsyncpreviously set Monitoring/logged "started" before the two physical COM taps had delivered data. The writer owns physical byte counters and FT1.2 frames, but those numbers were shown on a separate advanced passive panel, not the empty primary Raw Frames workspace.PassiveFt12Scannercorrectly waits for complete framing; without explicit UART/decode/GUI provenance a blank grid could falsely look like a broken decoder.Patch, exact head:
15c66d9957ba5f2aa8bc0c1a426d7701d3f468f7(supersedes initiala416fa71with an isolated WPF fixture). The raw receive writer now separately counts checksum-valid FT1.2 frames, untrusted/noise/partial candidates and pending incomplete frame bytes, besides original per-COM byte totals and preview published/consumed counts.PassiveNoFrameDiagnosispure policy distinguishes (1) opening COM, (2) zero UART bytes (RX tap, wiring/ground or silent line), (3) physical bytes present but no accepted FT1.2 (baud/framing/partial/bad checksum), and (4) decoded frames awaiting/hidden by UI. Only the original raw-completed COM receive stream drives counts; no fabricated process events, no extra polling, no TX. The original Raw Frames ListBox displays a compact, unobtrusive empty-state explanation with selected COM identities and counts. A silent, opened capture after five seconds emits one session-scoped warning in Diagnostics, never repetitive polling or a claim that the remote RTU is down. Existing live 160ms UI timer owns refresh; no new timer.Hard regression:
PassiveMonitorP0Testsasserts honest no-data and separate undecoded/GUI-lag states. Real Windows--observation-ui-acceptancechecks the actual visible WPF zero-state after clearing earlier synthetic smoke history (the first CI try ona416fa71exposed harness fixture leakage; it was corrected without weakening the assertion). Exact-head Windows CI #42197612476: SUCCESS, Release 0 warnings/0 errors, 19/19 protocol smoke, 603/603 xUnit (70 Core, 187 Master, 108 Monitor, 5 Reporting, 218 Desktop, 15 Repository), real-WPF 1400-frame + empty-screen acceptance PASS, GUI and field-tools ZIP packaging PASS. Dependency review #42197612509 and repo hygiene #42197612477 SUCCESS. CodeQL #42197612465: SUCCESS.Field-test artifacts:
Physical acceptance not asserted. To close the field issue, run this exact build with electrically isolated RX-only taps on existing SCADA TX and RTU TX (and signal ground), correct COM identity and configured baud/parity/stop (e.g. 1200 bps if this is the field setup); observe COM4/COM3 byte counts and FT1.2 validity separately. If both count zero while an independent capture shows traffic, investigate adapters/driver/tap. If positive bytes but zero valid frames, use byte sample/HEX and UART framing/width evidence. If valid frames but zero WPF rows, capture the new queue counters and logs; that is an application bug. Zero physical frames cannot be fixed by a GUI decoder or green CI. PR remains Draft until real RX field verification and outstanding C3 whole-path acceptance.
P0 COM4/COM3 regression: raw UART preview must bypass FT1.2 framing (2026-11-06, latest)
Field constraint, not a speculative hardware fault: operator reports the same two COM4/COM3 receive-only adapters and physical installation previously produced frames, and both adapter RX LEDs blink in the failing newer build. DO NOT tell the operator to rewire/recheck baud as the default diagnosis. Screenshot alone cannot establish the COM driver read count or exact build. Treat regression in acquisition-to-WPF evidence path as P0.
Code-level failure proven: the primary
Raw Framespage was populated only when the FT1.2 scanner emitted a candidate; actual receivedPassiveChunkPreviewUART samples were exclusively shown on a separate Setup panel. In addition, an incomplete0x68...candidate can be buffered until a subsequent serial chunk or Stop; with bytes already read, the primary viewport could be entirely blank. This behavior remains possible even if the physical COM receiver is active. The earlier passive scanner was replaced with the shared Core framer in merged PR #93; don't claim that refactor itself broke real field RX without raw field data.Actual corrective implementation on exact head
3b1687949dc25037a7358a2f0cec8be573105f8bwithin this same PR:Raw Framesnow displays a bounded, selectable, real received UART HEX sample grid directly from originalPassiveRawRowswhen no FT1.2 frame appears. These are explicitly raw COM chunks, not synthetic protocol frames or trusted process SOEs. This bypasses scanner/decode success altogether without duplicating the read or issuing TX.All frames.WaitToReadAsyncread owner and one writer-owned 200-ms idle timer to publish incomplete scanner tails as original-bytePartialevents after configured inter-frame silence while the monitor is still running, not only on Stop. Never promotes checksum-unverified partials to process values or silently discards wire bytes. No new serial reads, polls, RTS/DTR or GI.68 0Cphysical raw sample appears on Raw Frames with zero completed FT1.2 candidates.Validated exact head: Windows CI run #42201227894 SUCCESS: Release 0 errors, 0 warnings; protocol smoke 19/19; xUnit 605/605 (Core 70, Master 187, Monitor 110, Reporting 5, Desktop 218, Repository 15) with no failed/skipped; WPF 1400-frame + actual no-frame raw-HEX acceptance SUCCESS; GUI/IEC101 RX toolkit packaging SUCCESS. CodeQL #42201227740, dependency review #42201227774, hygiene #42201227842 all SUCCESS.
Field-test artifacts from EXACT head, not earlier broken package:
Open hardware gate: CI has no COM4/COM3 devices and cannot confirm real field 1200-bps reception or end-to-end SICAM SOE integrity. Have operator test new exact-HEAD ZIP, observe both per-COM real raw byte HEX/FT1.2 candidates and compare with earlier working version using same physical ports; if raw read counters remain zero despite blinking LEDs, inspect serial reader-driver behavior/software config and direct CLI at the same ports without reassigning a wiring fault. Keep PR Draft and master unchanged pending this evidence.
P0-C4 — Wire-first COM receive and fail-closed Unknown ASDU operator contract (2026-11-06)
Source root cause and operator principle: the user's exact same COM4/COM3 setup previously displayed IEC-101 frames, and both serial RX LEDs now show physical activity. No automatic inference that the plant wiring is broken is acceptable. The newly audited source in the same PR already provides original COM chunk HEX in Raw Frames before framing, publisher-owned idle partials, and reset to All frames on Start. This milestone closes the next layer: the previous GUI could promote a supported Type ID with incomplete information-element payload to Value/Event and could describe a malformed/noise candidate using incorrect fallback message text. The canonical ASDU decoder legitimately reports an object with
Issuesfor a short element; a checksum-valid FT1.2 envelope is not proof of a complete process value.Clean-room line-monitor architecture, no vendor source copied:
src/ARIEC60870.Desktop/ViewModels/PassiveWirePresentation.csis one stateless classification gate shared by backgroundPassiveFramePreparationand the existing non-batch WPF path. It distinguishes Decoded, Link only, Unknown/invalid ASDU (checksum-valid FT1.2), Invalid frame, Partial, Noise and Link Width Mismatch. Every original raw physical observation continues to enter the same existing bounded Trace with original HEX, stream/offset, timestamp and an operator-readable reason. No false fallback A2 messages for other unrecognized material. Only confirmed supported, complete objects withIssues.Count == 0, exact VSQ object count and independently verified wire structure can project live process values. The independent writer-owned event ledger already rejects invalid process objects and remains authoritative. No new UART read, poll, GI, baud retune, RTS/DTR, parallel parser, WPF per-frame Dispatcher or unbounded GUI data store.Deterministic tests: checksum-valid unknown/private Type, checksum-valid but truncated known Type 1, noise, partial, malformed and prohibited A2 all retain byte-for-byte original HEX but never advertise trusted process facts; the existing known good multi-object Type 1 and 19-object SICAM Type 31 remain decoded. Windows executable
--observation-ui-acceptancechecks unknown Type/Noise/Partial reach actual Raw Frames together and leave Values/EventLog empty. Historical noise and Link Width Mismatch operator text are preserved, with original WPF smoke assertions still enforced.Agent handoff: append new mandatory wire-first release gate to
AGENTS.md; detailed implementation/backpressure/security/field-gate acceptance specification indocs/P0_WIRE_FIRST_MONITOR_ARCHITECTURE_20261106.mdand policydocs/OUTPUT_AND_PERFORMANCE_POLICY.md. This makes cross-thread direction durable and forbids a decoder dependency for raw visibility. Public docs deliberately vendor neutral.EXACT integrated HEAD
8655b4fa7b286fc5e93cd44aae14e7b415d8ddfevalidated by Windows CI #42205188671 SUCCESS: Windows Release 0 errors/0 warnings; 19/19 protocol smoke; 608/608 xUnit (Core 70, Master 187, Monitor 110, Reporting 5, Desktop 221, Repository 15) no failed/skipped; real-WPF 1400-frame + unknown/noise/partial acceptance PASS; GUI and 2/4-RX portable ZIP packaging PASS. CodeQL #42205189133, dependency #42205189710, hygiene #42205188946 all SUCCESS.Exact-head artifacts: Windows GUI ZIP, independent IEC-101 2/4-RX tool ZIP, real-WPF screenshot/metrics, test TRX.
Not yet physically proven: direct real COM4/COM3 receive with this exact ZIP, 2k SOE 1200-bps field receipt/FIFO attribution, and full native 50k mixed-system fatigue/latency benchmark. CI proves the controlled wire-first software receive and WPF contract, not lossless delivery from the physical RTU. Keep PR Draft/unmerged and stable/main unchanged until field evidence.