impacted_as_planned
Impacted As-Planned (IAP) on an unprogressed as-planned
baseline. Implements AACE RP 29R-03 MIP 3.6 (Modeled /
Additive / Single Base) and SCL Protocol 2nd ed. §11.6(a).
Two modes.
**screen** (default): inserts each delay fragnet into the
as-planned baseline, first one at a time and then all together,
re-runs CPM, and reads the joint impact against verdict bands
(NO SIGNAL, LOW SIGNAL, MODERATE SIGNAL, STRONG SIGNAL, or
INDETERMINATE when the joint pass fails). Use it as a quick read
on whether a delay claim has legs before a fuller analysis. The
sum of the one-at-a-time impacts is reported beside the joint
impact; ``overstatement_days`` is the difference, from fragnets
that share a path. Check each ``per_fragnet[].status`` before
quoting a figure: a fragnet that failed on its own carries
``status`` "error" and its ``error``, and is left out of the
one-at-a-time sum. The joint pass inserts every fragnet
together, so read ``joint.status`` and the "iap-joint" warnings
too: with a bad fragnet the joint pass can fail (verdict
INDETERMINATE) or run without the ties it could not insert.
**rebut**: tests an opposing expert's IAP submission. Supply at
least one of: ``opposing_impacted_xer_path`` or
``opposing_impacted_xer_content`` (tier A: re-runs their
impacted schedule and diffs it against the baseline),
``opposing["fragnets"]`` (tier B: re-models their fragnets on
the baseline), or ``opposing["claimed_impact_days"]`` (tier C:
their stated figure).
IAP does not look at what actually happened on site: it
measures the planned logic plus the inserted delays. The result
carries ``iap_method_caveat`` saying so, and a ``precondition``
block that flags a baseline carrying progress (not a pure
as-planned schedule). Every activity is laid out on one uniform
timeline with no weekends or holidays, each timeline day being
one working day of that activity's own calendar. Where every
unfinished activity is on one calendar, each impact is exact in
working days on it, apart from constraint dates and any stretch
before the data date, which the run places on the project's
default calendar. With more than one calendar, paths on
different calendars change length against each other on that
timeline, so float, the driving path and the impact can differ
from a calendar-aware run, and the impact is a mix of those
calendars' working days; the result lists the calendars
(``calendars_in_use``, and ``opposing_calendars_in_use`` for a
tier A file) and warns when there is more than one. The absolute
dates the run shows are not P6 calendar dates (``date_basis``):
quote the day counts, not the dates. For an impact measured on each event's own
contemporaneous baseline use ``time_impact_analysis_fragnet``
(MIP 3.7); for retrospective windows use
``forensic_windows_analysis`` (MIP 3.3); for a subtractive
but-for use ``collapsed_as_built`` (MIP 3.8).
Args:
baseline_xer_path: server-side as-planned baseline XER.
baseline_xer_content: full text of the as-planned baseline
XER (alternative for hosted/remote use).
Supply EXACTLY ONE of path/content.
fragnets: SCREEN (required): list of fragnet dicts, each
with ``id``, ``name``, ``liability`` (responsible
party), ``activities`` (list of {code, name,
duration_days}; duration_days in working days) and
``ties`` (list of {from_code, to_code, type, lag_days};
pred/succ are accepted aliases for from_code/to_code;
type is FS, SS, FF or SF in any case, with or without
P6's PR_ prefix; a missing type is FS and any other
type is refused).
mode: "screen" (default) or "rebut" (case does not matter).
opposing: REBUT: dict of the opposing material, with any of
``fragnets`` (same shape as above),
``claimed_impact_days`` (number), ``claimed_finish``
(YYYY-MM-DD), ``proj_id``, ``expert_name``,
``report_ref``. Other keys are refused. Pass the
opposing impacted schedule through the two arguments
below, not in this dict.
opposing_impacted_xer_path: REBUT tier A: server-side
opposing impacted XER.
opposing_impacted_xer_content: REBUT tier A: full text of
the opposing impacted XER.
Supply at most ONE of this
path/content pair.
own_results: REBUT, optional: your own results from the
primary methods in working days, {windows_days,
tia_days, collapsed_days}, read beside the opposing
figure.
proj_id: optional project selector inside a multi-project
baseline XER.
screen_bands: SCREEN, optional: verdict band overrides,
{low_pct, strong_pct, wd_floor_moderate}. Defaults
2.0, 5.0 and 20; low_pct must stay below strong_pct.
baseline_name / opposing_name: optional file names to
print in the report for XERs sent as content (a
content upload has no file name of its own).
preparer / company: optional, printed on the report and
dashboard as who prepared the analysis. Both are blank
unless supplied.
output_dir: output dir for the HTML dashboard, TXT report
and CSVs (tempdir if "").
project_name: optional override.
Limits for hosted use: 500 fragnets on each side, and 5,000
inserted activities and 20,000 ties across all of them.
Returns:
{
"mode": "screen" | "rebut",
"method": "Impacted As-Planned — AACE 29R-03 §3.6 / MIP 3.6 ...",
"baseline": {project_finish, plan_start,
baseline_duration_wd, critical_count, ...},
"precondition": {progressed_count, total_count,
pure_as_planned},
"per_fragnet": [{fragnet_id, status, error,
impact_days, impact_working_days, ...}], # SCREEN
"joint": {status, impact_days, impact_working_days, ...}, # SCREEN
"sum_isolated_days": int, # SCREEN
"sum_isolated_working_days": int, # SCREEN
"overstatement_days": int, # SCREEN: sum minus joint
"screen_verdict": {band, pct, joint_wd, bands_used, basis}, # SCREEN
"rebut": {...}, # REBUT: tiers A/B/C and findings
"critique": {...},
"iap_method_caveat": str,
"date_basis": str,
"day_unit_basis": str, # what every day count counts
"calendars_in_use": [str] | None, # None: could not be read
"opposing_calendars_in_use": [str] | None, # REBUT tier A
"output_files": {report, events_csv, dashboard, ...},
"warnings": [...],
"baseline_sha256": str, "baseline_sha256_basis": str,
"opposing_impacted_sha256": str, # REBUT tier A
"opposing_impacted_sha256_basis": str, # REBUT tier A
}