Feature request or bug? How to tell before it reaches engineering
The bug/feature boundary is a structural question, not a judgment call: a reproducible deviation from expected behavior traceable to existing code is a bug, and everything else needs a different queue before it wastes triage time.
Watari classifies every inbound ticket from Zendesk or Intercom into one of three categories before a human reads it: a structured bug, a code-actionable feature request, or an open-ended request that belongs in a product backlog. The distinction matters because mis-routing in either direction is expensive. Feature requests inflating the bug queue distort severity metrics; real defects labeled "enhancement" in Linear or Jira miss SLAs by days.
The decision boundary is structural, not a judgment call
A bug has two required components: a reproducible deviation from expected behavior, and a traceable cause in existing code. Strip either one and you no longer have a bug. A feature request describes desired behavior the product does not currently have, with no implied defect. Most teams treat the distinction as fuzzy, which is why it defaults to whoever handles the ticket first.
The structural test removes the fuzz:
- Repro steps exist. Can the reporter describe a sequence that reliably produces the behavior?
- Expected versus actual is stated. Is there a gap between what the product should do and what it does?
- The gap points at existing code. Is this a change to something already there, or a request to add something new?
If all three are true, you have a bug. If the third is absent, you have a feature request. If none of them are present, you have a vague complaint that needs clarification before it enters any queue.
This test is mechanical. It does not require engineering judgment to run. That is the point. Running it in triage, before a ticket reaches a GitHub issue or a Jira board, is what keeps the queues clean.
The third category most teams skip: code-actionable feature requests
There is a category between "clear bug" and "open-ended wishlist item" that most triage workflows collapse into one or the other, usually the wrong one. Consider: "The CSV export should include the date column." That is not a bug. No expected behavior is being violated. But it is also not vague product ideation. It is a specific, bounded change to existing code that an engineer can implement without a design cycle.
Watari calls these code-actionable feature requests, and it treats them like bugs for the purposes of the engineering handoff. The Mapped Issue meter treats code-actionable feature requests identically to bugs: both pass through the same two confidence gates (extraction confidence and code-location confidence) before the pipeline opens a draft pull request and routes the result to GitHub, Linear, or Jira.
The distinction matters operationally:
- Open-ended requests ("I wish the product had better reporting") belong in a product roadmap discussion, not an engineering queue. Routing them there skips triage entirely.
- Code-actionable requests ("Add the date column to the CSV export") are implementable without further specification. Treating them as bugs for handoff purposes means they get the same structured extraction, the same code mapping, and the same visibility to both support and engineering.
- Bugs get the same treatment as code-actionable requests at the pipeline level, but carry severity and SLA implications that feature requests do not.
Collapsing code-actionable requests into the open-ended pile wastes engineering capacity on specification work that was already done in the ticket. Collapsing them into bugs inflates severity counts and makes your defect rate look worse than it is.
The core concepts page defines a Mapped Issue precisely: a bug or a code-actionable feature request that passes both confidence gates. That definition is the product's formalization of this three-way split.
What structured extraction surfaces that manual triage misses
The structural test above is useful conceptually. Applied manually to a Zendesk or Intercom queue of 200 tickets per week, it is a full-time job. Structured extraction is the mechanical version.
When a ticket arrives, the ticket-to-bug pipeline reads the full conversation thread, including attachments, screenshots, screen recordings, and stack traces, and attempts to extract consistent fields:
- Severity
- Repro steps
- Expected versus actual behavior
- Customer impact
- Item type (bug or feature request)
The extraction model scores its own confidence in that extraction. A ticket that yields a high-confidence structured record with repro steps and an expected-versus-actual gap is a candidate bug. A ticket that yields a high-confidence structured record with desired behavior but no repro steps is a candidate code-actionable feature request. A ticket that the extraction model cannot confidently structure is routed for human review rather than silently dropped.
This matters for two reasons.
First, it runs before any human reads the ticket in detail. The support team does not need to make the bug-versus-feature call; the structured output makes it for them, with the reasoning visible in the extraction result.
Second, it is consistent. Manual triage has the problem that the same ticket reads differently to different agents depending on how the reporter wrote it. Structured extraction applies the same decision logic to every ticket, regardless of writing quality. A terse one-line ticket and a detailed four-paragraph report both end up with the same field structure if the information is there.
The failure mode is the ticket that lacks the information needed to extract either category confidently. The right response to that is a clarification request, not a guess. Pushing an under-specified ticket into the bug queue because it sounds vague and angry produces exactly the mismapping that inflates engineering triage cost.
Why mis-routing is expensive in both directions
The cost of feature requests landing in the bug queue is not just triage time. It is metric contamination.
If your severity-1 bug count includes feature requests routed there by an agent who thought "the button doesn't do what I want" sounded like a defect, your severity-1 count is not a reliable indicator of product stability. Engineering managers use that number to make staffing and prioritization decisions. Support leads use it to negotiate SLAs. A contaminated metric makes both decisions worse.
The cost runs the other direction too. A real code-breaking behavior labeled "enhancement" in Jira or Linear does not trigger SLA alerts. It sits in the backlog until a customer escalates again, at which point the original ticket is stale and the reproduction context has been lost. The engineering team has to reconstruct the bug from scratch.
Mis-routing is not a people problem. Triage agents are not failing when they make this call incorrectly. They are operating without a structural decision tool. The structural test, applied mechanically at intake, removes the ambiguity before any routing decision is made.
Making the triage decision visible to both teams
The triage decision is only useful if both support and engineering can see it and act on it. A bug classification that lives only in the support tool does not help the engineer who picks up the GitHub issue. A code-actionable feature request that lives only in the engineering backlog without the original support context attached does not help the PM who needs to explain the priority decision to the customer.
The routing integrations with Slack, Linear, and Jira exist to close this gap. When a Mapped Issue clears both confidence gates, Watari posts the structured extraction, code locations, and item type to whichever destination the workspace has configured. Engineering sees a Jira ticket with severity, repro steps, and the specific file and function implicated. Support sees the same Mapped Issue status in the dashboard. Neither team is surprised by what the other is working on.
For code-actionable feature requests specifically, the item type label in the routed ticket prevents the confusion that happens when an engineer picks up what looks like a bug and cannot reproduce it, because it was never a bug. The label communicates: this is a real engineering task, not a defect, and here is the specific change being requested.
See plans and pricing for the integrations included at each tier, and the routing and notifications docs for setup.
The practical output of getting this right
When the bug/feature boundary is enforced structurally at intake, three things happen:
- Severity metrics become reliable. Bug counts reflect actual defects. Engineering and support leadership can trust the numbers they use to make decisions.
- Code-actionable requests get implemented faster. They enter the engineering queue with full context and a proposed code location, not as vague feature asks that need a specification cycle before anyone can estimate them.
- Open-ended requests stop clogging engineering triage. They go to a product backlog or get closed with a clear explanation, rather than consuming engineering review cycles that should be reserved for defects and bounded changes.
None of this requires a new process. It requires applying a structural test, consistently, at intake. The test is not complicated: repro steps, expected versus actual, and whether the gap points at existing code. The complexity is applying it at volume without making it a human bottleneck. That is the problem structured extraction solves.
Get new posts in your inbox
One email when a new post lands. No spam. Unsubscribe in one click.
Frequently asked questions
- What is the difference between a bug and a feature request?
- A bug has reproducible steps, a stated gap between expected and actual behavior, and a cause traceable to existing code. A feature request describes desired new behavior without implying any existing defect. If repro steps or the expected-versus-actual gap is absent, the ticket is a feature request, not a bug.
- What is a code-actionable feature request?
- A code-actionable feature request is a bounded, implementable change to existing code that does not involve fixing a defect. For example, adding a column to a CSV export. It is specific enough to map to code and implement without a design cycle, so it receives the same structured engineering handoff as a bug.
- Why does mis-routing feature requests into the bug queue matter?
- Feature requests in the bug queue inflate severity metrics and distort the defect counts that engineering and support use to make staffing and SLA decisions. Real bugs routed to the feature backlog miss SLA alerts and lose reproduction context by the time they are escalated again.
- How does structured extraction surface the bug/feature distinction?
- Structured extraction reads the full ticket, including attachments and screenshots, and attempts to populate consistent fields: severity, repro steps, expected versus actual behavior, and item type. The extraction model scores its own confidence, routing low-confidence tickets for human review rather than making a silent guess.
Related posts
When Engineering Closes the Bug but Support Still Owns the Ticket
A merged PR is not a customer resolution. This post explains the gap between engineering 'done' and support 'done', and how to close Zendesk and Intercom tickets with a structured, deploy-confirmed RCA instead of a manual one-liner.
Support Ticket Still Open After Bug Fix Ships? Here's Why
A merged pull request is not a customer resolution event. This post explains the exact workflow gap between 'fix merged' and 'ticket closed', and how to close that loop automatically using production deploy confirmation rather than a human checklist.
Support Ticket Lifecycle After Escalation: The Handoff Is Not the Finish Line
When a support ticket reaches engineering, a second lifecycle begins: triage, code location, PR review, deploy confirmation, and customer notification. This post maps every checkpoint from the support lead's seat and explains where silence turns into churn.