diff --git a/docs/architecture.md b/docs/architecture.md index d4208117..32538afb 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -93,11 +93,11 @@ Last.fm schemas (separate, not Ecto-persisted to main DB): | Context | Schemas | Responsibility | |---------|---------|---------------| -| `Records` | Record, RecordEmbedding, SearchIndex | CRUD, search, import from MusicBrainz, cover/genre/embedding management, PubSub notifications | +| `Records` | Record, RecordEmbedding, SearchIndex | CRUD, search, import from MusicBrainz, cover/genre/color/embedding management, PubSub notifications | | `Collection` | Record (via SearchIndex) | Querying collected records (purchased_at != nil), stats, collected artist IDs | | `Wishlist` | Record (via SearchIndex) | Querying wishlisted records (purchased_at is nil) | | `Artists` | ArtistInfo, ArtistRecord | Artist metadata from MusicBrainz/Discogs/Wikipedia/Last.fm, images, search | -| `Assets` | Asset | Binary asset storage (covers, artist images), cache tracking | +| `Assets` | Asset | Binary asset storage (covers, artist images), cache tracking, pruning unreferenced assets | | `Notes` | Note | Free-text notes for records and artists | | `Chats` | Chat, Message, StreamProvider, RecordChat, ArtistChat | Persistent AI chat conversations for records and artists, streaming AI chat behaviour and entity-specific implementations | | `RecordSets` | RecordSet, RecordSetItem | User-curated record groupings with ordering | @@ -127,7 +127,8 @@ Last.fm schemas (separate, not Ecto-persisted to main DB): | `Req.RateLimiter.SystemClock` | Real clock implementation using System.monotonic_time | | `Assets.Cache` | ETS-based asset cache with TTL | | `Assets.Image` / `Assets.Transform` | Image processing via Vix (libvips) | -| `Colors.KMeansExtractor` | Color extraction via K-Means clustering (dominant_colors library) | +| `Colors.Extractor` | Behaviour for dominant color extraction (configurable, allows test stubbing) | +| `Colors.KMeansExtractor` | Color extraction via K-Means clustering (dominant_colors library), implements `Colors.Extractor` | | `Chats.StreamProvider` | Behaviour for streaming AI chat (`stream_response/3` callback) | | `Chats.RecordChat` | Chat implementation for records (OpenAI streaming, web search enabled) | | `Chats.ArtistChat` | Chat implementation for artists (OpenAI streaming, uses Wikipedia/artist context) | diff --git a/docs/project-conventions.md b/docs/project-conventions.md index da908240..073d8e5d 100644 --- a/docs/project-conventions.md +++ b/docs/project-conventions.md @@ -18,6 +18,7 @@ Rules extracted from commit history that are specific to this project and not al - **LiveComponents communicate with parent** via `send(self(), {__MODULE__, msg})`. - **Function components go in domain-specific modules:** `CoreComponents` for generic UI, `RecordComponents` for records, `ScrobbleComponents` for scrobbles, `SearchComponents` for search. - **External API integrations** follow a three-module pattern: Facade (public API), API (Req HTTP client), Config (NimbleOptions). +- **Behaviours are separate modules** containing only `@callback` definitions. Concrete implementations use `@behaviour` and `@impl true`. - **Oban workers are thin wrappers** that delegate to context modules. `perform/1` should be minimal. - **Shared utilities** live at parent namespace level (`MusicLibrary.Batch`, not `MusicLibrary.Records.Batch`). - **Domain sub-modules group under their context.** Modules strongly related to a context live as sub-modules (e.g., `Chats.StreamProvider`, `Chats.RecordChat`), distinct from shared utilities which live at the parent namespace level.