The flag was plumbed through pbrig.Deployment to the host-tool subprocess
calls and nowhere else, so identity() and scan() opened a raw port and drove
a shared line as though it were two wires. On real one-wire hardware the
adapter's echo answers the knock before the device does, so the suite would
have died at its very first check — "the loader never answered; nothing below
can be trusted" — for the one deployment the flag exists to test, and every
result after it is gated on that check passing.
Both now open through pbrig.Rig.open_port(), which applies the deployment's
link mode. The gap underneath was that only the subprocess path could reach
those facts at all; anything driving the protocol in-process had to restate
them, and did not.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A rig hiccup mid-walk records the scan check as failed and lets the suite
continue, matching its siblings' envelope; a nonexistent --port path
reports as an error instead of a traceback.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
--scan's walk was unwalkable on POSIX: probe rates have no termios
B-constant, so the first off-nominal probe raised out of the loop. The port
speaks termios2 BOTHER now (red-proven on a pty at 9984 Bd), the probe's
open lives inside the walk's error handling, an fd no longer leaks on an
unmakeable rate, and the swallowed unknown-signature reply is named at
timeout instead of reported as silence. CMakePresets.json's generator emits
the submodule toolchain path it had drifted from — a hand edit on a
generated file, exactly the class rule 10 exists for — and presets.generated
gates the pair from here on (the marker CMake rejects at the
presets root stayed out; the check is the guard). The over-slot image guard
the tsb runner gained reaches the pureboot runner too; the GPIO bridge's
delivery comment states the hardware truth (RXC at the stop bit's sampling
point); the hardware suite gains the scan check — the one place the rate
physics is real; and the libavr pin advances over both audit rounds.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
check.sh proves the protocol under simavr on every chip; it cannot prove a
board. Two things live only on silicon — an RC oscillator that is not on its
nominal, and a reset edge that has to come from somewhere — and until now the
scripts that reached them were per-session scratch on the machine holding the
programmer, which is where the ATtiny13A run's findings nearly stayed.
pbrig.py is the primitives, knowing nothing per-board: every deployment fact is
a flag or a PUREBOOT_* variable. Two rig facts are encoded in it because neither
is guessable and each cost a session to learn: an ISP access *is* the reset edge
where the adapter's DTR is unwired, so a session begins with an ISP touch and
knocks immediately after; and avrdude splits -U on colons, so a Windows drive
letter breaks the spec and every file goes as a bare name with avrdude run in
its own directory. Its `rate` subcommand is the one that turns "the loader is
silent, so the wiring must be wrong" into a number, by sweeping the host rate
against a fixed cycles-per-bit transmitter — PUREBOOT_HEARTBEAT makes the
existing fixture into one, software link only, since the hardware-link idle owes
the self-update tests its command loop.
pbhw.py takes every bound from the info block the loader reports, so one run
covers a 1 KiB tiny and a 128 KiB mega alike. Both are exercised on an ATtiny13A:
backup verified against a known-good capture, the clock measured at 9.048 MHz
against a 9.6 MHz nominal, and the suite 11/11.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>