Protokoll #28437

ID28437
Zeitstempel2025-12-28 13:27:57.167695
Clientroot
IP145.224.72.140
Modellclaude-sonnet-4-20250514
Statuscompleted
Tokens4,197 (Input: 2,096, Output: 2,101)
Dauer100 ms
Request-Zeit2025-12-28 13:27:57.167695
Response-Zeit2025-12-28 13:27:57.268054

Request

{
    "event": "PreToolUse",
    "tool_name": "Write",
    "tool_input": {
        "file_path": "\/var\/www\/mcp-servers\/mcp_contracts\/validators\/rule_evaluator.py",
        "content": "\"\"\"\nRule Evaluator - Domain Service fuer Regel-Auswertung.\n\nWICHTIG: Dies ist KEIN Repository!\nKeine CRUD-Operationen, nur Business-Logik.\n\"\"\"\n\nimport re\nfrom typing import Any\n\nfrom domain.contracts import ContractValidationResult\n\n\nclass RuleEvaluator:\n    \"\"\"Evaluiert Contract-Regeln gegen Code.\"\"\"\n\n    def evaluate_rule(\n        self,\n        file_path: str,\n        content: str,\n        rule: dict[str, Any],\n        result: ContractValidationResult,\n    ) -> None:\n        \"\"\"Prueft eine einzelne Rule gegen eine Datei.\"\"\"\n        check_type = rule.get(\"check_type\", \"\")\n\n        if check_type == \"line_count\":\n            self._check_line_count(file_path, content, rule, result)\n        elif check_type == \"forbidden_pattern\":\n            self._check_forbidden_pattern(file_path, content, rule, result)\n        elif check_type == \"required_pattern\":\n            self._check_required_pattern(file_path, content, rule, result)\n        elif check_type == \"dependency_check\":\n            self._check_dependency(file_path, content, rule, result)\n\n    def evaluate_legacy_forbidden(\n        self,\n        file_path: str,\n        content: str,\n        forbidden: list,\n        result: ContractValidationResult,\n    ) -> None:\n        \"\"\"Prueft auf verbotene Elemente (Legacy-Format).\"\"\"\n        for item in forbidden:\n            if isinstance(item, dict):\n                element = item.get(\"element\", \"\")\n                severity = item.get(\"severity\", \"minor\")\n                message = item.get(\"message\", f\"Forbidden element found: {element}\")\n            else:\n                element = str(item)\n                severity = \"minor\"\n                message = f\"Forbidden element found: {element}\"\n\n            if element and element in content:\n                self._add_violation(result, severity, {\n                    \"factor\": \"forbidden_element\",\n                    \"file\": file_path,\n                    \"message\": message,\n                })\n\n    def evaluate_legacy_required(\n        self,\n        file_path: str,\n        content: str,\n        required: list,\n        result: ContractValidationResult,\n    ) -> None:\n        \"\"\"Prueft auf erforderliche Elemente (Legacy-Format).\"\"\"\n        for item in required:\n            if isinstance(item, dict):\n                element = item.get(\"element\", \"\")\n                severity = item.get(\"severity\", \"major\")\n                message = item.get(\"message\", f\"Required element missing: {element}\")\n                applies_to = item.get(\"applies_to\", [])\n            else:\n                element = str(item)\n                severity = \"major\"\n                message = f\"Required element missing: {element}\"\n                applies_to = []\n\n            if applies_to:\n                matches = any(\n                    file_path.endswith(p.lstrip(\"*\")) for p in applies_to\n                )\n                if not matches:\n                    continue\n\n            if element and element not in content:\n                self._add_violation(result, severity, {\n                    \"factor\": \"required_element\",\n                    \"file\": file_path,\n                    \"message\": message,\n                })\n\n    def determine_outcome(self, result: ContractValidationResult) -> str:\n        \"\"\"Bestimmt das Validierungsergebnis basierend auf Violations.\"\"\"\n        if result.critical > 0:\n            return \"rejected\"\n        elif result.major > 2:\n            return \"revision_required\"\n        return \"passed\"\n\n    def _check_line_count(\n        self, file_path: str, content: str, rule: dict, result: ContractValidationResult\n    ) -> None:\n        \"\"\"Prueft Zeilenanzahl einer Datei.\"\"\"\n        max_lines = rule.get(\"max_lines\", 500)\n        line_count = len(content.splitlines())\n\n        if line_count > max_lines:\n            self._add_violation(result, rule.get(\"severity\", \"major\"), {\n                \"rule_id\": rule.get(\"id\", \"line_count\"),\n                \"factor\": \"line_count\",\n                \"file\": file_path,\n                \"message\": f\"File has {line_count} lines (max: {max_lines})\",\n                \"actual\": line_count,\n                \"limit\": max_lines,\n            })\n\n    def _check_forbidden_pattern(\n        self, file_path: str, content: str, rule: dict, result: ContractValidationResult\n    ) -> None:\n        \"\"\"Prueft auf verbotene Patterns.\"\"\"\n        patterns = rule.get(\"patterns\", [])\n\n        for pattern in patterns:\n            try:\n                matches = re.findall(pattern, content)\n            except re.error:\n                matches = [pattern] if pattern in content else []\n\n            if matches:\n                line_no = self._find_line_number(content, pattern)\n                self._add_violation(result, rule.get(\"severity\", \"major\"), {\n                    \"rule_id\": rule.get(\"id\", \"forbidden_pattern\"),\n                    \"factor\": \"forbidden_pattern\",\n                    \"file\": file_path,\n                    \"message\": f\"Forbidden pattern found: '{pattern}'\",\n                    \"description\": rule.get(\"description\", \"\"),\n                    \"line\": line_no,\n                    \"occurrences\": len(matches),\n                })\n\n    def _check_required_pattern(\n        self, file_path: str, content: str, rule: dict, result: ContractValidationResult\n    ) -> None:\n        \"\"\"Prueft auf erforderliche Patterns.\"\"\"\n        patterns = rule.get(\"patterns\", [])\n\n        for pattern in patterns:\n            try:\n                found = bool(re.search(pattern, content))\n            except re.error:\n                found = pattern in content\n\n            if not found:\n                self._add_violation(result, rule.get(\"severity\", \"major\"), {\n                    \"rule_id\": rule.get(\"id\", \"required_pattern\"),\n                    \"factor\": \"required_pattern\",\n                    \"file\": file_path,\n                    \"message\": f\"Required pattern not found: '{pattern}'\",\n                    \"description\": rule.get(\"description\", \"\"),\n                })\n\n    def _check_dependency(\n        self, file_path: str, content: str, rule: dict, result: ContractValidationResult\n    ) -> None:\n        \"\"\"Prueft auf verbotene Dependencies\/Imports.\"\"\"\n        forbidden_imports = rule.get(\"forbidden_imports\", [])\n\n        for forbidden in forbidden_imports:\n            php_pattern = rf\"use\\s+.*{re.escape(forbidden)}\"\n            py_pattern = rf\"(from|import)\\s+.*{re.escape(forbidden)}\"\n\n            try:\n                if re.search(php_pattern, content) or re.search(py_pattern, content):\n                    self._add_violation(result, rule.get(\"severity\", \"critical\"), {\n                        \"rule_id\": rule.get(\"id\", \"dependency_check\"),\n                        \"factor\": \"forbidden_dependency\",\n                        \"file\": file_path,\n                        \"message\": f\"Forbidden import\/dependency: '{forbidden}'\",\n                    })\n            except re.error:\n                pass\n\n    def _find_line_number(self, content: str, pattern: str) -> int | None:\n        \"\"\"Findet die Zeilennummer eines Patterns.\"\"\"\n        for i, line in enumerate(content.splitlines(), 1):\n            if pattern in line:\n                return i\n            try:\n                if re.search(pattern, line):\n                    return i\n            except re.error:\n                pass\n        return None\n\n    def _add_violation(\n        self, result: ContractValidationResult, severity: str, finding: dict\n    ) -> None:\n        \"\"\"Fuegt eine Violation zum Result hinzu.\"\"\"\n        finding[\"type\"] = severity\n\n        if severity == \"critical\":\n            result.critical += 1\n        elif severity == \"major\":\n            result.major += 1\n        else:\n            result.minor += 1\n\n        result.findings.append(finding)\n"
    }
}

Response

{
    "tool_response": {
        "type": "create",
        "filePath": "\/var\/www\/mcp-servers\/mcp_contracts\/validators\/rule_evaluator.py",
        "content": "\"\"\"\nRule Evaluator - Domain Service fuer Regel-Auswertung.\n\nWICHTIG: Dies ist KEIN Repository!\nKeine CRUD-Operationen, nur Business-Logik.\n\"\"\"\n\nimport re\nfrom typing import Any\n\nfrom domain.contracts import ContractValidationResult\n\n\nclass RuleEvaluator:\n    \"\"\"Evaluiert Contract-Regeln gegen Code.\"\"\"\n\n    def evaluate_rule(\n        self,\n        file_path: str,\n        content: str,\n        rule: dict[str, Any],\n        result: ContractValidationResult,\n    ) -> None:\n        \"\"\"Prueft eine einzelne Rule gegen eine Datei.\"\"\"\n        check_type = rule.get(\"check_type\", \"\")\n\n        if check_type == \"line_count\":\n            self._check_line_count(file_path, content, rule, result)\n        elif check_type == \"forbidden_pattern\":\n            self._check_forbidden_pattern(file_path, content, rule, result)\n        elif check_type == \"required_pattern\":\n            self._check_required_pattern(file_path, content, rule, result)\n        elif check_type == \"dependency_check\":\n            self._check_dependency(file_path, content, rule, result)\n\n    def evaluate_legacy_forbidden(\n        self,\n        file_path: str,\n        content: str,\n        forbidden: list,\n        result: ContractValidationResult,\n    ) -> None:\n        \"\"\"Prueft auf verbotene Elemente (Legacy-Format).\"\"\"\n        for item in forbidden:\n            if isinstance(item, dict):\n                element = item.get(\"element\", \"\")\n                severity = item.get(\"severity\", \"minor\")\n                message = item.get(\"message\", f\"Forbidden element found: {element}\")\n            else:\n                element = str(item)\n                severity = \"minor\"\n                message = f\"Forbidden element found: {element}\"\n\n            if element and element in content:\n                self._add_violation(result, severity, {\n                    \"factor\": \"forbidden_element\",\n                    \"file\": file_path,\n                    \"message\": message,\n                })\n\n    def evaluate_legacy_required(\n        self,\n        file_path: str,\n        content: str,\n        required: list,\n        result: ContractValidationResult,\n    ) -> None:\n        \"\"\"Prueft auf erforderliche Elemente (Legacy-Format).\"\"\"\n        for item in required:\n            if isinstance(item, dict):\n                element = item.get(\"element\", \"\")\n                severity = item.get(\"severity\", \"major\")\n                message = item.get(\"message\", f\"Required element missing: {element}\")\n                applies_to = item.get(\"applies_to\", [])\n            else:\n                element = str(item)\n                severity = \"major\"\n                message = f\"Required element missing: {element}\"\n                applies_to = []\n\n            if applies_to:\n                matches = any(\n                    file_path.endswith(p.lstrip(\"*\")) for p in applies_to\n                )\n                if not matches:\n                    continue\n\n            if element and element not in content:\n                self._add_violation(result, severity, {\n                    \"factor\": \"required_element\",\n                    \"file\": file_path,\n                    \"message\": message,\n                })\n\n    def determine_outcome(self, result: ContractValidationResult) -> str:\n        \"\"\"Bestimmt das Validierungsergebnis basierend auf Violations.\"\"\"\n        if result.critical > 0:\n            return \"rejected\"\n        elif result.major > 2:\n            return \"revision_required\"\n        return \"passed\"\n\n    def _check_line_count(\n        self, file_path: str, content: str, rule: dict, result: ContractValidationResult\n    ) -> None:\n        \"\"\"Prueft Zeilenanzahl einer Datei.\"\"\"\n        max_lines = rule.get(\"max_lines\", 500)\n        line_count = len(content.splitlines())\n\n        if line_count > max_lines:\n            self._add_violation(result, rule.get(\"severity\", \"major\"), {\n                \"rule_id\": rule.get(\"id\", \"line_count\"),\n                \"factor\": \"line_count\",\n                \"file\": file_path,\n                \"message\": f\"File has {line_count} lines (max: {max_lines})\",\n                \"actual\": line_count,\n                \"limit\": max_lines,\n            })\n\n    def _check_forbidden_pattern(\n        self, file_path: str, content: str, rule: dict, result: ContractValidationResult\n    ) -> None:\n        \"\"\"Prueft auf verbotene Patterns.\"\"\"\n        patterns = rule.get(\"patterns\", [])\n\n        for pattern in patterns:\n            try:\n                matches = re.findall(pattern, content)\n            except re.error:\n                matches = [pattern] if pattern in content else []\n\n            if matches:\n                line_no = self._find_line_number(content, pattern)\n                self._add_violation(result, rule.get(\"severity\", \"major\"), {\n                    \"rule_id\": rule.get(\"id\", \"forbidden_pattern\"),\n                    \"factor\": \"forbidden_pattern\",\n                    \"file\": file_path,\n                    \"message\": f\"Forbidden pattern found: '{pattern}'\",\n                    \"description\": rule.get(\"description\", \"\"),\n                    \"line\": line_no,\n                    \"occurrences\": len(matches),\n                })\n\n    def _check_required_pattern(\n        self, file_path: str, content: str, rule: dict, result: ContractValidationResult\n    ) -> None:\n        \"\"\"Prueft auf erforderliche Patterns.\"\"\"\n        patterns = rule.get(\"patterns\", [])\n\n        for pattern in patterns:\n            try:\n                found = bool(re.search(pattern, content))\n            except re.error:\n                found = pattern in content\n\n            if not found:\n                self._add_violation(result, rule.get(\"severity\", \"major\"), {\n                    \"rule_id\": rule.get(\"id\", \"required_pattern\"),\n                    \"factor\": \"required_pattern\",\n                    \"file\": file_path,\n                    \"message\": f\"Required pattern not found: '{pattern}'\",\n                    \"description\": rule.get(\"description\", \"\"),\n                })\n\n    def _check_dependency(\n        self, file_path: str, content: str, rule: dict, result: ContractValidationResult\n    ) -> None:\n        \"\"\"Prueft auf verbotene Dependencies\/Imports.\"\"\"\n        forbidden_imports = rule.get(\"forbidden_imports\", [])\n\n        for forbidden in forbidden_imports:\n            php_pattern = rf\"use\\s+.*{re.escape(forbidden)}\"\n            py_pattern = rf\"(from|import)\\s+.*{re.escape(forbidden)}\"\n\n            try:\n                if re.search(php_pattern, content) or re.search(py_pattern, content):\n                    self._add_violation(result, rule.get(\"severity\", \"critical\"), {\n                        \"rule_id\": rule.get(\"id\", \"dependency_check\"),\n                        \"factor\": \"forbidden_dependency\",\n                        \"file\": file_path,\n                        \"message\": f\"Forbidden import\/dependency: '{forbidden}'\",\n                    })\n            except re.error:\n                pass\n\n    def _find_line_number(self, content: str, pattern: str) -> int | None:\n        \"\"\"Findet die Zeilennummer eines Patterns.\"\"\"\n        for i, line in enumerate(content.splitlines(), 1):\n            if pattern in line:\n                return i\n            try:\n                if re.search(pattern, line):\n                    return i\n            except re.error:\n                pass\n        return None\n\n    def _add_violation(\n        self, result: ContractValidationResult, severity: str, finding: dict\n    ) -> None:\n        \"\"\"Fuegt eine Violation zum Result hinzu.\"\"\"\n        finding[\"type\"] = severity\n\n        if severity == \"critical\":\n            result.critical += 1\n        elif severity == \"major\":\n            result.major += 1\n        else:\n            result.minor += 1\n\n        result.findings.append(finding)\n",
        "structuredPatch": [],
        "originalFile": null
    }
}
← Vorheriger Zur Liste Nächster →