---
phase: "41"
plan: "01"
subsystem: python-api
tags: [api-design, option-objects, backward-compat]
dependency-graph:
  requires: []
  provides: [ProcessingOptions, CacheOptions]
  affects:
    [
      get_open_deviation_bars,
      get_n_open_deviation_bars,
      get_open_deviation_bars_pandas,
    ]
tech-stack:
  added: []
  patterns: [expand-contract, frozen-dataclass]
key-files:
  created: []
  modified:
    - python/opendeviationbar/types.py
    - python/opendeviationbar/__init__.py
    - python/opendeviationbar/__init__.pyi
    - python/opendeviationbar/orchestration/open_deviation_bars.py
    - python/opendeviationbar/orchestration/open_deviation_bars.pyi
    - python/opendeviationbar/orchestration/count_bounded.py
    - python/opendeviationbar/orchestration/count_bounded.pyi
    - pyproject.toml
decisions:
  - Expand-contract pattern for full backward compatibility
  - Frozen dataclasses (immutable, hashable)
  - Option object values override individual params when both provided
  - Renamed internal `cache` context vars to `ch_cache` to avoid PLR1704 shadowing
metrics:
  duration: ~5min
  completed: "2026-03-30"
---

# Phase 41 Plan 01: Option Objects + Public API (#338) Summary

Frozen dataclasses ProcessingOptions (5 fields) and CacheOptions (4 fields) consolidate 10 boolean parameters into structured option objects with expand-contract backward compatibility.

## What Was Done

### ProcessingOptions dataclass

Added to `types.py` with 5 fields matching existing defaults:

- `include_microstructure` (False)
- `include_incomplete` (False)
- `include_orphaned_bars` (False)
- `include_exchange_sessions` (False)
- `prevent_same_timestamp_close` (True)

### CacheOptions dataclass

Added to `types.py` with 4 fields matching existing defaults:

- `use_cache` (True)
- `fetch_if_missing` (True)
- `verify_checksum` (True)
- `materialize` (True)

### API Integration

- `get_open_deviation_bars()` accepts `processing=` and `cache=` keyword args
- `get_n_open_deviation_bars()` accepts `processing=` and `cache=` keyword args
- `get_open_deviation_bars_pandas()` passes through via `**kwargs` (no changes needed)
- All existing callers work unchanged (individual bool params still accepted)

### Type Stubs

- Updated `orchestration/open_deviation_bars.pyi` with new params in all overloads
- Updated `orchestration/count_bounded.pyi` with new params
- Updated `__init__.pyi` with re-exports for both new types

### Lint Fixes

- Added `*.pyi` ANN401 per-file-ignore in `pyproject.toml`
- Renamed `with OpenDeviationBarCache() as cache` to `as ch_cache` in both orchestration files to avoid PLR1704 shadowing with the new `cache` parameter

## Deviations from Plan

### Auto-fixed Issues

**1. [Rule 3 - Blocking] PLR1704 parameter shadowing**

- **Found during:** API integration
- **Issue:** New `cache: CacheOptions | None` parameter shadows `with OpenDeviationBarCache() as cache:` variable
- **Fix:** Renamed context manager variable to `ch_cache` in both files
- **Files modified:** `open_deviation_bars.py`, `count_bounded.py`

**2. [Rule 3 - Blocking] ANN401 on .pyi stub**

- **Found during:** Stub updates
- **Issue:** `**kwargs: Any` in `.pyi` file triggers ANN401 (no existing per-file-ignore for stubs)
- **Fix:** Added `"*.pyi" = ["ANN401"]` to `[tool.ruff.lint.per-file-ignores]`
- **Files modified:** `pyproject.toml`

## Known Stubs

None - all types are fully wired.

## Commits

| Task | Commit  | Description                                                                 |
| ---- | ------- | --------------------------------------------------------------------------- |
| All  | f486ead | feat: add ProcessingOptions + CacheOptions for structured API params (#338) |

## Self-Check: PASSED

All 7 modified files verified on disk. Commit f486ead verified in git log.
