Context
Audit 2026-04-23 found that core/ports/qgis_port.py exists as the intended abstraction boundary but is bypassed by 52 files in core/. 37+ services and 5 domain modules import qgis.PyQt or qgis.core directly — defeating the stated hexagonal design.
Representative violations:
Consequences
- Unit tests against
core/ must load PyQGIS (slow + fragile).
- Swapping providers requires edits across the whole core tree.
- QGIS4/PyQt6 migrations become multi-tree diffs instead of adapter-layer diffs.
Proposed sequencing (multi-sprint)
Phase 1 — Audit & Port
Phase 2 — Tasks
Phase 3 — Services
Phase 4 — Domain
Phase 5 — Lint
Priority
EPIC — multi-sprint. Pair with H3/H4 refactors; they are natural entry points since they already live in the boundary.
Acceptance
Part of: [AUDIT] EPIC — Audit 2026-04-23 follow-ups
Context
Audit 2026-04-23 found that
core/ports/qgis_port.pyexists as the intended abstraction boundary but is bypassed by 52 files incore/. 37+ services and 5 domain modules importqgis.PyQtorqgis.coredirectly — defeating the stated hexagonal design.Representative violations:
QgsTask,pyqtSignalpyqtSignal, QObjectConsequences
core/must load PyQGIS (slow + fragile).Proposed sequencing (multi-sprint)
Phase 1 — Audit & Port
core/with categorization: task / service / domain.core/ports/with missing abstractions (TaskPort, SignalPort, GeometryPort, etc.).Phase 2 — Tasks
Phase 3 — Services
pyqtSignal/QObjectin services with a port-owned event bus.Phase 4 — Domain
core/domain/.Phase 5 — Lint
import-lintercontract) that fails CI onqgis.*imports insidecore/.Priority
EPIC — multi-sprint. Pair with H3/H4 refactors; they are natural entry points since they already live in the boundary.
Acceptance
grep -r "from qgis" core/returns 0 results.tests/unit/core/run without any QGIS import.Part of: [AUDIT] EPIC — Audit 2026-04-23 follow-ups