Skip to content

[9/12] refactor: rewire app services onto native stack (persistence, logging, audio, dictation, meetings, tray) - #18

Open
Mvkd108 wants to merge 10 commits into
feat/meeting-live-transcript-windowfrom
feat/rebuild-app-shell
Open

[9/12] refactor: rewire app services onto native stack (persistence, logging, audio, dictation, meetings, tray)#18
Mvkd108 wants to merge 10 commits into
feat/meeting-live-transcript-windowfrom
feat/rebuild-app-shell

Conversation

@Mvkd108

@Mvkd108 Mvkd108 commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Status: REVIEW ONLY — do not merge. PR 9 of 12 in a stacked series; stacked on #17. This PR shows only its own chunk. Series intro, divergence notes and full map: #10. Next: #19.

This PR (9/12): rewire app services onto the native stack

Commits:

  • c4b38c9 refactor: app data and settings onto atomic persistence — Services/AppDataStore.cs, Services/SettingsStore.cs
  • f4baa65 refactor: logging and runtime diagnostics for the native stack — Services/AppLogService.cs, Services/RuntimeDiagnosticsService.cs, docs/WINDOWS_PRIVACY.md
  • b781d04 refactor: microphone and system audio capture for streaming recognition — Services/AudioCaptureService.cs, Services/SystemAudioCaptureService.cs
  • 3c57865 refactor: dictation onto the native transcription client — Services/DictationCoordinator.cs, Services/ActiveAppPasteService.cs, Services/DictionaryCorrectionService.cs, Services/GlobalHotkeyService.cs
  • f3e01de refactor: meeting recording and detection onto the session lifecycle — Services/MeetingRecordingCoordinator.cs, Services/MeetingDetectionService.cs
  • 32e5942 refactor: meeting summary, export and prompt services — Services/MeetingSummaryService.cs, Services/MeetingExporter.cs, Services/MeetingPromptService.cs
  • 552cdd9 refactor: tray, toast and startup registration — Services/TrayIconService.cs, Services/ToastNotificationService.cs, Services/StartupRegistrationService.cs
  • 17fe008 feat: application identity, icon and manifest — app.manifest, Assets/muesli.ico, App.xaml
  • e5a6839 feat: rebuild application shell around single-instance startup and runtime qualification — App.xaml.cs

25 files, +5,196/−1,140.

Review focus

  • SettingsStore/AppDataStore — migration onto PR 2's atomic persistence; no torn writes on crash.
  • AudioCaptureService — reworked for streaming recognition; normalizes 1/2/>2-channel input to 16 kHz mono (this natively covers the "non-stereo mic crash" that was patched on main after this stack was cut — see PR 1 divergence notes).
  • RuntimeDiagnosticsService — surfaces CUDA/runtime readiness (covers the "Parakeet unavailable on non-NVIDIA" diagnostic intent from main).
  • DictationCoordinator + GlobalHotkeyService + ActiveAppPasteService — dictation now runs on the PR 3 native client via the PR 5 state machine.
  • App.xaml.cs — startup ordering: single-instance gate → runtime qualification → shell.

Expected — do not flag: MainWindow still runs the old pipeline here — PR 10 rebuilds it and removes the Python worker (TranscriptionWorkerClient is deleted there, not here). Dead-looking references are cleaned up in PR 10.

Test evidence

  • Full stack at tip: build clean (--no-restore); 484/484 passing.
  • Suite lands in PR 11; classes covering this chunk: CapturePrivacyAndRuntimeTests, ToastNotificationServiceTests, SecretsAndSettingsTests, Phase2DictationTests.

Previous: #17 | Next: #19

Copilot AI lite review requested due to automatic review settings August 4, 2026 09:04
@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: bf8f2309-06ba-4aa5-bc4f-a06bf2f25c7a

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Mvkd108 and others added 10 commits August 18, 2026 20:24
Rewrites AppDataStore and SettingsStore to persist through AtomicJsonFile
so a crash or power loss mid-write cannot truncate user settings, and
moves API keys behind the DPAPI secret store.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Reports on the native runtime, installed models and hardware instead of
the Python worker, and bounds log growth.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…cognition

Feeds capture buffers through the streaming PCM normaliser, journals
capture state for meeting recovery, applies the dictation temp-audio and
benchmark retention policies, and adds process-scoped loopback capture.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Switches the dictation coordinator off the Python worker and onto the
native client, adopts the hotkey gesture model and conflict probe, and
reworks dictionary correction and active-app paste around the new
pipeline output.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…cycle

Drives the recording coordinator through the explicit session state
machine with journalling, live transcription, gap recovery and audio
health monitoring, and moves detection onto the new URL parser, candidate
resolver and presence signals.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Aligns summarisation, PDF/markdown export and prompt handling with the
new transcript timeline and speaker aliases, and surfaces which provider
handled a summary.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Reworks tray state for the new runtime status, makes toasts placement
aware, and hardens startup registration.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Adds product/company/version metadata, the Muesli application icon and an
application manifest declaring per-monitor DPI awareness and the
supported Windows versions. Ships the privacy notice alongside the app
and exposes internals to the test assembly.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ntime qualification

Rewrites App startup to enforce single instance, qualify the native
runtime and models before the window opens, restore the model catalog and
lifecycle services, and route unhandled exceptions to the log.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Two disposal races surfaced as an "unexpected error" dialog on exit.

ToastNotificationService: DispatcherTimer.Stop() does not cancel a tick
already queued on the dispatcher, and WPF closes every window during
application shutdown while the service still held its _window reference.
The queued tick ran after teardown, reached ShowIndicator, and called
Show() on a closed Window, which WPF rejects. Nothing caught it, so it
reached the global unhandled-exception handler.

Guard with a _disposed flag set before Stop() and checked in both the
tick handler and ShowIndicator, and subscribe to Window.Closed so a
window closed by WPF clears the field and a fresh one is created rather
than a dead instance being reused.

DictationCoordinator: Dispose() disposed _gate while the global hotkey
was still live, so every subsequent keypress awaited a disposed
SemaphoreSlim. This logged ObjectDisposedException five or more times
per millisecond and left the dictation hotkey silently dead just before
the crash. StartAsync now returns early once disposed, and Dispose is
idempotent.

Verified over three graceful start/shutdown cycles plus a fresh launch:
Unhandled UI exception, "after a Window has closed",
ObjectDisposedException, and "Could not start dictation microphone" all
drop from repeated occurrences to zero, with no ERROR entries in the
fresh log slice. Full suite passes 484/484.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@Mvkd108
Mvkd108 force-pushed the feat/rebuild-app-shell branch from f370425 to 6516144 Compare August 18, 2026 15:02
@claude

claude Bot commented Aug 18, 2026

Copy link
Copy Markdown

Claude encountered an error after 4m 16s —— View job


Claude is reviewing this PR

Todo list

  • Gather context (PR description, changed files, CLAUDE.md)
  • Kick off /code-review — several of its background finder agents hit the session's API rate limit and failed, so falling back to a direct manual review of the diff
  • Manually review the diff against origin/feat/meeting-live-transcript-window
  • Post review feedback

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.

2 participants