docs(phase29ai): add P4 first LoopFacts instructions

This commit is contained in:
2025-12-29 07:28:15 +09:00
parent 3fb5c1a544
commit 4fa425fac2
4 changed files with 73 additions and 2 deletions

View File

@ -2,7 +2,7 @@
## Current Focus: Phase 29aiPlan/Frag single-planner
Next: `docs/development/current/main/phases/phase-29ai/P3-TYPED-FREEZE-CANDIDATESET-IMPLEMENTATION-INSTRUCTIONS.md`
Next: `docs/development/current/main/phases/phase-29ai/P4-FIRST-LOOPFACTS-PATTERN6-SCAN_WITH_INIT-INSTRUCTIONS.md`
**2025-12-29: Phase 29ag P1 完了**
- 目的: coordinator の ValueId(idx) 前提を撤去し、boundary.join_inputs を SSOT 化(仕様不変)

View File

@ -19,7 +19,7 @@ Related:
- **Phase 29aicandidate: Plan/Frag single-plannerFacts SSOT**
- 入口: `docs/development/current/main/phases/phase-29ai/README.md`
- Next: P3Typed Freeze + CandidateSet implementation
- Next: P4First LoopFacts: Pattern6 scan-with-init
- **Phase 29ae P1✅ COMPLETE: JoinIR Regression Pack (SSOT固定)**
- 入口: `docs/development/current/main/phases/phase-29ae/README.md`

View File

@ -0,0 +1,66 @@
# Phase 29ai P4: First LoopFacts (Pattern6 scan-with-init) — Instructions
Status: Ready for execution
Scope: Facts→Planner を “1ケースだけ” 前進(仕様不変・未接続)
## Goal
Facts SSOT を「実際に1ケース取れる」状態にし、Planner が `Ok(Some(plan))` まで到達できる最小の縦割りを作る。
- 対象: Pattern6 `scan_with_init`**最小・正規形**(既存で PASS している fixture の形に限る)
- 入口は single-planner のままpattern 名で分岐しない)
- 既存ルーティング/emit には接続しない(仕様不変)
## Non-goals
- Pattern6 の全派生reverse/matchscan/splitscan 等)の吸収
- 既存 `plan/normalizer/*` の置換
- 新しいトグル/環境変数の追加
- 永続ログの追加
## Target Shape (canonical only)
Loop + step の最小形だけを認識する(例):
- loop condition: `i < n``ASTNode::BinaryOp { operator: Less, left: Variable{i}, right: Variable{n} }`
- loop body 末尾 step: `i = i + 1``Assignment(target=Variable{i}, value=BinaryOp(Add, Variable{i}, Literal(Int(1))) )`
上記以外は **Ok(None)**NotApplicableで返す。
「対象っぽいのに契約違反」は **Err(Freeze::contract(...))** で Fail-Fastただし P4 では Freeze を出す形を最小に絞る)。
## Implementation Steps
1) `facts/scan_shapes.rs` を最小だけ具体化
- `StepShape::AssignAddConst { var: String, k: i64 }`
- `ConditionShape::VarLessVar { left: String, right: String }`
- Unknown は残す(拡張余地)
2) `facts/loop_facts.rs` で canonical 抽出(厳格)
- `try_build_loop_facts(condition, body)` で上記 shape を抽出できたときだけ `Ok(Some(LoopFacts{...}))`
- それ以外は `Ok(None)`NotApplicable
- “loop だけど条件/step が壊れてる” と断定できる場合のみ `Err(Freeze::contract(...))`
3) `normalize/canonicalize.rs` は表現ゆれ吸収の座席だけ用意
- P4 では実質 no-op でも良いP5 で reverse 等を吸収するための前提を置く)
4) `planner/build.rs` に最小 rule を追加(候補集合方式)
- `rule = "loop/scan_with_init"` のような内部名で `PlanCandidate` を1件だけ出す
- `PlanKind``ScanWithInit` を追加Plan はまだ placeholder でも良い)
5) テスト(軽量)
- Rust unit test`#[cfg(test)]`)で `try_build_loop_facts``Ok(Some)`/`Ok(None)` を固定
- 既存の quick/回帰パックも緑維持(仕様不変)
## Verification (SSOT)
- `cargo build --release`
- `./tools/smokes/v2/run.sh --profile quick`
- `./tools/smokes/v2/profiles/integration/joinir/phase29ae_regression_pack_vm.sh`
## Acceptance Criteria
- 仕様不変Plan/Frag 既存経路に未接続、quick/回帰パックが緑)
- Facts が “1ケースだけ” `Ok(Some)` を返せる
- Planner がその Facts で `Ok(Some(plan))` まで到達できる(候補集合→一意化)
- `Ok(None)` / `Err(Freeze)` の境界が docs の taxonomy と矛盾しない

View File

@ -24,6 +24,11 @@ Goal: pattern 名による分岐を外部APIから消し、Facts事実
- 指示書: `docs/development/current/main/phases/phase-29ai/P3-TYPED-FREEZE-CANDIDATESET-IMPLEMENTATION-INSTRUCTIONS.md`
- ねらい: Planner の契約を型/候補集合で固定Facts 未実装の間は未到達、仕様不変)
## P4: First LoopFactsPattern6 scan-with-init
- 指示書: `docs/development/current/main/phases/phase-29ai/P4-FIRST-LOOPFACTS-PATTERN6-SCAN_WITH_INIT-INSTRUCTIONS.md`
- ねらい: Facts→Planner を 1 ケースだけ前進(未接続のまま、仕様不変)
## Verification (SSOT)
- `cargo build --release`