Skip to main content

The test suite

bun run test runs the integration suite on the GPU test renderer. The real app is mounted, painted and hit tested, so the tests drive the same tree the user sees.

Two things the test renderer cannot do

  • Exit animations never settle. The renderer only paints on demand, so an AnimatePresence exit keeps the element in the tree forever. Assert on the painted state when a row is removed.
  • A sliding panel has to settle before it is clicked. The automation clicks the last painted bounds, so freeze the clock, advance it, and wait until the element stops moving.

The CI

.github/workflows/ci.yml runs: The test job is not on Linux: the native test renderer only ships with the GPUIX builds that carry the test-support feature, and on Linux the suites skip themselves. integration.yml drives source and compiled windows on Windows, checks intentional close does not restart the packaged cockpit, and runs the browser preview smoke. release.yml packages and smoke-tests the compiled cockpit and engine on Windows, macOS and Linux, then extracts the actual archive and runs its binaries outside the checkout. The engine suite also tests incomplete, corrupt and inconsistent release artifacts against the publication gate. Tag builds publish signed release provenance and delta manifests only after all platforms pass. The aggregate verify complete release job downloads all three platforms and delta chunks and checks the actual publication inputs on every PR, without publishing a release. The install is bun install --frozen-lockfile, so the lockfile and package.json cannot drift apart. .bun-version pins Bun for the local runtime and for CI.

Driving the app

@gpuix/react/automation gives a Playwright shaped API over the GPU renderer. It drives the real input pipeline, not a DOM.
GPUIX_BACKGROUND=1 opens the window without taking the keyboard. Use it whenever you drive the app yourself. screenshot.ts uses an isolated HIROSHI_HOME and temporary workspace, captures the current controls, closes its window and stops its daemon in cleanup. It needs a desktop session and GPU. Windows hosted runners support real window tests; macOS hosted runners do not provide a desktop session.

Browser preview

bun run web:dev serves the preview at http://127.0.0.1:4173 (override PORT). bun run web:build only checks the bundle. web-entry.tsx mounts the published GPUIX Wasm renderer with demo conversations and no engine. The native window dragging and geometry adapters are replaced with no-ops; OS window controls are hidden. Workspace operations and model calls need the desktop engine. The preview has been verified in headless Chrome with software WebGPU on Windows. bun run test:web waits for the rendered canvas keyboard target, sends a demo prompt through GPUIX automation, asserts the reply and captures screenshots/browser-preview.png. It creates its own Chrome profile and removes it afterward. Set HIROSHI_CHROME for a Chrome/Chromium executable elsewhere; the default is the standard Windows Chrome install path. Hosting elsewhere must preserve the server’s COOP/COEP headers for Wasm shared memory.

Resource limits on Windows

Run builds and automated tests sequentially through scripts/run-guarded.ps1:
The guard assigns a suspended child to a Windows Job Object before it starts. The kernel caps total process count and committed memory, including detached descendants. The guard logs peak tree memory and free system RAM every ten seconds, aborts at the free-memory floor or timeout, and kills the whole tree on exit. It refuses to start when free memory is already low. Desktop integration uses the same 12-process/3072 MB cap with a 300-second deadline; builds use 3 processes/2048 MB. Do not put app launches inside retry loops.

The rules that matter

The repository carries its own rules, in AGENTS.md and in the hiroshi-gpuix skill. The ones that bite most often:
  • A drag region needs pointerEvents: 'auto' and the three mouse handlers.
  • An unfilled div has no hitbox, so an empty region is dead.
  • There is no zIndex; the tree order is the stacking order.
  • A <text> with several children wraps. Use one template literal.
  • Never use Unicode symbols for icons; they resolve to Windows emojis. Use the SVG set in assets/icons/.