diff --git a/.claude/settings.local.json b/.claude/settings.local.json
deleted file mode 100644
index 6b5c9c0..0000000
--- a/.claude/settings.local.json
+++ /dev/null
@@ -1,64 +0,0 @@
-{
- "permissions": {
- "allow": [
- "Bash(git add *)",
- "Bash(git commit *)",
- "Bash(git checkout *)",
- "Bash(git *)",
- "Bash(python *)",
- "Bash(python3 *)",
- "Bash(pytest test/ *)",
- "Bash(pytest test/test_*.py *)",
- "Bash(python -m pytest *)",
- "Bash(python -m py_compile *)",
- "Bash(python -m pylint *)",
- "Bash(flake8 .)",
- "Bash(flake8 *)",
- "Bash(bandit -r . -ll)",
- "Bash(bandit *)",
- "Bash(python ci/qgis_plugin_validate.py *)",
- "Bash(docker build *)",
- "Bash(docker run *)",
- "Bash(docker --version)",
- "Bash(docker info *)",
- "Bash(gh issue *)",
- "Bash(gh pr *)",
- "Bash(pyrcc5 resources.qrc -o resources.py)",
- "Bash(.venv\\\\Scripts\\\\pytest.exe --tb=short)",
- "PowerShell(Head *)",
- "Skill(update-config)",
- "Bash(pylint --version)",
- "PowerShell(cd \"C:\\\\Users\\\\Oliver\\\\AppData\\\\Roaming\\\\QGIS\\\\QGIS3\\\\profiles\\\\default\\\\python\\\\plugins\\\\ibtoolpartion\"; $f=git diff --cached --name-only --diff-filter=ACM|Where-Object{$_ -match '\\\\.py$'}; if\\(!$f\\){ Write-Host 'Keine Python-Dateien staged - OK'; exit 0 }; Write-Host \"Gefunden: $f\")",
- "PowerShell(git *)",
- "PowerShell(cd \"C:\\\\Users\\\\Oliver\\\\AppData\\\\Roaming\\\\QGIS\\\\QGIS3\\\\profiles\\\\default\\\\python\\\\plugins\\\\ibtoolpartion\"; powershell.exe -ExecutionPolicy Bypass -File \".claude/pre_commit_checks.ps1\" 2>&1 | Select-Object -First 5)",
- "PowerShell(pylint *)",
- "PowerShell(cd \"C:\\\\Users\\\\Oliver\\\\AppData\\\\Roaming\\\\QGIS\\\\QGIS3\\\\profiles\\\\default\\\\python\\\\plugins\\\\ibtoolpartion\"; git diff --cached --name-only --diff-filter=ACM | Where-Object { $_ -match '\\\\.py$' })",
- "PowerShell(Get-ChildItem \"C:\\\\Users\\\\Oliver\\\\AppData\\\\Roaming\\\\QGIS\\\\QGIS3\\\\profiles\\\\default\\\\python\\\\plugins\\\\ibtoolpartion\\\\\" -File | Where-Object { $_.Extension -in \".py\", \".ui\", \".txt\" } | Select-Object Name)",
- "PowerShell(Get-Command *)",
- "PowerShell(& \"C:\\\\OSGeo4W\\\\apps\\\\qt5\\\\bin\\\\lrelease.exe\" \"C:\\\\Users\\\\Oliver\\\\AppData\\\\Roaming\\\\QGIS\\\\QGIS3\\\\profiles\\\\default\\\\python\\\\plugins\\\\ibtoolpartion\\\\i18n\\\\IbToolPartition_de.ts\" -qm \"C:\\\\Users\\\\Oliver\\\\AppData\\\\Roaming\\\\QGIS\\\\QGIS3\\\\profiles\\\\default\\\\python\\\\plugins\\\\ibtoolpartion\\\\i18n\\\\IbToolPartition_de.qm\")",
- "PowerShell(& \"C:\\\\OSGeo4W\\\\apps\\\\qt5\\\\bin\\\\lrelease.exe\" 2>&1 | Select-Object -First 3)",
- "PowerShell(lrelease *)",
- "Bash(.venv\\\\Scripts\\\\python -m pip show pytest-cov)",
- "Bash(where detect-secrets-hook *)",
- "Bash(where python *)",
- "Bash(C:\\\\Python37\\\\python.exe *)"
- ]
- },
- "hooks": {
- "PreToolUse": [
- {
- "matcher": "Bash",
- "hooks": [
- {
- "type": "command",
- "command": ".claude/pre_commit_checks.ps1",
- "if": "Bash(git commit *)",
- "shell": "powershell",
- "timeout": 120,
- "statusMessage": "Qualitätsprüfung: flake8 / pylint / bandit..."
- }
- ]
- }
- ]
- }
-}
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..bf635c9
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,32 @@
+# Zeilenenden repo-weit normalisieren: git speichert LF, die Arbeitskopie darf
+# plattformueblich sein. Ohne diese Datei meldete git unter Windows den halben
+# Baum als geaendert - ein reiner CRLF/LF-Unterschied ohne Inhaltsaenderung.
+* text=auto
+
+# Dateien, die im Linux-Container ausgefuehrt werden, brauchen LF auch in der
+# Arbeitskopie: CRLF laesst bash mit "\r: command not found" scheitern.
+Dockerfile text eol=lf
+*.sh text eol=lf
+*.yml text eol=lf
+*.yaml text eol=lf
+
+# Windows-Skripte umgekehrt.
+*.bat text eol=crlf
+*.ps1 text eol=crlf
+
+# Binaerdateien nie konvertieren. `text=auto` erkennt die meisten davon
+# ohnehin, die Liste macht es fuer die Geodatenformate explizit.
+*.png binary
+*.jpg binary
+*.ico binary
+*.qm binary
+*.zip binary
+*.gpkg binary
+*.shp binary
+*.shx binary
+*.dbf binary
+*.qix binary
+*.tif binary
+
+# Nicht als binaer markieren: *.asc (ESRI-ASCII-Grid), *.prj, *.cpg und *.qml
+# sind Textformate und werden von `text=auto` korrekt behandelt.
diff --git a/.idea/.gitignore b/.idea/.gitignore
deleted file mode 100644
index 26d3352..0000000
--- a/.idea/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-# Default ignored files
-/shelf/
-/workspace.xml
diff --git a/.idea/ibtoolpartion.iml b/.idea/ibtoolpartion.iml
deleted file mode 100644
index 1df408a..0000000
--- a/.idea/ibtoolpartion.iml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
deleted file mode 100644
index 105ce2d..0000000
--- a/.idea/inspectionProfiles/profiles_settings.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
deleted file mode 100644
index 648b138..0000000
--- a/.idea/misc.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
deleted file mode 100644
index 54f1504..0000000
--- a/.idea/modules.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
deleted file mode 100644
index 94a25f7..0000000
--- a/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/README.md b/README.md
index 309f380..a06e9d5 100644
--- a/README.md
+++ b/README.md
@@ -14,7 +14,7 @@ and
[`docs/quickstart.md`](https://github.com/IB-Tool/IB-Tool-3/blob/master/docs/quickstart.md)
for how it fits into IB-Tool 3's own workflow.
-IBTool needs four more input layers. Its sibling plugin
+IB-Tool 3 needs four more input layers. Its sibling plugin
**[Data Wizard](https://github.com/IB-Tool/data_wizard)** produces the
`HU` / `RN` / `Aux` layers from raw ATKIS Basis-DLM data — the building
footprints it outputs can be fed straight into this plugin as input.
diff --git a/docs/test-strategy.md b/docs/test-strategy.md
index 5286f60..6dcb965 100644
--- a/docs/test-strategy.md
+++ b/docs/test-strategy.md
@@ -6,7 +6,7 @@ This document is the single authoritative reference for **why** the test suite i
- A tutorial on pytest syntax — see the pytest documentation.
- A list of tactical rules for geometry checks or test structure — see [`ai/core/testing-rules.md`](../ai/core/testing-rules.md).
-This plugin is a companion to **[IBTool](https://github.com/IB-Tool/IB-Tool-3)** and mirrors its testing conventions at a scale appropriate for a single-module plugin. See [IBTool's own `docs/test-strategy.md`](https://github.com/IB-Tool/IB-Tool-3/blob/master/docs/test-strategy.md) for the full-size version of this document.
+This plugin is a companion to **[IB-Tool 3](https://github.com/IB-Tool/IB-Tool-3)** and mirrors its testing conventions at a scale appropriate for a single-module plugin. See [IB-Tool 3's own `docs/test-strategy.md`](https://github.com/IB-Tool/IB-Tool-3/blob/master/docs/test-strategy.md) for the full-size version of this document.
---
@@ -209,6 +209,8 @@ def test_single_building(self, plugin, tmp_path):
|---|---|
| Full `run()` success path untested | Add a unit test that configures the mock dialog with valid paths/`cell_size`, stubs `siedgr()`, and asserts the success `pushMessage` call |
| No `@pytest.mark.performance` test for `siedgr()` at scale | Add a `performance` + `slow` test with 50+ buildings, asserting it completes within a stated time budget |
+| A missing `qgis:heatmapkerneldensityestimation` skips every `siedgr()` integration test without failing | The collection-time `skipif` in `test_siedgr_integration.py` keeps the suite green even when the algorithm is absent from the Processing build — CI then reports success while `siedgr()` has zero real coverage. In the Docker image the algorithm *must* be present: make its absence a hard error there (assert it is registered when `QGIS_PREFIX_PATH=/usr`) and keep the skip for local runs only |
+| `siedgr()` is a single ~120-line method with 12 `processing.run()` calls | Its steps cannot be tested individually — any failing step surfaces as "the whole pipeline is wrong". Splitting it into named steps (centroids → heatmap → voronoi → cleanup → polygonize) would let the integration tests pinpoint failures. It also still writes to stdout via `print()` instead of the QGIS logger (`IbToolPartion.py`, `run()`) |
### Priority 2 — Larger effort, lower urgency
@@ -262,4 +264,3 @@ pytest test/test_siedgr_integration.py -v
|------|---------|
| [`docs/contributing.md`](contributing.md) | CI/CD pipeline, Docker environment, code linting |
| [`ai/core/testing-rules.md`](../ai/core/testing-rules.md) | Tactical rules: geometry checks, test structure, framework conventions |
-| [`docs/Testplan-data_wizard-ibtoolpartion.md`](Testplan-data_wizard-ibtoolpartion.md) | Implementation plan this document and the current test suite were built from |
diff --git a/i18n/IbToolPartition_de.qm b/i18n/IbToolPartition_de.qm
deleted file mode 100644
index ad6557e..0000000
Binary files a/i18n/IbToolPartition_de.qm and /dev/null differ
diff --git a/test/test_plugin_structure.py b/test/test_plugin_structure.py
index 0d1b637..826a63d 100644
--- a/test/test_plugin_structure.py
+++ b/test/test_plugin_structure.py
@@ -1,11 +1,10 @@
# -*- coding: utf-8 -*-
"""Structural tests that don't require QGIS to be available.
-Taken over from the former test/test_test.py (dissolved — see
-docs/Testplan-data_wizard-ibtoolpartion.md Phase 3.3). The other tests that
-used to live there duplicated coverage found elsewhere or tested the Python
-standard library / MagicMock itself and carried no assertion value, so they
-were dropped rather than moved.
+Taken over from the former test/test_test.py, which was dissolved. The other
+tests that used to live there duplicated coverage found elsewhere or tested
+the Python standard library / MagicMock itself and carried no assertion
+value, so they were dropped rather than moved.
"""
import sys
from pathlib import Path
diff --git a/test/test_siedgr_integration.py b/test/test_siedgr_integration.py
index addca94..f3bde4c 100644
--- a/test/test_siedgr_integration.py
+++ b/test/test_siedgr_integration.py
@@ -7,14 +7,13 @@
test/layer_factories.py and written to tmp_path — no test data checked into
the repository is needed.
-Requires a full QGIS Processing environment (Docker, see
-docs/Testplan-data_wizard-ibtoolpartion.md Phase 3.2). All tests are skipped
+Requires a full QGIS Processing environment (Docker). All tests are skipped
automatically when QGIS is unavailable, and again when the
qgis:heatmapkerneldensityestimation algorithm siedgr() depends on is not
-registered in the running QGIS/Processing build (this is checked at
-collection time instead of via the one-off Docker experiment described in
-the plan, so the gap is self-documenting no matter which QGIS image runs
-these tests).
+registered in the running QGIS/Processing build (checked at collection time,
+so the gap is self-documenting no matter which QGIS image runs these tests -
+see docs/test-strategy.md, Gap Analysis, on why a silent skip is not enough
+in CI).
"""
# pylint: disable=possibly-used-before-assignment
# QgsWkbTypes/QgsVectorLayer/IbToolPartition/the layer_factories imports are