Skip to main content

max / alloy

Turn weak deps off in the client package block The last of the four dnf install sites in this file to pass the flag, and the one behind the largest layer in the image. The printing block below had been split into its own RUN specifically to get the flag around a block that did not have it, which was a workaround for the gap rather than a reason for it. Resolved the block both ways against the same repos before touching it: weak deps on 504 packages weak deps off 418 packages off, load-bearing named back 448 packages So 56 packages and 99.3 MiB go, and nothing new arrives. Named back, each with why: sway-systemd, which starts the entire systemd user session and had been warned about in the sway config template since July; xdg-utils, desktop-file-utils and mailcap, because yazi binds xdg-open to Enter; mesa-vulkan-drivers, which IMAGE.md already argues about as a stack decision and which has no rpm dependents at all; mesa-va-drivers, which is what the shipped mpv.conf's hwdec=auto-safe actually selects; yt-dlp; upower; PipeWire's ALSA and JACK shims; the camera path; the CJK monospace face. The two the measurement caught and reading would not: without the JACK shim the resolver satisfies the interface with the real JACK daemon instead and the transaction grows by six packages, and the default-fonts-* metapackages survive on hard requires, so what drops there is seventeen supplementary Thai display faces rather than script coverage.
Author: Max Johnson <me@maxj.phd> · 2026-08-18 21:29 UTC
Signed with PGP, not checked
Commit: bb27b4d21c041810bb4654ce01af2458d97a4ac1
Parent: f3f2a01
2 files changed, +157 insertions, -6 deletions
M Containerfile +139 -6
@@ -1136,9 +1136,55 @@
1136 1136 # profile_split.rs enforces the rule across the whole file; the
1137 1137 # PROFILE-validity assertion above is what makes the condition itself
1138 1138 # trustworthy.
1139 + #
1140 + # WEAK DEPS ARE OFF HERE, since 2026-08-18, which closes the last gap in
1141 + # the installation discipline (wiki `alloy-installation-discipline`): the
1142 + # other three install sites in this file already passed the flag and this
1143 + # one, behind the largest layer in the image, did not. The printing block
1144 + # below says outright that it was split into its own RUN to get the flag
1145 + # around a block that does not have it, which is a workaround for the gap
1146 + # rather than a reason for it.
1147 + #
1148 + # TAKING THE FLAG IS NOT THE WHOLE MOVE, AND THIS IMAGE HAS THE CAUTIONARY
1149 + # TALE TWICE OVER. A recommend is sometimes load-bearing: `helix-parsers`
1150 + # is 185 MiB of grammars that arrived as one, and sway-systemd, which
1151 + # starts the entire systemd user session, arrives as a recommend of
1152 + # sway-config-upstream — as the sway config template has warned in writing
1153 + # since July. So the rule is take the flag and then name back what is
1154 + # wanted, and the group at the end of this list is that naming.
1155 + #
1156 + # MEASURED 2026-08-18 by resolving this exact package list both ways
1157 + # against the same repos (fedora, updates, terra, the three COPRs):
1158 + #
1159 + # weak deps on 504 packages
1160 + # weak deps off 418 packages
1161 + # off, load-bearing named back 448 packages
1162 + #
1163 + # So the change drops 56 packages and 99.3 MiB installed and pulls in
1164 + # nothing new, which is the half worth checking: a naive flag pulled six
1165 + # packages that were not there before, and the JACK note below is why. The
1166 + # two largest are `intel-mediasdk` (22.4 MiB) and
1167 + # `intel-vpl-gpu-rt` (11.7 MiB), the QuickSync path, which the shipped
1168 + # mpv.conf's `hwdec=auto-safe` does not select; `mesa-va-drivers` is what
1169 + # it does use and is named back below. The rest is the GNOME metadata
1170 + # estate (localsearch, tinysparql, poppler, exiv2, the osinfo set), iOS
1171 + # device support, event sounds, seventeen supplementary Thai display faces
1172 + # (6.9 MiB, and not coverage — see below), and bash and fish completions
1173 + # for shells nobody here runs.
1174 + #
1175 + # THE ONE THAT LOOKED LIKE A CASUALTY AND IS NOT: the two
1176 + # `default-fonts-*` metapackages. A metapackage whose payload is recommends
1177 + # becomes a no-op under this flag, which would have taken script coverage
1178 + # for most of the web with it and said nothing at all. Measured rather than
1179 + # assumed: `default-fonts-other-sans` requires 62 per-language metapackages
1180 + # and each of those requires its Noto face, so every script resolves with
1181 + # the flag on. What drops is about twenty supplementary Thai display faces
1182 + # recommended a level further down, which are alternative faces for a
1183 + # covered script rather than coverage. The CJK monospace face is the one
1184 + # real loss and is named back explicitly.
1139 1185 # ---------------------------------------------------------------------
1140 1186 RUN if [ "$PROFILE" = client ]; then \
1141 - dnf install -y \
1187 + dnf install -y --setopt=install_weak_deps=False \
1142 1188 # Compositor and Wayland session (Fedora main)
1143 1189 sway \
1144 1190 # Portals: -wlr is the wlroots backend sway needs for screencast.
@@ -1229,6 +1275,19 @@
1229 1275 # than absorbed: -cjk-sans is 62 MiB over 4 packages (the CJK faces are
1230 1276 # simply large), -other-sans is 13 MiB over 95.
1231 1277 #
1278 + # THESE SURVIVE THE WEAK-DEPS FLAG, and it was worth checking rather
1279 + # than assuming, because a metapackage whose payload is recommends
1280 + # would have become a no-op that installs a manifest and nothing to
1281 + # render with. Measured 2026-08-18: -other-sans *requires* 62
1282 + # per-language metapackages, each of which *requires* its Noto face,
1283 + # so every script this line exists for is a hard dependency and all
1284 + # 62 resolve with the flag on. What the flag does drop is about
1285 + # twenty supplementary Thai display faces recommended one level
1286 + # further down: Sarabun, Charmonman, Chakra Petch and their
1287 + # neighbours. Those are alternative faces for a script that is
1288 + # already covered rather than coverage, so they go. The one real
1289 + # loss is the CJK monospace face, named back explicitly below.
1290 + #
1232 1291 # No fontconfig change goes with this. The aliases in
1233 1292 # etc/skel/.config/fontconfig/fonts.conf use <prefer>, which leaves
1234 1293 # fontconfig free to fall through to a font that has the glyph, so
@@ -1340,6 +1399,71 @@
1340 1399 # was installed without it, so both watchers failed at every login
1341 1400 # and the clipboard history could never be populated or pasted from.
1342 1401 wl-clipboard \
1402 + # --------------------------------------------------------------
1403 + # Named back in, because weak deps are off above and each of these
1404 + # was arriving as somebody's recommend. Measured 2026-08-18 by
1405 + # diffing the resolved transaction both ways; anything not here is
1406 + # in the 40 packages the flag drops, and that list is in the
1407 + # comment above this RUN.
1408 + # --------------------------------------------------------------
1409 + #
1410 + # sway-systemd is the one that would have taken the whole session.
1411 + # It arrives as a recommend of sway-config-upstream and its
1412 + # /etc/sway/config.d/10-systemd-session.conf is what execs
1413 + # session.sh, which starts sway-session.target, which
1414 + # graphical-session.target binds to. Every user unit in the image
1415 + # depends on that chain: pipewire, wireplumber, xdg-user-dirs, the
1416 + # clipboard watchers. templates/etc/skel/.config/sway/config.in has
1417 + # said so in writing since 2026-07-21, when it was proven by
1418 + # reading the uid 1000 journal off a booted install.
1419 + sway-systemd \
1420 + # xdg-open, and the database it resolves against.
1421 + # etc/skel/.config/yazi/yazi.toml binds `xdg-open` to Enter and to
1422 + # Reveal, so without these the file manager's primary action is a
1423 + # command not found. mailcap is the /etc/mime.types half of the
1424 + # same answer.
1425 + xdg-utils desktop-file-utils mailcap \
1426 + # Vulkan, which docs/IMAGE.md#size argues about at length and
1427 + # treats as a stack decision rather than an accident: six of its
1428 + # twelve ICDs drive hardware this image boots on. It has no rpm
1429 + # dependents at all, because the loader dlopens an ICD off a JSON
1430 + # manifest, so it was arriving as a recommend and nothing would
1431 + # have reported its absence except a black window.
1432 + mesa-vulkan-drivers \
1433 + # VA-API, which is what `hwdec=auto-safe` in the shipped mpv.conf
1434 + # actually selects. Hardware decode is a documented behaviour of
1435 + # the video player (docs/STACK.md#video), so it is not a recommend
1436 + # here.
1437 + mesa-va-drivers \
1438 + # mpv plays streams through yt-dlp, capped at 1080p in the shipped
1439 + # config, and both STACK.md and manual chapter 9 promise it. Its
1440 + # own recommends (the metadata and cipher helpers) are not named
1441 + # back: they degrade features rather than remove playback.
1442 + yt-dlp \
1443 + # upower. crates/alloy/src/status.rs reads battery from sysfs
1444 + # rather than through it and says so, but docs/STACK.md states it
1445 + # is in the image, the power stack that HARDWARE-FW12 documents
1446 + # wants it, and it is 311 KiB.
1447 + upower \
1448 + # PipeWire's ALSA and JACK shims. These are the ones that punish a
1449 + # naive flag rather than merely thinning the image: without the
1450 + # JACK shim the resolver satisfies the same interface with the real
1451 + # JACK daemon instead, and the measurement caught it doing exactly
1452 + # that (jack-audio-connection-kit, libffado, glibmm2.4 and three
1453 + # more appeared in the transaction the flag was supposed to
1454 + # shrink). ALSA-only applications route through the shim too.
1455 + pipewire-alsa pipewire-jack-audio-connection-kit \
1456 + # The camera path. Alloy ships no video-call application and the
1457 + # browser is one, so a webcam that does not work in a call is a
1458 + # defect on a laptop-first distro. -ipa is where the per-pipeline
1459 + # image processing lives and libcamera is close to useless without
1460 + # it.
1461 + libcamera libcamera-ipa pipewire-plugin-libcamera \
1462 + # CJK coverage for the cell grid. The fonts RUN below carries the
1463 + # proportional metapackages; this is the monospace face, which a
1464 + # terminal showing CJK text needs and a sans metapackage does not
1465 + # supply.
1466 + google-noto-sans-mono-cjk-vf-fonts \
1343 1467 && dnf clean all \
1344 1468 # bibata-cursor-theme installs FOURTEEN directories and Alloy names one.
1345 1469 # At 179 MB it was the third-largest package in the image, behind the
@@ -1506,12 +1630,15 @@
1506 1630 # already resolving .local (see the avahi block). So a driverless
1507 1631 # printer appears by itself and most users never configure anything.
1508 1632 #
1509 - # Weak dependencies off, and that is why this is a separate `dnf
1510 - # install` rather than more lines in the block above: on the default
1633 + # Weak dependencies off. This was a separate `dnf install` because the
1634 + # client block above did not pass the flag, so folding these lines in
1635 + # would have taken the larger set silently: on the default
1511 1636 # `install_weak_deps=True` this transaction is 52 packages instead of
1512 - # 33, and the extra 19 are recommends nothing here asked for. The block
1513 - # above does not pass the flag, so folding these in would have taken
1514 - # the larger set silently.
1637 + # 33, and the extra 19 are recommends nothing here asked for. That gap
1638 + # closed on 2026-08-18 and the client block passes the flag too, so the
1639 + # split is no longer load-bearing for this reason. It stays because the
1640 + # assertions below are printing's and belong beside printing's install,
1641 + # and because a layer per subsystem is what the rest of this file does.
1515 1642 #
1516 1643 # No scanning. sane-backends is per-device backends and USB permission
1517 1644 # work, its failures are opaque, and a scanner is far rarer on a laptop
@@ -1666,6 +1793,12 @@
1666 1793 # Client, Foot Server), which is how an unused package stops being
1667 1794 # merely 0.8 MB of dead weight. Recommends are not requirements, so
1668 1795 # this does not disturb sway-config-upstream itself.
1796 + #
1797 + # Since 2026-08-18 the client block turns weak deps off, so foot no
1798 + # longer arrives and this line removes nothing. Kept anyway: `|| true`
1799 + # already covers the not-installed path, it is the standing answer to
1800 + # the day somebody hard-requires it, and a build that reintroduced it
1801 + # would otherwise reintroduce the three launcher entries with it.
1669 1802 foot \
1670 1803 || true
1671 1804
@@ -238,6 +238,24 @@
238 238 cursor prune above is the counter-example, with the database declaring 188 MB against
239 239 27 MB on disk by design.
240 240
241 + - **Recommends in the client block, 99.3 MB.** The layer behind the 1.44 GB desktop
242 + entry was the last `dnf install` in the file not passing
243 + `--setopt=install_weak_deps=False`. It passes it now, with the load-bearing
244 + recommends named back explicitly: `sway-systemd` (which starts the whole systemd
245 + user session), `xdg-utils` and its database, `mesa-vulkan-drivers`,
246 + `mesa-va-drivers`, `yt-dlp`, `upower`, PipeWire's ALSA and JACK shims, the camera
247 + path, and the CJK monospace face. Measured by resolving the block both ways against
248 + the same repos: 504 packages down to 448, and nothing new pulled in.
249 +
250 + Two things the measurement caught that reading the list would not. Taking the flag
251 + naively **replaces PipeWire's JACK shim with the real JACK daemon**, because
252 + something in the set requires the interface either way, so six packages appear in
253 + the transaction the flag was meant to shrink. And the two `default-fonts-*`
254 + metapackages look like casualties and are not: they *require* 62 per-language
255 + metapackages which *require* their Noto faces, so every script survives. What drops
256 + there is seventeen supplementary Thai display faces, 6.9 MB, which are alternative
257 + faces for a covered script rather than coverage.
258 +
241 259 None of this is a race to a number. Two of the four largest layers are the desktop and the
242 260 browser and both are the product; the point is that every large thing in this image is now
243 261 either explained above or gone.