From 6dc89469acbcbe788ae970a341fa7b5fa15fcf76 Mon Sep 17 00:00:00 2001 From: Oleksandr Shyshatskyi Date: Sun, 30 Aug 2026 01:14:44 +0300 Subject: [PATCH] patch.sh asserts nothing about the payload it just installed Two gates go, both of the same shape: a pkg_die run against $PAYLOAD_DIR a few lines after bin/build-payload.py filled it, asking whether opkg had installed the packages it was handed. * section 1: a klippy tree at $MODDIR/klipper/klippy, and a c_helper.so inside it * section 5b-2: etc/s6-rc/compiled/current resolving Neither was ever this script's question. patch.sh no longer builds either subject -- anvil-klipper installs the klippy tree, and case-build-payload.sh compiles the database in the replica with the s6-rc-compile anvil-s6-rc ships -- so a gate here can only report that a package manager did what it said it did, on a staging directory, on the build host. Both are already asked on the two vehicles that actually reach a printer: * bin/verify.sh reads the PACKED artefact -- the klippy tree, c_helper.so, and compiled/current resolving, plus the one thing about the database a host can genuinely tell that patch.sh never asked: the execline named by the oneshot runner's #!. * qa/replica asks an INSTALLED filesystem. test_install.py's test_klippy_is_present is the klippy question by name, test_abi.py sweeps c_helper.so for the ABI, and test_s6rc.py boots the thing -- s6-rc-init reads the database, the boot set comes up, and a database moved aside is reported as a negative control. The two `say` lines went with them. Both existed to narrate a gate; the Klipper one printed a pin that pkgs/klipper/pkg.conf already stamps into PKG_VERSION, and the s6-rc one readlink'd the path the gate had just tested. KEPT, and it is the same call 4ce928f made for the toolchain wrapper: the anvil-core check in section 0. It judges the INPUT feed rather than the produced payload, which is a question no downstream gate can ask, and it guards a silent failure -- the MOD_INSTALL loop drops a root with no .ipk without a word, because that is how PKG_WHEN reaches this script, so a missing anvil-core would otherwise build a payload without it rather than stop. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01GAQKdBfZxbnPagQyidFk6Y --- bin/patch.sh | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/bin/patch.sh b/bin/patch.sh index 5cdf7c0..c8f36b2 100755 --- a/bin/patch.sh +++ b/bin/patch.sh @@ -70,14 +70,13 @@ say "payload: $(grep -c '^Package:' "$PAYLOAD_DIR/var/lib/opkg/status") packages # klipper_pri.sh, their SCHED_FIFO helper. klipperDaemon at that path is a # symlink to our shim, pointed there by anvil-link-prog.sh. # -# The assertion is all that is left, and it is cheap: an anvil-klipper that did -# not install is now a printer with no Klipper at all, with no component copy -# to mask it. -[ -d "$PAYLOAD_DIR/klipper/klippy" ] || pkg_die \ - "the payload has no $MODDIR/klipper/klippy -- anvil-klipper did not install" -[ -f "$PAYLOAD_DIR/klipper/klippy/chelper/c_helper.so" ] || pkg_die \ - "the payload has no $MODDIR/klipper/klippy/chelper/c_helper.so -- klippy cannot connect to an MCU without it" -say "Klipper: fork tree from pinned commit ${KLIPPER_VERSION:0:8} (payload only)" +# Nothing is asserted here either. The two gates that were -- a klippy tree at +# $MODDIR/klipper/klippy, and a c_helper.so inside it -- asked whether opkg had +# just installed the package it was handed, of a staging root three lines after +# it was filled. qa/replica/test_install.py::test_klippy_is_present asks it of +# an installed filesystem, and bin/verify.sh asks it of the packed artefact, so +# the same absence is already caught twice on the two vehicles that reach a +# printer. A gate here could only fail on a build that both of those fail on. # --- 2. Toolchanger # Gone with section 1: the ff_*.py ride the klippy tree anvil-klipper installs @@ -101,9 +100,12 @@ say "Klipper: fork tree from pinned commit ${KLIPPER_VERSION:0:8} (payload only) # be --prefix=$MODDIR or the #! baked into the oneshot runner pointed at the # build host's execline. Compiling with the compiler we SHIP cannot get that # wrong. (Byte-identical either way: 80-s6-migration.md, measured 2026-08-28.) -[ -d "$PAYLOAD_DIR/etc/s6-rc/compiled/current" ] || pkg_die \ - "the payload has no compiled s6-rc database -- case-build-payload.sh did not compile one" -say "s6-rc: database $(readlink "$PAYLOAD_DIR/etc/s6-rc/compiled/current") -- $(ls "$PAYLOAD_DIR/etc/s6-rc/source" | wc -l) definitions" +# +# So there is nothing left to assert. compiled/current resolving was gated here +# and is gated in bin/verify.sh, which also reads the one thing a host can tell +# about the database -- the execline the oneshot runner's #! names. On a +# machine, qa/replica/test_s6rc.py boots the thing: s6-rc-init reads the +# database, the boot set comes up, and a database moved aside is reported. # --- 6. SSH # Nothing to install: the stock rootfs ships dropbear and an enabled