Codex stop-hook review: child nodes were saved without ids. batch_design
only assigns an id to the top-level inserted node — nested children
(inner row, cards, texts, icon_fonts) come through the DSL unchanged,
which breaks any later tree operation that resolves by id (update /
delete / move / post-processing / spatial index lookup).
Fix: assignIdsRecursively walks the wrapper subtree before serializing
to DSL and stamps every node with generateId(). batch_design's own
overwrite of the top-level id is harmless.
Test: 4 new id-coverage tests (one per children_type + uniqueness
across a 3-card tree). Total 17 tests in add-scroll-row-v0, 74 in
pen-mcp suite. format + tsc green.