---
name: visual-review-agent
description: Create or maintain the repository visual review agent that runs after frontend-screenshots, reads Playwright HTML/DOM snapshots plus a live reference page, calls NVIDIA through an OpenAI-compatible chat API, and comments on pull requests. Use when the user asks to set up or repair the current agentic PR visual review flow; do not use for screenshot capture alone.
---

# Visual Review Agent

Use this skill to create or maintain the agentic pull request review flow used by this repository.

This skill assumes the screenshot pipeline already exists or will be created with the `frontend-screenshots` skill. The visual review agent depends on the `frontend-screenshots` artifact containing PNG screenshots and sibling `.html` DOM snapshots for each captured page/viewport.

## Goal

Create a GitHub Actions flow that:

- runs only after the **Frontend Screenshots** workflow completes;
- checks that the pull request has the configured review label, normally `visual-review`;
- downloads the `frontend-screenshots` artifact from that completed run;
- reads the per-page `.html` DOM snapshots generated by Playwright;
- captures a comparable HTML/DOM snapshot from a real reference URL configured through `FRONTEND_MOKUP_URL`, `FRONTEND_MOCKUP_URL`, or a `visual-reference: https://...` line in the pull request body;
- asks an NVIDIA-hosted model for a brief, specific review using only text/HTML context;
- creates or updates a single pull request comment identified by a stable HTML marker;
- writes the same review to the GitHub Actions job summary when GitHub cannot comment.

Do not send images to the model in this flow. The current implementation is HTML/DOM based to avoid free endpoint limits around multimodal requests and image count.

## Required Files

Create or update:

- `.github/workflows/visual-review.yml`;
- `.github/scripts/visual-review.mjs`;
- README documentation for enabling the workflow.

If `frontend-screenshots` does not yet generate `.html` DOM snapshots next to each PNG, update that pipeline first with the `frontend-screenshots` skill. The agent should not try to infer DOM from PNGs.

## Workflow Shape

The visual review workflow should be triggered by `workflow_run` for the screenshot workflow:

```yaml
on:
  workflow_run:
    workflows: ["Frontend Screenshots"]
    types: [completed]
```

Use `workflow_run` so the visual review job runs in the base repository context and can comment on pull requests without checking out or executing untrusted pull request code.

The workflow should:

- stop unless the triggering screenshot workflow concluded successfully;
- resolve the pull request from `workflow_run.pull_requests`, with a commit-associated-PR lookup fallback;
- check out the repository default branch;
- set up Node using the current project version, normally Node 24;
- install `web` dependencies and Chromium because the script uses Playwright to capture the reference DOM;
- download artifact `frontend-screenshots` from `github.event.workflow_run.id`;
- run `node .github/scripts/visual-review.mjs`.

Use these permissions:

```yaml
permissions:
  actions: read
  contents: read
  issues: write
  pull-requests: write
```

Use the repository environment expected by this project:

```yaml
environment: SplitIt Env
```

Do not give broader permissions than required.

## GitHub Configuration

Document these values in the README. It is fine that the user creates them in GitHub manually.

Required secret:

```text
NVIDIA_API_KEY
```

Required or defaulted reference URL:

```text
FRONTEND_MOKUP_URL=https://...
```

Support both spellings in the script:

```text
FRONTEND_MOKUP_URL
FRONTEND_MOCKUP_URL
```

Optional repository variables:

```text
NVIDIA_BASE_URL=https://integrate.api.nvidia.com/v1
NVIDIA_MODEL=meta/llama-3.2-11b-vision-instruct
VISUAL_REVIEW_HTML_MAX_CHARS=28000
VISUAL_REVIEW_VIEWPORTS=desktop
```

The label should default to:

```text
VISUAL_REVIEW_LABEL=visual-review
```

## Agent Script Behavior

The script should be plain Node ESM and should not require third-party runtime packages beyond the frontend's existing Playwright install.

Keep these behaviors:

- fail early when required environment variables are missing, except the reference URL can be missing long enough to post a useful PR comment;
- log timestamped progress with a `[visual-review ...]` prefix;
- clean URLs copied from Markdown by removing trailing punctuation;
- verify that the PR has the configured label before spending model tokens;
- list PNGs from `SCREENSHOTS_DIR` only to select the relevant page group, then read the sibling `.html` files;
- select screenshots using PR-title tokens and aliases such as `login`, `signin`, `register`, `signup`, `registro`, and `registrarse`;
- if title matching fails, prefer the first non-home page group;
- respect `VISUAL_REVIEW_VIEWPORTS`, defaulting to `desktop`;
- capture reference DOM for the same selected viewport set;
- build a text-only model prompt from the reference DOM snapshots and Playwright DOM snapshots;
- cap prompt size with `VISUAL_REVIEW_HTML_MAX_CHARS`;
- call `${NVIDIA_BASE_URL}/chat/completions` with `Authorization: Bearer ${NVIDIA_API_KEY}`;
- retry transient GitHub and NVIDIA failures with logs and bounded timeouts;
- tolerate non-standard model payload shapes only for final text extraction, never publish reasoning fields;
- do not parse the model output into JSON, tables, or forced categories;
- publish the model's final text directly under the normal review comment heading.

The NVIDIA request must be text-only:

```js
messages: [
  {
    role: "user",
    content: promptText,
  },
]
```

Do not include `image_url` parts. Do not use a separate `system` message unless the selected NVIDIA endpoint explicitly supports it with the chosen payload shape.

## DOM Snapshot Requirements

For the reference page, use Playwright to load the configured URL and produce a snapshot similar to the `.html` files in `frontend-screenshots`.

The snapshot should include:

- metadata with source, viewport, and path;
- visible element summary as JSON;
- sanitized HTML.

The visible element summary should include useful review fields when available:

- tag name;
- visible text;
- accessible label;
- placeholder;
- input type;
- class name;
- approximate bounding box;
- selected computed styles: `display`, `color`, `backgroundColor`, `fontSize`, `fontWeight`, and `borderRadius`.

Sanitize HTML by removing:

- `script`;
- `style`;
- `noscript`;
- `svg`;
- noisy `data-*` attributes;
- `srcset`.

Trim whitespace and cap large HTML strings. Do not include cookies, local storage, secrets, request headers, or environment variables in snapshots or prompts.

## Prompt Requirements

The prompt should ask for the final pull request comment only. It should tell the model:

- compare the reference HTML/DOM against the HTML generated by `frontend-screenshots`;
- be specific about concrete differences in visible text, labels, buttons, links, placeholders, classes, colors, sizes, approximate positions, layout, and missing or extra elements;
- keep the review brief and actionable;
- prioritize issues that should block approval before lower-risk observations;
- use simple Markdown if helpful;
- avoid repeating the PR title, reference URL, file names, or instructions;
- avoid inventing visual differences that are not supported by the HTML/DOM context.

Do not force `Rojo`, `Amarillo`, and `Verde` categories in the current flow. Do not request JSON.

## Comment Behavior

Use a stable marker:

```html
<!-- visual-review-agent -->
```

The PR comment body should include:

- the marker;
- heading `## Revisión visual`;
- a `Referencia:` link;
- the model's review text.

Find an existing bot comment with the marker and update it instead of creating duplicates.

If GitHub returns `403 Resource not accessible by integration`, write the review to `$GITHUB_STEP_SUMMARY` and do not fail the workflow solely because the comment could not be posted.

## Validation

Before finishing changes made with this skill:

- run `node --check .github/scripts/visual-review.mjs`;
- validate edited workflow YAML;
- run frontend lint if the screenshot pipeline changed;
- run the screenshot command when possible and verify `.html` snapshots are created next to `.png` screenshots;
- check that the visual review script contains no `image_url` payloads;
- confirm that the workflow still downloads the `frontend-screenshots` artifact before invoking the agent.

If local Playwright cannot bind the development server port due to sandbox restrictions, report that explicitly and validate everything else possible.
