Давайте разберемся.
.h файлы нужны для того чтобы описать типы данных и функции которые могут использоваться из разных .c файлов. Если у вас есть самодостаточный .c файл - хедер файл вообще ему не нужен.
Когда же вы в си файле описываете функцию int make_me_coffie(int coffeine_level) то для того чтобы ее можно было вызывать из других си файлов - вам нужно этим файлам сообщить о существовании такой функции. Для этого вы можете в каждом из этих си файлов добавить описание этой функции.
Так например в kitchen.c вы можете написать
int make_me_coffie(int );
и дальше спокойно пользоваться этой функцией. Никаких инклюдов тут не вообще нужно. Всем понятно что тащить в каждый си файл кучу определений типов и функций банально неудобно, и может привести к ошибкам, поэтому придумали инклюды. Инклюд включает содержимое файла в то место где он стоит. То есть все те определения функций появятся в вашем файле перед его сборкой.
Теперь к вашим вопросам. Включать header.h в теле header.c не обязательно ( так как обязательного вообще ничего нет ) - то логично и разумно. Если уж у вас есть один модуль header то скорее всего функции и типы данных описаны именно в header.h а значит header.c должен его включать.
Включать в header.c если он уже включен в header.h совершенно не обязательно, так как наш header.c уже включает header.h который включает stdio.h - а значит все необходимые определения функций уже будут в нашем файле. Впрочем включить stdio.h можно, это ничему не повредит благодаря системе дефайнов, которые обычно добавляются в каждый хедер файл, чтобы предотвратить множественное его включение.