Why does comments_open() return false when publishing a scheduled post?

The problem was caused by referencing the global $post object. The global $post has not yet been initialized with the new post’s details, so checking to see whether or not its comments are open will always return false at the transition_post_status hook.

The $post variable passed to my do_stuff() function does contain all the correct information about my new post, so I work with it instead. I eventually ended up with something like the following, which functions correctly with both regular and scheduled posts:

function do_stuff( $new_status, $old_status, $post ) {
   if ( $post->comment_status == 'closed' ) {
     return;
   }

   /* do stuff */
}
add_action( 'transition_post_status', 'do_stuff', 10, 3 );