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


# schedule_state

Schedules `data` once and returns a [`StateDoc`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/schedule-state.md#statedoc>): the final task dates and conflicts, sorted so that two runs can be compared field by field. It backs the CLI's `schedule --format state` output.

:::warning Unstable
`schedule_state` is `#[doc(hidden)]`. `StateDoc` is an internal parity document, not a stable shape, and can change in any release. Use [`schedule`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/schedule.md>) or [`Project`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/project.md>) for application code.
:::

## Signature

```rust
pub fn schedule_state(data: ProjectData, options: &SolveOptions) -> Result<StateDoc, Error>
```

## Parameters

| Name | Type | Description |
|---|---|---|
| `data` | [`ProjectData`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/project-data.md>) | Project to schedule. Consumed. |
| `options` | [`&SolveOptions`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/solve-options.md>) | Scheduling options for this run. |

`data` is validated strictly. There's no [`ProjectOptions`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/project-options.md>) argument, so [`Validation::Repair`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/validation.md>) isn't available.

## Returns

`Ok(StateDoc)` with every imported task, every conflict, and run metadata.

### StateDoc

```rust
pub struct StateDoc {
    pub tasks: Vec<StateTask>,
    pub conflicts: Vec<StateConflict>,
    pub meta: StateMeta,
}
```

| Field | Type | Description |
|---|---|---|
| `tasks` | `Vec<StateTask>` | One entry per imported task, sorted by `id`. |
| `conflicts` | `Vec<StateConflict>` | Dependency cycles and scheduling conflicts, sorted by `kind`, then by `tasks`. |
| `meta` | `StateMeta` | Run metadata. |

### StateTask

```rust
pub struct StateTask {
    pub id: String,
    pub start: DateTime,
    pub end: DateTime,
}
```

| Field | Type | Description |
|---|---|---|
| `id` | `String` | Task id in its normalized string form. |
| `start` | [`DateTime`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/date-time.md>) | Scheduled start. |
| `end` | [`DateTime`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/date-time.md>) | Scheduled end. |

### StateConflict

```rust
pub struct StateConflict {
    pub kind: String,
    pub tasks: Vec<String>,
    pub constraint_type: Option<ConstraintType>,
    pub violation: Option<Violation>,
    pub required: Option<DateTime>,
    pub actual: Option<DateTime>,
}
```

| Field | Type | Description |
|---|---|---|
| `kind` | `String` | `"cycle"`, `"calendar-non-working"` or `"constraint-violation"`. |
| `tasks` | `Vec<String>` | Ids of the tasks involved. A cycle lists all its tasks, sorted; the other kinds list one task. |
| `constraint_type` | `Option<`[`ConstraintType`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/constraint-type.md>)`>` | `Some` only for `"constraint-violation"`. |
| `violation` | `Option<`[`Violation`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/results/violation.md>)`>` | `Some` only for `"constraint-violation"`. |
| `required` | `Option<`[`DateTime`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/date-time.md>)`>` | `Some` only for `"constraint-violation"`. |
| `actual` | `Option<`[`DateTime`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/date-time.md>)`>` | `Some` only for `"constraint-violation"`. |

`"calendar-non-working"` and `"constraint-violation"` are flattened from [`Conflict`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/results/conflict.md>); see that page for what each one means.

### StateMeta

```rust
pub struct StateMeta {
    pub engine: &'static str,
    pub ok: bool,
    pub converged: bool,
    pub iterations: u32,
    pub notes: Vec<Note>,
}
```

| Field | Type | Description |
|---|---|---|
| `engine` | `&'static str` | Always `"rust"`. |
| `ok` | `bool` | Always `true`; failures return `Err` instead. |
| `converged` | `bool` | Whether scheduling converged, as in [`ScheduleResult`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/results/schedule-result.md>). |
| `iterations` | `u32` | Scheduling iterations used. |
| `notes` | `Vec<`[`Note`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/results/note.md>)`>` | Notes from the run. |

All four types derive `Clone` and `Debug`. With the `serde` feature they also implement `Serialize`; the `Option` fields of `StateConflict` are left out when `None`.

## Errors

| Error | When it occurs |
|---|---|
| [`Error::Input`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/errors/error.md>) | `data` fails validation, or `options` scopes the run to a task that's unknown or unscheduled. |

Dependency cycles aren't errors here. They appear in `conflicts` with `kind: "cycle"`.

## Example

```rust
use plen_core::{schedule_state, ProjectData, SolveOptions};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let state = schedule_state(ProjectData::default(), &SolveOptions::default())?;

    for task in &state.tasks {
        println!("{} {:?} - {:?}", task.id, task.start, task.end);
    }
    println!("conflicts: {}", state.conflicts.len());
    Ok(())
}
```

## Related

- [`schedule`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/schedule.md>) - the stable one-shot call to use instead
- [`ScheduleResult`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/results/schedule-result.md>) - the full result the snapshot is built from
