{
"event": "PreToolUse",
"tool_name": "Write",
"tool_input": {
"file_path": "\/var\/www\/dev.campus.systemische-tools.de\/docs\/codequality\/04-action-items.md",
"content": "# Priorisierte Massnahmen\n\n**Projekt:** dev.campus.systemische-tools.de\n**Erstellt:** 2025-12-22\n\n---\n\n## Prioritaet 1: Kritisch (Sofort)\n\n### 1.1 Base Controller erweitern\n**Aufwand:** 1h | **Impact:** HOCH\n\n```php\n\/\/ src\/Framework\/Controller.php - Ergaenzen:\n\nprotected function notFound(string $message = 'Nicht gefunden'): never {\n http_response_code(404);\n if ($this->isJsonRequest()) {\n $this->json(['error' => $message], 404);\n } else {\n echo \"404 - {$message}\";\n }\n exit;\n}\n\nprotected function decodeJson(?string $json): array {\n return json_decode($json ?? '[]', true) ?: [];\n}\n\nprotected function getInput(string $key, mixed $default = ''): mixed {\n return $_GET[$key] ?? $_POST[$key] ?? $default;\n}\n\nprotected function getPage(): int {\n return max(1, (int)($_GET['page'] ?? 1));\n}\n\nprotected function getLimit(int $max = 50, int $default = 10): int {\n return min($max, max(1, (int)($_GET['limit'] ?? $default)));\n}\n```\n\n**Betroffene Dateien:** Alle Controller (32 Stellen mit http_response_code(404))\n\n---\n\n### 1.2 PHPStan Level 5 zuerst\n**Aufwand:** 4h | **Impact:** MITTEL\n\nAktuell 510 Level-9-Errors. Schrittweise:\n1. Level 1 → 0 Errors\n2. Level 3 → ~50 Errors\n3. Level 5 → ~150 Errors\n4. Level 7 → ~300 Errors\n5. Level 9 → 510 Errors\n\n**Kommando:**\n```bash\n\/opt\/php-tools\/vendor\/bin\/phpstan analyse src --level=5\n```\n\n---\n\n## Prioritaet 2: Hoch (Diese Woche)\n\n### 2.1 Repository Interfaces erstellen\n**Aufwand:** 2h | **Impact:** HOCH\n\n```php\n\/\/ src\/Domain\/Repository\/TaskRepositoryInterface.php\nnamespace Domain\\Repository;\n\ninterface TaskRepositoryInterface {\n public function find(int $id): ?array;\n public function findAll(array $filters = []): array;\n public function create(array $data): int;\n public function update(int $id, array $data): bool;\n public function delete(int $id): bool;\n}\n```\n\n**Zu erstellen:**\n- [ ] TaskRepositoryInterface\n- [ ] ContentRepositoryInterface\n- [ ] CollectionRepositoryInterface\n- [ ] DokumentationRepositoryInterface\n\n---\n\n### 2.2 ChatController aufteilen (Phase 1)\n**Aufwand:** 4h | **Impact:** HOCH\n\n**Schritt 1:** Repository extrahieren\n```php\n\/\/ src\/Infrastructure\/Persistence\/ChatSessionRepository.php\nclass ChatSessionRepository {\n public function findByUuid(string $uuid): ?array;\n public function create(string $uuid, string $title): int;\n public function updateTitle(string $uuid, string $title): void;\n public function delete(string $uuid): void;\n public function findAll(): array;\n}\n\n\/\/ src\/Infrastructure\/Persistence\/ChatMessageRepository.php\nclass ChatMessageRepository {\n public function findBySessionUuid(string $uuid): array;\n public function create(string $sessionUuid, array $message): int;\n}\n```\n\n**Schritt 2:** ChatController reduzieren auf HTTP-Handling\n\n---\n\n### 2.3 SemanticExplorerController aufteilen\n**Aufwand:** 3h | **Impact:** HOCH\n\n**Neue Controller:**\n```\nSemanticExplorerController.php → Dashboard (index, suche)\nEntityController.php → Entities CRUD\nRelationController.php → Relations CRUD\nTaxonomyController.php → Taxonomy CRUD\nOntologyController.php → Ontology CRUD\n```\n\n**Routing-Aenderungen in Router.php:**\n```php\n'\/semantic-explorer\/entitaeten' → EntityController::index\n'\/semantic-explorer\/entitaeten\/new' → EntityController::create\n\/\/ etc.\n```\n\n---\n\n## Prioritaet 3: Mittel (Naechste 2 Wochen)\n\n### 3.1 UseCases fuer Chat-Domain\n**Aufwand:** 4h | **Impact:** MITTEL\n\n```php\n\/\/ src\/UseCases\/Chat\/SendMessageUseCase.php\nclass SendMessageUseCase {\n public function execute(string $sessionUuid, string $message, string $model): MessageResponse;\n}\n\n\/\/ src\/UseCases\/Chat\/LoadSessionUseCase.php\nclass LoadSessionUseCase {\n public function execute(string $uuid): SessionDTO;\n}\n```\n\n---\n\n### 3.2 Pagination Value Object\n**Aufwand:** 1h | **Impact:** MITTEL\n\n```php\n\/\/ src\/Domain\/ValueObject\/Pagination.php\nfinal class Pagination {\n public function __construct(\n public readonly int $page,\n public readonly int $limit,\n public readonly int $offset,\n public readonly int $totalCount = 0\n ) {}\n\n public static function fromRequest(int $defaultLimit = 50): self {\n $page = max(1, (int)($_GET['page'] ?? 1));\n return new self($page, $defaultLimit, ($page - 1) * $defaultLimit);\n }\n\n public function withTotal(int $count): self {\n return new self($this->page, $this->limit, $this->offset, $count);\n }\n\n public function totalPages(): int {\n return (int)ceil($this->totalCount \/ $this->limit);\n }\n\n public function hasNextPage(): bool {\n return $this->page < $this->totalPages();\n }\n\n public function hasPrevPage(): bool {\n return $this->page > 1;\n }\n}\n```\n\n---\n\n### 3.3 HTML aus Controllern entfernen\n**Aufwand:** 2h | **Impact:** MITTEL\n\n**ContentController.php:**\n- `renderVersionPartial()` → `src\/View\/content\/partials\/version.php`\n- `renderCritiquePartial()` → `src\/View\/content\/partials\/critique.php`\n\n---\n\n### 3.4 Konfiguration externalisieren\n**Aufwand:** 1h | **Impact:** NIEDRIG\n\n```php\n\/\/ config\/services.php\nreturn [\n 'ollama' => [\n 'url' => 'http:\/\/localhost:11434',\n 'embed_model' => 'mxbai-embed-large',\n ],\n 'qdrant' => [\n 'url' => 'http:\/\/localhost:6333',\n ],\n];\n```\n\n---\n\n## Prioritaet 4: Niedrig (Spaeter)\n\n### 4.1 DI-Container einfuehren\n**Aufwand:** 8h | **Impact:** HOCH (langfristig)\n\n**Option A: PHP-DI**\n```bash\ncomposer require php-di\/php-di\n```\n\n**Option B: Symfony DI Component**\n```bash\ncomposer require symfony\/dependency-injection\n```\n\n---\n\n### 4.2 Event System\n**Aufwand:** 6h | **Impact:** MITTEL\n\nFuer asynchrone Verarbeitung und Entkopplung.\n\n---\n\n### 4.3 API Versioning\n**Aufwand:** 4h | **Impact:** NIEDRIG\n\nFuer zukuenftige Breaking Changes.\n\n---\n\n## Checkliste fuer Supervision\n\n### Woche 1\n- [ ] Base Controller erweitert (notFound, decodeJson, getInput)\n- [ ] PHPStan Level 5 ohne Errors\n- [ ] Mindestens 4 Repository Interfaces erstellt\n\n### Woche 2\n- [ ] ChatController aufgeteilt (Phase 1 abgeschlossen)\n- [ ] SemanticExplorerController aufgeteilt\n- [ ] Pagination Value Object implementiert\n\n### Woche 3-4\n- [ ] UseCases fuer Chat-Domain\n- [ ] HTML aus allen Controllern entfernt\n- [ ] Konfiguration externalisiert\n\n### Monat 2\n- [ ] DI-Container eingefuehrt\n- [ ] PHPStan Level 7 ohne Errors\n- [ ] Alle grossen Controller < 300 LOC\n\n---\n\n## Metriken zur Erfolgsmessung\n\n| Metrik | Aktuell | Ziel Woche 2 | Ziel Monat 2 |\n|--------|---------|--------------|--------------|\n| PHPStan Errors (L5) | ~150 | 0 | 0 |\n| PHPStan Errors (L9) | 510 | 400 | 100 |\n| Groesster Controller | 978 LOC | 600 LOC | 300 LOC |\n| DIP Violations | 30+ | 20 | 0 |\n| 404 Pattern Duplikate | 32 | 0 | 0 |\n| Repository Interfaces | 0 | 4 | 10 |\n\n---\n\n## Schnellreferenz: Dateien die zuerst angefasst werden\n\n1. `src\/Framework\/Controller.php` - Base erweitern\n2. `src\/Controller\/ChatController.php` - Aufteilen\n3. `src\/Controller\/SemanticExplorerController.php` - Aufteilen\n4. `src\/Domain\/Repository\/*.php` - Interfaces erstellen\n5. `src\/Infrastructure\/Persistence\/ChatSessionRepository.php` - Neu\n6. `src\/Infrastructure\/Persistence\/ChatMessageRepository.php` - Neu\n"
}
}
{
"tool_response": {
"type": "create",
"filePath": "\/var\/www\/dev.campus.systemische-tools.de\/docs\/codequality\/04-action-items.md",
"content": "# Priorisierte Massnahmen\n\n**Projekt:** dev.campus.systemische-tools.de\n**Erstellt:** 2025-12-22\n\n---\n\n## Prioritaet 1: Kritisch (Sofort)\n\n### 1.1 Base Controller erweitern\n**Aufwand:** 1h | **Impact:** HOCH\n\n```php\n\/\/ src\/Framework\/Controller.php - Ergaenzen:\n\nprotected function notFound(string $message = 'Nicht gefunden'): never {\n http_response_code(404);\n if ($this->isJsonRequest()) {\n $this->json(['error' => $message], 404);\n } else {\n echo \"404 - {$message}\";\n }\n exit;\n}\n\nprotected function decodeJson(?string $json): array {\n return json_decode($json ?? '[]', true) ?: [];\n}\n\nprotected function getInput(string $key, mixed $default = ''): mixed {\n return $_GET[$key] ?? $_POST[$key] ?? $default;\n}\n\nprotected function getPage(): int {\n return max(1, (int)($_GET['page'] ?? 1));\n}\n\nprotected function getLimit(int $max = 50, int $default = 10): int {\n return min($max, max(1, (int)($_GET['limit'] ?? $default)));\n}\n```\n\n**Betroffene Dateien:** Alle Controller (32 Stellen mit http_response_code(404))\n\n---\n\n### 1.2 PHPStan Level 5 zuerst\n**Aufwand:** 4h | **Impact:** MITTEL\n\nAktuell 510 Level-9-Errors. Schrittweise:\n1. Level 1 → 0 Errors\n2. Level 3 → ~50 Errors\n3. Level 5 → ~150 Errors\n4. Level 7 → ~300 Errors\n5. Level 9 → 510 Errors\n\n**Kommando:**\n```bash\n\/opt\/php-tools\/vendor\/bin\/phpstan analyse src --level=5\n```\n\n---\n\n## Prioritaet 2: Hoch (Diese Woche)\n\n### 2.1 Repository Interfaces erstellen\n**Aufwand:** 2h | **Impact:** HOCH\n\n```php\n\/\/ src\/Domain\/Repository\/TaskRepositoryInterface.php\nnamespace Domain\\Repository;\n\ninterface TaskRepositoryInterface {\n public function find(int $id): ?array;\n public function findAll(array $filters = []): array;\n public function create(array $data): int;\n public function update(int $id, array $data): bool;\n public function delete(int $id): bool;\n}\n```\n\n**Zu erstellen:**\n- [ ] TaskRepositoryInterface\n- [ ] ContentRepositoryInterface\n- [ ] CollectionRepositoryInterface\n- [ ] DokumentationRepositoryInterface\n\n---\n\n### 2.2 ChatController aufteilen (Phase 1)\n**Aufwand:** 4h | **Impact:** HOCH\n\n**Schritt 1:** Repository extrahieren\n```php\n\/\/ src\/Infrastructure\/Persistence\/ChatSessionRepository.php\nclass ChatSessionRepository {\n public function findByUuid(string $uuid): ?array;\n public function create(string $uuid, string $title): int;\n public function updateTitle(string $uuid, string $title): void;\n public function delete(string $uuid): void;\n public function findAll(): array;\n}\n\n\/\/ src\/Infrastructure\/Persistence\/ChatMessageRepository.php\nclass ChatMessageRepository {\n public function findBySessionUuid(string $uuid): array;\n public function create(string $sessionUuid, array $message): int;\n}\n```\n\n**Schritt 2:** ChatController reduzieren auf HTTP-Handling\n\n---\n\n### 2.3 SemanticExplorerController aufteilen\n**Aufwand:** 3h | **Impact:** HOCH\n\n**Neue Controller:**\n```\nSemanticExplorerController.php → Dashboard (index, suche)\nEntityController.php → Entities CRUD\nRelationController.php → Relations CRUD\nTaxonomyController.php → Taxonomy CRUD\nOntologyController.php → Ontology CRUD\n```\n\n**Routing-Aenderungen in Router.php:**\n```php\n'\/semantic-explorer\/entitaeten' → EntityController::index\n'\/semantic-explorer\/entitaeten\/new' → EntityController::create\n\/\/ etc.\n```\n\n---\n\n## Prioritaet 3: Mittel (Naechste 2 Wochen)\n\n### 3.1 UseCases fuer Chat-Domain\n**Aufwand:** 4h | **Impact:** MITTEL\n\n```php\n\/\/ src\/UseCases\/Chat\/SendMessageUseCase.php\nclass SendMessageUseCase {\n public function execute(string $sessionUuid, string $message, string $model): MessageResponse;\n}\n\n\/\/ src\/UseCases\/Chat\/LoadSessionUseCase.php\nclass LoadSessionUseCase {\n public function execute(string $uuid): SessionDTO;\n}\n```\n\n---\n\n### 3.2 Pagination Value Object\n**Aufwand:** 1h | **Impact:** MITTEL\n\n```php\n\/\/ src\/Domain\/ValueObject\/Pagination.php\nfinal class Pagination {\n public function __construct(\n public readonly int $page,\n public readonly int $limit,\n public readonly int $offset,\n public readonly int $totalCount = 0\n ) {}\n\n public static function fromRequest(int $defaultLimit = 50): self {\n $page = max(1, (int)($_GET['page'] ?? 1));\n return new self($page, $defaultLimit, ($page - 1) * $defaultLimit);\n }\n\n public function withTotal(int $count): self {\n return new self($this->page, $this->limit, $this->offset, $count);\n }\n\n public function totalPages(): int {\n return (int)ceil($this->totalCount \/ $this->limit);\n }\n\n public function hasNextPage(): bool {\n return $this->page < $this->totalPages();\n }\n\n public function hasPrevPage(): bool {\n return $this->page > 1;\n }\n}\n```\n\n---\n\n### 3.3 HTML aus Controllern entfernen\n**Aufwand:** 2h | **Impact:** MITTEL\n\n**ContentController.php:**\n- `renderVersionPartial()` → `src\/View\/content\/partials\/version.php`\n- `renderCritiquePartial()` → `src\/View\/content\/partials\/critique.php`\n\n---\n\n### 3.4 Konfiguration externalisieren\n**Aufwand:** 1h | **Impact:** NIEDRIG\n\n```php\n\/\/ config\/services.php\nreturn [\n 'ollama' => [\n 'url' => 'http:\/\/localhost:11434',\n 'embed_model' => 'mxbai-embed-large',\n ],\n 'qdrant' => [\n 'url' => 'http:\/\/localhost:6333',\n ],\n];\n```\n\n---\n\n## Prioritaet 4: Niedrig (Spaeter)\n\n### 4.1 DI-Container einfuehren\n**Aufwand:** 8h | **Impact:** HOCH (langfristig)\n\n**Option A: PHP-DI**\n```bash\ncomposer require php-di\/php-di\n```\n\n**Option B: Symfony DI Component**\n```bash\ncomposer require symfony\/dependency-injection\n```\n\n---\n\n### 4.2 Event System\n**Aufwand:** 6h | **Impact:** MITTEL\n\nFuer asynchrone Verarbeitung und Entkopplung.\n\n---\n\n### 4.3 API Versioning\n**Aufwand:** 4h | **Impact:** NIEDRIG\n\nFuer zukuenftige Breaking Changes.\n\n---\n\n## Checkliste fuer Supervision\n\n### Woche 1\n- [ ] Base Controller erweitert (notFound, decodeJson, getInput)\n- [ ] PHPStan Level 5 ohne Errors\n- [ ] Mindestens 4 Repository Interfaces erstellt\n\n### Woche 2\n- [ ] ChatController aufgeteilt (Phase 1 abgeschlossen)\n- [ ] SemanticExplorerController aufgeteilt\n- [ ] Pagination Value Object implementiert\n\n### Woche 3-4\n- [ ] UseCases fuer Chat-Domain\n- [ ] HTML aus allen Controllern entfernt\n- [ ] Konfiguration externalisiert\n\n### Monat 2\n- [ ] DI-Container eingefuehrt\n- [ ] PHPStan Level 7 ohne Errors\n- [ ] Alle grossen Controller < 300 LOC\n\n---\n\n## Metriken zur Erfolgsmessung\n\n| Metrik | Aktuell | Ziel Woche 2 | Ziel Monat 2 |\n|--------|---------|--------------|--------------|\n| PHPStan Errors (L5) | ~150 | 0 | 0 |\n| PHPStan Errors (L9) | 510 | 400 | 100 |\n| Groesster Controller | 978 LOC | 600 LOC | 300 LOC |\n| DIP Violations | 30+ | 20 | 0 |\n| 404 Pattern Duplikate | 32 | 0 | 0 |\n| Repository Interfaces | 0 | 4 | 10 |\n\n---\n\n## Schnellreferenz: Dateien die zuerst angefasst werden\n\n1. `src\/Framework\/Controller.php` - Base erweitern\n2. `src\/Controller\/ChatController.php` - Aufteilen\n3. `src\/Controller\/SemanticExplorerController.php` - Aufteilen\n4. `src\/Domain\/Repository\/*.php` - Interfaces erstellen\n5. `src\/Infrastructure\/Persistence\/ChatSessionRepository.php` - Neu\n6. `src\/Infrastructure\/Persistence\/ChatMessageRepository.php` - Neu\n",
"structuredPatch": [],
"originalFile": null
}
}