First question, where is this behaviour defined in the C# specs
Your first question is the answerable one, and it got answered in Matthew Watson's excellent answer.
why was it designed this way?
All design processes require making tradeoffs between a variety of competing design goals. The design goals of C# included such diverse elements as familiarity to C++ developers, ability to interoperate with unmanaged libraries that use non-.NET-friendly conventions such as unsigned integer types, the ability to write a compiler that figures out what you meant in possibly ambiguous situations, but still informs you when it looks like you did something wrong, and so on.
"Values can be seamlessly substituted for symbols evaluating to those values" is a good principle of language design. But it's not the only one. Since several of these goals are, in your case, contradictory, something's got to give. (Also, as I note below, you aren't substituting values!)
I agree with you that the fact that x + -1 and x - 1 have different types is weird. What type would you like them both to be?
Let's suppose you want them both to be long. Now we have the following problem: what is the type of x - x? If it is uint, because we have the different of two uints, then we have the weirdness that x - x and x - 1 are different types. If it is long, then we have the weirdness that the difference of two uints that fits into a uint is not a uint.
Let's suppose you want them both to be uint. Then should x + anySignedInt be uint? Why should it be uint instead of int? Surely if we have uint 2 and int -3, then 2 + -3 should be the int -1.
No matter what you do, you end up with a weird situation. That's because unsigned quantities don't obey the usual rules of arithmetic. The language design team is doing the best they can with a bad situation.
The exact details of how these decisions were arrived at 17 years ago is lost to the mists of time.
Second question, the types of 1 and -1 are System.Int32. Why then is it behaving differently to const int y=-1?
I assume your question is "why are x + y and x - 1 analyzed differently when plainly they are equivalent expressions?", but they are not the same expression. x + y and x + -1 are the same expression, and they are analyzed the same; the sum of a uint and an int constant which does not fit into a uint promotes both to long. The difference of two uints is a uint.
Your fundamental error is that you believe that addition of a negative, and subtraction of a positive are the same thing. In unsigned arithmetic they are not because in unsigned arithmetic there's no such thing as "addition of a negative". There are no negatives!
if it implicitly gets converted to uint, then how do we explicitly tell the compiler it's a signed integer (1i isn't a valid syntax!)?
I don't understand the question. You tell the compiler the types of things with casts, but I don't think that's what you're asking.
Last question, this can't be a desired behaviour intended by the language design team (Eric Lippert to chime in?), can it?
I no longer speak on behalf of the language design team, but I can tell you what I would say had you asked this question when I was:
The language design team strongly desires you to not use uints, and particularly, to never mix int and uint in the same expression, because doing so is confusing and weird. Only use uints for interoperating with unmanaged code that uses uints.
You'll notice that uints are not in the common language subset, and that many quantities that are logically never negative, like the length of a string or an array, are nevertheless always ints in .NET. There's a reason for that. Use ints or longs.