Skip to content

feat(console): add demo GIFs, VHS correctness tests, and fix KeyEventKind double-dispatch#105

Open
YuanYuYuan wants to merge 12 commits intomainfrom
dev/ros-z-console
Open

feat(console): add demo GIFs, VHS correctness tests, and fix KeyEventKind double-dispatch#105
YuanYuYuan wants to merge 12 commits intomainfrom
dev/ros-z-console

Conversation

@YuanYuYuan
Copy link
Copy Markdown
Collaborator

@YuanYuYuan YuanYuYuan commented Feb 23, 2026

Summary

  • Add VHS-based TUI demo generation system (scripts/demos/) with 8 annotated tapes covering all major workflows: startup, topics, topic detail, services, nodes, rate measurement, filter mode, and help overlay
  • Extract demos into a dedicated mdbook subchapter (console-demos.md) to keep the main console chapter concise
  • Add VHS-based TUI correctness test suite (tests/run-vhs-tests.nu + 6 tapes) that launches zenohd and ros-z examples for realistic data, then asserts expected TUI state via screenshot size analysis
  • Fix real TUI bug: filter KeyEventKind::Release events to prevent help overlay double-dispatch (crossterm 0.29 + ttyd sends both Press and Release; without the filter, ? would dismiss then immediately re-open the overlay)
  • Fix node panel bugs: double-slash in node names (//Sub/Sub) and empty node detail ("No topics or services") caused by namespace normalisation mismatch between display code and graph HashMap keys
  • Move generic utilities from console into ros-z: ros_z::dynamic::formatter (DynamicMessage → JSON / pretty text) and ros_z::dynamic::DynamicTopicSubscriber (async flume channel bridge over ZSub)

Changes

  • crates/ros-z-console/src/main.rs — filter release events in the TUI event loop
  • crates/ros-z-console/src/app/render/nodes.rs — fix namespace normalisation for display and HashMap lookup
  • crates/ros-z/src/dynamic/formatter.rs — moved from console; JSON and pretty-text formatters for DynamicMessage
  • crates/ros-z/src/dynamic/subscriber.rs — moved from console; async DynamicTopicSubscriber wrapping ZSub with a flume channel
  • scripts/demos/ — VHS tapes + Nushell runner for generating documentation GIFs (starts zenohd, talker, listener, z_srvcli)
  • book/src/img/*.gif — committed demo GIFs for mdbook (01–08)
  • book/src/chapters/console-demos.md — new subchapter with annotated walkthroughs
  • book/src/chapters/console.md — trimmed TUI section, links to demos subchapter
  • tests/run-vhs-tests.nu + tests/tapes/ — 6 correctness tests covering panel navigation, filter mode, help overlay, rate measurement
  • flake.nix — add vhs and ttyd to dev shell
  • .gitignore — add .venv-mcp/

@YuanYuYuan YuanYuYuan changed the title feat(console): TUI demo GIFs, VHS correctness tests, and KeyEventKind fix feat(console): add TUI demo GIFs, VHS correctness tests, and KeyEventKind fix Feb 23, 2026
@github-actions
Copy link
Copy Markdown

github-actions bot commented Feb 23, 2026

PR Preview Action v1.8.1

QR code for preview link

🚀 View preview at
https://ZettaScaleLabs.github.io/ros-z/pr-preview/pr-105/

Built to branch gh-pages at 2026-03-13 14:19 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

@YuanYuYuan YuanYuYuan changed the title feat(console): add TUI demo GIFs, VHS correctness tests, and KeyEventKind fix feat(console): TUI demo GIFs, VHS correctness tests, and keyEventKind fix Feb 23, 2026
@YuanYuYuan YuanYuYuan changed the title feat(console): TUI demo GIFs, VHS correctness tests, and keyEventKind fix feat(console): add demo GIFs, VHS correctness tests, and fix KeyEventKind double-dispatch Feb 23, 2026
Adds automated demo recording infrastructure using VHS (terminal GIF
recorder). Records four demos showcasing ros-z-console features:
startup/discovery, panel navigation, filter mode, and help overlay.

The generate.nu script handles the full lifecycle: building binaries,
starting a Zenoh router + z_pubsub for realistic data, running VHS
tapes with warmup and retry logic, and cleanup.

Key design decisions for reliability on this system:
- Warmup loop (up to 10 attempts) absorbs chromium cold-start latency
- Per-tape retry loop (up to 10 attempts, 3s gaps) mirrors warmup
- After each successful tape: kill leaked ttyd + chromium processes
  and wait 5s, preventing RAM exhaustion from VHS process leaks
- SIGKILL on ttyd/chromium ensures immediate port/resource release
…atch

crossterm 0.29 + ttyd (used by VHS) reports both Press and Release events
for keypresses. Without filtering, pressing ? would:
1. Press event (in show_help branch) → show_help = false
2. Release event (in normal branch) → show_help = true

This prevented the help overlay from being dismissed with ?. Adding a
key.kind != KeyEventKind::Release guard fixes this for all keys.
Tape fixes:
- Add Env DIRENV_DISABLE "1" to all tapes to prevent direnv from
  re-evaluating flake.nix (which is modified) and blocking TUI startup
- Increase Escape sleep in 04-filter.tape from 200ms to 600ms to avoid
  capturing blank frame during alt-screen re-render

Test runner fixes:
- Increase tape retry count from 5 to 10 for chromium warm-up latency
- Add --force to save latest.json to allow overwriting on reruns
- Replace navigation_changes_display (unreliable with 1 topic) with
  initial_is_tui size check (>100 KB confirms TUI loaded, not direnv)
- Remove r_key_triggers check: status bar text change has negligible
  PNG size impact; keep rate_shown_after which reliably detects the
  rate value appearing in the topic list after measurement completes
…to img/

demos/ at the repo root was misplaced — it is a utility script collection,
not a project artifact. Moving it under scripts/ aligns it with the other
Nushell utilities (generate.nu alongside test-pure-rust.nu, etc.).

book/src/demos/ renamed to book/src/img/ which is the conventional name
for image assets in mdbook projects.

- demos/ -> scripts/demos/ (generate.nu + tapes/)
- book/src/demos/ -> book/src/img/
- Update all internal path references and .gitignore
Split the TUI demos out of the main console.md chapter into a dedicated
console-demos.md subchapter. The main chapter now links to it rather
than embedding GIFs inline.

Expanded demo coverage with four new VHS tapes:
- 05-topic-detail: publishers, subscribers, and QoS profiles for a topic
- 06-services: services panel with AddTwoInts service
- 07-nodes: nodes panel showing per-node topic/service associations
- 08-measurement: quick rate check (r) and Measure panel time-series chart

Updated generate.nu to start talker, listener, and z_srvcli server as
separate background processes, providing richer graph data for all panels.
… panel

Two bugs in render/nodes.rs caused by get_node_names() returning the
denormalized root namespace "/":

1. Double-slash display: format!("{}/{}", namespace, name) with
   namespace="/" produced "//Sub" instead of "/Sub". Fixed by
   special-casing root namespace in display formatting.

2. Empty node detail: node_key was built from the denormalized namespace
   "/", but the graph HashMap stores entries under the normalized key
   "" (empty string). Lookups always failed, producing "(No topics or
   services)". Fixed by normalizing "/" → "" before the HashMap lookup.
…emos

Updated 01-04 GIFs reflect the corrected node panel behavior.
New GIFs cover the remaining typical workflows:
- 05-topic-detail: publishers, subscribers, type hash, QoS
- 06-services: services panel with AddTwoInts service detail
- 07-nodes: nodes panel showing /Pub→/chatter, /add_two_ints_server→/add_two_ints
- 08-measurement: quick rate check (r) and Measure panel time-series chart
Both utilities are generic and useful beyond the console:
- `ros_z::dynamic::formatter`: converts DynamicMessage → JSON / pretty text
- `ros_z::dynamic::DynamicTopicSubscriber`: async channel bridge over ZSub

Console now imports from ros_z::dynamic instead of local core modules.
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