Files
UmbraAudio/specs
B.D. Murphy 9f3a0a4b18 Release comment as a release step; releasing grants implicit voice approval
Two corrections from the operator, and I had both wrong.

1. "I didn't explicitly approve all minor character voices. By releasing the
   audiobook I have given implicit approval those voices are ready and should be
   tagged." The previous session reported "24 of 61 speakers have an approval
   record; 38 do not" as if it were a gap. It is not a gap. Releasing IS the
   approval, and those voices were waiting to be tagged.

   chapter_approved and audiobook_approved now read true, with
   approved_by: "this publication record" - there is no separate audiobook
   approval in this system, and pretending otherwise understated the release.

   The boundary matters, so it is measured rather than assumed: implicit
   approval covers voices that HAVE LINES in the released chapters, computed from
   the database. A character who never speaks is not covered, because releasing a
   book does not approve a voice it never uses. On Deal Hunter edition 1 that is
   24 explicitly approved, 29 implicitly approved, and 10 in-profile voices with
   no lines. The three categories are never summed - an explicitly approved voice
   can also be one that stopped speaking.

   grant_implicit_voice_approval() writes plain status strings, the shape the web
   UI already reads, and keeps the provenance in the immutable publication record
   rather than the mutable ledger, so it cannot be edited away.

2. The m4b inter-chapter gap should be the same 2 s as the lead and trail
   padding. export.py had gap_ms=4000 in one path and a default of 1000 in the
   other, while ar_export.SILENCE_MS = 2000 governed lead and trail: three
   drifting values for one concept. The gap now imports SILENCE_MS as
   CHAPTER_GAP_MS, so all three are one number that changes in one place.

New umbraaudio/release_comments.py - the comment is a gate, not a caption.

  designator  2026-10-03 #2 14:32:05
  slug        release-20261003-143205-02

The sequence is per date, not global, which is the whole point: a problem found
and corrected on the same day is unambiguous about which was last. Two comments
authored in the same second still get distinct slugs, because the sequence is
allocated by scanning the directory. First line is the summary, the rest is the
body, like a commit message. An approved comment is FROZEN - changing an approved
note is a different claim about a different state, so it needs a new comment and
therefore a new publication.

require_approved() blocks --publish: passing a draft exits 2 and says what to do
next. Verified live.

draft_comment_text() composes the comment from the measured build rather than
from memory. Deal Hunter's draft is written and waiting:
release-20261003-133508-01, 32 chapters, the 24/29/10 voice split, 32/32
loudness and peak gates green, and the post-approval padding note.

New invariants R-8 through R-11 in spec 22. Two of my own test premises were
wrong and the implementation was right - recorded in AGENTS.md because the tests
were the weaker artefact.

Full suite 538 passed / 8 failed, the same 8 pre-existing failures. ruff clean.
Nothing was published: the Deal Hunter comment is a draft awaiting review, and
voice_status.json is untouched because publishing never ran.
2026-10-03 06:49:42 -07:00
..

UmbraAudio Specifications

Index of all specification documents for the UmbraAudio audiobook generation system.

Specifications

File Topic Description
00-project-overview.md Architecture Pipeline overview, tech stack, data layout
01-parsing.md Pass 1a EPUB, PDF, TXT, MD manuscript parsing
02-analysis.md Pass 1b BookNLP, character profiling, pronunciation
03-voice-design.md Pass 2 Per-character voice reference generation
04-mapping.md Pass 3 Text segmentation, speaker attribution, manifests
05-generation.md Pass 5 Audio generation, caching, retry, CUDA management
06-normalization-watermarking.md Post-gen Audio normalization, ACX compliance, Perth watermark
07-assembly-export.md Export M4B, MP3, WAV export via FFmpeg
08-database.md Database SQLite schema, entity relationships, CRUD API
09-web-review-ui.md Web UI FastAPI + HTMX review interface
10-cli-orchestrator.md CLI Click commands, full pipeline orchestration
11-configuration-dependencies.md Config Pydantic settings, dependencies, build system
12-quality.md Quality MOS, WER, consistency, ACX compliance

Quick Reference

Pipeline Passes

1a: Parse    → chapters table
1b: Analyze  → characters, pronunciation_guide
2:  Voices   → voice_ref WAVs
3:  Map      → manifests/*.json
4:  Test     → sample audio (optional)
5:  Generate → audio/*.wav, audio_normalized/*.wav
    Export   → export/*.m4b, *.mp3

Key Entry Points

Component File Class/Function
CLI cli.py main Click group
Pipeline orchestrator.py run_pipeline()
TTS voices/chatterbox.py ChatterboxEngine
Segmenter mapping/segmenter.py Segmenter
Generator generation/chapter.py ChapterGenerator
Normalizer assembly/normalize.py AudioNormalizer
Web UI web/__init__.py create_app()
Database database.py Database