xtask: add record-demo subcommand (v0)#190
Open
whme wants to merge 2 commits into
Open
Conversation
The README's demo/csshw.gif is currently re-recorded by hand each time it drifts from the product, requiring a developer to manually configure their workstation (wallpaper, fake SSH hosts, keystroke overlay, ScreenToGif). This commit lays the foundation for "demo as code" - a typed Rust DSL describing the demo plus an xtask subcommand that runs it. This is v0 of a four-stage plan: a local-only proof that produces target/demo/csshw.gif on the developer's own desktop. v1 adds Windows Sandbox isolation + Carnac overlay + visual normalisation; v2 adds CI workflows + an append-only demo-assets orphan branch with SHA-pinned filenames; v3 adds the chord/Press DSL primitive plus the full canonical scene. Architecture mirrors the existing xtask modules (e.g. social_preview.rs): - DemoSystem trait + RealSystem behind which all side effects (windows input synthesis, fs, subprocess) sit so unit tests exercise the driver via mockall with zero real-system effects. - Closed Step enum + Script builder validating capture pairing and regex compilation at build time, so a typo in the script fails cargo check rather than a half-completed recording. - Driver interprets steps via the trait; the in-flight ffmpeg capture is cleaned up even when a step errors mid-script. - config_override writes target/demo/csshw-config.toml, a dispatcher.bat that strips an optional user@ prefix from csshw's USERNAME_AT_HOST substitution, and per-host enter.bat scripts with curated home directories. - env/local.rs copies csshw.exe into target/demo/ so csshw's startup set_current_dir(exe_dir) lands on our config (csshw rebases its cwd at startup, so a plain cwd-based override does not work). - terminate_csshw kills the daemon child and best-effort kills any CREATE_NEW_CONSOLE-detached client csshw.exe instances. v0 requires ffmpeg and gifski on PATH; v1 will vendor them as SHA-pinned binaries downloaded into target/demo/bin/. The full plan lives at C:/Users/whme/.claude/plans/tranquil-hopping-karp.md. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
|
🤖 News Fragment Check ✅ Success! This PR meets the news fragment requirements. |
|
🤖 Diff Coverage Check ✅ Success! Diff CoverageDiff: origin/main...HEAD, staged and unstaged changesNo lines with coverage information in this diff. |
|
🤖 Coverage Check
|
Contributor
There was a problem hiding this comment.
Pull request overview
Introduces a new cargo xtask record-demo subcommand that records a reproducible “demo as code” GIF via a typed Rust DSL, a mockable driver (DemoSystem), and a v0 local environment implementation.
Changes:
- Add
record-demoCLI subcommand wiring inxtask, plus a newxtask::demomodule with DSL, driver, script, and environment scaffolding. - Implement v0 local demo environment: generates a demo-only
csshw-config.toml+ fake-host filesystem, launchescsshw, and orchestrates ffmpeg→gifski recording. - Add unit tests for DSL validation, driver semantics, config override output, and canonical script structure.
Reviewed changes
Copilot reviewed 16 out of 17 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| xtask/src/main.rs | Adds RecordDemo subcommand and dispatches into demo::record_demo. |
| xtask/src/demo/mod.rs | Defines DemoSystem abstraction + RealSystem and the record_demo entrypoint. |
| xtask/src/demo/dsl.rs | Adds typed Step enum + Script builder with compile-time-ish validation via build(). |
| xtask/src/demo/driver.rs | Implements step interpreter, capture lifecycle, and window wait/focus/type primitives. |
| xtask/src/demo/script.rs | Defines canonical v0 demo script builder. |
| xtask/src/demo/config_override.rs | Writes demo-only config, dispatcher, and fake host home trees. |
| xtask/src/demo/recorder.rs | Implements ffmpeg capture + frame extraction + gifski encoding pipeline. |
| xtask/src/demo/windows_input.rs | Wraps Win32 window enumeration + input injection with non-Windows stubs. |
| xtask/src/demo/env/mod.rs | Introduces env module namespace (v0: local only). |
| xtask/src/demo/env/local.rs | v0 local provider: prepares demo tree, copies csshw.exe, runs driver, cleans up. |
| xtask/src/tests/test_demo_dsl.rs | Tests DSL ordering, defaults, and validation failures. |
| xtask/src/tests/test_demo_driver.rs | Tests driver behavior with a mock DemoSystem. |
| xtask/src/tests/test_demo_config_override.rs | Tests config/dispatcher/fakehost generation via mock writes. |
| xtask/src/tests/test_demo_script.rs | Sanity-checks canonical v0 script build and expected step shape. |
| xtask/src/tests/test_demo_mod.rs | Smoke-tests demo module public surface types. |
| xtask/Cargo.toml | Adds regex dependency and Windows-only windows dependency/features for demo input APIs. |
| Cargo.lock | Locks new dependencies (regex and transitive crates). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
8 tasks
Three follow-ups on the v0 record-demo subcommand surfaced during review: - driver: thread `out_gif` through to `StopCapture` so the produced GIF lives at the path the caller requested instead of always ending in `.gif`-derived-from-`.mkv`. Mark `state.capturing = false` before calling `stop_recording` (both in the step handler and the cleanup path) so a failing stop cannot be retried by the cleanup loop and double-consume the in-flight ffmpeg child. - mod: bail in `record_demo` when `cfg!(target_os = \"windows\")` is false, with the same message the `windows_input` stub already uses. Previously non-Windows callers proceeded and failed later with misleading `csshw.exe`/`gdigrab` errors. - env/local: route the `csshw.exe` existence check through a new `DemoSystem::file_exists` method instead of `Path::exists`, so `env::local::run` is fully mockable and consistent with the rest of the trait's side-effect surface. GitHub: #190 Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The README's
demo/csshw.gifis currently re-recorded by hand eachtime it drifts from the product, requiring a developer to manually
configure their workstation (wallpaper, fake SSH hosts, keystroke
overlay, ScreenToGif). This PR turns that artifact into a
reproducible build output.
This is v0 of a four-stage plan: a typed Rust DSL + driver +
local env that produces
target/demo/csshw.gifon the developer'sown desktop. Requires
ffmpegandgifskion PATH. v1 (WindowsSandbox provider, vendored SHA-pinned binaries, Carnac overlay,
visual normalisation) is in a separate stacked PR. v2 (CI workflows
Press(Chord)primitive + full canonical scene) are out of scope.
The PRs are stacked Gerrit-style: the v1 PR currently contains v0+v1
commits and targets
main; once this PR merges, the v1 PR will berebased on
mainso only v1 changes remain.v0 highlights
DemoSystemtrait +RealSystembehind which all side effects(Windows input synthesis, fs, subprocess) sit so unit tests
exercise the driver via mockall with zero real-system effects.
Stepenum +Scriptbuilder validating capture pairingand regex compilation at build time, so a typo in the script
fails
cargo checkrather than a half-completed recording.capture is cleaned up even when a step errors mid-script.
config_overridewritestarget/demo/csshw-config.toml, adispatcher.batthat strips an optionaluser@prefix fromcsshw's
USERNAME_AT_HOSTsubstitution, and per-hostenter.batscripts with curated home directories.env/local.rscopiescsshw.exeintotarget/demo/socsshw's startup
set_current_dir(exe_dir)lands on our config.terminate_csshwkills the daemon child and best-effort killsany
CREATE_NEW_CONSOLE-detached clientcsshw.exeinstances.Test plan
cargo build -p xtaskclean (no warnings)cargo fmtcleancargo lintcleancargo test(all green)cargo doc-testscleancargo xtask check-typographycleancargo xtask record-demo --env localproduces aplayable
target/demo/csshw.gifThe full plan lives at
C:/Users/whme/.claude/plans/tranquil-hopping-karp.md.