Engineering metrics caveats — generated by the render, not written by a person

Every dashboard has a page of disclaimers that nobody reads. This one is assembled from what the render actually did to this window, so a caveat that does not apply is absent rather than greyed out — which is the only thing that keeps the ones present worth reading.

deckgauge · Board · Team Focus
KeyCaveat
Window2026-04-01 to 2026-06-30.
Two grainsThe delivery funnel and the shipped ratio count 37 FEATURES. Every other figure counts 122 issues. The two are not meant to match.
SystemsJira and Azure DevOps — 122 tasks after de-duplication.
De-duplication14 tasks existed in both systems and were merged on a normalised title: keys stripped, brackets removed, punctuation collapsed.
Late joinerEngineer C: first recorded ticket movement 2026-05-14. Every rate for this person runs from that date, not the full window.
Unclassified16 tasks carry no classification. They are counted as their own class rather than assumed into one of the others.
Attention daysA share-of-attention proxy, not effort. Tasks overlap.

A window's own caveats. A different window produces a different list.

Written by the render, not by a person. A caveat that does not apply to this window is absent rather than greyed out.

What it measures, and where the data comes from

It measures the render. Each entry is emitted because a specific condition held while the widgets on this page were computed — a task existed in both trackers, a person's first activity fell inside the window, a board state was unrecognised.

Two entries are unconditional because they are true of the method rather than of the data: attention-days are a proxy, and lines-changed is unavailable. Dropping either would let someone quote a number the view cannot support. (Window and Systems also appear on every render, but they describe what this render covered rather than a limit on what it can support — so four entries are always present, and two of those four are caveats in the strict sense.)

Why generated rather than authoredA fixed list of disclaimers gets skimmed once and then stops being read — which makes it worse than nothing, because it looks like disclosure while functioning as decoration. Tying each entry to something that happened to this particular window is what keeps the list short enough to read and specific enough to act on. No late joiner, no late-joiner entry.

The caveats, and what each one is protecting you from

KeyEmitted whenWhat it prevents
WindowalwaysQuoting a figure without the period it covers.
Commit windowcommit data stops before the window endsReading a data boundary as inactivity — the two are indistinguishable in a chart.
Two grainsthe page is showing both features and issuesReading two deliberately different totals as a bug. See below.
Cancelled before startingany task was cancelled with no work recordedAn exclusion nobody can see, which is indistinguishable from a defect.
SystemsalwaysNot knowing which trackers the count spans.
Both systemsone system alone would have found fewer tasksUnder-counting a window that spans a migration.
De-duplicationtasks were merged across systemsAssuming a task in two trackers was counted twice.
Task agea migration cutoff is configuredTreating an importer's changelog burst as work.
Identitylogins were resolved to fewer peopleTrusting a per-person split without knowing identities were merged — and the entry says the view cannot show you which merges it made.
Late joinera person's first activity falls inside the windowReading a start date as idleness. One entry per person, naming the date.
"Approved"the board has an Approved stateGuessing whether that state means groomed or completed — it reports what transitions out of it actually did.
Unmapped statesa raw state is not in the stage mapA delivery funnel whose middle bars are empty for a configuration reason.
Unclassifiedany task carries no classificationAssuming unclassified work was quietly folded into another class.
Attention daysalwaysConverting a share-of-attention proxy into effort or FTE.
Not measuredalwaysQuoting lines changed or pull-request size from this view. Azure DevOps reports zero additions and deletions on nearly all pull requests and counts files rather than lines, so both are omitted rather than estimated.

That is the complete set — fifteen possible entries, of which four appear on every render (Window, Systems, Attention days and Not measured) and the other eleven appear only when they apply.

The one that matters most: two grains

Two totals on one page that are not meant to match is the single thing readers most often report as a bug, so it gets the longest entry:

Two grainsThe delivery funnel and the shipped ratio count features — issues rolled up to the top-level item they hang under, so work on a sub-task counts for its epic. Every other figure on the page counts issues. A feature is listed when anything under it moved in the window, but its stage is read from every issue under it, including ones the window does not contain — so a feature is only "in production" when nothing beneath it is still open.

That last clause is the part that surprises people. A feature can appear in the window because one sub-task moved, and be placed in the funnel using children that were never in the window at all. That is correct — a feature's stage is a fact about the feature, not about the window — and it is why the funnel's shape can change without any in-window activity explaining it.

How to read it

Read it before quoting anything from the page, and read it as a list of things that are true rather than a list of apologies. Most entries are statements about coverage — which systems, how many tasks, whose rates start when.

Treat an Unmapped states entry as blocking. It means the delivery funnel's shape is a configuration artefact, and the entry names both the states and the fix.

Treat an Identity entry as a caution on every per-person widget, and note its unusual honesty: it tells you merges happened and that it cannot show you which ones. A wrong merge is as damaging as a missing one.

Note the limitation the late-joiner entry declares about itself: commits are not yet counted in the first-activity date, so someone who was committing before their first ticket movement gets a window that is too short and a rate that is flattered.

What it tells you over time

A caveat list that gets shorter across windows is a board being cleaned up: states mapped, epics marked, classifications filled in. That is the trend to drive, and it is the closest thing to a data-quality score the view offers.

A new entry appearing is worth investigating on its own. An Unmapped states entry that was not there last window means someone added a workflow state; an Identity entry that appears means logins started resolving differently.

Check the raw data Every number here is reproducible. Add Every Task, and Why — the ledger — to the same board and the same period. It lists every task with its raw state from Jira or Azure DevOps sitting beside the delivery stage it was mapped to, its class, the reason the classifier gave, its owner, its source system and its move count, and it filters by person, class and stage.

For this widget: the caveats describe the population in aggregate — the ledger is that same population row by row. When a caveat names a count (14 merged, 16 unclassified), the corresponding filter in the ledger shows you exactly which tasks it means.

The raw state sits next to the mapped stage deliberately: that is what lets you see how a state was interpreted and argue with it, rather than being handed a stage and asked to trust it. See the ledger reference for the full column list, or Ledger & caveats for the method behind it.

Example situations

1. Circulating the view outside the team

What you're seeing: a quarter's Team Focus view that you are about to put in a board pack. The numbers are good. The caveats say 31% of tasks were off-board, 16 are unclassified, and one person's rates run from six weeks into the window.

How to react: send the caveats with it. Every one of those three facts is something a reader would otherwise assume the opposite of, and each is the kind of thing that destroys trust in a dashboard when discovered later rather than disclosed upfront.

Managerial playPaste the caveat block into the appendix verbatim rather than summarising it — it is already written in plain language, and paraphrasing is how "attention-days are a proxy, not effort" becomes "effort data". Lead the summary with the grain statement if the pack quotes both a feature figure and an issue figure, because that is the question you will be asked. The habit worth building is that disclosing the limits with the numbers is what buys the numbers credibility; a dashboard that discloses nothing gets challenged on everything.

2. Two widgets that appear to contradict each other

deckgauge · Team Focus
WidgetTotalGrain
Where the Work Ended Up37features
Landed in Production37features
How Work Was Classified122issues
Never Moved122issues

Two totals on one page, neither wrong.

What you're seeing: 37 in two widgets and 122 in two others, on one screen. It looks like a filtering bug and it is not — it is two grains, reported as such. Three of the four widgets say which grain they are on their own face, and this widget prints both numbers together.

How to react: check the Two grains caveat before raising it as a defect. If it is present, the discrepancy is explained and expected.

Managerial playWhen someone brings you this as a bug, show them the caveat rather than explaining the roll-up from memory — it is faster and it teaches them where to look next time. Then use the right grain for the question being asked: features for "did we deliver what we promised", issues for "where did the attention go". Mixing them in a single sentence is the actual error, and it is one people make in decks far more often than the dashboard makes it.

Frequently asked

What are the limitations of these engineering metrics?
Method & Caveats lists them for the specific window you are looking at, generated by the render rather than written in advance. Two entries are unconditional because they are true of the method: attention-days are a proxy rather than effort, and lines-changed is unavailable.
Why does the caveat list change between windows?
A caveat that does not apply is absent rather than greyed out. A fixed list of disclaimers gets skimmed and stops being read; a list where every entry corresponds to something that happened to this window keeps its weight.
Why do two widgets on the page show totals that do not match?
Because they count different things, and the Two grains caveat says so explicitly. The delivery funnel and the shipped ratio count features; every other figure counts issues. It is the discrepancy readers most often report as a bug.
What does the commit-window caveat mean?
That commit data stops before the window ends, so commit and active-day figures are bounded there. It is a data boundary, not inactivity — a distinction the widget makes explicitly because the two look identical in a chart.

Related widgets

Last updated