master
John Lauer docs/contract: golden fixtures recorded from the Node build 2.0.399 for the Rust port 71c0e87 1mo ago
{
  "_hint": "Opened in the BACKGROUND (behind the user's windows, did NOT steal focus). This is the HARD default so pup never disrupts the user's main work. It is FULLY drivable here: pup_screenshot / pup_eval / pup_navigate all work while it stays hidden. ONLY bring it to the user's screen if they EXPLICITLY want to WATCH (a demo, a recording, a \"show me\") — pass foreground:true on open (or call pup_raise_os_window). Sizing alone does NOT foreground anymore. LONG MULTI-STAGE TASK in this window (crawling a site, login->search->download loops, batch harvesting)? Paint the taskbar progress bar so the user sees the work: pup_progress {mode:\"indeterminate\", note:\"crawling ti.com\"} to start, {mode:\"value\", value:40, note:\"12/40 datasheets\"} as stages advance, {mode:\"off\"} when done. A single quick page open does NOT need it — your call. Full guidance: the pup-progress skill. PROFILE: this window uses pup's durable shared \"adom-you\" profile — logins, cookies and localStorage are SAVED and SHARED across ALL pup windows, so a site you sign into once stays signed in everywhere and app state (localStorage) persists between windows. This is deliberate. For a PRIVATE throwaway window instead, reopen with {isolated:true}. POWER: NORMAL window on Chrome's own power behaviour — it throttles when occluded, so it costs nothing sitting in the background. Right default for driving, scraping and screenshots. If you need to RECORD VIDEO of this window while it is occluded, a normal window only yields ~1-2 fps: reopen with pup_open_window {highFps:true} for full-rate background frames. highFps is leased (default 20 min) and auto-downgrades when idle, so it can never flatten the user's battery. Driving chrome-for-testing (cache) — C:\\Users\\azureuser\\.cache\\puppeteer\\chrome\\win64-148.0.7778.97\\chrome-win64\\chrome.exe, in a FRESH isolated profile (the user's real tabs/logins are untouched). Available on this machine: chrome-for-testing(cache), edge(system). Default is chrome-for-testing (auto — cached from a prior successful launch). To switch the browser pup drives: pup_use {browser:\"chrome\"|\"edge\"|\"cft\"|\"auto\"}. To install & pin full Chrome for Testing: pup_use {browser:\"cft\"} (fetches ~150 MB once, then every open uses it) or pup_prewarm.",
  "_next": [
    "pup_screenshot {} — screenshot YOUR window (no ids: pup resolves your --ai-thread name to your window)",
    "pup_reload {} — reload it (e.g. after you publish or rebuild something it shows)",
    "pup_my_windows {} — full state of everything your thread owns: windows, tabs, urls, titles",
    "pup_open_window {\"url\":\"...\"} — another page = another TAB in your same window",
    "pup_raise_os_window {\"foregroundReason\":\"...\"} — bring it onto the user's screen (gated)",
    "Windows open MAXIMIZED already. NEVER hunt hwnds (desktop_find_window / desktop_set_window_state) for a pup window — pup verbs already know your window.",
    "pup_screenshot {} captures the PAGE (CDP, pixel-perfect, works in background — the shot you want 99% of the time). Only when you need the browser CHROME in frame (tab strip, toolbar icons): pup_window_info {} hands you this window's hwnd for desktop_screenshot_window — no searching, ever."
  ],
  "_verifyRender": "VERIFY WHAT YOU JUST PUT ON SCREEN — do not assume it rendered. ok:true means the NAVIGATION succeeded; it says NOTHING about whether the page actually painted. Take a screenshot and READ the image: `adom-bridge-cli --ai-thread \"<your thread>\" pup_screenshot {\"sessionId\":\"contract-fx\"}` — it returns a real PNG path you can open. Look for: a blank or white page, an unstyled flash of plain HTML (CSS never loaded), a stack trace or framework error overlay, missing images, a broken or overlapping layout, content cut off past the fold, a dev-server \"Cannot GET /\" page, or the wrong build entirely. If it is wrong: fix the source, `pup_reload`, and screenshot AGAIN — ralph-test that loop until the render is genuinely correct, rather than reporting success after one open. If the viewport is too small to judge, pup_set_viewport first; for a long page use pup_screenshot {fullPage:true}. Showing the user a screenshot of their own working app is also the fastest way to prove it works.",
  "active": true,
  "activeTabId": "tab-1",
  "ageMinutes": 0,
  "aiThread": "pup-bridge",
  "availableBrowsers": [
    "chrome-for-testing(cache)",
    "edge(system)"
  ],
  "background": "backgrounded",
  "browser": {
    "executablePath": "C:/Users/azureuser/.cache/puppeteer/chrome/win64-148.0.7778.97/chrome-win64/chrome.exe",
    "kind": "chrome-for-testing",
    "source": "cache"
  },
  "defaultBrowser": {
    "forced": false,
    "kind": "chrome-for-testing",
    "pendingInstall": false,
    "source": "cache"
  },
  "defaultPermissionsApplied": true,
  "defaultPermissionsCount": 33,
  "defaultPermissionsNote": "full browser permissions pre-granted (clipboard, camera, geolocation, window-management, ...) — pup_describe has the exact list",
  "downloadPath": "C:/Users/azureuser/Downloads",
  "downloadsEnabled": true,
  "durationMs": 1362,
  "emulatedViewport": null,
  "errorCount": 0,
  "flash": "none",
  "flashCount": 0,
  "highFps": false,
  "lastAgentUpdate": null,
  "lastForeground": null,
  "ok": true,
  "overlay": "none (not yet applied)",
  "owner": "pup-bridge",
  "ownerSource": "caller-identity",
  "pitfalls": [
    "sessionId is OPTIONAL: omit it and your thread gets its OWN window (keyed on your --ai-thread name; later opens become tabs in it). Pass one only for a deliberate separate window — it is then your handle for every later call",
    "profile defaults to the durable shared 'adom-you' profile (logins/localStorage persist + are shared across all pup windows); isolated:true for a private throwaway — omit it for a plain \"open in pup\"",
    "sessionIds are SHARED across all AI threads on this desktop — a generic id (\"wiki\", \"test\") may collide with another thread's window and navigating it away steals their work. Use a task-prefixed sessionId + pass owner:\"<your-task>\" so pup can protect it",
    "reusing an existing sessionId with a new url NAVIGATES that window — check pup_status (shows owner per window) first if unsure"
  ],
  "placement": "background",
  "profile": "adom-you",
  "progress": {
    "confidence": "measured",
    "elapsedSec": 1.3,
    "estimatedSec": 11,
    "etaSec": 0,
    "percent": 100,
    "phase": "open_window",
    "startKind": "warm",
    "stepLabel": "Opened the window in the running browser"
  },
  "progressBarCount": 0,
  "progressBarMs": 0,
  "related": [
    "pup_navigate",
    "pup_list_windows",
    "pup_close_window"
  ],
  "renderCheck": {
    "bodyChars": 129,
    "elements": 5,
    "httpStatus": 200,
    "ok": true,
    "signals": [],
    "title": "Example Domain"
  },
  "restoredTabsClosed": 0,
  "reused": null,
  "sessionId": "contract-fx",
  "size": null,
  "status": "ok",
  "tabCount": 1,
  "title": "Example Domain",
  "url": "https://example.com/",
  "window": "contract-fx",
  "windowEtiquette": "background"
}