Skip to content

feat: M1 software ACs — descriptor, codec, and mockable bosunctl - #4

Merged
RaapTechllc merged 2 commits into
mainfrom
cursor/bosun-m1-software-9a85
Sep 16, 2026
Merged

RaapTechllc merged 2 commits into
mainfrom
cursor/bosun-m1-software-9a85

Conversation

@RaapTechllc

@RaapTechllc RaapTechllc commented Sep 16, 2026

Copy link
Copy Markdown
Owner

M1 software acceptance criteria that can run without a finger on the G13. Live AC-R1 and physical LEFT/DOWN/TOP mapping stay parked. Engine, adapters, and Tauri are untouched.

What landed

  • G13 TOML descriptor load + validation (devices/logitech-g13.toml now includes ignored_key_bits)
  • Codec: bits 0..=21 and 24..=35 → named edge events; ignored bits emit no key events; stick bytes are 0–255 axes
  • bosunctl device info|watch|record|rgb|leds|lcd test over MockTransport
  • Mock hot-plug: scripted disconnect, one reconnect line, resume ≤ 2 s
  • Golden 8-byte fixtures under crates/bosun-hid/tests/fixtures/g13/ (synthetic protocol goldens, not a measured stick envelope)
  • CI: Windows MSVC host assert, no-Tokio check, ignored hardware tests skip without BOSUN_HW=1

Asserted, not rewritten

Transport, HidTransport, MockTransport, device match/select, g13_probe, and bosunctl device list filters.

Review follow-up

Two-axis review (standards + spec) after the first commit. Follow-up commit asserts an empty event stream for ignored bits, restores device list parse helpers, covers new clap commands, and keeps watch/record off feature report 6. Output builders stay a small measured codec (D11), not a second device layer.

Gates (local)

  • cargo fmt --all -- --check
  • cargo clippy --workspace --all-targets --all-features -- -D warnings
  • cargo test --workspace --all-features
  • cargo deny check
  • Hardware tests remain #[ignore] and print skipped: set BOSUN_HW=1... unless that gate is set

Out of scope

  • AC-R1 live shared-input / inventing a pass/fail in docs/hardware-notes.md
  • Physical LEFT/DOWN/TOP mapping
  • Engine, adapters, Tauri, HTTP/WS, profiles, LCD widgets
  • GPL G13 sources, libusb/WinUSB/Zadig/kexts/EVIOCGRAB

Do not merge until review.

Open in Web Open in Cursor 

cursoragent and others added 2 commits September 16, 2026 02:18
Load the committed TOML descriptor, decode kept key bits into edge
events, and exercise info|watch|record|rgb|leds|lcd test over
MockTransport with golden fixtures. Hardware tests stay ignored;
AC-R1 and physical LEFT/DOWN/TOP mapping remain parked.

Co-authored-by: RaapTechllc <RaapTechllc@users.noreply.github.com>
Assert ignored-bit flips produce an empty event stream, restore
device-list parse helpers, cover new clap commands, and keep
watch/record off the feature-report-6 path. Drop process-only
docs/agents files that pointed at untracked scratch tickets.

Co-authored-by: RaapTechllc <RaapTechllc@users.noreply.github.com>
@RaapTechllc
RaapTechllc marked this pull request as ready for review September 16, 2026 02:28
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 16, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-16T02:33:52.525255Z 19121da Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@RaapTechllc
RaapTechllc merged commit 706ecd8 into main Sep 16, 2026
4 checks passed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 19121da376

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/bosunctl/src/lib.rs
}
}
}
Err(HidError::Disconnected) => match opener() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Reconnect on live backend read errors

When a live device is unplugged, HidTransport::read maps every hidapi failure to HidError::Backend in crates/bosun-hid/src/hid.rs, so the Disconnected arm is only reachable with MockTransport; the following catch-all returns an error and terminates device watch instead of reopening after a real hot-plug. Treat live read failures as reconnect signals, as the transport's own documentation requires.

Useful? React with 👍 / 👎.

Comment thread apps/bosunctl/src/lib.rs
fn open_live(descriptor: &DeviceDescriptor, path: Option<&str>) -> bosun_hid::Result<HidTransport> {
let api = HidTransport::api()?;
match path {
Some(path) => HidTransport::open_path(&api, path),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Validate explicit paths against the descriptor match

When --path names another collection of the same composite device, such as its keyboard-page interface, this branch opens it without checking the descriptor's VID, PID, or usage page. Consequently watch may receive no vendor reports and output commands may target the wrong HID collection; resolve the enumerated path and require it to satisfy match_criteria before opening it.

AGENTS.md reference: AGENTS.md:L26-L26

Useful? React with 👍 / 👎.

Comment thread apps/bosunctl/src/lib.rs
Comment on lines +201 to +202
let mut file = std::fs::File::create(&args.output)
.with_context(|| format!("could not create {}", args.output.display()))?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve existing recordings when device opening fails

When --output already exists and the device is absent or cannot be opened, File::create truncates the recording before record_reports invokes the opener and returns its error. A failed capture can therefore destroy the previous hardware fixture; open the transport first or write to a temporary file and replace the destination only after capture begins or succeeds.

Useful? React with 👍 / 👎.

Comment on lines +189 to +194
if keys.len() + raw.caps.ignored_key_bits.len() != KEY_BIT_COUNT {
return Err(DescriptorError::Malformed(format!(
"caps.keys ({}) plus ignored_key_bits ({}) must cover {KEY_BIT_COUNT} bits",
keys.len(),
raw.caps.ignored_key_bits.len()
)));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep the G13 bitmap width out of descriptor loading

Any descriptor whose key report is not exactly 40 bits is rejected here before its device-specific codec can inspect it, so the generic TOML layer cannot represent the planned second device or another HID layout without inventing fake ignored bits. Keep the 40-bit coverage invariant in the G13 codec and allow the descriptor loader to accept other key counts.

AGENTS.md reference: AGENTS.md:L12-L12

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants