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


# SchedulingChanges

One set of edits to a live [`Project`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/project.md>): tasks, links, resources and assignments to add, update or remove. [`Project::apply`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/project.md#apply>) commits it, [`Project::preview`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/project.md#preview>) tries it on a copy, and each [`Candidate`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/evaluate/candidate.md>) passed to [`Project::evaluate`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/project.md#evaluate>) carries one. [`Project::suggest_assignments`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/project.md#suggest_assignments>) returns one in its [`SuggestProposal`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/suggest/suggest-proposal.md>).

Start from `SchedulingChanges::default()`, where every bucket is empty, and push records into the buckets the edit needs.

## Declaration

```rust
#[derive(Clone, Debug, Default)]
pub struct SchedulingChanges {
    pub baseline_id: Option<String>,
    pub tasks: Changes<TaskData, TaskUpdate>,
    pub links: Changes<LinkAdd, LinkUpdate>,
    pub resources: Changes<ResourceData, ResourceUpdate>,
    pub assignments: Changes<AssignmentData, AssignmentUpdate>,
}
```

## Fields

| Field | Type | Default | Description |
|---|---|---|---|
| `baseline_id` | `Option<String>` | `None` | Baseline token the edits were made against. `None` skips the check. `Some(token)` must name the project's current baseline, or the call fails with [`ProjectError::StaleBaseline`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/errors/project-error.md>). |
| `tasks` | [`Changes`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/changes/changes.md>)`<`[`TaskData`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/task-data.md>)`, `[`TaskUpdate`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/changes/task-update.md>)`>` | empty | Tasks to add, update or remove by id. |
| `links` | [`Changes`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/changes/changes.md>)`<`[`LinkAdd`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/changes/link-add.md>)`, `[`LinkUpdate`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/changes/link-update.md>)`>` | empty | Links to add, update or remove by id. |
| `resources` | [`Changes`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/changes/changes.md>)`<`[`ResourceData`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/resource-data.md>)`, `[`ResourceUpdate`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/changes/resource-update.md>)`>` | empty | Resources to add, update or remove by id. |
| `assignments` | [`Changes`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/changes/changes.md>)`<`[`AssignmentData`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/assignment-data.md>)`, `[`AssignmentUpdate`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/changes/assignment-update.md>)`>` | empty | Assignments to add, update or remove by id. |

Take the token for `baseline_id` from the latest solve result ([`ScheduleResult::baseline_id`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/results/schedule-result.md>)). Tokens are opaque: don't compare them across runs.

A set has no calendar bucket. Calendars can't be added or edited through `SchedulingChanges`; that takes a full [`solve(Some(data))`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/project.md#solve>).

## Operation order

Operations run in a fixed order, not in the order they were pushed. Kinds run in the order tasks, links, resources, assignments. Within a kind:

| Kind | Order |
|---|---|
| `tasks` | `remove`, `add`, `update` |
| `links` | `remove`, `update`, `add` |
| `resources` | `remove`, `add`, `update` |
| `assignments` | `remove`, `update`, `add` |

Within a bucket, records run in vector order. Each operation is identified by its bucket and index, such as `tasks.update[0]`, in [`AppliedOperation`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/changes/applied-operation.md>) and [`RejectedOperation`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/changes/rejected-operation.md>).

## Example

Move a task, add a link and check the edit against the current baseline.

```rust
use plen_core::{
    DateTime, LinkAdd, LinkType, Patch, Project, ProjectData, ProjectOptions,
    SchedulingChanges, SolveOptions, TaskData, TaskUpdate,
};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let monday = DateTime::from_ymd_hm(2026, 8, 10, 8, 0).ok_or("invalid date")?;
    let wednesday = DateTime::from_ymd_hm(2026, 8, 12, 8, 0).ok_or("invalid date")?;

    let data = ProjectData {
        tasks: vec![
            TaskData {
                start_date: Some(monday),
                duration: Some(1.0),
                ..TaskData::new(1)
            },
            TaskData {
                start_date: Some(monday),
                duration: Some(2.0),
                ..TaskData::new(2)
            },
        ],
        ..Default::default()
    };

    let mut project = Project::new(ProjectOptions::default());
    let solved = project.solve(Some(data), &SolveOptions::default())?;

    let mut changes = SchedulingChanges {
        baseline_id: solved.baseline_id.clone(),
        ..Default::default()
    };

    let mut moved = TaskUpdate::new(1);
    moved.start_date = Patch::Value(wednesday);
    changes.tasks.update.push(moved);

    changes.links.add.push(LinkAdd {
        id: None,
        source: 1.into(),
        target: 2.into(),
        link_type: LinkType::Fs,
        lag: 0.0,
        lag_unit: None,
    });

    let report = project.apply(&changes)?;
    for op in &report.rejected {
        println!("rejected {}: {}", op.path, op.message);
    }
    Ok(())
}
```

## Related

- [`ApplyReport`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/changes/apply-report.md>) - what `Project::apply` returns for a change set
- [`ProjectError`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/errors/project-error.md>) - the error a stale `baseline_id` causes
- [Data Updates](<https://docs.dhtmlx.com/planning-engine/rust/live-projects/editing-a-project.md>) - shows how to build and apply change sets
- [Previewing Changes](<https://docs.dhtmlx.com/planning-engine/rust/live-projects/previewing-changes.md>) - shows how to try a change set without committing it
