A plugin reload (or a disable/enable) tears the client fiber down while this
module's own service/store subscriptions are still live: unregistering each
built-in descriptor notifies the plugin's service, and every notification ran
`sync()` again. The `files` takeover is never a descriptor — its key is
`FILES_KIND` — so the drop loop released it every single time, and the block
below re-created it. Re-registering on the now-inactive context throws inside
`registerSlots` (`ctx.slots.inject` cannot create an effect on an inactive
context) *after* `tabs.register` already put the type into the host registry,
so that registration's disposer was lost with the exception.
The id then stayed taken for the rest of the page's life: every later attempt
was refused with
sidebarRight: tab type id "dsh-better-sidebar:files" is already registered
and the kind rendered the host's "nothing here can view this kind of content
yet" face until a page refresh.
- `sync()` skips the `files` takeover in its drop loop: the takeover is owned
by the editor-type switch, so an unrelated notification no longer puts its
host-side type through a tear-down/re-register window;
- a registration that fails after its type was registered releases the type
again (and whatever slot disposers it collected), so the same id stays
registrable and a retry can succeed;
- one descriptor that cannot register no longer aborts the whole sync, so the
remaining types are still brought up;
- teardown releases every registration even when one release throws.
Verified: tests/native-registration.spec.ts (new, 4 cases) is red 4/4 against
the unfixed code and green with the fix; tsc/eslint clean and the full unit
suite passes.