I've been feeling my way around on trying to build a script around that concept, but I have only been giving it a micro-fraction of my attention, with my other more "pressing" interests keeping me sidetracked. Last time I touched it was August 2024. 
If we look at Caja, for example, I have generated a directory full of reports, one for each package installed. The reports contain the following values for the "keywords" captured:
Package: caja
Depends: caja-common (= 1.24.0-1), desktop-file-utils, gvfs, libcaja-extension1 (= 1.24.0-1), libglib2.0-bin, libglib2.0
-data, mate-desktop, shared-mime-info, libatk1.0-0 (>= 1.12.4), libc6 (>= 2.14), libcairo-gobject2 (>= 1.10.0), libcairo
2 (>= 1.10.0), libexempi8 (>= 2.5.0), libexif12 (>= 0.6.21-1~), libgail-3-0 (>= 3.0.0), libgdk-pixbuf2.0-0 (>= 2.22.0),
libglib2.0-0 (>= 2.57.2), libgtk-3-0 (>= 3.21.5), libice6 (>= 1:1.0.0), libmate-desktop-2-17 (>= 1.24), libnotify4 (>= 0
.7.0), libpango-1.0-0 (>= 1.44.6), libpangocairo-1.0-0 (>= 1.14.0), libselinux1 (>= 1.32), libsm6, libx11-6, libxml2 (>=
2.7.4)
Description: file manager for the MATE desktop
Status: install ok installed
Architecture: amd64
Breaks: caja-common (<< 1.20.0-2~), libcaja-extension (<< 1.10.0), libcaja-extension1 (<< 1.10.0), mate-session-manager
(<< 1.8.1-7)
Essential: no
Homepage: https://mate-desktop.org/
Installed-Size: 3416
Maintainer: Ubuntu Developers <[email protected]>
Priority: optional
Recommends: gvfs-backends
Replaces: caja-common (<< 1.20.0-2~)
Section: universe/utils
Suggests: engrampa, gstreamer1.0-tools, meld
I believe the "Depends:" keyword values are key to building the relationship-tree that I am looking for.
My intent was to create a report, by "stand-alone" application regarding the full-set package dependencies required for independent build/install, including the list of packages that each of those "Depend:" items themselves depend upon, recursively. That way, if you collected the package bundles, according to that list, you would not find yourself with any component missing during the compile stage. At least, that is the concept I had visualized. 
The script I have (as yet not complete, work-in-progress) is this (getPkgInfo.sh):
#!/bin/bash
dbg=0
packageDetails="/Local/PkgInfo"
packageNameList="/Local/PkgList.txt"
packageScanStat="/Local/PkgList.details"
getPackageList()
{
dpkg-query --list |
tail --lines=+6 |
awk '{ print $2 }'
}
details_long()
{
dpkg-query --show --showformat='Package: ${Package}
Depends: ${Depends}
Pre-Depends: ${Pre-Depends}
Description: ${Description}
Status: ${Status}
Architecture: ${Architecture}
Bugs: ${Bugs}
Conffiles: ${Conffiles}
Config-Version: ${Config-Version}
Conflicts: ${Conflicts}
Breaks: ${Breaks}
Enhances: ${Enhances}
Essential: ${Essential}
Filename: ${Filename}
Homepage: ${Homepage}
Installed-Size: ${Installed-Size}
MD5sum: ${MD5sum}
MSDOS-Filename: ${MSDOS-Filename}
Maintainer: ${Maintainer}
Origin: ${Origin}
Priority: ${Priority}
Provides: ${Provides}
Recommends: ${Recommends}
Replaces: ${Replaces}
Revision: ${Revision}
Section: ${Section}
Size: ${Size}
Source: ${Source}
Suggests: ${Suggests}
Tag: ${Tag}
Triggers-Awaited: ${Triggers-Awaited}
Triggers-Pending: ${Triggers-Pending}
Version: ${Version}' "${package}"
}
details_short()
{
dpkg-query --show --showformat='Package: ${Package}
Description: ${Description}
Depends: ${Depends}
Pre-Depends: ${Pre-Depends}
Priority: ${Priority}
Version: ${Version}
Status: ${Status}
Architecture: ${Architecture}' "${package}" |
awk '{
pos=index( $0, ":") ;
beg=substr( $0, 1, pos-1 ) ;
rem=substr( $0, pos+2 ) ;
if( rem == "" ){
printf("%s: %s\n", beg, "NO_ATTRIB_VAL" ) ;
}else{
printf("%s\n", $0 ) ;
} ;
}' | grep -v 'NO_ATTRIB_VAL'
#Bugs: ${Bugs}
#Conffiles: ${Conffiles}
#Config-Version: ${Config-Version}
#Conflicts: ${Conflicts}
#Breaks: ${Breaks}
#Enhances: ${Enhances}
#Essential: ${Essential}
#Filename: ${Filename}
#Homepage: ${Homepage}
#Installed-Size: ${Installed-Size}
#MD5sum: ${MD5sum}
#MSDOS-Filename: ${MSDOS-Filename}
#Maintainer: ${Maintainer}
#Origin: ${Origin}
#Provides: ${Provides}
#Recommends: ${Recommends}
#Replaces: ${Replaces}
#Revision: ${Revision}
#Section: ${Section}
#Size: ${Size}
#Source: ${Source}
#Suggests: ${Suggests}
#Tag: ${Tag}
#Triggers-Awaited: ${Triggers-Awaited}
#Triggers-Pending: ${Triggers-Pending}
}
if [ -s "${packageNameList}" ]
then
rm -i "${packageNameList}"
fi
if [ ! -s "${packageNameList}" ]
then
getPackageList >"${packageNameList}"
gvim "${packageNameList}"
fi
#mode=long
mode=short
count=$(wc -l "${packageNameList}" | awk '{ print $1 }' )
if [ ! -f "${packageScanStat}" ]
then
if [ ${dbg} -eq 1 ]
then
head -5 "${packageNameList}"
else
tac "${packageNameList}"
fi |
while read package
do
printf "\t [${count}] ${package} ...\n"
details_${mode} >${packageDetails}/${package}.${mode}.txt 2>${packageDetails}/${package}.${mode}.err
test -s ${packageDetails}/${package}.${mode}.err || rm -f ${packageDetails}/${package}.${mode}.err
count=$(expr ${count} - 1 )
done
touch "${packageScanStat}"
ls -l ${packageDetails} | more
fi
grep 'gtk-2' ${packageDetails}/*.${mode}* >PkgList.gtk2.txt
grep 'gtk-3' ${packageDetails}/*.${mode}* >PkgList.gtk3.txt
grep 'gtk-4' ${packageDetails}/*.${mode}* >PkgList.gtk4.txt
To add further clarification regarding my final intent for these efforts, I had hoped to define a list of Applications, i.e. Firefox, Geany, IDLE, Builder, etc., then have a "Distro-Builder" which would build the ISO image using ONLY the packages identified as dependencies for those packages.
The expectation is that such a Distro-Builder would then create the minimal set of ONLY those packages (from amongst all the packages usually included as part of a Distro) that fulfill the functional requirements of those applications, almost like what the intent of using Ada was for ensuring fully encapsulated and embedded but reliably functional hardware.
So, for example, if you never specified a Game, none of the gaming-related libraries would be installed, either for the end-user applications or for the gaming-specific OS libraries. Also, if you only specified Firefox, and nothing else, you would end-up with a single-application Distro, where the Firefox dependencies, driven by it's package dependencies would eventually dictate the need to install all (the minimal-set) of the libraries required for the OS along with only Firefox !!!
End goal: zero bloat!
I also can't imagine that nobody has done something like this before. It seem too inherent to the overall goal of Disto-building to not have been done anywhere out there, regardless of Distro.
Cross-referencing to other discussion that seems to have a parallel end-purpose: