---
phase: 01-modularize-long-files-live-engine-rs-checkpoint-py-backfill-py
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
  - crates/opendeviationbar-streaming/src/live_engine.rs
  - crates/opendeviationbar-streaming/src/live_engine/mod.rs
  - crates/opendeviationbar-streaming/src/live_engine/types.rs
  - crates/opendeviationbar-streaming/src/live_engine/trade_dispatch.rs
  - crates/opendeviationbar-streaming/src/live_engine/puck.rs
  - crates/opendeviationbar-streaming/src/live_engine/symbol_task.rs
  - crates/opendeviationbar-streaming/src/lib.rs
autonomous: true
requirements: []

must_haves:
  truths:
    - "All existing Rust tests pass without modification"
    - "All public types re-exported from crate root unchanged"
    - "live_engine module is a directory with submodules instead of a single file"
  artifacts:
    - path: "crates/opendeviationbar-streaming/src/live_engine/mod.rs"
      provides: "LiveBarEngine impl + re-exports of all public symbols"
      contains: "pub use types::"
    - path: "crates/opendeviationbar-streaming/src/live_engine/types.rs"
      provides: "CompletedBar, FormingBar, FormingBarWatches, LiveEngineMetrics, LiveEngineMetricsSnapshot, LiveEngineConfig"
      exports:
        [
          "CompletedBar",
          "FormingBar",
          "LiveEngineMetrics",
          "LiveEngineConfig",
          "LiveEngineMetricsSnapshot",
        ]
    - path: "crates/opendeviationbar-streaming/src/live_engine/trade_dispatch.rs"
      provides: "process_trade_through_processors, maybe_reset_at_midnight"
    - path: "crates/opendeviationbar-streaming/src/live_engine/puck.rs"
      provides: "puck_fill async fn"
    - path: "crates/opendeviationbar-streaming/src/live_engine/symbol_task.rs"
      provides: "symbol_task async fn"
  key_links:
    - from: "crates/opendeviationbar-streaming/src/live_engine/mod.rs"
      to: "types.rs, trade_dispatch.rs, puck.rs, symbol_task.rs"
      via: "mod + pub use"
      pattern: "pub use types::"
    - from: "crates/opendeviationbar-streaming/src/lib.rs"
      to: "live_engine module"
      via: "pub use live_engine::"
      pattern: "pub use live_engine::\\{CompletedBar"
---

<objective>
Extract live_engine.rs (2,436 lines) into a live_engine/ directory with submodules: types.rs, trade_dispatch.rs, puck.rs, symbol_task.rs, and mod.rs.

Purpose: Improve maintainability by splitting a monolithic file into focused submodules, following the proven interbar.rs extraction pattern.
Output: live_engine/ directory with 5 files, all public symbols re-exported, all tests passing.
</objective>

<execution_context>
@$HOME/.claude/get-shit-done/workflows/execute-plan.md
@$HOME/.claude/get-shit-done/templates/summary.md
</execution_context>

<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/phases/01-modularize-long-files-live-engine-rs-checkpoint-py-backfill-py/01-CONTEXT.md

@crates/opendeviationbar-streaming/src/live_engine.rs
@crates/opendeviationbar-streaming/src/lib.rs

<interfaces>
<!-- Existing crate re-exports that MUST remain unchanged in lib.rs -->
From crates/opendeviationbar-streaming/src/lib.rs (lines 48-52):
```rust
#[cfg(feature = "binance-integration")]
pub use live_engine::{
    CompletedBar, FormingBar, FormingBarWatches, LiveBarEngine, LiveEngineConfig,
    LiveEngineMetrics,
};
```

<!-- Consumers of live_engine types within the crate -->

From stream_manager.rs: `use crate::live_engine::{CompletedBar, FormingBar, FormingBarWatches, LiveBarEngine, LiveEngineConfig, LiveEngineMetrics}`
From engine/odb_engine.rs: `use crate::live_engine::CompletedBar`
From engine/traits.rs: `use crate::live_engine::CompletedBar`
From engine/source_live.rs: `use crate::live_engine::{CompletedBar, LiveBarEngine}` and `use crate::live_engine::LiveEngineConfig`
From engine/sink_channel.rs: `use crate::live_engine::CompletedBar`
</interfaces>
</context>

<tasks>

<task type="auto">
  <name>Task 1: Convert live_engine.rs to live_engine/ directory with submodules</name>
  <files>
    crates/opendeviationbar-streaming/src/live_engine.rs
    crates/opendeviationbar-streaming/src/live_engine/mod.rs
    crates/opendeviationbar-streaming/src/live_engine/types.rs
    crates/opendeviationbar-streaming/src/live_engine/trade_dispatch.rs
    crates/opendeviationbar-streaming/src/live_engine/puck.rs
    crates/opendeviationbar-streaming/src/live_engine/symbol_task.rs
    crates/opendeviationbar-streaming/src/lib.rs
  </files>
  <read_first>
    crates/opendeviationbar-streaming/src/live_engine.rs
    crates/opendeviationbar-streaming/src/lib.rs
    crates/opendeviationbar-streaming/src/stream_manager.rs (first 40 lines -- imports only)
    crates/opendeviationbar-streaming/src/engine/odb_engine.rs (first 20 lines -- imports only)
    crates/opendeviationbar-streaming/src/engine/traits.rs (first 15 lines -- imports only)
    crates/opendeviationbar-streaming/src/engine/source_live.rs (first 15 lines -- imports only)
    crates/opendeviationbar-streaming/src/engine/sink_channel.rs (first 10 lines -- imports only)
  </read_first>
  <action>
    Convert `live_engine.rs` monolith into `live_engine/` directory package. Follow the interbar.rs precedent (sibling modules, re-exported via mod.rs).

    **Step 1: Create live_engine/ directory** (delete old live_engine.rs, create live_engine/ with submodules)

    **Step 2: Create types.rs** (~200 lines) containing:
    - `const DAY_US: i64 = 86_400_000_000;`
    - `pub struct CompletedBar` (lines 41-45)
    - `pub struct FormingBar` (lines 52-61)
    - `type FormingBarKey = (Arc<str>, u32);` (line 64)
    - `pub type FormingBarWatches = HashMap<FormingBarKey, watch::Receiver<Option<FormingBar>>>;` (line 68)
    - `pub struct LiveEngineMetrics` (lines 74-84) + `impl Default` (lines 86-100)
    - `pub struct LiveEngineConfig` (lines 104-130) + `impl LiveEngineConfig` (lines 132-184)
    - `pub struct LiveEngineMetricsSnapshot` (lines 1077-1086)
    - All necessary `use` imports for these types (`std::collections::HashMap`, `std::sync::Arc`, `std::sync::atomic::*`, `tokio::sync::watch`, `opendeviationbar_core::*`, `opendeviationbar_providers::binance::*`)
    - `DAY_US` should be `pub(crate)` so trade_dispatch.rs and puck.rs can use it

    **Step 3: Create trade_dispatch.rs** (~130 lines) containing:
    - `const MAX_BURST_DRAIN: usize = 1024;` (line 1095) -- keep as module-private
    - `pub(crate) fn process_trade_through_processors(...)` (lines 1102-1208)
    - `pub(crate) fn maybe_reset_at_midnight(...)` (lines 1217-1231)
    - Imports: `use super::types::*;` plus `use opendeviationbar_core::*;`, `use crate::ring_buffer::ConcurrentRingBuffer;`, `use std::sync::Arc;`, `use std::collections::HashMap;`, `use std::sync::atomic::Ordering;`, `use tokio::sync::watch;`
    - Note: `MAX_BURST_DRAIN` is used in symbol_task.rs -- either make it `pub(crate)` or move it to symbol_task.rs where it's actually consumed. Check usage: it's used in the `symbol_task` fn (around line 1500-1600 in the original). Move it to symbol_task.rs.

    **Step 4: Create puck.rs** (~150 lines) containing:
    - `pub(crate) async fn puck_fill(...)` (lines 1242-1381)
    - Imports: `use super::types::*;`, `use super::trade_dispatch::maybe_reset_at_midnight;`, `use opendeviationbar_core::*;`, `use crate::ring_buffer::ConcurrentRingBuffer;`, `use opendeviationbar_providers::binance::AdaptiveRateLimiter;`, `use std::sync::Arc;`, `use std::collections::HashMap;`, `use std::sync::atomic::Ordering;`, `use tokio::sync::watch;`, `use tokio_util::sync::CancellationToken;`

    **Step 5: Create symbol_task.rs** (~430 lines) containing:
    - `const MAX_BURST_DRAIN: usize = 1024;` (moved here from original line 1095)
    - `pub(crate) async fn symbol_task(...)` (lines 1391-1815)
    - Imports: `use super::types::*;`, `use super::trade_dispatch::process_trade_through_processors;`, `use super::puck::puck_fill;`, `use opendeviationbar_core::*;`, `use crate::gap::*;`, `use crate::ring_buffer::ConcurrentRingBuffer;`, `use opendeviationbar_providers::binance::*;`, `use std::sync::Arc;`, `use std::collections::HashMap;`, `use tokio::sync::{mpsc, watch};`, `use tokio_util::sync::CancellationToken;`

    **Step 6: Create mod.rs** containing:
    - Module-level doc comment (preserve from original lines 1-11)
    - `mod types;`, `mod trade_dispatch;`, `mod puck;`, `mod symbol_task;`
    - `pub use types::{CompletedBar, FormingBar, FormingBarWatches, LiveEngineConfig, LiveEngineMetrics, LiveEngineMetricsSnapshot};`
    - `use types::{FormingBarKey, DAY_US};` (for internal use in mod.rs)
    - The `LiveBarEngine` struct definition (lines 190-215) and its entire `impl LiveBarEngine` block (lines 217-1073) -- these stay in mod.rs
    - `#[cfg(test)] mod tests` block (lines 1817-2436) -- stays in mod.rs since tests use `super::*`
    - Imports needed by LiveBarEngine: all the original imports from lines 13-33 that are still needed

    **Step 7: Update lib.rs** -- NO changes needed. The `pub mod live_engine;` declaration works for both file and directory modules in Rust. The `pub use live_engine::{...}` re-exports remain identical.

    **CRITICAL**: Do not change any function signatures, visibility, or behavior. This is pure code movement.

  </action>
  <verify>
    <automated>cd /Users/terryli/eon/opendeviationbar-py && cargo check -p opendeviationbar-streaming --features binance-integration 2>&1 | tail -5</automated>
  </verify>
  <acceptance_criteria>
    - File `crates/opendeviationbar-streaming/src/live_engine.rs` no longer exists (replaced by directory)
    - File `crates/opendeviationbar-streaming/src/live_engine/mod.rs` exists and contains `pub struct LiveBarEngine`
    - File `crates/opendeviationbar-streaming/src/live_engine/types.rs` exists and contains `pub struct CompletedBar`
    - File `crates/opendeviationbar-streaming/src/live_engine/types.rs` contains `pub struct LiveEngineConfig`
    - File `crates/opendeviationbar-streaming/src/live_engine/types.rs` contains `pub struct LiveEngineMetricsSnapshot`
    - File `crates/opendeviationbar-streaming/src/live_engine/trade_dispatch.rs` exists and contains `fn process_trade_through_processors`
    - File `crates/opendeviationbar-streaming/src/live_engine/trade_dispatch.rs` contains `fn maybe_reset_at_midnight`
    - File `crates/opendeviationbar-streaming/src/live_engine/puck.rs` exists and contains `async fn puck_fill`
    - File `crates/opendeviationbar-streaming/src/live_engine/symbol_task.rs` exists and contains `async fn symbol_task`
    - `cargo check -p opendeviationbar-streaming --features binance-integration` exits 0
    - `crates/opendeviationbar-streaming/src/lib.rs` still contains `pub use live_engine::{CompletedBar, FormingBar, FormingBarWatches, LiveBarEngine, LiveEngineConfig`
  </acceptance_criteria>
  <done>live_engine.rs split into 5 submodule files under live_engine/ directory, cargo check passes, all public re-exports preserved</done>
</task>

<task type="auto">
  <name>Task 2: Verify all Rust tests pass after extraction</name>
  <files>
    crates/opendeviationbar-streaming/src/live_engine/mod.rs
  </files>
  <read_first>
    crates/opendeviationbar-streaming/src/live_engine/mod.rs (last 50 lines -- test module)
  </read_first>
  <action>
    Run the full streaming crate test suite to confirm zero regressions. Also run cargo check on the full workspace to ensure no downstream breakage in stream_manager.rs, engine/ submodules, or PyO3 bindings.

    If any test fails, fix the import/visibility issue in the submodule that caused it. Common issues:
    - `pub(crate)` vs `pub(super)` visibility mismatch
    - Missing re-export in mod.rs
    - `use super::*` in tests not pulling in types from submodules (fix by adding `pub use` in mod.rs)

    Run:
    1. `cargo nextest run -p opendeviationbar-streaming --features binance-integration` -- all streaming crate tests
    2. `cargo check --workspace` -- full workspace check for downstream consumers

  </action>
  <verify>
    <automated>cd /Users/terryli/eon/opendeviationbar-py && cargo nextest run -p opendeviationbar-streaming --features binance-integration 2>&1 | tail -10</automated>
  </verify>
  <acceptance_criteria>
    - `cargo nextest run -p opendeviationbar-streaming --features binance-integration` exits 0 with all tests passing
    - `cargo check --workspace` exits 0
  </acceptance_criteria>
  <done>All Rust tests pass, full workspace compiles, zero regressions from live_engine extraction</done>
</task>

</tasks>

<verification>
1. `cargo check -p opendeviationbar-streaming --features binance-integration` -- compiles
2. `cargo nextest run -p opendeviationbar-streaming --features binance-integration` -- tests pass
3. `cargo check --workspace` -- no downstream breakage
4. `ls crates/opendeviationbar-streaming/src/live_engine/` shows mod.rs, types.rs, trade_dispatch.rs, puck.rs, symbol_task.rs
5. `! test -f crates/opendeviationbar-streaming/src/live_engine.rs` -- old file gone
</verification>

<success_criteria>

- live_engine.rs replaced by live_engine/ directory with 5 files
- All public types (CompletedBar, FormingBar, FormingBarWatches, LiveBarEngine, LiveEngineConfig, LiveEngineMetrics, LiveEngineMetricsSnapshot) re-exported from crate root
- All streaming crate tests pass unchanged
- Full workspace compiles
  </success_criteria>

<output>
After completion, create `.planning/phases/01-modularize-long-files-live-engine-rs-checkpoint-py-backfill-py/01-01-SUMMARY.md`
</output>
