Так что после того, как я едва не сломал свой компьютер, я нашёл обходной путь — вероятно, не идеальный 
Похоже, что при нажатии на кнопку «Ответить» внутри Full App Embed композер (поле ввода) на самом деле корректно открывается в DOM (#reply-control.open), но по какой-то причине остаётся с display: none.
Я проверил это в консоли браузера: композер присутствовал, но его вычисленное значение display было “none”. Ручное выполнение:
document.querySelector('#reply-control').style.setProperty('display', 'block', 'important');
немедленно сделало композер видимым, и всё заработало нормально.
В качестве обходного пути добавление следующего JS в тему Discourse решает проблему для меня:
import { apiInitializer } from "discourse/lib/api";
export default apiInitializer((api) => {
if (!document.body.classList.contains("embed-mode")) {
return;
}
const fixComposer = () => {
const composer = document.querySelector("#reply-control.open");
if (composer) {
composer.style.setProperty("display", "block", "important");
}
};
const observer = new MutationObserver(fixComposer);
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: true,
attributeFilter: ["class"],
});
fixComposer();
});
Похоже, это полностью исправляет проблему, и я ограничил область действия обходного пути режимом embed-mode, чтобы он не влиял на обычный интерфейс Discourse.
Очевидно, что это, вероятно, не идеальное долгосрочное решение, но, надеюсь, это поможет определить, что заставляет открытый композер оставаться с display: none в Full App Embed.