SmartConfig

Review of M5: the package (steps 1-8)

Date: 2026-10-08, after M5 steps 1-8 were built (cd5dd63..82e4168: sc version and the version string, /usr/sbin/sc, make deb, the maintainer scripts and the takeover of a hand install, the package in CI, the lab’s --deb mode with D.1-D.4, the README). Two reviewers (AI agents), each in its own clone of 82e4168 (pushing disabled): A on the package (build-deb.sh, the maintainer scripts, version.sh, 42_smartconfig’s early exit, the tests, the README’s apt install), B on the lab’s --deb mode. No sudo, nothing installed, no QEMU. A ran the real dpkg 1.22.6 on a fake root (fakeroot dpkg --root --force-script-chrootless, stub tools first in PATH). Both read the --deb lab run on 82e4168, which passed in both modes. Claude reran the probes each reviewer wrote before fixing. Reports: ~/smartconfig-work/review-m5/findings-{a,b}.md.

Gate: no high-severity finding open. Two were high:

Both are fixed, with every medium and low finding, in 5e9f1e3, 8284709, 9ab3586, 37207e9, 99d91ba, f502c34, 8cd9c8d and 84f9959. Two are not code fixes: A6 is a documented limit (plan change C6), and A11 is a question for you (plan question 7).

What held up

Findings

Area Finding Severity Fixed by
preinst (A1) After a remove, dpkg passes preinst the old version. preinst took the package’s own 42_smartconfig (a conffile then) for a hand install and moved it aside, and dpkg kept it deleted. Install, remove, install left no rescue entry; with a changed 42_smartconfig, the package was left unconfigured. high The takeover runs only when dpkg passes no version (5e9f1e3). Lab D.5 (remove, then install again) and TestDebHandInstall cover it.
lab 0.5, D.x (B1) install.sh ran its own update-grub after dpkg -i, and 0.5 read that one. A package whose postinst ran no update-grub, or one that failed, passed the whole run. high Deb mode runs none. 0.5 holds postinst’s “Adding SmartConfig rescue entry” in dpkg’s output. D.1, D.4 and D.5 require it of their dpkg -i, with one entry in grub.cfg (99d91ba).
preinst, postrm (A2) A first install that failed after preinst (a file conflict, a full disk) left the hand install disabled and moved aside. There was no abort-install. medium preinst moves only 42_smartconfig; postinst’s first configure moves the rest, once the package’s files are in; postrm abort-install puts 42_smartconfig back (5e9f1e3).
version.sh (A3) <commit second>.<sha7>: two commits in the same second sorted by sha. 82e4168 came below its parent, and apt refuses that “downgrade”. medium 0.N.99+git<count since mN>.<time>.<sha7> (8284709).
build-deb.sh (A4) Installed-Size came from du, so a build staged on tmpfs gave other bytes. medium Counted as dpkg-gencontrol does. A test stages a build in /dev/shm (9ab3586).
lab verdict (B2) A D.x ([M5]) FAIL ended INCONCLUSIVE (“the lab, rerun it”), and a later lab error replaced it. medium Any class but [lab] is SmartConfig’s (37207e9).
lab D.2, D.3 (B3) “The store kept” was only test -d. medium The rows (counted by the package’s own sc) and the boots file’s sha256 (99d91ba).
preinst (A5) Only an unrecognised unit was named; an unrecognised sc, 42_smartconfig or drop-in was left without a word. low Each is named (5e9f1e3).
scripts (A6) With DPKG_ROOT set, daemon-reload, the restart and update-grub act on the running system. low Documented (plan C6): no tool takes a root, the tests need DPKG_ROOT, and such installs need a force flag.
accept-m4 (A7) Step 7’s 42_smartconfig adds nothing without /usr/sbin/sc. low Its sc= line points at the run’s sc (8cd9c8d).
version.sh (A8) With no mN tag, it gave 0.0.99+..., below every release. low An error that says to fetch the tags (8284709).
preinst (A9) chmod a-x followed a symlink to its target. low Not on links (5e9f1e3, f502c34).
README (A10) A purge deletes 42_smartconfig.dpkg-old, as dpkg does next to a conffile. low The README says so (84f9959).
name (A11) /usr/sbin/sc hides Ubuntu’s sc spreadsheet (/usr/bin/sc, universe). low Plan question 7, for you.
tests (A12, B5) Survivors in the package tests: the no-systemd and no-GRUB paths, abort-*, the purge message’s guard, recognition of anything but units, md5sums, Installed-Size. Survivors in the lab tests: D.2’s flag, scd and rescue checks, D.3’s store, D.1’s is-active, D.4’s MainPID 0 and x bit, 0.4’s deb keys, 0.6’s deb path, --no-boot5’s skip. Test cases each held several faults at once. low A test for each; one fault per case (47 for D.1-D.5).
lab D.2 (B4) The flag set before dpkg -r was never read back. low Read back; not set is a LabError.
lab (B6) Nothing tied the package to the bin/sc the lab vouches for. build-deb.sh took SC_BIN and the rest from the lab’s environment. low Each packaged file is held to this tree’s; none of the stand-ins is passed (99d91ba).
lab D.1 (B7) Answers were read by position: a short answer crashed it, giving INCONCLUSIVE. low key=value lines.
install.sh (B8) is-enabled of three units exits 0 if any one is enabled; the package did not have to be in MANIFEST; 0.4 used files mode’s text. low One unit at a time; the package required in MANIFEST; deb mode’s own text.
lab vs plan (B9) D.2 did not check the units. A half hand install (M2/M3) was not covered. The lab uses dpkg -i, the README apt install. low D.2 checks that no unit is left enabled. TestDebHandInstall has a half install. Plan C5; this VM’s sign-off uses apt install.
docs (B10, A) The lab README’s D row; header comments that still said “install it by hand”; plan text (grub-script-check, “match a released build”, CI’s list). md5sums listed the conffile; a native package’s changelog is changelog.gz; make clean left dist/; the README’s smartconfig_*.deb takes the highest version; apt’s _apt note was not mentioned. cleanup 84f9959, 9ab3586, 99d91ba; plan C1-C5.

Maintainer: and the copyright holder still come from HEAD’s author (A): that is the owner’s identity, and DEB_MAINTAINER overrides it.

Tests

New or extended Go tests:

New or extended lab tests:

Mutations:

The real dpkg on a fake root (A’s harness) now shows:

Full checks, make lab-test (364) and the root and race passes all pass. The fixes to the lab itself are proven by the sign-off’s make lab-e2e LAB_E2E_ARGS=--deb.