Apparently, the official rule is that a chain is correct if the reference client says it is correct.
I wonder if the creation of some block-chain serialization format would be appropriate. This could be combined with a verifier.
This would be a much shorter program than an entire client that needs to deal with networking.
Maybe that could be vetted into some kind of semi-official spec.
Probably all the blocks, one after another, in the same format as the network protocol, is sufficient, so maybe I am over-thinking it.
Well, you gotta look at the process by which the reference client determines a block is valid. First of all it's received from a peer with ProcessMessage(). That function almost immediately calls ProcessBlock(), which first calls CheckBlock() to do context independent validation of the block; basic rules like "Does it have a coinbase?" which must be true for any block. The real heavy lifting is the next step, AcceptBlock(), which does the context dependent validation. This is where transactions in the block are validated, and that requires the blockchain as well as full knowledge of the unspent transaction outputs. (the UTXO set) Getting those rules right is very difficult - the scripting system is complex and depends on a huge amount of code. Like it or not, there is no way to turn it into a "short verifier program"; the reference implementation itself is your short verifier program.
Thus right now we are far safer if all miners use the reference implementation to generate blocks and nothing else. However, we are also a lot safer if the vast majority of relay nodes also continue to use the reference implementation, at least right now. The problem is that even if a block is valid by the validation rules, if for some reason it doesn't get relayed to the majority of hash power you've caused a fork anyway. With the reference implementation this is really unlikely - as I explained above the relay rules are the validation rules - alternate implementations of relay nodes might not have that property though.
An interesting example of relay failure is how without the block-size limit any sequence of blocks with a size large enough that some minority of the hashing power can't download and validate them fast enough creates a fork. Specifically the blocks need to be large enough that the hash power in the "smaller-block" fork still creates blocks at a faster rate than the large-blocks are downloaded. Technically, with the block-size limit this can happen too, but the limit is so low even most dial-up modems can keep up. Block "discouragement" rules can also have the same effect, for much the same reasons.
For merchants a hard-fork bug leaves them vulnerable to double-spends by anyone with a lot of hashpower, but it'll cost the attacker one block reward per confirmation required. (the attacker can amortize the attack across multiple merchants) Merchants should be running code that looks for unusually long block creation time, and automatically shuts down their service if it looks like the hash rate has dropped significantly. Just doing this is probably good enough for the vast majority of merchants that take at least 12 hours to process and ship an order.
Some merchants are more vulnerable - a really bad example would be a chaum token issuing bank. Once you accept a deposit, give the customer the chaum token you have absolutely no way of invalidating the token because redemption is anonymous. Merchants like that should be running their own reference implementation nodes, double-checking those blockchains with other sources, and keeping their clocks accurate so they'll know when hashing power has dropped off mysteriously.
For instance you could run a service that would (ab)use DNS to publish each block header as a DNS record. Headers are just 96 bytes long so they'd still fit in single UDP packet DNS requests I think. Caching at the ISP level would reduce load on the server. (although ISP's that don't respect TTL's are a problem) The proof-of-work inherently authenticates the data and parallel services should be run by multiple people with different versions of the reference client. I wouldn't want to only trust such a service, but it'd make for a good "WTF is going on, shut it all down" failsafe mechanism for detecting forks.