Repository navigation
Conversation
added 4 commits
November 12, 2026 11:36
When the provider cannot generate the meeting notes (a signed-out Claude CLI, a timeout, an HTTP error), the job still finishes with its transcript and the warning "Protocol generation failed — transcript saved". The only notification was "Transcript Saved", which reads like success, so a signed-out CLI went unnoticed for weeks while every meeting lost its notes. The job now keeps the provider's message as protocolFailure, and the done notification for such a job reads "Meeting Notes Failed" with the reason, time-sensitive since the user can still act on it. A signed-out Claude CLI also gets the hint to sign in with /login. "Notify when meeting notes fail" in Settings > Output turns it off; it is on by default. The message is already content-free (see the catch in generateProtocol), so it can go into a notification as it is.
….swift A pure move, no change: DebugRPCServer.swift is at the file_length limit, and the next commit adds a route family that needs three lines there.
A job whose notes could not be generated now stays in the menu, past the 60-second cleanup and across a relaunch, with Retry Meeting Notes, and Retry All Meeting Notes (N) from two such jobs. The retry generates the notes from the saved transcript through the protocol-only resume, so the meeting is not transcribed again, and it never overwrites notes that already exist next to the transcript. The automation API gets the same: POST /v1/jobs/<id>/notes/retry and POST /v1/jobs/notes/retry.
Generate Meeting Notes from Transcript... in the menu takes one or more
.txt transcripts and queues a notes-only job for each: no transcription,
the notes saved next to the transcript as <name>.md, and the transcript
itself never removed or renamed. A transcript that already has notes is
skipped and named in a notification; nothing is queued while the notes
provider is None.
The automation API gets the same: POST /v1/jobs/notes/generate with
{"paths": [...]}.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Requested by Mick
What changed and why
Builds on #970 (retry meeting notes), which builds on #969; review the last commit,
feat(app): generate meeting notes from saved transcripts. It reuses #970'sMeetingNotesActionsandDebugRPCServer+MeetingNotes.swift, so on its own it would conflict with it.A retry needs the job, and the job is gone for a meeting from before the app kept failed ones, or one that was dismissed. Its transcript is still in the notes folder. This makes notes for transcripts the user picks, several at once, and offers the same over
/v1.Menu bar Process Audio/Video Files... ⌘P + Generate Meeting Notes from Transcript...Change
PipelineQueue.enqueueNotes(fromTranscripts:)queues one job per.txt, in order, withPipelineJob.generatesNotesOnly,transcriptPathandnamingSlugset to the file and its name, andmeetingStartTimefrom a leadingyyyyMMdd_HHmm, so the prompt gets the meeting date. A transcript with a.mdof its name next to it is left out (notesExist), as is one that is not a.txtor cannot be read (unreadable).runPipelinesends such a job togenerateNotesOnly, right after the protocol-only resume and ahead of the engine guard, so it never transcribes, also after a relaunch. It checks again before generating: notes written, or the transcript gone, while the job waited end it in an error, never in an overwrite or a full run.PipelineController.generateNotes(fromTranscripts:)(newPipelineController+MeetingNotes.swift) refuses while the provider is None, since the jobs would end without notes, and names skipped files in a notification.settingsandnotifieronPipelineControllerwent fromprivateto internal for it.A11yID.generateNotesFromTranscriptButton), anNSOpenPanelfor plain text with multiple selection, starting in the output folder./v1:POST /v1/jobs/notes/generatewith{"paths": [...]}: 200 withjobIDs,notesExistandunreadable, 400 without paths, 409 while the provider is None.docs/automation-api.md,docs/architecture/pipeline.md,docs/architecture-macos.md, README features.Tests
PipelineQueue+Stages.swift:230,job.generatesNotesOnly == trueset to== falseNotesFromTranscriptTests.testEachTranscriptGetsItsNotesWithoutTranscribingPipelineQueue+MeetingNotes.swift:141,job.generatesNotesOnly = trueset tonilNotesFromTranscriptTests.testEachTranscriptGetsItsNotesWithoutTranscribingPipelineQueue+MeetingNotes.swift:137,saveRawTranscriptSeparately: true, useAITitleForFilenames: falseset tonil, nilNotesFromTranscriptTests.testThePickedTranscriptIsNeitherRemovedNorRenamed(queue with the other two values)PipelineController+MeetingNotes.swift:16,!= .noneset to!= .openAICompatibleNotesFromTranscriptTests.testWithoutANotesProviderNothingIsQueuedAndTheUserIsToldAppState+RPC.swift:250, thegenerate:line removedNotesFromTranscriptTests.testTheAppWiresTheV1GenerateToItsControllerMenuBarView.swift:211,onGenerateNotesFromTranscripts()set toonProcessFiles()NotesFromTranscriptTests.testTheMenuItemAsksForTranscriptsDebugRPCServer+MeetingNotes.swift:55, thegenerateMeetingNotesPathmatch changed to a path that never occursNotesFromTranscriptTests.testV1GenerateAnswersWithWhatWasQueuedAndLeftOutMeetingTranscriberApp.swift:210(onGenerateNotesFromTranscripts: generateNotesFromTranscripts) and theNSOpenPanelitself, which the tests cannot reach (manual QA perdocs/architecture/gui-testing.md; tried by hand in a local build). The App Store build: not tried; under the sandbox a picked file grants access to that file, and I did not measure whether writing the.mdbeside a transcript outside the output folder is allowed there.Also: notes written while the job waited are not overwritten, a waiting job still makes only notes after a relaunch, the stamp parsing, and the skipped-files notification.
AI assistance
Checklist
main, no merge commits, since a merge commit pulls commits that arealready on
maininto this branch and the review reads it commit by commit:git fetch https://github.com/pasrom/meeting-transcriber main && git rebase FETCH_HEAD(the URL spelled out because in a fork clone
originis your fork)./scripts/lint.shis clean, and./scripts/lint.sh --analyzetoo (CI runs both)cd app/MeetingTranscriber && swift test(
MenuBarIconSnapshotTestscompare pixels and depend on the macOS version, so CIskips them; if only they fail, add
--skip MenuBarIconSnapshotTestsand tick this)