chore: add CORE-003 roadmap task for mypy type safety

- Remove '|| true' from CI type-check job to enforce strict checking
- Begin type narrowing pattern in units.py with _typed property accessors
- Document all 42 type errors across 15 files in roadmap backlog
- Priority: medium, estimated 4-6 hours to complete

Type errors fall into categories:
- Union types not narrowed after __post_init__ coercion
- float() on object types
- Duplicate method definitions
- Provider interface type mismatches
This commit is contained in:
Bu5hm4nn
2026-03-29 23:40:55 +02:00
parent 1ad369727d
commit 367960772b
4 changed files with 165 additions and 27 deletions

View File

@@ -14,6 +14,7 @@ notes:
- Alpha migration policy: once alpha is declared, compatibility only needs to move forward; backward migrations are not required.
priority_queue:
- EXEC-002
- CORE-003
- DATA-DB-005
- DATA-002A
- DATA-001A

View File

@@ -0,0 +1,112 @@
name: CORE-003 Mypy Type Safety
description: |
Fix all mypy type errors to enable strict type checking in CI.
Currently 42 errors in 15 files. The CI uses `|| true` to allow warnings,
but we should fix these properly with strong types and conversion functions.
status: backlog
priority: medium
created_at: 2026-03-29
dependencies: []
acceptance_criteria:
- mypy passes with 0 errors on app/core app/models app/strategies app/services
- CI type-check job passes without `|| true`
- All type narrowing uses proper patterns (properties, cast(), or isinstance checks)
- No duplicate method definitions
scope:
in_scope:
- Fix type errors in app/domain/units.py
- Fix type errors in app/domain/portfolio_math.py
- Fix type errors in app/models/portfolio.py
- Fix type errors in app/domain/backtesting_math.py
- Fix type errors in app/domain/instruments.py
- Fix type errors in app/services/*.py
- Fix type errors in app/pages/*.py
- Remove `|| true` from type-check job in CI
out_of_scope:
- Adding new type annotations to previously untyped code
- Refactoring business logic
files_with_errors:
- file: app/domain/units.py
errors: 6
pattern: "WeightUnit | str" not narrowed after __post_init__
fix: Use _unit_typed property for type-narrowed access
- file: app/models/portfolio.py
errors: 1
pattern: "Duplicate _serialize_value definition"
fix: Remove duplicate method definition
- file: app/domain/backtesting_math.py
errors: 1
pattern: "assert_currency" argument type
fix: Use Money.assert_currency properly or add type narrowing
- file: app/domain/instruments.py
errors: 1
pattern: "to_unit" argument type
fix: Use _unit_typed property or explicit coercion
- file: app/domain/portfolio_math.py
errors: 11
pattern: "float(object), Weight | Money union, dict type mismatch"
fix: Add proper type guards and conversion functions
- file: app/services/backtesting/ui_service.py
errors: 2
pattern: "Provider type mismatch, YFinance vs Databento source"
fix: Use proper union types for provider interface
- file: app/services/event_comparison_ui.py
errors: 1
pattern: "FixtureBoundSyntheticHistoricalProvider type"
fix: Update type annotations for provider hierarchy
- file: app/services/cache.py
errors: 1
pattern: "str | None to Redis URL"
fix: Add None check or use assertion
- file: app/services/price_feed.py
errors: 2
pattern: "float(object)"
fix: Add explicit type coercion
- file: app/pages/settings.py
errors: 1
pattern: "Return value on ui.button scope"
fix: Proper return type annotation
implementation_notes: |
The root cause is that frozen dataclass fields with `Field: UnionType`
are not narrowed by `__post_init__` coercion. Mypy sees the declared
type, not the runtime type.
Solutions:
1. Add `@property def _field_typed(self) -> NarrowType:` for internal use
2. Use `cast(NarrowType, self.field)` at call sites
3. Use `isinstance` checks before operations requiring narrow type
Pattern example from units.py fix:
```python
@property
def _unit_typed(self) -> WeightUnit:
"""Type-narrowed unit accessor for internal use."""
return self.unit # type: ignore[return-value]
def to_unit(self, unit: WeightUnit) -> Weight:
return Weight(amount=convert_weight(self.amount, self._unit_typed, unit), unit=unit)
```
estimated_effort: 4-6 hours
tags:
- type-safety
- mypy
- technical-debt
- ci-quality