Metrics#

The scores of one plan state against the solved baseline: project and focus-task finish, resource overload, conflict and cycle counts, and one cost number for ranking. Metrics is a response payload only. JsonProject.evaluate returns it for the baseline and for the scheduled stage of each candidate, and JsonProject.suggestAssignments returns it for the proposed state. The leveled stage comes as LeveledMetrics: the same fields plus a leveling summary.

Every measurement is an absolute value plus a delta against the baseline. In the baseline's own metrics, every delta is 0.

Fields#

Field Type Description
finish object Finish of the project and of each focus task
overload object Resource overload: total, per resource and per focus task
conflicts Amount Number of conflicts in the stage's schedule result
cycles Amount Number of dependency cycles in the stage's schedule result. Above 0 when the stage is cyclic
cost number Ranking score of the stage. Lower is better. See Cost

Every field is always present.

Finish fields#

Field Type Description
project Shift | null Latest end over the scheduled tasks. null when the stage has no tasks. The delta is measured on the global calendar, and it's 0 when the baseline has no tasks
tasks object[] One entry per focus task, in focus order. Empty without focus tasks

Focus task finish#

Field Type Description
id Id The focus task
finish Shift | null The task's end. The delta is measured on the task's calendar. null when the task isn't in the stage, for example after the candidate removed it

Overload fields#

Overload is the sum over time buckets of how far a resource's load goes over its capacity: Σ max(0, load − capacity). The unit is capacity × buckets, so on a "day" basis, 2 means two resource-days over. The baseline and every stage of every candidate use one bucket size: level.basis when the options give it, otherwise the basis derived from config.duration_unit.

Field Type Description
total Amount Overload summed over all resources
resources ResourceOverload[] One entry per resource that's non-zero in the stage or in the baseline. Resources in stage order come first, then resources that are non-zero only in the baseline
focus object[] One entry per focus task, in focus order. Empty without focus tasks

ResourceOverload#

Field Type Description
resource Id The resource
overload Amount The resource's overload. value can be 0 when the resource is overloaded only in the baseline

Focus task overload#

Field Type Description
task Id The focus task
resources ResourceOverload[] | null Overload per resource, summed over the buckets that intersect the task's [start, end) in this stage. Lists every resource that's non-zero there in the stage or in the baseline, in the same order as overload.resources. null when the task isn't in the stage. A zero-length milestone covers no bucket

Shift#

A date and its distance from the baseline date.

Field Type Description
date DateValue The date in this stage, as YYYY-MM-DD HH:mm
delta number Working time from the baseline date to date, in config.duration_unit. Positive when later

Amount#

A count or a sum and its difference from the baseline.

Field Type Description
value number The value in this stage
delta number value minus the baseline's value

Cost#

cost is one fixed formula:

cost = max(0, finish.project.delta)
     + overload.total.value
     + 1000 × (conflicts.value + cycles.value)

An earlier finish earns no bonus. The 1000 penalty puts any stage with conflicts or cycles behind every stage without them. To rank by other rules, read the raw fields instead. How the stages are scored and compared is covered in Evaluating Alternatives.

LeveledMetrics#

The metrics of the leveled stage. All Metrics fields sit flat in the same object, next to a summary of the leveling run. Present only when the call's options set level.

Field Type Description
finish, overload, conflicts, cycles, cost As in Metrics, measured after leveling
converged boolean Whether the final scheduling pass after leveling reached a fixed point within max_iterations. Same as converged in the level result
rounds number Leveling rounds that proposed a correction. As rounds in the level result
windows number Overallocation windows left after leveling, whatever their reason

At the leveled stage, focus overload shows what leveling couldn't resolve around the task.

Used by#

Example#

Two tasks of 2 days each, both on dev1 at full capacity, with task B in focus. The baseline Metrics: dev1 is 2 resource-days over, and nothing is late yet.

{
  "conflicts": { "delta": 0, "value": 0 },
  "cost": 2,
  "cycles": { "delta": 0, "value": 0 },
  "finish": {
    "project": { "date": "2026-08-12 08:00", "delta": 0 },
    "tasks": [{ "finish": { "date": "2026-08-12 08:00", "delta": 0 }, "id": "B" }]
  },
  "overload": {
    "focus": [
      { "resources": [{ "overload": { "delta": 0, "value": 2 }, "resource": "dev1" }], "task": "B" }
    ],
    "resources": [{ "overload": { "delta": 0, "value": 2 }, "resource": "dev1" }],
    "total": { "delta": 0, "value": 2 }
  }
}

The LeveledMetrics of the unchanged plan after leveling: the overload is gone, and B and the project finish 2 days later.

{
  "conflicts": { "delta": 0, "value": 0 },
  "converged": true,
  "cost": 2,
  "cycles": { "delta": 0, "value": 0 },
  "finish": {
    "project": { "date": "2026-08-14 08:00", "delta": 2 },
    "tasks": [{ "finish": { "date": "2026-08-14 08:00", "delta": 2 }, "id": "B" }]
  },
  "overload": {
    "focus": [
      { "resources": [{ "overload": { "delta": -2, "value": 0 }, "resource": "dev1" }], "task": "B" }
    ],
    "resources": [{ "overload": { "delta": -2, "value": 0 }, "resource": "dev1" }],
    "total": { "delta": -2, "value": 0 }
  },
  "rounds": 2,
  "windows": 0
}