diff --git a/docs/development/current/main/10-Now.md b/docs/development/current/main/10-Now.md
index ccb7aa96..061a7662 100644
--- a/docs/development/current/main/10-Now.md
+++ b/docs/development/current/main/10-Now.md
@@ -3,7 +3,7 @@
## Current Focus
- Phase: `docs/development/current/main/phases/phase-29ap/README.md`
-- Next: Phase 29ap P5 (planned; see `docs/development/current/main/phases/phase-29ap/README.md`)
+- Next: Phase 29ap P7 (planned; see `docs/development/current/main/phases/phase-29ap/README.md`)
## Gate (SSOT)
diff --git a/docs/development/current/main/30-Backlog.md b/docs/development/current/main/30-Backlog.md
index 1a768142..d746e5c2 100644
--- a/docs/development/current/main/30-Backlog.md
+++ b/docs/development/current/main/30-Backlog.md
@@ -5,7 +5,7 @@ Scope: 「次にやる候補」を短く列挙するメモ。入口は `docs/dev
## Active
-- Phase 29ap: `docs/development/current/main/phases/phase-29ap/README.md` (Next: P5 planned)
+- Phase 29ap: `docs/development/current/main/phases/phase-29ap/README.md` (Next: P7 planned)
- JoinIR regression gate SSOT: `docs/development/current/main/phases/phase-29ae/README.md`
- CorePlan hardening (docs-first): `docs/development/current/main/phases/phase-29al/README.md`
diff --git a/docs/development/current/main/design/coreplan-migration-roadmap-ssot.md b/docs/development/current/main/design/coreplan-migration-roadmap-ssot.md
index 85bb9ada..175e3fdd 100644
--- a/docs/development/current/main/design/coreplan-migration-roadmap-ssot.md
+++ b/docs/development/current/main/design/coreplan-migration-roadmap-ssot.md
@@ -34,7 +34,7 @@ Related:
## 1.1 Current (active)
- Active phase: `docs/development/current/main/phases/phase-29ap/README.md`
-- Next step: Phase 29ap P5 (planned)
+- Next step: Phase 29ap P7 (planned)
## 2. すでに固めた SSOT(再発防止の土台)
diff --git a/docs/development/current/main/phases/phase-29ap/README.md b/docs/development/current/main/phases/phase-29ap/README.md
index c75bdc5d..a2b0ad45 100644
--- a/docs/development/current/main/phases/phase-29ap/README.md
+++ b/docs/development/current/main/phases/phase-29ap/README.md
@@ -57,12 +57,30 @@ Gate (SSOT):
- Scope:
- Remove Pattern8 from `LOOP_PATTERNS` so plan/composer stays SSOT for normal loops.
- - Keep legacy table as last resort for Pattern2/4/9 only.
+ - Keep legacy table as last resort for Pattern6_NestedLoopMinimal / Pattern4 / Pattern9 only.
- Guardrails:
- No change to logs or error strings.
- Legacy routing remains a last-resort fallback.
+## P5: Remove Pattern2 from JoinIR legacy table ✅
+
+- Scope:
+ - Remove Pattern2 (with break) from `LOOP_PATTERNS`.
+ - Keep plan/composer as the only routing path for Pattern2.
+- Guardrails:
+ - No change to logs or error strings.
+ - Fallback remains `Ok(None)` for non-matching plan cases.
+
+## P6: stdlib trim_start/trim_end subset (Pattern2BreakFacts) ✅
+
+- Scope:
+ - Add a conservative Pattern2BreakFacts subset for `trim_start`/`trim_end`.
+ - Normalize `not is_whitespace(...)` into `is_whitespace(...) == false` in facts.
+ - Restore quick smoke by ensuring stdlib loops are handled by plan/composer.
+- Guardrails:
+ - No new logs or error strings.
+ - Subset only: if shape deviates, return `Ok(None)`.
+
## Next (planned)
-- P5: Router pattern-name branching reduction (planner outcome + composer SSOT)
-- P6: Facts/Feature expansion if needed
+- P7: Legacy table shrink (Pattern9 removal) or leave as-is with justification
diff --git a/src/mir/builder/control_flow/joinir/patterns/condition_env_builder.rs b/src/mir/builder/control_flow/joinir/patterns/condition_env_builder.rs
index bbaf0897..891ba6b6 100644
--- a/src/mir/builder/control_flow/joinir/patterns/condition_env_builder.rs
+++ b/src/mir/builder/control_flow/joinir/patterns/condition_env_builder.rs
@@ -77,7 +77,7 @@ impl ConditionEnvBuilder {
// Phase 79-2: Register loop variable BindingId (dev-only)
// NOTE: We don't have access to builder.binding_map here, so this registration
- // needs to happen at the call site (in pattern2_with_break.rs, pattern3_with_if_phi.rs, etc.)
+ // needs to happen at the call site (pattern2 lowerer/orchestrator, pattern3_with_if_phi.rs, etc.)
// This comment serves as a reminder for future developers.
// For each condition variable, allocate JoinIR-local ValueId and build binding
diff --git a/src/mir/builder/control_flow/joinir/patterns/mod.rs b/src/mir/builder/control_flow/joinir/patterns/mod.rs
index 56c794af..383afc37 100644
--- a/src/mir/builder/control_flow/joinir/patterns/mod.rs
+++ b/src/mir/builder/control_flow/joinir/patterns/mod.rs
@@ -2,7 +2,6 @@
//!
//! Phase 2: Extracted from control_flow.rs
//! - Pattern 1: Simple While Loop (pattern1_minimal.rs)
-//! - Pattern 2: Loop with Conditional Break (pattern2_with_break.rs)
//! - Pattern 3: Loop with If-Else PHI (pattern3_with_if_phi.rs)
//! - Pattern 4: Loop with Continue (pattern4_with_continue.rs) [Phase 194+]
//!
@@ -78,7 +77,6 @@ pub(in crate::mir::builder) mod exit_binding_constructor; // Phase 222.5-C
pub(in crate::mir::builder) mod exit_binding_validator; // Phase 222.5-C
pub(in crate::mir::builder) mod loop_scope_shape_builder;
pub(in crate::mir::builder) mod pattern1_minimal;
-pub(in crate::mir::builder) mod pattern2_with_break;
pub(in crate::mir::builder) mod pattern3_with_if_phi;
pub(in crate::mir::builder) mod pattern4_carrier_analyzer;
pub(in crate::mir::builder) mod pattern4_with_continue;
diff --git a/src/mir/builder/control_flow/joinir/patterns/pattern2_break_condition_policy_router.rs b/src/mir/builder/control_flow/joinir/patterns/pattern2_break_condition_policy_router.rs
index 62dacccf..fea204fb 100644
--- a/src/mir/builder/control_flow/joinir/patterns/pattern2_break_condition_policy_router.rs
+++ b/src/mir/builder/control_flow/joinir/patterns/pattern2_break_condition_policy_router.rs
@@ -1,7 +1,7 @@
//! Pattern2 break-condition routing (policy → break_cond + allow-list + flags)
//!
-//! This box exists to keep `pattern2_with_break.rs` focused on orchestration and
-//! JoinIR wiring. It applies Pattern2-specific policies to derive:
+//! This box exists to keep the Pattern2 lowering orchestrator focused on wiring.
+//! It applies Pattern2-specific policies to derive:
//! - a normalized `break when true` condition node
//! - an allow-list of body-local variables permitted in conditions (Phase 92 P3)
//! - flags that affect later lowering (e.g. schedule and promotion heuristics)
diff --git a/src/mir/builder/control_flow/joinir/patterns/pattern2_steps/mod.rs b/src/mir/builder/control_flow/joinir/patterns/pattern2_steps/mod.rs
index 746ba070..c5f6fb3c 100644
--- a/src/mir/builder/control_flow/joinir/patterns/pattern2_steps/mod.rs
+++ b/src/mir/builder/control_flow/joinir/patterns/pattern2_steps/mod.rs
@@ -1,7 +1,7 @@
//! Phase 106: Pattern2 Step Boxes (SSOT)
//!
-//! Goal: keep `pattern2_with_break.rs` and the orchestrator thin by splitting
-//! the Pattern2 pipeline into explicit steps with clear boundaries.
+//! Goal: keep the Pattern2 lowering orchestrator thin by splitting the pipeline
+//! into explicit steps with clear boundaries.
//!
//! Each step should have a single responsibility and fail-fast with a clear tag
//! at the step boundary.
diff --git a/src/mir/builder/control_flow/joinir/patterns/pattern2_with_break.rs b/src/mir/builder/control_flow/joinir/patterns/pattern2_with_break.rs
deleted file mode 100644
index 50cd7457..00000000
--- a/src/mir/builder/control_flow/joinir/patterns/pattern2_with_break.rs
+++ /dev/null
@@ -1,471 +0,0 @@
-//! Pattern 2: Loop with Conditional Break minimal lowerer
-
-use super::super::trace;
-use crate::ast::ASTNode;
-use crate::mir::builder::MirBuilder;
-use crate::mir::ValueId;
-
-/// Phase 194: Detection function for Pattern 2
-///
-/// Phase 282 P4: Updated to ExtractionBased detection with safety valve
-///
-/// Pattern 2 matches:
-/// - Pattern kind is Pattern2Break (safety valve, O(1) early rejection)
-/// - Extraction validates: 比較条件/loop(true) + HAS break + NO continue/return
-pub(crate) fn can_lower(builder: &MirBuilder, ctx: &super::router::LoopPatternContext) -> bool {
- use crate::mir::loop_pattern_detection::LoopPatternKind;
-
- // Step 1: Early rejection guard (safety valve, O(1))
- if ctx.pattern_kind != LoopPatternKind::Pattern2Break {
- if ctx.debug {
- trace::trace().debug(
- "pattern2/can_lower",
- &format!("reject: pattern_kind={:?}", ctx.pattern_kind),
- );
- }
- return false;
- }
-
- // Step 2: ExtractionBased validation (SSOT, deep check)
- use super::extractors::pattern2::extract_loop_with_break_parts;
-
- let parts = match extract_loop_with_break_parts(ctx.condition, ctx.body) {
- Ok(Some(p)) => p,
- Ok(None) => {
- if ctx.debug {
- trace::trace().debug(
- "pattern2/can_lower",
- "reject: not Pattern2 (no break or has continue/return)",
- );
- }
- return false;
- }
- Err(e) => {
- if ctx.debug {
- trace::trace().debug("pattern2/can_lower", &format!("error: {}", e));
- }
- return false;
- }
- };
-
- if ctx.debug {
- trace::trace().debug(
- "pattern2/can_lower",
- &format!(
- "accept: extractable (break_count={}, is_loop_true={}) (Phase 282 P4)",
- parts.break_count, parts.is_loop_true
- ),
- );
- }
-
- // Step 3: Extract loop variable (hybrid for loop(true))
- use super::loop_true_counter_extractor::LoopTrueCounterExtractorBox;
-
- let loop_var_name = if parts.is_loop_true {
- // loop(true): Use LoopTrueCounterExtractorBox
- match LoopTrueCounterExtractorBox::extract_loop_counter_from_body(
- ctx.body,
- &builder.variable_ctx.variable_map,
- ) {
- Ok((name, _)) => name,
- Err(_) => {
- if ctx.debug {
- trace::trace().debug(
- "pattern2/can_lower",
- "reject: loop(true) but no counter found",
- );
- }
- return false;
- }
- }
- } else {
- // Normal loop: Use condition-based extraction
- match builder.extract_loop_variable_from_condition(ctx.condition) {
- Ok(name) => name,
- Err(_) => {
- // Try parts.loop_var as fallback
- if parts.loop_var.is_empty() {
- if ctx.debug {
- trace::trace().debug(
- "pattern2/can_lower",
- "reject: cannot extract loop variable",
- );
- }
- return false;
- }
- parts.loop_var.clone()
- }
- }
- };
-
- // Step 4: Carrier update validation (SSOT)
- use super::common_init::CommonPatternInitializer;
- match CommonPatternInitializer::check_carrier_updates_allowed(
- ctx.body,
- &loop_var_name,
- &builder.variable_ctx.variable_map,
- ) {
- true => true,
- false => {
- if ctx.debug {
- trace::trace().debug(
- "pattern2/can_lower",
- "reject: carrier updates not allowed (method calls)",
- );
- }
- false
- }
- }
-}
-
-/// Phase 194: Lowering function for Pattern 2
-///
-/// Phase 282 P4: Re-extracts for SSOT (no caching from can_lower)
-///
-/// Wrapper around cf_loop_pattern2_with_break_impl to match router signature
-pub(crate) fn lower(
- builder: &mut MirBuilder,
- ctx: &super::router::LoopPatternContext,
-) -> Result