Der Weg eines Belegs von Mail oder Upload bis zum Menschen, in 8 Stationen und 34 Prüfpunkten. Die Heimat dieser Kette ist Datenfluss § 1c; diese Seite ist ihre lebende Fassung.
01_ITERATIONS/CONTROL_TOWER_HANDOFF/EINGANGSKETTE_SOLL.md) — unten
wörtlich durchgetragen. ·
IST = Messung, erzeugt aus 08_OPS/eingangskette.json; jeder
Punkt trägt seine eigene Uhr.acfa70d26 ·
Erzeuger gen_eingangskette.py.
Die Zahlen unten sind nicht von heute — sie sind von der Messuhr, die an
jedem Punkt steht.
42 Knoten, 19 Kanten, gelesen von
eingangskette_graph.eingangskette_kanten() und gekappt von
graph_projektion.reduziere() — kein zweites Bild, dieselbe Quelle,
die auch den Screen speisen wird.
⛔ Wo keine Kante steht, ist keine gemessen. Ein gestrichelter Pfeil würde „schwach, aber da“ sagen; die Messung sagt „nicht da“. Ein rot gemessener Prüfpunkt bekommt seinen Knoten, aber keine Kante — die Lücke steht im Bild, nicht im Kleingedruckten.
◆ SOLL · Urteil · von Hand · wörtlich durchgetragen
Diese Datei ist URTEIL und bleibt von Hand. Sie sagt, welcher Schritt fehlt und warum — und jede Aussage trägt ihr Datum und ihren Urheber. Der Erzeuger
08_OPS/gen_eingangskette.pyträgt sie wörtlich in06_DASHBOARD/konzepte/eingangskette.html; er rechnet hier nichts nach und lässt nichts weg.⛔ Was hier NICHT hingehört: Messungen. Die stehen in
08_OPS/eingangskette.json, tragen je Punkt eine Uhr und werden erzeugt. Wer hier eine Zahl schreibt, baut die siebte Handfassung dieser Kette — genau das, wogegen diese Seite gebaut ist.⭐ Der Grund für die Trennung ist eine Hausnarbe (Register #3741, 04./05.10.2026): eine Ablösung, die nur den rechenbaren Teil übernimmt, ist dort ein Verlust, wo das Urteil stand. Also beides — nie vermischt, nie eines ohne das andere.
Urheber: TOWER#64 · 05.10.2026 · auf JCs ausdrückliches JA
Die Eingangskette war am 05.10.2026 mindestens siebenmal dargestellt, und keine Darstellung war die geltende (die sieben stehen unten in §3). Im Kompendium — der Arbeitsgrundlage — gab es die Stationen überhaupt nicht: konzept_datenfluss.html und konzept_dokumente.html beschreiben das Prinzip, keine zeigte den Weg eines Belegs Punkt für Punkt.
⭐ Und zwei der sieben waren an diesem Tag nachweislich überholt. Das ist der ganze Grund: eine handgeschriebene Kette altert in Tagen. Deshalb ist der IST-Teil dieser Seite erzeugt und läuft im register-nachzug bei jedem Master-Merge mit.
Urheber: FOLLOW#01 (Messung) · TOWER#64 (Eignerzuteilung) · 04./05.10.2026
Die Kette trägt heute: die Bytes gehen nicht verloren, die Mandantenwand hält, der Router läuft. Sie endet nicht beim Menschen: die drei letzten Stationen — Zuordnung, Sichtbarkeit, Klärung — sind zusammen 9x rot und 2x grün.
In einem Satz: Die Übergabe an TGV ist gesichert, die Ablage ist kanonisch, die automatische Zuordnung ist unvollständig von Entwurf wegen, und die Abarbeitung endet in einem Regal, das niemand liest.
Was fehlt: der Mail-Body als Beleg. Wenn der Beleg die Mail selbst ist, ist seine Sicherung nicht verdrahtet; sechs freigegebene Belege existieren nur als Text. Warum: gestundet unter #537 — und der Wächter davor endet mit rc=0, damit er nicht dauerrot jeden Wächter hinter sich verdeckt. ⭐ Das ist die Regel „ein dauerrotes Tor ist ein toter Meldeweg“ richtig angewandt — und es heißt, dass hier ein rc=0 kein Grün ist. (Eigner: STORAGE / #537)
Was fehlt: nichts am laufenden Weg — der Kanon „Bytes zuerst“ hat gehalten. Was offen ist: ein Altbestand ohne Bytes und ein Band, das wächst statt zu schrumpfen. ⛔ Das Zweite ist der ernstere Satz: eine Grundlinie, die nur schrumpfen darf, und die trotzdem wächst, ist kein Bestandsproblem, sondern ein laufender Zufluss. (Eigner: STORAGE für die Heimholung, ABLAGE für das Band)
Was gut ist, und es gehört laut gesagt: der Ablage-Skill hätte den Parkpfad in final_path schreiben können, und der Beleg hätte als abgelegt gegolten. Er tut es ausdrücklich nicht und begründet es. Die Ablage der zehn ist deshalb kein eigener Bruch, sondern die korrekte Folge des Bruchs in Station 4.
Was fehlt: das Aggregat sagt nicht, was das Ereignis sagt. Der Ereignistext ist ehrlich (parked), die Liste skills_done ist es nicht (done). ⭐ Dieselbe Sache, zwei Vorzeichen je Schicht — und ein Prüfer zählt Listen, nicht Fließtext. (Eigner: ORCH / ABLAGE)
⭐⭐ Hier ist die Wurzel, und sie ist eine Entwurfs-Lücke, kein Programmfehler. intake_raw.py:91-98 legt ausdrücklich fest, dass Entität und Mandant nie beim Eingang gesetzt werden, und begründet es: „Ein Zweit-Upload, der die Entität einer bestehenden Zeile setzt, verschiebt einen Beleg über die Mandantenwand — als NEBENWIRKUNG einer Wiederholung, ohne dass jemand es entschieden hätte.“ Der Mandant wandert über Re-Triage oder assign-project — ausdrückliche Handlungen, und das sollen sie bleiben.
⇒ Die Kette ist genau hier zu Ende gedacht und nicht zu Ende gebaut. Das Haus weiß seit dem Eingang, zu welcher Entität jeder Beleg gehört, und schreibt es auf (4.2 ist grün). Niemand liest es (8.2 ist rot). Zwischen „gewusst“ und „entschieden“ fehlt kein Algorithmus, sondern ein Regal und ein Knopf.
Was außerdem fehlt: die Vertraulichkeitsstufe. Prinzip 3 nennt sie Fundament, nicht Add-on; bei fast der Hälfte des Bestandes ist sie leer. ⛔ NULL gilt als streng, also ist das kein Leck, sondern eine Unsichtbarkeit — und beide sehen in einer Zählung gleich aus. (Eigner: BANKING#05 für die zehn, ABLAGE/VERTRAULICH für den Bestand)
Was gut ist: ein 500 im Umschlag gilt nicht mehr als Erfolg. Der Fix vom 03.10. hält, live am Bestand nachgemessen.
Was fehlt: der Grund des 500, und er wird an zwei Zeilen weggeworfen. Der Skill antwortet mit detail="<Ausnahmetyp>:<Meldung>"; der Richter im Dispatch liest davon nur statusCode. Im Zweig daneben — für Antworten ohne Umschlag — liest dieselbe Anweisung sehr wohl body.get("error"). ⇒ ⛔ Der Umschlag-Zweig ist der einzige, der den Grund fallen lässt — und er ist derselbe Zweig, der gebaut wurde, um Fehler sichtbar zu machen. Der Fix machte den Fehler sichtbar und seinen Grund unsichtbar. (Eigner: BANKING#05)
Was fehlt: ein done trägt kein Maß der Wirkung. Drei Belege mit 0, 4 und 13 Buchungen tragen zeichengleich denselben Satz. ⭐ Der Befund ist nicht „ein Import hat verloren“, sondern: das done-Ereignis kann „es gab nichts zu importieren“ nicht von „der Import hat alles verloren“ unterscheiden. Im gemessenen Fall war es das Harmlose — und dass es das war, wusste FOLLOW#01 aus dem Dateinamen, nicht aus dem Ereignis, das das Haus selbst geschrieben hat. (Eigner: BANKING#05)
⛔⛔ Der schwerste Bruch der ganzen Kette, und er stand in keinem Auftrag. Das Fenster, durch das KAI offene Belege zeigt, ist 30 Zeilen groß und seit Monaten vollständig belegt — von undatierten Belegen aus Mai bis August. ⭐ Solange diese undatiert bleiben, kann in diesem Werkzeug kein einziger neuer Beleg je erscheinen — nicht die zehn vom 04.10., und nicht der nächste. Der Eingang funktioniert, die Anzeige ist blind.
Und der Mechanismus ist eine Sortierregel, kein Fehler: ORDER BY date_received DESC stellt in Postgres NULLS FIRST. Niemand hat etwas falsch programmiert; die Voreinstellung der Sortierung und ein limit 30 ergeben zusammen ein Fenster, das sich selbst verschließt.
Was außerdem fehlt: der Buchhalter erreicht entitätslose Belege nie — seine Tür ist die Entität. Solange Station 4 rot ist, ist seine Sicht leer, und das betrifft das Monatspaket. (Eigner: TOWER-Ball für das Fenster, BANKING#05 für die Buchhalter-Sicht)
⭐⭐ Hier endet die Kette, und zwar in drei Regalen. Das Haus erzeugt den Befund (4.2 grün), parkt den Beleg korrekt (3.2 grün), hält die Wand (7.2 grün) — und legt das Ergebnis dann in drei Regale, von denen eines seit fünf Monaten nicht befüllt wird, eines strukturell leer ist und eines keinen Leser hat.
⛔ Die Kette bricht nicht an einer Maschine, sondern an der Übergabe an den Menschen. (Eigner: KLÄRUNG — TOWER-Ball; inbox_view: KAI)
Urheber: FOLLOW#02 · 05.10.2026 · Auftrag TOWER#64 ⑥
⛔ Nichts davon ist gelöscht. Die Hausregel Kompendium gegen Archiv sieht vor, dass Archiv Inspiration bleibt: aufbewahrt, nicht maßgeblich. Diese Liste sagt nur, welche Rolle jede Darstellung ab heute hat.
| # | Darstellung | Datum | Was sie ist | Rolle ab 05.10.2026 |
|---|---|---|---|---|
| ① | Artefakt „Der Weg eines Dokuments durch TGV“, 67 Etappen | 02.09.2026 | SOLL-Bild (grün = läuft, orange = fehlt) | Archiv — und seine Soll-Aussage lebt hier weiter. Sein Zweck (was fehlt und warum) ist genau das, was §2 dieser Datei fortführt. Für die Stationen gilt die erzeugte Seite. |
| ② | Artefakt „Die Reise eines Belegs“, 41 Etappen in drei Wegen (A Upload 11 · B Mail 13 · C gemeinsam 17), acht Störstellen mit Datei:Zeile | 04.09.2026 | IST-Bild von Hand | Überholt als IST — genau die Klasse, gegen die diese Seite gebaut ist. Die Wegetrennung A/B/C ist weiter wertvoll und in der erzeugten Seite nicht enthalten: dort sind die Stationen gemeinsam gezählt. |
| ③ | Artefakt „Der Weg der Belege“ (ADMIN#04 mit PIPELINE#03 und SICHERHEIT#07, Register #2004) | 15.09.2026 | Diagnose eines ORCH-Stillstands mit Live-Zahlen, nicht eine Kettendarstellung | Archiv. Es ist eine datierte Diagnose, kein Weg-Bild; seine Zahlen gelten für den 15.09. Sein Verfahren bleibt vorbildlich (vier Verdächtige geprüft und ausgeschlossen, zwei eigene Annahmen widerlegt). |
| ④ | 01_ITERATIONS/CONTROL_TOWER_HANDOFF/FOLLOW_THE_INPUT_2026-10-04.md, 34 Checkpoints | 04.10.2026 | IST-Bild mit Live-Messung je Punkt | ⭐ Gilt weiter — und ist die QUELLE dieser Seite. Alle 34 Punkte stehen maschinenlesbar in 08_OPS/eingangskette.json. Das Blatt bleibt die Langfassung mit Begründungen; die Seite ist seine lebende Kurzfassung. |
| ⑤ | 01_ITERATIONS/CONTROL_TOWER_HANDOFF/DOKUMENT_REISE_KARTE_2026-08-30.md, Fassung 3 | 30.08.2026 | Dieselbe Linie wie ② — die Datei nennt das Artefakt ② ausdrücklich als „Fassung 2“ ihrer eigenen Reihe | Archiv, und es sind nicht zwei Darstellungen, sondern eine Reihe. ⭐ Korrektur an der Beauftragung: ② und ⑤ wurden als zwei gezählt; sie sind Fassung 2 und 3 derselben Karte. Ihr dauerhafter Wert ist die Modell-/Tabellen-Tafel (welches Modell wo, welche feste Tabelle entscheidet wo) — die steht in der erzeugten Seite nicht. |
| ⑥ | 00_LEITDOKUMENT/KI_FIRST_KLASSIFIKATION_WERKBANK_KONZEPT.md | 01.06.2026 | Konzept zu Klassifikation, Eingabe und Werkbank — kein Stationsweg | Gilt weiter als Konzept, ist kein Vorgänger dieser Seite. Es beantwortet eine andere Frage (wie geurteilt werden soll), nicht diese (welche Station heute trägt). |
| ⑦ | 00_LEITDOKUMENT/KONZEPT_MEDIA_PIPELINE.md | 13.07.2026 | Entwurf eines Medien-/Video-Subsystems | Gilt weiter als Entwurf, ist keine Teilstrecke dieser Kette. Er beschreibt eine Medien-Fähigkeit für Mandantenprojekte, nicht den Belegeingang. |
① „Archive auspacken ist gebaut, also ist ① überholt“ — gebaut ist nicht live. Der Auftrag führte ①s Eintrag „Archive auspacken fehlt“ als nachweislich falsch, weil ARCHIV#01 es in der Nacht vom 04./05.10. gebaut habe. Gemessen (05.10.2026, gh pr list): die Arbeit liegt im offenen, dienstwirksamen Vorgang #3226 — nicht auf master, nicht ausgeliefert. ⇒ ①s Eintrag ist im Betrieb weiter wahr und wird erst mit Merge und Deploy falsch. ⭐ Die Lehre ist dieselbe wie der Anlass, nur in die andere Richtung: nicht nur die Kette altert in Tagen — ein Urteil ÜBER die Kette altert genauso. „Gebaut“, „gemergt“ und „live“ sind drei Zustände, und nur der dritte macht einen Fehlt-Eintrag falsch.
② „Ein gescanntes PDF ohne Textschicht hat keinen Leseweg“ — am Quelltext widerlegt, am Betrieb ungemessen. Es gibt zwei erklärte Lesewege: 08_OPS/volltext.py liest Seiten ohne Textschicht über eine OCR-Kaskade (ocr_noetig, Vorgabemodell mistral-ocr-latest), und 08_OPS/tgv-skills-service/dispatch.py:440 führt PDF_READ mit tgv-skill-pdf-ocr-fallback. ⛔ Aber: dieser Rückfall ist in 02_SKILLS/_registry.yaml:861 ein n8n-Webhook (tgv-pdf-ocr-fallback), kein lokaler Skill — und ob dieser n8n-Zweig heute lebt, habe ich nicht gemessen. ⇒ Das richtige Wort ist deshalb nicht „überholt“, sondern: der Leseweg ist erklärt, seine Ausführung ist ungemessen, und ein Bein davon hängt an n8n.
⭐ Nachmessung SOUVERAEN#04 · 11.10.2026 · Registerzeile #4050 — jetzt am Betrieb gemessen. Ein Leseweg trägt, das n8n-Bein war tot. ① Die OCR-Kaskade ist live gelaufen: agent_events des Volltext-Lesers tragen zweimal ocr.modell = mistral-ocr-latest, Extraktor pypdf-6.12.2+mistral-ocr-latest — #8519 (28.09., 4 Seiten, 23.941 Zeichen) und #8250 (11.10., 1 Seite, 1.051 Zeichen), beide Status vollstaendig. ② Das n8n-Bein: Workflow zKjQkYKKmSe076KM inaktiv, 0 Läufe, alle drei Rufer inaktiv (n8n-API, 11.10.); der Name stand nie in SKILL_TARGETS. ⛔ Und er hat gebissen — nicht über PDF_READ (dort nur Filter), sondern über agent_orch01/taxonomy.KNOWN_SKILLS, den Skill-Katalog im Orchestrator-Prompt: 14× tgv-pdf-ocr-fallback geplant ⇒ router.unresolved_skill, 8 Belege needs_review (16.–26.09.). Beide Namen gestrichen, Wächter 07_TESTS/souveraen04. ③ Office-Leser: docling-serve läuft seit ITER_54 auf Hetzner (nicht mehr Railway); der Dienst ruft 127.0.0.1:5001. Live: #7520 (pptx, 11.10., 0,05 s Verarbeitung). Ein Kaltstart wie auf Railway fällt dort weg — der Wecker pREuIhe0R0g3cDqi ist mit Absicht aus (ITER_54 Fd5).
konzept_datenfluss.html §2, §4 und §7.08_OPS/eingangskette.json und trägt dort ihre eigene Uhr.Letzte Hand-Änderung: 11.10.2026 · SOUVERAEN#04 · Registerzeile #4050 (§3 ② nachgemessen). Vorher: 05.10.2026 · FOLLOW#02 · #3750. Wer diese Datei ändert, ändert ein Urteil — und setzt die Zeile oben auf heute.
◆ IST · erzeugt aus 08_OPS/eingangskette.json
Quelle der Messungen:
01_ITERATIONS/CONTROL_TOWER_HANDOFF/FOLLOW_THE_INPUT_2026-10-04.md · Urheber FOLLOW#01 · Register
#3710 · Messfenster 2026-10-04T21:38Z – 2026-10-04T21:53Z.
Messart: Live-DB über 08_OPS/db_query.py (nur SELECT), agent_events, zwei Wächter live gefahren. ·
⛔ Nicht gefahren: kein Schreibweg, kein DDL, kein Deploy, keine Reparatur.
Die Zahl hinter jeder Station liest sich
grün · rot · ungemessen.
⛔ Ungemessen ist nicht rot — rot ist eine Aussage, ungemessen ist das
Fehlen einer Aussage.
Kommt überhaupt etwas an?
| Nr | Checkpoint | Zustand | Messung | Fundstelle | ⛔ was die Messung NICHT sagt | Eigner |
|---|---|---|---|---|---|---|
| 1.1 | Mail-Intake hat Takt Läuft der Poller, und wie lange ist der letzte Lauf her? | 🟢 grün | `mail_intake.poll.done` 11 831x gesamt, letzter 1,3 min vor der DB-Uhr. Schalter `use_local_mail_intake` = true. Uhr 2026-10-04T21:49Z | 08_OPS/tgv-skills-service/mail_intake.py:1-60; system_config.use_local_mail_intake | Der Takt ist aus `agent_events` gemessen, NICHT aus `/health`. Takt heißt: der Poller läuft — nicht, dass eine Mail korrekt verarbeitet wurde. | — |
| 1.2 | Stille ist von Tod unterscheidbar Die Narbe: der IMAP-Trigger starb 04.08. und 14.08. STILL. Kann man heute „keine Mail“ von „keiner schaut“ trennen? | 🟢 grün | Polls je Tag 27.09.-04.10. = 280 279 285 284 284 278 258. An den drei mailfreien Tagen (27.09. 30.09. 01.10.) liefen 280/285/284 Polls ⇒ Stille war echte Stille. Uhr 2026-10-04T21:50Z | 08_OPS/check_stille_wie_normalbetrieb.py:54-60 | Gilt für die acht gemessenen Tage, nicht für die zwei Ausfälle im August — die sind Vergangenheit, nicht Gegenprobe. | — |
| 1.3 | Upload-/KAI-Composer-Weg trägt Entsteht je Upload eine Zeile mit Spur? | 🟢 grün | `source=upload` 45 Belege gesamt, 10 davon heute; je Beleg genau ein `upload.abgelegt` („Upload abgelegt: Umsaetze_DE33…7705_2026.09.30.csv -> Beleg #8541“). Uhr 2026-10-04T21:40Z | 08_OPS/tgv-skills-service/intake_raw.py; Ereignis `upload.abgelegt` | Gemessen am Ereignis, nicht an der Fläche: dass der Composer den Upload ANNIMMT, ist hier nicht gemessen. | — |
| 1.4 | Drive-Weg bewusst stillgelegt Kommt noch etwas über Drive, und ist das Schweigen gewollt? | 🟢 grün | `source=gdrive` 350 Belege, jüngster 23.08.2026 — deckt sich mit dem dokumentierten Entscheid, die Drive-Bindung fallen zu lassen. Uhr 2026-10-04T21:41Z | 08_OPS/tgv-skills-service/mail_intake.py:21-27 (STORAGE#04-Auflage #538) | „Gewollt“ ist aus dem Entscheid gelesen, nicht gemessen; gemessen ist nur, dass seit 23.08. nichts mehr kam. | — |
| 1.5 | Mail-BODY als Beleg gesichert Wenn der Beleg die Mail selbst ist (kein Anhang) — überlebt er? | 🔴 rot | Wächter live: eml-Sicherung NICHT verdrahtet. 191 `.eml` liegen im Roh-Layer, aber aus einer Bestands-Heilung; kein aktiver Rufer sendet `kind='eml'`. Folge: 6 freigegebene Belege existieren nur als Text (#8179 #8180 #8182 #8183 #8184 #8187). Uhr 2026-10-04T21:47Z | 08_OPS/check_eml_sicherung_verdrahtet.py; 08_OPS/ablage_kanon.yaml -> folder_structure.raw | ⛔ Der Wächter endet mit rc=0, obwohl er „NICHT VERDRAHTET“ meldet — absichtlich gestundet (#537), damit er nicht dauerrot jeden Wächter hinter sich verdeckt. Scharf wird er mit `--verlangt-verdrahtung`. Ein rc=0 ist hier KEIN Gruen. | STORAGE / #537 |
Liegt die Datei, bevor die Zeile entsteht?
| Nr | Checkpoint | Zustand | Messung | Fundstelle | ⛔ was die Messung NICHT sagt | Eigner |
|---|---|---|---|---|---|---|
| 2.1 | Keine STUMMEN Waisen Freigegebene Belege ohne Datei UND ohne Text = echter Verlust | 🟢 grün | Wächter live: „OK: keine stummen Waisen“ — 0. Uhr 2026-10-04T21:45Z | 08_OPS/check_belege_ohne_ablageort.py | Null stumme Waisen sagt nichts über Belege, die eine Adresse haben, aber am falschen Ort liegen (das ist 3.1). | — |
| 2.2 | Zeilen ohne Bytes (Bestand) `documents`-Zeilen, deren `raw_key` leer ist | 🔴 rot | 406 von 947 Belegen ohne `raw_key`; jüngste 26.09.2026, älteste 01.04.2026 ⇒ Altbestand, kein laufender Bruch. Uhr 2026-10-04T21:42Z | Kanon `raw_before_dbrow` in 08_OPS/ablage_kanon.yaml | „Kein laufender Bruch“ folgt aus dem jüngsten Datum, nicht aus einer Messung am heutigen Schreibweg. | STORAGE (Heimholung) |
| 2.3 | Das Band wächst nicht `needs_review` OHNE JEDE Adresse darf nur schrumpfen | 🔴 rot | Wächter live, echter rc = 3: Grundlinie 05.09. 41 -> heute 47, 6 NEUE (#8477 #8479 #8480 #8485 #8490 #8509), 0 erledigt. Uhr 2026-10-04T21:45Z | 08_OPS/check_belege_ohne_ablageort.py (ABLAGE#05) | Der rc wurde OHNE Rohr gemessen; eine erste Messung mit `| tail` las tails rc=0 und war falsch. | ABLAGE |
| 2.4 | Die zehn von heute: Bytes gesichert Liegen die Bytes der zehn CSVs wirklich? | 🟢 grün | 10/10 mit `raw_key` UND `raw_sha256`, Bucket `tgv-raw-unassigned`. Kanon „Bytes zuerst“ hat für den heutigen Eingang gehalten. Uhr 2026-10-04T21:40Z | documents.raw_key / documents.raw_sha256 | Gemessen ist die ZEILE (Schlüssel + Hash), nicht ein Abruf der Bytes aus dem Bucket. | — |
Kommt die Datei an ihren Kanon-Ort?
| Nr | Checkpoint | Zustand | Messung | Fundstelle | ⛔ was die Messung NICHT sagt | Eigner |
|---|---|---|---|---|---|---|
| 3.1 | Kanon-Ort erreicht (Bestand) Wie viele Belege tragen keinen `final_path`? | 🔴 rot | 339 von 947 ohne `final_path` (35,8 %). Uhr 2026-10-04T21:42Z | 08_OPS/ablage_kanon.yaml; credentials/_ordnung.ordne() | Die Zahl zählt leere Felder. Ob ein GESETZTER `final_path` auch auf eine existierende Datei zeigt, ist hier nicht gemessen. | ABLAGE |
| 3.2 | PARKEN statt Phantom-Lokation Wenn nicht abgelegt werden kann — schreibt das Haus trotzdem einen Ort hinein? | 🟢 grün | Die zehn stehen auf `storage_status=parked`, `op=none`, KEIN `final_path`, Bytes bleiben in `raw_key`. Das Ereignis sagt es wörtlich: „store-file done (status=parked, op=none)“. Uhr 2026-10-04T21:43Z | 02_SKILLS/tgv-skill-store-file-to-drive/skill.py:588-593, :1132 | Gemessen an den zehn von heute, nicht am Bestand: ob früher je ein Parkpfad in `final_path` geschrieben wurde, ist ungemessen. | — |
| 3.3 | `skills_done` sagt die Wahrheit über die Ablage Ein Aggregat, das „abgelegt“ meldet, wo nur geparkt wurde | 🔴 rot | `tgv-store-file-to-drive` steht bei 10/10 in `skills_done`, während `final_path` bei 10/10 leer ist. Nur der EREIGNISTEXT sagt `parked` — die LISTE sagt `done`. Uhr 2026-10-04T21:43Z | documents.skills_done gegen documents.final_path | Gemessen an den zehn. Wie viele Belege im Bestand dieselbe Lücke tragen, ist nicht gezählt. | ORCH / ABLAGE |
Entität, Dokumentart, Vertraulichkeitsstufe
| Nr | Checkpoint | Zustand | Messung | Fundstelle | ⛔ was die Messung NICHT sagt | Eigner |
|---|---|---|---|---|---|---|
| 4.1 | Entität gesetzt Trägt der Beleg seine Mandanten-Achse? | 🔴 rot | 10/10 auf `unassigned`, `entity_quelle=gehirn`. Hausweit 52 von 947 ohne Entität. Uhr 2026-10-04T21:40Z | documents.entity | `unassigned` ist ein Platzhalter mit WAHREM Wert — er fällt durch jedes `if not x` UND durch jeden Scope-Filter. „52 ohne Entität“ zählt NULL und `unassigned` zusammen nur, wenn die Abfrage beide nennt. | BANKING#05 (die zehn) / ABLAGE (Bestand) |
| 4.2 | Die Entität IST bekannt und wird benannt Weiß das Haus, wohin der Beleg gehört — und sagt es? | 🟢 grün | 10/10 tragen `skill.tgv-classify-csv.konto_entitaet_weicht_ab`, z. B. #8541 „Konto …7705 gehört laut Stammdaten zu 'c3-convis-gmbh', der Beleg steht auf 'unassigned'“; #8543 -> 'privat'. Uhr 2026-10-04T21:41Z | 02_SKILLS/tgv-skill-classify-csv/skill.py:485-493 | Gemessen ist, dass der Befund ENTSTEHT. Dass ihn jemand LIEST, ist 8.2 — und das ist rot. | — |
| 4.3 | Dokumentart gesetzt Trägt der Beleg seine Art? | 🟢 grün | 10/10 `doc_type='Banking-CSV'` (Fix #3497 vom 03.10. hält). Hausweit 76 von 947 ohne Art. Uhr 2026-10-04T21:40Z | 08_OPS/tgv-skills-service/dispatch.py (#3497, DOC_TYPE_MAP) | Gruen gilt für die zehn Banking-CSVs. Die 76 ohne Art im Bestand sind dieselbe Frage mit anderer Antwort. | — |
| 4.4 | Vertraulichkeitsstufe gesetzt Prinzip 3 — Stufe ist Fundament, kein Add-on | 🔴 rot | 10/10 `confidentiality_level = NULL`. Hausweit 408 von 947 (43,1 %) ohne Stufe. Uhr 2026-10-04T21:40Z | documents.confidentiality_level; Lesewand rag_conf_rank() | NULL gilt als streng. Der Befund ist also kein Leck, sondern eine Unsichtbarkeit — und die beiden sehen in einer Zählung gleich aus. | VERTRAULICH / ABLAGE |
| 4.5 | `mandant_id` gesetzt Die Wand braucht eine Seite | 🔴 rot | 10/10 `mandant_id = NULL`; hausweit 52 von 947 — deckungsgleich mit 4.1. Uhr 2026-10-04T21:44Z | 08_OPS/tgv-skills-service/intake_raw.py:280-287 (PIPELINE#02 #465, Kontrakt R1) | Deckungsgleich mit 4.1 heißt: dieselben Belege, nicht dieselbe Ursache. | BANKING#05 |
| 4.6 | Der Re-Triage-Weg setzt sie wirklich `/api/skills/orch/retriage` bzw. `assign-project` als vorgesehener Weg | ⚪ ungemessen | NICHT gefahren — das ist ein SCHREIBWEG, und FOLLOW#01s Auftrag war nur-SELECT. Im Code gelesen, nicht gemessen. Uhr 2026-10-04T21:53Z | 08_OPS/tgv-skills-service/intake_raw.py:96-98 | Gelesen ist nicht gemessen. Über das Verhalten dieses Weges sagt dieses Register NICHTS. | BANKING#05 |
Wird der Router gerufen, und sagt er die Wahrheit?
| Nr | Checkpoint | Zustand | Messung | Fundstelle | ⛔ was die Messung NICHT sagt | Eigner |
|---|---|---|---|---|---|---|
| 5.1 | Router wird gerufen und schließt ab Läuft ORCH je Beleg vollständig? | 🟢 grün | 10/10 mit `router.dispatch_started` UND `router.finalized`; Router 0.9.5-py, Orchestrator `hetzner-dispatch.py`; Schalter `dispatch_after_intake_on_hetzner` = true. Uhr 2026-10-04T21:41Z | 08_OPS/tgv-skills-service/dispatch.py:36 | Der Schalter ist ein Wert in `system_config` — er ändert sich ohne Commit. Gruen gilt für den Stand der Uhr. | — |
| 5.2 | Ein 500 im Umschlag gilt nicht mehr als Erfolg Die Narbe bis #3200/#3502: `.error http=500` und 0,2 s später `skill.done ok`, „4/4 skills“ | 🟢 grün | Live am Bestand nachgemessen, der Fix hält: #8545 #8546 #8548 #8549 haben `skill.error` UND `tgv-import-banking-csv` fehlt in ihrem `skills_done` (3 Skills statt 4). KEIN begleitendes `skill.done`. Uhr 2026-10-04T21:42Z | 08_OPS/tgv-skills-service/dispatch.py:1111-1116; Probe 07_TESTS/banking04/test_router_umschlag_3502.py:81 | Gemessen an vier Fällen EINER Art (Umschlag-500 des Banking-Imports). Andere Fehlerformen sind nicht gegengeprobt. | — |
| 5.3 | Der GRUND des 500 landet im Ereignis Steht im Ereignis, WARUM es scheiterte? | 🔴 rot | `tool_output` von #8545 trägt genau fünf Felder — `error="umschlag_500"`, `status=200`, `target`, `orchestrator`, `router_version`. Das Skill-eigene Ereignis trägt fünf andere — `statusCode=500`, `entity`, `bank_format`, `filename`, `skill_version`. IN KEINEM steht ein Grund. Uhr 2026-10-04T21:43Z | Der Grund ENTSTEHT in 02_SKILLS/tgv-skill-import-banking-csv/skill.py:288-290 als detail="<Typ>:<Meldung>" und wird VERWORFEN in 08_OPS/tgv-skills-service/dispatch.py:1115-1117 | Gemessen an #8545 und am Code beider Stellen. Dass JEDER Umschlag-500 den Grund verliert, folgt aus dem Zweig — gezählt ist es an einem Fall. | BANKING#05 |
| 5.4 | Ursache der vier 500 bestimmbar Lässt sich aus dem Bestand sagen, WAS schiefging? | ⚪ ungemessen | Nein. Prüfhypothese „leerer Dateiname“ WIDERLEGT — `filename` ist bei allen zehn leer, auch bei den fünf erfolgreichen. Was bleibt, ist ein Namensmuster (vier Belege in drei anderen Formaten, zwei davon französisch), KEINE gemessene Ursache. Uhr 2026-10-04T21:52Z | — | Ohne 5.3 ist die Ursache nicht messbar. Das Namensmuster ist eine HYPOTHESE für BANKING#05, kein Befund. | BANKING#05 |
Laufen die Skills, und wirken sie?
| Nr | Checkpoint | Zustand | Messung | Fundstelle | ⛔ was die Messung NICHT sagt | Eigner |
|---|---|---|---|---|---|---|
| 6.1 | Skills laufen je Dokumentart Werden für `Banking-CSV` die vorgesehenen Skills gerufen? | 🟢 grün | 10/10 mit `tgv-classify-csv`, `tgv-reconcile-sweep`, `tgv-store-file-to-drive`; 6/10 zusätzlich `tgv-import-banking-csv` (die vier 500er fehlen korrekt). Uhr 2026-10-04T21:41Z | 08_OPS/tgv-skills-service/dispatch.py -> plan_skills | Gilt für EINE Dokumentart. Für jede andere ist es 6.3 — und das ist ungemessen. | — |
| 6.2 | `done` trägt ein MASS DER WIRKUNG Kann man einem `done` ansehen, ob es gewirkt hat? | 🔴 rot | Nein, zeichengleich: #8547 (0 Buchungen), #8541 (4) und #8550 (13) tragen DENSELBEN Satz: „banking-import done (http=200, entity=unassigned)“. Kein Zähler, keine Zeilenzahl. Uhr 2026-10-04T21:44Z | 02_SKILLS/tgv-skill-import-banking-csv/skill.py:296-301 | Der Fall selbst war harmlos: #8547 ist eine Depotübersicht, 0 ist dort die richtige Zahl. Dass es harmlos war, ist aus dem DATEINAMEN gewusst, nicht aus dem Ereignis. | BANKING#05 |
| 6.3 | Skills je ANDERER Dokumentart Laufen für Rechnung/Quittung/PDF die richtigen Skills, und melden sie `done` ohne Wirkung? | ⚪ ungemessen | NICHT gemessen. FOLLOW#01 fuhr den CSV-Fall; die anderen Arten sind nur im Code gelesen. Uhr 2026-10-04T21:53Z | 08_OPS/tgv-skills-service/dispatch.py -> SKILL_TARGETS | Über jede Dokumentart ausser Banking-CSV sagt dieses Register NICHTS. | offen |
Sieht der Nutzer das Ergebnis?
| Nr | Checkpoint | Zustand | Messung | Fundstelle | ⛔ was die Messung NICHT sagt | Eigner |
|---|---|---|---|---|---|---|
| 7.1 | KAI zeigt neu eingegangene Belege Erscheinen die zehn in dem Werkzeug, mit dem KAI offene Belege zeigt? | 🔴 rot | Nein, und zwar keiner von ihnen. In GENAU DER ABFRAGE, die `get_pending_documents` führt (`status IN ('pending_review','needs_review','inbox')`, `ORDER BY date_received DESC`, `limit 30`), liegen die zehn auf Rang 71-80. Ursache gemessen: 70 offene Belege haben `date_received IS NULL`, und Postgres sortiert NULL in DESC ZUERST ⇒ alle 30 Plätze des Fensters sind von undatierten Belegen aus 31.05.-26.08.2026 besetzt. Gegenprobe: von den 30 auf Rang 1-30 sind 30 undatiert. Uhr 2026-10-04T21:46Z | TGV -App files/tgv_mcp_server.py:402-419 (.in_(...), .order("date_received", desc=True), .limit(30)) | ⛔ Gemessen ist die ABFRAGE, nicht die Fläche. Ob `#/dokumente` dieselbe Grenze hat, ist NICHT gemessen. | TOWER-Ball (Flaeche/KAI) |
| 7.2 | Mandantenwand hält bei `mandant_id = NULL` Sind die zehn ein Datenabfluss? | 🟢 grün | Nein, die Wand hält. `documents_select_mandant_or_project` prüft `mandant_id = ANY(my_mandant_ids(auth.uid()))`; mit NULL ist das nicht wahr ⇒ default-deny, wie Prinzip 3 verlangt. Uhr 2026-10-04T21:44Z | pg_policies -> documents_select_mandant_or_project | Gemessen ist EINE Bedingung einer ODER-verketteten Policy. Dass der Beleg unsichtbar ist, folgt erst mit 7.3/7.4/7.5 daneben. | — |
| 7.3 | Der Uploader sieht seinen eigenen Beleg Kommt JC an die zehn heran? | 🟢 grün | Ja. 10/10 tragen `hochgeladen_von` ⇒ die letzte OR-Klausel `hochgeladen_von = auth.uid()` greift. Über die Belegfläche sind sie erreichbar. Uhr 2026-10-04T21:45Z | pg_policies -> documents_select_mandant_or_project, letzte Klausel | „Erreichbar“ ist an der Policy gemessen, nicht an einem geöffneten Screen. | — |
| 7.4 | Der BUCHHALTER sieht sie Die Entität ist der Zugang des Buchhalters | 🔴 rot | Nie. Sein Zweig ist `entity = ANY(buchhalter_entity_slugs(auth.uid()))`; 'unassigned' ist in keiner Entitätenliste ⇒ die zehn sind für ihn unerreichbar, solange 4.1 rot ist. Betrifft das September-Paket. Uhr 2026-10-04T21:45Z | pg_policies -> documents_select_mandant_or_project, Buchhalter-Zweig | Gemessen ist die Entitäts-Wand. Die Stufen-Wand daneben ist eine zweite Bedingung und hier nicht gemessen. | BANKING#05 |
| 7.5 | Entitätslose Belege haben IRGENDEINEN Leser Wer sieht die 52 ohne Entität? | 🔴 rot | 30 von 52 haben AUCH KEINEN `hochgeladen_von` ⇒ weder Mandanten-, noch Projekt-, noch Buchhalter-, noch Uploader-Zweig greift. Sichtbar NUR für `is_super_admin` und die Service-Rolle. Uhr 2026-10-04T21:45Z | pg_policies -> documents_select_mandant_or_project, alle Zweige | Gemessen an den Policy-Zweigen, nicht durch einen Anmeldeversuch als eingeschränkter Nutzer. | ABLAGE |
| 7.6 | KAI zeigt im Gespräch die BUCHUNGEN Sieht der Nutzer die 71 Buchungen im Scope? | ⚪ ungemessen | NICHT gefahren — dazu müsste KAI als Nutzer aufgerufen werden. Gemessen ist nur, dass die 71 Buchungen in `txn_master` die RICHTIGE Entität tragen (`c3-convis-gmbh`, `privat`). Uhr 2026-10-04T21:53Z | txn_master.entity | Dass die Buchungen die richtige Entität tragen, sagt NICHT, dass KAI sie zeigt. | offen |
Was landet beim Menschen, und findet er es?
| Nr | Checkpoint | Zustand | Messung | Fundstelle | ⛔ was die Messung NICHT sagt | Eigner |
|---|---|---|---|---|---|---|
| 8.1 | Das Klärungs-Regal wird gefüttert Kommen neue Fälle in `intake_review_queue_v1`? | 🔴 rot | 311 Zeilen, alle 311 mit `requires_human_review = true` — jüngste Zeile 06.05.2026. Seit fünf Monaten kommt dort nichts mehr an; aus den letzten 14 Tagen: keine einzige Zeile. Uhr 2026-10-04T21:47Z | intake_review_queue_v1; 08_OPS/klaerung03_toepfe.py | Gemessen ist der Zufluss in DIESE Tabelle. Ob die Klärung heute über ein anderes Regal läuft, ist damit nicht ausgeschlossen. | KLAERUNG — TOWER-Ball |
| 8.2 | Der Entitäts-Befund wird zur ENTSCHEIDUNG Liest irgendwer `konto_entitaet_weicht_ab` und legt es JC vor? | 🔴 rot | Niemand. Gesucht über `08_OPS/**` und `02_SKILLS/**` — die einzigen Treffer sind die ERZEUGER (`app.py`, `dispatch.py`). Kein Wächter, kein Cron, keine Fläche, kein Klärungs-Topf liest dieses Ereignis. Uhr 2026-10-04T21:46Z | Erzeuger: 02_SKILLS/tgv-skill-classify-csv/skill.py:485-493 · Leser: keiner in den befragten Regalen | ⛔ R-193: „niemand“ gilt für `08_OPS/**` und `02_SKILLS/**`. NICHT befragt: die Fläche (06_DASHBOARD), n8n-Leinwände, die Datenbank-Sichten. | KLAERUNG — TOWER-Ball |
| 8.3 | `inbox_view` zeigt den Posteingang Die als Posteingang benannte Sicht | 🔴 rot | 0 Zeilen. Grund: sie filtert `status = 'inbox'`, und KEIN EINZIGER Beleg trug je diesen Wert (count=0 über alle 947; vorkommende Werte: `approved` 458, `needs_review` 354, `duplicate` 96, `rejected` 38, `source_lost` 1). Zwei Namen für dasselbe Fach. Uhr 2026-10-04T21:46Z | pg_views -> inbox_view: WHERE status = 'inbox' AND project_id IS NULL; definiert in 05_SCHEMA/140_lm09_c2_namespace_containment_views.sql:38 | Der richtige Satz ist NICHT „KAIs Posteingang ist leer“: gesucht wurde in `02_SKILLS` und `08_OPS`, und dort liest die Sicht NIEMAND. Treffer nur in `05_SCHEMA/*.sql` und im Konzept-HTML. | KAI |
◆ erzeugt · aus dem Register
08_OPS/eingangskette.json. Jede Zeile trägt ihre eigene Uhr; eine
Messung ohne Uhr ist keine.01_ITERATIONS/CONTROL_TOWER_HANDOFF/EINGANGSKETTE_SOLL.md, mit Datum und
Urheber.Gegenprobe von Hand (Git-Bash, Repo-Wurzel):
python 08_OPS/gen_eingangskette.py --pruefe 06_DASHBOARD/konzepte/eingangskette.html
— der Wächter vergleicht die Substanz (Register + Urteil), nicht die
Bytes: die Seite trägt eine Uhr, ein Byte-Vergleich wäre bei jedem Lauf rot.