---
phase: 16-sidecar-aion-startup
plan: 01
subsystem: streaming-engine
tags: [ouroboros, aion-mode, pyo3, live-engine, puck, symbol-task]
dependency_graph:
  requires:
    - phase: 14-rust-core-gap-fields-conditional-reset
      provides: OuroborosMode enum, conditional maybe_reset_at_midnight
  provides:
    - Per-symbol OuroborosMode threading from Python through PyO3 to all Rust call sites
    - PyStreamManager symbol_modes constructor parameter
  affects: [sidecar, streaming-sidecar, puck-gap-fill]
tech_stack:
  added: []
  patterns: [per-symbol-mode-lookup-with-default]
key_files:
  created: []
  modified:
    - crates/opendeviationbar-streaming/src/live_engine/types.rs
    - crates/opendeviationbar-streaming/src/live_engine/mod.rs
    - crates/opendeviationbar-streaming/src/live_engine/symbol_task.rs
    - crates/opendeviationbar-streaming/src/live_engine/puck.rs
    - crates/opendeviationbar-streaming/src/live_engine/trade_dispatch.rs
    - crates/opendeviationbar-streaming/src/lib.rs
    - src/stream_manager_bindings.rs
key_decisions:
  - "symbol_modes defaults to empty HashMap -- all symbols default to Day mode for backward compatibility"
  - "Python passes string modes ('aion'/'day') converted to OuroborosMode in PyO3 layer"
  - "OuroborosMode re-exported from streaming crate lib.rs for external consumption"
patterns-established:
  - "Per-symbol mode lookup: symbol_modes.get(&symbol).copied().unwrap_or_default()"
requirements-completed: [SIDE-03]
duration: 19min
completed: "2026-03-27T09:24:00Z"
---

# Phase 16 Plan 01: Wire Per-Symbol OuroborosMode Summary

Per-symbol OuroborosMode threaded from Python through PyO3 into all 7 Rust call sites that previously hardcoded OuroborosMode::Day; StreamManager accepts symbol_modes dict

## Performance

- **Duration:** 19 min
- **Started:** 2026-03-27T09:05:59Z
- **Completed:** 2026-03-27T09:24:31Z
- **Tasks:** 3
- **Files modified:** 7

## Accomplishments

- Added `symbol_modes: HashMap<String, OuroborosMode>` to LiveEngineConfig
- Replaced all 5 hardcoded `OuroborosMode::Day` call sites in production code with per-symbol lookups (1 in mod.rs fill_from_rest, 3 in symbol_task.rs, 1 in puck.rs)
- PyO3 StreamManager constructor accepts optional `symbol_modes` dict for Python callers
- All 35 existing streaming tests pass unchanged (Day mode is default)
- Removed all `TODO(v7.0 Phase 16)` comments

## Task Commits

Each task was committed atomically:

1. **Task 1: Add symbol_modes to LiveEngineConfig and thread through start()/fill_from_rest()** - `3135308` (feat)
2. **Task 2: Thread ouroboros_mode through symbol_task and puck_fill** - `c76db6a` (feat)
3. **Task 3: PyO3 bindings -- StreamManager accepts symbol_modes dict** - `d867990` (feat)

## Files Created/Modified

- `crates/opendeviationbar-streaming/src/live_engine/types.rs` - Added symbol_modes field to LiveEngineConfig
- `crates/opendeviationbar-streaming/src/live_engine/mod.rs` - Thread ouroboros_mode through start() and fill_from_rest()
- `crates/opendeviationbar-streaming/src/live_engine/symbol_task.rs` - Accept ouroboros_mode param, replace 3 hardcodes, pass to puck_fill
- `crates/opendeviationbar-streaming/src/live_engine/puck.rs` - Accept ouroboros_mode param, replace 1 hardcode
- `crates/opendeviationbar-streaming/src/live_engine/trade_dispatch.rs` - Updated comment from TODO to Phase 16 reference
- `crates/opendeviationbar-streaming/src/lib.rs` - Re-export OuroborosMode from crate root
- `src/stream_manager_bindings.rs` - Add symbol_modes parameter to PyStreamManager::new()

## Decisions Made

- symbol_modes defaults to empty HashMap so all existing callers get Day mode without changes
- Python passes string modes ("aion"/"day") rather than enum -- simpler PyO3 boundary
- OuroborosMode re-exported from streaming crate lib.rs for external crate consumption

## Deviations from Plan

### Auto-fixed Issues

**1. [Rule 3 - Blocking] OuroborosMode not re-exported from streaming crate**

- **Found during:** Task 3 (PyO3 bindings)
- **Issue:** Plan assumed OuroborosMode was already re-exported from `opendeviationbar_streaming`, but lib.rs re-exports did not include it
- **Fix:** Added OuroborosMode to the re-export list in lib.rs
- **Files modified:** crates/opendeviationbar-streaming/src/lib.rs
- **Verification:** cargo check -p opendeviationbar-py passes
- **Committed in:** d867990 (Task 3 commit)

---

**Total deviations:** 1 auto-fixed (1 blocking)
**Impact on plan:** Minor missing re-export, essential for PyO3 compilation. No scope creep.

## Issues Encountered

None.

## User Setup Required

None - no external service configuration required.

## Next Phase Readiness

- Per-symbol OuroborosMode fully wired from Python to Rust
- Ready for Plan 02: Python sidecar startup changes to pass symbol_modes from symbols.toml
- All existing behavior preserved (Day mode default when symbol not in modes map)

---

_Phase: 16-sidecar-aion-startup_
_Completed: 2026-03-27_
