Join the flow of an `if`'s branches instead of chaining it

The behaviour lens explored an unknown condition's branches ONE AFTER ANOTHER
in the same `Interp`, so the flow state carried over between them: a branch that
terminated made the NEXT branch's first statement look unreachable, and whatever
the LAST branch left behind was what survived past the whole `if`.

`guard` is modelled as an `SIf` with an EMPTY then-branch, so the then never
terminates and this is the falsest case there is:

    fn f(g : Int?) -> Int {
      guard g is Some(v) else {
        return 0
      }
      return v        // reported as `unreachable code`, and is not
    }

The else terminates, the then does not, and the else's flow won the race. This
is the shape moonbit-community/proton 0.3.4 `facade_app_metadata.mbt:81-82`
has, with a `raise` in the else instead of a `return` -- and it reproduces with
no `raise` anywhere. 0.4.24 recorded it and did not fix it; this is the fix.

Each branch now resets `self.flow = FNormal` before running and contributes
`falls = self.flow == FNormal` after. A MISSING else is always `falls = true`,
because when no branch is taken nothing runs and control continues. The join is
`self.flow = if falls { FNormal } else { FReturn }`. `exec_alt` changed from
`Unit` to returning `Bool` and joins the same way, and `SIf`'s `ABool(false)`
arm now takes its flow from it instead of inheriting whatever ran last.

Every branch terminating is STILL reported as dead code. That direction is the
one that matters and the one a coverage number cannot see: a check whose
precondition can never hold is a failure mode, and it is worse than the false
positive being fixed, because nothing reports it.

MEASURED, and stated plainly because a zero is easy to misread: across the six
corpora, 12,428 files, this change moves NOTHING. Every scan is byte-identical
before and after -- checked twice, against both the 0.4.24 baseline and the
earlier 0.4.25 scan. Zero `Unreachable` findings existed before it and zero
exist after. This is a correctness fix with a reproducer and no corpus delta,
not a claim that it cleaned up anything it can be measured cleaning up.

An `ABottom` condition keeps its old meaning (it does not terminate, it falls
through). Whether a bottom condition should suppress everything downstream is a
separate question and this answers it in neither direction.

Tests js 398 / wasm 470 / wasm-gc 398 (added 12).

The mutation gate took three rounds, and the two kinds of survivor were dumber
than "not enough tests", so both are written down rather than quietly fixed:

  - A fixture must actually REACH the code it claims to test. `f(1)` binds `n`
    to `AInt(1)`, `binop` folds `n > 0` to `ABool(true)`, and the then-branch
    runs alone -- the arm the join lives in is never entered. `f(g())` with `g`
    undefined returns `ABottom` and silences the whole body, which looks
    exactly like a passing test. Four mutations died on this. What reaches the
    join is a condition the abstract interpreter cannot fold: `s == "a"`, since
    `binop`'s `OpEq | OpNe` arm returns `AType("bool")` unconditionally. The
    control that makes it meaningful is the FOLDED fixture with the same shape
    and the OPPOSITE expected count -- an earlier version used `f(1)` for both,
    so its "control" was only re-testing constant folding.

  - A NO-OP mutation is only reported after a full suite run. Three pattern
    strings never matched the source (wrong indentation; `None => true` where
    the arm reads `None => falls = true`) and each cost a `moon test` to learn
    nothing. There is now a pre-flight that aborts in milliseconds and prints the
    line it was looking for; it immediately caught one of my own mistakes.

  - M6's survivor was neither: `exec_alt`'s terminal `match els` only runs when
    there are no else-ifs left, and every chain fixture had one, so no fixture
    reached it. Adding one also turned up M8 -- the terminal version of "a
    missing else falls through", equally unobserved. M6 and M8 now change one
    line inside the same 8-line block and are the two directions of one decision.

Final gate: 8 mutations, 8 killed, 0 survived, 0 no-op, every restore verified
byte-identical by SHA256.