Compare commits
6 Commits
062e010d7b
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 50ba153904 | |||
| f525fb4862 | |||
| a11f2740f7 | |||
| 5209539ba3 | |||
| 1594aa9cbd | |||
| 4a9e06f66e |
+94
-7
@@ -5,10 +5,12 @@ Rollender Übergabe-Log für agent-Threads. Workflow: `.agents/SKILL.md`
|
||||
|
||||
## Current focus
|
||||
|
||||
M1, M2 und **M3 (Bake-off) sind abgeschlossen** — `qwen3.8:27b` ist als
|
||||
Antwortmodell fixiert (D7). Offen: Fehlverweigerungs-Tuning (q-008,
|
||||
q-031 — beide Finalisten betreffend) und Odoo-Integration (M4, separat
|
||||
zu planen).
|
||||
Retrieval-/Antwort-Tuning für komplexe Gestaltungsfragen läuft (D16).
|
||||
Goldset q-124–126 und deterministischer Decision-Support-Pfad sind umgesetzt;
|
||||
offen ist der vollständige 53-Fragen-Antwortmodus-Eval. Danach folgen die
|
||||
bewusste Publikations-/Lizenzfreigabe der quellentreuen Rechtsprechungs-
|
||||
Volltexte und M4 (API-first Odoo-Integration inkl. separat zu planender
|
||||
Privacy-Grenze für Lohndaten).
|
||||
|
||||
## Completed (2026-09-14)
|
||||
|
||||
@@ -57,8 +59,8 @@ zu planen).
|
||||
## Completed (2026-09-15)
|
||||
|
||||
- **KB-Erweiterung um WKO-Kollektivverträge + RIS-Gesetze** (User-Auftrag):
|
||||
`.firecrawl/wko-kv/docs/` (614 KV-Dokumente: Lohn-/Gehaltsordnungen mit
|
||||
Lohntabellen, KV-Abschlüsse, Erläuterungen, Zusatz-KVs) und `.ris/` (59
|
||||
`.firecrawl/kv-portal/wko-kv/docs/` (614 KV-Dokumente: Lohn-/Gehaltsordnungen mit
|
||||
Lohntabellen, KV-Abschlüsse, Erläuterungen, Zusatz-KVs) und `.firecrawl/ris/gesetze/` (59
|
||||
Gesetze, nur die im Lexis360-Bestand zitierten §-Ausschnitte, Stand
|
||||
2026-09-13) → **1 274 Layer-2-Einträge** (`kv-kvt-001…614`,
|
||||
`ris-<prefix>-nn`), 14 984 Chunks, Reindex 8,5 min (11 947 neue
|
||||
@@ -97,6 +99,55 @@ zu planen).
|
||||
- **Tests:** 41 → 49, alle grün (neue ID-Räume, html-Source, Konverter,
|
||||
LAW_MAP-Vollabdeckung, Korpus-Integrationszahl 1 274).
|
||||
|
||||
- **D15 (Rechtsprechungs-Intake, 2026-09-15):** `.rechtsprechung/` → neuer
|
||||
ID-Raum `rj-rjs-*`, gemeinsamer Cluster `rechtsprechung`: 320 RIS-OGD-
|
||||
Entscheidungen/Rechtssätze, 23 zitierte RIS-Normauszüge und 5 als
|
||||
nichtamtlich markierte EuGH-lexetius-Textwiedergaben. Parser:
|
||||
`tools/ingest_sources.py --source rj`; lange Volltexte werden an
|
||||
Absatzgrenzen in H2-Chunks geteilt. `rj_catalog.json` friert die IDs ein;
|
||||
Registry/Index und Agent-Zitatvalidierung kennen `rj-*`. Korpus 1.274 →
|
||||
**1.622** Einträge / 77 Cluster; Reindex: 16.480 Chunks, 1.496 neue
|
||||
Embeddings in 75 s. Retrieval-Goldset erweitert um q-120–123:
|
||||
Hit-Rate 0,956 · Recall@8 **0,922** (Gate ✓) · MRR 0,661, alle vier
|
||||
neuen Fälle gefunden. Gezielte Antwortläufe q-120–123: alle zitiergültig,
|
||||
nicht verweigert, keine Regenerierung; Systemprompt verlangt für als
|
||||
nicht amtlich markierte Quellen die gleiche Einschränkung in der Antwort
|
||||
(q-123 verifiziert). Voller Antwortmodus-Eval (50 Fragen): **100 %
|
||||
Zitier-Präzision**, **100 % Verweigerung korrekt**, erwartete Quelle
|
||||
93,3 %, mean 39,4 s / p95 82,2 s, 5 Regenerierungen; Report
|
||||
`data/eval-qwen38-rj.json` (lokal/unversioniert). Offline-Tests: 65
|
||||
grün. **Nicht als generelle
|
||||
Commit-Freigabe lesen:** Die gelieferten OGH/VwGH/VfGH-Dateien nennen
|
||||
überwiegend RIS-OGD, der User sprach jedoch von Lexis/opendataloader;
|
||||
die Publikations-/Lizenzfreigabe der quellentreuen Volltexte ist vor
|
||||
Commit ausdrücklich zu prüfen. EuGH-Wiedergaben sind als nichtamtlich
|
||||
markiert und verweisen auf EUR-Lex.
|
||||
|
||||
## Completed (2026-09-16)
|
||||
|
||||
- **D16 (Gestaltungsfragen / Retrieval-Tuning):** Goldset um q-124–126
|
||||
erweitert (500-Euro-Zusatzzahlung, Alternativen, Mitarbeiterprämie 2026).
|
||||
`agent/query_planner.py` erkennt Decision-Support deterministisch und zerlegt
|
||||
in drei gesetzlich gescopte Queries: Mitarbeiterprämie samt §-49-Konflikt,
|
||||
Zukunftssicherung sowie Sach-/zweckgebundene Leistungen. Decision-Support
|
||||
läuft als `specific`, nicht als Survey/Map-Reduce. `Retriever.search()` nutzt
|
||||
denselben Plan im Offline-Eval; `search_multi()` behält Scope/Jahr auch bei
|
||||
einer einzelnen Query. Ergebnis (53 Goldsetfragen / 48 Retrieval-Fälle):
|
||||
q-124/q-125/q-126 jeweils Recall@8 **1,00**, gesamt Recall@8 **0,9271**
|
||||
(Gate >0,9), Hit-Rate 0,9583, MRR 0,6158. Bekannte Altfehler q-015/q-113
|
||||
bleiben unverändert.
|
||||
- **Decision-Support-Grounding:** Systemprompt trennt Barzahlung von
|
||||
zweckgebundenen Leistungen, verbietet pauschale Sieger ohne Kontext,
|
||||
verlangt vergleichbare Abgabendimensionen und genau eine Rückfrage. Der
|
||||
bekannte Konflikt Mitarbeiterprämie 2026 wird offen dargestellt:
|
||||
`wk-akt-04` nennt SV/BV/DB/DZ/KommSt-Pflicht, `lb-sva-03` ordnet die Prämie
|
||||
systematisch in den taxativen Katalog beitragsfreier Bezüge ein. Zusätzlich
|
||||
erzwingt ein semantischer Post-Validation-Gate ⚠ + beide IDs + korrekte
|
||||
Rollen und verhindert interne Regelverweise bzw. Quellenpriorisierung.
|
||||
Gezielte Real-Läufe: q-124/q-125 nicht verweigert, zitiergültig; q-126 war
|
||||
bereits sauber. Tests **72 grün**; `git diff --check` sauber. Vollständiger
|
||||
Antwortmodus-Eval steht noch aus.
|
||||
|
||||
## Open issues / blockers
|
||||
|
||||
- **Push**: Remote localhost:3003 aus der Sandbox nicht erreichbar — User
|
||||
@@ -222,6 +273,40 @@ zu planen).
|
||||
q-113 (Gesetz+KV Multi-Source). Tests 50 -> 57.
|
||||
Offen: q-029 Survey (Stufe-2-Hebel: Map-Reduce), q-113 Planer-
|
||||
Scope flaky (1/2 Laeufe ohne gesetz-Marker).
|
||||
- **D13 (Antworttyp-Routing / Stufe 2, 2026-09-15):** (a) Planer liefert
|
||||
jetzt `type: survey|specific`; Survey-Fragen („Welche Neuerungen …“)
|
||||
laufen ueber Map-Reduce: breiteres Retrieval (`survey_blocks`=16,
|
||||
PV_SURVEY_BLOCKS), ein Map-Call destilliert JE Block als Stichpunkte
|
||||
mit seiner KB-ID (MAP_SYSTEM_PROMPT), ein Reduce-Call synthetisiert
|
||||
daraus die Antwort mit dem normalen Grounding-Prompt; Zitier-
|
||||
Validierung weiterhin strikt ueber die Retrieved-Union, leerer
|
||||
Map-Output -> Fallback Einzelantwort. (b) Systemprompt-Regel 9: bei
|
||||
wesentlicher Kontextabhaengigkeit (Branche, Bundesland, Zeitraum)
|
||||
belegte allgemeine Aussage + EINE Rueckfrage statt Verweigerung
|
||||
(API-first; Odoo-Chat kann die Rueckfrage als Follow-up nutzen).
|
||||
Ergebnis: **q-029 geheilt** (vorher jahrelange Fehlverweigerung;
|
||||
jetzt Teilantwort mit 5 belegten Heften, 95 s — Map-Reduce-Latenz
|
||||
nur bei Survey-Fragen), **q-015** antwortet mit expliziter
|
||||
KV-Abhaengigkeit + Rueckfrage statt Branchen-Noise. Eval (46 Fragen):
|
||||
Zitier-Praezision 97,8 %, Verweigerung 97,8 % (Gate erfuellt),
|
||||
erwartete Quelle 90,2 %, Latenz mean 34,2 s. Tests 57 -> 59.
|
||||
Report `data/eval-qwen38-stage2.json`. Verbleibend: q-024 transiente
|
||||
Flakiness (Think-Ghost-Verdacht, 2/3 Laeufe sauber).
|
||||
- **D14 (Output-Budget + length-Retry, 2026-09-15):** q-024-Flakiness
|
||||
Ursache gefunden — NICHT Thinking (Hypothese widerlegt: thinking-Feld
|
||||
leer, keine Tags), sondern `num_predict=1024`: lange belegte Antworten
|
||||
wurden bei `done_reason=length` abgschnitten (q-024: 3/3 Sondenlaeufe)
|
||||
→ unvollstaendige Zitationen → CITE_RE matcht partielle IDs →
|
||||
Verletzung → Regen-Eskalation → UNCERTAIN. Fix: (a) num_predict
|
||||
1024 → 2048; (b) `OllamaClient.chat_full()` liefert (content,
|
||||
done_reason); (c) `chat_with_length_retry`: ein technischer Retry
|
||||
mit 2× num_predict bei length (zaehlt nicht als Regel-Regenerierung,
|
||||
laeuft auch im Map- und im Regenerierungspfad).
|
||||
**Voll-Eval: Zitier-Praezision 100 %, Verweigerung korrekt 100 %**
|
||||
(46/46 — alle M3-Gates erfuellt, erstmals ueber Basislinie),
|
||||
erwartete Quelle 92,7 %, Latenz mean 39,6 s / p95 78 s (+5 s:
|
||||
vollstaendige statt abgeschnittener Antworten). q-024: 4/4 stabil.
|
||||
Tests 59 → 60. Report `data/eval-qwen38-lengthfix.json`.
|
||||
- **Bake-off-Protokoll** (Skill): Modellwechsel nur über dokumentierten
|
||||
Goldset-Vergleich; Kriterium: Zitier-Präzision > Verweigerungs-
|
||||
korrektheit > Latenz.
|
||||
@@ -233,4 +318,6 @@ zu planen).
|
||||
- `agent/README.md` — Betrieb, Konfiguration, Host-Schritte.
|
||||
- `agent/eval/goldset.yaml` — Goldset (IDs gegen kb.json verifiziert).
|
||||
- `agent/generate.py` — Grounding-Kern (Prompt, Post-Validierung).
|
||||
- `wissensbasis/README.md` — Layer-2-Schema (unverändert gültig).
|
||||
- `wissensbasis/README.md` — Layer-2-Schema + Rechtsprechungs-Provenance.
|
||||
- `tools/ingest_sources.py` / `tools/catalogs/rj_catalog.json` — rj-Intake und gefrorene IDs.
|
||||
- `agent/eval/goldset.yaml` — q-120–123; als Nächstes Antwortmodus-Eval.
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
.firecrawl/
|
||||
|
||||
# Scraped legal reference texts — local only
|
||||
.ris/
|
||||
.rechtsprechung/
|
||||
|
||||
# RAG service artifacts (index, caches, venv)
|
||||
data/
|
||||
|
||||
+51
-8
@@ -1,10 +1,10 @@
|
||||
# PV RAG Agent
|
||||
|
||||
Lokaler RAG-Agent für österreichische Personalverrechnung: beantwortet
|
||||
Fragen **ausschließlich** aus der kuratierten Wissensbasis (Layer 2,
|
||||
`wissensbasis/`, **1274 Einträge**: 601 lb/wk-Kuratierung + 614 WKO-KV-
|
||||
Dokumente + 59 RIS-Gesetze) — mit ID- und Stand-Beleg, ohne
|
||||
Trainingswissen, ohne Web-Zugriff. Verbindliche Regeln:
|
||||
Fragen **ausschließlich** aus der Wissensbasis (Layer 2,
|
||||
`wissensbasis/`, **1622 Einträge**: 601 lb/wk-Kuratierung + 614 WKO-KV-
|
||||
Dokumente + 59 RIS-Gesetze + 348 Rechtsprechungs-/Normquellen) — mit ID-
|
||||
und Stand-Beleg, ohne Trainingswissen, ohne Web-Zugriff. Verbindliche Regeln:
|
||||
`.agents/skills/pv-rag-agent/SKILL.md`, Plan: `planung.md`.
|
||||
|
||||
## Architektur (Kurzfassung)
|
||||
@@ -64,6 +64,7 @@ python -m agent.cli serve # http://127.0.0.1:8080 (/ask, /health, /r
|
||||
| `PV_QUERY_PLANNER` | `true` | Query-Planer an (Heuristik-Gate entscheidet je Frage) |
|
||||
| `PV_PLANNER_MODEL` | leer = Antwortmodell | Modell des Planer-Calls |
|
||||
| `PV_TEMPORAL_BOOST` | `0.0` | Bonus für kv-Einträge im gefragten Geltungsjahr |
|
||||
| `PV_SURVEY_BLOCKS` | `16` | Map-Reduce: breiteres Retrieval für Survey-Fragen (Typ `survey` vom Planer) |
|
||||
| `PV_NUM_CTX` | `32768` | Modell-Kontextfenster (KV-Chunks überschreiten 16k — Overflow trunciert den Systemprompt) |
|
||||
| `PV_MAX_CONTEXT_CHARS` | `90000` | User-Content-Budget; niedrig gerankte Blöcke werden ganz weggelassen (`trim_results`) |
|
||||
| `PV_CONTEXT_BLOCKS` | `8` | Kontextblöcke im Prompt |
|
||||
@@ -155,6 +156,45 @@ Report: `data/eval-qwen38-stage1-final.json`. Offen: q-029 Survey
|
||||
(Stufe-2-Hebel: Map-Reduce), q-015 Branchen-Noise → API-first-Rückfrage
|
||||
(Stufe 2).
|
||||
|
||||
**Antworttyp-Routing Stufe 2 (2026-09-15, M6/D13):** Planer liefert
|
||||
`type: survey|specific`. Survey-Fragen („Welche Neuerungen …“) →
|
||||
**Map-Reduce**: Retrieval auf `survey_blocks` (16) erweitert, ein Map-Call
|
||||
destilliert jeden Block als Stichpunkte mit seiner KB-ID, ein Reduce-Call
|
||||
synthetisiert die Endantwort — Zitier-Validierung weiterhin strikt über
|
||||
die Retrieved-Union. **Regel 9** (Kontext-Abhängigkeit): belegte allgemeine
|
||||
Aussage + eine Rückfrage statt Verweigerung (Branche/Bundesland/Zeitraum).
|
||||
Ergebnisse: q-029 geheilt (5 belegte Hefte, ~95 s Map-Reduce-Latenz),
|
||||
q-015 antwortet mit KV-Abhängigkeit + Rückfrage. Eval (46 Fragen):
|
||||
Zitier-Präzision 97,8 % · Verweigerung 97,8 % (Gate ✓) · erwartete
|
||||
Quelle 90,2 % · Latenz mean 34,2 s. Report: `data/eval-qwen38-stage2.json`.
|
||||
|
||||
**Output-Budget + length-Retry (2026-09-15, D14):** Die q-024-Flakiness
|
||||
war kein Thinking, sondern `num_predict=1024`: lange belegte Antworten
|
||||
wurden bei `done_reason=length` abgeschnitten → unvollständige Zitationen
|
||||
→ Verletzungs-/Eskalationsspirale. Fix: `num_predict=2048`, `chat_full()`
|
||||
liefert `done_reason`, bei `length` ein technischer Retry mit 2× Budget
|
||||
(kein Regel-Regenerierungs-Zähler). **Voll-Eval: Zitier-Präzision
|
||||
100 % · Verweigerung korrekt 100 %** (46/46, alle M3-Gates erstmals
|
||||
voll erfüllt) · erwartete Quelle 92,7 % · Latenz mean 39,6 s / p95 78 s.
|
||||
Report: `data/eval-qwen38-lengthfix.json`. Offene Restfälle: keine
|
||||
Fehlverweigerungen/Verletzungen mehr; 3-4 Fragen zitiert gültige,
|
||||
aber nicht die erwartete Quelle (q-015-Klasse).
|
||||
|
||||
**Rechtsprechungs-Intake (2026-09-15, D15):** Korpus 1.274 → **1.622**
|
||||
Einträge: 320 RIS-OGD-Entscheidungen/Rechtssätze, 23 zitierte RIS-
|
||||
Normauszüge und 5 als nichtamtlich markierte EuGH-Textwiedergaben im neuen
|
||||
`rj-rjs-*`-ID-Raum. Der Reindex erzeugte **16.480 Chunks** (1.496 neue
|
||||
`bge-m3`-Embeddings, 75 s). Retrieval mit dem erweiterten 50-Fragen-Goldset:
|
||||
Hit-Rate **0,956** · Recall@8 **0,922** · MRR 0,661; das Recall-Gate >0,9
|
||||
bleibt erfüllt, alle vier neuen Rechtsprechungsfälle werden gefunden. Der
|
||||
vollständige Antwortmodus-Eval (50 Fragen) erreicht **100 % Zitier-Präzision**
|
||||
und **100 % korrekte Verweigerungen**, bei 93,3 % erwarteter Quelle, mean
|
||||
39,4 s / p95 82,2 s und fünf Regenerierungen. Report:
|
||||
`data/eval-qwen38-rj.json` (lokal, unversioniert). EuGH-Texte sind im Kontext
|
||||
und in der Quelle explizit als nichtamtliche lexetius-Wiedergabe
|
||||
gekennzeichnet; der Systemprompt verlangt nun dieselbe Einschränkung auch in
|
||||
der Antwort.
|
||||
|
||||
## Dateien
|
||||
|
||||
```
|
||||
@@ -171,7 +211,7 @@ agent/
|
||||
eval/ goldset.yaml + evaluate.py
|
||||
web/index.html Minimaler Test-Chat
|
||||
tools/ Intake + Registry (build_registry.py, ingest_sources.py)
|
||||
tests/ 49 Tests (offline, Fake-Ollama)
|
||||
tests/ 64 Tests (offline, Fake-Ollama)
|
||||
data/ index.db (gitignored)
|
||||
```
|
||||
|
||||
@@ -183,6 +223,9 @@ python -m pytest -q # 49 Tests, alle offline
|
||||
|
||||
## Lizenz-Disziplin
|
||||
|
||||
`.lexis360/`, `.wiku/`, `.firecrawl/`, `.ris/` sind lokal und unversioniert
|
||||
(`.gitignore`). Der Index enthält ausschließlich Layer-2-Kuratierung;
|
||||
Layer-1-Prompts wären ein Lizenzverstoß und sind im Code nicht vorgesehen.
|
||||
`.lexis360/`, `.wiku/`, `.firecrawl/`, `.firecrawl/ris/gesetze/`, `.rechtsprechung/` sind lokal
|
||||
und unversioniert (`.gitignore`). Der Index enthält ausschließlich Layer-2-
|
||||
Inhalte; Layer-1-Prompts wären ein Lizenzverstoß und sind im Code nicht
|
||||
vorgesehen. Die quellentreuen `rj_*.md` sind vor einer Versionierung anhand
|
||||
von Provenance und Lizenzfreigabe der gelieferten Volltexte zu prüfen; die
|
||||
EuGH-Wiedergaben sind ausdrücklich nicht amtlich.
|
||||
+6
-1
@@ -51,7 +51,9 @@ class Config:
|
||||
# (KV-Cache @32k ~6-8 GB -> gesamt ~21 GB, Budget ok)
|
||||
max_context_chars: int = 90_000 # Budget fuer User-Content; niedrig gerankte
|
||||
# Bloecke werden weggelassen statt trunciert
|
||||
num_predict: int = 1024
|
||||
num_predict: int = 2048 # Output-Budget; 1024 schnitt lange belegte
|
||||
# Antworten ab (done_reason=length, q-024-Fall)
|
||||
# -> unvollstaendige Zitationen
|
||||
think: bool = False # Thinking per Request abschalten (Latenz)
|
||||
chat_timeout_s: float = 300.0
|
||||
embed_timeout_s: float = 240.0
|
||||
@@ -80,6 +82,8 @@ class Config:
|
||||
planner_model: str = "" # leer = Antwortmodell
|
||||
per_query_slots: int = 2 # Multi-Query: garantierte Kontext-Slots
|
||||
# je Sub-Query (Multi-Hop-Abdeckung)
|
||||
survey_blocks: int = 16 # Map-Reduce (Stufe 2): breiteres
|
||||
# Retrieval fuer Survey-Fragen
|
||||
temporal_boost: float = 0.0 # Bonus fuer kv-Eintraege im gefragten
|
||||
# Geltungsjahr (0 = nur FTS-Tag-Signal)
|
||||
|
||||
@@ -115,6 +119,7 @@ class Config:
|
||||
planner_num_predict=_env_int("PV_PLANNER_NUM_PREDICT", d.planner_num_predict),
|
||||
planner_model=_env_str("PV_PLANNER_MODEL", d.planner_model),
|
||||
per_query_slots=_env_int("PV_PER_QUERY_SLOTS", d.per_query_slots),
|
||||
survey_blocks=_env_int("PV_SURVEY_BLOCKS", d.survey_blocks),
|
||||
temporal_boost=_env_float("PV_TEMPORAL_BOOST", d.temporal_boost),
|
||||
port=_env_int("PV_PORT", d.port),
|
||||
)
|
||||
@@ -146,6 +146,39 @@ questions:
|
||||
expect_refusal: true
|
||||
note: "Branche nicht im KV-Korpus — Retrieval darf nicht leer sein, Antwort muss verweigern."
|
||||
|
||||
# --- Rechtsprechung / Normauszüge (Batch rj 1, 2026-09-15) ---
|
||||
- id: q-120
|
||||
question: "Rechtfertigt eine schriftliche Rüge eines Hauptbuchhalters den vorzeitigen Austritt?"
|
||||
expected_ids: [rj-rjs-020]
|
||||
note: "OGH-Rechtssatz; nur die konkret dokumentierte Rüge und Verschuldensabwägung behaupten."
|
||||
- id: q-121
|
||||
question: "Was entschied der Verfassungsgerichtshof zur Strafbestimmung des AVRAG bei nicht bereitgestellten Lohnunterlagen?"
|
||||
expected_ids: [rj-rjs-006]
|
||||
- id: q-122
|
||||
question: "Wann ist das fortlaufende Gehalt nach § 15 AngG zu zahlen?"
|
||||
expected_ids: [rj-rjs-333]
|
||||
- id: q-123
|
||||
question: "Welche Bedeutung hat nach EuGH C-29/91 der Übergang von Tätigkeiten nach einer Subventionsverlagerung?"
|
||||
expected_ids: [rj-rjs-002]
|
||||
note: "Nur als nichtamtliche lexetius-Textwiedergabe im Korpus; Antwort muss den Stand 1992-05 führen."
|
||||
|
||||
# --- Gestaltungsfragen / Entscheidungsunterstützung ---
|
||||
- id: q-124
|
||||
question: "Ich will meinem Mitarbeiter 500 Euro zusätzlich auszahlen. Was ist die günstigste Lösung?"
|
||||
expected_ids: [wk-akt-04, lb-sva-03]
|
||||
note: "Offene Gestaltungsfrage: Zeitraum, Branche/KV, gewünschte Barzahlung und persönliche Voraussetzungen fehlen. Für 2026 ist die Mitarbeiterprämie ein direkter Kandidat; Konflikt zur SV-Behandlung zwischen wk-akt-04 (pflichtig) und lb-sva-03 (beitragsfrei) ausdrücklich mit beiden IDs darstellen und gezielt rückfragen. Keine pauschale Empfehlung."
|
||||
tags: [decision-support, clarification, conflict]
|
||||
- id: q-125
|
||||
question: "Welche abgabenbegünstigten Möglichkeiten gibt es 2026 statt einer normalen zusätzlichen Barprämie von 500 Euro?"
|
||||
expected_ids: [wk-akt-04, lb-vor-11, lb-ges-01, lb-sva-04]
|
||||
note: "Vergleichs-/Survey-Frage: Mitarbeiterprämie, Zukunftssicherung, Sachzuwendungen und Mahlzeiten-/Kinderbetreuungsleistungen unterscheiden; Voraussetzungen und fehlenden Arbeitnehmerkontext nennen. Nicht behaupten, alle Alternativen seien frei als Bargeld auszahlbar."
|
||||
tags: [decision-support, survey]
|
||||
- id: q-126
|
||||
question: "Kann ich 2026 jedem Mitarbeiter einfach 500 Euro steuerfrei als Mitarbeiterprämie auszahlen?"
|
||||
expected_ids: [wk-akt-04]
|
||||
note: "Prämisse korrigieren: keine voraussetzungslose Auszahlung; lohngestaltende Grundlage, Zeitraum, Zusätzlichkeit und Abgaben außerhalb der Lohnsteuer anhand der Quelle erklären."
|
||||
tags: [decision-support, premise-correction]
|
||||
|
||||
# --- Komplexe Fragen (Stufe 1, M6: Multi-Query + Temporal-Intent) ---
|
||||
- id: q-110
|
||||
question: "Wie hoch war der kollektivvertragliche Mindestmonatslohn für angelernte Friseurinnen und Friseure ab 1.4.2023?"
|
||||
|
||||
+144
-16
@@ -13,7 +13,7 @@ import time
|
||||
from .config import Config
|
||||
from .normalize import normalize_text
|
||||
from .ollama_client import OllamaClient
|
||||
from .query_planner import SubQuery, plan_queries
|
||||
from .query_planner import SubQuery, is_decision_support, plan_queries
|
||||
from .retrieve import ChunkResult, Retriever
|
||||
|
||||
REFUSAL_MESSAGE = "Dazu enthält die Wissensbasis keine Aussage."
|
||||
@@ -39,20 +39,57 @@ Verbindliche Regeln:
|
||||
mache klar, welcher Aspekt belegt ist. Verweigere nur, wenn KEIN
|
||||
Block thematisch zur Frage passt, mit exakt:
|
||||
„Dazu enthält die Wissensbasis keine Aussage.“ — und schlage nichts vor.
|
||||
5. Widersprechen sich Kontextblöcke, nenne beide Werte mit ihren IDs und
|
||||
kennzeichne den Widerspruch mit ⚠. Löse Widersprüche niemals stillschweigend auf.
|
||||
5. Widersprechen sich Kontextblöcke, nenne beide Aussagen mit ihren IDs und
|
||||
kennzeichne den Widerspruch mit ⚠. Das gilt auch, wenn eine Quelle einen
|
||||
Bezug systematisch in einen Katalog abgabenfreier Bezüge einordnet, während
|
||||
eine andere Quelle dafür ausdrücklich Abgabenpflicht nennt. Löse
|
||||
Widersprüche niemals stillschweigend auf.
|
||||
6. Nenne Paragraphen und Gesetze nur, wenn ein Kontextblock sie nennt.
|
||||
7. Antworte auf Deutsch und prägnant (Stichpunkte, wo sinnvoll).
|
||||
8. Baut die Frage auf einer falschen Annahme auf (z. B. ein nicht
|
||||
existierendes Gesetz), korrigiere die Annahme anhand der Blöcke und
|
||||
gib die zutreffende, belegte Aussage. Muster: Auf „Was regelt das
|
||||
Mindestlohngesetz?“ antworte sinngemäß „Ein Mindestlohngesetz existiert
|
||||
laut Kontext nicht; stattdätzlich gilt …“ — mit Beleg [ID].
|
||||
laut Kontext nicht; stattdessen gilt …“ — mit Beleg [ID].
|
||||
Verweigere in diesem Fall nicht.
|
||||
9. Hängt die Antwort wesentlich von nicht genanntem Kontext ab (z. B.
|
||||
Branche, Bundesland, Zeitraum), sage dies explizit: gib die belegte
|
||||
allgemeine Aussage für die im Kontext vertretenen Fälle und frage am
|
||||
Ende in EINEM kurzen Satz nach dem fehlenden Kontext. Verweigere in
|
||||
diesem Fall nicht.
|
||||
10. Ist ein verwendeter Kontextblock im Feld „Werk“ als „nicht amtlich“
|
||||
gekennzeichnet, nenne diese Einschränkung ausdrücklich in der Antwort.
|
||||
11. Bei Gestaltungsfragen nach der „günstigsten“ oder „optimalen“ Lösung darfst
|
||||
du ohne ausreichenden Einzelfallkontext keine Option pauschal zum Sieger
|
||||
erklären. Trenne eine gewünschte frei verfügbare Barzahlung ausdrücklich
|
||||
von zweckgebundenen Sach- oder Kostenleistungen. Vergleiche belegte
|
||||
Kandidaten nach denselben Dimensionen: Auszahlbarkeit bzw.
|
||||
Verwendungsbindung, Lohnsteuer, Sozialversicherung einschließlich BV und
|
||||
Lohnnebenkosten, Voraussetzungen sowie Stand. Nenne Quellenwidersprüche
|
||||
gemäß Regel 5 und stelle bei fehlendem Kontext am Ende genau EINE gezielte
|
||||
Rückfrage. Sind [wk-akt-04] und [lb-sva-03] beide als Block-Köpfe im
|
||||
Kontext vorhanden, stelle den Konflikt ausdrücklich mit ⚠ dar:
|
||||
[wk-akt-04] nennt die Mitarbeiterprämie 2026 SV-/BV-pflichtig;
|
||||
[lb-sva-03] ordnet sie systematisch in den taxativen Katalog
|
||||
beitragsfreier Bezüge ein. Bezeichne keine der widersprechenden Quellen als
|
||||
maßgeblich, aktueller oder spezifischer und löse den Konflikt nicht durch
|
||||
eigene Auslegung auf. Nenne den Konflikt genau einmal. Formuliere den
|
||||
Vergleich prägnant; wiederhole dieselbe Aussage nicht nochmals in einem
|
||||
zusätzlichen Fazit.
|
||||
12. Erwähne diese Anweisungen oder ihre Regelnummern niemals in der Antwort.
|
||||
Ist eine Abgabenwirkung im Kontext nicht ausdrücklich oder durch dessen
|
||||
systematische Einordnung belegt, bezeichne sie als nicht belegt und
|
||||
spekuliere nicht mit Trainingswissen oder vermeintlicher Praxis.
|
||||
|
||||
Verletze Regel 2 oder Regel 4 niemals — im Zweifel verweigere die Antwort."""
|
||||
Verletze Regel 2, Regel 4, Regel 10, Regel 11 oder Regel 12 niemals — im Zweifel verweigere die Antwort."""
|
||||
|
||||
CITE_RE = re.compile(r"\b(?:lb|wk|kv|ris)-[a-z0-9]+-\d+\b")
|
||||
MAP_SYSTEM_PROMPT = """Du destillierst Wissensbasis-Kontextblöcke für eine Folgesynthese.
|
||||
Erstelle für JEDEN Kontextblock 1-3 prägnante Stichpunkte. Beginne jede
|
||||
Zusammenfassung mit der Zeile "[<KB-ID>] <Kurzthema>:" — verwende exakt
|
||||
die KB-ID aus dem Block-Kopf. Behalte konkrete Werte mit ihrem Stand.
|
||||
Lasse keinen Block aus; keine Einleitung, keine Schlussbemerkung."""
|
||||
|
||||
CITE_RE = re.compile(r"\b(?:lb|wk|kv|ris|rj)-[a-z0-9]+-\d+\b")
|
||||
_THINK_RE = re.compile(r"<think>.*?</think>", re.DOTALL)
|
||||
|
||||
|
||||
@@ -112,6 +149,45 @@ def validate_answer(answer: str, allowed_ids: list[str]) -> list[str]:
|
||||
return violations
|
||||
|
||||
|
||||
def validate_decision_support_answer(
|
||||
question: str, answer: str, allowed_ids: list[str]
|
||||
) -> list[str]:
|
||||
"""Semantischer Gate für den bekannten Mitarbeiterprämien-Konflikt.
|
||||
|
||||
Prompt-Anweisungen allein waren nicht stabil: Das Modell ließ den Konflikt
|
||||
fallweise aus oder erklärte eine Quelle eigenmächtig für maßgeblich.
|
||||
"""
|
||||
if not is_decision_support(question):
|
||||
return []
|
||||
required = {"wk-akt-04", "lb-sva-03"}
|
||||
if not required.issubset(set(allowed_ids)):
|
||||
return []
|
||||
cited = set(CITE_RE.findall(answer))
|
||||
violations: list[str] = []
|
||||
if "⚠" not in answer or not required.issubset(cited):
|
||||
violations.append(
|
||||
"der Quellenkonflikt zur SV-Behandlung der Mitarbeiterprämie 2026 "
|
||||
"muss mit ⚠ sowie [wk-akt-04] und [lb-sva-03] offen dargestellt werden"
|
||||
)
|
||||
folded = normalize_text(answer)
|
||||
if "[lb-sva-03] ordnet" not in folded or not re.search(
|
||||
r"\[wk-akt-04\].{0,160}(?:pflicht|pflichtig)", folded, re.DOTALL
|
||||
):
|
||||
violations.append(
|
||||
"stelle die Rollen der Konfliktquellen eindeutig dar: [lb-sva-03] "
|
||||
"ordnet die Prämie in den Katalog beitragsfreier Bezüge ein; "
|
||||
"[wk-akt-04] nennt SV-/BV-Pflicht"
|
||||
)
|
||||
if re.search(r"\bgemäß (?:der )?regel|\bregel \d+", folded):
|
||||
violations.append("erwähne keine internen Regeln oder Regelnummern")
|
||||
if re.search(r"\b(?:aktuellere|maßgebliche|spezifischere)\w* (?:quelle|news|aussage)", folded):
|
||||
violations.append(
|
||||
"priorisiere bei dem offenen Konflikt keine Quelle als aktueller, "
|
||||
"maßgeblicher oder spezifischer"
|
||||
)
|
||||
return violations
|
||||
|
||||
|
||||
def _source_rows(results: list[ChunkResult]) -> list[dict]:
|
||||
rows = []
|
||||
seen: set[str] = set()
|
||||
@@ -157,15 +233,19 @@ def answer_question(
|
||||
|
||||
sub_queries = [SubQuery(text=question)]
|
||||
planned = False
|
||||
qtype = "specific"
|
||||
if cfg.planner_enabled:
|
||||
try:
|
||||
sub_queries, planned = plan_queries(question, client, cfg)
|
||||
sub_queries, planned, qtype = plan_queries(question, client, cfg)
|
||||
sub_queries = sub_queries[: cfg.planner_max_queries] or sub_queries[:1]
|
||||
except Exception:
|
||||
sub_queries, planned = [SubQuery(text=question)], False
|
||||
sub_queries, planned, qtype = [SubQuery(text=question)], False, "specific"
|
||||
|
||||
n_entries = top_k
|
||||
if n_entries is None and qtype == "survey":
|
||||
n_entries = cfg.survey_blocks
|
||||
try:
|
||||
results = retriever.search_multi(sub_queries, n_entries=top_k)
|
||||
results = retriever.search_multi(sub_queries, n_entries=n_entries)
|
||||
finally:
|
||||
if own_retriever:
|
||||
retriever.close()
|
||||
@@ -202,21 +282,68 @@ def answer_question(
|
||||
{"role": "system", "content": SYSTEM_PROMPT},
|
||||
{"role": "user", "content": build_user_content(question, results)},
|
||||
]
|
||||
map_messages = None
|
||||
if qtype == "survey":
|
||||
# Map-Reduce (Stufe 2): alle Bloecke destillieren (Map), dann
|
||||
# synthetisieren (Reduce). Zitiert werden duerfen weiterhin nur IDs
|
||||
# aus der Retrieved-Menge — die Post-Validierung bleibt unveraendert.
|
||||
map_messages = [
|
||||
{"role": "system", "content": MAP_SYSTEM_PROMPT},
|
||||
{"role": "user", "content": build_user_content(question, results)},
|
||||
]
|
||||
|
||||
def chat(msgs):
|
||||
return strip_think(
|
||||
client.chat(
|
||||
def chat(msgs, num_predict: int | None = None):
|
||||
"""Ein Chat-Zug; liefert (gestrippter Content, done_reason).
|
||||
Bei done_reason='length' (Antwort bei num_predict abgeschnitten)
|
||||
sind Zitationen ggf. unvollstaendig — der Aufrufer ruft einmal mit
|
||||
doppeltem Budget neu (technischer Retry, kein Regel-Regeneration)."""
|
||||
budget = num_predict or cfg.num_predict
|
||||
if hasattr(client, "chat_full"):
|
||||
raw, done_reason = client.chat_full(
|
||||
cfg.answer_model,
|
||||
msgs,
|
||||
temperature=cfg.temperature,
|
||||
num_ctx=cfg.num_ctx,
|
||||
num_predict=cfg.num_predict,
|
||||
num_predict=budget,
|
||||
think=cfg.think,
|
||||
)
|
||||
)
|
||||
else:
|
||||
raw = client.chat(
|
||||
cfg.answer_model,
|
||||
msgs,
|
||||
temperature=cfg.temperature,
|
||||
num_ctx=cfg.num_ctx,
|
||||
num_predict=budget,
|
||||
think=cfg.think,
|
||||
)
|
||||
done_reason = "stop"
|
||||
return strip_think(raw), done_reason
|
||||
|
||||
final = chat(messages)
|
||||
def chat_with_length_retry(msgs):
|
||||
final, done_reason = chat(msgs)
|
||||
if done_reason == "length":
|
||||
final, done_reason = chat(msgs, num_predict=cfg.num_predict * 2)
|
||||
return final
|
||||
|
||||
if map_messages is not None:
|
||||
summary = chat_with_length_retry(map_messages)
|
||||
if summary:
|
||||
messages = [
|
||||
{"role": "system", "content": SYSTEM_PROMPT},
|
||||
{
|
||||
"role": "user",
|
||||
"content": (
|
||||
"Kontextblöcke aus der Wissensbasis "
|
||||
f"(Block-Zusammenfassungen):\n\n{summary}\n\n"
|
||||
f"Frage: {question}"
|
||||
),
|
||||
},
|
||||
]
|
||||
# leerer Map-Output -> Fallback: messages bleibt die Einzelantwort
|
||||
|
||||
final = chat_with_length_retry(messages)
|
||||
violations = validate_answer(final, allowed)
|
||||
violations += validate_decision_support_answer(question, final, allowed)
|
||||
regenerations = 0
|
||||
if violations:
|
||||
regenerations = 1
|
||||
@@ -227,12 +354,13 @@ def answer_question(
|
||||
"Beantworte die Frage erneut und zitiere nur diese IDs — oder verweigere "
|
||||
f"mit dem vorgesehenen Satz („{REFUSAL_MESSAGE}“)."
|
||||
)
|
||||
retry = chat(
|
||||
retry = chat_with_length_retry(
|
||||
messages
|
||||
+ [{"role": "assistant", "content": final},
|
||||
{"role": "user", "content": warn}]
|
||||
)
|
||||
retry_violations = validate_answer(retry, allowed)
|
||||
retry_violations += validate_decision_support_answer(question, retry, allowed)
|
||||
if not retry_violations:
|
||||
final = retry
|
||||
violations = []
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ from pathlib import Path
|
||||
|
||||
import yaml
|
||||
|
||||
ID_RE = re.compile(r"^(lb|wk|kv|ris)-[a-z0-9]+-\d+$")
|
||||
ID_RE = re.compile(r"^(lb|wk|kv|ris|rj)-[a-z0-9]+-\d+$")
|
||||
STAND_RE = re.compile(r"^\d{4}-\d{2}$")
|
||||
REQUIRED_KEYS = (
|
||||
"id", "batch", "title", "work", "chapter", "topic", "author",
|
||||
|
||||
+18
-4
@@ -74,10 +74,14 @@ class OllamaClient:
|
||||
|
||||
# -- Chat ---------------------------------------------------------------
|
||||
|
||||
def chat(self, model: str, messages: list[dict],
|
||||
temperature: float = 0.1, num_ctx: int = 16384,
|
||||
num_predict: int = 1024, think: bool = False) -> str:
|
||||
"""POST /api/chat, stream=False; `think`-Flag mit 404/400-Fallback."""
|
||||
def chat_full(self, model: str, messages: list[dict],
|
||||
temperature: float = 0.1, num_ctx: int = 16384,
|
||||
num_predict: int = 1024,
|
||||
think: bool = False) -> tuple[str, str]:
|
||||
"""POST /api/chat; liefert (content, done_reason). done_reason ==
|
||||
'length' bedeutet: Antwort wurde bei num_predict abgeschnitten —
|
||||
Zitationen koennen dann unvollstaendig sein (Think-Ghost-Ursache
|
||||
q-024, D13-Follow-up)."""
|
||||
body: dict[str, Any] = {
|
||||
"model": model,
|
||||
"messages": messages,
|
||||
@@ -105,4 +109,14 @@ class OllamaClient:
|
||||
content = msg.get("content") or ""
|
||||
if not content.strip():
|
||||
raise OllamaError(f"empty response from {model} (keys: {list(data.keys())})")
|
||||
return content, str(data.get("done_reason") or "stop")
|
||||
|
||||
def chat(self, model: str, messages: list[dict],
|
||||
temperature: float = 0.1, num_ctx: int = 16384,
|
||||
num_predict: int = 1024, think: bool = False) -> str:
|
||||
"""POST /api/chat, stream=False; `think`-Flag mit 404/400-Fallback."""
|
||||
content, _ = self.chat_full(
|
||||
model, messages, temperature=temperature, num_ctx=num_ctx,
|
||||
num_predict=num_predict, think=think,
|
||||
)
|
||||
return content
|
||||
+86
-12
@@ -11,6 +11,7 @@ from __future__ import annotations
|
||||
import json
|
||||
import re
|
||||
from dataclasses import dataclass
|
||||
from datetime import date
|
||||
|
||||
YEAR_RE = re.compile(r"\b(?:19|20)\d{2}\b")
|
||||
JSON_RE = re.compile(r"\{.*\}", re.DOTALL)
|
||||
@@ -19,6 +20,12 @@ AGGREGATION_RE = re.compile(
|
||||
r"neuerungen|übersicht|zusammenfassung|alle\s|übersicht", re.I
|
||||
)
|
||||
COMPARISON_RE = re.compile(r"unterschied|vergleic|\bbzw\.|\bsowie\b", re.I)
|
||||
DECISION_SUPPORT_RE = re.compile(
|
||||
r"günstig(?:ste|er|e)?\s+lösung|abgabenbegünstigt|steuerfrei.*(?:auszahl|präm)|"
|
||||
r"(?:zusätzlich|extra).*(?:auszahl|präm)",
|
||||
re.IGNORECASE,
|
||||
)
|
||||
|
||||
|
||||
PLANNER_PROMPT = """Du planst Suchanfragen für eine Wissensbasis zur österreichischen
|
||||
Personalverrechnung (kuratierte Briefings, Kollektivverträge je Branche und
|
||||
@@ -37,9 +44,11 @@ beantworten. Regeln:
|
||||
- Setze "scope" je Suchanfrage: "gesetz", wenn nach der gesetzlichen/
|
||||
allgemeinen Grundlage gefragt ist (nur Gesetze und Fachbriefings, ohne
|
||||
Branchen-Kollektivverträge); "kv", wenn ausdrücklich nach kollektivvertrag-
|
||||
lichen Branchenregelungen gefragt ist; null für alles andere.
|
||||
lichen Branchenregelungen gefragt ist; null für alles anderes.
|
||||
- Setze "type" auf "survey", wenn die Frage eine Übersicht über viele
|
||||
Dokumente verlangt (Neuerungen, Entwicklungen, alle …); sonst "specific".
|
||||
- Antworte ausschließlich mit JSON, ohne Erklärung:
|
||||
{{"queries": [{{"text": "...", "stand_year": null, "scope": null}}]}}"""
|
||||
{{"type": "specific", "queries": [{{"text": "...", "stand_year": null, "scope": null}}]}}"""
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -49,6 +58,11 @@ class SubQuery:
|
||||
scope: str | None = None # "gesetz" (ohne Branchen-KV) | "kv" | None
|
||||
|
||||
|
||||
def is_decision_support(question: str) -> bool:
|
||||
"""Erkennt Gestaltungsfragen, die den deterministischen Plan benötigen."""
|
||||
return bool(DECISION_SUPPORT_RE.search(question))
|
||||
|
||||
|
||||
def should_plan(question: str) -> bool:
|
||||
"""Heuristik-Gate: nur komplexe Fragen bekommen einen Planer-Call.
|
||||
|
||||
@@ -62,6 +76,8 @@ def should_plan(question: str) -> bool:
|
||||
return True
|
||||
if COMPARISON_RE.search(q):
|
||||
return True
|
||||
if is_decision_support(q):
|
||||
return True
|
||||
if AGGREGATION_RE.search(q):
|
||||
return True
|
||||
if " und " in q.casefold() and len(words) >= 10:
|
||||
@@ -69,8 +85,59 @@ def should_plan(question: str) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
def parse_plan(raw: str, original: str) -> list[SubQuery]:
|
||||
"""Robustes JSON-Parsing; jeder Fehler → [Originalfrage]."""
|
||||
def decision_support_plan(
|
||||
question: str, default_year: str | None = None
|
||||
) -> tuple[list[SubQuery], str] | None:
|
||||
"""Deterministische Zerlegung für Gestaltungsfragen zu zusätzlichen
|
||||
Arbeitnehmerleistungen. Sie verhindert, dass die vielen Branchen-KV-
|
||||
Treffer allgemeine Abgabenregeln verdrängen.
|
||||
|
||||
Ohne genanntes Jahr wird der neueste Indexstand verwendet; die Antwort
|
||||
muss fehlenden Einzelfallkontext weiterhin über die Prompt-Regel erfragen.
|
||||
"""
|
||||
if not is_decision_support(question):
|
||||
return None
|
||||
explicit_year = YEAR_RE.search(question)
|
||||
year = explicit_year.group(0) if explicit_year else default_year
|
||||
year_text = f" {year}" if year else ""
|
||||
direct = SubQuery(
|
||||
text=(
|
||||
f"Mitarbeiterprämie{year_text} WIKU Personal aktuell Nr 12 FAQ "
|
||||
"Höchstbetrag 500 Lohnsteuer SV BV Beitragsfreie Bezugsbestandteile "
|
||||
"§ 49 Abs 3 Z 30"
|
||||
),
|
||||
stand_year=year,
|
||||
scope="gesetz",
|
||||
)
|
||||
cash_and_benefits = SubQuery(
|
||||
text=(
|
||||
"Zukunftssicherungsmaßnahmen 300 Kalenderjahr Risikoversicherung "
|
||||
"Gruppenerfordernis Bezugsumwandlung Lohnsteuer SV BV DB DZ KommSt"
|
||||
),
|
||||
stand_year=year,
|
||||
scope="gesetz",
|
||||
)
|
||||
purpose_bound = SubQuery(
|
||||
text=(
|
||||
"Sachzuwendungen Geschenke Barzahlungen stets steuerpflichtig Freibetrag "
|
||||
"Beitragsfreie Bezugsbestandteile Z 1 bis Z 16a Mahlzeiten "
|
||||
"Kinderbetreuungszuschuss"
|
||||
),
|
||||
stand_year=year,
|
||||
scope="gesetz",
|
||||
)
|
||||
broad = bool(
|
||||
re.search(r"günstig|möglichkeiten|statt|alternative", question, re.IGNORECASE)
|
||||
)
|
||||
# Ein Gestaltungsvergleich ist kein Korpus-Survey: Die drei gezielten
|
||||
# Queries passen in den normalen Antwortpfad und vermeiden unnötiges
|
||||
# Map-Reduce samt zusätzlicher Latenz/Fehlverweigerungsrisiko.
|
||||
return ([direct, cash_and_benefits, purpose_bound] if broad else [direct]), "specific"
|
||||
|
||||
|
||||
def parse_plan(raw: str, original: str) -> tuple[list[SubQuery], str]:
|
||||
"""Robustes JSON-Parsing; jeder Fehler → [Originalfrage]. Liefert
|
||||
(Sub-Queries, Fragetyp 'survey' | 'specific')."""
|
||||
try:
|
||||
match = JSON_RE.search(raw)
|
||||
if not match:
|
||||
@@ -89,8 +156,10 @@ def parse_plan(raw: str, original: str) -> list[SubQuery]:
|
||||
scope = item.get("scope")
|
||||
scope = scope if scope in ("gesetz", "kv") else None
|
||||
subs.append(SubQuery(text=text, stand_year=year, scope=scope))
|
||||
return subs
|
||||
qtype = data.get("type") if data.get("type") in ("survey", "specific") else "specific"
|
||||
return subs, qtype
|
||||
except (ValueError, TypeError, KeyError, json.JSONDecodeError):
|
||||
return [SubQuery(text=original)], "specific"
|
||||
return [SubQuery(text=original)]
|
||||
|
||||
|
||||
@@ -98,12 +167,16 @@ def plan_queries(
|
||||
question: str,
|
||||
client,
|
||||
cfg,
|
||||
) -> tuple[list[SubQuery], bool]:
|
||||
"""Liefert (Sub-Queries, geplant?) — Call-/Parse-Fehler → Original als
|
||||
Einzel-Query. Der Planer-Call ist klein (Frage ohne Kontext, kurzes
|
||||
num_predict); Temperature 0."""
|
||||
) -> tuple[list[SubQuery], bool, str]:
|
||||
"""Liefert (Sub-Queries, geplant?, Fragetyp) — Call-/Parse-Fehler →
|
||||
Original als Einzel-Query, Typ 'specific'. Der Planer-Call ist klein
|
||||
(Frage ohne Kontext, kurzes num_predict); Temperature 0."""
|
||||
deterministic = decision_support_plan(question, default_year=str(date.today().year))
|
||||
if deterministic:
|
||||
subs, qtype = deterministic
|
||||
return subs, True, qtype
|
||||
if not should_plan(question):
|
||||
return [SubQuery(text=question)], False
|
||||
return [SubQuery(text=question)], False, "specific"
|
||||
prompt = PLANNER_PROMPT.format(question=question.strip())
|
||||
try:
|
||||
raw = client.chat(
|
||||
@@ -118,5 +191,6 @@ def plan_queries(
|
||||
think=False,
|
||||
)
|
||||
except Exception:
|
||||
return [SubQuery(text=question)], False
|
||||
return parse_plan(raw, question), True
|
||||
return [SubQuery(text=question)], False, "specific"
|
||||
subs, qtype = parse_plan(raw, question)
|
||||
return subs, True, qtype
|
||||
+17
-3
@@ -13,7 +13,7 @@ import numpy as np
|
||||
from .config import Config
|
||||
from .normalize import fts_query
|
||||
from .ollama_client import OllamaClient
|
||||
from .query_planner import SubQuery
|
||||
from .query_planner import SubQuery, decision_support_plan
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -386,8 +386,18 @@ class Retriever:
|
||||
return main + extra
|
||||
|
||||
def search(self, question: str, n_entries: int | None = None) -> list[ChunkResult]:
|
||||
"""Liefert die Top-Kontextblöcke (Hauptretrieval + cross_ref-Erweiterung)."""
|
||||
"""Liefert die Top-Kontextblöcke (Hauptretrieval + cross_ref-Erweiterung).
|
||||
|
||||
Gestaltungsfragen zu zusätzlichen Arbeitnehmerleistungen werden
|
||||
deterministisch in Direktzahlung und Alternativen zerlegt. Das gilt
|
||||
auch für den Offline-Retrieval-Eval, der keinen LLM-Planer aufruft.
|
||||
"""
|
||||
n = n_entries or self.cfg.context_blocks
|
||||
latest_year = str(self._stand_max)[:4]
|
||||
deterministic = decision_support_plan(question, default_year=latest_year)
|
||||
if deterministic:
|
||||
sub_queries, _qtype = deterministic
|
||||
return self.search_multi(sub_queries, n_entries=n)
|
||||
fused, bm_all, dn_all = self._fuse_queries(
|
||||
[SubQuery(text=question)], self.cfg.candidate_pool
|
||||
)
|
||||
@@ -403,7 +413,11 @@ class Retriever:
|
||||
mehreren Sub-Queries mittelgut matchen). Temporal-Intent: kv-
|
||||
Einträge im gefragten Geltungsjahr erhalten temporal_boost."""
|
||||
n = n_entries or self.cfg.context_blocks
|
||||
if len(sub_queries) == 1:
|
||||
if (
|
||||
len(sub_queries) == 1
|
||||
and sub_queries[0].scope is None
|
||||
and sub_queries[0].stand_year is None
|
||||
):
|
||||
return self.search(sub_queries[0].text, n_entries=n)
|
||||
pool = self.cfg.candidate_pool
|
||||
fused_total: dict[int, float] = {}
|
||||
|
||||
+36
@@ -306,4 +306,40 @@ tests/ # pytest: Ingest-, Retrieval-, Grounding-Unit-Tests
|
||||
46 Fragen (q-110–113). Offen für Stufe 2: Aggregation → Map-Reduce
|
||||
(q-029), Rückfragen statt Verweigerung (API-first), danach
|
||||
Rechtsprechung-Intake (`rj-*`, Lexis-md/json).
|
||||
- **Antworttyp-Routing Stufe 2 (2026-09-15, M6/D13):** Planer-Typ
|
||||
`survey` → Map-Reduce (survey_blocks=16; Map destilliert je Block
|
||||
mit KB-ID, Reduce synthetisiert; Validierung unverändert über die
|
||||
Union). Systemprompt-Regel 9: Kontext-Abhängigkeit → belegte allgemeine
|
||||
Aussage + eine Rückfrage (API-first). q-029 geheilt (vorher hart-
|
||||
näckigste Fehlverweigerung), q-015 mit KV-Abhängigkeits-Hinweis.
|
||||
Eval: 97,8 % / 97,8 % / 90,2 %, Latenz mean 34,2 s (Map-Reduce nur
|
||||
bei Survey-Fragen, ~95 s). Nächster Schritt: Rechtsprechung-Intake
|
||||
(`rj-*`), dann M4 (Odoo; Privacy-Neubewertung für Lohndaten-Zugriff).
|
||||
- **Output-Budget + length-Retry (2026-09-15, M6/D14):** q-024-Flakiness
|
||||
war num_predict=1024 (done_reason=length, abgeschnittene Zitationen),
|
||||
nicht Thinking. Fix: num_predict=2048, chat_full() mit done_reason,
|
||||
technischer 2×-Budget-Retry bei length. **Voll-Eval erstmals mit allen
|
||||
Gates erfüllt: Zitier-Präzision 100 %, Verweigerung 100 %, erwartete
|
||||
Quelle 92,7 %** (46/46), Latenz mean 39,6 s. M6 damit abgeschlossen;
|
||||
nächster Schritt: Rechtsprechung-Intake (`rj-*`), dann M4 (Odoo;
|
||||
Privacy-Neubewertung für Lohndaten-Zugriff).
|
||||
- **Rechtsprechungs-Intake (2026-09-15, D15):** `.rechtsprechung/` wurde
|
||||
über `tools/ingest_sources.py --source rj` in den neuen ID-Raum
|
||||
`rj-rjs-*` übernommen: 320 RIS-OGD-Entscheidungen/Rechtssätze, 23
|
||||
zitierte RIS-Normauszüge sowie 5 als nichtamtliche lexetius-
|
||||
Textwiedergaben markierte EuGH-Urteile. Korpus: 1.274 → **1.622**
|
||||
Einträge, 77 Cluster; lange Volltexte werden an Absatzgrenzen in H2-
|
||||
Chunks geteilt. Reindex: 16.480 Chunks, 1.496 neue bge-m3-Embeddings,
|
||||
75 s. Erweiterter Retrieval-Eval (50 Fragen, inkl. q-120–123): Hit-Rate
|
||||
0,956 · Recall@8 **0,922** (Gate >0,9 ✓) · MRR 0,661; alle neuen Fälle
|
||||
gefunden. Die gezielten Antwortläufe q-120–123 sind alle zitiergültig,
|
||||
nicht verweigert und ohne Regenerierung; EuGH q-123 weist nach einer
|
||||
Prompt-Regel explizit auf die nichtamtliche Wiedergabe hin. Voller
|
||||
Antwortmodus-Eval (50 Fragen): **100 % Zitier-Präzision**, **100 %
|
||||
Verweigerung korrekt**, erwartete Quelle 93,3 %, Latenz mean 39,4 s /
|
||||
p95 82,2 s, fünf Regenerierungen; Report `data/eval-qwen38-rj.json`
|
||||
(lokal, unversioniert). Vor einem Commit der
|
||||
quellentreuen Volltexte ist die Publikations-/Lizenzfreigabe bewusst zu
|
||||
bestätigen; sie folgt nicht automatisch aus der Regel zu amtlichen
|
||||
Gesetzestexten.
|
||||
- Betrieb: `agent/README.md`.
|
||||
|
||||
@@ -8,6 +8,7 @@ import pytest
|
||||
from agent.retrieve import ChunkResult
|
||||
from agent.generate import (
|
||||
REFUSAL_MESSAGE,
|
||||
SYSTEM_PROMPT,
|
||||
UNCERTAIN_MESSAGE,
|
||||
answer_question,
|
||||
build_user_content,
|
||||
@@ -15,6 +16,7 @@ from agent.generate import (
|
||||
strip_think,
|
||||
trim_results,
|
||||
validate_answer,
|
||||
validate_decision_support_answer,
|
||||
)
|
||||
|
||||
|
||||
@@ -37,6 +39,57 @@ class TestValidateAnswer:
|
||||
assert validate_answer("Siehe lb-min-02 für Details.", ["lb-min-02"]) == []
|
||||
|
||||
|
||||
def test_system_prompt_requires_nonofficial_source_disclosure():
|
||||
assert "nicht amtlich" in SYSTEM_PROMPT
|
||||
|
||||
|
||||
def test_system_prompt_requires_contextual_decision_support():
|
||||
assert "keine Option pauschal zum Sieger" in SYSTEM_PROMPT
|
||||
assert "frei verfügbare Barzahlung" in SYSTEM_PROMPT
|
||||
assert "systematisch in einen Katalog abgabenfreier Bezüge" in SYSTEM_PROMPT
|
||||
assert "[wk-akt-04] und [lb-sva-03]" in SYSTEM_PROMPT
|
||||
assert "Bezeichne keine der widersprechenden Quellen als" in SYSTEM_PROMPT
|
||||
assert "genau EINE gezielte" in SYSTEM_PROMPT
|
||||
assert "Regelnummern niemals" in SYSTEM_PROMPT
|
||||
assert "spekuliere nicht mit Trainingswissen" in SYSTEM_PROMPT
|
||||
|
||||
|
||||
class TestDecisionSupportValidation:
|
||||
question = (
|
||||
"Ich will meinem Mitarbeiter 500 Euro zusätzlich auszahlen. "
|
||||
"Was ist die günstigste Lösung?"
|
||||
)
|
||||
allowed = ["wk-akt-04", "lb-sva-03"]
|
||||
|
||||
def test_requires_conflict_when_both_sources_are_in_context(self):
|
||||
violations = validate_decision_support_answer(
|
||||
self.question, "Nur lohnsteuerfrei [wk-akt-04].", self.allowed
|
||||
)
|
||||
assert violations and "Quellenkonflikt" in violations[0]
|
||||
|
||||
def test_accepts_explicit_conflict(self):
|
||||
answer = (
|
||||
"⚠ [lb-sva-03] ordnet die Prämie in den Katalog beitragsfreier "
|
||||
"Bezüge ein; [wk-akt-04] nennt sie SV- und BV-pflichtig."
|
||||
)
|
||||
assert validate_decision_support_answer(self.question, answer, self.allowed) == []
|
||||
|
||||
def test_rejects_reversed_source_roles_and_prompt_leakage(self):
|
||||
answer = (
|
||||
"⚠ [wk-akt-04] und [lb-sva-03] ordnen die Prämie als beitragsfrei "
|
||||
"ein; gemäß Regel 11 ist die aktuellere News-Quelle maßgeblich."
|
||||
)
|
||||
violations = validate_decision_support_answer(self.question, answer, self.allowed)
|
||||
assert any("Rollen" in item for item in violations)
|
||||
assert any("internen Regeln" in item for item in violations)
|
||||
assert any("priorisiere" in item for item in violations)
|
||||
|
||||
def test_does_not_require_missing_source(self):
|
||||
assert validate_decision_support_answer(
|
||||
self.question, "Lohnsteuerfrei [wk-akt-04].", ["wk-akt-04"]
|
||||
) == []
|
||||
|
||||
|
||||
class TestRefusalDetection:
|
||||
def test_refusal_phrase(self):
|
||||
assert looks_like_refusal("Dazu enthält die Wissensbasis keine Aussage.")
|
||||
@@ -167,3 +220,33 @@ def test_trim_results_drops_tail_under_budget():
|
||||
assert sum(len(b.text) for b in trimmed) + len(trimmed) * 64 <= 90_000 + 8_000
|
||||
# Unbegrenzt: Original unveraendert
|
||||
assert trim_results(blocks, None) is blocks
|
||||
|
||||
|
||||
def test_length_retry_doubles_budget(mini_index):
|
||||
"""done_reason='length' (abgeschnittene Antwort) -> ein technischer
|
||||
Retry mit doppeltem num_predict; zaehlt nicht als Regel-Regenerierung."""
|
||||
class LengthyOllama:
|
||||
def __init__(self):
|
||||
self.calls = []
|
||||
self.budgets = []
|
||||
|
||||
def chat_full(self, model, messages, temperature=0.1, num_ctx=16384,
|
||||
num_predict=1024, think=False):
|
||||
self.calls.append(messages[-1])
|
||||
self.budgets.append(num_predict)
|
||||
if len(self.budgets) == 1:
|
||||
return "Halbe Zitation [lb-min-0", "length"
|
||||
return "Antwort mit Beleg [lb-min-01].", "stop"
|
||||
|
||||
def chat(self, *a, **k):
|
||||
raise AssertionError("chat() sollte via chat_full laufen")
|
||||
|
||||
def close(self):
|
||||
pass
|
||||
|
||||
client = LengthyOllama()
|
||||
result = answer_question("Altersteilzeit?", mini_index, client=client)
|
||||
assert result["verified"] is True
|
||||
assert result["citations"] == ["lb-min-01"]
|
||||
assert result["regenerations"] == 0 # technischer Retry, keine Regel-Regen
|
||||
assert client.budgets == [mini_index.num_predict, mini_index.num_predict * 2]
|
||||
|
||||
@@ -134,4 +134,109 @@ def test_ris_entry(tmp_path, monkeypatch):
|
||||
assert 'legal_bases: ["TestG"]' in md
|
||||
assert "## § 1. Geltungsbereich" in md
|
||||
assert "(1) Dieses Gesetz gilt für alle." in md
|
||||
assert "ris-nso-06" in md # ID-Zeile im Body
|
||||
assert "ris-nso-06" in md # ID-Zeile im Body
|
||||
|
||||
|
||||
def _rj_catalog():
|
||||
return {"source": "rj", "updated": None, "next_seq": 1, "entries": {}}
|
||||
|
||||
|
||||
def _rj_stats():
|
||||
return {"rj_written": 0, "rj_unparsed": [], "rj_empty": []}
|
||||
|
||||
|
||||
def test_rj_rechtssatz_preserves_court_date_and_norm(tmp_path, monkeypatch):
|
||||
root = tmp_path / ".rechtsprechung"
|
||||
source = root / "originale" / "JJR_test.md"
|
||||
source.parent.mkdir(parents=True)
|
||||
source.write_text(
|
||||
"# Rechtssatz\n\n"
|
||||
"**Gericht:** OGH\n"
|
||||
"**Entscheidungsdatum:** 15. 7. 1954\n"
|
||||
"**Geschäftszahl:** 4 Ob 100/54\n"
|
||||
"**Norm:** AngG § 26 Z 4\n"
|
||||
"**Rechtssatz:** Ein Austrittsgrund ist unverzüglich geltend zu machen.\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
monkeypatch.setattr(ing, "RJ_DIR", root)
|
||||
|
||||
slug, md = ing.rj_entry(source, _rj_catalog(), _rj_stats())
|
||||
|
||||
assert slug == "rj_jjr-test"
|
||||
assert "id: rj-rjs-001" in md
|
||||
assert 'chapter: "OGH-Rechtssatz"' in md
|
||||
assert "stand: 1954-07" in md
|
||||
assert 'legal_bases: ["AngG § 26 Z 4"]' in md
|
||||
assert "## Rechtssatz" in md
|
||||
|
||||
|
||||
def test_rj_volltext_splits_long_reasoning_at_paragraphs(tmp_path, monkeypatch):
|
||||
root = tmp_path / ".rechtsprechung"
|
||||
source = root / "originale" / "JJT_test.md"
|
||||
source.parent.mkdir(parents=True)
|
||||
paragraphs = [f"Absatz {i}: " + "x" * 900 for i in range(5)]
|
||||
source.write_text(
|
||||
"# Entscheidung\n\n"
|
||||
"**Gericht:** OGH\n"
|
||||
"**Entscheidungsdatum:** 1. 2. 2020\n"
|
||||
"**Geschäftszahl:** 1 Ob 2/20a\n\n---\n\n"
|
||||
+ "\n\n".join(paragraphs),
|
||||
encoding="utf-8",
|
||||
)
|
||||
monkeypatch.setattr(ing, "RJ_DIR", root)
|
||||
|
||||
_, md = ing.rj_entry(source, _rj_catalog(), _rj_stats())
|
||||
|
||||
assert "## Begründung (1)" in md
|
||||
assert "## Begründung (2)" in md
|
||||
|
||||
|
||||
def test_rj_norm_supports_h2_and_flat_wording(tmp_path, monkeypatch):
|
||||
root = tmp_path / ".rechtsprechung"
|
||||
h2_source = root / "gesetze" / "AngG_§15.md"
|
||||
flat_source = root / "gesetze" / "ABGB_§1435.md"
|
||||
h2_source.parent.mkdir(parents=True)
|
||||
h2_source.write_text(
|
||||
"# Angestelltengesetz\n\n**Kurztitel:** Angestelltengesetz\n"
|
||||
"**Abkürzung:** AngG\n**§/Artikel/Anlage:** § 15\n\n---\n\n"
|
||||
"## § 15\n\nWortlaut.\n\n## Zuletzt aktualisiert am\n\n1. 7. 2023\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
flat_source.write_text(
|
||||
"# ABGB\n\n**Kurztitel:** ABGB\n**Abkürzung:** ABGB\n"
|
||||
"**§/Artikel/Anlage:** § 1435\n\n---\n\nDer Wortlaut ohne H2.\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
monkeypatch.setattr(ing, "RJ_DIR", root)
|
||||
catalog = _rj_catalog()
|
||||
|
||||
_, h2_md = ing.rj_entry(h2_source, catalog, _rj_stats())
|
||||
_, flat_md = ing.rj_entry(flat_source, catalog, _rj_stats())
|
||||
|
||||
assert "stand: 2023-07" in h2_md
|
||||
assert 'legal_bases: ["AngG § 15"]' in h2_md
|
||||
assert "## § 15 – Wortlaut" in h2_md
|
||||
assert "stand: 2026-09" in flat_md
|
||||
assert "stand-abruf" in flat_md
|
||||
assert "## Normtext" in flat_md
|
||||
|
||||
|
||||
def test_rj_eugh_marks_lexetius_copy_as_nonofficial(tmp_path, monkeypatch):
|
||||
root = tmp_path / ".rechtsprechung"
|
||||
source = root / "originale" / "EUGH_C-29-1991.md"
|
||||
source.parent.mkdir(parents=True)
|
||||
source.write_text(
|
||||
"# EuGH C-29/91\n\n"
|
||||
"**URL:** https://www.lexetius.com/1992,1\n"
|
||||
"**Offizielle Fassung:** https://eur-lex.europa.eu/example\n\n---\n\n"
|
||||
"Urteil vom 19. 5. 1992\n\nEntscheidungsgründe.",
|
||||
encoding="utf-8",
|
||||
)
|
||||
monkeypatch.setattr(ing, "RJ_DIR", root)
|
||||
|
||||
_, md = ing.rj_entry(source, _rj_catalog(), _rj_stats())
|
||||
|
||||
assert 'work: "EuGH – Rechtsprechung (Textwiedergabe lexetius, nicht amtlich)"' in md
|
||||
assert "stand: 1992-05" in md
|
||||
assert "Textwiedergabe (nicht amtlich): https://www.lexetius.com/1992,1" in md
|
||||
assert "amtliche Fassung: https://eur-lex.europa.eu/example" in md
|
||||
|
||||
+15
-6
@@ -67,21 +67,21 @@ def test_real_corpus_loads_and_matches_registry():
|
||||
"""Integrationstest gegen die echte Wissensbasis (Gate inklusive)."""
|
||||
entries = load_kb("wissensbasis", verify_registry=True)
|
||||
ids = {e.id for e in entries}
|
||||
# 601 kuratierte (lb/wk) + 614 WKO-KV + 59 RIS-Gesetze
|
||||
assert len(entries) == 1274
|
||||
# 601 kuratierte (lb/wk) + 614 WKO-KV + 59 RIS-Gesetze + 348 Rechtsprechungsquellen
|
||||
assert len(entries) == 1622
|
||||
assert "lb-atz-07" in ids and "wk-akt-01" in ids
|
||||
assert "kv-kvt-001" in ids and "ris-url-01" in ids
|
||||
assert "kv-kvt-001" in ids and "ris-url-01" in ids and "rj-rjs-001" in ids
|
||||
atz = [e for e in entries if e.id == "lb-atz-07"][0]
|
||||
assert atz.topic == "altersteilzeit"
|
||||
assert any(s.title.startswith("Kernwerte") for s in atz.sections)
|
||||
|
||||
|
||||
def test_new_id_spaces_and_html_source(tmp_path):
|
||||
"""kv-/ris-IDs und html-only-Quellenangabe sind gültig; Unbekanntes nicht."""
|
||||
"""kv-/ris-/rj-IDs und html-/text-Quellenangaben sind gültig; Unbekanntes nicht."""
|
||||
kv = DOC_ATZ.replace("id: lb-min-01", "id: kv-kvt-001").replace(
|
||||
'source:\n pdf: ".lexis360/Lexis360_test_atz.pdf"\n'
|
||||
' text: ".lexis360/md/test_atz.md"',
|
||||
'source:\n html: ".firecrawl/wko-kv/docs/test.html"',
|
||||
'source:\n html: ".firecrawl/kv-portal/wko-kv/docs/test.html"',
|
||||
)
|
||||
p = tmp_path / "kv_doc.md"
|
||||
p.write_text(kv, encoding="utf-8")
|
||||
@@ -90,12 +90,21 @@ def test_new_id_spaces_and_html_source(tmp_path):
|
||||
ris = DOC_ATZ.replace("id: lb-min-01", "id: ris-url-01").replace(
|
||||
'source:\n pdf: ".lexis360/Lexis360_test_atz.pdf"\n'
|
||||
' text: ".lexis360/md/test_atz.md"',
|
||||
'source:\n text: ".ris/Test.md"',
|
||||
'source:\n text: ".firecrawl/ris/gesetze/Test.md"',
|
||||
)
|
||||
p2 = tmp_path / "ris_doc.md"
|
||||
p2.write_text(ris, encoding="utf-8")
|
||||
assert load_entry(p2).id == "ris-url-01"
|
||||
|
||||
rj = DOC_ATZ.replace("id: lb-min-01", "id: rj-rjs-001").replace(
|
||||
'source:\n pdf: ".lexis360/Lexis360_test_atz.pdf"\n'
|
||||
' text: ".lexis360/md/test_atz.md"',
|
||||
'source:\n text: ".rechtsprechung/originale/Test.md"',
|
||||
)
|
||||
p3 = tmp_path / "rj_doc.md"
|
||||
p3.write_text(rj, encoding="utf-8")
|
||||
assert load_entry(p3).id == "rj-rjs-001"
|
||||
|
||||
bad = DOC_ATZ.replace("id: lb-min-01", "id: xx-min-01")
|
||||
p3 = tmp_path / "bad.md"
|
||||
p3.write_text(bad, encoding="utf-8")
|
||||
|
||||
+97
-17
@@ -6,7 +6,13 @@ import pytest
|
||||
|
||||
from agent.config import Config
|
||||
from agent.generate import answer_question
|
||||
from agent.query_planner import SubQuery, parse_plan, plan_queries, should_plan
|
||||
from agent.query_planner import (
|
||||
SubQuery,
|
||||
decision_support_plan,
|
||||
parse_plan,
|
||||
plan_queries,
|
||||
should_plan,
|
||||
)
|
||||
from tests.conftest import FakeOllama
|
||||
|
||||
|
||||
@@ -20,47 +26,91 @@ def test_should_plan_gate():
|
||||
"Wie wird die Überstundenpauschale behandelt und wie wirkt sie sich "
|
||||
"auf die Sozialversicherung und die Lohnsteuer aus?"
|
||||
)
|
||||
# Gestaltungsfrage -> planen, auch wenn sie unter der Längenschwelle bleibt
|
||||
assert should_plan(
|
||||
"Ich will meinem Mitarbeiter 500 Euro zusätzlich auszahlen. "
|
||||
"Was ist die günstigste Lösung?"
|
||||
)
|
||||
# einfach -> Single-Shot
|
||||
assert not should_plan("Wie viele Werktage Urlaub stehen Arbeitnehmern zu?")
|
||||
assert not should_plan("Was ist Altersteilzeit?")
|
||||
assert not should_plan("Wie hoch ist der KV-Mindestlohn im Friseurgewerbe?")
|
||||
|
||||
|
||||
def test_decision_support_plan_splits_direct_payment_and_alternatives():
|
||||
planned = decision_support_plan(
|
||||
"Ich will meinem Mitarbeiter 500 Euro zusätzlich auszahlen. "
|
||||
"Was ist die günstigste Lösung?",
|
||||
default_year="2026",
|
||||
)
|
||||
assert planned is not None
|
||||
subs, qtype = planned
|
||||
assert qtype == "specific"
|
||||
assert len(subs) == 3
|
||||
assert all(s.scope == "gesetz" for s in subs)
|
||||
assert all(s.stand_year == "2026" for s in subs)
|
||||
assert "Mitarbeiterprämie 2026" in subs[0].text
|
||||
assert "Zukunftssicherung" in subs[1].text
|
||||
assert "Mahlzeiten" in subs[2].text
|
||||
|
||||
|
||||
def test_decision_support_plan_keeps_explicit_year_and_specific_intent():
|
||||
subs, qtype = decision_support_plan(
|
||||
"Kann ich 2025 jedem Mitarbeiter einfach 500 Euro steuerfrei auszahlen?",
|
||||
default_year="2026",
|
||||
)
|
||||
assert qtype == "specific"
|
||||
assert len(subs) == 1
|
||||
assert subs[0].stand_year == "2025"
|
||||
assert "Mitarbeiterprämie 2025" in subs[0].text
|
||||
|
||||
|
||||
def test_parse_plan_valid_and_fallback():
|
||||
subs = parse_plan(
|
||||
'Vorab: {"queries": [{"text": "mindestlohn friseur", "stand_year": "2024"}, '
|
||||
subs, qtype = parse_plan(
|
||||
'Vorab: {"type": "specific", "queries": [{"text": "mindestlohn friseur", "stand_year": "2024"}, '
|
||||
'{"text": "lohnberechnung friseur", "stand_year": null}]}',
|
||||
original="Originalfrage?",
|
||||
)
|
||||
assert [s.text for s in subs] == ["mindestlohn friseur", "lohnberechnung friseur"]
|
||||
assert subs[0].stand_year == "2024"
|
||||
assert subs[1].stand_year is None
|
||||
assert qtype == "specific"
|
||||
|
||||
# Fallbacks: kaputtes JSON, leeres Array, leere Texte
|
||||
for raw in ("kein json", '{"queries": []}', '{"queries": [{"text": ""}]}'):
|
||||
subs = parse_plan(raw, original="Originalfrage?")
|
||||
subs, qtype = parse_plan(raw, original="Originalfrage?")
|
||||
assert len(subs) == 1 and subs[0].text == "Originalfrage?"
|
||||
assert qtype == "specific"
|
||||
|
||||
# Ungueltiges Jahr -> None erzwingen, Text bleibt
|
||||
subs = parse_plan(
|
||||
'{"queries": [{"text": "x", "stand_year": "98"}]}', original="orig"
|
||||
# Ungueltiges Jahr -> None erzwingen, Text bleibt; unbekannter scope -> None
|
||||
subs, _ = parse_plan(
|
||||
'{"queries": [{"text": "x", "stand_year": "98", "scope": "xyz"}]}', original="orig"
|
||||
)
|
||||
assert subs == [SubQuery(text="x", stand_year=None)]
|
||||
assert subs == [SubQuery(text="x", stand_year=None, scope=None)]
|
||||
|
||||
|
||||
def test_parse_plan_type_survey():
|
||||
subs, qtype = parse_plan(
|
||||
'{"type": "survey", "queries": [{"text": "wiku personal aktuell 2026 neuerungen", "scope": null}]}',
|
||||
original="orig",
|
||||
)
|
||||
assert qtype == "survey"
|
||||
assert subs[0].scope is None
|
||||
|
||||
|
||||
def test_parse_plan_caps_at_three_queries():
|
||||
raw = json.dumps(
|
||||
{"queries": [{"text": f"q{i}"} for i in range(5)]}
|
||||
)
|
||||
subs = parse_plan(raw, original="orig")
|
||||
subs, _ = parse_plan(raw, original="orig")
|
||||
assert len(subs) == 3
|
||||
|
||||
|
||||
def test_plan_queries_simple_question_no_llm_call():
|
||||
client = FakeOllama(answers=[]) # darf nicht aufgerufen werden
|
||||
cfg = Config(planner_enabled=True)
|
||||
subs, planned = plan_queries("Was ist Altersteilzeit?", client, cfg)
|
||||
assert planned is False
|
||||
subs, planned, qtype = plan_queries("Was ist Altersteilzeit?", client, cfg)
|
||||
assert planned is False and qtype == "specific"
|
||||
assert subs == [SubQuery(text="Was ist Altersteilzeit?")]
|
||||
assert client.calls == 0
|
||||
|
||||
@@ -68,19 +118,19 @@ def test_plan_queries_simple_question_no_llm_call():
|
||||
def test_plan_queries_uses_planner_and_falls_back_on_error():
|
||||
cfg = Config(planner_enabled=True)
|
||||
client = FakeOllama(
|
||||
answers=['{"queries": [{"text": "atz lohnausgleich"}, {"text": "atz altersteilzeitgeld", "stand_year": null}]}']
|
||||
answers=['{"type": "specific", "queries": [{"text": "atz lohnausgleich"}, {"text": "atz altersteilzeitgeld", "stand_year": null}]}']
|
||||
)
|
||||
subs, planned = plan_queries(
|
||||
subs, planned, qtype = plan_queries(
|
||||
"Wie funktioniert der Lohnausgleich bei Altersteilzeit und was ersetzt das AMS?", client, cfg
|
||||
)
|
||||
assert planned is True and len(subs) == 2
|
||||
assert planned is True and qtype == "specific" and len(subs) == 2
|
||||
assert subs[0].text == "atz lohnausgleich"
|
||||
|
||||
# Fehler -> Originalfrage, geplant False
|
||||
failing = FakeOllama(answers=[])
|
||||
failing.chat = lambda *a, **k: (_ for _ in ()).throw(RuntimeError("offline"))
|
||||
subs, planned = plan_queries("Wie funktioniert der Lohnausgleich 2026?", failing, cfg)
|
||||
assert planned is False
|
||||
subs, planned, qtype = plan_queries("Wie funktioniert der Lohnausgleich 2026?", failing, cfg)
|
||||
assert planned is False and qtype == "specific"
|
||||
assert subs[0].text.startswith("Wie funktioniert")
|
||||
|
||||
|
||||
@@ -95,7 +145,7 @@ def test_answer_question_planner_integration(mini_index):
|
||||
planner_max_queries=2,
|
||||
)
|
||||
client = FakeOllama(answers=[
|
||||
json.dumps({"queries": [
|
||||
json.dumps({"type": "specific", "queries": [
|
||||
{"text": "altersteilzeit lohnausgleich", "stand_year": None},
|
||||
{"text": "urlaubsanspruch", "stand_year": None},
|
||||
]}),
|
||||
@@ -112,6 +162,36 @@ def test_answer_question_planner_integration(mini_index):
|
||||
assert len(result["planned_queries"]) == 2
|
||||
|
||||
|
||||
def test_answer_question_survey_map_reduce(mini_index):
|
||||
"""Survey-Frage: 1. Planer (type=survey), 2. Map-Destillat,
|
||||
3. Reduce-Antwort. Zitier-Validierung weiterhin gegen die Union."""
|
||||
cfg = Config(
|
||||
kb_dir=mini_index.kb_dir,
|
||||
db_path=mini_index.db_path,
|
||||
embed_off=True,
|
||||
planner_enabled=True,
|
||||
survey_blocks=8,
|
||||
)
|
||||
client = FakeOllama(answers=[
|
||||
json.dumps({"type": "survey", "queries": [
|
||||
{"text": "wiku personal aktuell 2026", "stand_year": None},
|
||||
]}),
|
||||
# Map-Ausgabe: Destillat je Block mit KB-ID
|
||||
"[lb-min-01] Altersteilzeit: Lohnausgleich + ATZ-Geld.\n"
|
||||
"[lb-min-02] Urlaub: 5 Wochen je Dienstjahr.",
|
||||
# Reduce-Antwort
|
||||
"Neuerungen: ATZ-Lohnausgleich [lb-min-01]; Urlaub 5 Wochen [lb-min-02].",
|
||||
])
|
||||
result = answer_question(
|
||||
"Welche Neuerungen behandeln die Wissensbasis 2026?",
|
||||
cfg, client=client,
|
||||
)
|
||||
assert client.calls == 3 # Planer + Map + Reduce
|
||||
assert result["verified"] is True
|
||||
assert result["refused"] is False
|
||||
assert set(result["citations"]) == {"lb-min-01", "lb-min-02"}
|
||||
|
||||
|
||||
def test_search_multi_fuses_across_queries(mini_index):
|
||||
"""Multi-Query-Retrieval: Sub-Queries summieren Beitraege; Treffer aus
|
||||
beiden Themen erscheinen im Kontext."""
|
||||
|
||||
+10
-8
@@ -1,4 +1,4 @@
|
||||
"""Registry-Generator für die Wissensbasis (alle vier ID-Räume lb/wk/kv/ris).
|
||||
"""Registry-Generator für die Wissensbasis (alle fünf ID-Räume lb/wk/kv/ris/rj).
|
||||
|
||||
Ersetzt in diesem Repo das im Schwesterprojekt verbliebene
|
||||
`build_lexis_kb.py --registry`: lädt alle Layer-2-Einträge über
|
||||
@@ -66,16 +66,16 @@ def build_kb_json(entries, topic_prefix: dict, cluster_names: dict) -> dict:
|
||||
"layers": {
|
||||
"curated": "wissensbasis/dokumente",
|
||||
"fulltext": ".lexis360/md + .wiku/md (lokal, unversioniert — lizenzierte Quellen)",
|
||||
"raw": ".firecrawl/wko-kv/docs (WKO-KV-Seiten) + .ris (Gesetze) — lokal, unversioniert; kv/ris-Layer-2 ist quellentreu generiert",
|
||||
"raw": ".firecrawl/kv-portal/wko-kv/docs (WKO-KV-Seiten) + .firecrawl/ris/gesetze (Gesetze) + .rechtsprechung (Entscheidungen/Normauszüge) — lokal, unversioniert; kv/ris/rj-Layer-2 ist quellentreu generiert",
|
||||
},
|
||||
"schema": {
|
||||
"id": "lb-<cluster-prefix>-<nn> (Lexis) | wk-<cluster-prefix>-<nn> (WIKU) | "
|
||||
"kv-kvt-<nnn> (WKO-KV, Cluster kollektivvertraege) | "
|
||||
"ris-<cluster-prefix>-<nn> (RIS-Gesetz)",
|
||||
"ris-<cluster-prefix>-<nn> (RIS-Gesetz) | rj-rjs-<nnn> (Rechtsprechung/Normauszug)",
|
||||
"stand": "YYYY-MM (Stand der Quelle; KV: Geltungsbeginn)",
|
||||
"legal_bases": "Rechtsgrundlagen as cited in the source",
|
||||
"cross_refs": "ids of related kb entries (alle ID-Räume dürfen kreuzen)",
|
||||
"generated_files": "kv_*.md / ris_*.md sind Tool-Output (tools/ingest_sources.py) — keine manuelle Kuratierung",
|
||||
"generated_files": "kv_*.md / ris_*.md / rj_*.md sind Tool-Output (tools/ingest_sources.py) — keine manuelle Kuratierung",
|
||||
},
|
||||
"clusters": [
|
||||
{
|
||||
@@ -119,15 +119,17 @@ def build_index_md(entries, topic_prefix: dict, cluster_names: dict) -> str:
|
||||
"Lexis Briefings Personalrecht (Lexis 360, lizenzierter Export), "
|
||||
"WIKU Personal (Fachbroschüren, Arbeitsunterlagen, Casebooks, "
|
||||
"„WIKU Personal aktuell“), WKO.at – Kollektivvertrag (KV-Dokumente, "
|
||||
"quellentreu generiert) und RIS – Rechtsinformationssystem des Bundes "
|
||||
"(Gesetzes-§-Auschnitte, quellentreu generiert). Rohquellen lokal/"
|
||||
"unversioniert (`.lexis360/`, `.wiku/`, `.firecrawl/`, `.ris/`). "
|
||||
"quellentreu generiert), RIS – Rechtsinformationssystem des Bundes "
|
||||
"(Gesetzes-§-Auschnitte, quellentreu generiert) sowie Rechtsprechung "
|
||||
"(RIS-OGD-Entscheidungen und Normauszüge; EuGH-Textwiedergaben separat "
|
||||
"als nicht amtlich markiert). Rohquellen lokal/unversioniert "
|
||||
"(`.lexis360/`, `.wiku/`, `.firecrawl/`, `.firecrawl/ris/gesetze/`, `.rechtsprechung/`). "
|
||||
"Werte gelten je zum Quell-Stand (`stand` im Frontmatter); Widersprüche "
|
||||
"und offene Punkte sind mit ⚠/❓ in den Einträgen selbst dokumentiert. "
|
||||
"Schema & Konventionen: `README.md`.\n"
|
||||
)
|
||||
out = [header]
|
||||
for space in ("lb", "wk", "kv", "ris"):
|
||||
for space in ("lb", "wk", "kv", "ris", "rj"):
|
||||
group = by_space.get(space)
|
||||
if not group:
|
||||
continue
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+313
-9
@@ -27,8 +27,11 @@ from pathlib import Path
|
||||
from tools.kb_common import ( # noqa: E402
|
||||
DATE_RE,
|
||||
LAW_MAP,
|
||||
WORK_EUGH,
|
||||
WORK_KV,
|
||||
WORK_NORM,
|
||||
WORK_RIS,
|
||||
WORK_RJ,
|
||||
YEAR_RE,
|
||||
ascii_slug,
|
||||
load_topic_prefix_map,
|
||||
@@ -36,8 +39,9 @@ from tools.kb_common import ( # noqa: E402
|
||||
)
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
KV_DIR = ROOT / ".firecrawl" / "wko-kv" / "docs"
|
||||
RIS_DIR = ROOT / ".ris"
|
||||
KV_DIR = ROOT / ".firecrawl" / "kv-portal" / "wko-kv" / "docs"
|
||||
RIS_DIR = ROOT / ".firecrawl" / "ris" / "gesetze"
|
||||
RJ_DIR = ROOT / ".rechtsprechung"
|
||||
DOCS = ROOT / "wissensbasis" / "dokumente"
|
||||
CATALOGS = ROOT / "tools" / "catalogs"
|
||||
CRAWL_STAND = "2026-09" # Beschaffungsstand der beiden Quellen
|
||||
@@ -368,7 +372,7 @@ def kv_entry(path: Path, catalog: dict, stats: dict) -> tuple[str, str] | None:
|
||||
f"author: \"WKO\"\n"
|
||||
f"stand: {stand}\n"
|
||||
f"source:\n"
|
||||
f" html: \".firecrawl/wko-kv/docs/{path.name}\"\n"
|
||||
f" html: \".firecrawl/kv-portal/wko-kv/docs/{path.name}\"\n"
|
||||
f"legal_bases: []\n"
|
||||
f"tags: {json.dumps(tags, ensure_ascii=False)}\n"
|
||||
f"cross_refs: []\n"
|
||||
@@ -434,7 +438,7 @@ def ris_entry(path: Path, catalog: dict, stats: dict) -> tuple[str, str] | None:
|
||||
f"author: \"RIS (Bundeskanzleramt)\"\n"
|
||||
f"stand: {stand}\n"
|
||||
f"source:\n"
|
||||
f" text: \".ris/{path.name}\"\n"
|
||||
f" text: \".firecrawl/ris/gesetze/{path.name}\"\n"
|
||||
f"legal_bases: {json.dumps([abbr], ensure_ascii=False)}\n"
|
||||
f"tags: {json.dumps(tags, ensure_ascii=False)}\n"
|
||||
f"cross_refs: []\n"
|
||||
@@ -460,6 +464,283 @@ def extract_law_abbreviation(title: str, base: str) -> str:
|
||||
return base
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Rechtsprechung (RJ): Metadaten-MD -> Layer 2
|
||||
# --------------------------------------------------------------------------
|
||||
|
||||
RJ_FIELD_RE = re.compile(r"^\*\*(.+?):\*\*\s*(.*)$", re.M)
|
||||
RJ_H2_SPLIT_RE = re.compile(r"(?m)^## ")
|
||||
RJ_NOISE_LINE_RE = re.compile(r"//-->|^\s*[\[\]]\s*$|^[\s\[]*(Kanzlei|Gesetze|Entscheidungen)\]?\s*$")
|
||||
|
||||
|
||||
def rj_parse_fields(raw: str) -> tuple[dict[str, str], str]:
|
||||
"""Extrahiert die '**Feld:** Wert'-Metadatenzeilen und den Body nach dem
|
||||
ersten '---'-Trenner (bei Rechtssätzen leer)."""
|
||||
fields: dict[str, str] = {}
|
||||
for m in RJ_FIELD_RE.finditer(raw):
|
||||
fields[m.group(1).strip()] = m.group(2).strip()
|
||||
parts = re.split(r"\n\s*---\s*\n", raw, maxsplit=1)
|
||||
body = parts[1] if len(parts) > 1 else ""
|
||||
return fields, body
|
||||
|
||||
|
||||
def rj_clean_body(body: str) -> str:
|
||||
"""Rauscht Zeilen (lexetius-Kommentarreste, Bracket-Fragmente) und
|
||||
führende Strukturetiketten heraus; kollabiert Leerzeilen."""
|
||||
lines = []
|
||||
for line in body.split("\n"):
|
||||
if RJ_NOISE_LINE_RE.search(line):
|
||||
continue
|
||||
lines.append(line.rstrip())
|
||||
text = "\n".join(lines)
|
||||
text = re.sub(
|
||||
r"\A\s*(?:Urteil|Beschluss|Erkenntnis|Entscheidung|Begr\u00fcndung:?|"
|
||||
r"Entscheidungsgr\u00fcnde:?|Spruch:?)\s*\n+",
|
||||
"",
|
||||
text,
|
||||
)
|
||||
text = re.sub(r"\n{3,}", "\n\n", text)
|
||||
return text.strip()
|
||||
|
||||
|
||||
def rj_split_text(text: str, limit: int = 3500) -> list[tuple[str, str]]:
|
||||
"""Lange Begründungen in ~limit-Zeichen-Stücke an Absatzgrenzen
|
||||
splitten -> eigene H2-Chunks (Retrieval-Granularität, D10/D11-Budget)."""
|
||||
if not text:
|
||||
return []
|
||||
if len(text) <= limit:
|
||||
return [("Begründung", text)]
|
||||
parts: list[str] = []
|
||||
current: list[str] = []
|
||||
size = 0
|
||||
for para in re.split(r"\n\n+", text):
|
||||
if size and size + len(para) > limit:
|
||||
parts.append("\n\n".join(current))
|
||||
current, size = [], 0
|
||||
current.append(para)
|
||||
size += len(para) + 2
|
||||
if current:
|
||||
parts.append("\n\n".join(current))
|
||||
if len(parts) == 1:
|
||||
return [("Begründung", parts[0])]
|
||||
return [(f"Begründung ({i})", p) for i, p in enumerate(parts, 1)]
|
||||
|
||||
|
||||
def _rj_short(text: str, limit: int = 100) -> str:
|
||||
if len(text) <= limit:
|
||||
return text
|
||||
cut = text[:limit + 1].rsplit(" ", 1)[0]
|
||||
return cut.rstrip(".,;") + "…"
|
||||
|
||||
|
||||
def rj_build_sections(fields: dict[str, str], body: str, kind: str) -> list[tuple[str, str]]:
|
||||
"""H2-Sektionen je Entscheidungstyp (Rechtssatz/Volltext/EuGH/Norm)."""
|
||||
sections: list[tuple[str, str]] = []
|
||||
if kind == "norm":
|
||||
h2 = _h2_sections(body)
|
||||
if not h2:
|
||||
# 17 Norm-Dateien haben den Wortlaut als Fließtext nach dem
|
||||
# '---'-Trenner (ohne H2-Struktur) — als eigene Sektion übernehmen.
|
||||
flat = rj_clean_body(body)
|
||||
if flat:
|
||||
sections.append(("Normtext", flat))
|
||||
return sections
|
||||
for title, text in h2:
|
||||
t = title.strip().rstrip(".")
|
||||
if t.lower().startswith("zuletzt aktualisiert"):
|
||||
continue
|
||||
if t.lower() in ("gesetzesnummer", "dokumentnummer", "alte dokumentnummer"):
|
||||
continue
|
||||
if t.startswith("\u00a7") or t.startswith("Art"):
|
||||
sections.append((f"{t} \u2013 Wortlaut", text))
|
||||
else:
|
||||
sections.append((f"{t} (Index)", text))
|
||||
return sections
|
||||
if kind == "rechtssatz":
|
||||
if fields.get("Rechtssatz"):
|
||||
sections.append(("Rechtssatz", fields["Rechtssatz"]))
|
||||
if fields.get("Entscheidungstexte"):
|
||||
sections.append(("Entscheidungstexte (Fundstellen)", fields["Entscheidungstexte"]))
|
||||
return sections
|
||||
# Volltext (JJT/JWT/JFT) und EuGH
|
||||
if fields.get("Betreff"):
|
||||
sections.append(("Sachbetreff", fields["Betreff"]))
|
||||
if fields.get("Leitsatz"):
|
||||
sections.append(("Leitsatz", fields["Leitsatz"]))
|
||||
if fields.get("Spruch"):
|
||||
sections.append(("Spruch", fields["Spruch"]))
|
||||
if fields.get("Rechtliche Beurteilung"):
|
||||
sections.append(("Rechtliche Beurteilung", fields["Rechtliche Beurteilung"]))
|
||||
text = rj_clean_body(body)
|
||||
sections.extend(rj_split_text(text))
|
||||
if fields.get("Beachte"):
|
||||
sections.append(("Beachte", fields["Beachte"]))
|
||||
return sections
|
||||
|
||||
|
||||
def _h2_sections(body: str) -> list[tuple[str, str]]:
|
||||
"""Bestehende H2-Struktur (gesetze/*.md) in (Titel, Text) zerlegen."""
|
||||
out: list[tuple[str, str]] = []
|
||||
parts = RJ_H2_SPLIT_RE.split(body)
|
||||
for part in parts[1:]:
|
||||
lines = part.split("\n", 1)
|
||||
title = lines[0].strip()
|
||||
text = lines[1].strip() if len(lines) > 1 else ""
|
||||
if title and text:
|
||||
out.append((title, text))
|
||||
return out
|
||||
|
||||
|
||||
def rj_entry(path: Path, catalog: dict, stats: dict) -> tuple[str, str] | None:
|
||||
rel = path.relative_to(RJ_DIR).as_posix()
|
||||
raw = path.read_text(encoding="utf-8")
|
||||
fields, body = rj_parse_fields(raw)
|
||||
|
||||
if path.parent.name == "gesetze":
|
||||
kind = "norm"
|
||||
elif rel.startswith("originale/EUGH"):
|
||||
kind = "eugh"
|
||||
elif not fields.get("Gericht"):
|
||||
stats["rj_unparsed"].append(rel)
|
||||
return None
|
||||
elif "Rechtssatz" in fields:
|
||||
kind = "rechtssatz"
|
||||
else:
|
||||
kind = "volltext"
|
||||
|
||||
court = fields.get("Gericht", "EuGH").strip()
|
||||
court_tag = ascii_slug(court)
|
||||
gnr = None
|
||||
|
||||
if kind == "norm":
|
||||
kurztitel = fields.get("Kurztitel", "Norm")
|
||||
abk = fields.get("Abk\u00fcrzung", "")
|
||||
para = fields.get("\u00a7/Artikel/Anlage", "")
|
||||
stand = None
|
||||
for title, text in _h2_sections(body):
|
||||
if title.strip().lower().startswith("zuletzt aktualisiert"):
|
||||
m = DATE_RE.search(text)
|
||||
if m:
|
||||
stand = stand_from_date(m.groups())
|
||||
if title.strip() == "Gesetzesnummer":
|
||||
gnr = text.strip()
|
||||
if not stand:
|
||||
m = DATE_RE.search(body or "")
|
||||
stand = stand_from_date(m.groups()) if m else CRAWL_STAND
|
||||
stand_fallback = True
|
||||
else:
|
||||
stand_fallback = False
|
||||
title = f"{kurztitel} ({abk}) \u2013 {para}" if abk else f"{kurztitel} \u2013 {para}"
|
||||
work = WORK_NORM
|
||||
chapter = "Zitierte Norm (Originalwortlaut)"
|
||||
legal_bases = [f"{abk} {para}".strip()] if abk and para else ([abk] if abk else [])
|
||||
tags = ["rechtsprechung", "norm", ascii_slug(abk) or "ris"]
|
||||
if stand_fallback:
|
||||
tags.append("stand-abruf")
|
||||
quelle = (
|
||||
f"*{work}, Stand {stand}. {kurztitel}"
|
||||
+ (f" ({abk})" if abk else "")
|
||||
+ (f", Gesetzesnummer {gnr}" if gnr else "")
|
||||
+ f" \u2013 Originalwortlaut aus dem RIS, zitiert in der Rechtsprechung dieses Korpus.*"
|
||||
)
|
||||
else:
|
||||
m = DATE_RE.search(fields.get("Entscheidungsdatum", ""))
|
||||
stand = stand_from_date(m.groups()) if m else CRAWL_STAND
|
||||
datum_de = fields.get("Entscheidungsdatum", "")
|
||||
gz = fields.get("Gesch\u00e4ftszahl", "")
|
||||
ecli = fields.get("European Case Law Identifier", "")
|
||||
if kind == "rechtssatz":
|
||||
title = _rj_short(fields.get("Rechtssatz", f"{court} {gz}"))
|
||||
chapter = f"{court}-Rechtssatz"
|
||||
tags = ["rechtsprechung", court_tag, "rechtssatz"]
|
||||
elif kind == "eugh":
|
||||
h1 = re.match(r"\s*#\s*(.+)", raw)
|
||||
rs = h1.group(1).strip() if h1 else path.stem.replace("_", " ")
|
||||
dm = re.search(r"Urteil vom (\d{1,2}\.\s*\d{1,2}\.\s*\d{4})", raw)
|
||||
datum_de = dm.group(1).replace(" ", " ").strip() if dm else datum_de
|
||||
dm2 = DATE_RE.search(datum_de)
|
||||
if dm2:
|
||||
stand = stand_from_date(dm2.groups())
|
||||
title = (
|
||||
f"{rs}, Urteil vom {datum_de}"
|
||||
if rs.lower().startswith("eugh")
|
||||
else f"EuGH {rs}, Urteil vom {datum_de}"
|
||||
)
|
||||
court_tag = "eugh"
|
||||
chapter = "EuGH-Urteil"
|
||||
tags = ["rechtsprechung", "eugh", "urteil"]
|
||||
else:
|
||||
title = f"{court} {gz} vom {datum_de}"
|
||||
chapter = f"{court}-Erkenntnis (Volltext)"
|
||||
tags = ["rechtsprechung", court_tag, "volltext"]
|
||||
year = YEAR_RE.search(stand)
|
||||
if year:
|
||||
tags.append(f"jahr-{year.group(1)}")
|
||||
work = WORK_EUGH if kind == "eugh" else WORK_RJ
|
||||
legal_bases = [
|
||||
n.strip().rstrip(";")
|
||||
for n in re.split(r";\s*", fields.get("Norm", ""))
|
||||
if n.strip()
|
||||
]
|
||||
quelle = (
|
||||
f"*{work}, {court}, Entscheidung vom {datum_de}"
|
||||
+ (f", GZ {gz}" if gz else "")
|
||||
+ (f", {ecli}" if ecli else "")
|
||||
)
|
||||
if kind == "eugh":
|
||||
quelle += (
|
||||
f". Textwiedergabe (nicht amtlich): {fields.get('URL', '')}"
|
||||
+ (
|
||||
f"; amtliche Fassung: {fields.get('Offizielle Fassung', '')}"
|
||||
if fields.get("Offizielle Fassung")
|
||||
else ""
|
||||
)
|
||||
+ ".*"
|
||||
)
|
||||
else:
|
||||
quelle += ".*"
|
||||
|
||||
key = rel
|
||||
entry = catalog["entries"].get(key)
|
||||
if entry is None:
|
||||
seq = catalog["next_seq"]
|
||||
catalog["next_seq"] = seq + 1
|
||||
slug = "rj_" + ascii_slug(path.stem)
|
||||
entry = {"id": f"rj-rjs-{seq:03d}", "slug": slug}
|
||||
catalog["entries"][key] = entry
|
||||
kid, slug = entry["id"], entry["slug"]
|
||||
|
||||
sections = rj_build_sections(fields, body, kind)
|
||||
body_md = "\n\n".join(f"## {t}\n\n{text}" for t, text in sections if text)
|
||||
if not body_md.strip():
|
||||
stats["rj_empty"].append(rel)
|
||||
return None
|
||||
md = (
|
||||
f"---\n"
|
||||
f"id: {kid}\n"
|
||||
f"batch: 1\n"
|
||||
f"title: {json.dumps(title, ensure_ascii=False)}\n"
|
||||
f"work: {json.dumps(work, ensure_ascii=False)}\n"
|
||||
f"chapter: {json.dumps(chapter, ensure_ascii=False)}\n"
|
||||
f"topic: rechtsprechung\n"
|
||||
f"author: {json.dumps(court if kind != 'norm' else (fields.get('Abk\u00fcrzung') or court), ensure_ascii=False)}\n"
|
||||
f"stand: {stand}\n"
|
||||
f"source:\n"
|
||||
f" text: \".rechtsprechung/{rel}\"\n"
|
||||
f"legal_bases: {json.dumps(legal_bases, ensure_ascii=False)}\n"
|
||||
f"tags: {json.dumps(tags, ensure_ascii=False)}\n"
|
||||
f"cross_refs: []\n"
|
||||
f"---\n\n"
|
||||
f"# {title}\n\n"
|
||||
f"{quelle}\n\n"
|
||||
f"*Wissensbasis-ID: {kid}*\n\n"
|
||||
f"{body_md}\n"
|
||||
)
|
||||
entry.update({"title": title, "stand": stand, "kind": kind})
|
||||
stats["rj_written"] += 1
|
||||
return slug, md
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# CLI
|
||||
# --------------------------------------------------------------------------
|
||||
@@ -477,8 +758,9 @@ def write_entries(results: list[tuple[str, str]], dry: bool) -> int:
|
||||
|
||||
|
||||
def run(source: str, dry: bool, limit: int | None, single: str | None) -> int:
|
||||
stats: dict = {"kv_written": 0, "ris_written": 0, "no_og": [], "no_main": [],
|
||||
"ris_unmapped": []}
|
||||
stats: dict = {"kv_written": 0, "ris_written": 0, "rj_written": 0,
|
||||
"no_og": [], "no_main": [], "ris_unmapped": [],
|
||||
"rj_unparsed": [], "rj_empty": []}
|
||||
written = 0
|
||||
|
||||
if source in ("kv", "all"):
|
||||
@@ -513,9 +795,31 @@ def run(source: str, dry: bool, limit: int | None, single: str | None) -> int:
|
||||
if not dry:
|
||||
save_catalog(catalog)
|
||||
|
||||
if source in ("rj", "all"):
|
||||
catalog = load_catalog("rj")
|
||||
files = sorted(RJ_DIR.glob("originale/*.md")) + sorted(
|
||||
RJ_DIR.glob("gesetze/*.md")
|
||||
)
|
||||
files = [f for f in files if f.name != "INDEX.md"]
|
||||
if single:
|
||||
files = [f for f in files if single in f.name]
|
||||
if limit:
|
||||
files = files[:limit]
|
||||
results = []
|
||||
for f in files:
|
||||
res = rj_entry(f, catalog, stats)
|
||||
if res:
|
||||
results.append(res)
|
||||
written += write_entries(results, dry)
|
||||
if not dry:
|
||||
save_catalog(catalog)
|
||||
|
||||
print(f"source={source} dry={dry} written={written}")
|
||||
print(f" kv: {stats['kv_written']} ris: {stats['ris_written']}")
|
||||
for key in ("no_og", "no_main", "ris_unmapped"):
|
||||
print(
|
||||
f" kv: {stats['kv_written']} ris: {stats['ris_written']} "
|
||||
f"rj: {stats['rj_written']}"
|
||||
)
|
||||
for key in ("no_og", "no_main", "ris_unmapped", "rj_unparsed", "rj_empty"):
|
||||
if stats[key]:
|
||||
print(f" {key}: {stats[key]}")
|
||||
return 0
|
||||
@@ -523,7 +827,7 @@ def run(source: str, dry: bool, limit: int | None, single: str | None) -> int:
|
||||
|
||||
def main() -> int:
|
||||
ap = argparse.ArgumentParser(description=__doc__)
|
||||
ap.add_argument("--source", choices=("kv", "ris", "all"), default="all")
|
||||
ap.add_argument("--source", choices=("kv", "ris", "rj", "all"), default="all")
|
||||
ap.add_argument("--dry-run", action="store_true")
|
||||
ap.add_argument("--limit", type=int, default=None)
|
||||
ap.add_argument("--file", default=None, help="Teilstring des Quelldateinamens")
|
||||
|
||||
+9
-1
@@ -22,9 +22,10 @@ ID_SPACES = {
|
||||
"wk": "WIKU Personal (Fachbroschüren, Arbeitsunterlagen, Casebook, Personal aktuell)",
|
||||
"kv": "WKO.at — Kollektivvertrag-Dokumente (Lohn-/Gehaltsordnungen, KV-Texte)",
|
||||
"ris": "RIS — Rechtsinformationssystem des Bundes (Gesetzes-§-Auschnitte)",
|
||||
"rj": "RIS/OGD — Rechtsprechung (OGH, VwGH, VfGH, EuGH) und zitierte Normen",
|
||||
}
|
||||
|
||||
# Neue Cluster der Quellen kv/ris: slug -> (ID-Präfix, Anzeigename).
|
||||
# Neue Cluster der Quellen kv/ris/rj: slug -> (ID-Präfix, Anzeigename).
|
||||
NEW_CLUSTERS = {
|
||||
"kollektivvertraege": ("kvt", "Kollektivverträge (WKO.at)"),
|
||||
"zivilrecht-normen": ("zvr", "Zivilrechtliche Normen (ABGB, ZPO & Co.)"),
|
||||
@@ -33,11 +34,18 @@ NEW_CLUSTERS = {
|
||||
"lohnsteuer": ("lst", "Lohnsteuer & Einkommensteuer (EStG)"),
|
||||
"abgabenverfahren": ("abo", "Abgabenverfahren (BAO)"),
|
||||
"normen-sonstige": ("nso", "Weitere Gesetze und Verordnungen"),
|
||||
"rechtsprechung": (
|
||||
"rjs",
|
||||
"Rechtsprechung (OGH, VwGH, VfGH, EuGH) und zitierte Normen",
|
||||
),
|
||||
}
|
||||
|
||||
# Werk-Namen der neuen Quellen (Frontmatter `work`).
|
||||
WORK_KV = "WKO.at – Kollektivvertrag"
|
||||
WORK_RIS = "RIS – Rechtsinformationssystem des Bundes"
|
||||
WORK_RJ = "RIS – Rechtsprechung (OGD-Justiz/VwGH/VfGH)"
|
||||
WORK_EUGH = "EuGH – Rechtsprechung (Textwiedergabe lexetius, nicht amtlich)"
|
||||
WORK_NORM = "RIS – Originalwortlaut zitierte Norm"
|
||||
|
||||
# .ris/<Datei ohne .md> -> (topic, chapter, lfd. Nummer im Cluster).
|
||||
# Nummern sind fix (dann eingefroren); neue Gesetze hängen in ihrem Cluster
|
||||
|
||||
+359
-1
@@ -1,6 +1,6 @@
|
||||
# Index — Wissensbasis Personalverrechnung
|
||||
|
||||
Generiert am 2026-09-14 · 1274 Einträge · 76 Cluster. Quellen: Lexis Briefings Personalrecht (Lexis 360, lizenzierter Export), WIKU Personal (Fachbroschüren, Arbeitsunterlagen, Casebooks, „WIKU Personal aktuell“), WKO.at – Kollektivvertrag (KV-Dokumente, quellentreu generiert) und RIS – Rechtsinformationssystem des Bundes (Gesetzes-§-Auschnitte, quellentreu generiert). Rohquellen lokal/unversioniert (`.lexis360/`, `.wiku/`, `.firecrawl/`, `.ris/`). Werte gelten je zum Quell-Stand (`stand` im Frontmatter); Widersprüche und offene Punkte sind mit ⚠/❓ in den Einträgen selbst dokumentiert. Schema & Konventionen: `README.md`.
|
||||
Generiert am 2026-09-15 · 1622 Einträge · 77 Cluster. Quellen: Lexis Briefings Personalrecht (Lexis 360, lizenzierter Export), WIKU Personal (Fachbroschüren, Arbeitsunterlagen, Casebooks, „WIKU Personal aktuell“), WKO.at – Kollektivvertrag (KV-Dokumente, quellentreu generiert), RIS – Rechtsinformationssystem des Bundes (Gesetzes-§-Auschnitte, quellentreu generiert) sowie Rechtsprechung (RIS-OGD-Entscheidungen und Normauszüge; EuGH-Textwiedergaben separat als nicht amtlich markiert). Rohquellen lokal/unversioniert (`.lexis360/`, `.wiku/`, `.firecrawl/`, `.firecrawl/ris/gesetze/`, `.rechtsprechung/`). Werte gelten je zum Quell-Stand (`stand` im Frontmatter); Widersprüche und offene Punkte sind mit ⚠/❓ in den Einträgen selbst dokumentiert. Schema & Konventionen: `README.md`.
|
||||
|
||||
|
||||
# Lexis Briefings Personalrecht (Lexis 360-Export) — 571 Einträge
|
||||
@@ -2170,3 +2170,361 @@ Generiert am 2026-09-14 · 1274 Einträge · 76 Cluster. Quellen: Lexis Briefing
|
||||
|---|---|---|---|---|
|
||||
| ris-prd-01 | Zivildienstgesetz 1986 (ZDG) | RIS (Bundeskanzleramt) | 2026-09 | ris_zdg.md |
|
||||
|
||||
|
||||
# RIS/OGD — Rechtsprechung (OGH, VwGH, VfGH, EuGH) und zitierte Normen — 348 Einträge
|
||||
|
||||
|
||||
## Rechtsprechung (OGH, VwGH, VfGH, EuGH) und zitierte Normen (`topic: rechtsprechung`) — 348 Einträge · Stand 1951-10 bis 2026-09
|
||||
|
||||
|
||||
| ID | Titel | Autor | Stand | Datei |
|
||||
|---|---|---|---|---|
|
||||
| rj-rjs-001 | EuGH C-171,172/94, Urteil vom 7. 3. 1996 | EuGH | 1996-03 | rj_eugh-c-171-172-1994.md |
|
||||
| rj-rjs-002 | EuGH C-29/91, Urteil vom 19. 5. 1992 | EuGH | 1992-05 | rj_eugh-c-29-1991.md |
|
||||
| rj-rjs-003 | EuGH C-458/05, Urteil vom 13.09.2007 | EuGH | 2007-09 | rj_eugh-c-458-2005.md |
|
||||
| rj-rjs-004 | EuGH C-463/09, Urteil vom 20. 1. 2011 | EuGH | 2011-01 | rj_eugh-c-463-2009.md |
|
||||
| rj-rjs-005 | EuGH C-466/07, Urteil vom 12. 2. 2009 | EuGH | 2009-02 | rj_eugh-c-466-2007.md |
|
||||
| rj-rjs-006 | Verfassungsgerichtshof G62/2018 vom 04.10.2018 | Verfassungsgerichtshof | 2018-10 | rj_jft-20181004-18g00062-00.md |
|
||||
| rj-rjs-007 | Verfassungsgerichtshof G135/2018 vom 04.10.2018 | Verfassungsgerichtshof | 2018-10 | rj_jft-20181004-18g00135-00.md |
|
||||
| rj-rjs-008 | Verfassungsgerichtshof G325/2018 vom 25.02.2019 | Verfassungsgerichtshof | 2019-02 | rj_jft-20190225-18g00325-00.md |
|
||||
| rj-rjs-009 | Verfassungsgerichtshof G326/2018 vom 25.02.2019 | Verfassungsgerichtshof | 2019-02 | rj_jft-20190225-18g00326-00.md |
|
||||
| rj-rjs-010 | Angebliche Mängel des Verfahrens I. Instanz, die vom Berufungsgerichte nicht als solche anerkannt… | OGH | 2026-06 | rj_jjr-19490720-ogh0002-0010ob00313-4900000-001.md |
|
||||
| rj-rjs-011 | Die für die Entlassung maßgebenden Gründe müssen nicht schon in der Entlassungserklärung angeführt… | OGH | 1951-10 | rj_jjr-19511018-ogh0002-0040ob00106-5100000-002.md |
|
||||
| rj-rjs-012 | Ein einmaliger Verzug bei Zahlung des Gehaltes berechtigt nicht zum Austritt. | OGH | 1952-06 | rj_jjr-19520610-ogh0002-0040ob00066-5200000-001.md |
|
||||
| rj-rjs-013 | Auf das Dienstverhältnis eines Redakteurs, das seine Erwerbstätigkeit nicht hauptsächlich in… | OGH | 1952-09 | rj_jjr-19520930-ogh0002-0040ob00122-5200000-001.md |
|
||||
| rj-rjs-014 | Der Vorwurf der Denunziation ist als erhebliche Ehrverletzung anzusehen. Ob eine Äußerung als… | OGH | 1952-09 | rj_jjr-19520930-ogh0002-0040ob00122-5200000-002.md |
|
||||
| rj-rjs-015 | Die Prozeßkostenersatzpflicht ist ausschließlich durch den Prozeßerfolg bedingt. Dies gilt auch… | OGH | 1952-11 | rj_jjr-19521111-ogh0002-0040ob00122-5200000-003.md |
|
||||
| rj-rjs-016 | Nur ein Verstoß gegen die dienstliche Treuepflicht bildet einen wichtigen Kündigungsgrund. Auch die… | OGH | 1953-01 | rj_jjr-19530120-ogh0002-0040ob00003-5300000-001.md |
|
||||
| rj-rjs-017 | Nichtzustandekommen einer neuen Lohnvereinbarung (Austrittsgrund?). | OGH | 1953-07 | rj_jjr-19530707-ogh0002-0040ob00090-5300000-001.md |
|
||||
| rj-rjs-018 | Bei der Beurteilung der Frage, ob eine Äußerung als erhebliche Ehrverletzung und damit als… | OGH | 2025-08 | rj_jjr-19530709-ogh0002-0040ob00120-5300000-001.md |
|
||||
| rj-rjs-019 | Wenn eine nach außen hin als Kündigung erscheinende Auflösung des Dienstverhältnisses durch den… | OGH | 1954-03 | rj_jjr-19540302-ogh0002-0040ob00022-5400000-002.md |
|
||||
| rj-rjs-020 | Schriftliche Rüge eines Angestellten (Hauptbuchhalters) keine erhebliche Ehrverletzung, die Austritt… | OGH | 1954-07 | rj_jjr-19540715-ogh0002-0040ob00100-5400000-001.md |
|
||||
| rj-rjs-021 | Die Bezahlung von Entgeltbeträgen, die dem Dienstnehmer über den kollektivvertraglichen… | OGH | 1955-03 | rj_jjr-19550322-ogh0002-0040ob00129-5400000-001.md |
|
||||
| rj-rjs-022 | Die Mitteilung des Dienstgebers, dem Dienstnehmer, dem ein höherer Gehalt vertraglich zusteht, ab… | OGH | 1955-03 | rj_jjr-19550322-ogh0002-0040ob00129-5400000-002.md |
|
||||
| rj-rjs-023 | Nervosität und Unbeherrschtheit eines Dienstnehmers sind keine Gründe, die den von ihm gesetzten… | OGH | 1955-05 | rj_jjr-19550524-ogh0002-0040ob00046-5500000-001.md |
|
||||
| rj-rjs-024 | Die Androhung der Entlassung, wenn sich der Dienstnehmer nicht binnen einer kurzen Frist zur… | OGH | 1955-06 | rj_jjr-19550614-ogh0002-0040ob00073-5500000-001.md |
|
||||
| rj-rjs-025 | Der die Entlassung aussprechende Dienstgeber ist nicht verpflichtet, die Entlassungsgründe im… | OGH | 1955-06 | rj_jjr-19550614-ogh0002-0040ob00073-5500000-002.md |
|
||||
| rj-rjs-026 | Der Revisionsgrund des § 503 Z 2 ZPO ist durch mangelhafte Begründung so wenig gegeben, wie der… | OGH | 2024-06 | rj_jjr-19550831-ogh0002-0070ob00352-5500000-002.md |
|
||||
| rj-rjs-027 | Dieser Austrittsgrund liegt nur vor, wenn der Schutz des Dienstgebers erfolglos angerufen… | OGH | 1955-09 | rj_jjr-19550906-ogh0002-0040ob00098-5500000-001.md |
|
||||
| rj-rjs-028 | Kein Entlassungsgrund, wenn Angestellter pornographische Bilder einem großjährigen Mitbediensteten… | OGH | 1955-09 | rj_jjr-19550906-ogh0002-0040ob00098-5500000-002.md |
|
||||
| rj-rjs-029 | Keine Ansprüche des Dienstnehmers aus der im Probemonat herbeigeführten Lösung des… | OGH | 2025-09 | rj_jjr-19550906-ogh0002-0040ob00109-5500000-001.md |
|
||||
| rj-rjs-030 | Ob ein Tatbestand einen wichtigen Austrittsgrund darstellt, ist nicht nach der subjektiven… | OGH | 1955-12 | rj_jjr-19551206-ogh0002-0040ob00170-5500000-001.md |
|
||||
| rj-rjs-031 | Eine Kündigung mit verkürzter Frist anstatt der Entlassung ist wirksam, wenn sie sich ausdrücklich… | OGH | 1956-02 | rj_jjr-19560214-ogh0002-0040ob00196-5500000-001.md |
|
||||
| rj-rjs-032 | Ein Dienstnehmer, der den Dienstgeber auf die ihm gesetzlich obliegenden Schutzverpflichtungen… | OGH | 1956-05 | rj_jjr-19560508-ogh0002-0040ob00015-5600000-001.md |
|
||||
| rj-rjs-033 | Keine Verwirkung des Austrittsrechtes eines Dienstnehmers, der einmal auf eine Verzögerung oder… | OGH | 2023-06 | rj_jjr-19561002-ogh0002-0040ob00076-5600000-001.md |
|
||||
| rj-rjs-034 | Indirekte Diebstahlsbeschuldigung. Eine Lösung des Dienstverhältnisses aus wichtigen Gründen liegt… | OGH | 1957-07 | rj_jjr-19570702-ogh0002-0040ob00025-5700000-001.md |
|
||||
| rj-rjs-035 | Nicht jede Vertragsverletzung berechtigt zum sofortigen Austritt. Wesentlich ist die… | OGH | 1957-07 | rj_jjr-19570702-ogh0002-0040ob00075-5700000-001.md |
|
||||
| rj-rjs-036 | Auch eine einmalige empfindliche Beleidigung kann einen Entlassungsgrund oder Austrittsgrund… | OGH | 1957-12 | rj_jjr-19571217-ogh0002-0040ob00121-5700000-001.md |
|
||||
| rj-rjs-037 | Der Vorwurf der Veruntreuung stellt einen Austrittsgrund dar, wenn der Vorwurf nicht durch das… | OGH | 1959-04 | rj_jjr-19590421-ogh0002-0040ob00034-5900000-001.md |
|
||||
| rj-rjs-038 | "Verletzung der Sittlichkeit" erfordert unzüchtige, also die Sittlichkeit in sexueller Beziehung… | OGH | 1960-06 | rj_jjr-19600621-ogh0002-0040ob00086-6000000-001.md |
|
||||
| rj-rjs-039 | Bei Prüfung des Entlassungsgrundes der Vertrauensunwürdigkeit ist an das Verhalten des Angestellten… | OGH | 2023-09 | rj_jjr-19600906-ogh0002-0040ob00093-6000000-001.md |
|
||||
| rj-rjs-040 | Die Weigerung des Dienstgebers, den Dienstnehmer zur Sozialversicherung anzumelden, bildet für den… | OGH | 1962-04 | rj_jjr-19620403-ogh0002-0040ob00035-6200000-001.md |
|
||||
| rj-rjs-041 | Nicht jede, sondern nur eine wesentliche Vertragsverletzung berechtigt zum Austritt; wesentlich ist… | OGH | 1962-11 | rj_jjr-19621113-ogh0002-0040ob00124-6200000-001.md |
|
||||
| rj-rjs-042 | Eine Verletzung einer wesentlichen Vertragsbestimmung gemäß § 82 a lit d GewO liegt vor, wenn der… | OGH | 1963-10 | rj_jjr-19631022-ogh0002-0040ob00094-6300000-001.md |
|
||||
| rj-rjs-043 | Eine an sich erhebliche Ehrverletzung bildet selbst dann, wenn sie zu einer strafgerichtlichen… | OGH | 1964-07 | rj_jjr-19640728-ogh0002-0040ob00065-6400000-001.md |
|
||||
| rj-rjs-044 | Zum Anspruch auf Urlaubsentschädigung (mit grundsätzlichen Ausführungen). | OGH | 1965-04 | rj_jjr-19650427-ogh0002-0040ob00052-6500000-001.md |
|
||||
| rj-rjs-045 | Die DO.A ist ein Kollektivvertrag (vgl auch EvBl 1956/87 = JBl 1956,240). | OGH | 1965-10 | rj_jjr-19651005-ogh0002-0040ob00112-6500000-002.md |
|
||||
| rj-rjs-046 | Gerechtfertigter Austritt einer Verwaltungsangestellten eines Sozialversicherungsträgers wegen… | OGH | 1967-02 | rj_jjr-19670228-ogh0002-0040ob00015-6700000-001.md |
|
||||
| rj-rjs-047 | Nach § 32 AngG braucht das Mitverschulden des - aus einem wichtigen Grund im Sinne des § 26 AngG… | OGH | 1967-04 | rj_jjr-19670418-ogh0002-0040ob00025-6700000-001.md |
|
||||
| rj-rjs-048 | Wiederholung einer Beleidigung ("Ich sage Ihnen noch einmal, Sie sind blöd!") als Austrittsgrund. | OGH | 1967-04 | rj_jjr-19670418-ogh0002-0040ob00025-6700000-002.md |
|
||||
| rj-rjs-049 | Dieser Entlassungsgrund ist ua dann gegeben, wenn der Angestellte sich gegenüber einem… | OGH | 1970-12 | rj_jjr-19701201-ogh0002-0040ob00099-7000000-001.md |
|
||||
| rj-rjs-050 | Der Dienstgeber kann ein vereinbartes Überstundenpauschale nicht einseitig aufheben. | OGH | 1971-10 | rj_jjr-19711012-ogh0002-0040ob00059-7100000-001.md |
|
||||
| rj-rjs-051 | Ein Überstundenpauschale ist in die Bemessungsgrundlage der Abfertigung miteinzubeziehen. | OGH | 1971-10 | rj_jjr-19711012-ogh0002-0040ob00059-7100000-002.md |
|
||||
| rj-rjs-052 | Berechtigter Austritt eines Angestellten wegen vertragswidriger einseitiger Aufhebung eines… | OGH | 1971-10 | rj_jjr-19711012-ogh0002-0040ob00059-7100000-003.md |
|
||||
| rj-rjs-053 | § 32 AngG dient nicht dazu, dass ein zur Erhebung des Schuldvorwurfes nicht ausreichendes Verhalten… | OGH | 2024-10 | rj_jjr-19730109-ogh0002-0040ob00094-7200000-001.md |
|
||||
| rj-rjs-054 | Von einer ungebührlichen Schmälerung oder einem ungebührlichen Vorenthalten des Entgeltes kann nur… | OGH | 1973-01 | rj_jjr-19730109-ogh0002-0040ob00094-7200000-002.md |
|
||||
| rj-rjs-055 | Voraussetzung für die Anwendung des § 32 AngG ist ein für das Zustandekommen des… | OGH | 1973-01 | rj_jjr-19730109-ogh0002-0040ob00103-7200000-001.md |
|
||||
| rj-rjs-056 | Ein Verzicht auf den kollektivvertraglich gebührenden Lohn vor dessen Fälligkeit ist jedenfalls… | OGH | 1973-09 | rj_jjr-19730911-ogh0002-0040ob00101-7300000-005.md |
|
||||
| rj-rjs-057 | Verschweigung von Austrittsgründen tritt nicht ein, wenn es sich bei den Tatbeständen um einen… | OGH | 1973-12 | rj_jjr-19731211-ogh0002-0040ob00098-7300000-001.md |
|
||||
| rj-rjs-058 | Die Fälligstellung des Überstundenentgeltanspruches setzt Bekanntgabe der Überstunden, allenfalls… | OGH | 1973-12 | rj_jjr-19731211-ogh0002-0040ob00098-7300000-002.md |
|
||||
| rj-rjs-059 | Weigert sich der Arbeitgeber bereits geleistete Überstunden abzugelten, so ist ein rechtswidriger… | OGH | 1973-12 | rj_jjr-19731211-ogh0002-0040ob00098-7300000-003.md |
|
||||
| rj-rjs-060 | Tätigt der Arbeitgeber aus der von einem Angestellten zu führenden Handkasse Entnahmen, ohne diese… | OGH | 1973-12 | rj_jjr-19731211-ogh0002-0040ob00098-7300000-004.md |
|
||||
| rj-rjs-061 | "Arbeiterverräter" gebraucht gegen Betriebsratsmitglied als Entlassungsgrund. | OGH | 1973-12 | rj_jjr-19731211-ogh0002-0040ob00101-7300000-001.md |
|
||||
| rj-rjs-062 | Nichteinhaltung der Pausenregelung durch den Arbeitnehmer kein Entlassungsgrund, wenn kein… | OGH | 1973-12 | rj_jjr-19731211-ogh0002-0040ob00101-7300000-002.md |
|
||||
| rj-rjs-063 | Es ist besonders schwerwiegend, wenn die beleidigende Äußerung gegen ein Mitglied des Betriebsrates… | OGH | 1973-12 | rj_jjr-19731211-ogh0002-0040ob00101-7300000-003.md |
|
||||
| rj-rjs-064 | Aus Judikat 26 neu kann keine unwiderlegliche Vermutung abgeleitet werden, daß ein vor Beendigung… | OGH | 1973-12 | rj_jjr-19731211-ogh0002-0040ob00101-7300000-004.md |
|
||||
| rj-rjs-065 | Beharrliche Pflichtverletzung im Sinne § 82 lit f GewO 1859, aufrechterhalten durch § 376 Z 47 GewO… | OGH | 1976-09 | rj_jjr-19760921-ogh0002-0040ob00098-7600000-002.md |
|
||||
| rj-rjs-066 | Urlaubsentschädigung auch bei einem nur wenig mehr als sechs Monate dauernden Dienstverhältnis. | OGH | 1977-03 | rj_jjr-19770322-ogh0002-0040ob00007-7700000-001.md |
|
||||
| rj-rjs-067 | Sobald die vereinbarte Dauer des Arbeitsvertrages die gesetzliche Wartefrist überstieg, stand der… | OGH | 1979-03 | rj_jjr-19790327-ogh0002-0040ob00004-7900000-001.md |
|
||||
| rj-rjs-068 | Vorwurf einer strafbaren Handlung ist für den betroffenen Arbeitnehmer regelmäßig ein Austrittsgrund… | OGH | 1979-03 | rj_jjr-19790327-ogh0002-0040ob00004-7900000-002.md |
|
||||
| rj-rjs-069 | Entscheidend für die Beurteilung der Tatbestandsmäßigkeit einer Ehrenbeleidigung und der… | OGH | 1979-07 | rj_jjr-19790710-ogh0002-0040ob00046-7900000-001.md |
|
||||
| rj-rjs-070 | Werden ehrenrührige Tatsachen nicht in beleidigender Absicht, sondern in Wahrung berechtigter… | OGH | 1979-07 | rj_jjr-19790710-ogh0002-0040ob00046-7900000-002.md |
|
||||
| rj-rjs-071 | Eine objektiv, aber nicht wissentlich falsche Beschuldigung aus Anlaß des Abhandenkommens eines… | OGH | 1979-07 | rj_jjr-19790710-ogh0002-0040ob00046-7900000-003.md |
|
||||
| rj-rjs-072 | Eine im Zusammenhang mit dem vom Betriebsrat betriebenen Sparverein gemachte Ehrenbeleidigung gegen… | OGH | 1979-07 | rj_jjr-19790710-ogh0002-0040ob00046-7900000-004.md |
|
||||
| rj-rjs-073 | Der Ehrenbeleidigung muss eine Verletzungsabsicht in Bezug auf die im Tatbestand angeführten… | OGH | 1979-07 | rj_jjr-19790710-ogh0002-0040ob00046-7900000-005.md |
|
||||
| rj-rjs-074 | Unter den "übrigen Hilfsarbeitern" sind alle - auch Betriebsratsmitglieder - beim selben Arbeitgeber… | OGH | 1979-07 | rj_jjr-19790710-ogh0002-0040ob00046-7900000-006.md |
|
||||
| rj-rjs-075 | Wird das Überstundenentgelt auf der Grundlage eines niedrigeren als des mit dem Arbeitnehmer… | OGH | 1980-04 | rj_jjr-19800429-ogh0002-0040ob00051-8000000-001.md |
|
||||
| rj-rjs-076 | Bei der Berechnung der Urlaubsentschädigung ist der unberechtigt entlassene Kläger gemäß § 9 UrlG… | OGH | 1981-09 | rj_jjr-19810915-ogh0002-0040ob00037-8100000-001.md |
|
||||
| rj-rjs-077 | Eine sachliche, nicht in beleidigender Form vorgebrachte Kritik des Arbeitgebers an der… | OGH | 2023-06 | rj_jjr-19820504-ogh0002-0040ob00036-8200000-001.md |
|
||||
| rj-rjs-078 | Unter den Tatbestand der Vertrauensunwürdigkeit im Sinne des § 27 Z 1 letzter Fall AngG fällt jede… | OGH | 2025-09 | rj_jjr-19830510-ogh0002-0040ob00051-8300000-003.md |
|
||||
| rj-rjs-079 | Die Rechtswirksamkeit von Änderungen des Arbeitsvertrages zum Nachteil des Arbeitnehmers ist Folge… | OGH | 2023-03 | rj_jjr-19831018-ogh0002-0040ob00105-8200000-004.md |
|
||||
| rj-rjs-080 | Der Entzug des auch für private Zwecke zur Verfügung gestellten Firmenfahrzeuges bei… | OGH | 1988-08 | rj_jjr-19880831-ogh0002-009oba00152-8800000-001.md |
|
||||
| rj-rjs-081 | OGH 4Ob152/84 vom 26.02.1985 | OGH | 1985-02 | rj_jjt-19850226-ogh0002-0040ob00152-8400000-000.md |
|
||||
| rj-rjs-082 | OGH 4Ob101/84 vom 28.10.1985 | OGH | 1985-10 | rj_jjt-19851028-ogh0002-0040ob00101-8400000-000.md |
|
||||
| rj-rjs-083 | OGH 14Ob7/86 vom 04.03.1986 | OGH | 1986-03 | rj_jjt-19860304-ogh0002-0140ob00007-8600000-000.md |
|
||||
| rj-rjs-084 | OGH 4Ob60/85 vom 13.05.1986 | OGH | 1986-05 | rj_jjt-19860513-ogh0002-0040ob00060-8500000-000.md |
|
||||
| rj-rjs-085 | OGH 14Ob90/86 vom 03.06.1986 | OGH | 1986-06 | rj_jjt-19860603-ogh0002-0140ob00090-8600000-000.md |
|
||||
| rj-rjs-086 | OGH 14Ob143/86 vom 30.09.1986 | OGH | 1986-09 | rj_jjt-19860930-ogh0002-0140ob00143-8600000-000.md |
|
||||
| rj-rjs-087 | OGH 14Ob201/86 vom 16.12.1986 | OGH | 1986-12 | rj_jjt-19861216-ogh0002-0140ob00201-8600000-000.md |
|
||||
| rj-rjs-088 | OGH 14ObA27/87 (14ObA28/87) vom 10.03.1987 | OGH | 1987-03 | rj_jjt-19870310-ogh0002-014oba00027-8700000-000.md |
|
||||
| rj-rjs-089 | OGH 14ObA38/87 vom 07.04.1987 | OGH | 1987-04 | rj_jjt-19870407-ogh0002-014oba00038-8700000-000.md |
|
||||
| rj-rjs-090 | OGH 9ObA113/87 vom 16.09.1987 | OGH | 1987-09 | rj_jjt-19870916-ogh0002-009oba00113-8700000-000.md |
|
||||
| rj-rjs-091 | OGH 14ObA77/87 vom 21.10.1987 | OGH | 1987-10 | rj_jjt-19871021-ogh0002-014oba00077-8700000-000.md |
|
||||
| rj-rjs-092 | OGH 9ObA201/87 vom 10.02.1988 | OGH | 1988-02 | rj_jjt-19880210-ogh0002-009oba00201-8700000-000.md |
|
||||
| rj-rjs-093 | OGH 9ObA44/88 vom 13.04.1988 | OGH | 1988-04 | rj_jjt-19880413-ogh0002-009oba00044-8800000-000.md |
|
||||
| rj-rjs-094 | OGH 9ObA112/88 vom 01.06.1988 | OGH | 1988-06 | rj_jjt-19880601-ogh0002-009oba00112-8800000-000.md |
|
||||
| rj-rjs-095 | OGH 9ObA120/88 vom 01.06.1988 | OGH | 1988-06 | rj_jjt-19880601-ogh0002-009oba00120-8800000-000.md |
|
||||
| rj-rjs-096 | OGH 9ObA155/88 vom 31.08.1988 | OGH | 1988-08 | rj_jjt-19880831-ogh0002-009oba00155-8800000-000.md |
|
||||
| rj-rjs-097 | OGH 9ObA189/88 vom 14.09.1988 | OGH | 1988-09 | rj_jjt-19880914-ogh0002-009oba00189-8800000-000.md |
|
||||
| rj-rjs-098 | OGH 9ObA68/89 vom 19.04.1989 | OGH | 1989-04 | rj_jjt-19890419-ogh0002-009oba00068-8900000-000.md |
|
||||
| rj-rjs-099 | OGH 9ObA188/89 vom 12.07.1989 | OGH | 1989-07 | rj_jjt-19890712-ogh0002-009oba00188-8900000-000.md |
|
||||
| rj-rjs-100 | OGH 9ObA5/90 vom 31.01.1990 | OGH | 1990-01 | rj_jjt-19900131-ogh0002-009oba00005-9000000-000.md |
|
||||
| rj-rjs-101 | OGH 9ObA166/90 vom 11.07.1990 | OGH | 1990-07 | rj_jjt-19900711-ogh0002-009oba00166-9000000-000.md |
|
||||
| rj-rjs-102 | OGH 9ObA231/90 (9ObA232/90) vom 26.09.1990 | OGH | 1990-09 | rj_jjt-19900926-ogh0002-009oba00231-9000000-000.md |
|
||||
| rj-rjs-103 | OGH 9ObA254/90 vom 07.11.1990 | OGH | 1990-11 | rj_jjt-19901107-ogh0002-009oba00254-9000000-000.md |
|
||||
| rj-rjs-104 | OGH 9ObA274/90 vom 21.11.1990 | OGH | 1990-11 | rj_jjt-19901121-ogh0002-009oba00274-9000000-000.md |
|
||||
| rj-rjs-105 | OGH 9Oba35/91 vom 10.04.1991 | OGH | 1991-04 | rj_jjt-19910410-ogh0002-0090oba0035-9100000-000.md |
|
||||
| rj-rjs-106 | OGH 9ObA73/91 vom 08.05.1991 | OGH | 1991-05 | rj_jjt-19910508-ogh0002-009oba00073-9100000-000.md |
|
||||
| rj-rjs-107 | OGH 9ObA120/91 vom 19.06.1991 | OGH | 1991-06 | rj_jjt-19910619-ogh0002-009oba00120-9100000-000.md |
|
||||
| rj-rjs-108 | OGH 9ObA127/91 vom 19.06.1991 | OGH | 1991-06 | rj_jjt-19910619-ogh0002-009oba00127-9100000-000.md |
|
||||
| rj-rjs-109 | OGH 9ObA19/92 (9ObA20/92) vom 26.02.1992 | OGH | 1992-02 | rj_jjt-19920226-ogh0002-009oba00019-9200000-000.md |
|
||||
| rj-rjs-110 | OGH 9ObA30/92 vom 26.02.1992 | OGH | 1992-02 | rj_jjt-19920226-ogh0002-009oba00030-9200000-000.md |
|
||||
| rj-rjs-111 | OGH 9ObA60/92 vom 18.03.1992 | OGH | 1992-03 | rj_jjt-19920318-ogh0002-009oba00060-9200000-000.md |
|
||||
| rj-rjs-112 | OGH 9ObA56/92 vom 08.04.1992 | OGH | 1992-04 | rj_jjt-19920408-ogh0002-009oba00056-9200000-000.md |
|
||||
| rj-rjs-113 | OGH 9ObA91/92 vom 17.06.1992 | OGH | 1992-06 | rj_jjt-19920617-ogh0002-009oba00091-9200000-000.md |
|
||||
| rj-rjs-114 | OGH 9ObA202/92 vom 25.11.1992 | OGH | 1992-11 | rj_jjt-19921125-ogh0002-009oba00202-9200000-000.md |
|
||||
| rj-rjs-115 | OGH 9ObA287/92 vom 27.01.1993 | OGH | 1993-01 | rj_jjt-19930127-ogh0002-009oba00287-9200000-000.md |
|
||||
| rj-rjs-116 | OGH 9ObA25/93 vom 24.02.1993 | OGH | 1993-02 | rj_jjt-19930224-ogh0002-009oba00025-9300000-000.md |
|
||||
| rj-rjs-117 | OGH 9ObA53/93 vom 14.04.1993 | OGH | 1993-04 | rj_jjt-19930414-ogh0002-009oba00053-9300000-000.md |
|
||||
| rj-rjs-118 | OGH 9ObA80/93 vom 28.04.1993 | OGH | 1993-04 | rj_jjt-19930428-ogh0002-009oba00080-9300000-000.md |
|
||||
| rj-rjs-119 | OGH 9ObA86/93 vom 19.05.1993 | OGH | 1993-05 | rj_jjt-19930519-ogh0002-009oba00086-9300000-000.md |
|
||||
| rj-rjs-120 | OGH 9ObA105/93 vom 09.06.1993 | OGH | 1993-06 | rj_jjt-19930609-ogh0002-009oba00105-9300000-000.md |
|
||||
| rj-rjs-121 | OGH 9ObA96/93 vom 08.07.1993 | OGH | 1993-07 | rj_jjt-19930708-ogh0002-009oba00096-9300000-000.md |
|
||||
| rj-rjs-122 | OGH 9ObA115/93 vom 08.07.1993 | OGH | 1993-07 | rj_jjt-19930708-ogh0002-009oba00115-9300000-000.md |
|
||||
| rj-rjs-123 | OGH 9ObA205/93 vom 22.09.1993 | OGH | 1993-09 | rj_jjt-19930922-ogh0002-009oba00205-9300000-000.md |
|
||||
| rj-rjs-124 | OGH 9ObA211/93 vom 24.11.1993 | OGH | 1993-11 | rj_jjt-19931124-ogh0002-009oba00211-9300000-000.md |
|
||||
| rj-rjs-125 | OGH 9ObA281/93 vom 22.12.1993 | OGH | 1993-12 | rj_jjt-19931222-ogh0002-009oba00281-9300000-000.md |
|
||||
| rj-rjs-126 | OGH 9ObA288/93(9ObA289/93) vom 22.12.1993 | OGH | 1993-12 | rj_jjt-19931222-ogh0002-009oba00288-9300000-000.md |
|
||||
| rj-rjs-127 | OGH 8ObA206/94 vom 17.03.1994 | OGH | 1994-03 | rj_jjt-19940317-ogh0002-008oba00206-9400000-000.md |
|
||||
| rj-rjs-128 | OGH 9ObA50/94 vom 06.04.1994 | OGH | 1994-04 | rj_jjt-19940406-ogh0002-009oba00050-9400000-000.md |
|
||||
| rj-rjs-129 | OGH 9ObA70/94 vom 25.05.1994 | OGH | 1994-05 | rj_jjt-19940525-ogh0002-009oba00070-9400000-000.md |
|
||||
| rj-rjs-130 | OGH 8ObA262/94 vom 16.06.1994 | OGH | 1994-06 | rj_jjt-19940616-ogh0002-008oba00262-9400000-000.md |
|
||||
| rj-rjs-131 | OGH 9ObA92/94 vom 29.06.1994 | OGH | 1994-06 | rj_jjt-19940629-ogh0002-009oba00092-9400000-000.md |
|
||||
| rj-rjs-132 | OGH 8ObA215/94 vom 31.08.1994 | OGH | 1994-08 | rj_jjt-19940831-ogh0002-008oba00215-9400000-000.md |
|
||||
| rj-rjs-133 | OGH 9ObA126/94 vom 14.09.1994 | OGH | 1994-09 | rj_jjt-19940914-ogh0002-009oba00126-9400000-000.md |
|
||||
| rj-rjs-134 | OGH 8ObA239/94 vom 15.09.1994 | OGH | 1994-09 | rj_jjt-19940915-ogh0002-008oba00239-9400000-000.md |
|
||||
| rj-rjs-135 | OGH 9ObA171/94 (9ObA172/94, 9ObA173/94) vom 12.10.1994 | OGH | 1994-10 | rj_jjt-19941012-ogh0002-009oba00171-9400000-000.md |
|
||||
| rj-rjs-136 | OGH 4Ob103/94 vom 18.10.1994 | OGH | 1994-10 | rj_jjt-19941018-ogh0002-0040ob00103-9400000-000.md |
|
||||
| rj-rjs-137 | OGH 9ObA241/94 vom 25.01.1995 | OGH | 1995-01 | rj_jjt-19950125-ogh0002-009oba00241-9400000-000.md |
|
||||
| rj-rjs-138 | OGH 9ObA142/95 vom 23.08.1995 | OGH | 1995-08 | rj_jjt-19950823-ogh0002-009oba00142-9500000-000.md |
|
||||
| rj-rjs-139 | OGH 9ObA180/95 vom 01.01.1996 | OGH | 1996-01 | rj_jjt-19960101-ogh0002-009oba00180-9500000-000.md |
|
||||
| rj-rjs-140 | OGH 9ObA11/96 vom 31.01.1996 | OGH | 1996-01 | rj_jjt-19960131-ogh0002-009oba00011-9600000-000.md |
|
||||
| rj-rjs-141 | OGH 8ObA211/96 vom 29.02.1996 | OGH | 1996-02 | rj_jjt-19960229-ogh0002-008oba00211-9600000-000.md |
|
||||
| rj-rjs-142 | OGH 9ObA2050/96b vom 29.05.1996 | OGH | 1996-05 | rj_jjt-19960529-ogh0002-009oba02050-96b0000-000.md |
|
||||
| rj-rjs-143 | OGH 8ObA2100/96y vom 13.06.1996 | OGH | 1996-06 | rj_jjt-19960613-ogh0002-008oba02100-96y0000-000.md |
|
||||
| rj-rjs-144 | OGH 8ObA2302/96d vom 14.11.1996 | OGH | 1996-11 | rj_jjt-19961114-ogh0002-008oba02302-96d0000-000.md |
|
||||
| rj-rjs-145 | OGH 9ObA2267/96i vom 04.12.1996 | OGH | 1996-12 | rj_jjt-19961204-ogh0002-009oba02267-96i0000-000.md |
|
||||
| rj-rjs-146 | OGH 9ObA32/97i vom 09.04.1997 | OGH | 1997-04 | rj_jjt-19970409-ogh0002-009oba00032-97i0000-000.md |
|
||||
| rj-rjs-147 | OGH 9ObA114/97y vom 09.04.1997 | OGH | 1997-04 | rj_jjt-19970409-ogh0002-009oba00114-97y0000-000.md |
|
||||
| rj-rjs-148 | OGH 8ObA142/97h vom 23.05.1997 | OGH | 1997-05 | rj_jjt-19970523-ogh0002-008oba00142-97h0000-000.md |
|
||||
| rj-rjs-149 | OGH 9ObA158/97v vom 09.07.1997 | OGH | 1997-07 | rj_jjt-19970709-ogh0002-009oba00158-97v0000-000.md |
|
||||
| rj-rjs-150 | OGH 9ObA87/97b vom 27.08.1997 | OGH | 1997-08 | rj_jjt-19970827-ogh0002-009oba00087-97b0000-000.md |
|
||||
| rj-rjs-151 | OGH 8ObA91/97h vom 28.08.1997 | OGH | 1997-08 | rj_jjt-19970828-ogh0002-008oba00091-97h0000-000.md |
|
||||
| rj-rjs-152 | OGH 9ObA162/97g vom 22.10.1997 | OGH | 1997-10 | rj_jjt-19971022-ogh0002-009oba00162-97g0000-000.md |
|
||||
| rj-rjs-153 | OGH 9ObA249/97a vom 05.11.1997 | OGH | 1997-11 | rj_jjt-19971105-ogh0002-009oba00249-97a0000-000.md |
|
||||
| rj-rjs-154 | OGH 9ObA275/97z vom 10.12.1997 | OGH | 1997-12 | rj_jjt-19971210-ogh0002-009oba00275-97z0000-000.md |
|
||||
| rj-rjs-155 | OGH 8ObA8/98d vom 26.02.1998 | OGH | 1998-02 | rj_jjt-19980226-ogh0002-008oba00008-98d0000-000.md |
|
||||
| rj-rjs-156 | OGH 8ObA61/98y vom 12.03.1998 | OGH | 1998-03 | rj_jjt-19980312-ogh0002-008oba00061-98y0000-000.md |
|
||||
| rj-rjs-157 | OGH 8ObA149/98i vom 25.06.1998 | OGH | 1998-06 | rj_jjt-19980625-ogh0002-008oba00149-98i0000-000.md |
|
||||
| rj-rjs-158 | OGH 9ObA100/98s vom 02.09.1998 | OGH | 1998-09 | rj_jjt-19980902-ogh0002-009oba00100-98s0000-000.md |
|
||||
| rj-rjs-159 | OGH 9ObA193/98t vom 07.10.1998 | OGH | 1998-10 | rj_jjt-19981007-ogh0002-009oba00193-98t0000-000.md |
|
||||
| rj-rjs-160 | OGH 9ObA276/98y vom 11.11.1998 | OGH | 1998-11 | rj_jjt-19981111-ogh0002-009oba00276-98y0000-000.md |
|
||||
| rj-rjs-161 | OGH 9ObA287/98s vom 09.12.1998 | OGH | 1998-12 | rj_jjt-19981209-ogh0002-009oba00287-98s0000-000.md |
|
||||
| rj-rjs-162 | OGH 9ObA10/99g vom 05.05.1999 | OGH | 1999-05 | rj_jjt-19990505-ogh0002-009oba00010-99g0000-000.md |
|
||||
| rj-rjs-163 | OGH 9ObA192/99x vom 01.09.1999 | OGH | 1999-09 | rj_jjt-19990901-ogh0002-009oba00192-99x0000-000.md |
|
||||
| rj-rjs-164 | OGH 9ObA140/99z vom 29.09.1999 | OGH | 1999-09 | rj_jjt-19990929-ogh0002-009oba00140-99z0000-000.md |
|
||||
| rj-rjs-165 | OGH 9ObA213/99k vom 17.11.1999 | OGH | 1999-11 | rj_jjt-19991117-ogh0002-009oba00213-99k0000-000.md |
|
||||
| rj-rjs-166 | OGH 9ObA240/99f vom 01.12.1999 | OGH | 1999-12 | rj_jjt-19991201-ogh0002-009oba00240-99f0000-000.md |
|
||||
| rj-rjs-167 | OGH 6Ob304/99w vom 20.01.2000 | OGH | 2000-01 | rj_jjt-20000120-ogh0002-0060ob00304-99w0000-000.md |
|
||||
| rj-rjs-168 | OGH 9ObA329/99v vom 26.01.2000 | OGH | 2000-01 | rj_jjt-20000126-ogh0002-009oba00329-99v0000-000.md |
|
||||
| rj-rjs-169 | OGH 8ObA12/00y vom 24.02.2000 | OGH | 2000-02 | rj_jjt-20000224-ogh0002-008oba00012-00y0000-000.md |
|
||||
| rj-rjs-170 | OGH 9ObA292/99b vom 05.04.2000 | OGH | 2000-04 | rj_jjt-20000405-ogh0002-009oba00292-99b0000-000.md |
|
||||
| rj-rjs-171 | OGH 8ObS86/00f vom 13.04.2000 | OGH | 2000-04 | rj_jjt-20000413-ogh0002-008obs00086-00f0000-000.md |
|
||||
| rj-rjs-172 | OGH 9ObA198/00h vom 04.10.2000 | OGH | 2000-10 | rj_jjt-20001004-ogh0002-009oba00198-00h0000-000.md |
|
||||
| rj-rjs-173 | OGH 8ObS204/00h vom 09.11.2000 | OGH | 2000-11 | rj_jjt-20001109-ogh0002-008obs00204-00h0000-000.md |
|
||||
| rj-rjs-174 | OGH 9ObA319/00b vom 10.01.2001 | OGH | 2001-01 | rj_jjt-20010110-ogh0002-009oba00319-00b0000-000.md |
|
||||
| rj-rjs-175 | OGH 9ObA332/00i vom 24.01.2001 | OGH | 2001-01 | rj_jjt-20010124-ogh0002-009oba00332-00i0000-000.md |
|
||||
| rj-rjs-176 | OGH 9ObA341/00p vom 14.03.2001 | OGH | 2001-03 | rj_jjt-20010314-ogh0002-009oba00341-00p0000-000.md |
|
||||
| rj-rjs-177 | OGH 9ObA144/01v vom 07.06.2001 | OGH | 2001-06 | rj_jjt-20010607-ogh0002-009oba00144-01v0000-000.md |
|
||||
| rj-rjs-178 | OGH 9ObA155/01m vom 05.09.2001 | OGH | 2001-09 | rj_jjt-20010905-ogh0002-009oba00155-01m0000-000.md |
|
||||
| rj-rjs-179 | OGH 8ObA215/01b vom 28.09.2001 | OGH | 2001-09 | rj_jjt-20010928-ogh0002-008oba00215-01b0000-000.md |
|
||||
| rj-rjs-180 | OGH 9ObA226/01b vom 28.11.2001 | OGH | 2001-11 | rj_jjt-20011128-ogh0002-009oba00226-01b0000-000.md |
|
||||
| rj-rjs-181 | OGH 9ObA280/01v vom 23.01.2002 | OGH | 2002-01 | rj_jjt-20020123-ogh0002-009oba00280-01v0000-000.md |
|
||||
| rj-rjs-182 | OGH 8ObA100/02t vom 16.05.2002 | OGH | 2002-05 | rj_jjt-20020516-ogh0002-008oba00100-02t0000-000.md |
|
||||
| rj-rjs-183 | OGH 9ObA120/02s vom 22.05.2002 | OGH | 2002-05 | rj_jjt-20020522-ogh0002-009oba00120-02s0000-000.md |
|
||||
| rj-rjs-184 | OGH 9ObA97/02h vom 05.06.2002 | OGH | 2002-06 | rj_jjt-20020605-ogh0002-009oba00097-02h0000-000.md |
|
||||
| rj-rjs-185 | OGH 9ObA115/02f vom 10.07.2002 | OGH | 2002-07 | rj_jjt-20020710-ogh0002-009oba00115-02f0000-000.md |
|
||||
| rj-rjs-186 | OGH 9ObA196/02t vom 04.09.2002 | OGH | 2002-09 | rj_jjt-20020904-ogh0002-009oba00196-02t0000-000.md |
|
||||
| rj-rjs-187 | OGH 8ObA150/02w vom 07.11.2002 | OGH | 2002-11 | rj_jjt-20021107-ogh0002-008oba00150-02w0000-000.md |
|
||||
| rj-rjs-188 | OGH 9ObA169/02x vom 13.11.2002 | OGH | 2002-11 | rj_jjt-20021113-ogh0002-009oba00169-02x0000-000.md |
|
||||
| rj-rjs-189 | OGH 9ObA233/02h vom 13.11.2002 | OGH | 2002-11 | rj_jjt-20021113-ogh0002-009oba00233-02h0000-000.md |
|
||||
| rj-rjs-190 | OGH 8ObA202/02t vom 28.11.2002 | OGH | 2002-11 | rj_jjt-20021128-ogh0002-008oba00202-02t0000-000.md |
|
||||
| rj-rjs-191 | OGH 9ObA230/02t vom 04.12.2002 | OGH | 2002-12 | rj_jjt-20021204-ogh0002-009oba00230-02t0000-000.md |
|
||||
| rj-rjs-192 | OGH 8ObA13/03z vom 20.03.2003 | OGH | 2003-03 | rj_jjt-20030320-ogh0002-008oba00013-03z0000-000.md |
|
||||
| rj-rjs-193 | OGH 8ObA21/03a vom 20.03.2003 | OGH | 2003-03 | rj_jjt-20030320-ogh0002-008oba00021-03a0000-000.md |
|
||||
| rj-rjs-194 | OGH 8ObA95/03h vom 16.10.2003 | OGH | 2003-10 | rj_jjt-20031016-ogh0002-008oba00095-03h0000-000.md |
|
||||
| rj-rjs-195 | OGH 9ObA119/03w vom 05.11.2003 | OGH | 2003-11 | rj_jjt-20031105-ogh0002-009oba00119-03w0000-000.md |
|
||||
| rj-rjs-196 | OGH 8ObA86/03k vom 13.11.2003 | OGH | 2003-11 | rj_jjt-20031113-ogh0002-008oba00086-03k0000-000.md |
|
||||
| rj-rjs-197 | OGH 8ObA44/03h vom 25.11.2003 | OGH | 2003-11 | rj_jjt-20031125-ogh0002-008oba00044-03h0000-000.md |
|
||||
| rj-rjs-198 | OGH 9ObA151/03a vom 21.01.2004 | OGH | 2004-01 | rj_jjt-20040121-ogh0002-009oba00151-03a0000-000.md |
|
||||
| rj-rjs-199 | OGH 9ObA143/03z vom 17.03.2004 | OGH | 2004-03 | rj_jjt-20040317-ogh0002-009oba00143-03z0000-000.md |
|
||||
| rj-rjs-200 | OGH 9ObA38/04k vom 21.04.2004 | OGH | 2004-04 | rj_jjt-20040421-ogh0002-009oba00038-04k0000-000.md |
|
||||
| rj-rjs-201 | OGH 9ObA52/04v vom 05.05.2004 | OGH | 2004-05 | rj_jjt-20040505-ogh0002-009oba00052-04v0000-000.md |
|
||||
| rj-rjs-202 | OGH 8ObA20/04f vom 24.09.2004 | OGH | 2004-09 | rj_jjt-20040924-ogh0002-008oba00020-04f0000-000.md |
|
||||
| rj-rjs-203 | OGH 8ObA20/04f vom 17.02.2005 | OGH | 2005-02 | rj_jjt-20050217-ogh0002-008oba00020-04f0000-000.md |
|
||||
| rj-rjs-204 | OGH 9ObA96/05s vom 29.06.2005 | OGH | 2005-06 | rj_jjt-20050629-ogh0002-009oba00096-05s0000-000.md |
|
||||
| rj-rjs-205 | OGH 9ObA108/05f vom 31.08.2005 | OGH | 2005-08 | rj_jjt-20050831-ogh0002-009oba00108-05f0000-000.md |
|
||||
| rj-rjs-206 | OGH 8ObA51/05s vom 08.09.2005 | OGH | 2005-09 | rj_jjt-20050908-ogh0002-008oba00051-05s0000-000.md |
|
||||
| rj-rjs-207 | OGH 9ObA42/05z vom 22.02.2006 | OGH | 2006-02 | rj_jjt-20060222-ogh0002-009oba00042-05z0000-000.md |
|
||||
| rj-rjs-208 | OGH 8ObA60/06s vom 13.07.2006 | OGH | 2006-07 | rj_jjt-20060713-ogh0002-008oba00060-06s0000-000.md |
|
||||
| rj-rjs-209 | OGH 9ObA110/06a vom 15.11.2006 | OGH | 2006-11 | rj_jjt-20061115-ogh0002-009oba00110-06a0000-000.md |
|
||||
| rj-rjs-210 | OGH 9ObA20/07t vom 02.03.2007 | OGH | 2007-03 | rj_jjt-20070302-ogh0002-009oba00020-07t0000-000.md |
|
||||
| rj-rjs-211 | OGH 9ObA165/07s vom 28.11.2007 | OGH | 2007-11 | rj_jjt-20071128-ogh0002-009oba00165-07s0000-000.md |
|
||||
| rj-rjs-212 | OGH 9ObA118/07d vom 19.12.2007 | OGH | 2007-12 | rj_jjt-20071219-ogh0002-009oba00118-07d0000-000.md |
|
||||
| rj-rjs-213 | OGH 8ObA39/08f vom 16.06.2008 | OGH | 2008-06 | rj_jjt-20080616-ogh0002-008oba00039-08f0000-000.md |
|
||||
| rj-rjs-214 | OGH 8ObA55/07g vom 10.07.2008 | OGH | 2008-07 | rj_jjt-20080710-ogh0002-008oba00055-07g0000-000.md |
|
||||
| rj-rjs-215 | OGH 8ObA48/08d vom 02.09.2008 | OGH | 2008-09 | rj_jjt-20080902-ogh0002-008oba00048-08d0000-000.md |
|
||||
| rj-rjs-216 | OGH 9ObA37/08v vom 08.10.2008 | OGH | 2008-10 | rj_jjt-20081008-ogh0002-009oba00037-08v0000-000.md |
|
||||
| rj-rjs-217 | OGH 8ObA50/08y vom 13.11.2008 | OGH | 2008-11 | rj_jjt-20081113-ogh0002-008oba00050-08y0000-000.md |
|
||||
| rj-rjs-218 | OGH 9ObA37/08v vom 17.12.2008 | OGH | 2008-12 | rj_jjt-20081217-ogh0002-009oba00037-08v0000-000.md |
|
||||
| rj-rjs-219 | OGH 9ObA87/08x vom 26.08.2009 | OGH | 2009-08 | rj_jjt-20090826-ogh0002-009oba00087-08x0000-000.md |
|
||||
| rj-rjs-220 | OGH 8ObA57/09d vom 23.03.2010 | OGH | 2010-03 | rj_jjt-20100323-ogh0002-008oba00057-09d0000-000.md |
|
||||
| rj-rjs-221 | OGH 9ObA113/10y vom 24.11.2010 | OGH | 2010-11 | rj_jjt-20101124-ogh0002-009oba00113-10y0000-000.md |
|
||||
| rj-rjs-222 | OGH 9ObA128/10d vom 28.02.2011 | OGH | 2011-02 | rj_jjt-20110228-ogh0002-009oba00128-10d0000-000.md |
|
||||
| rj-rjs-223 | OGH 8ObA49/10d vom 22.03.2011 | OGH | 2011-03 | rj_jjt-20110322-ogh0002-008oba00049-10d0000-000.md |
|
||||
| rj-rjs-224 | OGH 8ObA35/11x vom 25.05.2011 | OGH | 2011-05 | rj_jjt-20110525-ogh0002-008oba00035-11x0000-000.md |
|
||||
| rj-rjs-225 | OGH 8ObA13/11m vom 29.06.2011 | OGH | 2011-06 | rj_jjt-20110629-ogh0002-008oba00013-11m0000-000.md |
|
||||
| rj-rjs-226 | OGH 8ObA45/11t vom 29.06.2011 | OGH | 2011-06 | rj_jjt-20110629-ogh0002-008oba00045-11t0000-000.md |
|
||||
| rj-rjs-227 | OGH 9ObA75/11m vom 25.10.2011 | OGH | 2011-10 | rj_jjt-20111025-ogh0002-009oba00075-11m0000-000.md |
|
||||
| rj-rjs-228 | OGH 8ObA35/11x vom 20.12.2011 | OGH | 2011-12 | rj_jjt-20111220-ogh0002-008oba00035-11x0000-000.md |
|
||||
| rj-rjs-229 | OGH 9ObA118/11k vom 21.12.2011 | OGH | 2011-12 | rj_jjt-20111221-ogh0002-009oba00118-11k0000-000.md |
|
||||
| rj-rjs-230 | OGH 9ObA119/12h vom 22.10.2012 | OGH | 2012-10 | rj_jjt-20121022-ogh0002-009oba00119-12h0000-000.md |
|
||||
| rj-rjs-231 | OGH 9ObA16/12m vom 26.11.2012 | OGH | 2012-11 | rj_jjt-20121126-ogh0002-009oba00016-12m0000-000.md |
|
||||
| rj-rjs-232 | OGH 8ObA74/12h vom 19.12.2012 | OGH | 2012-12 | rj_jjt-20121219-ogh0002-008oba00074-12h0000-000.md |
|
||||
| rj-rjs-233 | OGH 9ObA25/13m vom 19.03.2013 | OGH | 2013-03 | rj_jjt-20130319-ogh0002-009oba00025-13m0000-000.md |
|
||||
| rj-rjs-234 | OGH 9ObA41/13i vom 24.04.2013 | OGH | 2013-04 | rj_jjt-20130424-ogh0002-009oba00041-13i0000-000.md |
|
||||
| rj-rjs-235 | OGH 9ObA53/13d vom 29.05.2013 | OGH | 2013-05 | rj_jjt-20130529-ogh0002-009oba00053-13d0000-000.md |
|
||||
| rj-rjs-236 | OGH 9ObA68/13k vom 25.06.2013 | OGH | 2013-06 | rj_jjt-20130625-ogh0002-009oba00068-13k0000-000.md |
|
||||
| rj-rjs-237 | OGH 9ObA2/14f vom 25.06.2014 | OGH | 2014-06 | rj_jjt-20140625-ogh0002-009oba00002-14f0000-000.md |
|
||||
| rj-rjs-238 | OGH 8ObA37/14w vom 26.06.2014 | OGH | 2014-06 | rj_jjt-20140626-ogh0002-008oba00037-14w0000-000.md |
|
||||
| rj-rjs-239 | OGH 5Ob113/14z vom 25.07.2014 | OGH | 2014-07 | rj_jjt-20140725-ogh0002-0050ob00113-14z0000-000.md |
|
||||
| rj-rjs-240 | OGH 9ObA3/15d vom 20.03.2015 | OGH | 2015-03 | rj_jjt-20150320-ogh0002-009oba00003-15d0000-000.md |
|
||||
| rj-rjs-241 | OGH 8ObA33/15h vom 28.04.2015 | OGH | 2015-04 | rj_jjt-20150428-ogh0002-008oba00033-15h0000-000.md |
|
||||
| rj-rjs-242 | OGH 9ObA116/15x vom 26.11.2015 | OGH | 2015-11 | rj_jjt-20151126-ogh0002-009oba00116-15x0000-000.md |
|
||||
| rj-rjs-243 | OGH 9ObA74/15w vom 27.01.2016 | OGH | 2016-01 | rj_jjt-20160127-ogh0002-009oba00074-15w0000-000.md |
|
||||
| rj-rjs-244 | OGH 4Ob37/16v vom 30.03.2016 | OGH | 2016-03 | rj_jjt-20160330-ogh0002-0040ob00037-16v0000-000.md |
|
||||
| rj-rjs-245 | OGH 9ObA40/16x vom 24.06.2016 | OGH | 2016-06 | rj_jjt-20160624-ogh0002-009oba00040-16x0000-000.md |
|
||||
| rj-rjs-246 | OGH 9Ob8/17t vom 28.02.2017 | OGH | 2017-02 | rj_jjt-20170228-ogh0002-0090ob00008-17t0000-000.md |
|
||||
| rj-rjs-247 | OGH 9ObA150/17z vom 27.02.2018 | OGH | 2018-02 | rj_jjt-20180227-ogh0002-009oba00150-17z0000-000.md |
|
||||
| rj-rjs-248 | OGH 8ObA28/18b vom 25.06.2018 | OGH | 2018-06 | rj_jjt-20180625-ogh0002-008oba00028-18b0000-000.md |
|
||||
| rj-rjs-249 | OGH 9ObA44/18p vom 28.06.2018 | OGH | 2018-06 | rj_jjt-20180628-ogh0002-009oba00044-18p0000-000.md |
|
||||
| rj-rjs-250 | OGH 9ObA50/18w vom 28.06.2018 | OGH | 2018-06 | rj_jjt-20180628-ogh0002-009oba00050-18w0000-000.md |
|
||||
| rj-rjs-251 | OGH 9ObA45/18k vom 30.08.2018 | OGH | 2018-08 | rj_jjt-20180830-ogh0002-009oba00045-18k0000-000.md |
|
||||
| rj-rjs-252 | OGH 8ObA51/18k vom 24.09.2018 | OGH | 2018-09 | rj_jjt-20180924-ogh0002-008oba00051-18k0000-000.md |
|
||||
| rj-rjs-253 | OGH 9ObA25/19w vom 15.05.2019 | OGH | 2019-05 | rj_jjt-20190515-ogh0002-009oba00025-19w0000-000.md |
|
||||
| rj-rjs-254 | OGH 9ObA29/19h vom 15.05.2019 | OGH | 2019-05 | rj_jjt-20190515-ogh0002-009oba00029-19h0000-000.md |
|
||||
| rj-rjs-255 | OGH 8ObA22/19x vom 27.06.2019 | OGH | 2019-06 | rj_jjt-20190627-ogh0002-008oba00022-19x0000-000.md |
|
||||
| rj-rjs-256 | OGH 9ObA92/19y vom 30.10.2019 | OGH | 2019-10 | rj_jjt-20191030-ogh0002-009oba00092-19y0000-000.md |
|
||||
| rj-rjs-257 | OGH 8ObA49/19t vom 18.11.2019 | OGH | 2019-11 | rj_jjt-20191118-ogh0002-008oba00049-19t0000-000.md |
|
||||
| rj-rjs-258 | OGH 8ObA64/19y vom 24.01.2020 | OGH | 2020-01 | rj_jjt-20200124-ogh0002-008oba00064-19y0000-000.md |
|
||||
| rj-rjs-259 | OGH 9ObA24/20z vom 29.04.2020 | OGH | 2020-04 | rj_jjt-20200429-ogh0002-009oba00024-20z0000-000.md |
|
||||
| rj-rjs-260 | OGH 8ObA18/20k vom 27.05.2020 | OGH | 2020-05 | rj_jjt-20200527-ogh0002-008oba00018-20k0000-000.md |
|
||||
| rj-rjs-261 | OGH 9ObA31/20d vom 25.11.2020 | OGH | 2020-11 | rj_jjt-20201125-ogh0002-009oba00031-20d0000-000.md |
|
||||
| rj-rjs-262 | OGH 9ObA9/21w vom 29.04.2021 | OGH | 2021-04 | rj_jjt-20210429-ogh0002-009oba00009-21w0000-000.md |
|
||||
| rj-rjs-263 | OGH 9ObA96/21i vom 17.02.2022 | OGH | 2022-02 | rj_jjt-20220217-ogh0002-009oba00096-21i0000-000.md |
|
||||
| rj-rjs-264 | OGH 8ObA15/22x vom 22.02.2022 | OGH | 2022-02 | rj_jjt-20220222-ogh0002-008oba00015-22x0000-000.md |
|
||||
| rj-rjs-265 | OGH 9ObA10/22v vom 24.03.2022 | OGH | 2022-03 | rj_jjt-20220324-ogh0002-009oba00010-22v0000-000.md |
|
||||
| rj-rjs-266 | OGH 8ObA26/22i vom 25.05.2022 | OGH | 2022-05 | rj_jjt-20220525-ogh0002-008oba00026-22i0000-000.md |
|
||||
| rj-rjs-267 | OGH 8ObS7/22w vom 29.06.2022 | OGH | 2022-06 | rj_jjt-20220629-ogh0002-008obs00007-22w0000-000.md |
|
||||
| rj-rjs-268 | OGH 8ObA38/22d vom 30.08.2022 | OGH | 2022-08 | rj_jjt-20220830-ogh0002-008oba00038-22d0000-000.md |
|
||||
| rj-rjs-269 | OGH 8ObA82/21y vom 30.08.2022 | OGH | 2022-08 | rj_jjt-20220830-ogh0002-008oba00082-21y0000-000.md |
|
||||
| rj-rjs-270 | OGH 9ObA48/22g vom 31.08.2022 | OGH | 2022-08 | rj_jjt-20220831-ogh0002-009oba00048-22g0000-000.md |
|
||||
| rj-rjs-271 | OGH 1Ob130/22g vom 14.09.2022 | OGH | 2022-09 | rj_jjt-20220914-ogh0002-0010ob00130-22g0000-000.md |
|
||||
| rj-rjs-272 | OGH 9ObA105/22i vom 20.10.2022 | OGH | 2022-10 | rj_jjt-20221020-ogh0002-009oba00105-22i0000-000.md |
|
||||
| rj-rjs-273 | OGH 8ObA84/22v vom 16.12.2022 | OGH | 2022-12 | rj_jjt-20221216-ogh0002-008oba00084-22v0000-000.md |
|
||||
| rj-rjs-274 | OGH 8ObA36/23m vom 27.06.2023 | OGH | 2023-06 | rj_jjt-20230627-ogh0002-008oba00036-23m0000-000.md |
|
||||
| rj-rjs-275 | OLG Innsbruck 13Ra21/23w vom 27.07.2023 | OLG Innsbruck | 2023-07 | rj_jjt-20230727-olg0819-0130ra00021-23w0000-001.md |
|
||||
| rj-rjs-276 | OGH 9ObA67/23b vom 27.09.2023 | OGH | 2023-09 | rj_jjt-20230927-ogh0002-009oba00067-23b0000-000.md |
|
||||
| rj-rjs-277 | OGH 8ObA70/23m vom 22.03.2024 | OGH | 2024-03 | rj_jjt-20240322-ogh0002-008oba00070-23m0000-000.md |
|
||||
| rj-rjs-278 | OGH 8ObA54/24k vom 05.12.2024 | OGH | 2024-12 | rj_jjt-20241205-ogh0002-008oba00054-24k0000-000.md |
|
||||
| rj-rjs-279 | OLG Wien 10Ra65/24p vom 22.01.2025 | OLG Wien | 2025-01 | rj_jjt-20250122-olg0009-0100ra00065-24p0000-000.md |
|
||||
| rj-rjs-280 | OLG Wien 8Ra98/24a vom 29.01.2025 | OLG Wien | 2025-01 | rj_jjt-20250129-olg0009-0080ra00098-24a0000-000.md |
|
||||
| rj-rjs-281 | OLG Graz 6Ra59/24d vom 13.02.2025 | OLG Graz | 2025-02 | rj_jjt-20250213-olg0639-0060ra00059-24d0000-000.md |
|
||||
| rj-rjs-282 | OLG Wien 8Ra4/25d vom 26.02.2025 | OLG Wien | 2025-02 | rj_jjt-20250226-olg0009-0080ra00004-25d0000-001.md |
|
||||
| rj-rjs-283 | OLG Linz 12Ra6/25a vom 17.03.2025 | OLG Linz | 2025-03 | rj_jjt-20250317-olg0459-0120ra00006-25a0000-000.md |
|
||||
| rj-rjs-284 | OLG Wien 8Ra106/24b vom 09.07.2025 | OLG Wien | 2025-07 | rj_jjt-20250709-olg0009-0080ra00106-24b0000-000.md |
|
||||
| rj-rjs-285 | OGH 9ObA83/24g vom 26.08.2025 | OGH | 2025-08 | rj_jjt-20250826-ogh0002-009oba00083-24g0000-000.md |
|
||||
| rj-rjs-286 | OLG Wien 10Ra27/25a vom 24.09.2025 | OLG Wien | 2025-09 | rj_jjt-20250924-olg0009-0100ra00027-25a0000-000.md |
|
||||
| rj-rjs-287 | OLG Graz 7Ra41/25s vom 24.09.2025 | OLG Graz | 2025-09 | rj_jjt-20250924-olg0639-0070ra00041-25s0000-000.md |
|
||||
| rj-rjs-288 | Die Mitwirkung an Manipulationen an den Tachographenblättern eines Firmen-LKW stellt, auch wenn… | Verwaltungsgerichtshof | 1984-01 | rj_jwr-1982010008-19840130x01.md |
|
||||
| rj-rjs-289 | Dem Arbeitsrecht ist eine allgemeine Verpflichtung des Arbeitnehmers fremd, für Verfehlungen eines… | Verwaltungsgerichtshof | 1984-01 | rj_jwr-1982010008-19840130x02.md |
|
||||
| rj-rjs-290 | Verwaltungsgerichtshof 2004/08/0101 vom 24.01.2006 | Verwaltungsgerichtshof | 2006-01 | rj_jwt-2004080101-20060124x00.md |
|
||||
| rj-rjs-291 | Verwaltungsgerichtshof 2004/08/0113 vom 16.11.2005 | Verwaltungsgerichtshof | 2005-11 | rj_jwt-2004080113-20051116x00.md |
|
||||
| rj-rjs-292 | Verwaltungsgerichtshof 2007/08/0296 vom 02.04.2008 | Verwaltungsgerichtshof | 2008-04 | rj_jwt-2007080296-20080402x00.md |
|
||||
| rj-rjs-293 | Verwaltungsgerichtshof 2012/08/0045 vom 28.03.2012 | Verwaltungsgerichtshof | 2012-03 | rj_jwt-2012080045-20120328x00.md |
|
||||
| rj-rjs-294 | Verwaltungsgerichtshof 2012/08/0081 vom 24.04.2014 | Verwaltungsgerichtshof | 2014-04 | rj_jwt-2012080081-20140424x00.md |
|
||||
| rj-rjs-295 | Verwaltungsgerichtshof Ro 2015/08/0020 vom 01.10.2015 | Verwaltungsgerichtshof | 2015-10 | rj_jwt-2015080020-20151001j00.md |
|
||||
| rj-rjs-296 | Verwaltungsgerichtshof Fr 2016/08/0011 vom 14.11.2016 | Verwaltungsgerichtshof | 2016-11 | rj_jwt-2016080011-20161114f00.md |
|
||||
| rj-rjs-297 | Verwaltungsgerichtshof Ra 2016/08/0011 vom 24.11.2016 | Verwaltungsgerichtshof | 2016-11 | rj_jwt-2016080011-20161124l00.md |
|
||||
| rj-rjs-298 | Verwaltungsgerichtshof Ra 2016/08/0132 vom 14.07.2017 | Verwaltungsgerichtshof | 2017-07 | rj_jwt-2016080132-20170714l00.md |
|
||||
| rj-rjs-299 | Verwaltungsgerichtshof Ra 2016/11/0053 vom 04.05.2016 | Verwaltungsgerichtshof | 2016-05 | rj_jwt-2016110053-20160504l00.md |
|
||||
| rj-rjs-300 | Verwaltungsgerichtshof Ra 2016/11/0164 vom 28.02.2017 | Verwaltungsgerichtshof | 2017-02 | rj_jwt-2016110164-20170228l00.md |
|
||||
| rj-rjs-301 | Verwaltungsgerichtshof Ra 2017/11/0003 vom 30.01.2017 | Verwaltungsgerichtshof | 2017-01 | rj_jwt-2017110003-20170130l00.md |
|
||||
| rj-rjs-302 | Verwaltungsgerichtshof Ra 2017/11/0003 vom 05.04.2017 | Verwaltungsgerichtshof | 2017-04 | rj_jwt-2017110003-20170405l00.md |
|
||||
| rj-rjs-303 | Verwaltungsgerichtshof Ro 2017/11/0003 vom 04.04.2019 | Verwaltungsgerichtshof | 2019-04 | rj_jwt-2017110003-20190404j00.md |
|
||||
| rj-rjs-304 | Verwaltungsgerichtshof Ra 2017/11/0016 vom 20.09.2017 | Verwaltungsgerichtshof | 2017-09 | rj_jwt-2017110016-20170920l00.md |
|
||||
| rj-rjs-305 | Verwaltungsgerichtshof Ro 2017/11/0016 vom 26.04.2018 | Verwaltungsgerichtshof | 2018-04 | rj_jwt-2017110016-20180426j00.md |
|
||||
| rj-rjs-306 | Verwaltungsgerichtshof Ra 2017/11/0152 vom 11.01.2018 | Verwaltungsgerichtshof | 2018-01 | rj_jwt-2017110152-20180111l00.md |
|
||||
| rj-rjs-307 | Verwaltungsgerichtshof Ra 2017/11/0219 vom 11.04.2018 | Verwaltungsgerichtshof | 2018-04 | rj_jwt-2017110219-20180411l00.md |
|
||||
| rj-rjs-308 | Verwaltungsgerichtshof Ra 2017/11/0224 vom 21.08.2017 | Verwaltungsgerichtshof | 2017-08 | rj_jwt-2017110224-20170821l00.md |
|
||||
| rj-rjs-309 | Verwaltungsgerichtshof Ra 2017/11/0224 vom 11.06.2018 | Verwaltungsgerichtshof | 2018-06 | rj_jwt-2017110224-20180611l00.md |
|
||||
| rj-rjs-310 | Verwaltungsgerichtshof Ra 2017/11/0233 vom 20.09.2018 | Verwaltungsgerichtshof | 2018-09 | rj_jwt-2017110233-20180920l00.md |
|
||||
| rj-rjs-311 | Verwaltungsgerichtshof Ra 2017/11/0276 vom 13.12.2018 | Verwaltungsgerichtshof | 2018-12 | rj_jwt-2017110276-20181213l00.md |
|
||||
| rj-rjs-312 | Verwaltungsgerichtshof Ra 2017/11/0301 vom 13.12.2018 | Verwaltungsgerichtshof | 2018-12 | rj_jwt-2017110301-20181213l00.md |
|
||||
| rj-rjs-313 | Verwaltungsgerichtshof Ra 2018/08/0028 vom 29.01.2020 | Verwaltungsgerichtshof | 2020-01 | rj_jwt-2018080028-20200129l00.md |
|
||||
| rj-rjs-314 | Verwaltungsgerichtshof Ra 2018/11/0118 vom 20.09.2018 | Verwaltungsgerichtshof | 2018-09 | rj_jwt-2018110118-20180920l00.md |
|
||||
| rj-rjs-315 | Verwaltungsgerichtshof Ra 2018/11/0216 vom 23.01.2019 | Verwaltungsgerichtshof | 2019-01 | rj_jwt-2018110216-20190123l00.md |
|
||||
| rj-rjs-316 | Verwaltungsgerichtshof Ra 2018/11/0248 vom 18.01.2019 | Verwaltungsgerichtshof | 2019-01 | rj_jwt-2018110248-20190118l00.md |
|
||||
| rj-rjs-317 | Verwaltungsgerichtshof Ra 2019/08/0003 vom 16.01.2019 | Verwaltungsgerichtshof | 2019-01 | rj_jwt-2019080003-20190116l00.md |
|
||||
| rj-rjs-318 | Verwaltungsgerichtshof Fr 2019/08/0003 vom 03.04.2019 | Verwaltungsgerichtshof | 2019-04 | rj_jwt-2019080003-20190403f00.md |
|
||||
| rj-rjs-319 | Verwaltungsgerichtshof Ro 2019/08/0003 vom 03.04.2019 | Verwaltungsgerichtshof | 2019-04 | rj_jwt-2019080003-20190403j00.md |
|
||||
| rj-rjs-320 | Verwaltungsgerichtshof So 2019/08/0003 vom 03.02.2020 | Verwaltungsgerichtshof | 2020-02 | rj_jwt-2019080003-20200203x00.md |
|
||||
| rj-rjs-321 | Verwaltungsgerichtshof Fr 2022/08/0006 vom 18.08.2022 | Verwaltungsgerichtshof | 2022-08 | rj_jwt-2022080006-20220818f00.md |
|
||||
| rj-rjs-322 | Verwaltungsgerichtshof Ro 2022/08/0006 vom 13.06.2023 | Verwaltungsgerichtshof | 2023-06 | rj_jwt-2022080006-20230613j00.md |
|
||||
| rj-rjs-323 | Verwaltungsgerichtshof Ra 2024/08/0034 vom 19.11.2024 | Verwaltungsgerichtshof | 2024-11 | rj_jwt-2024080034-20241119l00.md |
|
||||
| rj-rjs-324 | Verwaltungsgerichtshof Ra 2024/08/0138 vom 20.12.2024 | Verwaltungsgerichtshof | 2024-12 | rj_jwt-2024080138-20241220l00.md |
|
||||
| rj-rjs-325 | Verwaltungsgerichtshof Ra 2025/08/0048 vom 03.07.2026 | Verwaltungsgerichtshof | 2026-07 | rj_jwt-2025080048-20260703l00.md |
|
||||
| rj-rjs-326 | Allgemeines bürgerliches Gesetzbuch – § 1431 | EuGH | 2026-09 | rj_abgb-1431.md |
|
||||
| rj-rjs-327 | Allgemeines bürgerliches Gesetzbuch – § 1435 | EuGH | 2026-09 | rj_abgb-1435.md |
|
||||
| rj-rjs-328 | Allgemeines bürgerliches Gesetzbuch (ABGB) – § 1437 | ABGB | 2017-11 | rj_abgb-1437.md |
|
||||
| rj-rjs-329 | Arbeitsvertragsrechts-Anpassungsgesetz – § 7d | EuGH | 2026-09 | rj_avrag-7d.md |
|
||||
| rj-rjs-330 | Arbeitsvertragsrechts-Anpassungsgesetz – § 7f | EuGH | 2026-09 | rj_avrag-7f.md |
|
||||
| rj-rjs-331 | Arbeitsvertragsrechts-Anpassungsgesetz – § 7g | EuGH | 2026-09 | rj_avrag-7g.md |
|
||||
| rj-rjs-332 | Arbeitsvertragsrechts-Anpassungsgesetz – § 7i | EuGH | 2026-09 | rj_avrag-7i.md |
|
||||
| rj-rjs-333 | Angestelltengesetz (AngG) – Art. 1 § 15 | AngG | 2023-07 | rj_angg-15.md |
|
||||
| rj-rjs-334 | Angestelltengesetz (AngG) – Art. 1 § 26 | AngG | 2023-07 | rj_angg-26.md |
|
||||
| rj-rjs-335 | Angestelltengesetz (AngG) – Art. 1 § 27 | AngG | 2023-08 | rj_angg-27.md |
|
||||
| rj-rjs-336 | Arbeitsverfassungsgesetz (ArbVG) – § 101 | ArbVG | 2017-03 | rj_arbvg-101.md |
|
||||
| rj-rjs-337 | Arbeitsverfassungsgesetz (ArbVG) – § 105 | ArbVG | 2022-10 | rj_arbvg-105.md |
|
||||
| rj-rjs-338 | Gewerbeordnung 1859 - Gewerbliches Hilfspersonal – § 82 | EuGH | 2024-05 | rj_gewo1859-82.md |
|
||||
| rj-rjs-339 | Gewerbeordnung 1859 - Gewerbliches Hilfspersonal – § 82a | EuGH | 2026-09 | rj_gewo1859-82a.md |
|
||||
| rj-rjs-340 | Gewerbeordnung 1994 (GewO 1994) – § 130 | GewO 1994 | 2024-11 | rj_gewo1994-130.md |
|
||||
| rj-rjs-341 | Lohn- und Sozialdumping-Bekämpfungsgesetz (LSD-BG) – § 14 | LSD-BG | 2021-09 | rj_lsd-bg-14.md |
|
||||
| rj-rjs-342 | Lohn- und Sozialdumping-Bekämpfungsgesetz (LSD-BG) – § 21 | LSD-BG | 2024-04 | rj_lsd-bg-21.md |
|
||||
| rj-rjs-343 | Lohn- und Sozialdumping-Bekämpfungsgesetz (LSD-BG) – § 22 | LSD-BG | 2022-07 | rj_lsd-bg-22.md |
|
||||
| rj-rjs-344 | Lohn- und Sozialdumping-Bekämpfungsgesetz (LSD-BG) – § 28 | LSD-BG | 2026-07 | rj_lsd-bg-28.md |
|
||||
| rj-rjs-345 | Strafgesetzbuch (StGB) – § 115 | StGB | 2022-10 | rj_stgb-115.md |
|
||||
| rj-rjs-346 | Strafgesetzbuch (StGB) – § 153 | StGB | 2022-09 | rj_stgb-153.md |
|
||||
| rj-rjs-347 | Strafgesetzbuch (StGB) – § 83 | StGB | 2019-10 | rj_stgb-83.md |
|
||||
| rj-rjs-348 | Urlaubsgesetz – § 6 | EuGH | 2026-09 | rj_urlg-6.md |
|
||||
|
||||
|
||||
+45
-14
@@ -1,5 +1,5 @@
|
||||
# Wissensbasis Personalverrechnung (Lexis360-Exporte, WIKU Personal,
|
||||
WKO-Kollektivverträge, RIS-Gesetze)
|
||||
WKO-Kollektivverträge, RIS-Gesetze, Rechtsprechung)
|
||||
|
||||
Kuratierte Wissensbasis aus vier Quellcorpora — den **LexisNexis-Briefings**
|
||||
des Werks *Lexis Briefings Personalrecht* (Export aus Lexis 360), den
|
||||
@@ -8,9 +8,12 @@ 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
|
||||
Paragraphen je Gesetz) sowie **Rechtsprechung** (OGH-, VwGH- und VfGH-
|
||||
Entscheidungen und Rechtssätze aus RIS-OGD sowie fünf als nicht amtlich
|
||||
markierte EuGH-Textwiedergaben). 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:
|
||||
`kv-*` (WKO-KV), `ris-*` (RIS) und `rj-*` (Rechtsprechung/Normentexte)
|
||||
liegen auf derselben Cluster-Map. Zweck:
|
||||
|
||||
1. **Entwicklungsreferenz** neben den Rechtsquellen-Übersichten
|
||||
(`RECHTSQUELLEN-*.md` im Schwesterprojekt) für die Personalverrechnungs-
|
||||
@@ -26,22 +29,34 @@ unterscheidet die Quellen, ID-Räume `lb-*` (Lexis), `wk-*` (WIKU),
|
||||
| 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) |
|
||||
| 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) |
|
||||
| Rohquellen kv/ris/rj | `.firecrawl/kv-portal/wko-kv/docs/*.html` · `.ris/*.md` · `.rechtsprechung/{originale,gesetze}/*.md` | **nein** (gitignored) | WKO-KV-Seiten, RIS-Gesetzes-Auschnitte sowie Rechtsprechung/Normentexte |
|
||||
| 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**) · `dokumente/rj_<slug>.md` (Rechtsprechung, **generiert**) | **ja** | Kuratierung in eigenen Worten (lb/wk) bzw. quellentreue Konvertierung (kv/ris/rj, 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) |
|
||||
| Kataloge kv/ris/rj | `tools/catalogs/kv_catalog.json` · `ris_catalog.json` · `rj_catalog.json` | **ja** | eingefrorene ID-Zuweisungen (nur Metadaten, keine Quelltexte) |
|
||||
|
||||
Volltexte der lizenzierten Quellen (Lexis/WIKU) sind Lizenzinhalt und
|
||||
bleiben wie `.firecrawl/` und `.ris/` lokal + unversioniert. Nur die
|
||||
bleiben wie `.firecrawl/` und `.firecrawl/ris/gesetze/` 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
|
||||
generieren. Die WKO-Seiten selbst und die `.firecrawl/ris/gesetze/`-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-
|
||||
und die WKO-/RIS-URL im Body.
|
||||
|
||||
**Rechtsprechung (Batch rj 1, 2026-09-15):** Die Lieferung unter
|
||||
`.rechtsprechung/` dokumentiert für OGH/VwGH/VfGH überwiegend RIS-OGD-
|
||||
Provenance. Ihre Layer-2-Dateien `rj_*.md` werden deshalb quellentreu aus den
|
||||
lokalen Markdown-Dateien generiert und behalten Gericht, Datum, Geschäftszahl,
|
||||
Normen und Quellenpfad. Rechtssätze, Volltexte, zitierte Normauszüge und EuGH-
|
||||
Fälle sind jeweils im `chapter`/`work` unterscheidbar. Die fünf EuGH-Dateien
|
||||
sind ausdrücklich als **„Textwiedergabe lexetius, nicht amtlich“** markiert
|
||||
und nennen zusätzlich die amtliche EUR-Lex-URL, soweit geliefert. Die
|
||||
Publikations- und Lizenzfreigabe der quellentreuen Rechtsprechungs-Volltexte
|
||||
ist vor einem Commit bewusst zu bestätigen; sie wird nicht aus der allgemeinen
|
||||
Ausnahme für amtliche Gesetzestexte abgeleitet. Die `overviews/` (1 820 Bundesland-Übersichts-
|
||||
seiten von WKO.at) werden derzeit **nicht** aufgenommen (Redundanz zu `docs/`).
|
||||
|
||||
## Frontmatter-Schema (Layer 2 — verbindlich)
|
||||
@@ -151,6 +166,7 @@ als ASCII-Slugs. Die Frontmatter ist **Single Source of Truth**;
|
||||
| `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 |
|
||||
| `rechtsprechung` | Rechtsprechung (OGH, VwGH, VfGH, EuGH) und zitierte Normen | `rjs` | rj-rjs-001 … 348 | 348 |
|
||||
|
||||
Weitere RIS-Gesetze liegen auf der bestehenden Cluster-Map (`ris-url-01`
|
||||
neben `lb-url-*`, `ris-asc-01` neben `lb-asc-*`, …; je Gesetz ein
|
||||
@@ -158,14 +174,16 @@ neben `lb-url-*`, `ris-asc-01` neben `lb-asc-*`, …; je Gesetz 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
|
||||
**1 622 Einträge in 77 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); WKO-KV: 614 Einträge im Cluster `kollektivvertraege` (Batch 1);
|
||||
RIS: 59 Gesetze, verteilt auf bestehende Cluster plus den neuen
|
||||
Rechtsgebiet-Clustern (Batch 1).
|
||||
Rechtsgebiet-Clustern (Batch 1); Rechtsprechung: 320 RIS-OGD-Entscheidungen/
|
||||
Rechtssätze + 5 nichtamtliche EuGH-Textwiedergaben + 23 zitierte
|
||||
RIS-Normauszüge (Batch 1, gemeinsamer Cluster `rechtsprechung`).
|
||||
|
||||
Frontmatter-`topic` = beschreibender ASCII-Slug, das ID-Präfix
|
||||
(`atz`, `leh`, `kvt`, …) nur im `id` selbst; die Registry
|
||||
@@ -177,7 +195,8 @@ 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/`).
|
||||
mit `ris_`-Präfix und Rechtsprechung mit `rj_`-Präfix (Kollisionsschutz im
|
||||
gemeinsamen `dokumente/`).
|
||||
|
||||
## Kurationskonventionen (verbindlich)
|
||||
|
||||
@@ -229,7 +248,7 @@ mit `ris_`-Präfix (Kollisionsschutz im gemeinsamen `dokumente/`).
|
||||
|
||||
**WKO-Kollektivverträge (kv):**
|
||||
|
||||
1. Neue Seiten nach `.firecrawl/wko-kv/docs/` (Crawl via Firecrawl;
|
||||
1. Neue Seiten nach `.firecrawl/kv-portal/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`
|
||||
@@ -237,13 +256,25 @@ mit `ris_`-Präfix (Kollisionsschutz im gemeinsamen `dokumente/`).
|
||||
|
||||
**RIS-Gesetze (ris):**
|
||||
|
||||
1. Neue Gesetze nach `.ris/` (Markdown; nur die im Lexis360-Bestand
|
||||
1. Neue Gesetze nach `.firecrawl/ris/gesetze/` (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`.
|
||||
|
||||
**Rechtsprechung (rj):**
|
||||
|
||||
1. Neue Markdown-Dateien nach `.rechtsprechung/originale/` (Entscheidungen,
|
||||
Rechtssätze, EuGH-Textwiedergaben) oder `.rechtsprechung/gesetze/`
|
||||
(zitierte Normauszüge) legen; XML-Originale nicht separat intaken.
|
||||
2. Provenance und Publikations-/Lizenzfreigabe der gelieferten Volltexte vor
|
||||
einer Versionierung prüfen; EuGH-Wiedergaben bleiben als nicht amtlich
|
||||
gekennzeichnet.
|
||||
3. `python3 tools/ingest_sources.py --source rj` — IDs aus
|
||||
`tools/catalogs/rj_catalog.json` bleiben eingefroren; lange Volltexte
|
||||
werden an Absatzgrenzen in H2-Chunks geteilt.
|
||||
|
||||
**Alle Quellen gemeinsam:**
|
||||
|
||||
3. `python3 tools/build_registry.py` — validiert das gesamte Layer-2
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2024-09
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/aenderung-anrechnung-vordienstzeiten-autobusbetriebe.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/aenderung-anrechnung-vordienstzeiten-autobusbetriebe.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "anderung"]
|
||||
cross_refs: []
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2025-01
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/aenderung-feiertagsentlohnung-kollektivvertrag-autobusbetriebe.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/aenderung-feiertagsentlohnung-kollektivvertrag-autobusbetriebe.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "anderung"]
|
||||
cross_refs: []
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-09
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/alle-kollektivvertr-ge-zusatzkollektivvertr-ge-lohn-und-ge.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/alle-kollektivvertr-ge-zusatzkollektivvertr-ge-lohn-und-ge.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "information", "stand-geschaetzt"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 1999-01
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/angestellte-konditoren-gewerbe-rahmenkollektivvertrag.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/angestellte-konditoren-gewerbe-rahmenkollektivvertrag.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "kollektivvertrag"]
|
||||
cross_refs: []
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2021-10
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/angleichung-der-kuendigungsfristen-baunebengewerbe-2021.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/angleichung-der-kuendigungsfristen-baunebengewerbe-2021.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "information", "jahr-2021"]
|
||||
cross_refs: []
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-05
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/anhang-kollektivvertrag-ambulatorien-physikalische-therapie-2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/anhang-kollektivvertrag-ambulatorien-physikalische-therapie-2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "anhang-anlage", "jahr-2026"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2020-06
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/anhang-kv-austrian-airlines-bordpersonal-2020.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/anhang-kv-austrian-airlines-bordpersonal-2020.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "anhang-anlage", "jahr-2020"]
|
||||
cross_refs: []
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-01
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/anlage-textaktualisierung-kv-werbung-marktkommunikation-2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/anlage-textaktualisierung-kv-werbung-marktkommunikation-2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "anhang-anlage", "jahr-2026", "stand-jahr"]
|
||||
cross_refs: []
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2021-01
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/berechnung-gehaltstabelle-immobilienverwalter-2021-2022.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/berechnung-gehaltstabelle-immobilienverwalter-2021-2022.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2021", "stand-jahr"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2023-01
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/berechnungsbeispiele-arbeitszeitverkuerzung-werbung.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/berechnungsbeispiele-arbeitszeitverkuerzung-werbung.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "berechnungsbeispiele", "stand-jahr"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-09
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/berechnungsbeispiele-kollektivvertrag-reisebueros.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/berechnungsbeispiele-kollektivvertrag-reisebueros.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "berechnungsbeispiele", "stand-geschaetzt"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-01
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/berechnungsbeispiele-kv-informationstechnologie-2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/berechnungsbeispiele-kv-informationstechnologie-2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "berechnungsbeispiele", "jahr-2026", "stand-jahr"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2023-04
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/brutto-netto-loehne-friseur-ab-01.04.2023.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/brutto-netto-loehne-friseur-ab-01.04.2023.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "sonstiges-kv-dokument", "jahr-2023"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2025-04
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/brutto-netto-loehne-friseur-ab-01.04.2025.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/brutto-netto-loehne-friseur-ab-01.04.2025.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "sonstiges-kv-dokument", "jahr-2025"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-04
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/brutto-netto-loehne-friseur-ab-01.04.2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/brutto-netto-loehne-friseur-ab-01.04.2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "sonstiges-kv-dokument", "jahr-2026"]
|
||||
cross_refs: []
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-01
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/collective-bargaining-agreement-petroleum-industry-2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/collective-bargaining-agreement-petroleum-industry-2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "sonstiges-kv-dokument", "jahr-2026", "stand-jahr"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2025-12
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/dienst-und-besoldungsordnung-privatbahnen-2025.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/dienst-und-besoldungsordnung-privatbahnen-2025.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "dienst--und-besoldungsordnung", "jahr-2025"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2025-03
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/dienstreisesaetze-propak-2025.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/dienstreisesaetze-propak-2025.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "sonstiges-kv-dokument", "jahr-2025"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-01
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/empfehlung-lohntafeln-arbeiter-handel-2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/empfehlung-lohntafeln-arbeiter-handel-2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "empfehlung", "jahr-2026"]
|
||||
cross_refs: []
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2024-02
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/erklaerung-kollektivvertragspartner-autobusbetriebe-2024.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/erklaerung-kollektivvertragspartner-autobusbetriebe-2024.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "erklarung", "jahr-2024"]
|
||||
cross_refs: []
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2024-01
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/erklaerungen-kollektivvertrag-filmschaffende-filmberufe-2024.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/erklaerungen-kollektivvertrag-filmschaffende-filmberufe-2024.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "erklarung", "jahr-2024", "stand-jahr"]
|
||||
cross_refs: []
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-09
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/erlaeuterung-zu-den-gagenpositionen-im-kv-fuer-filmberufe.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/erlaeuterung-zu-den-gagenpositionen-im-kv-fuer-filmberufe.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "erlauterungen", "stand-geschaetzt"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2021-08
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/erlaeuterungen-generalkollektivvertrag-corona-test.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/erlaeuterungen-generalkollektivvertrag-corona-test.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "generalkollektivvertrag"]
|
||||
cross_refs: []
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-09
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/erlaeuterungen-kollektivvertrag-werbung-marktkommunikation.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/erlaeuterungen-kollektivvertrag-werbung-marktkommunikation.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "erlauterungen", "stand-geschaetzt"]
|
||||
cross_refs: []
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2021-10
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/erlaeuterungen-lohnordnung-fusspfleger-kosmetiker-masseure.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/erlaeuterungen-lohnordnung-fusspfleger-kosmetiker-masseure.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "erlauterungen"]
|
||||
cross_refs: []
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2021-10
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/erlaeuterungen-zusatz-kv-arbeitskraefteueberlasser-2021.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/erlaeuterungen-zusatz-kv-arbeitskraefteueberlasser-2021.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "erlauterungen", "jahr-2021"]
|
||||
cross_refs: []
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-09
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/flexible-arbeitszeit-denkmal-fassaden-gebaeudereinigung.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/flexible-arbeitszeit-denkmal-fassaden-gebaeudereinigung.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "sonstiges-kv-dokument", "stand-geschaetzt"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2021-02
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/floristen-blumeneinzelhaendler-kv-arbeiter-2021.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/floristen-blumeneinzelhaendler-kv-arbeiter-2021.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "kollektivvertrag", "jahr-2021"]
|
||||
cross_refs: []
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-01
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/fragen-antworten-kollektivvertrag-informationstechnologie-2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/fragen-antworten-kollektivvertrag-informationstechnologie-2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "fragen-antworten", "jahr-2026", "stand-jahr"]
|
||||
cross_refs: []
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2025-03
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gaertner-landschaftsgaertner-kollektivvertrag-arbeiter-2025.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gaertner-landschaftsgaertner-kollektivvertrag-arbeiter-2025.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "kollektivvertrag", "jahr-2025"]
|
||||
cross_refs: []
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2024-01
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehalts-rahmenbeschluss-gastronomie-und-hotellerie-2024-2025.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehalts-rahmenbeschluss-gastronomie-und-hotellerie-2024-2025.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "sonstiges-kv-dokument", "jahr-2024", "stand-jahr"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2024-10
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-baecker-angestellte-2024.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-baecker-angestellte-2024.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2024"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2025-10
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-baecker-angestellte-2025.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-baecker-angestellte-2025.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2025"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-10
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-baecker-angestellte-2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-baecker-angestellte-2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2026"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-04
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-banken-und-bankiers-2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-banken-und-bankiers-2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2026"]
|
||||
cross_refs: []
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-05
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-baugewerbe-bauindustrie-angestellte-2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-baugewerbe-bauindustrie-angestellte-2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2026"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2025-07
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-bekleidungsindustrie-2025.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-bekleidungsindustrie-2025.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2025"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-07
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-bekleidungsindustrie-2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-bekleidungsindustrie-2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2026"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-07
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-bekleidungsindustrie-vorarlberg-2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-bekleidungsindustrie-vorarlberg-2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2026"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2025-11
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-bergwerke-stahl-angestellte-2025-2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-bergwerke-stahl-angestellte-2025-2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2025"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-05
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-chemische-industrie-2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-chemische-industrie-2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2026"]
|
||||
cross_refs: []
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2025-05
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-elektro-elektronikindustrie-angestellte-2025.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-elektro-elektronikindustrie-angestellte-2025.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2025"]
|
||||
cross_refs: []
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-05
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-elektro-elektronikindustrie-angestellte-2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-elektro-elektronikindustrie-angestellte-2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2026"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-04
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-fahrschulen-2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-fahrschulen-2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2026"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2025-01
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-film-musikwirtschaft-angestellte-2025.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-film-musikwirtschaft-angestellte-2025.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2025"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-01
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-film-musikwirtschaft-angestellte-2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-film-musikwirtschaft-angestellte-2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2026"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-07
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-fleischer-angestellte-2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-fleischer-angestellte-2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2026"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-01
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-gewerbe-handwerk-dienstleistung-2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-gewerbe-handwerk-dienstleistung-2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2026"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2025-11
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-gewerbliche-molkereien-kaesereien-2025.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-gewerbliche-molkereien-kaesereien-2025.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2025"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-06
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-glasindustrie-2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-glasindustrie-2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2026"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-01
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-gueterbefoerderung-kleintransporte-2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-gueterbefoerderung-kleintransporte-2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2026"]
|
||||
cross_refs: []
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-06
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-holzverarbeitende-industrie-angestellte-2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-holzverarbeitende-industrie-angestellte-2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2026"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2025-01
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-immobilienverwalter-2025.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-immobilienverwalter-2025.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2025"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-04
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-immobilienverwalter-2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-immobilienverwalter-2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2026"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-01
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-information-consulting-angestellte-2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-information-consulting-angestellte-2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2026"]
|
||||
cross_refs: []
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-04
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-kinobetriebe-steiermark-angestellte-2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-kinobetriebe-steiermark-angestellte-2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2026"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-04
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-kinobetriebe-wien-2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-kinobetriebe-wien-2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2026"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-01
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-konditoren-angestellte-2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-konditoren-angestellte-2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2026"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2025-05
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-kunststoffverarbeiter-2025.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-kunststoffverarbeiter-2025.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2025"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-05
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-kunststoffverarbeiter-2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-kunststoffverarbeiter-2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2026"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-04
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-landes-hypothekenbanken-2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-landes-hypothekenbanken-2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2026"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-01
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-ledererzeugende-industrie-2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-ledererzeugende-industrie-2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2026"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-06
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-lederwaren-kofferindustrie-2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-lederwaren-kofferindustrie-2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2026"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-01
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-metallgewerbe-angestellte-2026-27.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-metallgewerbe-angestellte-2026-27.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2026"]
|
||||
cross_refs: []
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2025-11
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-metalltechnische-industrie-angestellte-2025-2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-metalltechnische-industrie-angestellte-2025-2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2025"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2024-11
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-molkereien-kaesereien-2024.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-molkereien-kaesereien-2024.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2024"]
|
||||
cross_refs: []
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2025-08
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-mueller-muehlen-mischfuttererzeuger-2025.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-mueller-muehlen-mischfuttererzeuger-2025.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2025"]
|
||||
cross_refs: []
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-08
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-mueller-muehlen-mischfuttererzeuger-2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-mueller-muehlen-mischfuttererzeuger-2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2026"]
|
||||
cross_refs: []
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2025-05
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-musiker-konzertlokal-musik-tanzbetriebe-2025.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-musiker-konzertlokal-musik-tanzbetriebe-2025.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2025"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-01
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-nahrungs-und-genussmittelwerbe-2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-nahrungs-und-genussmittelwerbe-2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2026"]
|
||||
cross_refs: []
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2025-11
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-ne-metallindustrie-angestellte-2025-2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-ne-metallindustrie-angestellte-2025-2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2025"]
|
||||
cross_refs: []
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-03
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-papier-karton-verarbeitende-industrie-2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-papier-karton-verarbeitende-industrie-2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2026"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-05
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-papierindustrie-angestellte-2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-papierindustrie-angestellte-2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2026"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2022-01
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-pharmazeutischer-grosshandel-2022.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-pharmazeutischer-grosshandel-2022.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2022"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2025-01
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-privatfernsehsender-angestellte-2025.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-privatfernsehsender-angestellte-2025.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2025"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-01
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-reisebueros-angestellte-2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-reisebueros-angestellte-2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2026"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2025-05
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-saegeindustrie-angestellte-2025.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-saegeindustrie-angestellte-2025.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2025"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-06
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-schuhindustrie-angestellte-2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-schuhindustrie-angestellte-2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2026"]
|
||||
cross_refs: []
|
||||
|
||||
@@ -8,7 +8,7 @@ topic: kollektivvertraege
|
||||
author: "WKO"
|
||||
stand: 2026-04
|
||||
source:
|
||||
html: ".firecrawl/wko-kv/docs/gehaltsordnung-spedition-logistik-angestellte-2026.html"
|
||||
html: ".firecrawl/kv-portal/wko-kv/docs/gehaltsordnung-spedition-logistik-angestellte-2026.html"
|
||||
legal_bases: []
|
||||
tags: ["kollektivvertrag", "gehaltsordnung", "jahr-2026"]
|
||||
cross_refs: []
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user