Skip to content

feat(app): re-open speaker naming on finished jobs (late re-naming recovery)#337

Open
pasrom wants to merge 1 commit into
mainfrom
worktree-late-speaker-renaming-recovery
Open

feat(app): re-open speaker naming on finished jobs (late re-naming recovery)#337
pasrom wants to merge 1 commit into
mainfrom
worktree-late-speaker-renaming-recovery

Conversation

@pasrom

@pasrom pasrom commented May 25, 2026

Copy link
Copy Markdown
Owner

Summary

Adds a recovery path for the speaker-naming dialog auto-confirm bug: the dialog sometimes confirms before the user names speakers (a stray Enter/Cmd-W while another app holds focus). PR #310 shipped prevention (a 750 ms keyboard-shortcut grace); this PR adds the recovery that prevention can't fully cover.

A finished (.done) meeting that retains its naming data now shows an "Edit Speaker Names" button in the menu-bar job row. Clicking it re-opens the naming dialog so the user can name speakers — or re-run diarization — after the fact.

How it works

  • Retain the naming sidecar — Confirm/Skip now free only the in-RAM caches (clearNamingCaches); the persisted _naming.json + audio sidecars stay on disk. Full deletion (removeNamingData) happens only on explicit Dismiss or cancel. This mirrors what the app already does with every recording: the original _mix.wav/_app.wav/_mic.wav are kept in recordings/ indefinitely, so the (small) naming data simply lives alongside them rather than being reaped on its own.
  • Don't auto-remove retained jobs — a .done job that retains a sidecar (signalled by a non-nil namingSlug) is no longer auto-removed from the menu after completedJobLifetime, so the affordance stays reachable. Jobs that never produced naming data keep the original ~60 s auto-clear.
  • Re-open affordancereopenSpeakerNaming(jobID:) reloads the retained data (RAM, else from disk) and flips .done → .speakerNamingPending, reusing the existing .showSpeakerNaming path. Confirming folds the applied names back into the sidecar (persistAppliedNames) so a second re-name anchors on the current transcript labels instead of the original auto-names.
  • Log recognition once per job — a re-opened + re-confirmed job no longer writes a second recognition-stats row whose suggested baseline is the already-applied names (a phantom perfect match).

Scope / limitations

  • Recovery is in-session: .done jobs are dropped from the snapshot on relaunch, so the menu affordance does not survive an app restart. The retained sidecar stays on disk (alongside the recordings the app already keeps), so a future "recent recordings" browser could surface it — intentionally out of scope here.
  • Finished diarized meetings now persist in the menu until Dismiss, where previously they auto-cleared after ~60 s. This is the deliberate tradeoff that keeps the re-name affordance reachable.

Tests

  • 9 new tests across PipelineQueueTests + MenuBarViewTests: deferred-delete, Dismiss cleanup, auto-remove gating (retained vs not), reopen transition / no-op / RAM-vs-disk, applied-name persistence for repeat re-name, and the "Edit Speaker Names" button visibility + callback.
  • Full PipelineQueueTests and MenuBarViewTests green; SwiftLint clean; release-build parity check passes.

Follow-up (noted, not in this PR)

The retained _16k.wav is a downsampled duplicate of the _mix.wav the app already keeps forever; lateDiarization could regenerate it on demand from the original instead of retaining a separate copy, removing the duplicate entirely.

@github-actions github-actions Bot added the enhancement New feature or request label May 25, 2026
@codecov

codecov Bot commented May 25, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 79.9%. Comparing base (fd87e5e) to head (9a8a861).

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##            main    #337     +/-   ##
=======================================
+ Coverage   79.8%   79.9%   +0.1%     
=======================================
  Files         89      89             
  Lines       9074    9123     +49     
=======================================
+ Hits        7246    7297     +51     
+ Misses      1828    1826      -2     
Flag Coverage Δ
appstore 79.9% <100.0%> (+<0.1%) ⬆️
audiotap 95.6% <ø> (ø)
homebrew 79.0% <100.0%> (-0.2%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
app/MeetingTranscriber/Sources/MenuBarView.swift 95.6% <100.0%> (+0.1%) ⬆️
app/MeetingTranscriber/Sources/PipelineQueue.swift 90.1% <100.0%> (+0.3%) ⬆️

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Adds a recovery path for the speaker-naming auto-confirm bug: the dialog
sometimes confirms before the user names speakers (a stray Enter/Cmd-W
while another app holds focus). PR #310 shipped prevention (a 750 ms
keyboard-shortcut grace); this adds the recovery that prevention can't
fully cover.

A finished (.done) meeting that retains its naming data now shows an
"Edit Speaker Names" button in the menu-bar job row, which re-opens the
naming dialog so the user can name speakers — or re-run diarization —
after the fact.

What:
- Retain the naming sidecar: Confirm/Skip free only the in-RAM caches
  (clearNamingCaches); the persisted _naming.json + audio sidecars stay
  on disk. Full deletion (removeNamingData) runs only on explicit Dismiss
  or cancel. This mirrors what the app already does with recordings — the
  original _mix/_app/_mic WAVs are kept in recordings/ indefinitely, so
  the small naming data lives alongside them rather than being reaped.
- Don't auto-remove jobs that retain a sidecar (namingSlug != nil) so the
  affordance stays reachable; jobs without naming data keep the ~60 s
  auto-clear.
- reopenSpeakerNaming(jobID:) reloads the data (RAM, else disk) and flips
  .done -> .speakerNamingPending via the existing .showSpeakerNaming path.
- persistAppliedNames folds confirmed names into the sidecar so a second
  re-name anchors on the current transcript labels, not the auto-names.
- Log recognition once per job (recognitionLoggedJobIDs) so a re-confirm
  doesn't write a phantom perfect-match stats row.

Reasoning:
- Recovery is in-session: .done jobs are dropped from the snapshot on
  relaunch, so the menu affordance doesn't survive a restart (the retained
  sidecar persists on disk for a future "recent recordings" surface).
- Finished diarized meetings now persist in the menu until Dismiss — the
  deliberate tradeoff that keeps the re-name affordance reachable.
@pasrom pasrom force-pushed the worktree-late-speaker-renaming-recovery branch from b2cec88 to 9a8a861 Compare May 25, 2026 16:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant