The P6 Schedule Options record, and why a forensic review reads it first
Primavera P6 keeps the settings that decide how a schedule was calculated in a
record of its own. In an XER export it is the SCHEDOPTIONS table, one row per
project. It is a handful of short fields, it is never printed on a Gantt chart,
and it is the most under-discussed thing in P6 forensics — because several of
those fields move the computed completion date by weeks while changing nothing
that appears on the page.
This project reads that record directly, so it can check how the file was computed — retained logic versus progress override, longest path versus total float, the lag calendar — and not only what it displays. A submission can satisfy every visible requirement and still have been calculated under a definition the contract prohibits. This page is the reference behind that sentence.
It is also where two questions meet. "How was this file computed?" is answerable from the file. "How was it required to be computed?" is answerable from the contract — and several agency specifications now name these settings individually, by their P6 names. That junction is why the page exists.
Where the settings live
| Setting | Field | Values seen in real exports |
|---|---|---|
| Progress mode for out-of-sequence work | sched_retained_logic, sched_progress_override |
Y / N, written as a pair and not always consistently |
| Definition of critical activities | PROJECT.critical_path_type, not SCHEDOPTIONS |
CT_DrivPath (Longest Path), CT_TotFloat |
| Calendar for scheduling relationship lag | sched_calendar_on_relationship_lag |
rcal_Predecessor, rcal_Successor, rcal_24Hour, rcal_Project |
| Total float computation | sched_float_type |
FT_SS (start float), FT_FF (finish float), ST_TotalFloat (the smaller of the two) |
| Start-to-start lag basis | sched_lag_early_start_flag |
Y / N |
| Make open-ended activities critical | sched_open_critical_flag |
Y / N |
| Use Expected Finish Dates | sched_use_expect_end_flag, older exports sched_use_expect_end_date |
Y / N |
| External (other-project) relationships | sched_outer_depend_type |
SD_Both, SD_None |
| Calculate float based on the finish date of | sched_use_project_end_date_for_float |
Y / N |
| Multiple float paths | enable_multiple_longest_path_calc, max_multiple_longest_path |
Y / N, and a count |
Two notes before the detail.
The row has to be the one for the project you are reviewing. A
multi-project export carries one SCHEDOPTIONS row per project, and taking the
first row schedules every project in the file under whichever project happened to
be written first. Match on proj_id. A project with no row of its own has P6's
defaults — not its neighbour's settings.
P6 XML names the same settings differently. A P6 XML export carries, among
others, OutOfSequenceScheduleType, RelationshipLagCalendar,
MakeOpenEndedActivitiesCritical, ComputeTotalFloatType,
StartToStartLagCalculationType, UseExpectedFinishDates,
IgnoreOtherProjectRelationships and CalculateFloatBasedOnFinishDate. Same
questions, different spellings, and the mapping between the two formats is not
one-to-one.
Progress mode: retained logic, progress override, actual dates
What it does. When a successor starts before its predecessor finishes, the field has already worked around a logic tie the schedule still contains. P6 offers three ways of dealing with that, each a rule about which relationships survive into the forward pass.
| Mode | Which ties it drops |
|---|---|
| Retained logic | None. The tie still binds, and the successor's remaining work waits for its predecessor. |
| Actual dates | Ties whose recorded dates already contradict the logic — the successor has an actual start and the predecessor either has no actual finish or finished after that start. |
| Progress override | Every tie from an incomplete predecessor to a started successor, whether or not the actuals conflict. |
What changes if it is set the other way. The modes are strictly nested, so
the finish dates they produce are ordered:
finish(override) ≤ finish(actual_dates) ≤ finish(retained).
CONCEPTS.md §4 owns that invariant and works a
three-activity example where the gap between the outer two is two weeks of
project finish. The ordering is why the setting matters commercially: progress
override can only ever shorten the schedule, by exactly the logic it dropped,
without deleting a single relationship from the file.
How a reviewer checks which was used. Read both flags, not one. P6 writes the
pair inconsistently across versions — some exports set only
sched_progress_override, others only clear sched_retained_logic — so reading
one field alone is wrong on some exports. Retained logic is the default where
neither flag is decisive, which is what P6 itself does; an explicit N on both
is the Actual Dates declaration.
One caveat, because it is load-bearing: this project's Actual Dates handling is its own interpretation of Primavera's behaviour, not a reproduction of it. See LIMITATIONS.md.
Definition of critical activities: longest path or total float
What it does. It decides which of two questions P6 answers when it paints the bars red. Total float asks "which activities have no spare time?"; longest path asks "which work is pushing the completion date?". P6 reports one at a time and discards the other silently.
What changes if it is set the other way. The set of red bars, and on some schedules enormously. Where a Must Finish By sits a working day past the computed finish, every activity on the driving chain carries a day of float — so the total-float definition returns a handful of activities on a schedule whose longest path runs through dozens. A review comment saying "your critical path is wrong" without naming the definition is arguing about a setting.
How a reviewer checks which was used. It is not in SCHEDOPTIONS. P6
stores it on the PROJECT row as critical_path_type, where CT_DrivPath is
Longest Path and CT_TotFloat the total-float definition. A checker looking only
at the scheduling options record finds nothing to read and abstains on every file
in existence.
Note what this setting is not: it is a declaration of how the submitter's software was configured. Comparing a computed longest path against a computed set of zero-float activities and calling the divergence a breach would file a finding about network topology under a clause about a setting — two chains tied at zero float make those sets differ on a schedule whose setting is exactly right. CONCEPTS.md §2 covers the two schools.
Calendar for scheduling relationship lag
What it does. A lag of three days is three days of something. This setting names the calendar those days are counted on: the predecessor's calendar, the successor's, the project default, or a 24-hour elapsed-time count.
What changes if it is set the other way. Where predecessor and successor sit on different calendars, every lagged link between them moves — three days on a five-day week and three days elapsed are different amounts of time, and across a schedule dense with lagged links the difference compounds into the completion date. Where both ends share a calendar it changes nothing, which is why the effect is easy to miss on a test file and expensive on a real one.
How a reviewer checks which was used. Read
sched_calendar_on_relationship_lag, and case-fold it — P6 7.0 writes the token
in upper case (RCAL_SUCCESSOR) where P6 18 and later write rcal_Successor,
so a case-sensitive lookup falls back silently to the predecessor's calendar,
the opposite of what such a file declares. P6's default is the predecessor's.
This is not a setting to reason about from taste: which mode reproduces P6's own stored successor dates is a measured question, and the answer is not the one an argument from first principles tends to reach. See lags and leads and schedule calendars.
Start-to-start lag basis
What it does. On a start-to-start link into an activity that has already started, it decides whether the lag is measured from the predecessor's early start or from its recorded actual start.
What changes if it is set the other way. Only progressed work moves, and only
on start-to-start links — which is precisely the population a delay analysis
argues about. P6 disables the choice in Actual Dates mode, so on a file
declaring that mode the field is carried and not applied. The field is
sched_lag_early_start_flag, and the informative value is N: the flag as
written is an affirmative "measure from early start".
Total float computation
What it does. It selects the arithmetic behind the total float column: start float (late start minus early start), finish float (late finish minus early finish), or the smaller of the two.
What changes if it is set the other way. On an activity whose calendar makes its start and finish floats differ — which is most activities on a mixed-calendar schedule — the reported float changes and so does the membership of the zero-float set. Where the contract also defines criticality by total float, the two settings interact: changing this one changes which bars are red.
How a reviewer checks which was used. sched_float_type, where FT_SS is
start float, FT_FF is finish float, and ST_TotalFloat is the smaller of the
two. Total float and free float covers what each
figure answers.
What the backward pass was anchored on
Two distinct settings sit under the question "float against what?", and they are easy to conflate.
sched_use_project_end_date_for_float decides whether float is calculated
against each project's own finish date or against the finish of the projects
opened together. On a single-project review it changes nothing. On a container
being scheduled jointly it changes the float of everything.
PROJECT.plan_end_date — the Must Finish By a planner typed — is not a
scheduling option at all, and is the more common cause of float figures that
look inexplicable. Where present it anchors the backward pass, so total float
becomes a measurement against a contractual deadline rather than against the
schedule's own computed finish: a Must Finish By one working day past the
computed finish gives the whole driving chain a day of float and empties the
zero-float set. Do not mistake it for scd_end_date, P6's own computed finish.
Schedule constraints covers the activity-level
equivalents.
Use Expected Finish Dates, and open-ended activities
Use Expected Finish Dates (sched_use_expect_end_flag; older exports write
sched_use_expect_end_date) makes P6 honour an expected finish recorded against
an activity in place of the finish its remaining duration would produce — a date
typed by a person overriding the arithmetic on any activity carrying one.
Make open-ended activities critical (sched_open_critical_flag) makes every
activity with no successor report zero float. Marked, the critical path becomes
the set of everything nobody tied down, and a schedule with very little logic
can present extremely well.
Both are settings a specification is likely to name, and both are read from the file rather than inferred from the network.
External relationships
sched_outer_depend_type is SD_Both or SD_None, and it decides whether
relationships to activities in other projects are honoured or ignored. In a
multi-project container this is the difference between a project bounded by its
neighbours and one floating free of them, and it changes dates without changing
a single row of TASKPRED.
Multiple float paths
enable_multiple_longest_path_calc, with max_multiple_longest_path, makes P6's
driving_path_flag mark membership of up to N near-critical paths ranked by
float, rather than the single driving path.
This project reads the setting, carries it, and deliberately does not implement it. The count is a ceiling and not a definition — it says how many paths to stop at, not which ones qualify, and P6's ranking rule is not documented in any source this project holds, so an implementation would be a guess with a tuning knob attached. The driving closure this engine computes answers a different question from a float ranking, and no closure of any width is a ranking. A report on a file with this setting marked is therefore answering a narrower question than the file was set to ask, and says so.
Where the contract meets the file
Several specifications now mandate particular values for the settings above, by name. That makes them among the cleanest checks in construction scheduling: the exported file states what the scheduler chose, so the clause is answerable from the file rather than from an opinion about the network, and the answer does not change if a scheduling engine's arithmetic changes.
| Specification | What it does with these settings | Page |
|---|---|---|
| UFGS 01 32 01.00 10 §3.12 | Eleven mandatory Primavera P6 requirements, including Longest Path (item f) and Retained Logic (item g) | UFGS |
| VDOT progress-schedule special provisions | Seven named Schedule Options values, prescribed individually in the contract language | VDOT |
| SCDOT | Retain logic required, progress override not permitted | SCDOT |
| MDOT SHA 2026 Standard Specifications, Section 109 | Retained logic stated in the specification itself | MDOT SHA |
Each of those pages carries the clause numbers and the agency's own wording; this one does not restate them. The point of the table is the pattern: four independent documents, written by different authorities, reaching for the same short list of fields — because those fields decide the answer and are invisible on the printed schedule.
One caution belongs with them. A specification binds where the contract incorporates it, not where the agency name matches. And a setting check is a check on a declaration: it reports what the file states, and whether the submission is acceptable is the reviewing authority's determination.
How to check a file in practice
- Identify the project you are reviewing, by
proj_id, first. See auditing a P6 schedule §2 for why a container is the most under-appreciated trap in XER review. - Find the
SCHEDOPTIONSrow whoseproj_idmatches it. If there is none, the project ran on P6's defaults — record that, and do not borrow a sibling's row. - Read
PROJECT.critical_path_typeseparately: the criticality definition is not in the options record. - Read
PROJECT.plan_end_date, because a Must Finish By changes every float figure in the file. - Record the values alongside your findings, not in an appendix. Two updates computed under different settings are not comparable, and this row is the only evidence that they were the same.
This project reports the settings it read as part of the schedule's own record, and rules that check them cite the clause and quote the field rather than consulting anything the engine computed. Where a clause needs a fact the file does not carry, the rule states that it could not be decided and names the missing input. See what it does, what each rule's verdict depends on, and the limitations.
Related reading
- How to audit a Primavera P6 schedule — the companion page: where each thing lives, and stored versus computed.
- What an XER file is — the table grammar, the traps, and what an export does not carry.
- CONCEPTS.md — §2 on the two definitions of critical, §4 on the three progress modes and the ordering invariant.
- Lags and leads · Schedule calendars · Schedule constraints · Total float and free float.
- The schedule review checklist — item 12 is the declared-settings check, in its place among the rest.
- Glossary — retained logic, progress override, longest path, lag calendar.
Source: web/pages/p6-schedule-options.md. Source commit date: 2026-09-11.