Bug Report Example: Named Elements Beat Pixel Guesses

WorkflowsAugust 22, 202615 min readBy PinVari
Bug Report Example: Named Elements Beat Pixel Guesses

A good bug report example tells the developer which element broke by its accessibility name and role—not "the button in the top right corner." The best reports ship the exact named UI element (AXButton "Submit Order", AXTextField "Email", AXWebArea URL), its frame coordinates, and a cropped screenshot, so a human or AI agent can fix it without asking "which one?" Most bug reports fail here: they describe position or color, the element moves in the next build, and the ticket bounces.

Developers and AI coding agents need executable data—a named target they can query in code. QA engineers who file dozens of reports a week know the pain: a vague description means a Slack ping, a screenshare, three back-and-forths, and a ticket that sits in triage for a sprint. The gap is that most tools capture pixels (CleanShot X, Jam.dev) or freeform annotations (Marker.io) but never resolve the underlying accessibility element the OS knows about.

What makes a bug report example actually good?

A good bug report gives the developer or AI agent three things: the exact UI element by name and role, repro steps tied to that element, and a screenshot cropped to the failure. If you write "the blue Submit button is disabled when it shouldn't be," the developer opens the screenshot, sees four blue buttons, and asks which one. If you write "AXButton 'Submit Order' (frame: x=1142 y=687 w=120 h=36, parent: AXGroup 'Checkout Footer') remains AXEnabled=false after entering a valid email," they know the target, the property, and the context.

The bug report life cycle starts when a tester finds unexpected behavior, ships a report to the tracker (Linear, GitHub, Jira), a developer triages it, an engineer fixes the code, QA verifies the fix, and the ticket closes. The bottleneck is step two: if the report is ambiguous, the ticket gets labeled "needs repro" and stalls. Named elements skip the ambiguity—the accessibility tree is the same tree the OS uses to support VoiceOver and keyboard navigation, so the label and role are stable across builds unless the developer explicitly renames them.

Key

The macOS Accessibility API exposes every on-screen UI element as a named, role-typed object with a frame, value, enabled state, and parent chain. Capturing that data—not just a PNG—gives developers and AI agents an executable target.

When you learn how AI agents know which UI element you mean, you realize they need the same named data a human QA engineer should file: role, title, bounds, and parent hierarchy. A screenshot alone is pixel soup to an agent; the agent has to OCR it, guess the element, and hope. A named element is a direct pointer.

How to make a bug report in testing: the workflow that works

The workflow that works is: see the bug, circle or point at the broken element, speak the issue, and let the tool resolve the element + file the ticket. This is how to make a bug report in testing when you're filing twenty bugs a day and can't afford a three-minute manual ritual per ticket.

Here's the manual baseline most QA teams use today:

  1. Reproduce the bug in the app.
  2. Take a screenshot (⇧⌘4 or CleanShot X).
  3. Open the screenshot, annotate the broken element with an arrow or rectangle.
  4. Open Linear/GitHub/Jira, create a new issue.
  5. Write a title, describe the repro steps, paste the screenshot, fill severity/labels.
  6. Submit, then ping the dev team in Slack with a link.

Total time: 2–4 minutes per bug. The failure mode: the annotation is a red box around "the button," the developer sees three buttons in that box, and asks which one. The report goes back to you.

The point-and-speak workflow on macOS:

  1. Hold ⌥⌘A, circle or point at the broken element, speak the issue (e.g., "Submit Order button stays disabled after entering a valid email").
  2. PinVari resolves the AXButton "Submit Order" with its role, label, frame, enabled state, and parent chain, plus a confidence score (e.g., 0.94).
  3. The tool transcribes your speech on-device (no API key), crops the screenshot to the circled region, and hands everything to your tracker or AI agent.
  4. If you've configured Linear or GitHub, it files the ticket with the named element as a structured field. If you've configured an MCP-connected agent (Claude Code, Cursor), it hands the instruction to the agent to write a test or fix.

Total time: ~10 seconds per bug. The dev opens the ticket and sees AXButton "Submit Order" (AXEnabled=false, frame: {1142, 687, 120, 36}, parent: AXGroup "Checkout Footer") plus your spoken description. No ambiguity.

Tip

For native macOS apps, Electron apps, and Safari/Chrome with the AXWebArea exposed, the Accessibility API gives you the real element. For canvas-rendered UI (games, some design tools), PinVari falls back to on-device Vision OCR to read visible text, so you still get a cropped screenshot + transcribed issue even if the element tree is empty.

What is a bug report in mobile vs. desktop testing?

What is bug report in mobile testing is usually a combination of device logs (ADB logcat on Android, Xcode Console on iOS), a screen recording or screenshot, and written repro steps. Mobile bug reports often include device model, OS version, and network state because the same bug behaves differently on a Pixel 7 vs. an iPhone 14. The tooling is more fragmented: TestFlight for iOS beta feedback, Firebase Crashlytics for crash reports, manual screenshots pasted into Jira.

Desktop testing—especially macOS—has an advantage: the Accessibility API is a first-class tree of every UI element, built into the OS for VoiceOver and keyboard navigation. You can programmatically query the element under any point on screen with AXUIElementCopyElementAtPosition and get its role (AXButton, AXTextField, AXWebArea), title, value, frame, and parent chain. Mobile platforms have accessibility APIs too (UIAccessibility on iOS, AccessibilityNodeInfo on Android), but third-party bug-capture tools rarely expose them; they ship pixel screenshots and logs instead.

The gap is that developers and AI agents need the named element, not a crop. If you file a mobile bug as "the login button doesn't respond," the developer opens the view hierarchy in Xcode or Android Studio and searches for a button near the coordinates you described. If you file it as UIButton "Login" (frame: {100, 500, 200, 44}, enabled: true, action: loginTapped), they jump straight to the code.

AI bug report tool for developers: what agents need

An ai bug report tool for developers must give the coding agent three things: the named UI element (not a pixel guess), the spoken or typed instruction anchored to that element, and a screenshot cropped to the region so the agent can verify context. The agent then writes a test, proposes a fix, or asks a clarifying question.

Here's why the named element matters: if you hand Claude Code a full-window screenshot and say "fix the Submit button," the agent sees ~20 buttons in the screenshot and guesses based on position or OCR. Can Claude Code see my screen? Yes, via screenshots you attach to the conversation—but screenshots are unstructured pixels. The agent doesn't know which rectangle is the button you meant unless you circle it, and even then it's guessing the bounding box from the annotation.

If you hand the agent AXButton "Submit Order" (role: AXButton, title: Submit Order, frame: {1142, 687, 120, 36}, parent: AXGroup "Checkout Footer", confidence: 0.94, provenance: circled), it knows the exact target. The agent can write await button.click() in a Playwright test, or search the codebase for "Submit Order" to find the SwiftUI Button("Submit Order") { ... } declaration. Named elements give agents executable hooks, not pixel archaeology.

The MCP (Model Context Protocol) layer is how agents consume this data. PinVari runs a local MCP server on 127.0.0.1 that exposes a tool called pinvari_next_instruction. When the agent calls it, it receives a JSON payload:

{
  "element": {
    "role": "AXButton",
    "title": "Submit Order",
    "frame": { "x": 1142, "y": 687, "width": 120, "height": 36 },
    "parentChain": ["AXWindow", "AXGroup 'Checkout Footer'"],
    "confidence": 0.94,
    "provenance": "circled"
  },
  "instruction": "Submit Order button stays disabled after entering a valid email",
  "screenshot": "base64-encoded crop of the circled region",
  "timestamp": "2026-08-22T14:32:18Z"
}

The agent sees the element, the issue, and the visual proof in one payload. It can propose a fix, write a regression test, or ask "is the email field's validation passing?" with the full context. Why Claude Code fixes the wrong element is usually because it guessed from a pixel crop; named elements solve that.

Heads up

If the confidence score is below 0.8, PinVari asks you to confirm the element before filing or handing to the agent. A 0.6 means the accessibility tree was sparse (canvas UI, minimal labels) and the tool fell back to OCR. You can still proceed, but the agent should know the element name is an OCR guess, not an AX-resolved fact.

For QA teams that want to route bugs to Linear or GitHub instead of an agent, the same named-element data populates the ticket description. Linear custom fields can store the element role and frame; GitHub issue bodies get a formatted block with the accessibility data. The dev clicks the element path and finds it in the code.

Voice to bug report mac: the push-to-talk advantage

Voice to bug report mac is faster than typing because you're already looking at the bug—you just speak the issue while circling the broken element. The transcription happens on-device (Apple's Speech framework, no API key, nothing uploaded), so it's private and instant.

The interaction is ⌥⌘A press-to-toggle: hold the hotkey, circle or point at the element, speak the bug (e.g., "Password reset link doesn't open in Safari"), then press ⌥⌘A again or hit ⏎ to finish. The tool resolves the element, transcribes your speech, and hands the instruction to the configured destination (Linear, GitHub, or MCP agent). If you prefer voice-only without marking, ⌥⌘V starts a voice-only capture—useful for filing a general issue not tied to a single element.

Why push-to-talk works for QA: you're filing bugs in context, the moment you see them. You don't context-switch to a browser, open a form, type a title, paste a screenshot, and write steps. You speak the steps while circling the element, and the tool files the ticket with the named target and your exact words. The transcription is accurate for technical terms because it's the same on-device engine Dictation uses—it knows "AXButton," "Electron," "SwiftUI," "localhost."

The push-to-talk voice for Claude Code on Mac article covers the voice interaction in depth, but the core idea is: the hotkey is a deliberate, non-always-on capture. You're not wearing a headset streaming audio to a cloud VAD; you're pressing ⌥⌘A when you see a bug, speaking the issue, and releasing. The capture is bounded, the transcription is local, and the output is structured data + cropped screenshot.

Bug report example: named element vs. pixel description

Here's a side-by-side comparison of a vague pixel-based bug report and a named-element report for the same issue.

AspectPixel-based report (bad example)Named-element report (good example)
TitleSubmit button brokenAXButton "Submit Order" stays disabled after valid email
ScreenshotFull window, red arrow pointing to a buttonCropped to the button + parent footer group
Element identification"The blue button in the bottom right"AXButton "Submit Order" (role: AXButton, title: Submit Order, frame: {1142, 687, 120, 36}, parent: AXGroup "Checkout Footer")
Repro steps1. Go to checkout 2. Enter email 3. Click SubmitSpoken: "Submit Order button stays disabled after entering a valid email into AXTextField 'Email Address'"
Confidence/provenanceNone—just a visual guessConfidence: 0.94, provenance: circled (you circled it, the tool resolved it)
Actionable by agent?No—agent has to OCR the screenshot, guess the button, hope it's the right oneYes—agent knows the exact element and can write await page.locator('button[title="Submit Order"]').click() or find the SwiftUI code
Time to file~3 minutes (screenshot, annotate, open Linear, type, paste, submit)~10 seconds (⌥⌘A, circle, speak, release)

The named-element report gives the developer or agent an executable target. The pixel report gives a visual clue that requires interpretation. When you file ten bugs in a QA session, the 3-minute-per-bug cost is half an hour; the 10-second cost is under two minutes total.

Comparison: bug capture tools and what they resolve

ToolPlatformResolves named elements?Voice input?Routes to tracker/agent?Price
PinVarimacOS (Sonoma+, Intel + Silicon)Yes—AX role, title, frame, parent chain with confidence scoreYes—on-device transcription, ⌥⌘A or ⌥⌘VLinear, GitHub, MCP agents (Claude Code, Cursor, Codex, Zed)$39 (launch, then $59), one-time
Jam.devChrome, Edge (browser only)Partially—console logs, network, DOM snapshot; no native app AXNoJira, Linear, GitHub, Slack, etc.Free (basic), $20+/mo (team)
Marker.ioBrowser onlyNo—freeform annotations over DOMNo50+ integrations (Jira, Trello, Asana, etc.)$39+/mo per workspace
CleanShot XmacOSNo—pixel screenshots, no element dataNoManual paste to any tool$29 one-time (basic), $8/mo (Cloud)

PinVari is the only tool in this table that resolves the named accessibility element on native macOS apps, Electron, and browser content, and routes it to both trackers and AI agents. Jam.dev is unbeatable for browser console/network capture but can't touch native Mac apps. Marker.io and CleanShot X ship pixels. The Jam.dev alternative for native Mac apps article explains why browser-only tools can't capture Xcode, Figma, or Electron windows.

Key

The named element is the moat. Pixel screenshots are commoditized—every screenshot tool can do that. The macOS Accessibility API exposes the UI tree; PinVari resolves the element under your pointer, assigns a confidence score, and hands it to the agent or tracker in a structured format.

How the bug report life cycle benefits from named elements

The bug report life cycle—file, triage, assign, fix, verify, close—has a choke point at triage. If the report is ambiguous, the developer labels it "needs repro" and pings the QA engineer in Slack. The engineer screenshares, clicks through the repro, the developer says "oh, that button," and updates the ticket. That's a 10-minute interruption for both people.

Named elements skip triage bottlenecks. The developer opens the ticket, sees AXButton "Submit Order" (parent: AXGroup "Checkout Footer", frame: {1142, 687, 120, 36}, AXEnabled=false), searches the codebase for "Submit Order", finds the SwiftUI declaration, and sees the disabled modifier is bound to !isEmailValid. They check the validation logic, find the regex is wrong, fix it, push a commit, and move the ticket to "in review." Total time: ~15 minutes, zero back-and-forth.

When you route named elements to an AI agent instead of a human, the agent can write the regression test before the dev even triages the ticket. The agent sees the element, the issue, and the screenshot, and proposes:

func testSubmitOrderButtonEnablesAfterValidEmail() {
    let app = XCUIApplication()
    app.launch()
    app.textFields["Email Address"].tap()
    app.textFields["Email Address"].typeText("[email protected]")
    XCTAssertTrue(app.buttons["Submit Order"].isEnabled)
}

The QA engineer reviews the test, approves it, and the ticket moves to the dev with both the bug report and a failing test. The bug report life cycle compresses from days to hours because the ambiguity is resolved up front.

FAQ

What should a bug report include for AI agents?

A bug report for AI agents should include the named UI element (role, title, frame, parent chain), the instruction or issue tied to that element, and a cropped screenshot of the region. The agent needs executable data—a target it can reference in code—not a full-window pixel dump. If you hand the agent "AXButton 'Login' is unresponsive," it can search for that button in the test suite or codebase and propose a fix or write a regression test.

How do I file a bug report faster on macOS?

Hold ⌥⌘A, circle or point at the broken element, speak the issue, and release the hotkey. The tool resolves the named element via the macOS Accessibility API, transcribes your speech on-device, crops the screenshot, and routes everything to Linear, GitHub, or your MCP-connected AI agent. Total time is ~10 seconds per bug instead of the 2–4 minutes a manual workflow costs.

Can I file bugs to Linear or GitHub from a native macOS app?

Yes. PinVari integrates with Linear and GitHub (and Slack for sharing) so you can file a bug directly from any native macOS app, Electron app, or browser without switching to a web form. The point-and-speak bug reports to Linear and GitHub workflow lets you circle the broken element, speak the issue, and file the ticket in under 15 seconds.

What is the difference between a bug report and a screenshot?

A screenshot is a pixel representation of what you see; a bug report is a structured description of the issue, the repro steps, the expected vs. actual behavior, and ideally the exact UI element that broke. Screenshots are evidence; bug reports are instructions. The best bug reports include a cropped screenshot plus the named element (AXButton "Submit", AXTextField "Password") so the developer knows which target to fix.

Why does the accessibility element matter for bug reports?

The accessibility element—the AX role, title, frame, and parent chain—gives the developer or AI agent an executable target instead of a pixel guess. If you report "the button in the top right is broken," the developer sees four buttons in that region and asks which one. If you report "AXButton 'Save Changes' (frame: {1050, 20, 100, 32}) doesn't fire the save action," they know exactly which button, where it is, and what's wrong.

Can AI coding agents use bug reports filed by QA engineers?

Yes, if the bug report includes the named element and structured data. AI agents like Claude Code, Cursor, and Codex can consume MCP server payloads that contain the element role, title, frame, and screenshot. The agent then writes a test, proposes a fix, or asks a clarifying question. If the bug report is just a freeform Jira description and a full-window screenshot, the agent has to OCR and guess—error-prone and slow.

---

The best bug report example is one the developer or agent can act on without asking "which element?" Named elements—captured via the macOS Accessibility API and resolved with confidence scores—give QA engineers a 10-second workflow that routes executable instructions to Linear, GitHub, or AI coding agents. You hold ⌥⌘A, circle the broken UI, speak the issue, and the tool handles the rest: element resolution, transcription, cropping, filing. No three-minute form ritual, no ambiguous pixel annotations, no triage ping-pong. If you're filing bugs against native macOS apps, Electron windows, or browser content, PinVari's one-time $39 launch price ships on-device capture with MCP agent integration and tracker routing—no subscription, no uploaded data, just named elements and cropped screenshots where you need them.

Hand your agent the exact element

PinVari resolves what you point at into a named, executable instruction — on-device, no keys, your own agent. If you run Claude Code, it is one command.

claude mcp add pinvari
Get PinVari — $39 →