Files
pv-agent/planung.md
T

346 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## User
bitte plane das folgende:
Eine Wissensdatenbank und ein Agent der Fragen zu Oesterreichischer Personalverrechnung mit dem Wissen aus der Wissensdatenbank beantwortet.
Entwicklungsumgebung-GPU: AMD Radeon Ai Pro r9700 - 32GB vram
Ollama-Server: http://100.183.83.12:11435
Agent: lokales Modell (ollama): empfehle ein Modell. der Agent darf nur wissen aus der wissensbasis verwenden, kein trainingswissen, kein web search
Wissensdatenbank: bitte um einen Vorschlag fuer die Umsetzung. bereits vorhanden: [@wissensbasis](file:///home/fegger/Projects/odoo-projects/pv-agent/wissensbasis/)
in weiterer Folge soll der Agent in Odoo-Enterprise verwendet werden.
---
# Plan: Wissensbasis-Agent Österreichische Personalverrechnung
*Stand: 2026-09-14 — Planung, noch keine Implementierung.*
## 1. Ist-Zustand (verifiziert)
- **Wissensbasis** (`wissensbasis/`): **601 kuratierte Layer-2-Einträge**
(571 Lexis Briefings Personalrecht, 30 WIKU), verteilt über 69 Cluster
(`INDEX.md`). Median ~7,3 KB, max ~31 KB, gesamt ~4,8 MB — ideale
Größe für vollständige Indizierung.
- **Struktur retrieval-gerecht:** verbindliches Frontmatter-Schema
(`id`, `stand`, `topic`, `tags`, `legal_bases`, `cross_refs`, …),
`kb.json` als generierte/validierte Registry, fixer Dokumentaufbau
(`## Zusammenfassung``## Kernwerte & Fristen``## Rechtsgrundlagen`
`## Payroll-Relevanz (Odoo)``## Verweise`).
- **Layer-1-Volltexte:** `.lexis360/md/` (572 Dateien) lokal vorhanden,
lizenzbeschränkt + unversioniert. `.wiku/` fehlt in diesem Checkout —
für Phase A irrelevant (Retrieval läuft auf Layer 2).
- **Ollama-Server** `http://100.103.83.12:11435` (Ziel-Instanz mit Modell-Zoo,
Custom-Port; der Host betreibt zusätzlich eine fast leere Instanz auf 11434):
aus der Zed-Sandbox erreichbar (2026-09-14, nach URL-Korrektur) —
`bge-m3` wurde per API gepullt, `qwen3.8:27b` war bereits installiert.
- **GPU:** Radeon AI Pro R9700, 32 GB (Strix Halo / RDNA 5) — budgetiert
Modellwahl auf ~2628 GB nutzbar.
## 2. Zielbild
Ein RAG-Agent, der Fragen zur österreichischen Personalverrechnung
**ausschließlich** aus den Layer-2-Einträgen beantwortet:
- jede fachliche Aussage mit KB-ID und `stand` belegt,
- **kein** Trainingswissen, **kein** Web, **keine** Tools,
- ehrliche Verweigerung, wenn die Wissensbasis nichts hergibt,
- Korpuskonflikte (z. B. ATZ-Ersatzquote 28,5 % vs. 27,5 %, lb-atz-07/09/12)
werden **beidseitig mit ⚠** referenziert — nie still aufgelöst,
- später Chat-Oberfläche in Odoo Enterprise.
## 3. Architektur (Phase A — eigener schlanker RAG-Service)
```mermaid
flowchart TD
KB[wissensbasis/dokumente/*.md + kb.json] -->|Ingest: Frontmatter + H2-Sektionen| IDX[(data/index.db - SQLite: FTS5 BM25 + Vektoren + Metadaten)]
IDX -->|Hybrid-Retrieval: BM25 + Dense, Metadaten-Filter, cross_refs| CTX[Kontextblöcke 8-12]
CTX -->|Systemprompt: nur Kontext, Zitierpflicht| LLM[Ollama qwen3:32b]
LLM -->|Antwort-Entwurf| CHECK{Post-Validierung: zitierte IDs ⊆ retrieved IDs?}
CHECK -->|ja| A[Antwort + Quellenblock]
CHECK -->|nein, 1x| LLM
CHECK -->|nein, 2x| R[Antwort als unsicher markiert / verweigert]
A --> API[FastAPI: POST /ask, GET /health, POST /reindex]
R --> API
API --> CLI[CLI + Mini-Web-UI zum Testen]
```
**Warum kein LangChain/LlamaIndex:** 601 Dokumente, sauberes Schema —
die Pipeline ist als eigenständiger Python-Code (~400600 Zeilen)
überschaubar und gibt volle Kontrolle über die Grounding- und
Zitier-Regeln, die hier der kritische Teil sind. Frameworks würden
Abhängigkeiten einführen, ohne das Kernproblem (Grounding) abzunehmen.
**Warum Layer 2 als Retrieval-Korpus:** kuratiert, eigene Worte
(lizenzkonform), versioniert, Metadaten-annotiert. Layer-1-Volltexte
bleiben außen vor (offener Lizenz-/Provisioning-Punkt laut README);
eine spätere Erweiterung für Tiefenzitate ist möglich, ohne die
Architektur zu ändern.
## 4. Modell-Empfehlung (Ollama)
| Modell | Rolle | Größe (Q4) | Begründung |
|---|---|---|---|
| **`qwen3.8:27b`** | **primärer Bake-off-Kandidat** | ~18 GB · 256k ctx | neueste Qwen-Generation (Ollama-Library, verifiziert 2026-09); Thinking per Request abschaltbar; Vision vorhanden, hier ungenutzt |
| `qwen3:32b` | bekannte Größe / Fallback | ~20 GB | bestes Deutsch + Instruction-Following im ≤32B-Bereich; Zitierdisziplin entscheidender als Weltwissen (das wir unterdrücken) |
| `gemma3:27b` | Alternative (Bake-off) | ~17 GB | sehr gutes Deutsch, 128k Kontext |
| `mistral-small3.2:24b` | Bake-off (Deutsch-Kandidat) | ~15 GB · 128k ctx | europäischer Anbieter, Europasprachen-Fokus → starke Deutsch-Hypothese (im Bake-off verifizieren); starkes Instruction-Following + wenige Wiederholungsfehler; kein Thinking-Modus |
| `qwen3:30b-a3b` | Latenz-Alternative | ~18 GB | MoE (3,3B aktiv) → deutlich schneller, etwas schwächer |
| `qwen3:14b` | Dev/Bake-off | ~9 GB | falls Zitierqualität reicht → halbe Latenz |
| **`bge-m3`** | **Embeddings** | ~1,2 GB | multilingual (Deutsch stark), 8k Kontext, über Ollama `/api/embed` |
| `bge-reranker-v2-m3` | optionales Reranking | ~1,1 GB | Rerank-API der installierten Ollama-Version vorher verifizieren; Fallback: Hybrid-Score ohne Reranker |
**VRAM-Budget:** Antwortmodell (1520 GB) + bge-m3 (~1,5 GB) + KV-Cache für
RAG-Prompts (48k Tokens Kontext, ~16k Kontextfenster ≈ 34 GB) ⇒
~2026 GB von 32 GB — passt mit Reserve. Thinking-Modus abschalten
(Latenz; bei `qwen3.8:27b` ist Thinking Default **an** → per Request
deaktivieren, API-Option lt. Library: `reasoning_effort`,
`preserve_thinking` — beim Implementieren verifizieren).
**Empfehlung:** Bake-off-Feld (M3): `qwen3.8:27b` und `qwen3:32b`
(Front-Runner) sowie `gemma3:27b` und `mistral-small3.2:24b` als
Deutsch-Kandidaten — Deutsch-/Zitierqualität ist jeweils unverifiziert.
Verbindliche Entscheidung erst nach Bake-off auf dem Goldset — Kriterium
bleibt Zitier-Präzision vor Latenz; liegt `qwen3:14b` bei gleicher
Zitierqualität auf, gewinnt Latenz.
> **Bake-off-Ergebnis (2026-09-14, Abschnitt 13):** `qwen3.8:27b` hat
> gewonnen und ist als Antwortmodell fixiert.
## 5. Grounding-Konzept (der kritische Teil)
1. **Systemprompt (deutsch):** antworte ausschließlich aus den
nummerierten Kontextblöcken; jede fachliche Aussage mit
`[kb-id]`-Beleg; Werte **immer mit** `(Stand YYYY-MM)`; fehlt etwas →
„Dazu enthält die Wissensbasis keine Aussage“ + ggf. verwandte
Cluster nennen; §-Zitate nur wenn die Quelle sie nennt; Korpus-
konflikte beidseitig mit ⚠ darstellen; keine Ergänzungen aus
Trainingswissen.
2. **Kontextblöcke** mit Metadatenkopf (ID · Titel · Stand · topic ·
Quellenwerk) — das Modell sieht nur, was im Retrieval war.
3. **Post-Validierung:** jede zitierte ID muss in der Retrieved-Menge
stehen; Verstoß → eine Regenerierung mit härterem Hinweis, dann
Verweigern/„unsicher“. Temperatur ~0,1.
4. **Kein Ausweg nach außen:** keine Tools, kein Browsing, kein
Web-Search-Hook — architektonisch gibt es nur Wissensbasis → Prompt.
## 6. Wissensdatenbank-Umsetzung (Vorschlag)
Die bestehende Wissensbasis ist bereits retrieval-gerecht — **kein
Umbau nötig**, nur ein Ingest-Index:
- **Chunking:** H2-Sektionen je Eintrag als Retrieval-Einheit (Parent-
Child: Treffer auf Sektion, Kontext = ganze Sektion + Metadatenkopf);
`Kernwerte & Fristen`-Tabellen als eigene Chunks (Zahlenfragen!);
Frontmatter im Index (topic, tags, legal_bases, stand).
- **Hybrid-Retrieval:** SQLite FTS5 (BM25; deutsche Normalisierung:
Umlaut-Folding beim Indexing) + Dense-Embeddings (bge-m3) + optional
Reranker; Reciprocal-Rank-Fusion; `cross_refs` der Top-Treffer als
kontrollierte Kontext-Erweiterung.
- **Metadaten-Filter:** `topic`-Vorfokus aus der Frage, Aktualitäts-
gewichtung über `stand`.
- **Quelle der Ingestion:** Layer-2-Frontmatter direkt (Single Source of
Truth); `kb.json` zusätzlich als Konsistenz-Gate (Anzahl/IDs müssen
matchen).
- **Update-Zyklus:** nach jedem neuen Batch einmal `POST /reindex`
(vollständiger Rebuild dauert bei 601 Einträgen Sekunden; Embeddings
gecacht, nur neue Einträge einbetten).
- **Speicherung:** eine SQLite-Datei `data/index.db` (gitignored) —
keine externe Vektor-DB nötig; Skalierungsreserve bis ~10.000
Einträge ohne Architekturwechsel.
## 7. Neue Dateien (Phase A)
```
agent/
config.py # Ollama-URL, Modellnamen, Ports (ENV-override)
ingest.py # Layer-2 → index.db (FTS5 + Vektoren via /api/embed)
retrieve.py # Hybrid-Suche + Filter + cross_refs (+ optional Rerank)
generate.py # Prompt-Bau, Ollama-Chat, Post-Validierung, Antwortformat
api.py # FastAPI: /ask, /health, /reindex
cli.py # Frage im Terminal (Dev-Loop)
eval/goldset.yaml # 3050 Fragen → Soll-IDs (inkl. Konfliktfälle)
eval/evaluate.py # Recall@k, Zitier-Präzision, Verweigerungsraten, Latenz
web/index.html # minimalistischer Test-Chat
data/ # index.db (gitignored)
tests/ # pytest: Ingest-, Retrieval-, Grounding-Unit-Tests
```
## 8. Validierung
- **Goldset:** 3050 Fragen mit Soll-IDs je Cluster, inkl. 35
Outside-KB-Fragen (Verweigerung!) und Konfliktfragen (ATZ-Quoten).
- **Metriken:** Retrieval-Recall@8 (Ziel >0,9), Zitier-Präzision
(100 % zitierte IDs ∈ retrieved), Verweigerungskorrektheit,
End-zu-End-Latenz.
- **Modell-Bake-off (M3):** qwen3.8:27b vs. qwen3:32b vs. gemma3:27b vs.
mistral-small3.2:24b (plus qwen3:14b als Latenz-Untergrenze) auf dem
Goldset; Entscheidung dokumentieren (analog D1/D2-Stil des Projekts).
- **Unit-Tests:** Ingest-Schema, Umlaut-Normalisierung, Post-Validierung
(Halluzinations-ID → Regenerierung), Konflikt-Darstellung.
## 9. Phase B: Odoo-Enterprise-Integration (später)
- **Option A (empfohlen):** dünnes Custom-Modul mit OWL-Chat-Panel,
`ir.config_parameter` für die Service-URL, rollenbasierter Zugriff.
Der RAG-Service bleibt Single Source of Truth für Grounding und
Zitate; Ollama bleibt extern. Unabhängig von Odoo-Version-Features.
- **Option B (zu prüfen):** nativer Odoo-LLM-Stack (in Odoo 19 neu
eingeführte `llm`/Agent-/Knowledge-Module) mit Ollama als
OpenAI-kompatiblem Provider. **Muss zuerst gegen Euren konkreten
Odoo-19-Quellstand verifiziert werden** (Modulnamen/APIs sind hier
nicht im Projekt und werden nicht aus Trainingswissen behauptet).
Striktes Grounding + Zitierdisziplin wären dort nachzubauen.
- Entscheidung erst nach Verifikation; Phase A läuft davon unabhängig
und wird von beiden Optionen unverändert genutzt.
- **Datenschutz-Bonus:** der Agent ist reiner Wissensassistent — es
fließen keine Mitarbeiter-/Abrechnungsdaten ins Modell, nur die
Frage und Layer-2-Fachtexte.
## 10. Risiken & offene Punkte
1. **Ollama-Erreichbarkeit** gegeben (Ziel-Instanz 11435; Sandbox kann
verbinden). Achtung Doppel-Instanz auf 11434 — URL nicht "korrigieren".
Cloud-Modelle (`*:cloud`) nicht für Antworten verwenden (Anforderung:
lokal).
2. **Ollama-Version:** `/api/embed` + allfällige Rerank-Unterstützung
prüfen; Fallback ohne Reranker ist unkritisch.
3. **Strix Halo (gfx-1151):** Ollama/ROCm muss die Karte unterstützen
(Server läuft offenbar bereits — im Bake-off Performance messen).
4. **Halluzination trotz allem:** Prompt + Post-Validierung reduzieren,
aber nicht eliminieren → Eval-Suite als Dauerschutz; Antworten
führen immer Quellen-IDs (Nachprüfbarkeit durch den Nutzer).
5. **WIKU-Layer-1** fehlt lokal — nur relevant, falls später Layer-1-
Tiefenzitate gewünscht (Lizenzpunkt aus README bleibt offen).
6. **Odoo-19-LLM-Module** unverifiziert → Phase B separat planen.
## 11. Meilensteine
| # | Inhalt | Ergebnis |
|---|---|---|
| M1 | Ingest + Index + Hybrid-Retrieval (ohne LLM) | Recall@8 auf Goldset messbar |
| M2 | Ollama-Anbindung (Embed + Generate), Grounding-Regeln, `/ask`-API, CLI | nutzbarer Agent im Terminal |
| M3 | Eval-Suite + Modell-Bake-off | dokumentierte Modell-Entscheidung |
| M4 | Odoo-Integration | separater Plan nach Odoo-19-Verifikation |
## 12. Entscheidungspunkte (an Dich)
1. **Modell:** `qwen3.8:27b` als primärer Bake-off-Kandidat ok — oder
gleich als Startmodell festlegen (und `qwen3:32b` nur als Fallback)?
2. **Bake-off:** vergleichst Du die drei Antwortmodelle auf dem Goldset
(empfohlen) oder legen wir qwen3:32b direkt fest?
3. **Layer 1:** bewusst außen vor in Phase A — einverstanden?
4. **Odoo-Version für Phase B:** Odoo 19 Enterprise (passend zu
`l10n_at_hr_payroll*`) — bitte bestätigen.
## 13. Umsetzungsstand (2026-09-14)
- **M1 erledigt und akzeptiert:** Hybrid-Index (601 Einträge → 3.005 Chunks,
FTS5-BM25 + bge-m3-Dense, Ollama :11435), Goldset 31 Fragen. **Recall@8
0,952 > 0,9** (Hit-Rate 0,968, MRR 0,690; BM25-only-Vergleich:
0,855 — die vier Komposita-Fehltreffer behebt die Dense-Suche alle).
41 Unit-Tests grün.
- **M2 erledigt und gegen das echte Modell validiert** (qwen3.8:27b,
Thinking aus): Zitier-Präzision **100 %** (4 Verletzungen → Post-
Validierung → Regenerierung, alle geheilt), Verweigerung korrekt 94,3 %,
Latenz mean 32 s / p95 53 s. ATZ-Konfliktfall wird korrekt beidseitig
mit ⚠ beantwortet; harte Verweigerungsfälle (UStVA) funktionieren.
- **M3 erledigt — Bake-off (2026-09-14, Goldset 35 Fragen, Thinking aus):**
| Kandidat | Zitier-Präzision | Verweigerung korrekt | Erw. Quelle | mean/p95 | Regen |
|---|---|---|---|---|---|
| **qwen3.8:27b** ✅ | **100 %** | **94,3 %** | **80,6 %** | 32 s / 53 s | 4 |
| gemma4:26b | 100 % | 91,4 % | 67,7 % | 7,9 s / 12 s | 4 |
| gemma4:12B | 94,3 % | 91,4 % | 77,4 % | 21 s / 40 s | 8 |
| qwen3.6:27B | 94,3 % | 85,7 % | 80,6 % | 43 s / 89 s | 10 |
| muse-glimmer:latest | 100 % | 77,1 % | 74,2 % | 37,5 s / 51 s | 1 |
| mistral-small3.1:24b | 100 % | 71,4 % | 58,1 % | 20 s / 43 s | 2 |
**Entscheidung (D7):** `qwen3.8:27b` ist das Antwortmodell (Protokoll:
Zitier-Präzision → Verweigerungskorrektheit → Latenz). `gemma4:26b`
wird als dokumentierter Latenz-Kandidat für späteres interaktives Tuning
geführt (4× schneller bei 100 % Zitier-Präzision, aber schwächere
Quellentreue und 3 statt 2 Fehlverweigerungen). mistral-small3.1
(Deutsch-Hypothese) ist praktisch widerlegt: 71,4 % Verweigerungs-
korrektheit. **muse-glimmer** (2026-09-14 nachgereicht): 100 %
Zitier-Präzision bei nur 1 Regenerierung (diszipliniertestes Modell),
aber 8/35 falsche Verweigerungen (Überverweigerung teils trotz
vorhandener Zitate) und 37,5 s mean — Rang 5 von 6, schlägt qwen3.8
in keiner Kennzahl. q-008 und q-031 verweigern alle Top-Kandidaten —
Prompt-/Retrieval-Tuning-Thema, kein Modellthema.
**Prompt v2 + Kontext-Tuning (2026-09-14):** (a) Regel 4 erlaubt
Teilantworten, Regel 8 verlangt Prämisse-Korrektur mit Muster-Beispiel;
(b) Kontextblöcke pro Eintrag = beste Inhaltssektion statt bester
Rangfolge-Chunk („Verweise“-Sektionen zuletzt — BM25-Längennormalisierung
rangiert die dünnen Navigations-Chips bevorzugt, Ursache q-008).
Bestätigungslauf qwen3.8:27b (35 Fragen): Zitier-Präzision **100 %**,
Verweigerung korrekt 94,3 % (q-008/q-031 behoben; neuer bekannter Fall
q-029 — breite Survey-Frage, sicherer Fehlermodus), erwartete Quelle
**83,9 %** (v1: 80,6 %), mean 34 s. Report `data/eval-qwen38-v2.json`.
- **M4 offen:** Odoo-Integration (separater Plan nach Verifikation der
Odoo-19-LLM-Module).
- **KV/RIS-Erweiterung (2026-09-15, D9/D10):** Korpus 601 → 1 274 Einträge
(614 WKO-KV-Dokumente `kv-kvt-…`, 59 RIS-Gesetze `ris-…`; quelltreu
generiert — D9), 14 984 Chunks. Retrieval kalibriert (D10:
dense_weight 2.0, rrf_k 20, Pool 150) → Recall@8 0,923 (>0,9 ✓).
Antwortmodus: Zitier-Präzision 95,2 %, Verweigerung 90,5 % —
Fehlverweigerungs-Tuning (offen, laufender Arbeitsstand) fortsetzen.
Intake: `tools/ingest_sources.py`, Registry: `tools/build_registry.py`.
- **Tuning abgeschlossen (2026-09-15, D11):** Ursache der Fehlverweige-
rungen war Prompt-Overflow (lange KV-Chunks > 16k — Systemprompt
trunciert weg). Fix: num_ctx 32 768, max_context_chars=90 000
(`trim_results`), cross_ref_expand 6 → alle 4 Fälle geheilt (10/10
Bestätigungsläufe). Retrieval Recall@8 0,946 · Antworten: Zitier-
Präzision 97,6 %, Verweigerung 97,6 % (Gate ✓), erwartete Quelle
91,9 %, Latenz mean 33 s. Offen: q-015 Branchen-Noise, q-024
transiente Flakiness (leerer Draft).
- **Komplexe-Fragen Stufe 1 (2026-09-15, M6/D12):** Query-Planer
(Heuristik-Gate → 1-3 Sub-Queries mit Stand-Jahr und Scope), Multi-
Query-Retrieval mit Per-Query-Slots und Scope-Filtern („gesetz“/„kv“).
Eval (46 Fragen): Zitier-Präzision 97,8 %, Verweigerung 97,8 %
(Gate ✓), erwartete Quelle 90,2 %, Latenz mean 33,5 s. Goldset 42 →
46 Fragen (q-110113). 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-120123): Hit-Rate
0,956 · Recall@8 **0,922** (Gate >0,9 ✓) · MRR 0,661; alle neuen Fälle
gefunden. Die gezielten Antwortläufe q-120123 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`.