From 981bd046da12d537e139d9a91a52cc03d2d65078 Mon Sep 17 00:00:00 2001 From: Caleb Allen Date: Sat, 28 Feb 2026 13:42:31 -0500 Subject: [PATCH] docs(quick-002): plan auto-rename duplicate playlists on import --- .../002-PLAN.md | 171 ++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 .planning/quick/002-auto-rename-duplicate-playlists-on-import/002-PLAN.md diff --git a/.planning/quick/002-auto-rename-duplicate-playlists-on-import/002-PLAN.md b/.planning/quick/002-auto-rename-duplicate-playlists-on-import/002-PLAN.md new file mode 100644 index 0000000..953a5dc --- /dev/null +++ b/.planning/quick/002-auto-rename-duplicate-playlists-on-import/002-PLAN.md @@ -0,0 +1,171 @@ +--- +phase: quick +plan: 002 +type: execute +wave: 1 +depends_on: [] +files_modified: + - backend/database/sql/queries/playlists.sql + - backend/database/sql/sqlcgen/playlists.sql.go + - backend/playlist/playlist.go +autonomous: true +requirements: [QUICK-002] + +must_haves: + truths: + - "Importing an M3U whose name matches an existing playlist auto-renames to Name (1)" + - "Importing again produces Name (2), Name (3), etc." + - "CreatePlaylist and CreatePlaylistWithTracks do NOT auto-rename (only import)" + artifacts: + - path: "backend/database/sql/queries/playlists.sql" + provides: "CountPlaylistsByName query" + contains: "CountPlaylistsByName" + - path: "backend/database/sql/sqlcgen/playlists.sql.go" + provides: "Generated CountPlaylistsByName function" + contains: "CountPlaylistsByName" + - path: "backend/playlist/playlist.go" + provides: "uniquePlaylistName helper and ImportPlaylist integration" + contains: "uniquePlaylistName" + key_links: + - from: "backend/playlist/playlist.go" + to: "backend/database/sql/sqlcgen/playlists.sql.go" + via: "s.db.Queries.CountPlaylistsByName" + pattern: "CountPlaylistsByName" +--- + + +Auto-rename duplicate playlists on import — when importing an M3U/M3U8 file whose +derived name matches an existing playlist, automatically append (1), (2), etc. instead +of creating a duplicate. Only applies to import, not manual CreatePlaylist. + +Purpose: Prevent confusing duplicate playlist names when importing the same file multiple times. +Output: Modified playlist SQL queries (+ regenerated sqlc), updated ImportPlaylist flow. + + + +@/home/caleb/.config/Claude/get-shit-done/workflows/execute-plan.md +@/home/caleb/.config/Claude/get-shit-done/templates/summary.md + + + +@backend/database/sql/queries/playlists.sql +@backend/database/sql/sqlcgen/playlists.sql.go +@backend/playlist/playlist.go +@backend/database/sqlc.yaml + + + + + + Task 1: Add CountPlaylistsByName SQL query and regenerate sqlc + + backend/database/sql/queries/playlists.sql + backend/database/sql/sqlcgen/playlists.sql.go + + + Add a new sqlc query to `backend/database/sql/queries/playlists.sql` at the end of the + existing playlist queries (after `CreatePlaylist`, before track queries): + + ```sql + -- name: CountPlaylistsByName :one + SELECT COUNT(*) AS count FROM playlists WHERE name = ?; + ``` + + Then regenerate sqlc from `backend/database`: + ```bash + cd backend/database && sqlc generate + ``` + + This produces a `CountPlaylistsByName(ctx, name string) (int64, error)` function in + `playlists.sql.go`. Verify the generated function exists and compiles. + + + `grep -q "CountPlaylistsByName" backend/database/sql/sqlcgen/playlists.sql.go` succeeds + AND `go build ./backend/database/sql/sqlcgen/` compiles cleanly. + + CountPlaylistsByName query exists in SQL and generated Go code compiles. + + + + Task 2: Add uniquePlaylistName helper and wire into ImportPlaylist + backend/playlist/playlist.go + + **Add helper method** to `backend/playlist/playlist.go` (place it just above ImportPlaylist, + around line 684): + + ```go + // uniquePlaylistName returns a name that doesn't collide with existing + // playlists. If "Chill Vibes" exists, returns "Chill Vibes (1)". + // If that also exists, returns "Chill Vibes (2)", etc. + func (s *Service) uniquePlaylistName(name string) string { + count, err := s.db.Queries.CountPlaylistsByName(s.db.Ctx, name) + if err != nil || count == 0 { + return name + } + for i := 1; ; i++ { + candidate := fmt.Sprintf("%s (%d)", name, i) + c, err := s.db.Queries.CountPlaylistsByName(s.db.Ctx, candidate) + if err != nil || c == 0 { + return candidate + } + } + } + ``` + + **Wire into ImportPlaylist** — after the `playlistName` derivation block (after the + closing brace of the `if playlistName == ""` block, around line 715) and BEFORE the + `s.db.Queries.CreatePlaylist` call (line 718), add: + + ```go + playlistName = s.uniquePlaylistName(playlistName) + ``` + + **Important:** Do NOT add this call to `CreatePlaylist`, `CreatePlaylistWithTracks`, or + any other method. Only `ImportPlaylist` gets auto-rename behavior. + + Verify the full package compiles: `go build ./backend/playlist/` + + + `go build ./backend/playlist/` compiles cleanly AND + `grep -q "uniquePlaylistName" backend/playlist/playlist.go` succeeds AND + `grep -c "uniquePlaylistName" backend/playlist/playlist.go` returns 3 (definition + method body call to self isn't counted — should be: func signature, call in ImportPlaylist, plus the function body references = at least 2-3 occurrences). + + + uniquePlaylistName helper exists and is called from ImportPlaylist (and ONLY ImportPlaylist). + `go build ./backend/...` compiles. `go vet ./backend/...` passes. + + + + + + +```bash +# Full backend build +go build ./backend/... + +# Vet check +go vet ./backend/... + +# Verify CountPlaylistsByName exists in generated code +grep "CountPlaylistsByName" backend/database/sql/sqlcgen/playlists.sql.go + +# Verify uniquePlaylistName is ONLY called from ImportPlaylist, not CreatePlaylist +# This grep should show the function definition and one call site in ImportPlaylist +grep -n "uniquePlaylistName" backend/playlist/playlist.go + +# Verify CreatePlaylist method does NOT reference uniquePlaylistName +# (manual scan — the grep above should show it's only in ImportPlaylist context) +``` + + + +- `go build ./backend/...` passes +- `go vet ./backend/...` passes +- CountPlaylistsByName query exists in SQL and generated Go +- uniquePlaylistName helper exists and is called only from ImportPlaylist +- CreatePlaylist / CreatePlaylistWithTracks unchanged + + + +After completion, create `.planning/quick/002-auto-rename-duplicate-playlists-on-import/002-SUMMARY.md` +