First live 26100 walk since #102 split the VS plausibility predicate and made the refusal count a count. Both changes paid off immediately, and what they show points somewhere I dismissed while writing them.
The measurement
pool_census over KDNET, 408,013 chunks walked (241,970 allocated) in ~19s, partial, 3,569 diagnostics in 14 categories. Every VS diagnostic:
542x # VS chunk headers refused, resynchronising from #
542x refusing VS chunk at # the chunk runs past the end of its subsegment (size # previous size # encoded #
68x # VS chunks disagreed with the size of the chunk before them, from #
68x VS chunk at # records a previous size of # where the chunk before it measured #
and the walk's own total, which no diagnostic can carry:
Two things worth separating
1. One predicate accounts for every refusal. decode_vs_chunk has three: the size word decoding to zero, a chunk smaller than its own headers, and a chunk running past its subsegment. On a walk with 106,516 refusals, the first two fired zero times. That is not what corruption looks like — a header rewritten under us, or a wrongly keyed word, would spray across all three. One predicate at 100% is the shape of a predicate that is wrong.
The obvious candidate is the bound itself, which is region.address + region.size. #93 raised exactly this ("worth checking while in here: whether region.size is the right bound") and I dismissed it in #102 on the grounds that the test is > rather than >=, so a chunk ending exactly at the boundary is accepted. That answers the exact-boundary case and says nothing about a bound that is systematically too small — which is what this looks like. #92's discover_segment_context advances a VS region past _HEAP_VS_SUBSEGMENT and shrinks its size to match; if that shrink is short, or if the walk starts at a base that is not the subsegment's, every chunk near the end of every extent overruns.
2. 106,516 is refusals, not lost chunks. A refusal advances 16 bytes and tries again, so one lost sync inside an extent bills one refusal per 16 bytes until it resynchronises: 106,516 refusals across 542 extents is ~196 per extent, ~3.1 KB of brute-force scanning each. The count is still the right number to carry — it is what the walk actually did — but it sizes the disruption, not a population of corrupt chunks, and anything reading it as the latter will overstate the damage by orders of magnitude.
What would settle it
The encoded word travels with the refusal now, precisely so a refused header can be re-decoded by hand. Take one refused chunk from a sample, decode its Sizes against the subsegment's own _HEAP_VS_SUBSEGMENT extent read directly from the target, and compare that extent with the region.size the walker was using. If they differ, the bound is the bug and 106,516 refusals are an artefact of it.
The chain check is the cross-check that makes this readable: only 68 extents show a chunk disagreeing with its predecessor's size. If the chunks themselves were corrupt at anything like the rate the refusals suggest, that number would not be 68.
Reproduce
cargo test --test mcp_smoke -- --ignored --nocapture --test-threads=1 live_kernel
with WINDBG_MCP_SMOKE_KERNEL sourced from the configured profile, then pool_diagnostics with filter VS chunk for verbatim samples carrying real numbers.
First live 26100 walk since #102 split the VS plausibility predicate and made the refusal count a count. Both changes paid off immediately, and what they show points somewhere I dismissed while writing them.
The measurement
pool_censusover KDNET, 408,013 chunks walked (241,970 allocated) in ~19s,partial, 3,569 diagnostics in 14 categories. Every VS diagnostic:and the walk's own total, which no diagnostic can carry:
Two things worth separating
1. One predicate accounts for every refusal.
decode_vs_chunkhas three: the size word decoding to zero, a chunk smaller than its own headers, and a chunk running past its subsegment. On a walk with 106,516 refusals, the first two fired zero times. That is not what corruption looks like — a header rewritten under us, or a wrongly keyed word, would spray across all three. One predicate at 100% is the shape of a predicate that is wrong.The obvious candidate is the bound itself, which is
region.address + region.size. #93 raised exactly this ("worth checking while in here: whetherregion.sizeis the right bound") and I dismissed it in #102 on the grounds that the test is>rather than>=, so a chunk ending exactly at the boundary is accepted. That answers the exact-boundary case and says nothing about a bound that is systematically too small — which is what this looks like.#92'sdiscover_segment_contextadvances a VS region past_HEAP_VS_SUBSEGMENTand shrinks its size to match; if that shrink is short, or if the walk starts at a base that is not the subsegment's, every chunk near the end of every extent overruns.2. 106,516 is refusals, not lost chunks. A refusal advances 16 bytes and tries again, so one lost sync inside an extent bills one refusal per 16 bytes until it resynchronises: 106,516 refusals across 542 extents is ~196 per extent, ~3.1 KB of brute-force scanning each. The count is still the right number to carry — it is what the walk actually did — but it sizes the disruption, not a population of corrupt chunks, and anything reading it as the latter will overstate the damage by orders of magnitude.
What would settle it
The
encodedword travels with the refusal now, precisely so a refused header can be re-decoded by hand. Take one refused chunk from a sample, decode itsSizesagainst the subsegment's own_HEAP_VS_SUBSEGMENTextent read directly from the target, and compare that extent with theregion.sizethe walker was using. If they differ, the bound is the bug and 106,516 refusals are an artefact of it.The chain check is the cross-check that makes this readable: only 68 extents show a chunk disagreeing with its predecessor's size. If the chunks themselves were corrupt at anything like the rate the refusals suggest, that number would not be 68.
Reproduce
with
WINDBG_MCP_SMOKE_KERNELsourced from the configured profile, thenpool_diagnosticswith filterVS chunkfor verbatim samples carrying real numbers.