{
"event": "PreToolUse",
"tool_name": "Edit",
"tool_input": {
"file_path": "\/var\/www\/tools\/ki-protokoll\/claude-hook\/quality\/pre_rules_guard.py",
"old_string": "import re\nfrom pathlib import Path\nfrom typing import Optional\nfrom .rule_base import GLOBAL_ALLOWLIST, is_in_allowlist\n\n\n# =============================================================================\n# HELPER FUNCTIONS\n# =============================================================================\n\ndef block(rule_id: str, message: str) -> dict:\n \"\"\"Erzeugt Block-Response.\"\"\"\n return {\n \"allowed\": False,\n \"message\": f\"QUALITY VIOLATION [{rule_id}]: {message}\"\n }",
"new_string": "import re\nfrom pathlib import Path\nfrom typing import Optional\nfrom .rule_base import GLOBAL_ALLOWLIST, is_in_allowlist, block"
}
}
{
"tool_response": {
"filePath": "\/var\/www\/tools\/ki-protokoll\/claude-hook\/quality\/pre_rules_guard.py",
"oldString": "import re\nfrom pathlib import Path\nfrom typing import Optional\nfrom .rule_base import GLOBAL_ALLOWLIST, is_in_allowlist\n\n\n# =============================================================================\n# HELPER FUNCTIONS\n# =============================================================================\n\ndef block(rule_id: str, message: str) -> dict:\n \"\"\"Erzeugt Block-Response.\"\"\"\n return {\n \"allowed\": False,\n \"message\": f\"QUALITY VIOLATION [{rule_id}]: {message}\"\n }",
"newString": "import re\nfrom pathlib import Path\nfrom typing import Optional\nfrom .rule_base import GLOBAL_ALLOWLIST, is_in_allowlist, block",
"originalFile": "#!\/usr\/bin\/env python3\n\"\"\"\nPre-Hook Guard Regeln (BLOCK) - SRP + OOP Basics.\n\nP1.x Regeln: Single Responsibility, KISS, Naming\nP4.x Regeln: OOP Basics, Encapsulation\n\"\"\"\n\nimport re\nfrom pathlib import Path\nfrom typing import Optional\nfrom .rule_base import GLOBAL_ALLOWLIST, is_in_allowlist\n\n\n# =============================================================================\n# HELPER FUNCTIONS\n# =============================================================================\n\ndef block(rule_id: str, message: str) -> dict:\n \"\"\"Erzeugt Block-Response.\"\"\"\n return {\n \"allowed\": False,\n \"message\": f\"QUALITY VIOLATION [{rule_id}]: {message}\"\n }\n\n\n# =============================================================================\n# PRÜFUNG 1: SRP + KISS\n# =============================================================================\n\ndef p1_1_responsibility_header(file_path: str, content: str) -> Optional[dict]:\n \"\"\"P1.1: @responsibility Header erforderlich.\"\"\"\n if is_in_allowlist(file_path, GLOBAL_ALLOWLIST):\n return None\n\n header_pattern = r\"\/\/\\s*@responsibility:\\s*(.+)\"\n match = re.search(header_pattern, content)\n\n if not match:\n return block(\"P1.1\", \"Missing @responsibility header. Add: \/\/ @responsibility: <single-responsibility>\")\n\n responsibility_text = match.group(1).strip()\n\n # Prüfe auf Multi-Responsibility-Wörter\n multi_words = r\"\\b(und|sowie|außerdem|also|zusätzlich|and|also|additionally)\\b\"\n if re.search(multi_words, responsibility_text, re.IGNORECASE):\n return block(\"P1.1\", f\"@responsibility contains multi-responsibility indicator: '{responsibility_text}'\")\n\n return None\n\n\ndef p1_2_garbage_names(file_path: str, content: str) -> Optional[dict]:\n \"\"\"P1.2: Müllhalden-Namen blockieren.\"\"\"\n if is_in_allowlist(file_path, GLOBAL_ALLOWLIST):\n return None\n\n filename = Path(file_path).stem.lower()\n forbidden = [\"helper\", \"utils\", \"common\", \"misc\", \"base\"]\n\n for term in forbidden:\n if term in filename:\n return block(\"P1.2\", f\"Forbidden name pattern: '{term}' indicates unclear responsibility\")\n\n return None\n\n\n# =============================================================================\n# PRÜFUNG 4: OOP\n# =============================================================================\n\ndef p4_1_no_public_properties_in_domain(file_path: str, content: str) -> Optional[dict]:\n \"\"\"P4.1: Keine public Properties in Domain.\"\"\"\n if \"\/Domain\/\" not in file_path:\n return None\n if is_in_allowlist(file_path, GLOBAL_ALLOWLIST):\n return None\n\n # public readonly ist erlaubt\n public_props = re.findall(\n r\"public\\s+(?!readonly|function|const|static\\s+function).*\\$\\w+\",\n content\n )\n\n if public_props:\n return block(\"P4.1\", \"Public property in Domain. Use getter methods or public readonly.\")\n\n return None\n\n\n# =============================================================================\n# RULE COLLECTION\n# =============================================================================\n\nRULES = [\n p1_1_responsibility_header,\n p1_2_garbage_names,\n p4_1_no_public_properties_in_domain,\n]\n",
"structuredPatch": [
{
"oldStart": 9,
"oldLines": 22,
"newStart": 9,
"newLines": 10,
"lines": [
" import re",
" from pathlib import Path",
" from typing import Optional",
"-from .rule_base import GLOBAL_ALLOWLIST, is_in_allowlist",
"+from .rule_base import GLOBAL_ALLOWLIST, is_in_allowlist, block",
" ",
" ",
" # =============================================================================",
"-# HELPER FUNCTIONS",
"-# =============================================================================",
"-",
"-def block(rule_id: str, message: str) -> dict:",
"- \"\"\"Erzeugt Block-Response.\"\"\"",
"- return {",
"- \"allowed\": False,",
"- \"message\": f\"QUALITY VIOLATION [{rule_id}]: {message}\"",
"- }",
"-",
"-",
"-# =============================================================================",
" # PRÜFUNG 1: SRP + KISS",
" # =============================================================================",
" "
]
}
],
"userModified": false,
"replaceAll": false
}
}