diff --git a/docs/ROLLBACK_MOTK_HOOKUP.md b/docs/ROLLBACK_MOTK_HOOKUP.md index 765e516e..b7f85131 100644 --- a/docs/ROLLBACK_MOTK_HOOKUP.md +++ b/docs/ROLLBACK_MOTK_HOOKUP.md @@ -4863,6 +4863,9 @@ window. `media_kf=0` because load was past the media/settle unsafe range. 5. **On heal Live/tip-hold** — clear DESYNC invent-hold and RELEASE lockstep. 6. **Pad-mispredict** begins in the post-FMV window still SPAN (optionally with MEDIA_KF via `rb_want_heal_kf`); only silent-fork recovery is apply-only. +7. **POST match → Live** — `ownership_on_post_match` treats heal like + peer-ahead light: no ownership SPAN hop (session 28: matched POST @826 + then chain target=850 hung guest wait-FOLLOW → disconnect). **Re-soak watch (Win↔Linux 2P through title FMV):** diff --git a/runtime/src/psx_netplay_rb.c b/runtime/src/psx_netplay_rb.c index 60237a1c..6fabc08a 100644 --- a/runtime/src/psx_netplay_rb.c +++ b/runtime/src/psx_netplay_rb.c @@ -4888,6 +4888,19 @@ static void ownership_on_post_match(uint32_t tip) ownership_exit_to_live(tip, frontier, "peer-ahead light", 1); return; } + /* §109: apply-only post-FMV heal KF — POST already matched at load. + * Do NOT ownership-chain SPAN through the soft-fork window (soak session + * 28: heal POST tip=826 matched, then chain hop target=850 hung guest + * wait-FOLLOW → peer disconnect). */ + if (g_post_fmv_heal_kf) { + fprintf(stderr, + "psxrecomp: rb post-FMV heal KF tip=%u frontier=%u → Live " + "(no ownership chain)\n", + (unsigned)tip, (unsigned)frontier); + fflush(stderr); + ownership_exit_to_live(tip, frontier, "post-FMV heal KF", 1); + return; + } /* §48/§49/§73/§86/§87 B/§104: micro frontiers at/below min_ahead do not * chain. min_ahead = max(6, D-1) — delay cushion is not catch-up backlog, * but tip+D still chains once (D-1 headroom) instead of tip-hold every