diff --git a/CURRENT_TASK.md b/CURRENT_TASK.md
index 4fc43490..1bea4df5 100644
--- a/CURRENT_TASK.md
+++ b/CURRENT_TASK.md
@@ -30,6 +30,9 @@ PlanRuleOrder を SSOT 化し、PlannerContext を配線(未使用)。single
**2025-12-29: Phase 29ak P1 COMPLETE (Pattern1 facts guard via planner)**
Pattern1 以外のループで pattern1_simplewhile facts 抽出を抑制。single_planner 側の guard は安全策として維持。
+**2025-12-29: Phase 29ak P2 COMPLETE (Pattern8 static box filter via planner)**
+static box では Pattern8 facts 抽出を抑制。single_planner 側の filter は安全策として維持。
+
**2025-12-29: Phase 29aj P10 COMPLETE (single_planner unified shape)**
single_planner を全パターンで planner-first → extractor フォールバックの共通形に統一(挙動不変)。
diff --git a/docs/development/current/main/10-Now.md b/docs/development/current/main/10-Now.md
index 8d311ebd..747f6bbd 100644
--- a/docs/development/current/main/10-Now.md
+++ b/docs/development/current/main/10-Now.md
@@ -2,10 +2,15 @@
## Current Focus: Phase 29ak(PlanRuleOrder + PlannerContext)
-Next: Phase 29ak P2(TBD)
+Next: Phase 29ak P3(TBD)
運用ルール: integration filter で phase143_* は回さない(JoinIR 回帰は phase29ae pack のみ)
運用ルール: phase286_pattern9_* は legacy pack (SKIP) を使う
+**2025-12-29: Phase 29ak P2 完了** ✅
+- 目的: Pattern8 static box filter を planner 側へ移し、facts 抽出を抑制(仕様不変)
+- 実装: `src/mir/builder/control_flow/plan/facts/loop_facts.rs`
+- 検証: `cargo build --release` / `./tools/smokes/v2/run.sh --profile quick` / `./tools/smokes/v2/profiles/integration/joinir/phase29ae_regression_pack_vm.sh` PASS
+
**2025-12-29: Phase 29ak P1 完了** ✅
- 目的: Pattern1 guard を planner 側へ移して facts 抽出を抑制(仕様不変)
- 実装: `src/mir/builder/control_flow/plan/facts/loop_facts.rs` / `src/mir/builder/control_flow/plan/planner/outcome.rs`
diff --git a/docs/development/current/main/30-Backlog.md b/docs/development/current/main/30-Backlog.md
index 48f7cdca..09e93046 100644
--- a/docs/development/current/main/30-Backlog.md
+++ b/docs/development/current/main/30-Backlog.md
@@ -26,8 +26,8 @@ Related:
- **Phase 29ak(candidate): PlanRuleOrder SSOT + PlannerContext plumbing**
- 入口: `docs/development/current/main/phases/phase-29ak/README.md`
- - 状況: P0/P1 ✅ 完了
- - Next: Phase 29ak P2(TBD)
+ - 状況: P0/P1/P2 ✅ 完了
+ - Next: Phase 29ak P3(TBD)
- **Phase 29ai(candidate): Plan/Frag single-planner(Facts SSOT)**
- 入口: `docs/development/current/main/phases/phase-29ai/README.md`
diff --git a/docs/development/current/main/phases/phase-29ak/P2-PLANNER-PATTERN8-STATIC-BOX-FILTER-INSTRUCTIONS.md b/docs/development/current/main/phases/phase-29ak/P2-PLANNER-PATTERN8-STATIC-BOX-FILTER-INSTRUCTIONS.md
new file mode 100644
index 00000000..dc4dd064
--- /dev/null
+++ b/docs/development/current/main/phases/phase-29ak/P2-PLANNER-PATTERN8-STATIC-BOX-FILTER-INSTRUCTIONS.md
@@ -0,0 +1,55 @@
+# Phase 29ak P2: Gate Pattern8 facts by static box ctx
+
+Date: 2025-12-29
+Status: Ready for execution
+Scope: PlannerContext.in_static_box を使って Pattern8 facts を抑制(挙動・ログ不変)
+Goal: single_planner の特例フィルタ責務を planner 側へ移す
+
+## Objective
+
+- in_static_box == true のとき Pattern8 facts 抽出を行わない
+- single_planner 側の static box reject 分岐は安全策として残す
+- ログ差分は出さない(planner 側は無言で Ok(None))
+
+## Non-goals
+
+- Pattern8 static box reject 分岐の削除
+- CandidateSet への順序移管
+- 新 env var 追加
+
+## Implementation Steps
+
+### Step 1: facts 入口で Pattern8 を抑制
+
+Update:
+- `src/mir/builder/control_flow/plan/facts/loop_facts.rs`
+
+Notes:
+- `try_build_loop_facts_with_ctx` で `ctx.in_static_box` を参照し、Pattern8 抽出関数を呼ばない
+
+### Step 2: planner outcome 側は ctx 版を継続使用
+
+Update:
+- `src/mir/builder/control_flow/plan/planner/outcome.rs`
+
+### Step 3: unit test 追加(facts)
+
+- in_static_box=true で Pattern8 facts が None になることを固定
+
+### Step 4: docs / CURRENT_TASK 更新
+
+Update:
+- `docs/development/current/main/phases/phase-29ak/README.md`
+- `docs/development/current/main/10-Now.md`
+- `docs/development/current/main/30-Backlog.md`
+- `CURRENT_TASK.md`
+
+## Verification
+
+- `cargo build --release`
+- `./tools/smokes/v2/run.sh --profile quick`
+- `./tools/smokes/v2/profiles/integration/joinir/phase29ae_regression_pack_vm.sh`
+
+## Commit
+
+- `git add -A && git commit -m "phase29ak(p2): gate pattern8 facts by static box ctx"`
diff --git a/docs/development/current/main/phases/phase-29ak/README.md b/docs/development/current/main/phases/phase-29ak/README.md
index f31b7684..98f4bbeb 100644
--- a/docs/development/current/main/phases/phase-29ak/README.md
+++ b/docs/development/current/main/phases/phase-29ak/README.md
@@ -15,3 +15,10 @@ Goal: single_planner の「順序・名前・ガード」の SSOT を 1 箇所
- ねらい: pattern_kind が Pattern1 以外のとき pattern1 facts 抽出を行わない
- 完了: PlannerContext を参照して loop_facts 入口で Pattern1 を抑制(single_planner 側の guard は維持)
- 検証: `cargo build --release` / `./tools/smokes/v2/run.sh --profile quick` / `./tools/smokes/v2/profiles/integration/joinir/phase29ae_regression_pack_vm.sh`
+
+## P2: Pattern8 static box filter を planner 側へ移動
+
+- 指示書: `docs/development/current/main/phases/phase-29ak/P2-PLANNER-PATTERN8-STATIC-BOX-FILTER-INSTRUCTIONS.md`
+- ねらい: static box では Pattern8 facts 抽出を抑制(single_planner 側の filter は維持)
+- 完了: PlannerContext.in_static_box を参照して loop_facts 入口で Pattern8 を抑制
+- 検証: `cargo build --release` / `./tools/smokes/v2/run.sh --profile quick` / `./tools/smokes/v2/profiles/integration/joinir/phase29ae_regression_pack_vm.sh`
diff --git a/src/mir/builder/control_flow/plan/facts/loop_facts.rs b/src/mir/builder/control_flow/plan/facts/loop_facts.rs
index 3b78dd9a..b71541ee 100644
--- a/src/mir/builder/control_flow/plan/facts/loop_facts.rs
+++ b/src/mir/builder/control_flow/plan/facts/loop_facts.rs
@@ -74,7 +74,7 @@ pub(in crate::mir::builder) fn try_build_loop_facts(
condition: &ASTNode,
body: &[ASTNode],
) -> Result