pub(crate) async fn seed_layout_via_reducer(
state: &AppState,
tab_id: &str,
new_tree: LayoutNode,
focused_node_id: String,
leaforder: Vec<LeafOrderEntry>,
magnified_node_id: String,
) -> Result<(), String>Expand description
SPEC_864 Phase 3 — single-writer layout seeding. Dispatch a
LayoutSetTree (tree + focus + leaforder as client slices) and persist
it inside ONE hold of the reducer mutex, so persist order equals
dispatch order — the same contract as UpdateObject’s Phase-2 route in
object.rs. Replaces the wcore-direct seeders
(write_default_three_pane_layout post-bootstrap caller,
setup_torn_off_block_layout): the reducer’s TabRecord.rootnode is
authoritative, and the persist subscriber is the sole db_layout
writer on this path.
On SQLite apply failure the reducer is rolled back to an empty tree
(the seed target is a fresh tab whose row was empty) inside the same
lock hold. Publishes events on success. Requires the tab to be known
to the reducer — true for every caller (all run after reducer-routed
CreateTab / sagas); the pre-bootstrap first-launch seed
(ensure_initial_data → seed_default_layout) deliberately stays
store-direct because the reducer isn’t hydrated yet (spec site #3).