Files
odoo-at-payroll/personalverrechnung/RUNBOOK.md
T
fegger e990488273 [REF] personalverrechnung: relocate Lexis360 raw layer to .lexis360/
Move the licensed PDF exports and the Layer-1 full texts from the
project root into the dot directory .lexis360/, keeping the root
listing to versioned content plus the tool checkouts.

The location also encodes provenance, distinct from .firecrawl/:
.lexis360/ holds user-supplied licensed exports that cannot be
re-fetched by an agent - if missing, stop and ask the user
(documented in MEMORY), whereas .firecrawl/ remains the home of
reconstructible web fetches.

- plain move of the unversioned directory (batch2/ subfolder spotted
  and left untouched for its own intake run)
- .gitignore, tool constants/messages, source.pdf/source.text
  frontmatter paths of all 55 curated entries, README/RUNBOOK/MEMORY
  mentions; kb.json/INDEX.md regenerated
- batch 2 (53 PDFs) recorded in MEMORY as staged in .lexis360/batch2/

Validated end to end: --extract 55/55 with stable ids, --registry
55 entries/6 clusters, --check 0 problems (every frontmatter path
resolves at the new location), no stale path references remain.
2026-09-10 10:27:12 +02:00

148 lines
7.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# RUNBOOK — Personalverrechnung
Operational memory for recurring workflows. Update when a procedure
changes or a validation step catches an error it should have caught.
## KV-Library (alle aktuellen Kollektivverträge, maschinenlesbar)
Stand: 2026-09-09 · Aufbau siehe `quellen/kv/` und die Skript-Docstrings.
### Architektur
| Quelle | Rolle | Werkzeug | Rohdaten (unversioniert) |
|---|---|---|---|
| kollektivvertrag.at (ÖGB-Verlag) | **Baseline** — einziger vollständiger, maschinenlesbarer Korpus über alle Kammern; Kreuzcheck-Referenz | `tools/fetch_kv_portal.py` | `.firecrawl/kv-portal/` |
| wko.at KV-Datenbank | **Main source** für WKO-Gewerbe/Industrie/Handel… | `tools/fetch_wko_kv.py` | `.firecrawl/wko-kv/` |
| Kammern (Ärzte, Apotheke, RA, Notariat, LWK, öffentl. Dienst) | Main source soweit öffentlich; Registry der Quellen + Lücken | `quellen/kv/chambers/chambers.json` (kuratiert) | — |
Merge/Crosscheck: `tools/build_kv_catalog.py``quellen/kv/kv-catalog.json|.csv`
mit `chamber`, `main_source`, `cross_check` (Match-Status + Datumsabgleich
WKO „gültig ab" vs. ÖGB-Slice-Version) und `manual_review`-Listen.
Kuratierte Texte: `quellen/kv/oegb/texts/SI-*.json|.md` (Struktur:
§-Hierarchie, Slices = Teile mit Versionsdatum, Topics; JSON ist das
maschinenlesbare Primärformat, MD nur Review/Diff) sowie
`quellen/kv/wko/texts/{slug}.json|.md`. Lohntafel-PDFs werden **nicht**
downgeloadet (nur verlinkt); im KV-Text enthaltene Entgelttabellen sind
Bestandteil der Konvertierung.
### Aktuell halten (Wartungszyklus)
Mindestens jährlich mit der Bezügeanpassungs-Runde (Jänner) und nach
bekannten KV-Abschluss-Runden (üblich: Jänner + Juli):
```bash
python3 personalverrechnung/tools/fetch_kv_portal.py --refresh # diff lastContentUpdate/validFrom
python3 personalverrechnung/tools/fetch_wko_kv.py --refresh # diff wko_lastmod (DV-Sitemap)
python3 personalverrechnung/tools/build_kv_catalog.py # Merge + Crosscheck neu
```
Danach manuell sichten (Reihenfolge):
1. `oegb/update-reports/update-<datum>.json` — changed/new/removed.
2. `kv-catalog.json → manual_review`:
- `wko_without_clear_match` (Match-Heuristik! Titelmorphologie,
Hilfsdokumente wie Lohnordnungen/Tabellen landen hier),
- `date_disagreements` (WKO-Datum vs. Portal-Slice — meist
noch nicht aktualisierte WKO-Seite oder neuere Konsolidierung),
- `unclassified` (v. a. Einzelträger-KVs: Austro Control, Diözesen,
Orchester … — nur prüfen, ob eine Zuordnung Sinn ergibt).
3. `chambers/chambers.json` stichprobenartig verifizieren (URLs können
sich ändern); nicht mehr öffentliche Quellen als solche vermerken.
### Validierung
- Strukturcheck: Katalog-Zahlen (entries = oegb + wko_only), alle
`texts/*.json` parsebar, jede ÖGB-Variante hat json+md
(Skript-Schnelltest siehe git-history dieses RUNBOOKs).
- Rechenfälle gegen Portaldarstellung: 23 bekannte KVs
(z. B. SI-2203 Handwerk und Gewerbe, SI-2748 Metallgewerbe,
SI-2757 Zahntechnik) im Dashboard/Volltext gegen `texts/*.md`
halten.
- Änderungen niemals aus Trainingswerten — nur aus den gespeicherten
Rohdaten (`--build-only` baut kuratierte Ausgaben offline neu).
### Bekannte Limitierungen (Stand 2026-09-09)
- Match WKO↔ÖGB ist heuristisch (Token-Overlap mit Prefix-Fuzzy);
alles unter Score 0,75 bzw. Hilfsdokumente landet bewusst in
`manual_review` statt stillschweigend zugeordnet zu werden.
- WKO-Übersichtsseiten listen je Bundesland identische, regionenneutrale
aktuelle Dokumente (614 aktuell); Archivjahre nur über die
DV-Sitemap (3.879 URLs, `wko_lastmod` getrieben).
- Kammer-PDFs teils Scans ohne Textlage (RA Vbg, LÄK NÖ/OÖ/Bgld) —
OCR wäre nötig, ist nicht eingebaut; ÖGB-Portal liefert dafür
maschinenlesbare Texte.
- Öffentlicher Dienst: GÖD-Volltexte member-only; Gemeindebedienstete
teils Landesgesetze statt KV (Bgld. GemBG 2014 — siehe
`RECHTSQUELLEN-Bgld.md`).
- Angestelltenärzte-KV (Krankenanstalten): nirgends öffentlich —
einzige systematische Lücke des Korpus.
## Lexis360-Wissensbasis (Lexis Briefings Personalrecht)
Stand: 2026-09-10 · Konventionen und Schema: `wissensbasis/README.md`
(dort auch die Lizenz-Entscheidung: Volltexte/PDFs lokal unversioniert,
nur Kuratierung versioniert).
### Architektur
| Schicht | Pfad | Werkzeug | Versioniert? |
|---|---|---|---|
| PDF-Exporte (Lexis 360, lizenziert) | `.lexis360/*.pdf` | manueller Export | nein (gitignored) |
| Layer 1 — Volltexte + Katalog | `.lexis360/md/` | `tools/build_lexis_kb.py --extract` | nein |
| Layer 2 — kuratierte Einträge | `wissensbasis/dokumente/<slug>.md` | manuell (Vorlage lb-atz-07) | **ja** |
| Registry + Index | `wissensbasis/kb.json`, `wissensbasis/INDEX.md` | `tools/build_lexis_kb.py --registry` | **ja** (generiert) |
Batch 1: 55 Einträge, 6 Cluster (atz 15 · leh 15 · jug 7 · pra 4 ·
bes 8 · tzb 6), Quell-Stände 2024-03 bis 2026-09. IDs sind **eingefroren**
(`lb-<prefix>-<nn>`) — neue Batches hängen hinten an, Nummern werden nie
wiederverwendet; `topic` im Frontmatter = beschreibender ASCII-Slug
(`altersteilzeit`, `lehrlinge`, `jugendliche`, `ferialpraktikanten`,
`beschaftigungsformen`, `teilzeit`), nicht das ID-Präfix.
### Neue Batches einspielen
```bash
# 1. PDFs nach .lexis360/ kopieren (Export-Namenskonvention beibehalten)
# 2. BATCH-Konstante in tools/build_lexis_kb.py hochsetzen
python3 personalverrechnung/tools/build_lexis_kb.py --extract # Layer 1 + Katalog
# 3. neue Layer-2-Einträge kuratieren (Schema/Regeln: wissensbasis/README.md)
python3 personalverrechnung/tools/build_lexis_kb.py --registry # kb.json + INDEX.md, validiert Frontmatter
python3 personalverrechnung/tools/build_lexis_kb.py --check # Vollständigkeit Layer-1↔Layer-2
```
### Validierung
- `--registry` prüft: Pflicht-Keys, ID-Muster, ID-Präfix↔topic-Konsistenz,
`stand`-Format, `batch`, dangling `cross_refs`.
- `--check` prüft: 1:1-Katalog↔Kuratierung, Layer-1- und PDF-Existenz.
- Stichproben: Kernwerte gegen Layer-1-Volltext (`sed -n '16,$p'
.lexis360/md/<slug>.md`); Werte nie aus Trainingswerten.
### Bekannte Limitierungen / offene Punkte (Stand 2026-09-10)
- **Korpus-Widersprüche (⚠, in den Einträgen dokumentiert):** AMS-
Ersatzquote geblockte ATZ 2026 — lb-atz-07 nennt 28,5 %, lb-atz-09/12
nennen 27,5 % (RIS/AMS-Klärung vor Implementierung nötig); DAG-Grenze
2023 751,36 € (lb-bes-02) vs 751,37 € (lb-bes-06); Lehrlinge-
Kurzarbeit lb-leh-11 („100 %") vs lb-leh-07 (seit 2023 ausgenommen);
Bande 34 Monate lb-jug-01 vs lb-pra-02.
- **Alte Quell-Stände im leh-Cluster** (2024-03, 2025-08): €-Werte dort
nur mit Stand-Kennzeichnung verwendbar; Vorzug für neuere Briefings
desselben Clusters.
- Nicht in Batch 1 enthalten und deshalb ❓: Bildungskarenz/
Beihilfen-Beitrag (Verweis in lb-tzb-01), mehrere im Text verweisene
Muster/Briefings („Jugendliche Arbeitszeit“ u. a.).
- **Copilot-Deployment (❓ offen):** Layer-1-Volltexte sind nicht im
Repo-Verteilungsumfang (Lizenz) — Bereitstellungspfad für RAG/Skills
muss separat lizenkonform geregelt werden.
- Dossier-Stil-Exporte (pra-Cluster): Breadcrumb kann mit Fließtext in
einer Zeile stehen, Footer („Page n“, „Erstellt von …“) im Text —
Parser behandelt das, Kuratierung muss es ignorieren.
## Weitere Workflows
(SV-Werte/TASY-Import und GemBG-Katalog siehe `tools/`-Docstrings und
`docs/CHANGELOG.md`; hier ergänzen, wenn sich wiederholende Beobachtungen
zeigen.)