Critical path and slack#
This guide shows how to find the tasks that decide the project's finish date and how much room every other task has. You can get these numbers from a scheduling run, from a preview, or from dates you already have, without scheduling.
How analytics work#
Analytics are off by default. Ask for them with an analytics object in the call options. It has two flags, criticalPath and slack, and both default to false. The same object fits three calls:
SolveOptionsforscheduleandJsonProject#solve. The analytics describe the freshly scheduled dates.PreviewOptionsforJsonProject#preview. The analytics describe the previewed dates.AnalyzeOptionsforJsonProject#analyze. The analytics describe dates you supply, or the project's current dates, as they are. Nothing gets scheduled.
When at least one flag is true, the result's analytics field holds an object with status and the lists you asked for. With both flags off, result.analytics is left out of the JSON. Its shape is on ScheduleResult.
The engine computes the numbers from two plans. The first plan is the dates being analyzed. For the second, the engine schedules the same tasks backward from the latest finish, which gives each task its latest possible start. The gap between the two plans is the slack:
- Total slack is how far a task can slip before the project's finish date moves. It's the latest start minus the planned start.
- Free slack is how far a task can slip before it pushes any successor. It's the smallest margin over the task's outgoing links, and it's never more than the total slack. A task with no successors has free slack equal to its total slack.
A task is critical when its total slack is zero or less. A link is critical when both of its tasks are critical and the link is binding, so its target starts exactly when the link allows. criticalPath lists the critical task and link ids. slack holds one {task, total, free} entry per task.
A few rules shape the output:
- Slack is a number in the configured
duration_unit(days by default) and counts working time on each task's calendar. A weekend between two tasks doesn't add slack. - Only leaf tasks and milestones get a slack entry. A summary has no slack, and it's critical when any of its non-summary descendants is.
- With
use_progress, completed tasks (progress == 1) report zero total and free slack, but they're never critical. - A dependency cycle makes the numbers meaningless.
statusis then"invalid", and both lists are left out.
Requesting analytics#
Set the flags in SolveOptions to get analytics together with the schedule.
const = ;
const = ;
const = ;
const = ;
const = response.;
;
;
Both build and docs wait for design. build takes three days and docs takes one, so design and build form the critical path, joined by link l1. The analytics part of the result looks like this:
docs can slip two working days before the project end moves. It ends on Thursday and build ends the following Monday, and the weekend doesn't count.
JsonProject#solve takes the same options. Its cache key is the whole options object, so solve(undefined, …) with analytics turned on recomputes from the accepted dates instead of returning a cached result without them.
Checking a change before you commit it#
Set the flags in the PreviewOptions of preview to see how an edit would change the critical path.
const = ;
const = ;
const = new;
With five days of docs, the critical path moves to design, docs, and build now has two days of slack:
critical: design, docs
design: total 0 free 0
build: total 2 free 2
docs: total 0 free 0
The project itself doesn't change. For more on previewing, see Previewing changes.
Analyzing without scheduling#
Use analyze when you already have dates, for example from your own database or a gantt chart, and want the critical path for those exact dates.
const = ;
// "build" starts a day after "design" ends. A solve would pull it back to Wednesday.
const = ;
const = ;
const = new;
Only build is critical. design has one day of total and free slack, because build starts a day later than the link requires. Link l1 isn't critical: it isn't binding, and design isn't critical.
analyze is read-only. With data, it validates and reads the snapshot but doesn't install it, so the project keeps whatever it held before. A fresh new JsonProject("{}") is enough when all you need is the analysis. Invalid data or options come back as an error envelope with kind parse or validation, as in Error handling. The result has an empty updates list and no planner conflicts, and it has no baselineId.
Analyzing the project's current dates#
Pass undefined (or null) as the data to analyze the dates the project holds now, including edits that haven't been solved yet.
const = ;
const = ;
const = ;
const = new;
After the edit, the critical path is design, docs. analyze doesn't change the project's solved status, so the project still needs solve(undefined, …) before preview works again. Until then, preview returns a project error with code no-baseline.
baselineId is set only when the project is solved and has no unsolved edits. That's how you tell whether the analytics describe the accepted baseline. When there's no baseline, the field is left out, never null.
Reading the result#
Check status first. Then read the lists you asked for: a flag you left off means its list is missing from the JSON, even when the status is "available".
const = ;
const = ;
const = ;
const = ;
const = response.;
The output shows each rule from the concept section:
critical: review, phase, release
spec: total 0 free 0
review: total 0 free 0
release: total 0 free 0
phaseis critical because its childreviewis. It has no slack entry, since summaries never get one.specis complete, so it reports zero slack. It still isn't on the critical path.- The critical task list follows the scheduling graph order, not input order. Look tasks up by id instead of relying on their position.
Ids come back as you sent them: a numeric id stays a JSON number and a string id stays a string. Slack values are plain numbers in duration_unit. With "duration_unit": "hour", a task that can slip one and a half working days reports total: 12.
If the links form a cycle, the solve returns unchanged dates and lists each cycle in result.cycles. The analytics then come back with only a status:
Fix the cycle and run again. For the rest of the result, see Reading results.