Protokoll #4314

ID4314
Zeitstempel2025-12-22 09:50:12.323122
Clientroot
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
Modellclaude-sonnet-4-20250514
Statuscompleted
Tokens4,216 (Input: 0, Output: 0)
Dauer98 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": "\/opt\/mcp-servers\/mcp-contracts\/validators\/contract_validator.py",
        "old_string": "    def _get_check_paths(self, target_path: Optional[str] = None) -> List[str]:\n        \"\"\"Ermittelt zu prüfende Pfade aus Scope\"\"\"\n        if target_path:\n            return [target_path]\n\n        check_paths = []\n        scope = self.contract_data.get(\"contract\", {}).get(\"scope\", {})\n\n        if \"includes\" in scope:\n            for inc in scope[\"includes\"]:\n                # Glob-Pattern zu Pfad konvertieren\n                pattern_path = inc.replace(\"*\", \"\").rstrip(\"\/\")\n                full_path = os.path.join(self.BASE_PATH, pattern_path.lstrip(\"\/\"))\n                if os.path.exists(full_path):\n                    check_paths.append(full_path)\n\n        return check_paths",
        "new_string": "    def _get_check_paths(self, target_path: Optional[str] = None) -> List[str]:\n        \"\"\"Ermittelt zu prüfende Pfade aus Scope (unterstützt alle Formate)\"\"\"\n        if target_path:\n            return [target_path]\n\n        check_paths = []\n        contract = self.contract_data.get(\"contract\", {})\n        scope = contract.get(\"scope\", {})\n\n        # Neues Standard-Format: scope.paths\n        paths_list = scope.get(\"paths\", [])\n\n        # Legacy-Formate als Fallback\n        if not paths_list:\n            paths_list = scope.get(\"includes\", [])  # Legacy: scope.includes\n        if not paths_list:\n            paths_list = scope.get(\"applies_to_paths\", [])  # Legacy\n        if not paths_list:\n            # Legacy: applicability.scope\n            applicability = self.contract_data.get(\"applicability\", {})\n            paths_list = applicability.get(\"scope\", [])\n            if isinstance(paths_list, str):\n                paths_list = [paths_list]\n\n        excludes = scope.get(\"excludes\", [])\n\n        for pattern in paths_list:\n            # Glob-Pattern expandieren\n            full_pattern = os.path.join(self.BASE_PATH, pattern.lstrip(\"\/\"))\n            matched = globlib.glob(full_pattern, recursive=True)\n\n            if matched:\n                for path in matched:\n                    # Excludes prüfen\n                    excluded = False\n                    for excl in excludes:\n                        excl_pattern = os.path.join(self.BASE_PATH, excl.lstrip(\"\/\"))\n                        if globlib.fnmatch.fnmatch(path, excl_pattern):\n                            excluded = True\n                            break\n                    if not excluded:\n                        check_paths.append(path)\n            else:\n                # Falls kein Match, versuche Basisverzeichnis\n                pattern_path = pattern.replace(\"**\", \"\").replace(\"*\", \"\").rstrip(\"\/\")\n                full_path = os.path.join(self.BASE_PATH, pattern_path.lstrip(\"\/\"))\n                if os.path.exists(full_path):\n                    check_paths.append(full_path)\n\n        return list(set(check_paths))  # Duplikate entfernen"
    }
}

Response

{
    "tool_response": {
        "filePath": "\/opt\/mcp-servers\/mcp-contracts\/validators\/contract_validator.py",
        "oldString": "    def _get_check_paths(self, target_path: Optional[str] = None) -> List[str]:\n        \"\"\"Ermittelt zu prüfende Pfade aus Scope\"\"\"\n        if target_path:\n            return [target_path]\n\n        check_paths = []\n        scope = self.contract_data.get(\"contract\", {}).get(\"scope\", {})\n\n        if \"includes\" in scope:\n            for inc in scope[\"includes\"]:\n                # Glob-Pattern zu Pfad konvertieren\n                pattern_path = inc.replace(\"*\", \"\").rstrip(\"\/\")\n                full_path = os.path.join(self.BASE_PATH, pattern_path.lstrip(\"\/\"))\n                if os.path.exists(full_path):\n                    check_paths.append(full_path)\n\n        return check_paths",
        "newString": "    def _get_check_paths(self, target_path: Optional[str] = None) -> List[str]:\n        \"\"\"Ermittelt zu prüfende Pfade aus Scope (unterstützt alle Formate)\"\"\"\n        if target_path:\n            return [target_path]\n\n        check_paths = []\n        contract = self.contract_data.get(\"contract\", {})\n        scope = contract.get(\"scope\", {})\n\n        # Neues Standard-Format: scope.paths\n        paths_list = scope.get(\"paths\", [])\n\n        # Legacy-Formate als Fallback\n        if not paths_list:\n            paths_list = scope.get(\"includes\", [])  # Legacy: scope.includes\n        if not paths_list:\n            paths_list = scope.get(\"applies_to_paths\", [])  # Legacy\n        if not paths_list:\n            # Legacy: applicability.scope\n            applicability = self.contract_data.get(\"applicability\", {})\n            paths_list = applicability.get(\"scope\", [])\n            if isinstance(paths_list, str):\n                paths_list = [paths_list]\n\n        excludes = scope.get(\"excludes\", [])\n\n        for pattern in paths_list:\n            # Glob-Pattern expandieren\n            full_pattern = os.path.join(self.BASE_PATH, pattern.lstrip(\"\/\"))\n            matched = globlib.glob(full_pattern, recursive=True)\n\n            if matched:\n                for path in matched:\n                    # Excludes prüfen\n                    excluded = False\n                    for excl in excludes:\n                        excl_pattern = os.path.join(self.BASE_PATH, excl.lstrip(\"\/\"))\n                        if globlib.fnmatch.fnmatch(path, excl_pattern):\n                            excluded = True\n                            break\n                    if not excluded:\n                        check_paths.append(path)\n            else:\n                # Falls kein Match, versuche Basisverzeichnis\n                pattern_path = pattern.replace(\"**\", \"\").replace(\"*\", \"\").rstrip(\"\/\")\n                full_path = os.path.join(self.BASE_PATH, pattern_path.lstrip(\"\/\"))\n                if os.path.exists(full_path):\n                    check_paths.append(full_path)\n\n        return list(set(check_paths))  # Duplikate entfernen",
        "originalFile": "\"\"\"Contract Validator - YAML-Validierung und Scope-Prüfung\"\"\"\nimport os\nimport re\nimport sys\nimport glob as globlib\nfrom typing import Optional, Dict, Any, List\n\nimport yaml\n\nsys.path.insert(0, \"\/opt\/mcp-servers\/mcp-contracts\")\nfrom domain.contracts import ContractValidationResult\n\n\nclass ContractValidator:\n    \"\"\"Validiert Contracts gegen ihren definierten Scope\"\"\"\n\n    BASE_PATH = \"\/var\/www\/dev.campus.systemische-tools.de\"\n\n    def __init__(self, contract_data: Dict[str, Any]):\n        self.contract_data = contract_data\n        self.contract_name = contract_data.get(\"contract\", {}).get(\"name\", \"unknown\")\n\n    def validate(self, target_path: Optional[str] = None) -> ContractValidationResult:\n        \"\"\"Führt vollständige Validierung durch\"\"\"\n        result = ContractValidationResult(\n            contract=self.contract_name,\n            outcome=\"passed\",\n            critical=0,\n            major=0,\n            minor=0,\n            findings=[],\n        )\n\n        # Scope ermitteln\n        check_paths = self._get_check_paths(target_path)\n\n        if not check_paths:\n            result.findings.append({\n                \"type\": \"info\",\n                \"message\": \"No paths to validate\",\n            })\n            return result\n\n        # Dateien validieren\n        for check_path in check_paths:\n            if not os.path.exists(check_path):\n                result.critical += 1\n                result.findings.append({\n                    \"type\": \"critical\",\n                    \"factor\": \"path_existence\",\n                    \"message\": f\"Path does not exist: {check_path}\",\n                })\n                continue\n\n            if os.path.isdir(check_path):\n                self._validate_directory(check_path, result)\n            else:\n                self._validate_file(check_path, result)\n\n        # Outcome bestimmen\n        result.outcome = self._determine_outcome(result)\n\n        return result\n\n    def _get_check_paths(self, target_path: Optional[str] = None) -> List[str]:\n        \"\"\"Ermittelt zu prüfende Pfade aus Scope\"\"\"\n        if target_path:\n            return [target_path]\n\n        check_paths = []\n        scope = self.contract_data.get(\"contract\", {}).get(\"scope\", {})\n\n        if \"includes\" in scope:\n            for inc in scope[\"includes\"]:\n                # Glob-Pattern zu Pfad konvertieren\n                pattern_path = inc.replace(\"*\", \"\").rstrip(\"\/\")\n                full_path = os.path.join(self.BASE_PATH, pattern_path.lstrip(\"\/\"))\n                if os.path.exists(full_path):\n                    check_paths.append(full_path)\n\n        return check_paths\n\n    def _validate_directory(self, dir_path: str, result: ContractValidationResult) -> None:\n        \"\"\"Validiert alle Dateien in einem Verzeichnis\"\"\"\n        for root, dirs, files in os.walk(dir_path):\n            for f in files:\n                if f.endswith((\".php\", \".js\", \".css\", \".py\")):\n                    file_path = os.path.join(root, f)\n                    self._validate_file(file_path, result)\n\n    def _validate_file(self, file_path: str, result: ContractValidationResult) -> None:\n        \"\"\"Validiert eine einzelne Datei gegen den Contract\"\"\"\n        try:\n            with open(file_path, \"r\", encoding=\"utf-8\") as f:\n                content = f.read()\n\n            # Forbidden elements prüfen\n            self._check_forbidden_elements(file_path, content, result)\n\n            # Required elements prüfen\n            self._check_required_elements(file_path, content, result)\n\n        except Exception as e:\n            result.minor += 1\n            result.findings.append({\n                \"type\": \"minor\",\n                \"factor\": \"file_read_error\",\n                \"file\": file_path,\n                \"message\": str(e)[:100],\n            })\n\n    def _check_forbidden_elements(\n        self, file_path: str, content: str, result: ContractValidationResult\n    ) -> None:\n        \"\"\"Prüft auf verbotene Elemente\"\"\"\n        forbidden = self.contract_data.get(\"contract\", {}).get(\"forbidden\", [])\n\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                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({\n                    \"type\": severity,\n                    \"factor\": \"forbidden_element\",\n                    \"file\": file_path,\n                    \"message\": message,\n                })\n\n    def _check_required_elements(\n        self, file_path: str, content: str, result: ContractValidationResult\n    ) -> None:\n        \"\"\"Prüft auf erforderliche Elemente\"\"\"\n        required = self.contract_data.get(\"contract\", {}).get(\"required\", [])\n\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            # applies_to prüfen (z.B. nur für bestimmte Dateiendungen)\n            if applies_to:\n                matches = False\n                for pattern in applies_to:\n                    if file_path.endswith(pattern.lstrip(\"*\")):\n                        matches = True\n                        break\n                if not matches:\n                    continue\n\n            if element and element not in content:\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({\n                    \"type\": 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        else:\n            return \"passed\"\n\n\ndef run_contract_validation(\n    contract_data: Dict[str, Any],\n    target_path: Optional[str] = None\n) -> ContractValidationResult:\n    \"\"\"Hilfsfunktion für Contract-Validierung\"\"\"\n    validator = ContractValidator(contract_data)\n    return validator.validate(target_path)\n",
        "structuredPatch": [
            {
                "oldStart": 63,
                "oldLines": 22,
                "newStart": 63,
                "newLines": 55,
                "lines": [
                    "         return result",
                    " ",
                    "     def _get_check_paths(self, target_path: Optional[str] = None) -> List[str]:",
                    "-        \"\"\"Ermittelt zu prüfende Pfade aus Scope\"\"\"",
                    "+        \"\"\"Ermittelt zu prüfende Pfade aus Scope (unterstützt alle Formate)\"\"\"",
                    "         if target_path:",
                    "             return [target_path]",
                    " ",
                    "         check_paths = []",
                    "-        scope = self.contract_data.get(\"contract\", {}).get(\"scope\", {})",
                    "+        contract = self.contract_data.get(\"contract\", {})",
                    "+        scope = contract.get(\"scope\", {})",
                    " ",
                    "-        if \"includes\" in scope:",
                    "-            for inc in scope[\"includes\"]:",
                    "-                # Glob-Pattern zu Pfad konvertieren",
                    "-                pattern_path = inc.replace(\"*\", \"\").rstrip(\"\/\")",
                    "+        # Neues Standard-Format: scope.paths",
                    "+        paths_list = scope.get(\"paths\", [])",
                    "+",
                    "+        # Legacy-Formate als Fallback",
                    "+        if not paths_list:",
                    "+            paths_list = scope.get(\"includes\", [])  # Legacy: scope.includes",
                    "+        if not paths_list:",
                    "+            paths_list = scope.get(\"applies_to_paths\", [])  # Legacy",
                    "+        if not paths_list:",
                    "+            # Legacy: applicability.scope",
                    "+            applicability = self.contract_data.get(\"applicability\", {})",
                    "+            paths_list = applicability.get(\"scope\", [])",
                    "+            if isinstance(paths_list, str):",
                    "+                paths_list = [paths_list]",
                    "+",
                    "+        excludes = scope.get(\"excludes\", [])",
                    "+",
                    "+        for pattern in paths_list:",
                    "+            # Glob-Pattern expandieren",
                    "+            full_pattern = os.path.join(self.BASE_PATH, pattern.lstrip(\"\/\"))",
                    "+            matched = globlib.glob(full_pattern, recursive=True)",
                    "+",
                    "+            if matched:",
                    "+                for path in matched:",
                    "+                    # Excludes prüfen",
                    "+                    excluded = False",
                    "+                    for excl in excludes:",
                    "+                        excl_pattern = os.path.join(self.BASE_PATH, excl.lstrip(\"\/\"))",
                    "+                        if globlib.fnmatch.fnmatch(path, excl_pattern):",
                    "+                            excluded = True",
                    "+                            break",
                    "+                    if not excluded:",
                    "+                        check_paths.append(path)",
                    "+            else:",
                    "+                # Falls kein Match, versuche Basisverzeichnis",
                    "+                pattern_path = pattern.replace(\"**\", \"\").replace(\"*\", \"\").rstrip(\"\/\")",
                    "                 full_path = os.path.join(self.BASE_PATH, pattern_path.lstrip(\"\/\"))",
                    "                 if os.path.exists(full_path):",
                    "                     check_paths.append(full_path)",
                    " ",
                    "-        return check_paths",
                    "+        return list(set(check_paths))  # Duplikate entfernen",
                    " ",
                    "     def _validate_directory(self, dir_path: str, result: ContractValidationResult) -> None:",
                    "         \"\"\"Validiert alle Dateien in einem Verzeichnis\"\"\""
                ]
            }
        ],
        "userModified": false,
        "replaceAll": false
    }
}
← Vorheriger Zur Liste Nächster →