Skill v1.0.2
currentAutomated scan96/1002 files
version: "1.0.2" name: issue-repro description: >- ALWAYS USE THIS SKILL when working on an issue that has "Steps to Reproduce". allowed-tools:
- bash
- chrome-devtools
- wdio
If you are working on a GitHub issue that includes "Steps to Reproduce", "Current Behavior", and "Expected Behavior" sections, you must follow this step-by-step guide to confirming the bug exists and validate your fix.
Follow these instructions directly, while observing the methodology described to you (regarding the usage of ci-monitor, test-diagnosis and puppeteer skills where appropriate). DO NOT deviate from this process, skip steps, or make assumptions about the cause of the error without first attempting to reproduce it as described.
By following the documented steps in the issue, you can reliably reproduce the problem and ensure your solution works as intended without guesswork or assumptions.
Stages
- Parse — extract Steps to Reproduce, Current Behavior, Expected Behavior, and the target platform (web / android / ios) from the issue.
- Set up the browser — pass the target platform to
browser-control, which attaches the right MCP, applies emulation, and navigates to the dev server. - Reproduce — drive the browser MCP through the steps; confirm the failure mode fires.
- Write the failing test — invoke
tdd-write-failing-testto turn the reproduction into an automated regression test and prove it fails for the right reason, before fixing. - Fix — root-cause and fix the code.
- Validate — re-run the test via
run-test; it must now pass (the failure is gone and the expected behavior holds).
You MUST be able to reproduce the issue directly – if you cannot, DO NOT assume the cause without first confirming with the user. DO NOT explore a fix until you have successfully reproduced the issue and written the failing test (Step 4). This is your priority. If you CANNOT FULLY REPRODUCE the steps, FAIL AND ESCALATE TO THE USER — except for an ambiguous [Mobile] issue, where you first retry on ios before escalating (see Step 3). Similarly, a fix is not complete until the test written in Step 4 passes (Step 6).
iOS is fully reproducible here — never opt out. iOS issues run on real iOS devices via BrowserStack App Automate, driven by thewdioMCP throughbrowser-control→browser-control-ios. You do not need a local Mac, a physical device, or a simulator. "This is iOS-specific / needs a physical device / I can't automate iOS" is never a valid reason to skip reproduction or to jump straight to a fix. Iftarget = ios, hand off tobrowser-controland reproduce on the cloud device exactly as you would for web or android.
Step 1: Parse the Issue
Use the GitHub MCP get_issue tool to read the full issue body. Extract these three sections — headings vary slightly across issues so match loosely:
| Section | Common headings | |
|---|---|---|
| Steps to reproduce | "Steps to Reproduce", "Step to Reproduce", "How to reproduce" | |
| Failure | "Current Behavior", "Current behavior", "Actual Behavior" | |
| Goal | "Expected Behavior", "Expected behavior" |
If the issue body is ambiguous, read any attached comments before asking the user for clarification. If a section is genuinely absent, stop and ask.
Sometimes, there may be multiple steps to reproduce within a single issue. If so, you must reproduce and fix each one separately, following the same process for each. Do not attempt to fix multiple reproduction paths at once.
Determine the target platform
Pick exactly one of web, android, or ios — browser-control is going to need it in Step 2. Use issue tags first, fall back to keyword scan, default to web.
Tags (primary):
| Tag | Target | |
|---|---|---|
[iOS], [Safari] | ios | |
[Android], [Mobile] | android | |
| no platform tag | web |
[Mobile] without [iOS] is treated as `android` — the cheaper environment (mobile Chrome via the puppeteer suite; no iOS device to spin up) that reproduces almost all mobile-only behavior. For these ambiguous-mobile cases (the [Mobile] tag, or the generic mobile language below), android is a default with an iOS fallback, not a commitment: if you cannot reproduce on mobile Chrome, the bug is most likely iOS-specific, so retry on ios before escalating (see Step 3). Explicit [Android] (or "Chrome on mobile") stays android with no fallback; explicit [iOS]/[Safari] goes straight to ios.
Body keywords (fallback):
If no tag is present, scan the title and body. If any of the iOS-specific terms below appear (and no Android-specific terms), pick ios:
- iOS-specific: "iPhone", "iPad", "iOS", "Safari", "WebKit", "Mobile Safari".
- Android-specific: "Android", "Chrome on mobile".
- Generic mobile (no platform commitment): "tap", "swipe", "long-press", "pinch", "on my phone", "bottom sheet", "on-screen keyboard", "virtual keyboard". These imply
androidunless paired with an iOS-specific term above.
If desktop-only language is used ("click", "hover", "right-click", no mobile hints), pick web.
If you cannot determine the target after this — for example, an issue mentioning both iOS and Android — stop and ask the user which platform to reproduce on. Do not guess: an iOS-only bug will not reproduce under Android emulation and vice-versa.
State the chosen target out loud before continuing — and for an ambiguous-mobile default, note the iOS fallback, e.g. issue-repro: target = android (issue tagged [Mobile], body mentions "swipe"); iOS fallback if mobile-Chrome repro fails.
Step 2: Set Up the Browser
Hand the target platform you picked in Step 1 to the `browser-control` skill. It will:
- Attach the correct MCP —
chrome-devtoolsforweb/android,wdioforios— and apply mobile emulation if needed, before any navigation. - Navigate to the dev server.
Do not pick the MCP, apply emulation, or start a dev server yourself — browser-control owns all of that. Wait for it to confirm the environment is up before continuing.
Step 3: Reproduce the Failure
The browser environment is now ready (Step 2) with a fresh browser profile and an empty localStorage — no app-state cleanup is needed before the first reproduction. Use the MCP that browser-control selected — chrome-devtools for web/android targets, wdio for iOS.
- Follow the Steps to Reproduce from the issue exactly as written —
same order, same actions, no shortcuts. After each step, verify the UI reflects the expected intermediate state before continuing.
- After the final step, check whether the Current Behavior described in the
issue occurs. Observe UI state, console log messages, or any other indication as stated in the issue.
- Document what you observed — quote the error message or describe the UI
state. If the failure does not occur, note this explicitly and do not proceed to fixing.
Ambiguous-mobile → iOS fallback. If the target was an ambiguous-mobile default (android chosen from [Mobile] or generic mobile language — not explicit [Android]) and the issue did not reproduce on mobile Chrome, re-run Step 2 with target = ios and attempt the reproduction on the real iOS device before escalating — a mobile bug that won't repro in Chrome is most likely iOS-specific. Only if it also fails on iOS do you escalate.
Otherwise — explicit web/android/ios (or iOS already retried and failed) — report to the user and ask for clarification (different browser, platform, version, or data state required?).
YOU MUST ESCALATE IF YOU CANNOT EXPLICITLY REPRODUCE — but for an ambiguous [Mobile] issue, run the iOS fallback above first.
em App Interaction Reference
Split every interaction into observing vs actuating — the kind decides the tool (full detail in browser-control's Driving em interactions).
- Observing is exploratory — reading state to figure out what's happening (evaluate scripts, inspect the DOM, screenshots, console, network). Use the full MCP/tool surface freely; nothing is off-limits.
- Actuating em goes through the canonical e2e helpers when one exists — anything that drives em's behaviour: tapping any em control (a thought, a button, a toolbar icon, a menu item), typing into a thought, gestures, selection. Drive them via the executor bridge. Two reasons: they encapsulate dispatch that's easy to get wrong by hand, and a repro built from helper calls transfers near-free into the automated test.
- The trap: em controls use
fastClick(touch events under mobile emulation), so a raw mouse click silently no-ops on a touch-emulated page — no error, you just misread it as "the button doesn't work." The `click` helper taps right per platform (page.tapmobile /page.clickdesktop). A tap is not "mechanical" just because it's a tap — if it's em's own UI, use the helper. Check the catalog before assuming otherwise. - If no helper covers an actuation, drive it with the MCP/tooling and keep going — no stopping, no escalation; just don't hand-reimplement an existing helper. (Note the gap as a candidate helper.) (Both iOS and web/android run helpers through the bridge — see the platform
browser-control-*sub-skill.) - To find helpers, list
src/e2e/<platform>/helpers/and read the relevant helper's source for its signature before composing — that directory is the catalog. - Read em's UI code to understand how to trigger certain behaviors if the steps are not explicit.
Step 4: Write the Failing Test (Mandatory)
Before exploring a fix, turn the reproduction into a permanent automated test. Execute the `tdd-write-failing-test` skill end-to-end. It reuses the same e2e helpers you drove during reproduction, asserts the issue's Expected Behavior, and confirms the test fails for the right reason (on the assertion, with the buggy value you observed — not a timeout or setup error) against the unfixed code.
Do not skip this and do not proceed to the fix until the test fails for the right reason. The reproduction is fresh in hand now — this is when the transfer to a test is near-free. Carry forward the helper sequence you used and the buggy-vs-expected values you observed.
Step 5: Fix the Issue
- Use the reproduction evidence (error message, stack trace, console output) to locate the root cause. Read the relevant source code. Do not guess the cause without evidence.
- Implement a targeted fix. Prefer the smallest change that addresses the root cause without breaking related behavior.
- Ensure related behavior is not broken by taking a moment to analyze any potential impact of your change on the surrounding code and features. Fix any issues you identify before proceeding to validation.
- Remove the `.skip` from the regression test written in Step 4 (
it.skip→it) — it was committed skipped to keep CI green while red; the fix must make it pass un-skipped, leaving permanent coverage. Never merge it still skipped (seetdd-write-failing-testStep 6). - Restart or hot-reload the app. (
yarn starthot-reloads on file change, so a page reload is usually sufficient. For build-level changes, re-runyarn build.)
Step 6: Fix-Validate Loop (Mandatory)
After applying a fix, validate it immediately. If validation fails, fix and validate again. Repeat until the issue is resolved or the attempt limit is reached.
Maximum attempts: 5. Track the attempt count. If the test still fails after 5 fix-and-validate cycles, stop and escalate to the user with a summary of what you tried and what you observed each time.
Validation criteria
6a — The failing test from Step 4 now passes (the mandatory gate). Re-run it via the `run-test` skill. It must pass on the assertion that previously failed — that green run is the proof the bug is fixed, and it replaces manual re-reproduction. A test that now errors for an infra reason (timeout, selector) is not a pass; diagnose it.
6b — Optional end-to-end confirmation. For extra confidence (or if the test had to assert a proxy for the visible symptom), re-drive the Steps to Reproduce once in the live environment browser-control set up — clear app state first (localStorage.clear(); location.reload();, then wait for #skip-tutorial or [aria-label="empty-thoughtspace"]) — and confirm the Expected Behavior holds and the Current Behavior is gone.
Loop
attempt = 1loop:fix the code (Step 5)run the Step 4 test via run-test (6a)if it passes → done, summarize what you changedif it fails → read the assertion diff, diagnose what still went wrongattempt += 1if attempt > 5 → escalate to user
Never claim success without the Step 4 test passing (6a). Never skip the loop.
Escalation Rules
- If the bug cannot be reproduced in Step 3 after a thorough attempt, stop and report to the user with what you observed. Do not proceed to fixing.
- Lacking a local device or simulator is not an escalation reason for iOS — iOS reproduces on BrowserStack real devices via
browser-control. Only escalate an iOS issue after a genuine reproduction attempt throughbrowser-control-ioshas actually failed. - If the fix-validate loop reaches 5 attempts without success, stop and summarize: what you tried, what changed, and what still fails.
- Default to autonomous action. Escalate only when the correct path is genuinely ambiguous.