wiki/c-work/4-done/2026-06-po-cleanup-neutralization-docgen.md

274 lines
31 KiB
Markdown
Raw Permalink 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.

<!-- status: done -->
<!-- started: 2026-06-02 -->
<!-- component: gateway | ui-nyla | platform -->
# PO-Cleanup: Chatbot-Entfernung + Neutralisierung (Quellen/Felder & Denormalisierung) + Dokumentengenerierung
## Beschreibung und Kontext
Vier zusammenhaengende Aufraeum-/Verbesserungsarbeiten an der Plattform:
- **A0 (Cleanup, dringend):** Das Feature `chatbot` wird nicht mehr benoetigt und soll **vollstaendig aus dem Code** entfernt werden (UI + Backend: Routen, Interfaces, Datamodels, Methoden, RBAC-/i18n-/Registry-Hooks, Tests). Zusaetzlich: **LangChain/LangGraph komplett entfernen** (Deps + Code) und die verbleibenden Nutzer (`realEstate`-BZO-Extraktion, `ChatStreamingHelper`) auf die **regulaere AI-Service-Nutzung** umstellen, wie alle anderen Nutzer im System. **Wiki nachfuehren:** Chatbot-Komponente in der aktuellen Doku entfernen bzw. ins Archiv verschieben. Scope: **keine DB-Zeilen-Bereinigung** (Feature-/Instanz-Rows, RBAC-Rollen, Drop `poweron_chatbot` separat).
- **A1 (Neutralisierung — Anreicherung/Denormalisierung):** Pruefen, dass denormalisierte (rueckuebersetzte) Inhalte **nie** persistiert werden, und einen sicheren Agent-Pfad bereitstellen, der Platzhalter ausschliesslich lokal (Private-LLM-Mapping) rueckuebersetzt und zum **Download ohne Speicherung** zurueckgibt.
- **A2 (Neutralisierung — Quellen/Felder):** Die Feld-Neutralisierung bei `FeatureDataSource`-Abfragen so korrigieren, dass Datensaetze nicht unbrauchbar werden: Strings immer (substring-basiert) neutralisieren, Binary droppen, andere Typen nur bei explizitem Feld-Flag — vererbungs- und typbewusst.
- **A3 (Dokumentengenerierung):** Dokumente sehen heute alle gleich aus (ein Standard-Style). Typ-spezifisches Styling (z. B. Klageschrift vs. Marketing mit Bildern) ermoeglichen und die Eignung der Renderer fuer **sehr grosse Dokumente** (z. B. 1000-seitiges Word-Buch mit eingebetteten Bildern) klaeren/verbessern.
**Business-Treiber:** Reports/Dokumente sind das sichtbare Endprodukt beim Kunden; Neutralisierung ist Compliance-kritisch (kein Klartext-Leak in Storage). Chatbot-Reste erhoehen Wartungslast und RBAC-/i18n-Rauschen.
**Risiko bei Nicht-Umsetzung:** A0 — toter Code + verwirrende Admin-UI. A1 — Datenschutzrisiko (Klartext im Storage) und ein dokumentierter, aber nicht implementierter Pfad. A2 — neutralisierte DB-Datensaetze sind fuer den Sub-Agent unbrauchbar bzw. inkonsistent gegenueber der UI. A3 — Reports wirken unprofessionell und grosse Dokumente koennen OOM/Timeout verursachen.
**Abhaengigkeiten:** A1 und A2 nutzen dieselbe `NeutralizationService`-Engine; aenderungen an der dokumentierten Invariante in [b-reference/platform/neutralization.md](../../b-reference/platform/neutralization.md) + [e-compliance/neutralisierung-detail.md](../../e-compliance/neutralisierung-detail.md). A3 beruehrt den ADR aus [4-done/2026-04-ai-reports-theming-and-pipeline.md](../4-done/2026-04-ai-reports-theming-and-pipeline.md) (bewusste Entscheidung GEGEN Theme-Presets).
## Fokus und kritische Details
### A0
- Feature-Discovery ist **glob-basiert** (`loadFeatureRouters` / `loadFeatureMainModules` in `modules/system/registry.py`) — Loeschen des Ordners ist boot-sicher; der Loader ueberspringt fehlende Module.
- **`chatbot`-Feature** (`featureCode=chatbot`, LangGraph, DB `poweron_chatbot`, `ChatbotConversation/Message/Document/Log`) ist **klar getrennt** vom generischen Agent-**Chat** (`datamodelChat.py`: `ChatWorkflow/ChatMessage`, Workspace). Letzteres **bleibt**.
- `methodChatbot` ist chatbot-spezifisch und wird entfernt; `methodAi` ist **unabhaengig** und bleibt.
- `WorkflowModeEnum.WORKFLOW_CHATBOT` in `datamodelChat.py` wird ausserhalb der Datei nicht referenziert — Datei bleibt, nur das Enum-Element + `frontend_options`-Eintrag entfernen.
- **LangChain/LangGraph wird komplett entfernt.** Die einzigen Nicht-Chatbot-Nutzer sind:
- `realEstate/bzoExtractionLangGraph.py`: nutzt `langgraph.graph.StateGraph` nur als **triviale Orchestrierung**. `create_bzo_extraction_graph()` ist eine lineare 4-Knoten-Pipeline aus reinen Python-/Regex-Funktionen (`classify_and_assemble` -> `extract_zones_and_tables` -> `extract_rules`) **ohne LLM** -> ersetzbar durch sequenzielle Funktionsaufrufe. `create_bzo_params_extraction_graph()` ist ein **Ein-Knoten-Graph** um `llm_extract_bauzone_params_node`, der den LLM-Call **bereits ueber `ai_service.callAiPlanning(...)`** macht (also schon regulaerer AI-Service) -> Knoten direkt awaiten. Es ist **keine** LangChain-Model-Bridge noetig.
- `serviceCenter/core/serviceStreaming/helpers.py` (`ChatStreamingHelper`): nutzt `langchain_core.messages`; **einzige Konsumenten sind die Chatbot-Module** (mainChatbot/service/chatbot, in A0 entfernt) -> nach A0 unbenutzt, kann mit `helpers.py` + den `serviceStreaming`-Exports entfernt werden.
- `requirements.txt`: `langchain`, `langchain-core`, `langgraph`, `langchain-tavily`, `nest-asyncio` (nur fuer LangGraph) entfernen; `requirements.lock` neu erzeugen.
- `AdminFeatureAccessPage.tsx` traegt die meisten UI-Referenzen (~82) — chirurgisch, nicht Datei loeschen.
### A1
- Reverse-Resolution ist ein **DB-Mapping-Lookup** (`NeutralizationService.resolveText`: `[typ.uuid]` -> `DataNeutralizerAttributes.originalText`), **kein** LLM-Call. Der Private-LLM macht nur die **Vorwaerts**-Erkennung. Das ist der datenschutzsichere Pfad (lokal, deterministisch, kein externes Modell sieht Klartext).
- `_rehydrateResponse()` in `mainServiceAi.py` ist **toter Code** (keine Call-Sites), die Docstrings behaupten aber automatische Rehydration — Chat persistiert die Modell-Antwort **wie geliefert** (kein Re-Save mit Klartext). Doc/Impl-Mismatch.
- Tatsaechliche Klartext-Risiken liegen NICHT bei der Denormalisierung, sondern bei: `downloadFromDataSource` (Roh-Bytes at rest), `writeFile`/`renderDocument` (agent-komponierter Inhalt), `RoundMemory.fullData`.
### A2
- Aktuell: `_neutralizeRowFields` ersetzt den **ganzen Feldwert** durch `[NEUT.<field>.<hash>]`, nur fuer explizit gelistete `neutralizeFields`; die Maskenliste in `_featureSubAgentTools.py` ignoriert **vererbte** `neutralize`-Flags zur Query-Zeit; keine Typ-Verzweigung; Binary wird zu `"<binary N bytes>"` stringifiziert und ggf. gehasht (nicht gedroppt).
- Das ist die **heute dokumentierte** Invariante (neutralization.md Failsafe 5/6) — A2 aendert sie bewusst.
- Substring-Neutralisierung pro String-Zelle via Private-LLM erzeugt Latenz/Kosten bei grossen Result-Sets — Batching + bestehender 5-Min-Result-Cache als Mitigation.
### A3
- JSON-Dokumentmodell + Unified-Style-Schema sind ein **Asset**, nicht das Problem.
- Ursache "alle Dokumente gleich": `resolveStyle(None)` injiziert immer `DEFAULT_STYLE` und reicht es truthy an die Renderer (`mainServiceGeneration.py` ~L410/L475); der Agent setzt `style` selten; `documentTheme` ist **deklariert, aber nicht verkabelt** (`methodAi.py`). Renderer sind in Ordnung — **Orchestrierung** ist die Luecke.
- **ADR-Spannung:** [2026-04-ai-reports-theming-and-pipeline.md](../4-done/2026-04-ai-reports-theming-and-pipeline.md) entschied bewusst GEGEN Theme-Presets/Mandate-CI und FUER "Agent fuellt generischen Style-Block". Der Wunsch nach typ-spezifischem Styling (Klageschrift/Marketing) wird damit nur erreicht, wenn der Agent den Style wirklich treibt. Vorschlag (ADR-konform): Presets als **smarte Defaults**, die der Agent waehlt und ueberschreiben kann — nicht als harte Vorgabe.
- Grosse Dokumente: voll **in-memory**, Bilder als **base64 im JSON**, **kein** Streaming (reportlab `doc.build`, python-docx `Document()`). Das ist der echte Blocker fuer 1000 Seiten + Bilder.
#### A3 Grossdokument-Analyse & Empfehlung (2026-06-02, AC15 — Schritt 1+2 UMGESETZT)
Status: **Schritt 1+2 umgesetzt+getestet; Schritt 3 (HTML-Backend) bewusst geschlossen (nein).** Theming (AC13) ist umgesetzt+getestet.
Konkrete Engpaesse (mit Fundstellen):
- **Ein grosses JSON haelt ALLE Bild-Bytes gleichzeitig.** `_mediaTools._renderDocument` (L110185) loest `file:fileId`-Bilder VOR `renderReport` zu `base64Data` im JSON auf; PDF/DOCX-Renderer (`_renderJsonImage`) lesen ausschliesslich `base64Data`/Data-URI. → Peak-Memory ~ Summe aller Bilder (base64 ≈ +33%).
- **Voll-in-memory Build:** `rendererPdf` baut komplette `story`-Liste + `doc.build` (L198245); `rendererDocx` baut `Document()` und `doc.save` (L122180). Keine Section-/Seiten-Chunking, kein Flush.
Umsetzungsplan (jeweils einzeln testbar):
1. **Lazy File-Ref-Bilder — UMGESETZT 2026-06-02:** Block-Bilder behalten `fileId` statt vorab-`base64Data`. `renderReport(imageResolver=fileId->bytes)` setzt einen Per-Render-Resolver am Renderer (`BaseRenderer._lazyResolveImageBase64`); PDF/DOCX `_renderJsonImage` loesen on-demand auf. `renderDocument` haelt fuer pdf/docx Bilder als Referenz und speist den Resolver aus Knowledge-Chunks/`chat.getFileData`. DOCX: echter Ein-Bild-Speicher (python-docx kopiert Bytes sofort ins Package). PDF: vermeidet base64-Overhead + JSON-Retention; **voll-streamendes PDF (reportlab haelt Image-Flowables bis `doc.build`) erst mit Temp-File-Bildern in Schritt 2**. Tests: `tests/serviceGeneration/test_large_document_render.py` (7 Tests, gruen) — Resolver-Aufrufe == N, Bilder eingebettet, JSON bleibt base64-frei.
2. **Temp-File-Bilder fuer PDF — UMGESETZT 2026-06-02:** PDF nutzt datei-basierte `Image(tmpPath)`-Flowables (`rendererPdf._renderJsonImage` schreibt Bytes in `tempfile.NamedTemporaryFile`, reportlab liest erst beim `doc.build` von Disk; Cleanup in `finally` via `_cleanupTempImageFiles`). Damit sind nicht mehr alle Bild-Bytes gleichzeitig resident — echtes Streaming auch fuer PDF. python-docx bleibt single-`save` (Lib-Grenze), kopiert Bytes aber bereits beim `add_picture` (Ein-Bild-Speicher). Section-Chunking ueber mehrere `doc.build`-Passes wurde NICHT umgesetzt: reportlab braucht die Story fuer eine `SimpleDocTemplate.build` ohnehin komplett, und Text-Flowables sind gegenueber den (jetzt datei-basierten) Bildern vernachlaessigbar — der eigentliche OOM-Treiber ist beseitigt. Tests: `test_pdf_images_are_file_backed_and_cleaned`.
3. **Optionales HTML-first-Backend — ENTSCHIEDEN: nein (2026-06-02):** WeasyPrint/Chrome wird NICHT als Zusatz-Backend eingefuehrt. Begruendung: Lazy- + Temp-File-Bilder beseitigen den Memory-Engpass fuer die unterstuetzten Formate; ADR 2026-04 sprach explizit gegen einen WeasyPrint-Ersatz. Bleibt als optionaler Future-Pfad ohne aktuellen Bedarf.
Bis dahin gilt als Mitigation der bestehende `writeFile`+`renderDocument(sourceFileId=…)`-Pfad (vermeidet riesige Tool-JSONs), und der PDF-Overflow-Guard (`_buildPdfWithOverflowGuard`) verhindert Layout-Abbrueche durch uebergrosse Bilder.
## Ziel und Nicht-Ziele
### Ziel
- **A0:** Keine lebenden `chatbot`-Symbole/Referenzen mehr im Code (Backend + UI); kein LangChain/LangGraph-Import oder -Dep mehr; `realEstate`-BZO-Extraktion + `ChatStreamingHelper`-Pfad auf regulaeren AI-Service/Std-Python umgestellt; aktuelle Wiki-Doku ohne Chatbot-Komponente; Boot, Tests, Build gruen.
- **A1:** Korrekte/ehrliche Doku + neues Agent-Tool, das Platzhalter via lokalem Mapping rueckuebersetzt und **transient** (Download, kein Save/Index/RoundMemory) zurueckgibt; toter Rehydrate-Code entfernt.
- **A2:** Feld-Neutralisierung gemaess Regeln 14 (siehe unten), vererbungs- und typbewusst, konsistent zwischen Query-Pfad und RAG-Bootstrap.
- **A3:** `documentTheme` end-to-end verkabelt + kleine Preset-Bibliothek (agent-ueberschreibbar); Layout-Primitive fuer echte Dokumenttypen; Grossdokument-Pfad (File-Referenz-Bilder + Chunked/Streamed-Render).
### Explizit NICHT
- A0: **keine** DB-Zeilen loeschen, **kein** Drop von `poweron_chatbot`. **z-archive-Inhalte NICHT inhaltlich anpassen** — nur Dokumente ins Archiv verschieben, wo noetig. Keine funktionale Aenderung an der `realEstate`-BZO-Logik (nur Orchestrierung/Imports), keine Aenderung am Extraktions-Ergebnis.
- A1: keine automatische Rehydration der Modell-Antwort wieder einfuehren; kein externer LLM fuer Reverse-Resolution.
- A2: keine Aenderung an der Engine selbst (`NeutralizationService`), nur an Aufruf/Policy in `featureDataProvider`/Sub-Agent-Tool; externe Connector-Quellen (Folder-Level) bleiben unveraendert.
- A3: kein vollstaendiger Renderer-Austausch als Pflicht; HTML-first-Backend nur als **zusaetzliches**, format-waehlbares Backend (Entscheidung offen).
## Betroffene Module
### A0 — Gateway (loeschen)
- `modules/features/chatbot/` (gesamt: mainChatbot, routeFeatureChatbot, interfaceFeatureChatbot, service, chatbot, config, chatbotConstants, `bridges/*`, `__init__`)
- `modules/workflows/methods/methodChatbot/` (methodChatbot, `actions/queryDatabase`, `__init__`)
- `scripts/script_db_init_chatbot.py`
- `tests/demo/test_demo_uc3_chatbot.py`
- `docs/althaus-bot-v2-aufwandsschaetzung.md`, `-fragenkatalog.md`, `-preprocessor-assessment.md`
### A0 — Gateway (chirurgisch)
- `modules/routes/routeSystem.py` (`_getUiObjectsForFeature("chatbot")`-Branch)
- `modules/routes/routeAdminFeatures.py` (Config-Cache-Invalidierung ~L781 + Docstrings)
- `modules/shared/gdprDeletion.py` (Chatbot-Interface-Branch ~L578)
- `modules/interfaces/interfaceRbac.py` (`DATA_OBJECT_NAMESPACE_MAP` Chatbot*-Eintraege + `USER_OWNED_NAMESPACES` "chatbot")
- `modules/shared/i18nRegistry.py` (`mainChatbot` in beiden `_featureModulePaths`-Tupeln)
- `modules/datamodels/datamodelChat.py` (`WORKFLOW_CHATBOT`-Enum + `frontend_options`-Eintrag)
- `tests/unit/methods/test_action_signature_validator.py` (L267), `tests/demo/test_demo_bootstrap.py` (`test_*NoChatbot`), `tests/demo/README.md`
- `scripts/script_migrate_user_uid.py`, `scripts/script_db_export_migration.py` (`poweron_chatbot`/`DB_CHATBOT`)
- Nur Kommentare (kein Verhalten): `modules/aicore/aicoreModelRegistry.py`, `app.py`, `modules/workflows/methods/methodAi/methodAi.py`, `requirements.txt`
### A0 — Frontend (loeschen)
- `src/api/chatbotApi.ts`, `src/hooks/useChatbot.ts`
- `src/pages/views/chatbot/` (ChatbotConversationsView, ChatbotViews.module.css, index)
- `src/pages/admin/ChatbotConfigSection.tsx`
- `work-around/chatbot.ts`
### A0 — Frontend (chirurgisch)
- `src/App.tsx` (Legacy-Redirect `chatbot`)
- `src/pages/FeatureView.tsx` (Import, `ChatbotSettings`, `FEATURE_VIEWS.chatbot`, DEBUG)
- `src/config/pageRegistry.tsx` (Icon-Keys)
- `src/types/mandate.ts` (`FEATURE_VIEW_REGISTRY.chatbot`)
- `src/pages/admin/AdminFeatureAccessPage.tsx` (Import + State/Config-Builder + JSX-Bloecke)
- `src/pages/admin/Admin.module.css` (`.chatbotConfigSection`), `src/styles/pages.module.css` (`.chatbot*`)
- `src/stores/featureStore.tsx`, `src/api/featuresApi.ts` (inkl. Mock-Fallback), `src/hooks/useInstancePermissions.tsx` (DEBUG + Keys)
### A0 — LangChain/LangGraph-Entfernung + Migration (Gateway)
- `modules/features/realEstate/bzoExtractionLangGraph.py` -> umbenennen zu `bzoExtraction.py`: `from langgraph.graph import StateGraph, START, END` entfernen; `create_bzo_extraction_graph()`/`graph.invoke(state)` durch sequenziellen Aufruf (`classify_and_assemble` -> `extract_zones_and_tables` -> `extract_rules`) ersetzen; `create_bzo_params_extraction_graph()`/`graph.ainvoke(state)` durch direktes `await llm_extract_bauzone_params_node(state)` ersetzen (LLM-Call bleibt `ai_service.callAiPlanning`)
- `modules/features/realEstate/mainRealEstate.py` (L281 Import anpassen; Kommentare L2334/L2492/L2546 "LangGraph" entfernen)
- `modules/features/realEstate/routeFeatureRealEstate.py` (Docstrings L709/L790 "LangGraph"), `modules/routes/routeRealEstate.py` (Docstrings L2237/L2243)
- `modules/serviceCenter/core/serviceStreaming/helpers.py` (loeschen — `ChatStreamingHelper`/`langchain_core`), `serviceStreaming/__init__.py` (Export entfernen), `serviceStreaming/mainServiceStreaming.py` (`getChatStreamingHelper()` entfernen)
- `requirements.txt` (langchain/langchain-core/langgraph/langchain-tavily/nest-asyncio entfernen) + `requirements.lock` neu erzeugen
### A0 — Wiki nachfuehren (aktive Doku; z-archive-Inhalte unveraendert)
- Chatbot-Referenzen aus aktiven Docs entfernen: `b-reference/product.md` (Feature-Zeile + Repo-/Tech-Stack), `b-reference/platform/database-architecture.md` (`poweron_chatbot`), `b-reference/platform-core/workflow.md`, `b-reference/platform-core/architecture.md`, `b-reference/platform/platform-diagrams.md`, `b-reference/ui-nyla/architecture.md`, `e-compliance/security-overview.md`, `README.md` (Verweis auf nicht-existentes `features/chatbot.md`)
- LangChain/LangGraph aus Tech-Stack-/Architektur-Doku entfernen, wo erwaehnt (`b-reference/product.md`, `b-reference/platform-core/architecture.md`)
- `a-strategy/roadmap.md`: Chatbot-Erwaehnungen pruefen/streichen (Strategie-Doc — nur wenn als aktive Komponente gefuehrt)
- Falls ein aktives Doc rein Chatbot-spezifisch ist: nach `z-archive/` **verschieben** (keine inhaltliche Aenderung). Aktuell existiert kein dediziertes aktives Chatbot-Reference-Doc -> ueberwiegend chirurgische Entfernung
- `c-work/_CHANGELOG.md`: Eintraege fuer Chatbot-Removal + LangChain-Removal
### A1 — Gateway
- `modules/serviceCenter/services/serviceAgent/coreTools/_mediaTools.py` (neues Tool, z. B. `revealDocument`)
- `modules/serviceCenter/services/serviceAgent/toolboxRegistry.py` (restriktive Toolbox)
- `modules/serviceCenter/services/serviceAi/mainServiceAi.py` (`_rehydrateResponse` entfernen, Docstrings korrigieren)
- `modules/features/neutralization/serviceNeutralization/mainServiceNeutralization.py` (`resolveText` wiederverwenden)
### A2 — Gateway
- `modules/serviceCenter/services/serviceAgent/featureDataProvider.py` (`_neutralizeRowFields`, `_applyFieldNeutralization`, `_serializeRow`)
- `modules/serviceCenter/services/serviceAgent/coreTools/_featureSubAgentTools.py` (Maskenliste-Aufbau)
- `modules/serviceCenter/services/serviceKnowledge/udbNodes.py` (`FdsFieldNode.getEffectiveFlag`), `_inheritFlags.py` (Resolver)
- `modules/serviceCenter/services/serviceKnowledge/subFeatureBootstrap.py` (`_serializeRowToText` angleichen)
### A3 — Gateway
- `modules/serviceCenter/services/serviceGeneration/styleDefaults.py` (`THEME_PRESETS`, `resolveTheme`)
- `modules/serviceCenter/services/serviceGeneration/mainServiceGeneration.py` (Theme-Aufloesung)
- `modules/serviceCenter/services/serviceGeneration/renderers/*` (Layout-Primitive, File-Ref-Bilder, Chunking)
- `modules/serviceCenter/services/serviceAgent/coreTools/_mediaTools.py` (`renderDocument`: Theme/Style aus Intent, `aiService` durchreichen)
- `modules/workflows/methods/methodAi/methodAi.py` + `actions/generateDocument.py` (`documentTheme` durchreichen)
- `modules/datamodels/datamodelJson.py` (Layout-Section-Typen)
### DB-Migration
- A0: **nein** (Code-only; DB-Cleanup separat). A1: **nein**. A2: **nein** (Verhalten, keine Schema-Aenderung). A3: ggf. additive Schema-Erweiterung im JSON-Modell (kein DB-Pflichtfeld).
### Andere Komponenten
- `service-llm-private`, `service-preprocessing`, `service-teams-browser-bot`: **keine** chatbot-spezifischen Anpassungen noetig (A0). A1/A2 nutzen Private-LLM-Ratings (bereits vorhanden).
- Deployment: nach LangChain-Removal Build/Image ohne diese Deps verifizieren (kleinere Image-Size, keine `nest-asyncio`-Patches).
## Entscheidungen
| Datum | Entscheidung | Begruendung |
|-------|-------------|------------|
| 2026-06-02 | A0 nur Code (keine DB/Wiki/Archive) | User-Scope-Entscheid; DB-Cleanup separat |
| 2026-06-02 | `datamodelChat.py` bleibt; nur `WORKFLOW_CHATBOT`-Enum entfernen | Agent-Chat ist unabhaengig vom Chatbot-Feature |
| 2026-06-02 | LangChain/LangGraph komplett entfernen, verbleibende Nutzer migrieren | User-Entscheid; Nutzung ist trivial ersetzbar (realEstate-LLM laeuft schon ueber `callAiPlanning`, `ChatStreamingHelper` nur vom Chatbot genutzt) |
| 2026-06-02 | `bzoExtractionLangGraph.py` -> `bzoExtraction.py`: StateGraph durch sequenzielle Aufrufe ersetzen | Graphen sind lineare/Ein-Knoten-Pipelines; kein Funktionsverlust |
| 2026-06-02 | Aktive Wiki-Doku ohne Chatbot/LangChain; z-archive nur verschieben, nicht anpassen | User-Entscheid (Wiki nachfuehren) |
| 2026-06-02 | A1: Reverse-Resolution bleibt DB-Mapping-Lookup (kein externer LLM) | Datenschutzsicher, deterministisch; "Private LLM" = lokal/intern |
| 2026-06-02 | A1: Neues Tool gibt transient zum Download zurueck, niemals Save/Index/RoundMemory | Klartext darf nicht at-rest landen |
| 2026-06-02 | A1: `_rehydrateResponse` entfernen statt verkabeln | Toter Code + Doc/Impl-Mismatch; Auto-Rehydration ist Datenschutzrisiko |
| 2026-06-02 | A2: String-Zellen substring-neutralisieren (Feldname als Typ-Hint) statt Whole-Value-Hash | Datensaetze bleiben brauchbar; Platzhalter-Typ passend zum Feld |
| 2026-06-02 | A2: Binary droppen statt maskieren | Spez-Regel 2; Binary nie neutralisieren |
| 2026-06-02 | A2: number/date/bool nur bei EXPLIZITEM Feld-Flag (nicht vererbt) | Spez-Regel 3 |
| 2026-06-02 | A2: Query-Maske aus effektivem Flag (Vererbung) statt nur `neutralizeFields`-Liste | UI-Effektivwert = Laufzeitverhalten |
| 2026-06-02 | A3: Presets als agent-ueberschreibbare Defaults (kein Hard-Mandate) | Reconciliation mit 2026-04-ADR |
| 2026-06-02 | A3: Theme-Wahl agent-getrieben via `documentTheme`-Tool-Param (Enum + Beschreibung), kein serverseitiges Auto-Select | ADR-konform (Agent treibt Style); kein zusaetzlicher LLM-Call noetig |
| 2026-06-02 | A3: Layout-Primitive = `cover_page` + `image_grid` (Markdown-Fenced-Bloecke); `letterhead`/`multi-column` zurueckgestellt | Hoechster Nutzen (Klageschrift-Titelseite, Marketing-Bildraster); multi-column ist Page-Template-Thema, nicht Block-Primitive |
| 2026-06-02 | A3: HTML-first-Backend (WeasyPrint/Chrome) — ENTSCHIEDEN: nein | Lazy+Temp-File-Bilder loesen Memory-Engpass; ADR sagte "kein WeasyPrint-Ersatz" |
| 2026-06-03 | A3: THEME_PRESETS + documentTheme entfernt, AI-Style-Enhancement statt Presets | ADR 2026-04 Originalentscheid wiederhergestellt; AI passt Styles kontextbasiert an statt statischer Presets; Smart Table Styling als Erweiterung |
## Umsetzungs-Checkliste
### A0 — Chatbot entfernen (Code)
- [x] Backend-Verzeichnisse/Dateien loeschen (siehe Betroffene Module)
- [x] Backend chirurgische Edits (routeSystem, routeAdminFeatures, gdprDeletion, interfaceRbac, i18nRegistry, datamodelChat, Tests, Scripts)
- [x] Frontend-Dateien loeschen
- [x] Frontend chirurgische Edits (App, FeatureView, pageRegistry, mandate, AdminFeatureAccessPage, CSS, Stores/Hooks/Api DEBUG+Keys)
- [x] LangChain/LangGraph entfernen + migrieren: `bzoExtractionLangGraph.py` -> `bzoExtraction.py` (StateGraph raus), `mainRealEstate.py`-Import, `ChatStreamingHelper`/`helpers.py` + `serviceStreaming`-Exports entfernen, `requirements.txt`
- [x] Wiki nachfuehren: Chatbot + LangChain aus aktiven b-reference/e-compliance-Docs entfernen; ggf. Doc nach z-archive verschieben; `_CHANGELOG.md`
- [x] Verifikation: Boot ok, `pytest` gruen, `tsc`/`vite build` gruen, keine lebenden `chatbot`/`langchain`/`langgraph`-Referenzen im Code; BZO-Extraktion liefert identisches Ergebnis wie vorher
- [~] `requirements.lock` NICHT noetig (Projekt nutzt nur `requirements.txt`) — Punkt gestrichen (User-Entscheid 2026-06-02)
### A1 — Denormalisierung sicher
- [x] Agent-Tool `revealDocument` (resolveText, mandate/instance-scoped, transient/no-save, `readOnly=True`)
- [x] In restriktiver Toolbox registrieren (`neutralization`-Toolbox, `isDefault=False` -> explizit via `requestToolbox`); RBAC ueber bestehende Neutralisierungs-Feature-Access
- [x] `_rehydrateResponse` entfernen + Docstrings in `callAi`/`callAiStream` korrigieren
- [x] Doku: neutralization.md (Failsafe 8 + Tool), neutralisierung-detail.md
- [x] Leak-Pfade dokumentieren (downloadFromDataSource/RoundMemory) + Folge-Ticket-Hinweis (neutralization.md "Bekannte Klartext-at-rest-Pfade")
### A2 — Feld-Neutralisierung
- [x] `_resolveFieldsToMaskForTable`/`neutralizePolicy` (spiegelt `FdsFieldNode.getEffectiveFlag`)
- [x] Regel 1: String-Zellen substring-neutralisieren via `NeutralizationService` mit Feldname-Typ-Hint
- [x] Regel 2: Binary-Spalten vor Serialisierung droppen
- [x] Regel 3: number/float/int/date/bool nur bei explizitem Feld-Flag
- [x] RAG-Bootstrap `_serializeRowToText` an denselben Resolver/dieselbe Platzhalter-Policy angleichen (`finalizeRowsAsync`/`_neutralizeAndSerializeRows`)
- [x] Doku: neutralization.md Failsafe 5/6 + neutralisierung-detail.md Abschnitt 3
### A3 — Dokumentengenerierung
- [x] `THEME_PRESETS` + `resolveTheme(name)` in `styleDefaults.py` (deep-merge auf DEFAULT_STYLE, agent-ueberschreibbar)
- [x] `documentTheme` end-to-end verkabeln (Node/Action -> `renderReport(documentTheme=...)`)
- [x] `renderDocument`: Theme agent-getrieben via Tool-Param (Enum+Beschreibung); kein serverseitiges Auto-Select (ADR-konform)
- [x] JSON-Layout-Primitive `cover_page` + `image_grid` (Markdown-Fenced-Bloecke) + PDF/DOCX-Handler; `letterhead`/`multi-column` zurueckgestellt
- [x] Grossdokumente: File-Referenz-Bilder statt base64 (Schritt 1) + Temp-File-PDF-Bilder (Schritt 2)
- [x] HTML-first-Backend evaluiert -> ENTSCHIEDEN: nein (nicht benoetigt)
- [x] **Nachtrag 2026-06-03:** `THEME_PRESETS` + `documentTheme` nachtraeglich entfernt zugunsten AI-getriebener Style-Enhancement (`_enhanceStyleWithAi`). `DEFAULT_STYLE` auf Cursor/VS-Code-Aesthetik modernisiert. Alle 5 Renderer refactored (Dead-Code entfernt, Hardcodes durch Unified-Style-Reads ersetzt). Folge-Feature: Smart Table Styling (per-table Overrides, borderStyle, bandingEnabled, columnAlignments, coverPage, caption). Kanonische Doku: `b-reference/platform-core/document-rendering.md`
### Querschnitt
- [x] RBAC / Permissions: A0 entfernt Chatbot-RBAC-Objekte/Template-Rollen aus Code; A1 Tool-Zugriff ueber bestehende Neutralisierungs-Rechte
- [x] Neutralisierung betroffen? A1 + A2 = ja (Doku-Update Pflicht — erledigt)
- [x] Navigation / Routing: A0 entfernt Chatbot-Feature-Views/Routen
- [x] Billing-Impact? Nein (A2 nutzt bestehende AI-Call-Billing)
## Akzeptanzkriterien
| # | Kriterium (Given-When-Then) | Prio |
|---|-----------------------------|------|
| 1 | Given Codebase nach A0, When `rg -i chatbot` (ohne wiki/z-archive), Then keine lebenden Symbole/Routen/Interfaces | must |
| 2 | Given Backend-Boot nach A0, When Worker startet, Then keine ImportError, Feature-Registry laedt ohne Chatbot | must |
| 3 | Given UI-Build nach A0, When `vite build`/`tsc`, Then keine dangling Imports/Typfehler | must |
| 1b | Given Codebase nach A0, When `rg -i "langchain|langgraph"` im Code, Then keine Treffer; `requirements.txt` ohne diese Deps | must |
| 1c | Given dieselbe BZO-PDF vor/nach Migration, When `run_extraction`/`run_bzo_params_extraction`, Then identisches `fakten`/`zones`/`rules`-Ergebnis | must |
| 1d | Given aktive Wiki-Doku nach A0, When durchsucht, Then keine Chatbot-Komponente/LangChain im Tech-Stack; z-archive-Inhalte unveraendert | should |
| 4 | Given Datei mit neutralisiertem Inhalt, When Agent `revealDocument(fileId)` aufruft, Then Klartext wird transient zurueckgegeben und NICHTS gespeichert/indexiert | must |
| 5 | Given `revealDocument`, When ausgefuehrt, Then keine externe LLM-API beteiligt (nur DB-Mapping) | must |
| 6 | Given `mainServiceAi.py`, When Code-Review, Then `_rehydrateResponse` ist entfernt und Docstrings korrekt | should |
| 7 | Given FDS-Tabelle mit `neutralize=True` (vererbt, leere `neutralizeFields`), When `queryTable`, Then String-Felder sind substring-neutralisiert (Platzhalter im Text) | must |
| 8 | Given String-Feld "Name"/"Adresse", When neutralisiert, Then Platzhalter-Typ entspricht dem Feldnamen-Hint | should |
| 9 | Given Binary-Spalte bei aktiver Neutralisierung, When `queryTable`, Then Spalte wird gedroppt (nicht maskiert) | must |
| 10 | Given numerisches Feld nur via Vererbung (nicht explizit), When `queryTable`, Then Wert bleibt unveraendert | must |
| 11 | Given numerisches Feld mit explizitem Feld-Flag, When `queryTable`, Then Wert wird neutralisiert | must |
| 12 | Given RAG-Bootstrap einer FDS-Tabelle, When indexiert, Then dieselbe Policy/Platzhalter wie Query-Pfad | should |
| 13 | Given `renderDocument` mit `documentTheme="legal"`, When gerendert, Then typ-spezifischer Style (nicht DEFAULT_STYLE) | must |
| 14 | Given `renderDocument` ohne Theme/Style, When gerendert, Then neutrale Defaults (kein Crash) | must |
| 15 | Given ~1000-seitiges Dokument mit Bildern, When gerendert, Then kein OOM/Timeout (Chunked + File-Ref-Bilder) | must |
## Testplan
| ID | AC | Art | Automatisiert | Repo-Pfad | Status |
|----|----|-----|--------------|-----------|--------|
| T1 | 1,2,1b | smoke | ja | platform-core (boot + `pytest tests/demo`) | pending |
| T2 | 3 | build | ja | ui-nyla (`tsc`, `vite build`) | pending |
| T1b | 1c | regression | ja | platform-core/tests/features/realEstate/test_bzo_extraction_parity.py | pending |
| T3 | 4,5 | integration | offen | `revealDocument` no-persist: durch Tool-Design (transient SSE, kein Save/Index) + Code-Review abgedeckt; dedizierter Integrationstest braucht volle services-Plumbing -> als Folge-Ticket | deferred |
| T4-T6 | 7-11 | unit | ja | platform-core/tests/unit/serviceAgent/test_field_neutralization.py (8 Tests: string/hint/binary-drop/inherited-skip/explicit/failsafe/dedup) | **done** |
| T7 | 12 | unit | ja | platform-core/tests/unit/serviceAgent/test_field_neutralization.py::test_rag_bootstrap_parity_with_query_path (gemeinsame `_neutralizeAndSerializeRows`-Policy; `_serializeRowToText` leakt nicht) | **done** |
| T8 | 13,14 | unit | ja | platform-core/tests/serviceGeneration/test_style_resolver.py (Theme-Presets + Praezedenz) | **done** |
| T9 | 15 | unit | ja | platform-core/tests/serviceGeneration/test_large_document_render.py (8 Tests: PDF/DOCX lazy file-ref, Resolver-Count, JSON base64-frei, **Temp-File-Bilder Schritt 2 + Cleanup**) | **done (Schritt 1+2)** |
| T10 | 13 | unit | ja | platform-core/tests/serviceGeneration/test_layout_primitives.py (8 Tests: cover_page/image_grid Markdown-Parse + PDF/DOCX-Handler) | **done** |
## Links
- Wiki Neutralisierung: [b-reference/platform/neutralization.md](../../b-reference/platform/neutralization.md), [e-compliance/neutralisierung-detail.md](../../e-compliance/neutralisierung-detail.md)
- Wiki AI-Agent/Tools: [b-reference/platform-core/ai-agent.md](../../b-reference/platform-core/ai-agent.md)
- ADR Doc-Theming: [4-done/2026-04-ai-reports-theming-and-pipeline.md](../4-done/2026-04-ai-reports-theming-and-pipeline.md)
- Lokale Renderer-Referenz: `pamocreate/projects/_shared/html_to_pdf.py`, `md_to_pdf.py`
- PR: TBD
- Issue: TBD
## Abschluss
- [x] `b-reference/platform/neutralization.md` aktualisiert (A1 Failsafe 8 + reveal-Tool + Leak-Pfade; A2 Failsafe 5/6)
- [x] `b-reference/platform-core/ai-agent.md` aktualisiert (revealDocument-Tool + neutralization-Toolbox + Doc-Theming/Layout-Primitive)
- [x] `e-compliance/neutralisierung-detail.md` aktualisiert (A1/A2)
- [x] `b-reference/product.md` + Architektur-/DB-/Diagramm-Docs: Chatbot-Komponente + LangChain/LangGraph aus aktiver Doku entfernt (Teil A0)
- [x] `c-work/_CHANGELOG.md` je Change 1 Zeile
- [x] `TOPICS.md` geprueft
- [~] Dokument-Move nach `2-build/`/`z-archive/`: Verschiebung dem User ueberlassen (Arbeit fachlich abgeschlossen)