Project delivery is a scheduling problem, not a tracking problem
What twenty years of research taught me about modelling dependencies, resources and uncertainty
For twenty years I've used tools like Jira and Azure DevOps to run software projects. They're good at telling you what work exists, who owns it, and whether you're ahead or behind plan. They are much less good at answering the one question that actually determines how fast a project finishes:
Given the people, skills, and approvals we have right now, what should we work on next to get the whole project done sooner?
That's not backlog prioritisation, and it's not a Gantt chart. It's a resource-scheduling problem – and it turns out two old research papers of mine, written about wireless sensor networks and underwater communication, offer a surprisingly useful way to think about it.
Resources aren't on/off – they have states
Project plans usually treat a person or an environment as a single box: "Engineer A," "Test Environment." In reality, a resource sits somewhere on a spectrum – an engineer might be unavailable, at 20% capacity, or fully free; a test environment might allow zero, one, or several deployments in parallel.
My 2004 paper on sensor networks used the same idea. A battery-powered sensor could transmit at several power levels, and modelling those levels explicitly – rather than treating the sensor as one uniform node – was what allowed the network to route around weak spots and avoid draining any one node too fast, which in turn maximised how long the whole network stayed alive.
The project equivalent: if scheduling only sees "Engineer A: busy or free," it can't make good trade-offs. If it sees the actual gradient of availability, it can ask sharper questions – does moving a specialist off their current task for two days, even though it slows that task, shorten the project? That's the kind of trade-off a plan can only make once resource states are visible, not just resource names.
This is easy to put in numbers. If each resource has an availability fraction somewhere between 0 (fully unavailable) and 1 (fully available), the capacity you actually have to plan against is:
Two engineers at 50% and one at 20% add up to – a bit more than "one person," but a plan that only records names, not fractions, will either overcommit them or leave that spare 20% invisible and unused.
Turn one resource into several, then let known algorithms do the work
There's a modelling trick behind that idea that's worth naming, because it's what makes resource states genuinely usable rather than just a nicer label. Instead of drawing "Engineer A" as one box with a variable dial attached, you can unfold that one person into several separate placeholders on the plan – one for each capacity level: Engineer A at 20%, Engineer A at 50%, Engineer A at 100%. Each placeholder connects only to the tasks it could realistically take on at that level, with the connection carrying its cost in effort or time.
This is a trick our team used elsewhere in our graph-theory work on networks: take a physical node with a quantitative property that can sit at several levels – a radio with several available transmission power levels, say – and instead of modelling one node with a variable setting, unfold it into one logical node per level, each wired into the network differently. The physical radio stays singular; the map of it grows richer. The same trick works for a test environment (unfold it into "zero slots," "one slot," "unlimited slots") or a budget line, or a contractor's availability.
The payoff is real: once a resource is unfolded this way, you don't need to invent bespoke scheduling logic for "variable-capacity things." You can point long-established, well-tested graph algorithms – the same families used for airline crew rostering, delivery-route planning, and job-shop scheduling – straight at the expanded map and let them search it.
The catch is that the map grows fast. Unfold a handful of resources – a few engineers, a couple of environments, one approval queue – each into their own set of states, and the number of legitimate combinations multiplies rather than adds:
where is the number of states per resource and is the number of resources. Ten resources with four states each already gives over a million combinations to weigh against each other. For problems of this shape, finding the single mathematically best schedule is a well-known category of hard problem – some versions are provably NP or NP-complete – meaning there is no shortcut that guarantees the optimal answer quickly as the project grows, no matter how much computing power you throw at it. That isn't a flaw in the modelling; it's a known property of scheduling problems in general, in projects as much as in networks. It's also why, in our own work, this kind of unfolded problem was tackled with carefully chosen heuristics rather than an exhaustive search for the perfect answer – including the local, energy-aware rule described next, from the 2004 broadcasting paper.
You don't need perfect information to make a good local decision
That same 2004 paper solved a second, harder problem: deciding which sensors should relay a message onward, without any of them knowing the full network layout. Instead of first mapping the whole network (which costs battery and time), each node made a simple local call – nodes with more remaining energy volunteered to forward messages sooner, and nearby nodes backed off once they heard that. No global map was ever built, yet the network as a whole lasted longer and carried more traffic than approaches that tried to plan centrally.
Projects collect an enormous amount of state – status fields, story points, burndown charts, risk registers – in the hope that more visibility produces a better plan. It often doesn't. A scheduling system probably doesn't need a perfect model of everything happening on a project. It needs the right local signals: how much capacity is actually free, what's downstream of this task, and what it costs to delay it. The goal isn't a perfect forecast – it's a good decision about what to do next.
The rule each sensor followed can be written as one line. If a resource has units of capacity left out of a maximum , the time it waits before acting is:
A resource with plenty left ( close to ) waits almost no time and moves first. One that's nearly spent waits longest, leaving room for someone with more capacity to step in. Nobody needs to coordinate this centrally – each resource only has to know its own state.
A known delay is not the same as dead time
My second paper dealt with underwater communication, where sound travels so slowly that simply waiting for a reply can dominate the whole exchange. The standard fix – wait for an acknowledgement before doing anything else –ß wasted enormous amounts of time. Our protocol, PCAP, used a different fact: while the exact delay was unpredictable, the maximum possible delay was almost a constant, because it depended only on distance and the speed of sound. Knowing that bound let a node get on with other work while it waited, instead of sitting idle – closer to a pipeline than a stop-and-wait conversation. That paper has since been cited around 188 times, and "propagation-delay-tolerant" designs went on to become a recognised category of their own in underwater networking research. Projects are full of the same shape of problem: an approval that takes two to five days, a vendor with a ten-day turnaround, a release window that only opens on Tuesdays. We usually model these as a flat "blocked" state. But if the maximum wait is known, that waiting time is schedulable – the project doesn't need to sit idle for the median case just because it must be safe for the worst case.
That's just as simple to express. If the maximum possible wait is and time has already elapsed, the amount of other work you can safely schedule in the meantime is:
If the approval or delivery arrives sooner than , that's a bonus – not something to plan around. What matters is that is a known, fixed number, which is what turns "blocked" from dead time into scheduling space.
"Blocked" needs more detail than a status field
Put together, these ideas point to one practical change: stop treating a blocked task as a dead end and start treating it as a dependency with its own properties – an owner, an expected duration, a known maximum duration, and a list of other work that could happen in that window. Once dependencies are modelled that way, and resources are modelled as states rather than names, scheduling becomes something you can actually optimise, not just document.
It also explains a pattern many delivery leads have felt but not named: a project's real duration isn't just the longest chain of dependencies (the critical path) – it's whichever is longer, that chain or the time needed to push everything through your scarcest resource:
That's why a project can look "on track" against its critical path and still slip. The sequence of tasks was never the real constraint – the one security specialist everything had to queue behind was.
Why this matters more now
Twenty years ago, continuously recalculating an optimal schedule for a real project would have been impractical. Today, with more computing power and increasingly capable AI, it's realistic to build a system that reacts to change – an engineer goes on leave, an approval lands early, a vendor frees up capacity – by immediately proposing a better sequence of work, rather than waiting for someone to manually redraw the plan. Humans would still decide. But they'd be choosing between good options instead of reconstructing the plan from scratch every time something shifts.
Toward a digital twin of delivery
Put the pieces together – activities and dependencies as distinct objects, resources unfolded into their real states, delays bounded rather than left as blank waiting – and what you have is the raw material for a digital twin of the organisation's delivery capacity: a live model that mirrors, in software, exactly what people, environments, budgets and approvals are doing at any moment, and how each one connects to the work in flight.
Aircraft manufacturers are leveraging digital twin to optimise the entire aircraft lifecycle from design to maintenance. They test a change on a jet engine in simulation before touching the physical thing, because a model is cheap to experiment on and reality is not. There's no reason the same idea stops at the factory floor. If a business can model its activities, dependencies and resource states the way described here, it can simulate itself before committing to a decision: what happens across the whole portfolio if we hire a second database engineer? If a vendor slips two weeks? If we pull our best tester onto an incident for three days? Today those questions get answered in a status meeting, after the decision has already been made. A twin of the organisation could answer them in seconds, before it's made.
A model, not a mandate
None of this works if it tries to reduce people to nodes on a graph. The protocols I started from were built for radios and sensors – objects with no judgment, no competing priorities, and nothing at stake beyond the physics of a battery. People are not that. The trust between a client and a delivery lead, a team's morale after a hard sprint, an engineer's reasons for wanting to finish what they started rather than being reassigned mid-task – none of that reduces cleanly to an edge weight, and a model that pretends otherwise will hand out confidently wrong advice.
The honest version of this idea is narrower, and better for it: let the model handle the arithmetic – which combinations of finite people, environments and approvals are actually feasible right now – so that the humans running the project can spend their judgment where it belongs: which trade-off is worth the political cost, which relationship needs protecting even when it isn't the "optimal" path, when an exception is the right call anyway. A good schedule recommendation should be the start of a conversation, not the end of one.
That changes what a delivery tool is for. It stops being a system of record that reports what already happened, and becomes a system of simulation that shows what would happen next – letting you compare a few versions of "next" before committing to one, with people still making the call. Jira and Azure DevOps will keep telling us where the work is. What I want from the next generation of delivery tooling isn't a system that runs the project for us – it's one that clears away the arithmetic, so the people running it have more time for the parts of the job that were always human.
References
[1] Guo, Frater, and Ryan, “Design of a Propagation-Delay-Tolerant MAC Protocol for Underwater Acoustic Sensor Networks,” IEEE Journal of Oceanic Engineering, vol. 34, no. 2, pp. 170–180, Apr. 2009, doi: 10.1109/JOE.2009.2015811.
[2] Guo, “Broadcasting for Network Lifetime Maximization in Wireless Sensor Networks,” in Proceedings of the IEEE International Conference on Sensor and Ad Hoc Communications and Networks (SECON), Santa Clara, CA, USA, Oct. 2004, pp. 525–528, doi: 10.1109/SAHCN.2004.1381936.