pre-PR gate skips build-contract coverage: validate builds named boards, check_build.py only checks coverage for a resolved scope
Author: hathachCreated Sep 21, 2026Updated Sep 21, 2026
LabelsPrio 📌followup
Problem
The pre-PR gate can report green on a change whose driver no built board compiled.
.claude/skills/build/scripts/check_build.py:839-842runscoverage()only when the scope was resolved (--scope/--base); under--boardit is skipped..claude/workflows/validate.js:168-170always dispatchesbuilderwith named boards, so every pre-PR build runs in--boardmode.
Result: a change to src/portable/<vendor>/<driver>.c plus the core file that registers it selects boards, the boards build green, and the uncovered verdict the build contract defines (a class no example enables, a driver the preprocessor removes on every built board, a -T target that writes no elf) is never produced. pre-pr then says ship.
Fix
- Add a selection-only mode to
check_build.py(overselect()/boards_for(),--basepreferred), output marked as a selection, not a build.pre-pruses it instead of its own board-sampling rules. validatecarries the original scope andci_selectreasons through the builds and evaluatescoverage()afterwards, or reports coverage as unverified in its verdict.- Regression cases: changed board file, portable driver, uncovered class, preprocessed-away driver (
dcd_nrf5x.con NRF54,hcd_rp2040.cunder MAX3421), tooling-only change, non-default-Ttarget.
Why deferred
It changes the gate's behaviour, not its plumbing; the workflow cleanup that removes full-check, fanout-dev and check.sh and makes pre-pr software-only lands first and does not touch this.
Source: hathach/tinyusb