Thank you for the detailed explanations, I was pulling my hair out...
I made a visual metronome as a comp, with 4 "beats", one at 0:00, 1:00, 2:00, and 3:00 (30 fps, though fps should not matter).
The ONLY way I could get everything working (no drifting forward or backward and no blank frame at the end) was to have 1 extra frame at the end of the comp. So the duration is 4:01, but as you mentioned, the last frame is at 4:00. This is similar to your example of a 10-frame animation...you need 11 frames for a proper loop if the start and end frames are different (as mine are).
When adding it to the main comp, I want the repeats to happen at each second, frame 0. I put in the comp, set Time Remapping, and moved TWO frames back from the end to add the keyframe. I moved the last keyframe one frame back and set its time to 0 (or whatever time the first keyframe is at, in my case it starts at 0...you can copy-paste the first keyframe for this). Then I added loopOut() and extended it. Works perfectly.
I do wish I had those hours back. Very unintuitive at first and incredibly frustrating to see "off-by-one" errors all over the place. Of course, this is a special case in which the frames must match up exactly over long periods of time, whereas some other looped animations aren't so frame-critical.
I will say that having an "easy loop" feature would be very helpful. Right-click a segment in the timeline and you can turn on looping, just like in many DAWs. Semitransparent clones of the segment would fill out to the end of the comp, or there could just be an indicator that shows it's looping. It would loop the whole segment, including frame 1 of it, which to me is intuitive. Anyway, not sure if that is possible or how difficult it would be, but given the number of issues people are having with looping, it would be extremely handy.
Thanks again for your help with this!