Some checks failed
ci / 정본·보안·린트·타입·테스트 (push) Successful in 54s
ci / 모바일 린트·타입·Jest (push) Successful in 42s
ci / Supabase Edge Functions + Cloudflare Worker (push) Successful in 22s
ci / .NET API 서버 테스트 (push) Successful in 17s
deploy-site / deploy (push) Successful in 35s
ci / 워크스페이스 빌드 검증 (push) Successful in 37s
release / release-windows (push) Failing after 6m8s
portable-unsigned / portable-windows (push) Failing after 14m8s
Knowledge documents move between desktop, phone and web as source text and are indexed on each device; desktop recordings upload to the shared storage and any recording plays from the history card; language, theme, auto-polish and the active command follow the phone. Document text survives a missing embedding model so it can be indexed later. Bumps the product version to 1.8.0 (Android/iOS build 1080000).
597 lines
38 KiB
Markdown
597 lines
38 KiB
Markdown
# Changelog
|
||
|
||
All notable changes to D3RO Voice will be documented in this file.
|
||
|
||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||
|
||
## [Unreleased]
|
||
|
||
### Planned
|
||
- macOS / Linux support
|
||
- Additional Whisper model management UI
|
||
- Plugin system for custom pipelines
|
||
|
||
## [1.8.0] - 2026-09-27
|
||
|
||
> Published from an annotated tag. Installer and update metadata are served by the
|
||
> canonical Forgejo feed; no binaries are committed to this repository.
|
||
|
||
### Added
|
||
- **Knowledge base syncs with your phone.** Documents added on the desktop can be
|
||
searched on the phone and web, and documents added there appear on the desktop and
|
||
are indexed with the local model. Deleting one removes it everywhere.
|
||
- **Recordings sync and play anywhere.** Desktop recordings are uploaded (up to 50 MB
|
||
each, can be turned off in Settings > Cloud) so the phone can play them, and each
|
||
history card has a play button that also plays recordings made on the phone.
|
||
- **Shared settings.** Language (Korean/English), light/dark/system theme,
|
||
auto-polish on or off and the active command follow the phone.
|
||
|
||
### Fixed
|
||
- A document's text is kept even when the local embedding model is unavailable, so
|
||
it can be indexed later without the original file.
|
||
|
||
## [1.7.0] - 2026-09-27
|
||
|
||
> Published from an annotated tag. Installer and update metadata are served by the
|
||
> canonical Forgejo feed; no binaries are committed to this repository.
|
||
|
||
### Added
|
||
- **Your desktop and phone now stay in step.** Signing in keeps history (with titles
|
||
and favorites), the dictionary, meetings with their memos and documents, memo tags,
|
||
your own commands and dictation/meeting templates the same on the desktop, the phone
|
||
and the web. Changes made offline wait and upload later; what you delete on one
|
||
device is deleted on the others; edits from the phone appear within seconds.
|
||
- **The desktop appears in the phone's device list.** Disconnecting it from the phone
|
||
signs the desktop out; signing out on the desktop removes it from the list.
|
||
- **Records made before signing in come with you.** The first account that signs in
|
||
on this computer receives the history, dictionary and meetings kept in local mode.
|
||
- **Favorites on the desktop**, shared with the phone.
|
||
- Settings > Cloud shows how many changes are waiting to upload or were refused.
|
||
- **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.
|
||
- The live-caption model is chosen next to the other caption settings in the General
|
||
tab.
|
||
|
||
### Fixed
|
||
- **Accepting a suggestion with Ctrl+Alt+Enter did not paste.** The paste was sent
|
||
while Ctrl+Alt were still held, so the app received Ctrl+Alt+V. The panel now closes
|
||
at once and the text is pasted as soon as the keys are released.
|
||
- **Clicking a suggestion did nothing** when a new candidate arrived between pressing
|
||
and releasing the mouse button; a candidate is now accepted on press.
|
||
- **Suggestions rarely appeared in chat boxes that grow as you type.** The growing box
|
||
was taken for a different field on every keystroke, which kept blocking suggestions
|
||
as "not typing". Fields are now told apart by window and control, and a mouse click
|
||
re-checks whether you have typed since.
|
||
- **Cloud sync was mostly one-way.** Data created on the phone never reached the
|
||
desktop after signing in, only the first meeting's memos and documents were
|
||
uploaded, deletions were never shared, team meetings leaked into personal data, and
|
||
live updates never connected. All fixed.
|
||
- Exporting account data failed for accounts with meetings; the export keeps its
|
||
original format again.
|
||
|
||
## [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
|