T04 said MISSING_INGEST_ENDPOINT. It was wrong about the codebase and right
about the running system, and both halves were avoidable.
The route is POST /api/node/audio/import, on agent_router mounted at /api/node,
guarded by node.require("dataset:ingest"), backed by audio_import.py and
migration 0008_audio_source_import.sql. I found it by reading app.py's
include_router calls - which I had already grepped earlier in this same session
and which printed `include_router(node_router, prefix="/api/node")` on screen
while I was writing the test that declared the path missing.
Two failures, not one:
* I probed six guessed paths when I held SSH access to the source that names the
router prefixes. A 404 to a guessed path proves only that the guess was wrong.
* I probed with GET only. The route is POST-only, so it answers GET with 404 and
POST with 405. That is why it looked absent for a whole session even to a
careful prober.
Both are fixed. T04 probes GET and POST and treats 405 as routed, because 405
means the path is in the table under another method. The failure case is now
UNCONFIRMED_INGEST_ENDPOINT rather than MISSING, and carries a note saying to
confirm against the route table rather than against its 404s. A new verdict,
INGEST_ROUTED_NEEDS_RESTART, distinguishes "routed but not serving" from
"absent".
Why it is routed but not serving: the process on :8442 started 2026-10-14 20:06.
audio_import.py was written 2026-10-15 11:15 and routes_compute.py 12:35, all
uncommitted. /health has been green throughout, because it probes liveness and
not the route table - so "healthy" was never evidence the new work was live.
Suite is 5 pass / 0 fail / 5 blocked now, verdict INGEST_ROUTED_NEEDS_RESTART.
48 tests pass. Nothing pushed.
UmbraAudio
Quality-first multi-pass audiobook generation from English manuscripts.
Features
- 5-pass pipeline: Analysis → Voice Design → Mapping → Test → Generate
- Multi-engine TTS: Chatterbox (primary), Qwen3-TTS (secondary)
- LLM-enhanced: BookNLP for NLP, LLM for profiling/emotion/pronunciation
- Web review: FastAPI + HTMX at checkpoints for human approval
Quick Start
python -m umbraaudio.cli init <manuscript.epub> --name 'My Book'
python -m umbraaudio.cli analyze
python -m umbraaudio.cli voices
python -m umbraaudio.cli review
Requirements
- Python 3.11+
- NVIDIA GPU with CUDA support (RTX 3060 or better recommended)
- ffmpeg
Development
pip install -e ".[dev]"
ruff check umbraaudio/
pytest tests/ -v
Commit cadence: commit at least once every Sunday. Never leave a week (let alone a month) of work uncommitted — a single accidental
git checkouton 2026-09-20 wiped out a month of changes toumbraaudio/web/routes.py. SeeAGENTS.md→ Commit Cadence.
scripts/commit_check.sh enforces the nudge: it exits non-zero once the tree has been dirty
longer than a week. The LaunchAgent com.umbraaudio.commitcheck runs it every Sunday at
18:00 and posts a macOS notification when there is uncommitted work.
scripts/commit_check.sh # warn if dirty > 7 days
scripts/commit_check.sh --days 3 # tighter threshold
scripts/commit_check.sh --any # warn on any uncommitted change
Rebuilding from source
The repo tracks source only; large runtime data is reconstructed as needed.
-
Models: weights are not committed (see
.gitignore). Download them:bash scripts/download_models.sh # ~9 GB, targets ./models -
Qwen3-TTS is a git submodule pinned to upstream commit
022e286:git submodule update --init --recursiveThe
tts_server/web-demo backend includes a local UI customization toqwen_tts/cli/demo.py. It is preserved as a patch — reapply it after checking out the submodule:cd Qwen3-TTS && git apply ../scripts/qwen3_tts_demo_umbra_patch.patch -
Environment: copy/keep
.env(contains secrets) and setUMBRA_TTS__*model paths undermodels/.
Book projects (e.g. DealHunterShip_...) are committed separately under their
own project directories and are not part of this program repository.