Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions .github/workflows/droid-control-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
name: droid-control tests

on:
pull_request:
paths:
- 'plugins/droid-control/scripts/render-showcase.sh'
- 'plugins/droid-control/tests/**'
- 'plugins/droid-control/remotion/**'
- '.github/workflows/droid-control-tests.yml'
push:
branches: [master]
paths:
- 'plugins/droid-control/scripts/render-showcase.sh'
- 'plugins/droid-control/tests/**'
- 'plugins/droid-control/remotion/**'
- '.github/workflows/droid-control-tests.yml'

env:
PYTHONDONTWRITEBYTECODE: 1

jobs:
render-helper:
name: render-showcase.sh behavior
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Install ffmpeg and agg
run: |
set -euo pipefail
sudo apt-get update
sudo apt-get install -y --no-install-recommends ffmpeg
curl -fsSL -o agg https://github.com/asciinema/agg/releases/download/v1.9.0/agg-x86_64-unknown-linux-gnu
echo "f111e315cd71056b116302342553dd765b7297579ed511f111d0cedb442aeda6 agg" | sha256sum -c -
sudo install -m 0755 agg /usr/local/bin/agg

- name: Run helper integration tests
run: python3 -m unittest discover -v -s plugins/droid-control/tests -p 'test_*.py'

remotion:
name: Remotion typecheck, duration tests, real render
runs-on: ubuntu-latest
defaults:
run:
working-directory: plugins/droid-control/remotion
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
# node --test with built-in type stripping (22.18+); Remotion runtime itself needs >= 18
node-version: 22
cache: npm
cache-dependency-path: plugins/droid-control/remotion/package-lock.json

- run: npm ci

- run: npx tsc --noEmit -p .

- run: npm test

- name: Install ffmpeg and the Remotion browser
run: |
set -euo pipefail
sudo apt-get update
sudo apt-get install -y --no-install-recommends ffmpeg
npx remotion browser ensure

- name: Render a synthetic clip through render-showcase.sh and check the encoded file
working-directory: .
env:
RENDER_SHOWCASE_E2E: 1
run: python3 -m unittest discover -v -s plugins/droid-control/tests -p 'test_*.py' -k RealRender
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
.factory/
node_modules/
# Per-render clip staging created by render-showcase.sh; only survives a SIGKILL
plugins/droid-control/remotion/public/render-*/
6 changes: 3 additions & 3 deletions .skillsrc
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# Skills listed here are excluded from the top-level skills/ directory.
# One skill path per line, relative to the repo root (plugin/skills/skill-name).
# Lines starting with # are comments. Blank lines are ignored.
droid-control/skills/agent-browser
droid-control/skills/browser-use
droid-control/skills/capture
droid-control/skills/compose
droid-control/skills/desktop-control
droid-control/skills/desktop-use
droid-control/skills/droid-cli
droid-control/skills/droid-control
droid-control/skills/pty-capture
droid-control/skills/showcase
droid-control/skills/terminal-use
droid-control/skills/true-input
droid-control/skills/tuistory
droid-control/skills/verify
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ Terminal, browser, and computer automation for Droids. Record demos, verify beha

**Commands:** `/demo`, `/verify`, `/qa-test`

**Skills:** `droid-control` (orchestrator), `tuistory`, `true-input`, `agent-browser`, `droid-cli`, `pty-capture`, `capture`, `compose`, `verify`, `showcase`
**Skills:** `droid-control` (orchestrator), `terminal-use`, `true-input`, `browser-use`, `desktop-use`, `droid-cli`, `pty-capture`, `capture`, `compose`, `verify`, `showcase`

See [plugins/droid-control/README.md](plugins/droid-control/README.md) for details.

Expand Down
2 changes: 1 addition & 1 deletion plugins/droid-control/.factory-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "droid-control",
"description": "Terminal, browser, and native desktop automation for testing, demos, QA, and computer-use tasks",
"version": "1.0.0"
"version": "1.1.0"
}
35 changes: 19 additions & 16 deletions plugins/droid-control/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ The plugin is designed to keep a droid focused while it operates real software:

- **Low context load:** load the Linux tuistory path without dragging in Windows KVM notes, macOS VM controls, browser automation, and Remotion internals.
- **Evidence-first workflows:** every command starts by making commitments, then ends by verifying the artifact against those commitments.
- **Parallel execution:** before/after captures and render jobs can run in worker droids without sharing session names or output paths.
- **Parallel execution:** independent capture environments and render jobs can run in workers. Shared desktop input stays serialized; session names do not isolate focus.
- **Clear ownership:** commands decide *what* must be produced; atom skills decide *how* to execute their slice.
- **Platform specificity:** OS-specific mechanics live in platform subdocuments, not in global instructions.

Expand All @@ -24,7 +24,7 @@ The three user-facing commands are deliberately thin:
|---|---|
| `/demo` | Turn a PR or feature description into a visible proof story and a video deliverable. |
| `/verify` | Test a claim as an investigator and report whether the evidence confirms or refutes it. |
| `/qa-test` | Drive a terminal, browser, or Electron flow and report step-level pass/fail evidence. |
| `/qa-test` | Drive a terminal, browser, Electron, or native desktop flow and report step-level `PASS` / `FAIL` / `BLOCKED` evidence. |

A command parses arguments into **commitments**: layout, comparison mode, evidence type, video/showcase requirements, keystroke overlays, and any user-specified constraints. Those commitments are not suggestions. The `verify` stage later checks them explicitly.

Expand All @@ -48,7 +48,7 @@ Each atom skill is a self-contained surface the droid reads at a specific point

| Atom type | Skills | Responsibility |
|---|---|---|
| Driver atoms | `tuistory`, `true-input`, `agent-browser`, `desktop-control` | How to drive a class of environment. |
| Driver atoms | `terminal-use`, `true-input`, `browser-use`, `desktop-use` | How to drive a class of environment. `terminal-use` is the terminal entrypoint; it runs the tuistory backend and routes real-terminal proof to `true-input`. |
| Target atoms | `droid-cli`, `pty-capture` | Target-specific shortcuts, launch rules, and byte-capture patterns. |
| Stage atoms | `capture`, `compose`, `verify` | Lifecycle phases with explicit inputs and outputs. |
| Polish atom | `showcase` | Visual presets and cinematic layer guidance. |
Expand Down Expand Up @@ -85,19 +85,20 @@ The parent droid keeps judgment. Workers get exact commands.

| Work | Owner | Reason |
|---|---|---|
| Short interactive desktop task | Parent | One controller owns observation, input, permission waits, and cleanup. |
| Interpret PR / claim / QA goal | Parent | Requires context and judgment. |
| Write the interaction script | Parent | Defines the proof story. |
| Capture baseline and candidate branches | Worker droids | Independent, mechanical, parallelizable. |
| Capture baseline and candidate branches | Workers only for independent environments | A shared desktop must be captured serially. |
| Render Remotion video | Worker droid | Mechanical once props and clips are fixed. |
| Verify commitments | Parent | Requires the original contract and evidence judgment. |

This boundary follows the stage handoffs. Capture workers need resolved `tctl` commands and worktree paths, not PR context. Render workers need a props JSON and clip paths, not a feature explanation.

## Runtime artifact pipeline

![droid-control capture compose verify pipeline](diagrams/capture-compose-verify.svg)
![droid-control terminal comparison pipeline](diagrams/capture-compose-verify.svg)

Editable source: [`diagrams/capture-compose-verify.excalidraw`](diagrams/capture-compose-verify.excalidraw)
Editable source: [`diagrams/capture-compose-verify.excalidraw`](diagrams/capture-compose-verify.excalidraw). The diagram shows the terminal comparison flow, where each branch has an isolated tuistory environment and can run in its own worker; a shared desktop is captured serially by the parent (see Delegation boundaries).

Every workflow starts by creating a run scope:

Expand Down Expand Up @@ -125,14 +126,14 @@ Browser/Electron and native-desktop workflows intentionally do **not** go throug

The compose stage uses the Remotion project in `remotion/` as a single video engine. The droid writes a `Showcase` props JSON; `scripts/render-showcase.sh` handles the mechanical rendering pipeline:

1. Normalize props and choose fidelity.
2. Convert `.cast` recordings through `agg` and `ffmpeg`.
3. Stage clips into Remotion `public/`.
4. Auto-detect `clipDuration` with `ffprobe` when omitted.
5. Render the `Showcase` composition.
6. Clean staged clips and temporary conversion outputs.
1. Accept `.cast`, `.mp4`, and `.webm` clips only; normalize props and resolve fidelity (omitted: side-by-side `inspect`, single `standard`).
2. Convert `.cast` recordings through `agg` and `ffmpeg` at 1x, keeping the recording's timeline.
3. Stage clips as `clip-<index>` inside a directory created under Remotion `public/` for this render only.
4. Set `clipDuration` to the longest clip with `ffprobe`.
5. Render the `Showcase` composition as limited-range `yuv420p`/`bt709` H.264, or one frame with `--still`.
6. Remove that render's staged directory and conversion outputs on exit.

This keeps droids out of the common failure modes: stale files in `public/`, mismatched `clipDuration`, wrong `agg` theme, invalid pixel formats, and hand-written Remotion commands with missing encode flags.
`remotion/src/lib/duration.ts` owns the timeline: the composition applies `speed` once to every clip, the clips run for `clipDuration / speed`, and the content sequence is padded by one crossfade on each side so the clips start after the title crossfade and the final frame is held through the outro crossfade. Total length is `4s title + clipDuration / speed + 3.5s outro`; a shorter clip holds its final frame. This keeps droids out of the common failure modes: two `recording.mp4` inputs overwriting each other in `public/`, concurrent renders deleting each other's clips, mismatched `clipDuration`, casts sped up twice, wrong `agg` theme, invalid pixel formats, and hand-written Remotion commands with missing encode flags.

### Composition surface

Expand Down Expand Up @@ -161,13 +162,15 @@ skills/true-input/platforms/macos.md
skills/pty-capture/platforms/linux.md
skills/pty-capture/platforms/windows.md
skills/pty-capture/platforms/macos.md
skills/desktop-control/platforms/linux.md
skills/desktop-control/platforms/windows.md
skills/desktop-control/platforms/macos.md
skills/desktop-use/SKILL.md
```

A Linux droid reads Linux Wayland instructions. A Windows VM byte-capture task reads Windows KVM instructions. The system does not rely on the droid to skim irrelevant sections correctly.

Desktop-use keeps routine setup, target selection, recovery, and recording rules in one compact entrypoint. It includes a host setup table rather than copied platform manuals. No user-home skill dependency or runtime documentation download is required.

For ordinary desktop tasks, the driver verifies each action and reports directly. Capture/verify stages are loaded for formal evidence deliverables, and compose only when a produced artifact was requested. Explicit GUI-only or cua-only constraints take precedence over Electron's default browser route.

## Extending the plugin

Use the same composition rules when adding capability:
Expand Down
21 changes: 21 additions & 0 deletions plugins/droid-control/CUA-LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2025 Cua AI, Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
6 changes: 5 additions & 1 deletion plugins/droid-control/NOTICES.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Third-Party Notices

This plugin depends on several third-party tools and libraries. They are not bundled -- each is installed separately by the user. Their respective licenses apply at the point of installation and use.
This plugin depends on several third-party tools and libraries. Executables are installed separately by the user.

## Desktop automation documentation

- **[Cua Driver](https://github.com/trycua/cua)** — desktop-use guidance is adapted from Cua under the [included MIT license](CUA-LICENSE.md). Driver code and binaries are not bundled.

## Video rendering

Expand Down
20 changes: 12 additions & 8 deletions plugins/droid-control/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Terminal, browser, and computer automation plugin for Droids.

Droids can read and write code. This plugin lets them *operate* it: launch apps, type commands, click buttons, record what happens, and produce polished evidence. No human hands required.
Droids can read and write code. This plugin lets them *operate* it: launch apps, type commands, click buttons, record what happens, and produce evidence. OS permission grants and consequential actions still require the appropriate user or host authorization.

## What you get

Expand All @@ -12,7 +12,7 @@ Droids can read and write code. This plugin lets them *operate* it: launch apps,
/demo pr-1847
```

Droid reads the PR, scripts the interactions that prove the change works, records both branches in parallel, and renders a side-by-side comparison video. Use Factory presets for cinematic warmth or macos/minimal presets for clean utilitarian demos.
Droid reads the PR, scripts the interactions that prove the change works, records both branches (in parallel when each has its own isolated terminal or browser environment), and renders a side-by-side comparison video. Use Factory presets for cinematic warmth or macos/minimal presets for clean utilitarian demos.

**Verify a behavior claim:**

Expand Down Expand Up @@ -48,6 +48,10 @@ Or use the `/plugins` UI: Browse tab, select droid-control, install.

Then open a Droid session and run `/demo`, `/verify`, or `/qa-test`.

For ordinary desktop work, ask directly: **“Using only cua, open Calculator and compute 17 × 23.”** Desktop-use runs the observe/act/verify loop without loading video-production stages.

The [desktop-use skill](skills/desktop-use/SKILL.md) includes setup and operating guidance. Install the `cua-driver` executable if missing; no separate Cua skill installation is needed. Installed driver versions and Wayland compositors may support different capabilities.

## Commands

### `/demo`
Expand All @@ -69,7 +73,7 @@ Runs automated QA against terminal CLIs, web apps, or Electron apps. Accepts a U
1. **Commands** parse user intent into commitments.
2. **The orchestrator** routes by target, stage, and artifact needs.
3. **Atom skills** provide only the mechanics needed right now: drivers, target patterns, capture, compose, verify, and showcase polish.
4. **Workers** handle mechanical capture/render jobs while the parent droid keeps planning and verification context.
4. **Workers** handle independent capture/render jobs. The parent keeps short interactive desktop tasks, including observations, input, permission waits, and cleanup.
5. **Verify** checks the final evidence against the original commitments.

For the full rationale and runtime pipeline, see [`ARCHITECTURE.md`](ARCHITECTURE.md).
Expand All @@ -78,18 +82,18 @@ For the full rationale and runtime pipeline, see [`ARCHITECTURE.md`](ARCHITECTUR

The compose stage uses [Remotion](https://www.remotion.dev/) for video compositing. Presets provide window chrome, spacing, palettes, backgrounds, particles, noise, color grading, configurable transitions (`motion-blur`, `flash`, `whip-pan`, `light-leak`, `glitch-lite`), zooms, spotlights, callout annotations, keystroke overlays, section headers, and syntax-highlighted code annotations.

The `render-showcase.sh` helper owns the full pipeline: `.cast` conversion via `agg`, clip staging, duration detection, Remotion rendering, and cleanup.
The `render-showcase.sh` helper owns the full pipeline: `.cast` conversion via `agg`, per-render clip staging, longest-clip duration, Remotion rendering (or a `--still` preview), and cleanup. Playback `speed` is applied once by the composition to every clip.

## Prerequisites

| Stage | Platform | Required |
|---|---|---|
| tuistory | All | `tuistory`, `asciinema`, `agg` |
| terminal-use (tuistory) | All | `tuistory`, `asciinema`, `agg` |
| true-input | Linux/Wayland | `cage`, `wtype`, Wayland terminal |
| true-input | Windows (KVM) | `libvirt`, `qemu`, KVM VM with SSH |
| true-input | macOS (QEMU) | `qemu`, `socat`, macOS VM with SSH |
| agent-browser | All | `agent-browser` |
| desktop-control | All | `cua-driver` |
| browser-use | All | `agent-browser` |
| desktop-use | All | `cua-driver` |
| compose | All | `ffmpeg`, `ffprobe`, `agg` |
| showcase | All | Node.js (>= 18), Chrome/Chromium |

Expand All @@ -103,4 +107,4 @@ curl -fsSL https://raw.githubusercontent.com/trycua/cua/main/libs/cua-driver/scr
cd plugins/droid-control/remotion && npm install # Remotion video rendering
```

Only install what you need for your use case. Terminal demos need tuistory, asciinema, agg, and ffmpeg. Web/Electron automation just needs agent-browser. Native desktop GUI automation just needs cua-driver.
Only install what you need, with approval. Terminal demos need tuistory, asciinema, agg, and ffmpeg. Web/Electron automation defaults to browser-use; an explicit cua-only/native-input request uses desktop-use instead. Native desktop automation needs cua-driver plus the graphical session and OS permissions reported by its preflight. Recording and rendering have additional dependencies; they are not required for ordinary desktop tasks.
Loading
Loading