Skip to content

Commit 515a084

Browse files
docs: update backlog tasks
1 parent ada9728 commit 515a084

4 files changed

Lines changed: 234 additions & 3 deletions

backlog/tasks/task-285.11 - Reduce-22-critical-complexity-symbols-CC-threshold.md

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ title: Reduce 22 critical-complexity symbols (CC > threshold)
44
status: In Progress
55
assignee: []
66
created_date: '2026-02-24 00:05'
7-
updated_date: '2026-02-24 20:13'
7+
updated_date: '2026-02-24 22:40'
88
labels:
99
- tech-debt
1010
- code-health
@@ -29,7 +29,52 @@ Run `roam complexity` to get the full list. Use `roam complexity --threshold 50`
2929

3030
## Acceptance Criteria
3131
<!-- AC:BEGIN -->
32-
- [ ] #1 No symbols with CC > 300 remain (top 3 handled by dedicated tasks)
32+
- [x] #1 No symbols with CC > 300 remain (top 3 handled by dedicated tasks)
3333
- [ ] #2 Critical-complexity count reduced from 22 to under 10
34-
- [ ] #3 All tests pass after each refactoring batch
34+
- [x] #3 All tests pass after each refactoring batch
3535
<!-- AC:END -->
36+
37+
## Implementation Notes
38+
39+
<!-- SECTION:NOTES:BEGIN -->
40+
## Progress (2026-02-24)
41+
42+
### Symbols refactored (CC before -> after):
43+
- **createArtistsBrowser**: 286 -> below 50 (extracted artist-utils, single-track-context-menu mixin, queue-builder utility)
44+
- **createSidebar**: 229 -> 87 (extracted playlist-crud and playlist-reorder mixins)
45+
- **createLibraryBrowser**: 300 -> 163 (replaced inline queue building with shared queue-builder utility)
46+
- **createNowPlayingView**: 63 -> below 50 (extracted queue-drag-reorder mixin)
47+
- **initEventListeners**: 54 -> below 50 (extracted 8 named handler functions)
48+
- **handleKeydown**: 65 -> below 50 (split into handleModifierShortcut + handlePlaybackShortcut)
49+
- **promptToAddWatchedFolders**: 65 -> below 50 (extracted addWatchedFoldersBatch + showWatchedFolderResultToast)
50+
- **openAddMusicDialogOp**: 59 -> below 50 (extracted showScanResultToast)
51+
52+
### New files created:
53+
- `app/frontend/js/utils/artist-utils.js`
54+
- `app/frontend/js/utils/queue-builder.js`
55+
- `app/frontend/js/mixins/single-track-context-menu.js`
56+
- `app/frontend/js/mixins/playlist-crud.js`
57+
- `app/frontend/js/mixins/playlist-reorder.js`
58+
- `app/frontend/js/mixins/queue-drag-reorder.js`
59+
60+
### Current state:
61+
- Critical symbols >= CC 50: 16 (down from 22 original, though some new ones from extractions)
62+
- All 281 unit tests pass
63+
- AC #2 not yet met (target: under 10). Remaining high-CC symbols need further work:
64+
createQueueStore (214), createSettingsView (211), createMetadataModal (206),
65+
createLibraryBrowser (163), createPlayerStore (131), createUIStore (121),
66+
createAlbumsBrowser (103), contextMenuActionsMixin (89), createSidebar (87),
67+
playlistCrudMixin (80), playlistReorderMixin (62), columnSettingsMixin (61),
68+
columnGeometryMixin (60), createLibraryStore (50)
69+
70+
Commits: 9a8ce15
71+
72+
## Analysis (2026-02-24)
73+
74+
CC extraction alone won't reach the health score target. The score dropped from 53 to 43 because extractions added files and import edges without addressing the structural issues roam weighs most heavily:
75+
- 1 dependency cycle (CRITICAL)
76+
- 7 actionable god components
77+
- 7 actionable bottlenecks
78+
79+
Further CC reduction on the remaining 16 symbols is still valuable but has diminishing returns on the health score. The cycle, api bottleneck, and god component issues need dedicated subtasks under TASK-285.
80+
<!-- SECTION:NOTES:END -->
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
---
2+
id: TASK-285.13
3+
title: Reduce api.js god component degree and bottleneck betweenness
4+
status: In Progress
5+
assignee: []
6+
created_date: '2026-02-24 22:40'
7+
updated_date: '2026-02-24 22:42'
8+
labels:
9+
- tech-debt
10+
- code-health
11+
- architecture
12+
dependencies:
13+
- TASK-285.12
14+
references:
15+
- app/frontend/js/api.js
16+
parent_task_id: TASK-285
17+
priority: medium
18+
---
19+
20+
## Description
21+
22+
<!-- SECTION:DESCRIPTION:BEGIN -->
23+
`api.js` is both the top god component (degree 35) and the top bottleneck (betweenness 1509) in the frontend. Every component imports it for IPC calls, making it a single point of coupling.
24+
25+
**Current state:** `api` is a monolithic object exporting namespaced methods (api.library.*, api.queue.*, api.playlists.*, api.favorites.*, etc.). All 35+ consumers import the entire object even when they only need one namespace.
26+
27+
**Approach options:**
28+
1. **Split by domain** — Break `api.js` into `api/library.js`, `api/queue.js`, `api/playlists.js`, etc. Consumers import only what they need. This reduces degree (fewer edges per module) and betweenness (paths no longer all flow through one node).
29+
2. **Re-export facade** — Keep `api.js` as a re-export barrel but move implementations to domain files. Consumers can import from either. Reduces betweenness while preserving the convenience import.
30+
31+
Option 1 is more impactful for the health score. Option 2 is lower risk.
32+
33+
Run `roam impact api` and `roam uses api` to see all consumers before refactoring.
34+
<!-- SECTION:DESCRIPTION:END -->
35+
36+
## Acceptance Criteria
37+
<!-- AC:BEGIN -->
38+
- [ ] #1 api.js god component degree reduced below 20
39+
- [ ] #2 api.js bottleneck betweenness reduced below 500
40+
- [ ] #3 All frontend tests pass
41+
- [ ] #4 No behavioral changes
42+
<!-- AC:END -->
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
---
2+
id: TASK-285.14
3+
title: 'Reduce Rust god components and bottlenecks (audio, metadata, artwork)'
4+
status: In Progress
5+
assignee: []
6+
created_date: '2026-02-24 22:41'
7+
updated_date: '2026-02-24 22:42'
8+
labels:
9+
- tech-debt
10+
- code-health
11+
- rust
12+
dependencies: []
13+
references:
14+
- crates/mt-tauri/src/audio/mod.rs
15+
- crates/mt-tauri/src/scanner/metadata.rs
16+
- crates/mt-tauri/src/scanner/artwork_cache.rs
17+
- crates/mt-tauri/src/scanner/fingerprint.rs
18+
parent_task_id: TASK-285
19+
priority: low
20+
---
21+
22+
## Description
23+
24+
<!-- SECTION:DESCRIPTION:BEGIN -->
25+
Roam identifies several actionable god components and bottlenecks in the Rust backend. These are lower impact than the frontend structural issues but contribute to the health score.
26+
27+
**God components (actionable):**
28+
- `error` module in `crates/mt-tauri/src/audio/mod.rs` — degree 40. Likely a broad error enum used by many audio subsystems. Consider splitting into domain-specific error types.
29+
- `len` / `is_empty` methods in `crates/mt-tauri/src/scanner/artwork_cache.rs` — degree 31/28. These are simple methods with high fan-in, likely because the artwork cache is widely referenced. May be inherent to the design.
30+
- `track` field in `crates/mt-tauri/src/commands/audio.rs` — degree 23
31+
- `data` field in `crates/mt-tauri/src/scanner/artwork.rs` — degree 21
32+
33+
**Bottlenecks (actionable):**
34+
- `extract_metadata` (betweenness 264), `extract_metadata_or_default` (254), `non_empty` (163), `extract_metadata_batch` (109) — all in `crates/mt-tauri/src/scanner/metadata.rs`. This file is a funnel for all metadata extraction. Consider whether the helper functions (`non_empty`, `extract_metadata_or_default`) can be made module-private or inlined to reduce their graph centrality.
35+
- `state` field in `crates/mt-tauri/src/audio/engine.rs` — betweenness 64
36+
- `FileFingerprint` struct in `crates/mt-tauri/src/scanner/fingerprint.rs` — betweenness 54
37+
38+
**Triage guidance:** Some of these (len/is_empty, track/data fields) may be inherent to the architecture and not worth refactoring. Focus on the error module (degree 40) and metadata bottleneck cluster (combined betweenness 791) for the best health score impact.
39+
<!-- SECTION:DESCRIPTION:END -->
40+
41+
## Acceptance Criteria
42+
<!-- AC:BEGIN -->
43+
- [ ] #1 No Rust god components with degree > 30 remain in actionable category
44+
- [ ] #2 Metadata bottleneck cluster combined betweenness reduced by at least 30%
45+
- [ ] #3 All Rust tests pass (cargo nextest run --workspace)
46+
<!-- AC:END -->
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
---
2+
id: TASK-288
3+
title: Add "Go to Album" context menu item to track context menus
4+
status: To Do
5+
assignee: []
6+
created_date: '2026-02-24 22:31'
7+
labels:
8+
- frontend
9+
- ux
10+
- context-menu
11+
dependencies: []
12+
references:
13+
- app/frontend/js/mixins/context-menu-actions.js
14+
- app/frontend/js/mixins/single-track-context-menu.js
15+
- app/frontend/js/components/albums-browser.js
16+
- app/frontend/js/stores/ui.js
17+
priority: medium
18+
---
19+
20+
## Description
21+
22+
<!-- SECTION:DESCRIPTION:BEGIN -->
23+
Add a "Go to Album" item to the track right-click context menu across all views (library, artists, albums detail). Clicking it should navigate to the Albums view and drill down into the track's album.
24+
25+
**User story**: Right-click "Sia - Chandelier" > "Go to Album" > navigates to Albums view showing "1000 Forms of Fear" album detail.
26+
27+
**Menu placement**: Between "Add to Liked Songs" and the separator before "Show in Finder" — matching the user's request.
28+
29+
## Current Context Menu Order (library)
30+
31+
1. Play Now
32+
2. Add to Queue
33+
3. ---separator---
34+
4. Play Next
35+
5. Add to Playlist (submenu)
36+
6. Add to Liked Songs
37+
7. ---separator--- ← INSERT "Go to Album" BEFORE this separator
38+
8. Show in Finder
39+
9. Edit Metadata
40+
10. ---separator---
41+
11. Remove from Library
42+
43+
## Target Context Menu Order
44+
45+
1. Play Now
46+
2. Add to Queue
47+
3. ---separator---
48+
4. Play Next
49+
5. Add to Playlist (submenu)
50+
6. Add to Liked Songs
51+
7. **Go to Album** ← NEW
52+
8. ---separator---
53+
9. Show in Finder
54+
10. Edit Metadata
55+
11. ---separator---
56+
12. Remove from Library
57+
58+
## Key Files
59+
60+
### Context menu mixins (add menu item here)
61+
- `app/frontend/js/mixins/context-menu-actions.js` — Library browser context menu (multi-track). Menu items defined in `handleContextMenu()` at line 80. Insert new item after "Add to Liked Songs" (line 104) and before the separator/Show in Finder block (line 131).
62+
- `app/frontend/js/mixins/single-track-context-menu.js` — Artists/albums browser context menu (single-track). Menu items defined in `handleContextMenu()` at line 24. Insert after "Add to Liked Songs" (line 36) and before the separator + "Show in Finder" (line 37-38).
63+
64+
### Albums browser (navigation target)
65+
- `app/frontend/js/components/albums-browser.js` — Has `openAlbumDetail(album)` (line 169) which drills into an album. Has `navigateToArtist()` (line 197) as a cross-view navigation precedent using `ui.setView()` + `CustomEvent`.
66+
67+
### UI store (view switching)
68+
- `app/frontend/js/stores/ui.js``setView('albums')` switches to albums view (line 86).
69+
70+
## Implementation Pattern
71+
72+
Follow the existing `navigateToArtist()` pattern in `albums-browser.js`:
73+
74+
1. **Dispatch event**: `window.dispatchEvent(new CustomEvent('mt:navigate-to-album', { detail: { album: track.album, albumArtist: track.album_artist || track.artist } }))`
75+
2. **Switch view**: `this.$store.ui.setView('albums')`
76+
3. **Listen in albums-browser.js**: Add event listener for `mt:navigate-to-album` in `init()`, find the matching album in `albumList`, and call `openAlbumDetail(album)`.
77+
78+
### Track → Album linkage
79+
Albums are identified by composite key: `track.album` + `track.album_artist` (falling back to `track.artist`). See `albumList` getter at line 83 of `albums-browser.js`.
80+
81+
### Menu item should be disabled when:
82+
- Multiple tracks are selected (in library view, `selectedCount > 1`)
83+
- Track has no album metadata (`!track.album`)
84+
85+
### Note on single-track-context-menu.js
86+
This mixin is used by both artists-browser and albums-browser. When the user is already in the album detail view, "Go to Album" should either be hidden or disabled (they're already looking at the album). Consider checking if `$store.ui.view === 'albums'` and the album matches.
87+
<!-- SECTION:DESCRIPTION:END -->
88+
89+
## Acceptance Criteria
90+
<!-- AC:BEGIN -->
91+
- [ ] #1 Right-clicking a track in the library view shows 'Go to Album' between 'Add to Liked Songs' and the separator before 'Show in Finder'
92+
- [ ] #2 Clicking 'Go to Album' switches to Albums view and opens the correct album detail (matching album name + album artist)
93+
- [ ] #3 Right-clicking a track in the artists view also shows 'Go to Album' with same behavior
94+
- [ ] #4 'Go to Album' is disabled when multiple tracks are selected in library view
95+
- [ ] #5 'Go to Album' is disabled or hidden when the track has no album metadata
96+
- [ ] #6 When already viewing an album in albums detail view, 'Go to Album' is hidden or disabled for tracks in that same album
97+
- [ ] #7 Context menu closes after clicking 'Go to Album'
98+
<!-- AC:END -->

0 commit comments

Comments
 (0)