# Phase 131 P1.5: Implementation Guide (Quick Reference)

Status: Implementation Guide
Scope: Step-by-step implementation instructions for Option B
Related:
- Root Cause: `p1.5-root-cause-summary.md`
- Design: `p1.5-option-b-analysis.md`

## Implementation Sequence

### Step 1: Create ExitReconnectorBox (New File)

**File**: `src/mir/control_tree/normalized_shadow/exit_reconnector.rs`

**Responsibility**: Generate host variable bindings from k_exit env parameters (Normalized IR only, PHI-free)

**API**:
```rust
pub struct ExitReconnectorBox;

impl ExitReconnectorBox {
    /// Reconnect k_exit env parameters to host variable_map
    ///
    /// For Normalized IR only: k_exit env params are SSOT for final values
    pub fn reconnect(
        builder: &mut MirBuilder,
        exit_meta: &ExitMeta,
        env_layout: &EnvLayout,
        debug: bool,
    ) -> Result<(), String> {
        // For each exit_value (var_name, k_exit_param_vid)
        // - k_exit_param_vid is already the final value (SSOT)
        // - Update builder.variable_ctx.variable_map[var_name] = k_exit_param_vid
        //
        // Strict mode: verify all env_layout.writes are in exit_meta
        //
        // Returns: Ok(()) on success, Err(msg) on contract violation
    }
}
```

**Algorithm**:
```rust
// 1. Validate (strict mode only)
if strict_enabled() {
    for var in &env_layout.writes {
        if !exit_meta.exit_values.iter().any(|(name, _)| name == var) {
            return Err(freeze_with_hint(
                "phase131/exit_reconnect/missing",
                &format!("Variable '{}' in writes but not in k_exit env", var),
                "Ensure env_layout.writes matches k_exit parameter list (SSOT)"
            ));
        }
    }
}

// 2. Update variable_map directly (no PHI)
for (var_name, k_exit_param_vid) in &exit_meta.exit_values {
    // k_exit_param_vid is the final value (SSOT)
    builder.variable_ctx.variable_map.insert(
        var_name.clone(),
        *k_exit_param_vid
    );

    if debug {
        eprintln!(
            "[phase131/exit_reconnect] {} → {:?}",
            var_name, k_exit_param_vid
        );
    }
}
```

**File Template**:
```rust
//! Phase 131 P1.5: ExitReconnectorBox - Normalized Exit Reconnection
//!
//! ## Responsibility
//!
//! - Wire k_exit env parameters to host variable_map (Normalized IR only)
//! - PHI-free: k_exit env params are SSOT for final values
//! - Fail-Fast: Strict mode catches contract violations
//!
//! ## Contract
//!
//! - Only used for Normalized shadow path
//! - k_exit env parameters represent final variable values (SSOT)
//! - No PHI generation (direct variable_map update)
//!
//! ## Design Philosophy
//!
//! Normalized IR uses continuation-based control flow:
//! - main(env) → loop_step(env) → loop_body(env) → k_exit(env)
//! - k_exit receives final env state as parameters
//! - No loop back edges, no PHI merging needed
//! - k_exit env params ARE the truth (SSOT)

use crate::mir::builder::MirBuilder;
use crate::mir::control_tree::normalized_shadow::env_layout::EnvLayout;
use crate::mir::join_ir::lowering::carrier_info::ExitMeta;
use crate::mir::join_ir::lowering::error_tags;

pub struct ExitReconnectorBox;

impl ExitReconnectorBox {
    // ... implementation here ...
}

#[cfg(test)]
mod tests {
    // ... tests here ...
}
```

### Step 2: Update routing.rs (Bypass Merge Pipeline)

**File**: `src/mir/builder/control_flow/joinir/routing.rs`

**Location**: Lines 441-532 (current Normalized shadow handling)

**Changes**:

1. **Add env_layout to JoinFragmentMeta** (if not already there)
2. **Detect Normalized shadow path**
3. **Use ExitReconnectorBox instead of merge pipeline**

**Code Change**:
```rust
// Around line 441
match StepTreeNormalizedShadowLowererBox::try_lower_if_only(&tree, &available_inputs) {
    Ok(Some((join_module, join_meta))) => {
        // ... existing trace ...

        // Phase 131 P1.5: Normalized-specific exit reconnection
        // Bypass PHI-based merge pipeline, use direct env→host wiring
        use crate::mir::control_tree::normalized_shadow::exit_reconnector::ExitReconnectorBox;
        use crate::mir::control_tree::normalized_shadow::env_layout::EnvLayout;

        // Build env_layout from contract (or get from join_meta if available)
        let env_layout = EnvLayout::from_contract(&tree.contract, &available_inputs);

        // Direct reconnection (no PHI)
        ExitReconnectorBox::reconnect(
            self,
            &join_meta.exit_meta,
            &env_layout,
            debug,
        )?;

        trace::trace().routing(
            "router/normalized",
            func_name,
            "Normalized exit reconnection complete (PHI-free)",
        );

        // Return void constant (loop executed successfully)
        // Note: If k_exit returns a value, use that instead
        use crate::mir::{ConstValue, MirInstruction};
        let void_id = self.next_value_id();
        self.emit_instruction(MirInstruction::Const {
            dst: void_id,
            value: ConstValue::Void,
        })?;

        Ok(Some(void_id))
    }
    Ok(None) => {
        // ... existing fallback ...
    }
    Err(e) => {
        // ... existing error handling ...
    }
}
```

**Note**: Remove the existing `ExitMetaCollector::collect()` and `JoinIRConversionPipeline::execute()` calls - those are for standard loops with PHI.

### Step 3: Update mod.rs (Export ExitReconnectorBox)

**File**: `src/mir/control_tree/normalized_shadow/mod.rs`

**Add**:
```rust
pub mod exit_reconnector;
pub use exit_reconnector::ExitReconnectorBox;
```

### Step 4: Testing

#### Unit Tests (in exit_reconnector.rs)

```rust
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_empty_writes() {
        // When env_layout.writes is empty
        // Should return Ok(()) without updating variable_map
    }

    #[test]
    fn test_single_write() {
        // When env_layout.writes = ["x"]
        // And exit_meta.exit_values = [("x", ValueId(6))]
        // Should update variable_map["x"] = ValueId(6)
    }

    #[test]
    #[should_panic]
    fn test_missing_variable_strict() {
        // When strict mode enabled
        // And env_layout.writes = ["x", "y"]
        // But exit_meta.exit_values = [("x", ValueId(6))]
        // Should panic with freeze_with_hint
    }
}
```

#### Integration Tests

1. **VM Smoke**:
   ```bash
   bash tools/smokes/v2/profiles/integration/apps/phase131_loop_true_break_once_vm.sh
   ```
   Expected: `[PASS] Output verified: 1 (exit code: 1)`

2. **LLVM EXE Smoke**:
   ```bash
   bash tools/smokes/v2/profiles/integration/apps/phase131_loop_true_break_once_llvm_exe.sh
   ```
   Expected: `[PASS] Output verified: 1`

3. **Regression**:
   ```bash
   # If-only patterns (Phase 130)
   bash tools/smokes/v2/profiles/integration/apps/phase130_if_only_post_if_add_vm.sh

   # Existing JoinIR patterns (Phase 97)
   bash tools/smokes/v2/profiles/integration/apps/phase97_next_non_ws_llvm_exe.sh
   ```
   Expected: All PASS (既定挙動不変)

### Step 5: Verification Checklist

Before committing:
- [ ] `cargo build --release` → 0 errors
- [ ] `cargo test --lib` → all tests pass
- [ ] Phase 131 VM smoke → PASS
- [ ] Phase 131 LLVM EXE smoke → PASS
- [ ] Phase 130 regression → PASS
- [ ] Phase 97 regression → PASS

## Commit Sequence

### Commit 1: Create ExitReconnectorBox
```
feat(normalized): Phase 131 P1.5 ExitReconnectorBox for host variable propagation

- Add exit_reconnector.rs with pure function design
- Wire k_exit env params to host variable_map (PHI-free)
- Strict mode verifier for contract violations
- Unit tests for empty/single/multiple writes
```

### Commit 2: Update Routing
```
fix(joinir/dev): bypass PHI generation for Normalized path

- Detect Normalized shadow in routing.rs
- Use ExitReconnectorBox instead of merge pipeline
- Direct env→host wiring (no PHI generation)
- Existing patterns (Pattern 1-4) unaffected
```

### Commit 3: Enable Tests
```
test(joinir): Phase 131 P1.5 enforce return parity (VM + LLVM EXE)

- Enable phase131 VM/LLVM EXE smokes
- Verify regression tests (phase130, phase97)
- Update test expectations
```

### Commit 4: Documentation
```
docs: Phase 131 P1.5 DONE (Normalized exit reconnection via Option B)

- Update 10-Now.md with completion status
- Update phase-131/README.md with P1.5 summary
- Add root cause analysis docs
```

## Common Pitfalls to Avoid

1. **Don't touch merge pipeline**: Standard loops (Pattern 1-4) still use it
2. **Don't generate PHI**: Normalized IR is PHI-free by design
3. **Don't forget strict mode**: Contract violations should freeze
4. **Don't skip regression tests**: 既定挙動不変 is critical

## Key Principles (SSOT)

1. **PHI禁止維持**: Normalized IR never generates PHI nodes
2. **既定挙動不変**: Standard patterns use existing merge pipeline
3. **責務分離**: ExitReconnectorBox handles Normalized-specific wiring
4. **箱化モジュール化**: New logic in dedicated box
5. **Fail-Fast**: Strict mode catches violations immediately

## Success Criteria

- [ ] loop(true) { x=1; break }; return x → returns 1 (not 0)
- [ ] VM and LLVM EXE both produce same result
- [ ] No regression in existing patterns
- [ ] Clean trace output (no PHI errors)
- [ ] Strict mode catches contract violations

## Reference

- Root Cause: `p1.5-root-cause-summary.md`
- Design Rationale: `p1.5-option-b-analysis.md`
- Phase 131 Overview: `README.md`
