I decided to compare with another fresh WordPress install. The fresh copy does not have this issue.
I discovered that the media library, when functioning properly, lists a hidden field with each item like this:
<input type="hidden" name="attachments[10][post_parent]" id="attachments[10][post_parent]" value="163">
This field is, for some reason, missing on the broken install.
I also discovered that WordPress renders this hidden field in /wp-admin/includes/media.php, around line 1404:
foreach ( $hidden_fields as $name => $value )
$item .= "\t<input type='hidden' name='$name' id='$name' value='" . esc_attr( $value ) . "' />\n";
if ( $post->post_parent < 1 && isset( $_REQUEST['post_id'] ) ) {
$parent = (int) $_REQUEST['post_id'];
$parent_name = "attachments[$attachment_id][post_parent]";
$item .= "\t<input type='hidden' name='$parent_name' id='$parent_name' value='$parent' />\n";
}
return $item;
Still not sure where to go with this, though. Thanks for any further ideas.