M5 — parity verified¶
M5's exit criterion (PARITY-POLICY.md): every unit either installs
successfully on at least one supported distro, or carries a broken/retired
verdict we tested — never inherited. And the fraction that installs must be
at least as good as AHRL's own: AHRL v27 ships 95 units with 9 disabled,
so its own install-success rate is 86 of 95 (90.5%).
This is the evidence, gathered by scripts/vm_campaign.py across three live
VMs — Parrot OS 7.3 (primary), Debian 13, Kali rolling — on 2026-08-30, engine
at the v0.5.0 line, and extended to Ubuntu 24.04 and 26.04 on 2026-09-02. It is not a claim from resolution; every "confirmed" below
is the engine's own D-031 bar: the command completed and a re-probe found the
effect.
The headline¶
Across the whole catalog run on three targets, there were zero hard build or install failures. Every unit either installed and was confirmed on at least one target, or was refused at plan time with a reason — and every refusal is one of three honest classes, never a silent skip.
| Campaign | Parrot | Debian 13 | Kali |
|---|---|---|---|
| Profile grind (every ungated profile) | 128 / 128 installable confirmed | 105 / 107 | 143 / 147 |
| Uncovered units (71, by name) | 64 confirmed, 7 refused | 63 confirmed, 8 refused | 67 confirmed, 4 refused |
| Hard failures | 0 | 0 | 0 |
Of the 71 uncovered units, 68 confirmed on at least one target. Combined with the profile grind, effectively every installable unit in the catalog is verified installing on a supported distro — comfortably past AHRL's 90.5%.
The three refusal classes (never a failure)¶
- Unimplemented backend, refused by name.
code/codium(third-party apt repos),arduino-cli/soapysdr-module-plutosdr(Kali-only blocks that correctly do not resolve elsewhere), AppImage units (post-1.0). The engine states the backend and stops — CLAUDE.md's no-shim rule. - Absent from that archive.
cqrlog/cwdaemonon Kali,dump1090-mutability/fbbon the three targets here (both are Ubuntu/Mint packages — closed on the Ubuntu VMs on 2026-09-02, below). The capability matrix records these; they are facts about a distribution, not about the catalog. - Tested-and-retired verdict.
noaa-aptcarriesstatus: retiredwith provenance (the NOAA APT satellites went out of service 2025-11-09) and is correctly refused everywhere. This is the M5 verdict shape: our verdict, with evidence, not an inherited comment.
The one declared conflict¶
wsjtx-improved refuses at plan time wherever the distribution's wsjtx-data
is installed (its vendor .deb ships a colliding pixmap with no Replaces
header) — measured identically on Parrot, Debian and Kali, and refused with
the removal command named. This is coexist-and-disclose (D-022) doing its job,
not a failure.
What "broken" units exist¶
None inherited, and the M5 rule held. Every AHRL "broken" verdict that this
project carried forward was re-attempted rather than trusted: ardopcf revived
(AHRL's error was a stale compiler generation), and the compiler-fragile set
(gsmc, qtsoundmodem, glfer, linrad, xwefax) all build with recorded
flags. The only standing verdicts are retired ones with tested provenance.
Re-run at v0.7.0 — the whole catalog, one pass per target (2026-09-01)¶
The grind above was run profile by profile and then by the uncovered names.
On 2026-09-01, engine at 382f49f, scripts/vm_campaign.py was pointed at
every one of the 242 units in the catalog on each of the three VMs, from
the clean-baseline snapshot, in one accumulating pass each — the way an
operator who installs everything would experience it.
| Target | Installed + confirmed | Refused at plan time | Hard failures |
|---|---|---|---|
| Parrot 7.3 | 232 | 10 | 0 |
| Debian 13 | 231 | 11 | 0 |
| Kali rolling | 233 | 9 | 0 |
726 unit-installs, zero failures. The first pass found exactly two, both fixed the same day and re-confirmed on all three targets:
hamclock-next— itsCMakeLists.txtaliases acpp-httplib::cpp-httplibtarget in the branch taken whenfind_package(httplib)succeeds, which it does on the second build because hamclock's owncmake --installleaks its bundled cpp-httplib into/usr/local, whose exported target ishttplib::httplib. Idempotent re-install failed on all three targets. Carried as the catalog's third real patch, two hunks.wireshark— non-interactive install takes debconf's default (no non-root capture), so thewiresharkgroup the manifest's membership needs never existed on Debian; and on a minimal imagesetcapwas absent so dumpcap got no capabilities. Fixed bydebconf_selections(preseed before apt),libcap2-binin the package list, andreconfigure_afterso the postinst re-runs once the whole transaction is present. Capabilities verified on all three.
Every refusal is one of the classes below, printed with its reason; per
target they were: aethersdr, dump1090-mutability, fbb, sdrangel
absent from the Parrot and Debian archives (and odr-audioenc from
Debian's); cqrlog, cwdaemon, soapysdr-module-rfspace absent from
Kali's; code/codium waiting on the third-party-repo backend;
arduino-cli and soapysdr-module-plutosdr declaring no block for the
target; noaa-apt retired; and wsjtx-improved refusing to collide with the
wsjtx installed earlier in the same pass.
Ubuntu 24.04 and 26.04 — the whole catalog, one pass each (2026-09-02)¶
Two Ubuntu VMs were provisioned on 2026-09-01 (docs/contributing/vm-testing.md
records how) and the same 242-unit pass run on each overnight, engine at
3efff4a, from a clean install. Ubuntu 24.04 was not a declared target when
this ran: it was here because Pop!_OS 24.04 and Linux Mint 22.3 draw on its
archive, standing in for both until a Pop VM exists. This campaign is why it
became one the next day (ubuntu-24.04, 2026-09-03). 4 GB and no swap on each, so the
memory-sized job count built every source unit with one compiler job.
| Target | Installed + confirmed | Refused at plan time | Hard failures |
|---|---|---|---|
| Ubuntu 24.04 | 224 | 18 | 0 |
| Ubuntu 26.04 | 233 | 9 | 0 |
dump1090-mutability and fbb — the two units none of the three earlier
archives carried — installed and confirmed on both, as did cqrlog and
cwdaemon that Kali lacks. Every unit in the catalog that any target's
archive offers has now installed on at least one target.
The pass itself filed three non-zero results, none of them a build defect:
js8callon 24.04: the git build's cmake configure refused Qt 6.4.2 (JS8Call needs 6.5). Ubuntu 24.04 has the same Qt as the Mint 22.3 the manifest already selected the repository package for; the selector now names Ubuntu 24.04 and Pop!_OS 24.04 alongside it, and the apt block installed and confirmed (2.2.0) on the VM.js8callon 26.04: built, and the pass recorded it confirmed the way the caveat below describes — with no executable installed. Rebuilt under the binary effect check after the no-install-rule fix; see the count above.qlogon 26.04: filed as failed at the campaign harness's 900 s budget. The single-job compile ran on unobserved to a verifiedtransaction_endat 1032 s. The harness now enforces its budget on the VM and files a stop as a stop, not a failure (scripts/vm_campaign.py); the count above includes it.
Refusals per target: 24.04 has ten units absent from noble's archive that
26.04 carries (gtk-meshtastic-client, m2kcli, mlat-client-adsbfi,
odr-audioenc, python3-meshtastic, pythonprop, readsb, rtl-ais,
satdump, voacapl) — the capability matrix's Mint 22.3 column, measured
again from the archive it is built on — plus sdrangel (whose 24.04 .deb
depends on a PPA's UHD; the 26.04 .deb is carried and installed) and
wsjtx-improved refusing to collide with wsjtx. 26.04 adds gr-gsm and
soapysdr-module-rfspace, absent from its archive. Both share the standing
classes: code/codium waiting on the third-party-repo backend,
arduino-cli/soapysdr-module-plutosdr declaring no block for the target,
aethersdr absent, and noaa-apt retired.
Caveats, stated¶
- Pop!_OS remains unrun. The engine permits Pop (
ID_LIKE), butdistro: ubuntuselectors will not match itsID=pop— a declare-the-target decision waits on that VM. Its archive is Ubuntu 24.04's, which the pass above covers. Run since, on 2026-09-04: the whole catalog and every profile, written up invm-campaign-pop.md. Same shape as Ubuntu 24.04 less two refusals, andcodeinstalled from Pop's own archive. - "Confirmed" for a source build meant its build dependencies until
2026-09-02. The effect check re-read apt and the group database only; a
build whose install step exited 0 having installed nothing passed. It
happened:
js8callv3.0.3 has no cmake install rule and was recorded confirmed on all three targets here with no/usr/local/bin/js8callon any of them. The check now demands an executable at<prefix>/bin/<install_as>for every declared binary (D-031 addendum), and a comparison of every declaration against the three VMs'/usr/local/binfound exactly that one unit missing and one misnamed (ais-catcher), both fixed and rebuilt. The counts above stand for apt units; for source units they are counts of builds whose install step exited 0, until the next full pass re-runs them under the stronger check. - GUI launch and hardware are console/passthrough-lane checks, not part of this install-success evidence; they are tracked separately.
- Consent-gated profiles (
rf-security,rf-research) were not campaigned autonomously — a human affirms their gate (D-021). Their member packages that also appear in the uncovered set did install by name (the gate is profile-level).
Verdict¶
The M5 install-success exit criterion is met: every installable unit is verified on a supported target, the fraction beats AHRL's own, and the only non-installs are documented refusals in three honest classes. The remaining 1.0 work (the Pop!_OS declaration, GUI/hardware verification, the maintainer's open decisions) is tracked elsewhere and does not bear on this criterion.