three-kit

Verification

How to see and measure. Screenshots are the evidence for every visual claim; numbers come from the console helpers.

Screenshots

Drive the studio in a browser you can script: a browser pane your agent drives, if it has one, or a headless one (agent-browser, Playwright). Run one browser session at a time: parallel ones saturate the CPU. The page saves its own canvas with saveShot(path), through three-studio serve, so the PNGs land on disk where three-studio diff and montage can use them.

Once per pass:

  1. Pick a pass folder in the project (plans/<object>/pass-<n>/, or a scratch folder when nothing should be committed) and start the receiver on it in the background:

    npx @zkmake/three-studio serve <pass folder>   # 127.0.0.1:8787; bunx / pnpm dlx work too

    When it says the port is taken (another pass is shooting), run it with --port <free port> and add &shots=<that port> to every studio URL below.

  2. Start the app’s dev server the project’s way and open the studio at its area and view (…/studio.html?windmill&view=play). Set a fixed viewport (1200 × 800) so every shot of a pass has one size.

Per shot, in the page:

await saveShot("before-play.png");
// "/abs/…/pass-1/before-play.png  14 calls · 4,812 tris"

saveShot draws a frame and reads it in the same task, so it works in a hidden or background tab where requestAnimationFrame never fires. Paths are relative to the receiver’s folder (or absolute inside it). studio.setView("close") moves the camera without a reload; switching area or variant is a navigation.

Before and after

Black frames

For passes that add new kinds of geometry to anything that moves or glows. Needs a visible browser window (headless ones have not reproduced black frames) and the app itself, not the studio, with its post-processing on.

  1. Install three-audit’s helpers on the app’s scene in dev, with the renderer (installAuditHelpers(scene, { renderer })), if the app doesn’t already.
  2. Open the app, start play so the object moves on screen.
  3. await blackFrames(10): { frames, blackFrames } over the next 10 s.
  4. Pass: blackFrames empty over a few hundred frames. A positive control (temporarily restoring a suspect) proves the setup catches them.

Checks

The project’s own typecheck, lint, tests and build, taken from package.json scripts (or the project’s hooks, where it runs them itself), all green before the report.

More of model-pass