diff --git a/src/mir/builder/control_flow/joinir/patterns/pattern8_scan_bool_predicate.rs b/src/mir/builder/control_flow/joinir/patterns/pattern8_scan_bool_predicate.rs
index 3e01f9e5..88105b38 100644
--- a/src/mir/builder/control_flow/joinir/patterns/pattern8_scan_bool_predicate.rs
+++ b/src/mir/builder/control_flow/joinir/patterns/pattern8_scan_bool_predicate.rs
@@ -1,7 +1,26 @@
-//! Pattern 8: Boolean Predicate Scan (is_integer/is_valid form)
+//! Pattern 8: Boolean Predicate Scan (is_integer/is_valid form) - LEGACY LINE
//!
//! Phase 259 P0: Dedicated pattern for boolean predicate validation loops
//!
+//! ## Legacy Status (Phase 286 P3)
+//!
+//! **RETAINED FOR STATIC BOX CONTEXTS**
+//!
+//! - **Plan line** (Phase 286 P2.4): Handles regular loops via extract_pattern8_plan()
+//! - **Legacy line** (this file): Handles static box loops ONLY
+//!
+//! ### Why Legacy is Still Needed:
+//!
+//! 1. **Static box filtering**: Plan extractors are pure functions without builder access
+//! - Plan extractors cannot check `builder.comp_ctx.current_static_box`
+//! - Legacy `can_lower()` rejects static box contexts (see static box check below)
+//! 2. **ReceiverNormalizeBox coordination**: Static box `this.method()` calls
+//! are normalized by ReceiverNormalizeBox, not Pattern8
+//! 3. **Fail-Fast**: Plan line succeeds → legacy unreachable. Plan line fails → fallback to legacy
+//!
+//! **Deletion Condition**: Legacy can be removed when Plan extraction router
+//! adds static box filtering OR when ReceiverNormalizeBox handles all static box loops.
+//!
//! ## Pattern Structure
//!
//! ```nyash
diff --git a/src/mir/builder/control_flow/joinir/patterns/router.rs b/src/mir/builder/control_flow/joinir/patterns/router.rs
index 6e52b5ec..f697bb42 100644
--- a/src/mir/builder/control_flow/joinir/patterns/router.rs
+++ b/src/mir/builder/control_flow/joinir/patterns/router.rs
@@ -178,6 +178,10 @@ enum PlanExtractorVariant {
WithFnBody(fn(&ASTNode, &[ASTNode], Option<&[ASTNode]>) -> Result