Docs: close the gaps an audit turned up

Audited README, BEDIENUNGSANLEITUNG and CLAUDE.md against what the repo and the
running stack actually do. Findings, all fixed:

- CLAUDE.md claimed the repo holds "only deployment config (docker-compose.yml,
  .env, .gitignore)". It has not been that for a while: services/ is our own
  source (TTS/STT servers + systemd units), scripts/ is tooling, and
  prompts/podcast/ + config/content_core.yaml are overlays bind-mounted over the
  image. Those overlays are the fragile part, so the section now says so and
  points at smoke_test.sh.
- CLAUDE.md still described the image as a moving tag and argued against patching
  app code "because it would rot against pull_policy: always" — both obsolete
  since the digest pin.
- README listed neither yt-dlp (needed by add_video_source.py) nor smoke_test.sh
  in the verification step, and section 2.3 still told you to `docker compose pull`
  as if the tag moved.
- BEDIENUNGSANLEITUNG had nothing at all about updates — the very thing a user has
  to do periodically. New section 8 covers check_updates / update_stack / smoke_test
  and, importantly, why updating is not automatic (DB migration is one-way without
  a backup; the local adaptations can break silently without crashing).
- Renumbered the ad-hoc "3a. Updates" in README into a real section 4, and the
  BEDIENUNGSANLEITUNG sections after the new 8 accordingly.

Verified mechanically: every scripts//services//config//prompts/ path named in the
docs exists, and all internal and cross-document anchors resolve (0 dead links —
one was already broken before this change: README pointed at
BEDIENUNGSANLEITUNG.md#stimmklonung instead of #5-stimmklonung).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Dieter Schlüter 2026-07-11 14:17:06 +02:00
commit 09c6d910a7
3 changed files with 82 additions and 16 deletions

View file

@ -4,7 +4,13 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## What this repo is
This is a local Docker Compose deployment of [Open Notebook](https://github.com/lfnovo/open-notebook) (upstream image `lfnovo/open_notebook`), not a clone of its source. There is no application source code here — only deployment config (`docker-compose.yml`, `.env`, `.gitignore`). Application bugs/features belong upstream; this repo only concerns itself with how the stack is run locally.
This is a local Docker Compose deployment of [Open Notebook](https://github.com/lfnovo/open-notebook) (upstream image `lfnovo/open_notebook`), not a clone of its source. The application's own code is **not** here and its bugs/features belong upstream — this repo only concerns itself with how the stack is run locally.
What *is* here, beyond `docker-compose.yml`/`.env`:
- `services/` — our own source: the TTS/STT wrapper servers (Open Notebook has no local TTS/STT provider) plus their systemd units.
- `scripts/` — setup, maintenance and update tooling (see Commands below).
- `prompts/podcast/`, `config/content_core.yaml`**overlays** bind-mounted over files inside the image, to fix upstream behaviour we can't configure otherwise (podcast language/reliability, YouTube caption languages). These are the fragile part: they can silently rot when the image is updated, which is what `scripts/smoke_test.sh` exists to catch.
## Commands
@ -71,7 +77,7 @@ check.
Two services, defined in `docker-compose.yml`:
- **surrealdb** (`surrealdb/surrealdb:v2`) — the database, RocksDB-backed, bound to `127.0.0.1:8000` only (local debugging access, e.g. `surreal sql`). Credentials come from `SURREAL_USER`/`SURREAL_PASSWORD` (default `root`/`root` if unset in `.env`) and are shared with the `open_notebook` service so they stay in sync.
- **open_notebook** (`lfnovo/open_notebook:v1-latest`) — bundles the web UI (port 8502) and REST API (port 5055) in one image, both bound to `127.0.0.1` only. Connects to `surrealdb` over the internal compose network (`ws://surrealdb:8000/rpc`).
- **open_notebook** (`lfnovo/open_notebook:v1-latest`, digest-pinned — see *Image versioning*) — bundles the web UI (port 8502) and REST API (port 5055) in one image, both bound to `127.0.0.1` only. Connects to `surrealdb` over the internal compose network (`ws://surrealdb:8000/rpc`).
Data persists in `./surreal_data` and `./notebook_data` (bind mounts, gitignored).
@ -130,8 +136,9 @@ dialogue segment), `outline.json` and `transcript.json`, is never touched, and n
Failed and `/retry`-replaced runs leak a directory too (the retry writes a *new* episode row with a new
uuid dir; the old one loses its DB entry and just stays). Upstream this would be roughly
`shutil.rmtree(audio_path.parent.parent)` in that handler. We deliberately do **not** patch it here by
bind-mounting a modified router — that would fork app logic into a deployment repo and silently rot
against `pull_policy: always`. Instead: `scripts/prune_podcast_data.py` (dry-run by default, `--yes` to
bind-mounting a modified router — that would fork app logic into a deployment repo and rot against
image updates (the same trap the existing overlays already carry). Instead:
`scripts/prune_podcast_data.py` (dry-run by default, `--yes` to
apply) reconciles the episode list from the API against the directories on disk and removes orphans plus
the `clips/` of completed episodes. Two guards matter — it aborts if any job is `running`/`pending`
(a running job has no `audio_file` yet, so its directory is indistinguishable from an orphan) and it