From 2626deeb722e75d5459431a53c049da8346ef62d Mon Sep 17 00:00:00 2001 From: tomoaki Date: Mon, 29 Dec 2025 14:34:34 +0900 Subject: [PATCH] phase29ak(p0): ssot rule order + planner context plumbing --- CURRENT_TASK.md | 6 + docs/development/current/main/10-Now.md | 9 +- docs/development/current/main/30-Backlog.md | 5 + ...T-PLANNER-CONTEXT-PLUMBING-INSTRUCTIONS.md | 71 +++++++++ .../current/main/phases/phase-29ak/README.md | 10 ++ .../control_flow/plan/planner/context.rs | 8 ++ .../builder/control_flow/plan/planner/mod.rs | 6 +- .../control_flow/plan/planner/outcome.rs | 9 ++ .../control_flow/plan/single_planner/mod.rs | 1 + .../plan/single_planner/rule_order.rs | 38 +++++ .../control_flow/plan/single_planner/rules.rs | 135 ++++++------------ 11 files changed, 202 insertions(+), 96 deletions(-) create mode 100644 docs/development/current/main/phases/phase-29ak/P0-RULE-ORDER-SSOT-PLANNER-CONTEXT-PLUMBING-INSTRUCTIONS.md create mode 100644 docs/development/current/main/phases/phase-29ak/README.md create mode 100644 src/mir/builder/control_flow/plan/planner/context.rs create mode 100644 src/mir/builder/control_flow/plan/single_planner/rule_order.rs diff --git a/CURRENT_TASK.md b/CURRENT_TASK.md index f21c7e0f..cbd70893 100644 --- a/CURRENT_TASK.md +++ b/CURRENT_TASK.md @@ -15,12 +15,18 @@ Scope: Repo root の旧リンク互換。現行の入口は `docs/development/cu **JoinIR 回帰 SSOT** `./tools/smokes/v2/profiles/integration/joinir/phase29ae_regression_pack_vm.sh` が唯一の integration gate。phase143_* は対象外(legacy pack で隔離)。phase286_pattern9_* は legacy pack (SKIP) で運用。 +**PlanRuleOrder SSOT** +single_planner の順序/名前 SSOT は `src/mir/builder/control_flow/plan/single_planner/rule_order.rs` に固定。PlannerContext は P0 では未使用で、P1 以降で段階的に利用する。 + **2025-12-29: Phase 29aj P6 COMPLETE (JoinIR regression gate SSOT)** JoinIR 回帰の integration gate を phase29ae pack に固定し、phase143_* を legacy pack で隔離。 **2025-12-29: Phase 29aj P7 COMPLETE (Pattern8 planner-first)** Pattern8 BoolPredicateScan の Facts→Planner-first を導入し、single_planner の extractor 依存を縮小。 +**2025-12-29: Phase 29ak P0 COMPLETE (PlanRuleOrder + PlannerContext plumbing)** +PlanRuleOrder を SSOT 化し、PlannerContext を配線(未使用)。single_planner の手書きテーブルを撤去。 + **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 825f5719..4670e21a 100644 --- a/docs/development/current/main/10-Now.md +++ b/docs/development/current/main/10-Now.md @@ -1,11 +1,16 @@ # Self Current Task — Now (main) -## Current Focus: Phase 29aj(PlannerOutcome SSOT) +## Current Focus: Phase 29ak(PlanRuleOrder + PlannerContext) -Next: Phase 29aj P11(TBD) +Next: Phase 29ak P1(TBD) 運用ルール: integration filter で phase143_* は回さない(JoinIR 回帰は phase29ae pack のみ) 運用ルール: phase286_pattern9_* は legacy pack (SKIP) を使う +**2025-12-29: Phase 29ak P0 完了** ✅ +- 目的: PlanRuleOrder SSOT を新設し、PlannerContext の配線だけ先に導入(仕様不変) +- 実装: `src/mir/builder/control_flow/plan/single_planner/rule_order.rs` / `src/mir/builder/control_flow/plan/planner/context.rs` / `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 P10 完了** ✅ - 目的: single_planner を全パターン planner-first 形に統一(挙動不変) - 実装: `src/mir/builder/control_flow/plan/single_planner/rules.rs` diff --git a/docs/development/current/main/30-Backlog.md b/docs/development/current/main/30-Backlog.md index 38b6b1d9..523d4646 100644 --- a/docs/development/current/main/30-Backlog.md +++ b/docs/development/current/main/30-Backlog.md @@ -24,6 +24,11 @@ Related: - 運用: integration filter で phase143_* は回さない(JoinIR 回帰は phase29ae pack のみ) - 運用: phase286_pattern9_* は legacy pack (SKIP) を使う +- **Phase 29ak(candidate): PlanRuleOrder SSOT + PlannerContext plumbing** + - 入口: `docs/development/current/main/phases/phase-29ak/README.md` + - 状況: P0 ✅ 完了 + - Next: Phase 29ak P1(TBD) + - **Phase 29ai(candidate): Plan/Frag single-planner(Facts SSOT)** - 入口: `docs/development/current/main/phases/phase-29ai/README.md` - Next: Phase 29ai P16(TBD: promotion hint を JoinIR 側の orchestrator へ配線、挙動不変) diff --git a/docs/development/current/main/phases/phase-29ak/P0-RULE-ORDER-SSOT-PLANNER-CONTEXT-PLUMBING-INSTRUCTIONS.md b/docs/development/current/main/phases/phase-29ak/P0-RULE-ORDER-SSOT-PLANNER-CONTEXT-PLUMBING-INSTRUCTIONS.md new file mode 100644 index 00000000..d648beb3 --- /dev/null +++ b/docs/development/current/main/phases/phase-29ak/P0-RULE-ORDER-SSOT-PLANNER-CONTEXT-PLUMBING-INSTRUCTIONS.md @@ -0,0 +1,71 @@ +# Phase 29ak P0: PlanRuleOrder SSOT + PlannerContext plumbing + +Date: 2025-12-29 +Status: Ready for execution +Scope: 構造整備(仕様不変)+ docs/Now/Backlog/CURRENT_TASK 更新 +Goal: single_planner の順序/名前/ガード SSOT を 1 箇所へ寄せ、planner 側へ ctx を通す土台を作る + +## Objective + +- ルール順序/表示名の SSOT を新設し、single_planner の手書きテーブルを撤去 +- PlannerContext を導入して planner へ ctx を渡せるようにする(P0 では未使用) +- 既定挙動・ログ・エラー文字列は不変 + +## Non-goals + +- CandidateSet へ順序=優先を移す +- Pattern1 guard / Pattern8 static box filter を planner 側へ移す +- extractor fallback の削除 + +## Implementation Steps + +### Step 1: ルール順序 SSOT を新設 + +New: +- `src/mir/builder/control_flow/plan/single_planner/rule_order.rs` + +Contents: +- `PlanRuleId` と `PLAN_RULE_ORDER` +- `rule_name()` は従来の名前を完全一致で返す + +### Step 2: single_planner を SSOT 参照に差し替え + +Update: +- `src/mir/builder/control_flow/plan/single_planner/rules.rs` + +Notes: +- Pattern1 guard / Pattern8 static box filter / Pattern2 promotion tag を維持 +- ループの順序/ログ文言は変えない + +### Step 3: PlannerContext の足場(未使用) + +New: +- `src/mir/builder/control_flow/plan/planner/context.rs` + +Update: +- `src/mir/builder/control_flow/plan/planner/mod.rs` +- `src/mir/builder/control_flow/plan/planner/outcome.rs` +- `src/mir/builder/control_flow/plan/single_planner/rules.rs` + +Rule: +- P0 では ctx を意思決定に使わない(挙動不変) + +### Step 4: docs / CURRENT_TASK 更新 + +Add: +- `docs/development/current/main/phases/phase-29ak/README.md` + +Update: +- `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(p0): ssot rule order + planner context plumbing"` diff --git a/docs/development/current/main/phases/phase-29ak/README.md b/docs/development/current/main/phases/phase-29ak/README.md new file mode 100644 index 00000000..7106d433 --- /dev/null +++ b/docs/development/current/main/phases/phase-29ak/README.md @@ -0,0 +1,10 @@ +# Phase 29ak: PlanRuleOrder SSOT + PlannerContext plumbing + +Goal: single_planner の「順序・名前・ガード」の SSOT を 1 箇所へ寄せ、planner 側へ ctx を通す土台を作る(仕様不変)。 + +## P0: PlanRuleOrder SSOT + PlannerContext plumbing + +- 指示書: `docs/development/current/main/phases/phase-29ak/P0-RULE-ORDER-SSOT-PLANNER-CONTEXT-PLUMBING-INSTRUCTIONS.md` +- ねらい: rule_order.rs を順序/名前 SSOT に固定し、PlannerContext を配線(未使用) +- 完了: PlanRuleOrder を追加し、single_planner の手書きテーブルを撤去 +- 検証: `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/planner/context.rs b/src/mir/builder/control_flow/plan/planner/context.rs new file mode 100644 index 00000000..ec9e96ac --- /dev/null +++ b/src/mir/builder/control_flow/plan/planner/context.rs @@ -0,0 +1,8 @@ +use crate::mir::loop_pattern_detection::LoopPatternKind; + +#[derive(Debug, Clone, Copy)] +pub(in crate::mir::builder) struct PlannerContext { + pub pattern_kind: Option, + pub in_static_box: bool, + pub debug: bool, +} diff --git a/src/mir/builder/control_flow/plan/planner/mod.rs b/src/mir/builder/control_flow/plan/planner/mod.rs index b4ed9993..6224b344 100644 --- a/src/mir/builder/control_flow/plan/planner/mod.rs +++ b/src/mir/builder/control_flow/plan/planner/mod.rs @@ -7,9 +7,13 @@ pub(in crate::mir::builder) mod build; pub(in crate::mir::builder) mod candidates; +pub(in crate::mir::builder) mod context; pub(in crate::mir::builder) mod freeze; pub(in crate::mir::builder) mod outcome; pub(in crate::mir::builder) use build::build_plan; +pub(in crate::mir::builder) use context::PlannerContext; pub(in crate::mir::builder) use freeze::Freeze; -pub(in crate::mir::builder) use outcome::{build_plan_with_facts, PlanBuildOutcome}; +pub(in crate::mir::builder) use outcome::{ + build_plan_with_facts, build_plan_with_facts_ctx, PlanBuildOutcome, +}; diff --git a/src/mir/builder/control_flow/plan/planner/outcome.rs b/src/mir/builder/control_flow/plan/planner/outcome.rs index 7432ce56..d492606c 100644 --- a/src/mir/builder/control_flow/plan/planner/outcome.rs +++ b/src/mir/builder/control_flow/plan/planner/outcome.rs @@ -8,6 +8,7 @@ use crate::mir::builder::control_flow::plan::normalize::{ use crate::mir::builder::control_flow::plan::DomainPlan; use super::build::build_plan_from_facts; +use super::context::PlannerContext; use super::Freeze; #[derive(Debug, Clone)] @@ -34,3 +35,11 @@ pub(in crate::mir::builder) fn build_plan_with_facts( plan, }) } + +pub(in crate::mir::builder) fn build_plan_with_facts_ctx( + _ctx: &PlannerContext, + condition: &ASTNode, + body: &[ASTNode], +) -> Result { + build_plan_with_facts(condition, body) +} diff --git a/src/mir/builder/control_flow/plan/single_planner/mod.rs b/src/mir/builder/control_flow/plan/single_planner/mod.rs index 0a567fbf..2dec235d 100644 --- a/src/mir/builder/control_flow/plan/single_planner/mod.rs +++ b/src/mir/builder/control_flow/plan/single_planner/mod.rs @@ -8,6 +8,7 @@ use crate::mir::builder::control_flow::joinir::patterns::router::LoopPatternCont use super::DomainPlan; mod rules; +mod rule_order; pub(in crate::mir::builder) fn try_build_domain_plan( ctx: &LoopPatternContext, diff --git a/src/mir/builder/control_flow/plan/single_planner/rule_order.rs b/src/mir/builder/control_flow/plan/single_planner/rule_order.rs new file mode 100644 index 00000000..93e0f3d9 --- /dev/null +++ b/src/mir/builder/control_flow/plan/single_planner/rule_order.rs @@ -0,0 +1,38 @@ +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub(super) enum PlanRuleId { + Pattern6, + Pattern7, + Pattern5, + Pattern8, + Pattern3, + Pattern4, + Pattern9, + Pattern2, + Pattern1, +} + +pub(super) const PLAN_RULE_ORDER: &[PlanRuleId] = &[ + PlanRuleId::Pattern6, + PlanRuleId::Pattern7, + PlanRuleId::Pattern5, + PlanRuleId::Pattern8, + PlanRuleId::Pattern3, + PlanRuleId::Pattern4, + PlanRuleId::Pattern9, + PlanRuleId::Pattern2, + PlanRuleId::Pattern1, +]; + +pub(super) fn rule_name(id: PlanRuleId) -> &'static str { + match id { + PlanRuleId::Pattern6 => "Pattern6_ScanWithInit (Phase 273)", + PlanRuleId::Pattern7 => "Pattern7_SplitScan (Phase 273)", + PlanRuleId::Pattern5 => "Pattern5_InfiniteEarlyExit (Phase 286 P3.2)", + PlanRuleId::Pattern8 => "Pattern8_BoolPredicateScan (Phase 286 P2.4)", + PlanRuleId::Pattern3 => "Pattern3_IfPhi (Phase 286 P2.6)", + PlanRuleId::Pattern4 => "Pattern4_Continue (Phase 286 P2)", + PlanRuleId::Pattern9 => "Pattern9_AccumConstLoop (Phase 286 P2.3)", + PlanRuleId::Pattern2 => "Pattern2_Break (Phase 286 P3.1)", + PlanRuleId::Pattern1 => "Pattern1_SimpleWhile (Phase 286 P2.1)", + } +} 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 b2e1a2ce..4db0b652 100644 --- a/src/mir/builder/control_flow/plan/single_planner/rules.rs +++ b/src/mir/builder/control_flow/plan/single_planner/rules.rs @@ -8,13 +8,20 @@ use crate::mir::loop_pattern_detection::LoopPatternKind; use crate::mir::builder::control_flow::plan::extractors; use crate::mir::builder::control_flow::plan::facts::pattern2_loopbodylocal_facts::LoopBodyLocalShape; -use crate::mir::builder::control_flow::plan::planner; +use crate::mir::builder::control_flow::plan::planner::{self, PlannerContext}; use crate::mir::builder::control_flow::plan::DomainPlan; +use super::rule_order::{rule_name, PlanRuleId, PLAN_RULE_ORDER}; + pub(super) fn try_build_domain_plan(ctx: &LoopPatternContext) -> Result, String> { use crate::mir::builder::control_flow::joinir::trace; - let outcome = planner::build_plan_with_facts(ctx.condition, ctx.body) + let planner_ctx = PlannerContext { + pattern_kind: Some(ctx.pattern_kind), + in_static_box: ctx.in_static_box, + debug: ctx.debug, + }; + let outcome = planner::build_plan_with_facts_ctx(&planner_ctx, ctx.condition, ctx.body) .map_err(|freeze| freeze.to_string())?; let planner_opt = outcome.plan.clone(); let promotion_facts = outcome @@ -22,65 +29,26 @@ pub(super) fn try_build_domain_plan(ctx: &LoopPatternContext) -> Result Result Result, kind: RuleKind) -> Option { +fn try_take_planner(planner_opt: &Option, kind: PlanRuleId) -> 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(_))) => { + (PlanRuleId::Pattern1, Some(DomainPlan::Pattern1SimpleWhile(_))) => planner_opt.clone(), + (PlanRuleId::Pattern2, Some(DomainPlan::Pattern2Break(_))) => planner_opt.clone(), + (PlanRuleId::Pattern3, Some(DomainPlan::Pattern3IfPhi(_))) => planner_opt.clone(), + (PlanRuleId::Pattern4, Some(DomainPlan::Pattern4Continue(_))) => planner_opt.clone(), + (PlanRuleId::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(_))) => { + (PlanRuleId::Pattern6, Some(DomainPlan::ScanWithInit(_))) => planner_opt.clone(), + (PlanRuleId::Pattern7, Some(DomainPlan::SplitScan(_))) => planner_opt.clone(), + (PlanRuleId::Pattern8, Some(DomainPlan::Pattern8BoolPredicateScan(_))) => { + planner_opt.clone() + } + (PlanRuleId::Pattern9, Some(DomainPlan::Pattern9AccumConstLoop(_))) => { planner_opt.clone() } - (RuleKind::Pattern9, Some(DomainPlan::Pattern9AccumConstLoop(_))) => planner_opt.clone(), _ => None, } } fn fallback_extract( ctx: &LoopPatternContext, - kind: RuleKind, + kind: PlanRuleId, ) -> Result, String> { match kind { - RuleKind::Pattern1 => extractors::pattern1::extract_pattern1_plan(ctx.condition, ctx.body), - RuleKind::Pattern2 => { + PlanRuleId::Pattern1 => extractors::pattern1::extract_pattern1_plan(ctx.condition, ctx.body), + PlanRuleId::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 => { + PlanRuleId::Pattern3 => extractors::pattern3::extract_pattern3_plan(ctx.condition, ctx.body), + PlanRuleId::Pattern4 => extractors::pattern4::extract_pattern4_plan(ctx.condition, ctx.body), + PlanRuleId::Pattern5 => extractors::pattern5::extract_pattern5_plan(ctx.condition, ctx.body), + PlanRuleId::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( + PlanRuleId::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), + PlanRuleId::Pattern8 => extractors::pattern8::extract_pattern8_plan(ctx.condition, ctx.body), + PlanRuleId::Pattern9 => extractors::pattern9::extract_pattern9_plan(ctx.condition, ctx.body), } }