SuperAPI AI Directory

surfaces

General & other

View repository

Updated 10-15 20:10

About this skill

Surfaces

Set up the surfaces review runs: end to end and visual regression. The framework decides how, and that answer lives in a recipe outside this plugin. Setup takes no task folder, the way the tool skill does. With no task active, it runs at the code path. Run from inside a task's worktree, which is outside the code path, it runs there instead, so the setup ships with the task's branch. The review skill runs the surfaces; this skill only sets them up. The guards live in the script: --enable and decline refuse unattended. This skill waits for a plain yes before install. So a stage's offer may invoke it.

Every call below runs surfaces-actions.sh, named in this skill's own grant, so it runs without asking. Read the exit code first, never the text alone. Exit 1 means no project owns this directory: say so, name the project skill, and stop.

Determine the run mode

Read the active task's run mode. A task that states none is interactive, and so is a call with no task active. Pass --run-mode autonomous on every call only when the task states it, or states light. Decide this once, at the start. A mode that names stages in brackets covers this call only when it names the stage this call runs inside. Exit 70 means a person's answer was passed with nobody present.

Read the state first

"${CLAUDE_PLUGIN_ROOT}"/skills/surfaces/scripts/surfaces-actions.sh read

It prints the project, the surfaces field, and the surface file with its state. It prints one line per surface, and a version 5 registry.yml when one sits beside the file. That registry is left in place. Its ids and URLs are candidates for discovery, below.

When the surface file is missing, read prints surface-branch:, the branch that holds the file, or none. When it names a branch, offer no setup, and install refuses. A new file would collide with that branch's file. Say the file reaches this tree once that branch lands on the trunk. If that branch is abandoned, deleting it, local and remote, lets setup run.

A stage's offer names the kind in its invocation. Run by hand with no kind, ask which kind after read, naming each kind's state, and then work that kind only.

A command as the end to end surface

A project with no page to drive, such as a command-line tool, has no setup recipe for e2e. Its end to end surface is a command. It needs no recipe and no install:

"${CLAUDE_PLUGIN_ROOT}"/skills/surfaces/scripts/surfaces-actions.sh --run-mode <mode> register <id> --command "<line>" --kind e2e --critical --enable

The line is the command that walks the path, such as a script in the code repository. Exit 0 means the path works. The line is split at spaces and runs without a shell. So a quote or a shell character is refused at 3. With no surface file, register writes one and turns end to end on in the project record, and commits both. Review runs the command in the task's tree, and nobody walks it. Exit 3 also means the file holds an e2e page surface already, because a project uses one form.

The command runs with the session's PATH. So it must reach this tree's own build, never an installed copy, for example through a path inside the tree. Register it before the build starts: on the trunk before tasks are cut, or in the first task's tree. A register during review moves the code under review, and review refuses that. A task cut before the trunk had the file cannot run it. Review reads a command unknown when the range changed it, or deleted its files, or changed their mode.

Resolve the recipes

Dispatch catalog-identifier, naming the role, once per point. The points are e2e-setup for the e2e kind, visual-regression for the visual-regression kind, and review when a baseline is taken. Each dispatch names the point as a line point: <phase>, then every framework the project records, then the project folder. A point is a point of AIDA's process, never a keyword search. Pass the answer in its own word, one flag per framework. A path on disk is --recipe <framework>=<path>. A failed lookup is --lookup-failed <framework>=<word>, with no-recipe, listing-unreachable or fetch-failed. Only the first word says anything about the framework. Never retype a command out of a recipe. The script reads the blocks.

Before install or baseline, invoke the tool skill with require <path> for each recipe path. Its section "Tools a recipe names" says what each answer means. Go on only when it exits 0.

Show, then install

"${CLAUDE_PLUGIN_ROOT}"/skills/surfaces/scripts/surfaces-actions.sh show <kind> <recipe flags>
"${CLAUDE_PLUGIN_ROOT}"/skills/surfaces/scripts/surfaces-actions.sh --run-mode <mode> install <kind> <recipe flags>

show prints the recipe, its commands, the files it writes, its viewports and its seed surfaces, and runs nothing. A recipe with no install block exits 3 from show too, so the exit code says what install would do. Interactive: run show first, print the commands and the files, and wait for a plain yes before install. Autonomous: halt here and say the install needs a person, because an install changes the project and nobody is there to approve it.

install runs every command in order and writes each file only when absent. It writes the surface file when absent, and turns the kind on in the project record. It runs again safely. It refuses a dirty tree at 61 before writing anything. It commits what it wrote, with the reason in the message, the way baseline does. It commits the project record too.

Exit code Meaning What to do
0 Every step ran, or not-applicable: no framework has a recipe. Nothing more for this kind. Name templates/process-recipe-setup.md in this plugin as the shape a catalog recipe follows.
3 A recipe with no install block, a refused command, a file present with content no version of the recipe declares, or unknown: nobody looked. Show the text and stop. It names the recipe or the file, which is where the fix belongs.
4 A step failed. The first: line quotes its first line of output. Show it; do not install by hand.
61 The tree is dirty. Say which paths. Commit or move them aside, then run install again.
72 Two frameworks each carry a recipe. Say which two, and stop.

--viewport <name>=<w>x<h> replaces the recipe's viewport list. It is a person's answer, so pass it only when a person gave it.

Discover the surfaces, then a person confirms

After install, open the discovery step through the script and follow it:

"${CLAUDE_PLUGIN_ROOT}"/skills/surfaces/scripts/surfaces-actions.sh step discover

A Read rule naming the plugin root does not reliably expand, which is why the step is read this way. Discovery ends with one register call per surface the person confirmed:

"${CLAUDE_PLUGIN_ROOT}"/skills/surfaces/scripts/surfaces-actions.sh --run-mode <mode> register <id> --url <url> --kind <kind>... [--mask <css>]... [--path <glob>]... [--critical] --enable

Pass --enable only for a surface the person confirmed. Nothing is enabled unattended. Each --path is a glob, relative to the code tree, naming files that render the surface. Review runs the surface only when the diff touches one of them. --critical makes it run on every review. A surface with no --path runs on every review too. Each register commits the surface file, the way install does, so baseline finds a clean tree. Exit 62 means install has not run. Exit 3 names an id already registered with different fields. Exit 61 means the tree is dirty with something else.

Take the first baselines

"${CLAUDE_PLUGIN_ROOT}"/skills/surfaces/scripts/surfaces-actions.sh --run-mode <mode> baseline [<id>]... --check-recipe <framework>=<path> [--value base-url=<address>]

Without --confirmed it prints the plan: the ids given, or every enabled visual regression surface, at every viewport. Show the plan and take the person's yes. Then run it again with --confirmed. It runs the review recipe's accept row over those ids only, and commits the baselines with the reason in the message. Never write a baseline unattended, and never by hand.

Ask for the base URL once, interactive, and pass it as --value base-url=<address>. Nothing stores it. When the task record has environment.address, pass that as --value base-url= and do not ask. Exit 3 means the recipe carries no accept row, exit 61 that the tree is dirty.

Decline

"${CLAUDE_PLUGIN_ROOT}"/skills/surfaces/scripts/surfaces-actions.sh decline <kind>

Records that the person declined that kind's setup. Every stage's offer, at scope, design and review, reads it and does not ask again for that kind. It is a person's answer, so it refuses unattended at 70. No kind, or an unknown one, refuses at 3, naming e2e and visual-regression. It commits the project record too.

What this skill never does

It never edits a recipe, and it never runs a command a recipe supplied through a shell.