How to audit a Primavera P6 schedule

Most P6 audit advice is a list of things to click. This page is organised around a different question, because it is the one that decides whether a finding survives being argued with: is the thing you are looking at recorded in the file, or is it something the application computed while you were looking at it?

The first is evidence: written by the submitter's own software at export time, the same tomorrow, and readable by anyone on the other side of the table. The second is a view, depending on the layout, the filter, the columns, and — for several of the most important numbers on the screen — on a project-level setting the schedule carries but does not display.

This page is the P6-specific companion to the schedule review checklist, which is software-agnostic and sorted by what decides each item. Read that first for what to check and what each item does not prove. This page is where the thing lives in P6 or in the exported file. It does not repeat the checklist's items.

Stored or computed: the two-column reading

What you are looking at Stored in the export Computed on the fly
Activity ID, name, WBS Yes — TASK.task_code, task_name, wbs_id
Original and remaining duration Yes, in hours (target_drtn_hr_cnt, remain_drtn_hr_cnt) The day figure on screen is hours divided by a calendar
Actual start, actual finish Yes
Early and late dates Yes, as P6 last calculated them Recalculated the moment anyone presses F9
Total float, free float Yes, in hours (total_float_hr_cnt, free_float_hr_cnt) Same
Critical (the red bars) No — a derived flag Depends on a project setting, see below
Longest path membership Yes — TASK.driving_path_flag Also derived when P6 reschedules
Relationships and lag Yes — TASKPRED, lag in hours
Calendars Yes — CALENDAR.clndr_data, a packed string The working-day arithmetic on screen
Scheduling settings Yes — SCHEDOPTIONS, one row per project
Layout, filter, column set, bar colours No Entirely a display choice

The practical consequence: a screenshot is never the finding. It shows a computed view under settings nobody recorded. The exported file plus the settings row is the finding, and it is reproducible.

1. Get the right file, and know what it is

Ask for the native export the submitter's own P6 produced — .xer or P6 XML — not a PDF, not a printed Gantt, not a .mpp. What each of those carries is on schedule file formats.

Three things about an XER, all covered at length on what an XER file is:

2. Get the right project out of it — the trap nobody warns you about

A single XER can hold several projects, and a real schedule is frequently exported alongside one or more near-empty stubs: a one-activity shell, or a PROJECT row with no activities at all. Which is written first is not governed by size, by name, or by anything a reader can predict.

A tool — or a person — that silently opens "the first project" can therefore produce a complete, confident, fully scored review of a one-activity stub while the several-thousand-activity schedule beside it in the same file is never read. Nothing about the output looks wrong.

So the first query on any XER is: how many PROJECT rows does it hold, and how many TASK rows carry each proj_id? Count activities from the TASK table by proj_id — not from anything the PROJECT row declares about itself. Then name the project you reviewed, in writing, and say if the container held others.

This project's importer enumerates the projects it finds and refuses to choose one on your behalf, listing each with its activity count so the choice is obvious without opening the file.

3. The data date, and which field it came from

The data date lives on the PROJECT row as last_recalc_date. It is not plan_start_date, which is the planned start of the project. Reading the wrong one makes every progressed schedule reschedule from its original start and report all the completed work as still to do — a failure that produces a complete, internally consistent, entirely wrong schedule.

Then settle the convention, because the file does not state it. A data date of 1 February means either that work is reported through and including 1 February, or that 1 February is the first day of the next period. Schedulers, specifications and software disagree, mostly without noticing, and the difference is one day per window boundary — over eleven monthly updates, eleven days of argument from an assumption neither side wrote down. CONCEPTS.md §3 sets out both readings.

Also read plan_end_date on the same row: the Must Finish By a planner typed. Where it is present it drives the backward pass, so it is the reason for float figures that otherwise look inexplicable. Do not confuse it with scd_end_date, P6's own computed finish; the two can sit months apart on one row.

4. Check which settings produced the dates, before you read any date

This is the step most reviews skip and the one that makes every later number comparable. P6 keeps the scheduling settings in a SCHEDOPTIONS record, one row per project, and they change computed dates by weeks: retained logic against progress override, the definition of critical activities, the calendar a lag is counted on. Each is a declared fact the file carries.

A schedule recalculated under different settings from the update it is compared against is not comparable to it, and nothing on the printed page says so. The P6 Schedule Options record is the reference for each setting, what changes if it is set the other way, and how to read which was used.

Two notes. The SCHEDOPTIONS row must be the one whose proj_id matches the project you selected in step 2 — a multi-project export carries one row per project. And the critical-activity definition is not in SCHEDOPTIONS at all: P6 stores it on the PROJECT row as critical_path_type.

5. The logic sweep

The relationships are in TASKPRED, one row per link: successor task_id, pred_task_id, pred_type, lag_hr_cnt.

The counts a reviewer wants out of this table — open ends, dangling logic, the finish-to-start share, the lag inventory — are items 1, 2, 9 and 10 of the checklist.

6. Constraints

Constraints are on the TASK row, as a type and a date. They are stored, so the inventory is evidence. What it cannot tell you is whether a constraint is artificial — that is intent, and no computation reaches it. The honest output is the population a prohibition describes, listed, for a person to read. Schedule constraints covers the types and what each does to the backward pass.

Look first for the constraint that has quietly become the anchor of the whole schedule: a Must Finish By on the project, or a mandatory constraint mid-network, either of which makes total float a measurement against that date rather than against the schedule's own finish.

7. Calendars

CALENDAR.clndr_data is a single cell holding a packed, bracketed tree: the working week, the shift times, and every holiday and shutdown. It is the column with no downstream symptom — get it wrong and every date, float and delay attribution moves together while the schedule still looks reasonable. Inside clndr_data has the grammar; the audit-side points:

More on the review question, as against the file question, on schedule calendars.

8. Progress and actual dates

Actual start and actual finish are stored, and comparing them against the data date is the one purely arithmetic status check there is. The subtler issue: P6 overwrites the early dates of a started activity with its recorded actual start, so early_start_date on a progressed row is not a forecast. A comparison that treats it as one reports a disagreement on every progressed activity in the file.

Out-of-sequence progress belongs here too, and it is where the display sits furthest from the file: whether an out-of-sequence successor's remaining work is held by its unfinished predecessor depends entirely on the progress mode in the settings row, and the bars give no indication of which mode drew them.

9. Float

total_float_hr_cnt and free_float_hr_cnt are hours, against the activity's own calendar. To convert to working days, divide by the day_hr_cnt of the calendar named in that activity's TASK.clndr_id, and carry the sign around the conversion — rounding the magnitude of a negative float is not the same as rounding the signed value.

What float means on a given file is decided by two settings, not one: how total float is computed, and what the backward pass was anchored on. Both are in the options reference; the difference between the two float figures is on total float and free float.

10. The critical path, and why two reviewers can disagree

P6 reports one criticality definition at a time, chosen by a project-level setting stored on the PROJECT row as critical_path_type: CT_DrivPath for Longest Path, CT_TotFloat for the total-float definition. Whichever is set, the red bars on screen show that one, and the other answer is discarded silently.

They are different questions. "Which activities have no spare time?" is a float question. "Which work is actually pushing the completion date?" is a longest-path question. On a schedule with a Must Finish By a working day past the computed finish, every activity on the driving chain can carry a day of float — so a reviewer filtering on total float at or below zero finds almost nothing, while a reviewer reading the longest path finds a chain of dozens. Both filtered correctly. Neither number corrects the other.

A third sense is worth knowing, because it is what driving_path_flag records: the driving set — every activity that drives the finish — is wider than the driving chain, because at a tie two predecessors both drive and a chain can follow only one.

So when a comment and a response disagree about the length of the critical path, the first question is not who counted wrong. It is which definition each was reading, and what the file's own setting says. CONCEPTS.md §2 sets out the two schools and why this project computes and reports both. UFGS 01 32 01.00 10 §3.12(f) requires the Longest Path setting specifically, which is answerable from the exported file without re-running anything — see the UFGS page.

What P6 shows you that is a display choice, not a fact

What a clean pass through this page does not establish

Everything above is mechanical: that the file is readable, that you are reading the right project in it, and that you know which settings produced the numbers. It establishes nothing about whether the durations are achievable, whether the sequence is how the work will be built, whether the scope is complete, or whether anybody is owed time. Those are Part 3 of the checklist, and they are decided by people with names. Whether a submission is acceptable is the reviewing authority's determination.

Source: web/pages/p6-schedule-audit.md. Source commit date: 2026-09-11.

See it in practice

Follow the evidence, from the schedule to the finding.

Explore the sample