Bug Report Form: Templates & Best Practices for QA

A bug report form is a short, fixed set of fields that forces a reporter to name the exact UI element, the steps, and the expected versus actual result. From zero, copy the template below into GitHub, Linear, or Jira and delete every field that does not save a round-trip.
Most forms fail because they are long. People skip the hard field. The hard field is which control is wrong.
There is a worked bug report example if you want to see a filled one. This post is the form itself and how QA should run it.
What belongs on a bug report form?
A field belongs if it answers a question a developer would otherwise ask. If it does not, it is padding.
The three fields that decide whether the ticket is actionable:
- Element — which control, with a label a stranger can find.
- Steps — the shortest path to the state.
- Expected / actual — two sentences, not one mushy paragraph.
URL or window name, environment, severity, and a crop sit next to those. They help. They do not replace the three.
A twelve-field form that asks for browser build, viewport, account tier, and "is this a regression?" on every cosmetic bug trains people to skip. The skipped field is usually Element.
The format of a bug report is the same idea in prose. The form is what you put in the tracker so the format is not optional.
Short forms get finished. Finished reports are the only kind that help.
"The save button" is not an element. "Primary Save in the top toolbar, next to Cancel, label Save changes" is an element. If the screen has three Saves, the first version will bounce.
The copy-paste bug report form
Paste this into a GitHub issue template, a Linear form, or a Jira description. Keep the labels.
Title: [what is broken and where]
Element: [role, visible label, where it sits]
URL / window: [page or native window]
Environment: [OS, app or browser version]
Steps:
1.
2.
3.
Expected:
Actual:
Severity: [blocker | major | minor | cosmetic]
Evidence: [crop of the element, not a full desktop]
That is the whole form. If your bug reporting software lets you make fields required, require Element, Steps, Expected, and Actual. Leave Severity optional if you do not trust reporters to set it.
Title should name the surface and the failure. "Checkout / Pay now stays disabled after valid card" beats "button bug."
Evidence should be a crop. A full-desktop PNG hides the control in a pile of pixels and burns space in an agent context window.
Split Expected and Actual. One combined sentence is how a spec question hides inside a "bug." Two sentences force you to state the correct behavior.
Why do bug report forms get abandoned?
They get abandoned when they feel like paperwork for someone else's process.
Required fields that the reporter cannot know (root cause, "module," internal component name) will be filled with junk. Junk trains developers to ignore the form.
Anonymous public forms also die when you ask for an account ID the user does not have. Ask for the URL and a screenshot first. Ask for an account only if the bug is account-scoped.
Internal QA forms die when the only way to fill Element is to inspect the DOM. QA should not need DevTools to file a visual bug. Give them a capture that resolves the accessibility name.
Point-and-speak bug reports for Linear and GitHub is the pairing workflow. Circle the control. Speak the expected change. The form fields get a crop and a name instead of a paragraph.
If a field needs DevTools, it is a developer field. Do not put it on a QA form.
GitHub issue form
Type: YAML issue form in the repo
Capture: markdown plus attachments
Resolution: only what the reporter types. Add an Element field or they will skip it.
Linear form
Type: intake or template
Capture: description plus files
Resolution: same limit. A named element in the first line helps triage.
Jira screen
Type: required custom fields
Capture: whatever you made required
Resolution: Jira cannot see the UI. It can only store what you send.
Point-and-speak into the tracker
Type: native Mac capture, then file
Capture: crop, transcript, AX role/label/frame
Resolution: the element field is filled by the Accessibility API, not by memory.
How does a beginner fill the element field?
Look at the control. Write the words on it. Write where it sits. Write the role if you know it (button, link, text field, checkbox).
If you do not know the role, say "button" or "field" in plain language. Do not invent a CSS class.
Better: hold ⌥⌘A, circle the control, speak "Pay now stays disabled after a valid Visa." PinVari resolves the named AX element, transcribes on-device, and keeps a crop. You paste or file that packet.
claude mcp add --scope user pinvari -- "$HOME/.pinvari/mcp/pinvari-mcp"
If an agent will fix the ticket, the same packet goes over MCP on 127.0.0.1:3402 as pinvari_next_instruction. The form and the agent should see the same identity.
Dwell about 0.2s if you do not want to draw a circle. Three marks in one breath get three word buckets. ⌥⌘P if you need to scroll. Confidence below 0.8 should ask, not guess.
On canvas, AX may be empty. On-device OCR is the fallback. Still attach the crop.
Do not attach a recording of the entire session if a 200-pixel crop shows the failure. Long videos do not get watched. Crops get used.
The capture layer is a one-time $39 launch license on the pricing section. Trackers stay whatever you already pay for.
What should a QA lead enforce on the form?
Enforce completion of the three fields. Do not enforce tone. Do not enforce a novel.
Bounce tickets that say "see screenshot" with a full desktop and no Element. Do not bounce tickets that have a named element, three steps, and a one-line actual.
If two teams share a form, keep one Element field. Do not add "Dev notes" as a required reporter field. Developers can add that after they accept the ticket.
For agents, add one optional field: Selector or AX name. Humans can leave it blank. A capture tool can fill it. That is how the same form feeds a person on Monday and Claude Code on Tuesday.
Window text and a URL help when the steps are thin. A capture can include focused-window text up to 40,000 characters, including text scrolled out of view, plus the browser URL from AXWebArea. Paste only what you need into the ticket. Do not dump 40,000 characters into Jira by default.
The form is a contract, not a diary. Keep it short enough that a contractor will finish it.
If you are rolling the form out to a new QA contractor, pair on the first three tickets. The first one will still say see screenshot. The second will name the page. The third will name the control. That is the training. Do not write a five-page SOP instead.
Keep a short library of good tickets next to the form. One blocker, one visual, one copy bug. People copy what they can see. They do not copy a style guide.
For agencies reviewing a client build, the same form works if Element is filled from a capture. The client does not need a Jira seat to circle a control and speak. You rewrite into the tracker. That is faster than teaching a client your field names.
When two bugs share a screen, file two tickets. One form row per control. A combined ticket with three actuals will be half-fixed and left open.
FAQ
What is a bug report form in QA?
It is the intake template your tracker shows when someone files a defect. The useful ones force element, steps, and expected versus actual. The rest is metadata.
How many fields should a bug report form have?
Enough to act, few enough to finish. Seven fields is plenty: title, element, URL, environment, steps, expected/actual, evidence. Add severity if you triage in the same pass.
Can I use the same bug report form for agents and humans?
Yes, if Element is a real identity. A person reads the label. An agent reads the AX role, label, and frame. A prose-only form wastes both.
What is the difference between a bug report form and a bug report template?
A template is the text. A form is the template with fields the tracker can require. Use both. Put the same labels in each.
Should customers fill the same form as QA?
No. Customer forms should ask for what happened and a screenshot. QA rewrites that into the internal form with a named element and steps. Do not make customers name AX roles.
How do I stop getting bounced tickets?
Fill Element so a stranger can find the control on the first try. Number the steps. Split expected and actual. Attach a crop. If you cannot name the control, circle it and let a capture tool name it.
Hand your agent the exact element
PinVari resolves what you point at into a named, executable instruction — on-device, no keys, your own agent. One click inside PinVari connects Claude Code, Cursor, VS Code or Codex — or paste one CLI line from pinvari.com/connect.
PinVari → Connect → your agent (one click)Get PinVari — $39 →


