Protokoll #4178
| ID | 4178 |
|---|---|
| Zeitstempel | 2025-12-22 09:27:46.535074 |
| 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,968 (Input: 0, Output: 0) |
| Dauer | 88 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": "\/opt\/mcp-servers\/mcp-contracts\/validators\/contract_validator.py"
}
}
Response
{
"tool_response": {
"type": "text",
"file": {
"filePath": "\/opt\/mcp-servers\/mcp-contracts\/validators\/contract_validator.py",
"content": "\"\"\"Contract Validator - YAML-Validierung und Scope-Prüfung\"\"\"\nimport os\nimport sys\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",
"numLines": 201,
"startLine": 1,
"totalLines": 201
}
}
}