# Pipeline Refactoring Summary ## Overview Refactored `pipeline.py` to remove all backwards compatibility and legacy code, consolidating on a single modern context-based approach using `PipelineStageContext`. ## Changes Made ### 1. Removed Legacy Global Variables - ❌ `_PIPE_EMITS` - Replaced with `PipelineStageContext.emits` - ❌ `_PIPE_ACTIVE` - Replaced with checking `_CURRENT_CONTEXT is not None` - ❌ `_PIPE_IS_LAST` - Replaced with `PipelineStageContext.is_last_stage` - ❌ `_LAST_PIPELINE_CAPTURE` - Removed (unused ephemeral handoff) ### 2. Removed Legacy Functions - ❌ `set_active(bool)` - No longer needed, context tracks this - ❌ `set_last_stage(bool)` - No longer needed, context tracks this - ❌ `set_last_capture(obj)` - Removed - ❌ `get_last_capture()` - Removed ### 3. Updated Core Functions #### `emit(obj)` **Before:** Dual-path with fallback to legacy `_PIPE_EMITS` ```python if _CURRENT_CONTEXT is not None: _CURRENT_CONTEXT.emit(obj) return _PIPE_EMITS.append(obj) # Legacy fallback ``` **After:** Single context-based path ```python if _CURRENT_CONTEXT is not None: _CURRENT_CONTEXT.emit(obj) ``` #### `emit_list(objects)` **Before:** Dual-path with legacy fallback **After:** Single context-based path, removed duplicate definition #### `print_if_visible()` **Before:** Checked `_PIPE_ACTIVE` and `_PIPE_IS_LAST` ```python should_print = (not _PIPE_ACTIVE) or _PIPE_IS_LAST ``` **After:** Uses context state ```python should_print = (_CURRENT_CONTEXT is None) or (_CURRENT_CONTEXT.is_last_stage) ``` #### `get_emitted_items()` **Before:** Returned `_PIPE_EMITS` **After:** Returns `_CURRENT_CONTEXT.emits` if context exists #### `clear_emits()` **Before:** Cleared global `_PIPE_EMITS` **After:** Clears `_CURRENT_CONTEXT.emits` if context exists #### `reset()` **Before:** Reset 10+ legacy variables **After:** Only resets active state variables, sets `_CURRENT_CONTEXT = None` ### 4. Updated Call Sites #### TUI/pipeline_runner.py **Before:** ```python ctx.set_stage_context(pipeline_ctx) ctx.set_active(True) ctx.set_last_stage(index == total - 1) # ... ctx.set_stage_context(None) ctx.set_active(False) ``` **After:** ```python ctx.set_stage_context(pipeline_ctx) # ... ctx.set_stage_context(None) ``` #### CLI.py (2 locations) **Before:** ```python ctx.set_stage_context(pipeline_ctx) ctx.set_active(True) ``` **After:** ```python ctx.set_stage_context(pipeline_ctx) ``` ## Result ### Code Reduction - Removed ~15 lines of legacy global variable declarations - Removed ~30 lines of legacy function definitions - Removed ~10 lines of dual-path logic in core functions - Removed ~8 lines of redundant function calls at call sites ### Benefits 1. **Single Source of Truth**: All pipeline state is now in `PipelineStageContext` 2. **Cleaner API**: No redundant `set_active()` / `set_last_stage()` calls needed 3. **Type Safety**: Context object provides better type hints and IDE support 4. **Maintainability**: One code path to maintain, no backwards compatibility burden 5. **Clarity**: Intent is clear - context manages all stage-related state ## Preserved Functionality All user-facing functionality remains unchanged: - ✅ @N selection syntax - ✅ Result table history (@.. and @,,) - ✅ Display overlays - ✅ Pipeline value storage/retrieval - ✅ Worker attribution - ✅ UI refresh callbacks - ✅ Pending pipeline tail preservation ## Type Checking Notes Some type checker warnings remain about accessing attributes on Optional types (e.g., `_LAST_RESULT_TABLE.source_command`). These are safe because: 1. Code uses `_is_selectable_table()` runtime checks before access 2. Functions check `is not None` before attribute access 3. These warnings are false positives from static analysis These do not represent actual runtime bugs.