Delay instantiation of `HookCollection` until a hook is added.

This allows us to avoid the allocation for example groups that do not have hooks.
Optimize HookCollections#process.

Previously, it had a triple-nested-loop:
  hooks.each -> parent_groups.any? -> include?

We’ve optimized it by flat mapping over the parent
group list to get all hooks once, which allows us
to subtract them and immediately get the list of
hooks to add.  It’s simpler, too.

This also allows us to remove a few methods that
were only used by this logic.
Prefer simple arrays for tracking suite hooks.

HookCollection no longer offers us anything over an array
for the purpose of suite hooks since they don’t support
metadata filtering, anyway.
Remove HookCollection in favor of FilterableItemRepository.

This simplifies things, removes an unneeded abstraction and
reduces our object allocations further.