Skip to content

One-command fleet UI check: commit the wire-only robot fixture behind browser_check.mjs - #89

Merged
MJohnson459 merged 1 commit into
mainfrom
fleet-ui-check
Aug 2, 2026
Merged

One-command fleet UI check: commit the wire-only robot fixture behind browser_check.mjs#89
MJohnson459 merged 1 commit into
mainfrom
fleet-ui-check

Conversation

@MJohnson459

Copy link
Copy Markdown
Contributor

One command brings up a fake fleet, checks the dashboard in a real browser, and tears it down.

What changed

  • mote_fleet/test/fake_robots.py — the wire-only robot, committed. Every payload is built by protocol.py, so it is the contract rather than a second robot implementation. It models what the UI renders differently: an ok robot and a degraded one, a pose that moves, task transitions (goto dropoff -> dispatched/accepted/succeeded, wibble -> rejected "unknown command", goto nowhere -> rejected "unknown zone"), a redelivered command recognised rather than re-run, and one robot that drops its socket without a DISCONNECT so the broker publishes its Last Will. Usable standalone against any broker for UI hacking.
  • mote_fleet/test/ui_check.py + pixi run fleet-ui-check — the stack around it: container broker (shipped mosquitto.conf, listener ports rewritten), fleet server, the sim's office_world site bundle copied into a temp --maps-dir as the basemap, robots enrolled through the real POST /v1/enroll, an operator token, then browser_check.mjs, then teardown. -- --keep leaves it up with the URL and token printed. --site picks another world.
  • browser_check.mjs — every assertion now polls to a deadline (settle()) instead of sleeping a guessed interval; chrome is located on PATH rather than assuming google-chrome (the old .find(Boolean) always returned the first name); the debugging port is ephemeral so two runs cannot attach to one browser.
  • mote_fleet/test/test_fake_robots.py — 15 tests holding the fixture to protocol.py and to the task layer's grammar. No broker, no ROS, runs in CI, so the fixture can never drift into being a second definition of the wire.
  • Docs: m3-verification.md §2 rewritten to cite the command (with the transcript) and to record the CI decision; mote_fleet/README.md test tiers; docs/fleet/README.md §9; CLAUDE.md M3 paragraph.

The CI decision (recorded, not left implied)

Not a gate. It needs docker — conda-forge's mosquitto is still built without websockets, re-measured at 2.0.20, ldd finds no libwebsockets — and a chrome. Hosted ubuntu-latest has both; ubuntu-24.04-arm, the other half of the build matrix, has no chrome, so wiring it in buys one architecture's coverage of a page with no architecture-specific behaviour, for a ~40 s job gating every PR. The flakiness objection is answered (polling, not sleeps), so it is one workflow step away if that changes. Written into m3-verification.md §2 as a choice rather than an oversight, alongside the sim smoke test's answer (#51).

Verified

  • pixi run fleet-ui-check: 9/9 checks, 6.5 s end to end, run five times. Screenshot shows three robots on the office_world corridor, mote-03 offline via the broker's will, the degraded roll-up, and the full dispatch lifecycle in the status log.
  • Isolation: the workstation was already running a broker and a fleet server on 1883/9001 for a real robot throughout; both were still serving afterwards. After every run: no container, no temp directory, no leftover process.
  • Two concurrent runs on different sites (office_world, hospital_world): 9/9 each, no shared port, container or directory.
  • Refusal paths driven through fleetctl against the fixture: goto dropoff exit 0 (dispatched/accepted/succeeded), wibble exit 1 ("unknown command 'wibble'"), goto nowhere exit 1 ("unknown zone 'nowhere'") — the same transcript shape as §3's real robot.
  • pytest mote_fleet/test in the ROS-free fleet env: 162 passed, 4 skipped (was 147+4 before the new file).
  • pre-commit run --all-files: clean.

Committed on branch fleet-ui-check (worktree at /home/michael/.claude/jobs/856562c1/wt), not pushed.

M3's browser checks (browser_check.mjs) needed a stack assembled by hand, and
the robots behind them were a throwaway script in a scratch directory — so the
next person to touch server/ui/ needed hardware or had to rewrite it.

mote_fleet/test/fake_robots.py is that script, committed: robots that exist
only on the wire. Every payload is built by protocol.py, so it is the contract
rather than a second robot implementation. It models what the UI renders
differently — an ok robot and a degraded one, a moving pose, the task
transitions including both refusals, a redelivered command recognised rather
than re-run, and one robot that drops its socket without a DISCONNECT so the
broker publishes its will.

mote_fleet/test/ui_check.py (pixi run fleet-ui-check) wraps a whole stack
around it: container broker, fleet server, the sim's office_world bundle as a
basemap, enrolled robots and an operator token, then browser_check.mjs, then
teardown. Ports are ephemeral and state is a temp directory, because the
workstation already runs a broker and a server on 1883/9001 for a real robot;
every process is setsid'd so teardown reaps this stack and nothing else. Two
runs at once on different sites both pass. `-- --keep` leaves it up for UI work.

browser_check.mjs now polls each assertion to a deadline instead of sleeping
guessed intervals, finds chrome on PATH rather than assuming google-chrome, and
takes an ephemeral debugging port so two runs cannot attach to one browser.

test_fake_robots.py holds the fixture to protocol.py and to the task layer's
grammar (no broker, no ROS, runs in CI). m3-verification.md §2 now cites the
command, and records why this stays an operator's tool rather than a CI gate:
it needs docker (conda's mosquitto still has no websockets) and a chrome, which
the arm runner has not.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XXRrpPSGvkTLHjFUAJfg4C
@claude

claude Bot commented Aug 2, 2026

Copy link
Copy Markdown

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

@MJohnson459
MJohnson459 merged commit a61eb0f into main Aug 2, 2026
3 checks passed
@MJohnson459
MJohnson459 deleted the fleet-ui-check branch August 2, 2026 10:04
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