Здравствуйте
Да, действительно у Liquibase есть такая особенность при работе с транзитивными include в ченджлогах.
Jmix со своей стороны помогает решить эту проблему для приложения (application), имеющего подобные сложные зависимости. Как вы могли заметить в changelog.xml аддонов тег include содержит фильтр по контексту: contextFilter="@jmix-addon". То есть данные include будут выполнены только если передан контекст jmix-addon. Например выполняя скрипты для модулей b и c из вашего примера котекст будет передан, include для аддона a будет выполнен.
При этом changelog.xml приложения содержит в себе include для всех аддонов, включая транзитивные зависимости, без фильтра. При выполнении скриптов в приложении контекст не передаётся, include из ченджлогов аддонов выполняться не будут, выполнятся только непосредственно включенные в ченджлог приложения, то есть дублирование будет исключено.
В вашем случае роль приложения выполняет аддон, то есть данная схема работать не будет, так как контекст для аддона передаётся, в результирующий ченджлог скрипты из аддона a попадут как из аддона b, так и из аддона c. Исключить дублирование в данном случае можно только убрав зависимость на аддон a из аддона b или c (или обоих и добавив зависимость на аддон a в аддон d).
Также для опытных пользователей Liquibase в теории возможно использовать подход используемый для приложения, для этого необходимо добавить зависимость на аддон a в аддон d изменив фильтр по контексту с @jmix-addon на какое-то другое значение для всех include в аддоне d и выполнить update с этим новым контекстом используя например Liquibase Gradle плагин.
Мы со своей стороны подумаем, что можно сделать для более удобной работы в подобных ситуациях.