Rewrites ABSCollectionStore's 8 methods to read/write
user_personal_collections (collection_type='manual') instead of the
dropped abs_user_collections / abs_collection_items tables. The
in-memory abs.Collection / abs.CollectionItem struct shape is
unchanged; ToABS() emitter helpers in internal/audiobooks/abs/
preserve the wire-shape contract.
Notable mappings:
- abs.Collection.IsPublic ↔ user_personal_collections.is_shared.
- profile_id is now text NOT NULL (defaults to ''), so we bind the
empty string for primary-profile rows rather than SQL NULL.
- user_personal_collection_items.user_id is NOT NULL with no FK
cascade from the parent — AddCollectionItem uses an INSERT ... SELECT
to copy user_id from the parent collection, and DeleteCollection
explicitly drops items before the parent within a single tx.
- ListCollectionItems filters sub_item_id='' to avoid leaking the
playlist podcast-episode rows that share the items table.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>