Bug vs feature is settled by what was written down

When an engineer says works as designed and a customer says broken, bug vs feature is decided by the written expectation. Where none exists, decide first.

One glass beam splits into three paths, with the unresolved branch glowing orange

An engineer says the behaviour is intended. A customer says it is broken. Each is reporting a fact about themselves, and neither classifies the report. A bug is behaviour that contradicts a written expectation. Where nothing was written, the report is a decision the product owner has not made yet, and it stays a dispute until somebody makes it.

“Works as designed” is a claim about a document

When an engineer closes a report as intended behaviour, the sentence asserts that a design exists and that the behaviour matches it. Ask to see the design. In a team that has been shipping for a while the answer is frequently a commit message, a chat thread, or a memory of a conversation in which somebody decided the export would round to two decimals. That is a design in the engineer’s head, and the customer was never party to it.

None of this is an accusation of bad faith. The engineer is right that the code does what it was written to do. What they cannot know from inside the codebase is whether anybody promised the customer something else, and a software bug is defined against the promise, never against the code. Code always does what it does.

So the first move on a disputed report is to find the written expectation, if there is one: the acceptance criterion on the story, the help article, the label on the button, the error message the customer should have seen. Any of those is a document a customer could reasonably have read. A commit message is not.

Three answers, and the third is the common one

A disputed report can be classified in exactly one of three ways, and the classification follows from whether a written expectation exists and what it says.

The reportClassificationWhat happens nextWho decides
Contradicts a written expectation the customer could have readBugSeverity from the evidence, priority against the sprint, a fixThe engineer, once the expectation is pointed at
Matches the written expectation; the customer wants something elseFeature requestThe backlog, with the customer told which stage it sits inProduct
Nothing written either wayNot yet classifiableA decision about what the behaviour should be, written down, and then one of the rows aboveProduct, and nobody else

Rows one and two rarely cause the argument. When the help article says the export rounds to two decimals, a customer who wants four has a feature request and knows it. When the acceptance criterion says the total includes tax and the export omits it, the engineer has a bug and knows it. The heat is in row three, and row three is where most disputed reports live, because most behaviour in a product was never specified in a place a customer could read.

One class of report skips the table. A crash, a failed request, a lost record or an error on the screen contradicts an expectation nobody has to write down, and is a bug whatever the documentation says or omits. Row three is for behaviour that completed and is disputed.

The failure mode is to force row three into one of the others. Called a bug, it puts a product decision in an engineer’s fix queue, and the engineer makes the decision by choosing what “fixed” means. Called a feature request, it tells a customer that the thing that broke their invoice is a nice-to-have. Both are the same mistake wearing different labels: a decision made by classification instead of by deciding.

Deciding first makes the classification stable

The way out of row three is to make the decision the report exposed. Should the export include tax? Somebody with authority over the product answers, writes the answer where the next reporter can read it, and only then is the report classified: a bug if the current behaviour contradicts the new sentence, a feature request if it matches it and the customer wanted otherwise.

This is the part that feels slow and is the opposite. A report classified without a decision comes back. The next customer to hit the same behaviour opens the same dispute, the engineer says the same thing, and support reopens the same thread. Once the expectation is written, the second report is classified by anybody who can read, because the answer is a sentence somebody can point at. Acceptance criteria written before the work does this for new features; for behaviour that predates the criteria, the disputed report is the moment the criterion gets written.

The distinction between an issue and a bug earns its keep here. Everything a customer sends is an issue. Only the subset contradicting a written expectation is a bug, and the classification is a property of the issue plus the document, never of the issue alone.

What the report has to carry before anybody argues

Many disputes start because the report describes an outcome and the engineer tests a behaviour. “The invoice total is wrong” is an outcome. Whether it is a bug depends on what the customer did, what they expected the total to be, what the screen showed, and whether the request behind it failed or returned a number the customer disagrees with. Those are four different reports and only some of them are bugs.

So before the classification argument, the report needs expected and observed, in the customer’s words, and the conditions around them. The conditions are the half a customer cannot supply, and asking them for a browser version is a reply that costs a day. When the report is filed from the page, evidence capture puts the network log on the ticket, each request with its status, beside the browser and viewport the customer was using, and the engineer reads whether the request behind the total failed or returned a value the customer disputes. A failed request is a bug in any row. A completed one whose value the customer disputes is a row-three dispute.

Every row-three report costs product one decision

Row three needs product, every time, and no support lead can staff that away. An engineer cannot classify it, because they would be deciding what the product does from inside the fix queue. A support agent cannot classify it, because they would be deciding what the product promises from inside a ticket. The person who owns what the product should do has to spend time on each report that lands in the unspecified row, and that time cannot be scheduled away by a better template or a faster tool.

What the process can do is make each such report cost one decision rather than several. It arrives with the evidence, so the question is about what the behaviour should be rather than about what happened. The decision is written where the next reporter can read it. And the customer who raised it watches the report move through its stages instead of being told “working as intended” and hearing “go away”, which a client portal showing the stage and the comments marked for them makes routine. The dispute is between the product and a sentence nobody had written, and the engineer and the customer are both standing in for it.

Common questions

What is the difference between a bug and a feature request?

A bug is behaviour that contradicts an expectation written somewhere the customer could have read it: an acceptance criterion, a help article, a label, an error message. A crash, a failed request or lost data is a bug without any document. A feature request is behaviour that matches the written expectation while the customer wants something else. Where nothing is written, the report is neither until the product owner decides what the behaviour should be.

Who decides whether a report is a bug or a feature?

When a written expectation exists, anybody can classify the report by comparing the behaviour to the document. When none exists, the decision belongs to whoever owns what the product should do, because an engineer classifying it would be deciding product behaviour from the fix queue, and a support agent would be deciding it from a ticket.

What does works as designed mean in bug triage?

The phrase asserts that the current behaviour matches a design. The useful response is to ask for the design. If it is an acceptance criterion or documentation the customer could have read, the report is a feature request. If it is a commit message or a memory, no written expectation exists and the report needs a product decision.

How should you respond to a customer who reports intended behaviour as a bug?

Point at the written expectation the behaviour matches, tell them the report has been logged as a request, and let them see its stage. If no written expectation exists, say that a decision is being made rather than that the behaviour is intended, because intended by whom is exactly what the customer is disputing.

Can the same report be a bug for one customer and a feature request for another?

Only when the documentation each customer could have read differs, for example a plan tier whose published behaviour differs from another tier's. Two customers reading the same documentation get the same answer. A contract that promises one customer behaviour the product has never had is a scope gap, tracked as a request with a date; calling it a bug hands the product decision to the engineer.

The Notarus team

The people who build Notarus. We write up the decisions behind the product when the reasoning is worth more than the changelog line.

Keep reading

Reports with the evidence attached.

Start free, one script tag.

<script src="…/widget.js" data-key="pb_pub_…">