# Phase 137-4: Loop Canonicalizer Router Parity Verification

**Status**: ✅ Complete
**Date**: 2025-12-16

## Summary

Dev-only verification that Loop Canonicalizer and Router pattern detection agree on pattern classification. On mismatch, provides detailed diagnostic with Fail-Fast option.

## Implementation

### Location

`src/mir/builder/control_flow/joinir/routing.rs`

### Components

1. **Parity Verification Function** (`verify_router_parity`)
   - Runs canonicalizer on the loop AST
   - Compares canonicalizer's chosen pattern with router's `ctx.pattern_kind`
   - Logs match/mismatch results
   - In strict mode, returns error on mismatch

2. **Integration Point**
   - Called in `cf_loop_joinir_impl` after `LoopPatternContext` is created
   - Only runs when `joinir_dev_enabled()` returns true
   - Deferred until after ctx creation to access `ctx.pattern_kind`

### Behavior Modes

#### Debug Mode (Default)
```bash
HAKO_JOINIR_DEBUG=1 ./target/release/hakorune program.hako
```
- Logs parity check results to stderr
- On mismatch: Logs warning but continues execution
- On match: Logs success message

#### Strict Mode
```bash
HAKO_JOINIR_STRICT=1 ./target/release/hakorune program.hako
```
- Same as debug mode, but on mismatch:
- Returns error and stops compilation
- Provides detailed mismatch diagnostic

### Output Examples

#### Match (Success)
```
[loop_canonicalizer/PARITY] OK in function 'foo':
  canonical and actual agree on Pattern1SimpleWhile
```

#### Mismatch (Warning in Debug)
```
[loop_canonicalizer/PARITY] MISMATCH in function 'main':
  canonical=Pattern3IfPhi, actual=Pattern2Break
```

#### Mismatch (Error in Strict)
```
[ERROR] ❌ MIR compilation error:
  [loop_canonicalizer/PARITY] MISMATCH in function 'main':
  canonical=Pattern3IfPhi, actual=Pattern2Break
```

#### Canonicalizer Failure
```
[loop_canonicalizer/PARITY] Canonicalizer failed for 'bar':
  Phase 3: Loop does not match skip_whitespace pattern
```

## Test Coverage

### Unit Tests

1. **`test_parity_check_mismatch_detected`**
   - Verifies mismatch detection on skip_whitespace pattern
   - Canonicalizer: Pattern3IfPhi (recognizes if-else structure)
   - Router: Pattern2Break (sees has_break flag)
   - Asserts inequality to document expected mismatch

2. **`test_parity_check_match_simple_while`**
   - Verifies canonicalizer fails on Pattern1 (not yet implemented)
   - Router: Pattern1SimpleWhile
   - Canonicalizer: Fail-Fast (only supports skip_whitespace in Phase 3)

### Integration Tests

```bash
# Verify mismatch detection (debug mode)
HAKO_JOINIR_DEBUG=1 ./target/release/hakorune \
  tools/selfhost/test_pattern3_skip_whitespace.hako

# Verify strict mode error
HAKO_JOINIR_STRICT=1 ./target/release/hakorune \
  tools/selfhost/test_pattern3_skip_whitespace.hako
# Expected: Exit with error due to mismatch
```

## Known Mismatches

### skip_whitespace Pattern

**Structure**:
```nyash
loop(p < len) {
  if is_ws == 1 {
    p = p + 1
  } else {
    break
  }
}
```

**Mismatch**:
- **Canonicalizer**: Pattern3IfPhi
  - Recognizes specific if-else structure with conditional carrier update
  - Sees: `if cond { carrier += 1 } else { break }` as Pattern3 variant

- **Router**: Pattern2Break
  - Classification based on `has_break` flag
  - Priority: break detection takes precedence over if-else structure

**Resolution Strategy**:
- Phase 4: Document and observe (current)
- Phase 5+: Refine classification rules to handle hybrid patterns
- Option A: Extend Pattern3 to include "break-in-else" variant
- Option B: Create new Pattern6 for this specific structure
- Option C: Make router defer to canonicalizer's decision

## Design Rationale

### Why Two Systems?

1. **Router (Existing)**
   - Feature-based classification (`has_break`, `has_continue`, etc.)
   - Fast, simple flags
   - Priority-based (e.g., break > if-else)

2. **Canonicalizer (New)**
   - Structure-based pattern matching
   - Deep AST analysis
   - Recognizes specific code idioms

### Why Parity Check?

- **Incremental Migration**: Allows canonicalizer development without breaking router
- **Safety Net**: Catches classification divergence early
- **Documentation**: Explicitly records where systems disagree
- **Flexibility**: Dev-only, no production overhead

### Why Dev-Only?

- **No Performance Impact**: Zero cost in release builds (flag-gated)
- **Development Insight**: Helps refine both systems
- **Fail-Fast Option**: Strict mode for CI/validation
- **Graceful Degradation**: Debug mode allows execution to continue

## Acceptance Criteria

- ✅ Flag OFF: No behavioral change
- ✅ Dev-only: Match/mismatch observable
- ✅ Strict mode: Mismatch stops compilation
- ✅ Debug mode: Mismatch logs warning
- ✅ Unit tests: 2 tests passing
- ✅ Integration test: skip_whitespace mismatch detected
- ✅ All tests: `cargo test --release --lib` passes (1046/1046)

## Future Work

### Phase 5: Pattern Classification Refinement

- Resolve skip_whitespace classification (Pattern2 vs Pattern3)
- Extend Pattern3 to handle break-in-else variant
- OR: Create Pattern6 for "conditional update with early exit"

### Phase 6: Canonicalizer Expansion

- Add Pattern1 (Simple While) to canonicalizer
- Add Pattern2 (Conditional Break) variants
- Add Pattern4 (Continue) support
- Add Pattern5 (Infinite Early Exit) support

### Phase 7: Router Migration

- Consider migrating router to use canonicalizer decisions
- Option: Make `ctx.pattern_kind = decision.chosen` if canonicalizer succeeds
- Gradual transition from feature-based to structure-based routing

## References

- **Phase 137-2**: Loop Canonicalizer observation (dev-only logging)
- **Phase 137-3**: skip_whitespace pattern recognition
- **Design SSOT**: `docs/development/current/main/design/loop-canonicalizer.md`
- **JoinIR Architecture**: `docs/development/current/main/joinir-architecture-overview.md`
