[Canonical page](<https://docs.dhtmlx.com/planning-engine/js/api/project-slots/>)
[Full documentation index](<https://docs.dhtmlx.com/planning-engine/llms.txt>)


# Project#slots

Turns a pool of workers with skills and a list of task requirements into the [`Slot`](<https://docs.dhtmlx.com/planning-engine/js/api/types/slot.md>)s that [`suggestAssignments`](<https://docs.dhtmlx.com/planning-engine/js/api/project-suggest-assignments.md>) takes. Existing active assignments are bound to the slots, so repeated runs stay stable after a commit. Needs a solved [`Project`](<https://docs.dhtmlx.com/planning-engine/js/api/project.md>) with no unsolved edits.

:::note
`slots` throws `InputError` / `ProjectError` like the other `Project` methods.
:::

## Signature

```ts
slots(pool: Pool, requirements: Requirement[]): Slot[]
```

Synchronous. Reads the project's accepted tasks, resources and assignments. Never modifies the project.

## Parameters

| Name | Type | Description |
|---|---|---|
| `pool` | [`Pool`](<https://docs.dhtmlx.com/planning-engine/js/api/project-slots.md#pool>) | Workers that may be assigned. Pool order sets the order of each slot's `allowed` |
| `requirements` | [`Requirement[]`](<https://docs.dhtmlx.com/planning-engine/js/api/project-slots.md#requirement>) | What each task needs. An empty array returns `[]` |

Unknown fields in any of these objects throw `InputError` `"parse"`. A `null` field takes its default.

### Pool

The workers available for assignment.

| Field | Type | Default | Description |
|---|---|---|---|
| `workers` | [`Worker[]`](<https://docs.dhtmlx.com/planning-engine/js/api/project-slots.md#worker>) | required | Workers in preference order. Earlier workers win ties |

### Worker

One resource and its skills.

| Field | Type | Default | Description |
|---|---|---|---|
| `resource` | `Id` | required | A resource of the project. Each resource can be listed once |
| `skills` | [`Skill[]`](<https://docs.dhtmlx.com/planning-engine/js/api/project-slots.md#skill>) | `[]` | The worker's skills. Each skill id can be listed once |

### Skill

One skill a worker has, with its grade.

| Field | Type | Default | Description |
|---|---|---|---|
| `id` | `Id` | required | Skill id, matched against [`SkillMatch.skill`](<https://docs.dhtmlx.com/planning-engine/js/api/project-slots.md#skillmatch>) |
| `value` | `number` | `1` | Grade: `0`/`1` for a yes/no skill, an integer grade otherwise. Must be finite |

### Requirement

What one task needs: a set of skill matches and the number of people.

| Field | Type | Default | Description |
|---|---|---|---|
| `id` | `Id` | required | Requirement id. Its slots get the ids `"<id>#1"` .. `"<id>#<count>"`. Unique across `requirements` |
| `task` | `Id` | required | A scheduled leaf task |
| `matches` | [`SkillMatch[]`](<https://docs.dhtmlx.com/planning-engine/js/api/project-slots.md#skillmatch>) | required | Every match must hold for a worker to be allowed. `[]` allows every worker |
| `count` | `number` | `1` | Number of slots, an integer `>= 1` |
| `units` | `number` | `1` | `value` of the assignment that fills each slot. Finite and `> 0` |
| `assignments` | `Id[] \| null` | `null` | Explicit binding: the assignments to bind to this requirement's slots, in order. Replaces automatic binding (see [Behavior](<https://docs.dhtmlx.com/planning-engine/js/api/project-slots.md#behavior>)). `[]` leaves every slot empty |

A requirement id must stay on one task. Its slot ids become assignment ids on that task after a commit. Reusing the id for another task then makes the next call throw at `requirements[i].id`.

### SkillMatch

One condition on a worker's skill: `worker value <op> value`, inclusive.

| Field | Type | Default | Description |
|---|---|---|---|
| `skill` | `Id` | required | Skill id. A worker that doesn't list it has value `0` |
| `op` | `"at_least" \| "no_more" \| "equal"` | `"at_least"` | `"at_least"`: `>=`; `"no_more"`: `<=`; `"equal"`: `==` |
| `value` | `number` | `1` | Value to compare with. Must be finite |

With the defaults, `{ skill: "backend" }` means "has the skill".

## Behavior

The task's existing active assignments are bound per task, across all requirements on that task, in three steps:

1. **Slot id.** An assignment whose id is one of the requirement's slot ids binds to that slot, even when its resource isn't in `allowed`. That slot is then broken, which `suggestAssignments` can repair. This step runs for every requirement of the task before any explicit list.
2. **Explicit list.** A requirement with `assignments` set uses that list instead of automatic binding. A listed slot-id assignment keeps its slot, the other entries take the remaining slots in order, and leftover slots stay empty.
3. **Matching.** A deterministic maximum matching binds the remaining assignments to the empty slots of requirements without a list. An assignment can take a slot only when its resource is in the slot's `allowed`. Input order decides between equal matchings, and an earlier requirement can't take the only worker a later one fits.

Assignments left unbound stay on the task without a slot.

## Returns

A `Slot[]`: `count` slots per requirement, in requirement order, then instance order.

| Field | Value |
|---|---|
| `id` | `"<requirement id>#<n>"`, `n` = 1..`count` (for example `be#1`, `be#2`) |
| `task` | The requirement's `task` |
| `allowed` | Pool workers for which every match of the requirement holds, in pool order |
| `value` | The requirement's `units` |
| `assignment` | The id of the active assignment bound to the slot. Absent when the slot is empty |

The array can be passed to [`suggestAssignments`](<https://docs.dhtmlx.com/planning-engine/js/api/project-suggest-assignments.md>) as is. An assignment created from a slot has the slot's id, so the next call binds it back to the same slot.

## Errors

The first failing check wins: the project state, then the pool, then each requirement in input order.

| Error | When |
|---|---|
| [`ProjectError`](<https://docs.dhtmlx.com/planning-engine/js/api/types/errors.md>) `"no-baseline"` | The project is unsolved or has unsolved edits (after [`apply`](<https://docs.dhtmlx.com/planning-engine/js/api/project-apply.md>)) |
| [`InputError`](<https://docs.dhtmlx.com/planning-engine/js/api/types/errors.md>) `"validation"` | The pool or a requirement is invalid. `path` names the item (table below) |
| `InputError` `"validation"`, `path: null` | A field has the wrong type or value, such as a non-integer `count` or an unknown `op` |
| `InputError` `"parse"` | An unknown field in the pool, a worker, a skill, a requirement or a match |
| `Error("Project has been disposed")` | The project was disposed |

`InputError` paths:

| Path | When |
|---|---|
| `pool.workers[i].resource` | Unknown resource, or the same resource listed as two workers |
| `pool.workers[i].skills[j].id` | The same skill listed twice on one worker |
| `pool.workers[i].skills[j].value` | Not finite |
| `requirements[i].id` | Duplicate requirement id, or one of its slot ids is an active assignment on another task |
| `requirements[i].task` | Unknown or unscheduled task |
| `requirements[i].count` | `0` |
| `requirements[i].units` | Not finite or `<= 0` |
| `requirements[i].matches[j].value` | Not finite |
| `requirements[i].assignments` | More entries than `count`, or an assignment with one of this requirement's slot ids left out of the list |
| `requirements[i].assignments[k]` | Unknown or inactive assignment, an assignment on another task, or one bound twice (the message names the other requirement when it already holds it) |

The call takes no baseline token, so it never throws `"stale-baseline"`.

## Example

Build the slot for a task that needs a backend grade of at least 2.

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

const project = new Project();
project.solve({
  tasks: [{ id: "B", start_date: "2026-08-10 08:00", duration: 2 }],
  resources: [{ id: "ann" }, { id: "bob" }],
});

const slots = project.slots(
  {
    workers: [
      { resource: "ann", skills: [{ id: "backend", value: 1 }] },
      { resource: "bob", skills: [{ id: "backend", value: 2 }] },
    ],
  },
  [{ id: "be", task: "B", matches: [{ skill: "backend", value: 2 }] }],
);
console.log(slots);
// [ { allowed: [ 'bob' ], id: 'be#1', task: 'B', value: 1 } ]
```

## Related

- [`Slot`](<https://docs.dhtmlx.com/planning-engine/js/api/types/slot.md>) - the returned slots
- [`Project#suggestAssignments`](<https://docs.dhtmlx.com/planning-engine/js/api/project-suggest-assignments.md>) - fills the slots
- [Errors](<https://docs.dhtmlx.com/planning-engine/js/api/types/errors.md>) - `InputError` and `ProjectError`
- [Skills and Requirements](<https://docs.dhtmlx.com/planning-engine/js/resources-and-assignment/skills-and-requirements.md>) - pools, requirements and binding
