Bug Triage & Prioritization at Scale
Turn a firehose of reports into a defensible, ranked queue
A severity-by-impact framework
After this you can rank any incoming issue with a defensible rubric.
At 1M+ DAU the reports never stop. The job isn't to feel busy clearing them, it's to make sure the right one gets worked first - and to be able to defend that ordering to an engineer who'd rather you left them alone.
A Product Quality Engineer on User Operations is the person who decides what's worth an engineer's afternoon. That decision can't be a gut call you redo every morning. It has to be a rubric: a severity axis (how bad is the failure) crossed with an impact axis (how much of the world it touches), producing a number you can put in a brief and stand behind.
Interactive diagram. Tab through its regions; each focused region shows its detail in the panel below.
The catastrophe in the top-left - high severity, low reach - is exactly the report a volume-only triage buries.
Severity: how bad is the failure itselfone report, judged on its worst outcome
Severity describes the damage independent of how many people hit it. A single user losing uncommitted work is a serious event even if they're the only one. Rank failure classes from the one you'd interrupt someone over down to the one that can wait a sprint.
- Tier
- S0 - Critical
- What it means
- Data loss, security exposure or full outage
- Cursor example
- An Agent edit silently overwrites unsaved files; a privacy-mode leak; backend down for all users
- Tier
- S1 - Major
- What it means
- Core workflow blocked, no workaround
- Cursor example
- Tab autocomplete returns nothing for everyone on the latest update; Agent loops and never completes
- Tier
- S2 - Degraded
- What it means
- Works but worse or a workaround exists
- Cursor example
- ⌘K latency doubled; codebase indexing is slow but eventually completes
- Tier
- S3 - Cosmetic
- What it means
- Annoyance, no functional loss
- Cursor example
- A misaligned icon in the model picker; a typo in a tooltip
| Tier | What it means | Cursor example |
|---|---|---|
| S0 - Critical | Data loss, security exposure or full outage | An Agent edit silently overwrites unsaved files; a privacy-mode leak; backend down for all users |
| S1 - Major | Core workflow blocked, no workaround | Tab autocomplete returns nothing for everyone on the latest update; Agent loops and never completes |
| S2 - Degraded | Works but worse or a workaround exists | ⌘K latency doubled; codebase indexing is slow but eventually completes |
| S3 - Cosmetic | Annoyance, no functional loss | A misaligned icon in the model picker; a typo in a tooltip |
Severity is graded on the worst plausible outcome, not the average one.
Anything that can destroy a user's code or expose their data is S0 even if exactly one person reported it. Data loss has no quorum. If you find yourself debating whether a single-user data-loss bug is “really” urgent, you've already mis-graded it.
Impact: how much of the world it touchesthe multiplier on severity
Impact is the reach. The same S1 bug is a different priority if it hits 0.1% of free users versus every seat at a paying enterprise. Four dimensions carry most of the signal.
- Users affected
- Raw count and percentage of DAU. 50 reports might be 50 users or a vanguard of 50,000.
- ARR affected
- Which accounts feel it. A bug hitting three Business-plan teams outranks one hitting a long tail of free trials.
- Frequency
- Every keystroke vs once a week. A papercut on a hot path can outweigh a crash on a cold one.
- Regression?
- Did we just break something that worked yesterday? Regressions jump the queue - we did this to them.
Combining the axes into a scoreso loud-but-rare can't beat quiet-but-catastrophic
Keep severity and impact as separate axes, then collapse them into a priority band. The point of the multiply is that volume alone never wins: a flood of S3 cosmetic complaints stays below a single S0 data-loss report with one reporter.
priority = severity_weight × impact_score
severity_weight: S0=100 S1=30 S2=8 S3=2
impact_score = (pct_DAU_affected × 10)
+ (arr_affected_usd / 10_000)
+ frequency_factor // 1 rare … 5 every-keystroke
+ (is_regression ? 15 : 0)
# S0 with one reporter: 100 × (0.001 + 0 + 1 + 0) ≈ 100
# S3 with 400 reporters: 2 × (4 + 0 + 3 + 0) ≈ 14
# the catastrophe wins and the math shows whyA formula's value is that it forces the inputs into the open. When you say P1, you can name the severity tier, the percent of DAU, the ARR exposed and whether it's a regression. The engineer can argue with an input, which is far better than arguing with your vibe.
Timebox investigation, escalate by ruleremove the per-ticket judgment tax
Two disciplines keep the rubric fast under load. First, timebox: give yourself a fixed window to reproduce and isolate before you either escalate or downgrade, so one gnarly bug doesn't eat the day the other forty needed. Second, write down the escalation line in advance so paging an engineer is a rule, not a fresh agony each time.
S2 and S3 with a known workaround
Reproduced and root-caused to a clear area
Goes into the ranked backlog with evidence
Any S0: data loss, security or outage
S1 regression confirmed in the latest release
Spiking volume on a hot path with no workaround
When they hand you a vague bug in the debugging or take-home round, don't start fixing. State your rubric out loud first: “I'd grade severity, then impact on users, ARR, frequency and whether it's a regression, then timebox the repro.” You've just shown the prioritization judgment the role is built around before writing a line.
“I don't triage by who shouted loudest. I grade severity on the worst outcome, multiply by reach - users, ARR, frequency, regression - and let that produce the order. A single data-loss report outranks a hundred cosmetic ones and I can show you the math.”
Takeaway. Severity (worst outcome) × impact (users, ARR, frequency, regression) gives a defensible priority - so a single S0 data-loss report beats a flood of cosmetic noise.
Self-check
QOne user reports that an Agent edit silently overwrote files they hadn't saved. Forty other users report a misaligned icon in the model picker. Which do you work first and why?
Dedup, clustering and regression detection
After this you can compress a firehose of reports into a small set of real problems.
Three hundred reports rarely mean three hundred bugs. They usually mean a dozen real problems, each described thirty different ways by people who don't share your vocabulary.
Clustering is the step that makes everything downstream honest. If you prioritize a raw inbox, you reward whichever bug happens to be described in the most tickets, not the one doing the most harm. The skill is collapsing reports onto the underlying defect, then counting the cluster - that count is what makes a priority number defensible.
Cluster on signals, not on phrasingusers describe the same bug a dozen ways
- Symptom shape - “Tab stopped suggesting,” “autocomplete is dead,” and “no ghost text” are one cluster.
- Error signature - the same stack trace, error code or log line is the strongest possible join key.
- Version - pin every report to the Cursor build and, separately, the model version in use.
- Feature area - Tab, Agent, ⌘K, chat, @-context, indexing, the model picker, privacy mode.
Prose lies and paraphrases; a stack trace doesn't. When two reports carry the same exception or the same failing log line, they're almost certainly the same bug regardless of how differently the humans described it. Always pull logs and HAR captures into the cluster before trusting symptom text.
Canonical issue plus linked duplicatescount once, count right
Pick one canonical issue per cluster and link every duplicate to it. Resist the urge to just close dupes - each linked report is a unit of volume and a different repro environment and the live count is what you'll cite to engineering. A cluster of 1 and a cluster of 600 need the same canonical record but produce very different priorities.
- 1Open or find the canonical. One issue per real defect, named by symptom and area, not by the loudest ticket.
- 2Attach evidence. Roll the strongest repro, logs, versions and affected accounts up to the canonical.
- 3Link, don't delete. Point duplicates at the canonical so volume and ARR stay countable.
- 4Recount on every new report. Volume, ARR affected and trend direction update live - that's the prioritization input.
New bug or regression? Correlate with the timelineCursor ships fast, so regressions are constant
The single most useful question about a spike is “what changed?” Overlay the cluster's first-seen timestamps on two timelines: app releases and model-version swaps. A cluster that appears the hour a new build rolls out is a regression and jumps the queue. A cluster smeared evenly across weeks is a long-standing issue you're only now seeing clearly.
- Pattern in the cluster
- First-seen clusters tightly at a release timestamp
- Likely diagnosis
- Release regression
- Action
- Escalate as regression; flag the suspect build for bisect
- Pattern in the cluster
- First-seen aligns with a model-version swap
- Likely diagnosis
- Model regression - behavior changed silently
- Action
- Pin model version in the report; compare old vs new on a fixed prompt
- Pattern in the cluster
- Steady trickle across many versions
- Likely diagnosis
- Long-standing latent bug
- Action
- Prioritize on volume × ARR; no rollback urgency
- Pattern in the cluster
- Sharp spike, then decay, no release nearby
- Likely diagnosis
- External cause (provider outage, viral thread)
- Action
- Confirm upstream; communicate status, don't chase a code fix
| Pattern in the cluster | Likely diagnosis | Action |
|---|---|---|
| First-seen clusters tightly at a release timestamp | Release regression | Escalate as regression; flag the suspect build for bisect |
| First-seen aligns with a model-version swap | Model regression - behavior changed silently | Pin model version in the report; compare old vs new on a fixed prompt |
| Steady trickle across many versions | Long-standing latent bug | Prioritize on volume × ARR; no rollback urgency |
| Sharp spike, then decay, no release nearby | External cause (provider outage, viral thread) | Confirm upstream; communicate status, don't chase a code fix |
A model swap is an invisible deploy. The app version can be identical while behavior, diff quality or latency shifts because the backend now routes to a different model. If you only correlate against app releases, you'll misclassify a whole class of regression as a mysterious new bug. Always log the model version alongside the build.
On the messy-bug-batch take-home, narrate the collapse: “These 23 tickets are 4 clusters. Cluster A is 14 reports, all on build 0.42, all S1 Tab failures - that's a regression and it leads.” Showing the firehose-to-shortlist compression, with a count and a release correlation, is exactly the prioritization-judgment artifact the stage grades.
Takeaway. Cluster reports by symptom, error signature, version and area; keep one canonical with linked dupes for live counts; and correlate first-seen against release and model timelines to catch regressions fast.
Self-check
Automating triage with agent-assisted tools
After this you can operationalize the JD's “automated bug prioritization at scale using agent-assisted tools.”
The JD doesn't ask you to triage by hand faster. It asks you to drive bug prioritization at scale using agent-assisted tools - meaning you point Cursor and LLM agents at the firehose and supervise, rather than reading every ticket yourself.
This is the line that separates a strong candidate from a generic support hire. Cursor is an AI-native company building an AI-native product and they expect the quality function to be AI-native too. The interview reads your judgment with agents: do you wield them aggressively and do you reject bad output instead of pasting it into a brief?
The pipeline you should be able to describeingest → classify → cluster → rank → brief
Interactive diagram. Tab through its regions; each focused region shows its detail in the panel below.
Agents do the labeling and dedup; the human-owned score and the final S0 call are gates the pipeline can't pass on its own.
- 1Ingest. Pull raw signal from support tickets, the forum, Discord, social and in-product feedback into one store.
- 2Classify. An LLM tags each report with feature area, candidate severity and sentiment - the boring labeling that used to eat hours.
- 3Cluster. Embed reports and group by similarity, joining on error signatures where present, to collapse dupes automatically.
- 4Rank. Apply the severity × impact score per cluster, with volume and ARR joined from account data.
- 5Brief. The agent drafts the weekly quality brief: top clusters, trend arrows, suspected regressions - you edit and own it.
What the agent is genuinely good atthe heavy lifting worth delegating
Tagging area / severity / sentiment at volume
Clustering and dedup by semantic similarity
Drafting a candidate repro from a vague ticket
Summarizing a cluster's common thread for review
Confirming the repro actually reproduces
Final severity call on anything near S0
The number that goes in front of leadership
Deciding what to escalate and when
Human-in-the-loop isn't a hedge, it's the same judgment bar the interview grades. An agent that guesses severity is a triage assistant; an agent whose guesses you accept blindly is a liability that will mislabel an S0 as an S2 and bury it. You own the output the agent drafts.
The same rule guards the repro the agent drafts for you. An agent will happily generate a check that asserts nothing and passes green, and a green check that proves nothing is worse than no check. Determine the golden state - the input and the expected output - and feed that to the agent as the anchor, then read the generated code before you trust it.
Never trust an automated test that you didn't see fail.
Two failure shapes recur when an agent writes its own checks: it logs a failure instead of actually failing the run, or it wraps the assertion in a try-catch that swallows the error. The fix is engineering discipline. Keep the agent's context lean and pointed at the one task - a long, cluttered conversation can overwrite your instructions as the window fills - and run a validator step that executes the check, reads the output and reruns to confirm a real failure surfaces before you rely on it.
Build lightweight tooling, don't wait for a platformscripts and small dashboards beat a roadmap ticket
A Product Quality Engineer at a ~300-person hypergrowth company won't get a polished internal platform handed to them. The expectation is that you build the scrappy thing yourself - a script that pulls tickets, calls a model to classify and cluster and writes a ranked Markdown brief you can paste into the channel.
Split the model the way you'd split the work when you write that script. Reach for a larger reasoning model - a frontier Opus 4.x or GPT-5.x - to draft the high-level plan, then drop to a leaner, faster in-house model like Composer 2Cursor's in-house agentic coding model: frontier-level coding quality at high speed and low cost, built as a software-engineering specialist rather than a general-purpose model. to do the building. After plan mode you pick the model and click Build, which moves into writing the code. You pay for heavy intelligence where the thinking is and let fast intelligence churn out the rest.
import { tickets } from "./ingest"; // tickets from support, forum, Discord
import { classify, cluster, draftRepro } from "./agent";
// 1. agent classifies each report - you set the schema, it fills it in
const tagged = await classify(tickets, {
area: ["tab", "agent", "cmd-k", "chat", "context", "indexing", "model-picker"],
severity: ["S0", "S1", "S2", "S3"],
sentiment: ["angry", "confused", "neutral"],
});
// 2. group by semantic similarity, join on error signature when present
const clusters = await cluster(tagged, { joinOn: "errorSignature" });
// 3. score per cluster - the human-owned formula, not the model's guess
const ranked = clusters
.map((c) => ({
...c,
priority: sevWeight(c.severity) * impactScore(c), // your rubric
repro: draftRepro(c.canonical), // agent drafts, you verify
}))
.sort((a, b) => b.priority - a.priority);
// 4. you review ranked[0..n], confirm the repros, then ship the briefDon't let the agent own the score. The classify step can suggest a severity, but the priority formula and the final S0/S1 call stay human. An LLM that quietly downgrades a data-loss report to S2 because the user was polite about it is exactly the failure the loop is checking you'd catch.
Mine the backlog, rank it, then file the ticketsone plan-mode prompt does the triage and the paperwork
The same agent loop works against your own codebase, not just the inbox. Point Cursor's plan mode at the FIXME and TODO comments rotting in a service and let it produce the ranked test plan you'd otherwise spend a meeting arguing about. Plan modeA mode that makes no edits: it researches the codebase and produces an editable plan you review before any code changes. runs search-and-retrieval first, then writes a Markdown plan you refine before any code touches the repo - so the ranking is reviewable, not a black box.
Find all my FIXME and TODO comments in the alerting module. Determine the top five most critical. Create a detailed testing plan to make sure behavior stays consistent, then migrate to the new functionality while making sure nothing else breaks.
Plan modeA mode that makes no edits: it researches the codebase and produces an editable plan you review before any code changes. came back with the items already banded P0-P2, each carrying a problem statement and a per-item unit-test plan - the kind of line that reads like triage you'd defend: “notification policy reset silently swallows errors, so users think the reset succeeded when it failed.” That is severity reasoning, written for you, on real backlog debt.
Do the plan-mode ranking first, then append a final task that files the work. Through the Atlassian MCPModel Context Protocol. A standard that lets an AI agent pull in context from outside the repo, like Jira tickets or internal docs. you can say “based on the to-do comments in the alerting module, create a set of Jira stories,” or have it update a Confluence doc off the plan. Anything you'd do by hand creating a ticket, you can outline to the agent.
If it's a process you repeat, package it as a skill so the rank-then-file sequence runs the same way every time.
“I'd stand up a pipeline - ingest, classify, cluster, rank, brief - and let agents do the labeling and dedup that used to eat my morning. But the severity formula and the final call stay mine. The agent proposes a repro and a tag; I confirm the repro and own the number.”
Takeaway. Describe a concrete ingest → classify → cluster → rank → brief pipeline where agents do the labeling, dedup and draft repros - and you keep the severity formula, the repro confirmation and the final number.
Self-check
QCursor's JD asks you to “drive automated bug prioritization at scale using agent-assisted tools.” In an interview, what's the strongest way to show you understand that - and where do you keep a human in the loop?
AI-product failure modes to recognize
After this you can speak fluently about how an AI code editor specifically breaks.
A generic QA person triages crashes and 500s. Cursor's product breaks in ways that don't throw an exception at all - the diff is just wrong, the context was stale, the model quietly got worse. Naming these classes on sight is what marks you as a power user who debugs like an engineer.
The product round and the debugging screen both probe whether you actually understand how an AI-native desktop app fails. Memorizing a taxonomy isn't enough; you should be able to map a vague report onto a failure class fast, because that class points at the right logs and the right team.
The five failure classesand the signal that names each one
Hallucinated APIs that don't exist
Wrong or oversized diff - touches far more than asked
Edits land in the wrong file entirely
Tell: output is confident and plausibly wrong
Lost or stale context mid-conversation
Bad retrieval - the relevant file never made it in
Indexing didn't pick up new or moved files
Tell: the answer ignores code that's right there
Loops - repeats the same failing tool call
Runaway tool calls that never converge
Multi-file edit left half-applied
Tell: it's busy but never finishes or stops mid-edit
Latency on Tab / ⌘K / chat
Timeouts and streaming stalls mid-response
High token and cost usage per task
Tell: it works but is slow, partial or expensive
The fifth class is the AI-native onemodel regression
The class a non-AI QA background will miss entirely: a model regression. A model upgrade or a backend routing change silently shifts behavior, diff quality or latency while the app version is unchanged. Nothing crashes. Users just feel that “it got dumber,” and your only tell is a behavior change correlated with a model swap rather than a release.
Every failure report should be sorted into client, context/retrieval, agent-orchestration, network or model. The fastest debugging question is “which layer owns this?” A hallucinated API is model/generation; an ignored file is context/retrieval; a streaming stall is network or backend. The layer tells you which logs to pull and which team to hand it to.
Interactive diagram. Tab through its regions; each focused region shows its detail in the panel below.
Name the layer before you investigate - it points you at the right logs and the right team.
- “It invented a function that doesn't exist”
- Generation - model output; capture prompt, context window and the exact output
- “It ignored the file I clearly had open”
- Context / retrieval - check indexing status and what @-context actually included
- “It kept retrying the same edit forever”
- Agent orchestration - pull the tool-call trace and look for a loop
- “Responses stall halfway through”
- Network / streaming - HAR capture, check the SSE stream and timeouts
- “It got worse this week, same version”
- Model regression - correlate against model swaps, compare old vs new on a fixed prompt
When given an AI-product bug, classify before you investigate: “This reads like a context-retrieval failure, not generation, so I'd check indexing and the actual @-context payload before I blame the model.” Naming the layer first shows the mental model of the architecture - VS Code fork, client talking to model backends, retrieval feeding context - that the product round is looking for.
Don't reflexively blame the model. Most loud “the AI is dumb” reports root-cause to context or retrieval - the model never saw the file, so of course it ignored it. Blaming the model when the bug is in indexing sends the report to the wrong team and burns a day.
Takeaway. Sort AI-product bugs into generation, context/retrieval, agent, performance and model regression - the model-regression class (behavior shifts with no release) is the AI-native one a generic QA background misses.
Self-check
QA user says Cursor “ignored the file I had open and gave me a totally generic answer.” Which failure class is most likely and what do you check first?
Metrics and SLAs for a quality program
After this you can define what “good” looks like and how you'd measure it.
The behavioral and hiring-manager rounds want to know you'd build the system, not just work the tickets. That means having a clear answer to “how would you know if Cursor's quality is improving?” - with metrics, SLAs tied to severity and trends rather than snapshots.
A quality program is judged on two layers of metrics. Operational metrics tell you whether the response machine is working. Quality metrics tell you whether the product is actually getting better. Confuse them and you can have a beautifully fast support team shipping users a steadily worse product.
Operational metrics: is the machine working?how well we respond
- Time-to-first-response
- How fast a user hears back. The trust metric - silence is its own bug.
- Time-to-resolution
- How fast it's actually fixed or worked around, sliced by severity tier.
- Escalation rate
- Share of issues that needed an engineer. Rising can mean harder bugs or a thinner front line.
- Reopen rate
- Issues that came back after being closed. High reopen means we declared victory too early.
Quality metrics: is the product getting better?what the program exists for
- Top issue themes by volume and ARR - the ranked clusters and which money sits behind them.
- Regression count per release - are we shipping new breakage as fast as we fix old?
- Repeat-contact rate - users coming back about the same theme means it isn't really resolved.
- Theme trend arrows - is each top cluster shrinking or growing week over week?
A spike in a single theme is a leading indicator - it tells you a support wave is coming before time-to-resolution degrades. Time-to-resolution and reopen rate are lagging; they confirm the wave already hit. The value of clustering daily is that you can warn engineering about the wave while it's still a ripple.
Tie SLAs to severity, not to a flat clockthe worst issues get the fastest clocks
A flat “respond within 24h” SLA is malpractice for a quality program - it gives a cosmetic typo the same clock as a data-loss bug. Anchor each SLA to the severity tier so urgency and the rubric stay aligned.
- Severity
- S0 - Critical
- First response
- Minutes - page on call
- Resolution / mitigation target
- Mitigate same day; rollback if it's a regression
- Severity
- S1 - Major
- First response
- Within hours
- Resolution / mitigation target
- Fix or solid workaround within days
- Severity
- S2 - Degraded
- First response
- Within a day
- Resolution / mitigation target
- Scheduled into the backlog by priority score
- Severity
- S3 - Cosmetic
- First response
- Acknowledged
- Resolution / mitigation target
- Batched; no individual clock
| Severity | First response | Resolution / mitigation target |
|---|---|---|
| S0 - Critical | Minutes - page on call | Mitigate same day; rollback if it's a regression |
| S1 - Major | Within hours | Fix or solid workaround within days |
| S2 - Degraded | Within a day | Scheduled into the backlog by priority score |
| S3 - Cosmetic | Acknowledged | Batched; no individual clock |
SLAs inherit the severity tier so the rubric drives the calendar.
Report trends, not snapshots. “We have 312 open bugs” is noise - leadership can't act on a single number. “Top theme is down 40% over three weeks, but regressions per release ticked up” is a decision. A snapshot flatters or panics; a trend tells you whether the program is working.
When asked what you'd measure, split it cleanly: operational metrics for the response machine, quality metrics for the product, SLAs tied to severity and everything reported as a trend. Then add the leading-indicator point - “a theme spike warns me of a wave before resolution time slips.” That structure signals you've run a program, not just answered tickets.
“I'd track two layers. Operational - first-response, resolution, escalation, reopen - to know the machine works. Quality - top themes by volume and ARR, regressions per release, repeat-contact - to know the product's improving. SLAs hang off severity tiers and I report trends so we can see whether quality is actually moving, not just a snapshot.”
Takeaway. Measure operational health (first-response, resolution, escalation, reopen) and product quality (top themes by volume/ARR, regressions per release, repeat-contact) separately; tie SLAs to severity; report trends, not snapshots.