How can extended public keys generate child public keys without generating the child private key in HD wallets?
Upon a bit more searching, I found the derivation for getting the child public key without the private key here:

child_private_key == (parent_private_key + lefthand_hash_output) % G
child_public_key == point( (parent_private_key + lefthand_hash_output) % G )
child_public_key == point(child_private_key) == parent_public_key + point(lefthand_hash_output)


In terms of K, k and G where prime denotes the child and h denotes the left-hand hash output:

k' = (k + h) % G
K' = point ( (k + h) % G)
K' = point (k')
K' = K + point(h)


Here are the exact implementation details from the BIP 32 documentation