{
  "_meta": {
    "id": "SCREEN_FACTORY_CONTRACTS",
    "stand": "2026-08-10",
    "owner": "KONZEPT#01 / SCREEN#01",
    "zweck": "Maschinenlesbarer Vertrag: User-Intention -> Screen-Typ -> Daten -> Bausteine -> Funktionen -> Abnahme.",
    "guard": "08_OPS/check_screen_factory_contracts.py",
    "ssot": "06_DASHBOARD/konzepte/konzept_seitenbau.html#screen-factory"
  },
  "screen_types": [
    "dialog",
    "inbox",
    "klaerung",
    "pipeline",
    "uebersicht",
    "dossier",
    "formular",
    "admin",
    "system"
  ],
  "required_fields": [
    "id",
    "title",
    "status",
    "owner",
    "file",
    "visible_url_local",
    "screen_type",
    "intent",
    "data_sources",
    "je_ids",
    "rule_ids",
    "component_ids",
    "k_ids",
    "ux_ids",
    "fx_or_skills",
    "icon_slugs",
    "chart_specs",
    "workbench_zone",
    "module_package",
    "menu_scope",
    "abnahme",
    "next_guard"
  ],
  "detail_view_contract": {
    "_meta": {
      "id": "DETAIL-ANSICHT-VERTRAG",
      "stand": "2026-08-10",
      "quelle": "Register #413 + #410c (JC 10.08.) — Fortschreibung dieses Vertragswerks, KEIN neues Dokument (CANON-GARANTIE#01, Tower#36)",
      "zweck": "EIN Vertrag fuer ALLE Detailansichten (Dokument, Buchung, Vertrag, kuenftige Objekte): der RAHMEN ist Pflicht, die BLOECKE sind waehlbar, und der screen-composer-Agent ENTSCHEIDET nach agent_entscheidet, welche Bloecke fuer ein Objekt Sinn machen. Der Agent kann nicht im Code flicken — was er braucht, muss als Katalog-Baustein existieren.",
      "gilt_fuer": "jede Objekt-Detailansicht in Screens: K-26 (doc) · K-60 (txn/ctr) · kuenftige Instanzen. NICHT fuer Klaerungs-Karten (K-22-Welt, E-21) und nicht fuer KAI-Antwort-Karten (kai-antwort-flaeche-Vertrag).",
      "referenz_impl": "06_DASHBOARD/konzepte/comp_panel.js (K-26-Referenz) · TGVEngine wirePanelBlocks/wireDockResize (engine.js) · components.css .ds-dock--side/.ds-panel__blk"
    },
    "rahmen_pflicht": {
      "_regel": "Der Rahmen ist NICHT verhandelbar — er ist auf jedem Screen identisch (EINE Steckbrief-Mechanik, komponenten_data.js:80: 'kein dritter Panel-Typ').",
      "traeger": "Slide-over rechts, position:fixed UEBER dem Content — Content wird NIE verkleinert oder gesplittet (PAN-01/E-27, JC 02.08. bindend). CSS-Kanon: components.css .ds-dock--side (:1070) bzw. gleichwertige Panel-Huelle; Breite AUSSCHLIESSLICH aus tokens.css --panel-w/--panel-w-min/--panel-w-max (:219-223), nie als nackte Zahl im Screen (#297).",
      "resize": "nach LINKS vergroesserbar am Griff — Verdrahtung NUR TGVEngine.wireDockResize (PAN-01/B8), keine Screen-Kopie (check_screen_haelt_komponenten_parameter.py:87-89).",
      "bloecke": "GRUPPIERTE AUFKLAPPBARE KARTEN (#410c): jeder Inhalts-Block ist ein klappbarer Panel-Block — natives <details> ODER .ds-panel__blk mit Titel-Marke data-panel-blk-h (components.css:967-1011); Verdrahtung NUR TGVEngine.wirePanelBlocks. Chevron IMMER rechts (K-42-Regel). Klassenlose Divs mit ds-h3-Titel bekommen KEINEN Griff — das ist der gemessene core_shell-openDocPanel-Zustand (die Luecke, die dieser Vertrag schliesst).",
      "mobil": "Bottom-Sheet mit Grabber, Grip aus (components.css:1086-1096); kein Popup.",
      "kopf_und_fuss": "Kopf: Titel mit #ID — bei Belegen ist die #ID der Drive-Link (R-91 GOLDENE REGEL) — plus Schliessen (Escape + ✕). Fuss: Aktionsleiste (K-40-Familie) + Rueckweg mit Ziel-Nennung (K-26-def).",
      "ehrlichkeit": "Jede Zeile zeigt Wert ODER benannten Leer-Zustand ('—' / 'folgt' / 'nicht eingestuft') — nie leer faken, nie Fake-Quittung (K-58-Geist). Felder lesen NUR Spalten, die die Tabelle hat (check_screen_liest_echte_spalte.py — Narbe: sensitivity vs confidentiality_level)."
    },
    "block_typen_waehlbar": {
      "_regel": "Jeder Block ist ein Katalog-Baustein mit K-ID. Fehlt ein Typ, laeuft er als Katalog-Kandidat (JC-Freigabe), NIE als Inline-Neubau im Screen.",
      "preview":        { "k_ids": ["K-29"], "wann": "eine Datei existiert (drive_file_id/raw_key) — dann ZUOBERST (JC #40: wer oeffnet, will das Dokument sehen); ohne Datei ehrlicher Leer-Zustand, nie Platzhalter-Fake" },
      "kerndaten":      { "k_ids": ["K-26", "K-60"], "wann": "immer — Identitaet des Objekts (Aussteller/Betreff/Datum/Betrag bzw. txn/ctr-Aequivalente); zwei Datums-Achsen getrennt beschriften (Dokumentdatum vs Eingang)" },
      "zusammenfassung":{ "k_ids": ["K-14", "K-56"], "wann": "KI-Summary vorhanden; sonst ehrlicher Pending-Block, nie leerer Abschnitt" },
      "einordnung":     { "k_ids": ["K-44"], "wann": "immer — Achsen-Badges (Entitaet · Vertraulichkeit · Konfidenz); Woerter NUR aus SENS_LBL/E4-Kanon (JE-157), nie erfunden; fehlende Einstufung heisst 'nicht eingestuft', nie stumm" },
      "verknuepfungen": { "k_ids": ["K-36"], "wann": "verknuepfte Objekte existieren (Zahlung/Buchung, Vertrag, Projekt) — jede Verknuepfung klickbar zum Nachbar-Panel; #ID mit Drive-Link (R-91)" },
      "volltext":       { "k_ids": ["K-56"], "wann": "extrahierter Text existiert — hinter Klapp/Tab, nie den Steckbrief fluten; laeuft Extraktion, ehrlicher 'wird extrahiert'-Zustand" },
      "herkunft":       { "k_ids": ["K-26"], "wann": "Provenienz-Fragen offen sind (Kanal, Absender, Eingang) — Inbox-/Eingangs-Kontext" },
      "fachblock":      { "k_ids": ["K-26", "K-60"], "wann": "der Objekt-Typ ihn verlangt: Rechnung→Betraege/Steuer + Zahlungs-Verknuepfung · Vertrag→Laufzeit/Kuendigung/Faelligkeit · Buchung→Konto/Gegenpartei/Abgleich · Reise→Etappen; berechnete Werte tragen ihre Annahme sichtbar ('19 % angenommen')" },
      "historie":       { "k_ids": ["K-42"], "wann": "das System schon gearbeitet hat (skills_done/Routing) — in KLARTEXT uebersetzt, nicht als Feldnamen-Liste" },
      "aktionen":       { "k_ids": ["K-40", "K-58"], "wann": "immer (Fuss) — verdrahtete Aktionen echt, unverdrahtete ehrlich als soon/deaktiviert mit benannter Naht, NIE toter Knopf" }
    },
    "agent_entscheidet": {
      "_regel": "Der screen-composer-Agent WAEHLT, ORDNET und LAESST WEG — innerhalb dieser Grenzen.",
      "darf": [
        "Bloecke nach Objekt-Typ und Datenlage waehlen und weglassen (ein Block ohne Daten und ohne ehrlichen Pending-Grund entfaellt)",
        "Reihenfolge innerhalb des Kanons anpassen: preview → kerndaten/einordnung → fachblock/verknuepfungen → langes (volltext/historie) → aktionen",
        "Default-Klappzustand setzen (Faustregel: die ersten 2-3 Bloecke offen, Rest zu; wirePanelBlocks persistiert je Titel in localStorage)",
        "fachliche Felder in den Fachblock legen (Gate E: fachliche Felder gehoeren ins Detail-Panel, NIE in den Composer)"
      ],
      "darf_nicht": [
        "neue Block-Markup-Typen oder CSS im Screen erfinden (NUXIN-N: fehlt ein Baustein → Katalog-Kandidat + Freigabe)",
        "den Rahmen aendern (Traeger, Resize, Klapp-Mechanik, Tokens sind SSOT)",
        "Vokabeln erfinden (Vertraulichkeits-/Achsen-Woerter NUR aus SENS_LBL/E4)",
        "Aktionen ohne Skill-Naht scharf schalten oder Fake-Quittungen zeigen",
        "Scope/RLS anfassen — das Panel zeigt NUR die RLS-gefilterte Zeile, die der Screen schon hat"
      ]
    },
    "referenzfall": {
      "screen": "Dokumente-Panel core_shell.html openDocPanel (:10551) — Referenz fuer Block-AUSWAHL (preview zuoberst, Kerndaten, Einordnung, Verknuepfung, Volltext/Quelle als Tabs, Aktions-Fuss), gemessen 10.08. (CANON-GARANTIE#01)",
      "bekannte_luecken_stand_2026_08_10": [
        "Bloecke NICHT aufklappbar: _stkSec (:10462) baut klassenlose Divs — DOM-gemessen 0 .ds-panel__blk / 0 aria-expanded trotz geladener engine (#410c; DIE Luecke dieses Vertrags)",
        "liest p.sensitivity statt confidentiality_level (:10572/:10585) — Einordnungs-Pille strukturell tot (#410a, SHELL#02-Naht sensCanon)",
        "Speicherort ohne Link, 'Drive ▸' hardcoded (:10585) — Resolver-Kette #1692 nutzen (#410b, STORAGE#02)",
        "eigener Panel-Typ .doc-panel (:1829) neben #tgvSp — 'EINE Steckbrief-Mechanik' (komponenten_data.js:80) noch nicht hergestellt; Resize heilt engine.js zur Laufzeit (gemessen: Grip da)"
      ]
    },
    "abnahme": [
      "panel_ist_slide_over_fixed_content_nie_gesplittet (PAN-01/E-27)",
      "breite_aus_panel_tokens_nie_nackte_zahl (#297)",
      "resize_nach_links_via_wireDockResize_gemessen_nicht_behauptet",
      "jeder_block_aufklappbar_details_oder_ds_panel_blk_mit_data_panel_blk_h (DOM-Messung: aria-expanded > 0)",
      "jede_zeile_wert_oder_benannter_leer_zustand_nie_leer_gefaked",
      "felder_lesen_nur_existierende_spalten (check_screen_liest_echte_spalte)",
      "id_im_kopf_ist_drive_link_bei_belegen (R-91)",
      "aktionen_echt_oder_ehrlich_soon_nie_tot",
      "einordnungs_woerter_nur_aus_SENS_LBL_E4 (JE-157)",
      "mobil_bottom_sheet_mit_grabber_kein_popup"
    ],
    "next_guard": "Detail-Panel-Guard: check_screen_haelt_komponenten_parameter.py um die Blocks-Frage erweitern — jedes Panel (PANEL_ROOT_SEL) muss seine Inhalts-Bloecke als <details> oder .ds-panel__blk tragen; klassenlose Titel-Divs im Panel-Koerper = ROT (die gemessene openDocPanel-Luecke als Sabotage-Selbsttest)."
  },
  "contracts": [
    {
      "id": "kosten-demo",
      "title": "Kosten-Cockpit Demo",
      "status": "staging_demo",
      "owner": "DATAVIZ#01 / KOSTEN#01",
      "file": "06_DASHBOARD/costs.html",
      "visible_url_local": "http://127.0.0.1:8787/costs.html?demo=1",
      "screen_type": "uebersicht",
      "intent": "JC sieht Kostenquellen, Schaetzanteile und Skill-Last als Chart plus Tabelle, ohne echte Kostendaten im lokalen Demo-Modus zu oeffnen.",
      "data_sources": [
        "v_tgv_costs_monthly via window.__shellAuth.restGet",
        "v_tgv_cost_volume via window.__shellAuth.restGet",
        "local demo data only when localhost/file and ?demo=1"
      ],
      "k_ids": [
        "K-33",
        "K-11"
      ],
      "fx_or_skills": [
        "TGVRenderers.chart",
        "window.__shellAuth.restGet"
      ],
      "icon_slugs": [
        "finance-overview",
        "analytics"
      ],
      "chart_specs": [
        {
          "id": "costs-by-source",
          "renderer": "TGVRenderers.chart",
          "type": "stacked-bar",
          "roles": [
            "confirm",
            "warn"
          ],
          "data_policy": "caller_supplies_rls_authorized_rows"
        }
      ],
      "abnahme": [
        "local_url_200",
        "script_syntax_ok",
        "no_direct_echarts_call_in_screen",
        "no_frontend_publishable_key",
        "demo_banner_when_local_demo"
      ],
      "next_guard": "Chart-Guard: direkte echarts.* Nutzung in Screens blockieren; nur tgv_renderers_chart.js darf ECharts intern nutzen.",
      "workbench_zone": "result_panel",
      "module_package": "finanzen-kosten-cockpit",
      "menu_scope": "Finanzen / intern / demo-local",
      "je_ids": [
        "JE-172"
      ],
      "rule_ids": [
        "R-91",
        "R-129"
      ],
      "component_ids": [
        "data-table",
        "scope-frame"
      ],
      "ux_ids": [
        "ECH-10",
        "SUR-02",
        "PAN-01"
      ]
    },
    {
      "id": "master-seitenbau",
      "title": "Master-Konzept Generative Seiten",
      "status": "documentation_contract",
      "owner": "KONZEPT#01 / SCREEN#01",
      "file": "06_DASHBOARD/konzepte/konzept_seitenbau.html",
      "visible_url_local": "http://127.0.0.1:8787/konzepte/konzept_seitenbau.html#screen-factory",
      "screen_type": "dossier",
      "intent": "Tower und JC sehen den Baukasten-Vertrag und die Propagation-Luecken an einem Ort, bevor neue Screens gebaut werden.",
      "data_sources": [
        "V3_INTENTION_AGENT_MAPPING.md",
        "taxonomie_data.js",
        "komponenten_data.js",
        "tgv_renderers_chart.js",
        "icons-global.json"
      ],
      "k_ids": [
        "K-10",
        "K-14",
        "K-16",
        "K-33",
        "K-45",
        "K-48"
      ],
      "fx_or_skills": [
        "familie_guard",
        "taxonomies_sync",
        "screen_factory_contract_guard"
      ],
      "icon_slugs": [
        "design-bible",
        "rules"
      ],
      "chart_specs": [],
      "abnahme": [
        "anchors_exist_screen_factory_propagation_icons_charts",
        "taxonomie_entries_exist",
        "roadmap_links_exist"
      ],
      "next_guard": "Contract-Guard: jeder neue Screen braucht diesen Vertrag vor Code/Markup.",
      "workbench_zone": "context",
      "module_package": "master-konzept-screen-factory",
      "menu_scope": "Verwaltung / Master-Konzepte / super_admin",
      "je_ids": [
        "JE-166",
        "JE-167",
        "JE-168",
        "JE-169",
        "JE-170",
        "JE-171",
        "JE-172",
        "JE-173"
      ],
      "rule_ids": [
        "R-84",
        "R-108",
        "R-128"
      ],
      "component_ids": [
        "statusline",
        "long-prose",
        "type-scale",
        "data-table",
        "composer"
      ],
      "ux_ids": [
        "SYS-01",
        "TXT-01",
        "SUR-02",
        "PAN-01",
        "cui-03c-selection-composer",
        "PIL-01",
        "ECH-10"
      ]
    },
    {
      "id": "kai-antwort-flaeche",
      "title": "KAI-Antwort-Flaeche (Chat-Bloecke, alle Surfaces)",
      "status": "tower_approved",
      "owner": "AGENT-CHAT#01",
      "file": "06_DASHBOARD/kai_renderer.js",
      "visible_url_local": "http://127.0.0.1:8787/core_shell.html",
      "screen_type": "dialog",
      "intent": "Jede KAI-Antwort (renderEnvelope, geteilt ueber core_shell + rka_chat + gabriel) baut ausschliesslich aus den Kanon-Bausteinen der kai-antwort-bloecke-Taxonomie: Langtext mit Formatvorlagen, K-33-Tabellen, Karten, Kanon-Badges, Collapse und Systemzeile — dieselbe Welt wie die Screens (ONE WORLD, E-7.1).",
      "data_sources": [
        "core-chat Envelope (payload v1) via window.__shellAuth.skillFetch",
        "taxonomie_data.js id kai-antwort-bloecke",
        "konzept_chatbot_first.html#kai-answer-contract"
      ],
      "je_ids": [
        "JE-169",
        "JE-161",
        "JE-157",
        "JE-170",
        "JE-171"
      ],
      "rule_ids": [
        "R-73",
        "R-91",
        "R-108",
        "R-128",
        "R-130"
      ],
      "component_ids": [
        "speaker-bubble",
        "kai-ava",
        "statusline",
        "long-prose",
        "data-table",
        "axis-badges",
        "type-scale",
        "ds-clamp",
        "chip",
        "composer"
      ],
      "k_ids": [
        "K-08",
        "K-09",
        "K-10",
        "K-14",
        "K-16",
        "K-18",
        "K-33",
        "K-44",
        "K-45",
        "K-56"
      ],
      "ux_ids": [
        "cui-01-speaker-bubble",
        "cui-04-content-frame",
        "TXT-01",
        "SYS-01",
        "PIL-01",
        "LNK-01",
        "PAN-01"
      ],
      "fx_or_skills": [
        "KAIChat.renderEnvelope",
        "KAIChat.systemLine",
        "KAIChat.userMsg",
        "fxDataTable",
        "core-chat (skillFetch)",
        "build_kai_inline.py (Inline-Sync-Pflicht)",
        "KAIChat.makeActions"
      ],
      "icon_slugs": [
        "ai-spark"
      ],
      "chart_specs": [],
      "abnahme": [
        "lange_antwort_traegt_ds_clamp_collapse_kai_und_user (R-JC-09, Schwelle 600)",
        "markdown_headings_als_h1_bis_h4_copy_paste (TXT-01/JE-169)",
        "markdown_tabelle_rendert_als_K-33_ds_table (R-V4-19)",
        "systemmeldung_nie_als_kai_bubble (SYS-01/R-108)",
        "badges_in_antworten_gleicher_kanon_wie_screens (JE-161/PIL-01)",
        "e4_woerter_aus_SENS_LBL_konsumiert_nie_eigene_woerter (E-5/JE-157, DESIGN#01 definiert)",
        "build_kai_inline_check_gruen (SSOT->Surfaces, kein Hand-Edit zwischen den Markern)",
        "keine_tote_karten_aktion_alle_11_typen_wirken (P1-Fix 01.08., KAIChat.makeActions)"
      ],
      "next_guard": "Antwort-Guard: check_screen_factory_contracts.py um answer_blocks-Pruefung erweitern (jeder Taxonomie-Block braucht k_ids+fundstelle; status todo/drift zaehlt als offener Befund, nie stillschweigend gruen).",
      "workbench_zone": "context",
      "module_package": "kai-antwort-kette",
      "menu_scope": "alle Surfaces / Zone 4 Conversation",
      "answer_blocks": {
        "_zweck": "AP1-Mapping AGENT-CHAT#01 (01.08.): je kai-antwort-block (Taxonomie element_count 12) der rendernde Kanon-Baustein mit Fundstelle. status: ok = gebunden · drift = existiert, weicht ab · todo = noch kein Renderer (ehrlich, kein Fake). Fundstellen zeigen auf die SSOT 06_DASHBOARD/kai_renderer.js; die Surfaces tragen den Code generiert (core_shell.html (generiert via 06_DASHBOARD/build_kai_inline.py, Marker KAI-INLINE)).",
        "long_text": {
          "k_ids": [
            "K-14",
            "K-45",
            "K-56"
          ],
          "ux_ids": [
            "TXT-01"
          ],
          "renderer": "appendProse -> .longprose (md() mit Heading-Ebenen h1-h4) + wireCollapse",
          "fundstelle": "06_DASHBOARD/kai_renderer.js appendProse/md/wireCollapse · kai_chat.css .longprose/.ds-clamp",
          "status": "ok"
        },
        "summary": {
          "k_ids": [
            "K-14"
          ],
          "ux_ids": [
            "cui-04-content-frame"
          ],
          "renderer": "prose-Block ohne longprose-Huelle (Kurzweiche <=220 Zeichen)",
          "fundstelle": "06_DASHBOARD/kai_renderer.js appendProse (long-Weiche)",
          "status": "ok"
        },
        "clarification": {
          "k_ids": [
            "K-18"
          ],
          "ux_ids": [
            "cui-01-speaker-bubble"
          ],
          "renderer": "klaerung_card (registerCard) + quick-reply-Chips",
          "fundstelle": "06_DASHBOARD/kai_renderer.js registerCard('klaerung_card')",
          "status": "drift",
          "note": "klaerung_card + beleg-preview fehlen als benannte K-IDs in komponenten_data.js (Landkarte-Gap, seit WP3-B im Code markiert) — Aufnahme = DESIGN#01/KONZEPT#01."
        },
        "evidence": {
          "k_ids": [
            "K-44"
          ],
          "ux_ids": [
            "LNK-01",
            "PIL-01"
          ],
          "renderer": ".srclinks Quell-Links + checkhint <details> (einklappbar) + Achsen-Badges",
          "fundstelle": "06_DASHBOARD/kai_renderer.js klaerung_card sources/check_md + axes()",
          "status": "ok"
        },
        "actions": {
          "k_ids": [
            "K-16",
            "K-18"
          ],
          "ux_ids": [
            "cui-03c-selection-composer"
          ],
          "renderer": "actBtn ds-btn--confirm/secondary/ghost + emit()-Surface-Hook",
          "fundstelle": "06_DASHBOARD/kai_renderer.js actBtn/emit",
          "status": "ok"
        },
        "panel_offer": {
          "k_ids": [],
          "ux_ids": [
            "PAN-01"
          ],
          "renderer": "ds-btn--ui 'im Panel oeffnen' / beleg-preview -> emit('open-doc')",
          "fundstelle": "06_DASHBOARD/kai_renderer.js klaerung_card beleg-preview; universeller panel_offer-Block fehlt",
          "status": "todo",
          "note": "Nur karten-lokal (Beleg) verdrahtet; generischer panel_offer-Renderer (Tabelle/Chart/Dossier ins Panel) fehlt — JE-171."
        },
        "screen_contract": {
          "k_ids": [],
          "ux_ids": [],
          "renderer": "kein Renderer",
          "fundstelle": "konzept_chatbot_first.html#kai-answer-contract (nur Vertragstext)",
          "status": "todo",
          "note": "Bei Screen-Erzeugung soll die Antwort den Vertrag einklappbar zeigen — haengt am Screen-Factory-Ausbau (KONZEPT#01/SCREEN#01)."
        },
        "system_statusline": {
          "k_ids": [
            "K-09",
            "K-10"
          ],
          "ux_ids": [
            "SYS-01"
          ],
          "renderer": "KAIChat.systemLine (Sysglyph, keine Bubble, kein Kai-Avatar; warn/danger)",
          "fundstelle": "06_DASHBOARD/kai_renderer.js systemLine · core_shell failWith/sysDone/__kaiLog-role-sys + Replay",
          "status": "ok",
          "note": "Fix 01.08. (AP2c): Fehler-/Vorschau-Pfade sprachen vorher als KAI-Bubble."
        },
        "copy_paste_formats": {
          "k_ids": [
            "K-14",
            "K-45"
          ],
          "ux_ids": [
            "TXT-01"
          ],
          "renderer": "md() Heading-Ebenen h1-h4 + echte <table>/<ul> im DOM",
          "fundstelle": "06_DASHBOARD/kai_renderer.js md() · kai_chat.css .longprose h1-h4 (Type-Scale K-45)",
          "status": "ok",
          "note": "Fix 01.08. (AP2b): vorher plaettete md() alle #-Ebenen auf h5 — Struktur ging beim Kopieren verloren (JE-169)."
        },
        "embedded_table": {
          "k_ids": [
            "K-33"
          ],
          "ux_ids": [
            "cui-04-content-frame"
          ],
          "renderer": "appendProse trennt Markdown-Tabellen ab -> fxDataTable (leichte Variante search:false)",
          "fundstelle": "06_DASHBOARD/kai_renderer.js _splitProse/_renderMdTable/appendProse",
          "status": "ok",
          "note": "Frueher Drift (nur in der core_shell-Inline-Kopie); mit dem DESIGN#01-SSOT-Resync + build_kai_inline.py ist es EINE Quelle."
        },
        "embedded_chart": {
          "k_ids": [],
          "ux_ids": [
            "cui-04-content-frame"
          ],
          "renderer": "kein Renderer im Antwort-Pfad",
          "fundstelle": "chart_typen-Taxonomie verlangt TGVRenderers.chart; renderEnvelope hat keinen chart-Block-Kind",
          "status": "todo",
          "note": "Ziel CUI-04: eCharts als Baustein in der Antwortgruppe via TGVRenderers.chart (DATAVIZ#01-Kapsel) — kein eigener Chart-Weg im Chat."
        },
        "right_panel_trigger": {
          "k_ids": [],
          "ux_ids": [
            "PAN-01"
          ],
          "renderer": "emit('open-doc'/'open-item') -> Surface-Hook KAIChat.onAction",
          "fundstelle": "06_DASHBOARD/kai_renderer.js emit + core_shell onAction-Verdrahtung",
          "status": "drift",
          "note": "Hook existiert; einheitliche Bindung an das universelle rechte Panel (PAN-01/JE-171, resizable nach E-4) ist je Screen unterschiedlich verdrahtet."
        }
      },
      "actions": {
        "_zweck": "Aktions-Vertrag (AGENT-CHAT#01 01.08., P1-Fix): die Karten emittieren diese Typen ueber emit()->KAIChat.onAction. Die Liste lebt in der SSOT (kai_renderer.js ACTION_TYPES/makeActions), damit keine Surface einen Typ vergessen kann — genau das war der Befund (core_shell behandelte 2 von 11, '📄 Beleg ansehen' war tot). Jede Surface liefert nur ihre Faehigkeiten (ask/openDoc/fillComposer/notify/openUrl); fehlt eine, MELDET der Handler das als Systemzeile statt still zu verpuffen.",
        "ssot": "06_DASHBOARD/kai_renderer.js (ACTION_TYPES + makeActions)",
        "schreib_grenze": "approve/klaer-accept loesen KEINEN Write aus — die Karte quittiert lokal (read-only), der scharfe Pfad bleibt JC-gated in Klaerung & Freigaben. Ein '✓ gespeichert' ohne Speicherung waere schlimmer als ein toter Knopf.",
        "typen": {
          "open-doc": "Beleg/Dokument im Panel (core_shell: openDocPanel · fragekai2: PAN-01 · rka_chat: Drive-Fenster)",
          "open-item": "Listen-Eintrag -> Frage in den Thread",
          "open-source": "Quell-Link oeffnen; ohne Link ehrliche Systemzeile",
          "ask-context": "Kontext-Frage in den Thread",
          "quick-reply": "KAIs angebotene Antwort -> als Frage senden",
          "approve": "Vorschlag annehmen (read-only, s. schreib_grenze)",
          "correct": "Korrektur -> Composer vorbefuellen, NICHT senden",
          "later": "zurueckstellen (ehrlich: nichts gespeichert)",
          "klaer-accept": "Klaer-Vorschlag annehmen (read-only, s. schreib_grenze)",
          "klaer-correct": "Klaer-Korrektur -> Composer vorbefuellen",
          "klaer-resolved": "Folge-EREIGNIS nach dem Annehmen — bewusst still (Karte quittiert selbst)"
        },
        "abnahme": "Jeder Typ hat sichtbare Wirkung (Panel / Frage / Composer / Systemzeile) — live gegengeprueft 01.08.: 0 tote Typen."
      }
    },
    {
      "id": "fragekai2",
      "title": "KAI fragen 2 (ONE-WORLD-Kanon-Neubau)",
      "status": "tower_approved",
      "owner": "AGENT-CHAT#01",
      "file": "06_DASHBOARD/fragekai2.html",
      "visible_url_local": "http://127.0.0.1:8787/fragekai2.html",
      "screen_type": "dialog",
      "intent": "JC stellt KAI eine freie Frage und bekommt eine Antwort, die aus denselben Bausteinen gebaut ist wie jeder Screen: Langtext mit Formatvorlagen, Kanon-Tabellen, Karten, Achsen-Badges, Collapse — Verhalten 1:1 aus core_shell #/chat (secChat) uebernommen, aber als eigenstaendiger Screen streng nach der 5-Zonen-Anatomie und den JC-Entscheiden E-1..E-10.",
      "data_sources": [
        "core-chat Envelope (payload v1) via window.__shellAuth.skillFetch — RLS-Scope kommt vom Aufrufer, Screen setzt keinen Scope",
        "06_DASHBOARD/kai_renderer.js + kai_chat.css (Chat-SSOT, inline via build_kai_inline.py)",
        "06_DASHBOARD/tgv_e4_labels.js (E4-Woerter JE-157/E-5 als ladbare Daten)",
        "01_ITERATIONS/DESIGN_01_DESIGN_SYSTEM_OWNER/icons/icons-global.json via TGVEngine.loadIconSet"
      ],
      "je_ids": [
        "JE-002",
        "JE-157",
        "JE-161",
        "JE-169",
        "JE-170",
        "JE-171"
      ],
      "rule_ids": [
        "R-02",
        "R-10",
        "R-11",
        "R-12",
        "R-14",
        "R-42",
        "R-73",
        "R-89",
        "R-90",
        "R-91",
        "R-95",
        "R-96",
        "R-108",
        "R-119",
        "R-126",
        "R-128",
        "R-130",
        "R-131",
        "R-142",
        "R-147"
      ],
      "component_ids": [
        "zone-anatomie",
        "zone-hero",
        "speaker-bubble",
        "kai-ava",
        "statusline",
        "thread-context",
        "long-prose",
        "composer",
        "composer-helper",
        "chip",
        "data-table",
        "axis-badges",
        "type-scale",
        "ds-clamp"
      ],
      "k_ids": [
        "K-01",
        "K-02",
        "K-08",
        "K-09",
        "K-10",
        "K-13",
        "K-14",
        "K-16",
        "K-17",
        "K-18",
        "K-33",
        "K-44",
        "K-45",
        "K-56"
      ],
      "ux_ids": [
        "WB-01",
        "cui-01-speaker-bubble",
        "cui-02-composer",
        "cui-03b-passive-composer",
        "cui-04-content-frame",
        "TXT-01",
        "SYS-01",
        "PIL-01",
        "LNK-01",
        "PAN-01",
        "SUR-01",
        "hero-01-kpi",
        "MOT-04",
        "MOT-05"
      ],
      "fx_or_skills": [
        "KAIChat.renderEnvelope",
        "KAIChat.userMsg",
        "KAIChat.systemLine",
        "KAIChat.thinking",
        "TGVEngine.icon / loadIconSet",
        "TGVEngine.SEND_SVG",
        "core-chat (window.__shellAuth.skillFetch)",
        "build_kai_inline.py (Inline-Sync-Pflicht)",
        "KAIChat.makeActions"
      ],
      "icon_slugs": [
        "ask-kai",
        "reset",
        "leave-context",
        "pin",
        "scope-all",
        "date",
        "eu-flag",
        "attach-plus",
        "ai-spark"
      ],
      "chart_specs": [],
      "abnahme": [
        "fuenf_zonen_anatomie_WB01 (Z2 Hero · Z4 Konversation · Z5 Composer; Z3 entfaellt bei Typ dialog)",
        "composer_breite_gleich_antwort_breite (E-10, beide --content-col)",
        "collapse_an_jeder_langen_kai_und_ich_antwort (JE-002 z4-bubble, R-JC-09-Schwelle 600)",
        "kein_screen_lokaler_composer_nur_ds_composer_klassen (K-16 SSOT, R-11/R-12)",
        "tgv_icons_via_TGVEngine_icon_kein_emoji_wo_slug_existiert (E-3)",
        "systemmeldung_nie_als_kai_bubble (SYS-01/R-108)",
        "e4_woerter_aus_tgv_e4_labels_konsumiert_nie_eigene (JE-157/E-5)",
        "keine_toten_buttons_nicht_verdrahtetes_ist_ehrlich_deaktiviert",
        "empty_loading_error_zustaende_echt (Thinking-Indikator · Systemzeile · leerer Thread)",
        "kein_scope_oder_rls_eingriff_im_screen (Datenpfad unveraendert)",
        "script_syntax_ok",
        "build_kai_inline_check_gruen",
        "keine_tote_karten_aktion_alle_11_typen_wirken (P1-Fix 01.08., KAIChat.makeActions)"
      ],
      "next_guard": "Screen-Guard: fragekai2 in die TGV_CONFORMANCE-/familie_guard-Laeufe aufnehmen (Composer-Drift, Icon-Drift, Antwort-Collapse) — heute per Hand + DOM-Gegenbeweis geprueft, noch nicht dauerhaft verguardet.",
      "workbench_zone": "context",
      "module_package": "kai-antwort-kette",
      "menu_scope": "KAI / alle Mandanten / eingeloggt",
      "actions": {
        "_zweck": "Aktions-Vertrag (AGENT-CHAT#01 01.08., P1-Fix): die Karten emittieren diese Typen ueber emit()->KAIChat.onAction. Die Liste lebt in der SSOT (kai_renderer.js ACTION_TYPES/makeActions), damit keine Surface einen Typ vergessen kann — genau das war der Befund (core_shell behandelte 2 von 11, '📄 Beleg ansehen' war tot). Jede Surface liefert nur ihre Faehigkeiten (ask/openDoc/fillComposer/notify/openUrl); fehlt eine, MELDET der Handler das als Systemzeile statt still zu verpuffen.",
        "ssot": "06_DASHBOARD/kai_renderer.js (ACTION_TYPES + makeActions)",
        "schreib_grenze": "approve/klaer-accept loesen KEINEN Write aus — die Karte quittiert lokal (read-only), der scharfe Pfad bleibt JC-gated in Klaerung & Freigaben. Ein '✓ gespeichert' ohne Speicherung waere schlimmer als ein toter Knopf.",
        "typen": {
          "open-doc": "Beleg/Dokument im Panel (core_shell: openDocPanel · fragekai2: PAN-01 · rka_chat: Drive-Fenster)",
          "open-item": "Listen-Eintrag -> Frage in den Thread",
          "open-source": "Quell-Link oeffnen; ohne Link ehrliche Systemzeile",
          "ask-context": "Kontext-Frage in den Thread",
          "quick-reply": "KAIs angebotene Antwort -> als Frage senden",
          "approve": "Vorschlag annehmen (read-only, s. schreib_grenze)",
          "correct": "Korrektur -> Composer vorbefuellen, NICHT senden",
          "later": "zurueckstellen (ehrlich: nichts gespeichert)",
          "klaer-accept": "Klaer-Vorschlag annehmen (read-only, s. schreib_grenze)",
          "klaer-correct": "Klaer-Korrektur -> Composer vorbefuellen",
          "klaer-resolved": "Folge-EREIGNIS nach dem Annehmen — bewusst still (Karte quittiert selbst)"
        },
        "abnahme": "Jeder Typ hat sichtbare Wirkung (Panel / Frage / Composer / Systemzeile) — live gegengeprueft 01.08.: 0 tote Typen."
      }
    },
    {
      "id": "core-dokumente",
      "title": "Dokumente & Ablage — core_shell #/dokumente (Live-Screen, Garantie-Gegenstand)",
      "status": "live_vertrag_nachgezogen_2026-08-10",
      "owner": "SHELL#02 (Bau #412) / CANON-GARANTIE#01 (Vertrag+Messung, Tower#36-L0-Entscheid)",
      "file": "06_DASHBOARD/core_shell.html",
      "visible_url_local": "http://127.0.0.1:8787/core_shell.html#/dokumente",
      "screen_type": "inbox",
      "intent": "JC findet jeden Beleg in der Shell, in der er taeglich arbeitet (Tower-L0-Entscheid 10.08.: DIESER Screen ist der Garantie-Gegenstand, dokumente2.html ist Referenz-Baustelle): Verzeichnisbaum je Entitaet/Monat (Sekundaermenue E-36), Filter-Leiste, Kanon-Tabelle mit Zeilen-Menue und Bulk, Klick auf die Zeile oeffnet den Beleg-Steckbrief (openDocPanel, Referenzfall des detail_view_contract). Der Menue-Punkt des Screens ist verdikt-gebunden (#415): gruen NUR mit gruenem DOM-Pruefbericht.",
      "data_sources": [
        "documents via window.__shellAuth.restGet (User-JWT, RLS) — Seite mit benannter Kappung _DOK_LIMIT=100 (core_shell.html secDokumente, #395) + eigene id-only-Bestandsabfrage bis _DOK_BESTAND_MAX=5000 fuer Baum/Zaehlung; Kappung wird ANGESAGT, nie still (#398)",
        "Vertraulichkeits-Lesekette _sensOf: confidentiality_level || confidentiality || sensitivity (SHELL#02-Fix 10.08. — documents traegt confidentiality_level, Mig 181; die 5 LM/Gabriel-Stufen erscheinen NICHT als Filter-Option, tauchen sie in Daten auf, ist das ein Wand-Befund)",
        "lokaler Demo-Datensatz NUR ohne Login mit sichtbarem Demo-Banner (dokDemoNote)"
      ],
      "je_ids": [
        "JE-002",
        "JE-157",
        "JE-161",
        "JE-171"
      ],
      "rule_ids": [
        "R-30",
        "R-91",
        "R-116",
        "R-120",
        "R-129",
        "R-131",
        "R-143",
        "R-147"
      ],
      "component_ids": [
        "zone-anatomie",
        "zone-hero",
        "kpi-tile",
        "kpi-block",
        "folder-tree",
        "data-table",
        "doc-steckbrief",
        "file-actions",
        "axis-badges",
        "composer",
        "collapsible-section",
        "statusline",
        "icon-resolver"
      ],
      "k_ids": [
        "K-02",
        "K-03",
        "K-04",
        "K-16",
        "K-26",
        "K-33",
        "K-40",
        "K-41",
        "K-42",
        "K-44",
        "K-48",
        "K-58"
      ],
      "ux_ids": [
        "WB-01",
        "NAV-02",
        "hero-01-kpi",
        "SUR-02",
        "PAN-01",
        "PIL-01",
        "SYS-01",
        "LNK-01"
      ],
      "fx_or_skills": [
        "window.__shellAuth.restGet (RLS-Datenpfad, Screen setzt keinen Scope)",
        "fxRender('data-table') -> Delegation an TGVEngine.dataTableFull wenn engine geladen (K-33-Hybrid, s. bekannte_schulden)",
        "mountScreenComposer/mountComposer (K-16 Shell-Instanz im PLAT#03-Slot — EINE Quelle fuer alle Shell-Screens)",
        "openDocPanel (K-26-Instanz-SOLL; heutige Luecken = detail_view_contract.referenzfall)",
        "safeIco -> TGVEngine.icon (K-48-Instanz mit ehrlichem Fallback)",
        "TGV_CONFORMANCE.runHere (DOM-Verdikt je Routenwechsel -> Menue-Punkt, #415)"
      ],
      "icon_slugs": [
        "documents",
        "folder",
        "detail",
        "clarify",
        "ai-spark"
      ],
      "chart_specs": [],
      "workbench_zone": "result_panel",
      "module_package": "dokumente-ablage",
      "menu_scope": "Eingang / Dokumente & Ablage / eingeloggt (Shell-Route #/dokumente; Menue-Punkt verdikt-gebunden #415)",
      "abnahme": [
        "script_syntax_ok",
        "tabelle_ist_k33_mit_rowAction_rowMenu_bulk_nie_selbstgebaute_spalte (B1/B2-Ablösung)",
        "pillen_lesen_confidentiality_level_lesekette_nie_totes_feld (K-44, #410a-Klasse)",
        "kappung_benannt_und_angesagt_nie_stille_100 (#395/#398)",
        "keine_toten_knoepfe_unverdrahtetes_sagt_zustand_und_aendert_nichts (K-58)",
        "beleg_panel_erfuellt_detail_view_contract (aufklappbare Bloecke + Grip + ehrliche Zeilen — Referenzfall-Luecken geschlossen)",
        "menue_punkt_nur_gruen_mit_gruenem_dom_verdikt (#415, fail-closed, beide Richtungen getestet)",
        "composer_ist_k16_slot_instanz_kein_screen_eigener_bau",
        "harte_1200px_durch_content_col_ersetzt (L6 -> SHELL#02 #1733; E-9.3)",
        "composer_inner_zentriert_wie_klaerung (L7-Arbitrage ZENTRIERT, SSOT composerWrap; SHELL#02 #1733)",
        "eingeloggte_dom_nachmessung_gruen (JC/Auto-QA nach Merge+Deploy — Garantie-Gate)"
      ],
      "next_guard": "Vertrag<->DOM-Guard (dokumente2.next_guard generalisieren): deklarierte k_ids muessen im GERENDERTEN Screen als Kanon-Klassen/Instanzen auftauchen. UND: 'dokumente' aus BASELINE_OHNE_GATE_A (08_OPS/check_gate_a_presence.py) streichen, sobald der Gate-A-Report nachgeholt ist — die Ausnahme ist Schuld, kein Freibrief.",
      "bekannte_schulden": {
        "_zweck": "Tower-L0-Auftrag 10.08.: bekannte Schulden stehen IM Vertrag, damit die Garantie-Messung sie zaehlen kann statt sie zu suchen. Jede Zeile traegt ihr Ende (Register/Lane).",
        "gate_a_fehlt": "Screen ist in BASELINE_OHNE_GATE_A eingefroren (check_gate_a_presence.py) — Gate-A-Report (Sinn/Zeitgewinn) nachholen; bis dahin ist die Ausnahme dokumentierte Schuld.",
        "panel_bloecke_unklappbar_L1": "_stkSec baut klassenlose Divs, wirePanelBlocks erreicht sie nicht (DOM-gemessen 0 aria-expanded) — Panel-Paket der Gate-A-Welle (Register #416), Messlatte = detail_view_contract",
        "dritter_panel_typ_L4": ".doc-panel neben #tgvSp — EINE Steckbrief-Mechanik herstellen (Register #416, mit L1 EIN Paket)",
        "baum_ohne_katalog_heimat_L5": ".dok-explorer/.ds-dirpanel/.ds-tree/.dok-crumb nur shell-lokal; K-41 braucht Komponenten-Heimat (Register #416)",
        "harte_1200_und_ausrichtung_L6_L7": "4x hartes 1200px statt var(--content-col) + margin:0 statt zentriert — SHELL#02 in #1733 (L7-Arbitrage: ZENTRIERT)",
        "komponenten_topologie": "Composer 6 Markup-Erzeuger, Breiten-Regel 3 Orte, Pillen 2x, K-33-Zweitfamilie — Register #417 (Konsolidierungs-Roadmap Composer->Panel->Pillen->K-33, Tower-Schnitt)"
      }
    },
    {
      "id": "dokumente2",
      "title": "Dokumente & Ablage (ONE-WORLD-Kanon)",
      "status": "canon_rebuild",
      "owner": "DESIGN#01",
      "file": "06_DASHBOARD/dokumente2.html",
      "visible_url_local": "http://127.0.0.1:8787/dokumente2.html",
      "screen_type": "inbox",
      "intent": "JC sieht seine Belege wie in einem Datei-Explorer: Verzeichnis links, Liste mit Suche/Sortierung/Mehrfachauswahl in der Mitte, Steckbrief mit echter Vorschau rechts — gebaut ausschliesslich aus Kanon-Bausteinen, damit der Screen die ONE-WORLD-Kette (JE/R/K/UX) nachweisbar erfuellt.",
      "data_sources": [
        "documents via window.__shellAuth.restGet, wenn der Screen aus der Shell geoeffnet wird (User-JWT, RLS-scoped)",
        "documents standalone via PostgREST mit dem USER-Access-Token aus der GETEILTEN Supabase-Session (storageKey 'tgv-core-shell-auth', Muster rka2.html:400-424) — kein Re-Login, identischer RLS-Pfad wie core_shell.html:9062",
        "lokaler Demo-Datensatz NUR auf localhost/file:// mit sichtbarem Demo-Banner"
      ],
      "je_ids": [
        "JE-002",
        "JE-157",
        "JE-161",
        "JE-166",
        "JE-167",
        "JE-168",
        "JE-169",
        "JE-171",
        "JE-173"
      ],
      "rule_ids": [
        "R-30",
        "R-32",
        "R-50",
        "R-91",
        "R-97",
        "R-116",
        "R-120",
        "R-125",
        "R-127",
        "R-129",
        "R-131",
        "R-143",
        "R-147"
      ],
      "component_ids": [
        "data-table",
        "folder-tree",
        "doc-steckbrief",
        "file-actions",
        "axis-badges",
        "zone-hero",
        "kpi-tile",
        "kpi-block",
        "beleg-preview",
        "composer",
        "collapsible-section",
        "source-link",
        "statusline"
      ],
      "k_ids": [
        "K-02",
        "K-03",
        "K-04",
        "K-11",
        "K-16",
        "K-26",
        "K-29",
        "K-33",
        "K-36",
        "K-40",
        "K-41",
        "K-42",
        "K-44"
      ],
      "ux_ids": [
        "SC-01-02",
        "WB-01",
        "hero-01-kpi",
        "NAV-02",
        "SUR-02",
        "PAN-01",
        "TPL-02",
        "LNK-01",
        "PIL-01",
        "CUI-02A",
        "SYS-01",
        "MOT-04"
      ],
      "fx_or_skills": [
        "window.__shellAuth.restGet (Shell-Modus)",
        "supabase-js createClient mit geteiltem storageKey (Standalone-Modus, nur supabase.auth)",
        "TGVEngine.dataTableFull / docSteckbrief / icon / sweepRawEmojiIcons"
      ],
      "icon_slugs": [
        "documents",
        "folder",
        "folder-open",
        "inbox",
        "search",
        "detail",
        "close",
        "fullscreen",
        "preview",
        "lock",
        "eu-flag",
        "entity",
        "date",
        "attachment",
        "download",
        "move",
        "send-mail",
        "knowledge",
        "chat-input",
        "delete",
        "clarify",
        "warning",
        "pending"
      ],
      "chart_specs": [],
      "workbench_zone": "result_panel",
      "module_package": "dokumente-ablage",
      "menu_scope": "Eingang / Dokumente & Ablage / viewer+",
      "abnahme": [
        "local_url_200",
        "script_syntax_ok",
        "keine_screen_lokale_komponenten_kopie",
        "icons_ueber_resolver_kein_rohes_emoji_im_slot",
        "composer_breite_gleich_antwortflaeche",
        "panel_ausklappbar_und_nach_links_resizable",
        "badges_tragen_E4_woerter_inkl_projekt_team",
        "keine_toten_buttons_nicht_verdrahtetes_ist_soon",
        "empty_loading_error_zustaende_echt",
        "kein_horizontaler_overflow_375_und_1280_hell_und_dunkel",
        "demo_banner_when_local_demo",
        "auth_ueber_geteilte_session_kein_re_login",
        "kein_endlos_laden_jeder_fehlerfall_endet_benannt"
      ],
      "next_guard": "Screen-Factory-Guard erweitern: pro Vertrag pruefen, dass die deklarierten k_ids im Markup wirklich als Kanon-Klassen auftauchen (Vertrag <-> DOM), statt nur die ID-Existenz zu pruefen.",
      "skill_needs": {
        "_zweck": "E-31.4 (JC 02.08.): jede soon-Aktion ist ein SKILL-BEDARF im Bauplan, kein blosser UI-Platzhalter. Diese Liste ist die Naht — je Aktion der noetige Skill (Registry-Eintrag folgt via Tower-Bauplan). Alle destruktiven: apply-Flag + JC-Gate (Muster rka-delete-trip E-17). Bulk = derselbe Skill mit ids[] (E-31.2 Bulk-Paritaet, gleiches Menue).",
        "aktionen": {
          "pdf": {
            "skill": "doc-export-pdf",
            "status": "fehlt",
            "naht": "Zeilen-/Bulk-⋯ -> Export-Executor; read-only, unkritisch"
          },
          "xlsx": {
            "skill": "doc-export-xlsx",
            "status": "fehlt",
            "naht": "wie pdf; eine Export-Familie, zwei Formate"
          },
          "thread": {
            "skill": "kein eigener Skill — Shell-Naht",
            "status": "teil",
            "naht": "Doc als Chat-Kontext in den Composer (core_shell openDocPanel/CUI-Bindung existiert); Standalone braucht nur den Deep-Link in die Shell"
          },
          "rag": {
            "skill": "doc-to-knowledge-folder",
            "status": "fehlt",
            "naht": "E-25 B2.2 Wissens-ORDNER-Modell (Sichtbarkeits-Badge, K-41-Vererbung); Chunking auto (E-26.3), Vertraulichkeit regelt nur KAI-Sichtbarkeit"
          },
          "move": {
            "skill": "doc-move",
            "status": "fehlt",
            "naht": "Dokumentalist-Executor; drive_folder_id+final_path konsistent setzen (Store-File-Muster)"
          },
          "archive": {
            "skill": "doc-archive",
            "status": "fehlt",
            "naht": "Status-Wechsel + Ablage-Ordner; GoBD-Blick: nie hart loeschen"
          },
          "delete": {
            "skill": "doc-delete",
            "status": "fehlt",
            "naht": "destruktiv: apply-Flag + JC-Gate + Kaskaden-Semantik (txn-Verknuepfung loesen, nie still)"
          },
          "folder_crud": {
            "skill": "folder-create/-delete",
            "status": "fehlt",
            "naht": "E-25 B1.14 (VARIANTE_3-Sekundaermenue); ehrlich-soon bis Dokumentalist-Schreibpfad"
          }
        }
      }
    },
    {
      "id": "rka2",
      "title": "Reisekosten-Cockpit — Kanon-Fassung (RKA2)",
      "status": "staging_canon",
      "owner": "RKA2-Lane / TOWER#29",
      "file": "06_DASHBOARD/rka2.html",
      "visible_url_local": "http://127.0.0.1:8787/rka2.html",
      "screen_type": "uebersicht",
      "intent": "JC rechnet eine Reise vollstaendig ab: RKA waehlen oder anlegen, Etappen im Assistenten beschreiben und korrigieren, Belege zuordnen, Pauschalen rechnen, Zahlung pruefen, Deckblatt und km-Erstattung ausgeben - in der ONE-WORLD-Kanon-Anatomie statt in screen-lokalen Karten-Nachbauten. Funktionsgleich zur Referenz 06_DASHBOARD/rka_v2.html (Funktions-Inventar 01_ITERATIONS/CONTROL_TOWER_HANDOFF/RKA2_FUNKTIONS_INVENTAR_2026-08-01.md), null stille Verluste.",
      "data_sources": [
        "skill rka-list-trips via user-JWT (window.__shellAuth.skillFetch, sonst eigene Supabase-Session storageKey tgv-core-shell-auth)",
        "skill rka-create-trip via user-JWT",
        "skill rka-autofind via user-JWT (Beleg-Matcher, include_assigned/apply/confirm_ids)",
        "skill rka-beleg-update via user-JWT",
        "skill rka-calculate via user-JWT (Verpflegung/Uebernachtung/km-Pauschale)",
        "skill rka-verify via user-JWT (Zahlungsabgleich Bank)",
        "skill rka-render via user-JWT (Deckblatt-HTML)",
        "skill rka-auto-modus via user-JWT (Freitext-Parse + Geocoding + Routing)",
        "skill rka-km-list via user-JWT (Fahrtenbuch + Etappen der RKA)",
        "skill rka-km-autofill via user-JWT (letzter Tacho-Stand je Kennzeichen)",
        "skill rka-km-erfassen via user-JWT (Fahrt schreiben)",
        "skill rka-km-delete-window via user-JWT (REPLACE-Vorstufe, nur reviewed=false)",
        "skill rka-km-orte-alias via user-JWT (Adress-Autocomplete)",
        "localStorage tgv_reisender (Name fuer die PDF-Unterschrift, rein lokal)",
        "kein Frontend-Datenkey: der publishable Supabase-Key traegt AUSSCHLIESSLICH supabase.auth (Login/Magic-Link), nie einen Daten-Read"
      ],
      "je_ids": [
        "JE-002",
        "JE-033",
        "JE-053",
        "JE-073",
        "JE-077",
        "JE-157",
        "JE-159",
        "JE-168",
        "JE-171"
      ],
      "rule_ids": [
        "R-02",
        "R-11",
        "R-13",
        "R-30",
        "R-31",
        "R-34",
        "R-51",
        "R-91",
        "R-99",
        "R-116",
        "R-120",
        "R-132",
        "R-143",
        "R-V4-ICON"
      ],
      "component_ids": [
        "zone-anatomie",
        "zone-hero",
        "kpi-tile",
        "kpi-block",
        "stepper",
        "zone-main",
        "speaker-bubble",
        "kai-ava",
        "statusline",
        "scope-frame",
        "composer",
        "composer-helper",
        "composer-soon",
        "chip",
        "vorschlags-chip",
        "done-state",
        "dock-panel",
        "doc-steckbrief",
        "txn-steckbrief",
        "data-table",
        "source-link",
        "file-actions",
        "collapsible-section",
        "callout",
        "axis-badges",
        "icon-resolver"
      ],
      "k_ids": [
        "K-01",
        "K-02",
        "K-03",
        "K-04",
        "K-05",
        "K-07",
        "K-08",
        "K-09",
        "K-10",
        "K-11",
        "K-16",
        "K-17",
        "K-18",
        "K-19",
        "K-25",
        "K-26",
        "K-27",
        "K-33",
        "K-35",
        "K-36",
        "K-40",
        "K-42",
        "K-43",
        "K-44",
        "K-48",
        "K-58",
        "K-60"
      ],
      "ux_ids": [
        "WB-01",
        "SC-01",
        "SUR-01",
        "SUR-02",
        "PAN-01",
        "hero-01-kpi",
        "hero-collapse",
        "scope-01-hero-controls",
        "TPL-04",
        "CARD-01",
        "BTN-01",
        "BTN-02",
        "BTN-03",
        "PIL-01",
        "TXT-01",
        "SYS-01",
        "LNK-01",
        "MOT-01",
        "cui-02-composer",
        "cui-03-bound-composer",
        "CUI-03C"
      ],
      "fx_or_skills": [
        "TGVEngine.icon",
        "TGVEngine.loadIconSet",
        "TGVEngine.dataTableFull",
        "TGVEngine.fileMenu",
        "TGVEngine.bxBadges",
        "TGVEngine.srcChip",
        "TGVEngine.driveHref",
        "TGVEngine.numGlyph",
        "TGVEngine.SEND_SVG",
        "TGVEngine.esc",
        "TGVEngine.assertConformance",
        "window.__shellAuth.skillFetch"
      ],
      "icon_slugs": [
        "travel-cockpit",
        "logbook",
        "etappe",
        "commute",
        "documents",
        "transactions",
        "month-close",
        "print-pdf",
        "download",
        "preview",
        "external",
        "detail",
        "search",
        "save",
        "reset",
        "date",
        "entity",
        "pending",
        "warning",
        "check",
        "blocked",
        "ai-ask",
        "dictate",
        "attach-plus",
        "close",
        "knowledge",
        "chat-input",
        "send-mail",
        "lock",
        "history",
        "edit",
        "delete",
        "pin",
        "placeholder"
      ],
      "chart_specs": [],
      "workbench_zone": "result_panel",
      "module_package": "reisekosten-rka-cockpit",
      "menu_scope": "Reisen / RKA / intern",
      "abnahme": [
        "local_url_200",
        "script_syntax_ok",
        "no_frontend_publishable_key_on_data_path",
        "five_zone_anatomy_present_wb01",
        "zone3_is_sur02_workblock_one_white_field",
        "table_is_k33_dataTableFull_search_and_sort_inside_component",
        "exports_in_k40_dots_menu_no_free_buttons",
        "pan01_panel_collapsible_blocks_and_resizable_to_the_left",
        "axis_badges_carry_e4_words_je157",
        "icons_via_icon_resolver_no_raw_emoji_where_slug_exists",
        "composer_width_equals_answer_width",
        "empty_loading_error_states_honest",
        "unwired_actions_visibly_disabled_soon_never_dead_button",
        "gegenprobe_alt_neu_table_complete_no_silent_loss"
      ],
      "next_guard": "RKA2-Gegenprobe-Guard: jede Zeile des Funktions-Inventars muss in der Gegenprobe-Tabelle einen Status tragen (erhalten/soon/nicht-portierbar) - ein stiller Verlust ist ROT."
    },
    {
      "id": "abgleich2",
      "title": "Zahlungs-Abgleich (ONE-WORLD-Kanon-Neubau)",
      "status": "canon_rebuild",
      "owner": "BUCHHALTUNG#01",
      "file": "06_DASHBOARD/abgleich2.html",
      "visible_url_local": "http://127.0.0.1:8787/abgleich2.html",
      "screen_type": "uebersicht",
      "intent": "INTENTION (Gate A, E-20.3 / Register #250): Monatlich (~3. fuer den VORMONAT) prueft JC je Entitaet in Minuten, dass jede Bank-Buchung ihren Beleg hat und jeder Beleg seine Zahlung. Hero-KPIs = Buchungen-ohne-Beleg / Belege-ohne-Zahlung / %-zugeordnet; hochkonfidente Auto-Matcher-Vorschlaege erscheinen als approve-Karten (K-21) mit Konfidenz-Pille und Quelle; unsichere Reste werden NICHT hier geklaert, sondern per Handoff-Karte als Klaerfall an Klaerung & Freigaben (/klaerung-min, K-22-Welt) uebergeben — E-21-Workflow-Gesetz. Fertig = ~100 % oder bewusste WARN-Ausnahmen, dann ist der Weg zum Monatsabschluss frei. SCREEN-TYP-BEGRUENDUNG: uebersicht, nicht klaerung — die Klaer-ARBEIT (Fall-Typen, __klBulkAccept) lebt per E-21 im Klaerungs-Screen; abgleich2 zeigt die Monats-Lage, quittiert hochkonfidente Zuordnungen und reicht Reste weiter. Ersetzt /abgleich (core_shell secAbgleich) als Kanon-Fassung — Alt-Screen wird NICHT geflickt (E-21.1).",
      "data_sources": [
        "documents via restGet (User-JWT, RLS) — identische Query wie core_shell secAbgleich (core_shell.html:7273): Monatsgrenzen auf invoice_date, status not.in.(rejected,duplicate,archived), Limit 200 mit sichtbarer Kappungs-Warnung",
        "txn_master via restGet (User-JWT, RLS) — identische Query wie core_shell secAbgleich (core_shell.html:7276): Monatsgrenzen auf booking_date, Limit 200",
        "txn_master-Nachladen der via payment_txn_id/txn_id verknuepften Buchungen (Muster core_shell.html:7286-7292) — ohne sie sagt _isReconciled ehrlich 'unbekannt', nie stillschweigend gruen",
        "Shell-Modus: window.__shellAuth.restGet · Standalone: PostgREST mit USER-Access-Token aus der GETEILTEN Supabase-Session (storageKey 'tgv-core-shell-auth', Muster rka2.html:400-424 / dokumente2.html:765ff) — kein Re-Login, kein Frontend-Key auf dem Datenpfad",
        "Matcher-Vorschlaege: READ-ONLY im Client berechnet als SPIEGEL der Reconcile-Heuristik (Richtung hart · Betrag ±2 % · Zahlung -3/+30 Tage um invoice_date · Transfer-Ausschluss) — SSOT = n8n Reconcile Engine v0.6.2 (RECONCILE#01) bzw. deren Spiegel 08_OPS/chat_engine/executors_reconcile.py; dieser Screen schreibt NICHTS",
        "lokaler Demo-Datensatz NUR auf localhost/file:// mit ?demo=1 und sichtbarem Banner (Muster dokumente2)"
      ],
      "je_ids": [
        "JE-002",
        "JE-157",
        "JE-161",
        "JE-168",
        "JE-171"
      ],
      "rule_ids": [
        "R-02",
        "R-30",
        "R-91",
        "R-108",
        "R-116",
        "R-120",
        "R-129",
        "R-131",
        "R-143",
        "R-147",
        "R-V4-ICON"
      ],
      "component_ids": [
        "zone-anatomie",
        "zone-hero",
        "kpi-tile",
        "kpi-block",
        "scope-frame",
        "statusline",
        "composer",
        "composer-soon",
        "approval-card",
        "data-table",
        "file-actions",
        "source-link",
        "callout",
        "dock-panel",
        "doc-steckbrief",
        "txn-steckbrief",
        "partyRoleBadge",
        "icon-resolver"
      ],
      "k_ids": [
        "K-01",
        "K-02",
        "K-03",
        "K-04",
        "K-10",
        "K-11",
        "K-16",
        "K-21",
        "K-26",
        "K-27",
        "K-33",
        "K-36",
        "K-40",
        "K-43",
        "K-48",
        "K-58",
        "K-60",
        "K-63"
      ],
      "ux_ids": [
        "WB-01",
        "SC-01",
        "SUR-02",
        "PAN-01",
        "hero-01-kpi",
        "hero-collapse",
        "scope-01-hero-controls",
        "CARD-01",
        "BTN-01",
        "PIL-01",
        "SYS-01",
        "LNK-01",
        "MOT-01",
        "cui-02-composer"
      ],
      "fx_or_skills": [
        "TGVEngine.icon",
        "TGVEngine.loadIconSet",
        "TGVEngine.dataTableFull",
        "TGVEngine.fileMenu",
        "TGVEngine.driveHref",
        "TGVEngine.esc",
        "TGVEngine.assertConformance",
        "window.__shellAuth.restGet (Shell-Modus)",
        "supabase-js createClient mit geteiltem storageKey (Standalone, NUR supabase.auth)"
      ],
      "icon_slugs": [
        "reconcile",
        "transactions",
        "documents",
        "no-receipt",
        "check",
        "warning",
        "pending",
        "lock",
        "clarify",
        "search",
        "date",
        "entity",
        "close",
        "detail",
        "external",
        "chat-input",
        "dictate",
        "attachment",
        "system-speaker",
        "avatar-user",
        "ai-ask",
        "expand",
        "collapse",
        "month-close",
        "send-mail",
        "pin"
      ],
      "chart_specs": [],
      "workbench_zone": "result_panel",
      "module_package": "finanzen-zahlungs-abgleich",
      "menu_scope": "Finanzen / Abgleich / eingeloggt (E-20.3: Menue Finanzen->Abgleich; Zugaenge Heute-Alerts, K-05-Pipeline-Schritt, KAI-Karten)",
      "abnahme": [
        "local_url_200",
        "script_syntax_ok",
        "five_zone_anatomy_present_wb01",
        "zeitraum_default_ist_VORMONAT_nie_laufender_monat (E-20)",
        "hero_kpis_in_EINER_reihe_nie_gestapelt (Register-#250-Befund) und klick_verdrahtet_nie_tote_kachel",
        "zone3_is_sur02_workblock (Vorschlaege + Tabelle in weissen Feldern, nicht nackt)",
        "approve_karten_zeigen_konfidenz_pille_und_quelle_mit_drive_link (R-91 goldene Regel)",
        "approve_schreibt_NICHTS_solange_reconcile_naht_nicht_deployt — Knopf sichtbar als K-58 soon mit benannter Naht, nie stille Fake-Quittung",
        "reste_gehen_als_klaerfall_karte_an_klaerung_und_freigaben_nie_adhoc_geklaert (E-21)",
        "k10_systemzeile_ueber_GESAMTE_konversationsbreite (E-15.3)",
        "composer_breite_gleich_antwort_breite (E-10.2)",
        "table_is_k33_dataTableFull_beide_richtungen_umschaltbar",
        "exports_im_k40_menue_keine_freien_buttons",
        "icons_via_resolver_kein_rohes_emoji_wo_slug_existiert",
        "auth_ueber_geteilte_session_kein_re_login (rka2-Muster)",
        "empty_loading_error_zustaende_echt_kein_endlos_laden",
        "kein_horizontaler_overflow_375_und_1280_hell_und_dunkel",
        "demo_banner_when_local_demo",
        "kappung_und_fragmente_sichtbar_gemeldet_nie_stumm (secAbgleich-Semantik uebernommen)",
        "matcher_spiegel_gegen_sabotage_gemessen (08_OPS/check_abgleich2_matcher.py, 13 Faelle + --selftest beisst)"
      ],
      "next_guard": "GEBAUT: 08_OPS/check_abgleich2_matcher.py haelt den Matcher-Spiegel gegen die RECONCILE#01-Heuristik (13 Sabotage-Faelle, --selftest sabotiert den Richtungs-Guard und erwartet ROT). OFFEN: (1) abgleich2 in TGV_CONFORMANCE-/familie_guard-Laeufe aufnehmen; (2) Contract-DOM-Guard (dokumente2.next_guard) auch hier: deklarierte k_ids muessen als Kanon-Klassen im Markup auftauchen; (3) Approve-Naht — sobald der Reconcile-Schreibpfad (ApprovalCard jc_direct -> documents.payment_txn_id) deployt ist, K-58-soon gegen echten Skill-Call tauschen und die Abnahme-Zeile drehen."
    },
    {
      "id": "inbox2",
      "title": "Sammeltore & Kanaele — Eingang mit Live-Ingestion-Verfolgung (ONE-WORLD-Kanon)",
      "status": "canon_rebuild",
      "owner": "PIPELINE#01/DESIGN (INBOX2-Lane, Tower#30)",
      "file": "06_DASHBOARD/inbox2.html",
      "visible_url_local": "http://127.0.0.1:8787/inbox2.html",
      "screen_type": "inbox",
      "intent": "INTENTION (Gate A, E-28.1 / Register #253, JC 02.08.): EINE Kanon-Seite in core_shell fuer ALLE Einspiel-Wege — uebersichtlich als KARTEN je Kanal (wie die fruehere 'Sammeltore & Kanaele'-Darstellung: Mail-Kanal, Drag&Drop-Box, Drive, +Beleg hochladen). Drag&Drop leicht fuer den User, mit Moeglichkeit, Hinweise zu geben WO es hingehoert oder zu kommentieren — am besten direkt mit KAI (Composer-Bindung K-16; Klaerfaelle laufen in die K-22-Welt). KERN = LIVE-VERFOLGUNG der Ingestion: Wenn der User Dateien in die Box legt, sieht er die System-Etappen mit Progressbar je Datei — der User SIEHT, was mit seiner Datei passiert, bis 'Import fertig' / 'KAI ist fertig, dir alle Antworten zu geben'. ETAPPEN-AUFLAGE (E-28.2): Die angezeigten Etappen sind aus der ECHTEN Pipeline gemessen (Messprotokoll in data_sources), kein Erfinden — JCs Skizzen-Etappen ohne echtes Signal (Malware-Check, Berechtigungs-Pruefung, EU-RAW-Server) werden ehrlich als 'geplant' gekennzeichnet, nie als Fortschritt angezeigt. SCREEN-TYP-BEGRUENDUNG: inbox (Taxonomie screen-typen B-i Inbox; die Pipeline-Verfolgung ist Zone-3-Spezialisierung mit K-05, kein eigener Screen-Typ noetig). Ersetzt den core_shell-wip-Stub 'sammeltore' als Kanon-Fassung — kein Flick am Alt-Stub (E-21.1).",
      "data_sources": [
        "documents via restGet (User-JWT, RLS) — Felder id,source,date_received,processed_at,provider,recipient,entity,doc_type,target_stream,processing_state,skills_done,last_orchestrator_run_at,extracted_text_snippet(nur Existenz-Signal),snippet_extracted_at,drive_file_id,drive_file_name,final_path,amount,currency,invoice_date; Zeitachse = date_received (documents hat KEIN created_at, live verifiziert Mig 216:62); test_run-Ausschluss Pflicht (BR#04, Muster core_shell.html:7867); Kanal = source: 'email' (Mail A2) / 'gdrive'+defensiv 'drive' (WF B, Iter-33-Falle S8); source='gabriel_cockpit_ocr' (Projekt-Welt) bewusst NICHT in der Finanz-Inbox",
        "ETAPPEN-SIGNALE (E-28.2, gemessen 02.08. an PIPELINE_CASCADE.md/PIPELINE_B_DRIVE_DROP.md + Live-WF-JSONs TGV_skill_router_v074/TGV_WFA2_v0133): 1 Empfangen=Row existiert (source,date_received) · 2 Gelesen=extracted_text_snippet/snippet_extracted_at gesetzt (pdf-text-snippet/parse-docling/pdf-ocr-fallback) · 3 Analysiert=last_orchestrator_run_at ODER target_stream!=UNBEKANNT · 4 Skills+Extraktion=skills_done[] waechst (Namen sichtbar) · 5 Abgelegt=final_path gesetzt (store-file-to-drive; BANKING-Route hat KEIN store-file, CSV bleibt in INBOX — ehrlich 'entfaellt') · 6 Wissen=count(rag_chunks WHERE source_document_id=id) — Auto-RAG-Ingest ist LIVE (Router v0.7.3 Finalize: done+RECHNUNG/STEUER+markdown>=120)",
        "rag_chunks via restGet OPPORTUNISTISCH: RLS-Divergenz Mig 212 (Header STAGED vs _applied_snapshot '2026-07-07') — Screen versucht den Read; 401/403 -> Etappe 6 sagt ehrlich 'mit deiner Rolle nicht pruefbar', nie stumm gruen (reference_migrations_header_ist_kein_beweis)",
        "agent_events NICHT als Datenquelle: RLS super_admin-only (Mig 158; /api/skill/audit-log ebenso 403 fuer Nicht-Admins) — NAHT benannt: mandant-scoped Event-Read (agent_events.mandant_id Mig 218 liegt bereit) waere die Ausbaustufe fuer eine Event-genaue Verfolgung",
        "TRIGGER-WAHRHEIT sichtbar im Screen: Drive-WF KRNRcSLSUiVC8nTW pollt TGV-CORE/INBOX (Folder 1wH4pl4uguwvIYbZrMU0QlJtjVpaaL7bF) alle 24h ODER auf Kommando (Webhook tgv-wf-b-v2-trigger, kein Browser-Auth-Pfad -> 'auf Kommando via KAI/Tower'); Cascade-Auto-Schedule ist AUS (Quota-Schutz) -> Docs in 'inbox' warten ehrlich 'auf den naechsten Verarbeitungslauf'",
        "UPLOAD-SCHREIBPFAD ehrlich (Auflage 3): es existiert HEUTE KEIN Browser-Upload-Endpunkt fuer Finanz-Belege (einziger Browser->documents-Pfad = /api/skill/ocr-to-source, projekt-gescopet source='gabriel_cockpit_ocr', laeuft an Orchestrator/Router vorbei; core_shell-Composer-Anhang ist selbst K-58-gated, PLAT_07_ASYNC_INTAKE/BRIEF.md B1 'Backend fehlt') -> Dropzone + '+ Beleg hochladen' = K-58 soon mit benannter Naht (Finanz-Upload-Endpunkt nach ocr-to-source-Muster ohne project_id-Hardcode + Router-Trigger); heutige echte Wege werden verlinkt: Mail-Kanal + Drive TGV-CORE/INBOX (FES-BANK#01-Pfad, Juli-CSVs E-28.4)",
        "Shell-Modus: window.__shellAuth.restGet · Standalone: PostgREST mit USER-Access-Token aus der GETEILTEN Supabase-Session (storageKey 'tgv-core-shell-auth', Muster rka2.html:400-424 / abgleich2.html §S) — kein Re-Login, kein Frontend-Key auf dem Datenpfad",
        "lokaler Demo-Datensatz NUR auf localhost/file:// mit ?demo=1 und sichtbarem Banner (Muster abgleich2/dokumente2)"
      ],
      "je_ids": [
        "JE-002",
        "JE-157",
        "JE-161",
        "JE-168",
        "JE-171"
      ],
      "rule_ids": [
        "R-02",
        "R-30",
        "R-91",
        "R-108",
        "R-116",
        "R-120",
        "R-129",
        "R-131",
        "R-143",
        "R-147",
        "R-V4-ICON"
      ],
      "component_ids": [
        "zone-anatomie",
        "zone-hero",
        "kpi-tile",
        "kpi-block",
        "scope-frame",
        "stepper",
        "statusline",
        "composer",
        "composer-soon",
        "data-table",
        "file-actions",
        "source-link",
        "callout",
        "dock-panel",
        "doc-steckbrief",
        "collapsible-section",
        "icon-resolver"
      ],
      "k_ids": [
        "K-01",
        "K-02",
        "K-03",
        "K-04",
        "K-05",
        "K-10",
        "K-11",
        "K-16",
        "K-21",
        "K-22",
        "K-26",
        "K-27",
        "K-33",
        "K-40",
        "K-42",
        "K-44",
        "K-48",
        "K-56",
        "K-58"
      ],
      "ux_ids": [
        "WB-01",
        "SC-01",
        "SUR-02",
        "PAN-01",
        "hero-01-kpi",
        "hero-collapse",
        "scope-01-hero-controls",
        "CARD-01",
        "BTN-01",
        "PIL-01",
        "SYS-01",
        "LNK-01",
        "MOT-01",
        "cui-02-composer",
        "cui-03-bound-composer"
      ],
      "fx_or_skills": [
        "TGVEngine.icon",
        "TGVEngine.loadIconSet",
        "TGVEngine.dataTableFull",
        "TGVEngine.fileMenu",
        "TGVEngine.driveHref",
        "TGVEngine.numGlyph",
        "TGVEngine.esc",
        "TGVEngine.assertConformance",
        "TGVEngine.sweepRawEmojiIcons",
        "window.__shellAuth.restGet (Shell-Modus)",
        "supabase-js createClient mit geteiltem storageKey (Standalone, NUR supabase.auth)"
      ],
      "icon_slugs": [
        "channels",
        "inbox",
        "inbox-hero",
        "source-mail",
        "send-mail",
        "folder",
        "folder-open",
        "bank-import",
        "attach-plus",
        "attachment",
        "documents",
        "transactions",
        "dispatch",
        "routing",
        "live-pulse",
        "knowledge",
        "check",
        "warning",
        "pending",
        "lock",
        "clarify",
        "search",
        "date",
        "entity",
        "close",
        "detail",
        "external",
        "chat-input",
        "dictate",
        "system-speaker",
        "ai-ask",
        "eu-flag",
        "history"
      ],
      "chart_specs": [],
      "workbench_zone": "result_panel",
      "module_package": "eingang-sammeltore-kanaele",
      "menu_scope": "Eingang / Sammeltore & Kanaele / eingeloggt (ersetzt core_shell-Stub 'sammeltore'; Zugaenge: Heute-Quick-Chip /eingang/sammeltore, Kanal-Karten, KAI)",
      "abnahme": [
        "local_url_200",
        "script_syntax_ok",
        "five_zone_anatomy_present_wb01",
        "kanal_karten_zaehler_aus_echten_documents_daten_nie_erfunden (source=email/gdrive, date_received)",
        "etappen_nur_aus_echten_signalen_der_messliste (E-28.2; jede Etappe nennt ihr DB-Feld im Tooltip)",
        "skizzen_etappen_ohne_signal_sichtbar_als_geplant_nie_als_fortschritt (Malware/Rechte/EU-RAW)",
        "kein_fake_progress_polling_echter_felder_nie_zeitbasierte_animation",
        "warte_zustaende_ehrlich_benannt (inbox ohne Lauf -> 'wartet auf Verarbeitungslauf, Auto-Lauf aus'; Drive-Abholung 24h/auf-Kommando)",
        "upload_und_dropzone_K58_soon_mit_benannter_naht_keine_fake_quittung (kein Finanz-Upload-Endpunkt heute)",
        "dropzone_kai_kommentar_sichtbar_gebunden_aber_ehrlich_nicht_gesendet (cui-03-bound-composer, WARN-Systemzeile)",
        "rag_etappe_fail_honest_bei_401_403_nie_stumm_gruen",
        "drive_links_nur_aus_echter_drive_file_id_sonst_ehrlicher_zustand (E-16, R-91)",
        "needs_review_geht_als_klaerfall_an_klaerung_und_freigaben_nie_hier_geklaert (E-21, K-22-Welt)",
        "hero_kpis_in_EINER_reihe_und_klick_verdrahtet_nie_tote_kachel",
        "k10_systemzeile_ueber_GESAMTE_konversationsbreite (E-15.3)",
        "composer_breite_gleich_antwort_breite (E-10.2)",
        "table_is_k33_dataTableFull_mit_zeilen_detail_und_k40_menue",
        "pan01_slide_over_ueber_content_nie_split_und_nach_links_resizable (E-27)",
        "icons_via_resolver_kein_rohes_emoji_wo_slug_existiert",
        "auth_ueber_geteilte_session_kein_re_login (rka2-Muster)",
        "empty_loading_error_zustaende_echt_kein_endlos_laden",
        "test_run_docs_ausgeschlossen (BR#04)",
        "kein_horizontaler_overflow_375_und_1280_hell_und_dunkel",
        "demo_banner_when_local_demo"
      ],
      "next_guard": "OFFEN: (1) inbox2 in TGV_CONFORMANCE-/familie_guard-Laeufe aufnehmen; (2) Contract-DOM-Guard (dokumente2.next_guard) auch hier; (3) Upload-Naht — sobald der Finanz-Upload-Endpunkt (ocr-to-source-Muster ohne project_id-Hardcode + Router-Trigger, PLAT#07 B1) deployt ist, Dropzone-K-58-soon gegen echten multipart-Call tauschen, source-Wert des neuen Kanals in die Kanal-Karten aufnehmen und die Abnahme-Zeile drehen; (4) Event-genaue Verfolgung — sobald agent_events mandant-scoped lesbar ist (Mig-218-Naht), Etappen-Detail im Panel um den echten Event-Feed erweitern."
    },
    {
      "id": "projekt-view",
      "title": "Projekte — Typ-A-Projekt-View + Projekt-Navigation (ONE-WORLD-Kanon)",
      "status": "canon_build",
      "owner": "PROJEKT#01 (Tower#30, JC-GO E-32.1/E-32.2)",
      "file": "06_DASHBOARD/projekt2.html",
      "visible_url_local": "http://127.0.0.1:8787/projekt2.html",
      "screen_type": "uebersicht",
      "intent": "INTENTION (PROJEKT#01 Gate A + E-32.2, JC 02.08. / JC 28.07.): JC erreicht jedes Projekt in 1 Klick vom Hauptmenue unter seiner Entitaet (Variante A ANGENOMMEN, Dossier projekt_nav_arbitrage.html) — 'Projekte' als Hauptmenue-Gruppe je Entitaet, GLEICHER Baum wie die dokumente2-#1359-Anker (Entitaet ▸ Projekte, E-25 B1.12: EIN Ordnungsprinzip ueberall). Die Projekt-KARTE und der Projekt-VIEW-KOPF tragen oben links den PROJEKT-ICON-KANON (E-32.2 NEU): User kann ein Bild waehlen; DEFAULT = farbiges abgerundetes Quadrat mit deterministischer Farbe je Projekt-Code. Der Typ-A-Projekt-View ist EIN TEMPLATE fuer ALLE Typ-A-Projekte (kein WH39-Flick) mit dem Minimal-Projekt-Menue (JC 28.07.): Frage KAI · Klaerung · Finanzen · zurueck — bewusst KEINE Etappen bei WH39 (JC fuehrt mit KAI als Projektleitung). WH39 Verkauf (Code wh39-verkauf, Entitaet privat, Admin JC) = erster echter Fall; die Anlage ist STAGED (Mig 236) und wartet auf JC-Apply-GO — der Screen ist deshalb auch mit 0 angelegten Projekten ehrlich (Empty-State nennt den staged Seed, erfindet nie Karten). Ab ~5 Projekten je Entitaet zeigt die Gruppe 'alle anzeigen →' (Dossier-Auflage).",
      "data_sources": [
        "prf_projects via restGet (User-JWT, RLS) — Felder id,project_code,name,entity_key,description,status_code,lifecycle_status,active,tgv_tracked,start_date; RLS = Mig 212 §2.3 prf_projects_select_mandant_or_project (super_admin OR mandant_id=ANY(my_mandant_ids) OR id=ANY(get_project_ids_for_user)); 401/403 -> fail-honest Mandanten-Wand-Meldung, nie stumm leer (reference_migrations_header_ist_kein_beweis)",
        "user_project_roles via restGet OPPORTUNISTISCH (eigene Rolle je Projekt, 'deine Rolle: owner'); 401/403 -> Rollen-Zeile entfaellt ehrlich ('mit deiner Rolle nicht pruefbar'), nie stumm gruen",
        "WH39-WAHRHEIT: prf_projects-Zeile wh39-verkauf existiert erst NACH JC-Apply von 05_SCHEMA/236_mandant01_wh39_verkauf_project_seed.sql (STAGED, Vorab-Verify 28.07.: Code existiert NICHT) — der 0-Projekte-Empty-State benennt genau das",
        "TYP-A-KENNZEICHNUNG ehrlich: prf_projects traegt KEIN Typ-Feld (Mig-236-Header: 'Typ A' = PROJEKT#01s Welt-B-projects-Tabelle, separat) — der Screen erfindet keine Typ-Pille aus Luft; der View IST das Typ-A-Template, die Daten-Naht (Typ-Feld bzw. Welt-B-Join) ist benannt",
        "PROJEKT-BILD ehrlich: prf_projects hat KEINE Bild-/Icon-Spalte und es existiert KEIN Browser-Upload-Endpunkt (nachgeschlagen 02.08.: app.py ohne prf_projects-Write, einziger Browser-Upload = ocr-to-source projekt-gescopet) -> 'Bild waehlen' = K-58 soon mit benannter Naht (Spalte icon_file_id + Upload-Executor, JC-gated); Default-Icon (deterministische Farbe aus project_code) ist der gebaute Kanon",
        "Shell-Modus: window.__shellAuth.restGet · Standalone: PostgREST mit USER-Access-Token aus der GETEILTEN Supabase-Session (storageKey 'tgv-core-shell-auth', Muster rka2.html:400-424 / abgleich2.html §S) — kein Re-Login, kein Frontend-Key auf dem Datenpfad",
        "lokaler Demo-Datensatz NUR auf localhost/file:// mit ?demo=1 und sichtbarem Banner (Muster abgleich2/dokumente2; Demo enthaelt eine Entitaet mit >5 Projekten als 'alle anzeigen'-Messfall)"
      ],
      "je_ids": [
        "JE-002",
        "JE-161",
        "JE-168"
      ],
      "rule_ids": [
        "R-02",
        "R-91",
        "R-108",
        "R-116",
        "R-120",
        "R-129",
        "R-131",
        "R-143",
        "R-147",
        "R-V4-ICON"
      ],
      "component_ids": [
        "zone-anatomie",
        "zone-hero",
        "kpi-tile",
        "kpi-block",
        "nav-rail",
        "statusline",
        "composer",
        "composer-soon",
        "callout",
        "collapsible-section",
        "icon-resolver"
      ],
      "k_ids": [
        "K-01",
        "K-02",
        "K-03",
        "K-04",
        "K-06",
        "K-10",
        "K-16",
        "K-42",
        "K-43",
        "K-48",
        "K-58"
      ],
      "ux_ids": [
        "WB-01",
        "SC-01",
        "SUR-02",
        "hero-01-kpi",
        "hero-collapse",
        "CARD-01",
        "BTN-01",
        "PIL-01",
        "SYS-01",
        "LNK-01",
        "MOT-01",
        "cui-02-composer"
      ],
      "fx_or_skills": [
        "TGVEngine.icon",
        "TGVEngine.loadIconSet",
        "TGVEngine.esc",
        "TGVEngine.assertConformance",
        "TGVEngine.sweepRawEmojiIcons",
        "window.__shellAuth.restGet (Shell-Modus)",
        "supabase-js createClient mit geteiltem storageKey (Standalone, NUR supabase.auth)"
      ],
      "icon_slugs": [
        "projects",
        "folder",
        "entity",
        "ask-kai",
        "clarify",
        "finance-overview",
        "return-context",
        "check",
        "warning",
        "pending",
        "lock",
        "search",
        "close",
        "detail",
        "external",
        "chat-input",
        "dictate",
        "attachment",
        "system-speaker",
        "date",
        "edit",
        "attach-plus",
        "send-mail",
        "placeholder"
      ],
      "chart_specs": [],
      "workbench_zone": "result_panel",
      "module_package": "projekte-typ-a-view",
      "menu_scope": "Projekte / je Entitaet / eingeloggt (E-32.2 Variante A: Hauptmenue-Gruppe 'Projekte' in core_shell, Stufe-1-Kanon-Link-Muster; Zugaenge: Nav-Gruppe je Entitaet, Scope-Achse ③ nach WH39-Apply)",
      "abnahme": [
        "local_url_200",
        "script_syntax_ok",
        "five_zone_anatomy_present_wb01",
        "projekt_icon_kanon_deterministische_farbe_je_code_auf_karte_UND_viewkopf (E-32.2)",
        "bild_wahl_K58_soon_mit_benannter_naht_kein_fake_upload (keine Bild-Spalte, kein Endpunkt)",
        "null_projekte_ehrlich_empty_state_nennt_staged_seed_mig236_nie_erfundene_karten",
        "minimal_projekt_menue_frage_kai_klaerung_finanzen_zurueck_echte_ziele_nie_toter_button (JC 28.07.)",
        "keine_etappen_bei_wh39_view_ist_template_kein_wh39_flick (JC 28.07.)",
        "ab_5_projekten_je_entitaet_alle_anzeigen_toggle (E-32.2/Dossier)",
        "nav_gruppe_projekte_je_entitaet_in_core_shell_stufe1_muster (Variante A)",
        "typ_a_kennzeichnung_ehrlich_kein_erfundenes_typ_feld (Naht Welt-B benannt)",
        "hero_kpis_in_EINER_reihe_und_klick_verdrahtet_nie_tote_kachel",
        "k10_systemzeile_ueber_GESAMTE_konversationsbreite (E-15.3)",
        "composer_breite_gleich_antwort_breite (E-10.2)",
        "icons_via_resolver_kein_rohes_emoji_wo_slug_existiert",
        "auth_ueber_geteilte_session_kein_re_login (rka2-Muster)",
        "empty_loading_error_zustaende_echt_kein_endlos_laden",
        "kein_horizontaler_overflow_375_und_1280_hell_und_dunkel",
        "demo_banner_when_local_demo"
      ],
      "next_guard": "OFFEN: (1) projekt2 in TGV_CONFORMANCE-/familie_guard-Laeufe aufnehmen; (2) Contract-DOM-Guard (dokumente2.next_guard) auch hier; (3) Bild-Upload-Naht — sobald prf_projects eine Bild-Spalte + Upload-Executor (JC-gated) hat, K-58-soon gegen echten Call tauschen und die Abnahme-Zeile drehen; (4) Nav-Ausbaustufe — nach WH39-Apply (Mig 236) + Service-Deploy dynamische Projekt-Eintraege im Hauptmenue aus account-status.projects (③, #1286) statt statischer Entitaets-Tueren; (5) Projekt-Scope-Handoff — Frage-KAI/Klaerung/Finanzen aus dem View heraus projekt-gescopet oeffnen, sobald die ③-Scope-Achse den Deep-Link traegt; (6) Typ-Feld-Naht — Typ-A-Pille aus echter Daten-Quelle (Welt-B projects bzw. neue Spalte), nie aus Annahme."
    },
    {
      "id": "buchhalter-versand",
      "title": "Buchhalter-Versand (Paket-Vorschau + Pre-Send-Gate, GOLD-Vorlage)",
      "status": "canon_rebuild",
      "owner": "BUCHHALTUNG#01",
      "file": "06_DASHBOARD/versand2.html",
      "visible_url_local": "http://127.0.0.1:8787/versand2.html",
      "screen_type": "dossier",
      "intent": "INTENTION (E-32.1 GO 02.08. / Register #241 / KONZEPT_BUCHHALTER_PRESEND_VERIFIKATION): JC prueft je Entitaet x Monat EIN Buchhalter-Paket komplett, BEVOR irgendetwas rausgeht - Belege, Bank-Abgleich-Status, Anschreiben, Pre-Send-Checks C1-C10 (rot=blockt EHRLICH sichtbar, kein Falsch-Gruen) - und loest dann den Versand als Trockenlauf-Quittung aus. Vorlage = JCs abgenommene GOLD-Vorschau des alten tgv-dashboard (Memory project_monatsabschluss_zieltabelle_jc: Empfaenger+CC+Betreff, Doc-Type-Filter-Pills, ZWEI Spalten IM PAKET <-> FEHLEND mit Vorjahres-Luecken-Zaehler, editierbarer Mail-Body, Fuss-Warnzeile, Abbrechen/Bestaetigen; geerntet aus index.html:3445-3503+10499-10646 - RECHERCHIERT+GEERNTET, nicht neu erfunden). SCREEN-TYP-BEGRUENDUNG: dossier - der Screen zeigt EIN Paket (Entitaet x Monat) in der Tiefe, nicht eine Liste vieler Objekte; die Paket-Wahl ist der Dossier-Einstieg. HARTES GESETZ (secBuchhalter-Kanon): MAIL PRO ENTITAET GETRENNT - c3/c4/privat je EIGENES Paket, nie gemischt; ohne Entitaets-Wahl gibt es KEIN Paket. NAHT ZUR JUNI-KETTE (E-26.4): der Screen ist das Sichtfenster fuer JCs 3x Abschluss (C3->C4->privat) nach dem ORCH-Backfill - Reihenfolge als Callout benannt, KEIN Versand vor Tower-GO. ECHTVERSAND bleibt JC-gated: der Client kennt NUR mode=self + dry_run=true (Quittung, nichts gesendet); der Echtversand-Knopf ist K-58 ehrlich-gesperrt mit benannter Naht (Owner-Gate + confirm + accountant_email leben SERVERSEITIG in /api/skill/accountant-send, Register #241). Ersetzt den Versand-Platzhalter in core_shell secBuchhalter (:7688, zwei disabled-Buttons) als Kanon-Fassung - Alt-Screen wird NICHT geflickt (E-21.1).",
      "data_sources": [
        "Pre-Send-Report via skillFetch POST /api/skill/presend-report {entity,year,month} (User-JWT) - der Server rendert die EINE Wahrheit aus 08_OPS/fes_ap2/presend_checks.py (C1-C10, totals, belege[], ready_to_send) und scopet fail-closed gegen die Mitgliedschaft (_assert_scope_allowed, Schnitt VOR der Rechnung); der Screen rechnet NICHTS nach - zwei Rechenwege waeren zwei Wahrheiten (NUXIN-N4). Muster core_shell.html:7658ff",
        "belege[] im Report = die WF-E-Load-Documents-Auswahl EXAKT (load_package spiegelt sie) - die IM-PAKET-Spalte zeigt genau, was versendet wuerde, nicht eine Client-Naeherung",
        "drive_probe aus dem Report ist PFLICHT-Anzeige: ohne Service-Account kann C1 tote Drive-Referenzen nicht sehen (gelb statt rot) - der Screen sagt das sichtbar, sonst falsch-gruen (app.py-Docstring ep_presend_report)",
        "Versand via skillFetch POST /api/skill/accountant-send {entity,year,month,mode:'self',dry_run:true} - DRY-RUN default, Antwort ist die Quittung (would_send_to, belege); ein gesperrtes Paket liefert success:false + Blocking-Report, der Screen zeigt ihn. Der Client sendet NIE mode:'accountant' und NIE dry_run:false - der Echtversand-Flip ist ein separates JC-Gate am Server (Register #241 Gate 3)",
        "FEHLEND-Spalte (Vorjahres-Luecken, GOLD): restGet v_monthly_closing_prep_public?year=&month=&delta=gt.0 (User-JWT, RLS) - TOLERANT: fehlt die View oder liefert sie nichts, sagt die Spalte 'Luecken-Analyse nicht verfuegbar' ehrlich statt leer-gruen; as_of wird angezeigt (kein stiller Alt-Stand). Kein RPC-Refresh vom Client (kein Write-Pfad)",
        "Shell-Modus: window.__shellAuth.skillFetch/restGet - Standalone: PostgREST/fetch mit USER-Access-Token aus der GETEILTEN Supabase-Session (storageKey 'tgv-core-shell-auth', Muster rka2.html:400-424 / fragekai2.html:1738-1752) - kein Re-Login, kein Frontend-Key auf dem Datenpfad",
        "lokaler Demo-Datensatz NUR auf localhost/file:// mit ?demo=1 und sichtbarem Banner (Muster dokumente2/abgleich2)"
      ],
      "je_ids": [
        "JE-060",
        "JE-168",
        "JE-171"
      ],
      "rule_ids": [
        "R-02",
        "R-30",
        "R-91",
        "R-108",
        "R-116",
        "R-120",
        "R-129",
        "R-131",
        "R-143",
        "R-147",
        "R-V4-ICON"
      ],
      "component_ids": [
        "zone-anatomie",
        "zone-hero",
        "kpi-tile",
        "kpi-block",
        "scope-frame",
        "statusline",
        "composer",
        "composer-soon",
        "data-table",
        "file-actions",
        "source-link",
        "callout",
        "dock-panel",
        "doc-steckbrief",
        "partyRoleBadge",
        "icon-resolver"
      ],
      "k_ids": [
        "K-01",
        "K-02",
        "K-03",
        "K-04",
        "K-10",
        "K-11",
        "K-16",
        "K-26",
        "K-27",
        "K-33",
        "K-40",
        "K-48",
        "K-58",
        "K-63"
      ],
      "ux_ids": [
        "WB-01",
        "SC-01",
        "SUR-02",
        "PAN-01",
        "hero-01-kpi",
        "hero-collapse",
        "scope-01-hero-controls",
        "CARD-01",
        "BTN-01",
        "PIL-01",
        "SYS-01",
        "LNK-01",
        "MOT-01",
        "cui-02-composer"
      ],
      "fx_or_skills": [
        "TGVEngine.icon",
        "TGVEngine.loadIconSet",
        "TGVEngine.dataTableFull",
        "TGVEngine.fileMenu",
        "TGVEngine.driveHref",
        "TGVEngine.esc",
        "TGVEngine.assertConformance",
        "window.__shellAuth.skillFetch + restGet (Shell-Modus)",
        "supabase-js createClient mit geteiltem storageKey (Standalone, NUR supabase.auth)",
        "POST /api/skill/presend-report (Server scopet, C1-C10-Wahrheit)",
        "POST /api/skill/accountant-send (dry_run default; Client nur mode self)"
      ],
      "icon_slugs": [
        "dispatch",
        "send-mail",
        "documents",
        "transactions",
        "no-receipt",
        "check",
        "warning",
        "pending",
        "lock",
        "clarify",
        "search",
        "date",
        "entity",
        "close",
        "detail",
        "external",
        "chat-input",
        "dictate",
        "attachment",
        "system-speaker",
        "expand",
        "collapse",
        "month-close",
        "pin"
      ],
      "chart_specs": [],
      "workbench_zone": "result_panel",
      "module_package": "finanzen-buchhalter-versand",
      "menu_scope": "Finanzen / Buchhalter-Paket / eingeloggt (Zugaenge: Monatsabschluss-CTA 'dann versenden', core_shell-Karte buchhalter_paket, KAI-Karten; Entitaets-Wahl ist Pflicht-Einstieg - kein Paket bei Scope 'alle')",
      "abnahme": [
        "local_url_200",
        "script_syntax_ok",
        "five_zone_anatomy_present_wb01",
        "paket_immer_pro_entitaet_nie_gemischt (secBuchhalter-Gesetz; ohne Entitaets-Wahl Dossier-Einstieg statt Daten)",
        "checks_c1_c10_aus_presend_report_gerendert_NIE_nachgerechnet (eine Wahrheit, NUXIN-N4)",
        "rote_checks_blocken_sichtbar_mit_items_und_drive_links (R-91 goldene Regel: jede Beleg-ID mit Drive-Link)",
        "drive_probe_unavailable_wird_sichtbar_gewarnt_nie_falsch_gruen (app.py ep_presend_report Pflicht-Anzeige)",
        "gold_zwei_spalten_im_paket_und_fehlend_nebeneinander (GOLD-Vorlage; FEHLEND tolerant mit as_of, ehrlich wenn View fehlt)",
        "doc_type_filter_pills_wirken_auf_im_paket_liste (GOLD-Vorlage)",
        "mail_vorschau_empfaenger_betreff_body_editierbar_mit_hinweis_wf_e_baut_die_mail (GOLD-Vorlage; keine vorgetaeuschte 1:1-Mail)",
        "versand_knopf_dry_run_liefert_echte_quittung_als_systemzeile (accountant-send mode self dry_run true; gesperrtes Paket zeigt Blocking-Report)",
        "kein_mode_accountant_und_kein_dry_run_false_im_client_code (Echtversand-Flip separat JC - Guard prueft statisch)",
        "echtversand_knopf_ist_k58_soon_mit_benannter_naht_nie_toter_button",
        "e26_4_reihenfolge_c3_c4_privat_als_callout_benannt_kein_versand_vor_tower_go",
        "naht_404_503_wird_ehrlich_gemeldet_mit_retry (Nahte evtl. noch nicht deployt - kein Endlos-Laden)",
        "k10_systemzeile_ueber_GESAMTE_konversationsbreite (E-15.3)",
        "composer_breite_gleich_antwort_breite (E-10.2)",
        "belege_tabelle_is_k33_dataTableFull_mit_detail_pan01",
        "exports_im_k40_menue_keine_freien_buttons",
        "icons_via_resolver_kein_rohes_emoji_wo_slug_existiert",
        "auth_ueber_geteilte_session_kein_re_login (rka2-Muster)",
        "empty_loading_error_zustaende_echt_kein_endlos_laden",
        "kein_horizontaler_overflow_375_und_1280_hell_und_dunkel",
        "demo_banner_when_local_demo"
      ],
      "next_guard": "GEBAUT: 07_TESTS/buchhaltung01/test_versand2_send_gate.py - statischer Send-Gate-Guard: (G1) jeder accountant-send-Aufruf im Screen traegt dry_run:true und mode:'self', kein 'accountant'-Mode und kein dry_run:false im Client-Code; (G2) deklarierte k_ids tauchen als Kanon-Klassen im Markup auf; (G3) der Screen rechnet keine eigene C-Check-Logik (kein 'blocking'-Nachbau); --selftest sabotiert G1 und erwartet ROT. OFFEN: (1) versand2 in TGV_CONFORMANCE-/familie_guard-Laeufe aufnehmen; (2) nach JC-Gate-Flip (Echtversand): K-58-soon gegen confirm-Dialog + mode accountant tauschen und Abnahme-Zeile drehen; (3) presend-report/accountant-send-Deploy-Smoke auf Staging (Naehte aus Register #241 sind Tower-Review+Deploy offen)."
    },
    {
      "id": "auswertung-banking",
      "title": "Auswertungen: Einnahmen/Ausgaben-Drilldown nach Banking (Ernte v11)",
      "status": "built_pending_qa",
      "owner": "DATAVIZ#01",
      "file": "06_DASHBOARD/core_shell.html",
      "visible_url_local": "http://127.0.0.1:8787/core_shell.html#/auswertungen",
      "screen_type": "uebersicht",
      "intent": "INTENTION (E-32.1b / Register #261, JC woertlich: 'Drilldown der Einnahmen/Ausgaben nach Banking - haben wir schon KOMPLETT gehabt bei tgv-dashboard'): JC sieht je Entitaet und Monat in Sekunden, wo Geld reinkam und rausging, und kommt per Klick bis zum einzelnen Beleg. ERNTE aus v11 (tgv-dashboard index.html, Finanzen-Seite): Cashflow-Chart Einnahmen(gruen)/Ausgaben(rot) je Monat + Klick->Buchungsliste + Beleg-Link; Aggregations-KANON portiert (v11 Iter 66 A1/C3): Vorzeichen aus txn_master.amount (SSOT), Einnahmen=SUM(amount>0), Ausgaben=SUM(|amount<0|), NIE aus direction. Drill-Pfad (ECH-10): Chart-Monat anklicken -> K-33-Tabelle der Buchungen des Monats (Default = VORMONAT, E-20) -> Zeile oeffnet Buchungs-Panel (Reuse openTxnPanel) -> Beleg-Link je Zeile NUR aus echter documents.drive_file_id (E-16; ohne drive_file_id ehrlich 'ohne Original', nie interner-ID-Link). Screen lebt als native core_shell-Sektion secAuswertungen (Typ-E-Traeger PR #1279: K-16 Composer-Dock).",
      "data_sources": [
        "txn_master via window.__shellAuth.restGet (User-JWT, RLS) - Uebersicht: 12 Monate, select=booking_date,entity,amount, limit 3000 mit sichtbarer Kappungs-Note (A9); Einzel-Scope zusaetzlich entity=eq. via _entQ (default-deny)",
        "txn_master via restGet - Drill je Monat: volle Zeilen (Kategorie L1/L2, Gegenpartei, Zweck, review_status, document_id), booking_date=gte/lt Monatsgrenzen, limit 1000 mit Kappungs-Note",
        "documents via restGet - NUR select=id,drive_file_id fuer die verknuepften document_ids (E-16-Beleg-Link); Nachlade-Fehler => ehrlicher Zustand 'Beleg-Daten gerade nicht ladbar', nie Fantasie-Link",
        "A2+ Scope VOR Aggregation: beide Charts und alle Summen rechnen NUR ueber die RLS-gefilterten Zeilen; A8: JEDER Folge-Abruf (Drill) ueber ctx.restGet, nie skillFetch; A10: scope_whitelist am Spec (Entitaets-Serien = autorisierte Scopes; Einnahmen/Ausgaben = feste neutrale Serien-Namen)"
      ],
      "je_ids": [
        "JE-156",
        "JE-166",
        "JE-168",
        "JE-171",
        "JE-172"
      ],
      "rule_ids": [
        "R-02",
        "R-30",
        "R-91",
        "R-V4-ICON"
      ],
      "component_ids": [
        "zone-hero",
        "scope-frame",
        "data-table",
        "composer",
        "callout",
        "source-link",
        "txn-steckbrief",
        "dock-panel",
        "icon-resolver"
      ],
      "k_ids": [
        "K-01",
        "K-02",
        "K-11",
        "K-16",
        "K-33"
      ],
      "ux_ids": [
        "WB-01",
        "SUR-02",
        "hero-01-kpi",
        "hero-collapse",
        "scope-01-hero-controls",
        "ECH-01",
        "ECH-03",
        "ECH-10",
        "LNK-01",
        "MOT-01",
        "cui-02-composer"
      ],
      "fx_or_skills": [
        "TGVRenderers.chart (EINZIGER ECharts-Zugang; A11 on_select = Drill-Naht, Renderer meldet nur die Auswahl)",
        "window.__shellAuth.restGet (User-JWT->RLS, alle drei Abrufe)",
        "fxRender('data-table') / wireDataTable (K-33-Kanon-Tabelle, foot=Summenzeile der gefilterten Menge)",
        "openTxnPanel (Reuse secBuchungen: Buchungs-Detail + Beleg-Verknuepfung -> openDocPanel)",
        "fxRender('composer') + wireComposerCore (K-16-Dock aus PR #1279, context:'auswertungen')",
        "TGVEngine.icon / safeIco (Icon-Kanon)"
      ],
      "icon_slugs": [
        "analytics",
        "transactions",
        "external"
      ],
      "chart_specs": [
        {
          "id": "aw-cashflow-monat",
          "renderer": "TGVRenderers.chart",
          "type": "bar",
          "series": "Einnahmen (role confirm) / Ausgaben (role danger) - feste neutrale Namen, scope_whitelist gesetzt",
          "x": "month (YYYY-MM, 12 Monate)",
          "data_policy": "caller_supplies_rls_authorized_rows",
          "drill": "on_select(month) -> K-33-Buchungstabelle via restGet (A8/A11), Default-Monat = Vormonat (E-20)"
        },
        {
          "id": "aw-salden-entitaet",
          "renderer": "TGVRenderers.chart",
          "type": "line",
          "series": "eine Serie je RLS-praesenter Entitaet (roles c3/c4/privat); bei genau einer Entitaet type area",
          "x": "month (YYYY-MM, 12 Monate)",
          "data_policy": "caller_supplies_rls_authorized_rows",
          "drill": "on_select(month) -> dieselbe K-33-Buchungstabelle"
        }
      ],
      "workbench_zone": "result_panel",
      "module_package": "finanzen-auswertungen",
      "menu_scope": "Hauptmenue /auswertungen / eingeloggt (ohne Login: ehrliche Anmelde-Karten, keine Demo-Zahlen)",
      "abnahme": [
        "local_url_200",
        "guard: python 08_OPS/check_screen_factory_contracts.py GRUEN",
        "guard: python 06_DASHBOARD/konzepte/familie_guard.py GRUEN",
        "smoke: hell/dunkel/375px - Charts rendern ueber Token (A7), Tabelle scrollt in der Karte",
        "drill: Klick auf Monat fuellt die Buchungstabelle (Klick-Versprechen verdrahtet)",
        "E-16: Beleg-Link nur bei echter drive_file_id; ohne -> 'ohne Original'-Zustand",
        "qa@: Gegenbeweis Scope - eingeschraenkter Nutzer sieht KEINE fremden Summen/Serien (A2+/A10, Muster #166)"
      ],
      "next_guard": "qa@-Lauf (JC 13:00-Rhythmus, E-32.5) + Gate B N4 Live-Gegenbeweis nach Deploy; CI-Job deploy-dataviz-assets nach 9.8. nachtragen (Memory project_dataviz01_lane)"
    },
    {
      "id": "chat-historie",
      "title": "Verlauf — Chat-Historie (Konversations-Verlauf, ONE-WORLD-Kanon)",
      "status": "canon_rebuild",
      "owner": "KONVERSATION#01 (Tower#30, E-32.1a / Register #260)",
      "file": "06_DASHBOARD/verlauf2.html",
      "visible_url_local": "http://127.0.0.1:8787/verlauf2.html",
      "screen_type": "uebersicht",
      "intent": "INTENTION (Gate A: GATE_A_CHAT_HISTORIE.md JC-validiert 14.07. + KONZEPT_KONVERSATION_UNIVERSAL.md §5 JC-GO 28.07. + E-32.1a 02.08. 'ich warte auf CHAT-Historie'): Der Verlauf ist das Frontend des Zwilling-Gedaechtnisses und das Archiv-Ziel jedes Resets — EINE Liste ALLER eigenen Konversationen (K-33), mit Titel, Kontext-Chip (Instanz + Scope), Art (chat/worklist/case), Status (offen/geloest) und Zuletzt-aktiv-Datum; Suche IN der Komponente (K-33-Kanon; Server-Volltextsuche ueber Nachrichten-Inhalte ist ein spaeteres API-Verb, ehrlich benannt). Klick auf eine Zeile = WIEDEREINSTIEG: {op:get} laedt die Turns, KAIChat re-rendert aus envelope_json OHNE LLM-Re-Run (kein Neubau des Chat-Renderings — Reuse kai_renderer.js/CUI), eine K-10-Zustandszeile markiert 'Ab hier: fortgesetzt', der Composer (K-16) setzt den Thread via thread_id fort (ask()-Muster fragekai2). ERNTE altes tgv-dashboard (Recherche 02.08., KONVERSATION01_VERLAUF_RECHERCHE_2026-08-02.md): v11 hatte KEINEN Verlauf-Screen (chatHistory session-only, index.html:12055) — was komplett existierte, war die persistente Schicht agent_conversations/agent_events (Mig 015); deren Erbe ist heute chat_sessions/chat_messages (Mig 203/205) — der Screen macht sie erstmals sichtbar. SCREEN-TYP-BEGRUENDUNG: uebersicht/Liste (SSOT §5: 'Typ B Liste — der Verlauf ist eine Listen-Komposition, kein Sonderbau'). SCOPE-HAERTE (Default-Deny): API ist JWT-only + user-eigen (RLS Mig 203:52 + Ownership-Check app.py:1044-1050); der Screen setzt KEINEN Scope und filtert nichts selbst — qa@ sieht NUR eigene Threads, niemals JCs (Gegenbeweis-Pflicht im qa@-Gate). JC-Entscheide: alle 8 KONVERSATION#01-Entscheide am 26.07. vertragt (SSOT §3), Entscheid 7 = 'Verlauf bauen, PRIO 1' — kein offener Entscheid blockiert.",
      "data_sources": [
        "POST /api/skill/chat-threads {op:list|get|resolve} — JWT-only, user-eigene Threads (08_OPS/tgv-skills-service/app.py:1031-1069; Store: 08_OPS/chat_engine/thread_store.py list_threads/get_thread)",
        "POST /api/skill/core-chat {question, thread_id} — Fortsetzen im Thread (Turn-Persistenz serverseitig, app.py:961-1015)",
        "chat_sessions/chat_messages (Mig 203 RLS default-deny user-eigen; Mig 205 Baum parent_session_id/session_kind; envelope_json = Re-Render-Quelle)",
        "06_DASHBOARD/kai_renderer.js + kai_chat.css (Chat-SSOT, inline via build_kai_inline.py — verlauf2 ist dort als Surface eingetragen)",
        "06_DASHBOARD/engine.js (TGVEngine.dataTableFull K-33, icon-Resolver) + tokens.css/components.css/foundation.css"
      ],
      "je_ids": [
        "JE-002",
        "JE-032",
        "JE-070",
        "JE-076",
        "JE-150",
        "JE-161",
        "JE-167",
        "JE-168",
        "JE-169",
        "JE-170"
      ],
      "je_begruendung": "WARUM GENAU DIESE (und warum die naheliegenden NICHT — ein Vertrag, der alles anhaekt, bindet nichts): JE-032 Screen-Skelett = die Anatomie Z2-Hero fest -> Thread haengt UNTEN an -> Z5-Composer fest, nichts wird ueberschrieben (verlauf2.html:501/527/533) · JE-070 Senden = runde Paper-Plane + Auto-Grow + 'Reset ARCHIVIERT' — der Verlauf ist das Archiv-Ziel, auf das dieser Entscheid zeigt (TGVEngine.SEND_SVG) · JE-076 'alter Thread bleibt Historie' + Verlassen ueber leave-context statt Loeschen (verlauf2.html:525) = die Daseinsberechtigung des Screens · JE-167 Systemmeldung traegt Sysglyphe, keine KAI-Bubble — die 'Ab hier: fortgesetzt'-Zustandszeile IST eine systemLine (verlauf2.html:426) · JE-168 Z3-Arbeitsblock als EIN weiss/grau gerahmtes Feld (verlauf2.html:464) · JE-169 lange KAI-Antwort behaelt ihre Formatstruktur — Pflicht beim Re-Render aus envelope_json · JE-170 Composer-Breite = Antwort-Breite (E-10.2, hier ueber das #281-Netz gebunden) · JE-161 EU-Kennzeichnung als Sternenkreis-SYMBOL, nie Buchstaben (verlauf2.html:554/1737) · JE-150 Archivierungs-Lifecycle — der Grund, warum 'archivieren' hier EHRLICH-soon ist statt fake-gebaut · JE-002 Katalog-Abnahme-Baseline wie bei allen Geschwister-Screens. ⛔ BEWUSST NICHT beansprucht: JE-171 (Detailpanel — im Screen NICHT gebaut, s. next_guard (5)) · JE-157 (Geheimhaltungs-Woerter — der Screen fuehrt KEINE Vertraulichkeits-Achse) · JE-008 (Multi-User-'Ab hier' — strategisch/offen, hier nicht umgesetzt) · JE-038 (MINIMAL-Hero ohne KPI gilt dem #KAI-Chat-Modus; verlauf2 ist ein Uebersichts-Hero MIT KPIs).",
      "rule_ids": [
        "R-02",
        "R-30",
        "R-34",
        "R-73",
        "R-88",
        "R-90",
        "R-91",
        "R-96",
        "R-130",
        "R-131",
        "R-147"
      ],
      "component_ids": [
        "zone-anatomie",
        "zone-hero",
        "data-table",
        "speaker-bubble",
        "kai-ava",
        "statusline",
        "thread-context",
        "composer",
        "chip",
        "type-scale",
        "ds-clamp"
      ],
      "k_ids": [
        "K-01",
        "K-02",
        "K-03",
        "K-08",
        "K-09",
        "K-10",
        "K-13",
        "K-16",
        "K-33",
        "K-45",
        "K-56",
        "K-58",
        "K-59"
      ],
      "ux_ids": [
        "WB-01",
        "cui-01-speaker-bubble",
        "cui-02-composer",
        "cui-04-content-frame",
        "TXT-01",
        "SYS-01",
        "LNK-01",
        "SUR-01",
        "hero-01-kpi"
      ],
      "fx_or_skills": [
        "TGVEngine.dataTableFull",
        "TGVEngine.icon / loadIconSet",
        "TGVEngine.SEND_SVG",
        "KAIChat.renderEnvelope",
        "KAIChat.userMsg",
        "KAIChat.systemLine",
        "KAIChat.thinking",
        "KAIChat.makeActions",
        "chat-threads (skillFetch)",
        "core-chat (skillFetch)",
        "build_kai_inline.py (Inline-Sync-Pflicht)"
      ],
      "icon_slugs": ["history", "leave-context", "context-thread", "attach-plus", "eu-flag", "pin", "edit", "move"],
      "chart_specs": [],
      "workbench_zone": "context",
      "module_package": "kai-antwort-kette",
      "menu_scope": "Verlauf / alle Mandanten / eingeloggt (nur eigene Konversationen)",
      "abnahme": [
        "local_url_200",
        "script_syntax_ok",
        "five_zone_anatomy_present_wb01 (Z2 Hero · Z3 K-33-Liste · Z4 Wiedereinstieg-Konversation · Z5 Composer)",
        "liste_ist_k33_dataTableFull_mit_suche_in_der_komponente_kein_screen_eigenes_suchfeld",
        "zeilen_klick_oeffnet_thread_re_render_aus_envelope_json_ohne_llm_re_run",
        "wiedereinstieg_traegt_k10_zustandszeile_ab_hier_fortgesetzt_mit_titel_und_scope",
        "composer_setzt_thread_id_fort_ask_muster_fragekai2_antwort_via_renderEnvelope",
        "composer_breite_gleich_antwort_breite (E-10.2)",
        "scope_haerte_kein_frontend_filter_api_jwt_only_user_eigen (Default-Deny; Screen setzt keinen Scope)",
        "qa_gegenbeweis_qa_sieht_NUR_eigene_threads_niemals_jcs (Pflicht-Prüfschritt im qa@-Gate, dokumentiert im PR)",
        "archivieren_umbenennen_anpinnen_verschieben_K58_soon_mit_benannter_naht_keine_fake_wirkung (API-Verben archive/rename fehlen serverseitig)",
        "geloeste_faelle_sichtbar_als_geloest_resolved_at_outcome_nie_versteckt",
        "empty_loading_error_zustaende_echt_kein_endlos_laden (leerer Verlauf = ehrliche Einladung, kein Spinner)",
        "auth_ueber_geteilte_session_kein_re_login (rka2/dokumente2-Muster, storageKey tgv-core-shell-auth)",
        "icons_via_resolver_kein_rohes_emoji_wo_slug_existiert",
        "kein_horizontaler_overflow_375_und_1280_hell_und_dunkel",
        "kai_inline_sync_ok (python 06_DASHBOARD/build_kai_inline.py --check exit 0)"
      ],
      "next_guard": "⭐ 03.08. GEMESSEN (Tower#31-Aufnahme, nicht behauptet): verlauf2 steht seit heute in `08_OPS/check_komponenten_konformitaet.py` SCREENS und ist auf allen 6 Achsen (D/G/C/K/S/W) sauber — Ratchet unveraendert 0. DOM-Beweis je Breite mit NEUEM Seiten-Load (nicht per Resize — der headless-Viewport-Override feuert kein `resize`, dadurch entsteht sonst Falsch-ROT): 1240/1280 hell+dunkel/375 → Composer-Kante == Antwort-Kante (dL=dR=0) an JEDER Scrollposition, Fuss klebt mit 0px ueber die GANZE Strecke inkl. Ende (B5-Punkt), Feld-Cap folgt 40% der Fensterhoehe, kein Quer-Ueberlauf bei 375 (Tabelle scrollt in `.ds-table-wrap`). ⚠️ NICHT ANWENDBAR statt gruen: PAN-01-Blockkollaps und Bulk-Regel — dieser Screen hat KEIN Detailpanel und keine Bulkbar (s. (5)); gestrichelt-Semantik ist trivial-konform (0 gestrichelte Kanten, 0 `act-prompt`). ⭐ 03.08. DATEN LIVE GEMESSEN: Mig 226 ist NICHT appliziert (keine Zeile in `tgv_migrations`; 203/205 seit 2026-06-28 live) — `chat_messages` hat 6 Spalten, `turn_id`/`llm_model`/`latency_ms` FEHLEN. Das trifft den Screen NICHT: er liest keine davon (nur `envelope_json`/`content_text`/`resolved_at`/`last_at`), und `thread_store.py:171 has_turn_columns()` probt zur Laufzeit und laesst die Felder weg, statt den INSERT zu brechen. OFFEN: (1) verlauf2 in TGV_CONFORMANCE-/familie_guard-Laeufe aufnehmen (der Komponenten-Guard hat ihn seit 03.08., die anderen beiden noch nicht); (2) Server-API-Verben archive/rename/search (Achse 2 🔴) — 03.08. PRAEZISIERT: die Spalte `chat_sessions.archived` (boolean) EXISTIERT live, es fehlt allein das VERB (`ChatThreadsBody.op` kennt nur list|get|resolve, app.py:1070). Die Naht ist also kleiner als gedacht: ein op, keine Migration. Sobald gebaut, K-58-soon-Aktionen gegen echte Calls tauschen und Abnahme-Zeile drehen; (3) Reset-RAM-Fix in core_shell.html (Reset archiviert nach DB statt window.__kaiArchive) = eigener kleiner Folge-PR, andere Flaeche; (4) ERLEDIGT 03.08. (Tower#31, VERLAUF-SHELL-Lane): Menuepunkt Start > 'Verlauf ² (Kanon)' in core_shell.html:2267 — GLOBAL im NAV_GROUPS-Literal (Zeile 2267 steht VOR `if(IA_MIN){` Zeile 4338), also strukturell NICHT die min-only-Falle aus Guard R3 / Register #242. Muster = fragekai2/dokumente2/abgleich2/rka2/projekt2 (statische Tuer in den Vertrags-Screen; KEINE zweite SPA-Route, kein SECTIONS-Zweitbau — der waere R-V4-19). Serve-Layer mitgezogen, sonst waere die Tuer ein 404: nginx `location = /verlauf2.html` (08_OPS/tgv-skills-service/nginx-tgv-skills.conf) + verlauf2 in der UI-Liste 08_OPS/tgv_deploy.sh:51. DOM-GEMESSEN je Breite mit NEUEM Load (nie per Resize): 1280 Vollansicht = Eintrag 197x48 sichtbar direkt unter 'KAI fragen ² (Kanon)' in Gruppe start, Icon-Slug `history` als echtes SVG (kein Emoji-Fallback), Klick → /verlauf2.html (h1 'Verlauf'); 375 Drawer = Eintrag 208x48 bei x=16 vollstaendig im Viewport (Tap-Ziel 48 >= 44), Klick → /verlauf2.html, kein Quer-Ueberlauf (scrollWidth 375). ⚠ `?ia=min` zeigt den Punkt BEWUSST NICHT: core_shell.html:4339 `NAV_GROUPS.length=0` baut das Min-Menue allein aus SCREEN_KANON — gemessen 0 von 6 Kanon-Links (fragekai2/dokumente2/abgleich2/rka2/projekt2/verlauf2 fehlen dort ALLE). Das ist der dokumentierte Menue-Schnitt, keine Regression; ein Sonderweg nur fuer verlauf2 waere genau die Drift, die der Schnitt verhindert; (5) Detail-Panel (Abstract + wichtigste Dateien, Gate-A-Feature) nach Telemetrie-/Digest-Baustein. (6) Icon-Naht: engine.js icoE() nimmt heute nur ein EMOJI (EMOJI_SLUG-Bruecke, engine.js:200-214) — fuer 'umbenennen/anpinnen' existieren die Slugs edit/pin, aber KEIN Emoji zeigt darauf, und das Pin-Emoji ist im Kanon die ENTITAET. Sauber waere: icoE akzeptiert auch einen Slug (Fundament-Arbeit DESIGN#01); bis dahin traegt verlauf2 kollisionsfreie Glyphen und die Sitzungs-Art als WORT statt Emoji."
    },
    {
      "id": "core-konten",
      "title": "Konten & Karten — core_shell #/konten (SCREEN-COMPOSER-Challenge, Register #422)",
      "status": "gebaut_2026-08-10_composer_challenge",
      "owner": "SCREEN-COMPOSER-CHALLENGE-Lane (Contract v2 JC-freigegeben 10.08., Tower#36)",
      "file": "06_DASHBOARD/core_shell.html",
      "visible_url_local": "http://127.0.0.1:8787/core_shell.html#/konten",
      "screen_type": "uebersicht",
      "intent": "Je Mandant alle Bankkonten UND Zahlkarten mit aktuellem Saldo, letzter Bewegung und ehrlichem Stand — in 10 Sekunden wissen, wo Geld liegt und wo etwas klemmt (CONTRACT_KONTEN_KARTEN_v2 §1). Konten-Karten je Entitaet nach v11-Gruppierungs-Muster, Stand-Pille nach bank_lag_check-Semantik (nur echter Rueckstand rot), Saldo IMMER mit Stand-Datum, IBAN maskiert (voll nur auf Aktion), Detail-Steckbrief nach detail_view_contract (klappbare .ds-panel__blk via TGVEngine.wirePanelBlocks).",
      "data_sources": [
        "md_accounts via window.__shellAuth.restGet (User-JWT; Mig 157: admin-only — Nicht-Admin sieht ehrlich leer, fail-closed wie secBuchungen) — balance/balance_date/entity/account_type/bank_name/entity_alternate_rules (Mischkonto Mig 101), live verifiziert 10.08.",
        "kb_payment_cards via restGet (Mig 145/149; nur last4, nie volle PAN) — Dubletten (gleiche last4+entity+expiry, NULL-expiry umgeht das UNIQUE) werden dedupliziert und ANGESAGT; gemessen 10.08.: 11 aktive Zeilen, 4 Dubletten",
        "txn_master via restGet, Fenster 5000 (= bank_lag_check-Fenster), Kappung wird ANGESAGT — daraus je Konto Neueste Buchung + N ohne Beleg (Umbuchungen via istTransfer/TRANSFER_CATS_SSOT ausgenommen); BEWUSST ohne Entitaets-Filter, weil Mischkonten txn.entity != Konto-Entitaet tragen koennen (RLS ist die Wand, aggregiert wird nur je geladenem Konto)",
        "KEIN skillFetch, KEIN service_role, KEIN Demo-Datensatz (Gate C: keine Fantasiezahlen; ohne Login ehrlicher Anmelde-Hinweis)"
      ],
      "je_ids": ["JE-162", "JE-163", "JE-164", "JE-165"],
      "rule_ids": ["R-31", "R-51", "R-91", "R-116", "R-131"],
      "component_ids": [
        "zone-anatomie",
        "zone-hero",
        "kpi-tile",
        "kpi-block",
        "data-table",
        "composer",
        "collapsible-section",
        "icon-resolver",
        "account-status-card",
        "txn-steckbrief"
      ],
      "k_ids": ["K-02", "K-03", "K-11", "K-16", "K-26", "K-33", "K-39", "K-40", "K-48", "K-58", "K-60"],
      "ux_ids": ["WB-01", "hero-01-kpi", "NAV-02", "PAN-01", "PIL-01", "LNK-01"],
      "fx_or_skills": [
        "window.__shellAuth.restGet (RLS-Datenpfad, Screen setzt keinen Scope)",
        "fxRender('data-table') (K-33 Karten-Tabelle + Bewegungs-Block im Steckbrief)",
        "mountScreenComposer (K-16 Shell-Instanz im zone-composer-Slot — Kontext 'konten')",
        "TGVEngine.wirePanelBlocks (detail_view_contract: klappbare Steckbrief-Bloecke, KEIN _stkSec)",
        "heroRow1/heroScopeK11/wireHero/kpiTileA/_entQ/_entBadge/_txnMoney/istTransfer/openTxnPanel/openChatWithContext (Shell-Instanzen, aufgerufen statt kopiert)",
        "safeIco -> TGVEngine.icon (K-48)"
      ],
      "icon_slugs": ["bank-import", "ask-kai", "ai-spark", "entity", "date"],
      "chart_specs": [],
      "workbench_zone": "result_panel",
      "module_package": "konten-karten",
      "menu_scope": "Finanzen / Konten & Karten / eingeloggt (Shell-Route #/konten, SCREEN_KANON grp finanzen)",
      "abnahme": [
        "script_syntax_ok",
        "topologie_jede_ui_stelle_ist_instanz_kein_kopiertes_markup (Contract §9 ①, Belege im Challenge-Protokoll)",
        "dom_pruefbericht_gruen_vor_menuepunkt_gruen (Contract §9 ②)",
        "qa_scope_beide_richtungen (Contract §9 ③ — heute strukturell: Mig 157 admin-only, Nicht-Admin 0 Zeilen fail-closed; Live-Gegenprobe qa@ = Abnahme-Schritt nach Deploy)",
        "kein_horizontaler_overflow_375_und_dark (Contract §9 ④)",
        "transfer_probe_umbuchung_neutral_und_verfaelscht_keine_summe (Contract §9 ⑥: Saldo=Bestand aus md_accounts, ohne-Beleg-Zaehlung schliesst istTransfer aus, Bewegungs-Block zeigt Umbuchung-Badge neutral)",
        "saldo_traegt_immer_stand_datum_oder_ehrlich_kein_saldo (Contract §9 ⑦)",
        "stand_pille_nur_echter_rueckstand_rot_folgemonatsregel (bank_lag_check-Semantik als deklarierter Spiegel)",
        "iban_maskiert_default_voll_nur_auf_aktion (R-51)",
        "steckbrief_bloecke_aufklappbar_ds_panel_blk_wirePanelBlocks_aria_expanded_messbar (detail_view_contract)",
        "l4_bank_kontakt_scharf_ueber_contact_search_role_bank_und_openKontaktPanel_fail_honest_bei_fehlendem_bank_kontakt (KONTAKTE#04 17.08. — Naht JE-162..165 geschlossen; vorher: ehrlich gesperrt, kein toter Knopf)",
        "l1_drilldown_ehrlich_link_ohne_konto_filter_mit_hinweis_kein_umbau_fremder_sektion",
        "i18n_x7_alle_sichtbaren_strings_ueber_t()"
      ],
      "next_guard": "① Spiegel-Guard bank_lag-Kanon (check_transfer_kanon_ssot.py-Muster): KTO_DRAW_DAY/KTO_RUHEND/KTO_JAEHRLICH/KTO_DEPOT_WORDS in core_shell.html gegen 08_OPS/fes_bank01/bank_lag_check.py pruefen — heute ist der Spiegel deklariert, aber unbewacht. ② TAXO#01: Zeile 'konten' (typ C / uebersicht) in screen_typen.html Per-Screen-IST nachtragen — SCREEN_KANON deklariert typ:C ohne Taxonomie-Rueckhalt. ③ L1-Naht: Konto-Param fuer secBuchungen (kleiner additiver Router-Param) als eigener PR mit Tower-Brief — dann l1-Abnahme-Zeile drehen und Drilldown scharf. ④ L3-Naht (Paar-Matching Transfer via counterparty_iban) existiert weiterhin nirgends — Neubau-Kandidat klein, RECONCILE#01. ⑤ Karten-Dubletten-Wurzel: UNIQUE (last4,entity,expiry) greift bei expiry NULL nicht (gemessen 4 Dubletten) — Daten-/Schema-Heilung gehoert RECONCILE#01/SCHEMA#01, der Screen dedupliziert nur ANZEIGE und sagt es an.",
      "bekannte_schulden": {
        "_zweck": "Ehrliche Naehte aus der Composer-Challenge — jede Zeile traegt ihr Ende.",
        "entity_badge_altsystem": "Entitaets-Pille laeuft ueber die Shell-Instanz _entBadge (.ds-badge--ent-*) wie alle Nachbar-Screens — R-116 verlangt .ds-axis V4; die Abloesung ist Shell-weite Arbeit (KANON#01), kein Screen-Alleingang",
        "steckbrief_traeger_doc_panel": ".doc-panel-Huelle (Reuse openTxnPanel) statt #tgvSp — 'EINE Steckbrief-Mechanik' ist Register #416, dieser Screen fuegt bewusst KEINEN dritten Typ hinzu sondern instanziiert den bestehenden",
        "kein_saldoverlauf_chart_v1": "balance_after nur 952/1451 gefuellt, juengste Buchungen NULL (live gemessen 10.08.) — eine Saldo-Linie daraus waere falsch; Naht: balance_after-Backfill (FES-BANK#01), dann eCharts-Kanon specCf-Muster",
        "frag_kai_chips_als_ds_btn": "Katalog kennt vorschlags-chip (K-58-Familie) nur als Katalog-Karte ohne Shell-Instanz — Chips laufen als ds-btn--ghost-Instanzen; Katalog-Heimat = DESIGN#01-Kandidat"
      }
    },
    {
      "id": "core-verlauf",
      "title": "Verlauf — core_shell #/verlauf nativ (Composer-Fall #3, Nacht-Welle #424a)",
      "status": "gebaut_2026-08-10_nacht_composer_fall_3",
      "owner": "SCREEN-COMPOSER-CHALLENGE-Lane (Tower#36-Nacht-Welle; Vorgaenger-Vertrag chat-historie/verlauf2 bleibt Referenz + Deep-Link-Datei)",
      "file": "06_DASHBOARD/core_shell.html",
      "visible_url_local": "http://127.0.0.1:8787/core_shell.html#/verlauf",
      "screen_type": "uebersicht",
      "intent": "Alle eigenen KAI-Gespraeche als durchsuchbare Historie: wiederfinden (K-33-Liste mit Suche IN der Komponente), weiterlesen und WIEDER EINSTEIGEN — der Faden wird aus envelope_json OHNE LLM-Re-Run rehydriert und im NATIVEN /chat fortgesetzt (__kaiLog + __kaiThreadCore -> core-chat thread_id). Die 4 Pflicht-Faehigkeiten aus #424a: persistente Threads · Volltextsuche · Wiedereinstieg · Vorlesen (kai-read in KAIChat.renderEnvelope, tts-gecapt).",
      "data_sources": [
        "POST /api/skill/chat-threads {op:list|get} via window.__shellAuth.skillFetch — JWT-only, user-eigene Threads (Mig 203 default-deny; thread_store list_threads/get_thread)",
        "POST /api/skill/core-chat {question, thread_id} — Fortsetzen laeuft im NATIVEN /chat (secChat body.thread_id, core_shell :11044ff), dieser Screen sendet selbst NICHTS an die Engine",
        "envelope_json = Re-Render-Quelle (KAIChat.userMsg/renderEnvelope/systemLine — Chat-SSOT inline via build_kai_inline)",
        "KEIN Demo-Datensatz in der Shell: ohne Login ehrlicher Anmelde-Hinweis (verlauf2.html behaelt seine Demo-Vorschau als Standalone)"
      ],
      "je_ids": ["JE-002", "JE-032", "JE-070", "JE-076", "JE-150", "JE-161"],
      "rule_ids": ["R-02", "R-30", "R-73", "R-88", "R-90", "R-91", "R-96", "R-131"],
      "component_ids": [
        "zone-anatomie",
        "zone-hero",
        "kpi-tile",
        "kpi-block",
        "data-table",
        "speaker-bubble",
        "kai-ava",
        "statusline",
        "thread-context",
        "composer",
        "icon-resolver"
      ],
      "k_ids": ["K-02", "K-03", "K-08", "K-09", "K-10", "K-11", "K-16", "K-33", "K-48", "K-59"],
      "ux_ids": ["WB-01", "hero-01-kpi", "NAV-02", "SYS-01", "LNK-01", "PIL-01"],
      "fx_or_skills": [
        "window.__shellAuth.skillFetch('chat-threads') (JWT-only; Screen setzt keinen Scope — die Wand ist serverseitig user-eigen)",
        "fxRender('data-table') (K-33 — Volltextsuche/Sortierung/Pager IN der Komponente, kein Screen-Suchfeld)",
        "heroRow1/heroScopeK11/wireHero/kpiTileA (Shell-Instanzen; U3: Scope filtert die Liste echt, Kappung wird angesagt)",
        "historyHook + window.__kaiLog/__kaiThreadCore (U9/#49: laufender Chat wird archiviert, nie gekapert; Rehydrierung -> navigate('/chat'))",
        "mountScreenComposer (K-16-Slot der Kontext-Zone — Fragen ZUM Verlauf, context core)",
        "safeIco -> TGVEngine.icon (K-48)"
      ],
      "icon_slugs": ["history", "context-thread", "ask-kai"],
      "chart_specs": [],
      "workbench_zone": "context",
      "module_package": "kai-antwort-kette",
      "menu_scope": "Start / Verlauf / eingeloggt (SCREEN_KANON grp:start ersetzt die navExtern-Tuer verlauf2.html; nur eigene Konversationen)",
      "abnahme": [
        "script_syntax_ok",
        "topologie_jede_ui_stelle_ist_instanz_kein_kopiertes_markup (Ernte verlauf2 = Verhalten, nicht Markup)",
        "dom_pruefbericht_gruen_eingeloggt_gemessen_qa_session (#415 Verdikt -> Menuepunkt; Nacht-Regel ③)",
        "liste_ist_k33_mit_suche_in_der_komponente_kein_screen_eigenes_suchfeld",
        "wiedereinstieg_rehydriert_aus_envelope_json_ohne_llm_re_run_und_setzt_im_nativen_chat_fort (__kaiThreadCore -> body.thread_id)",
        "abhier_zustandszeile_beim_wiedereinstieg_als_systemzeile (K-10, R-88/R-90; role sys im Replay)",
        "laufender_chat_wird_archiviert_nie_gekapert_nie_geloescht (historyHook, U9/#49/R-96)",
        "vorlesen_an_kai_antworten_im_fortgesetzten_faden (kai-read via renderEnvelope, tts-gecapt — fail-closed ohne Capability)",
        "scope_wand_serverseitig_user_eigen_kein_frontend_filter_als_grenze (Mig 203 default-deny)",
        "u3_scope_filtert_liste_echt_und_sagt_kappung_an (scope_hint-Zeile)",
        "leer_login_fehler_zustaende_ehrlich_kein_endlos_laden",
        "i18n_x7_alle_sichtbaren_strings_ueber_t()"
      ],
      "next_guard": "① Verwaltungs-Verben (umbenennen/anpinnen/archivieren/verschieben): Server kennt nur op list|get|resolve (chat-historie next_guard (2) — chat_sessions.archived existiert, das VERB fehlt); der native Screen zeigt sie BEWUSST NICHT (der FX-data-table-Wrapper traegt kein rowMenu — erst Verb bauen, dann Menue, sonst Soon-Friedhof). ② TAXO#01: Zeile 'verlauf' (typ B) in der IST-Liste nachtragen (wie konten). ③ chat-historie-Vertrag (verlauf2) als 'abgeloest_durch: core-verlauf' markieren, sobald Tower die Tuer-Abloesung abnimmt — Datei bleibt fuer Deep-Links. ④ Auszug-Spalte (erster/letzter Satz) braucht ein Listen-Feld im Server-op:list (heute nur Titel/Meta) — kleine Schema-Erweiterung, kein Frontend-Nachbau.",
      "bekannte_schulden": {
        "_zweck": "Ehrliche Naehte aus Composer-Fall #3.",
        "art_als_wort": "Sitzungs-Art (Gespraech/Klaerungs-Sitzung/Fall) als WORT — fuer chat/worklist/case existiert kein Icon-Slug (verlauf2-Befund, E-14 K3); Slug-Familie = DESIGN#01-Kandidat",
        "auszug_fehlt": "Tower-Contract nennt 'Titel/Datum/Auszug' — op:list liefert keinen Auszug (nur Titel/Meta); ehrlich weggelassen statt clientseitig aus op:get N Threads nachzuladen (N+1-Lawine); Naht = next_guard ④"
      }
    },
    {
      "id": "core-kontakte",
      "title": "Kontakte — core_shell #/kontakte (CRM-Verzeichnis, KONTAKTE#02 Etappe 1)",
      "status": "live_deployed_2026-08-15_wartet_erstbefuellung_und_jc_abnahme",
      "owner": "KONTAKTE#02 (Register #433, Contract-Text CONTRACT_KONTAKTE_v1 JC-freigegeben 10.08. ohne Rotstift)",
      "file": "06_DASHBOARD/core_shell.html",
      "visible_url_local": "http://127.0.0.1:8787/core_shell.html#/kontakte",
      "screen_type": "uebersicht",
      "min_klasse": "T2",
      "intent": "JC findet in 10 Sekunden den richtigen Ansprechpartner samt Kanal: je Mandant alle Personen/Organisationen mit Erreichbarkeit, Rollen je Entitaet (Buchhalter/StB/Bank/Kunde/Projekt-Partner) und ehrlicher Herkunft jedes Eintrags (Hand oder KI-Vorschlag mit Konfidenz-Badge+Funke). Menue-Name 'Kontakte' OHNE Hochzahl (#419, direkt nativ geboren). I18N-Zusatz JC 10.08.: Header-Sprachwahl fuehrt ueberall, KEIN hart-deutscher Systemtext (alle Strings ueber t(), 7 Locales).",
      "data_sources": [
        "contacts+contact_channels+contact_roles+contact_consents (Mig 251, APPLIED 10.08.) AUSSCHLIESSLICH via POST /api/skill/contact-search (operation=search|get|export_vcard) — Scope aus user_mandant_roles des Aufrufers, Vertraulichkeits-DECKE im Skill (filtert auch Suche+Zaehlung; streng=nur Ersteller ohne super_admin-Bypass); der Screen setzt keinen Scope und filtert keine Vertraulichkeit selbst",
        "hidden_by_confidentiality wird als ZAHL angezeigt (kt.hidden_note), nie als Inhalt",
        "Schreibwege: POST /api/skill/contact-approve (approve|reject|grant_project_role — NUR Person, #401; apply-gated + Golden-Read-Back) — Service 0.57.0 (0.56.0 reserviert fuer SICHERHEIT#02/#1694), Deploy ausstehend",
        "Stadium-ehrlich: Mig-251-Hint des Skills -> kt.mig_hint-Callout; noauth -> kt.noauth; Fehler -> kt.load_err; NIE Demo-Daten"
      ],
      "je_ids": [
        "JE-157",
        "JE-162",
        "JE-163",
        "JE-164",
        "JE-165"
      ],
      "rule_ids": [
        "R-30",
        "R-91",
        "R-131",
        "R-168"
      ],
      "component_ids": [
        "zone-anatomie",
        "zone-hero",
        "kpi-tile",
        "data-table",
        "doc-steckbrief",
        "axis-badges",
        "composer",
        "statusline"
      ],
      "k_ids": [
        "K-02",
        "K-03",
        "K-16",
        "K-26",
        "K-33",
        "K-40",
        "K-44"
      ],
      "ux_ids": [
        "WB-01",
        "NAV-02",
        "hero-01-kpi",
        "PAN-01",
        "PIL-01"
      ],
      "fx_or_skills": [
        "window.__shellAuth.skillFetch('contact-search'|'contact-approve') — User-JWT, wie klaerung",
        "fxRender('data-table') K-33 mit rowAction+rowMenu+bulk (onRowMenu/_ktRowAct, onBulk/_ktBulk)",
        "vCard 4.0 Download client-seitig aus export_vcard-Text (_ktDownloadVcf, Blob)",
        "sensKey/axisBadge_sens (EINE Vertraulichkeits-Lesekette) + axisBadge_ent + _stkSec/_stkRow (Steckbrief) + _cmpToast"
      ],
      "icon_slugs": [
        "entity",
        "attachment"
      ],
      "chart_specs": [],
      "workbench_zone": "result_panel",
      "module_package": "kontakte-crm",
      "menu_scope": "Finanzen / Kontakte / eingeloggt (Shell-Route #/kontakte; min_klasse T2 deklariert — faehrt mit, bis Sicht-Klassen (#1730 §4b) gebaut sind; Menue-Punkt verdikt-gebunden #415 via AUDIT_SCREENS)",
      "abnahme": [
        "script_syntax_ok (node --check ueber alle Inline-Bloecke, 11.08. gruen)",
        "tabelle_ist_k33_mit_rowAction_rowMenu_bulk (B1/B2/B3 von Dokumente geerbt)",
        "vorschlags_probe: KI-Zeile traegt Funke+KI-Pille+Vorschlag-Pille (kt.pill.*); nach APPROVE wechselt 'angelegt/bestaetigt von' beweisbar auf Person (DB-CHECK chk_contacts_confirmed_complete)",
        "decke_probe: fremder streng-Kontakt weder sichtbar noch Suchtreffer; hidden_by_confidentiality nur als Zahl",
        "qa_scope_beide_richtungen (qa@-Gegenprobe)",
        "leerzustand_ehrlich: vor Mig-251-Apply kt.mig_hint-Callout, kein Fake/Endlos-Spinner",
        "vcard_probe: exportierte .vcf oeffnet in Kontakte-App (Formatbeweis, nicht nur Download); Vorschlaege NIE im Export",
        "folgen_sichtbarkeit: approve nennt VOR der Freigabe den Sichtbarkeits-Kreis (kt.folgen.approve, #401-Auflage 2)",
        "i18n_x7_kein_hartdeutsch (alle sichtbaren Strings via t(); check_i18n_ssot gruen)",
        "375px_und_dark",
        "kontakt_anlegen_im_screen (Etappe-1 'speichern': + Kontakt -> propose(person)+approve, DB-CHECK erfuellt) — gebaut 16.08.",
        "rollen_schnellzugriff_setzbar (contact-approve grant_role, Rolle OHNE Projekt: 'Buchhalter von C3') — gebaut 16.08.",
        "erstbefuellung_aus_eigenem_bestand (08_OPS/seed_kontakte_stamm.py --apply, JC-Hand; Banken+Lieferanten, KEINE erfundenen Kanaele)"
      ],
      "next_guard": "R-168-Endpunkt-Beweis nach Service-Deploy (contact-search/approve per Aufruf, nie /health-Zahl); danach Live-Abnahme mit Seed-Kontakten (Banken/StB/Buchhalter) + DOM-Pruefbericht -> Menue-Punkt-Verdikt (#415)",
      "bekannte_schulden": {
        "_zweck": "bekannte Schulden stehen IM Vertrag (Tower-L0-Muster core-dokumente), damit die Messung sie zaehlt statt sucht.",
        "rollen_spalte_fehlt_in_liste": "contact-search liefert in der LISTE keine Rollen (nur im Detail) — Spalte 'Rollen' bewusst weggelassen statt N+1-Aufrufe; Ende: contact-search um roles_summary erweitern (KONTAKTE#02 Etappe 2)",
        "kpi_ohne_kanal_nicht_gebaut": "Kanal-Zahl fehlt der Liste (gleiche Wurzel) — dritter KPI zeigt Organisationen; Ende: mit roles_summary/channels_count nachziehen",
        "grant_projekt_via_prompt": "Projekt-Freischaltung fragt die Projekt-Nr per window.prompt statt Projekt-Picker (K-33-Bulk traegt die Aktion; Picker braucht Projekt-Liste im Screen); Ende: Projekt-Picker mit prf_projects-Liste (PROJEKT#01-Naht)",
        "kai_executor_fehlt": "Contract Abschnitt 6 S3: chat_engine-Executor fuer contact-search nicht Teil dieses PR (AGENT-CHAT-Naht, R-171-Klasse); Ende: AGENT-CHAT#01-Zuruf",
        "icon_luecke": "Slug 'kontakte' ohne Serie-B-Icon — markierter Emoji-Fallback (WP5-ehrlich); Ende: Icon-Generator-Prozess"
      }
    },
    {
      "id": "core-vertraege",
      "title": "Vertraege & Abos — core_shell #/vertraege (Bestands-Ueberblick + Steckbrief, VERTRAG#03)",
      "status": "gebaut_vor_dem_vertrag_2026-08-16_vertrag_nachgezogen_L0",
      "owner": "VERTRAG#03 (Register #258 Gate A 'A+B kombiniert' · #421 Vertrags-Welle)",
      "file": "06_DASHBOARD/core_shell.html",
      "visible_url_local": "http://127.0.0.1:8787/core_shell.html#/vertraege",
      "screen_type": "uebersicht",
      "min_klasse": "T2",
      "intent": "JC sieht in 10 Sekunden, welche Vertraege und Abos laufen, was sie kosten, was demnaechst faellig wird und welcher Beleg dahinter liegt — je Entitaets-Scope, nach Anbieter gruppiert, bald Faelliges zuerst. Zeile -> Steckbrief (detail_view_contract) mit Kerndaten, Laufzeit/Faelligkeit und verknuepftem Beleg samt Vorschau. ⛔ WICHTIG ZUR HERKUNFT: dieser Vertrag beschreibt einen Screen, der SCHON GEBAUT UND LIVE IST (secVertraege :7209, openCtrPanel :7319) — er wird hier nachgezogen, nicht vorab entworfen. Das ist genau der Zustand, den Register #421 anprangert ('gebaut ohne Vertrag'); der Vertrag macht das Gebaute messbar und benennt seine Schulden, statt einen zweiten Screen daneben zu stellen (NUXIN-N).",
      "data_sources": [
        "prf_contracts via window.__shellAuth.restGet — 'select=*&order=next_renewal_date.asc.nullslast&limit=200' + _entQ(ent) (default-deny; der Screen setzt keinen eigenen Scope, RLS ist die Wand). Gelesene Felder: name/provider/entity/amount/currency/frequency/next_renewal_date/contract_end_date/status/document_id + defensiv gemappte Steckbrief-Felder (summary/category/notice_period/note) + confidentiality_level.",
        "⛔ KAPPUNG: limit=200 ist heute STILL — die Fusszeile zaehlt 'X von Y' gegen die GELADENEN Zeilen, nicht gegen den Bestand. Wird der Bestand 200 erreichen, behauptet der Screen Vollstaendigkeit, die er nicht hat (JC-Befund-Klasse 'genau 100 Zeilen'). Ansage ist Bau-Auflage dieses Vertrags, siehe abnahme.",
        "Basis-Filter EXCLUDE status in ('stub','test') — prf_contracts enthaelt Rechnungs-Stubs (invoice_inference) und BR04-Testlieferanten, die KEINE Vertraege sind (JC #920). KPI-Zaehlung und Liste nutzen DIESELBE Grundmenge (_rows minus EXCL) — Kachel und Liste koennen nicht auseinanderlaufen (JC-Befund-Klasse 'Kachel zeigt 5, Liste zeigt 0').",
        "VERTR_DEMO (7 Zeilen) AUSSCHLIESSLICH im no-login/IA_MIN-Vorschaupfad, mit sichtbarem Demo-Callout und data-data-mode='demo' am Wrapper (Verhaltens-Guard R-V4-21) — eingeloggt NIE Demo-Daten.",
        "DOMAIN-SICHT (WEBFACTORY#03, Register #3977, JC 11.10.2026 „ich brauch einen screen in TGV und KAI antwort fähig natürlich“): Umschalter Verträge · Domains im selben Screen, Adresse #/vertraege/domains. Quelle kb_domains via window.__shellAuth.restGet — select=id,domain,registrar,contract_number,expiry_date,status,brand,entity,manage_url,updated_at · order=expiry_date.asc.nullslast · limit=500 (Kappung angesagt, min.dom.kappung) + _entQ(ent). Die Mandanten-Wand ist RLS (Mig 299: super_admin ODER my_mandant_ids, Default-Deny) — VOR dem Apply von 299 sieht jeder angemeldete Nutzer 0 Zeilen (RLS an, 0 Policies, gemessen 11.10.). Bausteine: K-04/K-03 (kpiTileA, Filter je Kachel) · K-43 (Ablauf-Hinweis ≤30 Tage + abgelaufen) · K-33 · K-44. Datenstand wird angesagt (jüngstes updated_at), weil die Zeilen ein Registrar-Abzug sind. ⛔ AUTO-VERLÄNGERUNG (Mig 300, TOWER#71 11.10.): das Registrar-Datum ist das Ende der laufenden Periode — auto_renew=true zählt nie als „läuft ab“/„abgelaufen“ (Datum vorbei ⇒ „Datum überholt“), NULL wird als „unbekannt“ gezeigt (eigene Spalte, Quelle im Tooltip). Demo nur lokal + ?demo=1 (klDemoWanted).",
        "POSITIONS-SICHT je Vertragsnummer (Befund B, Register #258) — weiter NICHT im Screen. ⛔ Der fruehere Grund 'keine DB-Quelle' ist UEBERHOLT: contract_positions (Mig 260) traegt live 19 Positionen, 13 mit Domain (gemessen 11.10.2026, WEBFACTORY#03). Offen ist nur noch der Screen-Block, nicht die Daten."
      ],
      "je_ids": [
        "JE-157",
        "JE-171"
      ],
      "rule_ids": [
        "R-30",
        "R-31",
        "R-41",
        "R-91",
        "R-116"
      ],
      "component_ids": [
        "zone-anatomie",
        "zone-hero",
        "kpi-tile",
        "kpi-block",
        "data-table",
        "doc-steckbrief",
        "axis-badges",
        "composer",
        "icon-resolver"
      ],
      "k_ids": [
        "K-02",
        "K-03",
        "K-16",
        "K-26",
        "K-33",
        "K-40",
        "K-44",
        "K-58",
        "K-60"
      ],
      "ux_ids": [
        "WB-01",
        "NAV-02",
        "hero-01-kpi",
        "PAN-01",
        "PIL-01",
        "LNK-01"
      ],
      "fx_or_skills": [
        "window.__shellAuth.restGet (RLS-Datenpfad, kein service_role, kein skillFetch)",
        "fxRender('data-table') — K-33 mit onRow/selectable/bulkActions; Volltext-Suche lebt IN der Komponente (nicht als Screen-Kopie), Sortierung/Suche ueberleben _paint via stabiler id",
        "wireHero / heroRow1 / kpiTileA / _entQ / entLabel / entLangToSlug / axisBadge_ent / axisBadge_sens / sensKey (Shell-Instanzen, aufgerufen statt kopiert)",
        "_stkSec/_stkRow (Steckbrief-Bloecke als .ds-panel__blk mit data-panel-blk-h — seit #416/#410c die Kanon-Instanz) + TGVEngine.wirePanelBlocks (Auto-Observer)",
        "docPreviewSlot/mountDocPreviews (Beleg-Vorschau im Steckbrief, dieselbe Kette wie openDocPanel) + openDocPanel (Sprung in die volle Beleg-Ansicht)",
        "openChatWithContext (K-16-Naht: 'KAI zu diesem Vertrag fragen' im Panel-Fuss)",
        "safeIco -> TGVEngine.icon (K-48-Kette)"
      ],
      "icon_slugs": [
        "contracts",
        "ask-kai",
        "preview",
        "attachment",
        "date",
        "edit",
        "ai-result",
        "detail",
        "entity"
      ],
      "chart_specs": [],
      "workbench_zone": "result_panel",
      "module_package": "vertraege-uebersicht",
      "menu_scope": "Finanzen / Vertraege / eingeloggt (Shell-Route #/vertraege; SCREEN_KANON :2540 grp 'finanzen', typ B; min_klasse T2 deklariert — faehrt mit, bis Sicht-Klassen (#1730 §4b, SICHTBARKEIT#01) gebaut sind)",
      "abnahme": [
        "script_syntax_ok (node --check ueber alle Inline-Bloecke)",
        "kachel_und_liste_aus_EINER_grundmenge: KPI 'Vertraege gesamt' == Zeilenzahl der ungefilterten Liste (beide _rows minus stub/test) — DOM-Messung, nicht Code-Lesung",
        "✅ kappung_wird_angesagt (DOM-gemessen 16.08.): _capped -> ds-callout--warn mit t('min.ctr.kappung'). Sabotage-Probe gefahren (Demo-Pfad kuenstlich auf _capped=true): Callout erscheint mit dem erwarteten Text, danach Quelltext zurueckgesetzt (0 Sabotage-Reste). Klassen-Guard: check_screen_sagt_seine_kappung_an.py",
        "✅ status_pille_hat_ein_ziel (DOM-gemessen 16.08.): Klick auf 'abgelaufen' filtert 7 -> 3 Zeilen, Dropdown zieht auf 'expired' nach (EINE Filter-Quelle), zweiter Klick loest zurueck auf 7, und der Steckbrief oeffnet dabei NICHT",
        "✅ steckbrief_bloecke_aufklappbar (DOM-gemessen 16.08.): 4 .ds-panel__blk, 4 data-panel-blk-h, 4 aria-expanded, erster Block 'true'. ⛔ MESS-FALLE, die dieser Vertrag festhaelt: SYNCHRON nach dem Zeilen-Klick sind es 0 aria-expanded, nach ~300 ms 4 — TGVEngine.wirePanelBlocks armiert per Auto-Observer, also asynchron. Wer sofort misst, meldet einen Defekt, den es nicht gibt (mein erster Messwert war genau dieser Fehlalarm). Jede kuenftige Panel-Messung MUSS einen Tick warten.",
        "effektiv_status_nie_gruen_bei_abgelaufenem_datum (#17: _ctrEffStatus; Filter und Anzeige lesen denselben Wert)",
        "jede_zeile_wert_oder_benannter_leer_zustand (kein leeres Feld gefaked; 'folgt' bei fehlender Anreicherung)",
        "beleg_id_ist_klickbar_R-91 (Beleg #xxxx oeffnet openDocPanel; ohne Beleg ehrlich '— ohne')",
        "aktionen_echt_oder_ehrlich_soon (Kuendigung/Erinnerung/Export sind disabled mit benannter Naht — NIE toter Knopf, K-58)",
        "firmennamen_kanon: keine Anzeige des Wortes 'Convis GmbH' fuer C3 — heute erfuellt, weil entLabel aus i18n 'ent.c3' = 'C3 GmbH' liest (kein Firmenname im Screen); die Regel bleibt als Dauerprobe stehen (reference_entitaeten_firmennamen_kanon)",
        "qa_scope_beide_richtungen (qa@-Gegenprobe: eingeschraenkter Nutzer sieht fremde Vertraege NICHT — Gegenbeweis, nicht Selbstbeschreibung)",
        "✅ 375px_und_dark_kein_horizontaler_overflow (DOM-gemessen 16.08.): 375x812 hell und data-theme=dark je scrollWidth==clientWidth; Status-Pille invertiert ueber die Badge-Tokens (hell rgb(59,109,17) auf rgb(234,243,222) · dunkel rgb(158,201,122) auf rgb(30,50,16)), keine eigene Farbe im Screen",
        "i18n_x7_kein_hartdeutsch (heute VERLETZT: Hero-Text, Spaltenkoepfe und Steckbrief-Titel sind hart deutsch — siehe bekannte_schulden)"
      ],
      "next_guard": "① Kappungs-Guard (Klasse, nicht Einzelfall): check_screen_sagt_seine_kappung_an.py — jeder Screen mit 'limit=' im restGet-Pfad muss im DOM eine Kappungs-Ansage tragen, wenn die Trefferzahl das Limit erreicht; Sabotage-Selbsttest = limit kuenstlich klein setzen, Guard muss ROT werden. Faengt /vertraege, /dokumente, /konten in EINEM Griff. ② Detail-Panel-Guard aus detail_view_contract (aria-expanded>0 je Panel) auf openCtrPanel ausdehnen. ③ TAXO#01: Zeile 'vertraege' (typ B / uebersicht) im Per-Screen-IST von screen_typen.html nachtragen — SCREEN_KANON deklariert typ:B ohne Taxonomie-Rueckhalt (gleiche Luecke wie 'konten'). ④ i18n-Guard check_i18n_ssot.py auf den Vertraege-Block anwenden, sobald die Strings ueber t() laufen.",
      "bekannte_schulden": {
        "_zweck": "Ehrliche Naehte des BESTEHENDEN Screens — jede Zeile traegt ihr Ende. Sie stehen IM Vertrag, damit die Messung sie zaehlt statt sucht (Tower-L0-Muster core-dokumente).",
        "audit_harness_liest_toten_selektor": "AUDIT_SCREENS-Probe fuer 'vertraege' (core_shell.html:4878) prueft '#ctrWrap [data-row]' — die Kanon-Tabelle markiert ihre Zeilen aber mit 'data-dt-row' (DOM-gemessen 16.08.: 0 Treffer auf [data-row], 7 auf tbody tr). Die Probe 'Zeile→Detail' kann so nur falsch-rot ausgehen. ⛔ Fremdes Regal (Audit-Harness, #415/AUDIT_SCREENS) — gemeldet, NICHT gepatcht. Ende: Tower-Zuteilung; betrifft vermutlich weitere Screens derselben Probe.",
        "positions_domain_sicht_ohne_quelle": "TEILWEISE EINGELOEST (11.10.2026, WEBFACTORY#03 #3977): die DOMAIN-Sicht steht (kb_domains, Umschalter im Screen). Offen bleibt die Positions-Sicht 'Vertragsnummer -> Positionen/Domains' (#258); ihre Quelle existiert inzwischen (contract_positions, Mig 260, 19 Zeilen live). Ende: Screen-Block auf contract_positions — Eigner VERTRAG-Bahn, nicht WEBFACTORY#03.",
        "vertragsnummer_nicht_in_der_liste": "prf_contracts fuehrt heute keine sichtbare contract_number-Spalte im Screen — JCs Frage ist aber nach Vertragsnummer gestellt. Ende: Spalte + Suchfeld, sobald geklaert ist, welche prf_contracts-Spalte die Nummer traegt (check_screen_liest_echte_spalte, nicht raten).",
        "i18n_rest_nach_der_pillen_arbeit": "Zwei neue Strings laufen ueber t() (min.ctr.kappung · min.ctr.st_filter, alle 7 Locales); der ALTE Bestand bleibt hart deutsch — siehe i18n_hartdeutsch. Kein neues Hart-Deutsch dazugekommen.",
        "i18n_hartdeutsch": "Hero-Satz, alle Spaltenkoepfe ('Vertrag/Entitaet/Betrag/Laeuft bis/Beleg/Status'), Steckbrief-Titel und die Bulk-Labels sind hart deutsch; nur KPI-Labels und Status-Woerter laufen ueber t(). Ende: Strings nach i18n heben (7 Locales, check_i18n_ssot) — I18N#01-Muster.",
        "aktionen_ohne_executor": "Kuendigung vormerken / Erinnerung / Export sind ehrlich deaktiviert (soon), weil der Executor fehlt. Ende: VERTRAG#01-Skill-Naht — ausdruecklich NICHT in Etappe 1 dieser Lane (Tower-Scope: keine Kuendigungs-Assistenz, keine Fristen-Automatik, kein Outbound).",
        "stub_bereinigung_nur_angezeigt": "Der Screen BLENDET status='stub'/'test' aus, heilt sie aber nicht — prf_contracts fuehrt weiter Rechnungs-Stubs als Vertraege. Ende: Bestands-Bereinigung VERTRAG#01/RECONCILE#01 (Datenfrage, kein Screen-Eingriff).",
        "zusammenfassung_meist_leer": "Der Steckbrief-Block 'Zusammenfassung' zeigt bei fehlender Anreicherung ehrlich 'Noch nicht angereichert' — gemessene Wurzel liegt anderswo: contract-extract schreibt nach prf_contracts, aber die Anreicherung erreicht die Bestandszeilen nicht (Register #376, Klasse 'gebaut, nicht verdrahtet'). Ende: VERTRAG#01/PIPELINE-Naht, nicht dieser Screen."
      }
    }
  ]
}