KV/RIS-Erweiterung: 614 WKO-KV-Dokumente + 59 RIS-Gesetze (D9)

- Korpus 601 -> 1274 Layer-2-Eintraege: kv-kvt-001...614 (ein Cluster
  kollektivvertraege, Branche als Tag) und ris-<cluster-prefix>-nn auf
  der bestehenden Cluster-Map + 7 neue Cluster (zvr/avr/agg/lst/abo/
  nso/kvt); LAW_MAP dokumentiert die 59 Gesetz-Zuordnungen.
- kv/ris-Eintraege sind quellentreu generiert (D9) - Gesetze sind
  amtliche Werke, KV-Lohntabellen zahlenexakt; Tool-Output in
  tools/ (ingest_sources.py, build_registry.py, kb_common.py),
  eingefrorene ID-Kataloge tools/catalogs/*.json (nur Metadaten).
- kb.json/INDEX.md regeneriert (1274 Eintraege, 76 Cluster);
  agent/kb.py: ID-Raeume kv|ris, source akzeptiert html-only.
- Tests 41 -> 49 (Konverter, LAW_MAP-Abdeckung, neue ID-Raeume,
  Korpus-Integrationszahl).
This commit is contained in:
2026-09-15 07:44:56 +02:00
parent b3e8e47cdd
commit 97aa3c1c82
684 changed files with 275146 additions and 16605 deletions
+95 -63
View File
@@ -1,15 +1,20 @@
# Wissensbasis Personalverrechnung (Lexis360-Exporte + WIKU Personal)
# Wissensbasis Personalverrechnung (Lexis360-Exporte, WIKU Personal,
WKO-Kollektivverträge, RIS-Gesetze)
Kuratierte Wissensbasis aus zwei lizenzierten Quellcorpora — den
LexisNexis-Briefings des Werks *Lexis Briefings Personalrecht*
(Export aus Lexis 360) und den WIKU-Personal-Publikationen
(Fachbroschüren, Arbeitsunterlagen, Casebooks, Fachzeitschrift
„WIKU Personal aktuell“). Ein **gemeinsamer Korpus**: `work`-Feld
unterscheidet die Quellen, ID-Räume `lb-*` (Lexis) und `wk-*` (WIKU)
liegen auf derselben Cluster-Map. Zweck:
Kuratierte Wissensbasis aus vier Quellcorpora — den **LexisNexis-Briefings**
des Werks *Lexis Briefings Personalrecht* (Export aus Lexis 360), den
**WIKU-Personal-Publikationen** (Fachbroschüren, Arbeitsunterlagen,
Casebooks, Fachzeitschrift „WIKU Personal aktuell“), den **Kollektivvertrags-
Dokumenten von WKO.at** (Lohn-/Gehaltsordnungen inkl. Lohntabellen,
KV-Abschlüsse, Erläuterungen, Zusatz-KVs) und den **RIS-Gesetzes-Texten**
(Rechtsinformationssystem des Bundes; nur die im Lexis360-Bestand zitierten
Paragraphen je Gesetz). Ein **gemeinsamer Korpus**: das `work`-Feld
unterscheidet die Quellen, ID-Räume `lb-*` (Lexis), `wk-*` (WIKU),
`kv-*` (WKO-KV) und `ris-*` (RIS) liegen auf derselben Cluster-Map. Zweck:
1. **Entwicklungsreferenz** neben `personalverrechnung/RECHTSQUELLEN-*.md`
für die Personalverrechnungsmodule (`l10n_at_hr_payroll*`), und
1. **Entwicklungsreferenz** neben den Rechtsquellen-Übersichten
(`RECHTSQUELLEN-*.md` im Schwesterprojekt) für die Personalverrechnungs-
module (`l10n_at_hr_payroll*`), und
2. **Copilot-Korpus**: Aufbau und Frontmatter sind retrieval-gerecht
(stabile IDs, maschinenlesbares `kb.json`), damit künftig ein
Frage-Antwort-Copilot darauf aufbauen kann.
@@ -21,16 +26,23 @@ liegen auf derselben Cluster-Map. Zweck:
| PDF-Exporte | `.lexis360/Lexis360_*.pdf` · `.wiku/*.pdf` | **nein** (gitignored) | lizensierte Original-PDFs |
| Layer 1 — Volltexte | `.lexis360/md/<slug>.md` · `.wiku/md/<slug>.md` | **nein** (gitignored) | vollständiger Extraktionstext + Metadaten-Frontmatter |
| Katalog | `.lexis360/md/_catalog.json` · `.wiku/md/_catalog.json` | **nein** (gitignored) | geparste Metadaten aller Quellen (Slug ↔ ID ↔ Stand ↔ Cluster) |
| Layer 2 — kuratierte Einträge | `dokumente/<slug>.md` (Lexis) · `dokumente/wiku_<slug>.md` (WIKU) | **ja** | Kuratierung in eigenen Worten (Schema unten) |
| Registry | `personalverrechnung/wissensbasis/kb.json` | **ja** | **generiert** aus dem Layer-2-Frontmatter beider Quellen (`--registry`) |
| Rohquellen kv/ris | `.firecrawl/wko-kv/docs/*.html` · `.ris/*.md` | **nein** (gitignored) | WKO-KV-Seiten (HTML) bzw. RIS-Gesetzes-Auschnitte (Markdown) |
| Layer 2 — Einträge | `dokumente/<slug>.md` (Lexis) · `dokumente/wiku_<slug>.md` (WIKU) · `dokumente/kv_<slug>.md` (WKO-KV, **generiert**) · `dokumente/ris_<slug>.md` (RIS, **generiert**) | **ja** | Kuratierung in eigenen Worten (lb/wk) bzw. quellentreue Konvertierung (kv/ris, Tool-Output) |
| Registry | `wissensbasis/kb.json` | **ja** | **generiert** aus dem Layer-2-Frontmatter aller Quellen (`tools/build_registry.py`) |
| Kataloge kv/ris | `tools/catalogs/kv_catalog.json` · `ris_catalog.json` | **ja** | eingefrorene ID-Zuweisungen (nur Metadaten, keine Quelltexte) |
Volltexte sind lizenzierter Inhalt (LexisNexis- bzw. WIKU-Abonnement)
und bleiben wie `.firecrawl/` lokal + unversioniert. Nur die
Kuratierung (eigene Worte, kurze Zitate mit Quellenachweis) wird
committet. WIKU-Publikationen haben keine Lexis-Breadcrumbs:
Metadaten (Slug, Cluster, Stand, `work`, Kapitel, Titel) werden beim
Intake als **`WIKU_PINS`**-Eintrag im Tool festgenagelt (1 Publikation
= 1 Eintrag; Granularitätsentscheidung 2026-09-10).
Volltexte der lizenzierten Quellen (Lexis/WIKU) sind Lizenzinhalt und
bleiben wie `.firecrawl/` und `.ris/` lokal + unversioniert. Nur die
Layer-2-Einträge werden committed. **Lizenz-Sonderfall der neuen Quellen
(Entscheidung 2026-09-15):** Gesetze sind amtliche Werke (§ 7 UrhG) und
WKO-KV-Texte müssen zahlenexakt bleiben (Lohntabellen) — daher sind
`kv_*.md`/`ris_*.md` **quellentreu generiert** (Konverter
`tools/ingest_sources.py`), NICHT in eigenen Worten kuratiert, und sie
sind **Tool-Output**: keine manuelle Bearbeitung, bei Änderungen neu
generieren. Die WKO-Seiten selbst und die `.ris/`-Dateien bleiben
unversioniert; die Einträge tragen ihre Quelle (`source.html`/`source.text`)
und die WKO-/RIS-URL im Body. Die `overviews/` (1 820 Bundesland-Übersichts-
seiten von WKO.at) werden derzeit **nicht** aufgenommen (Redundanz zu `docs/`).
## Frontmatter-Schema (Layer 2 — verbindlich)
@@ -57,7 +69,7 @@ englisch** (konsistent mit `kv-catalog.json`/`chambers.json`),
(österreichischer Fachbegriff, ISO-Wert `YYYY-MM`) und `topic`/`tags`
als ASCII-Slugs. Die Frontmatter ist **Single Source of Truth**;
`kb.json` wird daraus generiert und schema-validiert
(`build_lexis_kb.py --registry`).
(`tools/build_registry.py`, in diesem Repo).
## Cluster (Lexis Batch 19 + WIKU Batch 1)
@@ -132,44 +144,51 @@ als ASCII-Slugs. Die Frontmatter ist **Single Source of Truth**;
| `pension` | Pensionsversicherung (Pensionsarten, Pensionskonto) | `pvs` | lb-pvs-01 … 13 | 13 |
| `aktuell` | WIKU Personal aktuell (Neuerungen, Urteile, Praxis) | `akt` | wk-akt-01 … 12 | 12 |
| `gewerbe` | Gewerbebezogene Personalverrechnung (Güterbeförderung, Gastgewerbe) | `gwe` | wk-gwe-01 … 02 | 2 |
| `kollektivvertraege` | Kollektivverträge (WKO.at — Lohn-/Gehaltsordnungen, KV-Texte je Branche) | `kvt` | kv-kvt-001 … 614 | 614 |
| `zivilrecht-normen` | Zivilrechtliche Normen (ABGB, IPRG, KSchG, ZPO) | `zvr` | ris-zvr-01 … 04 | 4 |
| `arbeitsvertragsrecht` | Arbeitsvertragsrecht (AVRAG) | `avr` | ris-avr-01 | 1 |
| `arbeitsgerichtsbarkeit` | Arbeits- und Sozialgerichtsbarkeit (ASGG) | `agg` | ris-agg-01 | 1 |
| `lohnsteuer` | Lohnsteuer & Einkommensteuer (EStG) | `lst` | ris-lst-01 | 1 |
| `abgabenverfahren` | Abgabenverfahren (BAO) | `abo` | ris-abo-01 | 1 |
| `normen-sonstige` | Weitere Gesetze und Verordnungen (ArbIG, RStDG, StGB, StPO, UGB) | `nso` | ris-nso-01 … 05 | 5 |
**601 Einträge in 69 Clustern** — Lexis: 571 Einträge in 67 Clustern
Weitere RIS-Gesetze liegen auf der bestehenden Cluster-Map (`ris-url-01`
neben `lb-url-*`, `ris-asc-01` neben `lb-asc-*`, …; je Gesetz ein
`ris-<cluster-prefix>-<nn>`-Eintrag, mehrere Gesetze teilen sich ein
Cluster fortlaufend — Zuordnungstabelle `LAW_MAP` in
`tools/kb_common.py`).
**1 274 Einträge in 76 Clustern** — Lexis: 571 Einträge in 67 Clustern
(Batch 1: 55, Batch 2: 52, Batch 3: 44, Batch 4: 54, Batch 5: 31,
Batch 6: 41, Batch 7: 97, Batch 8: 134, Batch 9: 63); WIKU: 30
Einträge in 18 Clustern (Batch 1: 13 Fachbroschüren, 3
Arbeitsunterlagen, 2 Casebooks, 12 Hefte „WIKU Personal aktuell“
2026). Die WIKU-Publikationen liegen auf der bestehenden Cluster-Map
(`wk-pfa-01` neben `lb-pfa-*`) plus den beiden eigenen Clustern
`akt`/`gwe`. Siebzehn Briefings-Kapitel: „Beschäftigungsverhältnisse“,
„Entgelt: Anspruch & Abrechnung“, „Arbeitszeit“, „Arbeitnehmerschutz“,
„Verhaltenspflichten“ (Batches 16), dazu „Urlaub & Karenzierung“,
„Schwangerschaft & Elternkarenz“, „Krankenstand & Arbeitsunfall“,
„Dienstverhinderung“ und „Außerhalb des Betriebsstandortes“ (Batch 7),
„Beendigungsarten“, „Betriebsrat & Betriebsvereinbarungen“,
„Beendigungsansprüche & Endabrechnung“, „Beendigungsphase - Sonstiges“,
„Meldungen & Verpflichtungen“ und „Unternehmensauflösung &
Betriebsübergang“ (Batch 8) sowie „Sozialversicherung“ (Batch 9)
(chapter-Feld je aus dem Katalog übernehmen).
2026); WKO-KV: 614 Einträge im Cluster `kollektivvertraege` (Batch 1);
RIS: 59 Gesetze, verteilt auf bestehende Cluster plus den neuen
Rechtsgebiet-Clustern (Batch 1).
Frontmatter-`topic` = beschreibender ASCII-Slug (linke Spalte), das
ID-Präfix (`atz`, `leh`, …) nur im `id` selbst; das Tool prüft die
Konsistenz beider (`--registry`). Neue Cluster erweitern alle vier
Strukturen im Tool (`TOPIC_MAP`, `KEYWORDS`, `CLUSTERS`,
`TOPIC_TO_PREFIX`); tritt derselbe Thema-Slug unter zwei Kapiteln
auf, zusätzlich `CHAPTER_TOPIC_MAP`.
IDs werden beim ersten `--extract` vergeben und danach **eingefroren**
(`load_previous_ids()`); neue Dokumente hängen hinten an, Nummern
ausscheidender Dokumente werden nie wiederverwendet. Dateiname eines
Layer-2-Eintrags = Layer-1-Slug (Lexis-Export-Stil: Umlaute **fallen**,
werden nicht transliteriert — `uberblick`, `beschaftigung`).
Frontmatter-`topic` = beschreibender ASCII-Slug, das ID-Präfix
(`atz`, `leh`, `kvt`, …) nur im `id` selbst; die Registry
(`tools/build_registry.py`) prüft die Konsistenz beider über die
Cluster-Map (bestehende Präfixe aus `kb.json` abgeleitet, neue Cluster
in `tools/kb_common.py`). IDs werden beim Intake vergeben und danach
**eingefroren** (`tools/catalogs/kv_catalog.json`, `ris_catalog.json`);
neue Dokumente hängen hinten an, Nummern ausscheidender Dokumente
werden nie wiederverwendet. Dateinamen: Layer-2 = Layer-1-Slug
(Umlaute fallen auf Basisbuchstaben — `uberblick`, `beschaftigung`;
ß → `ss`), WIKU mit `wiku_`-Präfix, WKO-KV mit `kv_`-Präfix und RIS
mit `ris_`-Präfix (Kollisionsschutz im gemeinsamen `dokumente/`).
## Kurationskonventionen (verbindlich)
1. **Sprache:** deutsch, Fachsprache wie im Original; Metadaten-Werte
UTF-8. `topic`/`tags` ASCII.
2. **Eigene Worte:** Kuratierung ist keine Volltextkopie (Lizenz!).
Wörtliche Zitate nur kurz und mit Stand gekennzeichnet.
2. **Eigene Worte (lb/wk):** Kuratierung ist keine Volltextkopie
(Lizenz!). Wörtliche Zitate nur kurz und mit Stand gekennzeichnet.
**Ausnahme kv/ris (2026-09-15):** quellentreu generierte Einträge
(`tools/ingest_sources.py`) — Gesetze sind amtliche Werke, KV-
Lohntabellen müssen zahlenexakt bleiben; diese Dateien sind
Tool-Output, keine manuelle Kuratierung.
3. **Werte immer mit Stand.** Stammt der Wert aus einem Briefing mit
älterem Stand (z. B. Lehrlinge 2024-03, 2025-08), so ist
„(Stand YYYY-MM)" am Wert zu führen. Niemals Werte aus
@@ -198,29 +217,42 @@ werden nicht transliteriert — `uberblick`, `beschaftigung`).
1. Neue PDFs nach `.lexis360/` kopieren (Export-Namenskonvention
`Lexis360_<slug>.pdf` beibehalten).
2. In `tools/build_lexis_kb.py` die Konstante `BATCH_LEXIS` hochsetzen,
dann `--extract --source lexis` ausführen: Layer 1 + Katalog neu;
bestehende IDs bleiben fix, neue Dokumente erhalten neue IDs + neue
Batch-Nummer.
2. Intake über das Schwesterprojekt-Tool (`build_lexis_kb.py --extract --source lexis`, im Repo `personalverrechnung`)
oder kuratieren wie bisher von Hand; Layer-1 + Katalog neu,
bestehende IDs bleiben fix.
**WIKU:**
1. Neue PDFs nach `.wiku/` kopieren (Dateinamen der Lieferung
beibehalten; Stand aus „Stand YYYY-MM“/Heft-Monat, sonst Impressum).
2. Je PDF einen `WIKU_PINS`-Eintrag im Tool ergänzen (slug, cluster,
stand, work, chapter, title) — ein PDF ohne Pin wird **nicht**
extrahiert (harter Warning, nie Metadaten raten). Dann
`BATCH_WIKU` hochsetzen und `--extract --source wiku` ausführen.
2. Kuratieren wie bisher (Layer-2-Einträge `wiku_<slug>.md`).
**Beide Quellen gemeinsam:**
**WKO-Kollektivverträge (kv):**
3. Neue Layer-2-Einträge kuratieren (Konventionen oben; WIKU-Dateiname
= `wiku_<slug>.md`).
4. `--registry` (generiert/validiert `kb.json` + `INDEX.md` über beide
Quellen), danach `--check --source all` (Layer-1↔Layer-2-
Vollständigkeit je Quelle, Quelldateien vorhanden).
5. `personalverrechnung/RUNBOOK.md` und `.agents/MEMORY.md` pflegen
(`INDEX.md` wird generiert, nicht manuell editiert).
1. Neue Seiten nach `.firecrawl/wko-kv/docs/` (Crawl via Firecrawl;
eine Seite = ein KV-Dokument).
2. `python3 tools/ingest_sources.py --source kv` — konvertiert HTML →
Layer-2 (`kv_<slug>.md`), IDs aus `tools/catalogs/kv_catalog.json`
(eingefroren, neue hängen an). `--dry-run` zum Vorschauen.
**RIS-Gesetze (ris):**
1. Neue Gesetze nach `.ris/` (Markdown; nur die im Lexis360-Bestand
zitierten Paragraphen).
2. **Zuerst** `LAW_MAP` in `tools/kb_common.py` um das Gesetz ergänzen
(topic, chapter, laufende Nummer im Cluster) — die ID encodiert das
Cluster, danach nie ändern.
3. `python3 tools/ingest_sources.py --source ris`.
**Alle Quellen gemeinsam:**
3. `python3 tools/build_registry.py` — validiert das gesamte Layer-2
(Schema, topic↔Präfix, Batches, cross_refs) und schreibt
`kb.json` + `INDEX.md` neu (beide generiert, nie manuell editieren).
4. Reindex + Eval gegen die Gates (Skill `pv-rag-agent`:
Recall@8 > 0,9, Zitier-Präzision): `python3 -m agent.cli ingest`,
dann `python3 -m agent.cli eval [--answers]`.
5. `agent/README.md` und `.agents/MEMORY.md` pflegen.
## Copilot-Konsum