77f1e84a34
The plugin context only tracked contribution/socket disposers, so a plugin's other side effects (store subscriptions) leaked across disable/re-enable. Add ctx.onDispose(fn) — an arbitrary cleanup collected alongside the rest and run on deactivate. bindApi now returns a disposer (unsubscribes its persisted-atom listeners, closes the socket, drops the rest handle) and the kanban plugin registers it via ctx.onDispose, so a toggle leaves nothing behind and never duplicates listeners. Also DRYs the atom-persistence into one `persist` helper.