원클릭으로
visual-proof
Capture before/after UI screenshots and video for Invoker plans that modify the UI.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Capture before/after UI screenshots and video for Invoker plans that modify the UI.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Generate a reusable loop instruction doc, loop driver script, and Invoker workflow from an interview. Trigger: "loop generator", "generate a loop", "invoker-loop-generator", "/invoker-loop-generator", or requests to build a reusable babysit/watch/retry loop. For benchmark/direct-output prompts with "Required output path", write the requested artifact directly to that literal path, do not ask clarifying questions, and do not validate, review-gate, or submit.
Convert a plan into an Invoker YAML plan file. Trigger: "convert to invoker", "submit to invoker", "create invoker plan", "invoker-plan-to-invoker", "/invoker-plan-to-invoker", "/plan-to-invoker", or turning a plan file into Invoker tasks. For benchmark/direct-output prompts with "Required output path", write a complete YAML document directly to that literal path; it must start with top-level name, onFinish, mergeMode, repoUrl, and tasks, never version or metadata wrappers, and must not scan, validate, submit, or discover env vars.
Create or update a pull request in this repo using the preferred PR schema, upstream-first branch workflow, and repo-specific publication rules. Trigger when asked to make a PR, update a PR body, prepare PR text, publish a stacked PR branch, or whenever a branch/PR change means the GitHub PR metadata may now be stale.
Shape code changes, workflow plans, and PR stacks so each diff is easy to review: one local claim, one safety invariant, clear architectural effect, and an explicit reason for the slice.
Land (queue/merge) a Mergify-managed PR stack safely. Trigger when asked to land, merge, ship, or queue a PR or PR stack with Mergify. Enforces that you act only on SHA-verified PR numbers — never a PR found by branch name.
Get a new machine "good to go" for Invoker and optionally wire up the Slack integration. Trigger when asked to set up Invoker, run the setup/tutorial, check the environment, fix missing tools, or configure the Slack bot ("set up slack", "/setup", "am I good to go?").
| name | visual-proof |
| description | Capture before/after UI screenshots and video for Invoker plans that modify the UI. |
Capture before/after UI screenshots and video for Invoker plans that modify the UI.
visualProof: true (i.e. it modifies packages/ui/)The script scripts/ui-visual-proof.sh provides four explicit subcommands:
Capture "before" screenshots to packages/app/e2e/visual-proof/before/.
bash scripts/ui-visual-proof.sh capture-before
Builds UI and app, runs Playwright tests, saves screenshots and video. Fails fast if build fails.
Capture "after" screenshots to packages/app/e2e/visual-proof/after/.
bash scripts/ui-visual-proof.sh capture-after
Same build and capture process as capture-before, outputs to after/ directory.
Generate diff images and side-by-side video comparison.
bash scripts/ui-visual-proof.sh compare
Requires:
before/ and after/ directories exist with matching .png filesffmpeg installed (for video comparison)compare (for per-image pixel diffs)Outputs to packages/app/e2e/visual-proof/diff/.
Generate markdown with base64-encoded before/after images.
bash scripts/ui-visual-proof.sh embed
Requires before/ and after/ directories. Outputs to packages/app/e2e/visual-proof/EMBED.md.
packages/app/e2e/visual-proof.spec.ts defines the UI states to capture. Each test case:
loadPlan, startPlan, etc.)captureScreenshot(page, 'state-name') which saves a PNG when CAPTURE_MODE is setcaptureScreenshot is defined in packages/app/e2e/fixtures/electron-app.ts. It's a no-op unless CAPTURE_MODE env var is set.
When visualProof: true is set on a plan, the merge gate in TaskExecutor.runVisualProofCapture() (in packages/executors/src/task-executor.ts) runs the capture subcommands and uploads assets to R2 via scripts/upload-pr-images.mjs
Edit packages/app/e2e/visual-proof.spec.ts and add a test case that calls captureScreenshot(page, 'my-state'). The capture subcommands will automatically include it.
Example:
test('approval modal', async ({ page }) => {
await loadPlan(page, PLAN_WITH_MANUAL_APPROVAL);
await startPlan(page);
await waitForTaskStatus(page, 'task-1', 'awaiting_approval', 30000);
await page.locator('[data-testid="rf__node-task-1"]').click();
await page.getByText('Approve').click();
await captureScreenshot(page, 'approval-modal');
});
| File | Role |
|---|---|
scripts/ui-visual-proof.sh | Capture script (build + Playwright + collect outputs) |
packages/app/e2e/visual-proof.spec.ts | Playwright spec defining UI states to capture |
packages/app/e2e/fixtures/electron-app.ts | captureScreenshot, loadPlan, startPlan helpers |
packages/app/playwright.config.ts | Playwright config (video, screenshot, timeout settings) |
packages/executors/src/task-executor.ts | runVisualProofCapture() — merge gate integration |
scripts/upload-pr-images.mjs | Upload captured assets to Cloudflare R2 |
scripts/create-pr.mjs | Create GitHub PR with uploaded visual proof |
UI-change plans must include explicit visual proof tasks, not just the visualProof: true flag.
During plan verification (Phase 1b), capture "before" screenshots on the base branch:
bash scripts/ui-visual-proof.sh capture-before
The implementation plan must include two visual-proof-related tasks:
E2E test case task (prompt): Adds a plan-specific test to visual-proof.spec.ts that
captures the exact UI state being changed. Runs in parallel with implementation tasks.
Capture task (command): Captures "after" screenshots. Depends on all
implementation tasks + the E2E test case task:
bash scripts/ui-visual-proof.sh capture-after
Each UI plan should add a test case to packages/app/e2e/visual-proof.spec.ts that targets
the exact UI state being changed.
test('<plan-slug> — <state description>', async ({ page }) => {
await loadPlan(page, MY_PLAN);
await startPlan(page);
await waitForTaskStatus(page, 'task-id', 'awaiting_approval', 30000);
await page.locator('[data-testid="rf__node-task-id"]').click();
await page.getByText('Approve').click();
await captureScreenshot(page, '<plan-slug>-<state>');
});
All from packages/app/e2e/fixtures/electron-app.ts:
| Helper | Purpose |
|---|---|
loadPlan(page, plan) | Load a plan object via IPC and wait for DAG to render |
startPlan(page) | Start plan execution via IPC |
waitForTaskStatus(page, taskId, status, timeout) | Poll until task reaches status |
captureScreenshot(page, name) | Save screenshot (only when CAPTURE_MODE is set) |
waitForStableUI(page) | Wait for animations to settle |
getTasks(page) | Get all current tasks via IPC |