"""Fixtures: Mini-Wissensbasis (3 Einträge), Index, Fake-Ollama-Client. Alle Tests laufen offline — kein Ollama, kein Netz. Die Mini-KB folgt dem verbindlichen Layer-2-Schema (Frontmatter + H2-Sektionen + kb.json-Gate). """ from __future__ import annotations import json from pathlib import Path import pytest from agent.config import Config DOC_ATZ = """--- id: lb-min-01 batch: 1 title: "Altersteilzeit - Überblick" work: "Lexis Briefings Personalrecht" chapter: "Beschäftigungsverhältnisse" topic: altersteilzeit author: "Marek" stand: 2026-01 source: pdf: ".lexis360/Lexis360_test_atz.pdf" text: ".lexis360/md/test_atz.md" legal_bases: ["AlVG", "AZG § 19e"] tags: [altersteilzeit, lohnausgleich] cross_refs: ["lb-min-02"] --- # Altersteilzeit – Überblick *Lexis Briefings Personalrecht, Marek, Stand Jänner 2026 (lb-min-01).* ## Zusammenfassung Altersteilzeit ist eine Teilzeit, bei der der Arbeitnehmer zusätzlich zum Teilzeitentgelt einen Lohnausgleich erhält; das AMS ersetzt dem Arbeitgeber einen Teil der Zusatzkosten (Altersteilzeitgeld). ## Kernwerte & Fristen (Stand 2026-01) | Wert / Regel | Detail | |---|---| | Ersatzquote | 28,5 % der ersetzbaren Kosten (Stand 2026-01) | ## Rechtsgrundlagen - AZG § 19e (Kündigungszuschlag) ## Verweise - lb-min-02 """ DOC_URL = """--- id: lb-min-02 batch: 1 title: "Urlaubsanspruch und Verbrauch" work: "Lexis Briefings Personalrecht" chapter: "Urlaub & Karenzierung" topic: urlaub author: "Marek" stand: 2026-07 source: pdf: ".lexis360/Lexis360_test_urlaub.pdf" text: ".lexis360/md/test_urlaub.md" legal_bases: ["UrlG"] tags: [urlaub, urlaubsentgelt] cross_refs: ["lb-min-01"] --- # Urlaubsanspruch und Verbrauch *Lexis Briefings Personalrecht, Marek, Stand Juli 2026 (lb-min-02).* ## Zusammenfassung Der gesetzliche Urlaubsanspruch beträgt fünf Werktage Wochenurlaub je Dienstjahr; das Urlaubsentgelt ist wie Entgeltfortzahlung zu berechnen. ## Kernwerte & Fristen (Stand 2026-07) | Wert / Regel | Detail | |---|---| | Mindesturlaub | 5 Wochen je Dienstjahr (Stand 2026-07) | ## Verweise - lb-min-01 """ DOC_WIKU = """--- id: wk-min-01 batch: 1 title: "WIKU Praxisfall: Lohnverrechnung" work: "WIKU Fachbroschüre" chapter: "WIKU Fachbroschüre" topic: lohnverrechnung author: "Wilhelm Kurzböck" stand: 2026-03 source: pdf: ".wiku/test_lohnverrechnung.pdf" text: ".wiku/md/test_lohnverrechnung.md" legal_bases: ["EStG § 25"] tags: [lohnverrechnung, praxisfall] cross_refs: ["lb-min-01"] --- # WIKU Praxisfall: Lohnverrechnung *WIKU Fachbroschüre, Wilhelm Kurzböck, Stand März 2026 (wk-min-01).* ## Zusammenfassung Praxisfall zur laufenden Lohnverrechnung: Abrechnungsperiode und Beitragsgrundlagen sind monatlich festzulegen. ## Verweise - lb-min-01 """ MIN_DOCS = { "altersteilzeit_uberblick.md": DOC_ATZ, "urlaubsanspruch.md": DOC_URL, "wiku_lohnverrechnung.md": DOC_WIKU, } MIN_IDS = ["lb-min-01", "lb-min-02", "wk-min-01"] def write_mini_kb(root: Path) -> Path: doc = root / "dokumente" doc.mkdir(parents=True, exist_ok=True) for name, content in MIN_DOCS.items(): (doc / name).write_text(content, encoding="utf-8") kb = { "n_entries": len(MIN_IDS), "entries": [{"id": i, "title": i} for i in MIN_IDS], } (root / "kb.json").write_text( json.dumps(kb, ensure_ascii=False, indent=1), encoding="utf-8" ) return root class FakeOllama: """Skriptbarer Chat-Client; embed() schlägt fehl (Dense bleibt ungetestet).""" def __init__(self, answers: list[str] | None = None): self.answers = list(answers or []) self.calls = 0 self.last_messages: list | None = None def chat(self, model, messages, **kwargs): self.calls += 1 self.last_messages = messages if not self.answers: raise AssertionError("FakeOllama: keine skriptierte Antwort mehr") return self.answers.pop(0) def embed(self, model, texts): raise RuntimeError("embed nicht verfügbar (offline Test)") def is_up(self): return False def close(self): pass @pytest.fixture def mini_kb(tmp_path): return write_mini_kb(tmp_path / "kb") @pytest.fixture def mini_cfg(tmp_path, mini_kb) -> Config: return Config( kb_dir=str(mini_kb), db_path=str(tmp_path / "index.db"), embed_off=True, planner_enabled=False, # Tests skripten Chat-Antworten; Planer # separat testbar (siehe test_generate/test_query_planner) ) @pytest.fixture def mini_index(mini_cfg) -> Config: from agent.ingest import build_index stats = build_index(mini_cfg) assert stats.n_entries == 3 assert stats.n_chunks >= 7 assert stats.embed_error is None return mini_cfg @pytest.fixture def fake_ollama(): return FakeOllama