Backports:
v31.1 still carries the pre-fix LoadBlockIndex, which re-adds a pruned block to m_blocks_unlinked when its parent is header-only (#35050). On the next block connected, CheckBlockIndex hits Assertion failed: (!foundInUnlinked). -checkblockindex is on by default only on regtest, so this crashes functional-test suites run against 31.x, not mainnet nodes.
Both commits cherry-pick cleanly with -x. The only difference from master is the surrounding context in test_runner.py. The added feature_prune_stale_fork.py fails against the v31.1 release binary on the assertion above and passes on this branch (2/2 each, macOS arm64, built from depends).
I left the release-notes entry to whoever assembles the 31.x notes.