mirror of
https://github.com/azaion/gps-denied-onboard.git
synced 2026-06-22 19:51:13 +00:00
docs(01-07): complete plan summary for hexagonal refactor plan 07
This commit is contained in:
@@ -0,0 +1,152 @@
|
|||||||
|
---
|
||||||
|
phase: "01-hexagonal-refactor"
|
||||||
|
plan: "01-07"
|
||||||
|
subsystem: "core-restructure"
|
||||||
|
tags: ["refactor", "protocol", "pipeline", "abc-to-protocol", "shim"]
|
||||||
|
|
||||||
|
dependency_graph:
|
||||||
|
requires: ["01-05", "01-06"]
|
||||||
|
provides: ["pipeline-package", "factor-graph-module", "testing-benchmark-module"]
|
||||||
|
affects: ["core/graph.py", "core/processor.py", "core/pipeline.py", "core/results.py", "core/sse.py", "core/benchmark.py", "core/chunk_manager.py", "core/recovery.py", "core/models.py", "core/rotation.py"]
|
||||||
|
|
||||||
|
tech_stack:
|
||||||
|
added: []
|
||||||
|
patterns: ["typing.Protocol with @runtime_checkable", "shim re-export pattern", "package decomposition"]
|
||||||
|
|
||||||
|
key_files:
|
||||||
|
created:
|
||||||
|
- src/gps_denied/core/factor_graph.py
|
||||||
|
- src/gps_denied/pipeline/__init__.py
|
||||||
|
- src/gps_denied/pipeline/orchestrator.py
|
||||||
|
- src/gps_denied/pipeline/image_input.py
|
||||||
|
- src/gps_denied/pipeline/result_manager.py
|
||||||
|
- src/gps_denied/pipeline/sse_streamer.py
|
||||||
|
- src/gps_denied/testing/benchmark.py
|
||||||
|
modified:
|
||||||
|
- src/gps_denied/core/graph.py (shim)
|
||||||
|
- src/gps_denied/core/processor.py (shim)
|
||||||
|
- src/gps_denied/core/pipeline.py (shim)
|
||||||
|
- src/gps_denied/core/results.py (shim)
|
||||||
|
- src/gps_denied/core/sse.py (shim)
|
||||||
|
- src/gps_denied/core/benchmark.py (shim)
|
||||||
|
- src/gps_denied/core/chunk_manager.py (ABC→Protocol in-place)
|
||||||
|
- src/gps_denied/core/recovery.py (ABC→Protocol in-place)
|
||||||
|
- src/gps_denied/core/models.py (ABC→Protocol in-place)
|
||||||
|
- src/gps_denied/core/rotation.py (ABC→Protocol in-place)
|
||||||
|
- pyproject.toml (ruff per-file-ignores updated)
|
||||||
|
|
||||||
|
decisions:
|
||||||
|
- "Protocol subclassing is valid Python — FactorGraphOptimizer(IFactorGraphOptimizer) kept as-is"
|
||||||
|
- "pipeline/result_manager.py imports from pipeline/sse_streamer.py directly, avoiding shim chain"
|
||||||
|
- "core/results.py and core/sse.py shims kept lean; no circular import issues"
|
||||||
|
- "pipeline/orchestrator.py internal imports updated to new paths; test shims handle old paths"
|
||||||
|
- "src/gps_denied/testing/harness.py and api/deps.py left using shim paths (backward-compat)"
|
||||||
|
|
||||||
|
metrics:
|
||||||
|
duration: "~8 minutes"
|
||||||
|
completed: "2026-05-11"
|
||||||
|
tasks_completed: 6
|
||||||
|
files_created: 7
|
||||||
|
files_modified: 11
|
||||||
|
---
|
||||||
|
|
||||||
|
# Phase 01-hexagonal-refactor Plan 07: Factor Graph, Pipeline Package, Benchmark, Protocol Conversions Summary
|
||||||
|
|
||||||
|
**One-liner:** Extracted pipeline orchestration into `pipeline/` package, moved factor graph to `core/factor_graph.py`, benchmarks to `testing/benchmark.py`, and converted 5 ABCs to `typing.Protocol` with `@runtime_checkable`.
|
||||||
|
|
||||||
|
## File Moves Performed
|
||||||
|
|
||||||
|
| Source | Target | Method |
|
||||||
|
|--------|--------|--------|
|
||||||
|
| `core/graph.py` (IFactorGraphOptimizer) | `core/factor_graph.py` | Copy + ABC→Protocol, shim left at source |
|
||||||
|
| `core/processor.py` (FlightProcessor) | `pipeline/orchestrator.py` | Copy + internal imports updated, shim left at source |
|
||||||
|
| `core/pipeline.py` (ImageInputPipeline) | `pipeline/image_input.py` | Copy verbatim, shim left at source |
|
||||||
|
| `core/results.py` (ResultManager) | `pipeline/result_manager.py` | Copy + SSE import updated, shim left at source |
|
||||||
|
| `core/sse.py` (SSEEventStreamer) | `pipeline/sse_streamer.py` | Copy verbatim, shim left at source |
|
||||||
|
| `core/benchmark.py` (AccuracyBenchmark et al.) | `testing/benchmark.py` | Copy verbatim, shim left at source |
|
||||||
|
|
||||||
|
## ABCs Converted to Protocol (5 total)
|
||||||
|
|
||||||
|
| Interface | File | Method count |
|
||||||
|
|-----------|------|-------------|
|
||||||
|
| `IFactorGraphOptimizer` | `core/factor_graph.py` | 13 methods |
|
||||||
|
| `IRouteChunkManager` | `core/chunk_manager.py` | 6 methods |
|
||||||
|
| `IFailureRecoveryCoordinator` | `core/recovery.py` | 2 methods |
|
||||||
|
| `IModelManager` | `core/models.py` | 5 methods |
|
||||||
|
| `IImageMatcher` | `core/rotation.py` | 1 method |
|
||||||
|
|
||||||
|
**Pattern applied to each:**
|
||||||
|
- Removed `from abc import ABC, abstractmethod`
|
||||||
|
- Added `from typing import Protocol, runtime_checkable`
|
||||||
|
- Replaced `class IXxx(ABC):` with `@runtime_checkable\nclass IXxx(Protocol):`
|
||||||
|
- Dropped `@abstractmethod` decorators; replaced `pass` bodies with `...`
|
||||||
|
- Concrete classes continue to subclass the Protocol (valid Python)
|
||||||
|
|
||||||
|
## pyproject.toml Changes
|
||||||
|
|
||||||
|
```diff
|
||||||
|
[tool.ruff.lint.per-file-ignores]
|
||||||
|
-"src/gps_denied/core/graph.py" = ["E501"]
|
||||||
|
+"src/gps_denied/core/factor_graph.py" = ["E501"]
|
||||||
|
-"src/gps_denied/core/metric.py" = ["E501"]
|
||||||
|
+"src/gps_denied/components/satellite_matcher/metric_refinement.py" = ["E501"]
|
||||||
|
"src/gps_denied/core/chunk_manager.py" = ["E501"]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Test Counts
|
||||||
|
|
||||||
|
| | Count |
|
||||||
|
|--|--|
|
||||||
|
| Baseline (before plan) | 216 passed, 8 skipped |
|
||||||
|
| After plan | 216 passed, 8 skipped |
|
||||||
|
| Regression floor met | YES |
|
||||||
|
|
||||||
|
## Internal Import Updates in Non-Test Source Files
|
||||||
|
|
||||||
|
`pipeline/orchestrator.py` (canonical location of `FlightProcessor`):
|
||||||
|
- `from gps_denied.core.pipeline import ImageInputPipeline` → `from gps_denied.pipeline.image_input import ImageInputPipeline`
|
||||||
|
- `from gps_denied.core.results import ResultManager` → `from gps_denied.pipeline.result_manager import ResultManager`
|
||||||
|
- `from gps_denied.core.sse import SSEEventStreamer` → `from gps_denied.pipeline.sse_streamer import SSEEventStreamer`
|
||||||
|
|
||||||
|
`pipeline/result_manager.py` (canonical location of `ResultManager`):
|
||||||
|
- `from gps_denied.core.sse import SSEEventStreamer` → `from gps_denied.pipeline.sse_streamer import SSEEventStreamer`
|
||||||
|
|
||||||
|
`src/gps_denied/testing/harness.py` and `src/gps_denied/api/deps.py`: left using legacy `core.*` shim paths — they continue to work transparently.
|
||||||
|
|
||||||
|
## Protocol Conversion Edge Cases
|
||||||
|
|
||||||
|
1. **`IFactorGraphOptimizer` in `core/factor_graph.py`**: The concrete class `FactorGraphOptimizer` subclasses the Protocol. Python allows this and it provides structural typing via `@runtime_checkable`. The existing `isinstance(x, IFactorGraphOptimizer)` calls in tests will work.
|
||||||
|
|
||||||
|
2. **Long method signatures in `factor_graph.py`**: The `E501` ruff ignore was updated from `core/graph.py` to `core/factor_graph.py` — signatures like `add_relative_factor_to_chunk(...)` with 6 parameters exceed 120 chars.
|
||||||
|
|
||||||
|
3. **`chunk_manager.py` import of `IFactorGraphOptimizer`**: Still imports from `gps_denied.core.graph` (which shims to `factor_graph`) — no change needed, backward-compat maintained.
|
||||||
|
|
||||||
|
4. **`IImageMatcher` in `rotation.py`**: Used as a DI parameter type in `try_rotation_sweep`. Concrete implementations (e.g., `MetricRefinement` from `components/satellite_matcher`) are not subclasses but satisfy the Protocol structurally.
|
||||||
|
|
||||||
|
5. **`IModelManager` return type `InferenceEngine`**: `InferenceEngine` is a Pydantic model, not changed. Protocol stub uses `...` which satisfies mypy for structural checks.
|
||||||
|
|
||||||
|
## Deviations from Plan
|
||||||
|
|
||||||
|
None — plan executed exactly as written.
|
||||||
|
|
||||||
|
## Known Stubs
|
||||||
|
|
||||||
|
None introduced by this plan. All moved code is functionally complete.
|
||||||
|
|
||||||
|
## Threat Flags
|
||||||
|
|
||||||
|
None. No new network endpoints, auth paths, or file access patterns introduced by these refactors.
|
||||||
|
|
||||||
|
## Self-Check: PASSED
|
||||||
|
|
||||||
|
Files created:
|
||||||
|
- FOUND: src/gps_denied/core/factor_graph.py
|
||||||
|
- FOUND: src/gps_denied/pipeline/__init__.py
|
||||||
|
- FOUND: src/gps_denied/pipeline/orchestrator.py
|
||||||
|
- FOUND: src/gps_denied/pipeline/image_input.py
|
||||||
|
- FOUND: src/gps_denied/pipeline/result_manager.py
|
||||||
|
- FOUND: src/gps_denied/pipeline/sse_streamer.py
|
||||||
|
- FOUND: src/gps_denied/testing/benchmark.py
|
||||||
|
|
||||||
|
Commit: 5a60c1e — FOUND
|
||||||
|
Regression: 216 passed >= 216 baseline — PASSED
|
||||||
Reference in New Issue
Block a user