Found out why WordPress had been acting so screwy. Apparently, the 2.9 upgrade messed with an old portion of the code… that handled timekeeping and scheduling. Combine this with the fact that WordPress assigns each scheduled post a unique cronjob…
So, in essence, every scheduled post has a timer that looks at the UNIX time, counts down to zero, and then publishes the post. Unless you just piddled with the timekeeping code, in which case, each timer never reaches zero. This means that the timer goes away (having passed the time it was set to execute), leaving a post with a publish date set to FUTURE.
The plugin I added takes care of this two ways. It fixes the code, so that the timer actually executes, and it has a SQL query that looks for posts with a status of “scheduled/missed schedule” and a post time that has passed, and then posts them. Belt and suspenders.