ScheduleResult#
The response payload of every scheduling call. It arrives as result in the success envelope returned by schedule, JsonProject.solve, JsonProject.preview and JsonProject.analyze. JsonProject.level returns the same fields plus rounds.
Cycles, conflicts and a planner that didn't converge are reported in the result with ok: true, not as an error envelope.
Fields#
Optional fields are left out when they don't apply. They're never null. Field names are camelCase; entries in updates use the snake_case task-data names. See Wire format.
| Field | Type | Present | Description |
|---|---|---|---|
baselineId |
string | see baselineId | Token of the baseline this result produced or read. |
updates |
Mutation[] |
always | New dates and fields of the reported tasks. |
cycles |
Cycle[] |
always | Dependency cycles found in the project. |
conflicts |
Conflict[] |
always | Constraint and calendar conflicts. |
notes |
Note[] |
always | Dropped input records and repairs made on import. |
converged |
boolean | always | true when the planner reached a fixed point within max_iterations of SchedulingConfig. analyze always returns true. |
analytics |
Analytics |
when the call's options request criticalPath or slack |
Critical path and slack. |
overallocations |
Overallocation[] |
when the project has at least one assignment | Resource overload windows. [] when no resource is overloaded. |
profile |
LoadProfile |
only from preview with options.profile set |
Resource load of the previewed dates. For the load of the accepted dates, call JsonProject.loadProfile. |
The encoder doesn't keep a fixed key order. Read fields by name.
baselineId#
An opaque token that names an accepted baseline.
| Call | baselineId |
|---|---|
solve |
Always present: the baseline the call accepted. |
preview |
Always present: the baseline the preview read. A following preview or apply accepts it. |
analyze without data_json |
Present only on a solved project with no unsolved edits. |
analyze with data_json |
Absent. |
schedule |
Present, but it names the baseline of a temporary project, so no later call can use it. |
The token changes when the accepted dates change. Don't store it or compare tokens from separate runs. Which calls check it is listed on each call's page.
updates#
One Mutation per reported task.
- By default the list is sparse: only tasks that changed.
solvewithout data andlevelalso report each task touched byapplysince the last solve. - With
includeUnchangedinSolveOptions,solveandschedulealso list every unchanged scheduled task. previewreports changes relative to the baseline it read.- On a project with cycles, the list is empty unless
includeUnchangedis set. analyzealways returns[].
cycles and conflicts#
cycles holds every unique simple dependency cycle. When it isn't empty, no task is moved. conflicts lists constraint violations and non-working-time placements; analyze always returns [].
Mutation#
One entry of updates. Fields use the snake_case names of TaskData, with the same units. Only reported fields are present.
| Field | Type | Present | Description |
|---|---|---|---|
id |
Id |
always | Task id. |
kind |
"task" | "summary" | "milestone" |
always | Task kind. A task imported as "project" is reported as "summary". |
start_date |
DateValue |
the start changed, or the task is reported in full | New start. |
end_date |
DateValue |
the end changed, or the task is reported in full | New end. |
duration |
number | the duration changed, or the task is reported in full | New working time in the task's duration unit. |
leveling_delay |
number | the leveling delay changed | New leveling delay. |
pauses |
Pause[] |
the pause list changed | The complete new pause list; [] when every pause was removed. |
reason |
Reason |
the call ran with reasons: true |
What placed the task. Absent when no planner ran (a cyclic project). |
A task is reported in full (start_date, end_date and duration all present) with includeUnchanged, or when apply touched it since the last solve.
An entry decodes as a TaskUpdate: kind and reason are ignored there as unknown fields, so an entry can be sent back through apply as is.
Reason#
Tagged by kind.
kind |
Fields | Description |
|---|---|---|
"asap" |
linkId, sourceId |
The incoming link linkId from predecessor sourceId set the start. |
"alap" |
linkId, targetId |
Backward scheduling: the outgoing link linkId to successor targetId set the end. |
"summary-translation" |
summaryId |
The task moved with its summary as one block. |
"constraint" |
- | A task constraint set the date. |
"preferred" |
- | No link or constraint moved the task; it sits at its own date. |
When several links give the same date, asap and alap name the first one. See Reading results.
Cycle#
| Field | Type | Description |
|---|---|---|
tasks |
Id[] |
Tasks on the cycle, in cycle order. |
links |
Id[] |
Links that form the cycle, in path order. A cycle closed through summary containment has fewer links than tasks. |
Conflict#
Tagged by kind.
kind |
Fields | Reported when |
|---|---|---|
"constraint-violation" |
task, constraint (ConstraintType), violation ("earliest-start" | "latest-start" | "earliest-end" | "latest-end"), required, actual (DateValue) |
A constraint placed the task at a date its driving link doesn't allow. required is the constraint's date, which the task keeps; actual is the date the link would give. Only with apply_constraints: true. |
"calendar-non-working" |
task, proposed, snapped (DateValue) |
A summary moved as a block and a descendant landed on non-working time. snapped currently always equals proposed. Only with strict_calendar: true. |
See Reading results.
Note#
Tagged by kind. Notes are information; the call still succeeds.
kind |
Fields | When |
|---|---|---|
"dropped-task" |
task, reason |
The task has unscheduled: true. |
"dropped-link" |
link, reason |
The link can't take part in the plan, for example its source or target is unknown or unscheduled. |
"dropped-assignment" |
assignment, reason |
The assignment's task is unscheduled. |
"repaired" |
path, message |
The project was created with {"validation": "repair"} and the input was changed at path. |
reason and message are human-readable text. Branch on kind, not on the text.
Analytics#
| Field | Type | Present | Description |
|---|---|---|---|
status |
"available" | "invalid" |
always | "invalid" on a cyclic project. |
criticalPath |
{ tasks: Id[], links: Id[] } |
criticalPath: true requested and status is "available" |
Critical tasks (summaries included) and links. |
slack |
{ task: Id, total: number, free: number }[] |
slack: true requested and status is "available" |
Total and free slack per task, in the configured duration_unit. |
Check status before reading the other fields. The options are described in AnalyticsOptions; how slack is computed is in Critical path and slack.
Used by#
schedule- responseJsonProject.solve- responseJsonProject.preview- response, withprofilewhen requestedJsonProject.analyze- response, no updates or planner conflictsJsonProject.level- the same fields, flattened intoLevelingResult
Example#
A schedule call with {"reasons": true, "analytics": {"criticalPath": true, "slack": true}} on two linked tasks, one unscheduled task, and two assignments. Only build moved:
Related#
SolveOptions- what the result reportsTaskUpdate- sending anupdatesentry back- Reading results - updates, reasons, conflicts and notes
- Critical path and slack - the
analyticsdata - Load all task dates - reporting every task with
includeUnchanged