diff --git a/CURRENT_TASK.md b/CURRENT_TASK.md index e5ea22ea..f21c7e0f 100644 --- a/CURRENT_TASK.md +++ b/CURRENT_TASK.md @@ -21,6 +21,9 @@ JoinIR 回帰の integration gate を phase29ae pack に固定し、phase143_* **2025-12-29: Phase 29aj P7 COMPLETE (Pattern8 planner-first)** Pattern8 BoolPredicateScan の Facts→Planner-first を導入し、single_planner の extractor 依存を縮小。 +**2025-12-29: Phase 29aj P10 COMPLETE (single_planner unified shape)** +single_planner を全パターンで planner-first → extractor フォールバックの共通形に統一(挙動不変)。 + **2025-12-29: Phase 29aj P9 COMPLETE (phase286 pattern9 legacy isolation)** phase286_pattern9_frag_poc を legacy pack (SKIP) に隔離し、JoinIR 回帰 SSOT を phase29ae pack に固定。 diff --git a/docs/development/current/main/10-Now.md b/docs/development/current/main/10-Now.md index a7e53a25..825f5719 100644 --- a/docs/development/current/main/10-Now.md +++ b/docs/development/current/main/10-Now.md @@ -2,10 +2,15 @@ ## Current Focus: Phase 29aj(PlannerOutcome SSOT) -Next: Phase 29aj P10(TBD) +Next: Phase 29aj P11(TBD) 運用ルール: integration filter で phase143_* は回さない(JoinIR 回帰は phase29ae pack のみ) 運用ルール: phase286_pattern9_* は legacy pack (SKIP) を使う +**2025-12-29: Phase 29aj P10 完了** ✅ +- 目的: single_planner を全パターン planner-first 形に統一(挙動不変) +- 実装: `src/mir/builder/control_flow/plan/single_planner/rules.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 29aj P9 完了** ✅ - 目的: phase286_pattern9_frag_poc を legacy pack (SKIP) に隔離して SSOT を固定 - 実装: `tools/smokes/v2/profiles/integration/joinir/phase286_pattern9_legacy_pack.sh` / `docs/development/current/main/phases/phase-29aj/README.md` / `docs/development/current/main/phases/phase-29ae/README.md` diff --git a/docs/development/current/main/30-Backlog.md b/docs/development/current/main/30-Backlog.md index 40d6bb9a..38b6b1d9 100644 --- a/docs/development/current/main/30-Backlog.md +++ b/docs/development/current/main/30-Backlog.md @@ -19,8 +19,8 @@ Related: - **Phase 29aj(candidate): PlannerOutcome observability SSOT** - 入口: `docs/development/current/main/phases/phase-29aj/README.md` - - 状況: P0/P1/P2/P3/P4/P5/P6/P7/P8/P9 ✅ 完了 - - Next: Phase 29aj P10(TBD) + - 状況: P0/P1/P2/P3/P4/P5/P6/P7/P8/P9/P10 ✅ 完了 + - Next: Phase 29aj P11(TBD) - 運用: integration filter で phase143_* は回さない(JoinIR 回帰は phase29ae pack のみ) - 運用: phase286_pattern9_* は legacy pack (SKIP) を使う diff --git a/docs/development/current/main/phases/phase-29aj/P10-SINGLE_PLANNER-UNIFY-PLANNER_FIRST-SHAPE-INSTRUCTIONS.md b/docs/development/current/main/phases/phase-29aj/P10-SINGLE_PLANNER-UNIFY-PLANNER_FIRST-SHAPE-INSTRUCTIONS.md new file mode 100644 index 00000000..d9102efa --- /dev/null +++ b/docs/development/current/main/phases/phase-29aj/P10-SINGLE_PLANNER-UNIFY-PLANNER_FIRST-SHAPE-INSTRUCTIONS.md @@ -0,0 +1,56 @@ +# Phase 29aj P10: Unify single_planner planner-first shape + +Date: 2025-12-29 +Status: Ready for execution +Scope: single_planner の分岐形を一本化(挙動不変の整形リファクタ)+ docs 更新 +Goal: 入口の形を最終形に寄せて「もう pattern 別 if を増やさない」状態にする + +## Objective + +- Pattern1/2/3/4/5/6/7/8/9 の順序 SSOT を維持しつつ、全パターンで + 1. planner_opt が該当 DomainPlan なら採用 + 2. そうでなければ extractor にフォールバック + の共通形に統一する +- Pattern1 guard と Pattern8 static box filter はそのまま維持 +- ログ・観測は不変(`route=plan strategy=extract pattern=...` 以外増やさない) + +## Non-goals + +- extractor の削除 / legacy の撤去 +- rule order SSOT を CandidateSet に移管 +- planner に ctx(pattern_kind/in_static_box)を渡す + +## Implementation Steps + +### Step 1: RuleKind を Pattern1..Pattern9 に統一 + +File: +- `src/mir/builder/control_flow/plan/single_planner/rules.rs` + +Changes: +- RuleKind を Pattern1..Pattern9 の列挙に整理 +- rules テーブルは name/kind のみ維持 +- try_take_planner / fallback_extract の helper を追加して共通形に統一 + +### Step 2: log_none の意味を SSOT 化 + +- planner 採用時: log_none=false +- extractor フォールバック時: log_none=true + +### Step 3: docs / CURRENT_TASK 更新 + +Files: +- `docs/development/current/main/phases/phase-29aj/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 "phase29aj(p10): unify single_planner planner-first shape"` diff --git a/docs/development/current/main/phases/phase-29aj/README.md b/docs/development/current/main/phases/phase-29aj/README.md index 8d5036f5..8adcb7b7 100644 --- a/docs/development/current/main/phases/phase-29aj/README.md +++ b/docs/development/current/main/phases/phase-29aj/README.md @@ -73,6 +73,13 @@ Goal: planner の facts/plan を 1 本の outcome に集約し、観測の SSOT - 完了: phase286_pattern9_legacy_pack を追加し、運用ルールを docs に固定 - 検証: `./tools/smokes/v2/run.sh --profile quick` / `./tools/smokes/v2/profiles/integration/joinir/phase29ae_regression_pack_vm.sh` / `./tools/smokes/v2/profiles/integration/joinir/phase286_pattern9_legacy_pack.sh` (SKIP) +## P10: single_planner planner-first 形の統一(挙動不変) + +- 指示書: `docs/development/current/main/phases/phase-29aj/P10-SINGLE_PLANNER-UNIFY-PLANNER-FIRST-SHAPE-INSTRUCTIONS.md` +- ねらい: 全パターンを planner-first → extractor フォールバックの共通形に統一 +- 完了: RuleKind と single_planner の分岐形を統一し、log_none の意味を SSOT 化 +- 検証: `cargo build --release` / `./tools/smokes/v2/run.sh --profile quick` / `./tools/smokes/v2/profiles/integration/joinir/phase29ae_regression_pack_vm.sh` + ## Verification (SSOT) - `cargo build --release` diff --git a/src/mir/builder/control_flow/plan/single_planner/rules.rs b/src/mir/builder/control_flow/plan/single_planner/rules.rs index 435fd6d7..b2e1a2ce 100644 --- a/src/mir/builder/control_flow/plan/single_planner/rules.rs +++ b/src/mir/builder/control_flow/plan/single_planner/rules.rs @@ -67,83 +67,17 @@ pub(super) fn try_build_domain_plan(ctx: &LoopPatternContext) -> Result { - match planner_opt.as_ref() { - Some(DomainPlan::ScanWithInit(_)) => (planner_opt.clone(), false), - _ => ( - extractors::pattern6_scan_with_init::extract_scan_with_init_plan( - ctx.condition, - ctx.body, - ctx.fn_body, - )?, - true, - ), - } - } - RuleKind::Pattern7 => { - match planner_opt.as_ref() { - Some(DomainPlan::SplitScan(_)) => (planner_opt.clone(), false), - _ => ( - extractors::pattern7_split_scan::extract_split_scan_plan( - ctx.condition, - ctx.body, - &[], - )?, - true, - ), - } - } - RuleKind::Pattern5 => { - match planner_opt.as_ref() { - Some(DomainPlan::Pattern5InfiniteEarlyExit(_)) => (planner_opt.clone(), false), - _ => (extractors::pattern5::extract_pattern5_plan(ctx.condition, ctx.body)?, true), - } - } - RuleKind::Pattern8 => { - match planner_opt.as_ref() { - Some(DomainPlan::Pattern8BoolPredicateScan(_)) => (planner_opt.clone(), false), - _ => (extractors::pattern8::extract_pattern8_plan(ctx.condition, ctx.body)?, true), - } - } - RuleKind::Pattern9 => { - match planner_opt.as_ref() { - Some(DomainPlan::Pattern9AccumConstLoop(_)) => (planner_opt.clone(), false), - _ => (extractors::pattern9::extract_pattern9_plan(ctx.condition, ctx.body)?, true), - } - } - RuleKind::Pattern2 => { - match planner_opt.as_ref() { - Some(DomainPlan::Pattern2Break(_)) => (planner_opt.clone(), false), - _ => ( - extractors::pattern2_break::extract_pattern2_plan(ctx.condition, ctx.body)?, - true, - ), - } - } - RuleKind::Pattern3 => { - match planner_opt.as_ref() { - Some(DomainPlan::Pattern3IfPhi(_)) => (planner_opt.clone(), false), - _ => (extractors::pattern3::extract_pattern3_plan(ctx.condition, ctx.body)?, true), - } - } - RuleKind::Pattern4 => { - match planner_opt.as_ref() { - Some(DomainPlan::Pattern4Continue(_)) => (planner_opt.clone(), false), - _ => (extractors::pattern4::extract_pattern4_plan(ctx.condition, ctx.body)?, true), - } - } - RuleKind::Pattern1 => { - match planner_opt.as_ref() { - Some(DomainPlan::Pattern1SimpleWhile(_)) => (planner_opt.clone(), false), - _ => (extractors::pattern1::extract_pattern1_plan(ctx.condition, ctx.body)?, true), - } - } + let planner_hit = try_take_planner(&planner_opt, entry.kind); + let (plan_opt, log_none) = if planner_hit.is_some() { + (planner_hit, false) + } else { + (fallback_extract(ctx, entry.kind)?, true) }; let promotion_tag = if matches!(entry.kind, RuleKind::Pattern2) @@ -165,7 +99,7 @@ pub(super) fn try_build_domain_plan(ctx: &LoopPatternContext) -> Result, kind: RuleKind) -> Option { + match (kind, planner_opt.as_ref()) { + (RuleKind::Pattern1, Some(DomainPlan::Pattern1SimpleWhile(_))) => planner_opt.clone(), + (RuleKind::Pattern2, Some(DomainPlan::Pattern2Break(_))) => planner_opt.clone(), + (RuleKind::Pattern3, Some(DomainPlan::Pattern3IfPhi(_))) => planner_opt.clone(), + (RuleKind::Pattern4, Some(DomainPlan::Pattern4Continue(_))) => planner_opt.clone(), + (RuleKind::Pattern5, Some(DomainPlan::Pattern5InfiniteEarlyExit(_))) => { + planner_opt.clone() + } + (RuleKind::Pattern6, Some(DomainPlan::ScanWithInit(_))) => planner_opt.clone(), + (RuleKind::Pattern7, Some(DomainPlan::SplitScan(_))) => planner_opt.clone(), + (RuleKind::Pattern8, Some(DomainPlan::Pattern8BoolPredicateScan(_))) => { + planner_opt.clone() + } + (RuleKind::Pattern9, Some(DomainPlan::Pattern9AccumConstLoop(_))) => planner_opt.clone(), + _ => None, + } +} + +fn fallback_extract( + ctx: &LoopPatternContext, + kind: RuleKind, +) -> Result, String> { + match kind { + RuleKind::Pattern1 => extractors::pattern1::extract_pattern1_plan(ctx.condition, ctx.body), + RuleKind::Pattern2 => { + extractors::pattern2_break::extract_pattern2_plan(ctx.condition, ctx.body) + } + RuleKind::Pattern3 => extractors::pattern3::extract_pattern3_plan(ctx.condition, ctx.body), + RuleKind::Pattern4 => extractors::pattern4::extract_pattern4_plan(ctx.condition, ctx.body), + RuleKind::Pattern5 => extractors::pattern5::extract_pattern5_plan(ctx.condition, ctx.body), + RuleKind::Pattern6 => { + extractors::pattern6_scan_with_init::extract_scan_with_init_plan( + ctx.condition, + ctx.body, + ctx.fn_body, + ) + } + RuleKind::Pattern7 => extractors::pattern7_split_scan::extract_split_scan_plan( + ctx.condition, + ctx.body, + &[], + ), + RuleKind::Pattern8 => extractors::pattern8::extract_pattern8_plan(ctx.condition, ctx.body), + RuleKind::Pattern9 => extractors::pattern9::extract_pattern9_plan(ctx.condition, ctx.body), + } }