I discovered what I believe is a bug - perhaps someone else can try to reproduce it?
Assume that logged in users see a list of courses on the main page (this is how my front page config is set).
Step 1: A student is not enrolled in a course.
Step 2: They then enrolled in the course by the administrator (using assign roles) or by an enrollment plugin (i.e., paying via paypal).
Step 3: The student then loads the root index.php (assuming /my/ is not forced), then My Courses does NOT show their enrollment even though they're already enrolled. But if they refresh the page, they are shown as enrolled.
(Note: This does NOT apply if users either self-enrol or if they view the course page using view.php between steps 2 and 3), for reasons outlined below.
In other words, the first time a student loads the main index subsequent to being enrolled in a course and before viewing the course, they have to load the page a second time (refresh) in order for the enrollment to be reflected under "My Courses."
The reason is because when print_my_moodle is first called, capabilities have not been refreshed. In the print_my_moodle function, $courses = get_my_courses(...) does NOT reflect the new enrollment. However, later on in the print_my_moodle function, print_courses is called, which in turn calls print_course, which in turn calls has_capabilities, which in turn calls load_all_capabilities(). Now, capabilities have been refreshed. Thus, when the student refreshes the browser, the enrollment is reflected. If the user visits view.php between steps 2 and 3, has_capabilities is called, and so capabilities are refreshed.
The fastest fix to this issue is to put "load_all_capabilities();" in the function print_my_moodle in course/lib.php immediately before the $courses = get_my_courses line. This way, all enrollments are up to date prior to the end of the script, when they are updated via the cascade described above.