From 121108f63c709728e63b4d5b2dfbc5b30dd40c4e Mon Sep 17 00:00:00 2001 From: joungmin Date: Mon, 15 Jun 2026 13:22:34 +0900 Subject: [PATCH] =?UTF-8?q?[07-Release]=20#311=20v0.4.1=20=E2=80=94=20Chat?= =?UTF-8?q?Screen=20LLM=20warm-up?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CHANGELOG 0.4.1 항목 + pubspec 0.4.0+4 → 0.4.1+5. Release artifact: - app-release.apk 288MB (301.0MB raw / 288MB on-disk) - SHA-256: 62b96a876afbda24e1cd3b9bf95db742255db5f40fc46eb08cb5cf824d3ec481 - Build: flutter build apk --release (Gradle assembleRelease 70.2s) KGP deprecation 경고 (device_info_plus, flutter_gemma, large_file_handler) 는 v0.4.0 release 노트와 동일. 미해결. Refs #311 --- CHANGELOG.md | 31 +++++++++++++++++++++++++++++++ app/pubspec.yaml | 2 +- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 844bc07..9332c5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,37 @@ 본 프로젝트의 모든 의미있는 변경은 본 파일에 기록한다. 형식: [Keep a Changelog](https://keepachangelog.com/) · 버전: [SemVer](https://semver.org/). +## [0.4.1] — 2026-06-15 + +### Added — ChatScreen LLM warm-up (Redmine #311, follow-up of #260) +- **백그라운드 warm-up** — `ChatScreen` 진입 시 `ChatWarmupController` 가 `LlmService.load()` 를 백그라운드로 트리거. 첫 send 에서 cold native-init (수 초) 비용 제거. +- **`ModelLifecycle.quickCheck()`** (신규) — SHA-256 재해싱 없이 meta_kv + 파일 존재만으로 ready 추정. ~2.4GB Gemma 4 E2B 파일에 대한 매 mount 마다의 hash 비용 회피. +- **Concurrent load guard** — `GemmaLlmService.load()` + `MockLlmService.load()` 에 `_loadingFuture` 가드 추가. ChatScreen warm-up + 동시 `userTurn` lazy load 가 race 해도 native init 1회만 실행. +- **Sealed state machine** — `ChatWarmupState`: Idle / Loading / Ready / Failed(kind) / Unavailable. autoDispose StateNotifier + `_disposed` 가드로 unmount race 방지. + +### UX (Designer + Reviewer) +- warmup 중 입력창 `enabled` 유지 — 사용자가 미리 메시지 작성 가능 (UX R1+R2). +- send 자리에 `CircularProgressIndicator(strokeWidth: 2)` — `isStreaming` 패턴과 일관. +- hintText 교체 — warmup: `AI 준비 중… 첫 시작은 몇 초 걸려요` / 평상: `습관 추가, 기록, 카탈로그 질문…`. +- 실패 메시지는 상태 기술만 (UX R5/AC12) — `AI 모델 파일을 찾을 수 없어요.` / `AI 를 시작하지 못했어요.`. 행동은 버튼이 담당. +- `_WarmupErrorBanner` 가 `kind` 분기: + - `fileMissing` → **[설정으로 가기]** + `SettingsScreen` push + pop 후 자동 `retry()` (UX R5/R6). + - `runtime` → **[다시 시도]** + 즉시 `retry()`. +- `isLoaded=true` 재진입 시 Loading state skip — 1 frame 라벨 깜빡임 방지 (UX R4/AC11). + +### Added — Tests +- 167/167 passed (1 pre-existing skip) — 신규 12 (`chat_warmup_test.dart` 8 + `model_lifecycle_test.dart` quickCheck 4). +- AC1~AC2, AC5~AC7, AC11, AC12 controller-level 검증. +- AC3/AC4/AC8/AC9/AC10 widget E2E 는 deferred — `CircularProgressIndicator` 무한 ticker + `Future.delayed` ↔ `pumpAndSettle` race. `chat_screen_test.dart` NOTE comment 에 사유 명시. + +### Docs +- 설계서 `docs/design/311-llm-warmup/` (4 파일) — README + 2 fn-spec + UX-REVIEW.md. +- 신규 페르소나 `ux-reviewer.md` — 02-Architect 단계의 parallel review. + +### Known follow-ups (후속 이슈 권장) +- Widget E2E 인프라 개선 (FakeAsync 또는 spinner 가짜 대체) — ticker race 해소. +- 다른 recovery loop 도 `Navigator.push().then((_) => retry())` 패턴 적용 검토. + ## [0.4.0] — 2026-06-15 ### Added — Phase 2-B in-app tool calling (Redmine #260) diff --git a/app/pubspec.yaml b/app/pubspec.yaml index 4eefaf8..06de7ed 100644 --- a/app/pubspec.yaml +++ b/app/pubspec.yaml @@ -1,7 +1,7 @@ name: life_helper description: "Huberman + Atomic Habits + Tiny Habits + If-Then. Local-first habit/checklist/todo." publish_to: 'none' -version: 0.4.0+4 +version: 0.4.1+5 environment: sdk: ^3.12.2