No. 108Product strategy

Normalization of Deviance

Nothing went wrong last time. That’s the problem.

This is the history of one decision at an invented company. The decision says: payment changes need a security owner before merge. Nobody ever proposed changing it.

  1. February. A checkout outage on a Friday night. The fix goes in without a security owner, because the security lead is asleep and customers can't pay. Someone writes "hotfix, will review Monday" in the pull request. Monday is busy.
  2. April. A one-line change to a currency label in the payments service. The author tags it "copy change, no logic" and merges. It really is a copy change.
  3. June. A contractor's pull request touches the refund path. The reviewer sees that the last two payment changes merged without a security owner and nothing happened, and approves it.
  4. August. A coding agent is asked to add a discount field to checkout. It reads the recent history of the payments service, where the last three payment changes all merged without a security owner, and follows the pattern. Its pull request description says the change "follows existing conventions for this service."
  5. October. The discount field accepts negative values. No security owner ever looked at it.

No step on that list was reckless. Each exception had a reason, and each one turned out fine, until the one that didn't. By August, the decision was still on the books, still "confirmed," and no longer describing how the team worked. The exceptions had become the rule without anyone deciding they should.

The sociologist Diane Vaughan named this pattern the normalization of deviance in The Challenger Launch Decision, her 1996 study of the decisions behind the loss of the Space Shuttle Challenger. It is the process by which a departure from a standard, repeated without disaster, stops looking like a departure and becomes the standard.

Got away with it last time

The public record of how that happened at NASA is the report of the Presidential Commission on the Space Shuttle Challenger Accident, published in 1986. Its sixth chapter is titled "An Accident Rooted in History," and its first sentence sets out the shape of the problem. The flaw in the booster joint "began with the faulty design of its joint and increased as both NASA and contractor management first failed to recognize it as a problem, then failed to fix it and finally treated it as an acceptable flight risk."

The chapter then tracks that change flight by flight. After the second Shuttle flight, in November 1981, inspectors found erosion of .053 inches on a primary O-ring, the seal meant to keep hot gas inside the booster. That anomaly "was not reported in the Level I Flight Readiness Review" for the next flight. In February 1984, on flight STS 41-B, it turned up on two joints at once. A calculated "safety margin," the report says, "was the basis for approving Shuttle flights while accepting the possibility of O-ring erosion."

By early 1985, the way the problem was presented had shrunk along with the concern. At the review for one flight that February, "the previous 18-page analysis had been reduced to a one page chart" whose resolution read "acceptable risk because of limited exposure and redundancy." Later that year, after a primary O-ring failed to seal, a formal "launch constraint" was placed on the system. The Commission found it was then waived in "the strange sequence of six consecutive launch constraint waivers" before Challenger's flight, "permitting it to fly without any record of a waiver, or even of an explicit constraint."

The Commission's summary of the reasoning is a single line: "NASA and Thiokol accepted escalating risk apparently because they 'got away with it last time.'" It quoted Richard Feynman, one of the commissioners, on how that logic works: "We can lower our standards a little bit because we got away with it last time."

One more finding matters for anyone who keeps records. NASA's tracking carried forward only anomalies that were "outside the data base" of prior flights. In effect, once erosion had happened often enough, it no longer counted, and the report says that rule "allowed major problems to be removed from, and lost by, the reporting system." The record system itself treated the repeated deviation as normal.

Decisions wear away by exception

Product decisions rarely get overturned in a meeting. Nobody proposes "payment changes no longer need a security owner." What happens instead is the list at the top of this post: an exception with a good reason, then a smaller exception with a weaker one, then an exception justified by the earlier exceptions. Each one is decided locally, by one person, in one pull request, and none of them is recorded as a decision. The original decision stays confirmed while the practice moves away from it.

Three things make this hard to see from inside a product team.

The exceptions live in different places. The hotfix is in an incident channel, the copy change is in a pull request label, the contractor's approval is in a review comment. People do see them as a series, but as a series of precedents, not as a series of exceptions. Nobody lines them up next to the decision, the way the Commission eventually lined up six waivers against the launch constraint.

Success is the evidence. Every exception that ships without an incident becomes an argument for the next one. That is the "got away with it last time" logic, and it feels like learning. The difference is that nobody asked whether the safeguard was still needed. They only noticed that skipping it hadn't hurt yet.

The record keeps saying the old thing. A decision log that shows the rule as confirmed, with no trace of the exceptions, is the "data base" problem in miniature. The record is accurate about what was decided and silent about what is happening.

Agents learn the deviation as the norm

Coding agents make the slide faster, because of how they learn what a team does. An agent reads the codebase and its history. It doesn't see the incident channel where the hotfix was excused, or the reasoning behind the label on the copy change. It sees the last three payment changes, all merged without a security owner, and draws the reasonable conclusion. In the list at the top, step 4 is the first time the exception was made by someone with no idea it was an exception.

Our essay on the modern product development lifecycle describes where this is headed: as agents show up in every team, "[r]eview gates become rules that agents check on every change." That only works if the rule the agent checks is the decision, not the recent pattern. An agent that checks the pattern will enforce the deviation, faithfully and at scale. We've written about copying the form without the reason. This is the step after: copying the exceptions as if they were the form.

Where Brief fits: an exception can meet the decision

Brief is the product strategy agent. The homepage says it "captures decisions where they happen, connects them into one graph, and acts on them." Brief doesn't gate merges. It sees an exception when someone asks it, an agent or a person, and with GitHub connected it also reads incoming pull requests for possible conflicts with decisions tagged important or strategic. When a change does meet the decision, it meets it while the change is being made, instead of the pattern being discovered months later.

Agents ask what was decided. Coding agents set up with Brief call brief_ask before they write code. On the homepage, D-198 says "Payments changes need a security owner before merge," and an agent asked to add per-seat pricing to the checkout API notes: "D-198 applies, so I'll request a security owner on the PR." That is step 4 of the list, done the other way. The agent didn't infer the rule from what recent pull requests got away with. It asked what was decided.

A deviation gets flagged as a deviation. brief ask --mode check checks a proposed change against existing decisions and flags conflicts. If the June reviewer had run that check on "merge this refund change without a security owner," it should have come back as a conflict with the decision. The reviewer could still approve it, but the approval would then be an exception someone chose, with the decision in view. The check only runs when someone asks for it, which is why agents asking by default matters most.

An exception can be recorded as one. When a team really does mean to make an exception, it can record it as a decision, with its own Why?: "Hotfixes during an outage can merge first and get a security owner within one business day." That turns the February exception from a precedent into a rule with a boundary. And the original decision can carry a Re-evaluate when condition, so the team states in advance what would justify changing the rule, instead of letting a run of exceptions decide.

Recorded exceptions stay on the record. An exception recorded as a decision sits in the same graph as the rule it bends, so the next person or agent that asks about payment changes can get both. A recorded decision's History shows its status changes, who made them, and any reason given. With Proactive Brief turned on, Brief can also send notices about decisions that may need reconfirming and possible contradictions with existing decisions, including ones it finds in incoming pull requests against decisions tagged important or strategic, capped at two interruptions a week. That check reads what a pull request says, not who reviewed it. A payment change merged without a security owner can pass unflagged, and it doesn't change the decision's status.

None of this stops a team from normalizing deviance. A conflict flag can be dismissed, and a team that dismisses it every time is doing exactly what the list describes, only with better records. What Brief changes is that an exception someone checks shows up as an exception, and an exception someone records has a place to live, with a reason and a boundary. Deciding is still the team's job.

If you looked at the last ten changes that touched your most important rule, how many of them followed the decision, and how many followed the change before them?

Objections

Objection 1

What is normalization of deviance?

Normalization of deviance is the process by which a departure from a rule or standard, repeated without harm, gradually stops being seen as a departure and becomes the accepted way of working. Sociologist Diane Vaughan named it in The Challenger Launch Decision (1996), her study of the decisions that preceded the loss of the Space Shuttle Challenger.

Objection 2

How did normalization of deviance contribute to the Challenger accident?

The 1986 Presidential Commission report found that O-ring erosion in the Shuttle's solid rocket boosters went from an unrecognized problem to "an acceptable flight risk" over several years of flights. It found that "NASA and Thiokol accepted escalating risk apparently because they 'got away with it last time,'" and that six consecutive launch constraint waivers preceded Challenger's flight.

Objection 3

How does normalization of deviance happen in product teams?

In product teams, decisions usually erode through exceptions. A hotfix skips a required review, a small change skips it because it seems too minor to need one, and later changes skip it because earlier ones did and nothing went wrong. The exceptions are made by different people in different places and are rarely recorded as decisions, so the original rule stays on record while practice moves away from it.

Objection 4

Why do coding agents make normalization of deviance worse?

Coding agents learn a team's conventions largely from its codebase and history. If recent changes skipped a required step, an agent sees the skipped step as the convention and follows it, without knowing the earlier skips were exceptions. That turns a series of human exceptions into a pattern applied automatically.

Objection 5

How does Brief help prevent normalization of deviance?

Coding agents set up with Brief call brief_ask before writing code, so they check the recorded decision instead of the recent pattern. brief ask --mode check flags proposed changes that conflict with existing decisions. Teams can record a deliberate exception as its own decision with a reason, add a Re-evaluate when condition to the original, and see a decision's status changes in its History. Brief shows exceptions that someone checks or records, and, with GitHub connected and Proactive Brief turned on, can flag a pull request whose title or description conflicts with a decision tagged important or strategic. It doesn't check who reviewed a change, and the team still decides whether an exception becomes the rule.


Previously
No. 107

Jevons Paradox

Make something cheaper to use, and you’ll find more uses for it.