[PPF] Fix navigation() in prospective runtime prerenders (#98000)
### Long story short
Fixes an analogous bug to #95665, but affecting
`prefetch()/navigation()`. Those two were accidentally always resolving
in the **prospective** runtime prerender, so we were warming content
that isn't needed for the final runtime prerender. We now guard them
properly.
Also, I replaced `PrerenderStoreModernRuntime.isSessionShell` with
`finalStage` (the same stage we're gonna use for the final prerender),
so we can include/exclude `navigation` properly -- the boolean only
distinguished shell/prefetch, not navigation.
### Long story long
We use runtime prerenders for three things: runtime shells, runtime
prefetches, and embedding a prefetch in navigations. These are aborted
after `ShellRuntime`, `Runtime`, and `NavigationRuntime` respectively
(accessible in `stageController.finalStage`). If we're doing the
**final** prerender for a shell, promises that would resolve in e.g.
`NavigationRuntime` would never resolve, because we abort the prerender
before we get there.
However, the **prospective** runtime prerender has no
`StagedRenderingController` and needs to model this separately (so that
the same APIs hang in both). This was [previously done via
`prerenderStore.isSessionShell`](https://github.com/vercel/next.js/pull/95665)
which we checked in URL data apis i.e. `params/searchParams` and the
metadata`pathname` to do this. `isSessionShell: true` meant they should
hang because it's a shell, and `isSessionShell: false` meant they should
resolve.
However, I forgot about this case when implementing
`navigation`/`prefetch`, and made them resolve unconditionally in the
prospective prerender. This means we'd potentially warm content that
would not actually be reached in the final prerender. In other words,
```ts
await navigation()
return <Expensive />
```
would needlessly render `<Expensive />` during the prospective render
but not in the final one. This kinda defeats `navigation`'s main
purpose, i.e. avoiding expensive work.
This PR fixes the bug by replacing `isSessionShell: boolean` with
`finalStage: AdvanceableRenderStage`, which is set to the same value we
put in `stageController.finalStage`. This lets us keep the logic of what
hangs and what resolves relatively close in both prerenders.
---
On a meta level, the fact that the same bug happened twice tells me that
having a `StageRenderingController` that is sometimes `null` is
error-prone, and we should figure out a better solution, but i'm gonna
keep this fix targeted and figure out a more holistic solution in a
follow-up