> If anyone knows of any resources which explain this problem from "first principles"
I don't have my library handy, but I seem to recall that Tanenbaum discusses TCP congestion control at length. I'm sure you'll find something good in Stevens too.
> I can't wrap my head around slow-start, probably because I don't think I understand the problem it's intended to solve.
I'll make the bold claim that nobody fully understands the dynamics of TCP.
I wasn't there (so I'm probably wrong), but I believe that slow-start was designed as a fairly naive mechanism because it was not supposed to matter much in practice. TCP connections were supposed to be either long-lived bulk transfers (FTP, say), or interactive flows (telnet, or the conversational phase of SMTP). In the first case, slow-start only happens at the beginning of the transfer, which is a negligible part of the connection, while in the second case the size of the congestion window doesn't matter.
The trouble is with HTTP, which causes a lot of short-lived connections. Such a short-lived connection spends most or all of its life in slow-start. Hence the need for sharing state between different connections (which Linux does AFAIR) or tweaking the initial window.
> since the sender already has an upper bound for the min-RTT, why is the initial congestion window set to a fixed number rather than to "the number of segments that can be transmitted in the RTT"
Recall that the congestion window is there to limit congestion: it should decrease as congestion increases. With typical queueing techniques, the RTT increases with congestion, so what you are suggesting has the opposite of the desired dynamics.
Yeah, it's tricky. No, I don't claim to understand the trade-offs involved.