Skip to content

refactor(hub): oneshot waiters and plugin hygiene - #40

Merged
s00d merged 15 commits into
mainfrom
refactor/hub-oneshot-cleanup
Sep 6, 2026
Merged

refactor(hub): oneshot waiters and plugin hygiene#40
s00d merged 15 commits into
mainfrom
refactor/hub-oneshot-cleanup

Conversation

@s00d

@s00d s00d commented Sep 6, 2026

Copy link
Copy Markdown
Owner

Summary

  • Replace Condvar read/drain waiters with sync_channel(1), atomic slot install, read fallthrough, and one shared drain idle path (desktop = shared).
  • Strengthen test process: trust matrix, command inventory, AT/mux serde contract, exchange-options Jest, ACL smoke, deflake sleeps.
  • Hygiene: drop dead deps/PortBackend, wide tauri/tauri-plugin reqs with updated lockfile, README drift fixes, thin guest-js cleanup, playground AT quick buttons.

Test plan

  • cargo test --lib hub::
  • cargo test --lib -- command_inventory acl_smoke invoke_contract
  • cargo test --lib -- cancel_exchange_while_at_in_flight write_succeeds_while_exchange_waiting exchange_fails_fast_on_disconnect
  • pnpm test
  • cargo clippy --all-targets -- -D warnings
  • Smoke playground AT quick buttons on a real modem (optional)

Made with Cursor


Summary by cubic

Replaces the hub's Condvar read/drain waiters with sync_channel(1) oneshot signaling and unifies desktop/shared drain idle paths, fixing waiter wake-up races. Also hardens CI, testing, dependencies, and release tooling for publish readiness.

Refactors

  • Read waiters install an atomic slot with fallthrough; the read completes and the waiter consumes the result instead of timing out.
  • PortBackend is deprecated as an alias of ExchangeIo but kept exported for patch compatibility until the next major.
  • SerialPort.open() now resolves with the canonical path string instead of undefined.
  • Pins jni to 0.21, widens tauri/tauri-plugin/serde requirements, and bumps base64/serialport.
  • License files keep the upstream Tauri notice, add s00d, and unify under LICENSE-MIT/LICENSE-APACHE; release tagging moved to release-it with a Cargo version sync hook and pnpm-only publish auth.

Testing & CI

  • Adds command-inventory, ACL smoke, exchange-options, and camelCase serde contract tests with coverage thresholds.
  • Windows CI runs plain cargo test (nextest hits an exe failure) and excludes the plugin lib from Windows runs; connected JNI tests stay local-only.
  • Replaces fixed sleeps with polling, covers the read/drain reclaim race, and clears pending waiters so harnesses exit cleanly.

Written for commit e101bd5. Summary will update on new commits.

Review in cubic

Replace Condvar slot wait with sync_channel, unify drain idle
semantics, and harden tests/deps/docs/playground AT quick cmds.

Co-authored-by: Cursor <cursoragent@cursor.com>
@bolt-new-by-stackblitz

Copy link
Copy Markdown

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

@cubic-dev-ai cubic-dev-ai 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.

All reported issues were addressed across 23 files

Tip: instead of fixing issues one by one fix them all with cubic

Re-trigger cubic

Comment thread examples/serialport-test/src/components/TerminalPanel.vue
Comment thread src/api/backend.rs Outdated
Comment thread src/tests/command_inventory_test.rs Outdated
Comment thread src/hub/shared.rs Outdated
Comment thread README.md
Comment thread src/tests/acl_smoke_test.rs Outdated
Comment thread examples/serialport-test/src/components/TerminalPanel.vue Outdated
Comment thread examples/serialport-test/src/components/TerminalPanel.vue Outdated
s00d and others added 2 commits September 6, 2026 10:08
Fix flaky live-URC PTY wait, expand ACL/contracts/JNI exchange,
Windows nextest, nightly emulator workflow, hub fixtures/chunking,
golden negatives, and publish-surface smoke.

Co-authored-by: Cursor <cursoragent@cursor.com>
Return open() canonical path, restore deprecated PortBackend,
cover read/drain reclaim race, and tighten inventory/AT tests.

Co-authored-by: Cursor <cursoragent@cursor.com>

@cubic-dev-ai cubic-dev-ai 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.

7 issues found across 30 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="scripts/ci-fast.sh">

<violation number="1" location="scripts/ci-fast.sh:25">
P3: This dedicated invocation recompiles the root crate and re-runs the `command_inventory` and `acl_smoke` lib tests immediately after `cargo test --workspace`/`cargo nextest run --workspace` (lines above) already executed the full lib test suite, which includes `src/tests/command_inventory_test.rs` and `src/tests/acl_smoke_test.rs`. The subset run adds a full rebuild + run cycle to a gate advertised as "fast" with no coverage gain. Since both lib tests are already covered by the workspace run, drop this step or run it in place of the full workspace run if the intent is a targeted fast subset.</violation>

<violation number="2" location="scripts/ci-fast.sh:27">
P3: This gate never installs JS dependencies, so on a fresh checkout `pnpm check && pnpm test` fails on missing node_modules rather than on the code being checked. Add `pnpm install` before the JS step (and ideally `cargo build`/fetch deps earlier) so the gate is runnable from a clean clone.</violation>
</file>

<file name="android/src/test/kotlin/app/tauri/serialplugin/manager/UsbFdBridgeTest.kt">

<violation number="1" location="android/src/test/kotlin/app/tauri/serialplugin/manager/UsbFdBridgeTest.kt:317">
P2: This test doesn't verify shutdown unblocks a pending permission wait. `shutdown()` never completes entries in `permissionFutures`, so the worker only finishes because the test explicitly calls `completePermissionForTest(DEVICE, false)` afterward — the test passes identically whether or not shutdown aborts the wait. In production a thread blocked in `requestPermission` (`fut.get(30s)` on the single-thread ioExecutor) is not unblocked by `shutdown()`, and this test masks that hang. Make shutdown complete/cancel pending permission futures and have the test assert the worker finishes from shutdown alone.</violation>
</file>

<file name="src/hub/shared.rs">

<violation number="1" location="src/hub/shared.rs:1234">
P3: The fixture's `expected_match` field is read but never used to drive the completion-variant check: the test hardcodes `matches!(matched, ExchangeMatch::Ok)` and separately asserts `expected_match == "ok"`. Derive the expected variant from `expected_match` (or drop the field) so a future fixture with a different expected match actually drives the assertion instead of failing on the hardcoded `matches!` first.</violation>
</file>

<file name="src/tests/acl_smoke_test.rs">

<violation number="1" location="src/tests/acl_smoke_test.rs:74">
P3: The synthetic test asserts on its own hand-built permissions array, so it can never fail and verifies nothing about the actual ACL wiring. The neighboring deny_open_permission_is_defined already covers the real contract by reading open.toml; drop this test or point it at a real source rather than self-constructed data.</violation>
</file>

<file name="src/android/registry.rs">

<violation number="1" location="src/android/registry.rs:229">
P2: After `exchange_wait` returns, the hub still retains this waiter because this helper never clears it. `feed_bytes` prioritizes that waiter over read/watch/idle routing, so later harness RX is swallowed; clear it after every wait result, including timeout/error.</violation>
</file>

<file name="crates/android-usb-serial/tests/golden_parity.rs">

<violation number="1" location="crates/android-usb-serial/tests/golden_parity.rs:461">
P2: The corruption `"!!!!"` is not valid base64, so `decode_b64` (which falls back to an empty vec via `unwrap_or_default()`) turns it into `[]` rather than real corrupted bytes. The test only passes because this fixture's `controls[0]` payload is `[0,0,0]`; if a fixture regen ever makes that first control payload empty, the corrupted value decodes to the same empty vec and `controls_match` returns true, failing the test confusingly. Corrupt with valid-but-different base64 (e.g. re-encode `[1,2,3]`) so the mismatch is a genuine byte difference independent of the decode fallback.</violation>
</file>

Tip: instead of fixing issues one by one fix them all with cubic

Re-trigger cubic

Comment thread src/android/registry.rs Outdated
Comment thread .github/workflows/test.yml Outdated
Comment thread crates/android-usb-serial/tests/golden_parity.rs Outdated
Comment thread scripts/ci-fast.sh Outdated
Comment thread src/tests/acl_smoke_test.rs Outdated
Comment thread .github/workflows/nightly-android.yml Outdated
Comment thread scripts/ci-fast.sh
Comment thread .github/workflows/nightly-android.yml Outdated
Comment thread src/hub/shared.rs Outdated
s00d and others added 2 commits September 6, 2026 15:02
Pin jni 0.21 for Android compile, replace Windows nextest with
cargo test, share Android setup action with caches, and clear
hub/permission waiters that left harness hangs.

Co-authored-by: Cursor <cursoragent@cursor.com>
Keep a single android-integration prebuild job in test.yml;
connected JNI stays local-only.

Co-authored-by: Cursor <cursoragent@cursor.com>

@cubic-dev-ai cubic-dev-ai 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.

All reported issues were addressed across 13 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Fix all with cubic | Re-trigger cubic

Comment thread .github/workflows/test.yml Outdated
Comment thread android/src/main/kotlin/app/tauri/serialplugin/manager/UsbFdBridge.kt Outdated
s00d and others added 5 commits September 6, 2026 15:13
Add npm description/keywords, crates discoverability fields,
leaner crate exclude, publish.sh (cargo then npm), SECURITY
and CONTRIBUTING.

Co-authored-by: Cursor <cursoragent@cursor.com>
Replace unmaintained standard-version with release-it + Cargo
sync hook; harden UsbFdBridge shutdown; run full Windows cargo test.

Co-authored-by: Cursor <cursoragent@cursor.com>
Check npm/cargo auth up front, install JS deps first, then npm
publish (session expiry) before cargo publish.

Co-authored-by: Cursor <cursoragent@cursor.com>
Drop mixed npm whoami/login from the release docs and script.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>

@cubic-dev-ai cubic-dev-ai 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.

All reported issues were addressed across 17 files (changes from recent commits).

Tip: instead of fixing issues one by one fix them all with cubic

Re-trigger cubic

Comment thread scripts/publish.sh
Comment thread android/src/main/kotlin/app/tauri/serialplugin/manager/UsbFdBridge.kt Outdated
Comment thread scripts/publish.sh Outdated
Comment thread scripts/check-publish-surface.sh Outdated
Comment thread scripts/check-publish-surface.sh
Comment thread LICENSE.spdx Outdated
Comment thread CONTRIBUTING.md Outdated
Comment thread Cargo.toml
s00d and others added 3 commits September 6, 2026 15:37
Exclude tauri-plugin-serialplugin from Windows cargo test
(0xc0000139), sync permission shutdown under lock, tighten
publish guards and license copyright metadata.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>

@cubic-dev-ai cubic-dev-ai 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.

All reported issues were addressed across 10 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Fix all with cubic | Re-trigger cubic

Comment thread LICENSE-MIT
Comment thread scripts/publish.sh
s00d and others added 2 commits September 6, 2026 15:51
MIT requires preserving upstream copyright on derivative code.
Document CARGO_REGISTRY_TOKEN alongside cargo login.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@s00d
s00d merged commit 641812b into main Sep 6, 2026
4 of 5 checks passed
@s00d
s00d deleted the refactor/hub-oneshot-cleanup branch September 6, 2026 11:52
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.

1 participant