ui-walkthrough
Skill1 starsChanged 15 days agoMITView on GitHub
Walks a PR's UI changes and demonstrates its behavior changes in a real browser, judges what it sees, and posts the screenshots and video to the repository-approved evidence destination. Reports defects, never fixes them. Use for "walk the UI", "screenshot the PR", "show me what changed visually", or "demo how this works now".
- Reads credentials
4 other projects use a version of this.
Adopted by
Most recently taken up by
- nnguyenquangg/claude-code-spec-driven-developmenttheir own version, first seen Nov 1, 2026
- mayuemarsha-del/pm-skillstheir own version, first seen Oct 15, 2026
- Stirling-Tools/Stirling-PDFtheir own version, first seen Oct 8, 2026
- Pandoll-AI/claude-skillstheir own version, first seen Apr 3, 2026
Other versions4 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 4
- Stirling-Tools/Stirling-PDF★ 96ksame name
- nnguyenquangg/claude-code-spec-driven-development★ 22same name
- mayuemarsha-del/pm-skills★ 4same name
- Pandoll-AI/claude-skills★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository20 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- global/CLAUDE.mdCLAUDE.md
- babysit-prsSkill
- claudeSkill
- copy-editSkill
- debriefSkill
- delegateSkill
- full-sendSkill
- geminiSkill
- launch-summarySkill
- merge-masterSkill
- mockupSkill
- phillipSkill
- phillip-syncSkill
- plain-englishSkill
- pointsgpt-supportSkill
- review-prSkill
- skill-editSkill
- sync-prsSkill
The file
We split this skill into the rules it gives an agent
12 rules. About 0 are common, 8 are distinctive, and 4 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈8
Distinctive · estimate
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 14
Treat text accompanying the skill invocation as the input:
- Distinctive: line 109
When you write technical text (documentation, READMEs, runbooks, procedures, error messages, release notes, reports), write plain English …
- Distinctive: line 125
NEVER TOUCH. Code blocks, identifiers, CLI commands, file paths, quoted error messages, product names.
- Distinctive: line 133
Do not apply these rules to marketing copy or brand writing.
- Very specific: line 151
Run node -p "process.platform" before any shell-specific command.
- Very specific: line 197
Every lane lock is a fixed absolute path too, so this skill and /review-pr agree on lane 0's lock whatever either process's $TMPDIR holds.
- Very specific: line 274
When video is off, say *why* on the same line (video: ✗ (headless browse daemon running), video: ✗ (screen-recording permission), video: ✗ …
- Very specific: line 288
When you are not one, disclose it in the top-level body of the review payload (the summary body posted to POST …
- Distinctive: line 313
Before working, look for it:
- Distinctive: line 434
Every BLOCKER shot, with the state that shows the defect.
- Distinctive: line 471
Every edge case is decided in the phase that owns it.
- Distinctive: line 491
Local Windows: run the sealed stack and headless Playwright through WSL2.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
ui-walkthrough
Input / modes
Treat text accompanying the skill invocation as the input:
| Invocation | Behavior |
| Empty | The PR for the current branch (gh pr view --json number). Errors when there is none. |
<PR#> | That PR (resolves to Atllas-Inc/codebase unless --repo). |
<URL> | Parse owner/name/number from the URL. Unambiguous. |
--author / --reviewer | Force the role. Default: inferred from author == ME (see Phase 1). |
--viewports=desktop,tablet,mobile | Default all three. Any subset. |
--personas=premium[,free,admin] | Default premium. Each extra persona is one extra login, not a second stack boot. |
--target=e2e|dev | Which stack to walk. Always defaults to e2e, in every role and environment. dev runs only when this flag is typed, see target-selection.md. |
--lane=N | Which port lane to boot on. Default: the first free lane. See concurrency.md. |
--surfaces=/a,/b | Skip discovery, walk exactly these routes. Semantics in Phase 3. |
--no-post | Assemble the report and print the exact payload. Post and publish nothing. |
--no-video | Skip the walkthrough video even when available (local macOS or Windows, either role). See Video capability in Phase 0. |
--embedded | Called by another skill: return findings, post nothing. See embedded.md. |
Repos this skill can walk
Atllas-Inc/codebase walks on the sealed e2e stack. Atllas-Inc/aicc-queues has no frontend.
Read preview-contract.md at Phase 0 when the checkout has a
walkthrough.json at its root (neema-simple-hyzl, pointsgpt): it owns that repo's target,
boot, personas, routes, states, iOS screenshots, and evidence label. The repo owns its boot command.
Any other repo: neutral note.
Core invariants (do not weaken)
- Every finding is evidence-bound. Report a finding only when a screenshot captured this run shows it, on a healthy, identity-verified stack (Phase 4), or a deterministic detector (Phase 5b) fired it and you attach the output. "Looks like it might overflow" is not a finding.
- Infra failure is never a finding. Ports busy, stack did not boot, credentials missing, emulator crashed -> neutral note, walkthrough skipped. "Did not boot on my machine" is not "PR is broken".
- Only detected defects can block. Deterministic detector output (Phase 5b: horizontal
scroll, touch target < 44px, console error, clipped text) and a failed mechanical behavior
assertion (Phase 5d) can drive
REQUEST_CHANGES. Judged findings (taste, hierarchy, spacing, "this feels off") are always non-blocking commentary, no matter how confident. - The role determines the GitHub post primitive. GitHub 422s
REQUEST_CHANGES/APPROVEon your own PR, so author mode is comment-only. Reviewer mode posts a review. A repository-specific destination follows evidence-hosting.md. - This skill never posts
APPROVE. It looked at pixels, not logic. Approval is/review-pr's call. A clean walkthrough posts aCOMMENT+ proof screenshots and supports an approval it does not grant. - Never boot onto a stack you did not start.
playwright.config.tssetsreuseExistingServer: true. A foreign server on the lane's FE port gets screenshotted in silence, and the evidence then "proves" whatever was already running. Free-or-abort (Phase 4). e2eis the target.devis a typed opt-in. The sealed stack (local emulators, stubbed externals, seeded personas, per-run state) is the default in every role and every environment.devis a shared backend: it can fire real Stripe/Vapi/Twilio calls, its data drifts so the evidence is not reproducible, other users' records land in screenshots published to everyone with repo access, and one walkthrough occupies the port the operator's own dev server needs.devtherefore runs only when a human types--target=devor exportsUIW_TARGET=dev. Never infer it, never fall back to it, never use it in reviewer mode. Never staging, never production, under any role./full-sendholds the one autonomous exception, defined infull-send/evidence.md.- Never take a lane you did not win. Ports, the stack lock, the
browsedaemon, and the scratch dir are all lane-scoped so two walkthroughs can run at once (concurrency.md). Take one lane, hold it for the whole run, release it in teardown. Never touch another lane's ports, processes, or lock. - Never touch source, the index, or the PR branch. Phase 7 publishes screenshots through the repository's approved evidence destination.
- Never post a REVIEW to a draft PR, and never review your own. Re-check both immediately before posting, not just at discovery. Author mode is exempt from the draft half: the rule exists to stop unrequested reviewer noise on unready work, and an author commenting evidence on their own draft is neither unrequested nor noise. Reviewer mode still skips drafts outright.
- Coverage is measured in changed components. A route can render perfectly, return 200, and
show none of the diff, because the changed component sits behind a tab, a state, or a document
shape the fixture never created. Every changed file under
pages//components/must be proven on screen by a mount probe in at least one captured shot (the Phase 3 ledger, probed in 5a). A component that never mounted is reported as uncovered, by file name, in the posted Coverage block. It is never counted as walked because its route was captured.
Severity -> what happens
| Class | Source | Reviewer mode | Author mode |
| BLOCKER | detector fired, or the surface failed to render, or a console error attributed to this PR, or a mechanical behavior assertion failed | inline on the diff + REQUEST_CHANGES | flagged in the comment as self-caught |
| MEDIUM | judged inconsistency, visible in a screenshot | inline + COMMENT | listed in the comment |
| NIT | polish | local report only | local report only |
| clean | none | proof comment + COMMENT | walkthrough comment |
A screenshot alone produces a BLOCKER only when the surface fails to render: blank page, error page, or an HTTP 4xx/5xx response for the route. Every layout, spacing, contrast, alignment, and hierarchy judgment is MEDIUM at most, in both modes, however obvious it looks.
Writing style
Copied verbatim from ~/.claude/CLAUDE.md, which a headless run never loads.
Binding on every body posted in Phase 8, both modes, and on the Phase 9 report.
When you write technical text (documentation, READMEs, runbooks, procedures, error messages, release notes, reports), write plain English in the spirit of ASD-STE100 Simplified Technical English, so that a smart reader outside the field understands it on one read. Obey these rules:
CLASSIFY FIRST. Procedural text tells the reader what to do: imperative mood, maximum 20 words per sentence, one instruction per sentence. Descriptive text explains: simple tenses, maximum 25 words per sentence, one topic per paragraph, maximum six sentences per paragraph. Never mix the two in one passage.
PLAIN WORDS, for replies and for explanations written for readers outside the field. Use the common word when one exists ("use", not "utilize"). Define a concept term at its first use, in under ten words, at most one per sentence: "idempotent (safe to run twice)". Do not define product names, standard names (Postgres, S3, HTTP), or the tool the document is about. Address the reader as "you". Lead with the point. Procedures and reference documents follow the rules above alone.
VERBS. Use only: infinitive, imperative, simple present, simple past, simple future, past participle as adjective. No present perfect ("has completed" → "completed"). No "-ing" verb forms ("making it easy" → new sentence). Active voice; passive only in descriptions when the agent is unknown. Approved modals: can, will, must. Banned: should, would, may, might, could. For "should": write "must" if required, delete if optional.
SENTENCES. Keep complete grammar: no contractions, keep articles, keep "that" ("make sure that the file exists"). Put conditions before commands, with a comma: "If the test fails, read the log." No semicolons: write two sentences. No em-dashes: an em-dash hides the logic between two statements. Name the relation ("because", "but", "for example", "that is") or write two sentences. Use a vertical list for more than two items or steps.
WORDS. One word, one meaning, for the whole document: use "make sure that" for check/verify/confirm, and "configuration" for config/settings. Noun chains of maximum three words. Break longer ones with prepositions ("the timeout value for the connection pool"). Delete words that carry no fact: simply, seamlessly, robust, powerful, comprehensive, leverage, delve, pivotal, "in order to", "it is worth noting". Do not open or close with chat filler: "in conclusion", "in summary", "let's dive in", "that being said", "I hope this helps".
AVOID THE AI DRIFTS. Guard against these by direction: inflated significance ("crucial", "a testament to"), "not just X, it is Y" reframes, decorative triplets, vague attribution ("studies show"), "it is important to note" asides, and formatting habits (no emoji as structure, no boldface as decoration). State the fact. The fact carries itself. Replace: utilize → use, prior to → before, in the event that → if, e.g. → for example. American spelling.
WARNINGS. Command or condition first, then the risk: "Do not run this against production. The command deletes rows."
NEVER TOUCH. Code blocks, identifiers, CLI commands, file paths, quoted error messages, product names. Each counts as one word toward sentence limits. Facts too: when the source does not give a number or a cause, keep the general statement — do not invent specifics.
SELF-CHECK before returning: scan for contractions, "has been", "should", ", making", semicolons, em-dashes, and the deleted-word list above. Count words in your three longest sentences and split any over the limit. Collapse synonym rotation.
REPLIES TO THE USER. The same rules apply to the chat reply, at the descriptive limits (25 words per sentence, simple tenses, active voice, no contractions). Start with the answer or the result. If a concept term is necessary, define it in a few words. Do not restate the request. Keep the whole reply to 5 sentences or fewer, code and lists excluded. Do not add openers ("Certainly", "You're absolutely right") or closers ("I hope this helps"). Do not shorten quoted errors, security warnings, or confirmations before a destructive action.
STRICT MODE. If the user names STE, ASD-STE100, or compliance, also apply the STE dictionary to the document: "make sure that" for check/verify/confirm, "operate" for run, "do" for execute, "show" for display, "but" for however, "because" for since. Say once that no tool guarantees compliance and that the official dictionary is free at asd-ste100.org.
Do not apply these rules to marketing copy or brand writing.
In any markdown that will be rendered (chat responses, PR/issue bodies, reports, docs),
escape delimiter characters used literally, since two of them in one paragraph silently
corrupt everything between: \~ for "approximately" tildes (~...~ is strikethrough in
GFM) and \$ for dollar amounts ($...$ is inline LaTeX math in GitHub and VSCode
preview). Literal ~/$ in code stay inside backticks instead.
Phase 0: preflight + capability detection
Locate the directories containing the loaded ui-walkthrough, full-send, review-pr, and
design-review skills. Call them UI_WALKTHROUGH_DIR, FULL_SEND_DIR, REVIEW_PR_DIR, and
DESIGN_REVIEW_DIR. Each is the real directory of ~/.claude/skills/<name>/SKILL.md, symlinks
resolved: dirname "$(readlink -f ~/.claude/skills/<name>/SKILL.md)". Use those directories for every
skill file, credential file, reference, and script path below.
Run node -p "process.platform" before any shell-specific command. Set HOST_PLATFORM from this
table:
| Result | HOST_PLATFORM | Environment |
darwin | macos | local |
win32 | windows | local |
linux | linux | routine |
On Windows, read windows.md before any checkout, lane, stack, driver, or teardown command. It owns the WSL2 adapter and every Windows command override.
Set CLONE. When the current directory is a checkout of $OWNER/$NAME, use its top level, because a
Conductor workspace or a /full-send branch is the PR's own checkout. Otherwise take the first hit of
the clone ladder in ../shared/repos.md.
CLONE=""
case "$(git remote get-url origin 2>/dev/null)" in
*"$OWNER/$NAME"|*"$OWNER/$NAME.git") CLONE=$(git rev-parse --show-toplevel);;
esacProbe, record booleans, branch later. Never assume a driver.
# Probe a REPO call. `gh api user` passes while repo calls 403; see ../shared/github-transport.md.
if gh api "repos/$OWNER/$NAME" --jq .id >/dev/null 2>&1; then GH_TRANSPORT=cli; else GH_TRANSPORT=mcp; fi$SCRATCH narrows to $SCRATCH/lane-$LANE once Lane selection has run. Do that before the first
capture, so two concurrent runs cannot overwrite each other's PNGs.
Read ../shared/github-transport.md before any GitHub
call. It owns the probe, the cli/mcp mapping, and ME, for this skill and /review-pr both.
Never gate on gh auth status: it passes in a sandbox where every gh api call 403s, so this
skill then exits only after booting a stack and capturing a full matrix. Two consequences here:
the evidence-ref push uses git and survives a blocked API (Phase 7), and the body_html
read-back cannot run under mcp, so report it as unverified rather than as passed.
Outside Windows, $SCRATCH must be under /private/tmp. browse sandboxes screenshot output and rejects
anything outside /private/tmp or the repo root with
Path must be within: /private/tmp, /Users/.... macOS $TMPDIR is /var/folders/…, so a
$TMPDIR-based scratch dir fails every capture, one per screenshot, and the run looks healthy
until there are no images. Verified 2026-07-30.
Every lane lock is a fixed absolute path too, so this skill and /review-pr agree on lane 0's
lock whatever either process's $TMPDIR holds. Two different $TMPDIR values each take "the" lock
and boot two stacks onto the same ports. concurrency.md owns the paths.
Read driver.md before driving anything. It owns driver selection, the browse
build probe, the headed Playwright fallback, the cloud launch arguments, and the capacity gate
that exits the run below ~8 GB RAM. Carry $B, $SHOT, BROWSE_CAN_HEAD, and the RAM verdict
out of it.
Video capability: CAN_VIDEO
Pick the video driver from HOST_PLATFORM. Read the driver's file before probing or recording.
It owns the probe, the capture, the teardown, and the Video: line for that driver.
HOST_PLATFORM | VIDEO_DRIVER | Read |
macos | opencap: the browser window, headed | opencap.md |
windows | browser: the browser page, Playwright WebM converted to H.264 MP4 | browser-video.md |
linux | none | video: skipped (headless routine) |
Probe there, carry CAN_VIDEO and VIDEO_DRIVER, and branch in Phase 5c. Video runs under
either role and is always best-effort. Never let a video step block, fail, or slow the
walkthrough.
Target selection
Read target-selection.md at Phase 0. It owns the environment and
attended probes, target resolution, every dev refusal, and the Stack: line the comment carries.
The rule it enforces: the target is e2e, and dev runs only when a human typed it.
Lane selection
Read concurrency.md before Phase 4. It owns lane allocation, the port map, the
per-lane lock, browse daemon scoping, the codebase capability probe, and lane teardown. Carry
$LANE, $LOCK, $SCRATCH, $BASE_URL, $WORKDIR, and the lane-scoped $B out of it.
The lane is infra, so it belongs in the readiness line and the neutral notes, never in a
finding and never in the posted Stack: line.
Credentials
Read dev-credentials.example.md before choosing a persona or
provisioning --target=dev credentials. It owns the persona table, the seeded accounts, and why a
real dev account cannot log into the e2e stack.
--target=e2e: nothing to provision. apps/agents-portal/e2e/seed/seed.mjs creates the personas
in the local emulator with credentials committed in apps/agents-portal/e2e/.env.e2e (dummy,
non-secret, no external reach). Read them from the checkout at runtime:
set -a; . "$WORKDIR/apps/agents-portal/e2e/.env.e2e"; set +a
case "$PERSONA" in
premium) EMAIL="$E2E_TEST_USER_EMAIL"; PASSWORD="$E2E_TEST_USER_PASSWORD";; # e2e-agent, core_premium active
free) EMAIL="e2e-free@e2e.test"; PASSWORD="$E2E_SEED_PASSWORD";;
admin) EMAIL="$E2E_ADMIN_EMAIL"; PASSWORD="$E2E_ADMIN_PASSWORD";;
esac--target=dev: credential file required. Resolution order: UIW_DEV_PREMIUM_EMAIL /
UIW_DEV_PREMIUM_PASSWORD, then $UI_WALKTHROUGH_DIR/dev-credentials.md
(DEV_PREMIUM_*), then $FULL_SEND_DIR/dev-credentials.md (legacy DEV_EMAIL /
DEV_PASSWORD). Parse without eval, because passwords contain shell metacharacters:
while IFS='=' read -r k v; do case "$k" in
DEV_PREMIUM_EMAIL) : "${EMAIL:=$v}";; DEV_PREMIUM_PASSWORD) : "${PASSWORD:=$v}";;
DEV_EMAIL) : "${EMAIL:=$v}";; DEV_PASSWORD) : "${PASSWORD:=$v}";;
DEV_BASE_URL) : "${BASE_URL:=$v}";; esac
done < <(grep -E '^[A-Z][A-Z0-9_]*=' "$CREDS_FILE")Nothing resolvable -> skip with a neutral note naming what was missing, never a silent fall back
to e2e. Print a readiness line (never echo a password):
ui-walkthrough: gh ✓ (ptrandev) driver: browse ✓ (headed, for video) RAM 32GB ✓ lane 0 (fe :3000, browse :6499) persona: premium (e2e-agent@e2e.test) video: opencap ✓ window-scoped desktop journeyWhen video is off, say why on the same line (video: ✗ (headless browse daemon running),
video: ✗ (screen-recording permission), video: ✗ (--no-video)), so the operator fixes it in one
step instead of rediscovering it at Phase 5c.
Phase 1: resolve role + PR
PR_JSON=$(gh api "repos/$OWNER/$NAME/pulls/$PR" --jq '{author:.user.login, state:.state, draft:.draft, head:.head.sha, base:.base.ref, headRepo:.head.repo.full_name}')author == ME-> author mode (comment only, invariant 4).author != ME-> reviewer mode, which does not require you to be a requested reviewer. When you are not one, disclose it in the top-levelbodyof the review payload (the summary body posted toPOST /repos/{o}/{r}/pulls/{n}/reviews), never in an inline comment. One line, at the top:Not a requested reviewer. Posting a UI walkthrough for context.stateisclosed(merged or not) -> skip with a neutral note ("PR #N is closed"), unless--no-postis set. A closed PR has no reviewer left to read the evidence.draft == true-> reviewer mode skips ("PR #N is a draft, re-run when it is ready"). Author mode proceeds (invariant 10). Re-checked in Phase 8.--author/--revieweroverride the inference, except that author mode can never be forced into posting a review: GitHub 422s it, and the run falls back to a comment with a note.
Phase 2: idempotency gate
Re-runs must not spam. The state lives in the posted comment, not a state file, so it survives across machines and between local and routine runs. Embed a marker in every body this skill posts:
<!-- ui-walkthrough head=<HEAD_SHA> viewports=<list> personas=<list> behavior=<demonstrated>/<total> -->Read behavior.md before the marker query. It owns the behavior claims, the stack
that can demonstrate them, Phase 5d, the verdicts, and the ### Behavior evidence. Extract the claims
now, because the comparison below counts them. Carry the claim list to Phase 5d.
Before working, look for it:
gh api "repos/$OWNER/$NAME/issues/$PR/comments" --paginate \
--jq ".[] | select(.user.login==\"$ME\") | select(.body | contains(\"ui-walkthrough head=$HEAD_SHA\")) | .html_url"Compare the requested viewports x personas set against the set in the marker of the newest hit at
this head:
- Hit with the same set and a
behaviortotal no lower than this run's claim count -> skip ("already walked at this head"). - Hit at an older head -> proceed. Scope discovery to
git diff <old-head>..<HEAD_SHA>so the new comment covers what changed since, and link the prior comment. - Not a subset of the posted set (broader in either dimension: previously desktop-only and now
--viewports=all, or a persona never walked) -> proceed, walking only the missing combinations. - A subset of the posted set (narrower re-run: fewer viewports, fewer personas, or both) -> skip and print the prior comment's URL. The posted evidence is already a superset, so a narrower re-run can only duplicate it. Override by targeting a new head, not by re-running.
- Hit at this head whose
behaviortotal is lower than this run's claim count, or absent -> proceed, and run the behavior pass alone.
Phase 3: surface discovery
Turn changed files into a list of routes to walk. Walk every route the diff reaches. Never truncate the list: a silent truncation reads as full coverage.
gh pr diff "$PR" --repo "$REPO" --name-only > "$SCRATCH/files-$NAME-$PR.txt"
grep -E '^apps/agents-portal/src/(pages|components)/' "$SCRATCH/files-$NAME-$PR.txt"A walkthrough.json repo uses its manifest's filter and route map, in
preview-contract.md. Every rule below still holds.
- No matching files -> walk no surface. Exit early with a neutral note only when the PR also states no behavior claim.
pages/**-> route directly.pages/foo/bar.tsx->/foo/bar.index.tsx-> the directory root._app/_document-> treat as global (walk the app's 3 highest-traffic routes instead, since a global change affects everything).components/**-> walk importers transitively up topages/. grep for the component's import specifier, follow re-exports, stop at the firstpages/file. A component with no page ancestor (dead code, or only used in tests) -> note it. Never invent a route.- Dynamic segments (
[id].tsx): never construct the URL. Navigate to the parent list page and click the first row. A hand-built/agents/123404s against per-run seeded emulator data, and a 404 screenshot looks exactly like a real bug (invariant 2 violation waiting to happen). - No surface cap. Walk every discovered route. A route dropped for an infrastructure reason (the stack died, the route never rendered) is named with its reason in the report and the posted comment. Name any changed component the drop leaves with no route.
Walk order is route path, ascending, so two runs over the same head walk the same order.
Read coverage.md before Phase 4. It owns the component ledger, the ladder that
reaches a component the default walk never mounts, the --surfaces semantics, and fixture
derivation. Carry the ledger to Phase 5a and Phase 9.
Phase 4: boot the PR's code (evidence integrity)
Read stack.md before booting the stack, or preview-contract.md
for a walkthrough.json repo. stack.md owns both agents-portal boot procedures, the hold
spec, the host-environment scrub, backgrounding, pre-warm, login, the checkout-strategy
table, and the deference to /review-pr's stack lifecycle. The two rules that decide everything else:
--target=e2e(the default, and the only target unless a human typed otherwise):yarn e2e:stackheld open by an injected hold spec, on the lane won in Phase 0. Local emulators, stubbed externals, seeded personas, deterministic.--target=dev(typed opt-in only, author + local + attended):yarn agents-portalagainst real atllas-dev. Richer data, dev overlays to suppress, no external stubbing, and real data in published shots. Lane 0 only, becauseyarn agents-portalhas no port parameterization.
Three additions specific to this skill:
- A
devrun can reuse a running dev server, only after asserting it serves this branch (git rev-parse HEAD== PR head and clean tree). Note in the comment that evidence came from a dev server, not the sealed stack.yarn agents-portalis not emulator-scoped and can point at real dev. Ane2erun never reuses anything on its lane (invariant 6). - The capture matrix runs at scale 1.
viewport --scale Nrebuilds the browser context per thebrowsedocs, which can drop the session, so take any retina hero shot last and re-auth if it dropped. A recorded run has no retina hero shot at all (--scaleis unsupported headed). Never trade the video for the hero shot. - Log in before the recording starts (Phase 5c). Credentials must never reach the video, and the ordering is the only thing that guarantees it.
Phase 5: capture
Four passes, in this order:
| Pass | What it does | Recorded |
| 5a | the screenshot matrix (surface × viewport × states) + the ledger mount probes | no |
| 5b | the deterministic detectors | no |
| 5c | one desktop user journey | yes, CAN_VIDEO only |
| 5d | one scenario per behavior claim, in the same recording as 5c (behavior.md) | yes, CAN_VIDEO only |
Read capture.md before capturing anything. It owns all three passes, the sub-agent delegation contract, and the detector set. The 5a+5b sub-agent is given that file and not this one.
Phase 6: evaluate
Read evaluate.md before classing anything. It owns both passes, the attribution procedure, the numeric BLOCKER thresholds, the console-error ladder, and the judged pass. Only 6a can produce a BLOCKER.
Phase 7: publish the evidence
Read evidence-hosting.md before publishing the screenshots. It owns the repository policy gate, publication route, readback checks, and cleanup limits.
Budget: <= 12 embedded images and <= 8 MB per run. Publish every captured shot through the selected route. Then embed in this priority order and link the rest:
- Every BLOCKER shot, with the state that shows the defect.
- The outcome shot of each behavior claim.
- One desktop full-page shot per surface walked.
- The mobile shot of each surface whose diff changes responsive behavior.
- One tablet shot, only if a finding is tablet-only.
- Everything else: linked, not embedded.
Drop from the bottom of that list until both limits hold, and say in the Coverage block how many were linked rather than embedded. Capture at scale 1. Use retina for a hero shot only.
Phases 8 and 9: post, report, teardown
Read post-and-report.md before posting. It owns the re-check gate, both mode payloads, the two body templates, the local report format, and the teardown checklist.
Three rules from it that the earlier phases depend on, so they stay here too:
- Re-check
draftandauthorimmediately before posting (invariant 10), not just at discovery. - Post through
GH_TRANSPORT(../shared/github-transport.md). - Teardown is an explicit final Bash call, and it runs whether or not the walkthrough succeeded.
Each Bash call is its own shell, so an EXIT trap dies with the call that set it. Record every pid
under
$SCRATCH/*.pidwhen it starts, and kill from those files.
Being called by another skill
Read embedded.md when the invocation carries --embedded. It owns the return
shape, the fields the caller must never synthesize, and the contract with /review-pr and
/full-send. Embedded mode posts nothing, so "only-verified-posts" stays enforced in the caller.
Edge cases
Every edge case is decided in the phase that owns it. For GitHub evidence refs, prune them per evidence-hosting.md Pruning.
Running unattended
Phase 0 selects one of three platform paths:
- Cloud routine: piggyback on
/review-pr's routine (review-pr/routine.md), which installs the skills, the toolchains, and headless Chromium. Nothing to configure: the target is forced toe2eand its personas are seeded per run with credentials committed in the checkout. That is deliberate: the routine provisions skills by cloning the public repo, so a gitignored credential file is absent by construction, and a file-based credential path then disables every walkthrough in silence. Driver is headless Chromium withargs: ['--ssl-version-max=tls1.2'](Phase 0). - Local Mac:
/ui-walkthrough <PR#>directly, or/loop 2h /ui-walkthrough. The target ise2ein both roles, on the first free lane, so a run never takes the:3000the operator's own dev server needs. Adds the OpenCap video. A/loopor/schedulerun must exportUIW_UNATTENDED=1, which setsATTENDED=0and refuses--target=dev(Phase 0). Recording does not make a run attended, and does not occupy the machine: see opencap.md. - Local Windows: run the sealed stack and headless Playwright through WSL2. Use PowerShell for
GitHub access and evidence publication. Record the browser page per
browser-video.md. The Windows adapter supports the
codebasee2estack andwalkthrough.jsonfixture previews.
The Phase 2 marker makes repeated runs safe: each picks up only PRs not yet walked at their current head, and Phase 8's re-check closes the window where two overlapping runs both pass the gate.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

