Lifecycle ownership bugs
Where
Widget tree, graph views, signal callbacks throughout assets/lua/
Problem
Before the April 2026 lifecycle hardening, the runtime had no clear ownership model:
- Frame update was split across multiple disconnected callers, each updating partially overlapping subsets
- Layout and widget teardown were confused — dropping layout didn't drop widgets, leaving orphaned objects
- Async completions could fire after the owning object was dropped (use-after-drop)
- Post-drop state was undefined — no explicit contract for what remains valid after teardown
- Stale rebuild contexts: when a widget was rebuilt, the rebuild function captured stale references to the old state
Why it matters
These bugs were the single largest source of runtime crashes during development. Without clear ownership, every async callback, every signal handler, and every rebuild was a potential crash site.
Plan
Resolved in April 2026 through a series of hardening commits:
fix(ui): centralize frame update ownership— single update entry point owns the full update passfix(ui): harden signal and graph view lifecycle— signals disconnect when owners dropfix(ui): stop double-dropping composite view children— teardown ownership clarified- See Lifecycle Invariants for the finalized rules
- See Lifecycle Hardening Plan for the full strategy
Related
- Lifecycle Hardening Plan
- Lifecycle Invariants
- Widget Ownership
- Goal: Core Platform
- See: commits from 2026-04-15 to 2026-04-22
