Files
gps-denied-onboard/.planning/phases/01-hexagonal-refactor/01-07-SUMMARY.md
T

7.1 KiB

phase, plan, subsystem, tags, dependency_graph, tech_stack, key_files, decisions, metrics
phase plan subsystem tags dependency_graph tech_stack key_files decisions metrics
01-hexagonal-refactor 01-07 core-restructure
refactor
protocol
pipeline
abc-to-protocol
shim
requires provides affects
01-05
01-06
pipeline-package
factor-graph-module
testing-benchmark-module
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
added patterns
typing.Protocol with @runtime_checkable
shim re-export pattern
package decomposition
created modified
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
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)
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)
duration completed tasks_completed files_created files_modified
~8 minutes 2026-05-11 6 7 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

 [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 ImageInputPipelinefrom gps_denied.pipeline.image_input import ImageInputPipeline
  • from gps_denied.core.results import ResultManagerfrom gps_denied.pipeline.result_manager import ResultManager
  • from gps_denied.core.sse import SSEEventStreamerfrom gps_denied.pipeline.sse_streamer import SSEEventStreamer

pipeline/result_manager.py (canonical location of ResultManager):

  • from gps_denied.core.sse import SSEEventStreamerfrom 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