diff --git a/.planning/phases/01-hexagonal-refactor/01-06-SUMMARY.md b/.planning/phases/01-hexagonal-refactor/01-06-SUMMARY.md new file mode 100644 index 0000000..d00561c --- /dev/null +++ b/.planning/phases/01-hexagonal-refactor/01-06-SUMMARY.md @@ -0,0 +1,101 @@ +--- +phase: "01" +plan: "06" +subsystem: mavlink_io +tags: [refactor, hexagonal, mavlink, shim] +dependency_graph: + requires: [01-05] + provides: [components/mavlink_io] + affects: [core/mavlink.py] +tech_stack: + added: [] + patterns: [shim-re-export, circular-import-avoidance-via-local-imports] +key_files: + created: + - src/gps_denied/components/mavlink_io/pymavlink_bridge.py + - src/gps_denied/components/mavlink_io/mock_mavlink.py + modified: + - src/gps_denied/components/mavlink_io/__init__.py + - src/gps_denied/core/mavlink.py +decisions: + - "Used local (deferred) imports of MockMAVConnection inside MAVLinkBridge methods to avoid circular import between pymavlink_bridge and mock_mavlink" + - "Shim re-exports all seven names including three private helpers (_confidence_to_fix_type, _eskf_to_gps_input, _unix_to_gps_time) per CRITICAL warning" +metrics: + duration: "~5 minutes" + completed: "2026-05-11" + tasks: 5 + files: 4 +--- + +# Phase 01 Plan 06: MAVLink I/O Split Summary + +Split `core/mavlink.py` (483 LOC) into component modules under `components/mavlink_io/`, replacing the original with a shim that re-exports all public and private names verbatim. + +## LOC Distribution + +| File | LOC | Contents | +|------|-----|----------| +| `components/mavlink_io/pymavlink_bridge.py` | 455 | MAVLinkBridge class + 3 module-level helpers + pymavlink conditional import | +| `components/mavlink_io/mock_mavlink.py` | 30 | MockMAVConnection (no-op for dev/CI) | +| `core/mavlink.py` (shim) | 29 | Re-export shim only | +| `components/mavlink_io/__init__.py` | 20 | Package surface | + +Original: 483 LOC → split across 4 files (514 total including shim and `__init__.py`). + +## Test Counts + +| Test file | Result | +|-----------|--------| +| `tests/test_mavlink.py` | 32 passed | +| `tests/test_gps_input_encoding.py` | included in the 32 above | +| Full regression (`tests/`) | 216 passed, 8 skipped | + +Regression floor: 216 passed (baseline). Status: MAINTAINED. + +## Private Helper Verification + +The three underscore names required by `test_mavlink.py` and `test_gps_input_encoding.py` resolve correctly via the shim: + +``` +python -c "from gps_denied.core.mavlink import _confidence_to_fix_type, _eskf_to_gps_input, _unix_to_gps_time; print('private helpers ok')" +# Output: private helpers ok +``` + +All three are exported from `core/mavlink.py` → `components/mavlink_io/pymavlink_bridge.py` → callable. + +## `_PYMAVLINK_AVAILABLE` on Dev Machine + +``` +_PYMAVLINK_AVAILABLE = True +``` + +pymavlink is installed on this development machine, so `MAVLinkBridge._open_connection()` will attempt a real connection before falling back to `MockMAVConnection`. + +## Deviations from Plan + +### Auto-fixed Issues + +**1. [Rule 3 - Blocking] Circular import between pymavlink_bridge and mock_mavlink** + +- **Found during:** Task 1 (design review before writing) +- **Issue:** `pymavlink_bridge.py` (MAVLinkBridge) uses `isinstance(self._conn, MockMAVConnection)` checks. If `mock_mavlink.py` were imported at module level in `pymavlink_bridge.py`, and `__init__.py` imports both, a circular import chain would form. +- **Fix:** Used local (deferred) imports of `MockMAVConnection` inside each method that references it (`_send_gps_input`, `_recv_imu`, `_send_reloc_request`, `_send_telemetry`, `_open_connection`). This matches the pattern used in similar hexagonal refactors in this codebase. +- **Files modified:** `pymavlink_bridge.py` +- **Commit:** f965ac7 + +## Known Stubs + +None. All data paths are wired: bridge reads from live ESKFState, writes to real or mock MAVLink connection. + +## Threat Flags + +None. No new network endpoints or auth paths introduced. The MAVLink UART connection was already present in the original `core/mavlink.py`. + +## Self-Check: PASSED + +- `src/gps_denied/components/mavlink_io/pymavlink_bridge.py` — FOUND +- `src/gps_denied/components/mavlink_io/mock_mavlink.py` — FOUND +- `src/gps_denied/components/mavlink_io/__init__.py` — FOUND (updated) +- `src/gps_denied/core/mavlink.py` — FOUND (shim, 29 LOC) +- Commit f965ac7 — FOUND +- 216 tests passed — CONFIRMED