The five residual src/hooks/ hooks (useConnectionStatus, useCardGridMetrics,
useTracklistColumns, useNavidromeAdminRole, useAnalysisPerfListener) are all
domain-agnostic — none imports @/features — so they join the other shared hooks
in src/lib/hooks/ (with their two colocated tests). Consumers repointed;
relative-up imports in the moved files become the @/ alias. src/hooks/ is removed.
Pure move + import updates, no behavior change. The layering baseline gains five
lib->store entries (the three hooks that read authStore/devOfflineBrowseStore are
only now caught under lib/) — same documented debt class as the api move.
Two lower-layer→feature inversions removed:
- Detail-route predicates (isAlbumDetailPath/isArtistDetailPath/isComposerDetailPath)
were defined in features/album's browse store but are pure URL checks. Extracted
to lib/navigation/detailRoutePaths; the browse store re-exports them so the
@/features/album barrel surface is unchanged. This frees albumDetailNavigation of
its only @/features import, so it moves utils/navigation → lib/navigation (drains
utils/navigation). Also fixes the M5 isArtistDetailPath misplacement.
- mixRatingFilter's sole feature dep is playback's userRatingOverrides and its only
binding consumer is playback's buildInfiniteQueueCandidates, so it belongs in the
playback feature: utils/mix → features/playback/utils (drains utils/mix). The
earlier handoff note that lib/api/subsonicStarRating consumes it was stale — that
is only a code comment, verified no runtime import.
Pure moves; tests pass unmodified. The share cluster + switchActiveServer stay in
utils/ — they are imported by the a11y-HELD PasteClipboardHandler, so relocating
them would rewrite a do-not-touch file.