UNPKG

@blundergoat/goat-flow

Version:

AI coding agent harness and local dashboard for Claude Code, OpenAI Codex, Google Antigravity, and GitHub Copilot - setup audits, guardrails, structured skills, deny hooks, and persistent learning loops.

284 lines (194 loc) 17.1 kB
--- goat-flow-reference-version: "1.12.1" --- # Page Capture Reference Use this when a task requires visiting a list of pages in a real browser, capturing a screenshot of each, and emitting a markdown record per page. Typical triggers: documenting new pages after a feature ships, capturing a UI baseline before a release, recording before/after evidence across multiple pages, or producing an audit-style page snapshot. Page Capture is the durable batch workflow: scripted, repeatable, evidence-grade. `browser-use` is the right tool for one-off mid-task observation. Playwright (any integration path) plus this reference is the right tool for batch capture across multiple pages with load verification, especially when authentication or framework-specific patterns matter. ## Availability Check Batch page capture requires Playwright. Playwright is a browser automation library, not a protocol - MCP is one way to use it, but running a Python or Node script is equally valid. Check these tiers in order and use the first that works: **Tier 1 - Playwright MCP** (best: native tool calls, no script needed) Check if these tools are callable: `browser_navigate`, `browser_screenshot`, `browser_snapshot`, `browser_evaluate`, `browser_resize`, `browser_wait_for`, `browser_console_messages`, `browser_network_requests`. If available, use them directly - the per-page loop in Step 2 maps to these tool calls. **Tier 2 - Project-local Playwright** (good: carries project config, fixtures, and browser version expectations) Check if the project has Playwright installed as a dependency: ```bash node -e "require.resolve('@playwright/test')" 2>/dev/null && echo "ok" # or: npm ls @playwright/test playwright --depth=0 npx playwright --version ``` For JS/TS projects, prefer this tier over the Python wrapper - project-local Playwright may carry storage-state conventions, browser version pins, or test fixtures that the generic Python path won't have. The agent writes a Node.js capture script and executes it. **Tier 3 - Python Playwright** (good: works for any coding agent that can run shell commands) ```bash browser-use-python -c "from playwright.sync_api import sync_playwright; print('ok')" # or the standard Playwright CLI if the venv wrapper is not present: python -m playwright --version ``` If a Python venv exposes Playwright through a `browser-use-python` wrapper (some environments place one on `PATH`, e.g. at `~/.local/bin/browser-use-python`), check it before declaring Playwright unavailable. If no Python Playwright path is available, offer to install it with `pip install playwright && python -m playwright install chromium`; never install it without approval. The agent writes a Python capture script using `playwright.sync_api`, executes it, and reads the output. See "Writing a capture script" below. **Tier 4 - browser-use CLI** (downgrade: less control, missing console/network capture) ```bash command -v browser-use && browser-use doctor ``` Only use browser-use for batch capture if no Playwright path (MCP, Node, or Python) is available AND the user explicitly accepts the downgrade. Ask: "No Playwright path found. Use browser-use CLI instead? Console error capture will be unavailable." Do not silently fall back. Use `browser-use open`, `browser-use screenshot`, `browser-use state`. This path cannot capture console errors - mark captures with `Console errors: not captured (browser-use CLI)` and note reduced evidence quality in the index. **Tier 5 - Manual fallback** (last resort: human provides evidence) See "Fallback When No Playwright Path Is Available" at the bottom. **If all automated tiers fail,** state which checks were run and their output. Do not silently fall back to a less capable tool. ## Intent A coding agent uses page capture to create durable, repeatable browser evidence across known pages. The output is not a screenshot gallery; it is an evidence bundle with one markdown record per page, a screenshot path that resolves on disk, load verification, console-error accounting, and an index that makes partial failures visible. ## Boundary | Job | Tool | Reference | |---|---|---| | Single observation, mid-skill, agent decides what to look at | `browser-use` CLI | `browser-use.md` | | Visit N known pages, screenshot each, emit structured MD | Playwright (any integration) | this file | | Test-suite-driven evidence (assertion -> screenshot -> record on fail) | Playwright Test + custom reporter | not in goat-flow; see Playwright reporter docs | | Crawl/discover pages an agent hasn't seen | `browser-use` with agent loop | `browser-use.md` | If the task fits row 1 or row 4, stop and load `browser-use.md` instead. If the task fits row 3, document it as a project-level test-runner concern, not a goat-flow workflow. ## Writing a Capture Script (Tier 2/3) When using Python or Node Playwright, the agent writes and executes a capture script. Minimal pattern (Python): ```python from playwright.sync_api import sync_playwright with sync_playwright() as p: browser = p.chromium.launch(headless=True) ctx = browser.new_context( viewport={"width": 1280, "height": 800}, storage_state="path/to/state.json" # omit if no auth ) page = ctx.new_page() errors = [] page.on("console", lambda m: errors.append(m.text) if m.type == "error" else None) page.goto(url) page.wait_for_selector(".expected-element", timeout=10000) page.screenshot(path="screenshots/slug.png", full_page=True) title = page.title() # write MD record with title, url, viewport, timestamp, len(errors) browser.close() ``` Adapt to the project's needs (SPA navigation, framework wait conditions, auth flows). The evidence requirements are the same regardless of implementation: consistent viewport, navigate each page, wait for a content anchor, screenshot, collect console error count, write one MD record per page, write an index, verify screenshots exist on disk. **Storage state by tier:** - Tier 1 (MCP): context-level configuration, tool-dependent - Tier 2 (Node): `browser.newContext({ storageState: "path/to/state.json" })` - Tier 3 (Python): `browser.new_context(storage_state="path/to/state.json")` - Tier 4 (browser-use): `browser-use --profile <name>` if supported by version ## Project Reference Pattern This file is generic by design. Project-specific knowledge does NOT live in `.goat-flow/skill-docs/` - that directory is reserved for goat-flow's own references. Project knowledge splits across two layers: | Layer | What it holds | Where it lives | |---|---|---| | Project reference | How-to playbook for driving the project's app - auth flow, framework gotchas, selectors, viewport conventions | `.goat-flow/learning-loop/patterns/<project>-playwright.md` (vendor-neutral, readable by any coding agent) | | Project learning loop | Recurring traps with file evidence, dated lessons from incidents, repeatable patterns | `.goat-flow/learning-loop/footguns/<category>.md`, `.goat-flow/learning-loop/lessons/<category>.md`, `.goat-flow/learning-loop/patterns/<category>.md` | A project reference typically covers: - Auth flow specifics - login URL, 2FA, storage state path - Framework gotchas - debug toolbars to hide, JS init waits, dropdown libraries that bypass native events, editor models that hide their value - Selector conventions - data attributes, class patterns, ID conventions - Viewport conventions if the project tests at non-default sizes - Pages or routes to exclude - admin, destructive, slow, flaky A goat-flow skill loading this `page-capture.md` reference should also: 1. Detect and load any project reference at the conventional path 2. Run the standard footgun grep against `.goat-flow/learning-loop/footguns/` for the target area before capture begins ## Capture Workflow ### Step 0 - Intake Confirm before proceeding. Ask only what's missing. 1. **Page list** - explicit URLs, manifest path, or a diff to derive from 2. **Auth** - required? If yes: storage state path, login flow, or none 3. **Viewport** - default `1280x800` desktop unless stated; `390x844` for mobile checks 4. **Output dir** - default: `.goat-flow/logs/sessions/<date>-<label>/` (gitignored, local-only). Screenshots go in a `screenshots/` subdirectory. **NEVER write captures to the project root, `captures/`, or any tracked directory.** Page captures are session artifacts, not committed project files. If the user specifies a different output dir, verify it is gitignored before writing 5. **Project reference** - does one exist at `.goat-flow/learning-loop/patterns/<project>-playwright.md`? Read it now if so. Also run the footgun grep for the target area against `.goat-flow/learning-loop/footguns/` per `skill-preamble.md` 6. **Playwright tier** - run the availability check; record which tier will be used If any answer is unclear, ask. Do not guess URLs or auth flow. ### Step 1 - Pre-flight - Set viewport once. Consistency across captures matters; do not resize per page. - If auth is required: - Storage state path -> load it before navigating (see per-tier instructions above) - Login flow -> run it once at the start, capture storage state, reuse for the rest of the run - Never paste credentials, tokens, or session IDs into MD output ### Step 2 - Per-Page Loop For each URL: 1. **Navigate** - load the URL 2. **Verify load** - wait for an anchor before screenshotting. In order of preference: - Wait for expected text (best - anchored to content) - Wait for CSS selector (good - anchored to structure) - Network idle polling (fallback) - Fixed time delay (last resort; mark capture's load as INFERRED) 3. **Apply project reference fixes** - hide debug toolbars, dismiss banners, wait for app-specific JS init, anything documented in the project reference 4. **Screenshot** - full page, save to `<output_dir>/screenshots/<slug>.png`. Slug is derived from the URL path (strip query params and fragments; use param values only if two URLs share the same path). Collisions get a numeric suffix 5. **Capture metadata** - URL, page title, viewport, UTC ISO 8601 timestamp, console error count (count only, do not paste contents). If the integration tier cannot capture console errors, note `not captured (<tier>)` instead of omitting the field 6. **Write MD record** to `<output_dir>/<slug>.md` using the output format below If verification fails (timeout, 4xx/5xx, console error class) - do NOT skip silently. Record the page with status `failed` and the failure reason. Continue to the next page. ### Step 3 - Index After all pages processed, write `<output_dir>/index.md`: ```markdown # Page Capture - <run_label> **Captured:** <UTC timestamp> **Viewport:** <W>x<H> **Auth:** authenticated / unauthenticated **Tool:** <tier used, e.g. "Python Playwright via browser-use-python" or "Playwright MCP"> **Pages:** <N total>, <N succeeded>, <N failed> ## Pages | # | Page | Status | Record | |---|------|--------|--------| | 1 | <title> | ok / failed | [<slug>.md](./<slug>.md) | ## Failures <list each failure with URL and reason, or "None"> ``` ## Verification Gate After the per-page loop and index step, verify before claiming the run complete: - Every URL in the input list has a corresponding MD file or a recorded failure - Every screenshot path in every MD file resolves to a real file on disk - Index file exists and lists every record - No credentials, tokens, or PII appear in any MD file (grep the output dir before closing) State the count: "Captured N/M pages successfully. Index at `<path>`." If any verification step fails, state which and stop. This is the Proof Gate from `skill-preamble.md` applied to the capture run - every claim ("captured", "succeeded") must be substantiated by a file on disk in this session, not by a tool call return value. ## Diff-Driven Mode When the task is "capture pages affected by these changes," map diff to pages via a manifest: - Project ships a manifest mapping routes to source files (e.g. `<project>-playwright.config` listing `{ route, source_paths }`) - Read `git diff` (or PR-derived diff via `gh pr diff`) - Intersect changed source paths with manifest entries - Capture matching routes; report unmatched changed paths so the manifest can be updated Heuristic mode (infer routes from changed file paths without a manifest) is possible but lower confidence. Mark such captures' page selection as INFERRED until a human confirms route coverage. ## Output Format One MD file per page: ```markdown # <Page title> **URL:** <url> **Captured:** <UTC ISO 8601> **Viewport:** <W>x<H> **Status:** ok / failed **Load verification:** text / selector / network-idle / time (INFERRED) **Console errors:** <count> ![<page title>](./screenshots/<slug>.png) ## Notes <one or two sentences describing what's on the page - visible headings, primary action, anything notable. OBSERVED only. Leave blank if nothing noteworthy.> ## Failure <only present when status: failed. Include the reason (timeout, 4xx, console error class) and the wait condition that didn't resolve. No stack traces, no full error bodies.> ``` ## Discipline - **Output location:** all capture artifacts (MD records, screenshots, index) MUST go inside `.goat-flow/logs/sessions/<date>-<label>/`. Never create a `captures/`, `screenshots/`, or any other directory at the project root. Page captures are gitignored session artifacts. - Screenshot evidence is OBSERVED. Any post-capture interpretation in the Notes section is INFERRED unless mapped to a `file + semantic anchor` or repeatable reproduction. - Failures are recorded, never skipped. A run that captured 8 of 10 pages with 2 failures is more honest than a run that silently dropped 2. - Read-only navigation. Do not click buttons that mutate state, submit forms, or follow destructive links unless the task explicitly requires it (e.g. capturing a confirmation page after submission). - Per-run consistency: viewport, auth, browser version stable across all pages in the same run. Different runs may legitimately differ; within a run they should not. ## Security Cautions - Never paste cookies, tokens, auth headers, session IDs, or credential-bearing URLs into MD output or screenshots' surrounding text - Console output may contain stack traces with secrets - record error counts and sanitised class names, never raw bodies - Network requests may contain auth headers - when summarising, give method, route shape, status; never headers or bodies - Screenshots may render sensitive content (PII, account data, internal IDs) - save to a temporary path until reviewed; only move to a shared location after review - For healthcare or regulated contexts, use synthetic accounts; never capture pages logged in as a real user ## Fallback When No Playwright Path Is Available If none of the Playwright tiers (MCP, Python, Node) are available, capture equivalent evidence manually: - Manual screenshot via OS or browser DevTools - Page title and headings via DevTools Console copy - Console errors via DevTools Console export - Network requests via DevTools Network tab -> HAR export Ask the user to provide this evidence. Manual evidence follows the same classification: raw captures are OBSERVED, interpretations are INFERRED. Note in the index that the run was manual; reproducibility drops and that should be visible. ## Troubleshooting - **`command -v playwright` fails but Playwright is installed** - check `browser-use-python -m playwright --version` and `npx playwright --version`. The global binary may not exist even when the library is usable through a wrapper or package manager - **Page seems loaded but screenshot is blank** - JS init not complete. Wait for a known late-rendered element from the project reference, or wait for a network idle window - **Screenshot crops the modal or content** - viewport too short. Resize to `1280x800` or larger and re-capture; document the size used - **Auth state not persisting between pages** - storage state file path wrong, or login session has IP/UA binding. Recapture storage state at run start - **Console errors on every page** - likely third-party (analytics, tracking). Filter by source URL before deciding the page failed; document filter in the project reference - **Same slug for two URLs** - append `-2`, `-3` deterministically. Do not silently overwrite - **Diff-driven mode captures wrong pages** - manifest is stale. Surface the unmatched changed paths and ask the user to update the manifest before relying on the run ## Related References - `browser-use.md` - single-observation probe; load this instead when the task is mid-skill spot-check - `skill-preamble.md` - Proof Gate, OBSERVED/INFERRED tagging, evidence discipline that all goat-flow output inherits - `skill-conventions.md` - footgun and lesson entry shapes for project-level traps that recur with evidence - Project Playwright reference (e.g. `.goat-flow/learning-loop/patterns/<project>-playwright.md`) - framework gotchas, auth, selectors. Vendor-neutral path so any coding agent can read it.