Skip to content

fix: make Home meeting reveal/delete robust to stale row paths#1134

Draft
r3dbars wants to merge 1 commit into
mainfrom
fix/home-meeting-context-menu-actions
Draft

fix: make Home meeting reveal/delete robust to stale row paths#1134
r3dbars wants to merge 1 commit into
mainfrom
fix/home-meeting-context-menu-actions

Conversation

@r3dbars

@r3dbars r3dbars commented Jun 16, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes the per-meeting overflow (⋯) menu on the Home dashboard. The reveal-in-Finder and delete actions failed in the field because the row holds the file URLs captured when the dashboard was last scanned, and background work moves those files afterwards:

  • the post-save restyle renames a meeting transcript (and its audio/<stem>_audio/ bundle)
  • retained audio is recompressed from WAV → M4A after save

NSWorkspace.activateFileViewerSelecting(_:) silently no-ops on a missing path — that is the "Show … in Finder does nothing / works on one machine but not another" report. "Delete meeting" shared the root cause: a stale path means the deletion plan removes nothing, the row is optimistically hidden, then reappears on the next refresh with no explanation.

Context: PRs #1126 / #1131 fixed the delete alert plumbing (the confirmation now appears and fires deleteMeeting). The delete data layer (HomeMeetingDeletion) is solid and well-tested. This PR addresses the remaining real-world failure mode — path staleness — and makes every reveal action fail loud instead of silent.

Per-action findings

Action Status Finding
Show transcript in Finder Fixed Raw activateFileViewerSelecting([transcriptURL]) silently no-ops when the transcript was renamed by the restyle after scan. Now resolved + falls back to the meetings folder + surfaces an error.
Show audio in Finder Fixed Same silent no-op; "works on one machine not another" = WAV→M4A recompression state differs. Now stem-rematches the recompressed file, falls back to the audio bundle dir, or errors.
Delete meeting Hardened Alert + data layer already correct (#1126/#1131 + HomeMeetingDeletionTests). Added: surface a failure when the delete removed nothing while the file is still on disk (stale path) instead of silently re-showing the row.
Run AI summary By design (not broken) Disabled when localMeetingSummaryUnavailableReason != nil: app busy, or the local-summary beta provider isn't set up (Gemma needs uv + enough memory, or Apple on-device model unavailable). Whole item is also behind the beta opt-in.
Re-transcribe with speaker ID By design (not broken) Only shown when retained split audio exists; disabled while the app is busy or when there's pending speaker review (which redirects to the review flow).
Report issue Works Opens the feedback sheet; unchanged.

Fix

  • HomeArtifactRevealResolver (new, Foundation-pure, unit-tested): reveal files that still exist → else stem-rematch in the same directory (catches WAV→M4A) → else fall back to the enclosing folder → else .unavailable.
  • Transcript, meeting-audio, and failed-meeting-audio reveal actions now route through a shared revealMeetingArtifact(...) helper that presents a failure alert when nothing can be revealed.
  • deleteMeeting surfaces a failure on a no-op stale delete.

Tests

  • HomeArtifactRevealResolverTests — direct hit, partial existence, WAV→M4A stem rematch, renamed-transcript directory fallback, both unavailable cases. (6 cases, passing.)
  • Source-contract guards in UIAutomationSurfaceContractTests and RepoCommandContractTests pin the resilient wiring.
  • Full fast suite: 5424 passed, 0 failed. App builds clean (build.sh --no-open).

⚠️ Manual proof still needed

Reveal and delete are real-app behaviors that tests alone cannot prove. On a running build, on a real meeting, a human should click:

  1. Show transcript in Finder → Finder reveals the .md (or its folder if renamed).
  2. Show audio in Finder → Finder reveals the retained audio (force a WAV→M4A recompression case if possible).
  3. Delete meeting → confirm → the row disappears and stays gone after the list refreshes; the on-disk .md, .summary.md, and audio/<stem>_audio/ are removed.
  4. Trigger a stale-path case (rename/move a transcript outside the app, then use the still-open row) → each action should show an error alert, never a dead click.

Notes

  • App is not sandboxed (com.apple.security.app-sandbox = false), so this was never a security-scoped-bookmark problem.
  • Draft — do not merge.

🤖 Generated with Claude Code

The per-meeting overflow (⋯) menu's "Show transcript in Finder" and
"Show audio in Finder" actions called
NSWorkspace.activateFileViewerSelecting(_:) directly on the URLs captured
when the Home dashboard was last scanned. Those URLs go stale between scan
and click:
  - the post-save restyle renames a meeting transcript (and its
    audio/<stem>_audio/ bundle)
  - retained audio is recompressed from WAV to M4A after save

activateFileViewerSelecting silently no-ops on a missing path, which is the
"Show … in Finder does nothing / works on one machine but not another"
report. "Delete meeting" had the same root cause: a stale path means the
deletion plan removes nothing, the row is optimistically hidden, then
reappears on refresh with no explanation.

Fix:
- Add HomeArtifactRevealResolver (Foundation-pure, unit-tested): reveal the
  files that still exist; else stem-rematch in the same directory (catches
  WAV→M4A); else fall back to the enclosing folder; else report
  .unavailable so the caller surfaces an error instead of a dead click.
- Route the transcript, meeting-audio, and failed-meeting-audio reveal
  actions through a shared revealMeetingArtifact(...) helper that presents a
  failure alert when nothing can be revealed.
- deleteMeeting now surfaces a failure when it removed nothing while the
  transcript is still on disk (stale path), instead of silently re-showing
  the row.

Tests:
- HomeArtifactRevealResolverTests covers direct hit, partial existence,
  WAV→M4A stem rematch, renamed-transcript directory fallback, and the two
  unavailable cases.
- Source-contract guards in UIAutomationSurfaceContractTests and
  RepoCommandContractTests pin the resilient wiring.

The greyed-out "Run AI summary" and "Re-transcribe with speaker ID" items
are disabled by design (gated on the local-summary beta provider being set
up / app-busy state and on retained split audio + no pending speaker
review); they are not broken. "Report issue" already works. No behavior
change to those.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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