Repository navigation
refactor: split the Recorder into Capture, Transcription and Publication - #121
Merged
Merged
Conversation
ChristopherPHolder
enabled auto-merge (squash)
October 31, 2026 10:57
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.
What and why
Closes #114.
The Recorder was one 1,200-line closure doing four jobs, and its only interface was the layer it runs as, so every fix and every test went through all of it. The last three fixes (#110, #111, #112) all landed there. It's now four modules:
Publication: takes a stopped recording to Finished or Silent. It waits for the clips, writes the summary and action items, posts once (fix: post a recording's summary to Slack only once #112), rewrites on request and keeps the Slack post current.catchUppicks up unfinished recordings, missing permalinks and waiting rewrites after a restart. It ownsSummaryRewriter.Transcription: the pending-clip loop. It takes audio from memory or the archive and waits out Whisper's daily limit. It owns the in-memory audio (ClipAudio).Capture: begins, pauses and ends capture for the running recording, saves each clip (keeping the ones still being saved on stop or pause, fix: keep the clips still being saved when a recording stops or pauses #110), and knows who is speaking.Recorder: acts on recording requests and edits, follows the office, publishes the recording status and runs the loops (fix: notice when one of the recorder's background loops dies #111). It's down to about 340 lines.The code moved as it was. Behaviour doesn't change, apart from span names (
Recorder.finishis nowPublication.finish, and so on). The Slack channel is still read when the Recorder starts, so missing config still fails startup.I left
RecordingStorein one piece for now. #118 and #119 change how it's guarded and how it selects by state, and it's easier to split once those are in.How I tested it
FINISH_POLLandFINISH_RETRYfromPublication.Publication: posts once with the transcript and finishes; a recording nobody spoke in finishes without a post; posts once when finishing fails after the post; refreshes the post after an edit;catchUpfinishes what was left and doesn't post twice.Transcription: audio from memory, audio from the archive, and giving up on a clip with no audio.Capture: saves clips and queues them; skips clips that are too short; keeps the clip being saved when capture ends; listening, paused and off modes; who is speaking.pnpm vp run cipasses.docs/architecture.mdlists the new modules.Checklist
vp run cipasses