design/70-risks: record the .NET reference's WriteCompleted half-implementation

R3's verdict gains an aside documenting why the original native
MxAccess `OnWriteComplete` event has historically only fired for the
one exact 5-byte pattern `00 00 50 80 00` (= `MxStatus.WriteCompleteOk`).

Verified at:
- `src/MxNativeClient/MxNativeCompatibilityServer.cs:756` —
  `if (!evt.Message.IsMxAccessWriteComplete) return;` gates the
  consumer-facing `WriteCompleted` event.
- `src/MxNativeCodec/NmxOperationStatusMessage.cs:18` —
  `IsMxAccessWriteComplete` requires
  `Format == StatusWord && StatusCode == 0x8050 && CompletionCode == 0x00`.

Every other completion frame is silently dropped — the 1-byte
`0x00`/`0x41`/`0xEF` ones, plus any non-success status word.

This was the underlying reason R3/R4 looked unsolvable for a year:
the answer "we don't know how to map" was actually "the native
compatibility shim deliberately doesn't map these because firing
typed failure events on ambiguous bytes was never a goal."

Path A's `MxStatus::from_packed_u32` (commit `c73a33e`) closes the
asymmetry on the Rust side: `Session::operation_status_events()`
exposes ALL typed outcomes the upstream synthesizer produces, not
just the WriteCompleteOk slice. The Rust port now has strictly
broader operation-status visibility than the .NET reference offered.

Recorded so future contributors don't re-derive this from scratch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Joseph Doherty
2026-05-06 07:13:28 -04:00
parent c73a33edd8
commit f98ab9846d
+2
View File
@@ -60,6 +60,8 @@ A second mapping was also ported: `MxStatus::from_nmx_response_code` covers the
**What about the 1-byte completion frames `0x00`/`0x41`/`0xEF`?** Those are NOT decoded by `FUN_10100ce0` — they're a different wire field (the NMX operation-status callback payload, not the `INmxService.GetResponse2 responseCode` parameter). `Lmx.dll`'s decoder for those frames does not invoke any status-synthesis logic; they propagate as raw byte → `MxStatus { success: 0, Unknown, Unknown, detail: byte }`. The Rust port preserves this exactly. R4 is settled by the same fact (see below).
**Aside — the .NET-reference shim was always half-implemented.** Verified at `src/MxNativeClient/MxNativeCompatibilityServer.cs:756` + `src/MxNativeCodec/NmxOperationStatusMessage.cs:18`: `MxNativeCompatibilityServer` fires `WriteCompleted` only when `IsMxAccessWriteComplete` is true, which gates strictly on `Format == StatusWord && StatusCode == 0x8050 && CompletionCode == 0x00` — i.e. the one exact 5-byte pattern `00 00 50 80 00` (= `MxStatus.WriteCompleteOk`). Every other completion frame (the 1-byte `0x00`/`0x41`/`0xEF` ones and any non-success status word) is silently dropped at the gate. The native consumer-facing `WriteCompleted` event has therefore **only ever fired for unambiguous successful writes** — failure outcomes have been invisible at the compatibility-shim layer for the entire history of the .NET reference. Path A's kernel (`from_packed_u32`) closes this asymmetry on the Rust side: `Session::operation_status_events()` exposes **all** typed outcomes the upstream synthesizer produces, not just the WriteCompleteOk slice. The Rust port now has strictly broader operation-status visibility than the .NET reference offered.
Logs:
- `analysis/ghidra/exports/Lmx.dll.aadct-decompile.md``aaDCT` symbol (stage 1)
- `analysis/ghidra/exports/LmxProxy.dll.completion-status-decompile.md` — Fire_* event handlers (stage 2)