TGV · KI-First-Architektur
Beschluss 17.09.2026: RAG und fachliche Arbeit: Bauplan ab 18.09., Bestand, Rechtevertrag und Abnahme. Historische Betriebsangaben unten sind datierte Befunde, keine aktuelle Live-Auskunft.
Nicht Bildschirme mit ein bisschen KI, sondern ein Gehirn (Agent), das mit Händen (Skills) arbeitet und dünne Oberflächen (Seiten) bedient. Hier: wie das zusammenspielt — und wie es mit den Seiten wechselwirkt.
Die Umkehrung des klassischen Apps: die Seite denkt NICHT, sie hostet ein Fenster auf den Agenten. Intelligenz lebt im Agenten, Fähigkeit in den Skills, die Seite zeigt & nimmt entgegen.
Plant, entscheidet, wählt Werkzeuge, formuliert. Adaptive Persona je User/Mandant. agent_loop
Tun die Arbeit: extrahieren, klassifizieren, abgleichen, suchen, versenden. ~45 Bausteine. /api/skill/*
Dünn: zeigt Karten, nimmt Eingaben, rendert kanonisch. Denkt nicht. core_shell + engine.js
Von der Absicht bis zur gerenderten Karte. Jeder Schritt ist scope- und vertraulichkeits-gegatet (RLS + conf), der Ton kommt aus der adaptiven Persona.
Texteingabe, Klärung, Screen-Kontext
versteht Absicht, wählt Werkzeuge, kennt den Kontext (CORE/RKA/Steuer/Vertrag)
ruft die passenden Skills/Lese-Tools — scope-gate fail-closed
nur Mandant + erlaubte Vertraulichkeit (Owner-Bypass)
render_hints → Envelope, keine nackten IDs
engine.js zeichnet die Karten in den Screen — du gibst frei
Seitenbau (wie eine Seite entsteht) und KI-First (Agent+Skills) sind zwei Gesichter DESSELBEN Systems — verbunden durch den einen Katalog und die eine Engine.
Jede Klärung / Frage / Composer-Eingabe ruft den Agenten (skillFetch core-chat). Die Seite ist ein dünnes Fenster — R-V4-17: NIE einen screen-eigenen Composer bauen.
Der Agent rendert Karten (render_hints) in die Seite, schlägt Aktionen vor, und in Phase 0 den Zweck der Seite selbst (Dialog: KAI schlägt vor, du validierst).
Für strukturierte Reads ruft die Seite Skills direkt (restGet / skillFetch, RLS) — kein Agent nötig. Reine Daten-Darstellung.
Jede Funktion (FX · Skill · Agent) lebt einmal im Kanon-Katalog mit Vertrag {scope · i18n · produkt · vertraulichkeit}. Die Seite konsumiert sie per Slug — nie neu programmiert.
↳ Diese Funktions-Landschaft IST das „② Funktionen"-Regal des Kanon-Katalogs im Seitenbau-Konzept. Die zwei Dokumente greifen ineinander.
Präzisierung (JC-Frage 13.07.): Eine „Karte" ist kein freies Template, sondern ein Daten-Vertrag: der Agent liefert Daten + einen Typ (render_hint) — NIE Markup (R-92). Der Renderer bindet jeden Typ an GENAU EINEN kanonischen Baustein. Deshalb ist die Tabellen-Karte (data-table: Suche · Sortierung · Multiselect · Pagination) etwas völlig anderes als die Klärungs-Karte (klaerung-card: R-94-Raster, Quell-Links, Entscheidung) — zwei Bausteine, zwei Verträge, EIN Prinzip. Definiert sind die Verträge in CARD_SCHEMA_REFERENCE.md (AGENT-CHAT#01, #697) + kai_renderer.js (Chat) + engine.js BAUSTEIN/POLICY (Sektionen); die Mensch-Sicht je Baustein steht in der Komponenten-Landkarte.
| render_hint (Daten-Typ) | Was der Agent damit sagt | Kanonischer Baustein | SSOT |
|---|---|---|---|
| result_card | generische Treffer-/Listen-Antwort | result-table | kai_renderer.js · CARD_SCHEMA §1 |
| contract_card | ein Vertrag (Fristen, Betrag, Status) | ds-card (Kanon-Hülle) | CARD_SCHEMA §2 |
| month_summary_card | Monatsstand (Kennzahlen-Block) | kpi-block | CARD_SCHEMA §3 |
| account_status_card | Konten GRUPPIERT (Karten-Flut-Fix; IBAN maskiert R-51) | account-status-card | CARD_SCHEMA §4 (#695) |
| next_actions_card | priorisierte nächste Aktionen (Aggregat) | vorschlags-chips + Liste | CARD_SCHEMA §5 |
| travel_summary_card | Reise-Zusammenfassung (RKA) | ds-card | CARD_SCHEMA §6 |
| approval_card | Schreib-Freigabe (Write-Pfad: „noch nichts gespeichert", Bestätigen rechts) | approval-card (R-94) | CARD_SCHEMA §7 |
| klaerung_card | Klär-Fall als bedienbare Karte (8 Fall-Typen, Quell-Links Beleg+Buchung) | klaerung-card | kai_renderer.js (PLAT#03 #727) |
| prose · list · dataTable · approval | die 4 Antwort-FORMEN des Sektions-Renderers (Policy pickComponent wählt — nicht der LLM) | long-prose · data-table (voll: Suche/Sort/Multiselect) | engine.js BAUSTEIN/POLICY |
| memoir_fiche · souvenir · etappe5 · photo · synopsis | gabriels Karten — GLEICHES Prinzip, eigener Wortschatz (Achse TGV-weit, Vokabular je Mandant) | ds-card · beleg-preview · audio-line | gabriel.html render_hints |
Bindung: der Agent wählt den TYP · Policy/Renderer wählen den Baustein · der Harness prüft das Ergebnis (R-92: kein Schema-injiziertes Markup · R-91: keine nackten IDs). Neuer Karten-Typ = neuer Vertrag in CARD_SCHEMA + Baustein im Katalog — nie ein Ad-hoc-Template im Screen.
Wer denkt — je Kontext ein Agent, EINE geteilte Engine, adaptive Persona.
| Agent | Rolle | Kontext / Wo | Stand |
|---|---|---|---|
| CORE-CHAT | Adaptiver Orchestrator — plant + ruft ~10 Lese-Tools | CORE · RKA · Steuer · Vertrag | staged |
| AGENT-ORCH#01 | LLM-First Triage — Dokument → Klassifikation/Entität | Intake-Pipeline (Shadow) | shadow |
| Klärung-Agent | Klärungs-Logik + Karten (list_pending → Envelope) | Klärung-Screen | skill live |
| Persona (adaptiv) | Ton/Verhalten je User+Mandant, editierbar (prompt_config) | CANON_LAYER im Prompt | live |
| FACH-AGENT je Dokumentart | Übernimmt NACH der Triage: füllt die Pflichtfelder seiner Dokumentart, setzt die Vertraulichkeit fachlich, knüpft die Verbindungen (Rechnung ↔ Vertrag ↔ Projekt ↔ Begünstigte). Darf ein stärkeres Modell nutzen als die Triage. | Intake-Kaskade, nach ORCH — Zuständigkeit aus der Registry, nicht hartcodiert | Kanon 04.08. · Bau offen (#303) |
| Gabriel | Eigenes Produkt (Biografie/Lebenserinnerung) | gabriel.html | live |
Warum das keine Komfort-Frage ist (der Kosten-Beweis, E-48/#301): KAI fragte JC sinngemäß „ist diese Versicherung vertraulich?" — gemessen waren alle 4 Hiscox-Verträge samt 16 rag_chunks pauschal streng_vertraulich, das Dokument selbst null; die Stufe entstand beim Ingest, pauschal. Ein Fach-Agent hätte erkannt: reine Betriebs-Versicherung ⇒ entitäts-intern. Die fehlende Kaskade kostet nicht Komfort, sondern Datenqualität und Nutzbarkeit — sie sperrt KAI aus den eigenen Verträgen aus.
Reuse statt Neubau — der Mechanismus existiert bereits: 08_OPS/chat_engine/gateway.py:17-21 hat die Tier-Tabelle trivial → haiku · standard → sonnet · komplex → opus und wählt heute „pro Anfrage das BILLIGSTE Modell, das die Anforderung erfüllt" (gateway.py:3). Es fehlt kein Getriebe, nur ein Anspruch: eine ROLLE muss einen Tier beanspruchen dürfen. Das Baseline-Protokoll MODELLWAHL01_BASELINE_2026-08-02.md denkt Modellwahl bisher ausschließlich kostenoptimierend, nicht rollenbasiert.
doc_type → Fach-Agent → Skills → Pflichtfelder → Modell-Tier.02_SKILLS/_registry.yaml, erweitert um eine routing:-Achse — plus ein generiertes DB-Read-Model für die Laufzeit (Sync-Richtung Code → DB, nie zurück; dasselbe Muster, das für die Taxonomien schon entschieden ist, Taxonomie-Register)._registry.yaml ist bereits „DIE eine deklarative Wahrheit für Skill → Verdrahtung" und generiert + validiert heute schon 6 zuvor divergierende Listen (_registry.yaml:1-16); es ist der einzige Kandidat mit einem laufenden Guard (08_OPS/validate_skill_registry.py, „Drift = exit 1"). ② Es weiß schon, dass contract-extract den Ghost ersetzt (_registry.yaml note zu contract-extract) — die Wahrheit steht da, nur liest sie niemand. ③ Gemessene Gegenprobe: eine doc_type-Achse hat es heute nicht (0 Treffer auf stream/doc_type) — die Erweiterung ist echt, nicht eingebildet. ④ Die Alternative 08_OPS/agent_orch01/taxonomy.py:60-88 trägt zwar schon STREAM → SKILLS, ist aber hartcodiertes Python (R-168) und ausdrücklich die Vergleichs-Vorlage für den Agenten, nicht die Betriebs-Wahrheit. ⑤ Eine Tabelle skill_routing_rules existiert ausdrücklich nicht (PIPELINE_A2_MAIL_INTAKE.md:166,270) — deshalb Read-Model statt Neuerfindung._registry.yaml hat sehr wohl ein Muster für „Vertrag da, Bau woanders" — class: n8n + n8n_wf_id + bundled:false/version_tracked:false (_registry.yaml:322-345 auf master, dort 3 Einträge). ⛔ Und die Angabe des Refs ist hier keine Pedanterie, sondern der ganze Unterschied (R-181): das Feld repo_dir: false — das den Verzeichnisbaum-Check genau für diesen Fall entschärft — existiert auf master NICHT (0 Treffer), auf dem ungemergten AGENT-ORCH#01-Branch claude/great-bell-6afe55 aber 18× (n8n_wf_id dort 31×). Dort ist extract-contract-pdf bereits ein echter skills:-Eintrag (class: n8n · repo_dir: false · n8n_wf_id: 5jYCxB9NzqyRMqjI, Notiz „n8n-Workflow AKTIV, aber 0 Executions"). „Gibt es nicht" wäre also falsch gewesen — richtig ist „auf master noch nicht". Die echte Grenze ist eine andere und schärfere: der Ghost tgv-extract-contract-pdf steht dort ausschließlich als Kommentar im Block „Referenziert, aber NICHT implementiert" — ausdrücklich „bewusst NICHT als skills:-Eintrag (sonst bricht der Verzeichnisbaum-Check)" und „von beiden Parsern ignoriert" (_registry.yaml:436-449). ⇒ Es fehlt nicht die Versionierung, sondern der Guard hat dort eine bewusste Parser-Blindstelle: ein Offline-Guard kann belegen, dass ein Routing-Ziel kein skills:-Eintrag ist — nicht, dass es nirgends existiert, denn die Fälle, die er finden müsste, sind genau die, die als Kommentar unsichtbar gemacht wurden. Dieser Befund gilt unabhängig vom Ref — der Kommentar-Block steht auf master und auf dem ORCH-Branch (dort :628-630). ⚠️ Und dort erzeugt der Fix einen Widerspruch mit sich selbst: 260 Zeilen über dem Kommentar, der sagt „bewusst NICHT als skills:-Eintrag", steht der Skill inzwischen als skills:-Eintrag. Beim Merge muss der Kommentar mit weg, sonst behauptet die SSOT beides gleichzeitig. Genau daran ist unsere eigene Annahme zerbrochen (siehe Korrektur in §4c: der „Ghost" hatte einen aktiven n8n-Workflow). Die routing:-Achse ist erst vollständig, wenn ALLE Ziele als skills:-Einträge geführt werden — auch die n8n-Skills, für die das Muster bereits existiert; bis dahin ist jede Ghost-Prüfung eine Teil-Prüfung und muss sich als solche ausweisen (R-160: die dritte Antwort ist n/a, nicht grün). Der Bau-Weg ist damit kleiner als gedacht: nicht „Versionierung für n8n erfinden", sondern das vorhandene class: n8n-Muster auf die fehlenden Ziele anwenden und den Kommentar-Block leerlaufen lassen.
prompt_config id=31 führt bereits [contract-extract, tgv-store-file-to-drive]). Eine SSOT, die ihren eigenen erledigten Stand als offen führt, schickt den nächsten Leser auf die falsche Fährte — dieselbe Klasse wie R-146. ② Derselbe Block nennt den Flip „JC-gated" — nach R-180 und JCs Wortlaut „Ich gate nix." ist auch das eine erfundene Freigabe-Instanz, diesmal nicht im UI, sondern in der Verdrahtungs-Wahrheit selbst.JCs Satz „alles ist da, aber nicht verdrahtet" ist belegt: TGV -App files/TGV_AGENT_SPEC_CONTRACTS_V2.md (13.04.2026) beschreibt exakt die Kaskade — Haupt-Triage delegiert an fünf Spezialisten. Zu ERNTEN, nicht neu zu erfinden (NUXIN-N②); jede Zeile mit ehrlichem Ist-Stand.
| Baustein aus dem Blueprint | Was er leistet | Ist-Stand in TGV (gemessen 04.08.) |
|---|---|---|
| 5 Sub-Agenten | Finance (Tranchen, Budget, IBAN-Betrugsschutz) · Legal & Deadline (Kündigungsfenster, Widerspruch, Alert 5 Tage vorher) · Digital-Asset/Subscription (Zombie-Abos, Domain-Ablauf, Auto-Verlängerung) · Real-Estate (umlagefähige Kosten, Hausgeld-Vorjahresvergleich) · Document-Completeness (Checklisten, z. B. Schlussrechnung braucht Abnahmeprotokoll) | nicht portiert kein Begriff „Fach-Agent" im Kanon (KONZEPT_AGENTEN_INSZENIERUNG.md:16-24 kennt nur ORCH · TOKEN · Dokumentalist) |
context_summary | Lebendes Gedächtnis je Vertrag (bis 4000 Zeichen): „Mängelrüge offen", „Tranche 2 bezahlt" — jeder Sub-Agent liest es, bevor er handelt | nicht portiert |
priority_score | Dringlichkeit aus Fristnähe × finanzieller Wirkung — schützt GF-Zeit, statt alles gleich laut zu melden | nicht portiert |
kb_contracts_patterns | Lernschicht: klassifiziert der Mensch ein unbekanntes Dokument, werden Muster/Keywords gespeichert — das System lernt | ⛔ existiert NUR als Name in einer RLS-Liste (05_SCHEMA/157:66,115) — nie mit CREATE TABLE angelegt |
| Rollentrennung Extraktion ≠ Bedeutung | „Was steht im Dokument?" ≠ „Was bedeutet der Vertrag operativ?" (Betriebs-/Projekt-/Privat-Klassifikation, Split-Beneficiaries, Wealth-Relevanz) | halb Extraktion live (contract-extract), die Bedeutungs-Hälfte fehlt — TGV_CONTRACT_PROFI_SKILL_ARCHITECTURE_v0100_20260423.md:16-45 |
08_OPS/agent_orch01/taxonomy.py:61,77 routet VERTRAG auf tgv-extract-contract-pdf — genau den Namen aus dem Blueprint (TGV_CONTRACT_PROFI…:18). Implementiert wurde stattdessen contract-extract (02_SKILLS/tgv-skill-contract-extract/skill.py, Endpoint app.py:1343-1360), und die Skill-SSOT weiß das auch („ersetzt Ghost tgv-extract-contract-pdf, Audit #479"). Nur die Vergleichs-Konstanten zeigen weiter auf den Plan statt auf den Bau. Regel: R-179. Zugehörig offen: der Routing-Flip (VERTRAG_01…/build/LIFT.md Schritt 3) ist nie abgehakt.
prompt_config id=31 führt für Vertrag ["contract-extract", "tgv-store-file-to-drive"] — 0 Ghost-Treffer in der gesamten Live-Taxonomie; und tgv-extract-contract-pdf hat sogar einen aktiven n8n-Workflow („Extract Contract PDF v0.5", 0 Executions). „Ghost" hieß also kein Python-Skill — nicht „nichts vorhanden". Der Live-Pfad ist lückenlos.
prf_contracts.project_id 0 belegt, direction 1 von 190 (Felder da seit Mig 193/195, kein Agent schreibt sie), mandant_id default 'jcbinetti' (Mig 193) = kein echter Multi-Mandant-Fill.
contract-extract wird geplant, aber nie ausgeführt. Null agent_events; alle drei seit dem Flip durchgelaufenen Verträge sind ohne ihn verarbeitet worden (AGENT-ORCH#01, 04.08. 01:24 UTC). Deshalb ist prf_contracts leer — nicht wegen eines Ghost-Namens. Damit wird die Reihenfolge-Auflage stärker, nicht schwächer: der Verträge-Screen zeigt leere Felder, weil der füllende Skill nie läuft. Ein Screen kann das nicht heilen, und ein Bug-Report gegen den Screen würde am falschen Ende ansetzen. ⚠️ Hypothese, nicht gemessen Warum er nicht läuft (Verdacht Reader-Gate BR#03) ist noch nicht belegt — bis dahin ist die Ursache „er läuft nicht" Tatsache, die Erklärung „weil …" nicht.JC 04.08. (Anlass, sinngemäß): „Der alte Matcher sollte auch lernen. Ziel ist, dass durch die Klärung und die Konversation mit dem User das System lernt und ORCH und die anderen Agenten immer bessere Entscheidungen treffen." — dazu die Frage, ob das verdrahtet ist. Gemessene Antwort: der Kreis ist eine offene Linie.
| Stufe | Stand | Fundstelle |
|---|---|---|
① Erfassen — Korrektur → learning_events | ⚠️ Sediment | 87 Zeilen / 36 Korrekturen, aber Backfill/Bulk — 0 aus dem Chat (DATEN#01, live 10.08.) ⇒ „User korrigiert seit Monaten" widerlegt. 05_SCHEMA/050 · Schreibpfad tgv-skill-klaerung/skill.py:156,558,630,683 |
② Verdichten — → kb_suppliers/pattern_rules | ❌ Promoter läuft NIE | pattern_rules=0 · Promoter (Windows-Task nie eingerichtet, 0 agent_events) liest learning_events gar nicht — Mining ist per SKILL.md:78 auf „Iter 18+" vertagt. Schwellen 05_SCHEMA/057 · View v_pattern_rules (025) |
| ③ Zurücklesen + Anwenden | ❌ DREIFACH offen | readback.py DRY („schreibt NICHTS") · Live-Engine erkennt 200+, wendet 0 an (stempelt nur skills_done_versions). Scharfschaltung E5R3_…STAGED.sql · Details in der Fortschreibung 4d· unten |
Warum AGENT und nicht Skill: Sortieren unter Mehrdeutigkeit ist eine Entscheidung, keine Handreichung (Skill = Hand · Agent = Gehirn). Auftrag in fünf Schritten: ① aufnehmen (einmal) · ② dreifach klassifizieren — Mehrfachzuordnung ist der Normalfall, nicht die Ausnahme (§4e) · ③ weiterreichen an den zuständigen Ort · ④ verdichten mit Korroborations-Gate — eine einzelne Korrektur ist noch keine Regel · ⑤ rückwirken — genau die heute fehlende Stufe ③.
readback.py; staged die Scharfschaltung; offen sind KVP-Status-Screen (#254), der Daumen (#302, zu ernten) und kb_contracts_patterns (nie angelegt, nur Name in 05_SCHEMA/157:66,115). ⇒ Der Aufwand liegt in Scharfschaltung, Scope-Achse und Agenten-Rolle — nicht in neuer Infrastruktur.learning_events trägt weder mandant_id noch entity als eigene Spalte (05_SCHEMA/050: user_id · created_at · context_doc_id · context_txn_id · decision_id · skill_name/-version · field · system_suggestion · user_choice · was_correction · confidence_pre/post · source · notes · raw_payload). entity kommt dort nur als möglicher Wert von field vor — das System lernt also über Entitäten, weiß aber nicht, in welcher es gelernt hat.context_doc_id → documents.entity → entities.slug → entities.mandant_id (Mig 209; documents hat selbst keine mandant_id, 05_SCHEMA/196:12 „Mandant wird über entity geführt"). ⛔ Und dieser Bezug ist vergänglich: beide Kontext-Fremdschlüssel stehen auf ON DELETE SET NULL — wird das Dokument gelöscht, verliert das Lern-Ereignis rückwirkend seinen einzigen Scope-Bezug. Ein Muster, das später daraus verdichtet wird, ist dann nicht mehr zuzuordnen.Die Stufen ①–③ oben stimmen im Gerüst — KVP#01 hat sie live gegengemessen (mit DATEN#01) und drei Dinge geschärft: der Kreis ist an drei Stellen offen, nicht an einer · JCs Feld-Vision war schon gebaut und ging verloren · und die Ablage dafür braucht ein eigenes Zuhause, kein fünftes Vokabular.
learning_events → pattern_rules — der Übersetzer läuft nie: der Promoter ist ein Windows-Task, nie eingerichtet (0 agent_events), und er liest learning_events ohnehin nicht (Mining auf „Iter 18+" vertagt, tgv-skill-pattern-promoter/SKILL.md:78).pattern_rules → Engine — die Regeltabelle wird nicht gelesen: die Live-Engine TGV_Skill_Pattern_Engine_v0_2 liest kb_suppliers/documents, nie pattern_rules/v_pattern_rules.Engine → Dokument (das teuerste) — die Engine stempelt nur skills_done_versions und schreibt entity/category nie zurück. „200+ Entscheidungen" heißt: 200+ mal erkannt und gemeldet, 0 mal angewandt. Das System erkennt seit Monaten Muster und tut nichts damit.contract_agent) gab dem alten Vertrags-Agenten den Prompt „entscheide selbst, was für DIESEN Vertragstyp relevant ist" + die jsonb-Ablage prf_contracts.extracted_data — genau JCs selbst-lernendes Feld. Der heutige tgv-skill-contract-extract nennt extracted_data 0× (git log -S = 0; Skill neu in 0afb6525 „VERTRAG#01" #498). ⇒ Kollateralschaden beim Neubau, nicht Absicht — die Fähigkeit lebte im Vorgänger, die Neuschrift begann leer. NUXIN-N② in Reinform: nicht was gelöscht wurde ist die Gefahr, sondern was beim Neubau nicht mitkam.Zwei Lern-Dimensionen, zwei Zuhause (Tower#35 entschieden 10.08.):
| Dimension | Zuhause (entschieden) | Was zu schließen ist |
|---|---|---|
| A · provider → {entity, category} | kb_suppliers — Live-Substrat, NUXIN „bau auf was läuft" (256 Zeilen, von der Engine gelesen) | (a) learning_events-Korrekturen → kb_suppliers-Upsert · (b) ⭐ die Engine muss ANWENDEN statt stempeln — das ist die eigentliche Arbeit |
| B · Feld/Datum (JCs Vision) | pattern_rules wiederbeleben (scope='extraction' im CHECK, Seeds da) — NICHT kb_suppliers, NICHT neue Tabelle | Leser bauen (= derselbe Aufwand wie neue Tabelle, aber kein 5. Vokabular) + jsonb-Beutel auf documents als Rohstoff-Eingang |
kb_suppliers hat PK (pattern, entity) — keine doc_type-Achse, kein field/date-Selektor; seine Datumsspalten (renewal_date, last_seen) sind Werte über einen Lieferanten, keine Meta-Regeln welches Feld zählt. Feld-Lernen dort hineinzuzwingen wäre der Wildwuchs-Fehler. Die Scope-Achse (§8b-Objekt) gehört an beide Zuhause: kb_suppliers hat entity schon, das Feld-Zuhause bekommt sie neu.Vier Lücken für Dimension B (in §4d bisher nicht benannt):
| Lücke | Befund (Fundstelle) |
|---|---|
① kein Feldbeutel auf documents | Verträge haben extracted_data (applied); documents nicht — ai_suggestion=TEXT (nicht GIN-abfragbar), media_meta STAGED (Mig 239) |
| ② ORCH-Vertrag fragt kein Feld | SAFE_AGENT_PROMPT (agent_loop.py:73) = doc_type·stream·entity·skill_plan — kein Datum (Register #337/N) |
| ③ keine Brücke Feld-in-N-Docs → Spalte | learning_events zählt Korrekturen, nicht die Häufigkeit gesehener Felder |
| ④ RAG speichert, gibt nicht zurück | rag.chunks.source_meta existiert (Mig 028), rag.search_chunks gibt es nicht zurück — JCs „im RAG-Chunk" halb gebaut |
entSameScope() für Felder. Der Beutel nimmt alles (nichts verloren), aber Beförderung zur Spalte setzt Kanonisierung voraus; unkanonisierte Schlüssel bleiben sichtbar+gezählt, aber in Quarantäne — omission_catalogue-Haltung (annotieren, nie still auffüllen).tunable_params (owner_tier=super_admin, is_interim; JC ändert per Zeile, kein Deploy). ② Kandidat automatisch, Spalten-Promotion = JCs Hand (DDL-Kanon); die Vorlage MUSS die Herkunft zeigen („in 23 Docs über C3+C4 gesehen, Beispiele…"). ③ Kanonisierung-vor-Beförderung (Feld-Taxonomie als Wand). ④ scope-CHECK um 'entity' zurückgenommen (Entität läuft über kb_suppliers; 'extraction' existiert schon). ⑤ v_pattern_rules pattern_rules unionen nur im Zuge von Dimension B — heilt nur den DRY-readback, kein Live-Fix.JC-Modell, bindend: Dieselbe Äußerung ist gleichzeitig drei Rohstoffe. Sie wird einmal aufgenommen und dreifach ausgewertet — nie dreimal erfasst. Wer sie nur als Fehler-Ticket behandelt, verliert Brille C; wer sie nur ablegt, verliert Brille B.
| Brille | Frage | Rohstoff | Ertrag |
|---|---|---|---|
| A · Antwort-Qualität | War die Antwort gut? | Antwort + Bewertung (Daumen, #302) + Dialog-Telemetrie: Tool-Wahl, Abbrüche, Nachfrage-Ketten, Token | Neuer Lern-Input — u. a. gegen die Klasse „unbemühte Absage" (E-42.C: KAI kapituliert, statt das passende Werkzeug zu wählen) |
| B · System-Verbesserung | Was sagt es über TGV? | JC-Befunde · Klärungs-Kommentare · KVP-Vorschläge (K-54) · UX-Auditor | Register-Zeile · Regel · Komponente · Kanon · Skill-Bedarf. ⚠️ Heute die einzige halbwegs laufende Brille — und sie läuft über Tower-Handarbeit |
| C · Digitaler Zwilling | Was sagt es über User, Projekt, Entität, Vorgang? | Zuordnungs-Gewohnheiten · Lieferanten-Muster · Orts-Repertoire · Vertraulichkeits-Urteile | Das Lebensgedächtnis — Grundlage dafür, nie zu fragen, bevor die Maschine fertig geprüft hat (E-26) |
JC-Auftrag 04.08. (Register #328): „Wer sie sind, was sie können, was sie machen, welche Skills sie abrufen, wie sie alle miteinander gut zusammenspielen. Die Workflows, Cascading und Routinen dieser Agenten." — Die Bausteine standen verstreut über acht Kompendium-Seiten; was fehlte, war die eine Ansicht. Diese Seite erfindet nichts: jede Zeile zeigt auf ihren SSOT, die Definition bleibt dort. ⛔ Und jede Zeile trägt ihren ehrlichen Zustand — läuft · gebaut, nicht verdrahtet · Konzept. Alles andere wäre R-188.
Core-Graph-Anschluss (JC 25.09.2026, #3120; geschrieben). Diese Landkarte liefert Rollenbegriffe, keine ungeprüfte Live-Topologie. Für den neuen Core-Graphen in KAI und Shell müssen Rollen, tatsächlich verfügbare Skills, Aufrufberechtigungen und beobachtete Ausführungen gegen den aktuellen Bestand abgeglichen werden. Entwicklungs-Lanes sind keine Laufzeit-Agenten; ein Skill-Registry-Eintrag beweist allein noch keinen Agenten-Aufruf. Historische n8n-/Drive-Verweise werden weder still zum Core-Ist erklärt noch aus dem weiterhin bestehenden Dashboard-Modell entfernt. Der Gesamtworkflow eines neuen Dokuments (§7f) ist der zweite fachliche Ausgangspunkt, mit gesondertem Nachweis je tatsächlichem Ausführungsschritt.
| Agent | Was er kann · was er tut | Skills / Werkzeuge, die er ruft | Stand (ehrlich) |
|---|---|---|---|
| KAI · Chat-Agent | Hauptdarsteller und Dirigent. Analysiert laufend, was jetzt für den User wichtig ist, wählt die Darstellung aus der Komponenten-Bibliothek und führt das Gespräch über alle Modalitäten — Tippen, Klick, Mail, Upload, Trigger | Lese-Executoren (query_documents · get_transactions · search_knowledge_scoped) · Antwort-Renderer | läuft agent_loop.py |
| ORCH-Agent | Bühnenmeister hinter den Kulissen: Intake · Triage · Klassifikation · Re-Triage. Sagt, worum es geht — nicht, was es bedeutet | Skill-Router mvOybw4cBU7y8X5Y (v0.7.4) · classify-csv · detect-duplicate · resolve-supplier | läuft |
| FACH-AGENT (je Dokumentart) | Der Spezialist nach der Triage: füllt die Pflichtfelder seiner Dokumentart, setzt die Vertraulichkeit fachlich, rechnet Fristen, knüpft Verknüpfungen (Rechnung ↔ Vertrag ↔ Projekt). ⛔ Darf ein stärkeres Modell rufen — Modellstärke folgt der Rolle, nicht dem Preis | contract-extract · pdf-invoice-extract · tax-extract · upsert-contract-from-invoice | Vertrags-Instanz läuft und schreibt wieder (04.08. belegt) · Registry offen (#303) |
| TOKEN-Agent | Produzent und Budget: bestimmt Modell, Aufwand, Kosten/Nutzen und hält die Inszenierung wirtschaftlich | gateway.py Tier-Tabelle | läuft, aber rollen-blind — wählt „das billigste Modell, das reicht"; der Rollen-Anspruch aus R-178 fehlt noch |
| UX-Agent | Bühnenbildner und Dramaturg: besitzt und vergrößert die Komponenten-Bibliothek, prüft jede Darstellung dagegen — Lücke ⇒ Bibliothek wächst ⇒ alle erben | Komponenten-Landkarte (65 K-IDs) · Konformitäts-Guard | läuft AGENT-UX#01 |
| Dokumentalist | Archivar: Ablage und Verschieben, prüft jede Bewegung. ⛔ Verschieben ist eine Freigabe-Handlung — der Ordner trägt die Reichweite, die Datei erbt sie (K-41). JC E-55: „Der Dokumentalist sortiert danach" — erst einstufen, dann sortieren | store-file-to-drive · (Bewegungs-Skills offen) | GESPERRT bis der Gabriel-Schlüsselbauer mandantenfähig ist (#323) — sonst Sisyphos |
| KVP-Agent | Nimmt jede Korrektur einmal auf und wertet sie dreifach aus (Antwort-Qualität · System-Verbesserung · digitaler Zwilling), verdichtet mit Korroborations-Gate und wirkt zurück in Triage und Fach-Agent | learning_events (Mig 050) · pattern-promoter · readback.py | Konzept (E-52) — Loop ~70 % gebaut, 0 % geschlossen: Zurücklesen ist DRY |
| WIZARD-Agent | Konfiguriert einen neuen Mandanten im Dialog, bis eine frische TGV-Oberfläche steht — inkl. diktiertem Erst-Interview (Firma, Vorhaben, Entitäten) als Teil des digitalen Zwillings. ⛔ JC: „nicht nur die Initialisierung" — er bekommt viele Aufgaben | audio-transcription · conversational-input · (Konfig-Skills offen) | Konzept (E-58); Persona-/Onboarding-Wizard existiert als Vorstufe |
| SCREEN-BUILDER -Agent | ⭐ Das Ziel hinter allem (E-53): baut Seiten allein nach der Intention des Users. Rollenbild JC: „Der User ist der Gestalter, KAI ist Berater, Web-Designer, Coder." | Screen-Factory-Vertrag · K-IDs · SCREEN_COMPOSER (5 Gates) | heute Playbook/Skill, nicht Agent — und er erklärt rückwirkend die ganze Kanon-Härte (s. u.) |
| Telemetrie-/Lern | Souffleur: macht das Stück besser (User · Mandant · TGV), pseudonymisiert | agent_events · Dialog-Telemetrie | existiert |
| Initiative | Proaktiv: Alerts und Vorschläge aus dem Ereignis-Strom | — | Vision |
| ⭐ HISTORIKER | Schaut zurück: „Das gab es schon — damals ging es so aus." Antwortet auf jede Absicht vor dem Plan · schreibt nach dem Lauf zurück · verdichtet (Doppeltes zusammenführen, Veraltetes stilllegen, Narben behalten) · meldet Widersprüche, statt sie zu glätten. ⛔ Sitzt an der Absicht, nicht an der Frage. Hütet Ebene ③ — nie ② mit Fall. §6 | Konzept-Index · Register · Katalog · screen_factory_contracts.json | Konzept (E-69) |
| ⭐ VERDRAHTER | Schaut vorwärts: „Das wurde beschlossen — hier fehlt es noch." Kein Beschluss bleibt ohne Wirkort. Jede Konzept-Aussage bekommt Eigentümer + next_guard, sonst gilt sie als geschrieben, nicht als beschlossen · meldet, was seit N Tagen beschlossen und unverdrahtet ist · ⛔ baut nicht selbst — er benennt und mahnt. §6i | Guards · Register · Roadmap-Gates | Konzept (E-69) |
Die Regie, Schritt für Schritt (SSOT: KONZEPT_AGENTEN_INSZENIERUNG.md): ① Der User kommuniziert mit KAI — durch Tippen und Handeln. ② KAI dirigiert: was ist wichtig? → holt Daten → wählt die Darstellung → der TOKEN-Agent bestimmt Modell und Aufwand. ②b Nach der Triage übergibt ORCH an den Fach-Agenten der Dokumentart — und der darf einen höheren Modell-Tier beanspruchen. ③ Der UX-Agent wirkt vorab und laufend. ③b Nach jedem Ergebnis und jeder Klärung übernimmt der KVP-Agent und schließt den Kreis. ④ Dokumentalist, Wizard, Telemetrie, Initiative treten ein, wenn ihre Sorge dran ist. ⑤ Alles innerhalb des Scope-Gates — die unverrückbare Bühnengrenze, fail-closed, die kein Agent überschreitet.
doc_type → Fach-Agent → Skills → Pflichtfelder → Modell-Tier. Heute lebt die Zuordnung verteilt (n8n-Router-Map, prompt_config, Python-Fallback) — deshalb konnte ein Routing-Ziel monatelang auf einen Namen zeigen, den es als Python-Skill nie gab (R-179).| Routine | Auslöser | Stand |
|---|---|---|
| Intake → Triage → Klassifikation | Mail-Eingang · Upload · Drive · Foto | läuft automatisch (Skill-Router v0.7.4) |
| Fach-Extraktion (Vertrag) | nach der Triage, je Dokumentart | läuft — schreibt seit 04.08. wieder |
Klärung → User-Entscheidung → learning_events | Klärungs-Karte im Dialog | läuft (Erfassen ✅) |
| Muster verdichten → zurücklesen | Korroborations-Gate | Promoter da, pattern_rules leer; Zurücklesen DRY |
| ⛔ Wissens-Index (RAG) | sollte am Ende der Kette laufen | es gibt KEINEN automatischen Ingest — der Index wird von einem handgestarteten Python-Skript gepflegt (#311) |
| Ablage aufräumen | Dokumentalist | gesperrt bis #323 |
doc_type · entity · provider · skill_plan — seit 08.08. auch die Vertraulichkeitsstufe. Modellwahl folgt der Rolle (R-178).
Was das System TUN kann — die wiederverwendbaren Bausteine (R-V4-19: nie neu programmieren). Gruppiert; Quelle: Skills-Registry. → Jeder EINZELNE Skill (Name · Endpoints · Verdrahtung, such-/filterbar): Skills-Register (43, generiert aus _registry.yaml).
| Gruppe | Skills (Auswahl) | Reichweite |
|---|---|---|
| Intake & OCR | pdf-invoice-extract · parse-docling · pdf-ocr-fallback · vision-extract · ocr-to-source · audio-transcription · store-file-to-drive | Pipeline-Backend |
| Klassifikation | classify-csv · classify-party-role · resolve-supplier · route-project-document · pattern-engine · tax-extract | Pipeline / ORCH |
| Abgleich & Dedup | reconcile-payment · detect-duplicate · contract-stub-safety-net | Buchungen-Screen + Agent |
| Verträge | contract-extract (live) · extract-contract-pdf · upsert-contract-from-invoice | Verträge-Screen |
| Wissen (RAG) | rag-ingest · rag-search · memory-search-chat · search_knowledge | „Kai fragen" (gated am CORE-CHAT-Flip) |
| Reisekosten (RKA) | create-trip · assign-beleg · calculate · render · versand · bmf-pauschalen · … (~13) | RKA-Cockpit (live) |
| Finanz & Steuer | import-banking-csv · monthly-closing-prep · tax-send-package · vat-currency | Banking · Buchhalter-Versand |
| Report & Audio | create-excel-report · create-drive-document · generate-cv · tts · audio-transcription | teils nur Gabriel/Backend |
| Lernen | record-decision · pattern-promoter · initiative-feed | Lernschleife (gesammelt, nie zurückgelesen — s. Kasten) |
~15 von 33 HTTP-Skills sind heute aus einem Screen erreichbar (dominiert vom RKA-Cockpit). Der Rest ist legitimes Pipeline-Backend ODER wartet auf den EINEN CORE-CHAT-Flip, der ~10 Lese-Tools auf einmal sichtbar macht.
08_OPS/check_lernschleife_ist_geschlossen.py).
Die Schleife hat vier Stufen, und drei davon laufen: ① learning_events wird gefüllt (gemessen 14.09.: 112 Zeilen, 40 Korrekturen — Felder entity 16 · skill_selection 10 · vat_treatment 6 · doc_type 3; Schreiber: tgv-skill-klaerung bis 08.09., KAI-Daumen bis 05.09., classify-party-role, tri02);
② readback.pattern_rules_candidates() (08_OPS/agent_orch01/readback.py) liest sie zurück und baut das Kandidaten-Set — schreibt aber nichts;
③ pattern_rules hat 0 Zeilen; ④ tgv-skill-pattern-promoter kann darum nichts befördern.
Welche Stufe liest zurück: nur ②, und nur trocken. Was ihr fehlt: derselbe Riegel wie dem Identifizierer — readback gehört zu agent_orch01 („ändert nichts live", Flip = JC-Wort).
Deshalb kein Bau vor Stufe 2: Stufe 2 (ORCH führt, #1910 Rang 3) muss ②→③ mitfreigeben — die Kandidaten von readback nach pattern_rules schreiben (Promoter-Schwellen aus Mig 057, trocken zuerst), und das Gehirn liest v_pattern_rules als Prior neben kb_suppliers. Ein Flip, der nur das Routing öffnet und die Schleife zu lässt, sammelt weiter Korrekturen, die niemand liest.
Lern-Box: „Read-Back" = die Korrektur des Menschen beim nächsten gleichartigen Beleg wieder vorlegen; „Promoter" = eine Regel erst nach genug Bestätigungen scharf schalten (Laplace-Vertrauen, Mig 057).
documents_routing_engine_check lautet gemessen CHECK (routing_engine = ANY (ARRAY['legacy','v2','orch'])) — Migration 283_riegel_c_routing_engine_orch steht seit 2026-09-15 in tgv_migrations. Der Satz „kennt nur legacy/v2" stand hier und im Wächter und wurde von dort ins Auftragsbrett kopiert. ⛔ „Ein Tor, zwei Symptome" gilt nicht mehr: die DB-Hälfte ist auf, die Modul-Hälfte (08_OPS/agent_orch01/__init__.py:14) ist ein Text-Riegel ohne Schalter — kein Flag, keine Zeile, die JC umlegt, sondern eine Absprache aus dem Juni. Gefahren ist trotzdem niemand: routing_engine='orch' hat 0 Zeilen (650 legacy · 258 v2). Eine mitgeschleppte Sperre lässt eine offene Tür wie eine verschlossene aussehen.
learning_events = 115 Zeilen (+17 seit der Wächter-Basis 07.09.), davon was_correction=true = 40, unverändert; die 17 neuen sind ausnahmslos field=doc_confirm, source=klaerung, was_correction=false. Die jüngste echte Korrektur ist vom 2026-09-05. ⇒ Nicht „die Schuld wächst um 17 Korrekturen", sondern: der Korrektur-Strom steht seit drei Wochen still — eine zweite, bis heute unbenannte Krankheit, die die erste Formulierung verdeckt hat. Wirkort des Fixes: 08_OPS/check_lernschleife_ist_geschlossen.py (Etikett getrennt, Tor gemessen statt behauptet, Selbsttest (5)/(6) mit Beißprobe).
pattern_rules hat im ganzen Schema genau einen Leser — ihren eigenen updated_at-Trigger. v_pattern_rules (351 Zeilen) unioniert gemessen pattern_rules_seed und kb_suppliers und nicht pattern_rules (Reichweite: alle Views/Matviews aller Schemata + alle Funktionen in public). ⛔ Selbst wenn der Riegel fiele und der Promoter schriebe, sähe die Engine nichts. Der Union-Punkt steht als Tower#35-Entscheid ⑤ vom 10.08. oben im Absatz 4d· („nur im Zuge von Dimension B") — er ist damit Voraussetzung der Schleife, nicht ihre Zugabe.KAI_QUALITAET_KVP_MONITORING_V1.md auf codex/kai-qa-testprogramm-20260925).
⛔ Die QA-Dateien unter 07_TESTS/kai_qa_corpus_100/ sind keine Live-Datenquelle. Wer auf ihnen baut, baut ein Schaufenster. Diese Tabelle ist gegen die Live-DB gemessen, nicht aus Migrationen gelesen.
| Feldgruppe (Vorgabe) | Live-Träger | Befund |
|---|---|---|
Bindung — turn_id, answer_id, conversation_id | nur learning_events.raw_payload (jsonb) | ❌ keine Spalte Mig 226 ist nicht appliziert (keine Zeile in tgv_migrations); chat_messages hat 6 Spalten, turn_id/llm_model/latency_ms fehlen. Schlüssel gezählt, nicht geraten: turn_id/answer_id/conversation_id in 6 von 115 Zeilen, model in 2, Latenz in 0. Bereits so gemessen am 03.08. (screen_factory_contracts.json → chat-historie.next_guard); 53 Tage später unverändert. Laufzeit-Sonde: 08_OPS/chat_engine/thread_store.py:171 has_turn_columns() |
Scope — mandant_id, entity_id, project_code | chat_sessions.scope_json · agent_events.mandant_id · chat_messages.envelope_json→scope | ⚠️ ungleich verteilt learning_events trägt keine Scope-Spalte (unverändert seit der 4d-Messung oben). chat_sessions.scope_json trägt mandant_id/entity/project_code/confidentiality_max in 146 von 146 Sitzungen — aber als JSONB, das keine Policy liest. agent_events.mandant_id: 12 280 von 44 654 Zeilen gefüllt (27 %). envelope_json→scope: 571 Antworten, Unterschlüssel mandant_id/entity/project_code/doc_scope/confidentiality_max |
| Messung — Modell, Latenz, Kosten, Werkzeugstatus | skill_call_costs (model/duration_ms/status/mandant_id) · agent_events.tool_* | ❌ für die Fläche unlesbar skill_call_costs hat genau eine Policy: skill_call_costs_service_all für service_role. ⇒ Kein angemeldeter Nutzer, auch kein super_admin, liest Kosten/Latenz aus dem Browser. Eine KPI-Kachel „Modell/Latenz/Kosten" wäre heute ohne Dienst-Endpunkt leer |
| KVP — Fehlerklasse, Befund, Retest, Tower-Commit | — | ❌ existiert nicht Reichweite der Suche: alle Schemata außer pg_catalog/information_schema/pg_toast, relkind r/v/m/p, neun Namensmuster (%retest% · %qa% · %befund% · %finding% · %kvp% · %turn% · %feedback% · %quality% · %qualitaet%) ⇒ 0 Treffer. Ein Retest-Register gibt es live nirgends; es liegt als Datei auf dem Codex-Zweig |
| Datenschutz — Pseudonymisierung für die Produktsicht | — | ❌ kein Feld, keine View Pseudonymisierung existiert heute nur als Satz im Konzept |
pg_policies, 25.09.): learning_events · agent_events · pattern_rules · audit_events tragen je eine einzige Policy für authenticated, und ihr Ausdruck ist is_global_admin(auth.uid()) — eine Ja/Nein-Wand ohne Mandanten-Achse. chat_sessions/chat_messages sind eigentümer-gebunden (user_id = auth.uid() oder global admin). ⇒ Ein mandant_admin (T3) sieht in allen vier Quellen heute NULL Zeilen, und zwar korrekt default-deny; die T3-Sicht der Vorgabe hat keinen Datenpfad, nicht nur zu wenige Daten. Und ein T4-super_admin, der über is_global_admin hineinkommt, sieht alle Mandanten roh — das ist das Gegenteil der geforderten pseudonymisierten Aggregation. Positivkontrolle der Messung: tgv_migrations 232 Zeilen, pg_class meldet relrowsecurity=true für alle zehn geprüften Tabellen, und 0 Basistabellen in public ohne RLS.
08_OPS/tgv-skills-service/app.py:6445 sagt im Klartext „Service-role PostgREST call (RLS bypassed — authoritative)"; die Gegenprobe im Schema steht in 05_SCHEMA/246:135 (prf_pnr_service_all … TO service_role USING (true)). ⭐ Auf dem Dienstpfad liegt die Wand in der ANWENDUNGSSCHICHT, nicht in der RLS — ein grüner RLS-Test wäre dort ein falsches Grün.
| Quelle | RLS-Policy (User-JWT-Pfad) | Pfad, über den die Fläche wirklich liest | Wo die T3-Wand liegt |
|---|---|---|---|
agent_events | is_global_admin — T3 sieht nichts | Service-Key über POST /api/skill/audit-log (app.py:8128) → _supa_rest (app.py:6445) | ✅ GEBAUT — nachschlagen statt bauen ep_audit_log ist der fertige Präzedenzfall genau dieser Wand: JWT-Pflicht (403 sonst) · _user_scope(auth.user_id) aus der Mitgliedschaft (app.py:6580, fail-closed, 15 s TTL) · mandant_id=in.(nur Mandanten mit Rolle mandant_admin/super_admin) · Default-Deny 403 ohne Mitgliedschaft · mandant_id IS NULL bleibt super_admin-only |
learning_events | is_global_admin — T3 sieht nichts | keiner — 0 GET-Endpunkte im Dienst (einzige Nennung app.py:4340 ist ein Kommentar); das Frontend schreibt nur über die RPC record_answer_rating | ❌ auf BEIDEN Pfaden zu kein Endpunkt und keine mandant_id-Spalte ⇒ auch der Anwendungscode-Weg ist heute nicht baubar. ⭐ Das macht Naht ① zum harten Blocker: sie blockiert nicht einen Pfad, sondern beide⭐ Stand 11.10.2026 (KAI-QA#03, #4029, JC „JA“ in #4023) — für die DAUMEN gibt es jetzt einen Leser: das KAI-Werkzeug daumen-durchsicht (TOWER#71: Fläche = KAI, Chatbot First; bewusst keine HTTP-Route) über 08_OPS/chat_engine/daumen_durchsicht.py, je Modell und je Dialog, Antwort als zwei Tabellen-Blöcke. Die Spalte mandant_id existiert inzwischen, ist auf allen 6 Daumen aber leer ⇒ die Wand hängt am Urheber (super_admin alle, jeder andere nur seine eigenen), nicht am Mandanten. Gegenbeweis live nur GET: super_admin 6/6, qa@/C3/C4 je 0 bei 6 fremden. ⛔ Ein Verwalter sieht die Daumen seiner Leute damit nicht — das wäre JCs Wort (#3550). ⛔ Das Modell fehlt auf 4 von 6 Altdaumen: chat_messages.llm_model ist erst seit kurzem gefüllt (67 von 728 Antworten). |
chat_sessions/chat_messages | eigentümergebunden user_id = auth.uid() | /api/skill/chat-threads, JWT-only + Ownership-Check | Eigentümer — bewusst kein Mandanten-Scope. Ein T3 sieht die Gespräche seiner Nutzer nicht, und das ist Absicht, kein Mangel |
skill_call_costs | nur service_role | Service-Key | ❌ zu bauen RLS kann hier gar nicht wirken — die Wand muss Anwendungscode sein, Muster ep_audit_log |
| Retest-Register | — | — | existiert nicht (s. o.) |
/verwaltung/kai-qualitaet braucht, bevor er gebaut werden darf — vier Nähte, keine neue Plattform:
learning_events (additiv, mandant_id/entity/project_code/geltungsebene, denormalisiert gegen ON DELETE SET NULL) — der Entwurf liegt seit dem 10.08. STAGED unter 01_ITERATIONS/KVP_01_LERN_LOOP/scope_achse.STAGED.sql und ist Voraussetzung, nicht Zugabe. ⛔ Ohne sie ist jede T3-Kachel entweder leer oder mandantenübergreifend.
ep_audit_log (app.py:8128-8171) — JWT-Pflicht, _user_scope aus der Mitgliedschaft, mandant_id=in.(eigene), Default-Deny 403. ⛔ Nicht neu erfinden: dieser Endpunkt ist der gebaute Präzedenzfall. Liest sie über User-JWT, braucht es zusätzlich eine zweite Policy aus der Mitgliedschaft (is_mandant_admin(auth.uid(), <mandant_id der Zeile>), Mig 252) statt is_global_admin. Default-Deny bleibt auf beiden Pfaden, und die RLS bleibt die Grundsicherung, auch wo der Dienst sie umgeht. ⛔ Gegenbeweis-Pflicht, dem Pfad folgend: der Fix gilt erst, wenn gemessen ist, dass ein eingeschränkter Nutzer die fremden Zeilen nicht sieht — gegen den Endpunkt, nicht gegen die RLS, wenn der Dienst liest. Heute nicht durchführbar, weil die QA-Sitzung von der Shell nicht angenommen wird (QA-AUTH-01, CODEX-KAI#01 Rang 1).
CREATE TABLE einer künftigen Befund-/Retest-Ablage braucht ENABLE ROW LEVEL SECURITY im selben PROPOSED-Skript — sonst spiegelt eine ungeschützte Tabelle geschützte Daten.
skill_call_costs (nur die DB-Seite ist gemessen) · ob ein n8n-Weg an der RLS vorbei liest.
vw-kai-qualitaet — und warum er heute NICHT in screen_factory_contracts.json steht.
Der Guard 08_OPS/check_screen_factory_contracts.py:129 verlangt für jeden Vertrag eine existierende file, und :148 einen visible_url_local, der auf eine vorhandene Datei unter 06_DASHBOARD/ zeigt. ⇒ Ein Vertrag ohne Screen lässt den Guard rot werden. Die Vorgabe sagt ausdrücklich „zuerst messen, nicht bauen" — beides zusammen heißt: der Vertrag lebt hier, bis der Screen gebaut wird, und wandert dann als Ganzes in die JSON. Kein zweiter Ort, keine zweite Liste.
| Feld | Wert |
|---|---|
id · route · screen_type | vw-kai-qualitaet · /verwaltung/kai-qualitaet · admin (im Kanon der neun Typen vorhanden — kein neuer Typ) |
| T3 · Mandantenansicht | Sieht nur den Scope der Mitgliedschaft des Aufrufers (user_mandant_roles, Mig 252 is_mandant_admin), nie Default, nie Hardcode. Inhalt: eigene Feedbacks · abstrahierte Fragenfamilien · Messreichweite · eigene offene Retests. ⛔ Heute ohne Datenpfad (s. RLS-Wahrheit oben) — der Screen wäre leer, nicht falsch, und muss das grau mit Reichweite sagen |
| T4 · Produktansicht | Pseudonymisiert und aggregiert über die berechtigten Mandanten — nie Rohgespräch als Analyse-Abkürzung. ⛔ Heute liefert is_global_admin das Gegenteil: alles roh. Die Pseudonymisierung ist zu bauen, nicht vorhanden |
| Datenquellen (nur diese) | Turn-/Antwort-Metadaten im autorisierten Scope · learning_events (Feedback) · agent_events (Technik) · Retest-Register. ⛔ Nicht 07_TESTS/kai_qa_corpus_100/ — Dateien im Repo sind kein Live-Screen |
| Pillen | Grau = nicht gemessen · Rot = Befund offen · Orange = begrenzt/offen eingeordnet · Grün = benannte Fragenfamilie unter benannter Version und Reichweite bestanden. Farbe allein trägt nie ein Urteil — Text, Reichweite und Zeitpunkt stehen daneben |
| Abnahme (die vier, die beißen) | ① Gegenbeweis: ein eingeschränkter Nutzer sieht die fremden Zeilen nachweislich nicht — sonst gilt der Scope nicht als gefixt · ② leere Datenlage ist grau mit Reichweite, nie grün · ③ jede KPI führt auf dieselbe Grundmenge · ④ ein Guard wird absichtlich verletzt und muss rot werden, bevor die Fläche als geschützt gilt |
| not_actions | Keine Prompt-, Modell-, Rollen- oder Regeländerung · keine globale Testausführung aus einer T3-Sitzung · keine stille Ausführung (Vorschlag · Freigabe · Vollzug bleiben getrennt) |
KAI_QUALITAET_KVP_MONITORING_V1.md · KAI_QUALITAETSKREISLAUF_V1.md · KAI_FEEDBACK_TELEMETRIE_KVP_INTEGRATION_V1.md, alle drei auf codex/kai-qa-testprogramm-20260925 und keine auf master.Der Abschnitt beantwortet JCs schärfste Frage: „Das Erinnerungsvermögen scheint mir das größte Problem, das wir in drei Monaten hatten." — und er ist kein Anhang, sondern die Klammer über allem darüber.
Was heute geschrieben wird, landet an sechs verschiedenen Orten: Anforderungs-Register (>350 Zeilen) · JC-Entscheide (E-1…E-68) · Kompendium (39 Seiten) · Roadmap-Board · Commit- und PR-Texte · und das private Gedächtnis des Agenten.
~/.claude/projects/…/memory/ — der Mensch kann sie weder finden noch lesen. Für ein Produkt, dessen Versprechen „dein Gedächtnis" lautet, ist ein Agenten-Gedächtnis ohne Lesezugang kein Merkmal, sondern eine Haftung. Es ist dasselbe Silo, gegen das TGV antritt — nur ein Stockwerk tiefer.
JC hat die Lösung selbst formuliert: „festzuhalten in wiederfindbarer, lesbarer Form, was wir als ABSICHT definiert haben, mit welchem VERTRAG es verankert ist, und mit welchem FERTIGUNGSGRAD wir es als Werkzeug anwenden können."
| Achse | Beantwortet die Frage | Existiert heute als | Fehlt |
|---|---|---|---|
| ABSICHT | Was wollten wir erreichen — und für wen? | JC-Entscheide (E-…) | ⛔ kein Objekt: keine Nummer, kein Zustand, kein Ergebnis, keine Spur |
| VERTRAG | Was ist zugesagt — und woran misst man den Bruch? | Katalog (K-IDs) · Regelwerk (R-…) · Skills-Registry | ⛔ nur für Oberflächen-Bausteine; Skills und Agenten haben keine Zusagen-Form |
| FERTIGUNGSGRAD | Wie weit ist es — und kann ich es benutzen? | Gates A–F auf dem Roadmap-Board | ⚠️ nicht je Gegenstand, nur je Screen/Lane |
Der Kanon dieser Woche lautet: Regeln werden müde, Prüfer nicht. Also sind es Bedingungen, keine Vorsätze.
| Regel | Warum |
|---|---|
| Kein privates Agenten-Gedächtnis | Was der Agent lernt, wird dort geschrieben, wo der Mensch es öffnen kann. Ein Gedächtnis, in das der Eigentümer nicht sehen kann, gehört ihm nicht. |
| Eine Sache, eine Adresse | Jede Absicht, jeder Vertrag, jeder Baustein hat eine aufrufbare Stelle — nicht Zeile 217 von 350. |
| Der Dreiklang ist Pflicht | Ein Gegenstand ohne Absicht, Vertrag oder Fertigungsgrad ist unvollständig — und ein Prüfer sagt das, statt dass es jemandem auffällt. |
| Rückfluss ist Teil der Arbeit | Jeder Lauf meldet, was gefehlt hat. Die Lücke ist der Kandidat für den nächsten Baustein — ohne sie wächst die Werkstatt nicht, sie füllt sich nur. |
| Schreiben am Wirkort, nicht im Bericht | Ein Beschluss, der nur im Gespräch lebt, zählt nicht. Diese Regel gibt es seit Juli — 6c macht sie prüfbar statt appellativ. |
Der Satz: In TGV formuliert der Mensch Absichten. Alles andere ist ableitbar — und was abgeleitet wurde, bleibt als Fähigkeit erhalten. Die Regel dazu: Eine Absicht ist ein Beleg — Nummer, Zustand, Ergebnis, Spur.
Absicht → Präzisierung → Plan → Verträge → Ergebnis → Rückfluss. Das Fundament sagt seit langem „LLM liefert Intent, NIE Markup" — bisher galt das nur für die Darstellung. 6d verallgemeinert es auf die ganze Kette.
| Schritt | Regel |
|---|---|
| Präzisierung | ⛔ Nur fragen, was den Bau VERZWEIGT. Ein Wizard, der zwanzig Dinge fragt, von denen achtzehn Standard sind, ist ein Formular mit Gesprächsanstrich. — Der Baustein dafür existiert (klHost/Klär-Karten), zeigt aber auf Dokumente statt auf Absichten. |
| Verträge | Je Zusage: gibt es das schon? Meistens ja. Was fehlt, wird gebaut und aufgehängt. |
| Ergebnis | ⭐ Gegen die ABSICHT prüfen, nicht gegen den Plan. Ein Test am Anfang bestätigt die Absicht, ein Test am Ende die Wirkung. |
Drei Teile: ① Absicht — was erreicht es für einen Menschen, in dessen Worten · ② Zusagen — was ist danach immer wahr, inklusive Verhalten im Fehlerfall · ③ Anschluss — rein, raus, und was es anfassen darf (Scope).
tgv-jean-chris — geprüft wurde die Spiegelung, nicht die Wirklichkeit. Ein Vertrag hätte gelautet: der zurückgegebene Bucket existiert und trägt die Daten dieses Mandanten — und das wäre prüfbar gewesen.
„KI erledigt deine Arbeit" verspricht jeder — das ist kein Alleinstellungsmerkmal, das ist der Markt. TGVs Versprechen lautet anders: jede gelöste Aufgabe macht die nächste billiger.
| Gedächtnis | Was es behält | Verbreitung |
|---|---|---|
| Fakten | Dokumente, Wissen, Belege | jeder baut das |
| Entscheidungen | warum etwas so ist | selten |
| ⭐ Fähigkeiten | was wir dafür gebaut haben — als Vertrag, nicht als Code | fast niemand |
| Ebene | Was darin lebt | Gehört | Liegt in |
|---|---|---|---|
| ① Nutzer | was dieser Mensch will, wie er arbeitet, seine Absichten | dem Nutzer | DB · Scope = Nutzer |
| ② Mandant | Fakten und Entscheidungen: Dokumente, Verträge, Konventionen, sein Master-Konzept | dem Mandanten | DB · Scope = Mandant |
| ③ Produkt (TGV) | Fähigkeiten: Bausteine, Skills, Verträge, Regeln, Narben | TGV (JC) | Repo, versioniert |
| ④ Werkzeug | das Arbeitsgedächtnis des Agenten | — | lokal · ⭐ Zielzustand: INDEX auf ①–③, kein Speicher |
| ⑤ Episodisch | was in diesem Austausch geschah | Gespräch | ⭐ muss verdichtet werden — oder es ist zu Recht weg |
| ⑥ Welt | fremdes Wissen: Gesetze, Pauschalen, Anbieterpreise | niemandem | kb_* · die Wahrheit liegt außerhalb |
| ⑦ Betrieb | was Läufe wirklich taten — Ereignisse, Kosten, Fehlschläge | TGV | agent_events · Beweismaterial, kein Wissen — muss beschnitten werden |
| ⛔ ⑧ Live-Server | was der Mensch tatsächlich sieht | — | Hetzner · eine Kopie, die alt sein kann |
master lag: 404.
| Brille | Frage | Warum sie fehlt = Sumpf |
|---|---|---|
| Verfall | Was darf altern, was muss altern, was darf nie altern? | Ein Preis muss altern, eine Narbe nie. Ohne Verfallsregel liest es irgendwann niemand mehr |
| Vorrang | Wer gewinnt bei Widerspruch? | Mensch vor Ableitung · Messung vor Behauptung · jung vor alt — außer bei Narben |
| Vergessen | Was passiert bei Löschverlangen? | Nur weil ③ vom Fall entkoppelt ist, ist Löschen in ② ohne Wissensverlust möglich |
| Vertraulichkeit | Erbt die Lehre die Stufe ihrer Quelle? | ⛔ Sonst ist eine Lehre aus einem streng_vertraulich-Dokument ein Leck mit Umweg |
| Herkunft | Wer, wann, aus welcher Messung? | Ohne sie ist „Vorrang" nicht anwendbar — man kann nicht entscheiden, wer recht hat, wenn man nicht weiß, woher es kommt |
| Zustand | Bedeutet | Prüfer |
|---|---|---|
| geschrieben | die Aussage steht im Kompendium | — |
| verdrahtet | sie wirkt an einem Wirkort | Eigentümer benannt |
| geprüft | ein Guard hält sie | next_guard |
| ⭐ sichtbar | der Mensch kann sie aufrufen | deployt + Link |
next_guard ist nicht „fertig", sondern „geschrieben" — und eine, die nicht deployt ist, existiert für den Menschen nicht.Absicht → Präzisierung → Plan → Verträge → Ergebnis → Rückfluss. ⛔ Ohne Schritt 2 kann eine Absicht den Zustand „geplant" nicht erreichen.
| Historiker spricht mit | Wann | Was er gibt | Was er bekommt |
|---|---|---|---|
| Orchestrator | ⛔ vor jedem Plan, verpflichtend | Fundstellen — oder „nichts, und das war der Suchraum" | die Absicht |
| Fach-Agenten | beim Bauen | den Vertrag des Bausteins | ⭐ die Lücke — die einzige Schnittstelle, die das Gedächtnis wachsen lässt |
| KVP-Agent | nach dem Lauf | Häufungen: „diese Klasse fünfmal" | Ereignisse aus ⑦ |
| Dokumentalist | nie | ⛔ nichts — Ebene ② bleibt drüben | ⛔ nichts |
| KAI | nur bei Präzedenz-Fragen | Fundstelle + Herkunft | die Frage |
| Mensch | bei Widerspruch | den Widerspruch, nicht die Glättung | die Entscheidung — sie schlägt jede Ableitung |
Gemessen 07.08. (02_SKILLS/tgv-skill-klaerung/skill.py:302-320 · 06_DASHBOARD/core_shell.html:1005 · komponenten_data.js Eintrag klaerung-card, status:"live"): ⭐ Die Klär-Karte ist gar nicht dokumentgebunden. Nur fünf Felder sind es (document_id · doc_label · doc_meta · drive_file_id · amount) — alles andere ist allgemein: question · check_md · recommendation · sources[] · quick_replies[] · accept/correct_label · resolved_msg · case_type. Und zwei Stellen sind bereits als Weiche gebaut: _confirm.target ist ein Feld, kein fester Wert — und case_type hat in der Shell schon eine eigene Spalte.
registerCard("klaerung_card") rendert überall, auch im Gespräch (selbstverankerter klHost-Dock).Und der KAI-Dialog entscheidet bereits, WANN gefragt wird — die Drei-Fall-Regel steht wörtlich in 08_OPS/chat_engine/grounding.py: ① bestätigte Aktion → ausführen, keine neue Frage erfinden · ② zumutbar klar, Detail offen → mit GENANNTER Annahme handeln · ③ echte Mehrdeutigkeit → kurz nachfragen. ⭐ Das ist der Wizard, und er ist schon da — er beantwortet die Frage, die einen Wizard schlecht macht: wann darf man fragen? ⛔ Was fehlt: Fall ② und ③ hinterlassen nichts. Die Annahme steht in einem Satz und verschwindet; die Rückfrage steht im Verlauf und verschwindet.
| Was ergänzt werden muss | Warum — aus der Messung, nicht aus dem Gefühl |
|---|---|
① answer_kind | Heute kennt die Karte nur bestätigen / korrigieren. Eine Absicht braucht auch wählen (aus N) und freitext. quick_replies[] gibt es schon — es fehlt die Aussage, ob die Auswahl verbindlich ist oder ein Vorschlag. |
| ② Eine Karte je offener Frage | ⛔ Nicht eine Karte mit drei Fragen, sondern drei Karten mit gemeinsamer Absichts-Nummer. So bleibt jede Karte atomar, der Lebenszyklus einfach, und die Liste zeigt Fortschritt statt eines Formulars. |
③ _confirm.target: "intent" | Die Antwort wird in die Absicht geschrieben, nicht in ein Dokument. Das Feld existiert bereits. |
klRenderList case_type wirklich als Spalte durchreicht, und ob der Karten-Dock mehrere Karten hintereinander trägt oder immer nur eine.
| Rolle / Vorhaben | Warum es blockiert ist |
|---|---|
| KVP-Agent (4d) | ⛔ hat keinen Rohstoff — er sieht Ereignisse, aber nie Wünsche |
| Klärungs-Dialog | ⛔ KORREKTUR 07.08. (JC): Die frühere Formulierung „auf das falsche Objekt gerichtet" war falsch. Die Klärung ist universal und richtig gebaut — 02_SKILLS/tgv-skill-klaerung/skill.py: list_pending · confirm_doc · confirm_txn · revert_doc, mit Dry-Run, Golden-Read-Back und Undo-by-default.⭐ „Absicht" ist der Oberbegriff, kein Konkurrent: „dieses Dokument richtig einordnen" ist eine Absicht — heute nur eine implizite, vom System abgeleitet. Eine Klär-Karte ist bereits die Präzisierungs-Stufe einer Absicht, sie hat nur keine Absicht über sich, an der sie hängt. ⛔ Die echte Lücke ist die Richtung: Klärung geht heute nur vom System aus („mir ist etwas unklar, entscheide du"). Es fehlt die Gegenrichtung vom Menschen („ich will X, hilf mir, es genau zu machen"). ⇒ Kein Umbau — ein zweiter Eingang zu einer Maschine, die schon läuft. ⚠️ Offen und ungemessen: die heutigen Karten kennen bestätigen · korrigieren · zurücknehmen. Eine Absicht braucht die Frageform „was ist hier noch unklar?" — ob dieselbe Kartenart beides trägt, ist eine Messung, keine Meinung. |
| Promotions-Gate (Modul-Katalog) | ⛔ hat keinen Eigentümer — in der Governance-Trias fehlt die Rolle, die Fähigkeiten kuratiert. Wir haben einen Dokumentalisten für Belege und niemanden für Werkzeuge. |
| Output-as-Input · Telemetrie-Fundus · Anti-Amnesie | alle drei brauchen die Absicht als Anker — man kann nicht lernen, was funktioniert hat, wenn man nicht weiß, was gewollt war |
| Screen-Builder-Agent (E-53) | kann nur aus Verträgen zusammensetzen, nicht aus einem Ordner mit Dateien |
Anlass JC 19.09.: „C3 ist die deutsche CONVIS Consult & Marketing GmbH, C4 die französische. convis GmbH ist ein Kunde von C3!! Das müsstest du schon längst parat haben." Er hat recht: der Satz stand seit Iter 44 in einer Migration (05_SCHEMA/088_iter44_a3_entity_signatures_aliases.sql:55 „KEIN c3-Alias auf convis gmbh“). Er stand nur nicht an dem Ort, den ORCH, KAI und Tower lesen. Das ist die Lücke aus 6a, an einer Firma gemessen: ein Wissen ohne Adresse ist ein Wissen, das man jedes Mal neu verliert.
Kanon (EINE Quelle: mandanten + entity_signatures) | Rechtsname · Land · USt-ID · Rolle |
|---|---|
C3 · c3-convis | CONVIS Consult & Marketing GmbH · DE · DE812421871 · HRB 102141 B · eigene Entität. Beleg: 77 Eingangsbelege mit diesem Empfängerblock und entity_signatures. |
C4 · c4-convis | CONVIS Consult & Marketing SARL · FR · FR34442540068 · eigene Entität. ⚠️ mandanten.name sagt „Convis SARL (C4)“, also nicht den Rechtsnamen. Mig 233 hat nur C3 korrigiert. |
| convis GmbH | KUNDE von C3 (debtor_customers, 8 Ausgangsrechnungen, Ansprechpartner Herr Stephan Ludwig, gleiche Anschrift Auerbachstr. 10). ⛔ Nicht C3. Und: JCs Mail-Signatur bei j.binetti@convis.com nennt sie. Deshalb trägt jede Weiterleitung von dort den Namen (246 von 887 Belegen kamen so herein). |
| ⚠️ offen (JC) | DE813141231 und DE812909449 stehen als C3-USt-IDs in 08_OPS/ablage_kanon.yaml:19. Die erste steht in keinem Belegtext (#7200), die zweite nur auf einer Google-Rechnung (#7802). Nicht geraten, sondern gefragt. |
entities.name für C3 lautet „C3 Convis GmbH“ (live-Tabelle). ② Der Cron ⑦ (betriebs-crons.yml:292) ruft 08_OPS/fesp2_d_entity_retriage.py auf. Dort wird aus :224 „Empfänger enthält GmbH“ → C3 und aus :255 „Aussteller convis + gmbh“ → C3. Er schreibt nie selbst, legt JC aber falsche Ein-Klick-Vorschläge mit Zitat vor. ③ 24 Belege haben als provider „convis GmbH“: gelesen aus der Signatur des Weiterleiters, nicht aus dem Beleg. ④ #8473 (Rechnung an „convis GmbH“) und #8155/#8156 (Vorgänge der convis GmbH) liegen im C3-Bestand. ⑤ kb_suppliers geht als LIEFERANTEN-HINWEIS in den ORCH-Prompt (08_OPS/agent_orch01/plan_service.py:123). Drei Zeilen sind richtig: „convis GmbH → C3, Einnahmen“ (#341, #371, #1090), also der Kunde. Zwei sind fraglich: #889 mit dem Muster „convis“ trifft jede Convis, auch C4 und C3 selbst; #1153 „Convis GmbH intern → Betrieb“ macht convis GmbH zur Kostenstelle. ⭐ Die Zeilen allein sind kein Fehler. Gefährlich werden sie, sobald der provider aus der Signatur stammt (③): dann liest ORCH „Einnahme von C3“ an einer Adobe-Rechnung. ⑥ Zwei Tests schreiben den Fehler fest, dazu rund 40 Konzept- und Mockup-Texte.
| Bestand: wo Wissen über eine Entität heute liegt | Zustand (6i) · Wand |
|---|---|
| „Second Brain je Mandant/Entität/Projekt/User“ | geschrieben: 00_LEITDOKUMENT/KI_FIRST_KLASSIFIKATION_WERKBANK_KONZEPT.md:154 und JE-081 „Entitäts-Steckbrief lernt aus Chat“ (offen seit 27.06.). Kein Schema, kein Code. |
contacts · contact_roles (Mig 251) | verdrahtet (Skill kontakt-finden, KAI) · Mandant + Stufe. Rolle kunde gibt es schon. ⭐ Das ist der natürliche Ort für „convis GmbH ist Kunde von C3“. |
kb_suppliers | verdrahtet in ORCH als einziger Entitäts-Hinweis ({{supplier_prior}}) · nur nach entity-Text gescoped, nicht nach mandant_id |
persona_profiles (Mig 202) | verdrahtet in KAI (app.py:3534), aber 0 Zeilen · mandant_id ist Text statt uuid (05_SCHEMA/PROPOSED_persona_profiles_fuenf_achsen.sql) |
entity_signatures (+ aliases) | verdrahtet, deterministisch (party_role, Signatur) · nach Entitäts-Slug geschlüsselt |
agent_knowledge · knowledge_graph_* | nur MCP bzw. Gabriel-Stub · ⛔ ohne Mandanten-Wand. Für Entitäts-Wissen nicht verwenden. |
nachbarschaft.py („was taten wir mit ähnlichen Belegen“) | gebaut, bewusst nicht verdrahtet: 75 von 778 hätte die Nachbarschaft falsch gelenkt (02.09.). ⭐ Die Lehre für 6m: Statistik über Nachbarn ist kein Wissen über die Entität. |
contacts/contact_roles + notes. Es ist damit je Mandant und trägt die Stufe (6h: die Lehre erbt die Stufe ihrer Quelle). Wissen über die eigene Entität (Rechtsname, USt-ID, Marken) liegt in mandanten/entity_signatures. Kein drittes Regal.
{{supplier_prior}} einen Block {{entitaets_hinweise}}. Er enthält nur Fakten aus Mandanten, die der Aufrufer sehen darf (user_mandant_roles), und nur bis zu seiner Stufe. Der Prompt sagt: „Der Beleg entscheidet; der Hinweis erklärt, was du siehst.“ Beispiel: „convis GmbH ist Kunde von C3. Ein Beleg AN convis GmbH ist nicht C3-eigen. Die Signatur ‚convis GmbH‘ unter einer Weiterleitung ist JCs Absender, kein Lieferant.“
check_firmennamen_kanon.py sperrt die Gleichung „C3 = Convis GmbH“ in Repo-Texten, Prompts und Tests. Der Kanon kommt aus der DB, nicht aus einer zweiten Liste.
kb_suppliers.mandant_id, persona_profiles.mandant_id → uuid). Datenkorrekturen (entities.name, mandanten.name C4, 24 provider, #889/#1153 in kb_suppliers) liegen als SQL-Vorschlag bei JC. Wirkort: Register #2157 · Memory reference_entitaeten_firmennamen_kanon.Lage: Kanon, Bestand und Fehlerorte sind gemessen (oben). Guard, Cron-Korrektur und Test-Umstellung baut die Bahn ENTITAETEN#01 ohne dich (Tower-OK 19.09.). Offen sind nur Dinge, die in keinem Beleg eindeutig stehen. Jede Frage hat eine Empfehlung. Ein „OK“ nimmt alle vier Empfehlungen an, abweichende Punkte nennst du mit Nummer.
| Frage | Variante A (Empfehlung) | Variante B | Was du danach siehst |
|---|---|---|---|
E1 · Die zwei unbelegten C3-USt-IDs DE813141231 (#7200) und DE812909449 (#7802, Google) | Streichen aus der Zuordnungsliste. C3 wird nur noch an DE812421871 erkannt. Die Google-Nummer prüfst du einmal in deinem Google-Rechnungsprofil. | Beide behalten, weil du sie kennst. Dann nenne bitte, wem sie gehören. | A: Ein Beleg mit einer dieser Nummern landet in der Klärung statt still in C3. |
| E2 · Stellt convis GmbH C3 jemals Rechnungen (C3 = Kreditor)? | Nein: convis GmbH ist nur Kunde von C3 (contact_roles.rolle = kunde). #341/#371/#1090 (Kunde → C3-Einnahmen) bleiben. #889 (Muster „convis“, zu breit) und #1153 („intern → Betrieb“) werden deaktiviert. | Ja, auch Lieferant: dann zwei Rollen, und die Richtung entscheidet je Beleg der Inhalt. | A: ORCH-Hinweis „Kunde von C3, Belege AN convis GmbH sind nicht C3-eigen“. |
| E3 · #8473 Herzapfelhof, 161,72 €, Rechnung an „convis GmbH“, liegt in C3 | Nicht C3-eigen: Status „fremd/abgelehnt“, kein Paket an den Buchhalter. | C3 hat bezahlt und rechnet weiter: bleibt in C3, mit Vermerk „Weiterberechnung“. | A: fällt aus dem C3-September-Paket heraus. |
E4 · Namen in der DB: entities.name C3 und mandanten.name C4 | Rechtsnamen: „CONVIS Consult & Marketing GmbH“ / „CONVIS Consult & Marketing SARL“, dazu das Kurz-Label C4 = „Convis (C4)“, analog zu Mig 233. SQL liegt bereit: 05_SCHEMA/PROPOSED_entitaeten01_firmennamen_kanon.sql. | Nur C4-Rechtsname, Label bleibt leer (der Umschalter zeigt dann den langen Namen). | A: Umschalter zeigt „Convis (C3)“ und „Convis (C4)“, Belege und Pakete den Rechtsnamen. |
rag_chunks, Felder, auch mit Leerzeichen): DE812909449 steht wörtlich auf der Google-Rechnung #7802 als USt-IdNr. von „Convis Consult & Marketing GmbH“ → bleibt als C3-Nummer, aber ⚠️ sie ist nicht die amtliche (DE812421871): das Google-Rechnungsprofil ist vermutlich falsch gepflegt. DE813141231 steht in keinem Belegtext, nur im extrahierten Feld von #7200 → unbelegt, fliegt aus ablage_kanon.yaml.
name = Rechtsname, short_label = „Convis (C3)“/„Convis (C4)“.
entity_signatures — HRB, USt-ID, Steuernummer, D-U-N-S, EORI, Gründung, Stammkapital, beide Geschäftsführer, BIC, IBAN (gesetzt, hier nicht zitiert); C4: RCS, SIRET, NAF, IDCC, TVA, D-U-N-S, Organisme de formation. 0 Abweichungen, nichts zu schreiben. Was fehlt, ist nur die Struktur: D-U-N-S, EORI, Kapital und Gründung stehen in notes als Freitext.Anlass, JC am 11.10. wörtlich: „Bitte mir erklären was bedeutet Gabriel als triage? können wir dadurch das thema Errinerung ( second Brain) damit verbinden? Ein doc oder einen Info in der Kai chat gibt informationen die das second brai der Entität oder der Person zuspeist? Ich brauche einen Erklärung wie ist unsere Konzept second brain / Digitales zwilling unter Nutzung NUXING von alle arbeiten in Gabriel ( was als Memory APP angedacht ist).“
Den Horizont beschreibt 00_LEITDOKUMENT/KONZEPT_DIGITALER_ZWILLING_LEBENSGEDAECHTNIS.md (26.07.: vier Schichten, Vertrauens-Pakt, Gabriel als rückwirkender Zwilling und TGV als vorausschauender). Dieser Abschnitt ergänzt den Fluss dazu: Eingang → Erkennen → Gedächtnisraum → Abruf. Er ist am Bestand gemessen, live und nur lesend am 11.10.
08_OPS/agent_orch01/taxonomy.py:23, Mail-Prompt 08_OPS/tgv-skills-service/mail_intake.py:879). Was keines dieser Ziele trifft, wird unassigned und geht in die Klärung.
entities.slug = gabriel, Eimer tgv-mb-lm-gabriel in 08_OPS/ablage_kanon.yaml:46). Nur die Triage kennt ihn nicht. Deshalb kamen alle 58 Gabriel-Dokumente, davon 34 Fotos, über gabriel.html herein und keines per Mail oder Inbox.
gabriel.html „Fiche vorschlagen“ drückt (proposeFicheFromDoc :3272, runKernSchleife :5580 → Skill source-to-fiche). In der Eingangskette schreibt keine Stelle in memoir_*. Gesucht wurde in dispatch.py, mail_intake.py und 08_OPS/agent_orch01/*.py.
| ② Eingang | Was heute damit geschieht (gemessen 11.10.) | Wand beim Abruf | Was fehlt |
|---|---|---|---|
| Dokument (Upload, Inbox) | documents plus rag_chunks (2090 Textstücke, jedes mit mandant_id und Stufe). KAI findet sie über search_knowledge_scoped. | ✅ Mandant ∩ Entität ∩ Decke ∩ Projekt (05_SCHEMA/263_rag02_projekt_wand_wissenssuche.sql) | Das Dokument bleibt Text. Niemand fragt: „Was sagt es über eine Person oder die Entität?“ |
| Foto | Drei Ausgänge nach JE-212. Den Ausgang „Erinnerung“ baut FOTO#02 (#3967, PR offen): Zustand erinnerung, der Eimer bleibt der der Entität. | ✅ wie Dokument | Keine Geschichte und keine Personen am Foto. photo-select läuft nur in Gabriel. |
| KAI-Gespräch | chat_sessions und chat_messages (1458 Nachrichten), ein Thread je Scope (Mig 203). KAI sieht die letzten 12 Züge (08_OPS/chat_engine/agent_loop.py:31). | ✅ eigener Nutzer | Nichts wird verdichtet (Ebene ⑤ in 6g). Für „merk dir …“ gibt es keinen Schreiber: remember_rule schreibt nur Mail-Routing-Regeln (TGV -App files/tgv_mcp_server.py:667). |
IMAP-Abruf (mail_intake.py:1770) → Triage → weiter wie ein Dokument. | ✅ wie Dokument | Gabriel ist kein Ziel (TRIAGE#02 ②). | |
| Gabriel-Eingabe (Text, Audio, Scan) | source-to-fiche → 62 Fiches · 141 Personen · 90 Orte · 128 Ereignisse, dazu 98 Textstücke im Gabriel-Mandanten. | ✅ Projektrolle und Gabriel-Stufe (Mig 113/115). ⛔ Schreibwand fehlt noch: Mig 301 (#4003) | Das ist das einzige strukturierte Erinnerungs-Gedächtnis, und es lebt nur in Projekt 5 (gabriel.html:2377). |
| Fakt über Person oder Entität | persona_profiles (Mig 202): der Leser in KAI ist verdrahtet, aber die Tabelle hat 0 Zeilen. Der Umbau auf fünf Achsen liegt als PROPOSED vor (#1262, JC-GO 02.09.; live ist mandant_id noch text). Gegenparteien stehen in contacts und contact_roles (6m). | ⚠️ Persona hat heute nur eine Eigentümer-Regel | Es gibt keinen Schreiber, der aus Dokument oder Gespräch einen Fakt macht (JE-081). |
| ③ Variante | Wiederverwendet (NUXIN) | Neu, als Baustein | Datenschutzfolgen |
|---|---|---|---|
| ⭐ A · Gabriel-Mechanik als Baustein in jedem Raum (Empfehlung) | Die memoir_*-Tabellen sind schon projektgebunden (get_project_ids_for_user und can_user_see_confidentiality, Mig 113/115). Ein neuer Gedächtnisraum ist deshalb ein neues Typ-B-Projekt wie 00-26-001-life-memory-gabriel, ohne neue Tabelle. Weiter genutzt werden source-to-fiche, photo-select, memory-search-chat, rag-ingest-project, gabriel.html als Memory-App, die Gabriel-Lesewerkzeuge für KAI (08_OPS/chat_engine/executors_gabriel.py:117), der Foto-Ausgang „Erinnerung“ (FOTO#02) und für Fakten persona_profiles/contacts wie in 6m. | (1) Gedächtnis-Erkenner nach der Triage: er schlägt vor und schreibt nie selbst. Muster sind source-to-fiche und bild_art. (2) „merk dir“ an KAI erzeugt eine Vorschlagskarte (Fiche oder Fakt) im aktiven Raum. (3) Die Memory-App mit Projekt als Parameter statt fest Projekt 5. (4) Gabriel als Triage-Ziel (TRIAGE#02 ②). | Die Wand aus Mandant, Projektrolle und Stufe steht schon. ⛔ Vorbedingung ist Mig 301 (#4003: auf 15 memoir_*-Tabellen war Lesen auch Schreiben). Ohne sie schreibt jeder Viewer in jedes neue Gedächtnis. Die Erkenntnis erbt die Stufe ihrer Quelle (6h). Gabriel behält seine eigene Skala, neue Räume nehmen die Haus-Stufen. |
| B · Nur Steckbrief und Foto-Regal | persona_profiles mit store.py und compose_persona, dazu contacts und FOTO#02. Fotos liegen als Zustand erinnerung, sortiert nach Jahr und Monat. | Das PROPOSED 05_SCHEMA/PROPOSED_persona_profiles_fuenf_achsen.sql wird angewandt (DDL ist JCs Hand). „merk dir“ schreibt dann einen Fakt. | Die Wand ist genau das PROPOSED. Bis dahin liest Persona ins Leere (fail-open). ⚠️ Grenze: „Wer ist auf dem Foto mit Tante Gina?“ (Zwilling, Schicht 2) bleibt unbeantwortbar, weil am Erlebnis keine Personen, Orte und Ereignisse hängen. |
| ⛔ C · Alles in Gabriel | Alles von Gabriel, nichts Neues: die Triage schickt jeden Erinnerungs-Kandidaten in Gabriels Mandanten. | nichts | ⛔ Verstößt gegen JE-193 („kein globaler Mischspeicher“) und gegen die Mandantenwand: Gabriels Familien- und Redaktionsrollen sähen Inhalte aus JCs C3 oder Privat. Steht hier nur zur Abgrenzung. |
persona_profiles und contacts (6m). Reihenfolge, gebaut wird erst auf JCs Wort:
rag_chunks.entity den Wert gabriel-binetti, ihre 73 Dokumente aber gabriel. Die Entitätswand der Live-Suche liest d.entity und hält. Der Filter p_entity vergleicht dagegen c.entity: ein auf Gabriel verengter Abruf fände also 0 Stücke. ⚠️ Das ist ein Verdacht, gelesen am Funktionstext und an den Zahlen. An einer Ausführung bewiesen ist er nicht.
rag_conf_rank den höchsten Rang (Mig 241). KAI mit der Standard-Decke intern sieht deshalb keine Gabriel-Erinnerung. Für Gabriel ist das gewollt, neue Räume sollen es nicht übernehmen.
remember_rule verspricht Gedächtnis, das Werkzeug schreibt aber Mail-Routing.
KONZEPT_DIGITALER_ZWILLING_LEBENSGEDAECHTNIS.md war bisher nur von der Foto-Vorlage aus verlinkt. Ab jetzt ist es auch von hier erreichbar.Beschlossen durch JC am 17.09.2026. Umsetzung mit Claude Code ab Freitag, 18.09.2026. Status: Zielarchitektur freigegeben, Umsetzung und Live-Abnahme offen. Dieser Abschnitt ist die maßgebliche Ergänzung zu den historischen Betriebsständen weiter oben; er behauptet keinen bereits erfolgten Rollout.
Begriffe: RAG bedeutet, dass KAI passende, berechtigte Quellstellen für eine Antwort abruft. Ein Chunk ist ein nachvollziehbarer Textabschnitt. Eine Indexgeneration ist ein zusammengehöriger, geprüfter Satz von Chunks einer Originalversion. Facharbeit erzeugt zusätzlich strukturierte Ergebnisse und gegebenenfalls autorisierte Aktionen.
Reihenfolge — erst vollständig erschließen, dann einstufen (JC-Grundsatz 19.09.2026): „Die Wahrheit zur Einstufung liegt im Dokument selbst, nicht in der Mail, mit der es versendet wurde. Deswegen wollen wir zuerst chunken, damit ORCH die Grundlage hat zu entscheiden.“ Daraus folgt verbindlich:
RAG beantwortet Quellenfragen, Vergleiche und Zusammenfassungen. Für eine vollständige Dokumentprüfung muss KAI alle relevanten Abschnitte systematisch abarbeiten; Top-k-Suche allein beweist keine Vollständigkeit. Beträge summieren, Buchungen erzeugen, Fristen verwalten oder Reisekosten bearbeiten erfolgt über bestehende strukturierte Werkzeuge und deren Freigaben. Fachlich extrahierte Angaben bleiben mit Originalversion und Fundstelle verbunden; ungeprüfte Angaben werden nicht zu bestätigten Tatsachen. Widersprüche zwischen Quelle und Fachdatensatz bleiben sichtbar.
Unabhängige Zustände: Original gespeichert · Extraktion vollständig/teilweise/fehlgeschlagen · Wissensindex bereit/in Arbeit/fehlgeschlagen · Facharbeit offen/in Arbeit/prüfbedürftig/abgeschlossen. Diese Bedeutungen an bestehende Zustandsfelder anbinden; keine parallele Statusmaschine erfinden. Ein einziges „done“ darf nicht alle vier Aussagen ersetzen.
Prüfreichweite: lokaler Quellcode und Live-Schema am 16./17.09.2026; konkrete Original-/Chunk-Prüfung an #8279. Schema, SQL-Datei oder Kommentar sind kein Nachweis wirksamer Live-Rechte. Vor Baubeginn aktuellen master, offene PRs, Migrationsledger und Dienstfassung erneut prüfen.
| Vorhandener Wirkort | Wiederverwenden / gezielt ergänzen |
|---|---|
08_OPS/credentials/_storage.py; documents | Kanonischer Originalzugriff; ID, Bucket, Fingerprints, Versionsfelder. Keine zweite Originalablage. Dateizeiger nicht selbst rekonstruieren. |
02_SKILLS/tgv-skill-parse-docling/skill.py; bestehende PDF/OCR-Wege und Registry | Vollständige gemeinsame Extraktion anschließen; tatsächliche Formatunterstützung und Eingabeverträge messen. Keine Providerumstellung; EU-/Datenschutzvorgaben beibehalten. |
02_SKILLS/tgv-skill-rag-ingest/skill.py; rag_chunks | Vorhandene Chunks/Embedding-Spalten nutzen. Kurzer DB-Text, „Chunks existieren“ und übersprungene Embeddings dürfen nicht mehr als Vollständigkeit gelten. Löschen-vor-Ersetzen durch geprüfte Aktivierung ersetzen. |
08_OPS/rag_wand.py; 08_OPS/chat_engine/scope_gate.py | Mandant/Vertraulichkeit und serverseitigen Benutzerscope wiederverwenden; unbekannte Zuordnung bleibt gesperrt. Alle Schreib- und Lesepfade inventarisieren. |
08_OPS/chat_engine/executors_rag.py; RPCs search_knowledge_scoped, search_knowledge_lexical | Produktive Suche weiterverwenden; Rechte, aktive Generation und Quellenbezug in beiden Wegen gleich durchsetzen. 08_OPS/rag01/rag_hybrid_search.py ist ein Auswertungswerkzeug, kein produktiver Ersatz. |
08_OPS/agent_orch01/agent_loop.py, verifier.py; 02_SKILLS/tgv-skill-contract-extract/skill.py | ORCH und Fachskills erhalten gemeinsamen vollständigen Text samt Version und Abdeckung. Vorschau nicht „Volltext“ nennen. Fachauftrag und tatsächliche Ausführung nachweisen. |
08_OPS/tgv-skills-service/app.py; agent_events; vorhandene Wiederholungs-/Jobwege | Originalabruf, Benutzerrechte, Audit und Wiederaufnahme weiterverwenden. Keine neue Queue/Agentenebene ohne nachgewiesene Lücke. |
Referenzfall #8279, CIT TRAVAUX: 35 Seiten und etwa 67.533 extrahierte Zeichen im Original; bisher zwei RAG-Chunks aus rund 5.282 Zeichen DB-Text. Erfasster Dokumenttyp „Vertrag“, Originaltitel jedoch „ASSIGNATION AU FOND DEVANT LE TRIBUNAL“. Das ist ein Test für vollständige Erschließung und eine zu überprüfende Klassifikation, kein Anlass, blind einen Vertrag anzulegen. Der Parser meldete fehlende Eingabe; vorhandene Chunks wurden später idempotent übersprungen. Keine personenbezogenen Dokumentinhalte in öffentliche Testfixtures übernehmen.
source_meta, section_anchor, Dokumentversions- und Ereignisfelder zuerst auf Eignung prüfen; neue Spalten/Tabellen nur für nachgewiesene Lücken.file-url. Bereits ausgestellte signierte Links bleiben gegebenenfalls bis zum Ablauf nutzbar. Vor Abnahme Widerrufsanforderung festlegen und umsetzen: sofortiger Widerruf erfordert einen bei jedem Abruf autorisierenden Weg; kurze Linklaufzeit allein erfüllt ihn nicht.Die Pakete sind Arbeitsschritte, keine neu gegründeten Lanes. Federführung: umsetzende Claude-Code-Lane; TOWER koordiniert Abhängigkeiten, Review, Merge und Deploy. Freitagsbeginn ist kein Versprechen, alle Pakete am selben Tag produktiv abzuschließen.
| Paket / Reihenfolge | Konkrete Lieferung | Tor zum nächsten Schritt |
|---|---|---|
| P0 · Bestand und Vertrag | CLAUDE.md, Memory, diesen Abschnitt, Register, Komponenten und Registry lesen. Master/offene PRs/Livedienst vergleichen. Alle Ingest-/Such-/Originalpfade und bereits laufende Reparaturen erfassen. Bestehende Tabellen/Versionen/Jobs gegen 7c abgleichen; minimale Datenänderung, Rechteprüfung und Rollback hier dokumentieren. | Datei-/Schema-Fundstellen und noch reproduzierbarer Fehler. Keine Doppelimplementierung. DDL nach geltendem TGV-Freigabeweg; eine Architekturfreigabe ist kein Nachweis bereits angewandter Migrationen. |
| P1 · Vollständige Extraktion | Kanonischen Originalzugriff mit vollständigem Parser verbinden, gemeinsame Extraktion samt Abdeckung persistieren. Vorschau und Volltext unterscheiden. PDF, Scan, Tabellen, Mail/Anlagen und nicht unterstützte Formate mit expliziten Ergebnissen behandeln. | Synthetische Testquelle mit eindeutigen Fundstellen am Anfang, in der Mitte und am Ende; fehlende Seite und Parserfehler werden erkannt. Fachskill liest dieselbe Version. |
| P2 · Index sicher erneuern | Generation/Idempotenz/atomare Aktivierung in bestehenden Ingest einbauen; fehlende Embeddings sind Fehler. Benötigte Migration separat mit Preview, Verify und Rollback vorbereiten. | Wiederholung, Teilfehler, Prozessabbruch und zwei gleichzeitige Versionen getestet. Letzter vollständiger Stand bleibt korrekt; neue Version wird nie teilweise aktiv. |
| P3 · Rechte und KAI | Beide Suchwege, Quellenbezug und Originalabruf mit aktuellem Scope verdrahten. Direkte DB-Zugänge und Cache prüfen. KAI kann gezielte Suche von vollständiger Dokumentarbeit unterscheiden und nennt Teil-/Altstände. | Positive und negative Rechtefälle aus 7e bestanden; Widerrufsverhalten belegt. Keine Abnahme nur mit service_role oder Owner. |
| P4 · ORCH und Facharbeit | Triage darf früh beginnen; Facharbeit nutzt geprüfte gemeinsame Extraktion. RAG läuft auch bei unbekanntem Dokumenttyp oder Fachfehler. Vorhandene Fachskills liefern verknüpfte, versionierte Ergebnisse; neue Dokumentarten erst nach Registry-/Taxonomieprüfung. | Fachskill-Ausfall blockiert Wissensindex nicht; erneute Fachausführung erzeugt keine Dubletten oder unautorisierten Aktionen. #8279 wird nicht allein wegen alter Triage zum Vertrag. |
| P5 · Referenzfall, Bestand, Betrieb | Zuerst #8279 kontrolliert nachverarbeiten und über KAI abnehmen; danach Dry-Run-Inventar unvollständiger Bestandsdokumente, Kostenabschätzung und begrenzte wiederaufnehmbare Stapel. Zustände für Nutzer verständlich anzeigen. | PRs grün, deployed SHA/Dienstfassung nachgewiesen, Live-Abnahme und Rollback geprüft. Bestandsbericht nennt vollständig/teilweise/gesperrt/fehlgeschlagen mit Nenner und Prüfreichweite. |
Vorhandene Prüfungen zuerst erweitern: 07_TESTS/agent_chat01/test_rag_executor.py, test_envelope_scope_caller.py, test_scope_verengung_kommt_an.py, test_s2s_scope_278.py, test_beleg_link_contract.py, 08_OPS/check_projekt_wand_wissenssuche.py und vorhandene Vertrags-/Parserprüfungen. Vor Aufruf aktuelle CLI/Fixtures lesen. Neue Tests sichern reale Fehlerklassen; jede negative Kontrolle muss durch eine gezielte Verletzung rot werden können. Testdaten synthetisch oder zugriffsgeschützt.
Claude-Code-Startauftrag: Diesen Abschnitt 7 vollständig umsetzen, beginnend mit P0. Bestehende Arbeit vor Änderungen erneut prüfen und übernehmen. Keine zweite RAG-Plattform, keine zusätzliche Agentenebene, keine neue Taxonomie aus Vermutung. Prüfberichte mit Quellenstand, Benutzerrolle, erwarteter und tatsächlicher Wirkung führen. Pro Paket den Ist-Stand hier aktualisieren; erst nach gemessener Live-Abnahme als produktiv markieren. Produktionsdaten-Nachlauf und DDL nach den geltenden TGV-Verfahren ausführen. Offene Geschäftsentscheidungen konkret vorlegen, technische Routine selbst lösen.
P0 — erledigt am 18.09.2026 (TOWER#57, nur gelesen; Registerzeile #2098). Geprüft gegen origin/master d7a070ca0 und lesend gegen die Datenbank (Spalten von rag_chunks und documents, Ereignisse). Nicht geprüft: RPC-Definitionen, RLS-Policies und Migrationsledger live, die Dienstfassung auf Hetzner.
tgv-skill-parse-docling/skill.py:172) und build_payload den MIME-Typ leer lässt (dispatch.py:673); der Ingest hält 20 Zeichen DB-Text für ausreichend (tgv-skill-rag-ingest/skill.py:109/189); ein fehlendes Embedding wird still übersprungen (:437); OCR ist aus (docling.py:258).rag_chunks (tgv-skill-rag-ingest-project, 08_OPS/rag01/ingest_core_privat.py, 08_OPS/ingest_life_memory_help.py, 08_OPS/rag01/purge_base64_reingest.py), ein dritter Lesepfad (tgv-skill-memory-search-chat), und der Vorschau-Leser tgv-pdf-text-snippet ist der einzige Ort, der die Seitenzahl kennt (documents.snippet_pages).source_meta (Lauf, Seite, raw_sha256), section_anchor, snippet_pages als erwartete Seitenzahl, agent_events als Laufprotokoll. Migration nötig für Generation und atomare Aktivierung (P2).claude/vibrant-lichterman-898620, gleiche Schlüsselmenge je Upsert-Zeile) und BELEGTEXT#01 (Zweig claude/optimistic-bouman-ef94a9, #2057). Dessen Vision-Leseweg ruft ein US-Modell und ist für den Volltext nicht zu verwenden.P1 — ausgeliefert, Live-Abnahme offen (Registerzeile #2099). Gebaut am 18.09.2026 von der Bahn RAG#01, gemergt über die Deploy-Naht 2 (#2794) am 19.09.2026 um 09:39; der Dienst meldet Fassung 1.12.167. Gemessen am 19.09. (nur gelesen): seit dem Deploy kein einziger Lauf von tgv-skill-rag-ingest oder tgv-parse-docling in agent_events. Ausgeliefert heißt deshalb noch nicht abgenommen; produktiv erst nach dem ersten gemessenen Lauf an einem echten Beleg.
08_OPS/volltext.py erschließt ein Original einmal — PDF Seite für Seite, Office/HTML über docling-serve (EU). Zustände: vollständig · teilweise · fehlgeschlagen · nicht unterstützt. Eine Scan-Seite ohne Textschicht zählt als nicht gelesen, eine wirklich leere Seite als leer. Seitenzahl wird gegen snippet_pages gezählt, der Fingerprint gegen raw_sha256.tgv-skill-parse-docling 0.2.0 holt die Datei über den Kanon (_storage.hole_bytes, Bucket zuerst) statt über eine Pflicht-Drive-ID, bestimmt den MIME-Typ aus den Bytes und liest PDF. Fremder DB-Text ist kein Skip mehr; ein nur teilweise gelesenes Original überschreibt vorhandenen Text nicht.tgv-skill-rag-ingest 0.3.0 liest das Original vor dem DB-Text; der Rückfall auf DB-Text heißt ausdrücklich vollstaendig: false. Ein fehlendes Embedding bricht ab, ohne zu schreiben. Jeder Chunk trägt Lauf, Fingerprint, Leser, Abdeckung und Seite (source_meta, section_anchor seite:N) — ohne DDL.07_TESTS/rag01, Fundstellen Anfang/Mitte/Ende, fehlende Seite, Scan-Seite, Parserabbruch, verschlüsselt, Embedding-Loch, gleiche Lesung in beiden Skills). Lesend an #8279: vollständig, 35 von 35 Seiten, 67.261 Zeichen, Fingerprint gleich, 24 Chunks statt 2 — nicht geschrieben.OCR — JC-Entscheid 18.09.2026, 23:50: Mistral OCR ist Standard, je Mandant umschaltbar. Umgesetzt in P1, nicht live.
extraktion.ocr.modell und im extraktor.volltext.ocr in llm_aufgaben (Vorlage für alle, Übersteuerung je Mandant), ausgewertet vom vorhandenen Auflöser samt EU-Riegel. Ohne Zeile gilt JCs Vorgabe Mistral; ist die Einstellung nicht lesbar, wird keine OCR gemacht (ein Ausfall darf die Abschaltung eines Mandanten nicht aufheben). Abschalten je Mandant: datenort_pflicht = onbox_pflicht. Vorlage zum Anwenden: 05_SCHEMA/PROPOSED_rag01_ocr_je_mandant.sql (JCs Hand).Vergleich an 8 echten Belegen (19.09.2026, nur gelesen, 08_OPS/rag01/r2_proof_docling_vs_mistral.py). Das Skript lief seit seinem Bau am 07.08. nie — und wäre an allen acht gescheitert: keiner trägt mehr eine Drive-ID. Jetzt über den Bucket-Zeiger. Preis Mistral OCR 0,001 USD je Seite (kb_model_prices), Docling ist ein eigener Dienst ohne Stückpreis.
| Beleg | Art | Textschicht (P1-Leser) | Docling | Mistral OCR | Kosten Mistral |
|---|---|---|---|---|---|
| #8064 | Zahlungsbeleg · jpg | keine (Bild) | nicht gemessen ¹ | 1 Seite · 382 Zeichen | 0,0009 € |
| #8023 | Quittung · jpeg | keine (Bild) | nicht gemessen ¹ | 1 Seite · 1.380 Zeichen | 0,0009 € |
| #8021 | Quittung · jpg | keine (Bild) | nicht gemessen ¹ | 1 Seite · 798 Zeichen | 0,0009 € |
| #7919 | Rechnung · jpg | keine (Bild) | nicht gemessen ¹ | 1 Seite · 2.015 Zeichen | 0,0009 € |
| #8007 | Sonstiges · png | keine (Bild) | nicht gemessen ¹ | 1 Seite · 6 Zeichen | 0,0009 € |
| #8150 | Rechnung · pdf | vollständig · 2/2 Seiten · 1.517 Zeichen | Textschicht · 1.516 Zeichen | 2 Seiten · 1.478 Zeichen | 0,0018 € |
| #8145 | Rechnung · pdf | vollständig · 3/3 Seiten · 4.523 Zeichen | Textschicht · 4.523 Zeichen | 3 Seiten · 5.582 Zeichen | 0,0028 € |
| #8079 | Rechnung · pdf | vollständig · 2/2 Seiten · 1.396 Zeichen | Textschicht · 1.395 Zeichen | 2 Seiten · 1.637 Zeichen | 0,0018 € |
Summe Mistral OCR: 12 Seiten, 0,0109 €. Lesart: bei PDFs mit Textschicht liefern alle drei Wege praktisch denselben Text — OCR ist dort überflüssig und wird deshalb nicht gerufen. Bilder liest nur Mistral; die Qualität der Zeichen ist hier gezählt, nicht inhaltlich geprüft. Ein gescanntes PDF ist unter den acht nicht; die Seitenauswahl (nur Scan-Seiten) ist an einer synthetischen Probe live belegt (1 von 2 Seiten gelesen und bezahlt). ¹ Docling antwortete bei allen fünf Bildern HTTP 401: auf diesem Rechner fehlen die Docling-Zugangsdaten in der .env. Das ist keine 0, sondern nicht gemessen.
Genauigkeit und Laufzeit, gemessen 11.10.2026 (SOUVERAEN#04, #4050, 08_OPS/souveraen04_extrakt_vergleich.py --ocr). Der Vergleich oben zählt Zeichen. Gemessen ist jetzt, ob die Zeichen stimmen: 12 echte Rechnungs-PDFs mit Textschicht wurden gerastert (Textschicht weg, wie ein Scan), über die Produktions-Naht volltext.mistral_ocr_seiten gelesen und gegen ihre eigene Textschicht gemessen — 17 Seiten. Wörter wiedergefunden: Median 99,4 % (schlechtester Beleg 88,1 %) · Beträge: 66 von 68 · 2,0 s je Seite (Median, höchstens 7,1 s, 18 Belege inkl. 6 echter Scans/Fotos). Beide verfehlten Beträge und der schlechteste Wert liegen an #8281, dessen eigene Textschicht verklebt ist (3.000,001.200,00) — dort irrt die Messlatte. Die Zeichen-Ähnlichkeit (Median 0,75) taugt nicht als Maß: sie bestraft Reihenfolge und Tabellenform (#8467: 0,48 bei 100 % Wörtern). ⭐ Live verdrahtet, nicht mehr nur „umgesetzt in P1“: der Volltext-Leser las #8519 (28.09., 4 Seiten) und #8250 (11.10., 1 Seite) mit pypdf+mistral-ocr-latest.
P2 — Migration als Vorlage bei JC (19.09.2026, Registerzeile #2102), nicht angewandt. 05_SCHEMA/PROPOSED_rag01_p2_indexgeneration.sql: die neue Generation entsteht in rag_chunks_aufbau, die kein Lesepfad kennt; rag_generation_aktivieren() prüft Anzahl, Lückenlosigkeit und jedes Embedding und tauscht dann in einer Transaktion. Scheitert die Prüfung, bleibt der alte Stand stehen; eine ältere Generation aktiviert sich nie über eine jüngere. Die Such-RPCs ändern sich nicht. Der Code dazu folgt nach dem Apply.
P2 — Grundlinie gemessen und gesichert, Code wartet auf die Migration (20.09.2026, Registerzeile #2266). Ein Abnahmekriterium wie „der letzte vollständige Stand bleibt korrekt“ lässt sich nur prüfen, wenn der Zustand vorher gemessen ist; sonst vergleicht die Abnahme mit einer Erinnerung. 08_OPS/rag01/check_index_grundlinie.py stellt dafür fünf Fragen (Vektor · Wand · lückenlose Chunk-Folge · Lauf-Kennung · Fassung) und läuft schon ohne die Migration. Stand live: 1.937 Chunks an 677 Belegen, dazu 105 ohne Beleg; 0 ohne Vektor, 0 ohne Mandant, 2 ohne Stufe (bekannt, bei JC), 0 Löcher und 0 Dubletten in der Folge; 415 Chunks vom neuen Leser, alle mit Lauf-Kennung, 1.522 Altbestand davor. Zwei Urteile sind bewusst kein Rot: Altbestand ohne Leser-Stempel wird gezählt statt angeklagt, und eine abweichende Fassungs-Prüfsumme heißt „Fassungsfrage“ — sie nennt die Belege, denn zwei gespeicherte Zahlen zu vergleichen ist kein Urteil über den Index. Dabei gefunden, fremde Bahn: sechs Mail-Anhänge (#8385, #8434, #8435, #8442, #8443, #8444) tragen am Beleg eine andere Prüfsumme als ihre Chunks; an der Datei nachgerechnet stimmt die Chunk-Zahl, der Wert am Beleg ist falsch (an den Eingangsweg gemeldet).
#8279: gehört zu C4, soll für die ganze Entität C4 und für C3 (Muttergesellschaft) erreichbar sein; JC-Entscheid 19.09. (über TOWER#57): Stufe „intern“, ganze Entität C4; die C3-Sichtbarkeit ist eine Frage der Mandanten-Hierarchie, nicht des Belegs. Am 19.09. um 18:00 als erster Beleg des Nachlaufs neu indexiert (siehe P5).
P4 — Einstieg ausgeliefert mit Deploy-Naht 4 (Dienst 1.12.174), Live-Abnahme offen (19.09.2026, Registerzeile #2104). Der Dispatcher lässt ein PDF zuerst vollständig erschließen (direkt hinter der Dublettenprüfung), bevor ORCH einstuft; ORCH liest danach den Volltext statt der Vorschau. Jeder ORCH-Ruf nennt im Ereignis den Erschließungsstand; ein Ruf ohne Volltext heißt router.orch_ohne_volltext. Vom Tower entschieden (19.09.): ORCH wird nicht gesperrt (#2055 gilt für die fachliche Einordnung); Stufe und Entität setzt VERTRAULICH#01 nur aus einer vollständigen Erschließung. Dafür reist der Erschließungsstand als plan.extraktion unverändert in den Plan. ORCH sieht jetzt jeden Abschnitt: bis 200.000 Zeichen den ganzen Text, darüber jeden Abschnitt einzeln mit Signalen; plan.abdeckung sagt immer, wie — ein stiller Schnitt ist ausgeschlossen. Gemessen an #8279: 24.287 statt 3.629 Eingabe-Token, und der Stufen-Vorschlag kippt mit dem Volltext von vertraulich auf intern. Euro nicht berechenbar, weil kb_model_prices für das Live-Modell keinen Preis führt.
P5 — Bestands-Inventar gemessen, Nachlauf gelaufen (19.09.2026, Registerzeilen #2137 und #2175). Nur gelesen, OCR aus, kein Modellaufruf, Werkzeug 08_OPS/rag01/inventar_volltext.py mit dem echten Leser. Nenner: alle 808 Belege mit Datei.
| Klasse | Belege | Bedeutung |
|---|---|---|
| Index deckt das Original | 387 | Chunk-Text ≥ 90 % des gelesenen Originals |
| Index mit Lücke | 64 | zusammen ~560.000 fehlende Zeichen; bei 50 hält der Index höchstens 2.000 Zeichen (12 genau 2.000 — die Kappung des Vorschau-Lesers). Größte: #8084 (83 von 66.076), #8081, #8279, #8042 |
| ohne Index | 61 | keine Chunks; Grund je Beleg: messe_204_ungechunkt.py |
| OCR nötig | 3 | Scan ohne Textschicht, kein Index |
| Scan mit OCR-Index | 36 | vom Batch-Weg per OCR indexiert; ohne OCR nicht nachprüfbar, nie als „deckt“ gezählt |
| nicht lesbar | 6 | 4 „.pdf“ sind Bilder, 2 unbekanntes Format |
| nicht gemessen | 251 | 58 nur auf Drive; sonst CSV, Mail, Text, Bild, Office — anderer Leseweg |
Nachlauf-Kandidaten (Lücke, OCR nötig, ohne Index): 128 Belege, dafür 4 OCR-Seiten und rund 202.000 Embedding-Token. Einen Euro-Betrag gibt es nicht: kb_model_prices führt für mistral-embed keinen Preis. Der Nachlauf selbst ist eine Freigabe von JC; laut Bauplan zuerst #8279 nach seiner Einstufung, danach begrenzte Stapel — mit der P2-Migration ohne Löschlücke.
Nachlauf 19.09.2026, 18:00–18:13 (JC-Wort über TOWER#57, Fenster 18–22 Uhr). Ohne P2 und trotzdem ohne Löschlücke: 08_OPS/rag01/nachlauf_volltext.py schreibt die neuen Chunks per Upsert über die alten und löscht danach nur die überzähligen Indizes; vor jedem Beleg wird die Wand (Mandant, Stufe) gegen den Bestand geprüft, bei der ersten Auffälligkeit bricht der Lauf ab. Ein Trockenlauf um 14:30 fand 8 auffällige Belege; sie sind ausdrücklich ausgenommen (Herabstufung streng_vertraulich → intern bei #8042, #8188, #8410; Mandantwechsel bei #8043, #8044; Wand nicht auflösbar bei #8484, #8486, #8487 — Befund an VERTRAULICH#01).
| Stapel | geschrieben | Fehler | Chunks vorher → nachher | Zeichen vorher → nachher |
|---|---|---|---|---|
| 1 (mit #8279) | 6 | 4 | 9 → 38 | 26.336 → 99.785 |
| 2 | 10 | 0 | 5 → 25 | 4.611 → 45.225 |
| 3 | 10 | 0 | 11 → 36 | 18.443 → 77.545 |
| 4 | 10 | 0 | 12 → 69 | 12.299 → 145.382 |
| 5 | 10 | 0 | 9 → 21 | 5.261 → 22.829 |
| 6 | 10 | 0 | 6 → 21 | 5.414 → 17.933 |
| 7 | 5 | 5 | 3 → 27 | 7.281 → 71.466 |
| 8 | 10 | 0 | 10 → 70 | 22.331 → 166.780 |
| 9 | 10 | 0 | 5 → 19 | 5.820 → 20.162 |
| 10 | 10 | 0 | 7 → 22 | 10.823 → 23.565 |
| 11 | 8 | 2 | 0 → 16 | 0 → 13.070 |
| 12 | 10 | 0 | 0 → 31 | 0 → 42.128 |
| Nachfahrt der 11 (18:12, mit Fix #2175) | 11 | 0 | 0 → 13 | 0 → 8.553 |
| zusammen | 120 | 0 | 77 → 408 | 118.619 → 754.423 |
Alle 120 mit Erschließung „vollständig“ aus dem Original; 4 OCR-Seiten; 382.737 Embedding-Token — fast doppelt so viel wie die Schätzung (Zeichen/4 ohne Mailtext), die Schätzregel ist also zu knapp. #8279: 2 → 24 Chunks, 5.682 → 67.261 Zeichen. Die 11 Fehler hatten eine Ursache: NUL-Zeichen aus pypdf, die Postgres nicht annimmt (22P05). Keiner der 11 hatte vorher einen Index, verloren ging also nichts. Die Wurzel liegt im Baustein volltext und ist behoben (#2175, PR #2877, Dienstfassung 1.12.188, wartet auf das Deploy-Wort); die 11 wurden mit dieser Fassung aus dem Worktree nachgefahren. Nicht im Nachlauf: #7326 (Volltext kürzer als der Index, übersprungen) und die 8 ausgenommenen. Noch offen: Abnahme über KAI an #8279 und die Live-Abnahme von P1 im Dienst — seit dem Deploy am 19.09. ist kein neuer Beleg eingegangen.
P3 — Rechte und KAI: Lesewege inventarisiert, eine Wache ergänzt (19.09.2026, Registerzeile #2180). Kein zweites Inventar: die Lesewege-Tabelle „Leseweg × Decke × Wache“ führt VERTRAULICH#01 an EINER Stelle, konzept_sicherheit §6 (dort auch das RPC-Gate von search_knowledge_scoped; die Tabellen-Policies von rag_chunks stehen in §5). RAG#01 hat die Wege auf rag_chunks beigesteuert: KAI Vektor- und Lexik-Suche (Mitgliedschaft des Aufrufers, Stufen-Cap in der RPC, bewacht), memory-search-chat (Projekt-Tor + Stufen-Nachfilter, bisher ohne Test — jetzt test_lesewege_memory_search_2180.py in Schritt ㊵, beide Richtungen, Gegenprobe: ohne Tor bzw. ohne Filter je 2 rot), MCP lookup_pipeline_doc (service_role, liest nur source_type='user_doc' — 6 Pipeline-Handbücher, Stufe intern, keine Belege; der ganze MCP-Server ist nur als lokales Einnutzer-Werkzeug tragbar, bewacht von test_mcp_nur_lokal_2181.py, VERTRAULICH#01), n8n-Webhook tgv-skill-rag-search (live am 19.09. inaktiv gemessen; Löschung der Funktion liegt als PROPOSED bei JC). Offen für P3: die Positiv-/Negativfälle aus 7e über KAI selbst (Teil-/Altstände nennen) und das Widerrufsverhalten.
Dieser Ablauf verbindet Touch Once, Human First, Sicherheit, Dokumentmanagement, KAI und fachliche Arbeit. Er ersetzt keine Schwester-Konzepte: dort stehen die jeweiligen Detailverträge. Er macht sichtbar, wann sie im selben Dokumentweg gelten. Die Stufen sind keine starre Warteschlange: nach der gemeinsamen vollständigen Erschließung laufen Wissensindex und Facharbeit unabhängig; Rechte, Herkunft, Version und Lebenszyklus gelten in jeder Stufe.
| Stufe | Ergebnis und verbindliche Anschlüsse |
|---|---|
| 0 · Absicht und Scope | Bestehende Absichten, Mandant, Entität, Projekt und Befugnisse bestimmen. Nur Fragen stellen, die den Weg wirklich verzweigen. Scope kommt serverseitig aus Mitgliedschaft und verengt sich nur. |
| 1 · Eingang und Original | Datei, Mail oder Anlage einmal erfassen; Roh-Original vor jeder Verarbeitung sichern. Herkunft, Elternbezug und Fingerprint bewahren. Eine Mail kann selbst das Original sein; unklare Fälle bleiben auffindbar. |
| 2 · Identität und Schutz | Identische Datei, neue Fassung, fachliche Dublette und Interco-Fall unterscheiden. Mandant, Entität, Projekt und Vertraulichkeit vor jeder Sichtbarkeit bestimmen; unaufgelöst bleibt fail-closed. Hier gilt nur ein vorläufiger Schutz: bis Stufe 3b entschieden hat, ist der Beleg nicht eingestuft und für niemanden sichtbar. Absender, Mail und Betreff sind Hinweise, keine Einstufung. |
| 3 · Vollständige Erschließung | Parser/OCR lesen Seiten, Tabellen und Anlagen vollständig. Abdeckung, Fehler und Extraktionsversion werden nachgewiesen. Vorschau ist nicht Volltext; Teilfehler werden nicht als Erfolg markiert. |
| 3b · Einstufung aus dem Dokument | ORCH entscheidet Vertraulichkeitsstufe und Entitäts-Zuordnung auf der vollständigen Extraktion aus Stufe 3, nicht auf Vorschau oder Mail (JC-Grundsatz 19.09.2026). Naht: VERTRAULICH#01 (#2795, #2796). Erst danach werden Chunks sichtbar und Fachskills gestartet; ein nur teilweise gelesenes Dokument wird mit Vorbehalt eingestuft. |
| 4a · Wissensweg | Geprüfte Chunks und Embeddings als aktive Generation bereitstellen. KAI antwortet mit Quellen, Sichtumfang und ehrlicher Teil-/Altstandsmarkierung. Semantische und lexikalische Suche verwenden dieselbe Wand. |
| 4b · Fachweg | ORCH plant passende Fachskills auf derselben Extraktionsversion: Parteien, Vertrag, Rechnung, Frist, Zahlung, Projekt und weitere strukturierte Ergebnisse. Fachfehler blockiert den Wissensweg nicht. |
| 5 · Klärung und Freigabe | Nur echte Unsicherheit, Konflikte, sensible Fälle und schreibende Aktionen erreichen den Menschen. Vorschlag, Korrektur, Bestätigung, Undo und tatsächlicher Vollzug bleiben getrennt und nachweisbar; die betroffene Arbeit läuft danach gezielt weiter. |
| 6 · Ergebnis und Rückfluss | KAI, Karten, Fachscreens und Belegöffnung zeigen dieselbe berechtigte Wahrheit. Jede Aussage trägt Quelle, Version und Bearbeitungsstand. Korrekturen erzeugen Lernereignisse für Antwortqualität, Systemverbesserung und berechtigtes Kontextwissen. |
| 7 · Lebenszyklus | Änderung, Hoch-/Runterstufung, Projektwechsel, Archivierung, Aufbewahrung, Export und Löschung aktualisieren Original, Fachobjekte, Index, Quellen, Cache und Rechte. Ein alter Link oder Chunk darf keine alte Berechtigung konservieren. |
Durchgehende Invarianten: Quelle an jeder Aussage und jeder Zahl; Original und Version reproduzierbar; keine Rechte aus Prompt oder Client; jeder Schreibvorgang mit der vorgesehenen Freigabe; keine Teilindex-Aktivierung; eindeutige Zustände für gespeichert, vollständig erschlossen, durchsuchbar, fachlich bearbeitet und prüfbedürftig. Aus jedem Lauf entsteht eine sichtbare Lücke oder ein geprüfter Erfolg, nicht stilles Vergessen.
Bestehende Bausteine und Lücken: Originalablage, Dokument-/Ereignisfelder, Dublettencheck, ORCH, Fachskills, Klärung mit Undo, RAG-Tabellen, zwei produktive Suchwege und Pattern-Promoter bestehen. Noch zu verdrahten beziehungsweise nachzuweisen sind Vollständigkeits- und Generationenvertrag, Rechtegegenproben über alle Lesepfade, Wiederaufnahme nach Klärung, sichere Nutzung gelernter Muster sowie der Bestandsnachlauf. Der vollständige Bau- und Verdrahtungsplan steht im zugehörigen Word-Dokument und wird nach jedem Paket mit diesem Abschnitt abgeglichen.
JC 11.10.2026 wörtlich: „wie sichern wir eine optimale Qualität der OCR Scans? und dass die chunks verlustfrei erstellt werden? haben wir im Workflow nur einen Scan-Durchgang? bei ORCH am Prozess-Anfang? oder weitere durch die Sub-Agenten? oder Skills?“ und „Ich frage mich ob dieser pauschale Wert 3200 für alle Art von Input die TGV bekommen wird der richtige Weg ist? Was ist mit Verträgen über 200 Seiten? […] Ist nicht eine Differenzierung der Input-Token-Limits je nach Prozessschritt ein passender Weg? Wie machen es die Profis, damit auch die Token-Kosten minimiert / optimiert bleiben?“ Status: Konzept. Es ist nichts gebaut, und der Bau wartet auf JCs Wort (§7g-5).
| Frage | Messwert | Fundstelle / Instrument |
|---|---|---|
| Wie oft wird das Original gelesen? | Bis zu 4×: parse-docling (Volltext), pdf-text-snippet (Vorschau), pdf-invoice-extract (eigenes pypdf, ohne OCR) und rag-ingest (liest neu, statt den Volltext zu übernehmen). OCR bis zu 2× bezahlt: parse-docling und rag-ingest bauen je ein eigenes OcrWahl. | parse-docling/skill.py:490-492 · tgv-skill-pdf-text-snippet/skill.py:313 · pdf-invoice-extract/skill.py:1247 · rag-ingest/skill.py:854-856 |
| Wer liest den gespeicherten Volltext? | ORCH, contract-extract und die KAI-Detailansicht lesen extracted_markdown. tax-extract liest nur die Vorschau (2.000 Zeichen). Der Erschließungsstand (vollständig/teilweise) steht in keiner Spalte von documents, sondern nur in Ereignis, Plan und source_meta. | tax-extract/skill.py:75,332 · executors_klaerung.py · dispatch.py:907-923 |
| Deckt der Index das Original? | 869 Belege mit Datei: 159 vollständig (neuer Leser) · 387 deckt · 5 Lücke · 19 ohne Index · 1 OCR nötig · 36 OCR-Index ungeprüft (606 Scan-Seiten) · 9 nicht lesbar · 253 nicht gemessen (66 CSV, 40 nur auf Drive, 34 Mail, 67 Bilder, 13 Office u. a.). Gegen 19.09.: Lücke 64 → 5, ohne Index 61 → 19. | 08_OPS/rag01/inventar_volltext.py, OCR aus |
| Wurde Text abgeschnitten? | #8042 (16 Seiten): Der Index hält 2.000 von 46.270 Zeichen. Das ist genau die Kappung der Vorschau. Der Beleg ist seit 19.09. vom Nachlauf ausgenommen, weil er herabgestuft wurde (VERTRAULICH#01). Die übrigen 4 Lücken betreffen Belege mit 1 bis 4 Seiten. | Inventar, Klasse index_luecke |
| Fertig, aber nie indexiert | 12 der 19 Belege ohne Index sind NIE_VERSUCHT, darunter 5 Verträge im Zustand „done“ (#8505 mit 12 Seiten, #8506, #8507, #8508, #8536). Der Auslöser am Kettenende startet rag-ingest nur für Finanzbelege. Die Taxonomie plant ihn auch für VERTRAG, an diesen fünf ist er aber nie gelaufen. | dispatch.py:1522-1531 · taxonomy.py:104 · messe_204_ungechunkt.py |
| Längster Beleg | #7707: 58 Seiten, 120.532 Zeichen, 45 Chunks, deckt. Längster Vertrag: #7987 mit 38 Seiten und 24 Chunks (OCR-Index). Im Bestand liegt kein Beleg über 58 Seiten, ein Vertrag mit 200 Seiten ist also noch nie durchgelaufen. Gemessen: 1.922–2.078 Zeichen je Seite (#8279, #7707). | Inventar · rag_chunks |
| ORCH: wie viel liest er? | 343 Pläne seit 19.09., alle verfahren=voll (keiner über 200.000 Zeichen). Eingabe-Token: Median 2.344, p90 3.606, Maximum 35.513 (#7707). Zusammen 960.160 Token ≈ 0,44 €. Befund: Alle 96 PDF-Pläne kamen über Retriage, und 56 davon tragen keinen Erschließungsstand (0 bis 1.019 Zeichen). ORCH urteilte dort auf der Vorschau. Das Retriage-Tor liest außerdem keine Chunks. | agent_events orch.plan_served · agent_loop.py:43-45 · dispatch.py:1264 |
| Token je Schritt | kai.chat: 467 Aufrufe, 8,43 Mio. Eingabe-Token, 6,06 € (Ø 18.041 je Aufruf) · pdf-invoice-extract: 260 Aufrufe, 384.422 Token, 1,31 € · rag-ingest: 146 Aufrufe, 208.585 Token, 0,25 €. ORCH bucht in skill_call_costs keine Token (nur in agent_events). OCR-Seiten bucht der Dienst nicht (bekannt, P1). | skill_call_costs 20.05.–11.10.2026 · kb_model_prices |
| OCR-Qualität | Wird nicht geprüft. TGV fragt Mistral nur nach Markdown. Die vorhandenen „confidence“-Werte sind Selbsteinschätzungen der LLMs, keine OCR-Messung. | volltext.py:423 · Prüfreichweite: alle *.py/*.sql/*.js |
| Baustein | A · heute | B | C | Empfehlung |
|---|---|---|---|---|
| (1) OCR-Qualitätstor | Keine Prüfung. Nur „Seite ohne Text gilt als nicht gelesen, nicht als leer“ ist gesichert. | Plausibilität ohne Mehrkosten: Zeichen je Seite, Beträge, Datum und IBAN-Prüfziffer gegen die Fachfelder. | B, dazu die Seiten-Konfidenz von Mistral (confidence_scores_granularity). Ein zweiter Durchgang nur für Seiten unter der Schwelle, gelesen von einem zweiten Leser als Gegenprobe (docling-OCR auf Hetzner, EU). Widersprechen sich die Beträge, geht der Beleg in die Klärung statt still weiter. | C. Die Schwelle ist ein Wert mit Herkunft nach §8 (zuerst Vorgabe, AUTO erst nach Messung). Erster Prüffall: die 36 OCR-Belege mit 606 ungeprüften Seiten. |
| (2) Zerlegung je Belegart | 3200/400 für alles. Der Seitenanker seite:N ist vorhanden. | Nach Struktur: Rechnung und Quittung als ein Chunk, wenn sie kurz sind · Vertrag und Urteil nach Überschrift oder Klausel · Kontoauszug je Buchung, mit Tabellenkopf · Mail und Anhang getrennt (gibt es schon). Dazu Eltern/Kind: das Kind (Absatz, Klausel) wird gesucht, das Eltern-Stück (Abschnitt, Seite) geht an KAI. | Semantische oder LLM-Zerlegung: kostet je Beleg einen Modellaufruf. Laut Chroma ist der Gewinn gegenüber gut eingestellter Zerlegung nach Regeln klein. | B, aber erst messen, dann umschalten (messe_chunk_groesse.py, §8d, je Belegart). ⛔ Ein Eltern-Abruf ist ein neuer Leseweg. Er geht durch dieselbe Wand wie die Suche (§7c), nie über einen direkten Tabellenzugriff. |
| (3) Ein Lesen, Lesetiefe nach Bedarf | Jeder Skill liest selbst, zum Teil nur die Vorschau. | Die Extraktion wird einmal gespeichert (Text, Seiten, Abdeckung, Fingerprint), und alle Leser lesen daraus. ORCH stuft auf dem Volltext ein (JC 19.09.). | B, dazu Lesetiefe in Stufen: 0 Vorschau, nur für Dublette und Format · 1 gespeicherter Volltext für ORCH, Fachskills und Index · 2 gezielt neu lesen, nur wenn das Qualitätstor eine Seite beanstandet, eine neue OCR-Fassung kommt oder ein Fachskill das Layout braucht (Tabelle, Unterschrift). Dann werden nur die betroffenen Seiten gelesen. KAI nennt bei jeder Antwort die Abdeckung, und ein Prüfauftrag über den ganzen Vertrag arbeitet alle Abschnitte ab, statt sich auf die Top-k-Suche zu verlassen (§7a). | C. Auf JCs Frage: ORCH stuft nicht auf einer Vorschau ein, und die Sub-Agenten scannen nicht neu. Neu gelesen wird nur, was das Tor beanstandet. |
| (4) Token-Budget je Schritt | Verstreute Konstanten im Code (Tabelle unten). | Eine Budget-Tabelle je Schritt in tunable_params, mit Leser (§8b). | B, dazu AUTO aus Messung (§8d). | B jetzt, C später. Die Kosten zeigt die Tabelle unten. |
Budget je Schritt — heute und Vorschlag, gerechnet für einen gescannten Vertrag mit 200 Seiten (≈ 400.000 Zeichen bei gemessenen ~2.000 Zeichen je Seite; Preise aus kb_model_prices, 0,92 €/USD):
| Schritt | Heute | Vorschlag | Kosten bei 200 Seiten |
|---|---|---|---|
| Lesen / OCR | Nur Scan-Seiten, aber bis zu 2× (siehe 7g-1) | 1×, nur Scan-Seiten. Den Bestand über den Batch-Weg zum halben Preis | 200 × 0,001 USD = 0,18 € (heute bis 0,37 €) |
| ORCH Einstufung | Bis 200.000 Zeichen ganz, darüber in Abschnitten von 60.000 mit Signalen agent_loop.py:43-45 | Bleibt so. Grenze als Budget-Zeile | ≈ 115.000 Token (gemessen ~3,5 Zeichen je Token) ≈ 0,05 € |
| Fachskill Rechnung | 12.000 Zeichen pdf-invoice-extract:133 | Bleibt (eine Rechnung passt fast immer hinein), aber aus der gespeicherten Extraktion | — |
| Fachskill Vertrag | Ganzer Text, ohne Schnitt | Je Klausel über die Eltern-Stücke, danach zusammenführen | Größenordnung wie ORCH |
| Fachskill Steuer | 6.000 aus einer Vorschau von 2.000 tax-extract:75,332 | Aus dem Volltext | — |
| Wissensindex | 3200/400 für alles | Je Belegart (2-B) | ≈ 230.000 Token × 0,10 USD/M ≈ 0,02 € |
| KAI | Suche: 6 Chunks · Detail: 20.000 Zeichen | Kind-Treffer mit Eltern-Kontext. Prüfauftrag: alle Abschnitte, Abdeckung wird genannt | Heute Ø 18.041 Token je Aufruf ≈ 0,013 € |
skill_call_costs). ORCH (0,44 €) und OCR sind dort nicht gebucht.search_knowledge_lexical).average_page_confidence_score und minimum_page_confidence_score, auf Wunsch auch je Wort. Mistral Docs · OCR ⛔ Am Live-Dienst nicht geprüft. Das ist der erste Handgriff des Baus.Reichweite: Repo-Code auf master f22dd1cc9 · Live-Datenbank am 11.10.2026, nur gelesen (rag_chunks, documents, agent_events, skill_call_costs, kb_model_prices) · Inventar mit dem echten Leser, OCR aus. Nicht gemessen: die laufende Dienstfassung auf Hetzner · n8n · ob die Mistral-Konfidenz live geliefert wird · die Güte der Antworten (nur Auffindbarkeit und Abdeckung) · die Zeichenqualität der 36 OCR-Belege.
JCs Auftrag, 06.10.2026, wörtlich: „dazu erwarte ich eine nachhaltiges KONZEPTION deinerseits und eine pragmatische Parameter/Einstellungsseite für Admins mit Erklärungen!!!! Bitte einbauen aber erst wenn du ein Gesamtkonzept der Eintuning durch user [hast] (mit ggf überall AUTO, damit der User sich darauf verlassen kann dass TGV es automatisch optimiert, wenn der user nicht weiss was er eingeben soll." ⇒ Drei getrennte Forderungen: Gesamtkonzept zuerst („erst wenn"), Erklärungen statt Felder, und AUTO als Vorgabe, die niemand verstehen muss. Dieser Abschnitt ist das Konzept; die Fläche selbst ist der zweite Schritt.
Anlass war die Beobachtung, CHUNK_CHARS = 3200 stehe an fünf Stellen, „ein Parameter, der an fünf Stellen steht, hat keinen Ort". Gemessen ist es anders — und schlimmer. Der Ort existiert dreifach gebaut: die Ablage tunable_params (05_SCHEMA/248_admin02_tunable_params_flaeche.sql:95-101, beide Zeilen leben), der getippte Leser chunk_chars() (08_OPS/tgv_tunables.py:138) und die Zeiger-Spalte code_ref mit eigenem Wächter. ⭐ Nicht der Ort fehlt, die Leser fehlen — und das ist eine ganz andere Reparatur.
Gemessen am 06.10.2026 mit 08_OPS/mess_parameter_ort.py (netzfrei, schreibt nichts, Selbsttest grün auf 4 Achsen je blind UND unscharf). Die Einheit eines Lesers ist die Datei, und als Leser zählt nur ein Aufrufknoten im Syntaxbaum — nicht eine Nennung im Text:
| Schlüssel | Ablage | Leser | Hardcode-Zwillinge daneben |
|---|---|---|---|
klaer_schwelle | ja | 1 · 08_OPS/agent_orch01/einstufung_entscheid.py:79 | 0 |
llm_model | ja | 0 | 0 |
max_tokens | ja | 0 | 0 |
chunk_chars | ja | 0 | 3 · rag01/ingest_core_privat.py:75 · tgv-skill-rag-ingest/skill.py:129 · tgv-skill-rag-ingest-project/skill.py:59 |
chunk_overlap | ja | 0 | 3 · …:76 · …/skill.py:130 (heißt dort OVERLAP_CHARS) · …/skill.py:60 |
gesamt_max | ja | 0 | 1 · 08_OPS/chat_engine/executors_rag.py:638 |
p_top_k | ja | 0 | 0 |
p_min_score | ja | 0 | 0 |
anforderungs_register.html); ein Blatt, das einen Ruf beschreibt, ruft nichts. ⓶ zu leer — sie verpasste den einzigen echten Ruf, weil der Import ihn umbenennt (import klaer_schwelle as _klaer_schwelle, gerufen als _klaer_schwelle()). ⭐ Ein Instrument, das Text liest, kann „wer RUFT" nicht beantworten — es sieht Namen, keine Rufe. Dieselbe Falle trägt die Fläche selbst: max_tokens steht als API-Körperfeld, llm_model als Log-Feld, p_top_k als RPC-Parameter im ganzen Haus. Wer am Wort zählt, meldet hier vier Leser, wo einer ist.Ein Schalter wirkt erst, wenn alle drei Stücke stehen. Sie fehlen unabhängig voneinander, und genau deshalb hat die Fläche heute den Anschein von Fertigkeit:
| Stück | Frage | Fehlt es, dann … | Stand 06.10. |
|---|---|---|---|
| ① Ablage | Gibt es eine Zeile, die den Wert hält? | … ist jede Eingabe sofort wieder weg. | 8 von 8 da |
| ② Leser | Fragt der Code sie, bevor er handelt? | … ist die Eingabe wirkungslos, und zwar still. Der schlimmste der drei Fälle: der Verwalter sieht einen Erfolg. | 1 von 8 |
| ③ Schreibrecht | Darf der, dem wir den Schalter zeigen, ihn auch setzen? | … ist der Schalter Dekoration, oder er schreibt für alle Mandanten. | alle 8 super_admin |
Dieselbe Dreiteilung hat die Vorarbeit schon gemessen und als Satz formuliert: „Drei verschiedene Lücken (Ablage · Leser · Schreibrecht) — wer eine schließt, hat nichts geschlossen." ⇒ Für die Seite ist das eine Bauvorschrift: eine Zeile darf nur dann als schaltbar erscheinen, wenn alle drei Stücke belegt sind. Für die übrigen gilt §8e.
Eine Einstellung hat nicht „einen Wert", sondern einen Wert und eine Herkunft. Vier Zustände, und der Unterschied zwischen ① und ② ist der ganze Sinn der Übung:
| Zustand | Was der User liest | Was es technisch heißt |
|---|---|---|
| ① AUTO · gewählt | „TGV hat 3200 Zeichen gewählt — gemessen am 04.10. an 895 Dokumenten. Warum: bei 800 Zeichen rutschten Treffer nach vorn, aber der Unsinn stieg mit." | herkunft='auto' + messbeleg zeigt auf einen echten Lauf. Nur dieser Zustand darf „AUTO" heißen. |
| ② VORGABE · noch nicht gemessen | „Steht auf 3200 — unser Hauswert. Für dich noch nicht gemessen; TGV misst, sobald genug Belege da sind." | herkunft='vorgabe', kein Messbeleg. ⛔ Ehrlichster Zustand und der häufigste. Sieht er wie ① aus, ist AUTO von einem Hardcode nicht zu unterscheiden — genau JCs Sorge. |
| ③ HAND | „Du hast 2400 gesetzt, am 06.10. — zurück auf AUTO." | herkunft='hand' + wer + wann. AUTO überschreibt das nie, auch nicht nach einer besseren Messung — es schlägt vor. |
| ④ GESPERRT | Der Grund, in seiner Sprache — siehe §8e. | Mindestens eines der drei Stücke aus §8b fehlt belegt. |
llm_aufgaben mit UNIQUE (aufgabe_key, mandant_id), Leseform holt beide Ebenen (08_OPS/modell01/policy_laden.py:67), Auswahl „Mandanten-Zeile schlägt Vorlage" (:152). ⇒ Die Fläche erbt diese Form, sie erfindet keine zweite.Und AUTO ist selbst eine Einstellung — die einzige, die der User immer versteht: „soll TGV das für mich entscheiden?" Steht sie auf ja, ist der Wert ein Zwischenstand einer Messung, kein Beschluss. Deshalb darf ein AUTO-Wert sich ändern, ohne dass jemand etwas falsch gemacht hat — und deshalb muss jede Änderung ihren Beleg mitführen, sonst ist sie von einem Fehler nicht zu unterscheiden.
Die Form dafür ist im Haus schon erfunden und gilt als die beste ihrer Art: das Telemetrie-Trio (05_SCHEMA/285_telemetrie01_achse_und_turn_STAGED.sql:239-264) speichert nicht nur die Zustimmung, sondern _von und _am dazu — und ein CHECK erzwingt, dass der Wert ohne seinen Nachweis nicht setzbar ist. Übertragen auf Einstellungen:
| Feld | Was es trägt |
|---|---|
wert | der geltende Wert |
herkunft | auto · vorgabe · hand — die vier Zustände aus §8c (gesperrt ergibt sich, es wird nicht gespeichert) |
gewaehlt_am / gewaehlt_von | wann, und bei hand: von wem |
messbeleg | Zeiger auf den Lauf, der diesen Wert gewählt hat — und auf die Zahl, die ihn trug |
CHECK (herkunft <> 'auto' OR messbeleg IS NOT NULL). ⇒ Ein AUTO ohne Erklärung ist nicht verboten, es ist unmöglich. Eine Grenze, die man umgehen kann, ohne dass eine Probe fällt, ist eine Absicht — sie gehört in den Schlüssel, nicht in eine Prüfung daneben.Woher der Messbeleg kommt — und was er nicht ist. 08_OPS/rag01/messe_chunk_groesse.py ist gebaut (431 Zeilen) und misst je Chunk-Größe vier Zahlen, die zusammengehören: Rang des richtigen Treffers · wer dabei verdrängt wird · ob der Unsinn mitsteigt · Aufrufe und 429er. Es sagt in seinem eigenen Kopf, was es nicht misst: „Auffindbarkeit, nicht Antwortgüte" — ein Chunk kann den richtigen Rang haben und zu wenig Kontext für eine brauchbare Antwort tragen. Und es schreibt nichts.
⇒ Es ist der Beweis-Erzeuger für AUTO, nicht AUTO selbst. Die Unterscheidung ist nicht akademisch: der Lauf ist korpusweit und kostet Embedding-Aufrufe, kann also nie zur Laufzeit je Dokument entscheiden. AUTO ist deshalb periodisch: ein Lauf wählt, schreibt Wert und Beleg, und der Dienst liest beides. ⭐ Ein Nebeneffekt ist das stärkste Argument für genau EINEN Ort: das Messwerkzeug importiert ingest_core_privat als Quelle der Chunk-Logik (messe_chunk_groesse.py: import ingest_core_privat as ING) — wandert die Konstante in die Fläche, folgt die Messung von selbst. Bleiben es drei Stellen, misst das Werkzeug irgendwann etwas anderes, als der Dienst tut, und niemand merkt es.
08_OPS/heimholung02/mutationsprobe.py:253 schreibt die Literalzeile vor: sie ersetzt Textanker wie "CHUNK_CHARS = 3200" und "if last_space > CHUNK_CHARS * 0.6:", um den Paritäts-Test rot zu machen. Wird die Größe im Schleifenrumpf ein Ruf, zeigen zwei dieser Anker ins Leere. ⭐ Korrektur an der ersten Fassung dieses Satzes, nachgelesen statt vermutet: dort stand *„meldet grün als überlebt"* — das ist falsch. Dieser Lauf zählt seinen Anker, bevor er schreibt (original.count(suchen) != 1 ⇒ durchgerutscht, dann [STUMPF] und rc=1). ⇒ Der Zug bleibt unteilbar, aber aus dem anderen Grund: wer die Leser verdrahtet und die Anker liegen lässt, macht die Probe stumpf und seine Bahn rot — er fälscht sie nicht. Ein Prüfer, der seinen eigenen Anker zählt, ist gegen genau diese Klasse schon gebaut — das war nachzulesen, nicht zu vermuten. Dazu verlangt 07_TESTS/heimholung06/test_rag_ingest_paritaet.py:26 die Chunk-Logik beider Skills zeichengleich. ⇒ Zwei Skills + Mutationsprobe + Paritäts-Test in einem Zug. ⭐ Und die „fünfte Stelle" ist gar keine Definition: 08_OPS/check_code_ref_zeigt_ins_leere.py:342 ist ein Fixture-String im Selbsttest. Von fünf Stellen sind drei Definitionen und zwei Wächter — wer alle fünf „aufräumt", entwaffnet zwei Prüfer.JCs Auflage: „ein gesperrter Schalter zeigt nicht nur DASS er gesperrt ist, sondern WARUM, in seiner Sprache — fehlt die Funktion, fehlt das Feld, oder gilt er fürs ganze Haus." Die drei Gründe sind genau die drei Stücke aus §8b, von hinten gelesen:
| Grund | Was dem User steht | Woran es gemessen wird |
|---|---|---|
| Fehlt das Feld | „Dafür gibt es bei uns noch keinen Platz — wir bauen ihn." | keine Zeile in der Ablage (Achse 1) |
| Fehlt die Funktion | „Du könntest das einstellen, aber noch würde es nichts ändern — TGV fragt diesen Wert noch nicht." | kein Aufrufknoten (Achse 2) — heute 7 von 8 |
| Gilt fürs ganze Haus | „Dieser Wert gilt für alle Mandanten. Nur der Betreiber kann ihn ändern." | owner_tier='super_admin' bzw. Schreib-Policy (Achse 3) |
Und die Erklärung ist Pflichtinhalt, nicht Hilfetext. Jede Zeile trägt vier Sätze, die ein Mensch ohne Vorwissen lesen kann: was es tut · was passiert, wenn du es hochstellst · was passiert, wenn du es runterstellst · woher der jetzige Wert kommt (§8c). Fehlt der dritte Satz, ist der Schalter eine Falle; fehlt der vierte, ist AUTO ein Gerücht.
Geerbte Vorbedingung, nicht Aufgabe dieser Fläche: die secSettings-Nabe und zwei weitere Menü-Renderer rufen das Klassen-Tor klasseErlaubt nicht (gemessener Fremdbefund, eigener Eigner). ⇒ Die Seite wird nicht an eine ungetorte Nabe gehängt. Kein Datenabfluss — die Endpunkte dahinter antworten per Mitgliedschaft des Aufrufers — aber eine Fläche mit gesperrten Zeilen darf nicht ausgerechnet über den Weg erreichbar sein, der die Rolle nicht prüft.
Die Fläche verspricht Mandantenfähigkeit an einer Stelle, an der sie sie nicht hat. owner_tier lässt 'mandant' ausdrücklich zu und der Tabellenkommentar sagt „mandant-justierbar (dann RLS-scoped, Default-Deny)" — aber der Primärschlüssel ist PRIMARY KEY (key) allein. ⇒ Zwei Mandanten können denselben Schlüssel nie verschieden belegen. Dazu liest der einzige produktive Leser ohne jeden Mandanten-Filter (08_OPS/tgv_tunables.py: ?key=eq.<key>&select=value&limit=1) und fährt mit dem Service-Schlüssel an der RLS vorbei.
owner_tier trägt. Die Seite zeigt sie nach §8e als „gilt fürs ganze Haus", und sie verspricht keine Mandanten-Spalte, solange der Schlüssel keine tragen kann.Der Weg hinaus ist bekannt und erprobt, nicht neu: die mandantenfähige Form läuft im Haus bereits als llm_aufgaben — UNIQUE (aufgabe_key, mandant_id), beide Ebenen gelesen, Mandanten-Zeile schlägt Vorlage, und eine Schreib-Policy (mandant_id IS NOT NULL) AND is_mandant_admin(…), die den Hauswert schützt. ⇒ Erben, nicht erfinden. ⚠️ Der Umbau selbst ist DDL an einer lebenden Tabelle mit RLS-Versprechen und liegt als Entscheidungsvorlage bei JC — er ist nicht Teil dieser Fläche.
owner_tier per CHECK auf 'super_admin' und hält die Spalte mandant_id (Mig 262, die zweite Tür derselben Erlaubnis) per CHECK auf NULL; Gegenbeweis in der Transaktion. Ⓑ (der Umbau oben) kommt erst, wenn ein Mandant es verlangt. Der Prüfer 08_OPS/mess_parameter_ort.py Achse 3 liest dafür den Stand (Seed + angewandte spätere Migrationen), nicht mehr nur den Seed. ⚠️ Bis JC Mig 294 fährt, gilt der Absatz darüber unverändert (PARAMETER#05, #3950).Befragt, und das ist die Reichweite jeder „kein Leser"-Aussage oben: die Regale 08_OPS · 02_SKILLS · 06_DASHBOARD, alle .py geparst (1074 Dateien im Blick), dazu der Seed Mig 248 und der Helfer tgv_tunables.py. Ausgenommen sind 07_TESTS (ein Test beweist den Helfer, nicht die Verdrahtung) und der Messlauf selbst.
Nicht befragt — und was deshalb offen bleibt: der ausgelieferte Dienst (gemessen ist Repo-Code, nicht die laufende Fassung auf Hetzner) · die n8n-Instanz · die Wirkung der Werte, wo ein Leser existiert (dass klaer_schwelle gelesen wird, ist gemessen; dass die Schwelle das Verhalten ändert, nicht) · ob 3200 heute der richtige Wert ist (das misst §8d und ist ungefahren) · die Baseline von check_werte_ohne_leser.py, die tunable_params-Spalten ausdrücklich stundet — grün heißt dort nicht leserlos-frei.