You're not... I can reproduce the issue (although there may be a few frames discrepancy).
Timecode is not real time... it only mimics time. Timecode is a way of labeling each frame with a unique identifier. It really doesn't have anything to do with TRT (especially for 29.97 drop frame).
Fractional frame rates (23.976, 29.97 NDF and 59.94) all require extra frames to sync with real time. (There are *no* fractional frames). The necessity and method of slowing down frame rates was something that was necessary in analog (NTSC) broadcast days. If you are not expressly required to do so, don't use them!
All files an hour long in *any* fractional frame rate are roughly 3.6 seconds shorter than one hour. This requires adding frames to each format in order to sync with one hour. In 23.976 fps, that is about 86 frames per hour or roughly 40 frames in 28 minutes.
I did your experiment. The XML file reports the duration as 201801600/120000s (seconds). Doing the math, that's 1681.68 seconds or 28.028 minutes or 28 minutes 1.68 seconds long. This is the exact time Quicktime 7 Pro reports:

[BTW - QT7Pro has an option to display playback time in "Standard", Timecode: Non-DropFrame and Frame Number. Switching the option to either Timecode or Frame Number changes the Duration displayed to an even 28 minutes in the inspector. Switching back to Standard restores the duration to what you see above.]
Quicktime X reports 28.02 [rounding, I believe — there are no options to change the playback time display]:

and FCPX shows this *occasionally [I'll explain this mystery in a few]:

If you play around with the playhead, it settles back down to show the play time as:

Which, btw, is still wrong because the last frame should be timecode: 27:59:23.
The mystery:
if you switch back and forth between projects, say the 28 minute long 23.976fps project with the playhead *on the last frame* and a 60fps project, then right back, you will find FCPX with its pants down displaying the actual length (in 60fps! no less). It corrects itself as soon as you move the playhead around and the last frame will display 28:00:00.
The inference is that FCPX will play your project as a broadcaster would. 28 minutes in timecode means 28 minutes of play time even if the actual length of the video is frames longer than the calculated length. The necessary extra frames are allocated for (they're not invented - you put them there) so that it ends on time. At least that's my understanding of how broadcasting the "fractional frame rates" works.
Speed compensation is not required for Drop Frame rates, because (in 29.97) every minute (except on multiples of 10), two frame numbers are skipped: 0 and 1 to make up the time difference (or artificially "speed up" the content). There is no Drop Frame standard for 23.976 to account for the time difference at 24fps, so extra frames need to be added.
I created an effect in Motion. It was created at 60fps for exactly 1 hour and it had a Project Loop End marker on the last frame. In terms of Final Cut, this effect should run *exactly* 1 hour, then repeat. Them's da rules. It works in ALL full frame formats. In 23.976 projects, the last correct event occurs exactly 86 frames short of the full hour of "play clock time" which means that at 23.976, the number of frames that constitute 1 hour (at least to a Motion template/effect) ends that much earlier than the time reported on the clock. (And that's not supposed to happen...)