Skip to content

WhimprFlow v0.2 — Dark mode, customizable shortcuts, voice Transforms, and a full brand + motion overhaul - #2

Open
ch1kim0n1 wants to merge 25 commits into
Blueturboguy07:mainfrom
ch1kim0n1:main
Open

ch1kim0n1 wants to merge 25 commits into
Blueturboguy07:mainfrom
ch1kim0n1:main

Conversation

@ch1kim0n1

Copy link
Copy Markdown

Overview

This is a large step forward for WhimprFlow: a new visual identity, a full dark theme, five new feature surfaces, a customizable shortcut system, and a round of engineering hardening. Everything is local-first and builds clean on macOS.

162 files changed · +14,571 / −1,934 · 73 tests passing · builds green (cargo build --workspace, tsc + vite).

New features

  • Dark mode + toggle. Full light/dark theming built on CSS custom properties, so a single data-theme flip re-themes the entire app instantly. New cohesive dark palette (cool slate + teal); warm cream light stays default. Toggle lives in Settings → Appearance, persists across launches, and applies before first paint (no flash).
  • Customizable keyboard shortcuts. A new Shortcuts pane with a live key-capture recorder, per-platform defaults, modifier validation, and conflict detection. Cancel / paste-last / copy-last / undo-last are fully rebindable; the native hotkey layer reads the new bindings live (no relaunch).
  • Style. A personal writing-style profile (tone, formality, free-text guidance) that feeds the cleanup engine so output reads the way you write, without inventing content.
  • Transforms. Turn dictated or pasted text into a finished draft (email, summary, to-do, and more) in one click, through the configured cleanup provider.
  • Scratchpad. A dedicated long-form dictation surface with local autosave, word/character count, one-click copy, and cleanup.
  • Snippets. Voice-triggered text expansion for signatures, addresses, and boilerplate.
  • Command Mode + backup. Instruction-following in-place rewrites, plus one-click local backup of settings, dictionary, snippets, and stats.

Design & UX

  • New brand identity. Regenerated app icon as a proper macOS squircle (continuous corners, correct icon grid, transparent margin) and a monochrome, auto-adapting menu-bar template icon that matches native status items.
  • Menu-bar shortcuts popup. Click the menu-bar icon for an at-a-glance list of your active shortcuts, built from your real bindings.
  • Redesigned Home. Full-page ambient "voice field" canvas, an editorial hero, and count-up usage stats.
  • GSAP motion system. Timeline-driven entrances, scroll reveals, per-page transitions, and a sliding sidebar indicator, all respecting reduced-motion.
  • Professional copy pass. Rewrote UI copy across every pane and removed em dashes from user-facing text.

Engineering & hardening

  • Retry/backoff on cloud cleanup calls, input length caps on dictionary and snippet entries, and deterministic cleanup gates with a raw-transcript fallback.
  • Integration test suite for the cleanup pipeline (73 tests total, all passing).
  • SECURITY.md documenting the local-first data posture, plus benchmark methodology and research notes.
  • Cross-platform scaffolding for the Windows and Linux native layers.

Notes for reviewers

  • Local-first by design: nothing leaves the device except optional, user-configured cloud cleanup.
  • macOS is the verified target; Windows/Linux layers are present but not yet hardware-verified.

ch1kim0n1 and others added 11 commits July 19, 2026 01:20
A malfunctioning editor hook had reverted every git-tracked file to the last
commit and character-mangled the new (untracked) files; that broken mix landed
in db04762. This restores the full working state, recovered from the session
transcripts (main + subagent-workflow logs) and rebuilt via a path that bypassed
the faulty hook.

Restored / reconstructed:
- whimpr-core: StyleProfile + Formality (settings), CleanupContext.style wiring,
  backup module, command_prompts, snippets, dictionary, stats, pipeline tests
- whimpr-cleanup: OpenAI/Anthropic command_edit path
- src-tauri: hotkey.rs hand-reconstructed (no complete snapshot existed) with
  keybinding rebinding (keycode_for_key/mods_match_chord), Style wire,
  run_command_edit/test_command_edit, backup_data; run_transform command in lib.rs
- Fixed a real-email leak in a snippets test fixture -> user@example.com

Builds clean (cargo build --workspace: 0 errors, 69 tests pass; ui builds).

Known follow-ups (lost in the incident, not yet re-added): ASR language param
(auto-detect only), Fn+Ctrl Command-Mode hotkey (Transforms + test card cover it),
dictionary/snippet length caps, cleanup retry/backoff.

Note: tauri.conf.json signingIdentity set to "-" (ad-hoc) for local building on a
machine without the Apple cert.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Home page: full-page ambient "voice field" canvas (flowing teal ribbons on the
warm palette, pointer-reactive, reduced-motion aware), an editorial Fraunces
hero, a count-up stat strip, and a restyled recent-dictations panel. Replaces
the old cyan-on-dark hero (which leaned on common AI-slop tells).

Motion: introduced GSAP + ScrollTrigger (bundled, no CDN) via a shared anim.ts.
- Home entrance timeline: clip-reveal headline, hairline draw, staggered figures,
  scroll-reveal on the history panel, GSAP number count-ups.
- App-wide page-enter cascade on navigation.
- Sidebar: single active-indicator pill that glides between items, plus an icon
  hover nudge.
- All entrances guard on prefers-reduced-motion AND document.hidden, so content
  is never left invisible when animations can't run.

Copy: removed every em dash from user-facing text and rewrote casual/marketing
lines to read professionally (hero eyebrow/subhead, empty states, Style,
Scratchpad, Transforms, Help, and two Rust error strings surfaced in the UI).

Also adds brand assets under public/ (app icons + logos).

Builds clean: cargo build --workspace, cargo test, ui tsc+vite.
Appearance:
- Theme system rebuilt on CSS custom properties (data-theme on <html>), so a
  single flip re-themes the whole app without touching the many inline styles.
- New cohesive dark palette (cool slate + teal), warm cream light stays default.
- Light/Dark toggle in Settings > Appearance; persisted in localStorage and
  applied in main.tsx before first paint (no flash). Added solidBg/solidText
  tokens so inverting buttons (CTA, Grant, primary) read correctly in both.
- VoiceField canvas ribbons adapt to the active theme.

Brand:
- Regenerated the Dock/bundle icon set from public/whimprflow-app-icon-1024.png.
- Sidebar now shows the mark chip (app icon) + wordmark, correct on light/dark.

Menu bar:
- Tray icon uses the new mark; left-click opens an at-a-glance popup listing the
  ACTIVE shortcuts, built from the user's real keybindings (push-to-talk,
  hands-free, Command Mode, cancel/paste/copy/undo) plus Open and Quit. Dropped
  the old demo tray items and the now-dead emit_bar_state helper.

Also: added vite/client types (vite-env.d.ts) and a background em-dash ->
hyphen normalization swept through some comments/docs.

Builds clean: cargo build --workspace, ui tsc+vite.
Dock / bundle icon:
- Reshaped from a full black square into a proper macOS squircle: continuous
  corners (superellipse), the 824/1024 icon grid with transparent margin, and
  transparent corners so the Dock shows the rounded shape (not a black tile).
  Kept the shaded aqua mark on the deep-slate surface. Regenerated icns/ico/png.

Menu-bar (status) icon:
- Now a template image (black + alpha of the mark, icon_as_template=true) so
  macOS renders it monochrome and adapts it to the bar (white on dark), matching
  native status items. Cropped to the mark's content and sized to fill the bar
  height instead of floating small.

Verified transparency/shape in the source, generated icon.png/icns, and the
installed bundle. Builds clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…t v1s

Tier 1 (trust wedge):
- Reversible editing: raw transcript persisted per dictation with a
  word-level raw-vs-final diff in Home history; Cmd+Shift+Z remains the
  one-key restore
- Privacy cockpit: per-dictation provenance ledger (engine, cleanup route,
  sent-to-cloud, gate verdict), retention controls with text pruning, and
  delete-all-text, in a new Privacy pane
- Reliability: whisper token-probability confidence with low-confidence
  word tap-to-fix, insertion receipts on every finalize (FlowBar flash +
  Home banner), and ASR/local-LLM/mic/accessibility health chips

Tier 2 (moat trio):
- Voice Memory: AES-256-GCM-encrypted local correction log (key in the OS
  keychain), auditable and exportable as plain JSON, fed by autolearn and
  manual dictionary edits
- Context Capsule: opt-in per-app context bundle (frontmost app, AX
  selection, glossary, style) feeding cleanup, fully inspectable in the
  Privacy pane
- Voice Workflows: versioned trigger-phrase automations routed through the
  command-edit provider path with Paste/Clipboard/Note destinations and
  approval-gated pending results

Tier 3:
- Streaming provisional text in the FlowBar while speaking (partials are
  never pasted; commit stays the verified finalize path)
- Voice Studio: Editor/Timeline/Notes tabs with full-history search,
  raw/final versions, Markdown/GitHub/Linear exports, and a Compile
  action producing a structured draft plus missing-facts card

Tier 4/5 v1s (each with a documented ceiling):
- Code Mode cleanup prompt for IDEs/terminals, history search (knowledge
  retrieval), screen-capture notes (multimodal capture), meeting mode
  (hands-free sessions land in Studio notes via long-form transcription),
  language threading into whisper with a Settings picker and hot model
  reload, and an accessibility pass (focus rings, aria labels, live
  status regions)

Hardening from a 34-finding adversarial review, including: keyring
platform keystore features (keys actually persist now), capture-thread
race that could leave the mic hot, provider HTTP moved out of mutex
guards, pending-workflow reachability (get_pending + target-app
reactivation on approve), retention edge cases, Unicode workflow
triggers, and non-blocking audio callback.

Windows/Linux platform layers mirrored but still unverified on their
targets; Context Capsule and streaming preview are macOS-only this pass.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The Workflows/Voice Memory/Privacy nav additions pushed total sidebar
content past the fixed window height, and overflow:hidden clipped the
Account entry off the bottom instead of leaving it reachable.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Implement 15-item roadmap: trust wedge, moat trio, and moonshot v1s
@ch1kim0n1

Copy link
Copy Markdown
Author

More features added

ch1kim0n1 and others added 14 commits July 20, 2026 18:15
Add distil-large-v3.5, distil-medium.en, distil-small.en, and q8_0
quantized siblings to the whisper model priority lists on macOS,
Windows, and Linux, so faster/smaller models get picked up with no
code changes once dropped into the models folder. Also decouple the
no-model-found fallback path from list ordering (it relied on
ENGLISH_FIRST.last(), which broke once the list grew).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Two user-reported bugs on macOS:

1. Permissions (Accessibility / Input Monitoring / Microphone) reset on
   every launch. Root cause: ad-hoc signing (`signingIdentity: "-"`)
   yields a different designated requirement per build, so TCC can't
   stably identify the app and re-prompts each launch. Switch the default
   signingIdentity to a stable self-signed cert ("WhimprFlow Dev") and add
   src-tauri/setup-signing.sh to create + install it in the login
   keychain. A stable CN gives a stable designated requirement, so TCC
   persists grants across rebuilds on the developer's machine. CI keeps
   ad-hoc signing via APPLE_SIGNING_IDENTITY="-" (no cert on runners);
   a future Developer ID secret overrides both.

2. RAM blowup / memory-pressure warnings on MacBook Air. Root cause:
   install() eagerly loaded the whisper ASR model AND spawned the local
   LLM worker (Qwen3-4B ~2.5GB) on every launch, even when cleanup mode
   was OpenAI/Anthropic/Raw and no dictation had happened. Both are now
   lazy: the ASR engine loads on the first Fn press (ensure_asr_loaded at
   StartCapture), and the local LLM worker spawns only when cleanup mode
   is Local or a cloud provider falls back to local (ensure_local_worker).
   An idle reaper unloads the worker after 10min inactivity, releasing its
   child process + model RAM; it respawns lazily on the next Local
   cleanup. The app now holds ~0 model RAM at rest.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…form, tests, i18n

Waves 1-3 of commercial readiness work:

- Auto-updater wiring (Tauri updater plugin, GitHub Releases endpoint, signing key)
- Offline ed25519 license keys + 14-day trial + cloud-cleanup gate
- EULA, Terms, Privacy Policy, billing docs, support surface
- Structured logging (tracing + rotating files + panic hook + diagnostics zip)
- JSON store corruption recovery, Whisper model magic validation
- GDPR wipe-all, data retention pruning, backup/restore with path-traversal guard
- Launch watchdog + safe-mode detection
- ASR idle unload, max_ram_mb LLM worker limit, clipboard hygiene
- Cloud-unavailable event + Hub banner, empty states in all panes
- Mic self-test in onboarding, reliable platform detection
- Sound feedback (start + complete), workflow presets, dictionary import/export
- Crash reporting opt-in, shortcut conflict detection
- i18n scaffolding (i18next + react-i18next, English locale)
- Vitest frontend tests (25 tests across 5 files)
- Rust tests (139 tests: license edge cases, IPC fuzz, JSON recovery, model magic, licensing, cloud gate)
- CI: Linux matrix, gitleaks, cargo audit, npm audit, SHA-pinned actions, SBOM, cargo auditable
- whisper-rs 0.16, Windows paste/hotkey dispatch, dev.ps1
- HTTP hardening (no redirects, SSRF guard, rate limiting, rustls)
- CSP, dependabot, .env.example, .gitignore for secrets
- Linux CI matrix (ubuntu-latest) with apt deps + Wayland guidance
- Auto-rollback: watchdog tracks previous_version, one-click restore in Hub
- E2E smoke tests (settings, entitlement, diagnostics, models, build info)
- System tray + autostart + minimize-to-tray
- Settings import/export, history search + export (json/txt)
- Voice Memory search with debounce + count
- Accessibility: skip link, aria-live regions, focus rings, reduced-motion CSS
- Toast notifications (context + event bridge)
- API key validation (OpenAI /models, Anthropic /messages)
- Network health indicator (TCP probe + HealthChip)
- Model management UI (list/set active/delete + download)
- Audio input device picker
- Auto-punctuation + custom filler words
- Changelog + settings schema migration
- Keyboard cheatsheet modal
- Onboarding 5-step progress with Back/Skip
- Corrupt model recovery (whimpr://model/corrupt event + re-download)
- Clipboard history clear (Win10 1809+ runtime-resolved)
- v1.0.0 release prep: manifests, CHANGELOG, release notes, pre-release gate
- docs/ARCHITECTURE.md + docs/CONTRIBUTING.md
- Clean up repo root: move process artifacts to .devin/
- Add machine fingerprinting to prevent trial reset by keychain deletion
- Add fuzzing targets for IPC codec and license parser
- Improve entity preservation logic with word-boundary-aware matching
- Document hotkey.rs decomposition plan for future refactoring
…vation

- Fix macOS machine ID extraction: properly parse ioreg quoted values
  (was capturing field name + value instead of just value)
- Fix start_trial logic: preserve original trial start time from machine ID
  file when keychain is deleted (was overwriting with new timestamp)
- Add fallback to keychain-only if machine ID unavailable (degraded tamper
  resistance but preserves usability)
- Add directory creation in save_trial_state for first-run safety
- Fix entity_present: add case-insensitive substring match (was only checking
  punctuation variants, missing bare lowercase matches)
- Fix unused variable in test (would fail clippy -D warnings)
…o, backup, dictionary, platform layers

State machine (state/machine.rs) +14 tests:
- cancel-during-finalizing, cancel-during-awaiting-lock, cancel-in-idle
- stray-up-in-idle, mismatched-binding-up, double-tap-after-window-expiry
- hands-free-chord-immediate-lock, stale-pipeline-event-ignored
- pipeline-failed-returns-to-idle, normal-key-during-arm-noop
- session-id-monotonic, tick-in-idle, tick-in-finalizing
- cooldown-after-lone-tap-timeout

IPC codec (codec.rs) +8 tests:
- truncated-length-prefix, truncated-body, empty-body-frame
- clean-eof-at-boundary, max-size-frame-accepted, write-to-sink
- unicode-payload-round-trip, interleaved-reads-writes-order

Settings (settings.rs) +17 tests:
- validate-keybindings empty/all-collide/partial-collision
- strip_fillers empty/only-fillers/case-insensitive/punctuation/custom/empty/whitespace
- strip_auto_punctuation sentence/unicode/empty
- settings save-load round-trip, missing-file, corrupt-file
- retention-days zero/none semantics, chord equality, escape key

Voice memory (voice_memory/mod.rs) +9 tests:
- empty-memory-encrypts, truncated-nonce, exactly-nonce-length
- tampered-ciphertext, tampered-nonce, save-creates-parent-dirs
- record-appends-in-order, unicode-round-trip, overwrite-replaces

Backup/restore (backup.rs) +10 tests:
- no-source-files, restore-nonexistent-dir, unknown-files-skipped
- missing-files-skipped, list-empty-for-nonexistent, list-newest-first
- list-ignores-files, prune-exactly-max, prune-zero, multi-file-round-trip

Dictionary (dictionary/mod.rs) +16 tests:
- unicode-entry, empty-mishears, duplicate-merges, duplicate-mishear-dedup
- remove-nonexistent, remove-case-insensitive, prefilter-empty/whitespace/max/punctuation
- phonetic-codes-empty/whitespace, phonetic-match-empty/similar
- is-common-word case/uncommon, save-load-round-trip, missing-file, corrupt-file
- load-backfills-phonetic-codes

Windows platform (win.rs) +9 tests:
- vk-for-escape, vk-for-char-letters/digits, ptt-vk-is-right-ctrl
- command-mode-vk-is-space, key-event-down/up, ctrl-v-sequence
- shift-insert-fallback, capture-screen-returns-error

Linux platform (linux.rs) +7 tests:
- xk-control-r-keysym, capture-screen-returns-error, overlay/hub-labels
- preview-chars-reasonable, double-tap-ms-from-core
- recording/locked-atomic-init-false, last-key-up-ms-init-max
The key_event function and VK_V/VK_INSERT/INPUT_KEYBOARD constants are
private to the imp module in paste.rs, not win.rs. Move the four
key_event tests into a #[cfg(test)] submodule inside imp so they have
access to private items via use super::*. Add is_trusted and
input_monitoring_granted smoke tests there too.

Also fix Linux atomic tests to read the actual module statics
(RECORDING, LOCKED, LAST_KEY_UP_MS) instead of constructing fresh
AtomicBool/AtomicU64 instances that tested nothing.
Test fixes found by actually running cargo test:

1. dictionary::add_duplicate_mishear_is_not_duplicated: The dedup only
   runs on the merge path (adding to an existing entry), not the
   new-entry path. Split into two add() calls to exercise the merge path.

2. dictionary::remove_is_case_insensitive: store() has two entries
   (Manvi + ChargeBee); removing one leaves the other. Fix assertion to
   check len==1 instead of is_empty().

3. state::double_tap_after_window_expires_starts_new_session: The down
   at 500ms was within the 500ms cooldown from the timeout at 401ms.
   Push the second press past cooldown (timeout + COOLDOWN_MS + 100).

4. ipc::interleaved_reads_and_writes_preserve_order: Pong.seq is u64
   but loop variable was u32. Change 0..3u32 to 0..3u64.

5. lib.rs: Add pub use machine_id::machine_id; re-export — the
   licensing module imports machine_id() as a function but only the
   module was exported, not the function inside it.

All 179 whimpr-core tests, 16 whimpr-ipc tests, and 26 whimpr-tauri
tests now pass.
Apply rustfmt formatting across all test code and fix two clippy
warnings under -D warnings:
- needless_borrows_for_generic_args in dictionary prefilter test
- bool_assert_comparison in settings safe_mode test
- Fix postcss moderate vulnerability via npm audit fix
- Add docs/buy.html as a placeholder buy page for whimprflow.com/buy
- This addresses P2 item from /ship review (npm audit)
- Buy page provides a starting point for the purchase URL in README
- Change `plugins.updater.windows.installMode` from `currentUser` to `passive`;
  the updater plugin expects `basicUi`/`quiet`/`passive`, while `currentUser` is
  a bundle-level NSIS option. This unblocks `whimpr-tauri.exe` from starting on
  Windows.
- Add local `.patches/` copies of `zmij` and `num-traits` without build scripts
  so Windows Device Guard does not block their build scripts. Wire them via
  `[patch.crates-io]` in the workspace root.
- Update `Cargo.lock` for the patched sources.
nitrimandylis added a commit to nitrimandylis/WhimprFlow that referenced this pull request Sep 4, 2026
nitrimandylis added a commit to nitrimandylis/WhimprFlow that referenced this pull request Sep 4, 2026
- Cherry-pick new icon files from PR Blueturboguy07#2 (squircle .icns/.png)
- Set ignoresMouseEvents on overlay so pill never steals focus
- Remove hover action buttons, drag handler, and related dead code
- ponytail: overlay is visual-only, dictation is Fn-key-driven
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant