Skip to content

fix: crash-safe WAV headers + orphaned-chunk recovery (#79)#80

Merged
fmasi merged 1 commit into
mainfrom
fix/wav-header-crash-recovery
Jun 15, 2026
Merged

fix: crash-safe WAV headers + orphaned-chunk recovery (#79)#80
fmasi merged 1 commit into
mainfrom
fix/wav-header-crash-recovery

Conversation

@fmasi

@fmasi fmasi commented Jun 14, 2026

Copy link
Copy Markdown
Owner

Fixes #79.

Problem

WavFileWriter only patched the real size/format into the header in finalize(); the 0.5 s periodic sync flushed audio data but never the header. When the capture service is killed mid-chunk (crash-recovery path), finalize()/swapWriters() never runs on the active writers, leaving valid PCM behind a placeholder "0-frames" header. The chunk then reads as empty → 0 transcript segments → archive step skipped → orphaned WAVs dropped from the transcript.

Discovered on the 2026-06-12 session: chunk 0's two 152 MB WAVs survived un-archived and ~26 min of real two-way conversation was missing from the transcript.

Fix

  • WavFileWriter.flushHeader() — patches the header in place; syncIfNeeded() now calls it every 0.5 s so a crash leaves a readable WAV (loss bounded to the last sync interval). finalize() reuses it.
  • WavFileWriter.repairHeader(path:) — static recovery that rebuilds the RIFF/data size fields of a WAV whose header underreports its payload, preserving the format block; returns whether it changed anything.
  • ChunkProcessor.transcribeStream — calls repairHeader defensively before reading each chunk WAV, so crash-orphaned chunks self-heal.

Tests

  • 3 new WavFileWriterTests (flush-without-finalize, repair underreported size, leave consistent file unchanged).
  • Full suite 464/464 green.
  • scripts/test-checklist.md updated with a crash-recovery manual test.

Related (adjacent, not duplicate)

Verification status

⚠️ Not yet manually verified on a live recording. Holding for a real crash-recovery test tomorrow before merge.

🤖 Generated with Claude Code

WavFileWriter only patched the real size/format into the header in
finalize(); the 0.5s periodic sync flushed data but not the header. A
capture service killed mid-chunk left valid PCM behind a placeholder
"0-frames" header, so the chunk read as empty, was skipped by archival,
and dropped from the transcript (~26 min lost in the 2026-06-12 session).

- WavFileWriter.flushHeader(): patch header in place; syncIfNeeded() now
  calls it every 0.5s so a crash leaves a readable WAV. finalize() reuses it.
- WavFileWriter.repairHeader(path:): static recovery that rebuilds the
  RIFF/data size fields of an under-reporting header, preserving the format
  block; returns whether it changed anything.
- ChunkProcessor.transcribeStream: repair each chunk WAV before reading it,
  so crash-orphaned chunks self-heal.
- 3 new WavFileWriterTests; full suite 464/464 green.
- scripts/test-checklist.md: crash-recovery manual test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@fmasi fmasi merged commit a165788 into main Jun 15, 2026
1 check passed
@fmasi fmasi deleted the fix/wav-header-crash-recovery branch June 15, 2026 13:36
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.

bug: WAV header never finalized on crash → orphaned chunk reads as empty, lost from transcript

1 participant