Back to blog
Keep work moving

How Do You Find the Ticket Nobody's Touched in Three Weeks?

It's been "In Progress" for three weeks and looks exactly like one updated an hour ago. Here's how to actually find it.


An In Progress ticket titled Shared API behavior that moved an hour ago, beside the same work flagged gone quiet for three weeks with no comment, no commit, or status change, over a pixel-art fjord

A ticket has said “In Progress” for three weeks. It says exactly the same thing a ticket that moved an hour ago says. Nothing about the board distinguishes the two, which means finding the stalled one requires either luck or a mechanism specifically built to look for silence, since the board itself was never built to show it.

A stalled ticket is one that’s gone quiet without being resolved, not just old. Thor flags tickets with no recent activity, comment, or status change against what’s normal for that kind of work, rather than applying one fixed day-count rule to everything. That distinction, stalled versus just slow, is the entire difficulty in finding one, and it’s worth being precise about before assuming a board review or an age filter solves it.

How do you find the ticket nobody’s touched in three weeks?

By looking specifically for silence relative to what’s normal, not by scanning for age or reading through status labels, which tell you almost nothing about whether a ticket is actually stuck. A ticket’s status field answers “what phase is this in.” It doesn’t answer “has anything actually happened here recently,” and those are different questions with different answers on plenty of tickets. Finding the genuinely stalled one means checking for an absence, no comment, no commit, no status change, over a stretch of time that’s unusual for that specific kind of work, not applying one blanket threshold and hoping it catches the real problem without also flagging half the board as false alarms.

Why are stalled tickets invisible in a normal board view?

Because a kanban board shows status, not silence, and those two things look identical from the outside. A ticket sitting in “In Progress” for three weeks renders exactly the same as one that moved an hour ago: same column, same color, same label. The board has no visual language for “this hasn’t changed in a while,” only for “this is currently in this phase.” Someone would have to actively check each ticket’s last-updated timestamp individually to notice the difference, and that’s not a habit most boards encourage or most people have time for across every item they’re not personally working on.

That’s a structural property of the format, not a failure of any particular board tool. A board is built to answer “what’s where,” which it does well. It was never built to answer “what’s stopped without anyone deciding it should,” which is a genuinely different question that requires comparing a ticket against its own history, not just displaying its current state.

Why isn’t “stalled” the same thing as “old”?

Because a ticket can sit untouched for a perfectly good reason, waiting on a dependency, deliberately deprioritized, correctly quiet over a weekend, and treating every old, untouched ticket as a problem produces so many false alarms that the real signal gets lost in the noise. A ticket that’s been open for three weeks because it’s genuinely low priority and nobody’s supposed to be working on it yet isn’t stalled in any meaningful sense. A ticket that’s been silent for three days when it should have had daily activity, because someone’s actively supposed to be working it, is a much sharper signal than either ticket’s raw age on its own.

That’s the real detection problem: distinguishing a ticket that’s stalled from one that’s simply slow requires knowing what’s normal for that specific kind of work, not applying a single day-count threshold to every ticket regardless of what it actually is. Flow-metrics research on tracking work item age makes a related distinction worth borrowing here: age is a leading indicator for work still in progress, separate from cycle time, which only applies once something’s finished. The point of tracking age at all is to catch a problem while the work is still live and cheap to unstick, not to retroactively explain why something took long after it’s already done, which is a much less useful use of the same underlying signal.

One ticket, three weeks of silence

Take a concrete, real-shaped example. A ticket sits in “In Progress,” assigned to an engineer, for three weeks. The board shows nothing unusual: correct column, correct owner, no red flags. What actually happened: two and a half weeks ago, the engineer hit a blocker, they needed a decision from someone on a related team about how a shared API should behave, and mentioned it once, briefly, in a Slack thread that nobody followed up on. The engineer moved on to other work in the meantime, reasonably, since there was nothing productive to do on the blocked ticket. Nobody updated the ticket to say it was blocked, because in the moment, updating the ticket felt like a formality separate from the actual problem, which was getting an answer from the other team.

Anyone looking at the board sees “In Progress,” same as always. Nothing there indicates that the ticket has been functionally frozen for over two weeks, waiting on a decision that got mentioned once and never chased. The engineer isn’t hiding anything and isn’t being careless. The board format simply has no way to show “this has been silently blocked” as distinct from “this is actively being worked.”

What does Thor actually surface, and how does it decide “stalled” versus “fine, just slow”?

By comparing a ticket’s actual activity, comments, commits, status changes, against what’s typical for tickets like it, and flagging the gap when it’s unusual, not when it simply crosses a fixed day count. In the example above, Thor would see a ticket assigned to an active engineer with no comment, no commit, and no status change for over two weeks, a pattern that doesn’t match the normal rhythm of tickets this engineer typically keeps moving. That mismatch, not the raw age of the ticket, is the actual signal worth surfacing.

What a fixed day-count rule catches What Thor’s actual comparison catches
Every ticket older than, say, 14 days, regardless of context A ticket that’s gone quiet relative to how tickets like it, or this specific owner’s tickets, normally move
Plenty of false alarms: legitimately low-priority or deliberately paused tickets The three-week silent ticket above, distinguished from a similarly old ticket that’s correctly waiting its turn
No sense of what’s actually unusual for this specific ticket A signal calibrated to what normal activity looks like for that kind of work

What happens once a ticket gets flagged?

Thor surfaces it with context, who owns it, when it last moved, whatever signal triggered the flag, and a person decides what’s actually going on. Thor doesn’t reassign the ticket, close it, or silently change anything about it. The entire intervention is visibility: putting the specific ticket in front of someone with enough detail to judge quickly, rather than leaving it to sit exactly as invisible as it was before. In the three-week example, that means the ticket surfaces with a note that it’s gone quiet since a specific date, prompting the engineer or their lead to check in, most likely surfacing the forgotten Slack thread and the still-unanswered question, rather than the ticket continuing to sit for another three weeks under the same “In Progress” label.

That’s a deliberate choice, not an oversight: deciding whether a stalled ticket needs an escalation, a nudge, or is actually fine for a reason the system can’t see, is exactly the kind of judgment call that should stay with a person, since the reason behind a stall matters as much as the fact of it.

FAQ

Doesn’t a simple “ticket older than X days” filter already solve this?

Partially, and with a real cost: it also flags every legitimately slow-but-fine ticket, which trains people to ignore the filter’s alerts entirely. Comparing against what’s normal for that specific kind of work catches the real stall with far fewer false alarms.

How would a team have caught the three-week example without this kind of detection?

Usually only by luck: someone happening to ask the engineer directly, or the engineer themselves remembering to chase the blocked decision. Neither is a reliable mechanism at any real team size.

Does flagging a ticket mean the person working it did something wrong?

No. In the example, the engineer made a reasonable call to move on to other work while blocked. The gap wasn’t in their judgment, it was that nothing captured the block anywhere the board could see it.

Is this the same as a generic “stale ticket” report most trackers already offer?

Not quite. A generic stale-ticket report usually applies one age threshold to everything. This compares each ticket against what’s actually typical for that kind of work, which is a meaningfully different and more accurate signal.

What’s the actual cost of not catching a stalled ticket like this?

The blocked decision stays unresolved for however long the silence continues, and whatever depends on that ticket, a related feature, a release timeline, drifts along with it, uncaught until something downstream forces the question.

See how Thor surfaces the ticket nobody’s touched in weeks. Book a demo.

Related Posts