# Validate & publish

Publishing is the boundary between a plan you are editing and the schedule workers may rely on. Fivexer keeps validation, preflight, and publication separate so an automated solve can never become an official roster by accident.

## Validate at any time

```
tsconst lint = await fivexer.rosters.lint(rosterId);
```

Lint checks the saved draft by default. You may also supply an assignment set to inspect an unsaved alternative. The result includes:

- `compliant`;
- hard, medium, and soft issue counts;
- filled and total slot counts;
- every unfilled shift occurrence;
- structured issues tied to people and shifts.

Validation is pure: it changes no assignments and sends no notifications.

## Explain before overriding

When a manager wants to place someone despite a warning, ask the engine for the actual verdict first:

```
tsconst explanation = await fivexer.rosters.explain(rosterId, {
  employeeId: 'worker_anna',
  shiftInstanceId: 'night_ward_a@2026-09-03',
});
```

For a shortlist, use `rosters.candidates`. It includes blocked workers with reasons instead of hiding them. That distinction matters operationally: “not shown” and “two hours short of required rest” lead to very different decisions.

## Run publishing preflight

```
tsconst preflight = await fivexer.rosters.publishPreflight(rosterId);
```

Preflight answers four questions:

1. Is the selected version compliant and fully covered?
2. What changed from the currently published version?
3. Which workers would be affected?
4. Are there notice-window issues or pending time-off requests?

Pending leave is intentionally separate from compliance. Only approved leave enters the solver; an undecided request is a management warning rather than a fact the engine may treat as absence.

## Publish a specific version

```
tsawait fivexer.rosters.publish(rosterId, {
  versionId: preflight.versionId,
});
```

Pass the version you reviewed. Publishing a specific immutable version prevents a last-second edit in another session from becoming official under your approval.

On first publication, assigned workers receive the published schedule. Later publication produces a diff and notifies the affected people about additions and removals. Published versions remain in history so you can establish what the official plan was at any point.

## Changes after publication

Do not rebuild an entire roster to handle one call-in. Use [time off and cover](/docs/rostering/time-off-cover/) so untouched assignments stay pinned and the change has its own operational record.

When deliberate manual changes are necessary:

1. edit a draft derived from the current plan;
2. lint it again;
3. inspect the publication diff and notice issues;
4. publish the reviewed version.

That workflow keeps “the grid looked right” from becoming the only audit trail.
