feat(mir): Phase 137-5 - Decision Policy SSOT化完了

## 目的
Canonicalizer の RoutingDecision.chosen を「lowerer 選択の最終結果」にする
(構造クラス名ではなく ExitContract ベースの決定)

## 実装内容

### 1. Canonicalizer の決定ロジック修正
- `src/mir/loop_canonicalizer/mod.rs`
  - `skip_whitespace` パターン認識で ExitContract (has_break=true) を考慮
  - Pattern3IfPhi → Pattern2Break に修正(構造は似ているが break あり)
  - 単体テスト更新(Pattern2Break 期待に変更)

### 2. Parity 検証テスト修正
- `src/mir/builder/control_flow/joinir/routing.rs`
  - `test_parity_check_mismatch_detected` → `test_parity_check_skip_whitespace_match`
  - Canonicalizer と Router の一致を検証(ミスマッチ検出からマッチ検証へ)
  - Phase 137-5 の SSOT 原則を反映

### 3. ドキュメント更新
- `docs/development/current/main/design/loop-canonicalizer.md`
  - Phase 137-5: Decision Policy SSOT セクション追加
  - ExitContract 優先の原則を明記
  - skip_whitespace の例を追加

- `docs/development/current/main/phases/phase-137/README.md`
  - Phase 4 完了マーク追加
  - Phase 5 完了セクション追加(実装・検証・効果)

## 検証結果
-  単体テスト: `cargo test --release --lib loop_canonicalizer::tests` (11/11 passed)
-  Parity テスト: `cargo test --release --lib 'routing::tests::test_parity'` (2/2 passed)
-  Strict モード: `HAKO_JOINIR_STRICT=1` で skip_whitespace parity OK

## 効果
- Router と Canonicalizer の pattern 選択が一致
- ExitContract が pattern 決定の SSOT として明確化
- 構造的特徴(if-else 等)は notes に記録(将来拡張に備える)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-12-16 06:17:03 +09:00
parent 9ea15e8417
commit 58f66e3fa2
4 changed files with 61 additions and 15 deletions

View File

@ -1,6 +1,6 @@
# Loop Canonicalizer設計 SSOT
Status: Phase 2 donedev-only 観測まで)
Status: Phase 3 doneskip_whitespace の安定認識まで)
Scope: ループ形の組み合わせ爆発を抑えるための “前処理” の設計fixture/shape guard/fail-fast と整合)
Related:
- SSOT (契約/不変条件): `docs/development/current/main/joinir-architecture-overview.md`
@ -166,6 +166,7 @@ pub enum CarrierRole {
注意:
- Phase 2 で `canonicalize_loop_expr(...) -> Result<(LoopSkeleton, RoutingDecision), String>` を導入し、JoinIR ループ入口で dev-only 観測できるようにした(既定挙動は不変)。
- 観測ポイントJoinIR ループ入口): `src/mir/builder/control_flow/joinir/routing.rs``joinir_dev_enabled()` 配下)
- Phase 3 で `skip_whitespace` の最小形を `Pattern3IfPhi` として安定に識別できるようにしたdev-only 観測)。
## Capability の語彙Fail-Fast reason タグ)
@ -197,6 +198,7 @@ Canonicalizer の判定結果は `RoutingDecision` に集約し、以下に流
```rust
pub struct RoutingDecision {
/// 選択された PatternNone = Fail-Fast
/// Phase 137-5: ExitContract に基づく最終 lowerer 選択を反映
pub chosen: Option<LoopPatternKind>,
/// 不足している Capability のリスト
@ -210,6 +212,20 @@ pub struct RoutingDecision {
}
```
### Phase 137-5: Decision Policy SSOT
**原則**: `RoutingDecision.chosen` は「lowerer 選択の最終結果」を返す(構造クラス名ではなく)。
- **ExitContract が優先**: `has_break=true` なら `Pattern2Break``has_continue=true` なら `Pattern4Continue`
- **構造的特徴は notes へ**: 「if-else 構造がある」等の情報は `notes` フィールドに記録
- **一致保証**: Router と Canonicalizer の pattern 選択が一致することを parity check で検証
**例**: `skip_whitespace` パターン
- 構造: if-else 形式Pattern3IfPhi に似ている)
- ExitContract: `has_break=true`
- **chosen**: `Pattern2Break`ExitContract が決定)
- **notes**: "if-else structure with break in else branch"(構造特徴を記録)
### 出力先マッピング
| 出力先 | 条件 | 用途 |