HITL: Implement logic analyzer HITL - #92
Open
fughilli wants to merge 11 commits into
Open
Conversation
fughilli
force-pushed
the
agent/fug-105-upgrade-sbc-deploy
branch
from
August 15, 2026 01:24
b1e9596 to
64dd31c
Compare
|
Move the sbc-deploy pin from cb70fcc to 18a5346 in lockstep across all four
spots (MODULE.bazel git_override + pi/hitl/flake.{nix,lock} + pi/provisioning/
nix/flake.lock). The new revs (upstream PRs #4 + #5) make the zero-conf macOS
aarch64 builder work for EXTERNAL bazel_dep consumers — the builder flake now
rides in each sbc_application target's runfiles, so `bazel run …image_sd` on
macOS auto-manages the sized VM from the pin (no --framework-subdir, no
vendoring, no --cross). Verified on hardware: the Pi 3 image builds via the
auto-started VM and deploys.
Locks regenerated with `nix flake update sbc-deploy` (only the sbc-deploy node
moved; transitive inputs unchanged). MODULE.bazel.lock needs no change
(git_override isn't content-pinned). Also gitignore .sbc-build/ (consumer-side
builder gc-roots/logs).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…fied New rig variant (//pi/hitl:hitl_la, board raspberry-pi-3) with an FX2/fx2lafw "Saleae clone" logic analyzer tapping the ESP32-C6 DUT's WS2812 DIN, closing the "real LED wire correctness needs a logic analyzer on a bench" gap. The FX2 is a rig-level SHARED instrument the daemon owns (never passed into a container): internal/analyzer brokers captures on the single device (mutex- serialized), maps each DUT to its channel subset + protocol, runs a triggered sigrok-cli capture, and decodes it (rgb_led_ws281x / rgb_led_spi — both built into libsigrokdecode >=0.5.3). New POST /capture endpoint; the container-side `hitl-capture` and the daemon are wired via $HITL_CAPTURE_SERVER. So the runner's per-DUT raw-USB isolation is untouched. sbc-deploy injects the board via $SBC_BOARD at eval, so nix/hitl-app.nix keys its sigrok closure + capture flags + FX2 udev rules on raspberry-pi-3 — one appModule yields a lean Pi 5 image and a capture-enabled Pi 3 image, no flake fork. Hardware-driven specifics: - analyzerChannelMap defaults to D6 (PIN20/GPIO20 -> FX2 CH6 on hitl-rig-la-1). - hitl_la hostname = the flake's nixosConfigurations attr "hitl-rig" (deploy_live's --hostname is the attr selector); per-rig identity via $SBC_HOSTNAME_OVERRIDE. - broker: when the tapped line is idle the trigger never fires and sigrok writes no .sr; detect that and return "no data captured …" instead of a cryptic decode error. Verified: go build/vet/test (incl. a synthetic-.sr golden that runs the real sigrok decode); the Pi 3 image builds + deploys; and on hardware, a driven counting pattern decodes correctly on D6. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… notes harness/led_pattern.py: pure helpers — build a set_counting_pattern message and the expected pixels; diff_structure() compares lit-channel STRUCTURE (the firmware scales the wire via WS2812 color-correction/gamma+brightness, so full-scale 255 arrives ~160 — assert the pattern, not exact bytes). Pinned by the CI unit test tests/test_led_pattern.py. harness/hitl_led_capture.py (manual+hitl py_test): drive a known counting pattern on the DUT over the player WSS, capture the WS2812 wire via the daemon's shared analyzer, assert the decoded pattern. --device-ws mode drives an already-reachable ws URL + captures via the daemon directly (no reserve/flash/provision) — the path used to confirm the rig on hardware, tunneling to the DUT through the rig host. WORKLOG: the LA rig is hardware-verified (a driven pattern decodes on D6). Two open rig-networking issues documented as follow-ups: the Pi 3 can't host the provisioning AP (brcmfmac AP mode won't start — needs a USB Wi-Fi dongle for the AP), and the reservation container can't reach a DUT on an external LAN. Until those are fixed, use --device-ws. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Tests couldn't tell rig types apart: every rig shares tag:splanc-hitl and
pool.Pick chooses by idle/shortest-queue, so an analyzer test could land on an
ESP-toolbox rig and fail at capture. Model the analyzer as a first-class,
self-describing CAPABILITY (tags are too coarse).
- api.Status gains Analyzer{present, driver, protocols, channels}; the daemon
advertises it via queue.WithAnalyzer(broker.Describe()) when the broker is
enabled (analyzer.Broker.Describe derives distinct protocols/channels from the
channel map). Additive/omitempty — non-analyzer rigs are unchanged.
- pool.Pick takes an optional pool.Require{Analyzer}: it narrows the pool to
rigs advertising the capability before ranking, or errors clearly if none.
- `hitl reserve/run --require analyzer` threads it through resolve→Pick.
- hitl_client.Reservation(require=...) passes --require; hitl_led_capture sets
require="analyzer" AND asserts the chosen rig's /status has one (so an explicit
--server / --device-ws pin can't silently target a non-analyzer rig either).
Unit tests: pool require-filter (picks the analyzer rig over an idle non-analyzer
one; errors when none) + Broker.Describe. go build/vet/test green; CLI validates
--require. Advertisement lights up once the daemon is redeployed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
fughilli
force-pushed
the
agent/fug-105-upgrade-sbc-deploy
branch
from
August 15, 2026 22:23
e69965e to
4d58340
Compare
The Pi 3's onboard brcmfmac can't reliably host an AP, so the analyzer rig uses a dedicated USB WiFi dongle for its AP (ap0) and leaves wlan0 free for STA. The dongle is an RTL8851BU (WiFi 6 + BT combo, 0bda:1a2b CD-ROM → 0bda:b851 after usb_modeswitch). Driver: nix/rtl8851bu.nix from morrownr/rtw89 (@ e2be1a0) — the mainline mac80211 rtw89 family backported to kernels 6.6+, so it supports hostapd AP cleanly. The rig's in-tree rtw89 predates 8851BU-USB (landed ~6.14; rig is 6.12.87), hence out-of-tree; it builds on 6.12 with zero source patches, and ships the WiFi firmware rtw8851b_fw-1.bin (nixpkgs' linux-firmware predates it). hitl-app.nix (gated on the analyzer board via SBC_BOARD): apIface = ap0; module rtw89_8851bu_git in boot.kernelModules (led-class-multicolor first, since rtw89 is built with CONFIG_RTW89_LEDS_MC); driver in boot.extraModulePackages + hardware.firmware (post-boot module → rides the deploy_live layer, no SD reimage); a .link renames the radio (matchConfig.Driver = rtw89_8851bu_git) to ap0; usb_modeswitch udev rule flips the CD-ROM dongle into WiFi mode; the AP profile / firewall forwarding target ap0. Verified on hitl-rig-2 across a clean reboot: modules autoload, firmware loads, wlan1 -> ap0 rename fires, and NetworkManager hitl-ap activates on ap0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
fughilli
force-pushed
the
agent/fug-105-upgrade-sbc-deploy
branch
from
August 16, 2026 03:35
d410e9b to
6be72c7
Compare
…ions hitl-capture (run over SSH by the harness) needs $HITL_CAPTURE_SERVER, but the daemon's `podman -e` vars reach only sshd's process, not the sessions it spawns (SetEnv was a static PATH/DBUS list, UsePAM no). The container's env-driven tools (hitl-capture, and HITL_DUT/HITL_ADAPTER_SERIAL as documented) were thus invisible to `ssh host cmd`. This surfaced now because the earlier LA capture was verified via --device-ws (daemon-side capture), never the container hitl-capture path. Fix: the entrypoint writes the HITL_* env to ~/.ssh/environment and sshd_config gets PermitUserEnvironment yes, so both interactive shells and `ssh host cmd` inherit them. Also add gnugrep to the entrypoint's runtimeInputs — it uses `printenv | grep` to select the vars, and only openssh+coreutils were on its PATH (grep was missing, so the env file came out empty). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… reload) Two fixes found bringing the full container capture path up on real hardware: - Capture window: the broker software-triggers within a fixed sample window (fx2lafw has no hardware trigger), and the default was ~8.3ms. But the C6's counting probe repaints the WS2812 frame only at its render cadence (10 Hz / every 100ms), so an 8ms window misses the burst ~92% of the time and sigrok reports "trigger never fired / no data". Bump the default to ~208ms (2× the 100ms cadence) so a burst's rising edge is reliably in the window. - Image reload: `podman load` won't move hitl-test:latest to the freshly-built image while the tag is still held by an old image that a stale reservation container references — so container.nix changes silently never reached the rig (had to podman-load by hand). hitl-image-load now clears stale hitl containers and untags the old image before loading, and orders Before=hitl-manager. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A shared-mailbox bridge so the claude-container agent can run host/macOS-only commands (bazel run …deploy_live / image_sd and other host bazel/nix that need the auto-managed aarch64 builder VM + SSH to the rig) without a human relaying each one. - tools/hostdeploy.py: host-side watcher, left running in the repo root. Watches .hostdeploy/request.json, runs allowlisted commands (bazel/bazelisk/nix/git), streams output to <id>.log, writes <id>.status, heartbeats .hostdeploy/alive. - tools/hostrun.sh: container-side submitter. Forwards SBC_* env, streams the log, exits with the real rc. Preflights the heartbeat and tells you to start the watcher. - .hostdeploy/ (runtime mailbox) gitignored. - .claude-container-overlay/skills/host-deploy: agent skill documenting the mechanism. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The lock recorded a stale @@//MODULE.bazel hash; bring it in line with the current MODULE.bazel content. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…BLE radio) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.