Protokoll #2162
| ID | 2162 |
|---|---|
| Zeitstempel | 2025-12-21 10:33:17.676187 |
| Client | root |
| IP | Warning: Undefined array key "request_ip" in /var/www/dev.campus.systemische-tools.de/src/View/protokoll/show.php on line 13 Deprecated: htmlspecialchars(): Passing null to parameter #1 ($string) of type string is deprecated in /var/www/dev.campus.systemische-tools.de/src/View/protokoll/show.php on line 13 |
| Modell | claude-sonnet-4-20250514 |
| Status | completed |
| Tokens | 10,259 (Input: 0, Output: 0) |
| Dauer | 95 ms |
| Request-Zeit | Warning: Undefined array key "request_timestamp" in /var/www/dev.campus.systemische-tools.de/src/View/protokoll/show.php on line 18 |
| Response-Zeit | - |
Warning: Undefined array key "error_message" in /var/www/dev.campus.systemische-tools.de/src/View/protokoll/show.php on line 22
Request
{
"event": "PreToolUse",
"tool_name": "Edit",
"tool_input": {
"file_path": "\/var\/www\/dev.campus.systemische-tools.de\/docs\/plan-form-components-refactoring.md",
"old_string": "---\n\n## 0f. Ressourcen-Übersicht",
"new_string": "---\n\n## 0g. Author Profile (aus content_config)\n\n### 0g.1 Architektur-Entscheidung\n\n**Gewählt: Bestehende Tabelle `content_config` nutzen**\n\n- Autorprofile sind bereits in `content_config` mit `type = 'author_profile'`\n- Kein neues DB-Schema nötig\n- Repository-Methode `findByType('author_profile')` existiert bereits\n- Admin-Seite `\/content-config` existiert bereits\n\n### 0g.2 Partial: author-profile.php\n\n```php\n\/\/ \/src\/View\/partials\/form\/author-profile.php\n<?php\n\/**\n * Benötigte Variablen (via Controller):\n * - $authorProfiles: array aus ContentConfigRepository::findByType('author_profile')\n * - $userPrefs: array aus UserPreferencesService\n *\n * Optionale Variablen:\n * - $selected: int (Session\/Order-Wert)\n * - $variant: 'default' | 'inline'\n * - $name: string (default: 'author_profile_id')\n *\/\n\n$authorProfiles = $authorProfiles ?? [];\n$selected = $selected \/\/ 1. Session\/Order-Wert\n ?? ($userPrefs['default_author_profile_id'] ?? null) \/\/ 2. User-Präferenz\n ?? null; \/\/ 3. Kein Profil\n$name = $name ?? 'author_profile_id';\n$id = $id ?? 'author_profile_id';\n$variant = $variant ?? 'default';\n$class = $variant === 'inline' ? 'form-select--inline' : 'form-select';\n?>\n<select name=\"<?= $name ?>\" id=\"<?= $id ?>\" class=\"<?= $class ?>\">\n <option value=\"\">Kein Profil<\/option>\n <?php foreach ($authorProfiles as $profile): ?>\n <option value=\"<?= $profile['id'] ?>\" <?= (int)$selected === (int)$profile['id'] ? 'selected' : '' ?>>\n <?= htmlspecialchars($profile['name']) ?>\n <\/option>\n <?php endforeach; ?>\n<\/select>\n```\n\n### 0g.3 Werte-Hierarchie\n\n```\n1. Session\/Order-Wert → $session['author_profile_id']\n ↓ falls null\n2. User-Präferenz → $userPrefs['default_author_profile_id']\n ↓ falls null\n3. System-Default → null (Kein Profil)\n```\n\n### 0g.4 Controller-Bereitstellung\n\n```php\n\/\/ ChatController und ContentController\n$authorProfiles = $this->contentConfigRepository->findByType('author_profile');\n```\n\n### 0g.5 Verwendung\n\n| View | Kontext | Variante |\n|------|---------|----------|\n| Chat | Session-Einstellungen | default |\n| Content New | Formular | default |\n| Content Show | - (nicht benötigt) | - |\n\n### 0g.6 Migrations-Schritte (Author Profile)\n\n1. [ ] Partial `author-profile.php` erstellen\n2. [ ] Chat auf Partial umstellen\n3. [ ] Content New auf Partial umstellen\n4. [ ] Variable `$profiles` in `$authorProfiles` umbenennen\n5. [ ] Testen: Default aus User-Präferenzen\n\n---\n\n## 0h. System Prompt (aus content_config)\n\n### 0h.1 Architektur-Entscheidung\n\n**Gewählt: Bestehende Tabelle `content_config` nutzen**\n\n- System Prompts sind bereits in `content_config` mit `type = 'system_prompt'`\n- Kein neues DB-Schema nötig\n- Repository-Methode `findByType('system_prompt')` existiert bereits\n\n### 0h.2 Partial: system-prompt.php\n\n```php\n\/\/ \/src\/View\/partials\/form\/system-prompt.php\n<?php\n\/**\n * Benötigte Variablen (via Controller):\n * - $systemPrompts: array aus ContentConfigRepository::findByType('system_prompt')\n * - $userPrefs: array aus UserPreferencesService\n *\n * Optionale Variablen:\n * - $selected: int (Session\/Order-Wert)\n * - $variant: 'default' | 'inline'\n * - $name: string (default: 'system_prompt_id')\n *\/\n\n$systemPrompts = $systemPrompts ?? [];\n$selected = $selected \/\/ 1. Session\/Order-Wert\n ?? ($userPrefs['default_system_prompt_id'] ?? null) \/\/ 2. User-Präferenz\n ?? null; \/\/ 3. Kein Prompt\n$name = $name ?? 'system_prompt_id';\n$id = $id ?? 'system_prompt_id';\n$variant = $variant ?? 'default';\n$class = $variant === 'inline' ? 'form-select--inline' : 'form-select';\n?>\n<select name=\"<?= $name ?>\" id=\"<?= $id ?>\" class=\"<?= $class ?>\">\n <option value=\"\">Standard (kein System-Prompt)<\/option>\n <?php foreach ($systemPrompts as $prompt): ?>\n <option value=\"<?= $prompt['id'] ?>\" <?= (int)$selected === (int)$prompt['id'] ? 'selected' : '' ?>>\n <?= htmlspecialchars($prompt['name']) ?>\n <\/option>\n <?php endforeach; ?>\n<\/select>\n```\n\n### 0h.3 Werte-Hierarchie\n\n```\n1. Session\/Order-Wert → $session['system_prompt_id']\n ↓ falls null\n2. User-Präferenz → $userPrefs['default_system_prompt_id']\n ↓ falls null\n3. System-Default → null (kein System-Prompt)\n```\n\n### 0h.4 Verwendung\n\n| View | Kontext | Variante |\n|------|---------|----------|\n| Chat | Session-Einstellungen | default |\n| Content New | - (nicht benötigt) | - |\n| Content Show | - (nicht benötigt) | - |\n\n### 0h.5 Migrations-Schritte (System Prompt)\n\n1. [ ] Partial `system-prompt.php` erstellen\n2. [ ] Chat auf Partial umstellen\n3. [ ] Testen: Default aus User-Präferenzen\n\n---\n\n## 0i. Contract (Content Studio only)\n\n### 0i.1 Architektur-Entscheidung\n\n**Gewählt: Bestehende Tabelle `content_config` nutzen**\n\n- Contracts sind in `content_config` mit `type = 'contract'`\n- Nur im Content Studio verwendet (nicht im Chat)\n- Auto-Apply: Erster aktiver Contract wird automatisch gewählt\n\n### 0i.2 Partial: contract.php\n\n```php\n\/\/ \/src\/View\/partials\/form\/contract.php\n<?php\n\/**\n * Benötigte Variablen (via Controller):\n * - $contracts: array aus ContentConfigRepository::findByType('contract')\n * - $userPrefs: array aus UserPreferencesService\n *\n * Optionale Variablen:\n * - $selected: int (Order-Wert)\n * - $variant: 'default' | 'inline'\n * - $name: string (default: 'contract_id')\n * - $autoSelect: bool (default: true) - Ersten automatisch wählen\n *\/\n\n$contracts = $contracts ?? [];\n$autoSelect = $autoSelect ?? true;\n\n\/\/ Werte-Hierarchie\n$selected = $selected \/\/ 1. Order-Wert\n ?? ($userPrefs['default_contract_id'] ?? null) \/\/ 2. User-Präferenz\n ?? ($autoSelect && !empty($contracts) ? $contracts[0]['id'] : null); \/\/ 3. Erster aktiver\n\n$name = $name ?? 'contract_id';\n$id = $id ?? 'contract_id';\n$variant = $variant ?? 'default';\n$class = $variant === 'inline' ? 'form-select--inline' : 'form-select';\n?>\n<select name=\"<?= $name ?>\" id=\"<?= $id ?>\" class=\"<?= $class ?>\">\n <option value=\"\">-- Kein Contract --<\/option>\n <?php foreach ($contracts as $contract): ?>\n <option value=\"<?= $contract['id'] ?>\" <?= (int)$selected === (int)$contract['id'] ? 'selected' : '' ?>>\n <?= htmlspecialchars($contract['name']) ?>\n <\/option>\n <?php endforeach; ?>\n<\/select>\n```\n\n### 0i.3 Werte-Hierarchie\n\n```\n1. Order-Wert → $order['contract_id']\n ↓ falls null\n2. User-Präferenz → $userPrefs['default_contract_id']\n ↓ falls null\n3. Auto-Select → Erster aktiver Contract\n ↓ falls leer\n4. System-Default → null (kein Contract)\n```\n\n### 0i.4 Verwendung\n\n| View | Kontext | Variante |\n|------|---------|----------|\n| Chat | - (nicht verwendet) | - |\n| Content New | Formular | default |\n| Content Edit | Formular | default |\n\n### 0i.5 Migrations-Schritte (Contract)\n\n1. [ ] Partial `contract.php` erstellen\n2. [ ] Content New auf Partial umstellen\n3. [ ] Content Edit auf Partial umstellen\n4. [ ] Auto-Apply Logik aus Controller in Partial verlagern\n5. [ ] Testen: Default aus User-Präferenzen\n\n---\n\n## 0j. Structure (Content Studio only)\n\n### 0j.1 Architektur-Entscheidung\n\n**Gewählt: Bestehende Tabelle `content_config` nutzen**\n\n- Structures sind in `content_config` mit `type = 'structure'`\n- Nur im Content Studio verwendet\n- Optional: kein Auto-Apply\n\n### 0j.2 Partial: structure.php\n\n```php\n\/\/ \/src\/View\/partials\/form\/structure.php\n<?php\n\/**\n * Benötigte Variablen (via Controller):\n * - $structures: array aus ContentConfigRepository::findByType('structure')\n * - $userPrefs: array aus UserPreferencesService\n *\n * Optionale Variablen:\n * - $selected: int (Order-Wert)\n * - $variant: 'default' | 'inline'\n * - $name: string (default: 'structure_id')\n *\/\n\n$structures = $structures ?? [];\n$selected = $selected \/\/ 1. Order-Wert\n ?? ($userPrefs['default_structure_id'] ?? null) \/\/ 2. User-Präferenz\n ?? null; \/\/ 3. Keine Struktur\n\n$name = $name ?? 'structure_id';\n$id = $id ?? 'structure_id';\n$variant = $variant ?? 'default';\n$class = $variant === 'inline' ? 'form-select--inline' : 'form-select';\n?>\n<select name=\"<?= $name ?>\" id=\"<?= $id ?>\" class=\"<?= $class ?>\">\n <option value=\"\">-- Keine Struktur --<\/option>\n <?php foreach ($structures as $structure): ?>\n <option value=\"<?= $structure['id'] ?>\" <?= (int)$selected === (int)$structure['id'] ? 'selected' : '' ?>>\n <?= htmlspecialchars($structure['name']) ?>\n <\/option>\n <?php endforeach; ?>\n<\/select>\n```\n\n### 0j.3 Werte-Hierarchie\n\n```\n1. Order-Wert → $order['structure_id']\n ↓ falls null\n2. User-Präferenz → $userPrefs['default_structure_id']\n ↓ falls null\n3. System-Default → null (keine Struktur)\n```\n\n### 0j.4 Verwendung\n\n| View | Kontext | Variante |\n|------|---------|----------|\n| Chat | - (nicht verwendet) | - |\n| Content New | Formular | default |\n| Content Edit | Formular | default |\n\n### 0j.5 Migrations-Schritte (Structure)\n\n1. [ ] Partial `structure.php` erstellen\n2. [ ] Content New auf Partial umstellen\n3. [ ] Content Edit auf Partial umstellen\n4. [ ] Testen: Default aus User-Präferenzen\n\n---\n\n## 0k. Ressourcen-Übersicht"
}
}
Response
{
"tool_response": {
"filePath": "\/var\/www\/dev.campus.systemische-tools.de\/docs\/plan-form-components-refactoring.md",
"oldString": "---\n\n## 0f. Ressourcen-Übersicht",
"newString": "---\n\n## 0g. Author Profile (aus content_config)\n\n### 0g.1 Architektur-Entscheidung\n\n**Gewählt: Bestehende Tabelle `content_config` nutzen**\n\n- Autorprofile sind bereits in `content_config` mit `type = 'author_profile'`\n- Kein neues DB-Schema nötig\n- Repository-Methode `findByType('author_profile')` existiert bereits\n- Admin-Seite `\/content-config` existiert bereits\n\n### 0g.2 Partial: author-profile.php\n\n```php\n\/\/ \/src\/View\/partials\/form\/author-profile.php\n<?php\n\/**\n * Benötigte Variablen (via Controller):\n * - $authorProfiles: array aus ContentConfigRepository::findByType('author_profile')\n * - $userPrefs: array aus UserPreferencesService\n *\n * Optionale Variablen:\n * - $selected: int (Session\/Order-Wert)\n * - $variant: 'default' | 'inline'\n * - $name: string (default: 'author_profile_id')\n *\/\n\n$authorProfiles = $authorProfiles ?? [];\n$selected = $selected \/\/ 1. Session\/Order-Wert\n ?? ($userPrefs['default_author_profile_id'] ?? null) \/\/ 2. User-Präferenz\n ?? null; \/\/ 3. Kein Profil\n$name = $name ?? 'author_profile_id';\n$id = $id ?? 'author_profile_id';\n$variant = $variant ?? 'default';\n$class = $variant === 'inline' ? 'form-select--inline' : 'form-select';\n?>\n<select name=\"<?= $name ?>\" id=\"<?= $id ?>\" class=\"<?= $class ?>\">\n <option value=\"\">Kein Profil<\/option>\n <?php foreach ($authorProfiles as $profile): ?>\n <option value=\"<?= $profile['id'] ?>\" <?= (int)$selected === (int)$profile['id'] ? 'selected' : '' ?>>\n <?= htmlspecialchars($profile['name']) ?>\n <\/option>\n <?php endforeach; ?>\n<\/select>\n```\n\n### 0g.3 Werte-Hierarchie\n\n```\n1. Session\/Order-Wert → $session['author_profile_id']\n ↓ falls null\n2. User-Präferenz → $userPrefs['default_author_profile_id']\n ↓ falls null\n3. System-Default → null (Kein Profil)\n```\n\n### 0g.4 Controller-Bereitstellung\n\n```php\n\/\/ ChatController und ContentController\n$authorProfiles = $this->contentConfigRepository->findByType('author_profile');\n```\n\n### 0g.5 Verwendung\n\n| View | Kontext | Variante |\n|------|---------|----------|\n| Chat | Session-Einstellungen | default |\n| Content New | Formular | default |\n| Content Show | - (nicht benötigt) | - |\n\n### 0g.6 Migrations-Schritte (Author Profile)\n\n1. [ ] Partial `author-profile.php` erstellen\n2. [ ] Chat auf Partial umstellen\n3. [ ] Content New auf Partial umstellen\n4. [ ] Variable `$profiles` in `$authorProfiles` umbenennen\n5. [ ] Testen: Default aus User-Präferenzen\n\n---\n\n## 0h. System Prompt (aus content_config)\n\n### 0h.1 Architektur-Entscheidung\n\n**Gewählt: Bestehende Tabelle `content_config` nutzen**\n\n- System Prompts sind bereits in `content_config` mit `type = 'system_prompt'`\n- Kein neues DB-Schema nötig\n- Repository-Methode `findByType('system_prompt')` existiert bereits\n\n### 0h.2 Partial: system-prompt.php\n\n```php\n\/\/ \/src\/View\/partials\/form\/system-prompt.php\n<?php\n\/**\n * Benötigte Variablen (via Controller):\n * - $systemPrompts: array aus ContentConfigRepository::findByType('system_prompt')\n * - $userPrefs: array aus UserPreferencesService\n *\n * Optionale Variablen:\n * - $selected: int (Session\/Order-Wert)\n * - $variant: 'default' | 'inline'\n * - $name: string (default: 'system_prompt_id')\n *\/\n\n$systemPrompts = $systemPrompts ?? [];\n$selected = $selected \/\/ 1. Session\/Order-Wert\n ?? ($userPrefs['default_system_prompt_id'] ?? null) \/\/ 2. User-Präferenz\n ?? null; \/\/ 3. Kein Prompt\n$name = $name ?? 'system_prompt_id';\n$id = $id ?? 'system_prompt_id';\n$variant = $variant ?? 'default';\n$class = $variant === 'inline' ? 'form-select--inline' : 'form-select';\n?>\n<select name=\"<?= $name ?>\" id=\"<?= $id ?>\" class=\"<?= $class ?>\">\n <option value=\"\">Standard (kein System-Prompt)<\/option>\n <?php foreach ($systemPrompts as $prompt): ?>\n <option value=\"<?= $prompt['id'] ?>\" <?= (int)$selected === (int)$prompt['id'] ? 'selected' : '' ?>>\n <?= htmlspecialchars($prompt['name']) ?>\n <\/option>\n <?php endforeach; ?>\n<\/select>\n```\n\n### 0h.3 Werte-Hierarchie\n\n```\n1. Session\/Order-Wert → $session['system_prompt_id']\n ↓ falls null\n2. User-Präferenz → $userPrefs['default_system_prompt_id']\n ↓ falls null\n3. System-Default → null (kein System-Prompt)\n```\n\n### 0h.4 Verwendung\n\n| View | Kontext | Variante |\n|------|---------|----------|\n| Chat | Session-Einstellungen | default |\n| Content New | - (nicht benötigt) | - |\n| Content Show | - (nicht benötigt) | - |\n\n### 0h.5 Migrations-Schritte (System Prompt)\n\n1. [ ] Partial `system-prompt.php` erstellen\n2. [ ] Chat auf Partial umstellen\n3. [ ] Testen: Default aus User-Präferenzen\n\n---\n\n## 0i. Contract (Content Studio only)\n\n### 0i.1 Architektur-Entscheidung\n\n**Gewählt: Bestehende Tabelle `content_config` nutzen**\n\n- Contracts sind in `content_config` mit `type = 'contract'`\n- Nur im Content Studio verwendet (nicht im Chat)\n- Auto-Apply: Erster aktiver Contract wird automatisch gewählt\n\n### 0i.2 Partial: contract.php\n\n```php\n\/\/ \/src\/View\/partials\/form\/contract.php\n<?php\n\/**\n * Benötigte Variablen (via Controller):\n * - $contracts: array aus ContentConfigRepository::findByType('contract')\n * - $userPrefs: array aus UserPreferencesService\n *\n * Optionale Variablen:\n * - $selected: int (Order-Wert)\n * - $variant: 'default' | 'inline'\n * - $name: string (default: 'contract_id')\n * - $autoSelect: bool (default: true) - Ersten automatisch wählen\n *\/\n\n$contracts = $contracts ?? [];\n$autoSelect = $autoSelect ?? true;\n\n\/\/ Werte-Hierarchie\n$selected = $selected \/\/ 1. Order-Wert\n ?? ($userPrefs['default_contract_id'] ?? null) \/\/ 2. User-Präferenz\n ?? ($autoSelect && !empty($contracts) ? $contracts[0]['id'] : null); \/\/ 3. Erster aktiver\n\n$name = $name ?? 'contract_id';\n$id = $id ?? 'contract_id';\n$variant = $variant ?? 'default';\n$class = $variant === 'inline' ? 'form-select--inline' : 'form-select';\n?>\n<select name=\"<?= $name ?>\" id=\"<?= $id ?>\" class=\"<?= $class ?>\">\n <option value=\"\">-- Kein Contract --<\/option>\n <?php foreach ($contracts as $contract): ?>\n <option value=\"<?= $contract['id'] ?>\" <?= (int)$selected === (int)$contract['id'] ? 'selected' : '' ?>>\n <?= htmlspecialchars($contract['name']) ?>\n <\/option>\n <?php endforeach; ?>\n<\/select>\n```\n\n### 0i.3 Werte-Hierarchie\n\n```\n1. Order-Wert → $order['contract_id']\n ↓ falls null\n2. User-Präferenz → $userPrefs['default_contract_id']\n ↓ falls null\n3. Auto-Select → Erster aktiver Contract\n ↓ falls leer\n4. System-Default → null (kein Contract)\n```\n\n### 0i.4 Verwendung\n\n| View | Kontext | Variante |\n|------|---------|----------|\n| Chat | - (nicht verwendet) | - |\n| Content New | Formular | default |\n| Content Edit | Formular | default |\n\n### 0i.5 Migrations-Schritte (Contract)\n\n1. [ ] Partial `contract.php` erstellen\n2. [ ] Content New auf Partial umstellen\n3. [ ] Content Edit auf Partial umstellen\n4. [ ] Auto-Apply Logik aus Controller in Partial verlagern\n5. [ ] Testen: Default aus User-Präferenzen\n\n---\n\n## 0j. Structure (Content Studio only)\n\n### 0j.1 Architektur-Entscheidung\n\n**Gewählt: Bestehende Tabelle `content_config` nutzen**\n\n- Structures sind in `content_config` mit `type = 'structure'`\n- Nur im Content Studio verwendet\n- Optional: kein Auto-Apply\n\n### 0j.2 Partial: structure.php\n\n```php\n\/\/ \/src\/View\/partials\/form\/structure.php\n<?php\n\/**\n * Benötigte Variablen (via Controller):\n * - $structures: array aus ContentConfigRepository::findByType('structure')\n * - $userPrefs: array aus UserPreferencesService\n *\n * Optionale Variablen:\n * - $selected: int (Order-Wert)\n * - $variant: 'default' | 'inline'\n * - $name: string (default: 'structure_id')\n *\/\n\n$structures = $structures ?? [];\n$selected = $selected \/\/ 1. Order-Wert\n ?? ($userPrefs['default_structure_id'] ?? null) \/\/ 2. User-Präferenz\n ?? null; \/\/ 3. Keine Struktur\n\n$name = $name ?? 'structure_id';\n$id = $id ?? 'structure_id';\n$variant = $variant ?? 'default';\n$class = $variant === 'inline' ? 'form-select--inline' : 'form-select';\n?>\n<select name=\"<?= $name ?>\" id=\"<?= $id ?>\" class=\"<?= $class ?>\">\n <option value=\"\">-- Keine Struktur --<\/option>\n <?php foreach ($structures as $structure): ?>\n <option value=\"<?= $structure['id'] ?>\" <?= (int)$selected === (int)$structure['id'] ? 'selected' : '' ?>>\n <?= htmlspecialchars($structure['name']) ?>\n <\/option>\n <?php endforeach; ?>\n<\/select>\n```\n\n### 0j.3 Werte-Hierarchie\n\n```\n1. Order-Wert → $order['structure_id']\n ↓ falls null\n2. User-Präferenz → $userPrefs['default_structure_id']\n ↓ falls null\n3. System-Default → null (keine Struktur)\n```\n\n### 0j.4 Verwendung\n\n| View | Kontext | Variante |\n|------|---------|----------|\n| Chat | - (nicht verwendet) | - |\n| Content New | Formular | default |\n| Content Edit | Formular | default |\n\n### 0j.5 Migrations-Schritte (Structure)\n\n1. [ ] Partial `structure.php` erstellen\n2. [ ] Content New auf Partial umstellen\n3. [ ] Content Edit auf Partial umstellen\n4. [ ] Testen: Default aus User-Präferenzen\n\n---\n\n## 0k. Ressourcen-Übersicht",
"originalFile": "# Plan: Einheitliche Form-Komponenten (Chat & Content Studio)\n\n## Status: PLANUNG\n**Erstellt:** 2025-12-21\n**Ziel:** DRY, KISS, SRP - Shared Partials für alle wiederverwendbaren Form-Elemente\n\n---\n\n## 0. LLM-Verwaltung (Grundlage für Modell-Dropdown)\n\n### 0.1 Architektur-Entscheidung\n\n**Gewählt: Variante B - Dedizierte LLM-Verwaltung**\n\nStatt dynamischer API-Abfrage bei jedem Seitenaufruf:\n- Zentrale Admin-Seite `\/ressourcen\/llm`\n- Datenbank-Tabelle als Single Source of Truth\n- Sync-Buttons für Provider (Anthropic, Ollama, weitere)\n- Sprechende Namen und Zusatzmetadaten\n\n### 0.2 Datenbank-Tabelle `llm_models`\n\n```sql\nCREATE TABLE llm_models (\n id INT AUTO_INCREMENT PRIMARY KEY,\n provider ENUM('anthropic', 'ollama', 'openai', 'google', 'mistral', 'custom') NOT NULL,\n model_id VARCHAR(100) NOT NULL, -- API-ID: \"claude-opus-4-5-20251101\"\n display_name VARCHAR(100) NOT NULL, -- Anzeige: \"Claude Opus 4.5\"\n description TEXT, -- Kurzbeschreibung\n context_window INT, -- Max. Tokens Input: 200000\n max_output_tokens INT, -- Max. Tokens Output: 8192\n input_price_per_mtok DECIMAL(10,4), -- Preis Input $\/MTok\n output_price_per_mtok DECIMAL(10,4), -- Preis Output $\/MTok\n capabilities JSON, -- {\"vision\": true, \"function_calling\": true}\n is_local BOOLEAN DEFAULT FALSE, -- Lokal (Ollama) vs. Cloud\n is_active BOOLEAN DEFAULT TRUE, -- In Dropdowns anzeigen?\n sort_order INT DEFAULT 0, -- Reihenfolge in Dropdowns\n last_synced_at DATETIME, -- Letzte Synchronisation\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n UNIQUE KEY unique_provider_model (provider, model_id)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;\n```\n\n### 0.3 Admin-Seite `\/ressourcen\/llm`\n\n**URL:** `\/ressourcen\/llm`\n**Controller:** `RessourcenController::llmIndex()`\n\n**Funktionen:**\n\n| Button | Aktion |\n|--------|--------|\n| \"Anthropic synchronisieren\" | `GET api.anthropic.com\/v1\/models` → DB aktualisieren |\n| \"Ollama synchronisieren\" | `ollama list` → DB aktualisieren |\n| \"Neuer Provider\" | Manuell weiteren Provider hinzufügen |\n\n**Tabellen-Ansicht:**\n\n| Provider | Model-ID | Display-Name | Context | Preis In\/Out | Lokal | Aktiv | Aktionen |\n|----------|----------|--------------|---------|--------------|-------|-------|----------|\n| Anthropic | claude-opus-4-5-20251101 | Claude Opus 4.5 | 200k | $15\/$75 | - | ✓ | Bearbeiten |\n| Ollama | mistral:latest | Mistral 7B | 32k | - | ✓ | ✓ | Bearbeiten |\n\n**Bearbeiten-Dialog:**\n- Display-Name ändern\n- Beschreibung hinzufügen\n- Context-Window \/ Max-Output korrigieren\n- Preise eintragen (für Kostenberechnung)\n- Aktivieren\/Deaktivieren\n- Sortierung ändern\n\n### 0.4 Sync-Logik\n\n**Anthropic Sync:**\n```php\n\/\/ GET https:\/\/api.anthropic.com\/v1\/models\n\/\/ Response: {\"data\": [{\"id\": \"claude-opus-4-5-20251101\", ...}]}\n\nforeach ($apiModels as $model) {\n \/\/ INSERT ... ON DUPLICATE KEY UPDATE\n \/\/ Neue Modelle: is_active = true, display_name = model_id (initial)\n \/\/ Existierende: last_synced_at aktualisieren\n \/\/ Fehlende: NICHT löschen, nur last_synced_at bleibt alt\n}\n```\n\n**Ollama Sync:**\n```php\n\/\/ $ ollama list\n\/\/ NAME ID SIZE MODIFIED\n\/\/ mistral:latest abc123... 4.1 GB 2 days ago\n\n$output = shell_exec('ollama list');\n\/\/ Parsen und in DB einfügen\n```\n\n### 0.5 Dropdown-Query\n\n```php\n\/\/ ModelService::getActiveModels()\npublic function getActiveModels(): array\n{\n return $this->db->query(\"\n SELECT model_id, display_name, provider, is_local, context_window\n FROM llm_models\n WHERE is_active = 1\n ORDER BY is_local ASC, sort_order ASC, display_name ASC\n \")->fetchAll();\n}\n```\n\n### 0.6 Partial nutzt DB-Daten\n\n```php\n\/\/ \/src\/View\/partials\/form\/model-select.php\n<?php\n$models = $models ?? [];\n$selected = $selected ?? '';\n$variant = $variant ?? 'default';\n$class = $variant === 'inline' ? 'form-select--inline' : 'form-select';\n?>\n<select name=\"model\" id=\"model\" class=\"<?= $class ?>\">\n <optgroup label=\"Cloud\">\n <?php foreach ($models as $m): ?>\n <?php if (!$m['is_local']): ?>\n <option value=\"<?= $m['model_id'] ?>\" <?= $selected === $m['model_id'] ? 'selected' : '' ?>>\n <?= htmlspecialchars($m['display_name']) ?>\n <\/option>\n <?php endif; ?>\n <?php endforeach; ?>\n <\/optgroup>\n <optgroup label=\"Lokal\">\n <?php foreach ($models as $m): ?>\n <?php if ($m['is_local']): ?>\n <option value=\"<?= $m['model_id'] ?>\" <?= $selected === $m['model_id'] ? 'selected' : '' ?>>\n <?= htmlspecialchars($m['display_name']) ?>\n <\/option>\n <?php endif; ?>\n <?php endforeach; ?>\n <\/optgroup>\n<\/select>\n```\n\n### 0.7 Migrations-Schritte (LLM-Verwaltung)\n\n1. [ ] Tabelle `llm_models` in `ki_dev` erstellen\n2. [ ] `LlmModelRepository` erstellen\n3. [ ] `LlmSyncService` erstellen (Anthropic + Ollama)\n4. [ ] Route `\/ressourcen\/llm` anlegen\n5. [ ] `RessourcenController::llmIndex()` implementieren\n6. [ ] View `\/ressourcen\/llm\/index.php` erstellen\n7. [ ] Sync-Buttons implementieren\n8. [ ] Bearbeiten-Funktionalität\n9. [ ] Initial-Sync durchführen (bestehende Modelle importieren)\n10. [ ] `ModelConfig.php` durch `LlmModelRepository` ersetzen\n11. [ ] Partial `model-select.php` erstellen\n12. [ ] Chat und Content auf Partial umstellen\n\n---\n\n## 0b. Collection-Verwaltung (Grundlage für Collection-Dropdown)\n\n### 0b.1 Architektur-Entscheidung\n\n**Gewählt: DB-Tabelle analog zu LLMs**\n\n- Zentrale Admin-Seite `\/ressourcen\/collections`\n- Datenbank-Tabelle als Single Source of Truth\n- Sync mit Qdrant (Metadaten abrufen)\n- Sprechende Namen und Beschreibungen\n- **Multi-Select** als einheitliche Darstellung\n\n### 0b.2 Datenbank-Tabelle `rag_collections`\n\n```sql\nCREATE TABLE rag_collections (\n id INT AUTO_INCREMENT PRIMARY KEY,\n collection_id VARCHAR(100) NOT NULL UNIQUE, -- Qdrant-Name: \"documents\"\n display_name VARCHAR(100) NOT NULL, -- Anzeige: \"Dokumente\"\n description TEXT, -- \"PDF-Dokumente aus Nextcloud\"\n\n -- Qdrant-Metadaten (via Sync)\n vector_size INT, -- 1024\n distance_metric VARCHAR(20), -- \"Cosine\"\n points_count INT DEFAULT 0, -- Anzahl Vektoren\n\n -- Konfiguration\n embedding_model VARCHAR(100), -- \"mxbai-embed-large\"\n chunk_size INT, -- 2000\n chunk_overlap INT, -- 200\n\n -- Verwaltung\n source_type ENUM('nextcloud', 'mail', 'manual', 'system') DEFAULT 'manual',\n source_path VARCHAR(500), -- \"\/var\/www\/nextcloud\/data\/...\"\n is_active BOOLEAN DEFAULT TRUE, -- In Dropdowns anzeigen?\n is_searchable BOOLEAN DEFAULT TRUE, -- Für RAG verfügbar?\n sort_order INT DEFAULT 0,\n\n -- Timestamps\n last_synced_at DATETIME,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;\n```\n\n### 0b.3 Impact-Analyse: Wer nutzt Collections?\n\n| System\/Seite | Aktueller Zugriff | Neuer Zugriff | Änderung |\n|--------------|-------------------|---------------|----------|\n| **Chat** | `$qdrantService->listCollections()` | `CollectionRepository::getActive()` | Query aus DB |\n| **Content Studio** | `$qdrantService->listCollections()` | `CollectionRepository::getActive()` | Query aus DB |\n| **Content Show** | `$qdrantService->listCollections()` | `CollectionRepository::getActive()` | Query aus DB |\n| **Pipeline (Python)** | `config.py QDRANT_COLLECTIONS` | DB-Query oder Config-Sync | Python liest DB |\n| **Semantic Explorer** | Direkt Qdrant | `CollectionRepository` + Qdrant | Metadaten aus DB |\n| **System Explorer** | - | Statistiken aus DB | Neu |\n| **API \/api\/v1\/search** | Qdrant direkt | Validierung gegen DB | Nur aktive Collections |\n| **Embedding-Service** | `config.py` | DB oder Sync | Konsistenz |\n\n### 0b.4 Admin-Seite `\/ressourcen\/collections`\n\n**URL:** `\/ressourcen\/collections`\n**Controller:** `RessourcenController::collectionsIndex()`\n\n**Funktionen:**\n\n| Button | Aktion |\n|--------|--------|\n| \"Qdrant synchronisieren\" | Collections + Metadaten von Qdrant abrufen |\n| \"Neue Collection\" | Manuell Collection registrieren |\n\n**Tabellen-Ansicht:**\n\n| Collection-ID | Display-Name | Vektoren | Größe | Quelle | Aktiv | Suchbar | Aktionen |\n|---------------|--------------|----------|-------|--------|-------|---------|----------|\n| documents | Dokumente | 1.247 | 1024d | Nextcloud | ✓ | ✓ | Bearbeiten |\n| dokumentation_chunks | Doku-Chunks | 892 | 1024d | System | ✓ | ✓ | Bearbeiten |\n| mail | E-Mails | 3.421 | 1024d | Mail | ✓ | ✓ | Bearbeiten |\n| entities | Entitäten | 156 | 1024d | System | ✓ | - | Bearbeiten |\n\n**Bearbeiten-Dialog:**\n- Display-Name ändern\n- Beschreibung hinzufügen\n- Quelle\/Pfad dokumentieren\n- Aktivieren\/Deaktivieren (Dropdown)\n- Suchbar ja\/nein (RAG-Verfügbarkeit)\n- Sortierung ändern\n\n### 0b.5 Sync-Logik\n\n**Qdrant Sync:**\n```php\n\/\/ QdrantService::getCollectionsInfo()\npublic function syncCollections(): array\n{\n $qdrantCollections = $this->client->getCollections();\n\n foreach ($qdrantCollections as $col) {\n $info = $this->client->getCollectionInfo($col['name']);\n\n \/\/ INSERT ... ON DUPLICATE KEY UPDATE\n $this->repository->upsert([\n 'collection_id' => $col['name'],\n 'display_name' => $col['name'], \/\/ Initial = ID\n 'vector_size' => $info['config']['params']['size'],\n 'distance_metric' => $info['config']['params']['distance'],\n 'points_count' => $info['points_count'],\n 'last_synced_at' => now(),\n ]);\n }\n}\n```\n\n### 0b.6 Repository-Interface\n\n```php\n\/\/ CollectionRepository.php\ninterface CollectionRepositoryInterfac... [TRUNCATED-f89b8e58072994d3]",
"structuredPatch": [
{
"oldStart": 1266,
"oldLines": 8,
"newStart": 1266,
"newLines": 313,
"lines": [
" ",
" ---",
" ",
"-## 0f. Ressourcen-Übersicht",
"+## 0g. Author Profile (aus content_config)",
" ",
"+### 0g.1 Architektur-Entscheidung",
"+",
"+**Gewählt: Bestehende Tabelle `content_config` nutzen**",
"+",
"+- Autorprofile sind bereits in `content_config` mit `type = 'author_profile'`",
"+- Kein neues DB-Schema nötig",
"+- Repository-Methode `findByType('author_profile')` existiert bereits",
"+- Admin-Seite `\/content-config` existiert bereits",
"+",
"+### 0g.2 Partial: author-profile.php",
"+",
"+```php",
"+\/\/ \/src\/View\/partials\/form\/author-profile.php",
"+<?php",
"+\/**",
"+ * Benötigte Variablen (via Controller):",
"+ * - $authorProfiles: array aus ContentConfigRepository::findByType('author_profile')",
"+ * - $userPrefs: array aus UserPreferencesService",
"+ *",
"+ * Optionale Variablen:",
"+ * - $selected: int (Session\/Order-Wert)",
"+ * - $variant: 'default' | 'inline'",
"+ * - $name: string (default: 'author_profile_id')",
"+ *\/",
"+",
"+$authorProfiles = $authorProfiles ?? [];",
"+$selected = $selected \/\/ 1. Session\/Order-Wert",
"+ ?? ($userPrefs['default_author_profile_id'] ?? null) \/\/ 2. User-Präferenz",
"+ ?? null; \/\/ 3. Kein Profil",
"+$name = $name ?? 'author_profile_id';",
"+$id = $id ?? 'author_profile_id';",
"+$variant = $variant ?? 'default';",
"+$class = $variant === 'inline' ? 'form-select--inline' : 'form-select';",
"+?>",
"+<select name=\"<?= $name ?>\" id=\"<?= $id ?>\" class=\"<?= $class ?>\">",
"+ <option value=\"\">Kein Profil<\/option>",
"+ <?php foreach ($authorProfiles as $profile): ?>",
"+ <option value=\"<?= $profile['id'] ?>\" <?= (int)$selected === (int)$profile['id'] ? 'selected' : '' ?>>",
"+ <?= htmlspecialchars($profile['name']) ?>",
"+ <\/option>",
"+ <?php endforeach; ?>",
"+<\/select>",
"+```",
"+",
"+### 0g.3 Werte-Hierarchie",
"+",
"+```",
"+1. Session\/Order-Wert → $session['author_profile_id']",
"+ ↓ falls null",
"+2. User-Präferenz → $userPrefs['default_author_profile_id']",
"+ ↓ falls null",
"+3. System-Default → null (Kein Profil)",
"+```",
"+",
"+### 0g.4 Controller-Bereitstellung",
"+",
"+```php",
"+\/\/ ChatController und ContentController",
"+$authorProfiles = $this->contentConfigRepository->findByType('author_profile');",
"+```",
"+",
"+### 0g.5 Verwendung",
"+",
"+| View | Kontext | Variante |",
"+|------|---------|----------|",
"+| Chat | Session-Einstellungen | default |",
"+| Content New | Formular | default |",
"+| Content Show | - (nicht benötigt) | - |",
"+",
"+### 0g.6 Migrations-Schritte (Author Profile)",
"+",
"+1. [ ] Partial `author-profile.php` erstellen",
"+2. [ ] Chat auf Partial umstellen",
"+3. [ ] Content New auf Partial umstellen",
"+4. [ ] Variable `$profiles` in `$authorProfiles` umbenennen",
"+5. [ ] Testen: Default aus User-Präferenzen",
"+",
"+---",
"+",
"+## 0h. System Prompt (aus content_config)",
"+",
"+### 0h.1 Architektur-Entscheidung",
"+",
"+**Gewählt: Bestehende Tabelle `content_config` nutzen**",
"+",
"+- System Prompts sind bereits in `content_config` mit `type = 'system_prompt'`",
"+- Kein neues DB-Schema nötig",
"+- Repository-Methode `findByType('system_prompt')` existiert bereits",
"+",
"+### 0h.2 Partial: system-prompt.php",
"+",
"+```php",
"+\/\/ \/src\/View\/partials\/form\/system-prompt.php",
"+<?php",
"+\/**",
"+ * Benötigte Variablen (via Controller):",
"+ * - $systemPrompts: array aus ContentConfigRepository::findByType('system_prompt')",
"+ * - $userPrefs: array aus UserPreferencesService",
"+ *",
"+ * Optionale Variablen:",
"+ * - $selected: int (Session\/Order-Wert)",
"+ * - $variant: 'default' | 'inline'",
"+ * - $name: string (default: 'system_prompt_id')",
"+ *\/",
"+",
"+$systemPrompts = $systemPrompts ?? [];",
"+$selected = $selected \/\/ 1. Session\/Order-Wert",
"+ ?? ($userPrefs['default_system_prompt_id'] ?? null) \/\/ 2. User-Präferenz",
"+ ?? null; \/\/ 3. Kein Prompt",
"+$name = $name ?? 'system_prompt_id';",
"+$id = $id ?? 'system_prompt_id';",
"+$variant = $variant ?? 'default';",
"+$class = $variant === 'inline' ? 'form-select--inline' : 'form-select';",
"+?>",
"+<select name=\"<?= $name ?>\" id=\"<?= $id ?>\" class=\"<?= $class ?>\">",
"+ <option value=\"\">Standard (kein System-Prompt)<\/option>",
"+ <?php foreach ($systemPrompts as $prompt): ?>",
"+ <option value=\"<?= $prompt['id'] ?>\" <?= (int)$selected === (int)$prompt['id'] ? 'selected' : '' ?>>",
"+ <?= htmlspecialchars($prompt['name']) ?>",
"+ <\/option>",
"+ <?php endforeach; ?>",
"+<\/select>",
"+```",
"+",
"+### 0h.3 Werte-Hierarchie",
"+",
"+```",
"+1. Session\/Order-Wert → $session['system_prompt_id']",
"+ ↓ falls null",
"+2. User-Präferenz → $userPrefs['default_system_prompt_id']",
"+ ↓ falls null",
"+3. System-Default → null (kein System-Prompt)",
"+```",
"+",
"+### 0h.4 Verwendung",
"+",
"+| View | Kontext | Variante |",
"+|------|---------|----------|",
"+| Chat | Session-Einstellungen | default |",
"+| Content New | - (nicht benötigt) | - |",
"+| Content Show | - (nicht benötigt) | - |",
"+",
"+### 0h.5 Migrations-Schritte (System Prompt)",
"+",
"+1. [ ] Partial `system-prompt.php` erstellen",
"+2. [ ] Chat auf Partial umstellen",
"+3. [ ] Testen: Default aus User-Präferenzen",
"+",
"+---",
"+",
"+## 0i. Contract (Content Studio only)",
"+",
"+### 0i.1 Architektur-Entscheidung",
"+",
"+**Gewählt: Bestehende Tabelle `content_config` nutzen**",
"+",
"+- Contracts sind in `content_config` mit `type = 'contract'`",
"+- Nur im Content Studio verwendet (nicht im Chat)",
"+- Auto-Apply: Erster aktiver Contract wird automatisch gewählt",
"+",
"+### 0i.2 Partial: contract.php",
"+",
"+```php",
"+\/\/ \/src\/View\/partials\/form\/contract.php",
"+<?php",
"+\/**",
"+ * Benötigte Variablen (via Controller):",
"+ * - $contracts: array aus ContentConfigRepository::findByType('contract')",
"+ * - $userPrefs: array aus UserPreferencesService",
"+ *",
"+ * Optionale Variablen:",
"+ * - $selected: int (Order-Wert)",
"+ * - $variant: 'default' | 'inline'",
"+ * - $name: string (default: 'contract_id')",
"+ * - $autoSelect: bool (default: true) - Ersten automatisch wählen",
"+ *\/",
"+",
"+$contracts = $contracts ?? [];",
"+$autoSelect = $autoSelect ?? true;",
"+",
"+\/\/ Werte-Hierarchie",
"+$selected = $selected \/\/ 1. Order-Wert",
"+ ?? ($userPrefs['default_contract_id'] ?? null) \/\/ 2. User-Präferenz",
"+ ?? ($autoSelect && !empty($contracts) ? $contracts[0]['id'] : null); \/\/ 3. Erster aktiver",
"+",
"+$name = $name ?? 'contract_id';",
"+$id = $id ?? 'contract_id';",
"+$variant = $variant ?? 'default';",
"+$class = $variant === 'inline' ? 'form-select--inline' : 'form-select';",
"+?>",
"+<select name=\"<?= $name ?>\" id=\"<?= $id ?>\" class=\"<?= $class ?>\">",
"+ <option value=\"\">-- Kein Contract --<\/option>",
"+ <?php foreach ($contracts as $contract): ?>",
"+ <option value=\"<?= $contract['id'] ?>\" <?= (int)$selected === (int)$contract['id'] ? 'selected' : '' ?>>",
"+ <?= htmlspecialchars($contract['name']) ?>",
"+ <\/option>",
"+ <?php endforeach; ?>",
"+<\/select>",
"+```",
"+",
"+### 0i.3 Werte-Hierarchie",
"+",
"+```",
"+1. Order-Wert → $order['contract_id']",
"+ ↓ falls null",
"+2. User-Präferenz → $userPrefs['default_contract_id']",
"+ ↓ falls null",
"+3. Auto-Select → Erster aktiver Contract",
"+ ↓ falls leer",
"+4. System-Default → null (kein Contract)",
"+```",
"+",
"+### 0i.4 Verwendung",
"+",
"+| View | Kontext | Variante |",
"+|------|---------|----------|",
"+| Chat | - (nicht verwendet) | - |",
"+| Content New | Formular | default |",
"+| Content Edit | Formular | default |",
"+",
"+### 0i.5 Migrations-Schritte (Contract)",
"+",
"+1. [ ] Partial `contract.php` erstellen",
"+2. [ ] Content New auf Partial umstellen",
"+3. [ ] Content Edit auf Partial umstellen",
"+4. [ ] Auto-Apply Logik aus Controller in Partial verlagern",
"+5. [ ] Testen: Default aus User-Präferenzen",
"+",
"+---",
"+",
"+## 0j. Structure (Content Studio only)",
"+",
"+### 0j.1 Architektur-Entscheidung",
"+",
"+**Gewählt: Bestehende Tabelle `content_config` nutzen**",
"+",
"+- Structures sind in `content_config` mit `type = 'structure'`",
"+- Nur im Content Studio verwendet",
"+- Optional: kein Auto-Apply",
"+",
"+### 0j.2 Partial: structure.php",
"+",
"+```php",
"+\/\/ \/src\/View\/partials\/form\/structure.php",
"+<?php",
"+\/**",
"+ * Benötigte Variablen (via Controller):",
"+ * - $structures: array aus ContentConfigRepository::findByType('structure')",
"+ * - $userPrefs: array aus UserPreferencesService",
"+ *",
"+ * Optionale Variablen:",
"+ * - $selected: int (Order-Wert)",
"+ * - $variant: 'default' | 'inline'",
"+ * - $name: string (default: 'structure_id')",
"+ *\/",
"+",
"+$structures = $structures ?? [];",
"+$selected = $selected \/\/ 1. Order-Wert",
"+ ?? ($userPrefs['default_structure_id'] ?? null) \/\/ 2. User-Präferenz",
"+ ?? null; \/\/ 3. Keine Struktur",
"+",
"+$name = $name ?? 'structure_id';",
"+$id = $id ?? 'structure_id';",
"+$variant = $variant ?? 'default';",
"+$class = $variant === 'inline' ? 'form-select--inline' : 'form-select';",
"+?>",
"+<select name=\"<?= $name ?>\" id=\"<?= $id ?>\" class=\"<?= $class ?>\">",
"+ <option value=\"\">-- Keine Struktur --<\/option>",
"+ <?php foreach ($structures as $structure): ?>",
"+ <option value=\"<?= $structure['id'] ?>\" <?= (int)$selected === (int)$structure['id'] ? 'selected' : '' ?>>",
"+ <?= htmlspecialchars($structure['name']) ?>",
"+ <\/option>",
"+ <?php endforeach; ?>",
"+<\/select>",
"+```",
"+",
"+### 0j.3 Werte-Hierarchie",
"+",
"+```",
"+1. Order-Wert → $order['structure_id']",
"+ ↓ falls null",
"+2. User-Präferenz → $userPrefs['default_structure_id']",
"+ ↓ falls null",
"+3. System-Default → null (keine Struktur)",
"+```",
"+",
"+### 0j.4 Verwendung",
"+",
"+| View | Kontext | Variante |",
"+|------|---------|----------|",
"+| Chat | - (nicht verwendet) | - |",
"+| Content New | Formular | default |",
"+| Content Edit | Formular | default |",
"+",
"+### 0j.5 Migrations-Schritte (Structure)",
"+",
"+1. [ ] Partial `structure.php` erstellen",
"+2. [ ] Content New auf Partial umstellen",
"+3. [ ] Content Edit auf Partial umstellen",
"+4. [ ] Testen: Default aus User-Präferenzen",
"+",
"+---",
"+",
"+## 0k. Ressourcen-Übersicht",
"+",
" ### Navigationsstruktur",
" ",
" ```"
]
}
],
"userModified": false,
"replaceAll": false
}
}