Gap
Redis 7+ types a non-empty XREAD/XREADGROUP reply as a RESP3 Map keyed by stream name (%N stream => entries). Moon emits the RESP2 Array shape (*N [name, entries]) in every protocol — there is no Frame::Map construction anywhere in src/command/stream/ (stream_read.rs / stream_write.rs build Frame::Array unconditionally).
Impact
A RESP3 client that dispatches on the reply container type (expecting a Map) is served the wrong shape. Systemic across the whole XREAD/XREADGROUP family, not specific to any one mode. The null-array miss case is unaffected (a null array is identical in both protocols).
Discovered by
The client-compat probe parity_xreadgroup_history_resp3_reply_is_map (added in #564, batch #527/#526/#469/#520/#521). It is currently waived in scripts/client-compat/manifest.yaml with owner resp3-type-fidelity; the waiver ratchets — test-client-compat.sh --strict will FAIL the moment Moon starts answering a Map, so this issue cannot silently rot.
Fix sketch
In the XREAD/XREADGROUP reply builders, when the connection negotiated RESP3 (HELLO 3), wrap the per-stream results in Frame::Map keyed by stream name instead of the array-of-pairs. Mirror the resp3-type-fidelity conversion approach already used for other reply types (src/protocol/resp3.rs). Add a resp3 unit test and flip the manifest waiver to a clean pass.
Owner milestone: resp3-type-fidelity.
Gap
Redis 7+ types a non-empty
XREAD/XREADGROUPreply as a RESP3 Map keyed by stream name (%N stream => entries). Moon emits the RESP2 Array shape (*N [name, entries]) in every protocol — there is noFrame::Mapconstruction anywhere insrc/command/stream/(stream_read.rs/stream_write.rsbuildFrame::Arrayunconditionally).Impact
A RESP3 client that dispatches on the reply container type (expecting a Map) is served the wrong shape. Systemic across the whole XREAD/XREADGROUP family, not specific to any one mode. The null-array miss case is unaffected (a null array is identical in both protocols).
Discovered by
The client-compat probe
parity_xreadgroup_history_resp3_reply_is_map(added in #564, batch #527/#526/#469/#520/#521). It is currently waived inscripts/client-compat/manifest.yamlwith ownerresp3-type-fidelity; the waiver ratchets —test-client-compat.sh --strictwill FAIL the moment Moon starts answering a Map, so this issue cannot silently rot.Fix sketch
In the XREAD/XREADGROUP reply builders, when the connection negotiated RESP3 (
HELLO 3), wrap the per-stream results inFrame::Mapkeyed by stream name instead of the array-of-pairs. Mirror the resp3-type-fidelity conversion approach already used for other reply types (src/protocol/resp3.rs). Add a resp3 unit test and flip the manifest waiver to a clean pass.Owner milestone: resp3-type-fidelity.