What's more, if I run this on the stream returned by OpenRead(uri)
new StreamReader(stream).ReadToEnd()
I get the full string, as expected.
In the end, the only way I found was to pass a string to HtmlDocument.Load. I suspect there is a bug in the stream processing code of the various HtmlDocument.Load overloads.