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


# Critical

The critical path of a schedule, as the ids of its critical tasks and links. It isn't built by hand. Read it from [`Analytics::critical_path`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/results/analytics.md>), which is `Some` when the run asked for it with [`AnalyticsOptions::critical_path`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/analytics-options.md>). For when a task or link counts as critical, see [Critical path and slack](<https://docs.dhtmlx.com/planning-engine/rust/scheduling/critical-path-and-slack.md>).

## Declaration

```rust
#[derive(Clone, Debug, PartialEq)]
pub struct Critical {
    pub tasks: Vec<Id>,
    pub links: Vec<Id>,
}
```

With the `serde` feature, it also implements `Serialize` and `Deserialize`.

## Fields

| Name | Type | Description |
|---|---|---|
| `tasks` | `Vec<`[`Id`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/id.md>)`>` | Ids of the critical tasks, summaries included. Each task appears once. Empty when no task is critical. |
| `links` | `Vec<`[`Id`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/id.md>)`>` | Ids of the critical links. Each link appears once. Empty when no link is critical. |

## Serialization

With the `serde` feature, a `Critical` serializes as:

```json
{ "tasks": ["design", "build"], "links": ["l1"] }
```

## Example

Schedule two tasks in sequence and a shorter one in parallel, then print the critical path.

```rust
use plen_core::{
    schedule, AnalyticsOptions, DateTime, LinkData, LinkType, ProjectData, SolveOptions, TaskData,
};

fn task(id: &str, start: DateTime, duration: f64) -> TaskData {
    let mut task = TaskData::new(id);
    task.start_date = Some(start);
    task.duration = Some(duration);
    task
}

fn fs(id: &str, source: &str, target: &str) -> LinkData {
    LinkData {
        id: id.into(),
        source: source.into(),
        target: target.into(),
        link_type: LinkType::Fs,
        lag: 0.0,
        lag_unit: None,
    }
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let monday = DateTime::from_ymd_hm(2026, 8, 10, 8, 0).ok_or("invalid date")?;
    let data = ProjectData {
        tasks: vec![
            task("design", monday, 2.0),
            task("build", monday, 3.0),
            task("docs", monday, 1.0),
        ],
        links: vec![fs("l1", "design", "build"), fs("l2", "design", "docs")],
        ..Default::default()
    };

    let options = SolveOptions {
        analytics: AnalyticsOptions {
            critical_path: true,
            ..Default::default()
        },
        ..Default::default()
    };
    let result = schedule(data, &options)?;

    let analytics = result.analytics.ok_or("analytics not requested")?;
    let critical = analytics.critical_path.ok_or("critical path not available")?;
    for id in &critical.tasks {
        println!("critical task: {id}"); // design, build
    }
    for id in &critical.links {
        println!("critical link: {id}"); // l1
    }
    Ok(())
}
```

## Related

- [`Analytics`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/results/analytics.md>) - holds the critical path
- [`TaskSlack`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/results/task-slack.md>) - per-task slack computed next to the critical path
- [`AnalyticsOptions`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/analytics-options.md>) - requests the critical path
- [Critical path and slack](<https://docs.dhtmlx.com/planning-engine/rust/scheduling/critical-path-and-slack.md>) - explains when tasks and links are critical
