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

  1. 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.
  2. Find the SCHEDOPTIONS row whose proj_id matches it. If there is none, the project ran on P6's defaults — record that, and do not borrow a sibling's row.
  3. Read PROJECT.critical_path_type separately: the criticality definition is not in the options record.
  4. Read PROJECT.plan_end_date, because a Must Finish By changes every float figure in the file.
  5. 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.

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

See it in practice

Follow the evidence, from the schedule to the finding.

Explore the sample