# ADR-002: Protocol-Based Ports Instead of ABCs ## Status Accepted ## Context Hexagonal architecture defines ports as abstract interfaces that adapters implement. Python offers two mechanisms for this: 1. `abc.ABC` with `@abstractmethod` — nominal subtyping. Implementations must explicitly inherit from the abstract class. 2. `typing.Protocol` — structural subtyping. Any class with matching method signatures satisfies the protocol without explicit inheritance. The project has two ports: `LLMPort` (LLM provider interface) and `OrchestratorPort` (analysis strategy interface). Each has exactly one method. ## Decision Use `typing.Protocol` for both `LLMPort` and `OrchestratorPort`. Implementation explicitly inherit the Port protocol class. ## Options Considered ### Option A: abc.ABC (rejected) - **Pro**: Explicit inheritance makes the relationship visible in the code. Forgetting to implement a method raises `TypeError` at class definition time. - **Con**: Requires import of the ABC in every adapter module, creating a compile-time coupling between the infrastructure layer and the domain layer. For two single-method interfaces, the ceremony of `class MyAdapter(LLMPort):` adds no clarity over a matching method signature. ### Option B: typing.Protocol (chosen) - **Pro**: Structural subtyping — any class with the right method signature satisfies the contract. No import needed in adapter code (though it can still be imported for documentation). Lighter, more Pythonic. Static type checkers (`mypy`, `ty`) verify conformance without runtime overhead. - **Con**: No runtime `TypeError` if a method is missing — the error surfaces at call time or during type checking, not at class definition time. - **Mitigation**: The project uses `ty` for type checking in CI. Conformance is verified on every push. ## Consequences - Port definitions in `domain/ports.py` are `Protocol` classes. - Adapter classes DO inherit from ports. - Type checkers verify conformance. Tests verify behavior. - Adding a new adapter requires matching the protocol's method signature. ## Participants - Devil's advocate (proposed Protocol as lighter alternative) - Architect (accepted — ABCs add no value for single-method interfaces)