Fix infinite loop in Pattern6 (nested loop minimal) caused by main→loop_step
overwriting k_inner_exit→loop_step latch values.
Root cause: JoinIR main entry block was incorrectly treated as BackEdge,
causing it to overwrite the correct latch incoming values set by the true
back edge (k_inner_exit → loop_step).
Solution:
- Restrict latch recording to TailCallKind::BackEdge only
- Treat only MAIN's entry block as entry-like (not loop_step's entry block)
- Add debug_assert! to detect double latch set in future
Refactoring:
- Extract latch recording to latch_incoming_recorder module (SSOT)
- Add boundary.loop_header_func_name for explicit header identification
- Strengthen tail_call_classifier with is_source_entry_like parameter
Tests: apps/tests/phase1883_nested_minimal.hako → RC:9 (was infinite loop)
Smoke: 154/154 PASS, no regressions
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>