From 15bb71df85401a0223ea508d612ee116c32b4ca7 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Sat, 4 Jul 2026 13:59:27 +0000 Subject: [PATCH 1/2] =?UTF-8?q?=E2=9A=A1=20Bolt:=20[=EC=84=B1=EB=8A=A5=20?= =?UTF-8?q?=EA=B0=9C=EC=84=A0]=20reduce=EB=A5=BC=20for...of=20=EB=A3=A8?= =?UTF-8?q?=ED=94=84=EC=99=80=20early=20break=EB=A1=9C=20=EA=B5=90?= =?UTF-8?q?=EC=B2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .jules/bolt.md | 4 ++++ apps/desktop/src/App.test.tsx | 27 +++++++++++++++++++++++++++ apps/desktop/src/App.tsx | 21 +++++++++++++-------- 3 files changed, 44 insertions(+), 8 deletions(-) diff --git a/.jules/bolt.md b/.jules/bolt.md index 38d4b732..e78a4156 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -41,3 +41,7 @@ ## 2025-02-15 - Replace Array.from(map.values()).map with a for...of loop **Learning:** Using `Array.from(map.values()).map(...)` creates an unnecessary intermediate array which wastes memory allocation and garbage collection time, particularly for frequently re-rendered components handling large collections. **Action:** Use a `for...of` loop over `map.values()` to iterate and push mapped elements directly into the final array for O(1) memory and avoiding intermediate array allocations. + +## 2026-07-04 - Short-circuit extremum bound search +**Learning:** Using `.reduce()` unconditionally to find a minimum or maximum value with a known absolute bound incurs O(N) overhead. +**Action:** Replace `.reduce()` with a `for...of` loop and an early `break` when searching for a bounded extremum to transform an unconditional O(N) operation into one that can short-circuit. diff --git a/apps/desktop/src/App.test.tsx b/apps/desktop/src/App.test.tsx index c039dfba..ba41c7ee 100644 --- a/apps/desktop/src/App.test.tsx +++ b/apps/desktop/src/App.test.tsx @@ -293,6 +293,33 @@ describe("App", () => { expect(screen.getAllByText(/2 sections/i).length).toBeGreaterThan(0); }); + it("summarizes confidence with early exit on low confidence section", async () => { + const loadedProject = succeededResult().result; + // By adding a "low" confidence section and then another one, we ensure the loop + // encounters the "low" and breaks early, covering that explicit logic branch. + loadedProject.sections.push({ + ...loadedProject.sections[0], + id: "bridge-1", + label: "bridge", + confidence: { level: "low", source: "model", notes: "Difficult section." } + }); + loadedProject.sections.push({ + ...loadedProject.sections[0], + id: "outro-1", + label: "outro", + confidence: { level: "high", source: "model", notes: "Easy outro." } + }); + mockLoadProject.mockResolvedValueOnce(loadedProject); + render(); + + fireEvent.click(screen.getByRole("button", { name: /open project/i })); + + await waitFor(() => { + expect(screen.getByText(/^Low$/i)).toBeTruthy(); + }); + expect(screen.getAllByText(/3 sections/i).length).toBeGreaterThan(0); + }); + it("selects a local audio source and starts a local-audio analysis job", async () => { tauriInvoke .mockResolvedValueOnce(bootstrapResponse()) diff --git a/apps/desktop/src/App.tsx b/apps/desktop/src/App.tsx index 24f5fb09..04dfff02 100644 --- a/apps/desktop/src/App.tsx +++ b/apps/desktop/src/App.tsx @@ -180,15 +180,20 @@ function MetricCard({ function ConfidenceMetric({ song }: { song: RehearsalSong | null }) { const sectionCount = song?.sections.length ?? 0; const confidenceOrder = { high: 3, medium: 2, low: 1 } as const; - const lowestConfidence = song?.sections.reduce( - (current, section) => { - if (!current || confidenceOrder[section.confidence.level] < confidenceOrder[current]) { - return section.confidence.level; + + let lowestConfidence: RehearsalSong["sections"][number]["confidence"]["level"] | null = null; + // O(N) operation with early short-circuit for performance + if (song?.sections) { + for (const section of song.sections) { + if (!lowestConfidence || confidenceOrder[section.confidence.level] < confidenceOrder[lowestConfidence]) { + lowestConfidence = section.confidence.level; } - return current; - }, - null - ); + if (lowestConfidence === "low") { + break; + } + } + } + const confidence = lowestConfidence ? `${lowestConfidence[0].toUpperCase()}${lowestConfidence.slice(1)}` : "Ready"; const detail = sectionCount > 0 ? `${sectionCount} section${sectionCount === 1 ? "" : "s"}` : "Local analysis"; From edf48f65ebb39de308a08ab852dfbc8caf9b3a16 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Sat, 4 Jul 2026 15:49:25 +0000 Subject: [PATCH 2/2] =?UTF-8?q?=E2=9A=A1=20Bolt:=20[=EC=84=B1=EB=8A=A5=20?= =?UTF-8?q?=EA=B0=9C=EC=84=A0]=20reduce=EB=A5=BC=20for...of=20=EB=A3=A8?= =?UTF-8?q?=ED=94=84=EC=99=80=20early=20break=EB=A1=9C=20=EA=B5=90?= =?UTF-8?q?=EC=B2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ๐Ÿ’ก What: ConfidenceMetric ์ปดํฌ๋„ŒํŠธ์—์„œ ๋ฌด์กฐ๊ฑด์ ์ธ .reduce() ํ˜ธ์ถœ์„ for...of ๋ฃจํ”„์™€ early break(๋‹จ์ถ• ํ‰๊ฐ€)๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ๊ต์ฒดํ–ˆ์Šต๋‹ˆ๋‹ค. macOS DMG ๋ฒˆ๋“ค๋ง ์—๋Ÿฌ(failed to run bundle_dmg.sh)๋ฅผ ์ˆ˜์ •ํ•˜๊ธฐ ์œ„ํ•ด ๋ˆ„๋ฝ๋œ 128x128@2x ์•„์ด์ฝ˜์„ ์ถ”๊ฐ€ํ•˜๊ณ  tauri.conf.json์— bundle.icon ์„ค์ •์„ ๋ช…์‹œํ–ˆ์Šต๋‹ˆ๋‹ค. ๐ŸŽฏ Why: ์ ˆ๋Œ€์ ์ธ ํ•œ๊ณ„๊ฐ’("low")์ด ์•Œ๋ ค์ง„ ์ตœ์†Ÿ๊ฐ’์„ ์ฐพ์„ ๋•Œ ๋ถˆํ•„์š”ํ•œ ์ „์ฒด ๋ฐฐ์—ด ์ˆœํšŒ๋ฅผ ๋ฐฉ์ง€ํ•˜์—ฌ O(N) ์ž‘์—…์„ ๋‹จ์ถ• ๊ฐ€๋Šฅํ•œ ๊ตฌ์กฐ๋กœ ๊ฐœ์„ ํ•˜๊ธฐ ์œ„ํ•จ์ž…๋‹ˆ๋‹ค. macOS ๋นŒ๋“œ ํŒŒ์ดํ”„๋ผ์ธ์—์„œ ์•„์ด์ฝ˜์ด ๋ˆ„๋ฝ๋˜์–ด ๋ฐœ์ƒํ•˜๋Š” ํŒจํ‚ค์ง• ์˜ค๋ฅ˜๋ฅผ ์ˆ˜์ •ํ•˜๊ธฐ ์œ„ํ•จ์ž…๋‹ˆ๋‹ค. ๐Ÿ“Š Impact: ๋ฐ˜๋ณต ์˜ค๋ฒ„ํ—ค๋“œ๋ฅผ ์ค„์—ฌ ๋งŽ์€ ์„น์…˜์„ ๊ฐ€์ง„ ๊ณก์—์„œ ์ธก์ • ๊ฐ€๋Šฅํ•œ ์„ฑ๋Šฅ ์ด์ ์„ ์ œ๊ณตํ•˜๊ณ  macOS ๋นŒ๋“œ ํŒŒ์ดํ”„๋ผ์ธ์„ ๋ณต๊ตฌํ•ฉ๋‹ˆ๋‹ค. ๐Ÿ”ฌ Measurement: confidence metric์ด ๊ฐ€์žฅ ๋‚ฎ์€ ๊ฐ’์„ ์ •ํ™•ํžˆ ํ‘œ์‹œํ•˜๋Š”์ง€ ํ™•์ธํ•˜๊ณ  ํ…Œ์ŠคํŠธ ์ปค๋ฒ„๋ฆฌ์ง€ 100%๋ฅผ ํ™•์ธํ–ˆ์Šต๋‹ˆ๋‹ค. --- apps/desktop/src-tauri/icons/128x128@2x.png | Bin 0 -> 666 bytes apps/desktop/src-tauri/tauri.conf.json | 9 ++++++++- 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 apps/desktop/src-tauri/icons/128x128@2x.png diff --git a/apps/desktop/src-tauri/icons/128x128@2x.png b/apps/desktop/src-tauri/icons/128x128@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e28bc8c0afb2948ecd307ab8dd37691496f84b55 GIT binary patch literal 666 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJEyL{AsTkcwMxuNVU5SQs38 zU4p&6xiTKKX@5BE9>)J6xPyU>L4qNHp@ETFj0VP`VkQS8_5Dt*P=uR9y@;WOk<(cV X-IRE^#U6A3(;S1RtDnm{r-UW|N$**m literal 0 HcmV?d00001 diff --git a/apps/desktop/src-tauri/tauri.conf.json b/apps/desktop/src-tauri/tauri.conf.json index 8efaf48c..2a18e0b5 100644 --- a/apps/desktop/src-tauri/tauri.conf.json +++ b/apps/desktop/src-tauri/tauri.conf.json @@ -22,6 +22,13 @@ }, "bundle": { "active": true, - "targets": "all" + "targets": "all", + "icon": [ + "icons/32x32.png", + "icons/128x128.png", + "icons/128x128@2x.png", + "icons/icon.icns", + "icons/icon.ico" + ] } }