diff --git a/design/followups.md b/design/followups.md
index 975ef4c..33f50a1 100644
--- a/design/followups.md
+++ b/design/followups.md
@@ -90,7 +90,12 @@ For the per-step body of every line listed in the cumulative execution log, see
For ops where the body is purely `IAsbCustomSerializableType` arrays (Read, Register, Unregister), no DataContract names appear — every payload is wrapped as `{bytes}` (binary fast-path) and our builders are correct. The DataContract schema only matters for ops carrying non-`IAsbCustomSerializable` types like `MonitoredItem` and `WriteValue`.
-**Resolves when:** `build_add_monitored_items_request_body` and `build_delete_monitored_items_request_body` rewrite each `MonitoredItem` child as the DataContract field-suffix names (`activeField` instead of `Active`, etc.), with the `*Specified` siblings emitted as their own elements (`activeFieldSpecified`, `idFieldSpecified`, etc.). The dictionary-id pre-population that .NET's WCF binary writer uses to compress these long strings is a perf optimisation; an inline-string emit will work for correctness. Likely the same fix applies to `WriteBasicRequest`'s `WriteValue[]? Values` field (also non-`IAsbCustomSerializable`) — that's a future capture-and-verify pass.
+**Resolves when:** Two prerequisites:
+
+1. **F30 dynamic-dict resolution bug** — captured `tests/fixtures/add-monitored-items-request-wire.bin` (the .NET probe's verbatim 695-byte AddMonitoredItems request via `examples/asb-relay.rs`), decoded via `decode_envelope` at `tests/add_monitored_items_request_capture.rs`. The trace shows `DefaultNamespace { value: Chars("nameField") }` and `NamespaceDeclaration { prefix: "i", value: Chars("activeField") }` — namespace URL slots resolved to field-name strings, plus most element names left as `Static(NN)` instead of resolving to inline names. The F30 cumulative dynamic-dict post-pass at `envelope.rs::resolve_dict_names_in_tokens` mis-maps per-session dynamic dict ids; the fix needs reproducing exactly which dict each id refers to (per-message header vs cumulative dynamic vs `[MC-NBFS]` static) and resolving in the right order.
+2. **Builder rewrite** — once (1) lands and we can read the captured request structurally, rewrite `build_add_monitored_items_request_body` and `build_delete_monitored_items_request_body` to emit each `MonitoredItem` child as the DataContract field-suffix names (`activeField` / `activeFieldSpecified` / `bufferedField` / `itemField` / `sampleIntervalField` / `timeDeadbandField` / `timeDeadbandFieldSpecified` / `userDataField` / `valueDeadbandField`) under a `b` namespace prefix that maps to `http://schemas.datacontract.org/2004/07/ArchestrAServices.ASBIDataV2Contract`. The nested `` carries an ItemIdentity serialized via DataContract (NOT the binary `` fast-path — that only kicks in at the outer body-member level) with children `contextNameField` / `idField` / `idFieldSpecified` / `nameField` / `referenceTypeField` / `typeField` under a different `b` prefix mapping to `http://schemas.datacontract.org/2004/07/ArchestrAServices.ASBContract`. The Variant fields (`userDataField` / `valueDeadbandField`) carry `lengthField` / `payloadField` / `typeField` children. Same fix likely applies to `WriteBasicRequest`'s `WriteValue[]? Values` field (also non-`IAsbCustomSerializable`); needs its own capture-and-verify pass.
+
+The dictionary-id pre-population that .NET's WCF binary writer uses is a perf optimisation; an inline-string emit will work for correctness once the structure is right.
**Bonus context discovered while debugging F34:**
- `MinimalMonitoredItem` gained an `active: Option` field with a `with_active(item, interval, active)` constructor. Without `true` on the wire, MxDataProvider treats the subscription as inactive even when AddMonitoredItems "succeeds" — F26 stream then never sees values. (Once the field-name fix lands, this becomes the determining factor for whether values flow.)
diff --git a/rust/crates/mxaccess-asb/tests/add_monitored_items_request_capture.rs b/rust/crates/mxaccess-asb/tests/add_monitored_items_request_capture.rs
new file mode 100644
index 0000000..165b92e
--- /dev/null
+++ b/rust/crates/mxaccess-asb/tests/add_monitored_items_request_capture.rs
@@ -0,0 +1,47 @@
+//! F34 — wire-byte trace of a captured `AddMonitoredItemsRequest`.
+//!
+//! `tests/fixtures/add-monitored-items-request-wire.bin` is the
+//! verbatim C→S bytes the .NET probe (`MxAsbClient.Probe --subscribe
+//! --via=net.tcp://127.0.0.1:8088/...`) sent to MxDataProvider on
+//! 2026-05-06. The exchange led to a working subscription that
+//! delivered values; this is the request shape MxDataProvider
+//! actually accepts.
+//!
+//! Test goal: dump every NBFX token in the body so we can read off
+//! the exact element-name shape (DataContract field-suffix names per
+//! `[DataMember(Name=...)]`, NOT XmlSerializer property names) and
+//! re-implement `build_add_monitored_items_request_body` against it.
+//!
+//! Frame layout: 3-byte NMF SizedEnvelope header (`06 b4 05`,
+//! varint length = 692) + 692-byte SOAP envelope.
+
+#![allow(
+ clippy::unwrap_used,
+ clippy::expect_used,
+ clippy::indexing_slicing,
+ clippy::panic
+)]
+
+use mxaccess_asb::decode_envelope;
+use mxaccess_asb_nettcp::nbfx::DynamicDictionary;
+
+#[test]
+fn add_monitored_items_request_capture_decoder_trace() {
+ let raw = std::fs::read(
+ std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
+ .join("tests/fixtures/add-monitored-items-request-wire.bin"),
+ )
+ .expect("read fixture");
+ assert_eq!(raw.len(), 695, "frame length sanity check");
+
+ // Strip 3-byte NMF SizedEnvelope header.
+ let envelope = &raw[3..];
+ assert_eq!(envelope.len(), 692);
+
+ let mut dict = DynamicDictionary::new();
+ let decoded = decode_envelope(envelope, &mut dict).expect("decode_envelope succeeds");
+ eprintln!("=== body tokens ({} total) ===", decoded.body_tokens.len());
+ for (i, tok) in decoded.body_tokens.iter().enumerate() {
+ eprintln!(" body[{i}]={tok:?}");
+ }
+}
diff --git a/rust/crates/mxaccess-asb/tests/fixtures/add-monitored-items-request-wire.bin b/rust/crates/mxaccess-asb/tests/fixtures/add-monitored-items-request-wire.bin
new file mode 100644
index 0000000..47c51c2
Binary files /dev/null and b/rust/crates/mxaccess-asb/tests/fixtures/add-monitored-items-request-wire.bin differ