Jira and Slack reporting: which blocked issues were only ever raised in a channel
It is Thursday afternoon, an hour before sprint review. The delivery lead has the board open on one screen: current sprint, thirty four issues, four of them carrying the blocked flag. She is writing the summary slide and the number she is about to type is four.
The engineering manager sitting next to her says the number is wrong. Not because Jira has made a mistake. Because on Tuesday, in #eng-platform, a backend engineer wrote that the staging certificate renewal still had not gone through and she could not test the new auth flow until it did. Three people reacted with an eyes emoji. Nobody opened the ticket. The issue is still sitting in In Progress, assigned, unflagged, quietly aging.
He can name that one because he happened to read the channel that day. He cannot name the others. The real question, the one that decides what goes on the slide, is: across the last two sprints, which issues were reported as stuck in a channel and never recorded as stuck in Jira. Both people have both tools open. Neither screen answers it.
What Jira shows, and where it stops
Jira is precise about everything it was told. Status, the blocked flag, issue links of the "is blocked by" kind, sprint membership, assignee, and a full changelog with timestamps. You can write JQL for sprint in openSprints() AND flagged is not EMPTY and get an exact answer in a second. Control charts will show you how long each issue sat in each status. If your team also uses the Jira Slack integration, issue events get posted into channels and anyone can promote a message into a new issue from the message menu, which is genuinely useful and is why most teams connect Jira and Slack in their first week.
Here is the boundary. A blocker exists in Jira from the moment somebody performs the act of recording it: setting the flag, adding a link, changing the status, writing a comment. Not from the moment the work actually stopped. If nobody performs that act, the issue looks healthy. In Progress, assigned, no flag, and the changelog is silent, which reads exactly like an engineer making steady progress.
Jira cannot represent a blocker that was never entered. That is not a gap in the product. That is what a record is.
The Slack integration does not close this either, because it runs in the direction of notification and deliberate promotion. It carries Jira events out into channels, and it carries a message into Jira when a human decides to move it. It does not read three weeks of channel history and tell you which conversations were about work whose ticket never caught up.
What Slack shows, and where it stops
Slack has the whole thing. Every sentence, in order, with a name and a timestamp on it. You can search in:#eng-platform blocked after:2026-07-14, you can filter to one person, you can pull up the thread and read what happened next.
Then you read the results and see the problem. The certificate message never used the word "blocked". It said "still waiting on the cert renewal, can't test auth until it lands". No ticket key, no status vocabulary, nothing a keyword search would reliably catch unless you already knew to search for "cert". Meanwhile "blocked" returns forty hits, most of them about a blocked calendar, a blocked IP range, and somebody's blocked drain at home.
Slack matches strings. It does not know which sentences are about work, because it has no model of work. It has a model of messages. It also cannot tell you which described blockers were later cleared, since a cleared blocker usually just stops being mentioned rather than being announced. Silence in a channel is not evidence of anything.
Why the gap is structural
Half of this question lives in a record and half of it lives in a sentence somebody wrote at 4:52pm on a Tuesday.
| The Jira side | The Slack side | |
|---|---|---|
| What it holds | Fields, statuses, changelog | Sentences, in order, by person |
| Stable identifier | Issue key, on every row | None, unless someone typed one |
| Query surface | JQL over a schema | String match over text |
| Tells you it was cleared | Yes, the changelog says so | Usually not, the topic just ends |
| Knows the work stopped | Only if someone recorded it | Often, but only in prose |
Joining those two columns is not a reporting feature Atlassian forgot to ship. A report is a query over a schema. To answer this you first have to decide, for each of a few thousand messages, whether that message describes work being stuck, and then decide which piece of work it belongs to. Both of those are readings, not lookups. There is no column on either side that holds the answer and no key that exists in the same shape on both.
It sits outside the neighbouring categories too, and for reasons worth being exact about. Zapier and Make are excellent at what they do, but they are trigger based: something happens, and the platform moves a record forward. They can post a blocker into a channel or open an issue from a message from now on. They cannot answer a question about the last two sprints, because at the time there was no trigger and the question is retrospective. Power BI Copilot and Looker Conversational Analytics are strong products too, and they will chart blocked issue counts from Jira's data beautifully. But they connect to databases and modelled sources, and the eleven sentences in #eng-platform are not a modelled source. That evidence is not badly represented in those tools. It is outside what they can see at all.
What the join actually requires
The strong key is the issue key. When someone types PROJ-1423 in a message, the match is exact and cheap. In most channels that covers roughly a third of the relevant messages.
The rest need a weaker composite key, and this is where the work is. The speaker matched against the issue assignee. The timestamp falling inside the sprint window. Subject overlap between the message and the issue summary: a service name, a vendor, a feature, an environment. "Waiting on the cert renewal" ties to an issue titled "Auth flow: staging verification" through the words cert, staging and auth, plus the fact that the person who wrote it is the person the issue is assigned to. Each of those is a probability, not a fact, and they have to be weighted together.
Then two judgement calls that no matcher settles. First, is this sentence a blocker at all. "Still waiting on legal" from an assignee mid sprint is one. "We might need infra to weigh in" is a risk, not yet a stoppage. Second, and this is the actual question, did the ticket ever catch up. The test is temporal: a message asserts a stoppage at time T, and the issue's changelog shows no flag, no move to Blocked, and no comment naming that impediment between T and now.
Answering it with Skopx
Skopx connects to Jira and Slack as two of nearly 1,000 tools it can read across, and the question goes in as a sentence. Something close to what the engineering manager would actually type:
Look through #eng-platform, #product-support and #releases for the last two sprints. Find messages where someone said work was stuck or waiting on something, match them to issues in the MOBILE and PLAT projects, and show me the ones where the issue was never flagged and never moved to Blocked.
What comes back is a list. Each row is an issue key, the quoted sentence with a permalink to the message, who wrote it and when, and what Jira currently says instead. Every claim traces back to the thing it came from, so the delivery lead can click into the channel and read the thread before she puts a number on a slide.
The same question can then be left standing as a console. You describe it once in chat and Skopx builds it, which is what Internal Apps is for: a table of issues that were reported stuck in conversation and never recorded as stuck in Jira, sorted by how many days have passed since the sentence was written, with columns for assignee, current Jira status, and the quote. It reads both sides fresh every time somebody opens it. Each row carries one button: flag the issue in Jira and paste the quoted message as a comment. A person clicks it, confirms, and that is the only thing that ever gets written.
What this does not do
It reads what it has been given access to. A blocker raised only in a private channel Skopx cannot see, or only in a DM, or only out loud in a huddle with no notes, leaves nothing to read and will not appear.
The matching is a judgement, so it will be wrong sometimes in both directions. It will surface a message that turned out not to be a blocker, and it will miss one phrased obliquely enough that nothing connects it to any issue. Every row is quoted and linked so a wrong one takes five seconds to dismiss, but you do have to look.
It does not watch. Nothing fires at nine in the morning, no alert lands when a new unrecorded blocker appears. The console is accurate at the moment you open it and dormant the rest of the time.
It stores nothing. There is no saved list, no record of what you dismissed last week, no history table accumulating behind it. Close it and it is gone. Open it tomorrow and it reads both systems again from scratch.
And it does not judge severity. It tells you a stoppage was described and never recorded. Whether that stoppage matters is still the conversation you have in the review.
If your team recorded blockers reliably, Jira would answer this on its own and none of the above would be worth building. This exists because the flag is one more step at the end of a hard afternoon, and the sentence in the channel is what people actually write instead. Skopx is $16 per seat per month on Team with 2.3 million AI tokens included, and $5 on Solo.
Skopx Team
The Skopx engineering and product team