From 7700af2ed7c12c9047699d20816e99b3622710e1 Mon Sep 17 00:00:00 2001 From: Tzu-Chieh Huang Date: Fri, 17 Jul 2026 11:28:56 -0700 Subject: [PATCH] docs: record Pi MR2 evidence --- AGENTS.md | 1 + CONTRIBUTING.md | 29 +++++--- docs/deployment.md | 5 +- docs/phases/phase-3-pi-compatibility.md | 88 +++++++++++++++++++++++-- docs/roadmap.md | 8 ++- 5 files changed, 113 insertions(+), 18 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index d828f87..7dec3e7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -31,6 +31,7 @@ each MR states scope, verification, and any hardware action needed. - Never edit, commit, or push `main` directly. Work on a dedicated branch and merge through a reviewed MR. Do not push any branch unless explicitly asked. +- Prefer short, descriptive branch names so manual pushes stay easy. - Run mock/unit tests before hardware tests. - Hardware validation runs on target Linux hardware; QEMU cannot validate USB control behavior. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 474173e..5f9760d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,8 +3,9 @@ ## Prerequisites - Native Linux with a C toolchain (`cc`) for Rust crates that compile native - code. Raspberry Pi OS accessed over SSH is the primary development target; - Zed Remote Development builds and runs code on the Pi. + code. Raspberry Pi OS local sessions are the primary development target. + SSH and Zed Remote Development are optional; when used, builds and hardware + commands still run on the Pi. - [rustup](https://rustup.rs/). The committed `rust-toolchain.toml` installs the selected compiler, Clippy, and rustfmt. @@ -43,20 +44,32 @@ install `usbutils` and `alsa-utils`. rustup show ``` -## Develop on the Pi over SSH +## Develop directly on the Pi -Clone the repository on the Pi under the SSH development user. Open that clone -through Zed Remote Development; editor, Cargo, and hardware commands then run -natively on the Pi. This is preferred even when editing from another laptop, -because it validates the actual target architecture and ALSA environment. +Work in the repository from a local Pi session. Editor, Cargo, and hardware +commands run natively on the Pi, validating target architecture and ALSA. +SSH/Zed Remote Development may access that same checkout when convenient, but +is not required. Before connecting hardware, run the checks in [Checks](#checks). If ALSA access -is needed, add the SSH user to the `audio` group, then reconnect the SSH session: +is needed, add the current local user to the `audio` group, then start a new +login session: ```sh sudo usermod -aG audio ``` +Before hardware probes, confirm the new session has both ALSA device nodes and +effective group membership: + +```sh +test -d /dev/snd +id -nG +``` + +Do not use `sudo` to mask a missing `/dev/snd` directory or inactive `audio` +membership; fix local device-node/session access first. + Do not run control writes, routing/clock changes, firmware updates, resets, or profile application without explicit approval. diff --git a/docs/deployment.md b/docs/deployment.md index f0b4f8f..7938f2c 100644 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -4,8 +4,9 @@ - Primary appliance: Raspberry Pi 5, 64-bit Linux, `aarch64-unknown-linux-gnu`. -- Primary development target: Raspberry Pi 5 over SSH, commonly through Zed - Remote Development. +- Primary development target: local Raspberry Pi 5 session. +- SSH and Zed Remote Development are optional remote access paths, not required + development workflow. - Laptop-local Linux or WSL are optional development environments; neither is a deployment target. diff --git a/docs/phases/phase-3-pi-compatibility.md b/docs/phases/phase-3-pi-compatibility.md index 22f9afe..7539bff 100644 --- a/docs/phases/phase-3-pi-compatibility.md +++ b/docs/phases/phase-3-pi-compatibility.md @@ -2,9 +2,9 @@ ## Status -In progress. MR 1 complete; MR 2 is next. Target is prepared Pi OS ARM64 with -Scarlett Solo 4th Gen connected directly by USB. Phase 2 WSL evidence remains -valid only for its WSL scope. +In progress. MR 1 and MR 2 complete; MR 3 is next. Target is prepared Pi OS +ARM64 with Scarlett Solo 4th Gen connected directly by USB. Phase 2 WSL +evidence remains valid only for its WSL scope. ## Goal @@ -89,6 +89,84 @@ FOCUSRITED_HARDWARE_CARD=Gen cargo test -p focusrited --test scarlett2_alsa \ Read-only only. No control write or stored-profile apply. +**Execution plan** + +1. On the prepared Pi, confirm the Solo is directly connected and record only + bounded, sanitized read-only evidence: + + ```text + uname -a + lsusb | grep -i focusrite + cat /proc/asound/cards + arecord -l + aplay -l + amixer -c CURRENT_CARD_INDEX controls + amixer -c CURRENT_CARD_INDEX contents | sed -n '1,400p' + ``` + + Replace `CURRENT_CARD_INDEX` with the index shown for Solo in the immediately + preceding `/proc/asound/cards` output; never assume card 0. Use its named + ALSA ID (for example, `Gen`) for `focusrited --card` and hardware-test + `FOCUSRITED_HARDWARE_CARD`. Redact serials, usernames, LAN addresses, + tokens, and unrelated USB/system data before saving any evidence. +2. Build and run local checks before touching Pi hardware: + + ```text + cargo fmt --check + cargo clippy --workspace --all-targets -- -D warnings + cargo test --workspace + ``` + +3. Run the ignored read-only discovery test against that explicit card: + + ```text + FOCUSRITED_HARDWARE_CARD=CARD cargo test -p focusrited \ + --test scarlett2_alsa discovers_attached_solo -- --ignored --test-threads=1 + ``` + + Confirm it reports only non-writable capabilities, rejects a command + without a hardware write, and exits successfully. +4. Start daemon with an empty temporary profile-store path, observe successful + startup, then stop it without issuing a command: + + ```text + profile_dir=$(mktemp -d) + profile_store="$profile_dir/profiles" + timeout --signal=INT 5s cargo run -p focusrited -- --card CARD \ + --profile-store "$profile_store" + rmdir "$profile_dir" + ``` + + `timeout` ending this foreground daemon is expected. Treat a startup error, + ALSA access error, or an unexpected file left in the temporary profile store + as MR2 evidence to investigate. +5. Compare sanitized Pi controls, types, counts, and availability with + `crates/focusrited/tests/fixtures/scarlett-solo-4th-gen.md`. Change fixture + or parsing only for a Pi-proven difference; otherwise add a dated evidence + summary and Pi prerequisites to the hardware/deployment documentation. + +**Evidence — 2026-07-17 (complete)** + +- Target reports Debian GNU/Linux 13.6 on `aarch64`, kernel + `6.12.62+rpt-rpi-2712`. +- `/proc/asound/cards` identifies Scarlett Solo 4th Gen as card index 2 with + ALSA ID `Gen`. Capture and playback both expose device 0. +- Direct Pi ALSA access has `/dev/snd` available and effective `audio` group + membership. The workspace sandbox intentionally does not mount `/dev/snd`; + hardware commands must run from a direct Pi terminal or an approved + unsandboxed runner. +- Bounded `amixer -c 2 controls` and contents report 56 controls. Their IDs, + types, access shape, enum domains, and integer ranges match Phase 2 fixture. + Current control values were observed only and are not recorded here. +- `FOCUSRITED_HARDWARE_CARD=Gen` read-only `discovers_attached_solo` passes: + all discovered capabilities remain non-writable and service commands are + rejected before hardware write. +- `focusrited --card Gen` starts successfully for five seconds with an empty + disposable profile-store path. It receives no command; temporary directory + removal confirms no profile file was written. +- No ALSA control, profile, fixture, or adapter code changed. MR3 may capture + metadata and verify an operator-initiated external Direct Monitor change. + ### MR 3: Native reconciliation and controlled write metadata **Scope** @@ -153,8 +231,8 @@ Read-only only. - [x] Read-only and write-capable hardware tests are structurally separated; write tests require explicit feature plus session approval. -- [ ] Solo service builds and starts natively on Pi against selected ALSA card. -- [ ] Sanitized Pi discovery proves capabilities and documented prerequisites. +- [x] Solo service builds and starts natively on Pi against selected ALSA card. +- [x] Sanitized Pi discovery proves capabilities and documented prerequisites. - [ ] External/front-panel change reconciles into authoritative service state. - [ ] Physical unplug/replug recovers to a fresh online snapshot. - [ ] Pi reboot returns daemon and Solo readiness without device-state mutation. diff --git a/docs/roadmap.md b/docs/roadmap.md index a8b6f60..d1201be 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -42,16 +42,18 @@ domains remain explicit but non-writable. Exit: mock and Solo-on-WSL tests cover supported control behavior, failure, disconnect/reconnect, and persistence; unsupported controls are explicit. -## Phase 3: Pi compatibility verification — planned +## Phase 3: Pi compatibility verification — in progress Execution plan: [Phase 3 Pi compatibility plan](phases/phase-3-pi-compatibility.md). -Develop directly on the Pi over SSH, including Zed Remote Development from a -laptop, then validate current Solo service natively on Pi Linux. Find and fix +Develop directly in a local Pi session, then validate current Solo service +natively on Pi Linux. SSH/Zed Remote Development is optional. Find and fix target-only build, ALSA, USB, system-service, reboot, and unplug/replug issues. Cross-compilation may be introduced only if native Pi development demonstrates a real need. +MR 1 and MR 2 are complete; MR 3 is next. + Before adding Phase 3 hardware coverage, split Solo tests into a read-only hardware suite (discovery, external changes, reconnect) and a write-capable suite. Gate the write-capable suite behind an explicit Cargo feature so running