Now you can read all previous outputs for all inputs for all txs in any block as long as all previous blocks are already stored, which the validation chaser ensures. So far so good. But then you realize that you are going to need to be able to determine chain-relative things like height, mtp, active forks, etc. (context) in order to validate. And for a given tx, this context can change, as txs end up in different blocks (and no block). So you realize you need to store this context for every bock with the block header so that its available out of block order. Or at least, the validator needs to maintain this context for the candidate branch and issue it to each block validation job. But since you have already validated the headers, which required the same context, and have already downloaded and checked the blocks out of order, which also required some of the same context, and you need it for other things, you don't want to keep regenerating it, you decide to store context with each header.