Skip to content

refactor: split the Recorder into Capture, Transcription and Publication - #121

Merged
ChristopherPHolder merged 1 commit into
mainfrom
refactor/split-recorder
Oct 31, 2026
Merged

ChristopherPHolder merged 1 commit into
mainfrom
refactor/split-recorder

Conversation

@ChristopherPHolder

Copy link
Copy Markdown
Collaborator

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. catchUp picks up unfinished recordings, missing permalinks and waiting rewrites after a restart. It owns SummaryRewriter.
  • 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.finish is now Publication.finish, and so on). The Slack channel is still read when the Recorder starts, so missing config still fails startup.

I left RecordingStore in 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

  • The existing Recorder tests pass unchanged, apart from importing FINISH_POLL and FINISH_RETRY from Publication.
  • New tests run through each module's own interface, against PGlite with the real migrations:
    • 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; catchUp finishes 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 ci passes.
  • docs/architecture.md lists the new modules.

Checklist

  • vp run ci passes
  • Tests cover the change
  • Docs updated if what gets posted, the configuration, the Console or the deploy changed (module table only)
  • New environment variables are wired through (none)
  • Ready to ship: merging this deploys it to production

@ChristopherPHolder
ChristopherPHolder enabled auto-merge (squash) October 31, 2026 10:57
@ChristopherPHolder
ChristopherPHolder merged commit a06f877 into main Oct 31, 2026
2 checks passed
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.

Split the Recorder into Capture, Transcription and Publication

1 participant