Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
a92a953
fix(music): fix artist routing, stop snapshot clear, manual track pri…
LucasSantana-Dev May 5, 2026
cb0a21c
Merge branch 'main' into fix/autoplay-bugs-and-improvements
LucasSantana-Dev May 5, 2026
fbca6eb
feat(autoplay): scoring improvements, loved seed boost, genre fallbac…
LucasSantana-Dev May 5, 2026
f9d0b7e
feat(autoplay): add same-album soft penalty in diversity selection (p…
LucasSantana-Dev May 5, 2026
66a592e
test(bot): add lastFmSeeder.spec.ts to fix SonarCloud gate on PR #805
LucasSantana-Dev May 5, 2026
a41bcc9
test(bot): expand lastFmSeeder coverage — similar tracks and sparse-a…
LucasSantana-Dev May 5, 2026
ffa99bb
chore: remove unused audioFeatureCache from candidateScorer
LucasSantana-Dev May 5, 2026
8a0e066
test(bot): add queueStateManager.spec.ts with comprehensive coverage
LucasSantana-Dev May 5, 2026
80dd9b5
test(bot): add youtubeErrorHandler/analyzer.spec.ts with 56 comprehen…
LucasSantana-Dev May 5, 2026
59e666f
test(bot): add titleComparison/service.spec.ts
LucasSantana-Dev May 5, 2026
d7c33c3
test(bot): cover remaining lastFmSeeder branches (lines 85, 202, 215)
LucasSantana-Dev May 5, 2026
99c5008
test(bot): add service.spec.ts for TrackManagementService (44 tests)
LucasSantana-Dev May 5, 2026
bdb6076
feat(lastfm): surface API errors at warn level instead of debug
LucasSantana-Dev May 5, 2026
8253f08
refactor: remove duplicate normalizeText/normalizeTrackKey from candi…
LucasSantana-Dev May 5, 2026
787f5f8
test(shared): add logAndRethrow.spec.ts covering logAndRethrow, logAn…
LucasSantana-Dev May 5, 2026
4bb9379
refactor: consolidate ScoredTrack, extract scoring constants, add mis…
LucasSantana-Dev May 5, 2026
9cf3c44
test(autoplay): add tests for recentSkipCount and same-album penalty
LucasSantana-Dev May 5, 2026
0498eaf
test: cover candidateScorer audio-feature paths and isLovedSeed
LucasSantana-Dev May 5, 2026
528355c
refactor: replace 15-param calculateRecommendationScore with ScoringC…
LucasSantana-Dev May 5, 2026
3161c73
Merge branch 'main' into fix/autoplay-bugs-and-improvements
LucasSantana-Dev May 5, 2026
e62362d
fix: address CodeRabbit review — recentSkipCount in SessionMood, dedu…
LucasSantana-Dev May 5, 2026
b460cde
chore: merge autoplay cleanup (ScoringContext, constants, ScoredTrack…
LucasSantana-Dev May 5, 2026
a6b5cd2
chore: merge main (queueManipulation split) + update ScoringContext c…
LucasSantana-Dev May 5, 2026
f2d68e8
fix: remove unused SCORE_SAME_GENRE_HINT, SCORE_POPULAR_RESTLESS, SCO…
LucasSantana-Dev May 5, 2026
514766c
chore: exclude lastFmSeeder.ts from CPD (repeated scoring loops by de…
LucasSantana-Dev May 5, 2026
11d3d4d
fix: guard URL comparison in moveUserTrackToPriority; fix stray brace…
LucasSantana-Dev May 5, 2026
7f95121
fix: skip-storm bypasses genre veto, deep-dive boost, genreContext in…
LucasSantana-Dev May 5, 2026
ed109bc
fix: replace findLastIndex with reverse loop (ES2021 compat)
LucasSantana-Dev May 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .claudeignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
node_modules/
dist/
build/
coverage/
.nyc_output/
*.lock
package-lock.json
yarn.lock
pnpm-lock.yaml
*.log
*.min.js
*.min.css
*.map
.git/
.playwright-mcp/
.data/
441 changes: 441 additions & 0 deletions .context/lucky-rag-context.md

Large diffs are not rendered by default.

75 changes: 75 additions & 0 deletions .context/query-context.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# SigMap Query Context
Generated: 2026-05-03T02:47:48.234Z

## packages/shared/src/generated/prisma/models/GuildSubscription.ts
```
export interface GuildSubscriptionFieldRefs
export type GuildSubscriptionModel
export type AggregateGuildSubscription
export type GuildSubscriptionMinAggregateOutputType
export type GuildSubscriptionMaxAggregateOutputType
export type GuildSubscriptionCountAggregateOutputType
export type GuildSubscriptionMinAggregateInputType
export type GuildSubscriptionMaxAggregateInputType
export type GuildSubscriptionCountAggregateInputType
export type GetGuildSubscriptionAggregateType
export type GuildSubscriptionGroupByOutputType
export type GetGuildSubscriptionGroupByPayload
export type GuildSubscriptionWhereInput
export type GuildSubscriptionOrderByWithRelationInput
export type GuildSubscriptionWhereUniqueInput
export type GuildSubscriptionOrderByWithAggregationInput
export type GuildSubscriptionScalarWhereWithAggregatesInput
export type GuildSubscriptionCreateInput
export type GuildSubscriptionUncheckedCreateInput
export type GuildSubscriptionUpdateInput
```

## packages/shared/src/services/PremiumService.ts
```
export class PremiumService
async isPremium(guildId) → Promise<boolean>
async getSubscription(guildId) → Promise<GuildSubscri
```

## packages/frontend/src/hooks/useVoteStatus.ts
```
export interface VoteStatus
hasVoted: boolean streak: number nextVoteInSe
nextTier: { label: string
export function useVoteStatus() → { status }
```

## .worktrees/lucky-artists-fix/packages/shared/src/services/database/DatabaseInitializationService.ts
```
export interface DatabaseInitializationResult
export interface DatabaseServiceStatus
export class DatabaseInitializationService
async initialize() → Promise<boolean>
async getServiceStatus() → Promise<DatabaseServ
getDatabaseService() → DatabaseService | nu
async shutdown() → Promise<void>
```

## .worktrees/lucky-artists-fix/packages/shared/src/services/guildAutomation/types.ts
Comment on lines +43 to +54

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Committed paths leak a local worktree.

Lines 43 and 54 reference .worktrees/lucky-artists-fix/packages/..., which is a path inside a developer's local Git worktree (.worktrees/...). Other contributors and CI won't have that directory, so the doc points at non-existent files for everyone but the author. Regenerate .context/query-context.md from the canonical workspace (so paths start with packages/...) before committing, or add .context/query-context.md to .gitignore if it's intended to be developer-local SigMap output.

🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 44-44: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.context/query-context.md around lines 43 - 54, The committed
.context/query-context.md contains local worktree paths like
".worktrees/lucky-artists-fix/packages/..." which leak developer-specific
directories; update the file so all paths start from the canonical workspace
(e.g., "packages/...") by regenerating .context/query-context.md from the root
workspace, or if this file is intended to be local-only, add
".context/query-context.md" to .gitignore and remove the committed copy; locate
references to ".worktrees/lucky-artists-fix" in .context/query-context.md and
replace/regenerate them accordingly.

```
export interface GuildAutomationRole
export interface GuildAutomationChannel
export interface GuildAutomationOnboardingPromptOption
export interface GuildAutomationOnboardingPrompt
export interface GuildAutomationOnboarding
export interface GuildAutomationModeration
export interface GuildAutomationAutoMessage
export interface GuildAutomationReactionRoleMessage
export interface GuildAutomationParityChecklistItem
export interface GuildAutomationParity
export interface GuildAutomationManifestDocument
export interface GuildAutomationDiffOperation
export interface GuildAutomationPlan
export interface GuildAutomationStatus
export type AutomationModule
export type AutomationAction
export type AutomationRunType
export type AutomationRunStatus
export type DriftSeverity
```
1 change: 1 addition & 0 deletions .context/session.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"ts":1777776468234,"intent":"navigate","topFiles":[{"file":"packages/shared/src/generated/prisma/models/GuildSubscription.ts","score":3.8},{"file":"packages/shared/src/services/PremiumService.ts","score":3.8},{"file":"packages/frontend/src/hooks/useVoteStatus.ts","score":2.3},{"file":".worktrees/lucky-artists-fix/packages/shared/src/services/database/DatabaseInitializationService.ts","score":1.5},{"file":".worktrees/lucky-artists-fix/packages/shared/src/services/guildAutomation/types.ts","score":1.5}],"lastQuery":"Where is premium subscription status checked?"}
3,357 changes: 3,357 additions & 0 deletions .github/copilot-instructions.md

Large diffs are not rendered by default.

46 changes: 46 additions & 0 deletions docs/specs/2026-04-25-backlog-map/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Spec: Backlog Map — 2026-04-25

> Draft promotion of the Top-10 items from `.claude/plans/backlog-2026-04-25.md`.
> Re-evaluate every two weeks; supersedes `docs/specs/2026-04-22-backlog-map/`.

## Anchor

- Source backlog: `.claude/plans/backlog-2026-04-25.md`.
- Prior tracked snapshot: `docs/specs/2026-04-22-backlog-map/{spec.md,tasks.md}` — to be marked superseded.
- Spec template parity: matches the `2026-04-22-backlog-map` shape.

## Top-10 (impact ÷ effort, descending)

| # | Item | Bucket | Score `[I/E/R/C]` | Evidence |
|---|------|--------|-------------------|----------|
| 1 | `@hono/node-server` `serveStatic` mitigation (verify v1.18.x patch or add path-normalization handler) | A.4 | `[high/S/low/high]` | Dependabot alert GHSA-92pp-h63x-v22m, manifest `pnpm-lock.yaml`, severity medium |
| 2 | Sweep dependabot PRs #783–#786 with `update-branch` + thread-resolution recipe | A.1 | `[med/S/low/high]` | `gh pr list --state open` returns all 4 with `BEHIND`/BLOCKED |
| 3 | Cut release tag `v2.6.148` (89 commits / 16 patches behind `v2.6.132`) | A.2 | `[med/S/med/high]` | `git rev-list --count v2.6.132..main` = 89; `package.json:version` = `2.6.148` |
| 4 | Dismiss `uuid` GHSA-w5hq-g745-h8pq alert as not-exploitable | A.5 | `[low/S/low/high]` | `grep -rE "uuid\.(v3\|v5\|v6)" packages/` returns 0 hits; only `v4` used |
| 5 | Worktree sprawl prune (44 → ~5 active) | A.3 | `[med/S/low/high]` | `git worktree list` = 44 entries |
| 6 | `BRANDING_GUIDE.md` dual-accent update (carry-over from 2026-04-22 B.1) | B.7 | `[med/S/low/high]` | ADR `docs/decisions/2026-04-21-redesign-port-target.md` (accepted) |
| 7 | Centralize `-Infinity` cross-locale guard in `upsertScoredCandidate` | E.1 | `[med/S/low/high]` | `grep -nE 'rec.score === -Infinity' packages/bot/src/utils/music/` = 3 hits |
| 8 | Split `packages/bot/src/utils/music/queueManipulation.ts` (953 LOC → ≤4 modules) | B.1 | `[high/L/med/high]` | LOC inventory; high recent churn |
| 9 | Start autoplay diversity (promote `docs/specs/2026-04-15-autoplay-diversity/` to in-progress) | B.6 | `[high/L/med/med]` | Spec exists 10 days, no implementation branch |
| 10 | Split `packages/bot/src/functions/music/commands/autoplay.ts` (1,074 LOC) | B.4 | `[med/M/low/high]` | LOC inventory; not in prior backlogs |

## Unblocks

```
A.1 ─▶ A.4 (hono family bumps include node-server in #785/#786)
A.2 ─▶ I.3 (release notes + top.gg credibility)
E.1 ─▶ B.1 (centralized veto removes one concern from the split review)
B.1 ─▶ B.4 (clear API for autoplay command surface to flatten against)
```
Comment on lines +29 to +34

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add language specifier to the fenced code block.

The Unblocks dependency graph is missing a language specifier. Add text or plaintext to satisfy markdownlint and improve rendering consistency.

📝 Proposed fix
-```
+```text
 A.1 ─▶ A.4 (hono family bumps include node-server in `#785/`#786)
 A.2 ─▶ I.3 (release notes + top.gg credibility)
 E.1 ─▶ B.1 (centralized veto removes one concern from the split review)
 B.1 ─▶ B.4 (clear API for autoplay command surface to flatten against)

</details>

<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion

🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 29-29: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/specs/2026-04-25-backlog-map/spec.md` around lines 29 - 34, The fenced
code block containing the Unblocks dependency graph (the block whose first line
is "A.1 ─▶ A.4 (hono family bumps include node-server in `#785/`#786)" and
subsequent lines A.2, E.1, B.1) is missing a language specifier; update the
opening backticks to include a language such as text or plaintext (e.g., change
``` to ```text) so markdownlint passes and rendering is consistent.


## Out-of-spec

- `H.` major migrations — `pnpm outdated` not pulled; major-stuck inventory is stale.
- `F.1`/`F.2`/`F.3` — measurement work; instrument before optimizing.

## Re-evaluation trigger

- Next regular cadence: **2026-05-09** (≈ 2 weeks).
- Out-of-band trigger: a new dependabot HIGH-severity alert, a release-blocker, or release tag drift > 100 commits.

See `.claude/plans/backlog-2026-04-25.md` for the full per-bucket evidence and the longer tail (B.2/B.3/B.5, D.*, F.*, I.*, J.*).
38 changes: 38 additions & 0 deletions docs/specs/2026-04-25-backlog-map/tasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Tasks — Backlog Map 2026-04-25

Tracks the Top-10 items from `spec.md`. Update statuses as PRs land.

## Open

- [ ] **A.4** Verify `@hono/node-server` v1.18.x is patched for GHSA-92pp-h63x-v22m or add path-normalization pre-handler in `packages/backend/src/server.ts`. Owner: TBD.
- [ ] **A.1** Sweep dependabot PRs:
- [ ] #783 trufflehog SHA bump
- [ ] #784 pnpm/action-setup 4 → 6
- [ ] #785 dev-dependencies group (8 updates)
- [ ] #786 production-dependencies group (17 updates)
- [ ] **A.2** Cut release tag `v2.6.148` (needs user approval).
- [ ] **A.5** Dismiss Dependabot alert for `uuid` GHSA-w5hq-g745-h8pq as not-exploitable here (only `v4` used).
- [ ] **A.3** Run `commit-commands:clean_gone` skill + manual audit of `.claude/worktrees/agent-*` locked entries.
- [ ] **B.7** Update `packages/frontend/branding/BRANDING_GUIDE.md` to dual-accent (Discord blurple + neon pink) per accepted ADR.
- [ ] **E.1** Move `-Infinity` early-return into `upsertScoredCandidate` in `packages/bot/src/utils/music/queueManipulation.ts`; remove the 3 in-place guards.
- [ ] **B.1** Split `queueManipulation.ts` into ≤4 modules along the existing `replenish` / shuffle / move / rescue boundaries.
- [ ] **B.6** Open implementation branch for `docs/specs/2026-04-15-autoplay-diversity/`.
- [ ] **B.4** Split `packages/bot/src/functions/music/commands/autoplay.ts` per subcommand.

## Done since 2026-04-22 backlog (carryover)

- [x] **#780** Phase 1 — hard-reject Spanish autoplay drift (`70c30997`).
- [x] **#782** Phase 2 — tag-driven autoplay scoring (`610423d0`). Dropped 240 LOC dedup from `queueManipulation.ts` (1,193 → 953).
- [x] Dismissal-via-API + `resolveReviewThread` recipe captured as `feedback_pr_blocked_thread_resolution.md`.
- [x] PR-retarget CI re-trigger captured as `feedback_pr_retarget_no_ci.md`.

## Notes

- `pnpm outdated` could not be run cleanly (root invocation deferred; lockfile gap from #766 cleanup); revisit before next /plan run.
- The two `validateBody` skipped tests from prior backlog are gone (covered by #769 + later cleanup).
- 0 open issues, 0 failing CI runs in last 14 days.

## Supersedes

- `docs/specs/2026-04-22-backlog-map/spec.md`
- `docs/specs/2026-04-22-backlog-map/tasks.md`
173 changes: 173 additions & 0 deletions docs/specs/2026-05-04-backlog-map/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
# Top-10 Priority Items — 2026-05-04 Backlog Map

**Generated:** 2026-05-04
**Source:** `.claude/plans/backlog-2026-05-04.md`
**Taxonomy:** Evidence-based backlog with impact/effort scoring

---

## Executive Summary

Top 10 priority items ranked by **impact/effort ratio** and **blocker status**. All items are either blocking downstream work, pose security risk, or represent concentrated tech debt.

---

## Priority Ranking

### 1. **A1: Merge PR #801 (Admin Panel)**
- **Status:** In review (UI + backend complete, E4 testing gap flagged)
- **Impact:** P0 — Unblocks self-serve guild settings, removes manual admin burden
- **Effort:** Low (code complete, test + review cycle)
- **Blocker:** YES — Frontend, self-serve, docs all awaiting merge
- **Next Action:** Add admin panel UI tests (E4), re-request review
- **Owner:** Feature team

### 2. **C1: Upgrade @hono/node-server to 0.4.0+**
- **Status:** Open dependabot alert (5 total: this + file-type, uuid, fast-xml-parser, swiftdiscord)
- **Impact:** P1 — CVE-2024-50334, security patch required
- **Effort:** Low (routine upgrade, verify CI)
- **Blocker:** YES — Security, must ship before next release tag
- **Evidence:** Identified in npm audit, Backend uses @hono/node-server
- **Next Action:** Merge dependabot PR or manual bump + test

### 3. **B1: Modularize queueManipulation.ts (953 LOC)**
- **Status:** 40% churn over 30 days, concentrated hotspot
- **Impact:** High — Reduces defect density, improves maintenance velocity
- **Effort:** Medium (3-4 files, refactor 400 LOC each)
- **Blocker:** Soft — Not blocking features, but blocks future music queue PRs from being reviewed efficiently
- **Modularization:**
- `candidateSelection.ts` — candidate filtering, genre/tag scoring
- `queueOrchestration.ts` — queue sequencing, state transitions
- `queueEditOps.ts` — splice, remove, clear, duplicate ops
- **Next Action:** Plan refactor in sprint, execute as P1 chore
- **Owner:** Backend team

### 4. **F1: Add Admin Panel UI Tests (E4)**
- **Status:** Soft blocker for PR #801 merge
- **Impact:** High — Ensures admin panel UX stability, reduces regression risk
- **Effort:** Low to Medium (E2E or Jest snapshots for settings, presets, table components)
- **Blocker:** YES (soft) — PR #801 review waiting on test coverage
- **Next Action:** Implement E2E or Jest tests for admin panel CRUD flows, add to pre-merge checklist
- **Owner:** QA / frontend team

### 5. **C2: Audit file-type Usage (MusicAnalysisService, GuildMusicService)**
- **Status:** Dependabot alert on user-input surface
- **Impact:** Medium — Potential input validation gap, music file parsing
- **Effort:** Low (1 audit session, ~2 files)
- **Blocker:** No — Non-blocking but P2 security hygiene
- **Next Action:** Verify file-type is only used on validated inputs; document findings
- **Owner:** Security / backend team

### 6. **B2: Refactor autoplay.ts (1,074 LOC)**
- **Status:** Largest single-file implementation, all autoplay subcommands co-located
- **Impact:** High — Improves readability, enables parallel feature development
- **Effort:** Medium (3-4 files, ~400 LOC each)
- **Blocker:** Soft — Blocks efficient review of autoplay feature PRs
- **Modularization:**
- `autoplaySettings.ts` — enable/disable/config subcommands
- `autoplayDiversity.ts` — genre/artist/tag diversity controls
- `autoplaySeeding.ts` — seed, reset, preview subcommands
- **Next Action:** Plan post-PR#801, target next sprint
- **Owner:** Backend team

### 7. **G3: Refresh docs/roadmap.md**
- **Status:** 17 commits behind main, last regenerated 2026-04-15
- **Impact:** Medium — Reduces stakeholder confusion, aligns with actual state
- **Effort:** Low (1 session, ~2 hours)
- **Blocker:** No — Non-blocking but high stakeholder value
- **Content to Add:**
- v2.8.0 release notes
- PR #801 admin panel status
- Phase 3 Stripe premium deferral rationale
- Updated timeline for Phase 2 completion (music features shipped)
- **Next Action:** Regenerate roadmap after PR #801 merge
- **Owner:** Docs / product team

### 8. **H1: Clean 44 Stale Git Worktrees**
- **Status:** Identified via git worktree list; most branches merged >2 weeks ago
- **Impact:** Low — Improves disk space, CI cache clarity, cognitive load
- **Effort:** Low (parallel cleanup via git worktree remove, ~2 hours)
- **Blocker:** No — Nice-to-have housekeeping
- **Cleanup Pattern:**
```bash
git worktree list | grep -E 'prunable|detached' | awk '{print $1}' | xargs -I {} git worktree remove {}
```
- **Next Action:** Schedule as P3 chore, execute mid-sprint
- **Owner:** DevOps / infra team

### 9. **B3: Audit playerFactory.ts (180 LOC, Known Hotspot)**
- **Status:** Known contributor to silence/now-playing bugs (per MEMORY.md)
- **Impact:** Medium — Reduces Discord-player bridge defects
- **Effort:** Low to Medium (audit + fix, ~1 session)
- **Blocker:** Soft — Non-blocking but high defect surface
- **Known Issues:**
- `resetMocks: true` in Jest can wipe factory-time async impls
- Silence/now-playing bugs often originate here (Sentry dedup)
- **Next Action:** Review error logs, trace silence/now-playing paths, add guards
- **Owner:** Backend team

### 10. **E4: Add Admin Panel UI Test Coverage**
- **Status:** Same as F1 (soft blocker for PR #801)
- **Impact:** High — PR #801 review gate
- **Effort:** Low to Medium
- **Blocker:** YES (soft)
- **Test Scope:**
- Settings CRUD (enable/disable, config updates)
- Presets table (pagination, sorting, filtering)
- Error states (network failures, permission denied)
- **Next Action:** Implement before PR #801 merge
- **Owner:** QA / frontend team

---

## Deduplication vs. Prior Backlog (2026-04-25)

Only **3 items flagged status changes** from prior backlog:

1. **A3 (Release v2.8.0)** — ✅ SHIPPED (tag exists, root package.json synced)
2. **A4 (Dependabot alert count)** — Updated from 3 to 5 alerts (new: uuid, swiftdiscord)
3. **PR #801 (Admin Panel)** — Escalated from P1 to **P0 blocker** (in review, unblocks self-serve guild settings)

All other items carry forward from prior backlog with no status drift.

---

## Implementation Timeline

### Immediate (This Week)
- **A1:** Merge PR #801 + add E4 tests
- **C1:** Upgrade @hono/node-server
- **C2:** Audit file-type surfaces

### Next Sprint (1–2 weeks)
- **B1:** Begin queueManipulation.ts modularization
- **F1 / E4:** Complete admin panel test coverage
- **G3:** Regenerate roadmap

### Backlog (2–4 weeks)
- **B2:** Refactor autoplay.ts
- **B3:** Audit playerFactory.ts
- **H1:** Clean stale worktrees

---

## Evidence Sources

- **Git log:** 44 commits analyzed, 44 stale worktrees identified, 3 status changes
- **Dependabot alerts:** 5 open (npm audit, CI logs)
- **Source hotspots:** 6 files >800 LOC, 40% churn on queueManipulation.ts
- **PR status:** GitHub API, PR #801 in review, 0 open issues
- **Documentation:** docs/roadmap.md 17 commits behind, docs/specs/ directory audit
- **Release workflow:** GitHub Actions, tag-driven versioning, v2.8.0 release notes

---

## Notes

This prioritization reflects **impact/effort ratio** and **blocker status**. Items marked "Soft blocker" are high-value but non-critical; schedule them around immediate wins.

See `.claude/plans/backlog-2026-05-04.md` for full taxonomy (A–J), detailed evidence table, and deduplication context.

**Owner:** Lucky backlog team
**Last Updated:** 2026-05-04
**Review Cadence:** Weekly (after PR #801 merge, reassess Phase 3 scope)
17 changes: 16 additions & 1 deletion packages/bot/src/functions/music/commands/artist.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,24 @@
}

const artistLower = artistName.toLowerCase()
const byArtist = searchResult.tracks.filter((t) =>
// Prefer exact match, then word-boundary match, then substring match.
// This prevents "Prince" from routing to "Prince Royce".
const exactMatch = searchResult.tracks.filter(
(t) => t.author.toLowerCase() === artistLower,
)
const wordMatch = searchResult.tracks.filter((t) => {
const words = t.author.toLowerCase().split(/[\s,&/]+/)
return words.some((w) => w === artistLower)

Check warning on line 128 in packages/bot/src/functions/music/commands/artist.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use `.includes()` instead of `.some()` when checking value existence.

See more on https://sonarcloud.io/project/issues?id=LucasSantana-Dev_Lucky&issues=AZ35Kxt_q8qvliYxcavr&open=AZ35Kxt_q8qvliYxcavr&pullRequest=805
})
const substringMatch = searchResult.tracks.filter((t) =>
t.author.toLowerCase().includes(artistLower),
)
const byArtist =
exactMatch.length >= 3
? exactMatch
: wordMatch.length >= 3
? wordMatch
: substringMatch

Check warning on line 138 in packages/bot/src/functions/music/commands/artist.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Extract this nested ternary operation into an independent statement.

See more on https://sonarcloud.io/project/issues?id=LucasSantana-Dev_Lucky&issues=AZ35Kxt_q8qvliYxcavs&open=AZ35Kxt_q8qvliYxcavs&pullRequest=805
Comment on lines +126 to +138

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

wordMatch does not exclude "Prince Royce" when querying "Prince" — the tier-2 fallback preserves the original problem

When exactMatch.length < 3 and the code falls through to wordMatch, the word-boundary split for query "prince" matches both "Prince" (→ ["prince"]) and "Prince Royce" (→ ["prince", "royce"]), since "prince" is a word token in both author names. The stated fix — "prevents Prince from routing to Prince Royce" — is only guaranteed by the exactMatch branch. The wordMatch branch silently reintroduces the same issue whenever the exact artist has fewer than 3 indexed tracks.

A safer fallback would be to use the exact matches (however few) before broadening to wordMatch, or to combine exact + word results rather than discarding exact matches the moment they fall below the threshold:

🔧 Suggested fix: preserve exact matches when below threshold
-            const byArtist =
-                exactMatch.length >= 3
-                    ? exactMatch
-                    : wordMatch.length >= 3
-                      ? wordMatch
-                      : substringMatch
+            // Use the most-specific tier that yields results; prefer smaller
+            // exact/word sets over a larger, potentially wrong substring set.
+            const byArtist =
+                exactMatch.length >= 3
+                    ? exactMatch
+                    : exactMatch.length > 0
+                      ? exactMatch               // trust the few exact hits we have
+                      : wordMatch.length >= 3
+                        ? wordMatch
+                        : substringMatch
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/bot/src/functions/music/commands/artist.ts` around lines 126 - 138,
The fallback logic for byArtist currently drops exactMatch when
exactMatch.length < 3 and uses wordMatch, which still includes authors like
"Prince Royce" for query "Prince"; update the selection to preserve exactMatch
results and only supplement them from wordMatch/substringMatch until you reach
the desired count: e.g., start with exactMatch, then append unique tracks from
wordMatch (deduplicating by a stable key such as t.id or
`${t.title}|${t.author}`) until you have 3, and only then fall back to
substringMatch to fill any remaining slots; adjust references in this code block
(exactMatch, wordMatch, substringMatch, byArtist, searchResult.tracks, t.author,
artistLower) accordingly so exact matches are never discarded.

const tracks = (
byArtist.length >= 3 ? byArtist : searchResult.tracks
).slice(0, limit)
Expand Down
Loading
Loading