feat: Installer fragt OCR-Sprachen und Archiv pro Instanz ab (v0.5.0)

- Sprach-Abfrage pro Instanz (Default-Vorschlag deu+eng), bewusst
  instanz-lokal: ein Hotfolder kann mit "deu" laufen, ein anderer mit
  "deu+eng+fra". Hinweis im Prompt, dass jede zusaetzliche Sprache
  Laufzeit und Erkennungsqualitaet kostet.
- Jeder Sprachcode wird gegen "tesseract --list-langs" geprueft, fehlende
  Pakete (tesseract-ocr-<code>) werden zur Installation angeboten; lehnt
  der User ab oder scheitert apt, wird gewarnt und erneut gefragt.
- Abfrage "Original archivieren?" mit $BASE/archive als Default; Archiv
  ausserhalb von $BASE wird eigens angelegt und gechownt. Ein Pfad auf
  incoming/outgoing/working/error wird abgewiesen.
- sed-Kette der Config-Erzeugung jetzt verankert (^key =) und escaped,
  setzt zusaetzlich languages, original_on_success und archive_dir;
  die erzeugte Config wird gegen die Eingabe nachgeprueft.
- README und Briefing um "Sprachen pro Instanz" ergaenzt

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-22 21:24:56 +02:00
parent 8da0b7da1c
commit 2062476252
6 changed files with 277 additions and 12 deletions
+35 -3
View File
@@ -1,7 +1,7 @@
# AI Agent Briefing — PDF OCR Hotfolder
**Zuletzt aktualisiert:** 2026-09-22
**Version:** 0.4.1
**Version:** 0.5.0
**Status:** Multi-Instanz-Betrieb, Preflight-Checks und Fehlerzählung vorhanden, Test-Suite grün (95 pytest-Tests). Ein Produktiv-Einsatz ist im Repo (README/CHANGELOG) nicht dokumentiert — die bisherigen Fixes stammen aus Issues #1–#6, nicht aus einem belegten Dauerbetrieb.
## 🎯 Projektziel
@@ -92,9 +92,41 @@ journalctl -u 'pdf-ocr-hotfolder@*' --since today # alle Instanzen, heute
- Erster Lauf: Basis-Install + erste Instanz anlegen (Pflicht)
- Folgender Lauf: Basis-Install wird übersprungen (erkannt an `venv` + Template-Unit), bestehende Instanzen werden gelistet, weitere Instanzen können ergänzt werden
- Eingaben pro Instanz: Name (`[a-z0-9][a-z0-9-]*`), Basis-Pfad (default `/var/lib/pdf-ocr-hotfolder/<name>`), Service-User
- Eingaben pro Instanz (seit 0.5.0 fünf statt drei):
1. Name (`[a-z0-9][a-z0-9-]*`)
2. Basis-Pfad (default `/var/lib/pdf-ocr-hotfolder/<name>`)
3. Service-User (default `pdfocr`)
4. **OCR-Sprachen** (default `deu+eng`) — Format `^[a-z]{3}(_[A-Za-z]+)?(\+…)*$`,
bei Unsinn wird erneut gefragt. Jeder Code wird gegen `tesseract --list-langs`
geprüft; fehlt einer, bietet der Installer `tesseract-ocr-<code>` an
(Unterstrich → Bindestrich, `chi_sim` → `tesseract-ocr-chi-sim`). Ablehnung
oder fehlgeschlagene Installation → Warnung, dass OCR mit dieser Sprache
**pro Datei** scheitert, und die Sprach-Abfrage beginnt von vorn (kein
harter Abbruch). Ist `tesseract` nicht aufrufbar, wird die Prüfung
übersprungen und die Eingabe unverändert übernommen.
5. **Original nach erfolgreichem OCR archivieren?** (default **nein** →
`original_on_success = "delete"`). Bei ja wird der Archiv-Pfad abgefragt
(Vorschlag `$BASE/archive`, absoluter Pfad Pflicht), angelegt und auf
`$SVC_USER:$SVC_GROUP` gechownt — innerhalb von `$BASE` erledigt das
bestehende `chown -R` das schon, nur ein Archiv **außerhalb** bekommt ein
eigenes `chown -R`.
- **Sprachen sind bewusst instanz-lokal**, nicht global: ein Hotfolder
`buchhaltung` läuft mit `deu`, ein Hotfolder `export` mit `deu+eng+fra`.
`LANGS`/`ORIG_MODE`/`ARCHIVE_DIR` sind `local` in `create_instance()` — jeder
Durchlauf fragt neu, `deu+eng` ist nur der vorgeschlagene Default. Die Liste
gehört eng gehalten: jede zusätzliche Sprache kostet Laufzeit **und**
Erkennungsqualität.
- Basis-Install prüft zusätzlich die Ghostscript-Version und bietet auf Debian 12 bookworm-backports an; erkennt Container (`systemd-detect-virt --container`) und bietet das LXC-Drop-in an
- `<instanz>.toml` wird aus `config.example.toml` mit sed-substituierten Pfaden generiert
- `<instanz>.toml` wird aus `config.example.toml` per `sed` generiert. Substituiert
werden die vier `[paths]`-Zeilen **sowie** (seit 0.5.0) `[ocr].languages`,
`[output].original_on_success` und `[output].archive_dir`. Die Ausdrücke sind
am Zeilenanfang verankert (`^key[[:space:]]*=`), damit die deutschen
Kommentarzeilen über den Keys nicht getroffen werden (im Beispiel steht z.B.
`"archive" : Original wird in archive_dir verschoben` als Kommentar);
Pfad-Variablen laufen vorher durch `sed_escape_repl()` (maskiert `\`, `&`, `|`).
Nach dem sed-Lauf liest `config_value()` die drei Keys zurück und vergleicht
sie mit der Eingabe; erst wenn das passt, nennt die Zusammenfassung Sprachen
und Archiv-Verzeichnis.
- Instanz wird sofort `enable --now` gestartet
Manuelles Löschen einer Instanz: