feat: add demo GIF for parallel worktrees + agents workflow#132
Merged
Conversation
Adds a scripted WebdriverIO spec (e2e/specs/demo-gif.spec.ts) that drives the real app through the core pitch -- create worktrees, launch simulated parallel agent sessions, review a diff, merge -- capturing a frame sequence that scripts/build-demo-gif.sh stitches into website/public/demo.gif via ffmpeg. The GIF is featured at the top of the README and in a new landing page section. Also fixes a real bug surfaced while building this: getWorktreeStatus's porcelain parser assumed the raw git output never has its leading whitespace trimmed, but gitForPath()'s SimpleGit client sets `trimmed: true`, which eats the leading space off an unstaged-only first status line -- misreporting it as staged and truncating its path by one character. Fixed in packages/git/src/staging.ts with a regression test. Also adds @sproutgit/fs-watch to electron.vite.config.ts's WORKSPACE_PACKAGES list -- it was missing since the package was extracted in #71, which broke `pnpm --filter app build` entirely (chokidar unresolved by rolldown). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a user-facing demo asset to better communicate SproutGit’s “parallel worktrees + parallel agents” workflow (per #122), and includes a small but important git-status parsing fix surfaced while producing the recording. It also introduces supporting automation to regenerate the GIF from scripted E2E frame capture.
Changes:
- Add a new “Demo GIF” section to the website landing page and embed the GIF near the top of the README.
- Fix
git status --porcelain=v1parsing for the “single unstaged file” case when SimpleGit output is globally trimmed; add regression tests. - Add an E2E spec + shell script to capture frames and stitch
demo.gif, plus a small Electron build config fix.
Reviewed changes
Copilot reviewed 10 out of 11 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| website/src/pages/index.astro | Inserts the new DemoGif section into the landing page flow. |
| website/src/components/DemoGif.astro | New landing-page section rendering /demo.gif with framing and copy. |
| website/public/demo.gif | Demo asset referenced by the website and README. |
| README.md | Embeds the demo GIF near the top for immediate value-prop clarity on GitHub. |
| scripts/build-demo-gif.sh | Automates regenerating demo.gif from captured E2E frames via ffmpeg. |
| packages/git/src/staging.ts | Fixes porcelain v1 status parsing when leading-space columns are shifted. |
| packages/git/src/tests/staging.test.ts | Adds regression coverage for staging/status parsing edge cases. |
| e2e/specs/demo-gif.spec.ts | New WDIO spec that drives a full “parallel agents/worktrees” story and captures frames. |
| e2e/package.json | Adds a dedicated demo-gif-frames script for frame capture. |
| e2e/helpers/screenshots.ts | Exports forceTheme for reuse by the new demo spec. |
| app/electron.vite.config.ts | Adds @sproutgit/fs-watch to workspace package handling to unblock app builds. |
- build-demo-gif.sh: use the correct platform subfolder (mac/windows/linux) for captured frames instead of hardcoding "mac", matching the logic in e2e/helpers/screenshots.ts. - staging.test.ts: clean up the temp git repos each test creates, matching the afterEach + rmSync convention used elsewhere in this package (e.g. first-worktree.test.ts). Addresses Copilot review comments on PR #132. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Contributor
Author
|
Addressed both review comments in 303d025:
|
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.
Closes #122
Type
Summary
Why
Issue #122 (P0, adoption blocker): the whole value prop fits in ~20 seconds of screen capture, but no demo asset existed.
How the GIF was produced
It's a real screen capture of the actual app, not a mockup.
e2e/specs/demo-gif.spec.tsextends the existing WebdriverIO hero-screenshots pattern to script a full session against a real Electron build: create 3 worktrees via the UI, launch a simulated agent in each (a cannednode -etranscript keyed off theSPROUTGIT_WORKTREE_NAMEenv var the app already injects — no live coding-agent CLI needed to look authentic), review a diff, then merge two branches and show the resulting graph. It captures a numbered PNG per beat, andscripts/build-demo-gif.shstitches them intowebsite/public/demo.gifwithffmpeg(palette-based encoding, ~414KB). Runpnpm --filter app buildthen./scripts/build-demo-gif.shto regenerate.I considered folding the GIF into the existing
ScreenshotSlidercomponent but it's purpose-built for static optimized PNGs (per-platform, light/dark variants viaastro:assets) — a GIF doesn't fit that model, so it's a new small standaloneDemoGifsection between the hero and the slider instead.Bug fix bundled in (found while building this)
Building the diff-review beat of the recording surfaced a real, pre-existing bug:
getWorktreeStatus's porcelain-status parser (packages/git/src/staging.ts) assumed the rawgit statusoutput never has leading whitespace trimmed. ButgitForPath()constructs its SimpleGit client withtrimmed: true, which trims the entire raw string — eating the leading space off an unstaged-only file when it's the first line of output (M path→M path). That shifts every column, so the file gets misreported as staged and its path loses its first character. This is a common case (any workspace with exactly one unstaged, alphabetically-first change) and was reproducible in the running app, not just synthetically. Fixed by detecting the column shift the same way simple-git's own built-in status parser does, with a regression test added (packages/git/src/__tests__/staging.test.ts).Also:
pnpm --filter app buildwas broken on main —@sproutgit/fs-watch(extracted in #71) was missing fromelectron.vite.config.ts'sWORKSPACE_PACKAGESexternalization-exclusion list, so bundling the main process failed outright (chokidarunresolved). Needed a one-line fix to get any build running for this task, included here since it blocks everyone.Breaking changes
None
Test plan
packages/git/src/__tests__/staging.test.ts(3 new tests) —pnpm --filter @sproutgit/git testpasses (67/67).pnpm lint && pnpm typecheckpass.e2e/specs/demo-gif.spec.tsagainst a real built app (CAPTURE_SCREENSHOTS=1 pnpm --filter @sproutgit/e2e demo-gif-frames) and visually reviewed all 15 captured frames.astro dev) and the GIF/section display as expected.