Repository navigation
fix(dictation): cap each debug journal; bound the journal registry (#1276) - #1301
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…istry (#1276) One press whose recorder ran 32.8 h (#1299) wrote a 1.196 GB journal, 96 % of it per-chunk and per-sample events. Past 16 MiB those high-frequency events are dropped (one marker says so); lifecycle, error and stop events still land. The registry now keeps at most 64 journals, flushing and evicting the oldest, since nothing ever disposed of them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…budget, a stable budget, awaited eviction - C / steering q29: one 'suppressed' marker erased the #1299 evidence (26 h of chunks and non-zero audio after deepgram:close). Past the budget the high-frequency events now fold into one summary line per minute (counts per kind, time span, last chunk index, peak stats), plus one before any kept event and on flush: ~430 KiB/day, bounded. - A/C: a writer re-created for an evicted press restarted its budget; it now starts from the file's size. - A/B: an eviction's flush was fire-and-forget and outside flushAll(); it is now awaited by the shutdown drain. - A: TRANSCRIPT preview:interim counts as high-frequency. - B: tests cover every classifier clause, ERROR/OUTCOME kept, exactly one marker, the #1299 tail, and both eviction paths. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…es, budget survives eviction, per-source chunk indexes - A2/B1: drain returned at once while a timed write was in flight, so a flush (eviction, quit) could finish before the batch landed. Drains are now chained and flush awaits the chain; the draining flag is gone. - A1: a writer re-created while the evicted one's write was in flight started from the smaller on-disk size. The registry keeps the evicted writer's accounted bytes until its flush lands. - A3: renderer/main count chunks from 0 and Deepgram from 1, so one merged max invented a missing chunk; lastChunkIndex is now per layer/event. - B2-B5: tests pin minute-scale summaries on disk before any flush, repeat counts and multiple peaks, the summary/close/summary order, the newest press never being evicted, and a blocked write at shutdown. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ess counts toward the budget One recorded count per press was wrong both ways: A's finalizer could delete B's entry, and if B's small write landed first, B's own finalizer removed the only entry while A's 16 MiB batch was still pending, so a third writer started below the budget and logged raw chunks. The registry now keeps each in-flight evicted writer's accounted bytes per press, takes the max on reopen, and each finalizer removes only its own. Tested A→B→C with both landing orders. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e press clock; plan matches the code A writer re-created for an evicted press restarted tMs at 0, so hours-late summaries sorted to the start of the press. It now anchors on the file's first event (read from its ts/tMs prefix). The plan now describes the per-minute summaries, the eviction budget and the chained drains instead of the first draft's single marker. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Final disposition (posted after merge; steering q35 correction). I merged this PR at Tested head:
Material fixes from review:
Known caveat (confirmed by reading Not addressed: B-r1 minor 5 (no sanitized recorded 🤖 Generated with Claude Code |
…osition gate, #369 needs-evidence Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fixes #1276. Related: #1299 (the recorder that ran 33 h, filed separately as P1).
Plan:
docs/plans/2026-09-25-dictation-journal-cap.md(first commit; updated to match the code).Evidence
One press produced a 1.196 GB
dictation-debugfile. By event, 96 % of it is per-chunk and per-sample:recorder:dataavailable, the CHUNK layer,deepgram:chunk:*,deepgram:messageand AUDIO_LEVELsample. Only 17 lifecycle events appear in the whole file. The only cleanup was a 14-day prune, andDictationDebugJournalRegistry.disposehad no callers.Merged behaviour
journal:high-frequency-summaryrow per minute. Each row has per-kind counts, per-source last chunk indexes,maxPeakandnonZeroPeaks. A kept event (lifecycle, error, outcome, stop, final transcript) first closes the open summary window, so ordering around it is preserved. This keeps a Dictation can keep the microphone open for hours: no max duration, no silence stop (33 h recorded) #1299-style tail visible at minute resolution.flushAll()(the shutdown drain) waits for eviction flushes and for a drain already in flight.tMsis anchored to the file's first{"ts","tMs"}line.tMsrestarts from the new writer's clock.tsand the byte budget are unaffected.Tests
src/main/dictationJournal.test.tscovers:The new tests were red on main.
npx tsc -bis clean. Review dispositions are in the comments.🤖 Generated with Claude Code