Report Bug
When something on the app goes wrong — a screen renders broken, a button doesn't do what it should, an AI reply lands in the wrong language — you can file a bug report directly from the app, without leaving the page.
Bug reports go to a triage queue. A Claude Code agent attempts to reproduce on preprod, analyzes the codebase, and files a GitHub issue with everything needed to fix it. You don't need to switch contexts to write a report.
Where the button lives
The Report Bug button sits in the top header on V28, to the right of the Pulse Copilot icon (gh#358 — earlier it floated at bottom-right and collided with Pulse Copilot; it's now in the header).
Keyboard shortcut: Cmd/Ctrl + Shift + B opens the capture modal from anywhere.
On mobile, the button is in the More menu.
What you can capture
The capture modal has three tabs you can combine:
1. Screenshot
Captures the current screen using DOM-to-image. This is a snapshot of what you currently see — it includes open dropdowns, hover states, and modals.
The Report Bug button itself is hidden from the capture so it doesn't occlude the area of interest.
Drag-rectangle region select (gh#465) — to capture just a piece of the screen instead of the full viewport, drag a rectangle over the area before tapping CAPTURE. The screenshot zooms to that region. Earlier the capture included the REPORT BUG dialog itself, occluding the bug; the region-select fixes that.
2. Video (up to 60 s)
Uses browser screen-recording. Default duration 30 s, max 60 s. Records the active tab only. Audio capture is optional.
Useful when the bug is a sequence — a hover state that breaks something three clicks later, an animation that stalls, a notification flood you can only show in motion.
3. Voiceover (up to 2 minutes)
Records audio narration. Transcribed server-side to text via Whisper or Claude.
The transcription appears in the report alongside the screenshot/video — you don't have to type your description if you'd rather talk through it.
You can also write a text description in the same modal — text + screenshot, text + video, voiceover + screenshot, etc., in any combination.
Auto-collected context
When you submit, the app automatically attaches:
- Current URL + route params
- Last 20 tRPC queries with timing + status
- Last 100 console log lines (in-app ring buffer)
- Last 20 failed network calls
- Last 20 user actions (route changes, clicks)
- Browser, viewport, build SHA, env (prod / preprod)
- React error-boundary errors from the current session
- Server-side log trace for the report submission's own request
You don't have to copy/paste any of this. It's bundled and stored with the report.
Anonymize PII toggle
The capture modal has an Anonymize PII toggle.
- For non-admin users, it's ON by default.
- For admin users, it's OFF by default but always visible.
When ON:
- Screenshots are run through OCR + PII regex; phone numbers, emails, IBANs, and guest names are blacked out before storage.
- Videos get the same redaction at 5 fps. The audio track from screen-recording is stripped entirely.
- Voiceover audio is not stored in anonymized mode — only the redacted transcript text.
- All log lines and context are passed through the PII scrubber (the same one used in server logs).
- Tenant ID and user ID are replaced with deterministic hashes — the triage agent can run as that role in preprod without knowing who you are.
What's kept regardless:
- The URL path (route is essential for reproduction).
- Hashed user ID (so the triage agent can run with the same permissions).
- Browser / OS / viewport.
- Stack traces, error messages, status codes.
- Click breadcrumb categories (e.g.
nav:click property-tab).
What happens after you submit
Submitted reports land in the bug_reports table with status new.
A Claude Code triage agent (gh#168) picks them up:
- Reads the description / transcript + the auto-collected context.
- Spins up a preprod environment seeded to the captured state (where possible).
- Attempts to reproduce the bug.
- Reads the codebase to find the relevant files.
- Files a GitHub issue with the screenshot / video / context + a reproducer.
The GitHub issue URL is written back to bug_reports.githubIssueUrl once filed.
Where to see your filed reports
Admin users can see the report queue and triage state at Admin → Bug Reports (gh#343). Each row shows:
- Status:
new/triaging/reproduced/filed/wontfix - Capture preview (screenshot thumbnail)
- Transcript snippet
- Linked GitHub issue (once filed)
Retention
Reports auto-expire 30 days after creation (gh#344) — they're hard-deleted at expiry to keep the bug_reports table from accumulating PII.
A tenant admin can extend the expiry on a per-report basis from the admin viewer if they need a longer window to follow up.
Implements: gh#167 (in-app Report Bug feature). Related: gh#168 (triage agent), gh#342 (capture wiring), gh#343 (admin viewer), gh#344 (retention sweep), gh#358 (move button to top header), gh#465 (drag-rectangle region select).