diff --git a/.jules/bolt.md b/.jules/bolt.md
index 38d4b732..d9841ed7 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.
+
+## 2023-07-05 - Avoid intermediate array iteration and apply early breaks for minimum search
+**Learning:** `song?.sections.reduce(...)` causes unconditional O(N) operations and `Array.from({ length: X }).map(...)` creates intermediate arrays of `undefined` values, reducing React rendering performance.
+**Action:** Replace `reduce` with a `for...of` loop with an early `break` when searching for absolute bounds (like a low confidence level), and use the built-in mapping argument `Array.from({ length: X }, ...)` to avoid allocating intermediate arrays.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 071a641d..65f8a866 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+## [0.1.4] - 2023-07-05
+### 성능 (Performance)
+- React 컴포넌트(`App.tsx`, `Workspace.tsx`)에서 `Array.from` 매핑 시 중간 배열이 생성되지 않도록 built-in 인자를 활용하여 최적화
+- `ConfidenceMetric` 컴포넌트 내 `reduce`를 이용한 최솟값 탐색 시 `low` confidence를 찾으면 바로 조기 종료(early break)하도록 개선하여 O(N) 연산을 최적화
+
# Changelog
## [Unreleased]
diff --git a/apps/desktop/src/App.test.tsx b/apps/desktop/src/App.test.tsx
index c039dfba..6dec742d 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("short-circuits confidence summarization when encountering a low-confidence section", async () => {
+ const loadedProject = succeededResult().result;
+ loadedProject.sections.push(
+ {
+ ...loadedProject.sections[0],
+ id: "verse-2",
+ label: "verse",
+ confidence: { level: "low", source: "model", notes: "Hard to hear." }
+ },
+ {
+ ...loadedProject.sections[0],
+ id: "chorus-2",
+ label: "chorus",
+ confidence: { level: "high", source: "model", notes: "Very clear." }
+ }
+ );
+ mockLoadProject.mockResolvedValueOnce(loadedProject);
+ render(