i have looked into the patch and it LGTM , will also look into the test.
a nitpick in the 003_tli_switch.pl file the comment says "....giving it a ".partial" suffix, and is not archived," but AFAIK, We do archive the .partial files right? CleanupAfterArchiveRecovery renames and notifies the archiver, or am I reading it wrong?
I think, there's a symmetric bug on the recovery side with the same root cause. Your patch makes the summarizer fall forward to a descendant timeline, which looks safe. XLogFileReadAnyTLI() does the opposite: when the switch-point segment is missing on the target timeline, it falls back to an ancestor and reads the same segno. But that segment holds divergent data continuing old timeline! Recovery applies it silently and then can't reach the intended timeline.
The comment you added to t/003_tli_switch.pl states the assumption that breaks here:
# ... recovery will read them from there and work just fine.
That holds only when the new timeline's segment is already there. Concretely, with just two timelines: TL2 forks from TL1 in segment 67, which is archived for TL1 but not yet for TL2. Recovery targets TL2 and asks for segment 67; TL2's copy isn't in the archive, so XLogFileReadAnyTLI() falls back to TL1 and hands back TL1's segment 67. Past the switch point that is the old primary's divergent WAL, recovery applies it, and now it can never get onto TL2. The beginseg check doesn't help here - it only skips a timeline for segments older than that timeline's start, so nothing stops the fallback to the ancestor TL1 for the very segment where the two diverge.