pub fn prune_dangling_block_refs(
root: &mut Option<LayoutNode>,
live_block_ids: &HashSet<String>,
) -> usizeExpand description
Removes every leaf whose data.block_id is not in live_block_ids,
using the same collapse semantics as an explicit user delete
(delete_node’s single-child-parent promotion). Returns the number of
leaves pruned (0 = tree was already clean — the common case, so this is
cheap to call unconditionally on every write).
This is the reducer’s referential-integrity enforcement for db_layout,
added after
docs/investigations/INVESTIGATION_LAYOUT_DEAD_SPACE_STALE_TREE_RESURRECTION_2026_07_08.md
found that a single point-fix (notifying the frontend on one specific
delete path) only closes the one mechanism it targets — any other
current or future caller that writes a stale/bad tree without going
through that same notification channel can still leave a dangling
blockId behind. Calling this at every layout-tree write site in the
reducer (the single writer of db_layout since SPEC_864) makes “no
layout leaf ever references a nonexistent block” an unconditional
invariant of the write path itself, not a property individual callers
have to remember to uphold — the same shape as WRR (Window Reality
Reconciliation, crates/cef/src/wrr/) enforcing “no window/pool
drift” at the point where reality is observed, rather than trusting
every caller to keep the model in sync.
Re-scans the tree fresh after each removal rather than working off a
pre-computed list of dangling node ids, since delete_node’s
single-child collapse can rewrite a surviving parent’s id out from
under a stale id — see the comment on delete_recursive. Terminates
because each iteration strictly shrinks the tree (bounded by leaf
count).