Skip to content

fix: route all Home/meeting own-file access through one resilient resolver (stop the reveal/delete whack-a-mole)#1137

Draft
r3dbars wants to merge 2 commits into
mainfrom
hardening/home-meeting-own-file-resolver
Draft

fix: route all Home/meeting own-file access through one resilient resolver (stop the reveal/delete whack-a-mole)#1137
r3dbars wants to merge 2 commits into
mainfrom
hardening/home-meeting-own-file-resolver

Conversation

@r3dbars

@r3dbars r3dbars commented Jun 16, 2026

Copy link
Copy Markdown
Owner

Why

The Home/meeting three-dots menu has been a string of dead controls patched one PR at a time — #1126 (delete confirmation), #1131 (delete-failure alert), #1134 (reveal/delete stale paths). They share one root cause: every Home/meeting control holds the file URL captured when the dashboard was last scanned, but background work moves those files afterward — the post-save restyle renames the transcript and its audio/<stem>_audio/ bundle, a preview rename moves the transcript + summary sidecar, and retained audio is recompressed WAV→M4A. A raw activateFileViewerSelecting / NSWorkspace.open / NSSound(contentsOf:) on a stale path silently no-ops — the "Show … in Finder does nothing / works on one machine but not another" reports.

This generalizes #1134's HomeArtifactRevealResolver into a single resolver every own-file access routes through, so a drifted path surfaces an error instead of a dead click — and a re-introduced dead control fails CI.

Note: based on origin/main (pre-#1134, which is still open). #1134's reveal/delete fixes are subsumed here; if #1134 lands first this will need a trivial rebase in TranscriptedSettingsView.swift.

What

OwnFileResolver (Sources/UI/Shared/OwnFileResolver.swift) — two intent-specific modes:

  • resolveForReveal: existing → stem-rematch (WAV→M4A) → enclosing folder → .unavailable. Revealing a folder beats a dead click.
  • resolveExistingFile / resolveExistingFiles: existing → stem-rematch only, no directory fallback (you can't open/read/play a folder). Returns nil so the caller surfaces an error.

Every Home/meeting control routed through it, each surfacing a failure alert instead of a silent no-op / NSSound.beep:

  • reveal in Finder: meeting transcript, meeting audio, failed-meeting audio, dictation
  • open: meeting preview, summary notice, enhanced transcript, current-activity card, dictation row + menu
  • copy-for-agent & re-transcribe: resolve the source first, error if missing
  • retained-audio playback: resolve each source so recompressed audio still plays
  • meeting-preview read: follow a drifted transcript instead of erroring

Delete deliberately does NOT use the lenient resolver — stem/folder fallback could remove the wrong file. Instead it detects a no-op delete on a stale path and surfaces it (port of #1134) so the row never silently reappears.

Tests (a dead control / broken own-file path fails CI)

  • OwnFileResolverTests — temp-dir behavioral coverage of both modes: direct hit, WAV→M4A stem rematch, enclosing-folder fallback, no-dir-fallback for open, multi-file drop-missing, dedup, unavailable.
  • UIAutomationSurfaceContractTests — assert every reveal/open/delete/playback site routes through OwnFileResolver and no raw stale-path NSWorkspace call remains.
  • RepoCommandContractTests — strengthened the delete gate to require the stale-path no-op detection.

Fast suite: 5441 passed, 0 failed (bash run-tests.sh).

Proof still needed

  • Full app build (bash build.sh) requires prebuilt SPM deps not present in this fresh worktree (build-deps.sh); compiled in CI. The fast suite compiles OwnFileResolver and all contract gates pass.
  • Manual UI smoke: rename/restyle a meeting, then exercise Show-in-Finder / Open / Re-transcribe / Delete from the row menu and confirm each either follows the file or shows an error alert (never a dead click).

Scope

Confined to Home/meeting interaction + the app's own-file resolution + tests. No audio-capture, pipeline, or dependency changes. No existing test weakened (the one delete-block assertion was updated to match the refactor and strengthened with the no-op gate).

r3dbars and others added 2 commits June 15, 2026 21:49
…t resolver

The Home/meeting three-dots menu had a string of dead controls patched one PR
at a time (#1126 delete confirmation, #1131 delete-failure alert, #1134
reveal/delete stale paths). The root cause is shared: every Home/meeting
control holds the file URL captured when the dashboard was last *scanned*, but
background work moves those files afterward (post-save restyle renames the
transcript + its audio bundle, a preview rename moves transcript/summary,
retained audio is recompressed WAV→M4A). A raw
activateFileViewerSelecting / NSWorkspace.open / NSSound(contentsOf:) on a
stale path silently no-ops — the "Show … in Finder does nothing" reports.

Generalize #1134's HomeArtifactRevealResolver into one OwnFileResolver that
every own-file access routes through, with two intent-specific modes:

  - resolveForReveal: existing → stem-rematch (WAV→M4A) → enclosing folder →
    .unavailable. Revealing a folder beats a dead click.
  - resolveExistingFile / resolveExistingFiles: existing → stem-rematch only,
    no directory fallback (you can't open/read/play a folder). Returns nil so
    the caller surfaces an error.

Wire every Home/meeting control through it and surface a failure alert instead
of a silent no-op / NSSound.beep:
  - reveal in Finder: meeting transcript, meeting audio, failed-meeting audio,
    dictation
  - open: meeting preview, summary notice, enhanced-transcript, current-activity
    card, dictation row + menu
  - copy-for-agent and re-transcribe: resolve source first, error if missing
  - retained-audio playback: resolve each source so recompressed audio plays
  - meeting preview read: follow a drifted transcript
Delete deliberately does NOT use the lenient resolver (stem/folder fallback
could remove the wrong file); instead it detects a no-op delete on a stale path
and surfaces it (port of #1134) so the row never silently reappears.

Tests:
  - OwnFileResolverTests: temp-dir behavioral coverage of both modes (direct
    hit, WAV→M4A stem rematch, folder fallback, no-dir-fallback for open,
    multi-file drop-missing, dedup, unavailable).
  - UIAutomationSurfaceContractTests: assert every reveal/open/delete/playback
    site routes through OwnFileResolver and no raw stale-path NSWorkspace call
    remains — a re-introduced dead control fails CI.
  - RepoCommandContractTests: strengthen the delete gate to require the
    stale-path no-op detection.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…olution

input.micURL is URL? and input.systemURL is URL — resolve the optional mic
track when present and require the system track to resolve, surfacing an error
if the required source drifted off disk.

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