The List Delusion
Open your issue tracker right now. What do you see? A list. Sorted by date, maybe by priority. Columns on a kanban board. Rows in a spreadsheet. Everything laid out flat, one item after another. Here’s the problem: your work isn’t flat. Issue #47 can’t start until #31 and #38 are both done. Issue #12 is blocking four other issues downstream. Issue #89 looks low-priority, but it’s the single bottleneck holding up your entire release. You can’t see any of that in a list. Every issue tracker I’ve used—JIRA, Linear, Asana, GitHub Issues—presents your backlog as a one-dimensional sequence. They let you sort and filter, maybe drag cards between columns. But the actual structure of your work—the dependency relationships that determine what can ship and when—is invisible. You’re navigating a graph with a tool designed for lists.Your Work Is a DAG
In computer science, a directed acyclic graph (DAG) is a graph with directed edges and no cycles. It’s the natural data structure for task dependencies: issue A blocks issue B, B blocks C, but C can never block A (that’s a cycle, a deadlock). Your backlog is a DAG whether you model it as one or not. The dependencies exist in reality even if your tooling ignores them. Consider a typical feature rollout: That changes your entire execution strategy.Three Things Your List Can’t Tell You
1. Which issue actually matters most
Most teams sort by priority: P0, P1, P2. But priority is a local property: how important this issue seems in isolation. What you want is a global property: how much total work does this issue unblock? A P2 bug that blocks five downstream features is more urgent than a P0 polish task that blocks nothing. Lists can’t express this. Graphs can.2. Where your real bottleneck is
You have 30 open issues. Three developers. Where do you assign them? A list says: pick the top three by priority. A graph says: find the issues that sit on the most dependency paths. Those are your bottlenecks—clear them, and the entire project accelerates. In graph theory, this is called betweenness centrality. It measures how often a node appears on shortest paths between other nodes. High betweenness = high leverage.3. What determines your actual ship date
Your ship date isn’t determined by the total number of issues. It’s determined by the critical path—the longest chain of sequential dependencies in your DAG. If your critical path is 8 issues deep, that’s your minimum timeline regardless of how many developers you throw at the other 22. Adding parallelism helps, but only for work that’s off the critical path.This is the insight behind CPM (Critical Path
Method), developed at
DuPont in the 1950s for managing construction projects. Seven decades later,
most software teams still don’t use it.
PageRank for Your Backlog
Here’s where it gets interesting. Google’s original insight was that the importance of a web page is determined by the structure of links pointing to it, not the page itself. A page linked by many important pages is itself important. The algorithm that captures this is PageRank. The same logic applies to issue dependencies. An issue that blocks many important issues is itself important, even if no one manually flagged it as P0. The importance propagates through the dependency graph, just like link authority propagates through the web graph.Traditional Priority
Input: Human judgment (P0/P1/P2)Problem: Doesn’t account for dependency structure. A P2 blocking five P0s stays P2.Result: Teams work on locally optimal tasks while globally critical work stalls.
Graph-Derived Priority
Input: Dependency structure + statusAlgorithm: PageRank over the dependency DAG, weighted by blocking relationships.Result: Issues that unblock the most downstream work rise to the top.
From Theory to tk triage
I built ticket-rs to make this practical.
Issues are stored as markdown files with YAML frontmatter. Dependencies are explicit: deps: [tk-31, tk-38]. The CLI runs graph algorithms over this structure and returns ranked recommendations.
tk-38 OAuth config issue is P2 by human judgment but the most important thing to work on by graph analysis. Without the graph, a developer would reasonably skip it in favor of the P1. With the graph, the priority inversion is obvious.
Why This Matters More with Coding Agents
This distinction matters more when AI agents are doing the work. Claude Code, Cursor, Windsurf, Codex — they all need to know what to build next. An agent working from a flat list picks the top item and runs. If that item is blocked by something else, the work either fails or can’t be integrated. Tokens spent, nothing to show for it. An agent working from a dependency graph knows:- What’s ready — issues with no open blockers
- What to prioritize — issues that maximize downstream unblocking
- What to parallelize — independent branches that can run concurrently
The Uncomfortable Math
Here’s a thought experiment. Suppose you have 50 open issues and a team of 3 developers (or 3 parallel AI agents). Your list-based approach says: sort by priority, assign top 3, repeat. But your dependency graph has:- 12 issues that are currently blocked
- 8 issues that are ready but low-impact (leaf nodes)
- 3 issues that each unblock 4+ downstream tasks
- 1 critical path of depth 7
Getting Started
So What?
My background is in machine learning. Finding structure in messy data is what I do. Turns out, most of us ignore the structure sitting right in front of us—in our own backlogs. Your issues have dependencies. Those dependencies form a graph. And that graph tells you what to work on next, where your bottlenecks are, and what determines your ship date. You don’t need a PhD to use PageRank. You need a dependency graph and a tool that knows what to do with it. Runtk triage once. If the top recommendation surprises you—if it shows you something you weren’t prioritizing—that’s the gap between list-thinking and graph-thinking.
That gap is where the interesting work happens.