d3ro-voice/CHANGELOG.md
Yun Chan 4b0f685941 feat(caption): let live captions use their own speech model
The speech engine now keeps an auxiliary model next to the dictation model
and transcribes with whichever the request names, reloading it once if the
engine restarted. Settings > STT gains a live-caption model so captions can
run on large-v3-turbo while dictation keeps its own model. The runtime
minimum rises to 1.7.0 because older engines would silently ignore the
model choice.

Suggestion paging moves to Up/Down: the page follows the selection and the
last item waits while more candidates are being generated. The Left/Right
page shortcuts are removed; they did nothing until a page had filled and
clash with Intel's display-rotation hotkeys.
2026-09-24 21:46:54 +09:00

35 KiB
Raw Blame History

Changelog

All notable changes to D3RO Voice will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[Unreleased]

Added

  • Live captions stream as you listen. Words appear about a second after they are spoken and keep updating while the sentence is in progress; the part that is no longer changing is shown solid and the rest dimmed. A pause finishes the line, and long unbroken speech is split at natural boundaries instead of waiting six seconds.
  • Captions are polished in context. Each finished line is corrected by the local model using the lines before it (spacing, punctuation, misheard words); rewrites that change too much are ignored. It can be turned off in Settings.
  • Live captions can use their own speech model. Settings > STT now has a separate live-caption model, loaded next to the dictation model, so captions can run on a faster or more accurate model without changing dictation. The local speech engine is updated for this and is downloaded again once.

Changed

  • Suggestions page with Up/Down only. Moving past the third candidate turns the page by itself, and at the last candidate the selection waits while more are still being generated. The separate Ctrl+Alt+Left/Right page shortcuts are gone; they also collided with the display-rotation shortcut of Intel graphics drivers.

Planned

  • macOS / Linux support
  • Additional Whisper model management UI
  • Cloud-optional backup (encrypted, opt-in)
  • Plugin system for custom pipelines

[1.6.0] - 2026-09-24

Published from an annotated tag. Installer and update metadata are served by the canonical Forgejo feed; no binaries are committed to this repository.

Added

  • Up to 12 next-sentence suggestions, three per page. The first candidate appears as soon as it is ready and the rest are generated one at a time in the background. Ctrl+Alt+Up/Down move between candidates, Ctrl+Alt+Left/Right flip pages, Ctrl+Alt+Enter accepts, and Esc closes the panel while it is showing. Accepting, typing on, or closing stops generation. Existing shortcuts that were still on the 1.5.0 defaults move to this layout automatically; customised ones are kept.
  • A key guide inside the panel built from your current shortcuts, so it follows whatever you rebind.
  • The live caption window can be moved. Hover it to reveal a small handle, drag it anywhere, and it reopens there next time; double-click the handle to return it to the bottom of the screen. The rest of the window still lets clicks through.
  • Live captions say they are getting ready from the moment you start them until the first line arrives, instead of showing an empty screen for several seconds.

Changed

  • The suggestion panel is redesigned: numbered candidates with a clear selection bar, two-line items that no longer break Korean words mid-word, no empty header row, and a two-line footer for progress and keys. The panel stays where it first appeared while candidates stream in, and sits outside the input box when the app cannot report a caret position.
  • The suggestion model stays loaded for 10 minutes and warms up on launch, and on Ollama reconnect, so the first suggestion no longer times out on a cold reload.
  • The personal phrase memory only learns everyday writing. Terminals, code editors and the Agent Switchboard coding hub are excluded, and lines that are mostly symbols or an empty field's placeholder text are ignored. Phrases learned under the old rules that break these rules are removed on the next launch.
  • Suggestions are never offered in terminals.

Fixed

  • Suggestion shortcuts started dictation. The voice service treated every shortcut it did not know as dictation, so the new suggestion keys switched on recording.
  • Suggestions never appeared after updating to 1.5.0 on installs whose local speech engine was downloaded by an earlier version: the old engine lacked the focus-reading endpoint. An engine older than the app requires is now downloaded again automatically.
  • Suggestions were cancelled while typing Korean because the syllable still being composed changed the text; cancelled requests also no longer use up the rate limit.
  • The panel appeared after a mouse click without typing, could not be closed with X while generating, and showed a spinner next to finished candidates.
  • Model runner windows flashed while typing when D3RO had started Ollama itself. It now starts Ollama through Ollama's own tray app.
  • The speech engine could start twice when two parts of the app needed it at the same moment.

[1.5.0] - 2026-09-23

Published from an annotated tag. Installer and update metadata are served by the canonical Forgejo feed; no binaries are committed to this repository.

Added

  • Next-sentence suggestions while you type. With the feature turned on, a small ghost-text panel sits next to the caret in whatever app has focus and offers up to three ways to continue the sentence. Ctrl+Alt+Right accepts, Down/Up move between candidates, Left or the panel's X dismisses, and all four are ordinary rebindable shortcuts. The panel never takes focus and is click-through until you turn interaction on.
  • Typed-text learning from the field you are in, read through UI Automation and diffed as a snapshot, so committed Korean and Japanese IME text is counted correctly (key codes cannot reconstruct it). Password fields are refused before any read, and IME composition suppresses learning and suggestions until the character is committed.
  • Weekly input insights (Settings > Input and a dashboard card): keystroke, click and scroll totals, mouse travel converted to meters, top hours and apps, flow windows, edit friction (edits per 100 characters) and per-app suggestion quality.
  • A personal phrase memory built from your own typed sentences and voice history, ranked by frequency, recency (30-day half-life) and same-app usage, and offered as prompt hints. Phrases can be deleted individually or all at once.
  • A privacy receipt that reports the real number of retained rows and the 30-day retention rule, plus smart exclusion: only the app you are in can be suggested for the exclusion list, and only after repeated unreadable fields, never automatically.
  • A shortcut safety audit in Settings that flags invalid or conflicting bindings across every action.
  • A local personal graph that links your sentences by "follows" and shared-terms relationships, so related context can surface even when the current prefix differs. It is local SQLite only, with no embeddings or network.

Changed

  • Local model requests are now bounded and individually cancellable. LocalLLMService gives every request its own abort controller, relays external cancellation, requires a done frame before a stream counts as successful, and clears incomplete streams. Generation and streaming are capped at 2048 tokens / 120 seconds and chat at 512 / 60 seconds. Text suggestions use keep_alive: 2m and no longer warm the model at startup.
  • Voice conversations are single-flight and pass their cancellation through to the active local chat request, so ending a conversation aborts its own inference instead of only changing what the UI shows.
  • Console windows are suppressed for the app's Windows helper processes (text to speech, voice actions, audio-device and active-window enumeration, and every ffmpeg path).

Fixed

  • Custom instructions ran the instruction instead of your text. Every built-in instruction (translate, summarize, rephrase, explain code, free prompt) inserted the instruction's own wording rather than the processed result, and only {{text}} was ever substituted, which none of the presets use. The instruction is now the system prompt, the transcript is the text, and {{text}}, {{userPrompt}} and {{targetLanguage}} are resolved in one shared place. This path had never worked in any shipped release.
  • The suggestion panel could refuse to close, revive itself, or appear on a bare click. Holding the modifier that Windows turns into Ctrl+Alt no longer fires the voice shortcut underneath, closing the panel during generation discards that request instead of re-showing it, a click without typing no longer triggers a suggestion, and pressing Enter stops the same text from being suggested again.
  • The global input hook is reference-counted, so the shortcut service and input telemetry can attach at the same time without one disabling the other.

[1.4.0] - 2026-09-21

Added

  • Several shortcuts per action. Every action now holds a list of bindings instead of a single one, so a second (or third) shortcut can be added with the + button and removed individually.
  • Mouse buttons as shortcuts. Side buttons (back / forward) can be bound on their own; right and middle click require a modifier. Left click cannot be bound because it drives every on-screen interaction. Mouse events cannot be swallowed, so a bound button still performs its original action — the settings screen says so before the binding is saved.
  • Pick a key from a searchable list. Besides pressing the key, a shortcut can now be chosen from a grouped dropdown with a search box inside it, which also makes keys reachable that are awkward to press while recording.
  • The history and command popups are rebindable. Ctrl+Shift+V and Ctrl+Shift+C were fixed in code and had no settings entry; they are now ordinary actions. The voice command shortcut, which had never been exposed in settings, is visible as well.

Fixed

  • Double-press hands-free never triggered. Dictation and hands-free ship with the same default key and are told apart by the double press, but shortcut lookup stopped at the first match, so hands-free was unreachable in installed builds. Both actions now receive the event and are split by press type.
  • Reserved system shortcuts could be assigned anyway. The check compared joined key names, so pressing the modifiers in a different order let Ctrl+C and friends through. Combinations are now compared structurally.
  • Turning shortcuts off also killed the popup shortcuts permanently. Disabling global shortcuts released every registration in the process, including ones it did not own, and re-enabling never restored them.
  • Enabling shortcuts after starting with them off left nothing bound.
  • Shortcut labels were frozen in the language they were recorded in and did not follow the app language or platform conventions. They are now derived on display.
  • The dashboard caption indicator never reflected the real state because the event payload was stored instead of the state inside it.

Changed

  • Shortcuts are stored as one list per action. Existing shortcuts are migrated automatically on first launch; no reconfiguration is needed.

[1.3.7] - 2026-09-19

Fixed

  • Recording and live caption overlays never worked in installed builds. Popup pages loaded their scripts as classic <script src> tags, which the renderer build does not bundle, so a packaged app rendered only the static markup: the recording tip froze at 0:00 with no wave bars and captions showed nothing. Popup scripts are now module scripts, a packaging check fails when a renderer page references an asset that was never emitted, and popups hold IPC until their renderer is ready and re-assert visibility on every show.

[1.3.6] - 2026-09-18

Fixed

  • Installing the local speech engine always failed with a hash mismatch, leaving local transcription unusable. The downloaded parts were checked against bytes counted from the network stream, while the joined archive was checked against what was actually written to disk, so a truncated write passed part verification and only surfaced later as an archive mismatch with no usable diagnostic. Every check now reads the file on disk, the joined archive is size-checked before hashing, mismatch errors report the actual and expected values, and a failed part is discarded and retried up to three times.

[1.3.5] - 2026-09-18

Fixed

  • The Ollama guide still listed the retired models as its recommendation while the app already defaults to . The guide now leads with the model the app actually uses and lists current lightweight alternatives.

[1.3.4] - 2026-09-18

Fixed

  • Automatic updates could not start on 1.3.3: its installer was missing the updater configuration file, because the packaging path used to guarantee the native module build does not create it. The file is now written from the single feed source and its presence in the packaged app is verified before publishing, so an installer that cannot update is never shipped.

[1.3.3] - 2026-09-18

Fixed

  • The released installer could not start: it carried a better-sqlite3 build for the host Node runtime instead of Electron, so the app failed immediately with a NODE_MODULE_VERSION mismatch when opening its database. Packaging now guarantees and verifies the Electron build of every runtime-sensitive native module before an installer or archive is produced, and publishes only from that verified tree.
  • The local language model default still pointed at a retired model: the stored default was a *.gguf file name that Ollama cannot serve, and the settings, onboarding, and Ollama guide still recommended gemma2:2b while the service code already preferred gemma4:e4b. All surfaces now default to gemma4:e4b.

[1.3.2] - 2026-09-18

Changed

  • Auto-update works again: the installer no longer carries the local speech engine and ffmpeg. Bundling them pushed the installer to 189 MB, and the download feed sits behind Cloudflare, which rejects uploads over ~100 MiB with HTTP 413 — so update metadata could not be published at all. The installer is now 90.5 MiB and the update feed is published again.
  • The app fetches its speech engine and ffmpeg when they are first needed, verifying every part and the joined archive by SHA-256 before installing them under the app data folder. Updates stay small (the engine is not re-downloaded on every release), and the Settings > STT tab shows the runtime status with a manual download action.

[1.3.1] - 2026-09-18

Fixed

  • Manual install no longer needs 7-Zip: the signing-free channel now also publishes the app as byte-split zip parts. The install script joins them and extracts with the built-in Windows Expand-Archive, so a user with nothing but Windows can install (the 7z volumes remain the smaller Scoop path). Split volumes from a different build are never mixed: every artifact of a release comes from one build, and a published version is not overwritten.

[1.3.0] - 2026-09-18

Published from an annotated tag through CI. Installer and update metadata are served by the canonical Forgejo feed; no binaries are committed to this repository.

Added

  • Live partial transcript while dictating: while the hotkey is held, the app now transcribes the recent window of audio every 1.5 seconds and shows it in the recording tip, so the text can be seen forming before the key is released. Partials never reach the clipboard or the result popup; only the final transcription is inserted.
  • Instant first dictation: the local speech engine (sidecar process + Whisper model) is warmed up in the background at app start, so the first press does not wait for the model to load.
  • Packaged local speech engine: desktop installers now ship the faster-whisper sidecar (sidecar.exe plus runtime data, including the Silero VAD model) and ffmpeg, so local transcription works on a fresh install without Python on the machine.
  • Sidecar build tooling: npm --prefix apps/desktop run sidecar:setup and sidecar:build, plus a packaging-time bundle verifier that fails the build when the engine or its VAD data is missing.

Added

  • Signing-free install path (portable channel): the canonical feed sits behind Cloudflare, which rejects any upload body over ~100 MiB with HTTP 413 (measured: 60 MiB accepted, 110 MiB rejected). The sidecar-carrying app exceeds that, so releases are now also published as 95 MiB 7z split volumes (688 MB app → 162 MiB) with a Scoop bucket manifest and a verifiable manual installer script. This channel never touches the auto-update feed and needs no Authenticode certificate, so users can install while the signing certificate is still being procured.

Changed

  • Local engine connections now target the IPv4 loopback (127.0.0.1) instead of localhost. On machines where localhost resolves only to IPv6, every local request (Ollama and the speech sidecar) was refused and local AI silently did nothing.
  • Whisper decoding is tuned for dictation: previous-text conditioning is disabled so repeated hallucinations cannot compound, silence is trimmed more aggressively, and low-confidence fallbacks are bounded. Same transcript quality, roughly five times faster on the same machine.
  • The sidecar reuses an already-loaded model instead of reloading it, and reports the load time it measured.
  • Local engine logs stream to the app log as complete UTF-8 lines instead of mangled fragments, so failures are diagnosable.
  • Failed local-engine startup now fails immediately with an actionable message (missing bundled engine, damaged virtualenv, or missing SoX) instead of waiting for a 30 second health check and reporting a generic error.

Fixed

  • Local transcription never worked in packaged builds: the sidecar was not part of the packaged resources and no pipeline step built it, so the app always fell back to a system Python that had no faster-whisper installed.
  • Local transcription and local LLM never worked in development: the sidecar and SoX paths were resolved against the Vite output directory (out/main) instead of the app root, so recording failed with a SoX ENOENT and the sidecar fell back to a Python without the runtime dependencies.
  • Silero VAD data was missing from the bundled engine, which would have made silence-trimmed transcription fail at runtime even with the engine bundled.
  • Audio capture and the speech sidecar no longer flash a console window on Windows, and SoX/spawn failures name the fix (npm --prefix apps/desktop run setup:sox).

[1.2.0] - 2026-09-16

Published from an annotated tag through CI. Installer and update metadata are served by the canonical Forgejo feed; no binaries are committed to this repository.

Added

  • Canonical desktop release channel: desktop auto-update now reads one Forgejo Generic Package Registry feed, published by a version-agnostic publisher (scripts/ci/publish-forgejo-release.mjs) from tag-triggered Forgejo Actions, GitLab, and GitHub pipelines. The GitLab registry stays a legacy mirror for pre-Forgejo installs.
  • Update policy SSOT (release/update-policy.json): channels (latest/beta/alpha), minimum supported version, forced install, full-installer thresholds, staged rollout percentage, and a remote kill switch, enforced at runtime by apps/desktop/src/main/update-policy.ts.
  • Dictionary import/export on desktop and web: round-trip import with per-entry conflict reporting, a web dictionary client, and an expanded knowledge add form.
  • Multi-transport push delivery: Web Push (VAPID) and token-based Apple Push (APNs) transports join Firebase Cloud Messaging, with a Cloudflare Worker cron drain over an outbox table.
  • Team activity feed: team activity events, migration, and the web feed component.
  • Shared entitlement gating in @d3ro/core for free/paid feature boundaries.
  • Infrastructure map (docs/map/) documenting the infrastructure and feature status per platform, with an update protocol so feature work and the map stay in step.
  • 21 unit tests for update policy decisions and feed helpers, plus tests for dictionary I/O, entitlements, push drain, Web Push, and APNs payloads.

Changed

  • Desktop runtime updater feed moved from GitLab project 1172 to the canonical Forgejo registry; electron-builder.yml, the metadata verifier, and both CI publishers now enforce the canonical/mirror split.
  • Release metadata verifier self-test expanded to negative cases covering the feed contract, policy schema, and Forgejo publisher invariants.
  • The canonical publisher refuses to re-publish a version whose registry assets already hold different bytes, so a same-version re-release fails closed instead of overwriting a shipped installer.
  • Landing site and web console download centers now link the canonical Forgejo feed instead of repository-local installer paths, which are not part of any deploy artifact.
  • Admin console data views (models, pipelines, users, subscriptions, audit log) read live back-office data, with a unified sidebar and console theme.
  • Desktop settings, ad surfaces, license, and meeting-export UI aligned on the shared theme tokens; meeting export filenames now go through one sanitizer.
  • Developer-only automation, scratch captures, .NET build output, and Playwright run output left the release checkout.
  • Product version moved to 1.2.0 with Android version code and iOS build number 1020001.

Fixed

  • Desktop configuration writes fail explicitly when the config store is unavailable instead of falling back to a throwaway in-memory store.
  • Speech provider and model failures reach the UI as errors instead of surfacing as empty transcriptions.
  • Removed the Forgejo release-publishing prohibition; the legacy hardcoded-version script is replaced by a version-gated publisher.
  • Dropped a stale admin bundle from the API server web root.
  • Mobile team, meeting, memo, template, command, and dictionary screens follow the server contract, and report submission no longer hangs without confirming to the user.

[1.1.0] - 2026-08-29

Added

  • Android/iOS product mobile app: implemented account bootstrap and lifecycle, onboarding, recording and audio import, transcription, history, meetings, templates, memos, teams and invitations, notifications, knowledge, AI Talk, generated documents, data portability, and role-aware administration flows.
  • Mobile-native recording and intake: added Android foreground recording with persistent controls and recovery, external ACTION_SEND audio/video intake, durable upload processing, and supported-device on-device Whisper transcription.
  • Server-verified mobile monetization: added Google Play purchase and restore verification, entitlement reconciliation, AdMob rewarded SSV validation, and replay-safe reward receipts.
  • Generated-content safety controls: added generation receipts, shared generative-AI safety instructions, and an authenticated report flow for owned AI-generated meeting documents.
  • Release verification tooling: added Android artifact, App Links, production Firebase/AdMob configuration, Play asset, secret scanning, signed provenance, and publication-boundary checks.
  • Complete mobile icon set: added canonical Android legacy/adaptive/monochrome launchers, the 512px Play icon, and all required iPhone, iPad, and App Store marketing icon slots.

Changed

  • Unified mobile authentication and invitation links on the canonical d3ro-voice app scheme and added fail-closed verification for the HTTPS App Links contract.
  • Hardened Supabase and mobile production configuration to fail closed when required public configuration is absent or does not match the release identity.
  • Expanded CI coverage across Node.js 24, .NET 10, Deno Edge Functions, React Native tests, Android emulator gates, 16 KB page-size compatibility, and reproducible release evidence.
  • Aligned account deletion guidance with external subscription cancellation requirements and centralized local sensitive-data purge on logout, account deletion, and session loss.
  • Centralized product version 1.1.0, Android version code 1010001, release notes, updater metadata, and app-store changelogs under release SSOT checks.
  • Finalized benchmarked ko-KR/en-US Play listing copy and a Console-previewed 1024×500 canonical feature graphic with preserved generation prompt, source, output, and hashes.

Security

  • Added atomic authorization and replay protection for teams, invitations, push delivery, transcription quotas, billing, ad rewards, administrative actions, data portability, and content reports.
  • Removed synthetic success fallbacks from protected STT and AI paths; provider and configuration failures now return explicit failures without creating fabricated user data.
  • Strengthened generated-document reporting so only the owner can report an existing document backed by immutable generation audit evidence.
  • Removed the repository-exposed desktop license private key and prefix-only paid-tier activation; production now accepts only Ed25519 licenses signed by the rotated external key.
  • Made Windows stable packaging fail closed unless an external public-trust code-signing PFX is provided and both the NSIS installer and unpacked app pass exact-version, updater SHA-512, Authenticode Valid, and expected signer-subject verification; local self-signed development certificates are rejected.

Fixed

  • Corrected realtime Edge Function model routing and type checks for team and enterprise tiers.
  • Removed the legacy d3ro:// deep-link surface to prevent divergent authentication callback identities.

[0.2.1-alpha] - 2026-07-22

Fixed

  • v0.2.0-alpha 치명적 버그 (앱 실행 불가): refactor-wave WS2(AppConfig SSOT)에서 7개 키(customInstructions, llmChains, voiceCommandRules, voiceCommandsEnabled, activeInstructionId, activeChainId, captionAudioSource)를 AppConfig 인터페이스에 추가하고 as never 16건을 제거했으나 CONFIG_DEFAULTS(ConfigService.ts) 기본값을 누락 → 기존 사용자 config(0.1.x) 마이그레이션 시 configGet()이 undefined 반환 → main 프로세스 .map() 크래시. CONFIG_DEFAULTS에 기본값([], [], [], false, '', null, 'mic') 추가.
  • 교훈: typecheck/lint/unit test가 GREEN이어도 런타임을 보장하지 않음. 배포 전 npm run dev 실행 + 산물 설치 e2e 필수 — 이번에 e2e를 건너뛰어 사용자가 발견.

[0.2.0-alpha] - 2026-07-22

다운로드: Windows D3RO-Voice-Setup-0.2.0-alpha-x64.exe · macOS D3RO-Voice-0.2.0-alpha-arm64.dmg (Release assets 첨부) — 기존 Windows 사용자는 자동 업데이트(4시간 주기)로 수신됩니다. macOS는 ad-hoc 서명 — Gatekeeper 차단 시 우클릭→열기.

Midnight Glass v2 전면 재설계 + refactor-wave 대규모 코드 품질 정리. 기능 추가보다 시각·구조 개선 중심.

Added

  • Midnight Glass v2 전면 리디자인: 미드나이트 네이비 + 글래스모피즘 카드(헤어라인 그라디언트 + 앰비언트 글로우) + 시안→블루→퍼플→마젠타 그라디언트. 6종 테마(dark/light/nord/solarized/catppuccin/dracula) 전환. 보더리스 UI + 커스텀 TitleBar. Pretendard Variable 폰트 오프라인 번들.
  • TiltCard DS: 커서 추종 3D 틸트 + 스페큘러 빛 반사 (reduced-motion 완전 존중)
  • GradientWave / StatRing DS 신규 (기존 CrtDisplay WebGL 오실로스코프를 그라디언트 스펙트럼 웨이브로 교체)
  • 실시간 부분 전사: 받아쓰기 홀드 중 RecordingTip에 interim 전사 표시
  • Windows 자동 업데이트: electron-updater + GitLab Generic Registry feed (4시간 주기, 재시작 다이얼로그)
  • 멀티플랫폼 배포: macOS arm64(ad-hoc 서명) + Windows 동시 릴리스. GitLab Package Registry(버전별+latest) + Release 자동 생성
  • 번들 Ollama v0.32.1: 온보딩 gemma4:e4b pull 412 실패 해소, GPU 런타임 가지치기로 ~1GB→119MB 슬림화
  • gpt-realtime-2.1 라이브 음성 대화 (Premium 백엔드, OpenAI Realtime) — 로컬 파이프라인 자동 fallback
  • Whisper large-v3-turbo 기본 STT: 6배 빠름, 사이드카 백그라운드 다운로드 API

Fixed

  • 한국어 날짜 "TODAY"/"YESTERDAY" 표시 버그 — date.today/yesterday 중복 정의(JSON last-wins) 해소
  • 팝업/렌더러 색상 충돌 — 팝업이 v1 주황(#f25b29)으로 렌더되던 것을 파랑(#3b82f6)으로 SSOT 정합
  • 받아쓰기 파이프라인 4버그: press 액션이 STT 초기화를 await하며 큐 점유→release 지연/유령 세션; 사이드카 crash 루프; RecordingTip hide 타이머 leak; 빈 STT 가드
  • 온보딩 무진행 구간 UX: verifying(모델 검증) 단계 피드백 + 중복 실행 가드
  • 마이크 테스트 조기 종료: 초기 level:0을 종료 신호로 오인하던 버그
  • 트레이 아이콘 빈 이미지 버그

Changed

  • accent.amber → accent.main 전면 통일 (162건, deprecated 별칭 2곳 제거) — desktop/web/admin/mobile/ui-native 전역. 6 테마 일관.
  • IPC 채널 SSOT 일원화: ipc-channels.ts에 9 그룹/키 추가(INSTRUCTION, POPUP_*, CLIPBOARD, APP 등), 하드코딩 채널 문자열 제거, ipcSuccess/ipcError 헬퍼 통일, catch(error) 패턴 32건
  • AppConfig 타입 강화: 7개 누락 키 추가, as never 16건 제거, dynamic require → static import
  • 팝업 i18n: 4종 팝업(command/history/result/recording-tip) 한국어/영어 하드코딩 → t() 키 주입 (popup.* 17키)
  • 매직 리터럴 토큰화: 인라인 fontSize/fontWeight/borderRadius → d3roTypo/d3roRadius 토큰 (렌더러 전역)

Removed

  • DS 미사용 3종: MetalDial, ButtonGroup, CrtDisplay (barrel export 포함)
  • 미사용 의존성 8종: @mui/icons-material, @d3ro/api-client, fluent-ffmpeg(+@types), pdf-parse, node-record-lpcm16(+.d.ts), electron-audio-loopback, @electron-toolkit/preload
  • i18n 고아 키 967건 (12 locale) — camelCase license.feature 15키 등 동적 참조는 P1 재검증으로 보존
  • services/index.ts 데드 레지스트리, electron-builder.yml Linux 섹션

Internal

  • refactor-wave Wave 1+2: 정책(docs/REFACTOR_POLICY.md) 수립 → 공격적 감사(106건) → 9 워크스트림 병렬 → 분리 커밋 9개 + 메타 2. 공유 패키지 토큰 SSOT, IPC/타입 정합, 데드코드 대량 제거. 보고서 docs/REFACTOR_WAVE1_REPORT.md·WAVE2_REPORT.md.

[1.0.0] - 2026-08-20

Added

Core Pipeline (Phase 1-3)

  • Electron 33 + React 19 + MUI 7 + TypeScript strict mode
  • AudioCaptureService: SoX-based PCM16 16kHz mono microphone capture
  • LocalSTTService: faster-whisper Python sidecar (dual-condition flush pattern)
  • VoiceModeService: 9-state RecognitionState + 4-state AudioState dual state machine
  • HotkeyService: uiohook-napi global keyboard hooking (hold/toggle/double-press)
  • TextInsertService: clipboard save/set/Ctrl+V/restore via @nut-tree-fork/nut-js
  • RecordingTip popup: 9 wave bars with cosine distribution, thinking progress bar
  • ResultPopup: auto-close with mouse hover pause, copy button
  • Settings modal: General/Audio/STT/LLM tabs
  • System tray with close-to-tray support

Cursor History Popup (Phase 3.5)

  • Ctrl+Shift+V global shortcut opens recent transcription history at cursor position
  • Arrow key navigation, Enter to paste, 1-9 direct select, ESC dismiss
  • focusable: false maintains active app focus

LLM Integration (Phase 4)

  • LocalLLMService: Ollama REST API with NDJSON streaming
  • 6 system prompts: refine/translate/summarize/grammar/expand/custom
  • VoiceModeService LLM integration with original text fallback

Database & History (Phase 5)

  • better-sqlite3 + drizzle-orm (WAL mode)
  • HistoryService: CRUD + search + stats + 30-day retention policy
  • DictionaryService: custom words + STT initialPrompt injection
  • Dashboard with real statistics

Custom Instructions & i18n (Phase 6)

  • CustomInstructionService: 5 presets + user-defined CRUD
  • i18n system: ko/en with t() function and React context

Build & Test (Phase 7)

  • vitest: 41 unit tests (HistoryService, DictionaryService, VoiceModeService, etc.)
  • electron-builder: NSIS installer for Windows x64
  • GitLab CI/CD: lint, typecheck, test, build, release pipeline
  • SoX download script, PyInstaller sidecar build script

Speakly Pattern Enhancement (Phase 7.5)

  • SoundEffectService: WAV preload, fire-and-forget playback
  • AutoLaunchService: app.setLoginItemSettings
  • TextInsertService: basic insertion verification
  • VoiceModeService: sound effect integration on session events

UI Redesign (Phase 8)

  • Industrial instrument aesthetic (dark theme, amber #f25b29 accent)
  • Design system: 9 DS components (CrtDisplay, InstrumentPanel, Led, PhysicalButton, MetalCard, PhosphorText, MetalDial, ScreenPanel, ButtonGroup)
  • d3roPalette SSOT: all colors via CSS custom properties
  • HotkeyRecordModal: key combination recording UI
  • DashboardPage: feature-focused layout with stats + history + system status

Quality & UX (Phase 9)

  • 4-step onboarding wizard (welcome, mic, hotkey, Ollama)
  • Microphone test UI with level meter
  • Audio recording WAV file saving
  • MetalDial component with drag rotation
  • Ctrl+Shift+C command popup at cursor position
  • Dictionary inline editing
  • Ollama installation guide with nudging bubble
  • Real-time UI refresh on data changes

Killer Features (Phase 10)

  • CaptionService: 3-second chunk continuous transcription with overlay popup
  • VoiceCommandService: keyword-to-command matching engine (4 preset keywords)
  • ScreenContextService: active window detection + selected text capture
  • ChainService: sequential LLM command pipeline with step-by-step events
  • MemoService: memo tags DB table + tag CRUD + markdown export
  • Shared components: EmptyStateCard, SearchInput, PageHeader, HistoryEntryCard
  • Shared utilities: formatters.ts (formatDuration, getDateKey, formatNumber)

Monetization (Phase 11)

  • LicenseService: Free/Pro/Pro+ 3-tier system
  • Feature gating with 16 feature enums and tier-based access mapping
  • Daily usage quota tracking (Free: 20 dictation/day, 10 LLM/day)
  • LemonSqueezy API integration for license key activation
  • UpgradePromptModal, ProBadge, useProFeature hook
  • Settings License tab with tier comparison table

Pro Features (Phase 12)

  • FileTranscriptionService: ffmpeg PCM conversion, 30s chunk sequential STT
  • MeetingSummaryService: caption session LLM summarization
  • DictationTemplateService: CRUD + session state machine, 3 presets

Pro+ Premium (Phase 13)

  • VoiceConversationService: STT-LLM-TTS loop for voice conversations
  • TTSPlaybackService: Windows SAPI via PowerShell
  • RAGService: Ollama nomic-embed-text embeddings, SQLite vector storage, cosine similarity
  • KnowledgeBasePage: document management, indexing progress, Q&A UI
  • VoiceActionService: LLM JSON action plans, 6 presets, dangerous command blocking

Landing Page

  • Promotional website at site/ directory
  • Vite + React 19 + Tailwind CSS
  • 4 design references integrated into D3RO brand identity
  • CRT screen effects, crosshair decorations, noise textures (CSS only)
  • 10-language i18n: en/ko/ja/zh/es/fr/de/pt/ru/vi
  • GitHub Pages auto-deployment workflow

Technical Details

  • Total IPC channels: ~200+
  • Total services: 20+
  • Total error codes: 0-878
  • Design system components: 9
  • Supported languages (app): ko, en
  • Supported languages (landing): 10
  • Test count: 41 unit tests
  • Build target: Windows x64 NSIS installer