Commit Graph

2903 Commits

Author SHA1 Message Date
Claudio Ortolina 8108645718 Shrink collection summary to fit OpenAI token limit
Deduplicate records by musicbrainz_id (merging formats)
and cap genres to 3 per record, reducing the summary from
~32K to ~24K estimated tokens.
2026-04-13 12:33:15 +01:00
Claudio Ortolina ac1954f9c8 Document ExSlop Credo checks convention 2026-04-13 12:18:17 +01:00
Claudio Ortolina 50407f154e Update architecture docs for Collection Chat 2026-04-13 12:17:27 +01:00
Claudio Ortolina 9c0e11bc84 Use smaller model so that we don't exhaust tokens 2026-04-13 12:06:24 +01:00
Claudio Ortolina f73be3f881 Handle OpenAI api streaming error messages 2026-04-13 11:54:05 +01:00
Claudio Ortolina e0ad83a774 Update gettext translations for collection chat 2026-04-13 10:17:03 +01:00
Claudio Ortolina 3b8415d8c4 Add Collection Chat to universal search 2026-04-13 10:15:43 +01:00
Claudio Ortolina a509248625 Wire up Chat component in CollectionLive.Index 2026-04-13 10:12:49 +01:00
Claudio Ortolina 34f484cc81 Add CollectionChat StreamProvider 2026-04-13 10:09:50 +01:00
Claudio Ortolina 24a3cc9265 Add Collection.collection_summary/0 2026-04-13 10:08:01 +01:00
Claudio Ortolina d845ab93dd Add collection sentinel UUID to Chats context 2026-04-13 10:06:16 +01:00
Claudio Ortolina 55be2a4bab Add :collection to chat entity enum 2026-04-13 10:04:37 +01:00
Claudio Ortolina 399c4e4a2a Remove empty packages from ui-framework usage rules 2026-04-13 08:29:38 +01:00
dependabot[bot] 14d318923c Update usage_rules from 1.2.5 to 1.2.6
Updates [usage_rules](https://github.com/ash-project/usage_rules) from 1.2.5 to 1.2.6.
- [Release notes](https://github.com/ash-project/usage_rules/releases)
- [Changelog](https://github.com/ash-project/usage_rules/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ash-project/usage_rules/compare/v1.2.5...v1.2.6)

---
updated-dependencies:
- dependency-name: usage_rules
  dependency-version: 1.2.6
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-13 08:28:48 +01:00
Claudio Ortolina 035b4e7197 Extract shared record action menu component
Closes #155
2026-04-12 23:23:11 +01:00
Claudio Ortolina 88906e10ad Add ex_slop, configure it, run it and fix issues 2026-04-12 22:07:27 +01:00
Claudio Ortolina 9370e5f64d No need to use a case 2026-04-12 22:05:09 +01:00
Claudio Ortolina 834226921e Update production infrastructure docs 2026-04-12 12:46:51 +01:00
Claudio Ortolina b95cfd6e43 Validate Docker builder image on CI 2026-04-12 12:42:42 +01:00
Claudio Ortolina ae262352c6 Add shellcheck to CI lint job 2026-04-12 12:33:02 +01:00
Claudio Ortolina 4a8af7be39 Move lint, precommit, shellcheck from mix aliases to mise scripts
Mix aliases should only compose mix tasks. Shell tool orchestration
(shellcheck, fd) belongs in mise scripts. This removes the mix cmd
escape hatch and makes the boundary clear: mix.exs for pure mix
composition, scripts/ for cross-toolchain orchestration.
2026-04-12 12:30:59 +01:00
Claudio Ortolina 65135a618d Add script/command to validate Dockerfile args versions 2026-04-12 12:10:34 +01:00
Claudio Ortolina 9c7ab5b229 Add Claude Code hooks, commands, and permissions
High priority:

- Auto-format on edit (.claude/hooks/format-elixir.sh): runs mix format
  synchronously after every Edit/Write on .ex, .exs, and .heex files.
  Ensures code is formatted before the next read or tool call.

- mix test permissions: added Bash(mix test) (bare) and Bash(mix test *)
  (with path/flags) to the allow list. Previously only Bash(mix test:*)
  was allowed, which didn't match common invocations.

- Slash commands: /precommit runs the full mix precommit pipeline and
  reports failures with fix suggestions. /oban-status queries Oban job
  state via Tidewave SQL, grouped by state and worker.

Medium priority:

- Chrome DevTools permissions: added 8 new tools (select_page,
  list_network_requests, get_network_request, list_console_messages,
  get_console_message, hover, press_key, wait_for) for debugging API
  traffic, JS hook errors, hover states, and keyboard navigation.

- Gettext extraction hook (.claude/hooks/gettext-extract.sh): runs
  mix gettext.extract --merge asynchronously after editing .heex files.
  Async because it's project-wide and doesn't need to block the next edit.

- Sobelow permission: added Bash(mix sobelow:*) to the allow list for
  independent security checks.
2026-04-12 09:54:32 +01:00
Claudio Ortolina e498dccde5 Provide sqlite3 console command
- Loads extensions
- Wraps with rlwrap for convenience
2026-04-12 07:36:07 +01:00
Claudio Ortolina ea9886a647 Update Erlang to 28.4.2 2026-04-12 07:16:14 +01:00
Claudio Ortolina 02761428c1 Format map and list query params as JSON 2026-04-11 23:57:40 +01:00
Claudio Ortolina a983698c72 Document SQLite query optimization conventions 2026-04-11 23:46:23 +01:00
Claudio Ortolina 1c8d63c4d7 Bump Docker image versions in production docs 2026-04-11 23:46:06 +01:00
Claudio Ortolina 754a71cf70 Update dependencies
igniter 0.7.8 => 0.7.9
2026-04-11 23:39:00 +01:00
Claudio Ortolina d8c84e787b Optimize ListeningStats query performance
Three independent refactors of lib/music_library/listening_stats.ex,
measured against the dev DB (104k tracks) via bench/listening_stats.exs:

| Query                           | Baseline  | After     | Speedup |
|---------------------------------|-----------|-----------|---------|
| recent_activity(tz, 100)        | 38.98 ms  | 2.87 ms   | 13.6x   |
| list_tracks(page 1, 200)        | 47.30 ms  | 4.81 ms   | 9.8x    |
| get_top_artists_by_days(7)      | 66.51 ms  | 1.02 ms   | 65x     |
| get_top_artists_by_days(30)     | 67.41 ms  | 2.84 ms   | 23.7x   |
| get_top_artists_by_days(365)    | 76.03 ms  | 25.57 ms  | 3.0x    |
| get_top_albums_by_days(7)       | 92.63 ms  | 1.61 ms   | 57.5x   |
| get_top_albums_by_days(30)      | 94.52 ms  | 3.69 ms   | 25.6x   |
| get_top_albums_by_days(365)     | 105.23 ms | 32.81 ms  | 3.2x    |
| get_top_artists(limit: 10)      | 123.96 ms | 101.68 ms | 1.22x   |
| get_top_albums(limit: 10)       | 209.64 ms | 108.23 ms | 1.94x   |

tracks_with_record_info_query/0 now uses correlated scalar subqueries
against record_releases and artist_records instead of materializing
helper subqueries on every call. The cost scales with the outer LIMIT,
not with the size of record_releases.

top_albums_base_query/0 and top_artists_base_query/0 are replaced by
aggregate_query + attach_metadata pairs. The pattern is aggregate first,
attach metadata second: GROUP BY runs against the raw track scan, then
a tiny outer SELECT attaches record_releases / artist_infos lookups for
the <= 10 result rows via correlated subqueries.

tracks_since_query/1 wraps the date-filtered inner scan with limit: -1.
SQLite cannot flatten a subquery that has a LIMIT, so it materializes
the date-bounded subset and the optimizer uses the timestamp index for
the range scan instead of the album/artist composite index. This trick
replaces SQLite's WITH ... AS MATERIALIZED (which ecto_sqlite3 doesn't
expose).

All json_extract(?, '\$.path') fragments use the canonical form rather
than the equivalent ? ->> '\$.path' shorthand. SQLite's index matcher
requires the GROUP BY expression to match the index expression
textually to use the composite index for natural ordering.

collected_releases_query/0 and wishlisted_releases_query/0 are removed
from Collection and Wishlist — they had a single internal caller that
no longer exists after the refactor.

New regression tests lock the semantics that the optimized queries
must preserve:
- count(DISTINCT scrobbled_at_uts) — 579 duplicate timestamps exist in
  the dev DB from rapid Last.fm scrobbles, so replacing with count(*)
  would silently change results
- :artist_id key in list_tracks result maps — ScrobbledTracksLive.Index
  destructures it even though the template body never references it

Closes #148
2026-04-11 23:36:32 +01:00
Claudio Ortolina d3da4e4559 Update architecture docs for embedding ownership 2026-04-11 21:48:59 +01:00
Claudio Ortolina 839566dd63 Update dependencies
igniter 0.7.7 => 0.7.8
2026-04-11 21:46:07 +01:00
Claudio Ortolina 82e4882aa9 Assert embedding enqueues in batch test 2026-04-11 21:43:00 +01:00
Claudio Ortolina ea6ecb2661 Assert embedding enqueues in artist info test 2026-04-11 21:43:00 +01:00
Claudio Ortolina 3da0865725 Drop Records embedding wrappers 2026-04-11 21:43:00 +01:00
Claudio Ortolina a608be7387 Move regenerate_artist_embeddings into Similarity 2026-04-11 21:43:00 +01:00
Claudio Ortolina 789ce04b87 Use MusicBrainz.get_all_releases in Records 2026-04-11 21:40:32 +01:00
Claudio Ortolina b7af9557c1 Add MusicBrainz.get_all_releases/1 2026-04-11 21:40:32 +01:00
Claudio Ortolina 755955df54 Update elixir to 1.20.0-rc.4 2026-04-10 23:12:51 +01:00
Claudio Ortolina 2422b6a243 Update dependencies
credo 1.7.17 => 1.7.18
2026-04-10 23:10:09 +01:00
Claudio Ortolina fcf5adde2f Add tests for QueryReporter 2026-04-10 11:10:12 +01:00
Claudio Ortolina 8826834549 Fix release status badge in grouped records on this day
The tooltip was using the group representative instead of the
actual record, causing all items in a group to show the same
badge regardless of their own selected_release_id.
2026-04-10 10:38:48 +01:00
Claudio Ortolina 90a0491924 Update architecture docs with QueryReporter 2026-04-10 10:31:21 +01:00
Claudio Ortolina 1c720c8394 Add query timing metadata to reporter output 2026-04-10 10:30:05 +01:00
Claudio Ortolina 27148c6507 Add dev query reporter and skill
Ecto telemetry reporter that captures executed SQL queries
to a log file with interpolated parameters and source
locations. Activated/deactivated at runtime via Tidewave
for LLM-driven query analysis workflows.
2026-04-10 10:27:12 +01:00
Claudio Ortolina b5686fa0f9 Allow creating a new page with chrome devtools 2026-04-10 09:14:27 +01:00
Claudio Ortolina eab5ec5ac1 Remove localhost URL from README (because port changes) 2026-04-10 07:49:42 +01:00
Claudio Ortolina 2c393db0f2 Add visual verification guidance to ui-framework skill 2026-04-10 07:45:22 +01:00
Claudio Ortolina 31ebfe41ed Allow use of Chrome Devtools for verification 2026-04-10 07:30:52 +01:00
Claudio Ortolina 3fb292ce35 Improve update-documentation skill
Add parallel analysis via subagents, skip-list for irrelevant
commits, format-matching guidance, and wider trigger description.
2026-04-09 16:27:49 +01:00