[Canonical page](<https://docs.dhtmlx.com/planning-engine/js/how-to/clear-leveling/>)
[Full documentation index](<https://docs.dhtmlx.com/planning-engine/llms.txt>)


# Clear leveling

Remove the delays and splits that [`level`](<https://docs.dhtmlx.com/planning-engine/js/api/project-level.md>) wrote into a project, so every task goes back to its unleveled dates.

Leveling stores its result in two task fields: `leveling_delay` and `pauses`. To clear leveling, set `leveling_delay` to `0` and `pauses` to `[]` on every task that has either, then reschedule. For how leveling sets these fields, see [Leveling resources](<https://docs.dhtmlx.com/planning-engine/js/resources-and-assignment/leveling-resources.md>).

## Prerequisites

- A solved [`Project`](<https://docs.dhtmlx.com/planning-engine/js/api/project.md>) that has leveling, either from a `level` call or from loaded data with a non-zero `leveling_delay` or non-empty `pauses`.
- The ids of the tasks that have a delay or pauses. Take them from your own model, or from the `updates` of the [`level`](<https://docs.dhtmlx.com/planning-engine/js/api/project-level.md>) result.

## Steps

1. Build one [`TaskUpdate`](<https://docs.dhtmlx.com/planning-engine/js/api/types/task-update.md>) per leveled task with `leveling_delay: 0` and `pauses: []`. Put all the updates into one [`SchedulingChanges`](<https://docs.dhtmlx.com/planning-engine/js/api/types/scheduling-changes.md>) object:

   ```js
   function clearLeveling(ids) {
     return {
       tasks: {
         update: ids.map((id) => ({ id, leveling_delay: 0, pauses: [] })),
       },
     };
   }
   ```

   Leave the dates out of the update. With no date in the same update, the `leveling_delay` change moves the stored start back by the delay. The `pauses` change keeps the start and duration and recomputes the end.

2. Apply the changes with [`apply`](<https://docs.dhtmlx.com/planning-engine/js/api/project-apply.md>) and check the [`ApplyReport`](<https://docs.dhtmlx.com/planning-engine/js/api/project-apply.md#applyreport>):

   ```js
   const report = project.apply(clearLeveling(ids));
   if (report.needsResync) {
     // Resync with project.solve(data) before the next edit.
   }
   ```

3. Reschedule with [`solve(null)`](<https://docs.dhtmlx.com/planning-engine/js/api/project-solve.md>) and write `result.updates` back to your model:

   ```js
   const result = project.solve(null);
   ```

   The cleared dates become the accepted baseline. The resource contention that leveling resolved shows up again in `result.overallocations`.

The full example below levels three 2-day tasks that share `dev1`, then clears the leveling. It uses the default calendar (Monday to Friday, 08:00-12:00 and 13:00-17:00) and starts on Monday, August 10, 2026:

```js
import { Project } from "plen-js";

function clearLeveling(ids) {
  return {
    tasks: {
      update: ids.map((id) => ({ id, leveling_delay: 0, pauses: [] })),
    },
  };
}

const start = "2026-08-10 08:00";
const data = {
  tasks: [
    { id: "A", start_date: start, duration: 2 },
    { id: "B", start_date: start, duration: 2 },
    { id: "C", start_date: start, duration: 2 },
  ],
  resources: [{ id: "dev1" }],
  assignments: ["A", "B", "C"].map((task) => ({
    task,
    resource: "dev1",
    value: 1,
  })),
};

const project = new Project();
project.solve(data);

// B is delayed to Wednesday, C to Friday.
const leveled = project.level();

// The tasks that leveling delayed or split.
const ids = leveled.updates
  .filter((u) => (u.leveling_delay ?? 0) !== 0 || (u.pauses?.length ?? 0) > 0)
  .map((u) => u.id);

const report = project.apply(clearLeveling(ids));
if (report.needsResync) {
  throw new Error("clearing was rejected, resync with solve(data)");
}

const result = project.solve(null);
for (const update of result.updates) {
  console.log(`${update.id}: ${update.start_date} .. ${update.end_date}`);
}
for (const over of result.overallocations ?? []) {
  for (const window of over.windows ?? []) {
    console.log(
      `${over.resource}: ${window.from} .. ${window.to}, peak ${window.peak}`,
    );
  }
}
```

> **Note:** The leveling result is a [`ScheduleResult`](<https://docs.dhtmlx.com/planning-engine/js/api/types/schedule-result.md>) with an added `rounds` field; read `updates` directly on it.

## Re-level from scratch instead

To replace old leveling with a fresh run, skip the steps above and call `level` again. [`clearFirst`](<https://docs.dhtmlx.com/planning-engine/js/api/types/leveling-options.md>) is `true` by default. The run first sets `leveling_delay: 0` and `pauses: []` on every in-scope task that has either, then levels the clean plan:

```js
const result = project.level();
```

The call diffs its `updates` against the state it started from. A task whose stale delay was cleared and not replaced still gets an update entry, so writing `updates` back to your model keeps it in sync.

With a `scope`, the run clears only in-scope tasks. Set `clearFirst: false` to keep the existing delays and pauses and level on top of them.

## Things to know

- `null` also works: on `leveling_delay` it restores the default of 0, and on `pauses` it clears the list.
- Only leveling produces pauses. Every pause counts as leveling-owned, whether or not its `by` is set, so clearing removes all of them.
- To see what clearing would do before you commit it, pass the same changes to [`preview`](<https://docs.dhtmlx.com/planning-engine/js/api/project-preview.md>). The project stays untouched. See [Previewing changes](<https://docs.dhtmlx.com/planning-engine/js/live-projects/previewing-changes.md>).
- In a live editor, set `baselineId` on the change set to the baseline your model shows. [`apply`](<https://docs.dhtmlx.com/planning-engine/js/api/project-apply.md>) then throws [`ProjectError`](<https://docs.dhtmlx.com/planning-engine/js/api/types/errors.md#projecterror>) with code `"stale-baseline"` if the project has moved on. See [Error handling](<https://docs.dhtmlx.com/planning-engine/js/error-handling.md>).
- If `apply` rejects an operation, `report.needsResync` is `true`, and [`solve(null)`](<https://docs.dhtmlx.com/planning-engine/js/api/project-solve.md>) throws `ProjectError` with code `"needs-resync"` until you send the full data with `solve(data)`. See [Recover from rejected changes](<https://docs.dhtmlx.com/planning-engine/js/how-to/recover-from-rejected-changes.md>).

## Result

The example prints `B` and `C` back on Monday, and the overallocation window on `dev1` returns:

```text
B: 2026-08-10 08:00 .. 2026-08-12 08:00
C: 2026-08-10 08:00 .. 2026-08-12 08:00
dev1: 2026-08-10 08:00 .. 2026-08-11 17:00, peak 3
```
