Repository navigation
v0.7.0 — with-device: the shared-bench claim, as a binary
Pre-release
⚠️ Superseded — do not use
with-device0.2.0 in this release reports exit 0 for commands it never ran. Mode flags
were matched across the whole argv, so any wrapped command containing-h,--help,-V,
--version,--statusor--self-testhijacked the invocation: the device was claimed and
released around nothing, and the caller got success.$ with-device d --registry reg.yaml -- echo --version with-device 0.2.0 # its OWN version rc=0 # and SUCCESSIts
--self-testwas green throughout — it only ever wrapssleep,trueandkill -9, so the
entire bug class sat outside every path it walks. Fixed in 0.2.1; see AFD-084.
with-device — jess's first shipped binary
jess has cut releases before, but never a binary: v0.6.0 and earlier were findings and
artifacts. This release exists because the shared bench needed a tool that a second agent could
run, and that varve could pin — neither of which a script sitting in the repo tree allows.
What it is
Two agents share one physical bench (an STLINK-V3, a Pixhawk 6X-RT). The failure with-device
prevents is not "both want the probe" — it is the silent one. Two readers on a single tty
each receive a subset of the stream and neither errors. Measured on the real board:
ONE reader alone : 66,872 B in 5.0 s
TWO readers together : 37,787 B + 40,053 B
Each got about half, and nothing reported a fault. That is indistinguishable from a flaky USB
link — the worst possible thing to have sitting in a safety campaign's evidence.
The claim is an flock(2) held for exactly the lifetime of the wrapped command, so a crash
releases it. No stale-lock reaper, no release step to forget.
with-device <device>... [--purpose <text>] [--wait <s>] -- <command>...
with-device --status [--format json]
with-device --self-test
Exit codes: 2 usage (including an unregistered device name — a typo must not create its own
lock and exclude nobody), 3 device busy with nothing run, otherwise the wrapped command's own
status.
Multi-device claims are deadlock-free — negative-controlled, not asserted
The original rationale was sorted acquisition (Dijkstra's resource hierarchy). The self-test —
two processes racing for the same two devices in opposite order — passed first run. Removing
the sort showed that was the wrong explanation:
| variant | opposite-order pair |
|---|---|
| as shipped | 0,0 in 2.1 s — pass |
| sort removed, rest intact | 0,0 in 2.1 s — still passes |
| sort removed and hold-and-wait restored | 3,3 in 15.1 s — a real cycle |
The load-bearing mechanism is no hold-and-wait: on contention the claimant drops every lock
it already holds before retrying. Sorting stays as defence in depth and the module header now
says which of the two the test can actually see. Recorded as AFD-083.
Assets
with-device-0.2.0-<triple>.tar.gz for x86_64-unknown-linux-gnu,
aarch64-unknown-linux-gnu, aarch64-apple-darwin, x86_64-apple-darwin, plus
SHA256SUMS.txt. Pin it the way you pin any PulseEngine tool:
release:pulseengine/jess@v0.7.0!with-device-0.2.0-<triple>.tar.gz!with-device
Known scope limit: aarch64-unknown-linux-gnu is cross-built and its self-test is skipped
in the release job — that asset ships unexecuted. It is the Raspberry Pi target, so it wants a
real run on aarch64 before it is trusted there. Every other target is built and self-tested on a
host that runs it.
Zero third-party dependencies — flock(2) is declared with a bare extern "C" — which is what
makes it reasonable to carry inside a signed varve layer (pulseengine/varve#130).
Falsification statement
If with-device is what it claims, then: a second claimant on a held device exits 3 having run
nothing; a device whose holder was kill -9'd is immediately claimable; an unregistered name is
refused rather than silently locked; and two processes claiming the same two devices in opposite
order both complete promptly. Each is asserted by --self-test, which runs on every PR. If any
one of those fails, this release is wrong.