Status accuracy: when 'done' and the repository disagree

Stefan-Iulian Tesoi · · 6 min read

An old handwritten register lying open, its foxed pages closely written in ink — a record of what happened, kept apart from the thing it describes and reconciled with it by nobody

Because the status is an assertion typed into one system about work that lives in another, and nothing compares them. Status accuracy is usually treated as a discipline problem, and it is a data-integrity problem: a tracker holds no reference into the repository, so a row can say done while nothing behind it exists.

That reframing matters because discipline problems are addressed by asking people to be more careful, and this one is not improved by care.

How does a ticket end up done when the code is not?

Somebody finished working and said so. Finishing feels identical whether the acceptance criteria were met or merely approached, and no part of a normal tracker knows the difference.

Databases solved this a long time ago and gave it a name. A foreign key constraint, in the PostgreSQL documentation's words, "specifies that the values in a column must match the values appearing in some row of another table", and that is what maintains referential integrity between them. Your backlog has no such constraint. The status column references nothing, and the thing it is about — a diff, a merge, a deployed behaviour — lives in Git, in a different system, with no relationship the board can enforce.

So a tracker stores a denormalised copy of a fact whose source of truth is somewhere else, and denormalised copies drift. Nothing here is anyone's fault, which is exactly why asking a team to be more careful does not fix it.

Why status accuracy decays in one direction

Because status only ever moves forward. Errors do not cancel out; they accumulate on the optimistic side.

Watch which transitions actually happen in a week. Items move from Ready to In Review to Done all day. The reverse transition exists in every tool and is used a fraction as often, because moving something back from Done is an admission with an audience, and because by the time anyone notices, the sprint it belonged to has closed.

Random error would be tolerable, since it would cancel out across a board. Status error does not cancel. Every mistake points the same way, so a backlog does not get noisier with age — it gets more optimistic, and so does every roadmap derived from it.

This is what makes project tracker accuracy different from ordinary data quality. A customer database with a 3% error rate has some records wrong in both directions. A board with a 3% error rate has 3% of its work claimed and not delivered, and a roadmap built on it is wrong by 3% in the direction that hurts.

What does the divergence actually cost?

Two opposite failures, and the second is the expensive one because it is self-reinforcing.

The board saysThe repository saysWhat the team doesWhat it costs
DoneNothing implements itSkips it — it shippedA customer finds the gap, months later
Nothing, or still openShipped weeks agoBuilds it againDuplicated work, and a merge conflict nobody expected

The first is the one people fear and the rarer of the two. The second is ordinary: work gets done without an item, or an item is finished and never moved, and the board quietly understates reality.

What both produce is the real cost. Once tickets marked done incorrectly are common enough to notice, people stop believing the board and start asking each other instead — and that is the failure that does not recover on its own. A board nobody reads is a board nobody corrects, so accuracy falls further, which drives more people to ask each other. Trusting the board is not a virtue to be encouraged in a team. It is the mechanism that keeps the board maintained, and it is load-bearing.

How do you detect it without reading every diff?

Make the link a by-product of committing, so the comparison happens continuously instead of as an audit somebody has to remember.

The cheap version has three parts, and none of them is a new meeting:

None of this checks whether the code does the right thing, and it is important to be clear about that. It checks that something exists. The periodic comparison that catches the rest — three lists, and what appears in only one — is set out in definition of done when an agent wrote the code, and the item-side defects that make the mapping impossible in the first place are in a backlog an agent can read.

Frequently asked questions

Is this worse with agents or with people?

Worse in rate, better in traceability. Coding agents produce far more status events per week, so a board drifts faster in absolute terms. Against that, agent work is commit-linked by construction and its evidence is written down rather than remembered, which makes the comparison cheap. The net result is better than a human-only team if the link exists, and worse if it does not.

Can the check be automated?

Partly, and knowing which part matters. A machine can check that every item marked done has commits referencing it, that the commits touched the paths the item named, and that the commands the item claims were run appear with exit codes. It cannot check that the change satisfies the intent, because that requires knowing what was wanted, which is the thing that never fully makes it into the item.

What should happen when divergence is found?

Reopen the item with a reason rather than editing the status quietly. A quiet correction loses the one piece of information worth having, which is that the board was wrong and in which direction. It is also worth not rewriting the delivery record of a sprint that has already closed: last month's velocity is a historical fact, and correcting today's board should not edit it.

How often is worth checking?

Monthly for the full comparison, and never for the rest if the commit link is in place. The audit is boring, takes about an hour, and finds most of what it will ever find in the first twenty minutes. Running it quarterly is usually a sign that it has stopped being read, at which point the board has already lost the trust that keeps it accurate.