Dependencies and the critical path

How to make one request wait for another, which predecessors it waits for, what a lag does, and how Orkyo computes the finish date.

A dependency records that one request cannot start until another one finishes. Orkyo uses it in four places. The scheduler honors it, the conflicts list reports a breach of it, and the critical path comes from it. Orkyo also refuses to start a request before its condition is met.

Containment and sequence are different

Orkyo has two relationships between requests, and they answer different questions.

The tree says what a request is part of. A group holds children, and its dates roll up from them.

A dependency says what must happen first. It is independent of the tree: precedence routinely crosses group and site boundaries, so an edge joins any two requests rather than ordering siblings inside a group.

A request can therefore sit in one group and wait for work in another. That is normal.

What can be linked

Only schedulable requests — leaves — can carry a dependency.

A group’s dates are derived from its children and it never reaches the scheduler, so an edge on one can not be enforced. Orkyo refuses the link rather than record a promise it can not keep. For the same reason, a leaf that carries dependencies must lose them before it can become a group.

Orkyo also refuses two other links:

  • A request can not wait for itself.
  • A link that closes a loop is refused. If B waits for A, then A can not be made to wait for B, directly or through any chain of other requests.

The Children tab of a container shows Sequence these tasks. This opens the plan of that container. The canvas holds the tasks that a dependency touches, as cards joined by arrows, and a padlock marks each task that can not start. The tasks that no dependency touches yet are in an Unsequenced list beside it. A canvas of four hundred unconnected cards hides the few that carry the plan. A task moves onto the canvas after you select it. The guide Sequence the tasks in a plan explains how to draw the links there.

Finish to start, and the lag

Every dependency is finish-to-start: the successor starts after the predecessor finishes.

A lag adds a minimum gap after that finish. Use it for work that must settle — paint that has to cure, a part that has to cool. A lag only ever delays a successor. It can not pull one earlier.

Orkyo plans in minutes, so a lag of four hours delays the successor by four hours. The scheduler counts a lag in working time, and the conflict check counts it in clock time. Both readings are safe: the scheduler never places a successor too early, and the conflict check never reports a false breach.

The start condition

A request with several predecessors does not always wait for all of them. The start condition says how many it waits for. It belongs to the request that waits, not to one link, because it is a statement about the whole set.

There are three conditions:

  • All predecessors — the request starts after every predecessor is done. This is the default, and it is what every request did before conditions existed.
  • Any predecessor — one is enough. Two suppliers can deliver the same part, and either delivery frees the work.
  • At least k — the request starts after the chosen number are done. A sign-off can need two of three inspections.

A canceled or deferred predecessor leaves the set before Orkyo counts. The count of predecessors decreases with it, and a k larger than the set reads as “all of them”. Abandoned work therefore never holds a request shut, and nobody has to delete a link to record that it happened.

The condition is on the Dependencies tab of a request, under Can start when. Orkyo shows the control only for a request that waits for more than one thing. With one predecessor, all three conditions mean the same.

What the scheduler does with a dependency

Auto-schedule respects the start condition, and it will not do otherwise.

  • If both requests are in the same run, the scheduler places them in order.
  • If the predecessor is already scheduled, its finish date bounds the successor.
  • Under Any predecessor or At least k, the scheduler waits for the earliest predecessors that satisfy the condition, not for the last one.
  • If too few predecessors are scheduled or placeable to satisfy the condition, the successor stays in the backlog. Its reason reads “predecessor unscheduled”.

That last case is deliberate. A placement there creates a conflict the moment it lands, and a reason in the backlog is more useful than a plan that is wrong on arrival.

One run fills every resource type its requests need. A chain that crosses resource types, saw then mill then inspection, is placed in one run.

Chains from a routing

A work order created from a routing arrives with its chain drawn. Each operation is a request. Each request waits for the one before it, with the lag the routing step names. Nobody draws the arrows by hand. See Routings.

The dependency conflict

If a start condition is not met, Orkyo reports a dependency violation on the successor:

  • It starts before enough predecessors finish, or before the lag has elapsed. This is an error.
  • Enough predecessors are unscheduled that the condition cannot be judged yet. This is a warning: the plan is incomplete rather than wrong.

A request that waits for all of its predecessors reports one conflict for each predecessor it starts too early against. Each conflict names that predecessor.

A request under Any predecessor or At least k reports one conflict for the whole set. The shortfall belongs to the set rather than to one link.

A condition that is already satisfied reports nothing. Under Any predecessor, an unscheduled second predecessor is not a problem, because the first one already frees the work.

Nothing is reported while the successor itself is unscheduled. A backlog item breaks no promise.

See Conflicts for how conflicts are surfaced.

Starting work early

Orkyo refuses to move a request to In progress while its start condition is unmet. The message names the shortfall, for example “2 of 3 predecessors must be done”. It also names the work that the request waits for.

A predecessor counts as done in two cases. Its scheduled window is in the past, or somebody marked it done. An unscheduled request that somebody marked done therefore counts, because a dependency is about order and not about placement.

This rule is about the deliberate act of starting work. A request whose scheduled window opens becomes In progress on its own, because the plan says it runs now. Work that is scheduled too early is a planning error, and the conflicts list reports it.

The critical path

The critical path is the work that decides when a chain finishes. An hour lost on it is an hour lost on the whole chain.

A chain is a group of requests that dependencies connect. Orkyo measures each chain against its own finish. A chain that ends in March gets no float from a chain that ends in December.

Orkyo computes it with a forward and a backward pass over the dependency graph:

  • Earliest dates come from working forward: each request starts as soon as its start condition allows. Under Any predecessor that is the earliest predecessor, and under At least k it is the k-th earliest.
  • Latest dates come from working backward from the finish of the chain: each request starts as late as it can without moving anything after it.
  • Float is the gap between the two. It is how long a request can slip before it costs something.

A request with zero float is critical.

A predecessor that the condition does not wait for carries float rather than lying on the critical path. Under Any predecessor, the branch that arrives second has slack, and Orkyo reports it as slack.

Two details are worth knowing.

Scheduled work anchors the path. When a request is already placed, its dates are facts about the plan, and the pass uses them rather than proposing something earlier. Only unscheduled work floats to where its predecessors allow. Unscheduled work starts no earlier than now.

Only open work counts. Finished work can not delay anything, so Orkyo removes it. A finished predecessor holds nothing back.

Everything is in minutes. The scheduler plans in minutes, so the critical path reports its dates to the minute and its float in days and hours. A deadline on a request tightens its float, because it can not finish later than its own window allows. The slack of a chain is the time between a deadline and the earliest finish of its request. Negative slack means that the chain is late.

Requests with no dependencies take no part in the critical path. They have nothing to be early or late against.