Three lifecycle gaps, benign among curated builtins but hazardous the
day Tier-6 Lua extensions land: a throw mid-contribution left earlier
contributions mounted while the extension recorded as failed (a retry
then double-applied them); deactivate ignored active dependents; and
the panel/command registries silently clobbered on id collision.
Activation now tracks what it mounted and unwinds it all on failure
(including the extension's own deactivate when its activate had
succeeded); deactivate refuses with a logged warning while active
dependents exist — disable the dependents first; duplicate
contribution/command ids throw, which the transactional path turns
into a clean failed activation with first-wins semantics.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>