load_ga_export, entity naming, climate setpoint shift; fix suggest_repairs crash; CI runs every test

Three things found by auditing a TapPlan export, plus one regression found on the way.

load_ga_export(path): new tool. Reads an ETS ga-export/01 XML (ETS "Export Group
Addresses", or the import file a planning tool writes) into a project without
devices, through safe_fromstring, capped at 50 MB and 8 levels of range nesting.
Invalid or duplicate addresses and unknown DPT tokens go to import_warnings, never
silently. Round trip with our own generate_ets_xml is covered by a test.

Entity naming: lights, covers and climates are named after the common word prefix
of their member names, cutting only function words. The first version of the rule
turned "01. <room> - All Blinds - Move" into "01" on a real project, so anything not
in the function vocabulary now stays. On six real projects 214 of 1189 entities got
a shorter name, each rename reviewed, no address mapping changed. Regenerated
packages show different names; noted in the changelog.

Setpoint shift: 9.002 / 6.010 with a shift word maps to setpoint_shift_address,
setpoint_shift_state_address and setpoint_shift_mode (keys checked against the HA
KNX climate docs). It used to become a plain sensor.

Fixed: suggest_repairs raised UnboundLocalError on any project with a missing status
GA. My local rename in the 12.09 typing cleanup left two references to the old name.
test_council_fixes covers it but was not in CI, so it shipped. CI now runs all 21
test files instead of a hand-picked 10; the 11 added ones pass from a clean clone.

Verified: all 21 tests, ruff, mypy with the package installed, corpus guard no drift.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Nikolay Miroshnichenko
2026-09-14 00:11:45 +02:00
co-authored by Claude Opus 5
parent 29bfba7684
commit ec63bcf106
8 changed files with 583 additions and 8 deletions
+36
View File
@@ -76,6 +76,42 @@ jobs:
- name: Stable ordering + cursor paging for large tool results
run: python tests/test_paging.py
- name: GA-export intake, entity naming, climate setpoint shift
run: python tests/test_ga_export.py
- name: Repair proposals and council-review fixes
run: python tests/test_council_fixes.py
- name: Domain classifier (name + DPT + range context)
run: python tests/test_domain_classifier.py
- name: explain_ga provenance
run: python tests/test_explain.py
- name: Aggregates carry their evidence
run: python tests/test_explainable_aggregates.py
- name: Device parameter checks
run: python tests/test_param_check.py
- name: Value-status completeness (brightness / position)
run: python tests/test_role_completeness.py
- name: Room template library
run: python tests/test_room_library.py
- name: Root-cause regressions
run: python tests/test_root_cause.py
- name: Hardened archive and XML parsing
run: python tests/test_safexml.py
- name: Theben reference projects
run: python tests/test_theben_corrections.py
- name: Topology limits
run: python tests/test_topology.py
- name: Console script is installed
run: |
python -c "import importlib.metadata as m; print('entry points:', [e.name for e in m.entry_points(group='console_scripts') if e.name == 'nickol-knx-mcp'])"