Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
39a511f
fix(hotkey): don't consume LWin keyup — kept Win stuck-down in OS state
devangk003 May 16, 2026
dc7a292
Phase 8 pill polish: full PILL_DESIGN.md + drag + multi-monitor sticky
devangk003 May 16, 2026
39b0748
Phase 9: MainWindow + 6 tabs + theming + pill flips with theme
devangk003 May 16, 2026
e2064b6
Phase 10: Onboarding modal — 7 steps + first-launch trigger
devangk003 May 16, 2026
dd3a399
Phase 11 + UX audit W1: crash reporter, egress killswitch, sidebar bi…
devangk003 May 16, 2026
65484f2
UX audit W2: design-system extraction (typography, dot, button, focus…
devangk003 May 16, 2026
c0729ff
UX audit W3: missing UX — history search/purge, log clear, model down…
devangk003 May 16, 2026
7b66456
UX follow-up: History as a table · pill Settings → Preferences · spac…
devangk003 May 17, 2026
a010d16
UX audit Round 2: tokens, surfaces, expanded typography, History sing…
devangk003 May 17, 2026
3fe3598
About tab: byline + 4 social icons · Models/About card spacing · 1px→8px
devangk003 May 17, 2026
2c7a69d
Sentry: forward unhandled exceptions to CaptureException
devangk003 May 17, 2026
eb1a5c3
Fix: OnboardingWindow black corners + model download pinned to real H…
devangk003 May 17, 2026
e835f5c
Audio tab: fix mic-always-on + add LIVE indicator + restore Test tran…
devangk003 May 17, 2026
ce40039
History hover-actions + Models redesign (action buttons, no radios)
devangk003 May 17, 2026
e5d37fe
Audio: input-device picker — user-selectable microphone
devangk003 May 17, 2026
f4d2413
Audio mic picker: fix dropdown lag (remove DropShadowEffect + per-ope…
devangk003 May 17, 2026
e1fdad4
Pill Phase 1: chrome restructure — dock drawer + pin + magic-wand but…
devangk003 May 17, 2026
2676b6f
Pill Phase 2: idle content swaps to visualizer + IDLE label on hover
devangk003 May 17, 2026
ee8f7b9
Pill Phase 3: breath + hue drift animations · Accessibility toggle
devangk003 May 17, 2026
a3faad4
Pill Phase 4: light-theme mint gradient on visualizer bars
devangk003 May 17, 2026
eae11fc
Pill follow-ups: 6 bug fixes (center-expand, height recovery, picker,…
devangk003 May 17, 2026
54b4ae9
Pill follow-ups round 2: black strips + picker lag + audio tab lag
devangk003 May 17, 2026
82654ed
Pill: pin = compact-mode toggle + mint idle wordmark
devangk003 May 17, 2026
8e102a3
Tray redesign + record-toggle wiring + nudge fix
devangk003 May 17, 2026
7e4b69f
Pill UX polish: BETA labels + pin lock + audit pass
devangk003 May 17, 2026
3dd6a2c
Default theme dark + Light [BETA] + onboarding step 6 = real dictation
devangk003 May 17, 2026
d94bb30
Roadmap: add R1.2-10 long-mode chunk-on-VAD streaming on second hotkey
devangk003 May 17, 2026
26b41c3
Onboarding step 3: mic chooser dropdown + CLAUDE.md deviation log update
devangk003 May 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 40 additions & 9 deletions CLAUDE.md

Large diffs are not rendered by default.

1,774 changes: 1,774 additions & 0 deletions docs/APP_DESIGN.md

Large diffs are not rendered by default.

381 changes: 381 additions & 0 deletions docs/PILL_DESIGN.md

Large diffs are not rendered by default.

34 changes: 29 additions & 5 deletions docs/ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

| | |
|---|---|
| **Status** | Draft v0.2 |
| **Status** | Draft v0.3 |
| **Scope** | Items deliberately deferred from `PRD.md` |
| **Updated** | 2026-05-16 (v0.2: code signing made permanent non-goal; auto-update demoted; minor priority shifts for friends-only audience) |
| **Updated** | 2026-05-17 (v0.3: added R1.2-10 long-mode chunk-on-VAD streaming on a second hotkey per dogfood UX request) |

This file is the **deferred-work log** for KusPus. Items here were considered during v1.0 design and intentionally pushed out. Each entry includes: what it is, why it was deferred, and what triggers it being scheduled.

Expand Down Expand Up @@ -110,6 +110,29 @@ Themes: things that don't fix bugs but build trust and reduce friction for a wid
- **What:** Build on R1.1-02. Add common European languages once Hinglish is shipped.
- **Trigger:** Tester demand. Mostly a model-manager UI change.

### R1.2-10 — Long-mode chunk-on-VAD continuous transcription (second hotkey)
- **What:** Add a second hotkey (default `Ctrl+Shift+LWin`) that enters a "long-mode" recording state. Mic stays open; Silero VAD on the live stream detects natural pauses (>=600 ms silence after speech); each detected utterance is handed to `whisper.exe` and pasted into whatever's currently focused. Loop continues until the user presses the long-mode hotkey again. Existing `Ctrl+Win` push-to-talk behaviour is unchanged.
- **Why deferred from v1:** ~2 weeks of focused build + iterate. v1's dogfood pass should validate the single-utterance UX first; layering streaming on top before the base is solid would blur which behaviour is the source of any bug.
- **Why valuable:** Dogfood feedback from author — long-form dictation (writing prose, code comments, Slack threads) feels constrained by the one-utterance-at-a-time push-to-talk model. Streaming with paste-on-pause removes the "remember-to-release" friction without changing the trust model (still local-first, still subprocess whisper).
- **Architecture (recommended after research, 2026-05-17):** chunk-on-VAD, NOT sliding-window. VAD runs in-process; whisper.exe stays subprocess; pastes are serialized. See https://github.com/Sharrnah/whispering for the closest reference impl.
- **Cluster plan (each ~0.5–2 days):**
1. Settings — add `LongModeHotkey` to `HotkeySettings`, default `Ctrl+Shift+LWin`, MainWindow listen+rebind UI mirrors existing hotkey card.
2. HotkeyEngine — support a second chord, new `LongModeChordEngaged` event into Coordinator.
3. Silero VAD plumbing — `ManySpeech.SileroVad` NuGet (MIT, .NET-friendly ONNX wrapper). `VadGate` processes 30 ms frames from the live audio stream, emits `SpeechStart`/`SpeechEnd` after a configurable hangover.
4. AppCoordinator streaming branch — new FSM transitions: `Idle + LongModeToggle → Streaming → chunk-on-VAD loop`. Serialized paste queue so chunk N+1 can't beat chunk N to the foreground.
5. Whisper warm-pool — keep one `whisper.exe` per session alive, pipe wav-per-chunk over stdin (or via a temp-file watch). Claws back ~150 ms spawn lag per chunk.
6. Pill UI variant — "STREAMING · CTRL+SHIFT+WIN TO STOP" label, brighter accent + slower breath so the user sees state.
7. Hallucination filter — min chunk 1.0 s, VAD-confidence integral floor, phrase blacklist for known whisper artifacts ("Thanks for watching", "Subtitles by …"), `--no-context --temperature 0` flags, foreground-HWND sanity check before paste (queue if it changed mid-utterance).
8. Manual milestone test — author walks long-form dictation scenarios (article writing, Slack thread, code comment block); iterate on hallucination filter + boundary handling based on what surfaces.
- **Top 3 risks:**
1. Whisper hallucinations on near-silent chunks land in the user's doc — high-visibility ("Thanks for watching" pasted into Slack). Mitigated in cluster 7 but never fully eliminated.
2. Mid-word VAD cuts on breath pauses ("trans-action"). Mitigated with 200 ms padding + `--prompt` previous-tail; expect one visible glitch per long session anyway.
3. Paste-into-wrong-app when user alt-tabs mid-utterance. Mitigated by foreground-HWND check at chunk-emit time.
- **Realistic latency:** ~0.7–1.0 s perceived after each pause with tiny.en on a modern CPU. Not instant; comparable to Wispr Flow push-to-talk responsiveness.
- **Trigger for promotion:** Author finishes dogfood pass on v1.0 push-to-talk AND still wants this OR ≥ 2 testers ask for "let me keep talking" UX.
- **Alternative considered + rejected (for now):** "Option A" soft-cap auto-flush (paste at 30 s OR first long pause after 10 s while keeping toggle-recording UX). Simpler, lower risk; rejected because dogfood feedback specifically asked for the speak-pause-paste loop, not a long-recording survival aid. If R1.2-10 proves too costly during implementation, fall back to this.
- **Cost estimate:** ~2 weeks build + 1 week dogfood + bug-tail.

---

## v1.3 — "ARM64 + GPU diversity"
Expand Down Expand Up @@ -159,9 +182,10 @@ Themes: things that don't fix bugs but build trust and reduce friction for a wid
- **What:** Reserved keywords that trigger app actions ("new line", "clear", "undo"). Local pattern match before whisper.
- **Why long-term:** Crosses from "dictation tool" into "voice assistant" — different product.

### LT-07 — Streaming transcription (partial results)
- **What:** Show transcript text appearing in real-time while user holds the chord, using whisper.cpp streaming mode.
- **Why long-term:** UX improvement; significant rework of the WhisperRunner; loss of the current "transcribe-on-release" simplicity.
### LT-07 — Streaming partial-results UI (separate from R1.2-10)
- **What:** Show transcript text appearing in real-time *while user holds the chord*, using whisper.cpp's sliding-window `examples/stream/stream.cpp` mode (`--step/--length/--keep`). Text mutates as the model revises — useful as a live caption overlay, NOT for paste-into-app.
- **Why long-term:** Different architecture from R1.2-10 (sliding-window vs chunk-on-VAD). Distinct UX value (visible live feedback in the pill) but emits unstable text — you can't un-paste a token whisper later revises. So this is a viewer feature, not a paste pipeline.
- **Why deferred indefinitely:** R1.2-10 covers the "continuous paste" use case via chunk-on-VAD. Sliding-window is only valuable if you want the *visible-text-mutating-in-pill* affordance, which is a separate UX hypothesis worth testing only after R1.2-10 ships and we see whether testers want more.

### LT-08 — LLM post-processing (opt-in)
- **What:** After transcription, optionally pipe text through a local LLM (Ollama / llama.cpp) for cleanup: filler-word removal, punctuation fix, capitalization.
Expand Down
Binary file added icons/icon-error.ico
Binary file not shown.
66 changes: 66 additions & 0 deletions icons/icon-error.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added icons/icon-idle.ico
Binary file not shown.
50 changes: 50 additions & 0 deletions icons/icon-idle.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added icons/icon-recording.ico
Binary file not shown.
56 changes: 56 additions & 0 deletions icons/icon-recording.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added icons/icon.ico
Binary file not shown.
50 changes: 50 additions & 0 deletions icons/icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 19 additions & 0 deletions icons/social/LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Social icons — attribution

Icons saved here as source-of-truth for the brand glyphs rendered in the
KusPus About tab footer. The actual rendering inlines the path data into
MainWindow.xaml (via `<Path>` elements with `Fill="{DynamicResource MutedText}"`)
so they theme-tint cleanly with dark/light mode — these `.svg` files exist
for licensing attribution and as the canonical source if the inline path
data ever needs to be re-synced.

| File | Source | License |
|--------------|----------------------------------------------------------------|---------|
| linkedin.svg | https://simpleicons.org/?q=linkedin (simple-icons npm package) | CC0-1.0 |
| x.svg | https://simpleicons.org/?q=x (simple-icons npm package) | CC0-1.0 |
| github.svg | https://simpleicons.org/?q=github (simple-icons npm package) | CC0-1.0 |
| globe.svg | https://lucide.dev/icons/globe (lucide-icons) | ISC |

All four icons use a 24×24 SVG viewBox. LinkedIn / X / GitHub are filled
paths (single `<path>` element). Globe is stroke-based (circle + 2 paths,
2 px stroke, round caps/joins) per Lucide's house style.
1 change: 1 addition & 0 deletions icons/social/github.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions icons/social/globe.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions icons/social/linkedin.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions icons/social/x.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 16 additions & 1 deletion src/KusPus.App/App.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,20 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
ShutdownMode="OnExplicitShutdown">
<Application.Resources/>
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- Design-system style sets (APP_DESIGN §13.5 P1-6 / P1-7 / P1-1).
Order matters: later dictionaries can reference earlier keys. -->
<!-- Tokens FIRST so later dictionaries can resolve Space.* / Pad.* / Radius.*. -->
<ResourceDictionary Source="Styles/Tokens.xaml"/>
<ResourceDictionary Source="Styles/Typography.xaml"/>
<ResourceDictionary Source="Styles/Dot.xaml"/>
<ResourceDictionary Source="Styles/Focus.xaml"/>
<ResourceDictionary Source="Styles/Buttons.xaml"/>
<ResourceDictionary Source="Styles/Surfaces.xaml"/>
<ResourceDictionary Source="Styles/Inputs.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
Loading
Loading