Project#level#

Resolves resource overallocation in a Project. It first runs solve(null) with default options, then writes leveling_delay and pauses on tasks and accepts the leveled state as the new baseline. Use it after loading data or after apply, in place of solve(null).

Signature#

level(options?: LevelingOptions): LevelingResult

Synchronous. Runs on the calling thread, so a long run blocks the event loop.

Parameters#

Name Type Description
options LevelingOptions Optional. Scope, order, basis and how leveling may move tasks. Default {}: the whole project with default settings.

Behavior#

  • Forward scheduling only.
  • The leveled dates, delays and pauses replace the baseline, and the project is marked solved. To see leveling without committing it, call level on a clone().
  • level never changes assignments.
  • On a cyclic project, it returns the initial solve's result with rounds: 0 and edits no delay or pause.
  • updates are relative to the state the call started from, so they can be applied to the task list the caller already holds. They include leveling_delay and pauses changes, and edits made by earlier apply calls.

For how leveling picks tasks to delay or split, see Leveling Resources.

Returns#

A LevelingResult: a fresh object that shares nothing with the project.

LevelingResult#

Every field of ScheduleResult, taken from the final solve, plus one field:

Field Type Description
rounds number Number of leveling rounds that proposed a correction. 0 when nothing was overallocated or the project has cycles.
Note

The leveling result is a ScheduleResult with an added rounds field; read updates on it.

Errors#

Error When
InputError An unknown id in options.scope.resources or options.scope.tasks (path scope.resources / scope.tasks); the project has config.schedule_from_end: true (path config.schedule_from_end); an unknown option key or a bad option value; a non-finite number or an invalid Date in options.
ProjectError "needs-resync" An earlier apply had rejected operations and no full solve(data) has run since.
Error("Project has been disposed") The project was disposed.

Example#

Two tasks share one resource. Level a copy first, then the project itself.

import { Project } from "plen-js";

const project = new Project();
project.solve({
  tasks: [
    { id: "a", start_date: "2026-08-10 08:00", duration: 2 },
    { id: "b", start_date: "2026-08-10 08:00", duration: 2 },
  ],
  resources: [{ id: "dev" }],
  assignments: [
    { task: "a", resource: "dev", value: 1 },
    { task: "b", resource: "dev", value: 1 },
  ],
});

// Preview: level a copy, the project keeps its dates.
const proposal = project.clone().level();
for (const update of proposal.updates) {
  console.log(`task ${update.id} delay ${update.leveling_delay}`);
}

// Commit: level the project itself.
const leveled = project.level();
console.log(`${leveled.rounds} round(s)`);