Install any skill in seconds. Free to start, no credit card required.
Get Started Free →do e2e tests, validate feature, prove it works, pass/fail, frame proof, screenshots, CDP assertions. Daytona validation loop for real app behavior with repair before declaring success.
.claude/skills/devin-axis-daytona-flow-validator/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-04 | ✗→✓ | ▲ Improved | 52% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 85% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 91% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 119% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 50% | 0% |
Use this skill to decide whether a Daytona Electron or browser flow actually works. Launching the sandbox is separate. This skill owns the feedback loop.
Never report success from a click, script return value, or recording alone. Validate the same path a human would take, using CDP to drive Chrome or Electron instead of replacing the journey with hidden state changes. Every meaningful action must follow this loop:
browser_snapshot first.browser_click or browser_fill against snapshot UIDs whenever possible.browser_snapshot.If any assertion is missing, the flow is not validated yet.
When a coded eval exists, prefer pnpm evals --flow <flow-id> because the runner binds assertions, screenshots, and validation metadata into one HTML proof. Use manual CDP only to debug or to create a new coded flow.
Use browser_eval, direct API calls, localStorage writes, filesystem edits, or database changes only when a human-visible path is impossible, unavailable in the current product, or needed as setup for data that the UI cannot create yet. When you use one of these shortcuts, say so in the report and do not let it replace the visible click-by-click demo claim.
For founder, designer, PR, or eval evidence, record the journey as a reviewer would experience it:
For a UI flow, collect all of these when feasible:
browser_list shows the intended target.navigator.userAgent contains Electron/ for desktop flows, or does not for standalone Chrome flows.daytona exec process/log/health check for sidecars, Den, worker proxy, or mock servers.daytona-recording-artifacts for how to produce the index.Frame proof is the default. Video is the exception for interactions that need motion. When the user says "test this on Daytona" and UI is involved, always produce frame-by-frame HTML proof unless the user explicitly asks for video.
Use this structure for each step in the final report:
textStep: <what was attempted> Before: <snapshot/eval showed X> Action: <tool/selector used> After: <snapshot/eval showed Y> Assertion: pass/fail because <observable signal> Evidence: <screenshot path or artifact URL if captured>
Start with browser_snapshot for normal UI controls because it gives stable UIDs for browser_click and browser_fill. Treat browser_eval as an escape hatch, not the default interaction mechanism. Use browser_eval when:
Even when browser_eval is necessary, keep the user-visible state coherent: observe before, perform the minimal hidden action, then observe the visible result with browser_snapshot or a screenshot.
Prefer synthetic paste for the iPolloWork composer:
js(function pasteComposer(text) { var editor = document.querySelector('[contenteditable="true"][data-lexical-editor="true"]'); if (!editor) return { ok: false, reason: 'composer not found' }; editor.focus(); var data = new DataTransfer(); data.setData('text/plain', text); editor.dispatchEvent(new ClipboardEvent('paste', { bubbles: true, cancelable: true, clipboardData: data })); return { ok: true, text: editor.innerText }; })('Reply with exactly: Daytona validation OK')
Then assert the Run button is enabled before clicking it.
Use CDP for renderer UI first. When the flow opens native Linux UI that CDP cannot control, such as GTK file pickers, OS permission dialogs, XFCE windows, or Electron-native dialogs, switch to desktop automation inside the sandbox.
Check/install the tools:
bashdaytona exec "$SANDBOX" -- "bash -lc 'if ! command -v xdotool >/dev/null 2>&1; then sudo apt-get update && sudo apt-get install -y xdotool wmctrl; fi'"
Inspect the real desktop window state before acting:
bashdaytona exec "$SANDBOX" -- "bash -lc 'DISPLAY=:99 wmctrl -l; DISPLAY=:99 xdotool getactivewindow getwindowname 2>/dev/null || true'"
Native file picker pattern:
bashdaytona exec "$SANDBOX" -- "bash -lc 'DISPLAY=:99 xdotool search --name \"Authorize folder\" windowactivate; DISPLAY=:99 xdotool mousemove 760 151 click 1 key ctrl+a type --delay 1 -- \"/workspace/hello\" key Return; sleep 1; DISPLAY=:99 xdotool mousemove 1465 927 click 1'"
Rules for native desktop automation:
wmctrl -l before and after to prove the expected native window opened orclosed.
Authorize folder over coordinates when possible.clicks are display-size dependent.
Escape before capturing evidence.screenshot. Native dialogs commonly remain on top and invalidate evidence.
Close stale native dialogs before recording or screenshots:
bashdaytona exec "$SANDBOX" -- 'bash -lc '\''DISPLAY=:99 xdotool search --name "Authorize folder" windowclose %@ 2>/dev/null || true; sleep 1; DISPLAY=:99 wmctrl -l'\'''
Use browser screenshots for renderer state:
textbrowser_screenshot({ browser_url: CDP_URL, target_id: TARGET_ID })
Use Daytona display screenshots for noVNC/window state:
bashdaytona exec "$SANDBOX" -- 'bash .devcontainer/capture-daytona-screenshot.sh'
Do not treat screenshots as the only assertion. Inspect text/state with CDP too.
Before publishing, commenting, or reporting a screenshot URL, open the saved image and visually verify it matches the claim. Use webfetch on the artifact URL, Read on the local PNG path, or another image-capable viewer. A screenshot is not valid evidence until the image itself has been inspected.
For every screenshot, assert these visual checks:
picker, modal, toast, desktop window, or unrelated overlay.
command output.
cards, or output panes are legible enough for a reviewer.
If any check fails, mark the evidence as failed, fix the visible state, capture a new screenshot, inspect the new image, and only then share it. If bad evidence was already posted, post a superseding correction that clearly says the earlier screenshot was invalid.
If a frame does not support the claim, repair before reporting a verdict:
screenshot, error state, native dialog, stale modal, or unreadable content.
for text/route stability, scroll the target into view, or rerun the visible action.
Incomplete or Failed, not Passed.
Before every Daytona display screenshot, run a native-window check and fail fast if a picker is present:
bashdaytona exec "$SANDBOX" -- 'bash -lc '\''DISPLAY=:99 wmctrl -l | tee /tmp/windows-before-shot.txt; ! grep -q "Authorize folder" /tmp/windows-before-shot.txt; DISPLAY=:99 .devcontainer/capture-daytona-screenshot.sh --output /daytona-artifacts/screenshots/<flow>/<step>.png'\'''
If a Chromium or Electron window is intentionally part of the shot, activate the right window first with wmctrl -a "iPolloWork - Dev" or wmctrl -a "iPolloWork Cloud - Chromium" so the screenshot shows the intended journey step.
When a step fails:
browser_snapshot or document.body.innerText.Common logs:
bashdaytona exec "$SANDBOX" -- 'tail -120 /tmp/electron.log' daytona exec "$SANDBOX" -- 'tail -120 /tmp/vite.log' daytona exec "$SERVER_SANDBOX" -- 'tail -120 /tmp/den-api.log'
For Den Web flows specifically:
Checking account, Loading your workspace, orChecking workspace access, verify whether the client hydrated by trying a real browser_click/browser_fill, not only browser_eval.
next build +next start before declaring the app broken.
proxy failure is an incomplete handoff, not a full pass.
in the final report and limit the pass claim to the downstream desktop flow.
Use one of these verdicts:
Passed: every expected outcome has an observable assertion and frame-by-frame proof is published.Failed: at least one assertion disproves the expected outcome.Incomplete: the sandbox/tooling failed, evidence is missing, or only a recording/screenshot was collected without frame proof.| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-21 | fail→fail | 13,284 | 14,914 | +12% | 1 | 1 | 0% | 2,561 | 5,714 | +123% | 0 | 0 | — |
case-01 | fail→fail | 15,351 | 16,124 | +5% | 1 | 1 | 0% | 250 | 3,099 | +1140% | 0 | 0 | — |
case-02 | fail→fail | 16,657 | 16,849 | +1% | 1 | 1 | 0% | 365 | 3,263 | +794% | 0 | 0 | — |
case-03 | fail→fail | 26,548 | 15,684 | -41% | 1 | 1 | 0% | 3,851 | 3,163 | -18% | 0 | 0 | — |
case-04 | fail→pass | 20,004 | 4,920 | -75% | 1 | 1 | 0% | 2,328 | 3,546 | +52% | 0 | 0 | — |
case-05 | fail→pass | 19,505 | 8,497 | -56% | 1 | 1 | 0% | 2,210 | 4,096 | +85% | 0 | 0 | — |
case-06 | fail→pass | 23,034 | 6,788 | -71% | 1 | 1 | 0% | 1,971 | 3,765 | +91% | 0 | 0 | — |
case-07 | fail→fail | 18,241 | 6,669 | -63% | 1 | 1 | 0% | 2,336 | 3,737 | +60% | 0 | 0 | — |
case-08 | pass→pass | 18,000 | 12,020 | -33% | 1 | 1 | 0% | 3,104 | 4,028 | +30% | 0 | 0 | — |
case-09 | fail→pass | 16,104 | 6,091 | -62% | 1 | 1 | 0% | 1,705 | 3,731 | +119% | 0 | 0 | — |
case-10 | fail→pass | 19,775 | 6,047 | -69% | 1 | 1 | 0% | 2,451 | 3,676 | +50% | 0 | 0 | — |
case-11 | fail→pass | 11,388 | 5,830 | -49% | 1 | 1 | 0% | 2,007 | 3,648 | +82% | 0 | 0 | — |
case-12 | fail→pass | 11,686 | 8,871 | -24% | 1 | 1 | 0% | 1,855 | 4,241 | +129% | 0 | 0 | — |
case-13 | fail→pass | 9,965 | 7,026 | -29% | 1 | 1 | 0% | 1,526 | 3,572 | +134% | 0 | 0 | — |
case-14 | fail→pass | 9,430 | 3,434 | -64% | 1 | 1 | 0% | 1,546 | 3,248 | +110% | 0 | 0 | — |
case-15 | pass→pass | 14,326 | 8,051 | -44% | 1 | 1 | 0% | 2,140 | 4,069 | +90% | 0 | 0 | — |
case-16 | fail→pass | 14,059 | 6,652 | -53% | 1 | 1 | 0% | 2,148 | 3,711 | +73% | 0 | 0 | — |
case-17 | pass→pass | 9,771 | 5,396 | -45% | 1 | 1 | 0% | 1,772 | 3,722 | +110% | 0 | 0 | — |
case-18 | pass→pass | 8,404 | 2,766 | -67% | 1 | 1 | 0% | 1,438 | 3,101 | +116% | 0 | 0 | — |
case-19 | fail→pass | 9,864 | 3,470 | -65% | 1 | 1 | 0% | 1,691 | 3,225 | +91% | 0 | 0 | — |
case-20 | fail→fail | 9,552 | 7,650 | -20% | 1 | 1 | 0% | 1,520 | 3,947 | +160% | 0 | 0 | — |
case-22 | fail→fail | 32,615 | 17,420 | -47% | 1 | 1 | 0% | 3,571 | 5,224 | +46% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 19 counted toward the lift figure. The other 3 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +50 percentage points is the difference between those two pass rates over the 19 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.