Protokoll #6564
| ID | 6564 |
|---|---|
| Zeitstempel | 2025-12-23 06:17:24.065993 |
| 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 | 1,299 (Input: 0, Output: 0) |
| Dauer | 86 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": "Read",
"tool_input": {
"file_path": "\/var\/www\/tools\/ki-protokoll\/claude-hook\/architecture_guard.py"
}
}
Response
{
"tool_response": {
"type": "text",
"file": {
"filePath": "\/var\/www\/tools\/ki-protokoll\/claude-hook\/architecture_guard.py",
"content": "#!\/usr\/bin\/env python3\n\"\"\"\nArchitecture Guard Hook\n\nBlockiert Architektur-Verletzungen BEVOR Code geschrieben wird.\n- Controller > 500 LOC: Block\n- Controller > 400 LOC: Warnung\n- PDO\/SQL in Controller: Block\n\nTrigger: PreToolUse (Write, Edit)\n\"\"\"\n\nimport json\nimport re\nimport sys\n\n# Patterns für direkten DB-Zugriff in Controllern\nPDO_PATTERNS = [\n r'\\$this->db\\s*=', # $this->db = ...\n r'\\$this->db->', # $this->db->query() etc.\n r'new\\s+\\\\?PDO\\(', # new PDO( oder new \\PDO(\n r'->query\\s*\\(', # ->query(\n r'->prepare\\s*\\(', # ->prepare(\n r'->exec\\s*\\(', # ->exec(\n r'DatabaseFactory::', # Direkter Factory-Zugriff\n r'getDatabase\\(\\)', # getDatabase() Methode\n]\n\nLOC_WARNING_THRESHOLD = 400\nLOC_BLOCK_THRESHOLD = 500\n\n\ndef count_lines(content: str) -> int:\n \"\"\"Zählt nicht-leere Zeilen.\"\"\"\n return len([line for line in content.split('\\n') if line.strip()])\n\n\ndef is_controller_file(file_path: str) -> bool:\n \"\"\"Prüft ob es sich um einen Controller handelt.\"\"\"\n return '\/Controller\/' in file_path and file_path.endswith('.php')\n\n\ndef check_pdo_patterns(content: str) -> list[str]:\n \"\"\"Findet PDO\/SQL-Patterns im Content.\"\"\"\n found = []\n for pattern in PDO_PATTERNS:\n if re.search(pattern, content):\n found.append(pattern)\n return found\n\n\ndef check_controller(file_path: str, content: str) -> dict:\n \"\"\"\n Prüft Controller auf Architektur-Verletzungen.\n\n Returns:\n dict mit keys: block, warn, reason\n \"\"\"\n if not is_controller_file(file_path):\n return {'block': False, 'warn': False, 'reason': ''}\n\n result = {'block': False, 'warn': False, 'reason': ''}\n messages = []\n\n # LOC-Prüfung\n loc = count_lines(content)\n\n if loc > LOC_BLOCK_THRESHOLD:\n result['block'] = True\n messages.append(f\"Controller hat {loc} LOC (max {LOC_BLOCK_THRESHOLD})\")\n elif loc > LOC_WARNING_THRESHOLD:\n result['warn'] = True\n messages.append(f\"Controller nähert sich LOC-Limit: {loc}\/{LOC_BLOCK_THRESHOLD}\")\n\n # PDO-Pattern-Prüfung\n pdo_matches = check_pdo_patterns(content)\n\n if pdo_matches:\n result['block'] = True\n messages.append(f\"Controller enthält direkten DB-Zugriff: {', '.join(pdo_matches[:3])}\")\n\n if messages:\n result['reason'] = '\\n'.join(messages)\n\n return result\n\n\ndef format_block_message(reason: str) -> str:\n \"\"\"Formatiert Blocknachricht mit Lösungshinweisen.\"\"\"\n return f\"\"\"ARCHITEKTUR-VERLETZUNG BLOCKIERT!\n\n{reason}\n\nLösungen:\n1. LOC zu hoch: Service\/Repository extrahieren\n2. PDO in Controller:\n - Nutze Repository-Pattern\n - Erstelle Infrastructure\/Persistence\/*Repository.php\n - Controller ruft nur Repository-Methoden auf\n\nBeispiel:\n \/\/ FALSCH (im Controller):\n $this->db->query(\"SELECT * FROM users\")\n\n \/\/ RICHTIG:\n $this->userRepository->findAll()\n\nArchitektur-Regeln: \/var\/www\/docs\/contracts\/code-quality-standards.yaml\"\"\"\n\n\ndef format_warning_message(reason: str) -> str:\n \"\"\"Formatiert Warnungsnachricht.\"\"\"\n return f\"\"\"ARCHITEKTUR-WARNUNG:\n\n{reason}\n\nEmpfehlung: Erwäge Refactoring bevor das Limit erreicht wird.\"\"\"\n\n\ndef main():\n try:\n input_data = json.load(sys.stdin)\n except json.JSONDecodeError:\n sys.exit(0)\n\n tool_name = input_data.get('tool_name', '')\n\n # Nur Write und Edit prüfen\n if tool_name not in ('Write', 'Edit'):\n sys.exit(0)\n\n tool_input = input_data.get('tool_input', {})\n file_path = tool_input.get('file_path', '')\n\n # Content ermitteln\n if tool_name == 'Write':\n content = tool_input.get('content', '')\n else: # Edit\n # Bei Edit: neuen String prüfen (vereinfacht)\n content = tool_input.get('new_string', '')\n # Edit-Prüfung nur auf PDO-Patterns, nicht LOC\n if is_controller_file(file_path):\n pdo_matches = check_pdo_patterns(content)\n if pdo_matches:\n print(format_block_message(\n f\"Edit fügt direkten DB-Zugriff hinzu: {', '.join(pdo_matches[:3])}\"\n ), file=sys.stderr)\n sys.exit(2)\n sys.exit(0)\n\n # Vollständige Prüfung nur bei Write\n result = check_controller(file_path, content)\n\n if result['block']:\n print(format_block_message(result['reason']), file=sys.stderr)\n sys.exit(2)\n\n if result['warn']:\n # Warnung ausgeben aber durchlassen\n print(format_warning_message(result['reason']), file=sys.stderr)\n sys.exit(0)\n\n sys.exit(0)\n\n\nif __name__ == '__main__':\n main()\n",
"numLines": 168,
"startLine": 1,
"totalLines": 168
}
}
}