PrivatereportedPrivatefirstPrivate ReadonlydeclinedDistinct declined paths, in first-seen order. A Set because the budget is
per-run and the reporter is per-scene: the same path re-declines on every
subsequent run, and an array would report one stuck node as thousands.
Record a byte-ceiling refusal; log the first one. Named for the LOGGING
side because RefinementResidencyBudget.admit calls it as its
report-the-ceiling step, and renaming would be churn across that call site.
The scene's byte-ceiling stop, or undefined when nothing was ever
declined.
undefined rather than a zero-valued object on purpose: the snapshot is
read across a serialisation boundary by tools that must be able to tell
"refinement never hit the ceiling" from "it hit it and declined nothing",
and a {declinedPathCount: 0} object is indistinguishable from the field
simply being present-but-empty on an older build.
Called on every getState(), so the sample is taken with a BOUNDED loop
rather than Array.from(set).slice(…): the array form materialises all
thousands of paths just to keep eight, which is the exact allocation
RESIDENCY_DECLINED_PATH_SAMPLE exists to avoid.
Report the residency ceiling once for a scene, across refinement runs, and RECORD every refusal for snapshot.
The two halves are deliberately asymmetric. Logging is once-per-scene because a scene parked at the ceiling starts a fresh run after every view change and would otherwise flood the console during slice playback. Recording is every time, because "how much of the scene declined" is the number a capture tool has to branch on and one console line cannot carry it.